@santi020k/lumen 3.0.0 → 4.0.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/README.md +207 -3
- package/dist/cli.js +49 -5
- package/dist/consumer-upgrade-audit.d.ts +10 -0
- package/dist/consumer-upgrade-audit.d.ts.map +1 -0
- package/dist/consumer-upgrade-audit.js +52 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +16 -0
- package/dist/integration-diagnostics.d.ts.map +1 -1
- package/dist/integration-diagnostics.js +199 -3
- package/dist/registry-component-name.d.ts +2 -0
- package/dist/registry-component-name.d.ts.map +1 -0
- package/dist/registry-component-name.js +53 -0
- package/dist/registry-data.d.ts +339 -18
- package/dist/registry-data.d.ts.map +1 -1
- package/dist/registry-data.js +789 -3
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +11 -9
- package/dist/source-script-ranges.d.ts +3 -0
- package/dist/source-script-ranges.d.ts.map +1 -0
- package/dist/source-script-ranges.js +41 -0
- package/dist/v2-migration.d.ts +38 -0
- package/dist/v2-migration.d.ts.map +1 -1
- package/dist/v2-migration.js +26 -14
- package/dist/v4-migration.d.ts +26 -0
- package/dist/v4-migration.d.ts.map +1 -0
- package/dist/v4-migration.js +272 -0
- package/dist/version-migration-dependencies.d.ts +8 -0
- package/dist/version-migration-dependencies.d.ts.map +1 -0
- package/dist/version-migration-dependencies.js +10 -0
- package/dist/version-migration-source.d.ts +4 -0
- package/dist/version-migration-source.d.ts.map +1 -0
- package/dist/version-migration-source.js +281 -0
- package/dist/version-migration.d.ts +34 -0
- package/dist/version-migration.d.ts.map +1 -0
- package/dist/version-migration.js +158 -0
- package/native-components.json +563 -16
- package/package.json +26 -11
- package/release-manifest.json +22 -17
- package/styles/critical.css +634 -61
- package/styles/motion.css +61 -0
- package/styles/world-map.css +30 -0
- package/styles.css +1750 -432
- package/templates/astro/advanced-fields/src/lumen/advanced-fields.astro +35 -0
- package/templates/astro/ai-docs/llms.txt +3 -0
- package/templates/astro/analytics-dashboard/src/lumen/analytics-dashboard.astro +110 -0
- package/templates/astro/auth-onboarding/src/lumen/auth-onboarding.astro +107 -0
- package/templates/astro/command-center/src/lumen/command-center.astro +34 -0
- package/templates/astro/commerce-dashboard/src/lumen/commerce-dashboard.astro +108 -0
- package/templates/astro/content-flow-actions/src/lumen/content-flow-actions.astro +10 -0
- package/templates/astro/content-flow-header/src/lumen/content-flow-header.astro +14 -0
- package/templates/astro/content-flow-list/src/lumen/content-flow-list.astro +13 -0
- package/templates/astro/content-flow-settings/src/lumen/content-flow-settings.astro +17 -0
- package/templates/astro/data-collections/src/lumen/data-collections.astro +52 -0
- package/templates/astro/feature-preview/src/lumen/feature-preview.astro +32 -0
- package/templates/astro/guided-onboarding/src/lumen/guided-onboarding.astro +35 -0
- package/templates/astro/interactive-pricing/src/lumen/interactive-pricing.astro +32 -0
- package/templates/astro/media-workspace/src/lumen/adjustment-controls.astro +89 -0
- package/templates/astro/media-workspace/src/lumen/media-processing.astro +47 -0
- package/templates/astro/media-workspace/src/lumen/media-workspace.astro +77 -0
- package/templates/astro/page-header/src/lumen/page-header.astro +41 -0
- package/templates/astro/project-workspace/src/lumen/project-workspace.astro +103 -0
- package/templates/astro/rich-text-editor/src/lumen/rich-text-editor.astro +21 -0
- package/templates/astro/saas-admin/src/lumen/saas-admin.astro +110 -0
- package/templates/astro/scheduler/src/lumen/scheduler.astro +36 -0
- package/templates/astro/section-header/src/lumen/section-header.astro +35 -0
- package/templates/astro/theme-builder/src/lumen/theme-builder.astro +28 -0
- package/templates/elements/advanced-fields/src/lumen/advanced-fields.html +25 -0
- package/templates/elements/analytics-dashboard/src/lumen/analytics-dashboard.html +28 -0
- package/templates/elements/auth-onboarding/src/lumen/auth-onboarding.html +79 -0
- package/templates/elements/command-center/src/lumen/command-center.html +15 -0
- package/templates/elements/commerce-dashboard/src/lumen/commerce-dashboard.html +24 -0
- package/templates/elements/content-flow-actions/src/lumen/content-flow-actions.html +11 -0
- package/templates/elements/content-flow-header/src/lumen/content-flow-header.html +15 -0
- package/templates/elements/content-flow-list/src/lumen/content-flow-list.html +14 -0
- package/templates/elements/content-flow-settings/src/lumen/content-flow-settings.html +18 -0
- package/templates/elements/data-collections/src/lumen/data-collections.html +31 -0
- package/templates/elements/feature-preview/src/lumen/feature-preview.html +13 -0
- package/templates/elements/guided-onboarding/src/lumen/guided-onboarding.html +16 -0
- package/templates/elements/interactive-pricing/src/lumen/interactive-pricing.html +13 -0
- package/templates/elements/media-workspace/src/lumen/media-workspace.html +57 -0
- package/templates/elements/media-workspace/src/lumen/media-workspace.ts +163 -0
- package/templates/elements/page-header/src/lumen/page-header.html +20 -0
- package/templates/elements/project-workspace/src/lumen/project-workspace.html +17 -0
- package/templates/elements/rich-text-editor/src/lumen/rich-text-editor.html +17 -0
- package/templates/elements/saas-admin/src/lumen/saas-admin.html +18 -0
- package/templates/elements/scheduler/src/lumen/scheduler.html +27 -0
- package/templates/elements/section-header/src/lumen/section-header.html +21 -0
- package/templates/elements/theme-builder/src/lumen/theme-builder.html +59 -0
- package/templates/react/advanced-fields/src/lumen/advanced-fields.tsx +37 -0
- package/templates/react/analytics-dashboard/src/lumen/analytics-dashboard.tsx +143 -0
- package/templates/react/auth-onboarding/src/lumen/auth-onboarding.tsx +129 -0
- package/templates/react/command-center/src/lumen/command-center.tsx +85 -0
- package/templates/react/commerce-dashboard/src/lumen/commerce-dashboard.tsx +148 -0
- package/templates/react/content-flow-actions/src/lumen/content-flow-actions.tsx +11 -0
- package/templates/react/content-flow-header/src/lumen/content-flow-header.tsx +14 -0
- package/templates/react/content-flow-list/src/lumen/content-flow-list.tsx +19 -0
- package/templates/react/content-flow-settings/src/lumen/content-flow-settings.tsx +26 -0
- package/templates/react/data-collections/src/lumen/data-collections.tsx +60 -0
- package/templates/react/feature-preview/src/lumen/feature-preview.tsx +42 -0
- package/templates/react/guided-onboarding/src/lumen/guided-onboarding.tsx +100 -0
- package/templates/react/import-review/src/lumen/import-review.tsx +150 -0
- package/templates/react/interactive-pricing/src/lumen/interactive-pricing.tsx +60 -0
- package/templates/react/media-workspace/src/lumen/adjustment-controls.tsx +61 -0
- package/templates/react/media-workspace/src/lumen/media-processing.tsx +43 -0
- package/templates/react/media-workspace/src/lumen/media-workspace.tsx +100 -0
- package/templates/react/operational-records/src/lumen/operational-records.tsx +92 -0
- package/templates/react/page-header/src/lumen/page-header.tsx +41 -0
- package/templates/react/project-workspace/src/lumen/project-workspace.tsx +112 -0
- package/templates/react/record-workspace/src/lumen/record-workspace.tsx +67 -0
- package/templates/react/review-workflow/src/lumen/review-workflow.tsx +202 -0
- package/templates/react/rich-text-editor/src/lumen/rich-text-editor.tsx +33 -0
- package/templates/react/saas-admin/src/lumen/saas-admin.tsx +119 -0
- package/templates/react/scheduler/src/lumen/scheduler.tsx +45 -0
- package/templates/react/section-header/src/lumen/section-header.tsx +33 -0
- package/templates/react/styles.d.ts +1 -0
- package/templates/react/theme-builder/src/lumen/theme-builder.tsx +57 -0
- package/templates/react/tsconfig.json +14 -0
- package/templates/react/validated-form/src/lumen/validated-form.tsx +166 -0
- package/templates/shared/common/src/lumen/lumen-template.css +247 -0
- package/templates/shared/media-workspace/src/lumen/media-workspace.css +14 -0
- package/templates/shared/visual-blocks/src/lumen/product-blocks.ts +224 -0
- package/v4-migration.json +447 -0
|
@@ -2,6 +2,8 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
3
3
|
import { extname, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { lumenComponentBehavior, lumenComponentNames, lumenGlobalBehaviors, lumenStylingContracts } from '@santi020k/lumen-core';
|
|
5
|
+
import { createSourceFile, forEachChild, isForOfStatement, isImportDeclaration, isNamedImports, isStringLiteral, ScriptKind, ScriptTarget, SyntaxKind } from 'typescript';
|
|
6
|
+
import { findMarkupTagEnd, getMarkupStart } from './v2-migration.js';
|
|
5
7
|
const sourceExtensions = new Set(['.astro', '.css', '.js', '.jsx', '.mjs', '.ts', '.tsx']);
|
|
6
8
|
const ignoredDirectories = new Set([
|
|
7
9
|
'.astro',
|
|
@@ -330,6 +332,199 @@ const getGlobalRuntimeBehaviors = (sources) => lumenGlobalBehaviors
|
|
|
330
332
|
return behavior.authoredBy.split(',').some(eventName => item.source.includes(eventName.trim()));
|
|
331
333
|
}))
|
|
332
334
|
.map(behavior => behavior.name);
|
|
335
|
+
const isRuntimeImport = (statement) => (isImportDeclaration(statement) && isStringLiteral(statement.moduleSpecifier) &&
|
|
336
|
+
statement.moduleSpecifier.text === '@santi020k/lumen-astro/runtime');
|
|
337
|
+
const getDefaultRuntimeName = (binding) => !binding.isTypeOnly && (binding.propertyName?.text ?? binding.name.text) === 'default' ? [binding.name.text] : [];
|
|
338
|
+
const getImportRuntimeNames = (statement) => {
|
|
339
|
+
const clause = statement.importClause;
|
|
340
|
+
if (!clause || clause.phaseModifier === SyntaxKind.TypeKeyword)
|
|
341
|
+
return [];
|
|
342
|
+
const names = clause.name ? [clause.name.text] : [];
|
|
343
|
+
const bindings = clause.namedBindings;
|
|
344
|
+
if (!bindings || !isNamedImports(bindings))
|
|
345
|
+
return names;
|
|
346
|
+
return [...names, ...bindings.elements.flatMap(getDefaultRuntimeName)];
|
|
347
|
+
};
|
|
348
|
+
const getRuntimeBindingNames = ({ file, source }) => {
|
|
349
|
+
if (!source.includes('@santi020k/lumen-astro/runtime'))
|
|
350
|
+
return new Set(['UIPrimitives']);
|
|
351
|
+
try {
|
|
352
|
+
const parsed = createSourceFile(file, source, ScriptTarget.Latest, false, ScriptKind.TS);
|
|
353
|
+
const imports = parsed.statements.filter(isRuntimeImport);
|
|
354
|
+
// Preserve canonical-name detection for legacy imports and wrapper components.
|
|
355
|
+
return imports.length > 0 ? new Set(imports.flatMap(getImportRuntimeNames)) : new Set(['UIPrimitives']);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (!(error instanceof RangeError))
|
|
359
|
+
throw error;
|
|
360
|
+
return new Set();
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
const runtimeTagDelimiter = /[\s/>]/u;
|
|
364
|
+
const getMarkupNameEnd = (source, start) => {
|
|
365
|
+
let end = start + 1;
|
|
366
|
+
while (end < source.length && source[end] !== '<' && !runtimeTagDelimiter.test(source[end] ?? ''))
|
|
367
|
+
end += 1;
|
|
368
|
+
return end;
|
|
369
|
+
};
|
|
370
|
+
const skipRuntimeQuotedText = (source, start) => {
|
|
371
|
+
let end = start + 1;
|
|
372
|
+
while (end < source.length) {
|
|
373
|
+
if (source[end] === '\\')
|
|
374
|
+
end += 2;
|
|
375
|
+
else if (source[end] === source[start])
|
|
376
|
+
return end + 1;
|
|
377
|
+
else
|
|
378
|
+
end += 1;
|
|
379
|
+
}
|
|
380
|
+
return source.length;
|
|
381
|
+
};
|
|
382
|
+
const runtimeRegexPrefixes = new Set(['{', '(', '[', '=', ':', ',', ';', '!', '?', '&', '|', '+', '*', '%', '~', '^', '<', '>', '-']);
|
|
383
|
+
const runtimeRegexKeywords = new Set(['return', 'throw', 'case', 'yield', 'typeof', 'void', 'delete', 'instanceof', 'in', 'new', 'await', 'else', 'do']);
|
|
384
|
+
const getForOfRegexStarts = (source) => {
|
|
385
|
+
const starts = new Set();
|
|
386
|
+
try {
|
|
387
|
+
const parsed = createSourceFile('runtime.tsx', source, ScriptTarget.Latest, true, ScriptKind.TSX);
|
|
388
|
+
const pending = [parsed];
|
|
389
|
+
while (pending.length > 0) {
|
|
390
|
+
const node = pending.pop();
|
|
391
|
+
if (!node)
|
|
392
|
+
continue;
|
|
393
|
+
if (isForOfStatement(node))
|
|
394
|
+
starts.add(node.expression.getStart(parsed));
|
|
395
|
+
forEachChild(node, child => {
|
|
396
|
+
pending.push(child);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
if (!(error instanceof RangeError))
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
return starts;
|
|
405
|
+
};
|
|
406
|
+
const runtimeCodePointStart = (source, index) => {
|
|
407
|
+
const current = source.charCodeAt(index);
|
|
408
|
+
const previous = source.charCodeAt(index - 1);
|
|
409
|
+
return current >= 0xdc00 && current <= 0xdfff && previous >= 0xd800 && previous <= 0xdbff ? index - 1 : index;
|
|
410
|
+
};
|
|
411
|
+
const previousRuntimeCharacter = (source, start, pattern) => {
|
|
412
|
+
let previous = start;
|
|
413
|
+
while (previous >= 0) {
|
|
414
|
+
const pointStart = runtimeCodePointStart(source, previous);
|
|
415
|
+
if (!pattern.test(source.slice(pointStart, previous + 1)))
|
|
416
|
+
break;
|
|
417
|
+
previous = pointStart - 1;
|
|
418
|
+
}
|
|
419
|
+
return previous;
|
|
420
|
+
};
|
|
421
|
+
const isRuntimeRegexStart = (source, start, forOfStarts) => {
|
|
422
|
+
if (forOfStarts.has(start))
|
|
423
|
+
return true;
|
|
424
|
+
const previous = previousRuntimeCharacter(source, start - 1, /\s/u);
|
|
425
|
+
if (previous < 0 || runtimeRegexPrefixes.has(source[previous] ?? ''))
|
|
426
|
+
return true;
|
|
427
|
+
const wordEnd = previous + 1;
|
|
428
|
+
const wordStart = previousRuntimeCharacter(source, previous, /[$\u200c\u200d\p{ID_Continue}]/u) + 1;
|
|
429
|
+
const keyword = source.slice(wordStart, wordEnd);
|
|
430
|
+
if (!runtimeRegexKeywords.has(keyword))
|
|
431
|
+
return false;
|
|
432
|
+
return source[previousRuntimeCharacter(source, wordStart - 1, /\s/u)] !== '.';
|
|
433
|
+
};
|
|
434
|
+
const skipRuntimeRegex = (source, start) => {
|
|
435
|
+
let cursor = start + 1;
|
|
436
|
+
let inClass = false;
|
|
437
|
+
while (cursor < source.length) {
|
|
438
|
+
const character = source[cursor];
|
|
439
|
+
if (character === '\\')
|
|
440
|
+
cursor += 2;
|
|
441
|
+
else {
|
|
442
|
+
if (character === '[')
|
|
443
|
+
inClass = true;
|
|
444
|
+
else if (character === ']')
|
|
445
|
+
inClass = false;
|
|
446
|
+
else if (character === '/' && !inClass)
|
|
447
|
+
return cursor + 1;
|
|
448
|
+
cursor += 1;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return source.length;
|
|
452
|
+
};
|
|
453
|
+
const skipRuntimeExpressionTrivia = (source, start, depth, forOfStarts) => {
|
|
454
|
+
if (depth === 0)
|
|
455
|
+
return start;
|
|
456
|
+
if (/['"`]/u.test(source[start] ?? ''))
|
|
457
|
+
return skipRuntimeQuotedText(source, start);
|
|
458
|
+
if (source.startsWith('/*', start)) {
|
|
459
|
+
const end = source.indexOf('*/', start + 2);
|
|
460
|
+
return end < 0 ? source.length : end + 2;
|
|
461
|
+
}
|
|
462
|
+
if (source.startsWith('//', start)) {
|
|
463
|
+
const end = source.indexOf('\n', start + 2);
|
|
464
|
+
return end < 0 ? source.length : end + 1;
|
|
465
|
+
}
|
|
466
|
+
if (source[start] === '/' && isRuntimeRegexStart(source, start, forOfStarts))
|
|
467
|
+
return skipRuntimeRegex(source, start);
|
|
468
|
+
return start;
|
|
469
|
+
};
|
|
470
|
+
const skipRuntimeRawText = (lowerSource, name, start) => {
|
|
471
|
+
if (name !== 'script' && name !== 'style')
|
|
472
|
+
return start;
|
|
473
|
+
let closing = lowerSource.indexOf(`</${name}`, start);
|
|
474
|
+
while (closing >= 0 && !runtimeTagDelimiter.test(lowerSource[closing + name.length + 2] ?? '')) {
|
|
475
|
+
closing = lowerSource.indexOf(`</${name}`, closing + name.length + 2);
|
|
476
|
+
}
|
|
477
|
+
return closing < 0 ? lowerSource.length : closing;
|
|
478
|
+
};
|
|
479
|
+
const getRuntimeExpressionDepth = (character, depth) => {
|
|
480
|
+
if (character === '{')
|
|
481
|
+
return depth + 1;
|
|
482
|
+
return character === '}' ? Math.max(0, depth - 1) : depth;
|
|
483
|
+
};
|
|
484
|
+
const skipRuntimeMarkupTrivia = (source, start) => {
|
|
485
|
+
if (source.startsWith('<!--', start)) {
|
|
486
|
+
const end = source.indexOf('-->', start + 4);
|
|
487
|
+
return end < 0 ? source.length : end + 3;
|
|
488
|
+
}
|
|
489
|
+
return /[A-Za-z_$/]/u.test(source[start + 1] ?? '') ? start : start + 1;
|
|
490
|
+
};
|
|
491
|
+
const countRuntimeMounts = (entry) => {
|
|
492
|
+
const names = getRuntimeBindingNames(entry);
|
|
493
|
+
let count = 0;
|
|
494
|
+
let depth = 0;
|
|
495
|
+
let start = getMarkupStart(entry.source, entry.file);
|
|
496
|
+
const forOfStarts = new Set([...getForOfRegexStarts(entry.source.slice(start))].map(position => position + start));
|
|
497
|
+
const lowerSource = entry.source.replace(/[A-Z]/gu, character => character.toLowerCase());
|
|
498
|
+
while (start < entry.source.length) {
|
|
499
|
+
const skipped = skipRuntimeExpressionTrivia(entry.source, start, depth, forOfStarts);
|
|
500
|
+
if (skipped !== start) {
|
|
501
|
+
start = skipped;
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
const character = entry.source[start];
|
|
505
|
+
depth = getRuntimeExpressionDepth(character, depth);
|
|
506
|
+
if (character !== '<') {
|
|
507
|
+
start += 1;
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
const markupStart = skipRuntimeMarkupTrivia(entry.source, start);
|
|
511
|
+
if (markupStart !== start) {
|
|
512
|
+
start = markupStart;
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
const end = getMarkupNameEnd(entry.source, start);
|
|
516
|
+
const name = entry.source.slice(start + 1, end);
|
|
517
|
+
const tagEnd = findMarkupTagEnd(entry.source, end, true);
|
|
518
|
+
if (tagEnd < 0) {
|
|
519
|
+
start += 1;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (names.has(name) && runtimeTagDelimiter.test(entry.source[end] ?? ''))
|
|
523
|
+
count += 1;
|
|
524
|
+
start = skipRuntimeRawText(lowerSource, name, tagEnd + 1);
|
|
525
|
+
}
|
|
526
|
+
return count;
|
|
527
|
+
};
|
|
333
528
|
const collectRuntimeFindings = (repositoryRoot, boundary) => {
|
|
334
529
|
const runtimeImports = getRuntimeImports(boundary.sources);
|
|
335
530
|
const runtimeComponents = [
|
|
@@ -338,15 +533,16 @@ const collectRuntimeFindings = (repositoryRoot, boundary) => {
|
|
|
338
533
|
...getGlobalRuntimeBehaviors(boundary.sources)
|
|
339
534
|
])
|
|
340
535
|
];
|
|
341
|
-
const mountSources = boundary.sources
|
|
536
|
+
const mountSources = boundary.sources
|
|
537
|
+
.map(item => ({ ...item, mountCount: countRuntimeMounts(item) }))
|
|
538
|
+
.filter(item => item.mountCount > 0);
|
|
342
539
|
const findings = [];
|
|
343
540
|
if (runtimeComponents.length > 0 && mountSources.length === 0) {
|
|
344
541
|
const firstRuntimeImport = runtimeImports[0];
|
|
345
542
|
findings.push(finding(firstRuntimeImport ? relative(repositoryRoot, firstRuntimeImport.file) : relative(repositoryRoot, boundary.root), 'astro-runtime-missing', `Interactive Astro usage requires UIPrimitives: ${runtimeComponents.join(', ')}.`, 'Mount <UIPrimitives /> once in the application root, or use a documented controlled prop when application code owns the behavior.'));
|
|
346
543
|
}
|
|
347
544
|
for (const mount of mountSources) {
|
|
348
|
-
|
|
349
|
-
if (mountCount > 1) {
|
|
545
|
+
if (mount.mountCount > 1) {
|
|
350
546
|
findings.push(finding(relative(repositoryRoot, mount.file), 'astro-runtime-duplicate', 'UIPrimitives is mounted more than once in this file.', 'Keep one mount in the application root layout.'));
|
|
351
547
|
}
|
|
352
548
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-component-name.d.ts","sourceRoot":"","sources":["../src/registry-component-name.ts"],"names":[],"mappings":"AAqDA,eAAO,MAAM,2BAA2B,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,MAEnE,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const reservedNames = new Set([
|
|
2
|
+
'arguments',
|
|
3
|
+
'await',
|
|
4
|
+
'break',
|
|
5
|
+
'case',
|
|
6
|
+
'catch',
|
|
7
|
+
'class',
|
|
8
|
+
'const',
|
|
9
|
+
'continue',
|
|
10
|
+
'debugger',
|
|
11
|
+
'default',
|
|
12
|
+
'delete',
|
|
13
|
+
'do',
|
|
14
|
+
'else',
|
|
15
|
+
'enum',
|
|
16
|
+
'eval',
|
|
17
|
+
'export',
|
|
18
|
+
'extends',
|
|
19
|
+
'false',
|
|
20
|
+
'finally',
|
|
21
|
+
'for',
|
|
22
|
+
'function',
|
|
23
|
+
'if',
|
|
24
|
+
'implements',
|
|
25
|
+
'import',
|
|
26
|
+
'in',
|
|
27
|
+
'instanceof',
|
|
28
|
+
'interface',
|
|
29
|
+
'let',
|
|
30
|
+
'new',
|
|
31
|
+
'null',
|
|
32
|
+
'package',
|
|
33
|
+
'private',
|
|
34
|
+
'protected',
|
|
35
|
+
'public',
|
|
36
|
+
'return',
|
|
37
|
+
'static',
|
|
38
|
+
'super',
|
|
39
|
+
'switch',
|
|
40
|
+
'this',
|
|
41
|
+
'throw',
|
|
42
|
+
'true',
|
|
43
|
+
'try',
|
|
44
|
+
'typeof',
|
|
45
|
+
'var',
|
|
46
|
+
'void',
|
|
47
|
+
'while',
|
|
48
|
+
'with',
|
|
49
|
+
'yield'
|
|
50
|
+
]);
|
|
51
|
+
// Names are interpolated into identifiers and custom-element tag names in the
|
|
52
|
+
// generated wrappers. Use their shared ASCII subset, without module keywords.
|
|
53
|
+
export const isSafeRegistryComponentName = (name) => (typeof name === 'string' && /^[A-Za-z_][A-Za-z0-9_]*(?![\s\S])/u.test(name) && !reservedNames.has(name));
|