@ui5/webcomponents-tools 0.0.0-47cc17a26 → 0.0.0-49bade48d
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/CHANGELOG.md +327 -1
- package/assets-meta.js +6 -4
- package/bin/dev.js +9 -4
- package/bin/ui5nps.js +44 -8
- package/components-package/eslint.js +1 -1
- package/components-package/nps.js +23 -18
- package/icons-collection/nps.js +1 -1
- package/lib/amd-to-es6/index.js +3 -1
- package/lib/cem/cem.js +4 -0
- package/lib/cem/custom-elements-manifest.config.mjs +88 -4
- package/lib/cem/merge.mjs +220 -0
- package/lib/cem/schema-internal.json +41 -1
- package/lib/cem/schema.json +41 -1
- package/lib/cem/types-internal.d.ts +32 -2
- package/lib/cem/types.d.ts +32 -2
- package/lib/cem/utils.mjs +13 -3
- package/lib/cem/validate.js +7 -2
- package/lib/chokidar/chokidar.js +28 -0
- package/lib/copy-and-watch/index.js +5 -0
- package/lib/copy-list/index.js +3 -1
- package/lib/create-icons/index.js +18 -13
- package/lib/create-illustrations/index.js +46 -4
- package/lib/css-processors/css-processor-components.mjs +14 -3
- package/lib/css-processors/css-processor-themes.mjs +148 -24
- package/lib/css-processors/merge-light-dark.mjs +131 -0
- package/lib/css-processors/postcss-plugin.mjs +153 -0
- package/lib/css-processors/scope-variables.mjs +26 -1
- package/lib/css-processors/shared.mjs +7 -6
- package/lib/eslint/eslint.js +44 -0
- package/lib/generate-js-imports/illustrations.js +3 -1
- package/lib/generate-json-imports/i18n.js +3 -1
- package/lib/generate-json-imports/themes.js +6 -2
- package/lib/i18n/defaults.js +3 -1
- package/lib/i18n/toJSON.js +28 -4
- package/lib/test-runner/test-runner.js +56 -48
- package/lib/vite-bundler/vite-bundler.mjs +35 -0
- package/package.json +2 -4
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
getTypeRefs,
|
|
18
18
|
normalizeDescription,
|
|
19
19
|
formatArrays,
|
|
20
|
+
formatSlotTypes,
|
|
20
21
|
isClass,
|
|
21
22
|
normalizeTagType,
|
|
22
23
|
logDocumentationError,
|
|
@@ -27,7 +28,44 @@ import { generateCustomData } from "cem-plugin-vs-code-custom-data-generator";
|
|
|
27
28
|
import { customElementJetBrainsPlugin } from "custom-element-jet-brains-integration";
|
|
28
29
|
|
|
29
30
|
const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
|
|
31
|
+
let aliasMap = {};
|
|
32
|
+
|
|
30
33
|
const devMode = process.env.UI5_CEM_MODE === "dev";
|
|
34
|
+
const isVerbose = process.env.UI5_VERBOSE === "true";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Wraps a CEM plugin to suppress console output in quiet mode.
|
|
38
|
+
* @param {Object} plugin - The plugin to wrap
|
|
39
|
+
* @returns {Object} - Wrapped plugin with silent console during packageLinkPhase
|
|
40
|
+
*/
|
|
41
|
+
const wrapPluginForQuietMode = (plugin) => {
|
|
42
|
+
if (isVerbose) return plugin;
|
|
43
|
+
|
|
44
|
+
const originalPackageLinkPhase = plugin.packageLinkPhase;
|
|
45
|
+
if (!originalPackageLinkPhase) return plugin;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...plugin,
|
|
49
|
+
packageLinkPhase(context) {
|
|
50
|
+
const originalLog = console.log;
|
|
51
|
+
console.log = () => { };
|
|
52
|
+
try {
|
|
53
|
+
return originalPackageLinkPhase.call(plugin, context);
|
|
54
|
+
} finally {
|
|
55
|
+
console.log = originalLog;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
aliasMap = JSON.parse(fs.readFileSync("./.ui5-cem-aliases.json"));
|
|
63
|
+
} catch (e) {
|
|
64
|
+
if (devMode && isVerbose) {
|
|
65
|
+
console.warn("No .ui5-cem-aliases.json file found. Continuing without aliases.");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
31
69
|
|
|
32
70
|
const extractClassNodeJSDoc = node => {
|
|
33
71
|
const fileContent = node.getFullText();
|
|
@@ -97,6 +135,13 @@ function processClass(ts, classNode, moduleDoc) {
|
|
|
97
135
|
if (currClass.superclass?.name === "UI5Element") {
|
|
98
136
|
currClass.customElement = true;
|
|
99
137
|
}
|
|
138
|
+
} else if (currClass.customElement && classNode?.heritageClauses) {
|
|
139
|
+
// Find the extends clause (not implements)
|
|
140
|
+
const extendsClause = classNode.heritageClauses.find(clause => clause.token === ts.SyntaxKind.ExtendsKeyword);
|
|
141
|
+
if (extendsClause?.types?.[0]?.expression?.text) {
|
|
142
|
+
const extendedClass = extendsClause.types[0].expression.text;
|
|
143
|
+
logDocumentationError(moduleDoc.path, `Class extends ${extendedClass} but @extends tag is missing in JSDoc`);
|
|
144
|
+
}
|
|
100
145
|
}
|
|
101
146
|
|
|
102
147
|
if (!currClass._ui5implements.length) delete currClass._ui5implements;
|
|
@@ -158,6 +203,7 @@ function processClass(ts, classNode, moduleDoc) {
|
|
|
158
203
|
|
|
159
204
|
if (member.type?.text) {
|
|
160
205
|
member.type.text = formatArrays(member.type.text);
|
|
206
|
+
member.type.text = formatSlotTypes(member.type.text);
|
|
161
207
|
}
|
|
162
208
|
|
|
163
209
|
if (member.type && typeRefs.length) {
|
|
@@ -378,10 +424,10 @@ const processPublicAPI = object => {
|
|
|
378
424
|
return true;
|
|
379
425
|
}
|
|
380
426
|
for (const key of keys) {
|
|
381
|
-
if ((key === "privacy" && object[key] !== "public") || (key === "_ui5privacy" && object[key] !== "public")) {
|
|
427
|
+
if (((key === "privacy" && object[key] !== "public") || (key === "_ui5privacy" && object[key] !== "public")) && !object.customElement) {
|
|
382
428
|
return true;
|
|
383
429
|
} else if (typeof object[key] === "object") {
|
|
384
|
-
if (key === "cssParts" || key === "attributes" || key === "_ui5implements") {
|
|
430
|
+
if (key === "cssParts" || key === "cssStates" || key === "attributes" || key === "_ui5implements") {
|
|
385
431
|
continue;
|
|
386
432
|
}
|
|
387
433
|
|
|
@@ -486,6 +532,12 @@ export default {
|
|
|
486
532
|
}
|
|
487
533
|
}
|
|
488
534
|
|
|
535
|
+
moduleDoc.declarations.forEach(declaration => {
|
|
536
|
+
if (declaration.superclass?.name && aliasMap[declaration.superclass.name]) {
|
|
537
|
+
declaration.superclass.name = aliasMap[declaration.superclass.name];
|
|
538
|
+
}
|
|
539
|
+
})
|
|
540
|
+
|
|
489
541
|
const typeReferences = new Set();
|
|
490
542
|
const registerTypeReference = reference => typeReferences.add(JSON.stringify(reference))
|
|
491
543
|
|
|
@@ -524,7 +576,39 @@ export default {
|
|
|
524
576
|
}
|
|
525
577
|
}
|
|
526
578
|
},
|
|
527
|
-
|
|
528
|
-
|
|
579
|
+
{
|
|
580
|
+
name: 'alphabetical-sort-plugin',
|
|
581
|
+
packageLinkPhase({ customElementsManifest }) {
|
|
582
|
+
const sortByName = (arr) => {
|
|
583
|
+
if (Array.isArray(arr)) {
|
|
584
|
+
arr.sort((a, b) => {
|
|
585
|
+
if (a?.name && b?.name) {
|
|
586
|
+
return a.name.localeCompare(b.name);
|
|
587
|
+
}
|
|
588
|
+
return 0;
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
const sortArraysInObject = (obj) => {
|
|
594
|
+
if (!obj || typeof obj !== 'object') return;
|
|
595
|
+
|
|
596
|
+
for (const key in obj) {
|
|
597
|
+
if (Array.isArray(obj[key])) {
|
|
598
|
+
sortByName(obj[key]);
|
|
599
|
+
obj[key].forEach(item => sortArraysInObject(item));
|
|
600
|
+
} else if (typeof obj[key] === 'object') {
|
|
601
|
+
sortArraysInObject(obj[key]);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
customElementsManifest.modules?.forEach(moduleDoc => {
|
|
607
|
+
sortArraysInObject(moduleDoc);
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
wrapPluginForQuietMode(generateCustomData({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false })),
|
|
612
|
+
wrapPluginForQuietMode(customElementJetBrainsPlugin({ outdir: "dist", cssFileName: null, cssPropertiesDocs: false }))
|
|
529
613
|
],
|
|
530
614
|
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { pathToFileURL } from "url";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
import { readFile, writeFile } from "fs/promises";
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
|
|
8
|
+
const UI5_BASE_CLASS = "UI5Element";
|
|
9
|
+
|
|
10
|
+
const main = async (argv) => {
|
|
11
|
+
let customElementsPath = null;
|
|
12
|
+
const CACHED_CEMS = new Map();
|
|
13
|
+
const DECLARATION_PACKAGE = new WeakMap();
|
|
14
|
+
const DECLARATION_MODULE = new WeakMap();
|
|
15
|
+
|
|
16
|
+
function removeInheritedFrom(obj) {
|
|
17
|
+
if (obj === null || typeof obj !== 'object') {
|
|
18
|
+
return obj;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (Array.isArray(obj)) {
|
|
22
|
+
return obj.map(item => removeInheritedFrom(item));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
27
|
+
if (key === 'inheritedFrom') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
result[key] = removeInheritedFrom(value);
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function readPackageJson(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.parse(await readFile(filePath, "utf-8"));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw new Error(`Failed to read package.json at ${filePath}: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function loadPackageJson(depName) {
|
|
44
|
+
try {
|
|
45
|
+
// First try the standard require method (works when exports includes package.json)
|
|
46
|
+
const pkg = require(`${depName}/package.json`);
|
|
47
|
+
const pkgPath = require.resolve(`${depName}/package.json`);
|
|
48
|
+
return { path: path.dirname(pkgPath), pkg };
|
|
49
|
+
} catch (e) {
|
|
50
|
+
// If that fails, resolve the package path and read package.json directly
|
|
51
|
+
try {
|
|
52
|
+
const packagePath = require.resolve(depName);
|
|
53
|
+
let currentDir = path.dirname(packagePath);
|
|
54
|
+
|
|
55
|
+
// Navigate up to find package.json (the resolved path might be deep in dist/ or similar)
|
|
56
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
57
|
+
try {
|
|
58
|
+
const pkgPath = path.join(currentDir, 'package.json');
|
|
59
|
+
const content = await readFile(pkgPath, 'utf-8');
|
|
60
|
+
const pkg = JSON.parse(content);
|
|
61
|
+
|
|
62
|
+
// Verify this is the correct package.json by checking the name
|
|
63
|
+
if (pkg.name === depName) {
|
|
64
|
+
return { path: currentDir, pkg };
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
// Continue searching up the directory tree
|
|
68
|
+
}
|
|
69
|
+
currentDir = path.dirname(currentDir);
|
|
70
|
+
}
|
|
71
|
+
} catch (resolveError) {
|
|
72
|
+
// console.warn(`Could not resolve ${depName}:`, resolveError.message);
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function collectThirdPartyCem() {
|
|
79
|
+
const packageJSONPath = path.resolve(process.cwd(), "package.json");
|
|
80
|
+
const packageJSON = await readPackageJson(packageJSONPath);
|
|
81
|
+
|
|
82
|
+
const dependencyKeys = Object.keys(packageJSON).filter(key => key.toLowerCase().includes("dependencies"));
|
|
83
|
+
const dependencies = dependencyKeys.flatMap(key => Object.keys(packageJSON[key]));
|
|
84
|
+
|
|
85
|
+
const thirdPartCEM = (await Promise.all(dependencies.map(async dep => {
|
|
86
|
+
const result = await loadPackageJson(dep);
|
|
87
|
+
if (!result?.pkg?.customElements) return null;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
path: result.path,
|
|
91
|
+
name: dep,
|
|
92
|
+
cem: result.pkg.customElements
|
|
93
|
+
};
|
|
94
|
+
}))).filter(Boolean);
|
|
95
|
+
|
|
96
|
+
await Promise.all(thirdPartCEM.map(async dep => {
|
|
97
|
+
const cemPath = path.resolve(dep.path, dep.cem);
|
|
98
|
+
try {
|
|
99
|
+
const cemContent = JSON.parse(await readFile(cemPath, "utf-8"));
|
|
100
|
+
CACHED_CEMS.set(dep.name, cemContent);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.warn(`Failed to read CEM for ${dep.name} from ${cemPath}: ${error.message}`);
|
|
103
|
+
}
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function readCurrentCEM() {
|
|
108
|
+
const packageJSONPath = path.resolve(process.cwd(), "package.json");
|
|
109
|
+
const packageJSON = await readPackageJson(packageJSONPath);
|
|
110
|
+
|
|
111
|
+
if (!packageJSON?.customElements) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
customElementsPath = packageJSON.customElements;
|
|
116
|
+
const cemPath = path.resolve(process.cwd(), customElementsPath);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const cemContent = JSON.parse(await readFile(cemPath, "utf-8"));
|
|
120
|
+
CACHED_CEMS.set(packageJSON.name, cemContent);
|
|
121
|
+
return cemContent;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
throw new Error(`Failed to read CEM from ${cemPath}: ${error.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function resolveReference(ref) {
|
|
128
|
+
const pkg = CACHED_CEMS.get(ref.package);
|
|
129
|
+
|
|
130
|
+
if (!pkg) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const mod = (pkg.modules || []).find(m => m.path === ref.module);
|
|
135
|
+
|
|
136
|
+
if (!mod) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const declaration = (mod.declarations || []).find(d => d.name === ref.name);
|
|
141
|
+
|
|
142
|
+
if (!declaration) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
DECLARATION_PACKAGE.set(declaration, ref.package);
|
|
147
|
+
DECLARATION_MODULE.set(declaration, ref.module);
|
|
148
|
+
|
|
149
|
+
return resolveDeclaration(declaration);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function resolveDeclaration(declaration) {
|
|
153
|
+
if (!declaration.superclass || declaration.superclass.name === UI5_BASE_CLASS) {
|
|
154
|
+
return [declaration];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const superclassDeclarations = await resolveReference(declaration.superclass);
|
|
158
|
+
return [declaration, superclassDeclarations].flat().filter(Boolean);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const merge = async () => {
|
|
162
|
+
const currentCEM = await readCurrentCEM();
|
|
163
|
+
if (!currentCEM) {
|
|
164
|
+
throw new Error("No custom elements manifest found in current project");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
await collectThirdPartyCem();
|
|
168
|
+
|
|
169
|
+
const modules = currentCEM.modules || [];
|
|
170
|
+
|
|
171
|
+
for (const mod of modules) {
|
|
172
|
+
const declarations = (mod.declarations || []).filter(d => d.kind === "class");
|
|
173
|
+
|
|
174
|
+
for (const declaration of declarations) {
|
|
175
|
+
const declarationHierarchy = await resolveDeclaration(declaration);
|
|
176
|
+
const allKeys = declarationHierarchy.flatMap(dec => Object.keys(dec));
|
|
177
|
+
const uniqueKeys = [...new Set(allKeys)];
|
|
178
|
+
const arrayKeys = uniqueKeys
|
|
179
|
+
.filter(key => !key.startsWith("_ui5"))
|
|
180
|
+
.filter(key => declarationHierarchy.some(dec => Array.isArray(dec[key])));
|
|
181
|
+
|
|
182
|
+
for (const key of arrayKeys) {
|
|
183
|
+
const allItems = declarationHierarchy.flatMap(dec => dec[key] || []);
|
|
184
|
+
|
|
185
|
+
// Remove duplicates based on name property
|
|
186
|
+
const seen = new Set();
|
|
187
|
+
declaration[key] = allItems.filter(item => {
|
|
188
|
+
if (!item.name) return true;
|
|
189
|
+
if (seen.has(item.name)) return false;
|
|
190
|
+
seen.add(item.name);
|
|
191
|
+
return true;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const cleanedCEM = removeInheritedFrom(currentCEM);
|
|
198
|
+
const outputPath = path.resolve(process.cwd(), customElementsPath);
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
await writeFile(outputPath, JSON.stringify(cleanedCEM, null, 2), "utf-8");
|
|
202
|
+
console.log(`Successfully merged CEM to ${outputPath}`);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
throw new Error(`Failed to write merged CEM to ${outputPath}: ${error.message}`);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
await merge();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const filePath = process.argv[1];
|
|
212
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
213
|
+
|
|
214
|
+
if (import.meta.url === fileUrl) {
|
|
215
|
+
main(process.argv)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export default {
|
|
219
|
+
_ui5mainFn: main
|
|
220
|
+
}
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"definitions": {
|
|
4
|
+
"CssCustomState": {
|
|
5
|
+
"description": "The description of a CSS Custom State\nhttps://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet",
|
|
6
|
+
"properties": {
|
|
7
|
+
"deprecated": {
|
|
8
|
+
"description": "Whether the CSS custom state is deprecated.\nIf the value is a string, it's the reason for the deprecation.",
|
|
9
|
+
"type": [
|
|
10
|
+
"string",
|
|
11
|
+
"boolean"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"description": {
|
|
15
|
+
"description": "A markdown description.",
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"name": {
|
|
19
|
+
"description": "The name of the state. Note: Unlike CSS custom properties, custom states\ndo not have a leading `--`.",
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"summary": {
|
|
23
|
+
"description": "A markdown summary suitable for display in a listing.",
|
|
24
|
+
"type": "string"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"required": [
|
|
28
|
+
"name"
|
|
29
|
+
],
|
|
30
|
+
"type": "object"
|
|
31
|
+
},
|
|
4
32
|
"Attribute": {
|
|
5
33
|
"additionalProperties": false,
|
|
6
34
|
"properties": {
|
|
@@ -521,6 +549,12 @@
|
|
|
521
549
|
},
|
|
522
550
|
"type": "array"
|
|
523
551
|
},
|
|
552
|
+
"cssStates": {
|
|
553
|
+
"items": {
|
|
554
|
+
"$ref": "#/definitions/CssCustomState"
|
|
555
|
+
},
|
|
556
|
+
"type": "array"
|
|
557
|
+
},
|
|
524
558
|
"customElement": {
|
|
525
559
|
"description": "Distinguishes a regular JavaScript class from a\ncustom element class",
|
|
526
560
|
"enum": [
|
|
@@ -676,6 +710,12 @@
|
|
|
676
710
|
},
|
|
677
711
|
"type": "array"
|
|
678
712
|
},
|
|
713
|
+
"cssStates": {
|
|
714
|
+
"items": {
|
|
715
|
+
"$ref": "#/definitions/CssCustomState"
|
|
716
|
+
},
|
|
717
|
+
"type": "array"
|
|
718
|
+
},
|
|
679
719
|
"customElement": {
|
|
680
720
|
"description": "Distinguishes a regular JavaScript class from a\ncustom element class",
|
|
681
721
|
"enum": [
|
|
@@ -1039,7 +1079,7 @@
|
|
|
1039
1079
|
"type": "string"
|
|
1040
1080
|
},
|
|
1041
1081
|
"path": {
|
|
1042
|
-
"description": "Path to the javascript file needed to be imported
|
|
1082
|
+
"description": "Path to the javascript file needed to be imported.\n(not the path for example to a typescript file.)",
|
|
1043
1083
|
"type": "string"
|
|
1044
1084
|
},
|
|
1045
1085
|
"summary": {
|
package/lib/cem/schema.json
CHANGED
|
@@ -258,6 +258,34 @@
|
|
|
258
258
|
],
|
|
259
259
|
"type": "object"
|
|
260
260
|
},
|
|
261
|
+
"CssCustomState": {
|
|
262
|
+
"description": "The description of a CSS Custom State\nhttps://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet",
|
|
263
|
+
"properties": {
|
|
264
|
+
"deprecated": {
|
|
265
|
+
"description": "Whether the CSS custom state is deprecated.\nIf the value is a string, it's the reason for the deprecation.",
|
|
266
|
+
"type": [
|
|
267
|
+
"string",
|
|
268
|
+
"boolean"
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
"description": {
|
|
272
|
+
"description": "A markdown description.",
|
|
273
|
+
"type": "string"
|
|
274
|
+
},
|
|
275
|
+
"name": {
|
|
276
|
+
"description": "The name of the state. Note: Unlike CSS custom properties, custom states\ndo not have a leading `--`.",
|
|
277
|
+
"type": "string"
|
|
278
|
+
},
|
|
279
|
+
"summary": {
|
|
280
|
+
"description": "A markdown summary suitable for display in a listing.",
|
|
281
|
+
"type": "string"
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"required": [
|
|
285
|
+
"name"
|
|
286
|
+
],
|
|
287
|
+
"type": "object"
|
|
288
|
+
},
|
|
261
289
|
"CssPart": {
|
|
262
290
|
"description": "The description of a CSS Part",
|
|
263
291
|
"properties": {
|
|
@@ -307,6 +335,12 @@
|
|
|
307
335
|
},
|
|
308
336
|
"type": "array"
|
|
309
337
|
},
|
|
338
|
+
"cssStates": {
|
|
339
|
+
"items": {
|
|
340
|
+
"$ref": "#/definitions/CssCustomState"
|
|
341
|
+
},
|
|
342
|
+
"type": "array"
|
|
343
|
+
},
|
|
310
344
|
"customElement": {
|
|
311
345
|
"description": "Distinguishes a regular JavaScript class from a\ncustom element class",
|
|
312
346
|
"enum": [
|
|
@@ -451,6 +485,12 @@
|
|
|
451
485
|
},
|
|
452
486
|
"type": "array"
|
|
453
487
|
},
|
|
488
|
+
"cssStates": {
|
|
489
|
+
"items": {
|
|
490
|
+
"$ref": "#/definitions/CssCustomState"
|
|
491
|
+
},
|
|
492
|
+
"type": "array"
|
|
493
|
+
},
|
|
454
494
|
"customElement": {
|
|
455
495
|
"description": "Distinguishes a regular JavaScript class from a\ncustom element class",
|
|
456
496
|
"enum": [
|
|
@@ -765,7 +805,7 @@
|
|
|
765
805
|
"type": "string"
|
|
766
806
|
},
|
|
767
807
|
"path": {
|
|
768
|
-
"description": "Path to the javascript file needed to be imported
|
|
808
|
+
"description": "Path to the javascript file needed to be imported.\n(not the path for example to a typescript file.)",
|
|
769
809
|
"type": "string"
|
|
770
810
|
},
|
|
771
811
|
"summary": {
|
|
@@ -56,7 +56,7 @@ export interface JavaScriptModule {
|
|
|
56
56
|
kind: 'javascript-module';
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* Path to the javascript file needed to be imported.
|
|
59
|
+
* Path to the javascript file needed to be imported.
|
|
60
60
|
* (not the path for example to a typescript file.)
|
|
61
61
|
*/
|
|
62
62
|
path: string;
|
|
@@ -258,6 +258,8 @@ export interface CustomElement extends ClassLike {
|
|
|
258
258
|
|
|
259
259
|
cssProperties?: CssCustomProperty[];
|
|
260
260
|
|
|
261
|
+
cssStates?: CssCustomState[];
|
|
262
|
+
|
|
261
263
|
demos?: Demo[];
|
|
262
264
|
|
|
263
265
|
/**
|
|
@@ -416,6 +418,34 @@ export interface CssPart {
|
|
|
416
418
|
deprecated?: boolean | string;
|
|
417
419
|
}
|
|
418
420
|
|
|
421
|
+
/**
|
|
422
|
+
* The description of a CSS Custom State
|
|
423
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet
|
|
424
|
+
*/
|
|
425
|
+
export interface CssCustomState {
|
|
426
|
+
/**
|
|
427
|
+
* The name of the state. Note: Unlike CSS custom properties, custom states
|
|
428
|
+
* do not have a leading `--`.
|
|
429
|
+
*/
|
|
430
|
+
name: string;
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* A markdown summary suitable for display in a listing.
|
|
434
|
+
*/
|
|
435
|
+
summary?: string;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* A markdown description.
|
|
439
|
+
*/
|
|
440
|
+
description?: string;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Whether the CSS custom state is deprecated.
|
|
444
|
+
* If the value is a string, it's the reason for the deprecation.
|
|
445
|
+
*/
|
|
446
|
+
deprecated?: boolean | string;
|
|
447
|
+
}
|
|
448
|
+
|
|
419
449
|
export interface CssCustomProperty {
|
|
420
450
|
/**
|
|
421
451
|
* The name of the property, including leading `--`.
|
|
@@ -632,7 +662,7 @@ export interface ClassField extends PropertyLike {
|
|
|
632
662
|
export interface CustomElementField extends ClassField {
|
|
633
663
|
/**
|
|
634
664
|
* The corresponding attribute name if there is one.
|
|
635
|
-
*
|
|
665
|
+
*
|
|
636
666
|
* If this property is defined, the attribute must be listed in the classes'
|
|
637
667
|
* `attributes` array.
|
|
638
668
|
*/
|
package/lib/cem/types.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export interface JavaScriptModule {
|
|
|
56
56
|
kind: 'javascript-module';
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* Path to the javascript file needed to be imported.
|
|
59
|
+
* Path to the javascript file needed to be imported.
|
|
60
60
|
* (not the path for example to a typescript file.)
|
|
61
61
|
*/
|
|
62
62
|
path: string;
|
|
@@ -250,6 +250,8 @@ export interface CustomElement extends ClassLike {
|
|
|
250
250
|
|
|
251
251
|
cssProperties?: CssCustomProperty[];
|
|
252
252
|
|
|
253
|
+
cssStates?: CssCustomState[];
|
|
254
|
+
|
|
253
255
|
demos?: Demo[];
|
|
254
256
|
|
|
255
257
|
/**
|
|
@@ -372,6 +374,34 @@ export interface CssPart {
|
|
|
372
374
|
deprecated?: boolean | string;
|
|
373
375
|
}
|
|
374
376
|
|
|
377
|
+
/**
|
|
378
|
+
* The description of a CSS Custom State
|
|
379
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet
|
|
380
|
+
*/
|
|
381
|
+
export interface CssCustomState {
|
|
382
|
+
/**
|
|
383
|
+
* The name of the state. Note: Unlike CSS custom properties, custom states
|
|
384
|
+
* do not have a leading `--`.
|
|
385
|
+
*/
|
|
386
|
+
name: string;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* A markdown summary suitable for display in a listing.
|
|
390
|
+
*/
|
|
391
|
+
summary?: string;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* A markdown description.
|
|
395
|
+
*/
|
|
396
|
+
description?: string;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Whether the CSS custom state is deprecated.
|
|
400
|
+
* If the value is a string, it's the reason for the deprecation.
|
|
401
|
+
*/
|
|
402
|
+
deprecated?: boolean | string;
|
|
403
|
+
}
|
|
404
|
+
|
|
375
405
|
export interface CssCustomProperty {
|
|
376
406
|
/**
|
|
377
407
|
* The name of the property, including leading `--`.
|
|
@@ -573,7 +603,7 @@ export interface ClassField extends PropertyLike {
|
|
|
573
603
|
export interface CustomElementField extends ClassField {
|
|
574
604
|
/**
|
|
575
605
|
* The corresponding attribute name if there is one.
|
|
576
|
-
*
|
|
606
|
+
*
|
|
577
607
|
* If this property is defined, the attribute must be listed in the classes'
|
|
578
608
|
* `attributes` array.
|
|
579
609
|
*/
|
package/lib/cem/utils.mjs
CHANGED
|
@@ -240,7 +240,7 @@ const allowedTags = {
|
|
|
240
240
|
event: [...commonTags, "param", "native", "allowPreventDefault"],
|
|
241
241
|
eventParam: [...commonTags],
|
|
242
242
|
method: [...commonTags, "param", "returns", "override"],
|
|
243
|
-
class: [...commonTags, "constructor", "class", "abstract", "experimental", "implements", "extends", "slot", "csspart"],
|
|
243
|
+
class: [...commonTags, "constructor", "class", "abstract", "experimental", "implements", "extends", "slot", "csspart", "cssstate", "cssState"],
|
|
244
244
|
enum: [...commonTags, "experimental",],
|
|
245
245
|
enumMember: [...commonTags, "experimental",],
|
|
246
246
|
interface: [...commonTags, "experimental",],
|
|
@@ -330,6 +330,9 @@ const validateJSDocTag = (tag) => {
|
|
|
330
330
|
return tag.type && tag.name && tag.description;
|
|
331
331
|
case "csspart":
|
|
332
332
|
return !tag.type && tag.name && tag.description;
|
|
333
|
+
case "cssState":
|
|
334
|
+
case "cssstate":
|
|
335
|
+
return !tag.type && tag.name && tag.description;
|
|
333
336
|
case "since":
|
|
334
337
|
return !tag.type && tag.name;
|
|
335
338
|
case "returns":
|
|
@@ -360,7 +363,8 @@ const validateJSDocComment = (fieldType, jsdocComment, node, moduleDoc) => {
|
|
|
360
363
|
}
|
|
361
364
|
|
|
362
365
|
if (!isValid) {
|
|
363
|
-
|
|
366
|
+
const nodeName = node ? ` in '${node}'` : '';
|
|
367
|
+
logDocumentationError(moduleDoc.path, `Incorrect use of @${tag.tag}${nodeName}. Ensure it is part of ${fieldType} JSDoc tags.`)
|
|
364
368
|
}
|
|
365
369
|
|
|
366
370
|
return !!isValid;
|
|
@@ -396,7 +400,12 @@ const displayDocumentationErrors = () => {
|
|
|
396
400
|
}
|
|
397
401
|
|
|
398
402
|
const formatArrays = (typeText) => {
|
|
399
|
-
return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
|
|
403
|
+
return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Convert Slot<T> and DefaultSlot<T> to Array<T> (the array is built into these types)
|
|
407
|
+
const formatSlotTypes = (typeText) => {
|
|
408
|
+
return typeText?.replace(/(Default)?Slot<(.+?)>/g, 'Array<$2>');
|
|
400
409
|
}
|
|
401
410
|
|
|
402
411
|
export {
|
|
@@ -415,6 +424,7 @@ export {
|
|
|
415
424
|
getTypeRefs,
|
|
416
425
|
normalizeDescription,
|
|
417
426
|
formatArrays,
|
|
427
|
+
formatSlotTypes,
|
|
418
428
|
isClass,
|
|
419
429
|
normalizeTagType,
|
|
420
430
|
displayDocumentationErrors,
|