@master/css-compiler 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.
- package/README.md +466 -0
- package/dist/compiler.d.ts +42 -0
- package/dist/compiler.js +248 -0
- package/dist/contracts.d.ts +31 -0
- package/dist/contracts.js +13 -0
- package/dist/diagnostics/contracts.d.ts +119 -0
- package/dist/diagnostics/contracts.js +1 -0
- package/dist/diagnostics/design-system.d.ts +31 -0
- package/dist/diagnostics/design-system.js +75 -0
- package/dist/diagnostics/index.d.ts +28 -0
- package/dist/diagnostics/index.js +304 -0
- package/dist/diagnostics/project-comparison.d.ts +4 -0
- package/dist/diagnostics/project-comparison.js +8 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +34 -0
- package/dist/node-compiler.d.ts +133 -0
- package/dist/node-compiler.js +417 -0
- package/dist/node-imports.d.ts +54 -0
- package/dist/node-imports.js +253 -0
- package/dist/node.d.ts +21 -0
- package/dist/node.js +47 -0
- package/dist/notices.d.ts +5 -0
- package/dist/notices.js +29 -0
- package/dist/prepared-graph-cache.d.ts +5 -0
- package/dist/prepared-graph-cache.js +31 -0
- package/dist/project/binding-project.d.ts +29 -0
- package/dist/project/binding-project.js +100 -0
- package/dist/project/entries.d.ts +7 -0
- package/dist/project/entries.js +30 -0
- package/dist/project/manifest-sync.d.ts +5 -0
- package/dist/project/manifest-sync.js +40 -0
- package/dist/project/manifest.d.ts +5 -0
- package/dist/project/manifest.js +49 -0
- package/dist/project/options.d.ts +43 -0
- package/dist/project/options.js +1 -0
- package/dist/pure-css-cache.d.ts +11 -0
- package/dist/pure-css-cache.js +39 -0
- package/dist/session.d.ts +19 -0
- package/dist/session.js +46 -0
- package/dist/stylesheet/browser.d.ts +32 -0
- package/dist/stylesheet/browser.js +71 -0
- package/dist/stylesheet/compiled-source.d.ts +11 -0
- package/dist/stylesheet/compiled-source.js +96 -0
- package/dist/stylesheet/composition-cache.d.ts +18 -0
- package/dist/stylesheet/composition-cache.js +79 -0
- package/dist/stylesheet/delivery.d.ts +103 -0
- package/dist/stylesheet/delivery.js +367 -0
- package/dist/stylesheet/directives.d.ts +31 -0
- package/dist/stylesheet/directives.js +105 -0
- package/dist/stylesheet/index-public.d.ts +3 -0
- package/dist/stylesheet/index-public.js +4 -0
- package/dist/stylesheet/index.d.ts +39 -0
- package/dist/stylesheet/index.js +501 -0
- package/dist/stylesheet/linked-stylesheet.d.ts +10 -0
- package/dist/stylesheet/linked-stylesheet.js +13 -0
- package/dist/stylesheet/output-map.d.ts +20 -0
- package/dist/stylesheet/output-map.js +222 -0
- package/dist/stylesheet/public.d.ts +171 -0
- package/dist/stylesheet/public.js +346 -0
- package/dist/stylesheet/reference-files.d.ts +6 -0
- package/dist/stylesheet/reference-files.js +13 -0
- package/dist/stylesheet/reference-origins.d.ts +4 -0
- package/dist/stylesheet/reference-origins.js +28 -0
- package/dist/stylesheet/render-core.d.ts +35 -0
- package/dist/stylesheet/render-core.js +28 -0
- package/dist/stylesheet/render-delivery.d.ts +4 -0
- package/dist/stylesheet/render-delivery.js +61 -0
- package/dist/stylesheet/render.d.ts +5 -0
- package/dist/stylesheet/render.js +31 -0
- package/dist/stylesheet/source-context.d.ts +8 -0
- package/dist/stylesheet/source-context.js +71 -0
- package/dist/stylesheet/source-map-url.d.ts +4 -0
- package/dist/stylesheet/source-map-url.js +11 -0
- package/dist/stylesheet/source.d.ts +3 -0
- package/dist/stylesheet/source.js +52 -0
- package/dist/stylesheet/types.d.ts +162 -0
- package/dist/stylesheet/types.js +1 -0
- package/dist/value-validation.d.ts +19 -0
- package/dist/value-validation.js +96 -0
- package/package.json +79 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { stylesheetValidationSource } from "./output-map.js";
|
|
2
|
+
import { assertValidationOptions, validateCompiledCSS } from "../value-validation.js";
|
|
3
|
+
import { toMasterCSSCompileResultInternal } from "../compiler.js";
|
|
4
|
+
import { normalizeStylesheetGraphID, prepareCSSImportGraph, prepareCSSImportGraphWithResolver } from "../node-imports.js";
|
|
5
|
+
import { analyzeCSSDependencies, inspectCSS } from "../node-compiler.js";
|
|
6
|
+
import { hasLocalStyleDirectives } from "./directives.js";
|
|
7
|
+
import { StylesheetCompositionCache } from "./composition-cache.js";
|
|
8
|
+
import { mapStylesheetError } from "./source-context.js";
|
|
9
|
+
import { cleanStyleRequest, collectStylesheetDependencies as collectStylesheetDependencies$1, compileRenderedStylesheet as compileRenderedStylesheet$1, compileStylesheet as compileStylesheet$1, createExtractedCSSResult, createStyleEntryEmittedGlobals, createStylesheetHostSource, isMasterCSSPackageStyleFile, isStylesheetRequest, prepareStylesheetSource, registerStylesheetSource, removeMasterStyleDirectives, resolveMasterStyleSource, transformLocalStylesheet } from "./index.js";
|
|
10
|
+
import { MasterCSSError } from "@master/css-schema";
|
|
11
|
+
// src/stylesheet/public.ts
|
|
12
|
+
function abortableOptions(options) {
|
|
13
|
+
options.signal?.throwIfAborted();
|
|
14
|
+
const { signal: _signal, ...compileOptions } = options;
|
|
15
|
+
return compileOptions;
|
|
16
|
+
}
|
|
17
|
+
function freezeEmittedGlobals(emittedGlobals) {
|
|
18
|
+
return Object.freeze({
|
|
19
|
+
variables: Object.freeze({ ...emittedGlobals.variables }),
|
|
20
|
+
keyframes: Object.freeze({ ...emittedGlobals.keyframes })
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function resolveStylesheetSync(id, source, options = {}) {
|
|
24
|
+
options.signal?.throwIfAborted();
|
|
25
|
+
if (!isStylesheetRequest(id)) return;
|
|
26
|
+
const normalizedId = cleanStyleRequest(id);
|
|
27
|
+
try {
|
|
28
|
+
return createStylesheetResolution(normalizedId, source, options, options.preserveImports ? resolveUnflattenedStylesheet(normalizedId, source, options.projectDir) : resolveMasterStyleSource(id, source, options.projectDir));
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw mapStylesheetError(error, normalizedId, options, source);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function createStylesheetResolution(normalizedId, source, options, resolved) {
|
|
34
|
+
const packageStyle = !normalizedId.startsWith("\0") && isMasterCSSPackageStyleFile(normalizedId, options.projectDir);
|
|
35
|
+
const entry = resolved && !resolved.local;
|
|
36
|
+
const local = resolved?.local || !resolved && hasLocalStyleDirectives(source, normalizedId);
|
|
37
|
+
const kind = packageStyle ? entry ? "master-package-entry" : "master-package" : entry ? "entry" : local ? "local" : "plain";
|
|
38
|
+
const outputSource = packageStyle ? removeMasterStyleDirectives(source).code : source;
|
|
39
|
+
const compilationSource = resolved?.source ?? outputSource;
|
|
40
|
+
const dependencies = resolved?.dependencies ?? (kind === "plain" ? [normalizedId] : collectStylesheetDependencies$1(normalizedId, source, options.projectDir));
|
|
41
|
+
return Object.freeze({
|
|
42
|
+
id: normalizedId,
|
|
43
|
+
kind,
|
|
44
|
+
source,
|
|
45
|
+
compilationSource,
|
|
46
|
+
outputSource,
|
|
47
|
+
dependencies: Object.freeze([...new Set(dependencies)])
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function resolveUnflattenedStylesheet(id, source, projectDir) {
|
|
51
|
+
let graph;
|
|
52
|
+
try {
|
|
53
|
+
graph = prepareCSSImportGraph(id, source, {
|
|
54
|
+
projectDir,
|
|
55
|
+
expandPackageImports: false
|
|
56
|
+
}, analyzeCSSDependencies);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (!inspectCSS(source).hasMasterEntry) return;
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
return classifyPreparedStylesheet(graph, source);
|
|
62
|
+
}
|
|
63
|
+
function classifyPreparedStylesheet(graph, source) {
|
|
64
|
+
const files = Object.entries(graph.files);
|
|
65
|
+
const entry = files.some(([, text]) => inspectCSS(text).hasMasterEntry);
|
|
66
|
+
if (!entry && !files.some(([file, text]) => hasLocalStyleDirectives(text, file))) return;
|
|
67
|
+
return {
|
|
68
|
+
source,
|
|
69
|
+
dependencies: Object.keys(graph.files),
|
|
70
|
+
local: !entry
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function resolveStylesheet(id, source, options = {}) {
|
|
74
|
+
if (!options.resolveImport && !options.baseFile) return resolveStylesheetSync(id, source, options);
|
|
75
|
+
options.signal?.throwIfAborted();
|
|
76
|
+
if (!options.preserveImports) throw new TypeError("Custom import resolution requires preserveImports.");
|
|
77
|
+
if (!isStylesheetRequest(id)) return;
|
|
78
|
+
const normalizedId = cleanStyleRequest(id);
|
|
79
|
+
const graph = await prepareCSSImportGraphWithResolver(normalizedId, source, {
|
|
80
|
+
projectDir: options.projectDir,
|
|
81
|
+
expandPackageImports: false,
|
|
82
|
+
onDependency: options.onDependency,
|
|
83
|
+
signal: options.signal,
|
|
84
|
+
baseFile: options.baseFile
|
|
85
|
+
}, analyzeCSSDependencies, options.resolveImport ?? (() => void 0));
|
|
86
|
+
options.signal?.throwIfAborted();
|
|
87
|
+
return createStylesheetResolution(normalizedId, source, options, classifyPreparedStylesheet(graph, source));
|
|
88
|
+
}
|
|
89
|
+
/** Resolve the complete delivery graph, including package CSS, without lowering or flattening.
|
|
90
|
+
* Unlike classification-only dependency collection, resolution failures propagate.
|
|
91
|
+
*/
|
|
92
|
+
function resolveStylesheetDependenciesSync(id, source, options = {}) {
|
|
93
|
+
options.signal?.throwIfAborted();
|
|
94
|
+
const filename = cleanStyleRequest(id);
|
|
95
|
+
let hasReferences = false;
|
|
96
|
+
const graph = prepareCSSImportGraph(filename, source, { projectDir: options.projectDir }, (text) => {
|
|
97
|
+
const analysis = analyzeCSSDependencies(text);
|
|
98
|
+
hasReferences ||= analysis.sourceWithoutReferences !== text;
|
|
99
|
+
return analysis;
|
|
100
|
+
});
|
|
101
|
+
options.signal?.throwIfAborted();
|
|
102
|
+
return Object.freeze({
|
|
103
|
+
hasReferences,
|
|
104
|
+
dependencies: Object.freeze(Object.keys(graph.files)),
|
|
105
|
+
edges: Object.freeze(graph.edges.map((edge) => Object.freeze({ ...edge })))
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function collectStylesheetDependenciesSync(id, source, options = {}) {
|
|
109
|
+
options.signal?.throwIfAborted();
|
|
110
|
+
return Object.freeze(collectStylesheetDependencies$1(id, source, options.projectDir));
|
|
111
|
+
}
|
|
112
|
+
function collectStylesheetDependencies(id, source, options = {}) {
|
|
113
|
+
return Promise.resolve(collectStylesheetDependenciesSync(id, source, options));
|
|
114
|
+
}
|
|
115
|
+
function composeStylesheetHostSync(source, options = {}) {
|
|
116
|
+
options.signal?.throwIfAborted();
|
|
117
|
+
return createStylesheetHostSource(source, options);
|
|
118
|
+
}
|
|
119
|
+
function composeStylesheetHost(source, options = {}) {
|
|
120
|
+
return Promise.resolve(composeStylesheetHostSync(source, options));
|
|
121
|
+
}
|
|
122
|
+
async function compileStylesheet(id, source, options) {
|
|
123
|
+
assertValidationOptions(options);
|
|
124
|
+
const compileOptions = abortableOptions(options);
|
|
125
|
+
const result = await compileStylesheet$1(id, source, {
|
|
126
|
+
...compileOptions,
|
|
127
|
+
loadSass: compileOptions.loadSass
|
|
128
|
+
});
|
|
129
|
+
options.signal?.throwIfAborted();
|
|
130
|
+
return toMasterCSSCompileResultInternal(result, options.onDiagnostic, options.validation, stylesheetValidationSource(result.css, id, result.sourceMap));
|
|
131
|
+
}
|
|
132
|
+
async function compileRenderedStylesheet(id, source, options) {
|
|
133
|
+
assertValidationOptions(options);
|
|
134
|
+
const compileOptions = abortableOptions(options);
|
|
135
|
+
const result = await compileRenderedStylesheet$1(id, source, {
|
|
136
|
+
...compileOptions,
|
|
137
|
+
loadSass: compileOptions.loadSass
|
|
138
|
+
});
|
|
139
|
+
options.signal?.throwIfAborted();
|
|
140
|
+
const compilation = toMasterCSSCompileResultInternal(result, options.onDiagnostic, options.validation, stylesheetValidationSource(result.css, id, result.sourceMap));
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
...compilation,
|
|
143
|
+
diagnostics: Object.freeze([...compilation.diagnostics, ...validateCompiledCSS((result.stylesheets ?? []).map((asset) => stylesheetValidationSource(asset.css, asset.id, asset.sourceMap)), options)]),
|
|
144
|
+
...result.stylesheets ? {
|
|
145
|
+
entry: result.entry,
|
|
146
|
+
stylesheets: Object.freeze(result.stylesheets.map(({ id, href, css, sourceMap }) => Object.freeze({
|
|
147
|
+
id,
|
|
148
|
+
href,
|
|
149
|
+
css,
|
|
150
|
+
sourceMap
|
|
151
|
+
}))),
|
|
152
|
+
resources: Object.freeze((result.resources ?? []).map((asset) => Object.freeze({ ...asset })))
|
|
153
|
+
} : {},
|
|
154
|
+
manifest: Object.freeze(result.manifest),
|
|
155
|
+
emittedGlobals: freezeEmittedGlobals(result.emittedGlobals)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function collectStylesheetEmittedGlobals(entries, options) {
|
|
159
|
+
assertValidationOptions(options);
|
|
160
|
+
const compileOptions = abortableOptions(options);
|
|
161
|
+
const result = await createStyleEntryEmittedGlobals([...entries], {
|
|
162
|
+
...compileOptions,
|
|
163
|
+
loadSass: compileOptions.loadSass
|
|
164
|
+
});
|
|
165
|
+
options.signal?.throwIfAborted();
|
|
166
|
+
return Object.freeze({
|
|
167
|
+
emittedGlobals: freezeEmittedGlobals(result.emittedGlobals),
|
|
168
|
+
dependencies: Object.freeze([...result.dependencies])
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async function transformStylesheet(id, source, options) {
|
|
172
|
+
assertValidationOptions(options);
|
|
173
|
+
const compileOptions = abortableOptions(options);
|
|
174
|
+
const result = await transformLocalStylesheet(id, source, {
|
|
175
|
+
...compileOptions,
|
|
176
|
+
loadSass: compileOptions.loadSass
|
|
177
|
+
});
|
|
178
|
+
options.signal?.throwIfAborted();
|
|
179
|
+
return Object.freeze({
|
|
180
|
+
code: result.code,
|
|
181
|
+
diagnostics: validateCompiledCSS([
|
|
182
|
+
stylesheetValidationSource(result.code, id, result.result?.sourceMap),
|
|
183
|
+
...result.globalStylesheet ? [stylesheetValidationSource(result.globalStylesheet.css, id, result.globalStylesheet.sourceMap)] : [],
|
|
184
|
+
...(result.stylesheets ?? []).map((asset) => stylesheetValidationSource(asset.css, asset.id, asset.sourceMap))
|
|
185
|
+
], options),
|
|
186
|
+
...result.globalStylesheet ? { globalStylesheet: Object.freeze({ ...result.globalStylesheet }) } : {},
|
|
187
|
+
...result.result?.sourceMap ? { sourceMap: result.result.sourceMap } : {},
|
|
188
|
+
dependencies: Object.freeze([...result.dependencies]),
|
|
189
|
+
transformed: result.transformed,
|
|
190
|
+
...result.stylesheets ? { stylesheets: Object.freeze(result.stylesheets.map((asset) => Object.freeze({ ...asset }))) } : {},
|
|
191
|
+
...result.resources ? { resources: Object.freeze(result.resources.map((asset) => Object.freeze({ ...asset }))) } : {},
|
|
192
|
+
...result.result ? { compilation: toMasterCSSCompileResultInternal(result.result, options.onDiagnostic, options.validation) } : {}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
let bindStylesheetCollection;
|
|
196
|
+
var MasterCSSStylesheetCollection = class MasterCSSStylesheetCollection {
|
|
197
|
+
#sources = /* @__PURE__ */ new Map();
|
|
198
|
+
#compositionCache = new StylesheetCompositionCache();
|
|
199
|
+
#disposed = false;
|
|
200
|
+
#scanners = /* @__PURE__ */ new Map();
|
|
201
|
+
#sourceIDs = /* @__PURE__ */ new Map();
|
|
202
|
+
constructor() {}
|
|
203
|
+
get size() {
|
|
204
|
+
this.assertActive();
|
|
205
|
+
return this.#sources.size;
|
|
206
|
+
}
|
|
207
|
+
async register(scanner, id, source, options) {
|
|
208
|
+
this.assertActive();
|
|
209
|
+
assertValidationOptions(options);
|
|
210
|
+
let compileOptions = abortableOptions(options);
|
|
211
|
+
const resolveImport = compileOptions.delivery?.resolveImport;
|
|
212
|
+
if (resolveImport) compileOptions = {
|
|
213
|
+
...compileOptions,
|
|
214
|
+
delivery: {
|
|
215
|
+
...compileOptions.delivery,
|
|
216
|
+
resolveImport: async (specifier, importer) => {
|
|
217
|
+
this.assertActive();
|
|
218
|
+
options.signal?.throwIfAborted();
|
|
219
|
+
const result = await resolveImport(specifier, importer);
|
|
220
|
+
this.assertActive();
|
|
221
|
+
options.signal?.throwIfAborted();
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const previousSources = new Map(this.#sources);
|
|
227
|
+
const stagedSources = new Map(previousSources);
|
|
228
|
+
const nativeRegistrations = [];
|
|
229
|
+
const stagedScanner = Object.create(scanner);
|
|
230
|
+
stagedScanner.registerNativeClasses = (owner, names) => {
|
|
231
|
+
nativeRegistrations.push([owner, names]);
|
|
232
|
+
return false;
|
|
233
|
+
};
|
|
234
|
+
const result = await registerStylesheetSource(stagedScanner, stagedSources, id, source, {
|
|
235
|
+
...compileOptions,
|
|
236
|
+
loadSass: compileOptions.loadSass
|
|
237
|
+
});
|
|
238
|
+
options.signal?.throwIfAborted();
|
|
239
|
+
const compilation = toMasterCSSCompileResultInternal(result, options.onDiagnostic, options.validation, stylesheetValidationSource(result.css, id, result.sourceMap));
|
|
240
|
+
this.assertActive();
|
|
241
|
+
this.#compositionCache.clear();
|
|
242
|
+
for (const [key, staged] of stagedSources) {
|
|
243
|
+
if (previousSources.get(key) === staged) continue;
|
|
244
|
+
this.#sources.set(key, staged);
|
|
245
|
+
this.#scanners.set(key, scanner);
|
|
246
|
+
this.#sourceIDs.set(id, key);
|
|
247
|
+
}
|
|
248
|
+
for (const [owner, names] of nativeRegistrations) scanner.registerNativeClasses(owner, names);
|
|
249
|
+
return compilation;
|
|
250
|
+
}
|
|
251
|
+
delete(id) {
|
|
252
|
+
this.assertActive();
|
|
253
|
+
this.#compositionCache.clear();
|
|
254
|
+
const key = this.#sourceIDs.get(id) ?? normalizeStylesheetGraphID(cleanStyleRequest(id));
|
|
255
|
+
this.#sourceIDs.delete(id);
|
|
256
|
+
this.#scanners.get(key)?.removeOwner(key);
|
|
257
|
+
this.#scanners.delete(key);
|
|
258
|
+
return this.#sources.delete(key);
|
|
259
|
+
}
|
|
260
|
+
clear() {
|
|
261
|
+
this.assertActive();
|
|
262
|
+
this.#compositionCache.clear();
|
|
263
|
+
for (const [id, scanner] of this.#scanners) if (scanner.initialized) scanner.removeOwner(id);
|
|
264
|
+
this.#scanners.clear();
|
|
265
|
+
this.#sourceIDs.clear();
|
|
266
|
+
this.#sources.clear();
|
|
267
|
+
}
|
|
268
|
+
async compose(options) {
|
|
269
|
+
this.assertActive();
|
|
270
|
+
const { sourceIds, ...compileOptions } = abortableOptions(options);
|
|
271
|
+
const selected = sourceIds && new Set(sourceIds.map(cleanStyleRequest));
|
|
272
|
+
const sources = selected ? new Map([...this.#sources].filter(([id]) => selected.has(id))) : this.#sources;
|
|
273
|
+
let result = this.#compositionCache.get(options, sources);
|
|
274
|
+
const cached = Boolean(result);
|
|
275
|
+
const captured = result ? void 0 : this.#compositionCache.capture(options, sources);
|
|
276
|
+
if (!result) {
|
|
277
|
+
result = await createExtractedCSSResult({
|
|
278
|
+
...compileOptions,
|
|
279
|
+
scanner: options.scanner,
|
|
280
|
+
stylesheetSources: sources,
|
|
281
|
+
loadSass: compileOptions.loadSass
|
|
282
|
+
});
|
|
283
|
+
options.signal?.throwIfAborted();
|
|
284
|
+
this.assertActive();
|
|
285
|
+
}
|
|
286
|
+
options.signal?.throwIfAborted();
|
|
287
|
+
const diagnostics = validateCompiledCSS([{ css: result.css }, ...(result.stylesheets ?? []).map((asset) => stylesheetValidationSource(asset.css, asset.id, asset.sourceMap))], options);
|
|
288
|
+
options.signal?.throwIfAborted();
|
|
289
|
+
this.assertActive();
|
|
290
|
+
if (!cached && !diagnostics.some((diagnostic) => diagnostic.severity === "error")) this.#compositionCache.set(options, sources, result, captured);
|
|
291
|
+
return Object.freeze({
|
|
292
|
+
css: result.css,
|
|
293
|
+
diagnostics,
|
|
294
|
+
...result.stylesheets ? { stylesheets: Object.freeze(result.stylesheets.map((asset) => Object.freeze({ ...asset }))) } : {},
|
|
295
|
+
...result.resources ? { resources: Object.freeze(result.resources.map((asset) => Object.freeze({ ...asset }))) } : {},
|
|
296
|
+
...result.dependencies ? { dependencies: Object.freeze([...result.dependencies]) } : {},
|
|
297
|
+
emittedGlobals: freezeEmittedGlobals(result.emittedGlobals)
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
snapshot() {
|
|
301
|
+
this.assertActive();
|
|
302
|
+
const sources = Object.freeze([...this.#sources.entries()].map(([id, source]) => freezeSourceSnapshot(id, source)));
|
|
303
|
+
return Object.freeze({
|
|
304
|
+
size: sources.length,
|
|
305
|
+
sourceIds: Object.freeze(sources.map(({ id }) => id)),
|
|
306
|
+
dependencies: Object.freeze([...new Set(sources.flatMap(({ dependencies }) => dependencies))]),
|
|
307
|
+
sources
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
dispose() {
|
|
311
|
+
if (this.#disposed) return;
|
|
312
|
+
this.#disposed = true;
|
|
313
|
+
this.#compositionCache.clear();
|
|
314
|
+
for (const [id, scanner] of this.#scanners) if (scanner.initialized) scanner.removeOwner(id);
|
|
315
|
+
this.#scanners.clear();
|
|
316
|
+
this.#sourceIDs.clear();
|
|
317
|
+
this.#sources.clear();
|
|
318
|
+
}
|
|
319
|
+
[Symbol.dispose]() {
|
|
320
|
+
this.dispose();
|
|
321
|
+
}
|
|
322
|
+
assertActive() {
|
|
323
|
+
if (this.#disposed) throw new MasterCSSError({
|
|
324
|
+
code: "SESSION_DISPOSED",
|
|
325
|
+
domain: "compiler",
|
|
326
|
+
message: "The Master CSS stylesheet collection has been disposed."
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
static {
|
|
330
|
+
bindStylesheetCollection = () => new MasterCSSStylesheetCollection();
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
function freezeSourceSnapshot(id, source) {
|
|
334
|
+
return Object.freeze({
|
|
335
|
+
id,
|
|
336
|
+
source: source.source,
|
|
337
|
+
dependencies: Object.freeze([...source.dependencies]),
|
|
338
|
+
sourceDependencies: Object.freeze([...source.sourceDependencies]),
|
|
339
|
+
isMasterCSS: source.masterCSS,
|
|
340
|
+
prunesNativeCSS: source.pruneNativeCSS
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function createStylesheetCollection() {
|
|
344
|
+
return bindStylesheetCollection();
|
|
345
|
+
}
|
|
346
|
+
export { MasterCSSStylesheetCollection, collectStylesheetDependencies, collectStylesheetDependenciesSync, collectStylesheetEmittedGlobals, compileRenderedStylesheet, compileStylesheet, composeStylesheetHost, composeStylesheetHostSync, createStylesheetCollection, prepareStylesheetSource as prepareStylesheet, resolveStylesheet, resolveStylesheetDependenciesSync, resolveStylesheetSync, transformStylesheet };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CSSDirectiveReference } from "@master/css-schema/css-directives";
|
|
2
|
+
/** File paths are host inputs, not CSS URLs. Preserve reserved filename characters. */
|
|
3
|
+
declare function referenceFileInputs(files?: readonly string[]): (CSSDirectiveReference & {
|
|
4
|
+
resolvedFile: string;
|
|
5
|
+
})[];
|
|
6
|
+
export { referenceFileInputs };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
// src/stylesheet/reference-files.ts
|
|
3
|
+
/** File paths are host inputs, not CSS URLs. Preserve reserved filename characters. */
|
|
4
|
+
function referenceFileInputs(files = []) {
|
|
5
|
+
return files.map((file) => {
|
|
6
|
+
if (!isAbsolute(file)) throw new TypeError("referenceFiles must contain absolute filesystem paths.");
|
|
7
|
+
return {
|
|
8
|
+
source: file,
|
|
9
|
+
resolvedFile: file
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export { referenceFileInputs };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CSSDirectiveReference } from "@master/css-schema/css-directives";
|
|
2
|
+
/** Adapt Rust reference offsets through a host map; CSS parsing stays in Rust. */
|
|
3
|
+
declare function resolveReferenceOrigins(source: string, references: readonly CSSDirectiveReference[], owner: string, serializedMap?: string): readonly CSSDirectiveReference[];
|
|
4
|
+
export { resolveReferenceOrigins };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { sourceMapBase, sourceMapURL } from "./source-map-url.js";
|
|
2
|
+
import { SourceMap } from "node:module";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { isAbsolute } from "node:path";
|
|
5
|
+
// src/stylesheet/reference-origins.ts
|
|
6
|
+
/** Adapt Rust reference offsets through a host map; CSS parsing stays in Rust. */
|
|
7
|
+
function resolveReferenceOrigins(source, references, owner, serializedMap) {
|
|
8
|
+
if (!serializedMap || !references.length) return references;
|
|
9
|
+
if (!isAbsolute(owner)) throw new TypeError("A stylesheet source map requires an absolute filesystem baseFile.");
|
|
10
|
+
const raw = JSON.parse(serializedMap);
|
|
11
|
+
const map = new SourceMap(raw);
|
|
12
|
+
const base = sourceMapBase(owner, raw.sourceRoot);
|
|
13
|
+
return references.map((reference) => {
|
|
14
|
+
const start = "start" in reference ? reference.start : void 0;
|
|
15
|
+
if (typeof start !== "number" || !Number.isInteger(start) || start < 0 || start >= source.length) throw new TypeError("A mapped CSS reference requires its compiler-provided source offset.");
|
|
16
|
+
const prefix = source.slice(0, start).split(/\r\n?|\n/);
|
|
17
|
+
const line = prefix.length - 1, column = prefix[line].length;
|
|
18
|
+
const origin = map.findEntry(line, column);
|
|
19
|
+
if (!("originalSource" in origin) || !origin.originalSource || origin.originalSource.includes("\0") || origin.generatedLine !== line) throw new TypeError(`Original source unavailable for mapped CSS reference: ${reference.source}`);
|
|
20
|
+
const url = sourceMapURL(origin.originalSource, base);
|
|
21
|
+
if (url.protocol !== "file:") throw new TypeError(`CSS reference source must identify a filesystem file: ${url.href}`);
|
|
22
|
+
return {
|
|
23
|
+
...reference,
|
|
24
|
+
file: fileURLToPath(url)
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export { resolveReferenceOrigins };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MasterCSSManifest } from "@master/css-schema/manifest";
|
|
2
|
+
import { CSSOutputMapping } from "@master/css-schema/css-directives";
|
|
3
|
+
import { MasterCSSEmittedGlobals } from "@master/css-schema/emitted-globals";
|
|
4
|
+
import { MasterCSSHydrationManifest } from "@master/css-schema/hydration-manifest";
|
|
5
|
+
import { MasterCSSEngineSnapshot } from "@master/css";
|
|
6
|
+
interface MasterCSSRenderBindingResult {
|
|
7
|
+
readonly outputMappings: CSSOutputMapping[];
|
|
8
|
+
readonly classes: string[];
|
|
9
|
+
readonly snapshot: MasterCSSEngineSnapshot;
|
|
10
|
+
readonly hydrationManifest: MasterCSSHydrationManifest;
|
|
11
|
+
}
|
|
12
|
+
interface RenderCompiledManifestCSSOptions {
|
|
13
|
+
manifest: MasterCSSManifest;
|
|
14
|
+
classNames?: Iterable<string>;
|
|
15
|
+
nativeCSS?: string | string[];
|
|
16
|
+
includeGeneratedCSS?: boolean;
|
|
17
|
+
emittedGlobals?: MasterCSSEmittedGlobals;
|
|
18
|
+
}
|
|
19
|
+
interface RenderCompiledManifestCSSResult {
|
|
20
|
+
css: string;
|
|
21
|
+
nativeCSS: string;
|
|
22
|
+
generatedCSS: string;
|
|
23
|
+
outputMappings: CSSOutputMapping[];
|
|
24
|
+
emittedGlobals: Required<MasterCSSEmittedGlobals>;
|
|
25
|
+
}
|
|
26
|
+
interface StylesheetRenderSession {
|
|
27
|
+
ensureClasses(classNames: string[]): void;
|
|
28
|
+
ensureStylesheetResources(nativeCSS: string): void;
|
|
29
|
+
emittedGlobals(): Required<MasterCSSEmittedGlobals>;
|
|
30
|
+
snapshot(): MasterCSSRenderBindingResult;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|
|
33
|
+
declare function normalizeNativeCSS(nativeCSS: string | string[] | undefined): string[];
|
|
34
|
+
declare function renderCompiledManifestCSSWithSession(options: RenderCompiledManifestCSSOptions, session: StylesheetRenderSession): RenderCompiledManifestCSSResult;
|
|
35
|
+
export { RenderCompiledManifestCSSOptions, RenderCompiledManifestCSSResult, StylesheetRenderSession, normalizeNativeCSS, renderCompiledManifestCSSWithSession };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/stylesheet/render-core.ts
|
|
2
|
+
function normalizeNativeCSS(nativeCSS) {
|
|
3
|
+
return (Array.isArray(nativeCSS) ? nativeCSS : [nativeCSS]).filter((source) => typeof source === "string").map((source) => source.replace(/\r\n?/g, "\n"));
|
|
4
|
+
}
|
|
5
|
+
function renderCompiledManifestCSSWithSession(options, session) {
|
|
6
|
+
const nativeCSS = normalizeNativeCSS(options.nativeCSS);
|
|
7
|
+
const nativeCSSText = nativeCSS.filter(Boolean).join("\n\n");
|
|
8
|
+
if (options.includeGeneratedCSS !== false) {
|
|
9
|
+
const classNames = [...options.classNames || []];
|
|
10
|
+
session.ensureClasses(classNames);
|
|
11
|
+
}
|
|
12
|
+
for (const css of nativeCSS) session.ensureStylesheetResources(css);
|
|
13
|
+
const rendered = session.snapshot();
|
|
14
|
+
const generatedCSS = rendered.snapshot.text;
|
|
15
|
+
const offset = nativeCSSText ? nativeCSSText.length + 2 : 0;
|
|
16
|
+
return {
|
|
17
|
+
css: [nativeCSSText, generatedCSS].filter(Boolean).join("\n\n"),
|
|
18
|
+
nativeCSS: nativeCSSText,
|
|
19
|
+
generatedCSS,
|
|
20
|
+
outputMappings: rendered.outputMappings.map((mapping) => ({
|
|
21
|
+
...mapping,
|
|
22
|
+
generatedStart: mapping.generatedStart + offset,
|
|
23
|
+
generatedEnd: mapping.generatedEnd === void 0 ? void 0 : mapping.generatedEnd + offset
|
|
24
|
+
})),
|
|
25
|
+
emittedGlobals: session.emittedGlobals()
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export { normalizeNativeCSS, renderCompiledManifestCSSWithSession };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CompileRenderedStylesheetOptions, CompileRenderedStylesheetResult } from "./types.js";
|
|
2
|
+
/** Render generated globals once while keeping native stylesheet boundaries. */
|
|
3
|
+
declare function compileRenderedDelivery(id: string, source: string, options: CompileRenderedStylesheetOptions): Promise<CompileRenderedStylesheetResult>;
|
|
4
|
+
export { compileRenderedDelivery };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { renderCompiledManifestCSS } from "./render.js";
|
|
2
|
+
import { compileDeliveredSource } from "./delivery.js";
|
|
3
|
+
import { mapStylesheetError } from "./source-context.js";
|
|
4
|
+
// src/stylesheet/render-delivery.ts
|
|
5
|
+
/** Render generated globals once while keeping native stylesheet boundaries. */
|
|
6
|
+
async function compileRenderedDelivery(id, source, options) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await compileDeliveredSource(id, source, {
|
|
9
|
+
...options,
|
|
10
|
+
transformNativeStylesheets: true
|
|
11
|
+
}, options.classes);
|
|
12
|
+
const entry = result.stylesheets.find((asset) => asset.id === result.entry);
|
|
13
|
+
const generated = renderCompiledManifestCSS({
|
|
14
|
+
manifest: result.resolutionManifest,
|
|
15
|
+
nativeCSS: result.stylesheets.map((asset) => asset.css),
|
|
16
|
+
classNames: options.classes,
|
|
17
|
+
emittedGlobals: options.emittedGlobals
|
|
18
|
+
});
|
|
19
|
+
const nativeCSS = entry.css;
|
|
20
|
+
const css = [nativeCSS, generated.generatedCSS].filter(Boolean).join("\n\n");
|
|
21
|
+
const shift = (nativeCSS ? nativeCSS.length + 2 : 0) - (generated.nativeCSS ? generated.nativeCSS.length + 2 : 0);
|
|
22
|
+
const resourceMappings = generated.outputMappings.map((mapping) => ({
|
|
23
|
+
...mapping,
|
|
24
|
+
generatedStart: mapping.generatedStart + shift,
|
|
25
|
+
generatedEnd: mapping.generatedEnd === void 0 ? void 0 : mapping.generatedEnd + shift
|
|
26
|
+
}));
|
|
27
|
+
const sourceMap = result.outputMap(css, [...entry.outputMappings, ...resourceMappings]);
|
|
28
|
+
const renderedCSS = {
|
|
29
|
+
...generated,
|
|
30
|
+
css,
|
|
31
|
+
nativeCSS,
|
|
32
|
+
outputMappings: resourceMappings
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
...result.directives,
|
|
36
|
+
entry: result.entry,
|
|
37
|
+
stylesheets: result.stylesheets.map((asset) => asset.id === entry.id ? {
|
|
38
|
+
...asset,
|
|
39
|
+
css,
|
|
40
|
+
sourceMap
|
|
41
|
+
} : {
|
|
42
|
+
...asset,
|
|
43
|
+
sourceMap: result.outputMap(asset.css, asset.outputMappings, asset.id)
|
|
44
|
+
}),
|
|
45
|
+
resources: result.resources,
|
|
46
|
+
sourceMap,
|
|
47
|
+
css,
|
|
48
|
+
nativeCSS,
|
|
49
|
+
generatedCSS: generated.generatedCSS,
|
|
50
|
+
emittedGlobals: generated.emittedGlobals,
|
|
51
|
+
manifest: result.manifest,
|
|
52
|
+
renderedCSS
|
|
53
|
+
};
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw mapStylesheetError(error, id, {
|
|
56
|
+
baseFile: options.delivery?.baseFile ?? options.baseFile,
|
|
57
|
+
sourceMap: options.delivery?.sourceMap ?? options.sourceMap
|
|
58
|
+
}, source);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export { compileRenderedDelivery };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RenderCompiledManifestCSSOptions, RenderCompiledManifestCSSOptions as RenderCompiledManifestCSSOptions$1, RenderCompiledManifestCSSResult, RenderCompiledManifestCSSResult as RenderCompiledManifestCSSResult$1 } from "./render-core.js";
|
|
2
|
+
/** Compare canonical Rust reference counts; referenced theme variables and keyframes are managed. */
|
|
3
|
+
declare function hasStylesheetResourceReferences(manifest: RenderCompiledManifestCSSOptions$1['manifest'], source: string): boolean;
|
|
4
|
+
declare function renderCompiledManifestCSS(options: RenderCompiledManifestCSSOptions$1): RenderCompiledManifestCSSResult$1;
|
|
5
|
+
export { type RenderCompiledManifestCSSOptions, type RenderCompiledManifestCSSResult, hasStylesheetResourceReferences, renderCompiledManifestCSS };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { renderCompiledManifestCSSWithSession } from "./render-core.js";
|
|
2
|
+
import { createRenderBindingSessionSync } from "@master/css-binding/engine/node";
|
|
3
|
+
// src/stylesheet/render.ts
|
|
4
|
+
/** Compare canonical Rust reference counts; referenced theme variables and keyframes are managed. */
|
|
5
|
+
function hasStylesheetResourceReferences(manifest, source) {
|
|
6
|
+
const session = createRenderBindingSessionSync({ manifest });
|
|
7
|
+
try {
|
|
8
|
+
const before = session.snapshot().snapshot.resources;
|
|
9
|
+
session.ensureStylesheetResources(source);
|
|
10
|
+
const after = session.snapshot().snapshot.resources;
|
|
11
|
+
return after.variables.some((value) => value.refCount > (before.variables.find((item) => item.name === value.name)?.refCount ?? 0)) || after.keyframes.some((value) => value.refCount > (before.keyframes.find((item) => item.id === value.id)?.refCount ?? 0));
|
|
12
|
+
} finally {
|
|
13
|
+
session.dispose();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function renderCompiledManifestCSS(options) {
|
|
17
|
+
const nativeSession = createRenderBindingSessionSync(options);
|
|
18
|
+
const session = {
|
|
19
|
+
ensureClasses: (classNames) => nativeSession.ensureClassRules(classNames),
|
|
20
|
+
ensureStylesheetResources: (nativeCSS) => nativeSession.ensureStylesheetResources(nativeCSS),
|
|
21
|
+
emittedGlobals: () => nativeSession.emittedGlobals(),
|
|
22
|
+
snapshot: () => nativeSession.snapshot(),
|
|
23
|
+
dispose: () => nativeSession.dispose()
|
|
24
|
+
};
|
|
25
|
+
try {
|
|
26
|
+
return renderCompiledManifestCSSWithSession(options, session);
|
|
27
|
+
} finally {
|
|
28
|
+
session.dispose();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export { hasStylesheetResourceReferences, renderCompiledManifestCSS };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface StylesheetSourceContext {
|
|
2
|
+
readonly baseFile?: string;
|
|
3
|
+
readonly sourceMap?: string;
|
|
4
|
+
readonly onDependency?: (file: string) => void;
|
|
5
|
+
}
|
|
6
|
+
/** Translate host-prepared locations; parsing and diagnostic policy stay in Rust. */
|
|
7
|
+
declare function mapStylesheetError(error: unknown, file: string, options: StylesheetSourceContext, preparedSource?: string): unknown;
|
|
8
|
+
export { StylesheetSourceContext, mapStylesheetError };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { sourceMapBase, sourceMapURL } from "./source-map-url.js";
|
|
2
|
+
import { SourceMap } from "node:module";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { MasterCSSError } from "@master/css-schema";
|
|
5
|
+
// src/stylesheet/source-context.ts
|
|
6
|
+
const mappedErrors = /* @__PURE__ */ new WeakSet();
|
|
7
|
+
/** Translate host-prepared locations; parsing and diagnostic policy stay in Rust. */
|
|
8
|
+
function mapStylesheetError(error, file, options, preparedSource) {
|
|
9
|
+
if (!(error instanceof MasterCSSError) || mappedErrors.has(error) || !options.sourceMap) return error;
|
|
10
|
+
try {
|
|
11
|
+
const payload = JSON.parse(options.sourceMap);
|
|
12
|
+
const map = new SourceMap(payload);
|
|
13
|
+
const base = sourceMapBase(options.baseFile ?? file, payload.sourceRoot);
|
|
14
|
+
const mapped = new MasterCSSError({
|
|
15
|
+
...error.payload,
|
|
16
|
+
diagnostics: error.diagnostics.map((diagnostic) => {
|
|
17
|
+
if (diagnostic.source !== file || !diagnostic.range) return diagnostic;
|
|
18
|
+
const { start, end } = diagnostic.range;
|
|
19
|
+
const point = map.findEntry(start.line, start.character);
|
|
20
|
+
if (!("originalSource" in point) || !point.originalSource || point.generatedLine !== start.line) return {
|
|
21
|
+
...diagnostic,
|
|
22
|
+
source: pathToFileURL(file).href + "?master-css-preprocessed",
|
|
23
|
+
notes: [...diagnostic.notes ?? [], "Original source location is unavailable; this range refers to preprocessed CSS."]
|
|
24
|
+
};
|
|
25
|
+
const url = sourceMapURL(point.originalSource, base);
|
|
26
|
+
const source = url.protocol === "file:" && !url.search && !url.hash ? fileURLToPath(url) : url.href;
|
|
27
|
+
const position = {
|
|
28
|
+
line: point.originalLine,
|
|
29
|
+
character: point.originalColumn
|
|
30
|
+
};
|
|
31
|
+
const generatedLine = preparedSource?.split(/\r\n?|\n/)[start.line];
|
|
32
|
+
const originalLine = payload.sourcesContent?.[payload.sources.indexOf(point.originalSource)]?.split(/\r\n?|\n/)[point.originalLine];
|
|
33
|
+
const offset = start.character - point.generatedColumn, length = end.character - point.generatedColumn;
|
|
34
|
+
if (start.line === end.line && offset >= 0 && length >= offset && generatedLine !== void 0 && originalLine !== void 0 && originalLine.slice(point.originalColumn, point.originalColumn + length) === generatedLine.slice(point.generatedColumn, end.character)) return {
|
|
35
|
+
...diagnostic,
|
|
36
|
+
source,
|
|
37
|
+
range: {
|
|
38
|
+
start: {
|
|
39
|
+
line: position.line,
|
|
40
|
+
character: position.character + offset
|
|
41
|
+
},
|
|
42
|
+
end: {
|
|
43
|
+
line: position.line,
|
|
44
|
+
character: position.character + length
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
...diagnostic,
|
|
50
|
+
source,
|
|
51
|
+
range: {
|
|
52
|
+
start: position,
|
|
53
|
+
end: position
|
|
54
|
+
},
|
|
55
|
+
notes: [...diagnostic.notes ?? [], "The source map identifies the originating segment; an exact original token range is unavailable."]
|
|
56
|
+
};
|
|
57
|
+
})
|
|
58
|
+
}, { cause: error });
|
|
59
|
+
mappedErrors.add(mapped);
|
|
60
|
+
return mapped;
|
|
61
|
+
} catch {
|
|
62
|
+
return new MasterCSSError({
|
|
63
|
+
...error.payload,
|
|
64
|
+
diagnostics: error.diagnostics.map((diagnostic) => ({
|
|
65
|
+
...diagnostic,
|
|
66
|
+
notes: [...diagnostic.notes ?? [], "Source mapping failed; the original compiler diagnostic is retained."]
|
|
67
|
+
}))
|
|
68
|
+
}, { cause: error });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export { mapStylesheetError };
|