akfun 5.3.3 → 5.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/package.json +6 -2
- package/src/loaders/component-scope-style-loader.js +0 -429
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
AKFun 是一个基于 Webpack 与 Rollup 的多场景前端打包工具,支持 Vue、React、React+TS 技术栈,致力于提供"零配置、开箱即用"的前端工程能力,让开发者专注于业务开发。
|
|
4
4
|
|
|
5
|
+
## 在线使用手册
|
|
6
|
+
[https://wibetter.github.io/akfun/](https://wibetter.github.io/akfun/)
|
|
7
|
+
|
|
8
|
+
国内访问地址: [https://akfun-docs.netlify.app/](https://akfun-docs.netlify.app/)。
|
|
9
|
+
|
|
5
10
|
## 目录
|
|
6
11
|
|
|
7
12
|
- [主要特性](#主要特性)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akfun",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.5",
|
|
4
4
|
"description": "前端脚手架:支持Vue技术栈和react技术栈",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"前端工程",
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
"main": "module/main.js",
|
|
19
19
|
"scripts": {
|
|
20
20
|
"akfun": "akfun",
|
|
21
|
+
"docs:dev": "vitepress dev docs",
|
|
22
|
+
"docs:build": "vitepress build docs",
|
|
23
|
+
"docs:preview": "vitepress preview docs",
|
|
21
24
|
"format": "prettier --write \"src/**/**/*.{js,vue,tsx,ts,scss,json}\""
|
|
22
25
|
},
|
|
23
26
|
"files": [
|
|
@@ -174,7 +177,8 @@
|
|
|
174
177
|
"@commitlint/config-conventional": "^20.4.2",
|
|
175
178
|
"husky": "^4.3.8",
|
|
176
179
|
"lint-staged": "^12.3.3",
|
|
177
|
-
"prettier": "^2.5.1"
|
|
180
|
+
"prettier": "^2.5.1",
|
|
181
|
+
"vitepress": "^1.3.0"
|
|
178
182
|
},
|
|
179
183
|
"overrides": {
|
|
180
184
|
"serialize-javascript": "^7.0.3",
|
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const curConfig = require('../config/index'); // 获取当前项目根目录下的配置文件
|
|
3
|
-
|
|
4
|
-
const DEFAULT_COMPONENTS_DIR = curConfig.componentsDir || './src/components';
|
|
5
|
-
const DEFAULT_SCOPE_KEY = 'data-scope';
|
|
6
|
-
|
|
7
|
-
function normalizePath(targetPath) {
|
|
8
|
-
return targetPath ? path.normalize(targetPath) : '';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 将驼峰命名转换为 kebab-case(短横线连接)
|
|
13
|
-
* @param {string} str - 输入字符串
|
|
14
|
-
* @returns {string} kebab-case 格式
|
|
15
|
-
*/
|
|
16
|
-
function camelToKebab(str) {
|
|
17
|
-
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* 将驼峰命名转换为 snake_case(下划线连接)
|
|
22
|
-
* @param {string} str - 输入字符串
|
|
23
|
-
* @returns {string} snake_case 格式
|
|
24
|
-
*/
|
|
25
|
-
function camelToSnake(str) {
|
|
26
|
-
return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* 生成组件名的所有可能变体(包括大小写、命名风格、container 后缀等)
|
|
31
|
-
* @param {string} componentName - 组件名称,如 simpleCmp__c
|
|
32
|
-
* @returns {string[]} 所有可能的变体数组
|
|
33
|
-
*/
|
|
34
|
-
function generateComponentNameVariants(componentName) {
|
|
35
|
-
if (!componentName) {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const variants = new Set();
|
|
40
|
-
|
|
41
|
-
// 原始名称
|
|
42
|
-
variants.add(componentName);
|
|
43
|
-
|
|
44
|
-
// 首字母大写
|
|
45
|
-
const capitalized = componentName.charAt(0).toUpperCase() + componentName.slice(1);
|
|
46
|
-
variants.add(capitalized);
|
|
47
|
-
|
|
48
|
-
// 全小写
|
|
49
|
-
variants.add(componentName.toLowerCase());
|
|
50
|
-
|
|
51
|
-
// 全大写
|
|
52
|
-
variants.add(componentName.toUpperCase());
|
|
53
|
-
|
|
54
|
-
// kebab-case(短横线连接)
|
|
55
|
-
const kebabCase = camelToKebab(componentName);
|
|
56
|
-
variants.add(kebabCase);
|
|
57
|
-
|
|
58
|
-
// snake_case(下划线连接)
|
|
59
|
-
const snakeCase = camelToSnake(componentName);
|
|
60
|
-
variants.add(snakeCase);
|
|
61
|
-
|
|
62
|
-
// 首字母大写的 kebab-case
|
|
63
|
-
const capitalizedKebab = kebabCase.charAt(0).toUpperCase() + kebabCase.slice(1);
|
|
64
|
-
variants.add(capitalizedKebab);
|
|
65
|
-
|
|
66
|
-
// 首字母大写的 snake_case
|
|
67
|
-
const capitalizedSnake = snakeCase.charAt(0).toUpperCase() + snakeCase.slice(1);
|
|
68
|
-
variants.add(capitalizedSnake);
|
|
69
|
-
|
|
70
|
-
// 生成带 container 后缀的变体
|
|
71
|
-
const containerSuffixes = ['-container', 'Container', '_container'];
|
|
72
|
-
const baseVariants = Array.from(variants);
|
|
73
|
-
baseVariants.forEach((variant) => {
|
|
74
|
-
containerSuffixes.forEach((suffix) => {
|
|
75
|
-
variants.add(variant + suffix);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
return Array.from(variants);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* 检查选择器是否匹配组件名(忽略大小写和命名风格)
|
|
84
|
-
* @param {string} selector - 选择器,如 .simpleCmp__c 或 #simpleCmp__c
|
|
85
|
-
* @param {string[]} componentNameVariants - 组件名的所有变体
|
|
86
|
-
* @returns {boolean} 是否匹配
|
|
87
|
-
*/
|
|
88
|
-
function isComponentRootSelector(selector, componentNameVariants) {
|
|
89
|
-
if (!selector || !componentNameVariants || componentNameVariants.length === 0) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const trimmedSelector = selector.trim();
|
|
94
|
-
|
|
95
|
-
// 提取类选择器或 ID 选择器的名称部分
|
|
96
|
-
// 匹配 .className 或 #idName 格式
|
|
97
|
-
const match = trimmedSelector.match(/^[.#]([a-zA-Z0-9_-]+)/);
|
|
98
|
-
if (!match) {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const selectorName = match[1];
|
|
103
|
-
|
|
104
|
-
// 检查是否匹配任何组件名变体(忽略大小写)
|
|
105
|
-
return componentNameVariants.some((variant) => {
|
|
106
|
-
return selectorName.toLowerCase() === variant.toLowerCase();
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* 为样式选择器添加作用域前缀
|
|
112
|
-
* @param {string} selector - 选择器字符串
|
|
113
|
-
* @param {string} scopeSelector - 作用域选择器,如 [data-scope="componentName"]
|
|
114
|
-
* @param {string[]} componentNameVariants - 组件名的所有变体,用于判断是否是最外层选择器
|
|
115
|
-
* @returns {string} 添加了作用域的选择器
|
|
116
|
-
*/
|
|
117
|
-
function addScopeToSelector(selector, scopeSelector, componentNameVariants = []) {
|
|
118
|
-
if (!selector || !selector.trim()) {
|
|
119
|
-
return selector;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const trimmedSelector = selector.trim();
|
|
123
|
-
|
|
124
|
-
// 处理 :global() 语法,不添加作用域
|
|
125
|
-
if (trimmedSelector.includes(':global(')) {
|
|
126
|
-
return selector;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 如果选择器已经是作用域选择器,直接返回
|
|
130
|
-
if (trimmedSelector.startsWith('[') && trimmedSelector.includes(scopeSelector)) {
|
|
131
|
-
return selector;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 处理多个选择器(逗号分隔)
|
|
135
|
-
if (trimmedSelector.includes(',')) {
|
|
136
|
-
return trimmedSelector
|
|
137
|
-
.split(',')
|
|
138
|
-
.map((sel) => addScopeToSelector(sel.trim(), scopeSelector, componentNameVariants))
|
|
139
|
-
.join(', ');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// 处理伪类和伪元素(如 :hover, ::before, :nth-child(2))
|
|
143
|
-
// 匹配格式:baseSelector:pseudo 或 baseSelector::pseudo
|
|
144
|
-
const pseudoMatch = trimmedSelector.match(
|
|
145
|
-
/^(.+?)(::?[a-zA-Z-]+(?:\([^)]*\))?(?:::?[a-zA-Z-]+(?:\([^)]*\))?)*)$/
|
|
146
|
-
);
|
|
147
|
-
if (pseudoMatch) {
|
|
148
|
-
const baseSelector = pseudoMatch[1].trim();
|
|
149
|
-
const pseudo = pseudoMatch[2];
|
|
150
|
-
// 为 baseSelector 添加作用域
|
|
151
|
-
const scopedBase = addScopeToSelector(baseSelector, scopeSelector, componentNameVariants);
|
|
152
|
-
return `${scopedBase}${pseudo}`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// 检查是否是最外层组件选择器(类选择器或 ID 选择器)
|
|
156
|
-
const isRootSelector = isComponentRootSelector(trimmedSelector, componentNameVariants);
|
|
157
|
-
|
|
158
|
-
// 处理普通选择器
|
|
159
|
-
if (trimmedSelector.startsWith('.') || trimmedSelector.startsWith('#')) {
|
|
160
|
-
// 如果是最外层组件选择器,直接拼接(无空格)
|
|
161
|
-
// 否则添加空格(包含在 scope 里面)
|
|
162
|
-
if (isRootSelector) {
|
|
163
|
-
return `${scopeSelector}${trimmedSelector}`;
|
|
164
|
-
} else {
|
|
165
|
-
return `${scopeSelector} ${trimmedSelector}`;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// 如果选择器以 [ 开头(属性选择器),直接拼接
|
|
170
|
-
if (trimmedSelector.startsWith('[')) {
|
|
171
|
-
return `${scopeSelector}${trimmedSelector}`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 处理标签选择器和其他选择器(添加空格)
|
|
175
|
-
return `${scopeSelector} ${trimmedSelector}`;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* 解析样式文件并添加作用域
|
|
180
|
-
* @param {string} source - 原始样式内容
|
|
181
|
-
* @param {string} scopeSelector - 作用域选择器
|
|
182
|
-
* @param {string[]} componentNameVariants - 组件名的所有变体
|
|
183
|
-
* @returns {string} 添加了作用域的样式内容
|
|
184
|
-
*/
|
|
185
|
-
function addScopeToStyles(source, scopeSelector, componentNameVariants = []) {
|
|
186
|
-
if (!source || !source.trim()) {
|
|
187
|
-
return source;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
let result = '';
|
|
191
|
-
let i = 0;
|
|
192
|
-
let depth = 0; // 大括号嵌套深度
|
|
193
|
-
let inString = false; // 是否在字符串中
|
|
194
|
-
let stringChar = ''; // 字符串的引号类型
|
|
195
|
-
let inComment = false; // 是否在注释中
|
|
196
|
-
let commentType = ''; // 注释类型:'//' 或 '/*'
|
|
197
|
-
let currentSelector = '';
|
|
198
|
-
let currentRule = '';
|
|
199
|
-
let braceStart = -1;
|
|
200
|
-
|
|
201
|
-
// 不需要添加作用域的 @ 规则(这些规则应该保持原样)
|
|
202
|
-
const skipScopeAtRules = ['@import', '@charset', '@namespace', '@font-face'];
|
|
203
|
-
// 需要递归处理的 @ 规则(内部的选择器也需要添加作用域)
|
|
204
|
-
const nestedAtRules = ['@media', '@supports', '@keyframes', '@page', '@viewport'];
|
|
205
|
-
let inAtRule = false;
|
|
206
|
-
let atRuleName = '';
|
|
207
|
-
let atRuleType = ''; // 'skip' 或 'nested'
|
|
208
|
-
|
|
209
|
-
while (i < source.length) {
|
|
210
|
-
const char = source[i];
|
|
211
|
-
const nextChar = source[i + 1] || '';
|
|
212
|
-
|
|
213
|
-
// 处理字符串
|
|
214
|
-
if (!inComment && (char === '"' || char === "'")) {
|
|
215
|
-
if (!inString) {
|
|
216
|
-
inString = true;
|
|
217
|
-
stringChar = char;
|
|
218
|
-
} else if (char === stringChar && source[i - 1] !== '\\') {
|
|
219
|
-
inString = false;
|
|
220
|
-
stringChar = '';
|
|
221
|
-
}
|
|
222
|
-
currentRule += char;
|
|
223
|
-
i++;
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// 处理注释
|
|
228
|
-
if (!inString) {
|
|
229
|
-
if (!inComment && char === '/' && nextChar === '/') {
|
|
230
|
-
inComment = true;
|
|
231
|
-
commentType = '//';
|
|
232
|
-
currentRule += char;
|
|
233
|
-
i++;
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
if (!inComment && char === '/' && nextChar === '*') {
|
|
237
|
-
inComment = true;
|
|
238
|
-
commentType = '/*';
|
|
239
|
-
currentRule += char;
|
|
240
|
-
i++;
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (inComment && commentType === '//' && char === '\n') {
|
|
244
|
-
inComment = false;
|
|
245
|
-
commentType = '';
|
|
246
|
-
currentRule += char;
|
|
247
|
-
i++;
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
if (inComment && commentType === '/*' && char === '*' && nextChar === '/') {
|
|
251
|
-
inComment = false;
|
|
252
|
-
commentType = '';
|
|
253
|
-
currentRule += char + nextChar;
|
|
254
|
-
i += 2;
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (inComment) {
|
|
258
|
-
currentRule += char;
|
|
259
|
-
i++;
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// 处理 @ 规则
|
|
265
|
-
if (!inString && !inComment && char === '@' && depth === 0) {
|
|
266
|
-
const remaining = source.substring(i);
|
|
267
|
-
// 检查是否是跳过作用域的规则
|
|
268
|
-
for (const atRule of skipScopeAtRules) {
|
|
269
|
-
if (remaining.startsWith(atRule)) {
|
|
270
|
-
inAtRule = true;
|
|
271
|
-
atRuleName = atRule;
|
|
272
|
-
atRuleType = 'skip';
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
// 检查是否是嵌套规则
|
|
277
|
-
if (!inAtRule) {
|
|
278
|
-
for (const atRule of nestedAtRules) {
|
|
279
|
-
if (remaining.startsWith(atRule)) {
|
|
280
|
-
inAtRule = true;
|
|
281
|
-
atRuleName = atRule;
|
|
282
|
-
atRuleType = 'nested';
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// 处理左大括号
|
|
290
|
-
if (!inString && !inComment && char === '{') {
|
|
291
|
-
if (depth === 0) {
|
|
292
|
-
// 保存当前选择器
|
|
293
|
-
currentSelector = currentRule.trim();
|
|
294
|
-
currentRule = '';
|
|
295
|
-
braceStart = i;
|
|
296
|
-
}
|
|
297
|
-
depth++;
|
|
298
|
-
currentRule += char;
|
|
299
|
-
i++;
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// 处理右大括号
|
|
304
|
-
if (!inString && !inComment && char === '}') {
|
|
305
|
-
depth--;
|
|
306
|
-
currentRule += char;
|
|
307
|
-
|
|
308
|
-
if (depth === 0) {
|
|
309
|
-
// 处理完整的规则块
|
|
310
|
-
if (inAtRule) {
|
|
311
|
-
if (atRuleType === 'skip') {
|
|
312
|
-
// 跳过作用域的 @ 规则直接添加
|
|
313
|
-
result += currentSelector + currentRule;
|
|
314
|
-
} else if (atRuleType === 'nested') {
|
|
315
|
-
// 嵌套 @ 规则:为内部的选择器添加作用域
|
|
316
|
-
const innerContent = currentRule.slice(1, -1); // 去掉外层大括号
|
|
317
|
-
const scopedInnerContent = addScopeToStyles(
|
|
318
|
-
innerContent,
|
|
319
|
-
scopeSelector,
|
|
320
|
-
componentNameVariants
|
|
321
|
-
);
|
|
322
|
-
result += currentSelector + '{' + scopedInnerContent + '}';
|
|
323
|
-
} else {
|
|
324
|
-
result += currentSelector + currentRule;
|
|
325
|
-
}
|
|
326
|
-
inAtRule = false;
|
|
327
|
-
atRuleName = '';
|
|
328
|
-
atRuleType = '';
|
|
329
|
-
} else {
|
|
330
|
-
// 普通规则,为选择器添加作用域
|
|
331
|
-
const scopedSelector = addScopeToSelector(
|
|
332
|
-
currentSelector,
|
|
333
|
-
scopeSelector,
|
|
334
|
-
componentNameVariants
|
|
335
|
-
);
|
|
336
|
-
result += scopedSelector + currentRule;
|
|
337
|
-
}
|
|
338
|
-
currentSelector = '';
|
|
339
|
-
currentRule = '';
|
|
340
|
-
braceStart = -1;
|
|
341
|
-
}
|
|
342
|
-
i++;
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// 其他字符
|
|
347
|
-
currentRule += char;
|
|
348
|
-
i++;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// 处理文件末尾可能剩余的内容
|
|
352
|
-
if (currentRule.trim()) {
|
|
353
|
-
if (depth === 0 && currentSelector) {
|
|
354
|
-
const scopedSelector = addScopeToSelector(
|
|
355
|
-
currentSelector,
|
|
356
|
-
scopeSelector,
|
|
357
|
-
componentNameVariants
|
|
358
|
-
);
|
|
359
|
-
result += scopedSelector + currentRule;
|
|
360
|
-
} else {
|
|
361
|
-
result += currentRule;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return result || source;
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* 自动添加组件样式作用域
|
|
369
|
-
* @param {string} source - 原始样式内容
|
|
370
|
-
* @returns {string} 添加了作用域的样式内容
|
|
371
|
-
* 实现关键路径:
|
|
372
|
-
* 1. 判断是否是目标文件
|
|
373
|
-
* 2. 获取组件名
|
|
374
|
-
* 3. 生成组件名的所有可能变体
|
|
375
|
-
* 4. 为选择器添加作用域
|
|
376
|
-
* 5. 返回添加了作用域的样式内容
|
|
377
|
-
*
|
|
378
|
-
* 特别说明,组件根节点的样式 需要和组件目录名称 产生关联,不然其根节点的样式会失效。
|
|
379
|
-
*/
|
|
380
|
-
module.exports = function componentScopeStyleLoader(source) {
|
|
381
|
-
if (typeof this?.cacheable === 'function') {
|
|
382
|
-
this.cacheable();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const options =
|
|
386
|
-
(typeof this?.getOptions === 'function' && this.getOptions()) || this?.query || {};
|
|
387
|
-
const scopeKey = options.scopeKey || DEFAULT_SCOPE_KEY;
|
|
388
|
-
const componentsDir = options.componentsDir || DEFAULT_COMPONENTS_DIR;
|
|
389
|
-
|
|
390
|
-
const resourcePath = this.resourcePath || '';
|
|
391
|
-
const isTargetFile = /(index|style)\.(scss|less)$/i.test(resourcePath);
|
|
392
|
-
if (!isTargetFile) {
|
|
393
|
-
return source;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const componentsDirAbs = path.isAbsolute(componentsDir)
|
|
397
|
-
? componentsDir
|
|
398
|
-
: path.resolve(process.cwd(), componentsDir);
|
|
399
|
-
|
|
400
|
-
const normalizedResourcePath = normalizePath(resourcePath);
|
|
401
|
-
const normalizedCmpDir = normalizePath(componentsDirAbs + path.sep);
|
|
402
|
-
|
|
403
|
-
// 仅处理位于组件目录下的样式文件
|
|
404
|
-
if (!normalizedResourcePath.startsWith(normalizedCmpDir)) {
|
|
405
|
-
return source;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// 组件目录的第一层子目录名即组件名
|
|
409
|
-
const relativePath = path.relative(componentsDirAbs, resourcePath);
|
|
410
|
-
const pathParts = relativePath.split(path.sep);
|
|
411
|
-
const cmpName = pathParts[0];
|
|
412
|
-
|
|
413
|
-
if (!cmpName) {
|
|
414
|
-
return source;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// 非组件直接子目录下的样式也不处理
|
|
418
|
-
if (pathParts.length > 2) {
|
|
419
|
-
return source;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// 生成组件名的所有可能变体
|
|
423
|
-
const componentNameVariants = generateComponentNameVariants(cmpName);
|
|
424
|
-
|
|
425
|
-
const scopeSelector = `[${scopeKey}="${cmpName}"]`;
|
|
426
|
-
const scopedContent = addScopeToStyles(source, scopeSelector, componentNameVariants);
|
|
427
|
-
|
|
428
|
-
return scopedContent;
|
|
429
|
-
};
|