Skip to content

Commit ee0bbdb

Browse files
committed
feat: experimental resolve external stylesheets
1 parent 56ac8b9 commit ee0bbdb

File tree

16 files changed

+339
-218
lines changed

16 files changed

+339
-218
lines changed

packages/language-core/lib/codegen/script/index.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import type { ScriptRanges } from '../../parsers/scriptRanges';
55
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
66
import type { Code, Sfc, VueCodeInformation, VueCompilerOptions } from '../../types';
77
import { generateGlobalTypes } from '../globalTypes';
8+
import { generateStyleModules } from '../style/modules';
89
import type { TemplateCodegenContext } from '../template/context';
910
import { endOfLine, generateSfcBlockSection, newLine } from '../utils';
1011
import { generateComponentSelf } from './componentSelf';
1112
import { createScriptCodegenContext, ScriptCodegenContext } from './context';
1213
import { generateScriptSetup, generateScriptSetupImports } from './scriptSetup';
1314
import { generateSrc } from './src';
14-
import { generateStyleModulesType } from './styleModulesType';
1515
import { generateTemplate } from './template';
1616

1717
export const codeFeatures = {
@@ -76,14 +76,16 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
7676
}
7777

7878
if (options.sfc.script?.src) {
79-
yield* generateSrc(options.sfc.script, options.sfc.script.src);
79+
yield* generateSrc(options.sfc.script.src);
80+
}
81+
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
82+
yield* generateScriptSetupImports(options.sfc.scriptSetup, options.scriptSetupRanges);
8083
}
8184
if (options.sfc.script && options.scriptRanges) {
8285
const { exportDefault, classBlockEnd } = options.scriptRanges;
8386
const isExportRawObject = exportDefault
8487
&& options.sfc.script.content[exportDefault.expression.start] === '{';
8588
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
86-
yield* generateScriptSetupImports(options.sfc.scriptSetup, options.scriptSetupRanges);
8789
if (exportDefault) {
8890
yield generateSfcBlockSection(options.sfc.script, 0, exportDefault.expression.start, codeFeatures.all);
8991
yield* generateScriptSetup(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
@@ -139,7 +141,6 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
139141
}
140142
}
141143
else if (options.sfc.scriptSetup && options.scriptSetupRanges) {
142-
yield* generateScriptSetupImports(options.sfc.scriptSetup, options.scriptSetupRanges);
143144
yield* generateScriptSetup(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges);
144145
}
145146

@@ -156,7 +157,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
156157
}
157158

158159
// #4788
159-
yield* generateStyleModulesType(options, ctx);
160+
yield* generateStyleModules(options, ctx);
160161

