@master/css-mcp 2.0.0-rc.88 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +47 -22
  2. package/dist/bin/index.js +4 -5
  3. package/dist/classes.js +153 -168
  4. package/dist/compare.js +99 -83
  5. package/dist/context.d.ts +5 -10
  6. package/dist/context.js +28 -10
  7. package/dist/design-system-schema.js +97 -0
  8. package/dist/directives.js +59 -109
  9. package/dist/document.js +2 -10
  10. package/dist/format.js +67 -56
  11. package/dist/index.d.ts +2 -3
  12. package/dist/index.js +1 -3
  13. package/dist/internal/src/workspace.js +70 -0
  14. package/dist/language.js +27 -23
  15. package/dist/lint.js +86 -96
  16. package/dist/manifest-query.js +40 -100
  17. package/dist/manifest-summary.js +15 -35
  18. package/dist/output-schema.js +207 -0
  19. package/dist/preview-write-lock.js +90 -0
  20. package/dist/project-comparison-schema.js +59 -0
  21. package/dist/project.js +77 -18
  22. package/dist/result.js +67 -8
  23. package/dist/scan.js +93 -73
  24. package/dist/semantic-schema.js +286 -0
  25. package/dist/server.d.ts +10 -9
  26. package/dist/server.js +123 -111
  27. package/dist/setup.js +28 -29
  28. package/dist/source-schema.js +141 -0
  29. package/dist/suggest.js +22 -0
  30. package/dist/tooling-session.js +27 -0
  31. package/package.json +63 -73
  32. package/LICENSE +0 -21
  33. package/dist/classes.d.ts +0 -236
  34. package/dist/compare.d.ts +0 -70
  35. package/dist/contributor.d.ts +0 -149
  36. package/dist/contributor.js +0 -499
  37. package/dist/directives.d.ts +0 -132
  38. package/dist/document.d.ts +0 -24
  39. package/dist/format.d.ts +0 -56
  40. package/dist/language.d.ts +0 -24
  41. package/dist/lint.d.ts +0 -55
  42. package/dist/manifest-query.d.ts +0 -148
  43. package/dist/manifest-summary.d.ts +0 -47
  44. package/dist/project.d.ts +0 -31
  45. package/dist/result.d.ts +0 -8
  46. package/dist/scan.d.ts +0 -156
  47. package/dist/setup.d.ts +0 -67
package/dist/compare.js CHANGED
@@ -1,44 +1,42 @@
1
+ import { loadWorkspaceManifest, manifestMetadata, requireWorkspaceManifest } from "./project.js";
2
+ import { compactClassInspection, createMCPToolingSession } from "./tooling-session.js";
1
3
  import { createMCPTextDocument } from "./document.js";
2
- import { loadWorkspaceManifest } from "./project.js";
3
- import { createRequire } from "node:module";
4
- import CSSLanguageService from "@master/css-language-service";
5
- import { createCSSWithNativeDeclarations } from "@master/css-validator/native-declaration";
6
- import { parseHTML } from "@master/css-server";
7
- //#region src/compare.ts
8
- const CSS_COMPARE_VERSION = 1;
9
- const defaultManifest = createRequire(import.meta.url)("@master/css-preset/default-manifest.json");
4
+ import { renderClassNamesSync } from "@master/css/node";
5
+ import { compareProjectSnapshots } from "@master/css-compiler/diagnostics";
6
+ // src/compare.ts
7
+ const CSS_COMPARE_VERSION = 2;
10
8
  function unique(values) {
11
9
  return [...new Set(values)];
12
10
  }
13
11
  function splitClassList(value) {
14
12
  return unique((value ?? "").split(/\s+/).map((className) => className.trim()).filter(Boolean));
15
13
  }
