@salty-css/core 0.1.0-alpha.3 → 0.1.0-alpha.30
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 +209 -0
- package/astro-component-5hrNTCJ5.js +4 -0
- package/astro-component-Dj3enX6K.cjs +4 -0
- package/bin/commands/build.d.ts +2 -0
- package/bin/commands/generate.d.ts +2 -0
- package/bin/commands/init.d.ts +2 -0
- package/bin/commands/update.d.ts +2 -0
- package/bin/commands/version.d.ts +2 -0
- package/bin/confirm-install.d.ts +34 -0
- package/bin/context.d.ts +22 -0
- package/bin/detection/css-file.d.ts +5 -0
- package/bin/frameworks/astro.d.ts +4 -0
- package/bin/frameworks/index.d.ts +13 -0
- package/bin/frameworks/react.d.ts +2 -0
- package/bin/frameworks/types.d.ts +27 -0
- package/bin/integrations/astro.d.ts +11 -0
- package/bin/integrations/eslint.d.ts +6 -0
- package/bin/integrations/index.d.ts +21 -0
- package/bin/integrations/next.d.ts +9 -0
- package/bin/integrations/types.d.ts +29 -0
- package/bin/integrations/vite.d.ts +8 -0
- package/bin/main.cjs +653 -336
- package/bin/main.d.ts +8 -0
- package/bin/main.js +653 -336
- package/bin/package-json.d.ts +21 -0
- package/bin/saltyrc.d.ts +31 -0
- package/bin/templates.d.ts +14 -0
- package/{class-name-generator-YeSQe_Ik.js → class-name-generator-B0WkxoIg.js} +17 -2
- package/{class-name-generator-B2Pb2obX.cjs → class-name-generator-BEOEMEKX.cjs} +17 -2
- package/compiler/resolve-import.d.ts +17 -0
- package/compiler/salty-compiler.cjs +131 -30
- package/compiler/salty-compiler.d.ts +8 -1
- package/compiler/salty-compiler.js +133 -31
- package/config/index.cjs +4 -0
- package/config/index.js +5 -1
- package/css/dynamic-styles.cjs +15 -0
- package/css/dynamic-styles.d.ts +10 -0
- package/css/dynamic-styles.js +15 -0
- package/css/index.cjs +3 -0
- package/css/index.d.ts +1 -0
- package/css/index.js +3 -0
- package/css/keyframes.cjs +1 -1
- package/css/keyframes.js +1 -1
- package/factories/define-font.d.ts +28 -0
- package/factories/define-import.d.ts +14 -0
- package/factories/index.cjs +141 -0
- package/factories/index.d.ts +2 -0
- package/factories/index.js +141 -0
- package/generators/index.cjs +1 -1
- package/generators/index.js +2 -2
- package/instances/classname-instance.cjs +1 -1
- package/instances/classname-instance.js +1 -1
- package/package.json +5 -1
- package/parse-styles-BBJ3PWyV.js +514 -0
- package/parse-styles-lOMGe_c5.cjs +513 -0
- package/parsers/index.cjs +93 -3
- package/parsers/index.d.ts +1 -0
- package/parsers/index.js +97 -7
- package/parsers/parse-templates.d.ts +10 -0
- package/parsers/parser-regexes.d.ts +3 -0
- package/parsers/resolve-template-variants.d.ts +21 -0
- package/parsers/strict.d.ts +2 -0
- package/runtime/index.cjs +1 -1
- package/runtime/index.js +1 -1
- package/{salty.config-cqavVm2t.cjs → salty.config-DogY_sSQ.cjs} +1 -1
- package/salty.config-GV37Q-D2.js +4 -0
- package/styled-file-BzmB9_Ez.cjs +12 -0
- package/{react-styled-file-U02jek-B.cjs → styled-file-CPd_rTW2.cjs} +2 -2
- package/{react-styled-file-B99mwk0w.js → styled-file-Cda3EeR6.js} +2 -2
- package/styled-file-DLcgYmGN.js +12 -0
- package/types/config-types.d.ts +42 -2
- package/types/font-types.d.ts +53 -0
- package/{react-vanilla-file-D9px70iK.js → vanilla-file-1kOqbCIM.js} +2 -2
- package/{react-vanilla-file-Bj6XC8GS.cjs → vanilla-file-r0fp2q_m.cjs} +2 -2
- package/parse-styles-BTIoYnBr.js +0 -232
- package/parse-styles-CA3TP5n1.cjs +0 -231
- package/salty.config-DjosWdPw.js +0 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PathLike } from 'fs';
|
|
2
|
+
export declare const defaultPackageJsonPath: string;
|
|
3
|
+
export interface PackageJson {
|
|
4
|
+
name?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
scripts?: Record<string, string>;
|
|
7
|
+
dependencies?: Record<string, string>;
|
|
8
|
+
devDependencies?: Record<string, string>;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare const readPackageJson: (filePath?: PathLike) => Promise<PackageJson>;
|
|
12
|
+
export declare const updatePackageJson: (content: string | object, filePath?: PathLike) => Promise<void>;
|
|
13
|
+
export declare const readThisPackageJson: () => Promise<PackageJson>;
|
|
14
|
+
export declare const corePackages: {
|
|
15
|
+
core: (version: string) => string;
|
|
16
|
+
eslintConfigCore: (version: string) => string;
|
|
17
|
+
};
|
|
18
|
+
export declare const addPrepareScript: (pkg: PackageJson) => {
|
|
19
|
+
changed: boolean;
|
|
20
|
+
pkg: PackageJson;
|
|
21
|
+
};
|
package/bin/saltyrc.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RCFile } from '../types/cli-types';
|
|
2
|
+
import { FrameworkAdapter } from './frameworks';
|
|
3
|
+
export declare const SALTYRC_FILENAME = ".saltyrc.json";
|
|
4
|
+
export declare const SALTYRC_SCHEMA = "./node_modules/@salty-css/core/.saltyrc.schema.json";
|
|
5
|
+
export declare const SALTYRC_INFO = "This file is used to define projects and their configurations for Salty CSS cli. Do not delete, modify or add this file to .gitignore.";
|
|
6
|
+
export interface ProjectEntry {
|
|
7
|
+
dir: string;
|
|
8
|
+
framework: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare const saltyrcPath: (rootDir?: string) => string;
|
|
12
|
+
export declare const readRc: (rootDir?: string) => Promise<RCFile>;
|
|
13
|
+
export declare const readRawRc: (rootDir?: string) => Promise<string | undefined>;
|
|
14
|
+
export declare const getDefaultProject: (rootDir?: string) => Promise<string | undefined>;
|
|
15
|
+
/**
|
|
16
|
+
* Pure transform: returns the new saltyrc content for an upsert. Does not touch the filesystem.
|
|
17
|
+
* - If `existingRaw` is undefined, returns a fresh file with the project as the only entry.
|
|
18
|
+
* - If the project entry already exists, returns the same content (no-op).
|
|
19
|
+
* - Otherwise appends the new entry and returns updated content.
|
|
20
|
+
*/
|
|
21
|
+
export declare const upsertProjectInRc: (existingRaw: string | undefined, relativeProjectPath: string, framework: FrameworkAdapter) => {
|
|
22
|
+
content: string;
|
|
23
|
+
changed: boolean;
|
|
24
|
+
created: boolean;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Writes the saltyrc file, creating or updating the project entry for the given dir.
|
|
28
|
+
* Returns true when a write occurred.
|
|
29
|
+
*/
|
|
30
|
+
export declare const writeProjectToRc: (cwd: string, relativeProjectPath: string, framework: FrameworkAdapter) => Promise<boolean>;
|
|
31
|
+
export declare const getProjectFramework: (rc: RCFile, relativeProjectPath: string) => string | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const templateLoaders: {
|
|
2
|
+
readonly 'salty.config.ts': () => Promise<any>;
|
|
3
|
+
readonly 'saltygen/index.css': () => Promise<any>;
|
|
4
|
+
readonly 'react/styled-file.ts': () => Promise<any>;
|
|
5
|
+
readonly 'react/vanilla-file.ts': () => Promise<any>;
|
|
6
|
+
readonly 'astro/styled-file.ts': () => Promise<any>;
|
|
7
|
+
readonly 'astro/component.astro': () => Promise<any>;
|
|
8
|
+
};
|
|
9
|
+
export type TemplateKey = keyof typeof templateLoaders;
|
|
10
|
+
export declare const readTemplate: <T extends object>(key: TemplateKey, options?: T) => Promise<{
|
|
11
|
+
fileName: "salty.config.ts" | "saltygen/index.css" | "react/styled-file.ts" | "react/vanilla-file.ts" | "astro/styled-file.ts" | "astro/component.astro";
|
|
12
|
+
content: string;
|
|
13
|
+
}>;
|
|
14
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
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
|
-
import { p as parseAndJoinStyles } from "./parse-styles-
|
|
4
|
+
import { p as parseAndJoinStyles, b as parseTemplateCallSite } from "./parse-styles-BBJ3PWyV.js";
|
|
5
5
|
import { d as dashCase } from "./dash-case-DblXvymC.js";
|
|
6
6
|
import { t as toHash } from "./to-hash-DAN2LcHK.js";
|
|
7
7
|
class StylesGenerator {
|
|
@@ -50,7 +50,22 @@ class StylesGenerator {
|
|
|
50
50
|
if (!(config == null ? void 0 : config.templates) || !this.params.base || this.priority > 0) return [];
|
|
51
51
|
const templateKeys = Object.keys(config.templates);
|
|
52
52
|
return Object.entries(this.params.base).reduce((acc, [key, value]) => {
|
|
53
|
-
if (templateKeys.includes(key)) acc
|
|
53
|
+
if (!templateKeys.includes(key)) return acc;
|
|
54
|
+
const callSite = parseTemplateCallSite(value);
|
|
55
|
+
if (!callSite || callSite.path.length === 0) return acc;
|
|
56
|
+
const { path, variants } = callSite;
|
|
57
|
+
const cumulative = [];
|
|
58
|
+
for (const part of path) {
|
|
59
|
+
cumulative.push(part);
|
|
60
|
+
const baseClassName = dashCase(`${key}-${cumulative.join(".")}`);
|
|
61
|
+
acc.push("t_" + toHash(baseClassName, 4));
|
|
62
|
+
for (const [axis, axisValue] of Object.entries(variants)) {
|
|
63
|
+
if (axisValue === false || axisValue === void 0) continue;
|
|
64
|
+
const valueSuffix = axisValue === true ? "" : `-${dashCase(String(axisValue))}`;
|
|
65
|
+
const variantClassName = `${baseClassName}-${dashCase(axis)}${valueSuffix}`;
|
|
66
|
+
acc.push("tv_" + toHash(variantClassName, 4));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
54
69
|
return acc;
|
|
55
70
|
}, []);
|
|
56
71
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
const parseStyles = require("./parse-styles-
|
|
5
|
+
const parseStyles = require("./parse-styles-lOMGe_c5.cjs");
|
|
6
6
|
const dashCase = require("./dash-case-DIwKaYgE.cjs");
|
|
7
7
|
const toHash = require("./to-hash-C05Y906F.cjs");
|
|
8
8
|
class StylesGenerator {
|
|
@@ -51,7 +51,22 @@ class StylesGenerator {
|
|
|
51
51
|
if (!(config == null ? void 0 : config.templates) || !this.params.base || this.priority > 0) return [];
|
|
52
52
|
const templateKeys = Object.keys(config.templates);
|
|
53
53
|
return Object.entries(this.params.base).reduce((acc, [key, value]) => {
|
|
54
|
-
if (templateKeys.includes(key)) acc
|
|
54
|
+
if (!templateKeys.includes(key)) return acc;
|
|
55
|
+
const callSite = parseStyles.parseTemplateCallSite(value);
|
|
56
|
+
if (!callSite || callSite.path.length === 0) return acc;
|
|
57
|
+
const { path, variants } = callSite;
|
|
58
|
+
const cumulative = [];
|
|
59
|
+
for (const part of path) {
|
|
60
|
+
cumulative.push(part);
|
|
61
|
+
const baseClassName = dashCase.dashCase(`${key}-${cumulative.join(".")}`);
|
|
62
|
+
acc.push("t_" + toHash.toHash(baseClassName, 4));
|
|
63
|
+
for (const [axis, axisValue] of Object.entries(variants)) {
|
|
64
|
+
if (axisValue === false || axisValue === void 0) continue;
|
|
65
|
+
const valueSuffix = axisValue === true ? "" : `-${dashCase.dashCase(String(axisValue))}`;
|
|
66
|
+
const variantClassName = `${baseClassName}-${dashCase.dashCase(axis)}${valueSuffix}`;
|
|
67
|
+
acc.push("tv_" + toHash.toHash(variantClassName, 4));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
55
70
|
return acc;
|
|
56
71
|
}, []);
|
|
57
72
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ImportSpec } from '../factories/define-import';
|
|
2
|
+
export interface ResolveImportOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Override for node_modules resolution. Receives the bare specifier (with any leading `~` already
|
|
5
|
+
* stripped) and the source file path of the salty file that called `defineImport`. Must return the
|
|
6
|
+
* absolute filesystem path of the resolved CSS file. Defaults to `createRequire(sourceFile).resolve`.
|
|
7
|
+
*/
|
|
8
|
+
resolveModule?: (specifier: string, sourceFile: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Override for copying resolved node_modules CSS into `<destDir>/imports/`. Receives the absolute
|
|
11
|
+
* source and destination paths. Defaults to `copyFileSync`.
|
|
12
|
+
*/
|
|
13
|
+
copyAsset?: (from: string, to: string) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare const resolveImport: (spec: ImportSpec, sourceFile: string, destDir: string, options?: ResolveImportOptions) => {
|
|
16
|
+
rule: string;
|
|
17
|
+
};
|
|
@@ -10,15 +10,15 @@ 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 defineTemplates = require("../define-templates-Deq1aCbN.cjs");
|
|
14
13
|
const dashCase = require("../dash-case-DIwKaYgE.cjs");
|
|
15
14
|
const toHash = require("../to-hash-C05Y906F.cjs");
|
|
16
|
-
const
|
|
15
|
+
const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
|
|
16
|
+
const module$1 = require("module");
|
|
17
|
+
const parseStyles = require("../parse-styles-lOMGe_c5.cjs");
|
|
17
18
|
const css_merge = require("../css/merge.cjs");
|
|
18
|
-
const compiler_getFiles = require("./get-files.cjs");
|
|
19
19
|
const parsers_index = require("../parsers/index.cjs");
|
|
20
|
+
const moduleType = require("../util/module-type");
|
|
20
21
|
const console = require("console");
|
|
21
|
-
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
22
22
|
function _interopNamespaceDefault(e) {
|
|
23
23
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
24
24
|
if (e) {
|
|
@@ -44,19 +44,53 @@ const logger = winston.createLogger({
|
|
|
44
44
|
const logError = (message) => {
|
|
45
45
|
logger.error(message);
|
|
46
46
|
};
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
return
|
|
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);
|
|
51
64
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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) };
|
|
60
94
|
};
|
|
61
95
|
function dotCase(str) {
|
|
62
96
|
if (!str) return "";
|
|
@@ -111,7 +145,7 @@ const saltyReset = {
|
|
|
111
145
|
}
|
|
112
146
|
};
|
|
113
147
|
class SaltyCompiler {
|
|
114
|
-
constructor(projectRootDir) {
|
|
148
|
+
constructor(projectRootDir, options = {}) {
|
|
115
149
|
__publicField(this, "importFile", (path2) => {
|
|
116
150
|
const now = Date.now();
|
|
117
151
|
return import(
|
|
@@ -173,7 +207,7 @@ class SaltyCompiler {
|
|
|
173
207
|
const destDir = await this.getDestDir();
|
|
174
208
|
const coreConfigPath = path.join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
|
|
175
209
|
const coreConfigDest = path.join(destDir, "salty.config.js");
|
|
176
|
-
const moduleType = await detectCurrentModuleType(this.projectRootDir);
|
|
210
|
+
const moduleType$1 = await moduleType.detectCurrentModuleType(this.projectRootDir);
|
|
177
211
|
const externalModules = this.getExternalModules(coreConfigPath);
|
|
178
212
|
await esbuild__namespace.build({
|
|
179
213
|
entryPoints: [coreConfigPath],
|
|
@@ -181,7 +215,7 @@ class SaltyCompiler {
|
|
|
181
215
|
treeShaking: true,
|
|
182
216
|
bundle: true,
|
|
183
217
|
outfile: coreConfigDest,
|
|
184
|
-
format: moduleType,
|
|
218
|
+
format: moduleType$1,
|
|
185
219
|
external: externalModules
|
|
186
220
|
});
|
|
187
221
|
const { config } = await this.importFile(coreConfigDest);
|
|
@@ -233,6 +267,7 @@ ${currentFile}`;
|
|
|
233
267
|
fs.mkdirSync(path.join(destDir, "types"));
|
|
234
268
|
fs.mkdirSync(path.join(destDir, "js"));
|
|
235
269
|
fs.mkdirSync(path.join(destDir, "cache"));
|
|
270
|
+
fs.mkdirSync(path.join(destDir, "imports"));
|
|
236
271
|
};
|
|
237
272
|
if (clean) clearDistDir();
|
|
238
273
|
const files = /* @__PURE__ */ new Set();
|
|
@@ -348,7 +383,7 @@ ${currentFile}`;
|
|
|
348
383
|
});
|
|
349
384
|
}
|
|
350
385
|
const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
|
|
351
|
-
const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css"];
|
|
386
|
+
const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css", "_fonts.css"];
|
|
352
387
|
const importsWithData = globalCssFilenames.filter((file) => {
|
|
353
388
|
try {
|
|
354
389
|
const data = fs.readFileSync(path.join(destDir, "css", file), "utf8");
|
|
@@ -357,9 +392,12 @@ ${currentFile}`;
|
|
|
357
392
|
return false;
|
|
358
393
|
}
|
|
359
394
|
});
|
|
360
|
-
const globalImports = importsWithData.map((file) =>
|
|
395
|
+
const globalImports = importsWithData.map((file) => {
|
|
396
|
+
const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
|
|
397
|
+
return `@import url('./css/${file}')${layerSuffix};`;
|
|
398
|
+
});
|
|
361
399
|
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;
|
|
400
|
+
let cssContent = `${generatorText}@layer imports, reset, global, templates, fonts, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
363
401
|
|
|
364
402
|
${globalImports.join(
|
|
365
403
|
"\n"
|
|
@@ -405,7 +443,9 @@ ${css}
|
|
|
405
443
|
mediaQueries: [],
|
|
406
444
|
globalStyles: [],
|
|
407
445
|
variables: [],
|
|
408
|
-
templates: []
|
|
446
|
+
templates: [],
|
|
447
|
+
imports: [],
|
|
448
|
+
fonts: []
|
|
409
449
|
};
|
|
410
450
|
await Promise.all(
|
|
411
451
|
[...configFiles].map(async (src) => {
|
|
@@ -415,6 +455,8 @@ ${css}
|
|
|
415
455
|
else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
|
|
416
456
|
else if (value.isDefineVariables) generationResults.variables.push(value);
|
|
417
457
|
else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
|
|
458
|
+
else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
|
|
459
|
+
else if (value.isDefineFont) generationResults.fonts.push(value);
|
|
418
460
|
});
|
|
419
461
|
})
|
|
420
462
|
);
|
|
@@ -511,23 +553,79 @@ ${css}
|
|
|
511
553
|
const templates = css_merge.mergeObjects(config.templates, generationResults.templates);
|
|
512
554
|
const templateStylesString = await parsers_index.parseTemplates(templates);
|
|
513
555
|
const templateTokens = parsers_index.getTemplateTypes(templates);
|
|
556
|
+
const templateVariantMaps = parsers_index.getTemplateVariantMaps(templates);
|
|
514
557
|
fs.writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
|
|
515
558
|
configCacheContent.templates = templates;
|
|
559
|
+
const importsPath = path.join(destDir, "css/_imports.css");
|
|
560
|
+
const importRules = [];
|
|
561
|
+
for (const factory of generationResults.imports) {
|
|
562
|
+
const sourceFile = factory._path;
|
|
563
|
+
if (!sourceFile) continue;
|
|
564
|
+
for (const spec of factory._current) {
|
|
565
|
+
try {
|
|
566
|
+
const { rule } = resolveImport(spec, sourceFile, destDir);
|
|
567
|
+
importRules.push(rule);
|
|
568
|
+
} catch (e) {
|
|
569
|
+
const url = typeof spec === "string" ? spec : spec.url;
|
|
570
|
+
logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
fs.writeFileSync(importsPath, importRules.join("\n"));
|
|
516
575
|
const configTemplateFactories = config.templates ? [defineTemplates.defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
|
|
517
576
|
const templateFactories = css_merge.mergeFactories(generationResults.templates, configTemplateFactories);
|
|
518
577
|
configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
|
|
578
|
+
const fontsStylesPath = path.join(destDir, "css/_fonts.css");
|
|
579
|
+
if (generationResults.fonts.length === 0) {
|
|
580
|
+
fs.writeFileSync(fontsStylesPath, "");
|
|
581
|
+
} else {
|
|
582
|
+
const fontImports = [];
|
|
583
|
+
const fontBodies = [];
|
|
584
|
+
for (const font of generationResults.fonts) {
|
|
585
|
+
const { imports, body } = font._toCss();
|
|
586
|
+
fontImports.push(...imports);
|
|
587
|
+
fontBodies.push(body);
|
|
588
|
+
}
|
|
589
|
+
const importBlock = fontImports.length ? `${fontImports.join("\n")}
|
|
590
|
+
|
|
591
|
+
` : "";
|
|
592
|
+
fs.writeFileSync(fontsStylesPath, `${importBlock}@layer fonts { ${fontBodies.join(" ")} }`);
|
|
593
|
+
}
|
|
519
594
|
const tsTokensPath = path.join(destDir, "types/css-tokens.d.ts");
|
|
520
595
|
const tsVariableTokens = [...variableTokens].join("|");
|
|
596
|
+
const pascal = (str) => str.split(/[.\-_]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
597
|
+
const templateVariantMapEntries = Object.entries(templateVariantMaps);
|
|
598
|
+
const hasVariantMaps = templateVariantMapEntries.some(([, pathMap]) => Object.keys(pathMap).length > 0);
|
|
599
|
+
const tsTemplateVariantMap = hasVariantMaps ? `type TemplateVariantTokens = {
|
|
600
|
+
${templateVariantMapEntries.filter(([, pathMap]) => Object.keys(pathMap).length > 0).map(([templateKey, pathMap]) => {
|
|
601
|
+
const pathEntries = Object.entries(pathMap).map(
|
|
602
|
+
([dotPath, axes]) => `'${dotPath}': { ${Object.entries(axes).map(([axis, valueType]) => `${axis}?: ${valueType}`).join("; ")} }`
|
|
603
|
+
).join(";\n ");
|
|
604
|
+
return `${templateKey}: {
|
|
605
|
+
${pathEntries}
|
|
606
|
+
}`;
|
|
607
|
+
}).join(";\n ")}
|
|
608
|
+
}` : `type TemplateVariantTokens = Record<string, Record<string, Record<string, never>>>;`;
|
|
609
|
+
const tsTemplateVariantAliases = templateVariantMapEntries.flatMap(
|
|
610
|
+
([templateKey, pathMap]) => Object.keys(pathMap).map((dotPath) => `type ${pascal(templateKey)}${pascal(dotPath)}Variants = TemplateVariantTokens['${templateKey}']['${dotPath}'];`)
|
|
611
|
+
).join("\n ");
|
|
521
612
|
const tsTokensTypes = `
|
|
522
613
|
// Variable types
|
|
523
|
-
type VariableTokens = ${tsVariableTokens || `''`};
|
|
614
|
+
type VariableTokens = ${tsVariableTokens || `''`};
|
|
524
615
|
type PropertyValueToken = \`{\${VariableTokens}}\`;
|
|
525
|
-
|
|
616
|
+
|
|
526
617
|
// Template types
|
|
527
618
|
type TemplateTokens = {
|
|
528
|
-
${Object.entries(templateTokens).map(([key, value]) =>
|
|
619
|
+
${Object.entries(templateTokens).map(([key, value]) => {
|
|
620
|
+
if (!value || value === "any") return `${key}?: ${value || "any"}`;
|
|
621
|
+
return `${key}?: ${value} | \`\${${value}}@\${string}\``;
|
|
622
|
+
}).join("\n")}
|
|
529
623
|
}
|
|
530
|
-
|
|
624
|
+
|
|
625
|
+
// Template variant types (per docs/template-variants-spec.md §7)
|
|
626
|
+
${tsTemplateVariantMap}
|
|
627
|
+
${tsTemplateVariantAliases}
|
|
628
|
+
|
|
531
629
|
// Media query types
|
|
532
630
|
type MediaQueryKeys = ${mediaQueryKeys || `''`};
|
|
533
631
|
`;
|
|
@@ -546,11 +644,12 @@ ${css}
|
|
|
546
644
|
let currentFile = fs.readFileSync(sourceFilePath, "utf8");
|
|
547
645
|
currentFile = this.replaceStyledTag(currentFile);
|
|
548
646
|
currentFile = this.addConfigCache(currentFile);
|
|
549
|
-
const
|
|
647
|
+
const currentFileHash = toHash.toHash(currentFile);
|
|
648
|
+
const outputFilePath = path.join(outputDirectory, "js", `${hashedName}-${currentFileHash}.js`);
|
|
550
649
|
const rcProject = await this.getRCProjectConfig(this.projectRootDir);
|
|
551
650
|
const coreConfigPath = path.join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
|
|
552
651
|
const externalModules = this.getExternalModules(coreConfigPath);
|
|
553
|
-
const moduleType = await detectCurrentModuleType(this.projectRootDir);
|
|
652
|
+
const moduleType$1 = await moduleType.detectCurrentModuleType(this.projectRootDir);
|
|
554
653
|
await esbuild__namespace.build({
|
|
555
654
|
stdin: {
|
|
556
655
|
contents: currentFile,
|
|
@@ -562,7 +661,7 @@ ${css}
|
|
|
562
661
|
treeShaking: true,
|
|
563
662
|
bundle: true,
|
|
564
663
|
outfile: outputFilePath,
|
|
565
|
-
format: moduleType,
|
|
664
|
+
format: moduleType$1,
|
|
566
665
|
target: ["node20"],
|
|
567
666
|
keepNames: true,
|
|
568
667
|
external: externalModules,
|
|
@@ -690,11 +789,13 @@ ${newContent}
|
|
|
690
789
|
});
|
|
691
790
|
});
|
|
692
791
|
this.projectRootDir = projectRootDir;
|
|
792
|
+
this.options = options;
|
|
693
793
|
if (typeof process === "undefined") {
|
|
694
794
|
throw new Error("SaltyServer can only be used in a Node.js environment.");
|
|
695
795
|
}
|
|
696
796
|
}
|
|
697
797
|
get isProduction() {
|
|
798
|
+
if (this.options.mode) return this.options.mode === "production";
|
|
698
799
|
try {
|
|
699
800
|
return process.env["NODE_ENV"] !== "development";
|
|
700
801
|
} catch {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { CachedConfig, SaltyConfig } from '../config';
|
|
2
|
+
export type SaltyCompilerMode = 'production' | 'development';
|
|
3
|
+
export interface SaltyCompilerOptions {
|
|
4
|
+
mode?: SaltyCompilerMode;
|
|
5
|
+
}
|
|
2
6
|
export declare class SaltyCompiler {
|
|
3
7
|
projectRootDir: string;
|
|
8
|
+
private options;
|
|
4
9
|
importFile: (path: string) => Promise<any>;
|
|
5
10
|
private cache;
|
|
6
|
-
constructor(projectRootDir: string);
|
|
11
|
+
constructor(projectRootDir: string, options?: SaltyCompilerOptions);
|
|
7
12
|
get isProduction(): boolean;
|
|
8
13
|
/**
|
|
9
14
|
* Locate and read the .saltyrc.json file starting from the current directory and moving up the directory tree.
|
|
@@ -39,6 +44,8 @@ export declare class SaltyCompiler {
|
|
|
39
44
|
isGlobalDefine?: boolean;
|
|
40
45
|
isDefineVariables?: boolean;
|
|
41
46
|
isDefineTemplates?: boolean;
|
|
47
|
+
isDefineImport?: boolean;
|
|
48
|
+
isDefineFont?: boolean;
|
|
42
49
|
isKeyframes?: boolean;
|
|
43
50
|
animationName?: string;
|
|
44
51
|
css?: Promise<string>;
|