@spacefast/common 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contracts/activity.d.ts +1 -1
- package/dist/contracts/activity.js +11 -6
- package/dist/contracts/annotations.d.ts +2 -0
- package/dist/contracts/annotations.js +2 -1
- package/dist/contracts/api-keys.d.ts +4 -0
- package/dist/contracts/api-keys.js +4 -0
- package/dist/contracts/archives.d.ts +2 -8
- package/dist/contracts/archives.js +3 -8
- package/dist/contracts/builds.d.ts +1 -0
- package/dist/contracts/builds.js +5 -0
- package/dist/contracts/comments.d.ts +309 -0
- package/dist/contracts/comments.js +200 -0
- package/dist/contracts/device-auth.d.ts +221 -1
- package/dist/contracts/device-auth.js +106 -4
- package/dist/contracts/device-team-scope.d.ts +10 -0
- package/dist/contracts/device-team-scope.js +17 -0
- package/dist/contracts/error-code-meta.d.ts +52 -0
- package/dist/contracts/error-code-meta.js +13 -0
- package/dist/contracts/error-codes.d.ts +1 -1
- package/dist/contracts/error-codes.js +13 -0
- package/dist/contracts/features.d.ts +37 -38
- package/dist/contracts/features.js +51 -59
- package/dist/contracts/generated-feature-launch-entries.d.ts +2 -2
- package/dist/contracts/generated-feature-launch-entries.js +6 -6
- package/dist/contracts/ids.d.ts +1 -1
- package/dist/contracts/ids.js +1 -1
- package/dist/contracts/oauth-resources.d.ts +7 -0
- package/dist/contracts/oauth-resources.js +10 -2
- package/dist/contracts/operations.d.ts +1 -3
- package/dist/contracts/operations.js +5 -1
- package/dist/contracts/pages.d.ts +70 -0
- package/dist/contracts/pages.js +89 -0
- package/dist/contracts/publishes.d.ts +5 -0
- package/dist/contracts/publishes.js +25 -8
- package/dist/contracts/resources.d.ts +14 -62
- package/dist/contracts/runtime-api.d.ts +13 -15
- package/dist/contracts/runtime-api.js +12 -70
- package/dist/contracts/space-config.d.ts +32 -90
- package/dist/contracts/space-config.js +49 -54
- package/dist/contracts/spaces.d.ts +47 -187
- package/dist/contracts/spaces.js +19 -3
- package/dist/contracts/superadmin-spaces.d.ts +14 -62
- package/dist/contracts/superadmin-teams.d.ts +79 -0
- package/dist/contracts/superadmin-teams.js +36 -0
- package/dist/contracts/superadmin.d.ts +2 -0
- package/dist/contracts/superadmin.js +1 -0
- package/dist/contracts/teams.d.ts +1 -0
- package/dist/contracts/teams.js +8 -0
- package/dist/contracts/theme-json.js +4 -5
- package/dist/dashboard-paths/index.d.ts +31 -0
- package/dist/dashboard-paths/index.js +80 -0
- package/dist/docs/agent-handoff-document.d.ts +15 -0
- package/dist/docs/agent-handoff-document.js +179 -0
- package/dist/docs/agent-setup.d.ts +12 -1
- package/dist/docs/agent-setup.js +30 -16
- package/dist/docs/catalog.d.ts +2 -2
- package/dist/docs/catalog.js +2 -2
- package/dist/docs/error-docs.js +52 -0
- package/dist/utils/asset-fingerprint.d.ts +53 -0
- package/dist/utils/asset-fingerprint.js +574 -0
- package/dist/utils/credential-policy.d.ts +5 -0
- package/dist/utils/credential-policy.js +31 -8
- package/dist/utils/pages.d.ts +53 -0
- package/dist/utils/pages.js +274 -0
- package/dist/utils/query-keys.d.ts +4 -3
- package/dist/utils/query-keys.js +4 -3
- package/dist/utils/space-config.d.ts +2 -2
- package/dist/utils/space-config.js +1 -1
- package/dist/utils/wpcom-auth-redirects.d.ts +0 -4
- package/dist/utils/wpcom-auth-redirects.js +0 -6
- package/dist/vocabulary.d.ts +2 -2
- package/package.json +6 -1
- package/dist/contracts/space-theme.d.ts +0 -25
- package/dist/contracts/space-theme.js +0 -49
- package/dist/utils/gate-theme.d.ts +0 -61
- package/dist/utils/gate-theme.js +0 -217
- package/dist/utils/space-theme.d.ts +0 -18
- package/dist/utils/space-theme.js +0 -98
package/dist/utils/gate-theme.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { sfThemeJsoncSchema } from "../contracts/space-config.js";
|
|
2
|
-
import { themeJsonSchema } from "../contracts/theme-json.js";
|
|
3
|
-
import { stripJsonComments } from "./space-config.js";
|
|
4
|
-
import { isSafeThemeColor, isSafeThemeFontFamily } from "./space-theme.js";
|
|
5
|
-
/** Bound on the raw `theme.json` / `sf.theme.jsonc` file size at finalize. */
|
|
6
|
-
export const GATE_THEME_FILE_MAX_BYTES = 64 * 1024;
|
|
7
|
-
/** Bound on the compiled additive CSS custom-property block. */
|
|
8
|
-
export const GATE_THEME_VARS_MAX_BYTES = 8 * 1024;
|
|
9
|
-
/**
|
|
10
|
-
* Parses a `theme.json` file's `settings.color.palette` /
|
|
11
|
-
* `settings.typography.fontFamilies` into gate-page tokens (accent/background
|
|
12
|
-
* derived from conventionally-named slugs: `accent`|`primary`, `background`)
|
|
13
|
-
* plus a full CSS custom-property block for every safe palette/font-family
|
|
14
|
-
* entry. Any problem (oversized, invalid JSON, invalid shape) warns and
|
|
15
|
-
* yields an empty result — the next tier down still applies.
|
|
16
|
-
*/
|
|
17
|
-
export function parseThemeJsonFile(raw) {
|
|
18
|
-
const empty = { theme: {}, themeVars: null, diagnostics: [] };
|
|
19
|
-
if (Buffer.byteLength(raw) > GATE_THEME_FILE_MAX_BYTES) {
|
|
20
|
-
return {
|
|
21
|
-
...empty,
|
|
22
|
-
diagnostics: [
|
|
23
|
-
{
|
|
24
|
-
severity: "warning",
|
|
25
|
-
code: "theme_json_too_large",
|
|
26
|
-
message: `theme.json exceeds the ${GATE_THEME_FILE_MAX_BYTES} byte limit and was ignored.`,
|
|
27
|
-
path: "theme.json",
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
let candidate;
|
|
33
|
-
try {
|
|
34
|
-
candidate = JSON.parse(raw);
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
return {
|
|
38
|
-
...empty,
|
|
39
|
-
diagnostics: [
|
|
40
|
-
{
|
|
41
|
-
severity: "warning",
|
|
42
|
-
code: "theme_json_invalid",
|
|
43
|
-
message: `theme.json is not valid JSON: ${error instanceof Error ? error.message : "parse error"}.`,
|
|
44
|
-
path: "theme.json",
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
const parsed = themeJsonSchema.safeParse(candidate);
|
|
50
|
-
if (!parsed.success) {
|
|
51
|
-
return {
|
|
52
|
-
...empty,
|
|
53
|
-
diagnostics: [
|
|
54
|
-
{
|
|
55
|
-
severity: "warning",
|
|
56
|
-
code: "theme_json_invalid",
|
|
57
|
-
message: "theme.json does not match the supported settings.color.palette/settings.typography.fontFamilies shape.",
|
|
58
|
-
path: "theme.json",
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const diagnostics = [];
|
|
64
|
-
const declarations = [];
|
|
65
|
-
const theme = {};
|
|
66
|
-
const palette = parsed.data.settings?.color?.palette ?? [];
|
|
67
|
-
for (const entry of palette) {
|
|
68
|
-
if (!isSafeThemeColor(entry.color)) {
|
|
69
|
-
diagnostics.push({
|
|
70
|
-
severity: "warning",
|
|
71
|
-
code: "theme_json_value_invalid",
|
|
72
|
-
message: `theme.json settings.color.palette[slug=${entry.slug}] is not a safe color and was dropped.`,
|
|
73
|
-
path: `theme.json:settings.color.palette.${entry.slug}`,
|
|
74
|
-
});
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
declarations.push(`--wp--preset--color--${entry.slug}:${entry.color.trim()}`);
|
|
78
|
-
if (entry.slug === "accent" || entry.slug === "primary") {
|
|
79
|
-
theme.accent ??= entry.color.trim();
|
|
80
|
-
}
|
|
81
|
-
if (entry.slug === "background") {
|
|
82
|
-
theme.background = entry.color.trim();
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const fontFamilies = parsed.data.settings?.typography?.fontFamilies ?? [];
|
|
86
|
-
fontFamilies.forEach((entry, index) => {
|
|
87
|
-
if (!isSafeThemeFontFamily(entry.fontFamily)) {
|
|
88
|
-
diagnostics.push({
|
|
89
|
-
severity: "warning",
|
|
90
|
-
code: "theme_json_value_invalid",
|
|
91
|
-
message: `theme.json settings.typography.fontFamilies[slug=${entry.slug}] is not a safe font-family stack and was dropped.`,
|
|
92
|
-
path: `theme.json:settings.typography.fontFamilies.${entry.slug}`,
|
|
93
|
-
});
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
declarations.push(`--wp--preset--font-family--${entry.slug}:${entry.fontFamily.trim()}`);
|
|
97
|
-
if (index === 0) {
|
|
98
|
-
theme.fontFamily ??= entry.fontFamily.trim();
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
let themeVars = declarations.join(";");
|
|
102
|
-
while (Buffer.byteLength(themeVars) > GATE_THEME_VARS_MAX_BYTES && declarations.length > 0) {
|
|
103
|
-
declarations.pop();
|
|
104
|
-
diagnostics.push({
|
|
105
|
-
severity: "warning",
|
|
106
|
-
code: "theme_json_value_invalid",
|
|
107
|
-
message: `theme.json compiled CSS exceeds ${GATE_THEME_VARS_MAX_BYTES} bytes; trailing tokens were dropped.`,
|
|
108
|
-
path: "theme.json",
|
|
109
|
-
});
|
|
110
|
-
themeVars = declarations.join(";");
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
theme,
|
|
114
|
-
themeVars: themeVars.length > 0 ? themeVars : null,
|
|
115
|
-
diagnostics,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Parses the `sf.theme.jsonc` escape hatch: same JSONC tolerance and the same
|
|
120
|
-
* validated token grammar as `spacefast.jsonc "pages.theme"`
|
|
121
|
-
* (`spacePagesThemeSchema`), just from a dedicated file. Any problem warns
|
|
122
|
-
* and yields an empty result.
|
|
123
|
-
*/
|
|
124
|
-
export function parseSfThemeJsonc(raw) {
|
|
125
|
-
if (Buffer.byteLength(raw) > GATE_THEME_FILE_MAX_BYTES) {
|
|
126
|
-
return {
|
|
127
|
-
theme: {},
|
|
128
|
-
diagnostics: [
|
|
129
|
-
{
|
|
130
|
-
severity: "warning",
|
|
131
|
-
code: "sf_theme_jsonc_too_large",
|
|
132
|
-
message: `sf.theme.jsonc exceeds the ${GATE_THEME_FILE_MAX_BYTES} byte limit and was ignored.`,
|
|
133
|
-
path: "sf.theme.jsonc",
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
let candidate;
|
|
139
|
-
try {
|
|
140
|
-
candidate = JSON.parse(stripJsonComments(raw));
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
return {
|
|
144
|
-
theme: {},
|
|
145
|
-
diagnostics: [
|
|
146
|
-
{
|
|
147
|
-
severity: "warning",
|
|
148
|
-
code: "sf_theme_jsonc_invalid",
|
|
149
|
-
message: `sf.theme.jsonc is not valid JSONC: ${error instanceof Error ? error.message : "parse error"}.`,
|
|
150
|
-
path: "sf.theme.jsonc",
|
|
151
|
-
},
|
|
152
|
-
],
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
const parsed = sfThemeJsoncSchema.safeParse(candidate);
|
|
156
|
-
if (!parsed.success) {
|
|
157
|
-
return {
|
|
158
|
-
theme: {},
|
|
159
|
-
diagnostics: [
|
|
160
|
-
{
|
|
161
|
-
severity: "warning",
|
|
162
|
-
code: "sf_theme_jsonc_invalid",
|
|
163
|
-
message: "sf.theme.jsonc does not match the gate-page theme token shape.",
|
|
164
|
-
path: "sf.theme.jsonc",
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
return { theme: parsed.data, diagnostics: [] };
|
|
170
|
-
}
|
|
171
|
-
function pickDefined(target, source) {
|
|
172
|
-
for (const key of ["accent", "background", "logo", "name", "fontFamily"]) {
|
|
173
|
-
const value = source[key];
|
|
174
|
-
if (value !== undefined) {
|
|
175
|
-
target[key] = value;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Compiles the full tier-3 cascade into the flat token shape the runtime
|
|
181
|
-
* already reads. `base` is the existing free-tier `spacefast.jsonc
|
|
182
|
-
* "pages.theme"` (already validated by `spaceConfigSchema` upstream — passed
|
|
183
|
-
* through as-is). `sf.theme.jsonc` only applies when `advancedThemingEntitled`
|
|
184
|
-
* is true; when it is present but NOT entitled, the tier is skipped with an
|
|
185
|
-
* info diagnostic (fail-safe by omission — the compiled artifact simply
|
|
186
|
-
* reflects the lower, entitled tiers, per access-plan §9).
|
|
187
|
-
*/
|
|
188
|
-
export function mergeGateTheme(input) {
|
|
189
|
-
const diagnostics = [];
|
|
190
|
-
const merged = {};
|
|
191
|
-
if (input.base) {
|
|
192
|
-
pickDefined(merged, input.base);
|
|
193
|
-
}
|
|
194
|
-
let themeVars = null;
|
|
195
|
-
if (input.themeJsonRaw !== null) {
|
|
196
|
-
const parsed = parseThemeJsonFile(input.themeJsonRaw);
|
|
197
|
-
diagnostics.push(...parsed.diagnostics);
|
|
198
|
-
pickDefined(merged, parsed.theme);
|
|
199
|
-
themeVars = parsed.themeVars;
|
|
200
|
-
}
|
|
201
|
-
if (input.sfThemeJsoncRaw !== null) {
|
|
202
|
-
if (!input.advancedThemingEntitled) {
|
|
203
|
-
diagnostics.push({
|
|
204
|
-
severity: "info",
|
|
205
|
-
code: "sf_theme_jsonc_not_entitled",
|
|
206
|
-
message: "sf.theme.jsonc is a paid (advanced theming) tier; this plan is not entitled, so it was ignored.",
|
|
207
|
-
path: "sf.theme.jsonc",
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
const parsed = parseSfThemeJsonc(input.sfThemeJsoncRaw);
|
|
212
|
-
diagnostics.push(...parsed.diagnostics);
|
|
213
|
-
pickDefined(merged, parsed.theme);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return { theme: merged, themeVars, diagnostics };
|
|
217
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { SpaceTheme } from "../contracts/space-theme.js";
|
|
2
|
-
export type SpaceThemeWarning = {
|
|
3
|
-
severity: "warning";
|
|
4
|
-
code: "theme_value_invalid";
|
|
5
|
-
message: string;
|
|
6
|
-
/** JSON-path-lite pointer into the theme shape. */
|
|
7
|
-
path: string;
|
|
8
|
-
};
|
|
9
|
-
export type CompiledSpaceTheme = {
|
|
10
|
-
/** CSS custom-property declarations (no selector), or null when empty. */
|
|
11
|
-
css: string | null;
|
|
12
|
-
warnings: SpaceThemeWarning[];
|
|
13
|
-
};
|
|
14
|
-
/** Engine-enforced ceiling for the compiled declaration block. */
|
|
15
|
-
export declare const SPACE_THEME_CSS_MAX_BYTES: number;
|
|
16
|
-
export declare function isSafeThemeColor(value: string): boolean;
|
|
17
|
-
export declare function isSafeThemeFontFamily(value: string): boolean;
|
|
18
|
-
export declare function compileSpaceTheme(theme: SpaceTheme | null | undefined): CompiledSpaceTheme;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/** Engine-enforced ceiling for the compiled declaration block. */
|
|
2
|
-
export const SPACE_THEME_CSS_MAX_BYTES = 16 * 1024;
|
|
3
|
-
// Categorically forbidden anywhere in a value: network reach, style escape,
|
|
4
|
-
// markup injection. Mirrors the runtime's defense-in-depth re-check.
|
|
5
|
-
const FORBIDDEN_VALUE_PATTERN = /url\s*\(|@import|expression\s*\(|data:|[<>{};\\]|\/\*|\*\//i;
|
|
6
|
-
const COLOR_PATTERN = new RegExp([
|
|
7
|
-
"^(?:",
|
|
8
|
-
"#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})",
|
|
9
|
-
"|rgba?\\([0-9.,\\s%/]{1,64}\\)",
|
|
10
|
-
"|hsla?\\([0-9.,\\s%deg/]{1,64}\\)",
|
|
11
|
-
"|[a-zA-Z]{3,30}", // CSS named colors (transparent, currentColor, rebeccapurple, ...)
|
|
12
|
-
"|var\\(--wp--preset--color--[a-z0-9-]{1,64}\\)",
|
|
13
|
-
")$",
|
|
14
|
-
].join(""));
|
|
15
|
-
const SIZE_PATTERN = new RegExp([
|
|
16
|
-
"^(?:",
|
|
17
|
-
"-?\\d{1,5}(?:\\.\\d{1,4})?(?:px|rem|em|%|vw|vh|vmin|vmax|pt|ch|ex)?",
|
|
18
|
-
"|var\\(--wp--preset--(?:font-size|spacing)--[a-z0-9-]{1,64}\\)",
|
|
19
|
-
")$",
|
|
20
|
-
].join(""));
|
|
21
|
-
// Font family stacks: platform-provided or validated-generic family names
|
|
22
|
-
// only — letters, digits, spaces, commas, hyphens, straight quotes. No src.
|
|
23
|
-
const FONT_FAMILY_PATTERN = /^[A-Za-z0-9 ,'"-]{1,256}$/;
|
|
24
|
-
function safeValue(value, pattern) {
|
|
25
|
-
const trimmed = value.trim();
|
|
26
|
-
return trimmed.length > 0 && !FORBIDDEN_VALUE_PATTERN.test(trimmed) && pattern.test(trimmed);
|
|
27
|
-
}
|
|
28
|
-
// Exported so other compilers that consume the same preset grammar (the gate-page
|
|
29
|
-
// theme cascade's `theme.json`/`sf.theme.jsonc` tiers, access-plan §8) reuse this
|
|
30
|
-
// ONE allowlist instead of re-deriving it — same posture, same forbidden set.
|
|
31
|
-
export function isSafeThemeColor(value) {
|
|
32
|
-
return safeValue(value, COLOR_PATTERN);
|
|
33
|
-
}
|
|
34
|
-
export function isSafeThemeFontFamily(value) {
|
|
35
|
-
return safeValue(value, FONT_FAMILY_PATTERN);
|
|
36
|
-
}
|
|
37
|
-
export function compileSpaceTheme(theme) {
|
|
38
|
-
if (!theme) {
|
|
39
|
-
return { css: null, warnings: [] };
|
|
40
|
-
}
|
|
41
|
-
const declarations = [];
|
|
42
|
-
const warnings = [];
|
|
43
|
-
const drop = (path) => {
|
|
44
|
-
warnings.push({
|
|
45
|
-
severity: "warning",
|
|
46
|
-
code: "theme_value_invalid",
|
|
47
|
-
message: `Theme value at ${path} is not a safe preset token and was dropped.`,
|
|
48
|
-
path,
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
theme.color?.palette?.forEach((entry, index) => {
|
|
52
|
-
if (safeValue(entry.color, COLOR_PATTERN)) {
|
|
53
|
-
declarations.push(`--wp--preset--color--${entry.slug}:${entry.color.trim()}`);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
drop(`theme.color.palette[${index}].color`);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
theme.typography?.fontSizes?.forEach((entry, index) => {
|
|
60
|
-
if (safeValue(entry.size, SIZE_PATTERN)) {
|
|
61
|
-
declarations.push(`--wp--preset--font-size--${entry.slug}:${entry.size.trim()}`);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
drop(`theme.typography.fontSizes[${index}].size`);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
const fontFamily = theme.typography?.fontFamily;
|
|
68
|
-
if (fontFamily !== undefined) {
|
|
69
|
-
if (safeValue(fontFamily, FONT_FAMILY_PATTERN)) {
|
|
70
|
-
declarations.push(`--sf--font-family:${fontFamily.trim()}`);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
drop("theme.typography.fontFamily");
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
theme.spacing?.spacingScale?.forEach((entry, index) => {
|
|
77
|
-
if (safeValue(entry.size, SIZE_PATTERN)) {
|
|
78
|
-
declarations.push(`--wp--preset--spacing--${entry.slug}:${entry.size.trim()}`);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
drop(`theme.spacing.spacingScale[${index}].size`);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
// Bounded output: drop trailing declarations past the engine ceiling with a
|
|
85
|
-
// warning instead of failing the version.
|
|
86
|
-
let css = declarations.join(";");
|
|
87
|
-
while (css.length > SPACE_THEME_CSS_MAX_BYTES && declarations.length > 0) {
|
|
88
|
-
declarations.pop();
|
|
89
|
-
warnings.push({
|
|
90
|
-
severity: "warning",
|
|
91
|
-
code: "theme_value_invalid",
|
|
92
|
-
message: `Compiled theme exceeds ${SPACE_THEME_CSS_MAX_BYTES} bytes; trailing tokens were dropped.`,
|
|
93
|
-
path: "theme",
|
|
94
|
-
});
|
|
95
|
-
css = declarations.join(";");
|
|
96
|
-
}
|
|
97
|
-
return { css: css.length > 0 ? css : null, warnings };
|
|
98
|
-
}
|