161162
if (options.edited) {
162163
yield `type __VLS_IntrinsicElementsCompletion = __VLS_IntrinsicElements${endOfLine}`;

packages/language-core/lib/codegen/script/scriptSetup.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,21 @@ export function* generateScriptSetup(
3838
}
3939
yield `export default `;
4040
}
41-
yield `(<`;
42-
yield [
43-
scriptSetup.generic,
44-
scriptSetup.name,
45-
scriptSetup.genericOffset,
46-
codeFeatures.all,
47-
];
48-
if (!scriptSetup.generic.endsWith(`,`)) {
49-
yield `,`;
41+
yield `(`;
42+
if (typeof scriptSetup.generic === 'object') {
43+
yield `<`;
44+
yield [
45+
scriptSetup.generic.text,
46+
scriptSetup.name,
47+
scriptSetup.generic.offset,
48+
codeFeatures.all,
49+
];
50+
if (!scriptSetup.generic.text.endsWith(`,`)) {
51+
yield `,`;
52+
}
53+
yield `>`;
5054
}
51-
yield `>(${newLine}`
55+
yield `(${newLine}`
5256
+ ` __VLS_props: NonNullable<Awaited<typeof __VLS_setup>>['props'],${newLine}`
5357
+ ` __VLS_ctx?: ${ctx.localTypes.PrettifyLocal}<Pick<NonNullable<Awaited<typeof __VLS_setup>>, 'attrs' | 'emit' | 'slots'>>,${newLine}` // use __VLS_Prettify for less dts code
5458
+ ` __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],${newLine}`
Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,51 @@
1-
import type { Code, Sfc } from '../../types';
2-
import { endOfLine } from '../utils';
1+
import type { Code, SfcBlockAttr } from '../../types';
2+
import { endOfLine, generateSfcBlockAttrValue } from '../utils';
33
import { codeFeatures } from './index';
44

5-
export function* generateSrc(
6-
script: NonNullable<Sfc['script']>,
7-
src: string
8-
): Generator<Code> {
9-
if (src.endsWith('.d.ts')) {
10-
src = src.slice(0, -'.d.ts'.length);
5+
export function* generateSrc(src: SfcBlockAttr): Generator<Code> {
6+
if (src === true) {
7+
return;
118
}
12-
else if (src.endsWith('.ts')) {
13-
src = src.slice(0, -'.ts'.length);
9+
let { text } = src;
10+
11+
if (text.endsWith('.d.ts')) {
12+
text = text.slice(0, -'.d.ts'.length);
13+
}
14+
else if (text.endsWith('.ts')) {
15+
text = text.slice(0, -'.ts'.length);
1416
}
15-
else if (src.endsWith('.tsx')) {
16-
src = src.slice(0, -'.tsx'.length) + '.jsx';
17+
else if (text.endsWith('.tsx')) {
18+
text = text.slice(0, -'.tsx'.length) + '.jsx';
1719
}
1820

19-
if (!src.endsWith('.js') && !src.endsWith('.jsx')) {
20-
src = src + '.js';
21+
if (!text.endsWith('.js') && !text.endsWith('.jsx')) {
22+
text = text + '.js';
2123
}
2224

2325
yield `export * from `;
24-
yield [
25-
`'${src}'`,
26-
'script',
27-
script.srcOffset - 1,
28-
{
29-
...codeFeatures.all,
30-
navigation: src === script.src
31-
? true
32-
: {
33-
shouldRename: () => false,
34-
resolveRenameEditText(newName) {
35-
if (newName.endsWith('.jsx') || newName.endsWith('.js')) {
36-
newName = newName.split('.').slice(0, -1).join('.');
37-
}
38-
if (script?.src?.endsWith('.d.ts')) {
39-
newName = newName + '.d.ts';
40-
}
41-
else if (script?.src?.endsWith('.ts')) {
42-
newName = newName + '.ts';
43-
}
44-
else if (script?.src?.endsWith('.tsx')) {
45-
newName = newName + '.tsx';
46-
}
47-
return newName;
48-
},
26+
yield* generateSfcBlockAttrValue(src, text, {
27+
...codeFeatures.all,
28+
navigation: text === src.text
29+
? true
30+
: {
31+
shouldRename: () => false,
32+
resolveRenameEditText(newName) {
33+
if (newName.endsWith('.jsx') || newName.endsWith('.js')) {
34+
newName = newName.split('.').slice(0, -1).join('.');
35+
}
36+
if (src?.text.endsWith('.d.ts')) {
37+
newName = newName + '.d.ts';
38+
}
39+
else if (src?.text.endsWith('.ts')) {
40+
newName = newName + '.ts';
41+
}
42+
else if (src?.text.endsWith('.tsx')) {
43+
newName = newName + '.tsx';
44+
}
45+
return newName;
4946
},
50-
},
51-
];
47+
},
48+
});
5249
yield endOfLine;
53-
yield `export { default } from '${src}'${endOfLine}`;
50+
yield `export { default } from '${text}'${endOfLine}`;
5451
}

packages/language-core/lib/codegen/script/styleModulesType.ts

Lines changed: 0 additions & 42 deletions
This file was deleted.

packages/language-core/lib/codegen/script/template.ts

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Code } from '../../types';
22
import { hyphenateTag } from '../../utils/shared';
3+
import { generateStyleScopedClasses } from '../style/scopedClasses';
34
import { TemplateCodegenContext, createTemplateCodegenContext } from '../template/context';
45
import { generateInterpolation } from '../template/interpolation';
56
import { generateStyleScopedClassReferences } from '../template/styleScopedClasses';
@@ -137,71 +138,6 @@ function* generateTemplateBody(
137138
yield `type __VLS_TemplateEl = typeof __VLS_rootEl${endOfLine}`;
138139
}
139140

140-
function* generateStyleScopedClasses(
141-
options: ScriptCodegenOptions,
142-
ctx: TemplateCodegenContext
143-
): Generator<Code> {
144-
const firstClasses = new Set<string>();
145-
yield `type __VLS_StyleScopedClasses = {}`;
146-
for (let i = 0; i < options.sfc.styles.length; i++) {
147-
const style = options.sfc.styles[i];
148-
const option = options.vueCompilerOptions.experimentalResolveStyleCssClasses;
149-
if (option === 'always' || (option === 'scoped' && style.scoped)) {
150-
for (const className of style.classNames) {
151-
if (firstClasses.has(className.text)) {
152-
ctx.scopedClasses.push({
153-
source: 'style_' + i,
154-
className: className.text.slice(1),
155-
offset: className.offset + 1
156-
});
157-
continue;
158-
}
159-
firstClasses.add(className.text);
160-
yield* generateCssClassProperty(
161-
i,
162-
className.text,
163-
className.offset,
164-
'boolean',
165-
true
166-
);
167-
}
168-
}
169-
}
170-
yield endOfLine;
171-
}
172-
173-
export function* generateCssClassProperty(
174-
styleIndex: number,
175-
classNameWithDot: string,
176-
offset: number,
177-
propertyType: string,
178-
optional: boolean
179-
): Generator<Code> {
180-
yield `${newLine} & { `;
181-
yield [
182-
'',
183-
'style_' + styleIndex,
184-
offset,
185-
codeFeatures.navigation,
186-
];
187-
yield `'`;
188-
yield [
189-
classNameWithDot.slice(1),
190-
'style_' + styleIndex,
191-
offset + 1,
192-
codeFeatures.navigation,
193-
];
194-
yield `'`;
195-
yield [
196-
'',
197-
'style_' + styleIndex,
198-
offset + classNameWithDot.length,
199-
codeFeatures.navigationWithoutRename,
200-
];
201-
yield `${optional ? '?' : ''}: ${propertyType}`;
202-
yield ` }`;
203-
}
204-
205141
function* generateCssVars(options: ScriptCodegenOptions, ctx: TemplateCodegenContext): Generator<Code> {
206142
if (!options.sfc.styles.length) {
207143
return;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { Code } from '../../types';
2+
import { codeFeatures } from '../script';
3+
import { newLine } from '../utils';
4+
5+
export function* generateClassProperty(
6+
styleIndex: number,
7+
classNameWithDot: string,
8+
offset: number,
9+
propertyType: string,
10+
optional: boolean
11+
): Generator<Code> {
12+
yield `${newLine} & { `;
13+
yield [
14+
'',
15+
'style_' + styleIndex,
16+
offset,
17+
codeFeatures.navigation,
18+
];
19+
yield `'`;
20+
yield [
21+
classNameWithDot.slice(1),
22+
'style_' + styleIndex,
23+
offset + 1,
24+
codeFeatures.navigation,
25+
];
26+
yield `'`;
27+
yield [
28+
'',
29+
'style_' + styleIndex,
30+
offset + classNameWithDot.length,
31+
codeFeatures.navigationWithoutRename,
32+
];
33+
yield `${optional ? '?' : ''}: ${propertyType}`;
34+
yield ` }`;
35+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Code, Sfc } from '../../types';
2+
import { codeFeatures } from '../script';
3+
import { generateSfcBlockAttrValue, newLine } from '../utils';
4+
5+
export function* generateExternalStylesheets(
6+
style: Sfc['styles'][number],
7+
): Generator<Code> {
8+
if (typeof style.src === 'object') {
9+
yield `${newLine} & typeof import(`;
10+
yield* generateSfcBlockAttrValue(style.src, style.src.text, codeFeatures.navigation);
11+
yield `).default`;
12+
}
13+
for (const { text, offset } of style.imports) {
14+
yield `${newLine} & typeof import('`;
15+
yield [
16+
text,
17+
style.name,
18+
offset,
19+
codeFeatures.navigation
20+
];
21+
yield `').default`;
22+
}
23+
}

0 commit comments

Comments
 (0)