@mui/internal-docs-infra 0.12.1-canary.2 → 0.12.1-canary.21
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/ChunkProvider/PreloadProvider.mjs +1 -2
- package/ChunkProvider/usePreload.d.mts +1 -1
- package/ChunkProvider/usePreload.mjs +0 -1
- package/CodeControllerContext/CodeControllerContext.d.mts +45 -10
- package/CodeControllerContext/CodeControllerContext.mjs +15 -1
- package/CodeHighlighter/CodeHighlighterClient.d.mts +3 -2
- package/CodeHighlighter/CodeHighlighterClient.mjs +113 -18
- package/CodeHighlighter/CodeHighlighterContext.d.mts +9 -3
- package/CodeHighlighter/buildStringFallback.d.mts +1 -1
- package/CodeHighlighter/codeToFallbackProps.d.mts +1 -1
- package/CodeHighlighter/createClientProps.mjs +3 -0
- package/CodeHighlighter/fallbackCompression.d.mts +1 -1
- package/CodeHighlighter/parseControlledCode.d.mts +13 -4
- package/CodeHighlighter/parseControlledCode.mjs +41 -49
- package/CodeHighlighter/types.d.mts +21 -0
- package/CodeHighlighter/useGrammarsReady.mjs +44 -9
- package/CodeProvider/CodeProvider.d.mts +1 -1
- package/CodeProvider/CodeProviderLazy.d.mts +1 -1
- package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
- package/CodeProvider/createParseSourceWorkerClient.mjs +83 -15
- package/CodeProvider/useCodeProviderValue.mjs +50 -4
- package/abstractCreateDemo/abstractCreateDemo.d.mts +15 -1
- package/abstractCreateDemo/abstractCreateDemo.mjs +8 -0
- package/abstractCreateDemoClient/abstractCreateDemoClient.mjs +4 -0
- package/abstractCreateTypes/abstractCreateTypes.d.mts +12 -1
- package/abstractCreateTypes/abstractCreateTypes.mjs +4 -0
- package/abstractCreateTypes/typesToJsx.d.mts +8 -0
- package/abstractCreateTypes/typesToJsx.mjs +2 -1
- package/cli/loadNextConfig.d.mts +9 -0
- package/cli/loadNextConfig.mjs +11 -2
- package/cli/runValidate.mjs +15 -7
- package/cli/validateWorker.d.mts +1 -0
- package/cli/validateWorker.mjs +2 -1
- package/createDemoData/createDemoData.d.mts +1 -1
- package/package.json +34 -5
- package/pipeline/cacheUtils/constants.d.mts +5 -0
- package/pipeline/cacheUtils/constants.mjs +5 -0
- package/pipeline/cacheUtils/hashCacheContent.d.mts +5 -0
- package/pipeline/cacheUtils/hashCacheContent.mjs +9 -0
- package/pipeline/cacheUtils/index.d.mts +9 -0
- package/pipeline/cacheUtils/index.mjs +7 -0
- package/pipeline/cacheUtils/loadFileCache.d.mts +13 -0
- package/pipeline/cacheUtils/loadFileCache.mjs +20 -0
- package/pipeline/cacheUtils/loadFileCacheEntry.d.mts +13 -0
- package/pipeline/cacheUtils/loadFileCacheEntry.mjs +47 -0
- package/pipeline/cacheUtils/resolveCachePath.d.mts +16 -0
- package/pipeline/cacheUtils/resolveCachePath.mjs +24 -0
- package/pipeline/cacheUtils/saveFileCache.d.mts +17 -0
- package/pipeline/cacheUtils/saveFileCache.mjs +54 -0
- package/pipeline/cacheUtils/types.d.mts +23 -0
- package/pipeline/cacheUtils/types.mjs +1 -0
- package/pipeline/cacheUtils/withFileCache.d.mts +40 -0
- package/pipeline/cacheUtils/withFileCache.mjs +81 -0
- package/pipeline/hastUtils/hastUtils.d.mts +1 -1
- package/pipeline/hastUtils/hastUtils.mjs +0 -1
- package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.d.mts +1 -1
- package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.mjs +1 -1
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +0 -1
- package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +1 -1
- package/pipeline/loadIsomorphicCodeVariant/hasAllCodeVariants.d.mts +1 -1
- package/pipeline/loadIsomorphicCodeVariant/maybeCodeInitialData.d.mts +1 -1
- package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.d.mts +6 -0
- package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.mjs +2 -1
- package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.d.mts +6 -0
- package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.mjs +5 -1
- package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.d.mts +1 -1
- package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.mjs +0 -1
- package/pipeline/loadServerPageIndex/enrichPageIndex.d.mts +15 -0
- package/pipeline/loadServerPageIndex/enrichPageIndex.mjs +50 -0
- package/pipeline/loadServerPageIndex/extractPrefixAndTitle.d.mts +19 -0
- package/pipeline/loadServerPageIndex/extractPrefixAndTitle.mjs +80 -0
- package/pipeline/loadServerPageIndex/index.d.mts +5 -2
- package/pipeline/loadServerPageIndex/index.mjs +4 -1
- package/pipeline/loadServerPageIndex/loadServerPageIndex.d.mts +13 -22
- package/pipeline/loadServerPageIndex/loadServerPageIndex.mjs +32 -124
- package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.d.mts +13 -0
- package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.mjs +23 -0
- package/pipeline/loadServerTypes/highlightTypes.d.mts +3 -3
- package/pipeline/loadServerTypes/highlightTypesMeta.d.mts +4 -4
- package/pipeline/loadServerTypes/loadServerTypes.d.mts +2 -2
- package/pipeline/loadServerTypes/loadServerTypes.mjs +67 -7
- package/pipeline/loadServerTypesMeta/createOptimizedProgram.d.mts +2 -1
- package/pipeline/loadServerTypesMeta/formatClass.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/formatComponent.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/formatFunction.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/formatHook.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/formatRaw.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/formatType.d.mts +1 -1
- package/pipeline/loadServerTypesMeta/loadServerTypesMeta.d.mts +7 -7
- package/pipeline/loadServerTypesMeta/loadServerTypesMeta.mjs +1 -1
- package/pipeline/loadServerTypesMeta/processTypes.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/worker.d.mts +1 -1
- package/pipeline/loadServerTypesText/loadServerTypesText.d.mts +16 -2
- package/pipeline/loadServerTypesText/loadServerTypesText.mjs +30 -8
- package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.d.mts +2 -0
- package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.mjs +144 -0
- package/pipeline/loadServerTypesText/resolveTypesCacheKey.d.mts +19 -0
- package/pipeline/loadServerTypesText/resolveTypesCacheKey.mjs +29 -0
- package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -3
- package/pipeline/loaderUtils/parseImportsAndComments.mjs +284 -40
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +2 -2
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +2 -3
- package/pipeline/parseSource/detectFileTypes.d.mts +16 -0
- package/pipeline/parseSource/detectFileTypes.mjs +44 -0
- package/pipeline/syncPageIndex/mergeMetadataMarkdown.d.mts +25 -1
- package/pipeline/syncPageIndex/mergeMetadataMarkdown.mjs +79 -49
- package/pipeline/syncPageIndex/metadataToMarkdown.d.mts +15 -1
- package/pipeline/syncPageIndex/metadataToMarkdown.mjs +32 -10
- package/pipeline/syncPageIndex/syncPageIndex.d.mts +12 -0
- package/pipeline/syncPageIndex/syncPageIndex.mjs +154 -40
- package/pipeline/syncTypes/generateTypesMarkdown.d.mts +2 -2
- package/pipeline/syncTypes/syncTypes.d.mts +7 -0
- package/pipeline/syncTypes/syncTypes.mjs +31 -1
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +1 -1
- package/pipeline/transformMarkdownCode/transformMarkdownCode.mjs +25 -15
- package/pipeline/transformMarkdownMetadata/transformMarkdownMetadata.mjs +3 -0
- package/pipeline/transformMarkdownMetadata/types.d.mts +8 -1
- package/useCode/EditableEngine.d.mts +1 -1
- package/useCode/Pre.d.mts +9 -2
- package/useCode/Pre.mjs +4 -3
- package/useCode/TransformEngine.d.mts +1 -1
- package/useCode/useCode.d.mts +17 -1
- package/useCode/useCode.mjs +22 -1
- package/useCode/useCopyFunctionality.d.mts +2 -2
- package/useCode/useEditable.browser.mjs +0 -1
- package/useCode/useFileNavigation.d.mts +3 -0
- package/useCode/useFileNavigation.mjs +3 -1
- package/useCode/useSourceEditing.mjs +45 -10
- package/useCode/useSourceEnhancing.mjs +41 -9
- package/useCode/useTransformManagement.d.mts +2 -2
- package/useCode/useTransformManagement.mjs +19 -3
- package/useCode/useUIState.d.mts +4 -0
- package/useCode/useUIState.mjs +8 -1
- package/useCode/useVariantSelection.d.mts +1 -1
- package/useCoordinated/useCoordinated.d.mts +1 -1
- package/useCoordinated/useCoordinatedLocalStorage.d.mts +1 -1
- package/useCoordinated/useCoordinatedLocalStorage.mjs +0 -1
- package/useCoordinated/useCoordinatedPreference.d.mts +1 -1
- package/useCoordinated/useCoordinatedPreference.mjs +0 -1
- package/useCrossTabState/index.d.mts +2 -0
- package/useCrossTabState/index.mjs +2 -0
- package/useCrossTabState/useCrossTabMirror.d.mts +26 -0
- package/useCrossTabState/useCrossTabMirror.mjs +108 -0
- package/useCrossTabState/useCrossTabState.d.mts +21 -0
- package/useCrossTabState/useCrossTabState.mjs +31 -0
- package/useDemo/exportVariant.mjs +2 -4
- package/useDemo/exportVariantAsCra.d.mts +1 -1
- package/useDemo/exportVariantAsCra.mjs +0 -1
- package/useDemo/useDemo.d.mts +4 -1
- package/useDemo/useDemo.mjs +5 -0
- package/useDemoController/BuildEngine.d.mts +2 -0
- package/useDemoController/BuildEngine.mjs +10 -0
- package/useDemoController/DemoRunner.d.mts +34 -0
- package/useDemoController/DemoRunner.mjs +83 -0
- package/useDemoController/ErrorBoundary.d.mts +34 -0
- package/useDemoController/ErrorBoundary.mjs +49 -0
- package/useDemoController/Runner.d.mts +44 -0
- package/useDemoController/Runner.mjs +71 -0
- package/useDemoController/absolutizeImports.d.mts +13 -0
- package/useDemoController/absolutizeImports.mjs +73 -0
- package/useDemoController/buildScope.d.mts +48 -0
- package/useDemoController/buildScope.mjs +270 -0
- package/useDemoController/collectSources.d.mts +67 -0
- package/useDemoController/collectSources.mjs +92 -0
- package/useDemoController/compileCssModule.d.mts +64 -0
- package/useDemoController/compileCssModule.mjs +40 -0
- package/useDemoController/compileCssWithPostcss.d.mts +17 -0
- package/useDemoController/compileCssWithPostcss.mjs +89 -0
- package/useDemoController/compileModule.d.mts +14 -0
- package/useDemoController/compileModule.mjs +17 -0
- package/useDemoController/constants.d.mts +13 -0
- package/useDemoController/constants.mjs +13 -0
- package/useDemoController/createRequire.d.mts +10 -0
- package/useDemoController/createRequire.mjs +17 -0
- package/useDemoController/createTranspileWorkerClient.d.mts +27 -0
- package/useDemoController/createTranspileWorkerClient.mjs +139 -0
- package/useDemoController/cssModules.d.mts +47 -0
- package/useDemoController/currentBrowserTarget.d.mts +16 -0
- package/useDemoController/currentBrowserTarget.mjs +36 -0
- package/useDemoController/evalCode.d.mts +12 -0
- package/useDemoController/evalCode.mjs +35 -0
- package/useDemoController/generateCssModuleSource.d.mts +11 -0
- package/useDemoController/generateCssModuleSource.mjs +55 -0
- package/useDemoController/generateElement.d.mts +21 -0
- package/useDemoController/generateElement.mjs +26 -0
- package/useDemoController/hashString.d.mts +11 -0
- package/useDemoController/hashString.mjs +20 -0
- package/useDemoController/importCode.d.mts +11 -0
- package/useDemoController/importCode.mjs +15 -0
- package/useDemoController/index.d.mts +1 -0
- package/useDemoController/index.mjs +1 -0
- package/useDemoController/instantiateElement.d.mts +24 -0
- package/useDemoController/instantiateElement.mjs +57 -0
- package/useDemoController/instantiateModule.d.mts +17 -0
- package/useDemoController/instantiateModule.mjs +24 -0
- package/useDemoController/resolveCssImports.d.mts +27 -0
- package/useDemoController/resolveCssImports.mjs +79 -0
- package/useDemoController/transformCode.d.mts +14 -0
- package/useDemoController/transformCode.mjs +42 -0
- package/useDemoController/transpileClientSingleton.d.mts +10 -0
- package/useDemoController/transpileClientSingleton.mjs +83 -0
- package/useDemoController/transpileSource.d.mts +29 -0
- package/useDemoController/transpileSource.mjs +36 -0
- package/useDemoController/transpileWorker.d.mts +14 -0
- package/useDemoController/transpileWorker.mjs +41 -0
- package/useDemoController/types.d.mts +30 -0
- package/useDemoController/types.mjs +1 -0
- package/useDemoController/useDemoController.d.mts +54 -0
- package/useDemoController/useDemoController.mjs +186 -0
- package/useDemoController/useRunner.d.mts +53 -0
- package/useDemoController/useRunner.mjs +118 -0
- package/useDemoController/useVariantBuilds.d.mts +31 -0
- package/useDemoController/useVariantBuilds.mjs +188 -0
- package/useSearch/types.d.mts +1 -1
- package/useType/TypesDataProvider.d.mts +1 -1
- package/useType/TypesDataProvider.mjs +1 -2
- package/useType/useType.d.mts +1 -1
- package/useType/useTypeProp.d.mts +1 -1
- package/withDocsInfra/withDeploymentConfig.mjs +57 -0
- package/withDocsInfra/withDocsInfra.d.mts +14 -0
- package/withDocsInfra/withDocsInfra.mjs +25 -11
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { parseImportsAndComments } from "../pipeline/loaderUtils/parseImportsAndComments.mjs";
|
|
2
|
+
import { rewriteImports } from "../pipeline/loaderUtils/rewriteImports.mjs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Rewrites a source's relative imports (`./x`, `../x`) to absolute specifiers
|
|
6
|
+
* under the scope-import prefix, resolving each against the importing file's
|
|
7
|
+
* own directory. This lets every extra file be registered under a single absolute
|
|
8
|
+
* key that resolves regardless of where the file lives — e.g. `dir/file.ts`
|
|
9
|
+
* importing `../root` becomes `<prefix>root`, and `root.ts` importing `./dir/file`
|
|
10
|
+
* becomes `<prefix>dir/file`. External (bare) specifiers are left untouched.
|
|
11
|
+
*
|
|
12
|
+
* Only needed when extra files span subdirectories; flat demos resolve fine with
|
|
13
|
+
* their plain `./name` specifiers and should skip this. `fileName` is the file's
|
|
14
|
+
* path within the demo (e.g. `dir/file.ts`); the main source lives at the root.
|
|
15
|
+
*/
|
|
16
|
+
export function absolutizeImports(source, fileName,
|
|
17
|
+
// Defaults to `SCOPE_IMPORT_PREFIX` (`./constants`) but INLINED as a literal rather
|
|
18
|
+
// than imported: this module lands in the lazy `transpileSource` worker chunk, and
|
|
19
|
+
// importing the eager `collectSources`'s `constants` would hoist that one-line module
|
|
20
|
+
// into its own shared chunk. The match is guarded by this file's tests, which call
|
|
21
|
+
// with the default and assert `SCOPE_IMPORT_PREFIX`-prefixed output.
|
|
22
|
+
prefix = '@mui/internal-docs-infra/useDemoController/imports/') {
|
|
23
|
+
const lastSlash = fileName.lastIndexOf('/');
|
|
24
|
+
const fromDir = lastSlash === -1 ? '' : fileName.slice(0, lastSlash);
|
|
25
|
+
|
|
26
|
+
// Reuse the loader's single-pass import scanner (it correctly skips specifiers
|
|
27
|
+
// inside strings, comments, and template literals) to find each relative
|
|
28
|
+
// specifier and the positions where it appears. The parse URL is a fixed JS
|
|
29
|
+
// name, NOT the real `fileName`: the extra files routed here are always JS/TS,
|
|
30
|
+
// and a `.mdx` name would otherwise switch the scanner into MDX mode (where
|
|
31
|
+
// quotes no longer delimit strings). The directory is tracked separately above,
|
|
32
|
+
// so the made-up URL doesn't affect resolution.
|
|
33
|
+
const {
|
|
34
|
+
relative
|
|
35
|
+
} = parseImportsAndComments(source, 'file:///source.tsx');
|
|
36
|
+
const mapping = new Map();
|
|
37
|
+
for (const specifier of Object.keys(relative)) {
|
|
38
|
+
mapping.set(specifier, `${prefix}${resolveFromDir(fromDir, specifier)}`);
|
|
39
|
+
}
|
|
40
|
+
return rewriteImports(source, mapping, relative);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a relative `specifier` against `fromDir` into a normalized path (no
|
|
45
|
+
* leading `./`, `..` collapsed against real segments). A `..` that points ABOVE
|
|
46
|
+
* the demo root is PRESERVED, not dropped: a demo can import a shared file outside
|
|
47
|
+
* its own folder (`../shared/Button`), which a canonical `storeAt` mode keys by
|
|
48
|
+
* that same `../`-prefixed path — so the resolved specifier must keep the `..` to
|
|
49
|
+
* line up with the key. Pure string work — no Node `path` — so it runs unchanged
|
|
50
|
+
* in the browser.
|
|
51
|
+
*/
|
|
52
|
+
function resolveFromDir(fromDir, specifier) {
|
|
53
|
+
const segments = fromDir ? fromDir.split('/') : [];
|
|
54
|
+
segments.push(...specifier.split('/'));
|
|
55
|
+
const stack = [];
|
|
56
|
+
for (const segment of segments) {
|
|
57
|
+
if (segment === '' || segment === '.') {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (segment === '..') {
|
|
61
|
+
// Collapse against a real preceding segment; otherwise keep the `..` (the
|
|
62
|
+
// path climbs above the root to a parent-directory file).
|
|
63
|
+
if (stack.length > 0 && stack[stack.length - 1] !== '..') {
|
|
64
|
+
stack.pop();
|
|
65
|
+
} else {
|
|
66
|
+
stack.push('..');
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
stack.push(segment);
|
|
71
|
+
}
|
|
72
|
+
return stack.join('/');
|
|
73
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ControlledVariantExtraFiles } from '@mui/internal-docs-infra/CodeHighlighter/types';
|
|
2
|
+
import type { Transpile } from "./transpileSource.mjs";
|
|
3
|
+
export interface BuildScopeOptions {
|
|
4
|
+
/** Sibling files the sources can import, keyed by file name. */
|
|
5
|
+
extraFiles?: ControlledVariantExtraFiles;
|
|
6
|
+
/** Identifiers (e.g. `react`) seeded into the registry before the demo's files. */
|
|
7
|
+
externals: Record<string, unknown>;
|
|
8
|
+
/** The variant's main source — registered so an extra can import the entry, and returned (transpiled) as `runnerCode`. */
|
|
9
|
+
mainCode?: string;
|
|
10
|
+
/** Transpiles one source off the main thread (worker) or on it (fallback). */
|
|
11
|
+
transpile: Transpile;
|
|
12
|
+
/** Aborts in-flight transpiles when a newer edit supersedes this build. */
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
/** Overrides the name the main source is registered + resolved under. */
|
|
15
|
+
mainName?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface BuiltScope {
|
|
18
|
+
/** The runner's module registry — the `import` map handed to the runner. */
|
|
19
|
+
imports: Record<string, unknown>;
|
|
20
|
+
/** The concatenated stylesheet text collected from CSS extra files. */
|
|
21
|
+
css: string;
|
|
22
|
+
/** Whether any extra file lives in a subdirectory (see {@link collectSources}). */
|
|
23
|
+
nested: boolean;
|
|
24
|
+
/** The transpiled main source for the runner to render. `undefined` when none was provided. */
|
|
25
|
+
runnerCode?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Builds the runner scope from a variant's extra files (and optionally the main
|
|
29
|
+
* source). {@link collectSources} plans the registry keys (pure); each JS/TS file
|
|
30
|
+
* is then transpiled — relative imports rewritten + sucrase — by `transpile`, which
|
|
31
|
+
* runs off the main thread in a Web Worker (with a main-thread async fallback); CSS
|
|
32
|
+
* is scoped + autoprefixed by PostCSS (dynamically imported, off the main bundle).
|
|
33
|
+
* The compiled files are assembled into a lazy, circular-safe `import` registry,
|
|
34
|
+
* with cross-file `composes ... from` resolved across the variant's CSS modules.
|
|
35
|
+
*
|
|
36
|
+
* Per-file transpilation is cached by object identity, so editing one file only
|
|
37
|
+
* re-transpiles that file; a broken but UNUSED file is harmless (its error is thrown
|
|
38
|
+
* only if required). The main source (when provided) is returned transpiled as
|
|
39
|
+
* `runnerCode` for the runner to evaluate.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildScope({
|
|
42
|
+
extraFiles,
|
|
43
|
+
externals,
|
|
44
|
+
mainCode,
|
|
45
|
+
transpile,
|
|
46
|
+
signal,
|
|
47
|
+
mainName
|
|
48
|
+
}: BuildScopeOptions): Promise<BuiltScope>;
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { compileCssModule, prefixCss } from "./compileCssModule.mjs";
|
|
2
|
+
import { instantiateModule } from "./instantiateModule.mjs";
|
|
3
|
+
import { ENTRY_EXPORTS_KEY } from "./instantiateElement.mjs";
|
|
4
|
+
import { collectSources } from "./collectSources.mjs";
|
|
5
|
+
import { resolveCssImports } from "./resolveCssImports.mjs";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A compiled extra file, cached by the file's object identity (see `compiledFiles`).
|
|
9
|
+
* A JS module keeps a reusable `run`; a module whose transpile FAILED keeps the
|
|
10
|
+
* error, thrown only if the module is actually required (so a broken but unused
|
|
11
|
+
* file stays harmless); CSS results are fully materialized.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Compiled-form cache keyed by the extra-file OBJECT. An edit replaces only the
|
|
16
|
+
* changed file's object (the controlled code is updated immutably), so unchanged
|
|
17
|
+
* files keep their reference and stay cache hits — skipping the costly re-transpile
|
|
18
|
+
* (and its worker round-trip) on every keystroke. Module-level so it survives
|
|
19
|
+
* re-renders; `WeakMap` so entries are reclaimed once a demo drops its files.
|
|
20
|
+
*/
|
|
21
|
+
const compiledFiles = new WeakMap();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Transpiles one JS/TS module (off the main thread) and caches the result, unless
|
|
25
|
+
* an up-to-date entry already exists. The cache is gated on `nested`: absolutization
|
|
26
|
+
* differs by mode, so the transpiled output does too. A transpile FAILURE is cached
|
|
27
|
+
* as `moduleError` and re-thrown only when the module is required — so a broken but
|
|
28
|
+
* unused extra file never breaks the demo. An abort propagates (and is not cached).
|
|
29
|
+
*/
|
|
30
|
+
async function transpileModule(module, nested, transpile, signal) {
|
|
31
|
+
const cached = compiledFiles.get(module.file);
|
|
32
|
+
if (cached && (cached.kind === 'module' || cached.kind === 'moduleError') && cached.nested === nested) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const transpiled = await transpile(module.source, {
|
|
37
|
+
fileName: module.fileName,
|
|
38
|
+
nested
|
|
39
|
+
}, signal);
|
|
40
|
+
compiledFiles.set(module.file, {
|
|
41
|
+
kind: 'module',
|
|
42
|
+
nested,
|
|
43
|
+
run: instantiateModule(transpiled)
|
|
44
|
+
});
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (signal?.aborted) {
|
|
47
|
+
throw error; // a superseded build — let it reject so the caller drops it (don't cache)
|
|
48
|
+
}
|
|
49
|
+
compiledFiles.set(module.file, {
|
|
50
|
+
kind: 'moduleError',
|
|
51
|
+
nested,
|
|
52
|
+
// `toString()` (not `.message`) keeps the error name (e.g. `SyntaxError:`) in the
|
|
53
|
+
// surfaced message — the transpile paths reject with a live, named error.
|
|
54
|
+
error: error instanceof Error ? error.toString() : String(error)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Compiles one CSS extra file and caches the result, unless an up-to-date entry
|
|
61
|
+
* exists. A `*.module.css` is scoped + autoprefixed by {@link compileCssModule}
|
|
62
|
+
* (its cross-file `composes ... from` left as `imports` for the assembly pass to
|
|
63
|
+
* resolve); a plain `*.css` is autoprefixed by {@link prefixCss}. Both are async
|
|
64
|
+
* (PostCSS is dynamically imported) but mode-independent, so the result is cached
|
|
65
|
+
* by file identity and reused as-is.
|
|
66
|
+
*
|
|
67
|
+
* Malformed CSS rejects inside PostCSS with a `CssSyntaxError` (labelled
|
|
68
|
+
* `name.module.css:L:C` via the `fileName`), which propagates so the whole build
|
|
69
|
+
* rejects and the caller surfaces it as the variant's error (keeping the last good
|
|
70
|
+
* preview) — a broken stylesheet is a real error, not something to silently pass
|
|
71
|
+
* through as raw, unscoped CSS. An abort drops the result quietly instead of
|
|
72
|
+
* surfacing (the build was superseded).
|
|
73
|
+
*/
|
|
74
|
+
async function compileStyleExtra(style, signal) {
|
|
75
|
+
const cached = compiledFiles.get(style.file);
|
|
76
|
+
if (cached && cached.kind !== 'module' && cached.kind !== 'moduleError') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
if (style.isModule) {
|
|
81
|
+
const {
|
|
82
|
+
css,
|
|
83
|
+
exports,
|
|
84
|
+
imports
|
|
85
|
+
} = await compileCssModule(style.source, {
|
|
86
|
+
fileName: style.fileName
|
|
87
|
+
});
|
|
88
|
+
if (signal?.aborted) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
compiledFiles.set(style.file, {
|
|
92
|
+
kind: 'cssModule',
|
|
93
|
+
exports,
|
|
94
|
+
css,
|
|
95
|
+
imports
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
const css = await prefixCss(style.source, style.fileName);
|
|
99
|
+
if (signal?.aborted) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
compiledFiles.set(style.file, {
|
|
103
|
+
kind: 'css',
|
|
104
|
+
css
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (signal?.aborted) {
|
|
109
|
+
return; // superseded build — drop without surfacing
|
|
110
|
+
}
|
|
111
|
+
throw error; // a real `CssSyntaxError`, already naming the file — surface it
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** A style's compiled form: a scoped CSS module (with exports) or a plain sheet. */
|
|
116
|
+
|
|
117
|
+
/** The cached compiled form for a style — defensively raw if it was never built. */
|
|
118
|
+
function cssExtraFor(style) {
|
|
119
|
+
const cached = compiledFiles.get(style.file);
|
|
120
|
+
if (cached && (cached.kind === 'cssModule' || cached.kind === 'css')) {
|
|
121
|
+
return cached;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
kind: 'css',
|
|
125
|
+
css: style.source
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Registers a module as a LAZILY-evaluated entry. It runs on first `require`, not
|
|
131
|
+
* eagerly, so registration order doesn't matter: a file can import a sibling (or
|
|
132
|
+
* the main source) registered later, and circular imports resolve via the
|
|
133
|
+
* in-progress `exports` (set before the body runs). `makeRun` is invoked once, on
|
|
134
|
+
* first access.
|
|
135
|
+
*
|
|
136
|
+
* `alwaysKeys` are claimed unconditionally; `ifFreeKeys` only when not already
|
|
137
|
+
* taken — so a concrete file wins over a weaker claimant on the same key (Node
|
|
138
|
+
* semantics: `foo.ts` beats `foo/index.ts`'s directory key, and an explicit extra
|
|
139
|
+
* beats the main entry).
|
|
140
|
+
*/
|
|
141
|
+
function defineLazyModule(imports, alwaysKeys, ifFreeKeys, makeRun) {
|
|
142
|
+
let exports = null;
|
|
143
|
+
const get = () => {
|
|
144
|
+
if (exports === null) {
|
|
145
|
+
// Set before running so a circular re-entry sees the in-progress exports.
|
|
146
|
+
exports = {};
|
|
147
|
+
makeRun()(imports, exports);
|
|
148
|
+
}
|
|
149
|
+
return exports;
|
|
150
|
+
};
|
|
151
|
+
const define = key => Object.defineProperty(imports, key, {
|
|
152
|
+
get,
|
|
153
|
+
enumerable: true,
|
|
154
|
+
configurable: true
|
|
155
|
+
});
|
|
156
|
+
alwaysKeys.forEach(define);
|
|
157
|
+
for (const key of ifFreeKeys) {
|
|
158
|
+
if (!Object.prototype.hasOwnProperty.call(imports, key)) {
|
|
159
|
+
define(key);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** The run a module's registry getter uses: its cached `run`, or a deferred throw. */
|
|
165
|
+
function moduleRunFor(module) {
|
|
166
|
+
const cached = compiledFiles.get(module.file);
|
|
167
|
+
if (cached?.kind === 'module') {
|
|
168
|
+
return cached.run;
|
|
169
|
+
}
|
|
170
|
+
// Transpile failed (or, defensively, was never run): surface it only here, when
|
|
171
|
+
// the module is actually required, so an unused broken file stays harmless.
|
|
172
|
+
const message = cached?.kind === 'moduleError' ? cached.error : `Module was not transpiled: ${module.fileName}`;
|
|
173
|
+
return () => {
|
|
174
|
+
throw new Error(message);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Assembles the runner registry SYNCHRONOUSLY from already-compiled files (the
|
|
180
|
+
* cache populated by {@link transpileModule} + {@link compileStyleExtra}). Kept
|
|
181
|
+
* synchronous so circular imports stay safe: every getter sets its in-progress
|
|
182
|
+
* `exports` before the body runs, and nothing here awaits.
|
|
183
|
+
*/
|
|
184
|
+
function assembleScope(collected, runnerCode, externals) {
|
|
185
|
+
const imports = {
|
|
186
|
+
...externals
|
|
187
|
+
};
|
|
188
|
+
const styleSheets = [];
|
|
189
|
+
|
|
190
|
+
// Gather each style's compiled sheet (order-preserving); a plain CSS file exports
|
|
191
|
+
// an empty module, while a CSS module's exports wait for the cross-file pass below.
|
|
192
|
+
const cssModules = [];
|
|
193
|
+
for (const style of collected.styles) {
|
|
194
|
+
const compiled = cssExtraFor(style);
|
|
195
|
+
styleSheets.push(compiled.css);
|
|
196
|
+
if (compiled.kind === 'cssModule') {
|
|
197
|
+
cssModules.push({
|
|
198
|
+
key: style.key,
|
|
199
|
+
fileName: style.fileName,
|
|
200
|
+
exports: compiled.exports,
|
|
201
|
+
imports: compiled.imports
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
imports[style.key] = {};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Resolve cross-file `composes ... from` against the CURRENT siblings. Done here,
|
|
208
|
+
// not in the per-file cache: a module's resolved names depend on sibling exports,
|
|
209
|
+
// which change when a sibling is edited even though this file's source did not.
|
|
210
|
+
const resolvedCssExports = resolveCssImports(cssModules);
|
|
211
|
+
for (const cssModule of cssModules) {
|
|
212
|
+
imports[cssModule.key] = resolvedCssExports.get(cssModule.key) ?? cssModule.exports;
|
|
213
|
+
}
|
|
214
|
+
for (const module of collected.modules) {
|
|
215
|
+
defineLazyModule(imports, module.primaryKeys, module.directoryKey ? [module.directoryKey] : [], () => moduleRunFor(module));
|
|
216
|
+
}
|
|
217
|
+
if (collected.entry) {
|
|
218
|
+
// The entry's keys and the hidden ENTRY_EXPORTS_KEY point at ONE exports object
|
|
219
|
+
// (claimed only where no extra took the key), so the rendered entry and any
|
|
220
|
+
// extra that imports it share a single evaluation.
|
|
221
|
+
const mainExports = {};
|
|
222
|
+
imports[ENTRY_EXPORTS_KEY] = mainExports;
|
|
223
|
+
for (const key of collected.entry.primaryKeys) {
|
|
224
|
+
if (!Object.prototype.hasOwnProperty.call(imports, key)) {
|
|
225
|
+
imports[key] = mainExports;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
imports,
|
|
231
|
+
css: styleSheets.join('\n'),
|
|
232
|
+
nested: collected.nested,
|
|
233
|
+
runnerCode
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Builds the runner scope from a variant's extra files (and optionally the main
|
|
239
|
+
* source). {@link collectSources} plans the registry keys (pure); each JS/TS file
|
|
240
|
+
* is then transpiled — relative imports rewritten + sucrase — by `transpile`, which
|
|
241
|
+
* runs off the main thread in a Web Worker (with a main-thread async fallback); CSS
|
|
242
|
+
* is scoped + autoprefixed by PostCSS (dynamically imported, off the main bundle).
|
|
243
|
+
* The compiled files are assembled into a lazy, circular-safe `import` registry,
|
|
244
|
+
* with cross-file `composes ... from` resolved across the variant's CSS modules.
|
|
245
|
+
*
|
|
246
|
+
* Per-file transpilation is cached by object identity, so editing one file only
|
|
247
|
+
* re-transpiles that file; a broken but UNUSED file is harmless (its error is thrown
|
|
248
|
+
* only if required). The main source (when provided) is returned transpiled as
|
|
249
|
+
* `runnerCode` for the runner to evaluate.
|
|
250
|
+
*/
|
|
251
|
+
export async function buildScope({
|
|
252
|
+
extraFiles,
|
|
253
|
+
externals,
|
|
254
|
+
mainCode,
|
|
255
|
+
transpile,
|
|
256
|
+
signal,
|
|
257
|
+
mainName
|
|
258
|
+
}) {
|
|
259
|
+
const collected = collectSources(extraFiles, mainCode, mainName);
|
|
260
|
+
|
|
261
|
+
// Transpile the entry and every module concurrently, off the main thread. The
|
|
262
|
+
// entry's transpile error rejects this build (there's nothing to render); module
|
|
263
|
+
// errors are deferred inside `transpileModule` (thrown only if required).
|
|
264
|
+
const [runnerCode] = await Promise.all([collected.entry ? transpile(collected.entry.source, {
|
|
265
|
+
fileName: collected.entry.fileName,
|
|
266
|
+
nested: collected.nested,
|
|
267
|
+
normalize: true
|
|
268
|
+
}, signal) : Promise.resolve(undefined), Promise.all(collected.modules.map(module => transpileModule(module, collected.nested, transpile, signal))), Promise.all(collected.styles.map(style => compileStyleExtra(style, signal)))]);
|
|
269
|
+
return assembleScope(collected, runnerCode, externals);
|
|
270
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ControlledVariantExtraFiles } from '@mui/internal-docs-infra/CodeHighlighter/types';
|
|
2
|
+
/** Name the main source is registered + resolved under (it lives at the demo root). */
|
|
3
|
+
export declare const MAIN_SOURCE_NAME = "index.tsx";
|
|
4
|
+
/** A JS/TS extra file to register, with the specifiers it answers to. */
|
|
5
|
+
export interface CollectedModule {
|
|
6
|
+
/** The extra-file object — used as the per-file transpile-cache key (identity). */
|
|
7
|
+
file: object;
|
|
8
|
+
/** Path within the demo (e.g. `dir/util.ts`) — drives absolutize + cache gating. */
|
|
9
|
+
fileName: string;
|
|
10
|
+
/** The raw source — absolutized later (in the transpile worker) when `nested`. */
|
|
11
|
+
source: string;
|
|
12
|
+
/** Specifiers this module always answers to (its own path). */
|
|
13
|
+
primaryKeys: string[];
|
|
14
|
+
/** Directory specifier an `index` file also answers to — claimed only if free. */
|
|
15
|
+
directoryKey?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A CSS extra file to register + collect. */
|
|
18
|
+
export interface CollectedStyle {
|
|
19
|
+
/** The extra-file object — used as the per-file compile-cache key (identity). */
|
|
20
|
+
file: object;
|
|
21
|
+
fileName: string;
|
|
22
|
+
source: string;
|
|
23
|
+
/** Registry key the class map (or empty module) is registered under. */
|
|
24
|
+
key: string;
|
|
25
|
+
/** `*.module.css` (scoped, exports a class map) vs a plain global `*.css`. */
|
|
26
|
+
isModule: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** The main source to render, with the specifiers it answers to. */
|
|
29
|
+
export interface CollectedEntry {
|
|
30
|
+
/** The raw main source — absolutized + normalized later (in the transpile worker). */
|
|
31
|
+
source: string;
|
|
32
|
+
/** The entry's path (the demo root) — used to resolve its relative imports. */
|
|
33
|
+
fileName: string;
|
|
34
|
+
/** Specifiers the entry answers to — claimed only if no extra already took them. */
|
|
35
|
+
primaryKeys: string[];
|
|
36
|
+
}
|
|
37
|
+
export interface CollectedSources {
|
|
38
|
+
/**
|
|
39
|
+
* Whether any extra file lives in a subdirectory (its key contains `/`). When
|
|
40
|
+
* `true`, keys are absolute `<SCOPE_IMPORT_PREFIX><path>` specifiers and every
|
|
41
|
+
* JS/TS source — including the main one — has its relative imports rewritten
|
|
42
|
+
* (during transpilation) so they resolve by absolute key.
|
|
43
|
+
*/
|
|
44
|
+
nested: boolean;
|
|
45
|
+
modules: CollectedModule[];
|
|
46
|
+
styles: CollectedStyle[];
|
|
47
|
+
entry?: CollectedEntry;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Plans the runner scope from a variant's extra files (and optionally the main
|
|
51
|
+
* source): the pure, transpile-free half of `buildScope`. It decides each file's
|
|
52
|
+
* registry keys and detects whether the demo is `nested`, but compiles nothing and
|
|
53
|
+
* — unlike before — does not rewrite imports: the raw source is carried through so
|
|
54
|
+
* the absolutize + sucrase transpile can run together off the main thread (see
|
|
55
|
+
* `transpileSource`). The result is a descriptor list the caller transpiles and
|
|
56
|
+
* assembles into a registry.
|
|
57
|
+
*
|
|
58
|
+
* Keys carry the `storeAt`-mode's leading `./` stripped, so a bare path
|
|
59
|
+
* (`dir/file.ts`) and an import specifier (`./dir/file.ts`) collapse to the same
|
|
60
|
+
* key — and a flat `./file.ts` is not mistaken for nested.
|
|
61
|
+
*
|
|
62
|
+
* Files are routed by extension: `*.css` become {@link CollectedStyle}s
|
|
63
|
+
* (`*.module.css` scoped, others global); everything else a {@link CollectedModule}
|
|
64
|
+
* keyed by its extension-less specifier, its full name, and — for an `index` file —
|
|
65
|
+
* its directory. Files with a non-string `source` (e.g. `null`) are skipped.
|
|
66
|
+
*/
|
|
67
|
+
export declare function collectSources(extraFiles: ControlledVariantExtraFiles | undefined, mainCode?: string, mainName?: string): CollectedSources;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { SCOPE_IMPORT_PREFIX } from "./constants.mjs";
|
|
2
|
+
|
|
3
|
+
/** Name the main source is registered + resolved under (it lives at the demo root). */
|
|
4
|
+
export const MAIN_SOURCE_NAME = 'index.tsx';
|
|
5
|
+
|
|
6
|
+
/** A JS/TS extra file to register, with the specifiers it answers to. */
|
|
7
|
+
|
|
8
|
+
/** A CSS extra file to register + collect. */
|
|
9
|
+
|
|
10
|
+
/** The main source to render, with the specifiers it answers to. */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The specifiers a JS/TS module answers to: its extension-less path (`dir/util`),
|
|
14
|
+
* its full name (`dir/util.ts`), and — for an `index` file — its containing
|
|
15
|
+
* directory (`dir/index.ts` also answers `import './dir'`), each under `prefix`.
|
|
16
|
+
*/
|
|
17
|
+
function moduleKeys(fileName, prefix) {
|
|
18
|
+
const pathWithoutExtension = fileName.replace(/\.[^.]+$/, '');
|
|
19
|
+
const primary = [...new Set([`${prefix}${pathWithoutExtension}`, `${prefix}${fileName}`])];
|
|
20
|
+
if (pathWithoutExtension.endsWith('/index')) {
|
|
21
|
+
return {
|
|
22
|
+
primary,
|
|
23
|
+
directory: `${prefix}${pathWithoutExtension.slice(0, -'/index'.length)}`
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
primary
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Plans the runner scope from a variant's extra files (and optionally the main
|
|
33
|
+
* source): the pure, transpile-free half of `buildScope`. It decides each file's
|
|
34
|
+
* registry keys and detects whether the demo is `nested`, but compiles nothing and
|
|
35
|
+
* — unlike before — does not rewrite imports: the raw source is carried through so
|
|
36
|
+
* the absolutize + sucrase transpile can run together off the main thread (see
|
|
37
|
+
* `transpileSource`). The result is a descriptor list the caller transpiles and
|
|
38
|
+
* assembles into a registry.
|
|
39
|
+
*
|
|
40
|
+
* Keys carry the `storeAt`-mode's leading `./` stripped, so a bare path
|
|
41
|
+
* (`dir/file.ts`) and an import specifier (`./dir/file.ts`) collapse to the same
|
|
42
|
+
* key — and a flat `./file.ts` is not mistaken for nested.
|
|
43
|
+
*
|
|
44
|
+
* Files are routed by extension: `*.css` become {@link CollectedStyle}s
|
|
45
|
+
* (`*.module.css` scoped, others global); everything else a {@link CollectedModule}
|
|
46
|
+
* keyed by its extension-less specifier, its full name, and — for an `index` file —
|
|
47
|
+
* its directory. Files with a non-string `source` (e.g. `null`) are skipped.
|
|
48
|
+
*/
|
|
49
|
+
export function collectSources(extraFiles, mainCode, mainName = MAIN_SOURCE_NAME) {
|
|
50
|
+
const entries = Object.entries(extraFiles ?? {}).map(([fileName, file]) => [fileName.replace(/^\.\//, ''), file]);
|
|
51
|
+
const nested = entries.some(([fileName]) => fileName.includes('/'));
|
|
52
|
+
const prefix = nested ? SCOPE_IMPORT_PREFIX : './';
|
|
53
|
+
const modules = [];
|
|
54
|
+
const styles = [];
|
|
55
|
+
for (const [fileName, file] of entries) {
|
|
56
|
+
if (!file || typeof file.source !== 'string') {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (fileName.endsWith('.css')) {
|
|
60
|
+
styles.push({
|
|
61
|
+
file,
|
|
62
|
+
fileName,
|
|
63
|
+
source: file.source,
|
|
64
|
+
key: `${prefix}${fileName}`,
|
|
65
|
+
isModule: fileName.endsWith('.module.css')
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const keys = moduleKeys(fileName, prefix);
|
|
70
|
+
modules.push({
|
|
71
|
+
file,
|
|
72
|
+
fileName,
|
|
73
|
+
source: file.source,
|
|
74
|
+
primaryKeys: keys.primary,
|
|
75
|
+
directoryKey: keys.directory
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
let entry;
|
|
79
|
+
if (mainCode !== undefined) {
|
|
80
|
+
entry = {
|
|
81
|
+
source: mainCode,
|
|
82
|
+
fileName: mainName,
|
|
83
|
+
primaryKeys: moduleKeys(mainName, prefix).primary
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
nested,
|
|
88
|
+
modules,
|
|
89
|
+
styles,
|
|
90
|
+
entry
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface CssModuleOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Seed for the generated class-name hash. Defaults to the source itself, so
|
|
4
|
+
* identical sources hash identically — keeping scoped names stable across
|
|
5
|
+
* server render, client hydration, and live-edit recompiles.
|
|
6
|
+
*/
|
|
7
|
+
hashSeed?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The file's name, used only to label a `CssSyntaxError` (`name.module.css:L:C`)
|
|
10
|
+
* so a multi-file demo points at the offending stylesheet.
|
|
11
|
+
*/
|
|
12
|
+
fileName?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CompiledCssModule {
|
|
15
|
+
/** The transformed CSS: class/id/keyframe names scoped, declarations autoprefixed. */
|
|
16
|
+
css: string;
|
|
17
|
+
/**
|
|
18
|
+
* Map of original local name to its scoped name — the module's exports. A
|
|
19
|
+
* `composes` target is merged in (space-separated). Register it in a runner
|
|
20
|
+
* scope's `import` map so demo code can resolve
|
|
21
|
+
* `import styles from './styles.module.css'` to `styles.button` etc.
|
|
22
|
+
*
|
|
23
|
+
* A cross-file `composes ... from` leaves an opaque placeholder token in the
|
|
24
|
+
* value (see {@link imports}); the caller resolves it against the sibling.
|
|
25
|
+
*/
|
|
26
|
+
exports: Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Cross-file `composes ... from "./other"` requests this single-file compile
|
|
29
|
+
* cannot resolve: `{ './other': { '<placeholder>': 'originalName' } }`. The
|
|
30
|
+
* placeholder also appears in {@link exports}; resolving it (swapping the token
|
|
31
|
+
* for the sibling's scoped name) is left to the caller, which has the sibling
|
|
32
|
+
* modules. Empty for the common, self-contained case.
|
|
33
|
+
*/
|
|
34
|
+
imports: Record<string, Record<string, string>>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compiles a CSS Modules source string into scoped CSS plus its name exports,
|
|
38
|
+
* using PostCSS with the same ICSS plugin chain css-loader runs (values →
|
|
39
|
+
* local-by-default → extract-imports → scope) followed by autoprefixer.
|
|
40
|
+
*
|
|
41
|
+
* Each local `.button`/`#id`/`@keyframes`/`@value`/animation name becomes
|
|
42
|
+
* `name-<hash>` in the CSS and `{ button: 'button-<hash>' }` in
|
|
43
|
+
* {@link CompiledCssModule.exports}. Full CSS Modules semantics are supported:
|
|
44
|
+
* `:global()`/`:local()`, same-file `composes`, `@keyframes` + `animation` name
|
|
45
|
+
* scoping, and `@value`. Cross-file `composes ... from` is surfaced as an
|
|
46
|
+
* {@link CompiledCssModule.imports} entry for the caller to resolve. Declaration
|
|
47
|
+
* values, comments, and string contents are preserved; autoprefixer then adds the
|
|
48
|
+
* vendor prefixes the Baseline Widely Available range still needs.
|
|
49
|
+
*
|
|
50
|
+
* The whole PostCSS toolchain is loaded behind a SINGLE dynamic import, so it
|
|
51
|
+
* ships as one lazy `compileCss` chunk (never in the main bundle) — paid for only
|
|
52
|
+
* when a demo first compiles CSS. Rejects with a PostCSS `CssSyntaxError` on
|
|
53
|
+
* malformed input — callers that recompile on every keystroke should catch it and
|
|
54
|
+
* keep the last good output.
|
|
55
|
+
*/
|
|
56
|
+
export declare function compileCssModule(source: string, options?: CssModuleOptions): Promise<CompiledCssModule>;
|
|
57
|
+
/**
|
|
58
|
+
* Autoprefixes a plain (non-module) stylesheet for the visitor's browser, without
|
|
59
|
+
* scoping any selectors — the global-CSS counterpart to {@link compileCssModule}.
|
|
60
|
+
* Class names pass through verbatim; only the vendor prefixes that browser needs are
|
|
61
|
+
* added. Shares the same lazy `compileCss` chunk. Rejects on malformed CSS, labelling
|
|
62
|
+
* the error with `fileName` when given.
|
|
63
|
+
*/
|
|
64
|
+
export declare function prefixCss(source: string, fileName?: string): Promise<string>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles a CSS Modules source string into scoped CSS plus its name exports,
|
|
3
|
+
* using PostCSS with the same ICSS plugin chain css-loader runs (values →
|
|
4
|
+
* local-by-default → extract-imports → scope) followed by autoprefixer.
|
|
5
|
+
*
|
|
6
|
+
* Each local `.button`/`#id`/`@keyframes`/`@value`/animation name becomes
|
|
7
|
+
* `name-<hash>` in the CSS and `{ button: 'button-<hash>' }` in
|
|
8
|
+
* {@link CompiledCssModule.exports}. Full CSS Modules semantics are supported:
|
|
9
|
+
* `:global()`/`:local()`, same-file `composes`, `@keyframes` + `animation` name
|
|
10
|
+
* scoping, and `@value`. Cross-file `composes ... from` is surfaced as an
|
|
11
|
+
* {@link CompiledCssModule.imports} entry for the caller to resolve. Declaration
|
|
12
|
+
* values, comments, and string contents are preserved; autoprefixer then adds the
|
|
13
|
+
* vendor prefixes the Baseline Widely Available range still needs.
|
|
14
|
+
*
|
|
15
|
+
* The whole PostCSS toolchain is loaded behind a SINGLE dynamic import, so it
|
|
16
|
+
* ships as one lazy `compileCss` chunk (never in the main bundle) — paid for only
|
|
17
|
+
* when a demo first compiles CSS. Rejects with a PostCSS `CssSyntaxError` on
|
|
18
|
+
* malformed input — callers that recompile on every keystroke should catch it and
|
|
19
|
+
* keep the last good output.
|
|
20
|
+
*/
|
|
21
|
+
export async function compileCssModule(source, options = {}) {
|
|
22
|
+
const {
|
|
23
|
+
compileCssModuleWithPostcss
|
|
24
|
+
} = await import(/* webpackChunkName: "compileCss" */"./compileCssWithPostcss.mjs");
|
|
25
|
+
return compileCssModuleWithPostcss(source, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Autoprefixes a plain (non-module) stylesheet for the visitor's browser, without
|
|
30
|
+
* scoping any selectors — the global-CSS counterpart to {@link compileCssModule}.
|
|
31
|
+
* Class names pass through verbatim; only the vendor prefixes that browser needs are
|
|
32
|
+
* added. Shares the same lazy `compileCss` chunk. Rejects on malformed CSS, labelling
|
|
33
|
+
* the error with `fileName` when given.
|
|
34
|
+
*/
|
|
35
|
+
export async function prefixCss(source, fileName) {
|
|
36
|
+
const {
|
|
37
|
+
prefixCssWithPostcss
|
|
38
|
+
} = await import(/* webpackChunkName: "compileCss" */"./compileCssWithPostcss.mjs");
|
|
39
|
+
return prefixCssWithPostcss(source, fileName);
|
|
40
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CompiledCssModule, CssModuleOptions } from "./compileCssModule.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* The PostCSS implementation behind {@link import('./compileCssModule').compileCssModule}.
|
|
4
|
+
*
|
|
5
|
+
* This module statically imports the WHOLE CSS toolchain (postcss + autoprefixer +
|
|
6
|
+
* the ICSS Modules plugins), so it is loaded behind ONE dynamic `import()` from the
|
|
7
|
+
* light `compileCssModule` shell — the bundler then emits a single `compileCss`
|
|
8
|
+
* chunk instead of a separate chunk per npm package. None of this enters the main
|
|
9
|
+
* bundle; it is paid for only when a demo first compiles CSS.
|
|
10
|
+
*
|
|
11
|
+
* Runs the same ICSS plugin chain css-loader uses (values → local-by-default →
|
|
12
|
+
* extract-imports → scope) followed by {@link lowerModernCss} and autoprefixer, then
|
|
13
|
+
* `extractICSS` for the exports. See the shell's docs for the full semantics.
|
|
14
|
+
*/
|
|
15
|
+
export declare function compileCssModuleWithPostcss(source: string, options?: CssModuleOptions): Promise<CompiledCssModule>;
|
|
16
|
+
/** The PostCSS implementation behind `prefixCss` — {@link lowerModernCss} + autoprefix, no scoping. */
|
|
17
|
+
export declare function prefixCssWithPostcss(source: string, fileName?: string): Promise<string>;
|