@master/css-vite 0.0.0-site.1793659883.g69c9aebcf628

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.
Files changed (121) hide show
  1. package/README.md +348 -0
  2. package/dist/common.d.ts +14 -0
  3. package/dist/common.js +26 -0
  4. package/dist/core.d.ts +23 -0
  5. package/dist/core.js +165 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.js +1 -0
  8. package/dist/internal/src/emitted-globals-module.js +12 -0
  9. package/dist/internal/src/manifest-facade.js +68 -0
  10. package/dist/internal/src/manifest-loader.js +33 -0
  11. package/dist/internal/src/manifest-module.js +58 -0
  12. package/dist/internal/src/manifest-virtual-module.js +123 -0
  13. package/dist/internal/src/node.js +22 -0
  14. package/dist/internal/src/program-module.js +50 -0
  15. package/dist/internal/src/project.js +10 -0
  16. package/dist/internal/src/runtime-bootstrap.js +80 -0
  17. package/dist/internal/src/style-module.js +3 -0
  18. package/dist/modes/pre-render.d.ts +5 -0
  19. package/dist/modes/pre-render.js +6 -0
  20. package/dist/modes/progressive.d.ts +5 -0
  21. package/dist/modes/progressive.js +12 -0
  22. package/dist/modes/runtime.d.ts +5 -0
  23. package/dist/modes/runtime.js +17 -0
  24. package/dist/modes/static.d.ts +5 -0
  25. package/dist/modes/static.js +5 -0
  26. package/dist/options.d.ts +20 -0
  27. package/dist/options.js +23 -0
  28. package/dist/plugins/avoid-fouc.d.ts +5 -0
  29. package/dist/plugins/avoid-fouc.js +48 -0
  30. package/dist/plugins/build-stylesheet-recovery.d.ts +5 -0
  31. package/dist/plugins/build-stylesheet-recovery.js +26 -0
  32. package/dist/plugins/context.d.ts +5 -0
  33. package/dist/plugins/context.js +12 -0
  34. package/dist/plugins/dev-stylesheet.d.ts +4 -0
  35. package/dist/plugins/dev-stylesheet.js +63 -0
  36. package/dist/plugins/emitted-globals-virtual-module.d.ts +14 -0
  37. package/dist/plugins/emitted-globals-virtual-module.js +167 -0
  38. package/dist/plugins/inject-runtime.d.ts +5 -0
  39. package/dist/plugins/inject-runtime.js +51 -0
  40. package/dist/plugins/inline-stylesheet.d.ts +5 -0
  41. package/dist/plugins/inline-stylesheet.js +197 -0
  42. package/dist/plugins/local-styles.d.ts +5 -0
  43. package/dist/plugins/local-styles.js +214 -0
  44. package/dist/plugins/manifest-loader.d.ts +4 -0
  45. package/dist/plugins/manifest-loader.js +102 -0
  46. package/dist/plugins/manifest-virtual-module.d.ts +4 -0
  47. package/dist/plugins/manifest-virtual-module.js +70 -0
  48. package/dist/plugins/pre-render.d.ts +5 -0
  49. package/dist/plugins/pre-render.js +224 -0
  50. package/dist/plugins/program-preload.d.ts +5 -0
  51. package/dist/plugins/program-preload.js +37 -0
  52. package/dist/plugins/runtime-bootstrap.d.ts +3 -0
  53. package/dist/plugins/runtime-bootstrap.js +14 -0
  54. package/dist/plugins/runtime-preload.d.ts +4 -0
  55. package/dist/plugins/runtime-preload.js +38 -0
  56. package/dist/plugins/sass-source.d.ts +5 -0
  57. package/dist/plugins/sass-source.js +176 -0
  58. package/dist/plugins/scanner.d.ts +5 -0
  59. package/dist/plugins/scanner.js +24 -0
  60. package/dist/plugins/style-entry-build.d.ts +5 -0
  61. package/dist/plugins/style-entry-build.js +121 -0
  62. package/dist/plugins/style-entry-hmr.d.ts +6 -0
  63. package/dist/plugins/style-entry-hmr.js +78 -0
  64. package/dist/plugins/style-entry.d.ts +5 -0
  65. package/dist/plugins/style-entry.js +89 -0
  66. package/dist/plugins/stylesheet-recovery.d.ts +5 -0
  67. package/dist/plugins/stylesheet-recovery.js +70 -0
  68. package/dist/plugins/usage-graph.d.ts +5 -0
  69. package/dist/plugins/usage-graph.js +48 -0
  70. package/dist/preset/src/default-manifest.js +15913 -0
  71. package/dist/utils/build-import-resolver.d.ts +29 -0
  72. package/dist/utils/build-import-resolver.js +101 -0
  73. package/dist/utils/build-sass-source.d.ts +38 -0
  74. package/dist/utils/build-sass-source.js +225 -0
  75. package/dist/utils/build-stylesheet-delivery.d.ts +12 -0
  76. package/dist/utils/build-stylesheet-delivery.js +130 -0
  77. package/dist/utils/build-watch-recovery.d.ts +10 -0
  78. package/dist/utils/build-watch-recovery.js +119 -0
  79. package/dist/utils/coalesced-task.d.ts +3 -0
  80. package/dist/utils/coalesced-task.js +25 -0
  81. package/dist/utils/dev-module-refresh.d.ts +9 -0
  82. package/dist/utils/dev-module-refresh.js +17 -0
  83. package/dist/utils/dev-stylesheet-delivery.d.ts +21 -0
  84. package/dist/utils/dev-stylesheet-delivery.js +98 -0
  85. package/dist/utils/environment-closing.d.ts +3 -0
  86. package/dist/utils/environment-closing.js +28 -0
  87. package/dist/utils/extracted-css.d.ts +4 -0
  88. package/dist/utils/extracted-css.js +34 -0
  89. package/dist/utils/failed-dependency-reconciliation.d.ts +15 -0
  90. package/dist/utils/failed-dependency-reconciliation.js +150 -0
  91. package/dist/utils/failed-stylesheet-dependencies.d.ts +16 -0
  92. package/dist/utils/failed-stylesheet-dependencies.js +92 -0
  93. package/dist/utils/html.d.ts +8 -0
  94. package/dist/utils/html.js +36 -0
  95. package/dist/utils/inline-stylesheet.d.ts +37 -0
  96. package/dist/utils/inline-stylesheet.js +129 -0
  97. package/dist/utils/local-stylesheet.d.ts +10 -0
  98. package/dist/utils/local-stylesheet.js +25 -0
  99. package/dist/utils/manifest-recovery.d.ts +11 -0
  100. package/dist/utils/manifest-recovery.js +77 -0
  101. package/dist/utils/module-sources.d.ts +26 -0
  102. package/dist/utils/module-sources.js +131 -0
  103. package/dist/utils/path.d.ts +5 -0
  104. package/dist/utils/path.js +27 -0
  105. package/dist/utils/recovery-error.d.ts +3 -0
  106. package/dist/utils/recovery-error.js +17 -0
  107. package/dist/utils/register-style-source.d.ts +4 -0
  108. package/dist/utils/register-style-source.js +23 -0
  109. package/dist/utils/sass-diagnostics.d.ts +4 -0
  110. package/dist/utils/sass-diagnostics.js +109 -0
  111. package/dist/utils/sass-proxy-access.d.ts +4 -0
  112. package/dist/utils/sass-proxy-access.js +28 -0
  113. package/dist/utils/sass-source-markers.d.ts +8 -0
  114. package/dist/utils/sass-source-markers.js +50 -0
  115. package/dist/utils/scanner-context.d.ts +12 -0
  116. package/dist/utils/scanner-context.js +100 -0
  117. package/dist/utils/scoped-plugins.d.ts +4 -0
  118. package/dist/utils/scoped-plugins.js +81 -0
  119. package/dist/utils/write-file.d.ts +3 -0
  120. package/dist/utils/write-file.js +9 -0
  121. package/package.json +62 -0
