Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions examples/css-color-variables/Input.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<div class="card">
<h2 class="card-title">Card Title</h2>
<p class="card-text">Card content goes here</p>
<button class="card-button">Action</button>
</div>
</template>

<style scoped>:root {
--color-text-primary: #333333;
--color-text-secondary: #666666;
--color-primary: #007bff;
--color-primary-dark: #0056b3;
--color-background: #ffffff;
--color-border: #e0e0e0;
--color-disabled: #cccccc;
--color-background: white;
--shadow-light: rgba(0, 0, 0, 0.1);
}

.card {
background: var(--color-background);
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.card-title {
color: var(--color-text-primary);
font-size: 1.25rem;
margin: 0 0 12px 0;
}

.card-text {
color: var(--color-text-secondary);
line-height: 1.5;
margin: 0 0 16px 0;
}

.card-button {
background: var(--color-primary);
color: var(--color-background);
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s;
}

.card-button:hover {
background: var(--color-primary-dark);
}

.card-button:disabled {
background: var(--color-disabled);
cursor: not-allowed;
}
</style>
52 changes: 52 additions & 0 deletions examples/css-color-variables/transformation.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module.exports = {
style: function convertToColorVariables(fileInfo, { root, postcss }) {
// Define color mappings - map actual colors to their variable names
const colorMap = {
'#333333': '--color-text-primary',
'#666666': '--color-text-secondary',
'#007bff': '--color-primary',
'#0056b3': '--color-primary-dark',
'#ffffff': '--color-background',
'#e0e0e0': '--color-border',
'#cccccc': '--color-disabled',
white: '--color-background',
'rgba(0, 0, 0, 0.1)': '--shadow-light',
}

// Only add variables if they don't already exist
let rootRule = null
root.walkRules(':root', (rule) => {
rootRule = rule
})

if (!rootRule) {
rootRule = new postcss.Rule({ selector: ':root' })

// Create CSS custom properties with actual color values
Object.entries(colorMap).forEach(([actualColor, varName]) => {
const decl = new postcss.Declaration({
prop: varName,
value: actualColor,
})
rootRule.append(decl)
})

// Insert the :root rule at the beginning
root.prepend(rootRule)
}

// Replace color values with CSS variable references (but not in the :root rule)
root.walkDecls((decl) => {
// Skip declarations inside :root rule to avoid circular references
if (decl.parent.selector === ':root') {
return
}

Object.entries(colorMap).forEach(([actualColor, varName]) => {
if (decl.value === actualColor) {
decl.value = `var(${varName})`
}
})
})
},
}
39 changes: 39 additions & 0 deletions examples/css-prefix-classes/Input.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="container">
<h1 class="title">Hello World</h1>
<p class="text">This is a paragraph</p>
<button class="btn">Click me</button>
</div>
</template>

<style scoped>
.my-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}

.my-title {
font-size: 2rem;
color: #333;
margin-bottom: 1rem;
}

.my-text {
line-height: 1.6;
color: #666;
}

.my-btn {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}

.my-btn:hover {
background: #0056b3;
}
</style>
16 changes: 16 additions & 0 deletions examples/css-prefix-classes/transformation.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
style: function prefixClasses(fileInfo, { root }, options) {
const prefix = options?.prefix || 'app-'

// Transform class selectors
root.walkRules((rule) => {
rule.selector = rule.selector.replace(/\.([a-zA-Z][\w-]*)/g, (match, className) => {
// Don't prefix if it already has the prefix
if (className.startsWith(prefix.replace('-', ''))) {
Comment on lines +4 to +9
Copy link

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Avoid calling prefix.replace('-', '') inside the loop on every rule. Compute the cleaned prefix once outside of root.walkRules for better clarity and slight performance gain.

Suggested change
// Transform class selectors
root.walkRules((rule) => {
rule.selector = rule.selector.replace(/\.([a-zA-Z][\w-]*)/g, (match, className) => {
// Don't prefix if it already has the prefix
if (className.startsWith(prefix.replace('-', ''))) {
const cleanedPrefix = prefix.replace('-', '')
// Transform class selectors
root.walkRules((rule) => {
rule.selector = rule.selector.replace(/\.([a-zA-Z][\w-]*)/g, (match, className) => {
// Don't prefix if it already has the prefix
if (className.startsWith(cleanedPrefix)) {

Copilot uses AI. Check for mistakes.
return match
}
return `.${prefix}${className}`
})
})
},
}
38 changes: 38 additions & 0 deletions examples/css-vue-deep-transform/Input.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<div class="wrapper">
<div class="content">
<slot />
</div>
</div>
</template>

<style scoped>
.wrapper {
border: 1px solid #ddd;
padding: 20px;
}

.wrapper::v-deep .child-component {
margin: 10px 0;
}

.wrapper::v-deep .child-component h2 {
color: #333;
font-size: 1.5rem;
}

.wrapper::v-slotted p {
color: #666;
line-height: 1.6;
}

.content::v-deep .nested .item {
background: #f5f5f5;
padding: 8px;
}

/* Mix of old and new syntax */
.wrapper::v-deep .legacy {
border: 1px solid red;
}
</style>
15 changes: 15 additions & 0 deletions examples/css-vue-deep-transform/transformation.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
style: function transformVueSelectors(fileInfo, { root }) {
// Transform Vue 3 deep and slotted selectors to Vue 2 syntax
root.walkRules((rule) => {
rule.selector = rule.selector
// Convert :deep() to ::v-deep
.replace(/:deep\(([^)]+)\)/g, '::v-deep $1')
// Convert :slotted() to ::v-slotted
.replace(/:slotted\(([^)]+)\)/g, '::v-slotted $1')
// Normalize existing ::v-deep syntax
.replace(/::v-deep\s*\(/g, '::v-deep ')
.replace(/\)$/, '')
})
},
}
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
"jscodeshift": "^0.15.2",
"lint-staged": "^15.5.2",
"lru-cache": "^11.1.0",
"postcss": "^8.5.6",
"postcss-less": "^6.0.0",
"postcss-scss": "^4.0.9",
"postcss-selector-parser": "^7.1.0",
"postcss-value-parser": "^4.2.0",
"rollup-plugin-vue": "^6.0.0",
"source-map-js": "^1.2.1",
"vue": "^3.5.17",
Expand Down
Loading
Loading