Skip to content

Commit 09b5dd6

Browse files
Maksym-Saukhm0ksem
andauthored
Fix#4541: update create-vue installation to include @vuestic/compiler (#4551)
* Create plugin to modify the project's vite.config * addDependency @vuestic/compiler * chore(create-vuestic): use latest create-vue * fix: correct peer deps in @vuestic/compiler * fix: upgrade min vite version in @vuestic/compiler * chore: bump @vuestic/compiler to 0.2.5 * fix: css-layers order * chore: bump @vuestic/compiler to 0.2.6. * fix(compiler/devtools): handle other plugins code transform * chore: bump @vuestic/compiler to 0.2.7 * fix(create-vuestic): add intent to vuestic vite plugin * chore: update yarn.lock * chore: rename compiler file --------- Co-authored-by: Maksim Nedoshev <m0ksem1337@gmail.com>
1 parent 86b2009 commit 09b5dd6

File tree

17 files changed

+589
-45
lines changed

17 files changed

+589
-45
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ dist
44
storybook-static
55
build-storybook.log
66
.nuxt
7-
packages/create-vuestic/vuestic-app
7+
packages/create-vuestic/vuestic-app/*
8+
!packages/create-vuestic/vuestic-app/yarn.lock
89

910
/packages/bundlers-tests/**/screenshots
1011
/packages/bundlers-tests/**/video

packages/compiler/css-layers/plugin.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Plugin } from 'vite'
22
import MagicString from 'magic-string'
33

