@stencil/core 5.0.0-beta.1 → 5.0.0-beta.10
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/{client-BRu0GtRn.mjs → client-Db2rdxUM.mjs} +34 -13
- package/dist/compiler/browser.d.ts +1 -1
- package/dist/compiler/browser.js +77 -41
- package/dist/compiler/index.d.mts +1 -1
- package/dist/compiler/index.mjs +2 -2
- package/dist/compiler/utils/index.d.mts +1 -1
- package/dist/{compiler-CJG6qvQt.mjs → compiler-PoywOlbq.mjs} +259 -117
- package/dist/declarations/stencil-public-compiler.d.ts +2 -1
- package/dist/{index-DmHmu3y0.d.mts → index-BAP9T4CB.d.mts} +1 -1
- package/dist/{index-BopBfjPu.d.mts → index-BvF31nqP.d.mts} +2 -1
- package/dist/index.mjs +1 -1
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/{node-75gQKkFz.mjs → node-BKtLn2R9.mjs} +1 -1
- package/dist/runtime/client/lazy.js +39 -19
- package/dist/runtime/client/runtime.js +39 -19
- package/dist/runtime/index.js +39 -19
- package/dist/runtime/server/index.mjs +39 -19
- package/dist/sys/node/index.d.mts +1 -1
- package/dist/sys/node/index.mjs +1 -1
- package/dist/sys/node/worker.mjs +2 -2
- package/dist/testing/index.d.mts +2 -1
- package/dist/testing/index.mjs +40 -20
- package/package.json +4 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as __require } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
-
import { S as HYDRATED_CSS } from "./client-
|
|
2
|
+
import { S as HYDRATED_CSS } from "./client-Db2rdxUM.mjs";
|
|
3
3
|
import { $ as VALID_CONFIG_OUTPUT_TARGETS, A as DIST_LAZY, D as COPY, E as COLLECTION_MANIFEST_FILE_NAME, J as STANDALONE, L as EVENT_FLAGS, P as DOCS_JSON, Q as TYPES, R as GENERATED_DTS, S as ASSETS, T as COLLECTION_APP_DATA_FILE_NAME, U as LOADER_BUNDLE, X as STYLE_EXT, Y as STATS, a as isBoolean$1, b as unique, c as isFunction, d as isObject, et as WATCH_FLAGS, f as isString$1, g as sortBy, i as fromEntries, l as isIterable, m as noop, p as mergeIntoWith, r as flatOne, t as dashToPascalCase, u as isNumber$1, v as toDashCase, w as COLLECTION, y as toTitleCase, z as GLOBAL_STYLE } from "./helpers-Cpp3qc3u.mjs";
|
|
4
4
|
import { E as escapeRegExpSpecialCharacters, S as formatComponentRuntimeMeta, T as byteSize, _ as loadRolldownDiagnostics, a as getSourceMappingUrlForEndOfFile, b as splitLineBreaks, c as err, f as augmentDiagnosticWithNode, g as isRolldownError, h as createOnWarnFn, i as getInlineSourceMappingUrlLinker, l as map, m as loadTypeScriptDiagnostics, n as validateComponentTag, p as loadTypeScriptDiagnostic, r as isRemoteUrl, s as rolldownToStencilSourceMap, t as validateComponentModes, u as ok, w as stringifyRuntimeData, x as isRootPath, y as normalizeDiagnostics } from "./validation-DAdGTrys.mjs";
|
|
5
5
|
import { $ as catchError, A as isOutputTargetDocsVscode, B as relativeImport, C as isOutputTargetDistLazy, D as isOutputTargetDocsCustomElementsManifest, E as isOutputTargetDocsCustom, F as isOutputTargetStandalone, G as normalizeFsPathQuery, H as join$2, I as isOutputTargetStats, J as resolve$2, K as normalizePath, L as isOutputTargetTypes, M as isOutputTargetLoaderBundle, N as isOutputTargetSsr, O as isOutputTargetDocsJson, P as isOutputTargetSsrWasm, Q as buildWarn, R as isOutputTargetWww, S as isOutputTargetCustom, T as isOutputTargetDocsAgentSkill, W as normalizeFsPath, X as buildError, Z as buildJsonFileError, a as hasDependency, b as isOutputTargetCollection, d as parsePackageJson, et as hasError, f as readOnlyArrayHasStringMember, g as getComponentsDtsSrcFilePath, h as filterExcludedComponents, i as getTextDocs, j as isOutputTargetGlobalStyle, k as isOutputTargetDocsReadme, l as isTsFile, m as filterActiveTargets, n as createJsVarName, o as isDtsFile, p as readPackageJson, q as relative$1, r as generatePreamble, rt as isGlob, t as addDocBlock, tt as hasWarning, u as isTsxFile, v as getComponentsFromModules, w as isOutputTargetDocs, x as isOutputTargetCopy, y as isOutputTargetAssets, z as isValidConfigOutputTarget } from "./util-IKfWWLJo.mjs";
|
|
6
|
-
import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-
|
|
6
|
+
import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-BKtLn2R9.mjs";
|
|
7
7
|
import ts, { default as ts$1 } from "typescript";
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
9
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
@@ -342,12 +342,13 @@ const scopeSelector = (selector, scopeSelectorText, hostSelector, slotSelector)
|
|
|
342
342
|
else return shallowPart.trim();
|
|
343
343
|
}).join(", ");
|
|
344
344
|
};
|
|
345
|
+
const isScopableAtRule = (selector) => selector.startsWith("@media") || selector.startsWith("@supports") || selector.startsWith("@page") || selector.startsWith("@document") || selector.startsWith("@layer");
|
|
345
346
|
const scopeSelectors = (cssText, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector) => {
|
|
346
347
|
return processRules(cssText, (rule) => {
|
|
347
348
|
let selector = rule.selector;
|
|
348
349
|
let content = rule.content;
|
|
349
350
|
if (rule.selector[0] !== "@") selector = scopeSelector(rule.selector, scopeSelectorText, hostSelector, slotSelector);
|
|
350
|
-
else if (
|
|
351
|
+
else if (isScopableAtRule(rule.selector)) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
|
|
351
352
|
return {
|
|
352
353
|
selector: selector.replace(/\s{2,}/g, " ").trim(),
|
|
353
354
|
content
|
|
@@ -439,14 +440,12 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
|
|
|
439
440
|
rule.selector = placeholder + rule.selector;
|
|
440
441
|
return rule;
|
|
441
442
|
};
|
|
442
|
-
|
|
443
|
+
const commentSelectors = (input) => processRules(input, (rule) => {
|
|
443
444
|
if (rule.selector[0] !== "@") return processCommentedSelector(rule);
|
|
444
|
-
|
|
445
|
-
rule.content = processRules(rule.content, processCommentedSelector);
|
|
446
|
-
return rule;
|
|
447
|
-
}
|
|
445
|
+
if (isScopableAtRule(rule.selector)) rule.content = commentSelectors(rule.content);
|
|
448
446
|
return rule;
|
|
449
447
|
});
|
|
448
|
+
cssText = commentSelectors(cssText);
|
|
450
449
|
}
|
|
451
450
|
const scoped = scopeCssText(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
|
|
452
451
|
cssText = [scoped.cssText, ...commentsWithHash].join("\n");
|
|
@@ -462,9 +461,9 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
|
|
|
462
461
|
};
|
|
463
462
|
//#endregion
|
|
464
463
|
//#region src/version.ts
|
|
465
|
-
const version = "5.0.0-beta.
|
|
466
|
-
const buildId = "
|
|
467
|
-
const vermoji = "
|
|
464
|
+
const version = "5.0.0-beta.10";
|
|
465
|
+
const buildId = "1789054824";
|
|
466
|
+
const vermoji = "🚘";
|
|
468
467
|
/**
|
|
469
468
|
* Get the installed version of a tool/dependency.
|
|
470
469
|
* Handles packages with exports maps that point to subdirectories.
|
|
@@ -7373,7 +7372,13 @@ function createEntryModule(cmps) {
|
|
|
7373
7372
|
}
|
|
7374
7373
|
const getLazyEntry = (isBrowser, assetPath, externalRuntime = false) => {
|
|
7375
7374
|
const s = new MagicString(``);
|
|
7376
|
-
|
|
7375
|
+
const platformExports = [
|
|
7376
|
+
"setNonce",
|
|
7377
|
+
"setRegistry",
|
|
7378
|
+
"setTagTransformer"
|
|
7379
|
+
];
|
|
7380
|
+
if (assetPath) platformExports.push("setAssetPath");
|
|
7381
|
+
s.append(`export { ${platformExports.join(", ")} } from '${STENCIL_CORE_ID}';\n`);
|
|
7377
7382
|
s.append(`import { bootstrapLazy } from '${STENCIL_CORE_ID}';\n`);
|
|
7378
7383
|
if (isBrowser) {
|
|
7379
7384
|
if (assetPath) s.append(`import { setAssetPath } from '${STENCIL_CORE_ID}';\n`);
|
|
@@ -9388,15 +9393,17 @@ const generateStandaloneTypesOutput = async (config, compilerCtx, buildCtx, type
|
|
|
9388
9393
|
if (outputTarget.autoLoader) {
|
|
9389
9394
|
const loaderFileName = typeof outputTarget.autoLoader === "object" ? outputTarget.autoLoader.fileName || "loader" : "loader";
|
|
9390
9395
|
const loaderDtsPath = join$2(outputTarget.dir, `${loaderFileName}.d.ts`);
|
|
9391
|
-
const
|
|
9396
|
+
const hasAssets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0);
|
|
9397
|
+
const loaderDtsCode = generateLoaderType(hasAssets);
|
|
9392
9398
|
await compilerCtx.fs.writeFile(loaderDtsPath, loaderDtsCode, { outputTargetType: outputTarget.type });
|
|
9393
9399
|
}
|
|
9394
9400
|
};
|
|
9395
9401
|
/**
|
|
9396
9402
|
* Generate a type declaration file for the auto-loader module
|
|
9403
|
+
* @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
|
|
9397
9404
|
* @returns the contents of the type declaration file for the loader
|
|
9398
9405
|
*/
|
|
9399
|
-
const generateLoaderType = () => {
|
|
9406
|
+
const generateLoaderType = (hasAssets) => {
|
|
9400
9407
|
return [
|
|
9401
9408
|
`/**`,
|
|
9402
9409
|
` * Start the auto-loader, scanning the DOM and watching for changes.`,
|
|
@@ -9410,7 +9417,18 @@ const generateLoaderType = () => {
|
|
|
9410
9417
|
` * Stop the auto-loader and disconnect the MutationObserver.`,
|
|
9411
9418
|
` */`,
|
|
9412
9419
|
`export declare function stop(): void;`,
|
|
9413
|
-
|
|
9420
|
+
``,
|
|
9421
|
+
...hasAssets ? [
|
|
9422
|
+
`/**`,
|
|
9423
|
+
` * Used to manually set the base path where component assets can be found. The`,
|
|
9424
|
+
` * default is relative to this module's own location, which may not hold once a`,
|
|
9425
|
+
` * consuming bundler relocates it - call this before start() to override.`,
|
|
9426
|
+
` * @param path the asset path to set`,
|
|
9427
|
+
` * @returns the set path`,
|
|
9428
|
+
` */`,
|
|
9429
|
+
`export declare function setAssetPath(path: string): string;`,
|
|
9430
|
+
``
|
|
9431
|
+
] : []
|
|
9414
9432
|
].join("\n");
|
|
9415
9433
|
};
|
|
9416
9434
|
/**
|
|
@@ -9900,7 +9918,7 @@ const FORM_ASSOCIATED_ATTRIBUTES = [
|
|
|
9900
9918
|
* @param cmp the metadata for the component that a type definition string is generated for
|
|
9901
9919
|
* @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
|
|
9902
9920
|
* @param areTypesInternal `true` if types being generated are for a project's internal purposes, `false` otherwise
|
|
9903
|
-
* @param signalBacking `true` if the component is using signal backing for its props; includes the signals map on the element interface
|
|
9921
|
+
* @param signalBacking `true` if the component is using signal backing for its props; includes the signals map on the element interface and unions JSX prop types with `ReadonlySignal<T>`
|
|
9904
9922
|
* @returns the generated types string alongside additional metadata
|
|
9905
9923
|
*/
|
|
9906
9924
|
const generateComponentTypes = (cmp, typeImportData, areTypesInternal, signalBacking = false) => {
|
|
@@ -9917,8 +9935,12 @@ const generateComponentTypes = (cmp, typeImportData, areTypesInternal, signalBac
|
|
|
9917
9935
|
const isDep = cmp.isCollectionDependency;
|
|
9918
9936
|
const propNames = new Set(propAttributes.map((p) => p.name));
|
|
9919
9937
|
const formAssociatedAttrs = cmp.formAssociated ? FORM_ASSOCIATED_ATTRIBUTES.filter((attr) => !propNames.has(attr.name)) : [];
|
|
9938
|
+
const jsxPropAttributes = signalBacking ? propAttributes.map((attr) => ({
|
|
9939
|
+
...attr,
|
|
9940
|
+
type: `${attr.type} | ReadonlySignal<${attr.type}>`
|
|
9941
|
+
})) : propAttributes;
|
|
9920
9942
|
const jsxAttributes = attributesToMultiLineString([
|
|
9921
|
-
...
|
|
9943
|
+
...jsxPropAttributes,
|
|
9922
9944
|
...eventAttributes,
|
|
9923
9945
|
...formAssociatedAttrs
|
|
9924
9946
|
], true, areTypesInternal);
|
|
@@ -10355,8 +10377,9 @@ const generateTypesOutput = async (config, compilerCtx, buildCtx, outputTarget)
|
|
|
10355
10377
|
await generateAppTypes(config, compilerCtx, buildCtx, distPath);
|
|
10356
10378
|
const typesDir = outputTarget.dir;
|
|
10357
10379
|
if (distDtsFilePath) await generateStandaloneTypes(config, compilerCtx, buildCtx, typesDir);
|
|
10358
|
-
|
|
10359
|
-
if (config.outputTargets.some(
|
|
10380
|
+
const hasAssets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0);
|
|
10381
|
+
if (config.outputTargets.some(isOutputTargetLoaderBundle)) await generateLoaderTypes(compilerCtx, typesDir, hasAssets);
|
|
10382
|
+
if (config.outputTargets.some(isOutputTargetStandalone)) await generateStandaloneApiTypes(compilerCtx, typesDir, hasAssets);
|
|
10360
10383
|
};
|
|
10361
10384
|
/**
|
|
10362
10385
|
* Generate loader.d.ts file for the loader entry point.
|
|
@@ -10364,8 +10387,9 @@ const generateTypesOutput = async (config, compilerCtx, buildCtx, outputTarget)
|
|
|
10364
10387
|
*
|
|
10365
10388
|
* @param compilerCtx the current compiler context
|
|
10366
10389
|
* @param typesDir the directory to write the loader.d.ts file to
|
|
10390
|
+
* @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
|
|
10367
10391
|
*/
|
|
10368
|
-
const generateLoaderTypes = async (compilerCtx, typesDir) => {
|
|
10392
|
+
const generateLoaderTypes = async (compilerCtx, typesDir, hasAssets) => {
|
|
10369
10393
|
const loaderDtsContent = `export * from './components';
|
|
10370
10394
|
export interface CustomElementsDefineOptions {
|
|
10371
10395
|
exclude?: string[];
|
|
@@ -10401,7 +10425,17 @@ export type TagTransformer = (tag: string) => string;
|
|
|
10401
10425
|
* Useful for namespacing (e.g. \`my-button\` → \`acme-button\`) in multi-library pages.
|
|
10402
10426
|
*/
|
|
10403
10427
|
export declare function setTagTransformer(transformer: TagTransformer): void;
|
|
10404
|
-
|
|
10428
|
+
${hasAssets ? `
|
|
10429
|
+
/**
|
|
10430
|
+
* Used to manually set the base path where component assets can be found. The
|
|
10431
|
+
* default is relative to this module's own location, which may not hold once a
|
|
10432
|
+
* bundler relocates it, or once its CDN URL diverges from the assets' own -
|
|
10433
|
+
* import and call this before the module's default has been used to override it.
|
|
10434
|
+
* @param path the asset path to set
|
|
10435
|
+
* @returns the set path
|
|
10436
|
+
*/
|
|
10437
|
+
export declare function setAssetPath(path: string): string;
|
|
10438
|
+
` : ""}`;
|
|
10405
10439
|
const loaderDtsPath = join$2(typesDir, "loader.d.ts");
|
|
10406
10440
|
await compilerCtx.fs.writeFile(loaderDtsPath, loaderDtsContent);
|
|
10407
10441
|
};
|
|
@@ -10411,8 +10445,9 @@ export declare function setTagTransformer(transformer: TagTransformer): void;
|
|
|
10411
10445
|
*
|
|
10412
10446
|
* @param compilerCtx the current compiler context
|
|
10413
10447
|
* @param typesDir the directory to write the standalone.d.ts file to
|
|
10448
|
+
* @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
|
|
10414
10449
|
*/
|
|
10415
|
-
const generateStandaloneApiTypes = async (compilerCtx, typesDir) => {
|
|
10450
|
+
const generateStandaloneApiTypes = async (compilerCtx, typesDir, hasAssets) => {
|
|
10416
10451
|
const standaloneDtsContent = `/**
|
|
10417
10452
|
* Used to specify a nonce value that corresponds with an application's CSP.
|
|
10418
10453
|
* When set, the nonce will be added to all dynamically created script and style tags at runtime.
|
|
@@ -10445,7 +10480,16 @@ export interface SetPlatformOptions {
|
|
|
10445
10480
|
rel?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
|
|
10446
10481
|
}
|
|
10447
10482
|
export declare const setPlatformOptions: (opts: SetPlatformOptions) => void;
|
|
10448
|
-
|
|
10483
|
+
${hasAssets ? `
|
|
10484
|
+
/**
|
|
10485
|
+
* Used to manually set the base path where component assets can be found. The
|
|
10486
|
+
* default is relative to this module's own location, which may not hold once a
|
|
10487
|
+
* consuming bundler relocates it - call this before any component module is imported to override.
|
|
10488
|
+
* @param path the asset path to set
|
|
10489
|
+
* @returns the set path
|
|
10490
|
+
*/
|
|
10491
|
+
export declare const setAssetPath: (path: string) => string;
|
|
10492
|
+
` : ""}`;
|
|
10449
10493
|
const standaloneDtsPath = join$2(typesDir, "standalone.d.ts");
|
|
10450
10494
|
await compilerCtx.fs.writeFile(standaloneDtsPath, standaloneDtsContent);
|
|
10451
10495
|
};
|
|
@@ -12406,7 +12450,7 @@ const generateLoaderModule = (components, outputTarget, relativeAssetPath) => {
|
|
|
12406
12450
|
const autoStart = typeof autoLoaderConfig === "object" ? autoLoaderConfig.autoStart !== false : true;
|
|
12407
12451
|
const tagsList = components.map((cmp) => `'${cmp.tagName}'`).join(", ");
|
|
12408
12452
|
const switchCases = components.map((cmp) => ` case '${cmp.tagName}': module = await import('./${cmp.tagName}.js'); break;`).join("\n");
|
|
12409
|
-
const assetPathImport = relativeAssetPath ? `import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';\n` : "";
|
|
12453
|
+
const assetPathImport = relativeAssetPath ? `import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';\nexport { setAssetPath };\n` : "";
|
|
12410
12454
|
const assetPathInit = relativeAssetPath ? `setAssetPath(new URL('${relativeAssetPath}', String(import.meta.url)).href);\n` : "";
|
|
12411
12455
|
return `
|
|
12412
12456
|
import { transformTag, getRegistry } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';
|
|
@@ -12767,12 +12811,25 @@ const addStandaloneInputs = (config, buildCtx, bundleOpts, outputTarget) => {
|
|
|
12767
12811
|
const indexImports = [];
|
|
12768
12812
|
const indexExports = [];
|
|
12769
12813
|
const exportNames = [];
|
|
12814
|
+
let relativeAssetPath;
|
|
12815
|
+
if (components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0)) {
|
|
12816
|
+
const assetsTarget = config.outputTargets.find(isOutputTargetAssets);
|
|
12817
|
+
if (assetsTarget?.dir && outputTarget.dir) {
|
|
12818
|
+
const rel = relative$1(outputTarget.dir, assetsTarget.dir);
|
|
12819
|
+
relativeAssetPath = rel.endsWith("/") ? rel : rel + "/";
|
|
12820
|
+
}
|
|
12821
|
+
}
|
|
12770
12822
|
components.forEach((cmp) => {
|
|
12771
12823
|
const exp = [];
|
|
12772
12824
|
const exportName = dashToPascalCase(cmp.tagName);
|
|
12773
12825
|
const importName = cmp.componentClassName;
|
|
12774
12826
|
const importAs = `$Cmp${exportName}`;
|
|
12775
12827
|
const coreKey = `\0${exportName}`;
|
|
12828
|
+
if (relativeAssetPath) {
|
|
12829
|
+
exp.push(`import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`);
|
|
12830
|
+
exp.push(`export { setAssetPath };`);
|
|
12831
|
+
exp.push(`setAssetPath(new URL('${relativeAssetPath}', import.meta.url).href);`);
|
|
12832
|
+
}
|
|
12776
12833
|
if (cmp.isPlain) {
|
|
12777
12834
|
exp.push(`export { ${importName} as ${exportName} } from '${cmp.sourceFilePath}';`);
|
|
12778
12835
|
indexExports.push(`export { ${exportName} } from '${coreKey}';`);
|
|
@@ -12787,14 +12844,6 @@ const addStandaloneInputs = (config, buildCtx, bundleOpts, outputTarget) => {
|
|
|
12787
12844
|
bundleOpts.inputs[cmp.tagName] = coreKey;
|
|
12788
12845
|
bundleOpts.loader[coreKey] = exp.join("\n");
|
|
12789
12846
|
});
|
|
12790
|
-
let relativeAssetPath;
|
|
12791
|
-
if (components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0)) {
|
|
12792
|
-
const assetsTarget = config.outputTargets.find(isOutputTargetAssets);
|
|
12793
|
-
if (assetsTarget?.dir && outputTarget.dir) {
|
|
12794
|
-
const rel = relative$1(outputTarget.dir, assetsTarget.dir);
|
|
12795
|
-
relativeAssetPath = rel.endsWith("/") ? rel : rel + "/";
|
|
12796
|
-
}
|
|
12797
|
-
}
|
|
12798
12847
|
bundleOpts.loader["\0core"] = generateEntryPoint(outputTarget, indexImports, indexExports, exportNames, relativeAssetPath);
|
|
12799
12848
|
if (outputTarget.autoLoader) {
|
|
12800
12849
|
const loaderFileName = typeof outputTarget.autoLoader === "object" ? outputTarget.autoLoader.fileName || "loader" : "loader";
|
|
@@ -12818,6 +12867,7 @@ const generateEntryPoint = (outputTarget, cmpImports = [], cmpExports = [], cmpN
|
|
|
12818
12867
|
exports.push(`export { setNonce, setRegistry, setTagTransformer, setPlatformOptions } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`, `export * from '${USER_INDEX_ENTRY_ID}';`);
|
|
12819
12868
|
if (relativeAssetPath) {
|
|
12820
12869
|
imports.push(`import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`);
|
|
12870
|
+
exports.push(`export { setAssetPath };`);
|
|
12821
12871
|
body.push(`setAssetPath(new URL('${relativeAssetPath}', import.meta.url).href);`);
|
|
12822
12872
|
}
|
|
12823
12873
|
if (outputTarget.includeGlobalScripts !== false) {
|
|
@@ -15225,14 +15275,16 @@ const parseWatchDecorator = (typeChecker, method, decoratorName) => {
|
|
|
15225
15275
|
* @param diagnostics for surfacing errors and warnings
|
|
15226
15276
|
* @param typeChecker a TypeScript typechecker instance
|
|
15227
15277
|
* @param program a {@link ts.Program} object
|
|
15278
|
+
* @param includeClassExpressions also convert `ts.ClassExpression` nodes (e.g. a mixin factory's
|
|
15279
|
+
* `(Base) => class extends Base {}`), not just named `ts.ClassDeclaration`s
|
|
15228
15280
|
* @returns a TypeScript transformer factory which can be passed to
|
|
15229
15281
|
* TypeScript to transform source code during the compilation process
|
|
15230
15282
|
*/
|
|
15231
|
-
const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) => {
|
|
15283
|
+
const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program, includeClassExpressions = false) => {
|
|
15232
15284
|
return (transformCtx) => {
|
|
15233
15285
|
let sourceFile;
|
|
15234
15286
|
const visit = (node) => {
|
|
15235
|
-
if (ts.isClassDeclaration(node)) return visitClassDeclaration(config, diagnostics, typeChecker, program, node, sourceFile);
|
|
15287
|
+
if (ts.isClassDeclaration(node) || includeClassExpressions && ts.isClassExpression(node)) return visitClassDeclaration(config, diagnostics, typeChecker, program, node, sourceFile);
|
|
15236
15288
|
return ts.visitEachChild(node, visit, transformCtx);
|
|
15237
15289
|
};
|
|
15238
15290
|
return (tsSourceFile) => {
|
|
@@ -15242,10 +15294,10 @@ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) =>
|
|
|
15242
15294
|
};
|
|
15243
15295
|
};
|
|
15244
15296
|
/**
|
|
15245
|
-
* Visit {@link ts.ClassDeclaration} nodes as part of the tree-traversal
|
|
15297
|
+
* Visit {@link ts.ClassDeclaration}/{@link ts.ClassExpression} nodes as part of the tree-traversal
|
|
15246
15298
|
* required for {@link convertDecoratorsToStatic} to work.
|
|
15247
15299
|
*
|
|
15248
|
-
* If a given class
|
|
15300
|
+
* If a given class node is not decorated with `@Component` this
|
|
15249
15301
|
* function will simply return it as-is. If it _is_ decorated, then it will
|
|
15250
15302
|
*
|
|
15251
15303
|
* 1. Convert the arguments to the `@Component` decorator to static values.
|
|
@@ -15254,7 +15306,7 @@ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) =>
|
|
|
15254
15306
|
* to static values.
|
|
15255
15307
|
* 3. Validate that the various options selected by the component author are
|
|
15256
15308
|
* valid, both individually and in combination.
|
|
15257
|
-
* 4. Return an updated class
|
|
15309
|
+
* 4. Return an updated class node which is ready to be used in
|
|
15258
15310
|
* the rest of the Stencil compilation pipeline (e.g. in output target
|
|
15259
15311
|
* generation).
|
|
15260
15312
|
*
|
|
@@ -15273,7 +15325,7 @@ const visitClassDeclaration = (config, diagnostics, typeChecker, program, classN
|
|
|
15273
15325
|
const decoratedMembers = classMembers.filter((member) => (retrieveTsDecorators(member)?.length ?? 0) > 0);
|
|
15274
15326
|
if (!decoratedMembers.length && !componentDecorator) return classNode;
|
|
15275
15327
|
const filteredMethodsAndFields = removeStencilMethodDecorators(Array.from(classMembers), diagnostics, importAliasMap);
|
|
15276
|
-
if (componentDecorator) componentDecoratorToStatic(config, typeChecker, diagnostics, classNode, filteredMethodsAndFields, componentDecorator);
|
|
15328
|
+
if (componentDecorator && ts.isClassDeclaration(classNode)) componentDecoratorToStatic(config, typeChecker, diagnostics, classNode, filteredMethodsAndFields, componentDecorator);
|
|
15277
15329
|
if (decoratedMembers.length > 0) {
|
|
15278
15330
|
const serializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("PropSerialize"), "PropSerialize", importAliasMap.get("Prop"));
|
|
15279
15331
|
const deserializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("AttrDeserialize"), "AttrDeserialize", importAliasMap.get("Prop"));
|
|
@@ -15289,7 +15341,8 @@ const visitClassDeclaration = (config, diagnostics, typeChecker, program, classN
|
|
|
15289
15341
|
validateMethods(diagnostics, classMembers);
|
|
15290
15342
|
const currentDecorators = retrieveTsDecorators(classNode);
|
|
15291
15343
|
const updatedClassFields = updateConstructor(classNode, filteredMethodsAndFields, []);
|
|
15292
|
-
|
|
15344
|
+
const updatedModifiers = [...filterDecorators(currentDecorators, CLASS_DECORATORS_TO_REMOVE.map((decorator) => importAliasMap.get(decorator))) ?? [], ...retrieveTsModifiers(classNode) ?? []];
|
|
15345
|
+
return ts.isClassDeclaration(classNode) ? ts.factory.updateClassDeclaration(classNode, updatedModifiers, classNode.name, classNode.typeParameters, classNode.heritageClauses, updatedClassFields) : ts.factory.updateClassExpression(classNode, updatedModifiers, classNode.name, classNode.typeParameters, classNode.heritageClauses, updatedClassFields);
|
|
15293
15346
|
};
|
|
15294
15347
|
/**
|
|
15295
15348
|
* Take a list of `ClassElement` AST nodes and remove any decorators from
|
|
@@ -15473,11 +15526,11 @@ const parseStaticWatchers = (staticMembers) => {
|
|
|
15473
15526
|
//#endregion
|
|
15474
15527
|
//#region src/compiler/transformers/static-to-meta/class-extension/shared.ts
|
|
15475
15528
|
/**
|
|
15476
|
-
* Warns when an `extends`/`Mixin(...)` target resolved to *something* but no class
|
|
15477
|
-
* could be found inside it - e.g. a mixin factory
|
|
15478
|
-
* (`(Base) =>
|
|
15479
|
-
*
|
|
15480
|
-
*
|
|
15529
|
+
* Warns when an `extends`/`Mixin(...)` target resolved to *something* but no class literal
|
|
15530
|
+
* could be found inside it - e.g. a mixin factory that returns an existing class by reference
|
|
15531
|
+
* (`(Base) => SomeExistingClass`) rather than a class literal. Without this, the target is
|
|
15532
|
+
* silently dropped: any `@Prop`/`@State` etc. it declares just never appears on the extending
|
|
15533
|
+
* component, with no diagnostic explaining why.
|
|
15481
15534
|
* @param buildCtx used to surface the warning - omit to warn silently (e.g. from tests)
|
|
15482
15535
|
* @param targetName the identifier the target was reached through
|
|
15483
15536
|
* @param anchor the node to attach the warning to
|
|
@@ -15485,27 +15538,32 @@ const parseStaticWatchers = (staticMembers) => {
|
|
|
15485
15538
|
function warnMixinFactoryClassNotFound(buildCtx, targetName, anchor) {
|
|
15486
15539
|
if (!buildCtx) return;
|
|
15487
15540
|
const err = buildWarn(buildCtx.diagnostics);
|
|
15488
|
-
err.messageText = `Found "${targetName}", but couldn't find a class
|
|
15541
|
+
err.messageText = `Found "${targetName}", but couldn't find a class inside it. If it's meant to be a mixin factory, make sure it returns a class literal directly, e.g. \`(Base) => class extends Base {}\` or \`(Base) => { class ${targetName}Class extends Base {} return ${targetName}Class; }\` - returning an existing class by reference (\`(Base) => SomeExistingClass\`) isn't recognized, and any \`@Prop\`/\`@State\`/etc. it declares won't be applied.`;
|
|
15489
15542
|
if (!buildCtx.config._isTesting) augmentDiagnosticWithNode(err, anchor);
|
|
15490
15543
|
}
|
|
15491
15544
|
/**
|
|
15492
|
-
* Walks the AST looking for a class declaration, optionally by name -
|
|
15493
|
-
* into a mixin factory's wrapping function (arrow function or `function`
|
|
15494
|
-
*
|
|
15495
|
-
*
|
|
15545
|
+
* Walks the AST looking for a class declaration or class expression, optionally by name -
|
|
15546
|
+
* descends into a mixin factory's wrapping function (arrow function or `function` declaration)
|
|
15547
|
+
* body too, since a mixin factory's class is always nested one level inside it. Recognizes all of:
|
|
15548
|
+
* `const Foo = (Base) => class extends Base {}` (concise arrow body), `const Foo = (Base) => {
|
|
15549
|
+
* return class extends Base {}; }` (block body, `return` of a class expression), and `const Foo =
|
|
15550
|
+
* (Base) => { class FooClass extends Base {} return FooClass; }` (block body, named declaration).
|
|
15496
15551
|
* @param node the node to search from
|
|
15497
|
-
* @param name if given, only matches a class
|
|
15498
|
-
* @returns the found class
|
|
15552
|
+
* @param name if given, only matches a class with this name
|
|
15553
|
+
* @returns the found class, or `undefined`
|
|
15499
15554
|
*/
|
|
15500
15555
|
function findClassWalk(node, name) {
|
|
15501
15556
|
if (!node) return void 0;
|
|
15502
|
-
if (ts.isClassDeclaration(node)) {
|
|
15557
|
+
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
|
15503
15558
|
if (!name || node.name?.text === name) return node;
|
|
15504
15559
|
} else if (ts.isVariableDeclaration(node) && (!name || name === node.name?.text) && node.initializer && ts.isArrowFunction(node.initializer)) {
|
|
15560
|
+
const body = node.initializer.body;
|
|
15561
|
+
if (ts.isClassExpression(body)) return body;
|
|
15505
15562
|
let found;
|
|
15506
|
-
ts.forEachChild(
|
|
15563
|
+
ts.forEachChild(body, (child) => {
|
|
15507
15564
|
if (found) return;
|
|
15508
15565
|
if (ts.isClassDeclaration(child)) found = child;
|
|
15566
|
+
else if (ts.isReturnStatement(child) && child.expression && ts.isClassExpression(child.expression)) found = child.expression;
|
|
15509
15567
|
});
|
|
15510
15568
|
return found;
|
|
15511
15569
|
}
|
|
@@ -15518,6 +15576,22 @@ function findClassWalk(node, name) {
|
|
|
15518
15576
|
return found;
|
|
15519
15577
|
}
|
|
15520
15578
|
/**
|
|
15579
|
+
* The declared name of a mixin-factory statement (`function Foo() {}`, or `const Foo = ...`) -
|
|
15580
|
+
* survives the decorator-to-static-getter transform even when the factory's inner class doesn't
|
|
15581
|
+
* have a name of its own, so it can anchor a post-transform re-lookup via `findClassWalk`.
|
|
15582
|
+
* @param node the factory statement (or its variable declaration) to read a name from
|
|
15583
|
+
* @returns the declared name, or `undefined` if it can't be determined
|
|
15584
|
+
*/
|
|
15585
|
+
function factoryDeclaredName(node) {
|
|
15586
|
+
if (!node) return void 0;
|
|
15587
|
+
if (ts.isFunctionDeclaration(node)) return node.name?.text;
|
|
15588
|
+
if (ts.isVariableDeclaration(node)) return ts.isIdentifier(node.name) ? node.name.text : void 0;
|
|
15589
|
+
if (ts.isVariableStatement(node)) {
|
|
15590
|
+
const decl = node.declarationList.declarations[0];
|
|
15591
|
+
return decl && ts.isIdentifier(decl.name) ? decl.name.text : void 0;
|
|
15592
|
+
}
|
|
15593
|
+
}
|
|
15594
|
+
/**
|
|
15521
15595
|
* Matches a top-level class/function/variable declaration by name - the three
|
|
15522
15596
|
* shapes a mixin or base-class export can take (a plain class, a mixin
|
|
15523
15597
|
* factory function declaration, or a mixin factory assigned to a `const`).
|
|
@@ -15639,7 +15713,7 @@ function convertDiskSourceFileDecorators(sourceFile, config, target = ts.ScriptT
|
|
|
15639
15713
|
const program = ts.createProgram([sourceFile.fileName], compilerOptions, host);
|
|
15640
15714
|
const typeChecker = program.getTypeChecker();
|
|
15641
15715
|
const ownSourceFile = program.getSourceFile(sourceFile.fileName) ?? sourceFile;
|
|
15642
|
-
const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program)]);
|
|
15716
|
+
const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program, true)]);
|
|
15643
15717
|
const printed = ts.createPrinter({ removeComments: false }).printFile(result.transformed[0]);
|
|
15644
15718
|
return ts.createSourceFile(sourceFile.fileName, printed, target, true);
|
|
15645
15719
|
}
|
|
@@ -15726,6 +15800,7 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
|
|
|
15726
15800
|
const targetScriptTarget = (ogModule?.staticSourceFile)?.languageVersion ?? ts.ScriptTarget.ESNext;
|
|
15727
15801
|
let classIdentifiers = [];
|
|
15728
15802
|
let foundClassDeclaration;
|
|
15803
|
+
let foundClassName;
|
|
15729
15804
|
let keepLooking = true;
|
|
15730
15805
|
extendsClause.types.forEach((type) => {
|
|
15731
15806
|
if (ts.isExpressionWithTypeArguments(type) && ts.isCallExpression(type.expression) && type.expression.expression.getText() === "Mixin") classIdentifiers = type.expression.arguments.filter(ts.isIdentifier);
|
|
@@ -15742,9 +15817,11 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
|
|
|
15742
15817
|
declarations = [...source.statements];
|
|
15743
15818
|
}
|
|
15744
15819
|
foundClassDeclaration = declarations?.find(ts.isClassDeclaration);
|
|
15820
|
+
foundClassName = foundClassDeclaration?.name?.getText();
|
|
15745
15821
|
if (!foundClassDeclaration) {
|
|
15746
15822
|
const node = declarations?.[0];
|
|
15747
15823
|
foundClassDeclaration = findClassWalk(node);
|
|
15824
|
+
foundClassName = foundClassDeclaration?.name?.getText() ?? factoryDeclaredName(node);
|
|
15748
15825
|
if (!node) throw "revert to sad path";
|
|
15749
15826
|
keepLooking = false;
|
|
15750
15827
|
if (!foundClassDeclaration) warnMixinFactoryClassNotFound(buildCtx, extendee.getText(), classDeclaration);
|
|
@@ -15753,7 +15830,7 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
|
|
|
15753
15830
|
const foundModule = compilerCtx.moduleMap.get(foundClassDeclaration.getSourceFile().fileName);
|
|
15754
15831
|
if (foundModule) {
|
|
15755
15832
|
const moduleSourceFile = foundModule.staticSourceFile;
|
|
15756
|
-
const sourceClass = findClassWalk(moduleSourceFile,
|
|
15833
|
+
const sourceClass = findClassWalk(moduleSourceFile, foundClassName);
|
|
15757
15834
|
if (sourceClass) {
|
|
15758
15835
|
dependentClasses.push({
|
|
15759
15836
|
classNode: sourceClass,
|
|
@@ -15774,20 +15851,24 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
|
|
|
15774
15851
|
if (!buildCtx.config._isTesting) augmentDiagnosticWithNode(err, classDeclaration);
|
|
15775
15852
|
return;
|
|
15776
15853
|
}
|
|
15777
|
-
if (matchedStatement && ts.isClassDeclaration(matchedStatement))
|
|
15778
|
-
|
|
15854
|
+
if (matchedStatement && ts.isClassDeclaration(matchedStatement)) {
|
|
15855
|
+
foundClassDeclaration = matchedStatement;
|
|
15856
|
+
foundClassName = foundClassDeclaration.name?.getText();
|
|
15857
|
+
} else if (matchedStatement) {
|
|
15779
15858
|
foundClassDeclaration = findClassWalk(matchedStatement);
|
|
15859
|
+
foundClassName = foundClassDeclaration?.name?.getText() ?? extendee.getText();
|
|
15780
15860
|
keepLooking = false;
|
|
15781
15861
|
if (!foundClassDeclaration) warnMixinFactoryClassNotFound(buildCtx, extendee.getText(), classDeclaration);
|
|
15782
15862
|
} else {
|
|
15783
15863
|
foundClassDeclaration = findClassWalk(currentSource, extendee.getText());
|
|
15864
|
+
foundClassName = foundClassDeclaration?.name?.getText() ?? extendee.getText();
|
|
15784
15865
|
keepLooking = false;
|
|
15785
15866
|
}
|
|
15786
15867
|
if (foundClassDeclaration && !dependentClasses.some((dc) => dc.classNode === foundClassDeclaration)) {
|
|
15787
15868
|
const foundModule = compilerCtx.moduleMap.get(currentSource.fileName);
|
|
15788
15869
|
if (foundModule?.staticSourceFile) {
|
|
15789
15870
|
const transformedSource = foundModule.staticSourceFile;
|
|
15790
|
-
const transformedClass = findClassWalk(transformedSource,
|
|
15871
|
+
const transformedClass = findClassWalk(transformedSource, foundClassName);
|
|
15791
15872
|
if (transformedClass) {
|
|
15792
15873
|
dependentClasses.push({
|
|
15793
15874
|
classNode: transformedClass,
|
|
@@ -16072,7 +16153,7 @@ function convertInMemorySourceDecorators(sourceFile, config) {
|
|
|
16072
16153
|
const program = ts.createProgram([sourceFile.fileName], compilerOptions, compilerHost);
|
|
16073
16154
|
const typeChecker = program.getTypeChecker();
|
|
16074
16155
|
const ownSourceFile = program.getSourceFile(sourceFile.fileName) ?? sourceFile;
|
|
16075
|
-
const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program)]);
|
|
16156
|
+
const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program, true)]);
|
|
16076
16157
|
const printed = ts.createPrinter({ removeComments: false }).printFile(result.transformed[0]);
|
|
16077
16158
|
const scriptKind = sourceFile.fileName.endsWith(".tsx") || sourceFile.fileName.endsWith(".ts") ? ts.ScriptKind.TSX : ts.ScriptKind.JS;
|
|
16078
16159
|
return ts.createSourceFile(sourceFile.fileName, printed, sourceFile.languageVersion, true, scriptKind);
|
|
@@ -16247,7 +16328,8 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
|
|
|
16247
16328
|
ancestors.push({
|
|
16248
16329
|
classNode: foundClass,
|
|
16249
16330
|
sourceFile: foundSf,
|
|
16250
|
-
path: foundPath
|
|
16331
|
+
path: foundPath,
|
|
16332
|
+
factoryName: parentName
|
|
16251
16333
|
});
|
|
16252
16334
|
if (keepLooking) resolveAncestors(foundClass, foundSf, foundPath, resolveImport, visited, ancestors, rootClassDeclaration, buildCtx);
|
|
16253
16335
|
}
|
|
@@ -16264,8 +16346,8 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
|
|
|
16264
16346
|
* @returns the ancestor's metadata
|
|
16265
16347
|
*/
|
|
16266
16348
|
function extractAncestorMeta(ancestor, cmpSourceFile, resolveImport, config) {
|
|
16267
|
-
const { classNode, sourceFile: parentSf, path: resolvedPath } = ancestor;
|
|
16268
|
-
const className = classNode.name?.text;
|
|
16349
|
+
const { classNode, sourceFile: parentSf, path: resolvedPath, factoryName } = ancestor;
|
|
16350
|
+
const className = classNode.name?.text ?? factoryName;
|
|
16269
16351
|
const parentStaticMembers = classNode.members.filter(isStaticGetter);
|
|
16270
16352
|
let resolvedClassNode = classNode;
|
|
16271
16353
|
let resolvedStaticMembers = parentStaticMembers;
|
|
@@ -18121,13 +18203,17 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
|
|
|
18121
18203
|
const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
|
|
18122
18204
|
const standalone = config.outputTargets.find(isOutputTargetStandalone);
|
|
18123
18205
|
const types = config.outputTargets.find(isOutputTargetTypes);
|
|
18206
|
+
const srcIndexPath = join$2(config.srcDir, "index.ts");
|
|
18207
|
+
const hasSrcIndex = compilerCtx.fs.accessSync(srcIndexPath);
|
|
18124
18208
|
const moduleOptions = [];
|
|
18125
|
-
if (loaderBundle?.dir)
|
|
18209
|
+
if (loaderBundle?.dir) {
|
|
18210
|
+
const loaderEntry = hasSrcIndex ? join$2(loaderBundle.dir, "index.js") : join$2(loaderBundle.dir, "esm", "loader.js");
|
|
18211
|
+
moduleOptions.push(normalizePath(relative$1(config.rootDir, loaderEntry)));
|
|
18212
|
+
}
|
|
18126
18213
|
if (standalone?.dir) moduleOptions.push(normalizePath(relative$1(config.rootDir, join$2(standalone.dir, "index.js"))));
|
|
18127
18214
|
const typesOptions = [];
|
|
18128
18215
|
if (types?.dir) {
|
|
18129
|
-
|
|
18130
|
-
if (compilerCtx.fs.accessSync(srcIndexPath)) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "index.d.ts"))));
|
|
18216
|
+
if (hasSrcIndex) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "index.d.ts"))));
|
|
18131
18217
|
else {
|
|
18132
18218
|
if (loaderBundle) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))));
|
|
18133
18219
|
if (standalone) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "standalone.d.ts"))));
|
|
@@ -18145,6 +18231,31 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
|
|
|
18145
18231
|
};
|
|
18146
18232
|
};
|
|
18147
18233
|
/**
|
|
18234
|
+
* Collect the rootDir-relative directories of every configured output target that must
|
|
18235
|
+
* ship in the published npm package for consumers (and their tooling) to be able to use
|
|
18236
|
+
* it - as opposed to dev-only artifacts like `www`.
|
|
18237
|
+
* @param config The validated Stencil configuration
|
|
18238
|
+
* @param buildCtx The build context (used to check whether there are actually component
|
|
18239
|
+
* assets to copy - the `assets` output target is otherwise a no-op and its directory is
|
|
18240
|
+
* never written)
|
|
18241
|
+
* @returns a de-duplicated list of rootDir-relative directory paths
|
|
18242
|
+
*/
|
|
18243
|
+
const getDistributableOutputDirs = (config, buildCtx) => {
|
|
18244
|
+
const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
|
|
18245
|
+
const standalone = config.outputTargets.find(isOutputTargetStandalone);
|
|
18246
|
+
const types = config.outputTargets.find(isOutputTargetTypes);
|
|
18247
|
+
const collections = config.outputTargets.filter(isOutputTargetCollection);
|
|
18248
|
+
const assets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0) ? config.outputTargets.find(isOutputTargetAssets) : void 0;
|
|
18249
|
+
const dirs = [
|
|
18250
|
+
loaderBundle?.dir,
|
|
18251
|
+
standalone?.dir,
|
|
18252
|
+
types?.dir,
|
|
18253
|
+
assets?.dir,
|
|
18254
|
+
...collections.map((c) => c.dir)
|
|
18255
|
+
].filter((dir) => !!dir).map((dir) => normalizePath(relative$1(config.rootDir, dir)));
|
|
18256
|
+
return Array.from(new Set(dirs));
|
|
18257
|
+
};
|
|
18258
|
+
/**
|
|
18148
18259
|
* Validate the package.json file for a project, checking that various fields
|
|
18149
18260
|
* are set correctly for the currently-configured output targets.
|
|
18150
18261
|
*
|
|
@@ -18158,8 +18269,8 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
|
|
|
18158
18269
|
const validateBuildPackageJson = async (config, compilerCtx, buildCtx) => {
|
|
18159
18270
|
if (config.watch || config.devMode || buildCtx.packageJson == null) return;
|
|
18160
18271
|
validatePackageJson(config, compilerCtx, buildCtx);
|
|
18161
|
-
|
|
18162
|
-
|
|
18272
|
+
await validateFilesField(config, compilerCtx, buildCtx);
|
|
18273
|
+
config.outputTargets.filter(isOutputTargetCollection).forEach((stencilCollectionOT) => validateCollectionField(config, compilerCtx, buildCtx, stencilCollectionOT));
|
|
18163
18274
|
};
|
|
18164
18275
|
/**
|
|
18165
18276
|
* Validates a project's package.json fields against recommended values
|
|
@@ -18277,40 +18388,49 @@ const validateTypeField = (config, compilerCtx, buildCtx, recommendations) => {
|
|
|
18277
18388
|
if (recommendations.moduleOptions.length > 0 && currentType !== "module") packageJsonWarn(config, compilerCtx, buildCtx, `package.json "type" property should be set to "module".`, "\"type\"");
|
|
18278
18389
|
};
|
|
18279
18390
|
/**
|
|
18280
|
-
*
|
|
18281
|
-
*
|
|
18282
|
-
* @param
|
|
18283
|
-
* @param
|
|
18284
|
-
* @
|
|
18285
|
-
* @param outputTarget the collection output target to validate against
|
|
18391
|
+
* Check if a rootDir-relative directory is covered by a package.json `files` array,
|
|
18392
|
+
* either directly or via a parent directory entry (e.g. "dist/" covers "dist/types/").
|
|
18393
|
+
* @param files the package.json "files" array
|
|
18394
|
+
* @param dir the rootDir-relative directory to check for
|
|
18395
|
+
* @returns true if `dir` is covered by one of the `files` entries
|
|
18286
18396
|
*/
|
|
18287
|
-
const
|
|
18288
|
-
|
|
18397
|
+
const isDirCoveredByFiles = (files, dir) => {
|
|
18398
|
+
const normalizedDir = dir.replace(/\/$/, "").replace(/^\.\//, "");
|
|
18399
|
+
return files.some((userPath) => {
|
|
18400
|
+
const normalizedUserPath = normalizePath(userPath).replace(/\/$/, "").replace(/^\.\//, "");
|
|
18401
|
+
if (normalizedUserPath === normalizedDir) return true;
|
|
18402
|
+
const userPathWithSlash = normalizedUserPath + "/";
|
|
18403
|
+
return normalizedDir.startsWith(userPathWithSlash);
|
|
18404
|
+
});
|
|
18289
18405
|
};
|
|
18290
18406
|
/**
|
|
18291
|
-
* Validate that the `files` field in `package.json`
|
|
18292
|
-
*
|
|
18407
|
+
* Validate that the `files` field in `package.json` covers every distributable output
|
|
18408
|
+
* directory (loader-bundle, standalone, types, collection) - not just one of them -
|
|
18409
|
+
* since `npm publish` needs all of them to produce a working package for consumers.
|
|
18293
18410
|
* @param config the Stencil configuration associated with the project being compiled
|
|
18294
18411
|
* @param compilerCtx the current compiler context
|
|
18295
18412
|
* @param buildCtx the context associated with the current build
|
|
18296
|
-
* @param outputTarget the collection output target to validate against
|
|
18297
18413
|
*/
|
|
18298
|
-
const
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
const
|
|
18304
|
-
if (
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18414
|
+
const validateFilesField = async (config, compilerCtx, buildCtx) => {
|
|
18415
|
+
const distDirs = getDistributableOutputDirs(config, buildCtx);
|
|
18416
|
+
if (distDirs.length === 0) return;
|
|
18417
|
+
const formatDirs = (dirs) => dirs.map((dir) => `"${dir}/"`).join(", ");
|
|
18418
|
+
if (!Array.isArray(buildCtx.packageJson.files)) {
|
|
18419
|
+
const npmignorePath = join$2(dirname$1(config.packageJsonFilePath), ".npmignore");
|
|
18420
|
+
if (!await compilerCtx.fs.access(npmignorePath)) {
|
|
18421
|
+
const msg = `package.json is missing a "files" array. Without one, "npm publish" falls back to ".gitignore" to decide what to include, which will likely exclude ${distDirs.length > 1 ? "the distribution directories" : "the distribution directory"} ${formatDirs(distDirs)}. Add a "files" array covering ${distDirs.length > 1 ? "them" : "it"} to package.json (or add a ".npmignore").`;
|
|
18422
|
+
packageJsonWarn(config, compilerCtx, buildCtx, msg, `"files"`);
|
|
18423
|
+
}
|
|
18424
|
+
return;
|
|
18425
|
+
}
|
|
18426
|
+
const files = buildCtx.packageJson.files;
|
|
18427
|
+
const uncoveredDirs = distDirs.filter((dir) => !isDirCoveredByFiles(files, dir));
|
|
18428
|
+
if (uncoveredDirs.length > 0) {
|
|
18429
|
+
const msg = `package.json "files" array must contain the distribution ${uncoveredDirs.length > 1 ? "directories" : "directory"} ${formatDirs(uncoveredDirs)} when generating a distribution.`;
|
|
18310
18430
|
packageJsonWarn(config, compilerCtx, buildCtx, msg, `"files"`);
|
|
18311
18431
|
return;
|
|
18312
18432
|
}
|
|
18313
|
-
await Promise.all(
|
|
18433
|
+
await Promise.all(files.map(async (pkgFile) => {
|
|
18314
18434
|
if (!isGlob(pkgFile)) {
|
|
18315
18435
|
const packageJsonDir = dirname$1(config.packageJsonFilePath);
|
|
18316
18436
|
const absPath = join$2(packageJsonDir, pkgFile);
|
|
@@ -18425,6 +18545,24 @@ const validateBuildFiles = (config, compilerCtx, buildCtx) => {
|
|
|
18425
18545
|
//#endregion
|
|
18426
18546
|
//#region src/compiler/build/write-export-maps.ts
|
|
18427
18547
|
/**
|
|
18548
|
+
* Create the shared {@link NpmPkgSet} used across a single `writeExportMaps` run.
|
|
18549
|
+
* @param buildCtx The build context to report a warning diagnostic on if `npm` can't be run
|
|
18550
|
+
* @returns A function that shells out to `npm pkg set`, swallowing failure after warning once
|
|
18551
|
+
*/
|
|
18552
|
+
const createNpmPkgSet = (buildCtx) => {
|
|
18553
|
+
let npmAvailable = true;
|
|
18554
|
+
return (cmd) => {
|
|
18555
|
+
if (!npmAvailable) return;
|
|
18556
|
+
try {
|
|
18557
|
+
execSync(`npm pkg set ${cmd}`);
|
|
18558
|
+
} catch (e) {
|
|
18559
|
+
npmAvailable = false;
|
|
18560
|
+
const warn = buildWarn(buildCtx.diagnostics);
|
|
18561
|
+
warn.messageText = `Unable to generate "exports" map in package.json: the "npm" CLI could not be run (${e.message ?? e}). Set "generateExportMaps: false" in your Stencil config to silence this warning.`;
|
|
18562
|
+
}
|
|
18563
|
+
};
|
|
18564
|
+
};
|
|
18565
|
+
/**
|
|
18428
18566
|
* Create export map entry point definitions for the `package.json` file using the npm CLI.
|
|
18429
18567
|
*
|
|
18430
18568
|
* In v5, this uses a "smart default" approach:
|
|
@@ -18435,15 +18573,17 @@ const validateBuildFiles = (config, compilerCtx, buildCtx) => {
|
|
|
18435
18573
|
* - Generate per-component exports for standalone output
|
|
18436
18574
|
*
|
|
18437
18575
|
* @param config The validated Stencil config
|
|
18576
|
+
* @param compilerCtx The compiler context (used to detect a user-authored src/index.ts)
|
|
18438
18577
|
* @param buildCtx The build context containing the components to generate export maps for
|
|
18439
18578
|
*/
|
|
18440
|
-
const writeExportMaps = (config, buildCtx) => {
|
|
18579
|
+
const writeExportMaps = (config, compilerCtx, buildCtx) => {
|
|
18441
18580
|
const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
|
|
18442
18581
|
const standalone = config.outputTargets.find(isOutputTargetStandalone);
|
|
18443
18582
|
const types = config.outputTargets.find(isOutputTargetTypes);
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
if (
|
|
18583
|
+
const npmPkgSet = createNpmPkgSet(buildCtx);
|
|
18584
|
+
generateRootExport(config, compilerCtx, buildCtx, loaderBundle, standalone, types, npmPkgSet);
|
|
18585
|
+
if (loaderBundle) generateLoaderExport(config, loaderBundle, types, npmPkgSet);
|
|
18586
|
+
if (standalone) generateComponentExports(config, buildCtx, standalone, npmPkgSet);
|
|
18447
18587
|
};
|
|
18448
18588
|
/**
|
|
18449
18589
|
* Generate the root export `exports["."]`.
|
|
@@ -18453,28 +18593,32 @@ const writeExportMaps = (config, buildCtx) => {
|
|
|
18453
18593
|
* - If valid, leave it alone
|
|
18454
18594
|
* - If missing or invalid, set default (loader-bundle > standalone priority)
|
|
18455
18595
|
* @param config The validated Stencil config
|
|
18596
|
+
* @param compilerCtx The compiler context (used to detect a user-authored src/index.ts)
|
|
18456
18597
|
* @param buildCtx The build context containing the components to generate export maps for
|
|
18457
18598
|
* @param loaderBundle The loader-bundle output target, if it exists
|
|
18458
18599
|
* @param standalone The standalone output target, if it exists
|
|
18459
18600
|
* @param types The types output target, if it exists
|
|
18601
|
+
* @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
|
|
18460
18602
|
*/
|
|
18461
|
-
const generateRootExport = (config, buildCtx, loaderBundle, standalone, types) => {
|
|
18603
|
+
const generateRootExport = (config, compilerCtx, buildCtx, loaderBundle, standalone, types, npmPkgSet) => {
|
|
18462
18604
|
if (!loaderBundle && !standalone) return;
|
|
18605
|
+
const hasSrcIndex = compilerCtx.fs.accessSync(join$2(config.srcDir, "index.ts"));
|
|
18606
|
+
const rootUsesEmptyLoaderIndex = !!loaderBundle && !hasSrcIndex;
|
|
18463
18607
|
const currentImport = ((buildCtx.packageJson?.exports)?.["."])?.import;
|
|
18464
18608
|
if (!(currentImport && isValidRootExport(config, currentImport, loaderBundle, standalone))) {
|
|
18465
18609
|
const primaryDir = loaderBundle?.dir ?? standalone?.dir;
|
|
18466
18610
|
if (primaryDir) {
|
|
18467
|
-
const
|
|
18468
|
-
|
|
18611
|
+
const entryFile = rootUsesEmptyLoaderIndex ? join$2("esm", "loader.js") : "index.js";
|
|
18612
|
+
npmPkgSet(`"exports[.][import]"="${normalizePath(relative$1(config.rootDir, join$2(primaryDir, entryFile)))}"`);
|
|
18469
18613
|
if (loaderBundle?.cjs) {
|
|
18470
|
-
const
|
|
18471
|
-
|
|
18614
|
+
const cjsEntryFile = rootUsesEmptyLoaderIndex ? join$2("cjs", "loader.cjs") : "index.cjs";
|
|
18615
|
+
npmPkgSet(`"exports[.][require]"="${normalizePath(relative$1(config.rootDir, join$2(loaderBundle.dir, cjsEntryFile)))}"`);
|
|
18472
18616
|
}
|
|
18473
18617
|
}
|
|
18474
18618
|
}
|
|
18475
18619
|
if (types?.dir) {
|
|
18476
|
-
const
|
|
18477
|
-
|
|
18620
|
+
const typesFile = rootUsesEmptyLoaderIndex ? "loader.d.ts" : "index.d.ts";
|
|
18621
|
+
npmPkgSet(`"exports[.][types]"="${normalizePath(relative$1(config.rootDir, join$2(types.dir, typesFile)))}"`);
|
|
18478
18622
|
}
|
|
18479
18623
|
};
|
|
18480
18624
|
/**
|
|
@@ -18517,20 +18661,16 @@ const ensureRelativePrefix = (path) => {
|
|
|
18517
18661
|
* @param config The validated Stencil config
|
|
18518
18662
|
* @param loaderBundle The loader-bundle output target
|
|
18519
18663
|
* @param types The types output target, if it exists
|
|
18664
|
+
* @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
|
|
18520
18665
|
*/
|
|
18521
|
-
const generateLoaderExport = (config, loaderBundle, types) => {
|
|
18666
|
+
const generateLoaderExport = (config, loaderBundle, types, npmPkgSet) => {
|
|
18522
18667
|
const esmDir = join$2(loaderBundle.dir, "esm");
|
|
18523
|
-
|
|
18524
|
-
execSync(`npm pkg set "exports[./loader][import]"="${esmLoaderPath}"`);
|
|
18668
|
+
npmPkgSet(`"exports[./loader][import]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(esmDir, "loader.js"))))}"`);
|
|
18525
18669
|
if (loaderBundle.cjs) {
|
|
18526
18670
|
const cjsDir = join$2(loaderBundle.dir, "cjs");
|
|
18527
|
-
|
|
18528
|
-
execSync(`npm pkg set "exports[./loader][require]"="${cjsLoaderPath}"`);
|
|
18529
|
-
}
|
|
18530
|
-
if (types?.dir) {
|
|
18531
|
-
const typesPath = ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))));
|
|
18532
|
-
execSync(`npm pkg set "exports[./loader][types]"="${typesPath}"`);
|
|
18671
|
+
npmPkgSet(`"exports[./loader][require]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(cjsDir, "loader.cjs"))))}"`);
|
|
18533
18672
|
}
|
|
18673
|
+
if (types?.dir) npmPkgSet(`"exports[./loader][types]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))))}"`);
|
|
18534
18674
|
};
|
|
18535
18675
|
/**
|
|
18536
18676
|
* Generate per-component exports for standalone output.
|
|
@@ -18538,13 +18678,14 @@ const generateLoaderExport = (config, loaderBundle, types) => {
|
|
|
18538
18678
|
* @param config The validated Stencil config
|
|
18539
18679
|
* @param buildCtx The build context containing the components to generate export maps for
|
|
18540
18680
|
* @param standalone The standalone output target
|
|
18681
|
+
* @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
|
|
18541
18682
|
*/
|
|
18542
|
-
const generateComponentExports = (config, buildCtx, standalone) => {
|
|
18683
|
+
const generateComponentExports = (config, buildCtx, standalone, npmPkgSet) => {
|
|
18543
18684
|
let outDir = relative$1(config.rootDir, standalone.dir);
|
|
18544
18685
|
if (!outDir.startsWith(".")) outDir = "./" + outDir;
|
|
18545
18686
|
buildCtx.components.forEach((cmp) => {
|
|
18546
|
-
|
|
18547
|
-
|
|
18687
|
+
npmPkgSet(`"exports[./${cmp.tagName}][import]"="${outDir}/${cmp.tagName}.js"`);
|
|
18688
|
+
npmPkgSet(`"exports[./${cmp.tagName}][types]"="${outDir}/${cmp.tagName}.d.ts"`);
|
|
18548
18689
|
});
|
|
18549
18690
|
};
|
|
18550
18691
|
//#endregion
|
|
@@ -18568,7 +18709,7 @@ const writeBuild = async (config, compilerCtx, buildCtx) => {
|
|
|
18568
18709
|
await compilerCtx.cache.commit();
|
|
18569
18710
|
buildCtx.debug(`in-memory-fs: ${compilerCtx.fs.getMemoryStats()}`);
|
|
18570
18711
|
buildCtx.debug(`cache: ${compilerCtx.cache.getMemoryStats()}`);
|
|
18571
|
-
if (config.generateExportMaps) writeExportMaps(config, buildCtx);
|
|
18712
|
+
if (config.generateExportMaps && !config.devMode) writeExportMaps(config, compilerCtx, buildCtx);
|
|
18572
18713
|
await outputServiceWorkers(config, buildCtx);
|
|
18573
18714
|
await validateBuildFiles(config, compilerCtx, buildCtx);
|
|
18574
18715
|
} catch (e) {
|
|
@@ -20603,10 +20744,11 @@ const validateConfig = (userConfig = {}, bootstrapConfig) => {
|
|
|
20603
20744
|
const devMode = isBoolean$1(config.devMode) ? config.devMode : false;
|
|
20604
20745
|
config._isTesting = !!(process.env.VITEST || process.env.PLAYWRIGHT_TEST || process.env.TEST_WORKER_INDEX || process.env.TEST_PARALLEL_INDEX || process.env.NODE_ENV === "test");
|
|
20605
20746
|
const sys = config.sys ?? bootstrapConfig.sys ?? createNodeSys({ logger });
|
|
20747
|
+
const hasExplicitGlobalStyleWithInput = (config.outputTargets || []).some((o) => isOutputTargetGlobalStyle(o) && isString$1(o.input));
|
|
20606
20748
|
if ((!isString$1(config.globalStyle) || !isString$1(config.globalScript)) && typeof sys.accessSync === "function") {
|
|
20607
20749
|
const preRootDir = typeof config.rootDir !== "string" ? "/" : config.rootDir;
|
|
20608
20750
|
const srcDir = typeof config.srcDir === "string" ? isAbsolute$1(config.srcDir) ? config.srcDir : join$1(preRootDir, config.srcDir) : join$1(preRootDir, "src");
|
|
20609
|
-
if (!isString$1(config.globalStyle)) for (const ext of STYLE_EXT) {
|
|
20751
|
+
if (!isString$1(config.globalStyle) && !hasExplicitGlobalStyleWithInput) for (const ext of STYLE_EXT) {
|
|
20610
20752
|
const candidate = join$1(srcDir, `global.${ext}`);
|
|
20611
20753
|
if (sys.accessSync(candidate)) {
|
|
20612
20754
|
config.globalStyle = candidate;
|
|
@@ -20626,7 +20768,7 @@ const validateConfig = (userConfig = {}, bootstrapConfig) => {
|
|
|
20626
20768
|
...config,
|
|
20627
20769
|
devMode,
|
|
20628
20770
|
compat: config.compat || {},
|
|
20629
|
-
generateExportMaps: isBoolean$1(config.generateExportMaps) ? config.generateExportMaps :
|
|
20771
|
+
generateExportMaps: isBoolean$1(config.generateExportMaps) ? config.generateExportMaps : !isString$1(config.configPath),
|
|
20630
20772
|
hydratedFlag: validateHydrated(config),
|
|
20631
20773
|
logLevel,
|
|
20632
20774
|
logger,
|