@htmlplus/element 3.3.0 → 3.4.0
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/dist/bundlers.d.ts +5 -5
- package/dist/bundlers.js +4 -4
- package/dist/client.d.ts +51 -26
- package/dist/client.js +710 -633
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +2 -1
- package/dist/jsx-runtime.d.ts +183 -183
- package/dist/transformer.d.ts +45 -40
- package/dist/transformer.js +394 -278
- package/package.json +96 -92
package/dist/transformer.js
CHANGED
|
@@ -1,99 +1,29 @@
|
|
|
1
|
-
import generator from '@babel/generator';
|
|
2
1
|
import t from '@babel/types';
|
|
3
|
-
import traverse from '@babel/traverse';
|
|
4
2
|
import { parse as parse$1 } from '@babel/parser';
|
|
5
3
|
import fs from 'fs-extra';
|
|
6
4
|
import { glob } from 'glob';
|
|
7
5
|
import template from '@babel/template';
|
|
8
6
|
import { pascalCase, kebabCase, camelCase, capitalCase } from 'change-case';
|
|
9
|
-
import ora from 'ora';
|
|
10
7
|
import path, { join, resolve, dirname } from 'node:path';
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
});
|
|
16
|
-
const log = (message, persist) => {
|
|
17
|
-
const content = `${new Date().toLocaleTimeString()} [${KEY}] ${message}`;
|
|
18
|
-
const log = logger.start(content);
|
|
19
|
-
if (!persist)
|
|
20
|
-
return;
|
|
21
|
-
log.succeed();
|
|
22
|
-
};
|
|
23
|
-
const transformer = (...plugins) => {
|
|
24
|
-
let global = {
|
|
25
|
-
contexts: []
|
|
26
|
-
};
|
|
27
|
-
const start = async () => {
|
|
28
|
-
log(`Started.`, true);
|
|
29
|
-
log(`${plugins.length} plugins detected.`, true);
|
|
30
|
-
log(`Plugins are starting.`, true);
|
|
31
|
-
for (const plugin of plugins) {
|
|
32
|
-
if (!plugin.start)
|
|
33
|
-
continue;
|
|
34
|
-
log(`Plugin '${plugin.name}' is starting.`);
|
|
35
|
-
global = (await plugin.start(global)) || global;
|
|
36
|
-
log(`Plugin '${plugin.name}' started successfully.`);
|
|
37
|
-
}
|
|
38
|
-
log(`Plugins have been successfully started.`, true);
|
|
39
|
-
};
|
|
40
|
-
const run = async (filePath) => {
|
|
41
|
-
path.join(filePath).split(path.sep).pop();
|
|
42
|
-
let context = {
|
|
43
|
-
filePath
|
|
44
|
-
};
|
|
45
|
-
const parsed = path.parse(filePath);
|
|
46
|
-
for (const plugin of plugins) {
|
|
47
|
-
if (!plugin.run)
|
|
48
|
-
continue;
|
|
49
|
-
const source = path.join(parsed.dir).split(path.sep).slice(-2).concat(parsed.base).join('/');
|
|
50
|
-
log(`Plugin '${plugin.name}' is executing on '${source}' file.`);
|
|
51
|
-
try {
|
|
52
|
-
context = (await plugin.run(context, global)) || context;
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
log(`Error in '${plugin.name}' plugin on '${source}' file.\n`, true);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
global.contexts = global.contexts
|
|
59
|
-
.filter((current) => {
|
|
60
|
-
return current.filePath != context.filePath;
|
|
61
|
-
})
|
|
62
|
-
.concat(context);
|
|
63
|
-
log(`Plugin '${plugin.name}' executed successfully on '${source}' file.`);
|
|
64
|
-
}
|
|
65
|
-
logger.stop();
|
|
66
|
-
return context;
|
|
67
|
-
};
|
|
68
|
-
const finish = async () => {
|
|
69
|
-
log(`Plugins are finishing.`, true);
|
|
70
|
-
for (const plugin of plugins) {
|
|
71
|
-
if (!plugin.finish)
|
|
72
|
-
continue;
|
|
73
|
-
log(`Plugin '${plugin.name}' is finishing.`);
|
|
74
|
-
global = (await plugin.finish(global)) || global;
|
|
75
|
-
log(`Plugin '${plugin.name}' finished successfully.`);
|
|
76
|
-
}
|
|
77
|
-
log(`Plugins have been successfully finished.`, true);
|
|
78
|
-
log(`Finished.`, true);
|
|
79
|
-
};
|
|
80
|
-
return { global, start, run, finish };
|
|
81
|
-
};
|
|
8
|
+
import { COMMENT_AUTO_ADDED, DECORATOR_PROPERTY, STATIC_TAG, DECORATOR_PROPERTY_TYPE, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL, UTILS_PATH, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, ELEMENT_HOST_NAME, TYPE_OBJECT, TYPE_NULL, TYPE_ARRAY, TYPE_STRING, TYPE_ENUM, TYPE_NUMBER, TYPE_DATE, TYPE_BOOLEAN, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, DECORATOR_CSS_VARIABLE, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_STATE, STATIC_STYLE, STYLE_IMPORTED, PACKAGE_NAME, DECORATOR_ELEMENT, KEY } from './constants.js';
|
|
9
|
+
import core from '@babel/traverse';
|
|
10
|
+
import core$1 from '@babel/generator';
|
|
11
|
+
import ora from 'ora';
|
|
82
12
|
|
|
83
13
|
const ASSETS_OPTIONS = {
|
|
84
14
|
destination(context) {
|
|
85
|
-
return path.join('dist', 'assets', context.fileName);
|
|
15
|
+
return path.join('dist', 'assets', context.fileName || '');
|
|
86
16
|
},
|
|
87
17
|
source(context) {
|
|
88
|
-
return path.join(context.directoryPath, 'assets');
|
|
18
|
+
return path.join(context.directoryPath || '', 'assets');
|
|
89
19
|
},
|
|
90
20
|
json(context) {
|
|
91
|
-
return path.join('dist', 'assets', context.fileName
|
|
21
|
+
return path.join('dist', 'assets', `${context.fileName || ''}.json`);
|
|
92
22
|
}
|
|
93
23
|
};
|
|
94
|
-
const assets = (
|
|
24
|
+
const assets = (userOptions) => {
|
|
95
25
|
const name = 'assets';
|
|
96
|
-
options = Object.assign({}, ASSETS_OPTIONS,
|
|
26
|
+
const options = Object.assign({}, ASSETS_OPTIONS, userOptions);
|
|
97
27
|
const finish = (global) => {
|
|
98
28
|
for (const context of global.contexts) {
|
|
99
29
|
context.assetsDestination = options.destination(context);
|
|
@@ -115,16 +45,16 @@ const assets = (options) => {
|
|
|
115
45
|
};
|
|
116
46
|
|
|
117
47
|
const COPY_OPTIONS = {
|
|
118
|
-
at: 'start'
|
|
48
|
+
at: 'start',
|
|
49
|
+
transformer: (content) => content
|
|
119
50
|
};
|
|
120
|
-
const copy = (
|
|
51
|
+
const copy = (userOptions) => {
|
|
121
52
|
const name = 'copy';
|
|
122
|
-
options = Object.assign({}, COPY_OPTIONS,
|
|
53
|
+
const options = Object.assign({}, COPY_OPTIONS, userOptions);
|
|
123
54
|
const copy = (caller) => {
|
|
124
|
-
if (options.at
|
|
55
|
+
if (options.at !== caller)
|
|
125
56
|
return;
|
|
126
|
-
let content;
|
|
127
|
-
content = fs.readFileSync(options.source, 'utf8');
|
|
57
|
+
let content = fs.readFileSync(options.source, 'utf8');
|
|
128
58
|
if (options.transformer)
|
|
129
59
|
content = options.transformer(content);
|
|
130
60
|
fs.ensureDirSync(path.dirname(options.destination));
|
|
@@ -142,11 +72,10 @@ const copy = (options) => {
|
|
|
142
72
|
return { name, start, run, finish };
|
|
143
73
|
};
|
|
144
74
|
|
|
145
|
-
|
|
146
|
-
const visitor =
|
|
147
|
-
(traverse.default || traverse)(ast, options);
|
|
148
|
-
};
|
|
75
|
+
const traverse = (core.default || core);
|
|
76
|
+
const visitor = traverse;
|
|
149
77
|
|
|
78
|
+
// biome-ignore-all lint: TODO
|
|
150
79
|
function addDependency(path, source, local, imported, comment) {
|
|
151
80
|
const isDefault = local && !imported;
|
|
152
81
|
const isImport = local && imported;
|
|
@@ -158,7 +87,7 @@ function addDependency(path, source, local, imported, comment) {
|
|
|
158
87
|
file = file.node || file;
|
|
159
88
|
visitor(file, {
|
|
160
89
|
ImportDeclaration(path) {
|
|
161
|
-
if (path.node.source.value
|
|
90
|
+
if (path.node.source.value !== source)
|
|
162
91
|
return;
|
|
163
92
|
declaration = path.node;
|
|
164
93
|
}
|
|
@@ -169,10 +98,10 @@ function addDependency(path, source, local, imported, comment) {
|
|
|
169
98
|
};
|
|
170
99
|
let specifier = declaration?.specifiers.find((specifier) => {
|
|
171
100
|
if (isDefault) {
|
|
172
|
-
return specifier.type
|
|
101
|
+
return specifier.type === 'ImportDefaultSpecifier';
|
|
173
102
|
}
|
|
174
103
|
else if (isImport) {
|
|
175
|
-
return specifier.imported?.name
|
|
104
|
+
return specifier.imported?.name === imported;
|
|
176
105
|
}
|
|
177
106
|
});
|
|
178
107
|
if (specifier)
|
|
@@ -211,10 +140,11 @@ function addDependency(path, source, local, imported, comment) {
|
|
|
211
140
|
|
|
212
141
|
const extractAttribute = (property) => {
|
|
213
142
|
try {
|
|
143
|
+
// biome-ignore lint: Keep using `any` type because of complexity
|
|
214
144
|
return property.decorators
|
|
215
|
-
.find((decorator) => decorator.expression.callee.name
|
|
216
|
-
.expression.arguments
|
|
217
|
-
.value;
|
|
145
|
+
.find((decorator) => decorator.expression.callee.name === DECORATOR_PROPERTY)
|
|
146
|
+
.expression.arguments.at(0)
|
|
147
|
+
.properties.find((property) => property.key.name === 'attribute').value.value;
|
|
218
148
|
}
|
|
219
149
|
catch { }
|
|
220
150
|
};
|
|
@@ -225,12 +155,12 @@ const extractFromComment = (node, whitelist) => {
|
|
|
225
155
|
description: ''
|
|
226
156
|
};
|
|
227
157
|
const lines = node.leadingComments
|
|
228
|
-
?.
|
|
229
|
-
if (comment.type
|
|
158
|
+
?.flatMap((comment) => {
|
|
159
|
+
if (comment.type === 'CommentLine') {
|
|
230
160
|
return comment.value;
|
|
161
|
+
}
|
|
231
162
|
return comment.value.split('\n');
|
|
232
163
|
})
|
|
233
|
-
?.flat()
|
|
234
164
|
?.map((line) => line.trim().replace(/^\*/, '').trim())
|
|
235
165
|
?.filter((line) => line.trim());
|
|
236
166
|
for (const line of lines || []) {
|
|
@@ -240,7 +170,7 @@ const extractFromComment = (node, whitelist) => {
|
|
|
240
170
|
}
|
|
241
171
|
if (!normalized.length)
|
|
242
172
|
normalized.push('');
|
|
243
|
-
normalized[normalized.length - 1] +=
|
|
173
|
+
normalized[normalized.length - 1] += ` ${line}`;
|
|
244
174
|
}
|
|
245
175
|
for (const line of normalized) {
|
|
246
176
|
if (!line.startsWith('@')) {
|
|
@@ -255,11 +185,14 @@ const extractFromComment = (node, whitelist) => {
|
|
|
255
185
|
const type = groups[2]?.trim().slice(1, -1);
|
|
256
186
|
const name = groups[3]?.trim();
|
|
257
187
|
const description = groups[4]?.trim();
|
|
188
|
+
// TODO
|
|
189
|
+
// const [, tag, type, name, description] = groups.map((g) => g?.trim() || '');
|
|
258
190
|
if (name && description) {
|
|
259
|
-
const key = tag
|
|
191
|
+
const key = `${tag}s`;
|
|
260
192
|
if (whitelist && !whitelist.includes(key))
|
|
261
193
|
continue;
|
|
262
|
-
|
|
194
|
+
result[key] ||= [];
|
|
195
|
+
result[key].push({ name, type, description });
|
|
263
196
|
}
|
|
264
197
|
else {
|
|
265
198
|
const key = tag;
|
|
@@ -272,18 +205,30 @@ const extractFromComment = (node, whitelist) => {
|
|
|
272
205
|
};
|
|
273
206
|
|
|
274
207
|
const getInitializer = (node) => {
|
|
208
|
+
// biome-ignore lint: Keep using `any` type because of complexity
|
|
275
209
|
return node?.extra?.raw || node?.['value'];
|
|
276
210
|
};
|
|
277
211
|
|
|
212
|
+
const getTypeReferenceName = (ref) => {
|
|
213
|
+
switch (ref.typeName.type) {
|
|
214
|
+
case 'Identifier':
|
|
215
|
+
return ref.typeName.name;
|
|
216
|
+
default:
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
278
220
|
const getType = (directory, file, node) => {
|
|
279
221
|
if (!node)
|
|
280
222
|
return node;
|
|
281
|
-
if (node.type
|
|
223
|
+
if (node.type !== 'TSTypeReference')
|
|
282
224
|
return node;
|
|
283
225
|
let result;
|
|
226
|
+
const typeName = getTypeReferenceName(node);
|
|
227
|
+
if (!typeName)
|
|
228
|
+
return node;
|
|
284
229
|
visitor(file, {
|
|
285
230
|
ClassDeclaration(path) {
|
|
286
|
-
if (path.node.id
|
|
231
|
+
if (path.node.id?.name !== typeName)
|
|
287
232
|
return;
|
|
288
233
|
result = path.node;
|
|
289
234
|
path.stop();
|
|
@@ -291,31 +236,25 @@ const getType = (directory, file, node) => {
|
|
|
291
236
|
ImportDeclaration(path) {
|
|
292
237
|
for (const specifier of path.node.specifiers) {
|
|
293
238
|
const alias = specifier.local.name;
|
|
294
|
-
if (alias
|
|
239
|
+
if (alias !== typeName)
|
|
295
240
|
continue;
|
|
296
|
-
switch (specifier.type) {
|
|
297
|
-
case 'ImportNamespaceSpecifier':
|
|
298
|
-
break;
|
|
299
|
-
case 'ImportDefaultSpecifier':
|
|
300
|
-
break;
|
|
301
|
-
case 'ImportSpecifier':
|
|
302
|
-
specifier.imported.name;
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
241
|
try {
|
|
306
242
|
const reference = glob
|
|
307
243
|
.sync(['.ts*', '/index.ts*'].map((key) => {
|
|
308
244
|
return join(directory, path.node.source.value).replace(/\\/g, '/') + key;
|
|
309
245
|
}))
|
|
310
|
-
.find((reference) => fs.existsSync(reference));
|
|
246
|
+
.find((reference) => reference && fs.existsSync(reference));
|
|
247
|
+
if (!reference)
|
|
248
|
+
continue;
|
|
311
249
|
const content = fs.readFileSync(reference, 'utf8');
|
|
312
|
-
const filePath = resolve(directory, path.node.source.value
|
|
313
|
-
|
|
250
|
+
const filePath = resolve(directory, `${path.node.source.value}.ts`);
|
|
251
|
+
const pathWithAst = path;
|
|
252
|
+
pathWithAst.$ast ||= parse$1(content, {
|
|
314
253
|
allowImportExportEverywhere: true,
|
|
315
254
|
plugins: ['typescript'],
|
|
316
255
|
ranges: false
|
|
317
256
|
});
|
|
318
|
-
result = getType(dirname(filePath),
|
|
257
|
+
result = getType(dirname(filePath), pathWithAst.$ast, node);
|
|
319
258
|
}
|
|
320
259
|
catch { }
|
|
321
260
|
path.stop();
|
|
@@ -323,32 +262,35 @@ const getType = (directory, file, node) => {
|
|
|
323
262
|
}
|
|
324
263
|
},
|
|
325
264
|
TSInterfaceDeclaration(path) {
|
|
326
|
-
if (path.node.id.name
|
|
265
|
+
if (path.node.id.name !== typeName)
|
|
327
266
|
return;
|
|
328
267
|
result = path.node;
|
|
329
268
|
path.stop();
|
|
330
269
|
},
|
|
331
270
|
TSTypeAliasDeclaration(path) {
|
|
332
|
-
if (path.node.id.name
|
|
271
|
+
if (path.node.id.name !== typeName)
|
|
333
272
|
return;
|
|
334
|
-
|
|
335
|
-
switch (
|
|
336
|
-
case 'TSUnionType':
|
|
273
|
+
const typeAnnotation = path.node.typeAnnotation;
|
|
274
|
+
switch (typeAnnotation.type) {
|
|
275
|
+
case 'TSUnionType': {
|
|
337
276
|
const types = [];
|
|
338
|
-
for (const prev of
|
|
277
|
+
for (const prev of typeAnnotation.types) {
|
|
339
278
|
const next = getType(directory, file, prev);
|
|
340
|
-
if (next.type
|
|
341
|
-
|
|
279
|
+
if (next.type === 'TSUnionType') {
|
|
280
|
+
types.push(...next.types);
|
|
342
281
|
}
|
|
343
282
|
else {
|
|
344
283
|
types.push(next);
|
|
345
284
|
}
|
|
346
285
|
}
|
|
347
|
-
|
|
286
|
+
typeAnnotation.types = types;
|
|
287
|
+
result = typeAnnotation;
|
|
348
288
|
break;
|
|
349
|
-
|
|
350
|
-
|
|
289
|
+
}
|
|
290
|
+
default: {
|
|
291
|
+
result = getType(directory, file, typeAnnotation);
|
|
351
292
|
break;
|
|
293
|
+
}
|
|
352
294
|
}
|
|
353
295
|
path.stop();
|
|
354
296
|
}
|
|
@@ -359,24 +301,17 @@ const getType = (directory, file, node) => {
|
|
|
359
301
|
const getTypeReference = (file, node) => {
|
|
360
302
|
if (!node)
|
|
361
303
|
return;
|
|
362
|
-
if (node.type
|
|
304
|
+
if (node.type !== 'TSTypeReference')
|
|
363
305
|
return;
|
|
364
306
|
let result;
|
|
365
307
|
visitor(file, {
|
|
366
308
|
ImportDeclaration(path) {
|
|
367
309
|
for (const specifier of path.node.specifiers) {
|
|
368
310
|
const alias = specifier.local.name;
|
|
369
|
-
if (
|
|
311
|
+
if (node.typeName.type !== 'Identifier')
|
|
312
|
+
continue;
|
|
313
|
+
if (alias !== node.typeName.name)
|
|
370
314
|
continue;
|
|
371
|
-
switch (specifier.type) {
|
|
372
|
-
case 'ImportNamespaceSpecifier':
|
|
373
|
-
break;
|
|
374
|
-
case 'ImportDefaultSpecifier':
|
|
375
|
-
break;
|
|
376
|
-
case 'ImportSpecifier':
|
|
377
|
-
specifier.imported.name;
|
|
378
|
-
break;
|
|
379
|
-
}
|
|
380
315
|
result = path.node.source.value;
|
|
381
316
|
path.stop();
|
|
382
317
|
break;
|
|
@@ -387,38 +322,51 @@ const getTypeReference = (file, node) => {
|
|
|
387
322
|
};
|
|
388
323
|
|
|
389
324
|
const hasDecorator = (node, name) => {
|
|
325
|
+
if ('decorators' in node === false)
|
|
326
|
+
return false;
|
|
390
327
|
if (!node.decorators)
|
|
391
328
|
return false;
|
|
392
|
-
|
|
329
|
+
for (const decorator of node.decorators) {
|
|
330
|
+
const expression = decorator.expression;
|
|
331
|
+
if (!t.isCallExpression(expression))
|
|
332
|
+
continue;
|
|
333
|
+
if (!t.isIdentifier(expression.callee))
|
|
334
|
+
continue;
|
|
335
|
+
if (expression.callee.name === name) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return false;
|
|
393
340
|
};
|
|
394
341
|
|
|
395
|
-
|
|
342
|
+
const generator = (core$1.default || core$1);
|
|
396
343
|
const print = (ast) => {
|
|
397
|
-
// TODO: the `ast` should not be undefined
|
|
398
344
|
if (!ast)
|
|
399
345
|
return '';
|
|
400
|
-
return
|
|
346
|
+
return generator(ast, { decoratorsBeforeExport: true }).code;
|
|
401
347
|
};
|
|
402
348
|
|
|
403
349
|
const CUSTOM_ELEMENT_OPTIONS = {
|
|
404
|
-
prefix:
|
|
350
|
+
prefix: '',
|
|
405
351
|
typings: true
|
|
406
352
|
};
|
|
407
353
|
// TODO: support {variable && jsxElement}
|
|
408
|
-
const customElement = (
|
|
354
|
+
const customElement = (userOptions) => {
|
|
409
355
|
const name = 'customElement';
|
|
410
|
-
options = Object.assign({}, CUSTOM_ELEMENT_OPTIONS,
|
|
356
|
+
const options = Object.assign({}, CUSTOM_ELEMENT_OPTIONS, userOptions);
|
|
411
357
|
const run = (context) => {
|
|
358
|
+
if (!context.fileAST)
|
|
359
|
+
return;
|
|
412
360
|
const ast = t.cloneNode(context.fileAST, true);
|
|
413
|
-
context.elementTagName = `${options.prefix
|
|
361
|
+
context.elementTagName = `${options.prefix}${context.elementKey}`;
|
|
414
362
|
context.elementInterfaceName = `HTML${pascalCase(context.elementTagName)}Element`;
|
|
415
363
|
// attach tag name
|
|
416
364
|
visitor(ast, {
|
|
417
365
|
ClassDeclaration(path) {
|
|
418
366
|
const { body, id } = path.node;
|
|
419
|
-
if (id
|
|
367
|
+
if (id?.name !== context.className)
|
|
420
368
|
return;
|
|
421
|
-
const node = t.classProperty(t.identifier(STATIC_TAG), t.stringLiteral(context.elementTagName), undefined, undefined, undefined, true);
|
|
369
|
+
const node = t.classProperty(t.identifier(STATIC_TAG), t.stringLiteral(context.elementTagName || ''), undefined, undefined, undefined, true);
|
|
422
370
|
t.addComment(node, 'leading', COMMENT_AUTO_ADDED, true);
|
|
423
371
|
body.body.unshift(node);
|
|
424
372
|
}
|
|
@@ -427,15 +375,18 @@ const customElement = (options) => {
|
|
|
427
375
|
visitor(ast, {
|
|
428
376
|
JSXAttribute(path) {
|
|
429
377
|
const { name, value } = path.node;
|
|
430
|
-
if (name.name
|
|
378
|
+
if (name.name !== 'style')
|
|
431
379
|
return;
|
|
432
380
|
if (!value)
|
|
433
381
|
return;
|
|
434
|
-
if (value.type
|
|
382
|
+
if (value.type !== 'JSXExpressionContainer')
|
|
383
|
+
return;
|
|
384
|
+
if (!value.expression)
|
|
385
|
+
return;
|
|
386
|
+
if (value.expression.type === 'JSXEmptyExpression')
|
|
435
387
|
return;
|
|
436
388
|
const { local } = addDependency(path, UTILS_PATH, UTILS_STYLES_LOCAL, UTILS_STYLES_IMPORTED);
|
|
437
|
-
|
|
438
|
-
path.replaceWith(t.jsxAttribute(t.jsxIdentifier('style'), t.jsxExpressionContainer(t.callExpression(t.identifier(local), [value.expression]))));
|
|
389
|
+
path.replaceWith(t.jsxAttribute(t.jsxIdentifier('style'), t.jsxExpressionContainer(t.callExpression(t.identifier(local || ''), [value.expression]))));
|
|
439
390
|
path.skip();
|
|
440
391
|
}
|
|
441
392
|
});
|
|
@@ -443,10 +394,14 @@ const customElement = (options) => {
|
|
|
443
394
|
visitor(ast, {
|
|
444
395
|
JSXAttribute(path) {
|
|
445
396
|
const { name, value } = path.node;
|
|
446
|
-
if (name.name
|
|
397
|
+
if (name.name !== 'className')
|
|
447
398
|
return;
|
|
448
|
-
|
|
449
|
-
return
|
|
399
|
+
if (!value)
|
|
400
|
+
return;
|
|
401
|
+
if (!t.isJSXOpeningElement(path.parent))
|
|
402
|
+
return;
|
|
403
|
+
const hasClass = path.parent.attributes.some((attribute) => {
|
|
404
|
+
return t.isJSXAttribute(attribute) && attribute.name.name === 'class';
|
|
450
405
|
});
|
|
451
406
|
if (hasClass)
|
|
452
407
|
return path.remove();
|
|
@@ -457,12 +412,14 @@ const customElement = (options) => {
|
|
|
457
412
|
visitor(ast, {
|
|
458
413
|
JSXAttribute(path) {
|
|
459
414
|
const { name, value } = path.node;
|
|
460
|
-
if (
|
|
461
|
-
|
|
415
|
+
if (!t.isJSXIdentifier(name))
|
|
416
|
+
return;
|
|
417
|
+
if (name.name === 'value') {
|
|
418
|
+
name.name = `.${name.name}`;
|
|
462
419
|
return;
|
|
463
420
|
}
|
|
464
|
-
if (name.name
|
|
465
|
-
name.name =
|
|
421
|
+
if (name.name === 'disabled') {
|
|
422
|
+
name.name = `.${name.name}`;
|
|
466
423
|
return;
|
|
467
424
|
}
|
|
468
425
|
const key = ['tabIndex', 'viewBox'];
|
|
@@ -480,7 +437,7 @@ const customElement = (options) => {
|
|
|
480
437
|
return;
|
|
481
438
|
const TODO = (node, attributes) => {
|
|
482
439
|
const { local } = addDependency(path, UTILS_PATH, UTILS_ATTRIBUTES_LOCAL, UTILS_ATTRIBUTES_IMPORTED);
|
|
483
|
-
return t.callExpression(t.identifier(local), [
|
|
440
|
+
return t.callExpression(t.identifier(local || ''), [
|
|
484
441
|
node,
|
|
485
442
|
t.arrayExpression(attributes.map((attribute) => {
|
|
486
443
|
switch (attribute.type) {
|
|
@@ -488,7 +445,7 @@ const customElement = (options) => {
|
|
|
488
445
|
return attribute.argument;
|
|
489
446
|
default:
|
|
490
447
|
return t.objectExpression([
|
|
491
|
-
t.objectProperty(t.stringLiteral(attribute.name.name), attribute.value?.type
|
|
448
|
+
t.objectProperty(t.stringLiteral(attribute.name.name), attribute.value?.type === 'JSXExpressionContainer'
|
|
492
449
|
? attribute.value.expression
|
|
493
450
|
: attribute.value || t.booleanLiteral(true))
|
|
494
451
|
]);
|
|
@@ -498,22 +455,22 @@ const customElement = (options) => {
|
|
|
498
455
|
};
|
|
499
456
|
const render = (node) => {
|
|
500
457
|
switch (node.type) {
|
|
501
|
-
case 'JSXElement':
|
|
458
|
+
case 'JSXElement': {
|
|
502
459
|
const attributes = node.openingElement.attributes;
|
|
503
|
-
const isHost = node.openingElement.name.name
|
|
460
|
+
const isHost = node.openingElement.name.name === ELEMENT_HOST_NAME;
|
|
504
461
|
// TODO
|
|
505
462
|
if (isHost) {
|
|
506
|
-
const children = node.children.
|
|
463
|
+
const children = node.children.flatMap(render);
|
|
507
464
|
if (!attributes.length)
|
|
508
465
|
return children;
|
|
509
466
|
return [TODO(t.thisExpression(), attributes), ...children];
|
|
510
467
|
}
|
|
511
468
|
const name = node.openingElement.name.name;
|
|
512
|
-
const children = node.children.
|
|
469
|
+
const children = node.children.flatMap(render);
|
|
513
470
|
const parts = [];
|
|
514
471
|
parts.push('<', name);
|
|
515
472
|
const hasSpreadAttribute = attributes.some((attribute) => {
|
|
516
|
-
return attribute.type
|
|
473
|
+
return attribute.type === 'JSXSpreadAttribute';
|
|
517
474
|
});
|
|
518
475
|
if (hasSpreadAttribute) {
|
|
519
476
|
parts.push(' ', 'ref=', t.arrowFunctionExpression([t.identifier('$element')], TODO(t.identifier('$element'), attributes)));
|
|
@@ -522,7 +479,7 @@ const customElement = (options) => {
|
|
|
522
479
|
for (const attribute of attributes) {
|
|
523
480
|
switch (attribute.type) {
|
|
524
481
|
case 'JSXAttribute':
|
|
525
|
-
if (attribute.name.name
|
|
482
|
+
if (attribute.name.name === 'dangerouslySetInnerHTML') {
|
|
526
483
|
try {
|
|
527
484
|
parts.push(' ', '.innerHTML');
|
|
528
485
|
parts.push('=');
|
|
@@ -556,12 +513,13 @@ const customElement = (options) => {
|
|
|
556
513
|
parts.push('<', '/', name, '>');
|
|
557
514
|
}
|
|
558
515
|
return parts;
|
|
516
|
+
}
|
|
559
517
|
case 'JSXFragment':
|
|
560
|
-
return node.children.
|
|
518
|
+
return node.children.flatMap(render);
|
|
561
519
|
case 'JSXText':
|
|
562
520
|
return [node.extra.raw];
|
|
563
521
|
case 'JSXExpressionContainer':
|
|
564
|
-
if (node.expression.type
|
|
522
|
+
if (node.expression.type === 'JSXEmptyExpression')
|
|
565
523
|
return [];
|
|
566
524
|
return [node.expression];
|
|
567
525
|
}
|
|
@@ -572,7 +530,7 @@ const customElement = (options) => {
|
|
|
572
530
|
let i = 0;
|
|
573
531
|
while (i < parts.length + 1) {
|
|
574
532
|
let quasi = '';
|
|
575
|
-
while (typeof parts[i]
|
|
533
|
+
while (typeof parts[i] === 'string') {
|
|
576
534
|
quasi += parts[i].replace(/[\\`]/g, (s) => `\\${s}`);
|
|
577
535
|
i += 1;
|
|
578
536
|
}
|
|
@@ -585,7 +543,7 @@ const customElement = (options) => {
|
|
|
585
543
|
// TODO
|
|
586
544
|
// if (!expressions.length) return template;
|
|
587
545
|
const { local } = addDependency(path, UTILS_PATH, UTILS_HTML_LOCAL, UTILS_HTML_IMPORTED, true);
|
|
588
|
-
return t.taggedTemplateExpression(t.identifier(local), templateLiteral);
|
|
546
|
+
return t.taggedTemplateExpression(t.identifier(local || ''), templateLiteral);
|
|
589
547
|
};
|
|
590
548
|
path.replaceWith(transform(render(path.node)));
|
|
591
549
|
}
|
|
@@ -594,14 +552,22 @@ const customElement = (options) => {
|
|
|
594
552
|
visitor(ast, {
|
|
595
553
|
Decorator(path) {
|
|
596
554
|
const { expression } = path.node;
|
|
597
|
-
if (expression
|
|
555
|
+
if (!t.isCallExpression(expression))
|
|
556
|
+
return;
|
|
557
|
+
if (!t.isIdentifier(expression.callee))
|
|
558
|
+
return;
|
|
559
|
+
if (expression.callee.name !== DECORATOR_PROPERTY)
|
|
598
560
|
return;
|
|
599
561
|
if (!expression.arguments.length) {
|
|
600
562
|
expression.arguments.push(t.objectExpression([]));
|
|
601
563
|
}
|
|
602
564
|
const [argument] = expression.arguments;
|
|
565
|
+
if (!t.isObjectExpression(argument))
|
|
566
|
+
return;
|
|
603
567
|
const property = argument.properties.find((property) => {
|
|
604
|
-
return property
|
|
568
|
+
return (t.isObjectProperty(property) &&
|
|
569
|
+
t.isIdentifier(property.key) &&
|
|
570
|
+
property.key.name === DECORATOR_PROPERTY_TYPE);
|
|
605
571
|
});
|
|
606
572
|
if (property)
|
|
607
573
|
return;
|
|
@@ -652,20 +618,25 @@ const customElement = (options) => {
|
|
|
652
618
|
input.types.forEach(extract);
|
|
653
619
|
break;
|
|
654
620
|
// TODO
|
|
655
|
-
case 'TSParenthesizedType':
|
|
656
|
-
if (input?.typeAnnotation?.type
|
|
621
|
+
case 'TSParenthesizedType': {
|
|
622
|
+
if (input?.typeAnnotation?.type !== 'TSIntersectionType')
|
|
657
623
|
break;
|
|
658
624
|
let types = input.types || input.typeAnnotation.types;
|
|
659
|
-
if (types.length
|
|
625
|
+
if (types.length !== 2)
|
|
660
626
|
return;
|
|
661
|
-
types = types.filter((type) => type.type
|
|
662
|
-
if (types.length
|
|
627
|
+
types = types.filter((type) => type.type !== 'TSTypeLiteral');
|
|
628
|
+
if (types.length !== 1)
|
|
663
629
|
return;
|
|
664
630
|
extract(types[0]);
|
|
665
631
|
break;
|
|
632
|
+
}
|
|
666
633
|
}
|
|
667
634
|
};
|
|
668
|
-
|
|
635
|
+
if (context.directoryPath) {
|
|
636
|
+
extract(
|
|
637
|
+
// biome-ignore lint: TODO
|
|
638
|
+
getType(context.directoryPath, ast, path.parent['typeAnnotation']?.typeAnnotation));
|
|
639
|
+
}
|
|
669
640
|
argument.properties.push(t.objectProperty(t.identifier(DECORATOR_PROPERTY_TYPE), t.numericLiteral(type)));
|
|
670
641
|
}
|
|
671
642
|
});
|
|
@@ -673,49 +644,62 @@ const customElement = (options) => {
|
|
|
673
644
|
if (options.typings) {
|
|
674
645
|
visitor(ast, {
|
|
675
646
|
Program(path) {
|
|
676
|
-
const attributes = context
|
|
677
|
-
.
|
|
647
|
+
const attributes = (context.classProperties || [])
|
|
648
|
+
.filter((property) => !t.isClassMethod(property))
|
|
678
649
|
.map((property) => {
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
650
|
+
const keyName = extractAttribute(property) ??
|
|
651
|
+
(t.isIdentifier(property.key) ? kebabCase(property.key.name) : '');
|
|
652
|
+
const typeAnnotation = property.typeAnnotation
|
|
653
|
+
? property.typeAnnotation
|
|
654
|
+
: undefined;
|
|
655
|
+
const signature = t.tSPropertySignature(t.stringLiteral(kebabCase(keyName)), typeAnnotation);
|
|
656
|
+
signature.optional = property.optional ?? false;
|
|
657
|
+
signature.leadingComments = t.cloneNode(property, true).leadingComments;
|
|
658
|
+
return signature;
|
|
685
659
|
});
|
|
686
|
-
const events = context.classEvents
|
|
660
|
+
const events = (context.classEvents ?? [])
|
|
661
|
+
.map((event) => {
|
|
662
|
+
if (!t.isIdentifier(event.key))
|
|
663
|
+
return null;
|
|
687
664
|
const key = event.key;
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
})
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
method
|
|
701
|
-
)
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
665
|
+
const parameter = t.identifier('event');
|
|
666
|
+
parameter.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('CustomEvent'),
|
|
667
|
+
// biome-ignore lint: TODO
|
|
668
|
+
event.typeAnnotation?.['typeAnnotation']?.typeParameters));
|
|
669
|
+
const functionType = t.tsFunctionType(undefined, [parameter], t.tsTypeAnnotation(t.tsVoidKeyword()));
|
|
670
|
+
const signature = t.tSPropertySignature(t.identifier(camelCase(`on-${key.name}`)), t.tsTypeAnnotation(functionType));
|
|
671
|
+
signature.optional = true;
|
|
672
|
+
signature.leadingComments = t.cloneNode(event, true).leadingComments;
|
|
673
|
+
return signature;
|
|
674
|
+
})
|
|
675
|
+
.filter((event) => !!event);
|
|
676
|
+
const methods = (context.classMethods ?? [])
|
|
677
|
+
.map((method) => {
|
|
678
|
+
if (!t.isIdentifier(method.key))
|
|
679
|
+
return null;
|
|
680
|
+
const parameters = (method.params ?? []);
|
|
681
|
+
const returnType = method.returnType;
|
|
682
|
+
const signature = t.tsMethodSignature(method.key, undefined, parameters, returnType);
|
|
683
|
+
signature.leadingComments = t.cloneNode(method, true).leadingComments;
|
|
684
|
+
return signature;
|
|
685
|
+
})
|
|
686
|
+
.filter((method) => !!method);
|
|
687
|
+
const properties = (context.classProperties ?? [])
|
|
688
|
+
.map((property) => {
|
|
689
|
+
if (!t.isIdentifier(property.key))
|
|
690
|
+
return null;
|
|
706
691
|
const key = property.key;
|
|
707
|
-
// TODO
|
|
692
|
+
// biome-ignore lint: TODO
|
|
708
693
|
const readonly = property.readonly || !!property['returnType'];
|
|
709
|
-
// TODO
|
|
710
|
-
const typeAnnotation =
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
// prettier-ignore
|
|
694
|
+
// biome-ignore lint: TODO
|
|
695
|
+
const typeAnnotation = property.typeAnnotation || property['returnType'];
|
|
696
|
+
const signature = t.tsPropertySignature(t.identifier(key.name), typeAnnotation);
|
|
697
|
+
signature.readonly = readonly;
|
|
698
|
+
signature.optional = property.optional ?? false;
|
|
699
|
+
signature.leadingComments = t.cloneNode(property, true).leadingComments;
|
|
700
|
+
return signature;
|
|
701
|
+
})
|
|
702
|
+
.filter((property) => !!property);
|
|
719
703
|
const ast = template.default.ast(`
|
|
720
704
|
// THE FOLLOWING TYPES HAVE BEEN ADDED AUTOMATICALLY
|
|
721
705
|
|
|
@@ -770,15 +754,24 @@ const customElement = (options) => {
|
|
|
770
754
|
preserveComments: true
|
|
771
755
|
});
|
|
772
756
|
path.node.body.push(...ast);
|
|
773
|
-
}
|
|
774
|
-
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
// TODO
|
|
760
|
+
visitor(ast, {
|
|
775
761
|
TSTypeReference(path) {
|
|
776
|
-
if (path.node.typeName
|
|
762
|
+
if (!t.isIdentifier(path.node.typeName))
|
|
763
|
+
return;
|
|
764
|
+
if (path.node.typeName.name !== 'OverridesConfig')
|
|
777
765
|
return;
|
|
778
|
-
const property = path.findParent((
|
|
766
|
+
const property = path.findParent((p) => p.isTSPropertySignature());
|
|
779
767
|
if (!property)
|
|
780
768
|
return;
|
|
769
|
+
if (!t.isTSPropertySignature(property.node))
|
|
770
|
+
return;
|
|
771
|
+
// biome-ignore lint: TODO
|
|
781
772
|
const name = property.node.key.name || property.node.key.extra.rawValue;
|
|
773
|
+
if (!name)
|
|
774
|
+
return;
|
|
782
775
|
if (!path.node.typeParameters?.params)
|
|
783
776
|
return;
|
|
784
777
|
path.node.typeParameters.params[1] = t.tsTypeReference(t.identifier('Omit'), t.tsTypeParameterInstantiation([
|
|
@@ -788,18 +781,51 @@ const customElement = (options) => {
|
|
|
788
781
|
path.skip();
|
|
789
782
|
}
|
|
790
783
|
});
|
|
784
|
+
// TODO
|
|
785
|
+
visitor(ast, {
|
|
786
|
+
TSTypeReference(path) {
|
|
787
|
+
if (!t.isIdentifier(path.node.typeName))
|
|
788
|
+
return;
|
|
789
|
+
if (path.node.typeName.name !== 'OverridableValue')
|
|
790
|
+
return;
|
|
791
|
+
const property = path.findParent((p) => p.isTSPropertySignature());
|
|
792
|
+
if (!property)
|
|
793
|
+
return;
|
|
794
|
+
if (!t.isTSPropertySignature(property.node))
|
|
795
|
+
return;
|
|
796
|
+
// biome-ignore lint: TODO
|
|
797
|
+
const name = property.node.key.name || property.node.key.extra.rawValue;
|
|
798
|
+
if (!name)
|
|
799
|
+
return;
|
|
800
|
+
if (!path.node.typeParameters?.params)
|
|
801
|
+
return;
|
|
802
|
+
if (path.node.typeParameters.params.length > 1)
|
|
803
|
+
return;
|
|
804
|
+
const interfaceName = pascalCase(`${context.className}-${name}-Overrides`);
|
|
805
|
+
path.node.typeParameters.params[1] = t.identifier(interfaceName);
|
|
806
|
+
path.skip();
|
|
807
|
+
const has = ast.program.body.some((child) => t.isExportNamedDeclaration(child) &&
|
|
808
|
+
t.isInterfaceDeclaration(child.declaration) &&
|
|
809
|
+
child.declaration.id.name === interfaceName);
|
|
810
|
+
if (has)
|
|
811
|
+
return;
|
|
812
|
+
ast.program.body.push(t.exportNamedDeclaration(t.interfaceDeclaration(t.identifier(interfaceName), undefined, undefined, t.objectTypeAnnotation([]))));
|
|
813
|
+
}
|
|
814
|
+
});
|
|
791
815
|
}
|
|
792
816
|
context.script = print(ast);
|
|
793
817
|
};
|
|
794
818
|
return { name, run };
|
|
795
819
|
};
|
|
796
820
|
|
|
821
|
+
// biome-ignore-all lint: TODO
|
|
797
822
|
const DOCUMENT_OPTIONS = {
|
|
798
|
-
destination: path.join('dist', 'document.json')
|
|
823
|
+
destination: path.join('dist', 'document.json'),
|
|
824
|
+
transformer: (_context, element) => element
|
|
799
825
|
};
|
|
800
|
-
const document = (
|
|
826
|
+
const document = (userOptions) => {
|
|
801
827
|
const name = 'document';
|
|
802
|
-
options = Object.assign({}, DOCUMENT_OPTIONS,
|
|
828
|
+
const options = Object.assign({}, DOCUMENT_OPTIONS, userOptions);
|
|
803
829
|
const finish = (global) => {
|
|
804
830
|
const json = {
|
|
805
831
|
elements: []
|
|
@@ -813,9 +839,9 @@ const document = (options) => {
|
|
|
813
839
|
for (const decorator of event.decorators) {
|
|
814
840
|
for (const argument of decorator.expression['arguments']) {
|
|
815
841
|
for (const property of argument.properties) {
|
|
816
|
-
if (property.key.name
|
|
842
|
+
if (property.key.name !== 'cancelable')
|
|
817
843
|
continue;
|
|
818
|
-
if (property.value.type
|
|
844
|
+
if (property.value.type !== 'BooleanLiteral')
|
|
819
845
|
continue;
|
|
820
846
|
if (!property.value.value)
|
|
821
847
|
continue;
|
|
@@ -848,7 +874,8 @@ const document = (options) => {
|
|
|
848
874
|
const comments = extractFromComment(method);
|
|
849
875
|
// TODO
|
|
850
876
|
const parameters = method.params.map((param) => ({
|
|
851
|
-
description: comments.params?.find((item) => item.name
|
|
877
|
+
description: comments.params?.find((item) => item.name === param['name'])
|
|
878
|
+
?.description,
|
|
852
879
|
required: !param['optional'],
|
|
853
880
|
name: param['name'],
|
|
854
881
|
type: print(param?.['typeAnnotation']?.typeAnnotation) || undefined,
|
|
@@ -888,7 +915,7 @@ const document = (options) => {
|
|
|
888
915
|
returns
|
|
889
916
|
},
|
|
890
917
|
// TODO
|
|
891
|
-
returns
|
|
918
|
+
returns !== 'void' &&
|
|
892
919
|
comments.returns && {
|
|
893
920
|
tags: [
|
|
894
921
|
{
|
|
@@ -903,7 +930,7 @@ const document = (options) => {
|
|
|
903
930
|
// TODO
|
|
904
931
|
const initializer = getInitializer(property.value);
|
|
905
932
|
const name = property.key['name'];
|
|
906
|
-
const readonly = property['kind']
|
|
933
|
+
const readonly = property['kind'] === 'get';
|
|
907
934
|
// TODO
|
|
908
935
|
const reflects = (() => {
|
|
909
936
|
if (!property.decorators)
|
|
@@ -912,9 +939,9 @@ const document = (options) => {
|
|
|
912
939
|
for (const decorator of property.decorators) {
|
|
913
940
|
for (const argument of decorator.expression['arguments']) {
|
|
914
941
|
for (const property of argument.properties) {
|
|
915
|
-
if (property.key.name
|
|
942
|
+
if (property.key.name !== 'reflect')
|
|
916
943
|
continue;
|
|
917
|
-
if (property.value.type
|
|
944
|
+
if (property.value.type !== 'BooleanLiteral')
|
|
918
945
|
continue;
|
|
919
946
|
if (!property.value.value)
|
|
920
947
|
continue;
|
|
@@ -990,7 +1017,10 @@ const document = (options) => {
|
|
|
990
1017
|
json.elements = json.elements.sort((a, b) => (a.title > b.title ? 1 : -1));
|
|
991
1018
|
const dirname = path.dirname(options.destination);
|
|
992
1019
|
fs.ensureDirSync(dirname);
|
|
993
|
-
fs.writeJSONSync(options.destination, json, {
|
|
1020
|
+
fs.writeJSONSync(options.destination, json, {
|
|
1021
|
+
encoding: 'utf8',
|
|
1022
|
+
spaces: 2
|
|
1023
|
+
});
|
|
994
1024
|
};
|
|
995
1025
|
return { name, finish };
|
|
996
1026
|
};
|
|
@@ -998,11 +1028,13 @@ const document = (options) => {
|
|
|
998
1028
|
const extract = () => {
|
|
999
1029
|
const name = 'extract';
|
|
1000
1030
|
const run = (context) => {
|
|
1001
|
-
const
|
|
1031
|
+
const body = context.fileAST?.program.body.find((child) => {
|
|
1002
1032
|
return t.isExportNamedDeclaration(child);
|
|
1003
1033
|
});
|
|
1004
|
-
context.class = declaration;
|
|
1005
|
-
context.class
|
|
1034
|
+
context.class = body?.declaration;
|
|
1035
|
+
if (context.class) {
|
|
1036
|
+
context.class.leadingComments = body?.leadingComments; // TODO
|
|
1037
|
+
}
|
|
1006
1038
|
context.classMembers = context.class?.body?.body || [];
|
|
1007
1039
|
context.className = context.class?.id?.name;
|
|
1008
1040
|
context.elementKey = kebabCase(context.className || '');
|
|
@@ -1018,11 +1050,11 @@ const PARSE_OPTIONS = {
|
|
|
1018
1050
|
sourceType: 'module',
|
|
1019
1051
|
plugins: [['decorators', { decoratorsBeforeExport: true }], 'jsx', 'typescript']
|
|
1020
1052
|
};
|
|
1021
|
-
const parse = (
|
|
1053
|
+
const parse = (userOptions) => {
|
|
1022
1054
|
const name = 'parse';
|
|
1023
|
-
options = Object.assign({}, PARSE_OPTIONS,
|
|
1055
|
+
const options = Object.assign({}, PARSE_OPTIONS, userOptions);
|
|
1024
1056
|
const run = (context) => {
|
|
1025
|
-
context.fileAST = parse$1(context.fileContent, options);
|
|
1057
|
+
context.fileAST = parse$1(context.fileContent || '', options);
|
|
1026
1058
|
};
|
|
1027
1059
|
return { name, run };
|
|
1028
1060
|
};
|
|
@@ -1043,12 +1075,12 @@ const read = () => {
|
|
|
1043
1075
|
|
|
1044
1076
|
const README_OPTIONS = {
|
|
1045
1077
|
source(context) {
|
|
1046
|
-
return path.join(context.directoryPath, `${context.fileName}.md`);
|
|
1078
|
+
return path.join(context.directoryPath || '', `${context.fileName}.md`);
|
|
1047
1079
|
}
|
|
1048
1080
|
};
|
|
1049
|
-
const readme = (
|
|
1081
|
+
const readme = (userOptions) => {
|
|
1050
1082
|
const name = 'readme';
|
|
1051
|
-
options = Object.assign({}, README_OPTIONS,
|
|
1083
|
+
const options = Object.assign({}, README_OPTIONS, userOptions);
|
|
1052
1084
|
const finish = (global) => {
|
|
1053
1085
|
for (const context of global.contexts) {
|
|
1054
1086
|
context.readmePath = options.source(context);
|
|
@@ -1066,18 +1098,14 @@ const readme = (options) => {
|
|
|
1066
1098
|
|
|
1067
1099
|
const STYLE_OPTIONS = {
|
|
1068
1100
|
source(context) {
|
|
1069
|
-
return [
|
|
1070
|
-
path.join(context.directoryPath, `${context.fileName}
|
|
1071
|
-
|
|
1072
|
-
path.join(context.directoryPath, `${context.fileName}.sass`),
|
|
1073
|
-
path.join(context.directoryPath, `${context.fileName}.scss`),
|
|
1074
|
-
path.join(context.directoryPath, `${context.fileName}.styl`)
|
|
1075
|
-
];
|
|
1101
|
+
return ['css', 'less', 'sass', 'scss', 'styl'].map((key) => {
|
|
1102
|
+
return path.join(context.directoryPath || '', `${context.fileName}.${key}`);
|
|
1103
|
+
});
|
|
1076
1104
|
}
|
|
1077
1105
|
};
|
|
1078
|
-
const style = (
|
|
1106
|
+
const style = (userOptions) => {
|
|
1079
1107
|
const name = 'style';
|
|
1080
|
-
options = Object.assign({}, STYLE_OPTIONS,
|
|
1108
|
+
const options = Object.assign({}, STYLE_OPTIONS, userOptions);
|
|
1081
1109
|
const run = (context) => {
|
|
1082
1110
|
const sources = [options.source(context)].flat();
|
|
1083
1111
|
for (const source of sources) {
|
|
@@ -1093,11 +1121,12 @@ const style = (options) => {
|
|
|
1093
1121
|
context.styleContent = fs.readFileSync(context.stylePath, 'utf8');
|
|
1094
1122
|
context.styleExtension = path.extname(context.stylePath);
|
|
1095
1123
|
context.styleName = path.basename(context.stylePath, context.styleExtension);
|
|
1124
|
+
if (!context.fileAST)
|
|
1125
|
+
return;
|
|
1096
1126
|
const { local } = addDependency(context.fileAST, context.stylePath, STYLE_IMPORTED, undefined, true);
|
|
1097
|
-
|
|
1098
|
-
const property = t.classProperty(t.identifier(STATIC_STYLE), t.identifier(local), undefined, null, undefined, true);
|
|
1127
|
+
const property = t.classProperty(t.identifier(STATIC_STYLE), t.identifier(local || ''), undefined, null, undefined, true);
|
|
1099
1128
|
t.addComment(property, 'leading', COMMENT_AUTO_ADDED, true);
|
|
1100
|
-
context.class
|
|
1129
|
+
context.class?.body.body.unshift(property);
|
|
1101
1130
|
};
|
|
1102
1131
|
return { name, run };
|
|
1103
1132
|
};
|
|
@@ -1106,30 +1135,36 @@ const validate = () => {
|
|
|
1106
1135
|
const name = 'validate';
|
|
1107
1136
|
const run = (context) => {
|
|
1108
1137
|
context.skipped = true;
|
|
1138
|
+
if (!context.fileAST)
|
|
1139
|
+
return;
|
|
1109
1140
|
visitor(context.fileAST, {
|
|
1110
1141
|
ImportDeclaration(path) {
|
|
1111
1142
|
if (path.node.source?.value !== PACKAGE_NAME)
|
|
1112
1143
|
return;
|
|
1113
1144
|
for (const specifier of path.node.specifiers) {
|
|
1114
|
-
if (specifier
|
|
1145
|
+
if (!t.isImportSpecifier(specifier) ||
|
|
1146
|
+
!t.isIdentifier(specifier.imported) ||
|
|
1147
|
+
specifier.imported.name !== DECORATOR_ELEMENT) {
|
|
1115
1148
|
continue;
|
|
1149
|
+
}
|
|
1116
1150
|
const binding = path.scope.getBinding(specifier.imported.name);
|
|
1117
|
-
if (binding.references
|
|
1118
|
-
|
|
1151
|
+
if (!binding || binding.references === 0) {
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1119
1154
|
const referencePaths = binding.referencePaths.filter((referencePath) => {
|
|
1120
|
-
|
|
1121
|
-
t.isDecorator(referencePath.parentPath
|
|
1122
|
-
t.isClassDeclaration(referencePath.parentPath.parentPath
|
|
1123
|
-
t.isExportNamedDeclaration(referencePath.parentPath.parentPath.parentPath
|
|
1124
|
-
return true;
|
|
1155
|
+
return (t.isCallExpression(referencePath.parent) &&
|
|
1156
|
+
t.isDecorator(referencePath.parentPath?.parent) &&
|
|
1157
|
+
t.isClassDeclaration(referencePath.parentPath.parentPath?.parent) &&
|
|
1158
|
+
t.isExportNamedDeclaration(referencePath.parentPath.parentPath.parentPath?.parent));
|
|
1125
1159
|
});
|
|
1126
1160
|
if (referencePaths.length > 1) {
|
|
1127
1161
|
throw new Error('In each file, only one custom element can be defined. \n' +
|
|
1128
1162
|
'If more than one @Element() decorator is used in the file, it will result in an error.\n');
|
|
1129
1163
|
}
|
|
1130
1164
|
context.skipped = false;
|
|
1131
|
-
if (referencePaths.length
|
|
1165
|
+
if (referencePaths.length === 1) {
|
|
1132
1166
|
break;
|
|
1167
|
+
}
|
|
1133
1168
|
throw new Error('It appears that the class annotated with the @Element() decorator is not being exported correctly.');
|
|
1134
1169
|
}
|
|
1135
1170
|
path.stop();
|
|
@@ -1140,12 +1175,15 @@ const validate = () => {
|
|
|
1140
1175
|
return { name, run };
|
|
1141
1176
|
};
|
|
1142
1177
|
|
|
1178
|
+
// biome-ignore-all lint: TODO
|
|
1143
1179
|
const VISUAL_STUDIO_CODE_OPTIONS = {
|
|
1144
|
-
destination: path.join('dist', 'visual-studio-code.json')
|
|
1180
|
+
destination: path.join('dist', 'visual-studio-code.json'),
|
|
1181
|
+
reference: () => '',
|
|
1182
|
+
transformer: (_context, element) => element
|
|
1145
1183
|
};
|
|
1146
|
-
const visualStudioCode = (
|
|
1184
|
+
const visualStudioCode = (userOptions) => {
|
|
1147
1185
|
const name = 'visualStudioCode';
|
|
1148
|
-
options = Object.assign({}, VISUAL_STUDIO_CODE_OPTIONS,
|
|
1186
|
+
const options = Object.assign({}, VISUAL_STUDIO_CODE_OPTIONS, userOptions);
|
|
1149
1187
|
const finish = (global) => {
|
|
1150
1188
|
const contexts = global.contexts.sort((a, b) => {
|
|
1151
1189
|
return a.elementKey.toUpperCase() > b.elementKey.toUpperCase() ? 1 : -1;
|
|
@@ -1205,34 +1243,40 @@ const visualStudioCode = (options) => {
|
|
|
1205
1243
|
}
|
|
1206
1244
|
const dirname = path.dirname(options.destination);
|
|
1207
1245
|
fs.ensureDirSync(dirname);
|
|
1208
|
-
fs.writeJSONSync(options.destination, json, {
|
|
1246
|
+
fs.writeJSONSync(options.destination, json, {
|
|
1247
|
+
encoding: 'utf8',
|
|
1248
|
+
spaces: 2
|
|
1249
|
+
});
|
|
1209
1250
|
};
|
|
1210
1251
|
return { name, finish };
|
|
1211
1252
|
};
|
|
1212
1253
|
|
|
1254
|
+
// biome-ignore-all lint: TODO
|
|
1213
1255
|
const WEB_TYPES_OPTIONS = {
|
|
1214
1256
|
destination: path.join('dist', 'web-types.json'),
|
|
1215
1257
|
packageName: '',
|
|
1216
|
-
packageVersion: ''
|
|
1258
|
+
packageVersion: '',
|
|
1259
|
+
reference: () => '',
|
|
1260
|
+
transformer: (_context, element) => element
|
|
1217
1261
|
};
|
|
1218
|
-
const webTypes = (
|
|
1262
|
+
const webTypes = (userOptions) => {
|
|
1219
1263
|
const name = 'webTypes';
|
|
1220
|
-
options = Object.assign({}, WEB_TYPES_OPTIONS,
|
|
1264
|
+
const options = Object.assign({}, WEB_TYPES_OPTIONS, userOptions);
|
|
1221
1265
|
const finish = (global) => {
|
|
1222
1266
|
const contexts = global.contexts.sort((a, b) => {
|
|
1223
|
-
return a.elementKey.toUpperCase()
|
|
1267
|
+
return (a.elementKey ?? '').toUpperCase().localeCompare((b.elementKey ?? '').toUpperCase());
|
|
1224
1268
|
});
|
|
1225
1269
|
const json = {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1270
|
+
$schema: 'http://json.schemastore.org/web-types',
|
|
1271
|
+
name: options.packageName,
|
|
1272
|
+
version: options.packageVersion,
|
|
1229
1273
|
'description-markup': 'markdown',
|
|
1230
1274
|
'framework-config': {
|
|
1231
1275
|
'enable-when': {
|
|
1232
1276
|
'node-packages': [options.packageName]
|
|
1233
1277
|
}
|
|
1234
1278
|
},
|
|
1235
|
-
|
|
1279
|
+
contributions: {
|
|
1236
1280
|
html: {
|
|
1237
1281
|
elements: []
|
|
1238
1282
|
}
|
|
@@ -1263,9 +1307,9 @@ const webTypes = (options) => {
|
|
|
1263
1307
|
default: getInitializer(property.value)
|
|
1264
1308
|
}, extractFromComment(property, ['description', 'deprecated', 'experimental'])));
|
|
1265
1309
|
const element = Object.assign({
|
|
1266
|
-
|
|
1310
|
+
name: context.elementKey,
|
|
1267
1311
|
'doc-url': options.reference?.(context),
|
|
1268
|
-
|
|
1312
|
+
js: {
|
|
1269
1313
|
events,
|
|
1270
1314
|
properties: [].concat(properties, methods)
|
|
1271
1315
|
},
|
|
@@ -1276,9 +1320,81 @@ const webTypes = (options) => {
|
|
|
1276
1320
|
}
|
|
1277
1321
|
const dirname = path.dirname(options.destination);
|
|
1278
1322
|
fs.ensureDirSync(dirname);
|
|
1279
|
-
fs.writeJSONSync(options.destination, json, {
|
|
1323
|
+
fs.writeJSONSync(options.destination, json, {
|
|
1324
|
+
encoding: 'utf8',
|
|
1325
|
+
spaces: 2
|
|
1326
|
+
});
|
|
1280
1327
|
};
|
|
1281
1328
|
return { name, finish };
|
|
1282
1329
|
};
|
|
1283
1330
|
|
|
1331
|
+
const logger = ora({
|
|
1332
|
+
color: 'yellow'
|
|
1333
|
+
});
|
|
1334
|
+
const log = (message, persist) => {
|
|
1335
|
+
const content = `${new Date().toLocaleTimeString()} [${KEY}] ${message}`;
|
|
1336
|
+
const log = logger.start(content);
|
|
1337
|
+
if (!persist)
|
|
1338
|
+
return;
|
|
1339
|
+
log.succeed();
|
|
1340
|
+
};
|
|
1341
|
+
const transformer = (...plugins) => {
|
|
1342
|
+
let global = {
|
|
1343
|
+
contexts: []
|
|
1344
|
+
};
|
|
1345
|
+
const start = async () => {
|
|
1346
|
+
log(`Started.`, true);
|
|
1347
|
+
log(`${plugins.length} plugins detected.`, true);
|
|
1348
|
+
log(`Plugins are starting.`, true);
|
|
1349
|
+
for (const plugin of plugins) {
|
|
1350
|
+
if (!plugin.start)
|
|
1351
|
+
continue;
|
|
1352
|
+
log(`Plugin '${plugin.name}' is starting.`);
|
|
1353
|
+
global = (await plugin.start(global)) || global;
|
|
1354
|
+
log(`Plugin '${plugin.name}' started successfully.`);
|
|
1355
|
+
}
|
|
1356
|
+
log(`Plugins have been successfully started.`, true);
|
|
1357
|
+
};
|
|
1358
|
+
const run = async (filePath) => {
|
|
1359
|
+
let context = {
|
|
1360
|
+
filePath
|
|
1361
|
+
};
|
|
1362
|
+
const parsed = path.parse(filePath);
|
|
1363
|
+
for (const plugin of plugins) {
|
|
1364
|
+
if (!plugin.run)
|
|
1365
|
+
continue;
|
|
1366
|
+
const source = path.join(parsed.dir).split(path.sep).slice(-2).concat(parsed.base).join('/');
|
|
1367
|
+
log(`Plugin '${plugin.name}' is executing on '${source}' file.`);
|
|
1368
|
+
try {
|
|
1369
|
+
context = (await plugin.run(context, global)) || context;
|
|
1370
|
+
}
|
|
1371
|
+
catch (error) {
|
|
1372
|
+
log(`Error in '${plugin.name}' plugin on '${source}' file.\n`, true);
|
|
1373
|
+
throw error;
|
|
1374
|
+
}
|
|
1375
|
+
global.contexts = global.contexts
|
|
1376
|
+
.filter((current) => {
|
|
1377
|
+
return current.filePath !== context.filePath;
|
|
1378
|
+
})
|
|
1379
|
+
.concat(context);
|
|
1380
|
+
log(`Plugin '${plugin.name}' executed successfully on '${source}' file.`);
|
|
1381
|
+
}
|
|
1382
|
+
logger.stop();
|
|
1383
|
+
return context;
|
|
1384
|
+
};
|
|
1385
|
+
const finish = async () => {
|
|
1386
|
+
log(`Plugins are finishing.`, true);
|
|
1387
|
+
for (const plugin of plugins) {
|
|
1388
|
+
if (!plugin.finish)
|
|
1389
|
+
continue;
|
|
1390
|
+
log(`Plugin '${plugin.name}' is finishing.`);
|
|
1391
|
+
global = (await plugin.finish(global)) || global;
|
|
1392
|
+
log(`Plugin '${plugin.name}' finished successfully.`);
|
|
1393
|
+
}
|
|
1394
|
+
log(`Plugins have been successfully finished.`, true);
|
|
1395
|
+
log(`Finished.`, true);
|
|
1396
|
+
};
|
|
1397
|
+
return { global, start, run, finish };
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1284
1400
|
export { ASSETS_OPTIONS, COPY_OPTIONS, CUSTOM_ELEMENT_OPTIONS, DOCUMENT_OPTIONS, PARSE_OPTIONS, README_OPTIONS, STYLE_OPTIONS, VISUAL_STUDIO_CODE_OPTIONS, WEB_TYPES_OPTIONS, assets, copy, customElement, document, extract, parse, read, readme, style, transformer, validate, visualStudioCode, webTypes };
|