44
const addLayer = (ms: MagicString, layer: string) => {
5-
ms.prepend(`@layer ${layer} {\n`)
5+
ms.prepend(`@layer vuestic.styles, vuestic.components;\n` + `@layer ${layer} {\n`)
66
ms.append(`\n}`)
77
return {
88
code: ms.toString(),
@@ -18,11 +18,11 @@ export const cssLayers: Plugin = {
1818
// Only transform CSS files
1919
if (!id.endsWith('.css')) return null
2020

21-
if (id.includes('vuestic-ui/dist/styles/')) {
21+
if (id.includes('vuestic-ui/dist/styles/') || id.includes('vuestic-ui/packages/ui/dist/styles/')) {
2222
return addLayer(new MagicString(code), 'vuestic.styles')
2323
}
2424

25-
if (id.includes('vuestic-ui/dist/es/')) {
25+
if (id.includes('vuestic-ui/dist/es/') || id.includes('vuestic-ui/packages/ui/dist/es/')) {
2626
return addLayer(new MagicString(code), 'vuestic.components')
2727
}
2828
}

packages/compiler/devtools/client/build/append-style.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Plugin } from "vite";
1+
import { type Plugin } from "vite";
22
import { writeFile, readFile } from 'fs/promises'
33
import { resolve } from 'path'
44

packages/compiler/devtools/plugin/compiler.ts

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import MagicString from 'magic-string'
44
import { minifyPath } from '../shared/slug'
55
import { PREFIX } from '../shared/CONST'
66
import { stringifyFileQuery } from '../shared/file-query'
7+
import { readFile } from 'node:fs/promises'
8+
import { makeDiffSyncByRow } from './diff-sync'
79

810
const walk = (node: TemplateChildNode | RootNode, cb: (node: TemplateChildNode | RootNode) => void) => {
911
cb(node)
@@ -71,8 +73,46 @@ const getNodeTagLoc = (source: string) => {
7173
}
7274
}
7375

76+
export const fromOutputToSourceShift = (source: string, output: string) => {
77+
const diff = makeDiffSyncByRow(source, output)
78+
79+
80+
return (start: number, end: number) => {
81+
let current: typeof diff[number] | undefined = undefined
82+
let shiftStart = 0
83+
let shiftEnd = 0
84+
85+
for (let i = 0; i < diff.length; i++) {
86+
current = diff[i]
87+
88+
if (current.end.output > end) {
89+
break
90+
}
91+
92+
if (current.type === 'equal') {
93+
continue
94+
} else if (current.type === 'insert') {
95+
if (current.start.output < start) {
96+
shiftStart -= current.source.length
97+
}
98+
if (current.end.output < end) {
99+
shiftEnd -= current.source.length
100+
}
101+
}
102+
}
103+
104+
if (!current) {
105+
return { start: 0, end: 0 }
106+
}
107+
108+
return { start: shiftStart, end: shiftEnd }
109+
}
110+
}
111+
74112

75113
export const transformFile = async (code: string, id: string) => {
114+
// Read the source file, ignore polluted code from other plugins
115+
const sourceFile = await readFile(id, 'utf-8')
76116
// TODO: remove old minified paths
77117
const result = parse(code)
78118
const templateAst = result.descriptor.template?.ast
@@ -83,17 +123,37 @@ export const transformFile = async (code: string, id: string) => {
83123

84124
let source = new MagicString(code)
85125

86-
// TODO: TS fix correct versions of @vue/compiler-core and @vue/compiler-sfc
87-
walk(templateAst as unknown as RootNode, (node) => {
88-
if (node.type === 1) {
89-
const tagLoc = getNodeTagLoc(node.loc.source)
90-
const nodeId = stringifyFileQuery(id, node.loc.start.offset, node.loc.end.offset)
126+
// Handle other plugins that may have modified the code
127+
if (code !== sourceFile) {
128+
const getShift = fromOutputToSourceShift(sourceFile, code)
129+
130+
// TODO: TS fix correct versions of @vue/compiler-core and @vue/compiler-sfc
131+
walk(templateAst as unknown as RootNode, (node) => {
132+
if (node.type === 1) {
133+
const tagLoc = getNodeTagLoc(node.loc.source)
134+
const shift = getShift(node.loc.start.offset, node.loc.end.offset)
135+
const nodeId = stringifyFileQuery(id, node.loc.start.offset + shift.start, node.loc.end.offset + shift.end)
136+
137+
const withAttribute = ` data-${PREFIX}="" data-${minifyPath(nodeId)}="${node.tag}"`
138+
139+
source.appendLeft(node.loc.start.offset + tagLoc.end.offset - tagLoc.endSymbol.length, withAttribute)
140+
}
141+
})
142+
} else {
143+
// TODO: TS fix correct versions of @vue/compiler-core and @vue/compiler-sfc
144+
walk(templateAst as unknown as RootNode, (node) => {
145+
if (node.type === 1) {
146+
const tagLoc = getNodeTagLoc(node.loc.source)
147+
const nodeId = stringifyFileQuery(id, node.loc.start.offset, node.loc.end.offset)
148+
149+
const withAttribute = ` data-${PREFIX}="" data-${minifyPath(nodeId)}="${node.tag}"`
150+
151+
source.appendLeft(node.loc.start.offset + tagLoc.end.offset - tagLoc.endSymbol.length, withAttribute)
152+
}
153+
})
154+
}
91155

92-
const withAttribute = ` data-${PREFIX}="" data-${minifyPath(nodeId)}="${node.tag}"`
93156

94-
source.appendLeft(node.loc.start.offset + tagLoc.end.offset - tagLoc.endSymbol.length, withAttribute)
95-
}
96-
})
97157

98158
return {
99159
code: source.toString(),
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
type Block = { start: { source: number, output: number }, end: { source: number, output: number }, type: string, source: string }
2+
3+
4+
export const makeDiffSyncByRow = (original: string, modified: string) => {
5+
const originalLines = original.split('\n')
6+
const modifiedLines = modified.split('\n')
7+
8+
let sourceShift = 0
9+
let outputShift = 0
10+
const blocks = []
11+
12+
for (let i = 0; i < Math.max(originalLines.length, modifiedLines.length); i++) {
13+
const sourceLine = (originalLines[i] ?? '') + '\n'
14+
const modifiedLine = (modifiedLines[i] ?? '') + '\n'
15+
16+
if (sourceLine === modifiedLine) {
17+
blocks.push({
18+
type: 'equal',
19+
start: { source: sourceShift, output: outputShift },
20+
end: {
21+
source: sourceShift + sourceLine.length,
22+
output: outputShift + sourceLine.length,
23+
},
24+
source: sourceLine,
25+
})
26+
} else {
27+
const lineDiff = makeDiffSync(sourceLine, modifiedLine)
28+
for (const block of lineDiff) {
29+
blocks.push({
30+
...block,
31+
start: {
32+
source: block.start.source + sourceShift,
33+
output: block.start.output + outputShift,
34+
},
35+
end: {
36+
source: block.end.source + sourceShift,
37+
output: block.end.output + outputShift,
38+
},
39+
})
40+
}
41+
}
42+
43+
sourceShift += sourceLine.length
44+
outputShift += modifiedLine.length
45+
}
46+
47+
return mergeEqualBlocks(blocks)
48+
}
49+
50+
const mergeEqualBlocks = (blocks: Block[]) => {
51+
return blocks.reduce((acc, block) => {
52+
const last = acc.at(-1)
53+
if (block.type === 'equal' && last?.type === 'equal') {
54+
last.source += block.source
55+
last.end = block.end
56+
} else {
57+
acc.push(block)
58+
}
59+
return acc
60+
}, [] as Block[])
61+
}
62+
63+
const makeDiffSync = (source: string, output: string) => {
64+
let originalShift = 0
65+
let modifiedShift = 0
66+
67+
function makeBlock(type: string, sourceStart: number, sourceEnd: number, outputStart: number, outputEnd: number) {
68+
const blockSource = type === 'insert' ? output.slice(outputStart, outputEnd) : source.slice(sourceStart, sourceEnd)
69+
70+
return {
71+
start: {
72+
source: sourceStart,
73+
output: outputStart
74+
},
75+
end: {
76+
source: sourceEnd,
77+
output: outputEnd
78+
},
79+
type,
80+
source: blockSource
81+
}
82+
}
83+
84+
const blocks = [
85+
makeBlock('equal', 0, 0, 0, 0),
86+
]
87+
88+
function findInsert(originalShift: number, modifiedShift: number) {
89+
const modifiedShiftStart = modifiedShift
90+
91+
while (originalShift < source.length && modifiedShift < output.length) {
92+
if (output[modifiedShift] === source[originalShift]) {
93+
break
94+
}
95+
96+
modifiedShift++
97+
}
98+
99+
if (output.length < modifiedShiftStart) {
100+
return
101+
}
102+
103+
return makeBlock('insert', originalShift, originalShift, modifiedShiftStart, modifiedShift)
104+
}
105+
106+
function findDelete(originalShift: number, modifiedShift: number) {
107+
const originalShiftStart = originalShift
108+
109+
while (originalShift < source.length && modifiedShift < output.length) {
110+
if (output[modifiedShift] === source[originalShift]) {
111+
return makeBlock('delete', originalShiftStart, originalShift, modifiedShift, modifiedShift)
112+
}
113+
114+
originalShift++
115+
}
116+
}
117+
118+
119+
while (originalShift < source.length && modifiedShift < output.length) {
120+
const originalChar = source[originalShift]
121+
const modifiedChar = output[modifiedShift]
122+
123+
const currentBlock = blocks[blocks.length - 1]
124+
125+
if (originalChar === modifiedChar) {
126+
if (currentBlock.type === 'equal') {
127+
currentBlock.end.output++
128+
currentBlock.end.source++
129+
currentBlock.source = source.slice(currentBlock.start.source, currentBlock.end.source)
130+
} else {
131+
blocks.push(makeBlock('equal', originalShift, originalShift + 1, modifiedShift, modifiedShift + 1))
132+
}
133+
originalShift++
134+
modifiedShift++
135+
} else {
136+
const nextChain = findDelete(originalShift, modifiedShift)
137+
const insertBlock = findInsert(originalShift, modifiedShift)
138+
139+
if (nextChain && insertBlock) {
140+
// Prioritize insert over deleting something in output string
141+
if (output.slice(modifiedShift).includes(nextChain.source)) {
142+
blocks.push(insertBlock)
143+
modifiedShift = insertBlock.end.output
144+
continue
145+
}
146+
147+
blocks.push(nextChain)
148+
originalShift = nextChain.end.source
149+
continue
150+
}
151+
if (insertBlock) {
152+
blocks.push(insertBlock)
153+
modifiedShift = insertBlock.end.output
154+
continue
155+
}
156+
if (nextChain) {
157+
blocks.push(nextChain)
158+
originalShift = nextChain.end.source
159+
continue
160+
}
161+
162+
break
163+
}
164+
}
165+
166+
return blocks
167+
}

packages/compiler/devtools/plugin/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const devtools = (options: PluginOptions = {}): Plugin => {
4646
}
4747
},
4848

49-
transform(code, id) {
49+
async transform(code, id) {
5050
if (config.isProduction) {
5151
return
5252
}

packages/compiler/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vuestic/compiler",
3-
"version": "0.2.4",
3+
"version": "0.2.7",
44
"type": "module",
55
"dependencies": {
66
"@rollup/pluginutils": "^5.1.0",
@@ -15,11 +15,16 @@
1515
"dev": "cd ./playground && yarn dev",
1616
"prepublishOnly": "npm run build"
1717
},
18+
"devDependencies": {
19+
"@vitejs/plugin-vue": "^6.0.0",
20+
"tsup": "^8.5.0",
21+
"vite": "^5.0.3"
22+
},
1823
"peerDependencies": {
1924
"@vue/compiler-core": "^3.4.21",
2025
"@vue/compiler-sfc": "^3.4.21",
21-
"tsup": "^8.1.0",
22-
"vite": "^5.3.3"
26+
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
27+
"vue": "^3.4.21"
2328
},
2429
"exports": {
2530
"./vite": {
@@ -44,10 +49,5 @@
4449
"files": [
4550
"dist",
4651
"Readme.md"
47-
],
48-
"devDependencies": {
49-
"@vitejs/plugin-vue": "^6.0.0",
50-
"tsup": "^8.5.0",
51-
"vite": "4.5.14"
52-
}
52+
]
5353
}

packages/compiler/playground/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@vue/tsconfig": "^0.5.1",
2121
"typescript": "~5.4.0",
2222
"vite": "^5.3.6",
23+
"vite-plugin-inspect": "0.8.8",
2324
"vue-tsc": "^2.0.21"
2425
}
2526
}

packages/compiler/playground/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default defineConfig({
1616
},
1717
autoImport: true,
1818
config: true,
19+
cssLayers: true,
1920
}),
2021
vue(),
2122
Inspect(),

0 commit comments

Comments
 (0)