@@ -0,0 +1,129 @@
1
+ import { getSassSourceFile } from "./build-sass-source.js";
2
+ import { getScanner } from "./scanner-context.js";
3
+ import { getBuildStylesheetDelivery } from "./build-stylesheet-delivery.js";
4
+ import { createHash } from "node:crypto";
5
+ import { createStylesheetCollection } from "@master/css-compiler/stylesheet";
6
+ // src/utils/inline-stylesheet.ts
7
+ const states = /* @__PURE__ */ new WeakMap();
8
+ const INLINE_URL_BASE = "https://master-css-inline.invalid/";
9
+ function inlineDigest(value) {
10
+ return createHash("sha256").update(value).digest("hex").slice(0, 20);
11
+ }
12
+ function isInlineStylesheet(id) {
13
+ return /[?&]inline(?:[=&]|$)/.test(id);
14
+ }
15
+ function inlineStylesheets(context) {
16
+ let state = states.get(context);
17
+ if (!state) {
18
+ state = /* @__PURE__ */ new Map();
19
+ states.set(context, state);
20
+ }
21
+ return state;
22
+ }
23
+ function disposeInlineStylesheets(context) {
24
+ for (const entry of inlineStylesheets(context).values()) entry.collection.dispose();
25
+ states.delete(context);
26
+ }
27
+ function inlineDelivery(context) {
28
+ const delivery = getBuildStylesheetDelivery(context);
29
+ return {
30
+ ...delivery,
31
+ entryURL: INLINE_URL_BASE + "entry.css",
32
+ stylesheetURL: (file, variant) => INLINE_URL_BASE + delivery.stylesheetURL(file, variant).slice(2),
33
+ resourceURL: (file) => INLINE_URL_BASE + delivery.resourceURL(file).slice(2),
34
+ relativeResourceURLs: false
35
+ };
36
+ }
37
+ async function registerInlineStylesheet(context, id, source, host) {
38
+ const entries = inlineStylesheets(context);
39
+ let entry = entries.get(id);
40
+ if (!entry) {
41
+ entry = {
42
+ collection: createStylesheetCollection(),
43
+ token: `__MASTER_CSS_INLINE_${inlineDigest(id)}__`
44
+ };
45
+ entries.set(id, entry);
46
+ }
47
+ return entry.collection.register(getScanner(context), id, source, {
48
+ baseManifest: getScanner(context).css.manifest,
49
+ projectDir: context.config?.root,
50
+ delivery: {
51
+ ...inlineDelivery(context),
52
+ ...host,
53
+ baseFile: getSassSourceFile(id)
54
+ }
55
+ });
56
+ }
57
+ function registerLocalInlineStylesheet(context, id, local) {
58
+ const entries = inlineStylesheets(context);
59
+ const entry = entries.get(id) ?? {
60
+ collection: createStylesheetCollection(),
61
+ token: `__MASTER_CSS_INLINE_${inlineDigest(id)}__`
62
+ };
63
+ entry.local = local;
64
+ entries.set(id, entry);
65
+ }
66
+ /** Return resource/import references using the compiler's source analysis. */
67
+ function inlineURLReferences(compiler, css) {
68
+ return compiler.prepareStylesheetBundle({
69
+ source: css,
70
+ from: "inline-url-source",
71
+ slotCSSRule: `#master-css-url-scan-${inlineDigest(css)}{--slot:0}`,
72
+ managed: {
73
+ entry: "empty",
74
+ stylesheets: [{
75
+ id: "empty",
76
+ href: "/empty.css",
77
+ css: ""
78
+ }]
79
+ }
80
+ }).sources.flatMap((source) => [...source.resources, ...source.imports]);
81
+ }
82
+ /** Rewrite host-issued URLs only at Rust-reported resource/import ranges. */
83
+ function rewriteInlineURLs(compiler, css, target, ownedURLs) {
84
+ const bundle = compiler.prepareStylesheetBundle({
85
+ source: css,
86
+ from: "inline-url-source",
87
+ slotCSSRule: `#master-css-url-scan-${inlineDigest(css)}{--slot:0}`,
88
+ managed: {
89
+ entry: "empty",
90
+ stylesheets: [{
91
+ id: "empty",
92
+ href: "/empty.css",
93
+ css: ""
94
+ }]
95
+ }
96
+ });
97
+ const references = bundle.sources.flatMap((source) => [...source.resources, ...source.imports]);
98
+ if (!references.some((reference) => ownedURLs.has(reference.url.split(/[?#]/)[0]))) return css;
99
+ const mappings = new Map(references.map((reference) => [reference.url, ownedURLs.has(reference.url.split(/[?#]/)[0]) ? encodeURI(target(reference.url)).replaceAll("%25", "%") : reference.url]));
100
+ let prefix = `https://master-css-relocation.invalid/${inlineDigest(css)}/`;
101
+ while (css.includes(prefix) || [...mappings.values()].some((value) => value.includes(prefix))) prefix += "_";
102
+ const resourceURLs = Object.fromEntries([...mappings].map(([url, value]) => [url, prefix + value]));
103
+ const urls = Object.fromEntries(bundle.graph.stylesheets.map((node) => [node.id, "/inline-url-source.css"]));
104
+ return compiler.renderStylesheetBundle({
105
+ bundle,
106
+ urls,
107
+ resourceURLs
108
+ }).find((asset) => asset.id === bundle.graph.entry).css.replaceAll(prefix, "");
109
+ }
110
+ /** Apply Vite's public output URL hook to the actual referenced file. */
111
+ function inlineBuiltURL(config, ssr, filename, hostId, hostType) {
112
+ let relative = config.base === "" || config.base === "./";
113
+ const result = config.experimental.renderBuiltUrl?.(filename, {
114
+ hostId,
115
+ hostType,
116
+ type: "asset",
117
+ ssr
118
+ });
119
+ if (typeof result === "string" && result) return { url: result };
120
+ if (result && typeof result === "object") {
121
+ if (result.runtime) {
122
+ if (hostType === "css") throw new Error("Vite renderBuiltUrl runtime expressions are not supported in CSS assets");
123
+ return { runtime: result.runtime };
124
+ }
125
+ if (typeof result.relative === "boolean") relative = result.relative;
126
+ }
127
+ return relative && (hostType === "css" || !ssr) ? { relative: true } : { url: config.base + filename };
128
+ }
129
+ export { INLINE_URL_BASE, disposeInlineStylesheets, inlineBuiltURL, inlineDelivery, inlineDigest, inlineStylesheets, inlineURLReferences, isInlineStylesheet, registerInlineStylesheet, registerLocalInlineStylesheet, rewriteInlineURLs };
@@ -0,0 +1,10 @@
1
+ import { MasterCSSStylesheetTransformResult } from "@master/css-compiler/stylesheet";
2
+ import { MasterCSSVitePluginContext } from "../core.js";
3
+ interface LocalStylesheet {
4
+ slot: string;
5
+ result: MasterCSSStylesheetTransformResult;
6
+ }
7
+ declare function localStylesheets(context: MasterCSSVitePluginContext): Map<string, LocalStylesheet>;
8
+ declare function clearLocalStylesheets(context: MasterCSSVitePluginContext): void;
9
+ declare function registerLocalStylesheet(context: MasterCSSVitePluginContext, id: string, result: MasterCSSStylesheetTransformResult): string;
10
+ export { LocalStylesheet, clearLocalStylesheets, localStylesheets, registerLocalStylesheet };
@@ -0,0 +1,25 @@
1
+ import { toRootRelativeModuleId } from "./path.js";
2
+ import { createHash } from "node:crypto";
3
+ // src/utils/local-stylesheet.ts
4
+ const states = /* @__PURE__ */ new WeakMap();
5
+ function localStylesheets(context) {
6
+ let entries = states.get(context);
7
+ if (!entries) {
8
+ entries = /* @__PURE__ */ new Map();
9
+ states.set(context, entries);
10
+ }
11
+ return entries;
12
+ }
13
+ function clearLocalStylesheets(context) {
14
+ states.delete(context);
15
+ }
16
+ function registerLocalStylesheet(context, id, result) {
17
+ const hash = createHash("sha256").update(toRootRelativeModuleId(context.config?.root, id)).digest("hex").slice(0, 20);
18
+ const slot = `#master-css-local-${hash}{--slot:local-${hash}}`;
19
+ localStylesheets(context).set(id, {
20
+ slot,
21
+ result
22
+ });
23
+ return slot;
24
+ }
25
+ export { clearLocalStylesheets, localStylesheets, registerLocalStylesheet };
@@ -0,0 +1,11 @@
1
+ import { MasterCSSVitePluginContext } from "../core.js";
2
+ import { DependencyHost } from "./failed-stylesheet-dependencies.js";
3
+ /** Manifest initialization can fail before an HTML or virtual module exists. */
4
+ declare function createManifestRecovery<T, Host extends DependencyHost = DependencyHost>(context: MasterCSSVitePluginContext, id: string, load: (onDependency: (file: string) => void, host: Host, active: () => boolean) => Promise<T>): {
5
+ run: (host: Host, isActive?: () => boolean) => Promise<T>;
6
+ assertReady(): void;
7
+ readonly failed: boolean;
8
+ isActive(environment?: object): boolean;
9
+ close(environment: object): void;
10
+ };
11
+ export { createManifestRecovery };
@@ -0,0 +1,77 @@
1
+ import { clearFailedStylesheets, withStylesheetDependencies } from "./failed-stylesheet-dependencies.js";
2
+ import { sendRecoveryError } from "./recovery-error.js";
3
+ import { onEnvironmentClosing } from "./environment-closing.js";
4
+ // src/utils/manifest-recovery.ts
5
+ /** Manifest initialization can fail before an HTML or virtual module exists. */
6
+ function createManifestRecovery(context, id, load) {
7
+ let failure;
8
+ let failed = false;
9
+ const closed = /* @__PURE__ */ new WeakSet();
10
+ const tracked = /* @__PURE__ */ new WeakSet();
11
+ let queue = Promise.resolve();
12
+ const run = (host, isActive = () => true) => {
13
+ if (host.environment && !tracked.has(host.environment)) {
14
+ const environment = host.environment;
15
+ tracked.add(environment);
16
+ onEnvironmentClosing(environment, () => {
17
+ closed.add(environment);
18
+ clearFailedStylesheets(context, environment);
19
+ });
20
+ }
21
+ const active = () => isActive() && (!host.environment || !closed.has(host.environment));
22
+ const operation = queue.then(async () => {
23
+ if (!active()) throw new Error("Master CSS manifest environment closed");
24
+ try {
25
+ const result = await withStylesheetDependencies(context, host, id, (onDependency) => load((file) => {
26
+ if (active()) onDependency(file);
27
+ }, host, active), "manifest", recover);
28
+ if (active()) {
29
+ failed = false;
30
+ failure = void 0;
31
+ }
32
+ return result;
33
+ } catch (error) {
34
+ if (active()) {
35
+ failed = true;
36
+ failure = error;
37
+ }
38
+ throw error;
39
+ }
40
+ });
41
+ queue = operation.catch(() => {});
42
+ return operation;
43
+ };
44
+ const recover = async (owner, _id, _files, active) => {
45
+ const environment = owner;
46
+ try {
47
+ await run({ environment }, active);
48
+ } catch (error) {
49
+ if (active() && !closed.has(environment)) sendRecoveryError(environment, error, id);
50
+ throw error;
51
+ }
52
+ if (!active() || closed.has(environment)) return;
53
+ const module = environment.moduleGraph.getModuleById(id);
54
+ if (module) environment.moduleGraph.invalidateModule(module);
55
+ if (module && module.isSelfAccepting !== void 0) await environment.reloadModule(module);
56
+ else if (environment.config.consumer === "client") environment.hot.send({
57
+ type: "full-reload",
58
+ path: "*"
59
+ });
60
+ };
61
+ return {
62
+ run,
63
+ assertReady() {
64
+ if (failed) throw failure;
65
+ },
66
+ get failed() {
67
+ return failed;
68
+ },
69
+ isActive(environment) {
70
+ return !environment || !closed.has(environment);
71
+ },
72
+ close(environment) {
73
+ closed.add(environment);
74
+ }
75
+ };
76
+ }
77
+ export { createManifestRecovery };
@@ -0,0 +1,26 @@
1
+ import { CSSOptions } from "vite";
2
+ type InlinePostCSS = Exclude<CSSOptions['postcss'], string | undefined>;
3
+ type HostPlugin = Exclude<Extract<NonNullable<InlinePostCSS['plugins']>[number], {
4
+ postcssPlugin: string;
5
+ }>, (...args: never[]) => unknown>;
6
+ type AdditionalData = NonNullable<NonNullable<CSSOptions['preprocessorOptions']>['scss']>['additionalData'];
7
+ interface ModuleSourceDiagnostic {
8
+ source: string;
9
+ code: string;
10
+ map?: string;
11
+ }
12
+ declare function moduleSourceID(owner: string, file: string): string;
13
+ declare function moduleSourceOwner(id: string): {
14
+ owner: string;
15
+ file: string;
16
+ } | undefined;
17
+ /** Project Vite's Modules AST changes onto its original per-file syntax trees. */
18
+ declare function createModuleSourceProjection(file: string): {
19
+ plugin: HostPlugin;
20
+ sources: Map<string, string>;
21
+ diagnostics: Map<string, ModuleSourceDiagnostic>;
22
+ sourceFiles: Map<string, string>;
23
+ copyDuplicate(id: string, source: string): void;
24
+ additionalData(value: AdditionalData): AdditionalData;
25
+ };
26
+ export { ModuleSourceDiagnostic, createModuleSourceProjection, moduleSourceID, moduleSourceOwner };
@@ -0,0 +1,131 @@
1
+ import { normalizeFilePath } from "./path.js";
2
+ import { createSassSourceMarkers } from "./sass-source-markers.js";
3
+ import { isAbsolute } from "node:path";
4
+ import { inspectCSSSync } from "@master/css-compiler/node";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ // src/utils/module-sources.ts
7
+ const PREFIX = "\0master-css:module-source:";
8
+ function moduleSourceID(owner, file) {
9
+ return `${PREFIX}${encodeURIComponent(owner)}:${encodeURIComponent(file)}.css`;
10
+ }
11
+ function moduleSourceOwner(id) {
12
+ if (!id.startsWith(PREFIX)) return;
13
+ const [owner, file] = id.slice(26, -4).split(":");
14
+ return {
15
+ owner: decodeURIComponent(owner),
16
+ file: decodeURIComponent(file)
17
+ };
18
+ }
19
+ /** Project Vite's Modules AST changes onto its original per-file syntax trees. */
20
+ function createModuleSourceProjection(file) {
21
+ file = normalizeFilePath(file);
22
+ const originals = /* @__PURE__ */ new Map();
23
+ const sources = /* @__PURE__ */ new Map();
24
+ const projectedInputs = /* @__PURE__ */ new Map();
25
+ const inputDiagnostics = /* @__PURE__ */ new Map();
26
+ const diagnostics = /* @__PURE__ */ new Map();
27
+ const authoredInputs = /* @__PURE__ */ new Map();
28
+ const preparation = createSassSourceMarkers((id, source) => authoredInputs.set(normalizeFilePath(id), source));
29
+ const { markers } = preparation;
30
+ const sourceFiles = /* @__PURE__ */ new Map();
31
+ const sourceFile = (id) => sourceFiles.get(normalizeFilePath(id)) ?? normalizeFilePath(id);
32
+ const key = (node) => `${node.type}:${node.source?.start?.offset}:${node.source?.end?.offset}`;
33
+ return {
34
+ plugin: {
35
+ postcssPlugin: "master-css:module-source-projection",
36
+ prepare({ root }) {
37
+ if (root.type === "root") originals.set(file, root.clone());
38
+ root.walkAtRules("import", (rule) => {
39
+ if (inspectCSSSync(`${rule.toString()};`).hasMasterCSSImport) rule.name = "--master-css-preserved-import";
40
+ });
41
+ return {};
42
+ },
43
+ Once(root, { postcss }) {
44
+ root.walk((node) => {
45
+ const input = node.source?.input;
46
+ if (input?.file && !originals.has(sourceFile(input.file))) originals.set(sourceFile(input.file), postcss.parse(input.css, { from: sourceFile(input.file) }));
47
+ });
48
+ root.walkComments((node) => {
49
+ if (node.source?.input.file && sourceFiles.has(normalizeFilePath(node.source.input.file)) && node.text.trim().startsWith("# sourceMappingURL=") || markers.has(node.text.trim())) node.remove();
50
+ });
51
+ },
52
+ OnceExit(root) {
53
+ const transformed = /* @__PURE__ */ new Map();
54
+ root.walk((node) => {
55
+ const input = node.source?.input;
56
+ if (input?.file) transformed.set(`${sourceFile(input.file)}:${key(node)}`, node);
57
+ });
58
+ for (const [id, original] of originals) {
59
+ for (const node of [...original.nodes]) {
60
+ if (node.type === "atrule" && node.name.toLowerCase() === "import") continue;
61
+ const next = transformed.get(`${id}:${key(node)}`);
62
+ if (next) node.replaceWith(next.clone());
63
+ else node.remove();
64
+ }
65
+ if (id === file) {
66
+ const firstRule = original.nodes.find((node) => node.type !== "comment" && !(node.type === "atrule" && (node.name === "import" || node.name === "charset" || node.name === "layer" && !node.nodes)));
67
+ for (const node of root.nodes.filter((node) => !node.source?.input.file)) if (firstRule) original.insertBefore(firstRule, node.clone());
68
+ else original.append(node.clone());
69
+ }
70
+ const css = original.toString();
71
+ sources.set(id, css);
72
+ const input = original.source?.input.css;
73
+ if (input !== void 0) {
74
+ projectedInputs.set(input, css);
75
+ const map = original.toResult({
76
+ from: id,
77
+ to: id,
78
+ map: {
79
+ inline: false,
80
+ annotation: false,
81
+ sourcesContent: true
82
+ }
83
+ }).map?.toJSON();
84
+ if (map) map.sources = map.sources.map((source, index) => {
85
+ const url = isAbsolute(source) ? pathToFileURL(source) : new URL(source, pathToFileURL(id));
86
+ const temporary = url.protocol === "file:" ? sourceFiles.get(normalizeFilePath(fileURLToPath(url))) : void 0;
87
+ if (!temporary) return source;
88
+ if (map.sourcesContent) map.sourcesContent[index] = "";
89
+ return `\0master-css:preprocessed:${temporary}`;
90
+ });
91
+ const diagnostic = {
92
+ source: authoredInputs.get(id) ?? input,
93
+ code: css,
94
+ map: map && JSON.stringify(map)
95
+ };
96
+ diagnostics.set(id, diagnostic);
97
+ inputDiagnostics.set(input, diagnostic);
98
+ }
99
+ }
100
+ const originalRoot = originals.get(file);
101
+ if (originalRoot) {
102
+ root.removeAll();
103
+ root.append(originalRoot.nodes.map((node) => node.clone()));
104
+ }
105
+ }
106
+ },
107
+ sources,
108
+ diagnostics,
109
+ sourceFiles,
110
+ additionalData: preparation.additionalData,
111
+ copyDuplicate(id, source) {
112
+ id = normalizeFilePath(id);
113
+ const projected = projectedInputs.get(source);
114
+ if (projected !== void 0 && !sources.has(id)) {
115
+ sources.set(id, projected);
116
+ const original = inputDiagnostics.get(source);
117
+ const raw = original?.map ? JSON.parse(original.map) : void 0;
118
+ if (raw?.sources.length === 1) {
119
+ raw.sources = [pathToFileURL(id).href];
120
+ raw.sourceRoot = "";
121
+ }
122
+ diagnostics.set(id, {
123
+ source,
124
+ code: projected,
125
+ map: raw?.sources.length === 1 ? JSON.stringify(raw) : void 0
126
+ });
127
+ }
128
+ }
129
+ };
130
+ }
131
+ export { createModuleSourceProjection, moduleSourceID, moduleSourceOwner };
@@ -0,0 +1,5 @@
1
+ /** Identify a module by its root-relative ID, so the identity survives moving the project. */
2
+ declare function toRootRelativeModuleId(root: string | undefined, id: string): string;
3
+ declare function normalizeFilePath(file: string): string;
4
+ declare function includesFile(dependencies: string[], file: string): boolean;
5
+ export { includesFile, normalizeFilePath, toRootRelativeModuleId };
@@ -0,0 +1,27 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
3
+ // src/utils/path.ts
4
+ /** Identify a module by its root-relative ID, so the identity survives moving the project. */
5
+ function toRootRelativeModuleId(root, id) {
6
+ const prefix = id.startsWith("\0") ? "\0" : "";
7
+ const path = id.slice(prefix.length);
8
+ if (!root || !isAbsolute(path)) return id;
9
+ return prefix + relative(root, path).replace(/\\/g, "/");
10
+ }
11
+ function normalizeFilePath(file) {
12
+ let ancestor = resolve(file);
13
+ const missing = [];
14
+ while (true) try {
15
+ return join(realpathSync.native(ancestor), ...missing).replace(/\\/g, "/");
16
+ } catch {
17
+ const parent = dirname(ancestor);
18
+ if (parent === ancestor) return resolve(file).replace(/\\/g, "/");
19
+ missing.unshift(basename(ancestor));
20
+ ancestor = parent;
21
+ }
22
+ }
23
+ function includesFile(dependencies, file) {
24
+ const normalizedFile = normalizeFilePath(file);
25
+ return dependencies.some((dependency) => normalizeFilePath(dependency) === normalizedFile);
26
+ }
27
+ export { includesFile, normalizeFilePath, toRootRelativeModuleId };
@@ -0,0 +1,3 @@
1
+ import { DevEnvironment } from "vite";
2
+ declare function sendRecoveryError(environment: DevEnvironment, error: unknown, id: string): void;
3
+ export { sendRecoveryError };
@@ -0,0 +1,17 @@
1
+ // src/utils/recovery-error.ts
2
+ function sendRecoveryError(environment, error, id) {
3
+ const failure = error && typeof error === "object" ? error : { message: String(error) };
4
+ environment.hot.send({
5
+ type: "error",
6
+ err: {
7
+ message: failure.message ?? String(error),
8
+ stack: failure.stack ?? "",
9
+ id: failure.id ?? id,
10
+ frame: failure.frame,
11
+ plugin: failure.plugin,
12
+ pluginCode: failure.pluginCode,
13
+ loc: failure.loc
14
+ }
15
+ });
16
+ }
17
+ export { sendRecoveryError };
@@ -0,0 +1,4 @@
1
+ import { MasterCSSStylesheetDeliveryOptions } from "@master/css-compiler/stylesheet";
2
+ import { MasterCSSVitePluginContext } from "../core.js";
3
+ declare function registerStylesheetSource(context: MasterCSSVitePluginContext, id: string, source: string, host?: Pick<MasterCSSStylesheetDeliveryOptions, 'resolveImport' | 'onDependency'>): Promise<import("~/packages/compiler/src").MasterCSSCompileResult>;
4
+ export { registerStylesheetSource };
@@ -0,0 +1,23 @@
1
+ import { getPreparedSassSourceMap, getSassSourceFile } from "./build-sass-source.js";
2
+ import { getScanner } from "./scanner-context.js";
3
+ import { getBuildStylesheetDelivery } from "./build-stylesheet-delivery.js";
4
+ import { getDevStylesheetDelivery } from "./dev-stylesheet-delivery.js";
5
+ import { createStylesheetCollection } from "@master/css-compiler/stylesheet";
6
+ // src/utils/register-style-source.ts
7
+ async function registerStylesheetSource(context, id, source, host) {
8
+ context.stylesheets ??= createStylesheetCollection();
9
+ const scanner = getScanner(context);
10
+ const delivery = getBuildStylesheetDelivery(context) ?? getDevStylesheetDelivery(context);
11
+ return context.stylesheets.register(scanner, id, source, {
12
+ baseManifest: scanner.css.manifest,
13
+ projectDir: context.config?.root,
14
+ pruneNativeCSS: context.pruneNativeCSS,
15
+ delivery: delivery ? {
16
+ ...delivery,
17
+ ...host,
18
+ baseFile: getSassSourceFile(id),
19
+ sourceMap: await getPreparedSassSourceMap(context, id)
20
+ } : void 0
21
+ });
22
+ }
23
+ export { registerStylesheetSource };
@@ -0,0 +1,4 @@
1
+ import { MasterCSSVitePluginContext } from "../core.js";
2
+ /** Keep compiler diagnostics intact while adapting preprocessing source locations. */
3
+ declare function withSassDiagnostics<T>(context: MasterCSSVitePluginContext, operation: () => Promise<T>): Promise<T>;
4
+ export { withSassDiagnostics };
@@ -0,0 +1,109 @@
1
+ import { normalizeFilePath } from "./path.js";
2
+ import { getPreparedSassDiagnosticSource } from "./build-sass-source.js";
3
+ import { SourceMap } from "node:module";
4
+ import { isAbsolute } from "node:path";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ import { MasterCSSError } from "@master/css-schema";
7
+ // src/utils/sass-diagnostics.ts
8
+ const mappedErrors = /* @__PURE__ */ new WeakSet();
9
+ async function mapDiagnostic(context, diagnostic) {
10
+ if (!diagnostic.source || !diagnostic.range) return diagnostic;
11
+ const cached = await getPreparedSassDiagnosticSource(context, diagnostic.source);
12
+ if (!cached) return diagnostic;
13
+ const language = cached.file.endsWith(".css") ? "CSS Modules" : "Sass";
14
+ const unavailable = {
15
+ ...diagnostic,
16
+ source: cached.generatedID,
17
+ notes: [...diagnostic.notes ?? [], `Original ${language} location is unavailable; this range refers to preprocessed CSS.`]
18
+ };
19
+ const prepared = cached.prepared;
20
+ const raw = typeof prepared.map === "string" ? JSON.parse(prepared.map) : prepared.map;
21
+ if (!raw || !("version" in raw) || !("sources" in raw) || !Array.isArray(raw.sources) || !raw.mappings) return unavailable;
22
+ const sourcesContent = "sourcesContent" in raw ? raw.sourcesContent ?? [] : [];
23
+ const sourceRoot = "sourceRoot" in raw ? raw.sourceRoot ?? "" : "";
24
+ const map = new SourceMap({
25
+ version: 3,
26
+ file: cached.file,
27
+ sourceRoot,
28
+ sources: raw.sources.map((source) => source ?? ""),
29
+ sourcesContent: sourcesContent.map((source) => source ?? ""),
30
+ names: "names" in raw ? raw.names ?? [] : [],
31
+ mappings: raw.mappings
32
+ });
33
+ const { start, end } = diagnostic.range;
34
+ const origin = map.findEntry(start.line, start.character);
35
+ if (!("originalSource" in origin) || !origin.originalSource || origin.originalSource.includes("\0") || origin.generatedLine !== start.line) return unavailable;
36
+ const rootSource = sourceRoot ? sourceRoot.replace(/\/?$/, "/") : "./";
37
+ const root = isAbsolute(rootSource) ? pathToFileURL(rootSource) : new URL(rootSource, pathToFileURL(cached.file));
38
+ const url = isAbsolute(origin.originalSource) ? pathToFileURL(origin.originalSource) : new URL(origin.originalSource, root);
39
+ const source = url.protocol === "file:" ? fileURLToPath(url) : url.href;
40
+ if (source.includes("\0")) return unavailable;
41
+ const position = {
42
+ line: origin.originalLine,
43
+ character: origin.originalColumn
44
+ };
45
+ let original = sourcesContent[raw.sources.indexOf(origin.originalSource)];
46
+ if (url.protocol === "file:" && normalizeFilePath(source) === cached.file) {
47
+ if (original != null && original !== cached.source) return unavailable;
48
+ original = cached.source;
49
+ }
50
+ const generatedLine = prepared.code.split(/\r\n?|\n/)[start.line];
51
+ const originalLine = typeof original === "string" ? original.split(/\r\n?|\n/)[origin.originalLine] : void 0;
52
+ const offset = start.character - origin.generatedColumn;
53
+ const length = end.character - origin.generatedColumn;
54
+ if (start.line === end.line && offset >= 0 && length >= offset && generatedLine !== void 0 && originalLine !== void 0 && originalLine.slice(origin.originalColumn, origin.originalColumn + length) === generatedLine.slice(origin.generatedColumn, end.character)) return {
55
+ ...diagnostic,
56
+ source,
57
+ range: {
58
+ start: {
59
+ line: position.line,
60
+ character: position.character + offset
61
+ },
62
+ end: {
63
+ line: position.line,
64
+ character: position.character + length
65
+ }
66
+ }
67
+ };
68
+ return {
69
+ ...diagnostic,
70
+ source,
71
+ range: {
72
+ start: position,
73
+ end: position
74
+ },
75
+ notes: [...diagnostic.notes ?? [], "The source map identifies the originating segment; an exact original token range is unavailable."]
76
+ };
77
+ }
78
+ /** Keep compiler diagnostics intact while adapting preprocessing source locations. */
79
+ async function withSassDiagnostics(context, operation) {
80
+ try {
81
+ return await operation();
82
+ } catch (error) {
83
+ if (!(error instanceof MasterCSSError) || mappedErrors.has(error)) throw error;
84
+ const diagnostics = await Promise.all(error.diagnostics.map(async (diagnostic) => {
85
+ try {
86
+ return await mapDiagnostic(context, diagnostic);
87
+ } catch {
88
+ return {
89
+ ...diagnostic,
90
+ notes: [...diagnostic.notes ?? [], "Sass source mapping failed; the original compiler diagnostic is retained."]
91
+ };
92
+ }
93
+ }));
94
+ if (diagnostics.every((diagnostic, index) => diagnostic === error.diagnostics[index])) throw error;
95
+ const mapped = new MasterCSSError({
96
+ ...error.toJSON(),
97
+ diagnostics
98
+ }, { cause: error });
99
+ mappedErrors.add(mapped);
100
+ const primary = diagnostics.find((diagnostic) => diagnostic.source && diagnostic.range);
101
+ if (primary?.range) Object.assign(mapped, { loc: {
102
+ file: primary.source,
103
+ line: primary.range.start.line + 1,
104
+ column: primary.range.start.character
105
+ } });
106
+ throw mapped;
107
+ }
108
+ }
109
+ export { withSassDiagnostics };
@@ -0,0 +1,4 @@
1
+ import { ViteDevServer } from "vite";
2
+ /** Apply the host file policy to the real owner before loading a virtual proxy. */
3
+ declare function installSassProxyAccessCheck(server: ViteDevServer): void;
4
+ export { installSassProxyAccessCheck };
@@ -0,0 +1,28 @@
1
+ import { getSassSourceFile } from "./build-sass-source.js";
2
+ import { isFileLoadingAllowed, normalizePath } from "vite";
3
+ // src/utils/sass-proxy-access.ts
4
+ /** Apply the host file policy to the real owner before loading a virtual proxy. */
5
+ function installSassProxyAccessCheck(server) {
6
+ server.middlewares.use((request, response, next) => {
7
+ const check = async () => {
8
+ if (!request.url) return next();
9
+ const url = new URL(request.url, "http://master-css.invalid");
10
+ let path = decodeURI(url.pathname);
11
+ const base = server.config.base;
12
+ if (base !== "/" && path.startsWith(base)) path = "/" + path.slice(base.length);
13
+ const id = (path.startsWith("/@id/") ? path.slice(5).replace("__x00__", "\0") : path) + url.search;
14
+ if (!getSassSourceFile(id)) return next();
15
+ const resolved = await server.environments.client.pluginContainer.resolveId(id);
16
+ const owner = resolved && getSassSourceFile(resolved.id);
17
+ if (owner && !isFileLoadingAllowed(server.config, normalizePath(owner))) {
18
+ response.statusCode = 403;
19
+ response.setHeader("Content-Type", "text/plain; charset=utf-8");
20
+ response.end("403 Restricted");
21
+ return;
22
+ }
23
+ next();
24
+ };
25
+ check().catch(next);
26
+ });
27
+ }
28
+ export { installSassProxyAccessCheck };
@@ -0,0 +1,8 @@
1
+ import { CSSOptions } from "vite";
2
+ type AdditionalData = NonNullable<NonNullable<CSSOptions['preprocessorOptions']>['scss']>['additionalData'];
3
+ /** Keep input identities visible through Sass and Vite's source-map chaining. */
4
+ declare function createSassSourceMarkers(onSource?: (file: string, source: string) => void): {
5
+ markers: Set<string>;
6
+ additionalData(value: AdditionalData): AdditionalData;
7
+ };
8
+ export { createSassSourceMarkers };