16
- function extractContentClasses(content, filePath) {
14
+ function extractContentClasses(content, filePath, session) {
17
15
  if (content === void 0) return [];
18
- const service = new CSSLanguageService();
19
16
  const document = createMCPTextDocument(filePath, content);
20
- return unique(service.getClassPositions(document).map((position) => position.token));
17
+ return unique(session.analyzeDocument({
18
+ source: content,
19
+ languageId: document.languageId
20
+ }).classPositions.map((position) => position.token));
21
21
  }
22
- function resolveClasses(options, side, filePath) {
22
+ function resolveClasses(options, side, filePath, session) {
23
23
  const classList = side === "before" ? options.beforeClassList : options.afterClassList;
24
24
  const html = side === "before" ? options.beforeHtml : options.afterHtml;
25
25
  const content = side === "before" ? options.beforeContent : options.afterContent;
26
26
  if (classList !== void 0) return splitClassList(classList);
27
- if (html !== void 0) return unique(parseHTML(html).classes);
28
- return extractContentClasses(content, filePath);
27
+ if (html !== void 0) return unique(session.extractSource({ files: [{
28
+ source: filePath,
29
+ content: html,
30
+ kind: "html"
31
+ }] }).files[0]?.candidates ?? []);
32
+ return extractContentClasses(content, filePath, session);
29
33
  }
30
34
  function renderClasses(manifest, classes) {
31
- const css = createCSSWithNativeDeclarations(manifest);
32
- const invalid = [];
33
- for (const className of classes) {
34
- const rules = css.generate(className);
35
- if (rules.length) for (const rule of rules) rule.layer.insert(rule);
36
- else invalid.push(className);
37
- }
35
+ const rendered = renderClassNamesSync(classes, { manifest });
38
36
  return {
39
- text: css.text,
40
- bytes: css.text.length,
41
- invalid
37
+ text: rendered.cssText,
38
+ bytes: Buffer.byteLength(rendered.cssText, "utf8"),
39
+ invalid: [...rendered.invalidClassNames]
42
40
  };
43
41
  }
44
42
  function diffValues(before, after) {
@@ -64,68 +62,86 @@ function createTextDiff(before, after) {
64
62
  ].join("\n");
65
63
  }
66
64
  async function compareCSS(context, options) {
67
- const manifest = await loadWorkspaceManifest(context);
65
+ if (options.beforeSnapshot || options.afterSnapshot) {
66
+ if (!options.beforeSnapshot || !options.afterSnapshot) throw new Error("Project comparison requires both beforeSnapshot and afterSnapshot.");
67
+ if (Object.entries(options).some(([key, value]) => key !== "beforeSnapshot" && key !== "afterSnapshot" && value !== void 0)) throw new Error("Project snapshots cannot be combined with class, content, filePath or context inputs.");
68
+ return {
69
+ version: 3,
70
+ mode: "project",
71
+ comparison: await compareProjectSnapshots({
72
+ before: options.beforeSnapshot,
73
+ after: options.afterSnapshot
74
+ })
75
+ };
76
+ }
77
+ const manifest = await loadWorkspaceManifest(context, options.context);
68
78
  const filePath = context.resolveVirtualPath(options.filePath || "index.html");
69
- const activeManifest = manifest.status === "loaded" ? manifest.manifest : defaultManifest;
70
- const beforeClasses = resolveClasses(options, "before", filePath);
71
- const afterClasses = resolveClasses(options, "after", filePath);
72
- const before = renderClasses(activeManifest, beforeClasses);
73
- const after = renderClasses(activeManifest, afterClasses);
74
- const classDiff = diffValues(beforeClasses, afterClasses);
75
- const ruleDiff = diffValues(splitRules(before.text), splitRules(after.text));
76
- return {
77
- version: CSS_COMPARE_VERSION,
78
- root: context.root,
79
- manifest: {
80
- status: manifest.status,
81
- entries: manifest.entries,
82
- ...manifest.status === "error" ? { error: manifest.error } : {}
83
- },
84
- inputs: {
85
- filePath,
86
- before: {
87
- classes: beforeClasses.length,
88
- invalid: before.invalid.length
79
+ const activeManifest = requireWorkspaceManifest(manifest);
80
+ const session = createMCPToolingSession(activeManifest, manifest.nativeClassNames);
81
+ try {
82
+ const beforeClasses = resolveClasses(options, "before", filePath, session);
83
+ const afterClasses = resolveClasses(options, "after", filePath, session);
84
+ const before = renderClasses(activeManifest, beforeClasses);
85
+ const after = renderClasses(activeManifest, afterClasses);
86
+ const inspections = {
87
+ before: beforeClasses.map((name) => compactClassInspection(session, name, true)),
88
+ after: afterClasses.map((name) => compactClassInspection(session, name, true))
89
+ };
90
+ const classDiff = diffValues(beforeClasses, afterClasses);
91
+ const ruleDiff = diffValues(splitRules(before.text), splitRules(after.text));
92
+ return {
93
+ version: CSS_COMPARE_VERSION,
94
+ root: context.root,
95
+ manifest: manifestMetadata(manifest),
96
+ inspections,
97
+ diagnostics: [...inspections.before, ...inspections.after].flatMap((inspection) => inspection.diagnostics ?? []),
98
+ inputs: {
99
+ filePath,
100
+ before: {
101
+ classes: beforeClasses.length,
102
+ invalid: before.invalid.length
103
+ },
104
+ after: {
105
+ classes: afterClasses.length,
106
+ invalid: after.invalid.length
107
+ }
89
108
  },
90
- after: {
91
- classes: afterClasses.length,
92
- invalid: after.invalid.length
93
- }
94
- },
95
- classes: classDiff,
96
- invalid: {
97
- before: before.invalid,
98
- after: after.invalid,
99
- added: after.invalid.filter((className) => !before.invalid.includes(className)),
100
- removed: before.invalid.filter((className) => !after.invalid.includes(className))
101
- },
102
- css: {
103
- changed: before.text !== after.text,
104
- before: {
105
- bytes: before.bytes,
106
- text: before.text
109
+ classes: classDiff,
110
+ invalid: {
111
+ before: before.invalid,
112
+ after: after.invalid,
113
+ added: after.invalid.filter((className) => !before.invalid.includes(className)),
114
+ removed: before.invalid.filter((className) => !after.invalid.includes(className))
107
115
  },
108
- after: {
109
- bytes: after.bytes,
110
- text: after.text
116
+ css: {
117
+ changed: before.text !== after.text,
118
+ before: {
119
+ bytes: before.bytes,
120
+ text: before.text
121
+ },
122
+ after: {
123
+ bytes: after.bytes,
124
+ text: after.text
125
+ },
126
+ bytesDelta: after.bytes - before.bytes,
127
+ diff: createTextDiff(before.text, after.text)
111
128
  },
112
- bytesDelta: after.bytes - before.bytes,
113
- diff: createTextDiff(before.text, after.text)
114
- },
115
- rules: {
116
- added: ruleDiff.added,
117
- removed: ruleDiff.removed,
118
- unchanged: ruleDiff.unchanged.length
119
- },
120
- summary: {
121
- changed: before.text !== after.text,
122
- addedClasses: classDiff.added.length,
123
- removedClasses: classDiff.removed.length,
124
- addedRules: ruleDiff.added.length,
125
- removedRules: ruleDiff.removed.length,
126
- bytesDelta: after.bytes - before.bytes
127
- }
128
- };
129
+ rules: {
130
+ added: ruleDiff.added,
131
+ removed: ruleDiff.removed,
132
+ unchanged: ruleDiff.unchanged.length
133
+ },
134
+ summary: {
135
+ changed: before.text !== after.text,
136
+ addedClasses: classDiff.added.length,
137
+ removedClasses: classDiff.removed.length,
138
+ addedRules: ruleDiff.added.length,
139
+ removedRules: ruleDiff.removed.length,
140
+ bytesDelta: after.bytes - before.bytes
141
+ }
142
+ };
143
+ } finally {
144
+ session.dispose?.();
145
+ }
129
146
  }
130
- //#endregion
131
147
  export { compareCSS };
package/dist/context.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- //#region src/context.d.ts
2
1
  interface MasterCSSMCPContextOptions {
3
2
  root?: string;
4
3
  roots?: string[];
@@ -19,12 +18,6 @@ interface StoredPreviewChange {
19
18
  afterText: string;
20
19
  diff: string;
21
20
  }
22
- interface StoredPreview {
23
- confirmToken: string;
24
- createdAt: number;
25
- expiresAt: number;
26
- changes: StoredPreviewChange[];
27
- }
28
21
  interface PreviewResult {
29
22
  confirmToken?: string;
30
23
  expiresAt?: number;
@@ -41,12 +34,13 @@ declare class MasterCSSMCPContext {
41
34
  readonly previewTTL: number;
42
35
  private readonly containmentRoots;
43
36
  private previews;
37
+ private applying;
44
38
  constructor(options?: MasterCSSMCPContextOptions);
45
39
  assertContained(filePath: string): string;
46
40
  resolveVirtualPath(filePath: string): string;
47
41
  resolveExistingFile(filePath: string): Promise<string>;
48
42
  resolveWritableFile(filePath: string): Promise<string>;
49
- validateGlobPatterns(patterns: string[]): void;
43
+ validateGlobPatterns(patterns: readonly string[]): void;
50
44
  createPreview(changes: PreviewChange[], ttl?: number): Promise<PreviewResult>;
51
45
  applyPreview(confirmToken: string): Promise<{
52
46
  applied: boolean;
@@ -55,6 +49,7 @@ declare class MasterCSSMCPContext {
55
49
  afterHash: string;
56
50
  }[];
57
51
  }>;
52
+ private applyStoredPreview;
53
+ dispose(): void;
58
54
  }
59
- //#endregion
60
- export { MasterCSSMCPContextOptions, PreviewChange, PreviewResult, StoredPreview, StoredPreviewChange, MasterCSSMCPContext as default };
55
+ export { MasterCSSMCPContextOptions, PreviewChange, PreviewResult, StoredPreviewChange, MasterCSSMCPContext as default };
package/dist/context.js CHANGED
@@ -1,9 +1,10 @@
1
- import { mkdir, readFile, realpath, stat, writeFile } from "node:fs/promises";
2
- import { dirname, isAbsolute, relative, resolve } from "node:path";
3
- import { createHash, randomBytes } from "node:crypto";
1
+ import { withPreviewWriteLock } from "./preview-write-lock.js";
4
2
  import { existsSync, realpathSync, statSync } from "node:fs";
5
- //#region src/context.ts
6
- const DEFAULT_PREVIEW_TTL = 300 * 1e3;
3
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ import { createHash, randomBytes } from "node:crypto";
5
+ import { lstat, mkdir, readFile, realpath, stat, writeFile } from "node:fs/promises";
6
+ // src/context.ts
7
+ const DEFAULT_PREVIEW_TTL = 3e5;
7
8
  function sha256(text) {
8
9
  return createHash("sha256").update(text).digest("hex");
9
10
  }
@@ -48,6 +49,7 @@ var MasterCSSMCPContext = class {
48
49
  previewTTL;
49
50
  containmentRoots;
50
51
  previews = /* @__PURE__ */ new Map();
52
+ applying = /* @__PURE__ */ new Set();
51
53
  constructor(options = {}) {
52
54
  const configuredRoots = options.roots?.length ? options.roots : [options.root || process.cwd()];
53
55
  const roots = [];
@@ -90,9 +92,10 @@ var MasterCSSMCPContext = class {
90
92
  return realPath;
91
93
  }
92
94
  this.assertContained(resolved);
95
+ if ((await lstat(resolved).catch(() => void 0))?.isSymbolicLink()) throw new Error(`Path is a dangling symbolic link: ${resolved}`);
93
96
  const parent = await realpath$1(dirname(resolved));
94
97
  this.assertContained(parent);
95
- return resolved;
98
+ return join(parent, basename(resolved));
96
99
  }
97
100
  validateGlobPatterns(patterns) {
98
101
  for (const pattern of patterns) assertFilePattern(pattern);
@@ -109,8 +112,8 @@ var MasterCSSMCPContext = class {
109
112
  beforeHash: beforeExists ? sha256(beforeText) : null,
110
113
  afterHash: sha256(change.afterText),
111
114
  beforeExists,
112
- beforeBytes: beforeText.length,
113
- afterBytes: change.afterText.length,
115
+ beforeBytes: Buffer.byteLength(beforeText, "utf8"),
116
+ afterBytes: Buffer.byteLength(change.afterText, "utf8"),
114
117
  afterText: change.afterText,
115
118
  diff: formatDiff(filePath, beforeText, change.afterText)
116
119
  });
@@ -143,6 +146,19 @@ var MasterCSSMCPContext = class {
143
146
  async applyPreview(confirmToken) {
144
147
  const preview = this.previews.get(confirmToken);
145
148
  if (!preview) throw new Error("Unknown or already applied preview token.");
149
+ if (this.applying.has(confirmToken)) throw new Error("Preview token is already being applied.");
150
+ this.applying.add(confirmToken);
151
+ try {
152
+ return await withPreviewWriteLock(async () => {
153
+ if (this.previews.get(confirmToken) !== preview) throw new Error("Unknown or already applied preview token.");
154
+ return await this.applyStoredPreview(preview);
155
+ });
156
+ } finally {
157
+ this.applying.delete(confirmToken);
158
+ }
159
+ }
160
+ async applyStoredPreview(preview) {
161
+ const { confirmToken } = preview;
146
162
  if (preview.expiresAt < Date.now()) {
147
163
  this.previews.delete(confirmToken);
148
164
  throw new Error("Preview token has expired.");
@@ -158,7 +174,7 @@ var MasterCSSMCPContext = class {
158
174
  }
159
175
  for (const change of preview.changes) {
160
176
  await mkdir(dirname(change.filePath), { recursive: true });
161
- await writeFile(change.filePath, change.afterText);
177
+ await writeFile(change.filePath, change.afterText, { flag: change.beforeExists ? "w" : "wx" });
162
178
  }
163
179
  this.previews.delete(confirmToken);
164
180
  return {
@@ -169,6 +185,9 @@ var MasterCSSMCPContext = class {
169
185
  }))
170
186
  };
171
187
  }
188
+ dispose() {
189
+ this.previews.clear();
190
+ }
172
191
  };
173
192
  async function realpath$1(filePath) {
174
193
  try {
@@ -185,5 +204,4 @@ async function readFileIfExists(filePath) {
185
204
  throw error;
186
205
  }
187
206
  }
188
- //#endregion
189
207
  export { MasterCSSMCPContext as default };
@@ -0,0 +1,97 @@
1
+ import { range, strings } from "./semantic-schema.js";
2
+ import * as z from "zod/v4";
3
+ // src/design-system-schema.ts
4
+ const tokenMetadata = z.object({
5
+ description: z.string().optional(),
6
+ deprecated: z.boolean().optional(),
7
+ replacement: z.string().optional()
8
+ }).strict();
9
+ const designSystemOptions = z.object({
10
+ version: z.literal(1),
11
+ metadata: z.record(z.string(), tokenMetadata).optional(),
12
+ rawValuePolicy: z.object({
13
+ allowRawValues: z.boolean().optional(),
14
+ allowProperties: strings.optional(),
15
+ requireProperties: strings.optional(),
16
+ allowedPatterns: strings.optional()
17
+ }).strict().optional()
18
+ }).strict();
19
+ const designSystemReport = z.object({
20
+ version: z.literal(1),
21
+ tokens: z.array(z.object({
22
+ name: z.string(),
23
+ metadata: tokenMetadata.optional()
24
+ })),
25
+ references: z.array(z.object({
26
+ source: z.string(),
27
+ token: z.string(),
28
+ registered: z.boolean(),
29
+ range,
30
+ property: z.string(),
31
+ declarationRange: range,
32
+ ancestry: z.array(z.object({
33
+ kind: z.enum(["selector", "at-rule"]),
34
+ name: z.string().optional(),
35
+ prelude: z.string(),
36
+ range
37
+ })),
38
+ hasFallback: z.boolean(),
39
+ inFallback: z.boolean(),
40
+ importers: strings
41
+ })),
42
+ collisions: z.array(z.object({
43
+ prefix: z.string(),
44
+ key: z.string(),
45
+ className: z.string(),
46
+ namespaces: strings,
47
+ properties: strings
48
+ })),
49
+ components: z.array(z.object({
50
+ className: z.string(),
51
+ attributes: z.array(z.object({
52
+ name: z.string(),
53
+ values: strings,
54
+ presence: z.boolean()
55
+ })),
56
+ sources: strings
57
+ })),
58
+ diagnostics: z.array(z.object({
59
+ code: z.string(),
60
+ severity: z.enum([
61
+ "error",
62
+ "warning",
63
+ "information"
64
+ ]),
65
+ message: z.string(),
66
+ source: z.string().optional(),
67
+ range: range.optional(),
68
+ token: z.string().optional(),
69
+ data: z.record(z.string(), z.json()).optional()
70
+ })),
71
+ coverage: z.object({
72
+ scope: z.literal("provided-stylesheets"),
73
+ browser: z.literal("not-checked"),
74
+ notes: strings
75
+ }),
76
+ summary: z.object({
77
+ stylesheets: z.number(),
78
+ tokens: z.number(),
79
+ references: z.number(),
80
+ collisions: z.number(),
81
+ errors: z.number(),
82
+ warnings: z.number()
83
+ }),
84
+ project: z.object({
85
+ cwd: z.string(),
86
+ entries: strings,
87
+ files: strings,
88
+ routeStylesheets: strings,
89
+ excluded: strings,
90
+ edges: z.array(z.object({
91
+ from: z.string(),
92
+ specifier: z.string(),
93
+ resolved: z.string()
94
+ }))
95
+ })
96
+ });
97
+ export { designSystemOptions, designSystemReport };
@@ -1,158 +1,108 @@
1
+ import { loadWorkspaceManifest, manifestFingerprint, manifestMetadata, requireWorkspaceManifest } from "./project.js";
1
2
  import { createMCPTextDocument } from "./document.js";
2
- import { getErrorMessage } from "./result.js";
3
3
  import { summarizeManifest } from "./manifest-summary.js";
4
- import { readFile } from "node:fs/promises";
5
4
  import { basename } from "node:path";
6
- import { collectCSSDirectiveRanges } from "@master/css-lexer";
7
- import { compileCSSManifest, compileCSSManifestFile } from "@master/css-compiler";
8
- //#region src/directives.ts
9
- const DIRECTIVE_INSPECTION_VERSION = 1;
5
+ import { readFile } from "node:fs/promises";
6
+ import { compileManifestFileSync, compileManifestSync, inspectCSSSync } from "@master/css-compiler/node";
7
+ // src/directives.ts
8
+ const DIRECTIVE_INSPECTION_VERSION = 2;
10
9
  function createDirectiveEntries(content, filePath) {
11
10
  const document = createMCPTextDocument(filePath, content);
12
- return collectCSSDirectiveRanges(content).map((directive) => ({
11
+ return inspectCSSSync(content).directives.map((directive) => ({
13
12
  name: directive.name,
14
- range: {
15
- start: directive.start,
16
- end: directive.end
17
- },
13
+ range: directive.range,
18
14
  loc: {
19
- start: document.positionAt(directive.start),
20
- end: document.positionAt(directive.end)
15
+ start: document.positionAt(directive.range.start),
16
+ end: document.positionAt(directive.range.end)
21
17
  },
22
18
  prelude: content.slice(directive.preludeRange.start, directive.preludeRange.end).trim(),
23
- hasBlock: Boolean(directive.blockRange),
24
- quotedStrings: directive.quotedStringRanges.length
19
+ hasBlock: directive.hasBlock,
20
+ quotedStrings: directive.quotedStrings
25
21
  }));
26
22
  }
27
- function countObjectKeys(value) {
28
- return value && typeof value === "object" ? Object.keys(value).length : 0;
29
- }
30
- function summarizeManifestInput(input) {
31
- const manifestInput = input && typeof input === "object" ? input : {};
32
- return {
33
- keys: Object.keys(manifestInput),
34
- counts: {
35
- settings: countObjectKeys(manifestInput.settings),
36
- variables: countObjectKeys(manifestInput.variables),
37
- utilities: Array.isArray(manifestInput.utilities) ? manifestInput.utilities.length : countObjectKeys(manifestInput.utilities),
38
- variants: Array.isArray(manifestInput.variants) ? manifestInput.variants.length : countObjectKeys(manifestInput.variants),
39
- conditions: countObjectKeys(manifestInput.conditions),
40
- selectors: countObjectKeys(manifestInput.selectors),
41
- animations: countObjectKeys(manifestInput.animations)
42
- }
43
- };
44
- }
45
23
  function summarizeCompileResult(result) {
46
- const styleDefinitions = result.directives.styleDefinitions ?? [];
24
+ const warnings = result.diagnostics.filter((diagnostic) => diagnostic.severity === "warning").map((diagnostic) => diagnostic.message);
47
25
  return {
48
26
  manifest: summarizeManifest(result.manifest),
49
27
  directives: {
50
- manifestInput: summarizeManifestInput(result.directives.manifestInput),
28
+ manifestInput: result.directiveSummary.manifestInput,
51
29
  classNames: result.classNames,
52
30
  nativeClassNames: result.nativeClassNames,
53
- styleDefinitions: styleDefinitions.length,
54
- extractionPolicy: result.extractionPolicy
31
+ styleDefinitions: result.directiveSummary.styleDefinitions,
32
+ extractionPolicy: result.directiveSummary.extractionPolicy
55
33
  },
56
34
  css: {
57
- bytes: result.css.length,
58
- nativeBytes: result.nativeCSS.length,
59
- generatedBytes: result.generatedCSS.length
35
+ bytes: Buffer.byteLength(result.css, "utf8"),
36
+ nativeBytes: Buffer.byteLength(result.nativeCSS, "utf8"),
37
+ generatedBytes: Buffer.byteLength(result.generatedCSS, "utf8")
60
38
  },
61
39
  dependencies: result.dependencies,
62
- warnings: result.warnings
40
+ warnings,
41
+ diagnostics: result.diagnostics
63
42
  };
64
43
  }
65
44
  async function compileDirectives(context, options) {
45
+ const manifest = await loadWorkspaceManifest(context, options.context, options.entryPath ? [await context.resolveExistingFile(options.entryPath)] : void 0);
46
+ const baseManifest = requireWorkspaceManifest(manifest);
66
47
  if (options.entryPath) {
67
48
  const filePath = await context.resolveExistingFile(options.entryPath);
68
- const [content, result] = await Promise.all([readFile(filePath, "utf8"), Promise.resolve(compileCSSManifestFile(filePath, {
49
+ const [content, result] = await Promise.all([readFile(filePath, "utf8"), Promise.resolve(compileManifestFileSync(filePath, {
69
50
  root: context.root,
51
+ baseManifest,
70
52
  preserveNativeCSS: options.preserveNativeCSS
71
53
  }))]);
72
54
  return {
73
55
  filePath,
74
56
  content,
75
- result
57
+ result,
58
+ context: manifestMetadata(manifest)
76
59
  };
77
60
  }
78
61
  if (options.content === void 0) throw new Error("Either entryPath or content is required.");
79
62
  const filePath = context.resolveVirtualPath(options.filePath || "master.css");
80
- const result = compileCSSManifest(options.content, {
81
- root: context.root,
63
+ const result = compileManifestSync(options.content, {
64
+ baseManifest,
82
65
  from: filePath,
83
66
  preserveNativeCSS: options.preserveNativeCSS
84
67
  });
85
68
  return {
86
69
  filePath,
87
70
  content: options.content,
71
+ context: manifestMetadata(manifest),
88
72
  result
89
73
  };
90
74
  }
91
75
  async function inspectDirectives(context, options) {
92
- try {
93
- const compiled = await compileDirectives(context, options);
94
- const inspection = summarizeCompileResult(compiled.result);
95
- const directiveEntries = createDirectiveEntries(compiled.content, compiled.filePath);
96
- return {
97
- version: DIRECTIVE_INSPECTION_VERSION,
98
- root: context.root,
76
+ const compiled = await compileDirectives(context, options);
77
+ const inspection = summarizeCompileResult(compiled.result);
78
+ const directiveEntries = createDirectiveEntries(compiled.content, compiled.filePath);
79
+ return {
80
+ version: DIRECTIVE_INSPECTION_VERSION,
81
+ root: context.root,
82
+ context: compiled.context,
83
+ status: inspection.warnings.length ? "warning" : "ok",
84
+ input: {
85
+ filePath: compiled.filePath,
86
+ name: basename(compiled.filePath),
87
+ mode: options.entryPath ? "entry" : "content"
88
+ },
89
+ directiveEntries,
90
+ ...inspection,
91
+ manifest: {
92
+ ...inspection.manifest,
93
+ fingerprint: manifestFingerprint(compiled.result.manifest),
94
+ languageVersion: compiled.result.manifest.languageVersion
95
+ },
96
+ diagnostics: inspection.diagnostics,
97
+ summary: {
99
98
  status: inspection.warnings.length ? "warning" : "ok",
100
- input: {
101
- filePath: compiled.filePath,
102
- name: basename(compiled.filePath),
103
- mode: options.entryPath ? "entry" : "content"
104
- },
105
- directiveEntries,
106
- ...inspection,
107
- diagnostics: inspection.warnings.map((warning) => ({
108
- code: "compiler-warning",
109
- severity: "warning",
110
- message: warning,
111
- source: "Master CSS",
112
- sourceKind: "directive",
113
- filePath: compiled.filePath
114
- })),
115
- summary: {
116
- status: inspection.warnings.length ? "warning" : "ok",
117
- directives: directiveEntries.length,
118
- classNames: inspection.directives.classNames.length,
119
- nativeClassNames: inspection.directives.nativeClassNames.length,
120
- dependencies: inspection.dependencies.length,
121
- warnings: inspection.warnings.length,
122
- cssBytes: inspection.css.bytes
123
- }
124
- };
125
- } catch (error) {
126
- const filePath = options.entryPath || options.filePath || "master.css";
127
- return {
128
- version: DIRECTIVE_INSPECTION_VERSION,
129
- root: context.root,
130
- status: "error",
131
- input: {
132
- filePath,
133
- mode: options.entryPath ? "entry" : "content"
134
- },
135
- directiveEntries: options.content ? createDirectiveEntries(options.content, context.resolveVirtualPath(options.filePath || "master.css")) : [],
136
- diagnostics: [{
137
- code: "directive-inspection-error",
138
- severity: "error",
139
- message: getErrorMessage(error),
140
- source: "Master CSS",
141
- sourceKind: "directive",
142
- filePath
143
- }],
144
- summary: {
145
- status: "error",
146
- directives: 0,
147
- classNames: 0,
148
- nativeClassNames: 0,
149
- dependencies: 0,
150
- warnings: 0,
151
- errors: 1,
152
- cssBytes: 0
153
- }
154
- };
155
- }
99
+ directives: directiveEntries.length,
100
+ classNames: inspection.directives.classNames.length,
101
+ nativeClassNames: inspection.directives.nativeClassNames.length,
102
+ dependencies: inspection.dependencies.length,
103
+ warnings: inspection.warnings.length,
104
+ cssBytes: inspection.css.bytes
105
+ }
106
+ };
156
107
  }
157
- //#endregion
158
108
  export { inspectDirectives };