@salty-css/core 0.1.0-refactor-add-additional-paths-to-config-cache.1 → 0.1.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.
- package/README.md +355 -374
- package/bin/main.cjs +57 -58
- package/bin/main.js +1 -2
- package/{class-name-generator-CMWY5KTJ.js → class-name-generator-CUEoPowv.js} +18 -4
- package/{class-name-generator-DB5aQwC_.cjs → class-name-generator-MtPkBfM_.cjs} +19 -5
- package/compiler/helpers.cjs +10 -2
- package/compiler/helpers.d.ts +3 -2
- package/compiler/helpers.js +11 -3
- package/compiler/resolve-import.d.ts +17 -0
- package/compiler/salty-compiler.cjs +144 -33
- package/compiler/salty-compiler.d.ts +2 -5
- package/compiler/salty-compiler.js +149 -38
- package/config/index.cjs +4 -0
- package/config/index.js +5 -1
- package/css/index.cjs +0 -4
- package/css/index.d.ts +0 -1
- package/css/index.js +0 -4
- package/css/keyframes.cjs +2 -2
- package/css/keyframes.js +2 -2
- package/factories/define-font.d.ts +28 -0
- package/factories/define-import.d.ts +14 -0
- package/factories/index.cjs +140 -0
- package/factories/index.d.ts +2 -0
- package/factories/index.js +140 -0
- package/generators/index.cjs +3 -3
- package/generators/index.js +3 -3
- package/helpers/color.d.ts +6 -0
- package/instances/classname-instance.cjs +1 -1
- package/instances/classname-instance.js +1 -1
- package/package.json +1 -13
- package/{parse-styles-C54MOrPg.cjs → parse-styles-BbI-2wdn.cjs} +196 -11
- package/{parse-styles-CLMTHo2H.js → parse-styles-BgVqQAni.js} +196 -11
- package/parsers/index.cjs +93 -5
- package/parsers/index.js +97 -9
- package/parsers/parse-templates.d.ts +10 -0
- package/parsers/parser-regexes.d.ts +1 -0
- package/parsers/resolve-template-variants.d.ts +21 -0
- package/runtime/index.cjs +16 -3
- package/runtime/index.d.ts +7 -0
- package/runtime/index.js +16 -3
- package/{to-hash-DAN2LcHK.js → to-hash-DSoCPs8D.js} +8 -0
- package/{to-hash-C05Y906F.cjs → to-hash-DT2ImSPA.cjs} +8 -0
- package/types/config-types.d.ts +33 -2
- package/types/font-types.d.ts +53 -0
- package/util/index.cjs +3 -4
- package/util/index.js +1 -2
- package/util/module-type.d.ts +1 -1
- package/cache/resolve-dynamic-config-cache.cjs +0 -64
- package/cache/resolve-dynamic-config-cache.d.ts +0 -20
- package/cache/resolve-dynamic-config-cache.js +0 -64
- package/compiler/copy-config-cache.cjs +0 -39
- package/compiler/copy-config-cache.d.ts +0 -17
- package/compiler/copy-config-cache.js +0 -39
- package/css/dynamic-styles.cjs +0 -28
- package/css/dynamic-styles.d.ts +0 -49
- package/css/dynamic-styles.js +0 -28
- package/dash-case-DIwKaYgE.cjs +0 -9
- package/dash-case-DblXvymC.js +0 -10
- package/logger-7xz0pyAz.cjs +0 -12
- package/logger-hHmCwThj.js +0 -13
|
@@ -5,17 +5,16 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
6
|
const esbuild = require("esbuild");
|
|
7
7
|
const path = require("path");
|
|
8
|
-
const
|
|
8
|
+
const winston = require("winston");
|
|
9
9
|
const promises = require("fs/promises");
|
|
10
10
|
const fs = require("fs");
|
|
11
11
|
const child_process = require("child_process");
|
|
12
12
|
const compiler_helpers = require("./helpers.cjs");
|
|
13
|
+
const toHash = require("../to-hash-DT2ImSPA.cjs");
|
|
13
14
|
const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const parseStyles = require("../parse-styles-C54MOrPg.cjs");
|
|
15
|
+
const module$1 = require("module");
|
|
16
|
+
const parseStyles = require("../parse-styles-BbI-2wdn.cjs");
|
|
17
17
|
const css_merge = require("../css/merge.cjs");
|
|
18
|
-
require("../css/dynamic-styles.cjs");
|
|
19
18
|
const compiler_getFiles = require("./get-files.cjs");
|
|
20
19
|
const parsers_index = require("../parsers/index.cjs");
|
|
21
20
|
const console = require("console");
|
|
@@ -37,6 +36,62 @@ function _interopNamespaceDefault(e) {
|
|
|
37
36
|
return Object.freeze(n);
|
|
38
37
|
}
|
|
39
38
|
const esbuild__namespace = /* @__PURE__ */ _interopNamespaceDefault(esbuild);
|
|
39
|
+
const logger = winston.createLogger({
|
|
40
|
+
level: "debug",
|
|
41
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.cli()),
|
|
42
|
+
transports: [new winston.transports.Console({})]
|
|
43
|
+
});
|
|
44
|
+
const logError = (message) => {
|
|
45
|
+
logger.error(message);
|
|
46
|
+
};
|
|
47
|
+
const EXTERNAL_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i;
|
|
48
|
+
const normaliseSpec = (spec) => {
|
|
49
|
+
if (typeof spec === "string") return { url: spec };
|
|
50
|
+
return spec;
|
|
51
|
+
};
|
|
52
|
+
const ensureRelativePrefix = (path2) => {
|
|
53
|
+
if (path2.startsWith(".") || path2.startsWith("/")) return path2;
|
|
54
|
+
return `./${path2}`;
|
|
55
|
+
};
|
|
56
|
+
const toPosix = (path2) => path2.split("\\").join("/");
|
|
57
|
+
const defaultResolveModule = (specifier, sourceFile) => {
|
|
58
|
+
return module$1.createRequire(sourceFile).resolve(specifier);
|
|
59
|
+
};
|
|
60
|
+
const defaultCopyAsset = (from, to) => {
|
|
61
|
+
const dir = path.dirname(to);
|
|
62
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
fs.copyFileSync(from, to);
|
|
64
|
+
};
|
|
65
|
+
const buildRule = (url, { media, supports }) => {
|
|
66
|
+
let rule = `@import url('${url}')`;
|
|
67
|
+
if (supports) rule += ` supports(${supports})`;
|
|
68
|
+
if (media) rule += ` ${media}`;
|
|
69
|
+
return `${rule};`;
|
|
70
|
+
};
|
|
71
|
+
const resolveImport = (spec, sourceFile, destDir, options = {}) => {
|
|
72
|
+
const opts = normaliseSpec(spec);
|
|
73
|
+
const { url } = opts;
|
|
74
|
+
const resolveModule = options.resolveModule ?? defaultResolveModule;
|
|
75
|
+
const copyAsset = options.copyAsset ?? defaultCopyAsset;
|
|
76
|
+
if (EXTERNAL_URL.test(url)) {
|
|
77
|
+
return { rule: buildRule(url, opts) };
|
|
78
|
+
}
|
|
79
|
+
if (url.startsWith("/")) {
|
|
80
|
+
return { rule: buildRule(url, opts) };
|
|
81
|
+
}
|
|
82
|
+
if (url.startsWith("./") || url.startsWith("../")) {
|
|
83
|
+
const absolute2 = path.resolve(path.dirname(sourceFile), url);
|
|
84
|
+
const fromImportsFile = path.relative(path.join(destDir, "css"), absolute2);
|
|
85
|
+
return { rule: buildRule(ensureRelativePrefix(toPosix(fromImportsFile)), opts) };
|
|
86
|
+
}
|
|
87
|
+
const specifier = url.startsWith("~") ? url.slice(1) : url;
|
|
88
|
+
const absolute = resolveModule(specifier, sourceFile);
|
|
89
|
+
const hash = toHash.toHash(absolute, 6);
|
|
90
|
+
const fileName = `${hash}-${path.basename(absolute)}`;
|
|
91
|
+
const destPath = path.join(destDir, "imports", fileName);
|
|
92
|
+
copyAsset(absolute, destPath);
|
|
93
|
+
return { rule: buildRule(`../imports/${fileName}`, opts) };
|
|
94
|
+
};
|
|
40
95
|
const readPackageJsonModule = async (dirname) => {
|
|
41
96
|
const packageJsonContent = await compiler_getFiles.getPackageJson(dirname);
|
|
42
97
|
if (!packageJsonContent) return void 0;
|
|
@@ -161,14 +216,6 @@ class SaltyCompiler {
|
|
|
161
216
|
this.cache.destDir = destDir;
|
|
162
217
|
return destDir;
|
|
163
218
|
});
|
|
164
|
-
/**
|
|
165
|
-
* Absolute path to the `config-cache.json` written during `generateCss()`.
|
|
166
|
-
* Plugins read this to copy the file into the production bundle output.
|
|
167
|
-
*/
|
|
168
|
-
__publicField(this, "getConfigCachePath", async () => {
|
|
169
|
-
const destDir = await this.getDestDir();
|
|
170
|
-
return path.join(destDir, "cache/config-cache.json");
|
|
171
|
-
});
|
|
172
219
|
__publicField(this, "generateConfig", async () => {
|
|
173
220
|
const rcProject = await this.getRCProjectConfig(this.projectRootDir);
|
|
174
221
|
const destDir = await this.getDestDir();
|
|
@@ -202,7 +249,8 @@ ${currentFile}`;
|
|
|
202
249
|
}
|
|
203
250
|
});
|
|
204
251
|
__publicField(this, "getConfigCache", async () => {
|
|
205
|
-
const
|
|
252
|
+
const destDir = await this.getDestDir();
|
|
253
|
+
const coreConfigDest = path.join(destDir, "cache/config-cache.json");
|
|
206
254
|
const contents = fs.readFileSync(coreConfigDest, "utf8");
|
|
207
255
|
if (!contents) throw new Error("Could not find config cache file");
|
|
208
256
|
return JSON.parse(contents);
|
|
@@ -220,8 +268,8 @@ ${currentFile}`;
|
|
|
220
268
|
__publicField(this, "generateCss", async (clean = true) => {
|
|
221
269
|
try {
|
|
222
270
|
const start = Date.now();
|
|
223
|
-
if (this.isProduction) logger.
|
|
224
|
-
else logger.
|
|
271
|
+
if (this.isProduction) logger.info("Generating CSS in production mode! 🔥");
|
|
272
|
+
else logger.info("Generating CSS in development mode! 🚀");
|
|
225
273
|
const globalCssFiles = [];
|
|
226
274
|
const cssFiles = [];
|
|
227
275
|
const destDir = await this.getDestDir();
|
|
@@ -233,6 +281,7 @@ ${currentFile}`;
|
|
|
233
281
|
fs.mkdirSync(path.join(destDir, "types"));
|
|
234
282
|
fs.mkdirSync(path.join(destDir, "js"));
|
|
235
283
|
fs.mkdirSync(path.join(destDir, "cache"));
|
|
284
|
+
fs.mkdirSync(path.join(destDir, "imports"));
|
|
236
285
|
};
|
|
237
286
|
if (clean) clearDistDir();
|
|
238
287
|
const files = /* @__PURE__ */ new Set();
|
|
@@ -342,13 +391,13 @@ ${currentFile}`;
|
|
|
342
391
|
const cssContent2 = localCssFile.map((file) => `@import url('./${file}');`).join("\n");
|
|
343
392
|
const hashName = toHash.toHash(src, 6);
|
|
344
393
|
const parsedPath = path.parse(src);
|
|
345
|
-
const dasherized =
|
|
394
|
+
const dasherized = toHash.dashCase(parsedPath.name);
|
|
346
395
|
const cssFile2 = path.join(destDir, `css/f_${dasherized}-${hashName}.css`);
|
|
347
396
|
fs.writeFileSync(cssFile2, cssContent2 || `/* Empty file */`);
|
|
348
397
|
});
|
|
349
398
|
}
|
|
350
399
|
const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
|
|
351
|
-
const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css"];
|
|
400
|
+
const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css", "_fonts.css"];
|
|
352
401
|
const importsWithData = globalCssFilenames.filter((file) => {
|
|
353
402
|
try {
|
|
354
403
|
const data = fs.readFileSync(path.join(destDir, "css", file), "utf8");
|
|
@@ -357,9 +406,12 @@ ${currentFile}`;
|
|
|
357
406
|
return false;
|
|
358
407
|
}
|
|
359
408
|
});
|
|
360
|
-
const globalImports = importsWithData.map((file) =>
|
|
409
|
+
const globalImports = importsWithData.map((file) => {
|
|
410
|
+
const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
|
|
411
|
+
return `@import url('./css/${file}')${layerSuffix};`;
|
|
412
|
+
});
|
|
361
413
|
const generatorText = "/*!\n * Generated with Salty CSS (https://salty-css.dev)\n * Do not edit this file directly\n */\n";
|
|
362
|
-
let cssContent = `${generatorText}@layer reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
414
|
+
let cssContent = `${generatorText}@layer imports, reset, global, templates, fonts, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
363
415
|
|
|
364
416
|
${globalImports.join(
|
|
365
417
|
"\n"
|
|
@@ -393,7 +445,7 @@ ${css}
|
|
|
393
445
|
const end = Date.now();
|
|
394
446
|
const time = end - start;
|
|
395
447
|
const emoji = time < 200 ? "🔥" : time < 500 ? "🚀" : time < 1e3 ? "🎉" : time < 2e3 ? "🚗" : time < 5e3 ? "🤔" : "🥴";
|
|
396
|
-
logger.
|
|
448
|
+
logger.info(`Generated CSS in ${time}ms! ${emoji}`);
|
|
397
449
|
} catch (e) {
|
|
398
450
|
console.error(e);
|
|
399
451
|
}
|
|
@@ -405,7 +457,9 @@ ${css}
|
|
|
405
457
|
mediaQueries: [],
|
|
406
458
|
globalStyles: [],
|
|
407
459
|
variables: [],
|
|
408
|
-
templates: []
|
|
460
|
+
templates: [],
|
|
461
|
+
imports: [],
|
|
462
|
+
fonts: []
|
|
409
463
|
};
|
|
410
464
|
await Promise.all(
|
|
411
465
|
[...configFiles].map(async (src) => {
|
|
@@ -415,6 +469,8 @@ ${css}
|
|
|
415
469
|
else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
|
|
416
470
|
else if (value.isDefineVariables) generationResults.variables.push(value);
|
|
417
471
|
else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
|
|
472
|
+
else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
|
|
473
|
+
else if (value.isDefineFont) generationResults.fonts.push(value);
|
|
418
474
|
});
|
|
419
475
|
})
|
|
420
476
|
);
|
|
@@ -433,10 +489,10 @@ ${css}
|
|
|
433
489
|
if (typeof value2 === "function") return await parseVariable(await value2());
|
|
434
490
|
if (typeof value2 === "object") return await parseVariables(value2, [...path2, key]);
|
|
435
491
|
const dottedKey = dotCase(key);
|
|
436
|
-
const dashedKey =
|
|
492
|
+
const dashedKey = toHash.dashCase(key);
|
|
437
493
|
const tsName = [...path2, dottedKey].join(".");
|
|
438
494
|
variableTokens.add(`"${tsName}"`);
|
|
439
|
-
const cssName = [...path2.map(
|
|
495
|
+
const cssName = [...path2.map(toHash.dashCase), dashedKey].join("-");
|
|
440
496
|
const result = parseStyles.parseVariableTokens(value2);
|
|
441
497
|
if (!result) return `--${cssName}: ${value2};`;
|
|
442
498
|
return `--${cssName}: ${result.transformed};`;
|
|
@@ -511,32 +567,85 @@ ${css}
|
|
|
511
567
|
const templates = css_merge.mergeObjects(config.templates, generationResults.templates);
|
|
512
568
|
const templateStylesString = await parsers_index.parseTemplates(templates);
|
|
513
569
|
const templateTokens = parsers_index.getTemplateTypes(templates);
|
|
570
|
+
const templateVariantMaps = parsers_index.getTemplateVariantMaps(templates);
|
|
514
571
|
fs.writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
|
|
515
572
|
configCacheContent.templates = templates;
|
|
573
|
+
const importsPath = path.join(destDir, "css/_imports.css");
|
|
574
|
+
const importRules = [];
|
|
575
|
+
for (const factory of generationResults.imports) {
|
|
576
|
+
const sourceFile = factory._path;
|
|
577
|
+
if (!sourceFile) continue;
|
|
578
|
+
for (const spec of factory._current) {
|
|
579
|
+
try {
|
|
580
|
+
const { rule } = resolveImport(spec, sourceFile, destDir);
|
|
581
|
+
importRules.push(rule);
|
|
582
|
+
} catch (e) {
|
|
583
|
+
const url = typeof spec === "string" ? spec : spec.url;
|
|
584
|
+
logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
fs.writeFileSync(importsPath, importRules.join("\n"));
|
|
516
589
|
const configTemplateFactories = config.templates ? [defineTemplates.defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
|
|
517
590
|
const templateFactories = css_merge.mergeFactories(generationResults.templates, configTemplateFactories);
|
|
518
591
|
configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
|
|
592
|
+
const fontsStylesPath = path.join(destDir, "css/_fonts.css");
|
|
593
|
+
if (generationResults.fonts.length === 0) {
|
|
594
|
+
fs.writeFileSync(fontsStylesPath, "");
|
|
595
|
+
} else {
|
|
596
|
+
const fontImports = [];
|
|
597
|
+
const fontBodies = [];
|
|
598
|
+
for (const font of generationResults.fonts) {
|
|
599
|
+
const { imports, body } = font._toCss();
|
|
600
|
+
fontImports.push(...imports);
|
|
601
|
+
fontBodies.push(body);
|
|
602
|
+
}
|
|
603
|
+
const importBlock = fontImports.length ? `${fontImports.join("\n")}
|
|
604
|
+
|
|
605
|
+
` : "";
|
|
606
|
+
fs.writeFileSync(fontsStylesPath, `${importBlock}@layer fonts { ${fontBodies.join(" ")} }`);
|
|
607
|
+
}
|
|
519
608
|
const tsTokensPath = path.join(destDir, "types/css-tokens.d.ts");
|
|
520
609
|
const tsVariableTokens = [...variableTokens].join("|");
|
|
610
|
+
const pascal = (str) => str.split(/[.\-_]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
611
|
+
const templateVariantMapEntries = Object.entries(templateVariantMaps);
|
|
612
|
+
const hasVariantMaps = templateVariantMapEntries.some(([, pathMap]) => Object.keys(pathMap).length > 0);
|
|
613
|
+
const tsTemplateVariantMap = hasVariantMaps ? `type TemplateVariantTokens = {
|
|
614
|
+
${templateVariantMapEntries.filter(([, pathMap]) => Object.keys(pathMap).length > 0).map(([templateKey, pathMap]) => {
|
|
615
|
+
const pathEntries = Object.entries(pathMap).map(
|
|
616
|
+
([dotPath, axes]) => `'${dotPath}': { ${Object.entries(axes).map(([axis, valueType]) => `${axis}?: ${valueType}`).join("; ")} }`
|
|
617
|
+
).join(";\n ");
|
|
618
|
+
return `${templateKey}: {
|
|
619
|
+
${pathEntries}
|
|
620
|
+
}`;
|
|
621
|
+
}).join(";\n ")}
|
|
622
|
+
}` : `type TemplateVariantTokens = Record<string, Record<string, Record<string, never>>>;`;
|
|
623
|
+
const tsTemplateVariantAliases = templateVariantMapEntries.flatMap(
|
|
624
|
+
([templateKey, pathMap]) => Object.keys(pathMap).map((dotPath) => `type ${pascal(templateKey)}${pascal(dotPath)}Variants = TemplateVariantTokens['${templateKey}']['${dotPath}'];`)
|
|
625
|
+
).join("\n ");
|
|
521
626
|
const tsTokensTypes = `
|
|
522
627
|
// Variable types
|
|
523
|
-
type VariableTokens = ${tsVariableTokens || `''`};
|
|
628
|
+
type VariableTokens = ${tsVariableTokens || `''`};
|
|
524
629
|
type PropertyValueToken = \`{\${VariableTokens}}\`;
|
|
525
|
-
|
|
630
|
+
|
|
526
631
|
// Template types
|
|
527
632
|
type TemplateTokens = {
|
|
528
|
-
${Object.entries(templateTokens).map(([key, value]) =>
|
|
633
|
+
${Object.entries(templateTokens).map(([key, value]) => {
|
|
634
|
+
if (!value || value === "any") return `${key}?: ${value || "any"}`;
|
|
635
|
+
return `${key}?: ${value} | \`\${${value}}@\${string}\``;
|
|
636
|
+
}).join("\n")}
|
|
529
637
|
}
|
|
530
|
-
|
|
638
|
+
|
|
639
|
+
// Template variant types (per docs/template-variants-spec.md §7)
|
|
640
|
+
${tsTemplateVariantMap}
|
|
641
|
+
${tsTemplateVariantAliases}
|
|
642
|
+
|
|
531
643
|
// Media query types
|
|
532
644
|
type MediaQueryKeys = ${mediaQueryKeys || `''`};
|
|
533
645
|
`;
|
|
534
646
|
fs.writeFileSync(tsTokensPath, tsTokensTypes);
|
|
535
|
-
const configCachePath =
|
|
647
|
+
const configCachePath = path.join(destDir, "cache/config-cache.json");
|
|
536
648
|
fs.writeFileSync(configCachePath, JSON.stringify(configCacheContent, null, 2));
|
|
537
|
-
const corePackageRoot = compiler_helpers.getCorePackageRoot();
|
|
538
|
-
const configCacheSecondaryPath = path.join(corePackageRoot, "cache/config-cache.json");
|
|
539
|
-
fs.writeFileSync(configCacheSecondaryPath, JSON.stringify(configCacheContent, null, 2));
|
|
540
649
|
});
|
|
541
650
|
__publicField(this, "compileSaltyFile", async (sourceFilePath, outputDirectory) => {
|
|
542
651
|
const hashedName = toHash.toHash(sourceFilePath);
|
|
@@ -665,7 +774,7 @@ ${newContent}
|
|
|
665
774
|
const cssContent = cssFiles.flat().map((file2) => `@import url('./${file2}');`).join("\n");
|
|
666
775
|
const hashName = toHash.toHash(file, 6);
|
|
667
776
|
const parsedPath = path.parse(file);
|
|
668
|
-
const dasherized =
|
|
777
|
+
const dasherized = toHash.dashCase(parsedPath.name);
|
|
669
778
|
const cssFile = path.join(destDir, `css/f_${dasherized}-${hashName}.css`);
|
|
670
779
|
fs.writeFileSync(cssFile, cssContent || `/* Empty file */`);
|
|
671
780
|
}
|
|
@@ -706,3 +815,5 @@ ${newContent}
|
|
|
706
815
|
}
|
|
707
816
|
}
|
|
708
817
|
exports.SaltyCompiler = SaltyCompiler;
|
|
818
|
+
exports.logError = logError;
|
|
819
|
+
exports.logger = logger;
|
|
@@ -26,11 +26,6 @@ export declare class SaltyCompiler {
|
|
|
26
26
|
* Caches the result to avoid redundant computations.
|
|
27
27
|
*/
|
|
28
28
|
getDestDir: () => Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
* Absolute path to the `config-cache.json` written during `generateCss()`.
|
|
31
|
-
* Plugins read this to copy the file into the production bundle output.
|
|
32
|
-
*/
|
|
33
|
-
getConfigCachePath: () => Promise<string>;
|
|
34
29
|
private generateConfig;
|
|
35
30
|
private addConfigCache;
|
|
36
31
|
private getConfigCache;
|
|
@@ -49,6 +44,8 @@ export declare class SaltyCompiler {
|
|
|
49
44
|
isGlobalDefine?: boolean;
|
|
50
45
|
isDefineVariables?: boolean;
|
|
51
46
|
isDefineTemplates?: boolean;
|
|
47
|
+
isDefineImport?: boolean;
|
|
48
|
+
isDefineFont?: boolean;
|
|
52
49
|
isKeyframes?: boolean;
|
|
53
50
|
animationName?: string;
|
|
54
51
|
css?: Promise<string>;
|
|
@@ -2,30 +2,85 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import * as esbuild from "esbuild";
|
|
5
|
-
import { join, parse } from "path";
|
|
6
|
-
import {
|
|
5
|
+
import { resolve, dirname, relative, join, basename, parse } from "path";
|
|
6
|
+
import { createLogger, transports, format } from "winston";
|
|
7
7
|
import { readFile } from "fs/promises";
|
|
8
|
-
import {
|
|
8
|
+
import { existsSync, mkdirSync, copyFileSync, readFileSync, statSync, readdirSync, writeFileSync } from "fs";
|
|
9
9
|
import { execSync } from "child_process";
|
|
10
|
-
import { isSaltyFile, resolveExportValue,
|
|
10
|
+
import { isSaltyFile, resolveExportValue, saltyFileExtensions } from "./helpers.js";
|
|
11
|
+
import { t as toHash, d as dashCase } from "../to-hash-DSoCPs8D.js";
|
|
11
12
|
import { d as defineTemplates } from "../define-templates-CVhhgPnd.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles-CLMTHo2H.js";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
import { p as parseAndJoinStyles, c as parseVariableTokens } from "../parse-styles-BgVqQAni.js";
|
|
15
15
|
import { mergeObjects, mergeFactories } from "../css/merge.js";
|
|
16
|
-
import "../css/dynamic-styles.js";
|
|
17
16
|
import { getPackageJson } from "./get-files.js";
|
|
18
|
-
import { parseTemplates, getTemplateTypes } from "../parsers/index.js";
|
|
17
|
+
import { parseTemplates, getTemplateTypes, getTemplateVariantMaps } from "../parsers/index.js";
|
|
19
18
|
import console from "console";
|
|
20
|
-
const
|
|
21
|
-
|
|
19
|
+
const logger = createLogger({
|
|
20
|
+
level: "debug",
|
|
21
|
+
format: format.combine(format.colorize(), format.cli()),
|
|
22
|
+
transports: [new transports.Console({})]
|
|
23
|
+
});
|
|
24
|
+
const logError = (message) => {
|
|
25
|
+
logger.error(message);
|
|
26
|
+
};
|
|
27
|
+
const EXTERNAL_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i;
|
|
28
|
+
const normaliseSpec = (spec) => {
|
|
29
|
+
if (typeof spec === "string") return { url: spec };
|
|
30
|
+
return spec;
|
|
31
|
+
};
|
|
32
|
+
const ensureRelativePrefix = (path) => {
|
|
33
|
+
if (path.startsWith(".") || path.startsWith("/")) return path;
|
|
34
|
+
return `./${path}`;
|
|
35
|
+
};
|
|
36
|
+
const toPosix = (path) => path.split("\\").join("/");
|
|
37
|
+
const defaultResolveModule = (specifier, sourceFile) => {
|
|
38
|
+
return createRequire(sourceFile).resolve(specifier);
|
|
39
|
+
};
|
|
40
|
+
const defaultCopyAsset = (from, to) => {
|
|
41
|
+
const dir = dirname(to);
|
|
42
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
43
|
+
copyFileSync(from, to);
|
|
44
|
+
};
|
|
45
|
+
const buildRule = (url, { media, supports }) => {
|
|
46
|
+
let rule = `@import url('${url}')`;
|
|
47
|
+
if (supports) rule += ` supports(${supports})`;
|
|
48
|
+
if (media) rule += ` ${media}`;
|
|
49
|
+
return `${rule};`;
|
|
50
|
+
};
|
|
51
|
+
const resolveImport = (spec, sourceFile, destDir, options = {}) => {
|
|
52
|
+
const opts = normaliseSpec(spec);
|
|
53
|
+
const { url } = opts;
|
|
54
|
+
const resolveModule = options.resolveModule ?? defaultResolveModule;
|
|
55
|
+
const copyAsset = options.copyAsset ?? defaultCopyAsset;
|
|
56
|
+
if (EXTERNAL_URL.test(url)) {
|
|
57
|
+
return { rule: buildRule(url, opts) };
|
|
58
|
+
}
|
|
59
|
+
if (url.startsWith("/")) {
|
|
60
|
+
return { rule: buildRule(url, opts) };
|
|
61
|
+
}
|
|
62
|
+
if (url.startsWith("./") || url.startsWith("../")) {
|
|
63
|
+
const absolute2 = resolve(dirname(sourceFile), url);
|
|
64
|
+
const fromImportsFile = relative(join(destDir, "css"), absolute2);
|
|
65
|
+
return { rule: buildRule(ensureRelativePrefix(toPosix(fromImportsFile)), opts) };
|
|
66
|
+
}
|
|
67
|
+
const specifier = url.startsWith("~") ? url.slice(1) : url;
|
|
68
|
+
const absolute = resolveModule(specifier, sourceFile);
|
|
69
|
+
const hash = toHash(absolute, 6);
|
|
70
|
+
const fileName = `${hash}-${basename(absolute)}`;
|
|
71
|
+
const destPath = join(destDir, "imports", fileName);
|
|
72
|
+
copyAsset(absolute, destPath);
|
|
73
|
+
return { rule: buildRule(`../imports/${fileName}`, opts) };
|
|
74
|
+
};
|
|
75
|
+
const readPackageJsonModule = async (dirname2) => {
|
|
76
|
+
const packageJsonContent = await getPackageJson(dirname2);
|
|
22
77
|
if (!packageJsonContent) return void 0;
|
|
23
78
|
return packageJsonContent.type;
|
|
24
79
|
};
|
|
25
80
|
let cachedModuleType;
|
|
26
|
-
const detectCurrentModuleType = async (
|
|
81
|
+
const detectCurrentModuleType = async (dirname2) => {
|
|
27
82
|
if (cachedModuleType) return cachedModuleType;
|
|
28
|
-
const packageJsonModule = await readPackageJsonModule(
|
|
83
|
+
const packageJsonModule = await readPackageJsonModule(dirname2);
|
|
29
84
|
if (packageJsonModule === "module") cachedModuleType = "esm";
|
|
30
85
|
else if (packageJsonModule === "commonjs") cachedModuleType = "cjs";
|
|
31
86
|
else if (import.meta.url.endsWith(".cjs")) cachedModuleType = "cjs";
|
|
@@ -114,10 +169,10 @@ class SaltyCompiler {
|
|
|
114
169
|
* Get the project configuration from the .saltyrc.json file based on the current directory.
|
|
115
170
|
* If no specific project configuration is found, it falls back to the default project.
|
|
116
171
|
*/
|
|
117
|
-
__publicField(this, "getRCProjectConfig", async (
|
|
172
|
+
__publicField(this, "getRCProjectConfig", async (dirname2) => {
|
|
118
173
|
var _a, _b;
|
|
119
|
-
const rcFile = await this.readRCFile(
|
|
120
|
-
const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) =>
|
|
174
|
+
const rcFile = await this.readRCFile(dirname2);
|
|
175
|
+
const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) => dirname2.endsWith(project.dir || ""));
|
|
121
176
|
if (!projectConfig) return (_b = rcFile.projects) == null ? void 0 : _b.find((project) => project.dir === rcFile.defaultProject);
|
|
122
177
|
return projectConfig;
|
|
123
178
|
});
|
|
@@ -141,14 +196,6 @@ class SaltyCompiler {
|
|
|
141
196
|
this.cache.destDir = destDir;
|
|
142
197
|
return destDir;
|
|
143
198
|
});
|
|
144
|
-
/**
|
|
145
|
-
* Absolute path to the `config-cache.json` written during `generateCss()`.
|
|
146
|
-
* Plugins read this to copy the file into the production bundle output.
|
|
147
|
-
*/
|
|
148
|
-
__publicField(this, "getConfigCachePath", async () => {
|
|
149
|
-
const destDir = await this.getDestDir();
|
|
150
|
-
return join(destDir, "cache/config-cache.json");
|
|
151
|
-
});
|
|
152
199
|
__publicField(this, "generateConfig", async () => {
|
|
153
200
|
const rcProject = await this.getRCProjectConfig(this.projectRootDir);
|
|
154
201
|
const destDir = await this.getDestDir();
|
|
@@ -182,7 +229,8 @@ ${currentFile}`;
|
|
|
182
229
|
}
|
|
183
230
|
});
|
|
184
231
|
__publicField(this, "getConfigCache", async () => {
|
|
185
|
-
const
|
|
232
|
+
const destDir = await this.getDestDir();
|
|
233
|
+
const coreConfigDest = join(destDir, "cache/config-cache.json");
|
|
186
234
|
const contents = readFileSync(coreConfigDest, "utf8");
|
|
187
235
|
if (!contents) throw new Error("Could not find config cache file");
|
|
188
236
|
return JSON.parse(contents);
|
|
@@ -213,6 +261,7 @@ ${currentFile}`;
|
|
|
213
261
|
mkdirSync(join(destDir, "types"));
|
|
214
262
|
mkdirSync(join(destDir, "js"));
|
|
215
263
|
mkdirSync(join(destDir, "cache"));
|
|
264
|
+
mkdirSync(join(destDir, "imports"));
|
|
216
265
|
};
|
|
217
266
|
if (clean) clearDistDir();
|
|
218
267
|
const files = /* @__PURE__ */ new Set();
|
|
@@ -328,7 +377,7 @@ ${currentFile}`;
|
|
|
328
377
|
});
|
|
329
378
|
}
|
|
330
379
|
const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
|
|
331
|
-
const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css"];
|
|
380
|
+
const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css", "_fonts.css"];
|
|
332
381
|
const importsWithData = globalCssFilenames.filter((file) => {
|
|
333
382
|
try {
|
|
334
383
|
const data = readFileSync(join(destDir, "css", file), "utf8");
|
|
@@ -337,9 +386,12 @@ ${currentFile}`;
|
|
|
337
386
|
return false;
|
|
338
387
|
}
|
|
339
388
|
});
|
|
340
|
-
const globalImports = importsWithData.map((file) =>
|
|
389
|
+
const globalImports = importsWithData.map((file) => {
|
|
390
|
+
const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
|
|
391
|
+
return `@import url('./css/${file}')${layerSuffix};`;
|
|
392
|
+
});
|
|
341
393
|
const generatorText = "/*!\n * Generated with Salty CSS (https://salty-css.dev)\n * Do not edit this file directly\n */\n";
|
|
342
|
-
let cssContent = `${generatorText}@layer reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
394
|
+
let cssContent = `${generatorText}@layer imports, reset, global, templates, fonts, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
343
395
|
|
|
344
396
|
${globalImports.join(
|
|
345
397
|
"\n"
|
|
@@ -385,7 +437,9 @@ ${css}
|
|
|
385
437
|
mediaQueries: [],
|
|
386
438
|
globalStyles: [],
|
|
387
439
|
variables: [],
|
|
388
|
-
templates: []
|
|
440
|
+
templates: [],
|
|
441
|
+
imports: [],
|
|
442
|
+
fonts: []
|
|
389
443
|
};
|
|
390
444
|
await Promise.all(
|
|
391
445
|
[...configFiles].map(async (src) => {
|
|
@@ -395,6 +449,8 @@ ${css}
|
|
|
395
449
|
else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
|
|
396
450
|
else if (value.isDefineVariables) generationResults.variables.push(value);
|
|
397
451
|
else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
|
|
452
|
+
else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
|
|
453
|
+
else if (value.isDefineFont) generationResults.fonts.push(value);
|
|
398
454
|
});
|
|
399
455
|
})
|
|
400
456
|
);
|
|
@@ -491,32 +547,85 @@ ${css}
|
|
|
491
547
|
const templates = mergeObjects(config.templates, generationResults.templates);
|
|
492
548
|
const templateStylesString = await parseTemplates(templates);
|
|
493
549
|
const templateTokens = getTemplateTypes(templates);
|
|
550
|
+
const templateVariantMaps = getTemplateVariantMaps(templates);
|
|
494
551
|
writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
|
|
495
552
|
configCacheContent.templates = templates;
|
|
553
|
+
const importsPath = join(destDir, "css/_imports.css");
|
|
554
|
+
const importRules = [];
|
|
555
|
+
for (const factory of generationResults.imports) {
|
|
556
|
+
const sourceFile = factory._path;
|
|
557
|
+
if (!sourceFile) continue;
|
|
558
|
+
for (const spec of factory._current) {
|
|
559
|
+
try {
|
|
560
|
+
const { rule } = resolveImport(spec, sourceFile, destDir);
|
|
561
|
+
importRules.push(rule);
|
|
562
|
+
} catch (e) {
|
|
563
|
+
const url = typeof spec === "string" ? spec : spec.url;
|
|
564
|
+
logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
writeFileSync(importsPath, importRules.join("\n"));
|
|
496
569
|
const configTemplateFactories = config.templates ? [defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
|
|
497
570
|
const templateFactories = mergeFactories(generationResults.templates, configTemplateFactories);
|
|
498
571
|
configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
|
|
572
|
+
const fontsStylesPath = join(destDir, "css/_fonts.css");
|
|
573
|
+
if (generationResults.fonts.length === 0) {
|
|
574
|
+
writeFileSync(fontsStylesPath, "");
|
|
575
|
+
} else {
|
|
576
|
+
const fontImports = [];
|
|
577
|
+
const fontBodies = [];
|
|
578
|
+
for (const font of generationResults.fonts) {
|
|
579
|
+
const { imports, body } = font._toCss();
|
|
580
|
+
fontImports.push(...imports);
|
|
581
|
+
fontBodies.push(body);
|
|
582
|
+
}
|
|
583
|
+
const importBlock = fontImports.length ? `${fontImports.join("\n")}
|
|
584
|
+
|
|
585
|
+
` : "";
|
|
586
|
+
writeFileSync(fontsStylesPath, `${importBlock}@layer fonts { ${fontBodies.join(" ")} }`);
|
|
587
|
+
}
|
|
499
588
|
const tsTokensPath = join(destDir, "types/css-tokens.d.ts");
|
|
500
589
|
const tsVariableTokens = [...variableTokens].join("|");
|
|
590
|
+
const pascal = (str) => str.split(/[.\-_]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
591
|
+
const templateVariantMapEntries = Object.entries(templateVariantMaps);
|
|
592
|
+
const hasVariantMaps = templateVariantMapEntries.some(([, pathMap]) => Object.keys(pathMap).length > 0);
|
|
593
|
+
const tsTemplateVariantMap = hasVariantMaps ? `type TemplateVariantTokens = {
|
|
594
|
+
${templateVariantMapEntries.filter(([, pathMap]) => Object.keys(pathMap).length > 0).map(([templateKey, pathMap]) => {
|
|
595
|
+
const pathEntries = Object.entries(pathMap).map(
|
|
596
|
+
([dotPath, axes]) => `'${dotPath}': { ${Object.entries(axes).map(([axis, valueType]) => `${axis}?: ${valueType}`).join("; ")} }`
|
|
597
|
+
).join(";\n ");
|
|
598
|
+
return `${templateKey}: {
|
|
599
|
+
${pathEntries}
|
|
600
|
+
}`;
|
|
601
|
+
}).join(";\n ")}
|
|
602
|
+
}` : `type TemplateVariantTokens = Record<string, Record<string, Record<string, never>>>;`;
|
|
603
|
+
const tsTemplateVariantAliases = templateVariantMapEntries.flatMap(
|
|
604
|
+
([templateKey, pathMap]) => Object.keys(pathMap).map((dotPath) => `type ${pascal(templateKey)}${pascal(dotPath)}Variants = TemplateVariantTokens['${templateKey}']['${dotPath}'];`)
|
|
605
|
+
).join("\n ");
|
|
501
606
|
const tsTokensTypes = `
|
|
502
607
|
// Variable types
|
|
503
|
-
type VariableTokens = ${tsVariableTokens || `''`};
|
|
608
|
+
type VariableTokens = ${tsVariableTokens || `''`};
|
|
504
609
|
type PropertyValueToken = \`{\${VariableTokens}}\`;
|
|
505
|
-
|
|
610
|
+
|
|
506
611
|
// Template types
|
|
507
612
|
type TemplateTokens = {
|
|
508
|
-
${Object.entries(templateTokens).map(([key, value]) =>
|
|
613
|
+
${Object.entries(templateTokens).map(([key, value]) => {
|
|
614
|
+
if (!value || value === "any") return `${key}?: ${value || "any"}`;
|
|
615
|
+
return `${key}?: ${value} | \`\${${value}}@\${string}\``;
|
|
616
|
+
}).join("\n")}
|
|
509
617
|
}
|
|
510
|
-
|
|
618
|
+
|
|
619
|
+
// Template variant types (per docs/template-variants-spec.md §7)
|
|
620
|
+
${tsTemplateVariantMap}
|
|
621
|
+
${tsTemplateVariantAliases}
|
|
622
|
+
|
|
511
623
|
// Media query types
|
|
512
624
|
type MediaQueryKeys = ${mediaQueryKeys || `''`};
|
|
513
625
|
`;
|
|
514
626
|
writeFileSync(tsTokensPath, tsTokensTypes);
|
|
515
|
-
const configCachePath =
|
|
627
|
+
const configCachePath = join(destDir, "cache/config-cache.json");
|
|
516
628
|
writeFileSync(configCachePath, JSON.stringify(configCacheContent, null, 2));
|
|
517
|
-
const corePackageRoot = getCorePackageRoot();
|
|
518
|
-
const configCacheSecondaryPath = join(corePackageRoot, "cache/config-cache.json");
|
|
519
|
-
writeFileSync(configCacheSecondaryPath, JSON.stringify(configCacheContent, null, 2));
|
|
520
629
|
});
|
|
521
630
|
__publicField(this, "compileSaltyFile", async (sourceFilePath, outputDirectory) => {
|
|
522
631
|
const hashedName = toHash(sourceFilePath);
|
|
@@ -686,5 +795,7 @@ ${newContent}
|
|
|
686
795
|
}
|
|
687
796
|
}
|
|
688
797
|
export {
|
|
689
|
-
SaltyCompiler
|
|
798
|
+
SaltyCompiler,
|
|
799
|
+
logError as a,
|
|
800
|
+
logger as l
|
|
690
801
|
};
|
package/config/index.cjs
CHANGED
|
@@ -5,9 +5,13 @@ const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
|
|
|
5
5
|
const defineConfig = (config) => {
|
|
6
6
|
return config;
|
|
7
7
|
};
|
|
8
|
+
exports.FontFactory = factories_index.FontFactory;
|
|
8
9
|
exports.GlobalStylesFactory = factories_index.GlobalStylesFactory;
|
|
10
|
+
exports.ImportFactory = factories_index.ImportFactory;
|
|
9
11
|
exports.VariablesFactory = factories_index.VariablesFactory;
|
|
12
|
+
exports.defineFont = factories_index.defineFont;
|
|
10
13
|
exports.defineGlobalStyles = factories_index.defineGlobalStyles;
|
|
14
|
+
exports.defineImport = factories_index.defineImport;
|
|
11
15
|
exports.defineMediaQuery = factories_index.defineMediaQuery;
|
|
12
16
|
exports.defineVariables = factories_index.defineVariables;
|
|
13
17
|
exports.TemplateFactory = defineTemplates.TemplateFactory;
|
package/config/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { GlobalStylesFactory, VariablesFactory, defineGlobalStyles, defineMediaQuery, defineVariables } from "../factories/index.js";
|
|
1
|
+
import { FontFactory, GlobalStylesFactory, ImportFactory, VariablesFactory, defineFont, defineGlobalStyles, defineImport, defineMediaQuery, defineVariables } from "../factories/index.js";
|
|
2
2
|
import { T, a, d } from "../define-templates-CVhhgPnd.js";
|
|
3
3
|
const defineConfig = (config) => {
|
|
4
4
|
return config;
|
|
5
5
|
};
|
|
6
6
|
export {
|
|
7
|
+
FontFactory,
|
|
7
8
|
GlobalStylesFactory,
|
|
9
|
+
ImportFactory,
|
|
8
10
|
T as TemplateFactory,
|
|
9
11
|
a as TemplatesFactory,
|
|
10
12
|
VariablesFactory,
|
|
11
13
|
defineConfig,
|
|
14
|
+
defineFont,
|
|
12
15
|
defineGlobalStyles,
|
|
16
|
+
defineImport,
|
|
13
17
|
defineMediaQuery,
|
|
14
18
|
d as defineTemplates,
|
|
15
19
|
defineVariables
|