@salty-css/core 0.1.0-alpha.26 → 0.1.0-alpha.27
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 +44 -0
- package/compiler/resolve-import.d.ts +17 -0
- package/compiler/salty-compiler.cjs +77 -21
- package/compiler/salty-compiler.d.ts +1 -0
- package/compiler/salty-compiler.js +78 -21
- package/config/index.cjs +2 -0
- package/config/index.js +3 -1
- package/factories/define-import.d.ts +14 -0
- package/factories/index.cjs +16 -0
- package/factories/index.d.ts +1 -0
- package/factories/index.js +16 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,6 +58,7 @@ To get help with problems, [Join Salty CSS Discord server](https://discord.gg/R6
|
|
|
58
58
|
- [defineMediaQuery](#media-queries) - create CSS media queries and use them in any styling function
|
|
59
59
|
- [defineTemplates](#templates) - create reusable templates that can be applied when same styles are used over and over again
|
|
60
60
|
- [defineFont](#custom-fonts) - register custom fonts via `@font-face` (or a remote stylesheet) and expose them as a CSS variable
|
|
61
|
+
- [defineImport](#importing-additional-css) - pull in external CSS files (relative, public, node_modules, or URL)
|
|
61
62
|
- [keyframes](#keyframes-animations) - create CSS keyframes animation that can be used and imported in any styling function
|
|
62
63
|
|
|
63
64
|
### Styling helpers & utility
|
|
@@ -402,6 +403,49 @@ export const Body = styled('p', {
|
|
|
402
403
|
});
|
|
403
404
|
```
|
|
404
405
|
|
|
406
|
+
## Importing additional CSS
|
|
407
|
+
|
|
408
|
+
Use `defineImport` to pull in CSS that lives outside of Salty's authoring API — a reset stylesheet from npm, a Google Fonts URL, an asset in your app's `public/` folder, or a sibling `.css` file. The compiler turns each spec into an `@import` rule in the generated `saltygen/index.css`, so the imported stylesheets travel with the rest of your build.
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
// /styles/imports.css.ts
|
|
412
|
+
import { defineImport } from '@salty-css/core/factories';
|
|
413
|
+
|
|
414
|
+
export default defineImport(
|
|
415
|
+
// Relative to this file
|
|
416
|
+
'./reset.css',
|
|
417
|
+
// From node_modules (bare specifier — same as Vite / native CSS @import)
|
|
418
|
+
'modern-normalize/modern-normalize.css',
|
|
419
|
+
// From node_modules (~ prefix — same resolver, webpack-style)
|
|
420
|
+
'~normalize.css/normalize.css',
|
|
421
|
+
// From your app's public/ folder (served at the host root)
|
|
422
|
+
'/fonts/inter.css',
|
|
423
|
+
// External URL
|
|
424
|
+
'https://fonts.googleapis.com/css2?family=Inter&display=swap',
|
|
425
|
+
// Object form — attach media or supports() conditions
|
|
426
|
+
{ url: './print.css', media: 'print' },
|
|
427
|
+
{ url: './p3.css', supports: 'color(display-p3 1 1 1)' }
|
|
428
|
+
);
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Path resolution:
|
|
432
|
+
|
|
433
|
+
| Pattern | Behaviour |
|
|
434
|
+
| --------------------------- | ---------------------------------------------------------------------------------------- |
|
|
435
|
+
| `http://`, `https://`, `//` | Emitted verbatim |
|
|
436
|
+
| Starts with `/` | Public-folder URL — emitted verbatim, the browser resolves it against your host |
|
|
437
|
+
| Starts with `./` or `../` | Resolved at build time relative to the file that called `defineImport` |
|
|
438
|
+
| `~package/file.css` | Stripped of the leading `~`, then resolved from `node_modules` and copied into the build |
|
|
439
|
+
| `package/file.css` (bare) | Same `node_modules` resolution as the `~` form |
|
|
440
|
+
|
|
441
|
+
All imports are placed inside a new `imports` cascade layer that sits **before** `reset`, `global`, `templates`, and your component styles. This means your own styles always win over third-party CSS you pull in — which is what most teams expect when they drop in something like `modern-normalize`.
|
|
442
|
+
|
|
443
|
+
The full layer order in the generated `index.css` is:
|
|
444
|
+
|
|
445
|
+
```css
|
|
446
|
+
@layer imports, reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
447
|
+
```
|
|
448
|
+
|
|
405
449
|
## Keyframes animations
|
|
406
450
|
|
|
407
451
|
```ts
|
|
@@ -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
|
+
};
|
|
@@ -13,12 +13,12 @@ const compiler_helpers = require("./helpers.cjs");
|
|
|
13
13
|
const dashCase = require("../dash-case-DIwKaYgE.cjs");
|
|
14
14
|
const toHash = require("../to-hash-C05Y906F.cjs");
|
|
15
15
|
const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
|
|
16
|
+
const module$1 = require("module");
|
|
16
17
|
const parseStyles = require("../parse-styles-jPtMfgXH.cjs");
|
|
17
18
|
const css_merge = require("../css/merge.cjs");
|
|
18
19
|
const parsers_index = require("../parsers/index.cjs");
|
|
19
|
-
const
|
|
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
51
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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) };
|
|
60
94
|
};
|
|
61
95
|
function dotCase(str) {
|
|
62
96
|
if (!str) return "";
|
|
@@ -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", "_fonts.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, fonts, 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"
|
|
@@ -406,6 +444,7 @@ ${css}
|
|
|
406
444
|
globalStyles: [],
|
|
407
445
|
variables: [],
|
|
408
446
|
templates: [],
|
|
447
|
+
imports: [],
|
|
409
448
|
fonts: []
|
|
410
449
|
};
|
|
411
450
|
await Promise.all(
|
|
@@ -416,6 +455,7 @@ ${css}
|
|
|
416
455
|
else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
|
|
417
456
|
else if (value.isDefineVariables) generationResults.variables.push(value);
|
|
418
457
|
else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
|
|
458
|
+
else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
|
|
419
459
|
else if (value.isDefineFont) generationResults.fonts.push(value);
|
|
420
460
|
});
|
|
421
461
|
})
|
|
@@ -515,6 +555,22 @@ ${css}
|
|
|
515
555
|
const templateTokens = parsers_index.getTemplateTypes(templates);
|
|
516
556
|
fs.writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
|
|
517
557
|
configCacheContent.templates = templates;
|
|
558
|
+
const importsPath = path.join(destDir, "css/_imports.css");
|
|
559
|
+
const importRules = [];
|
|
560
|
+
for (const factory of generationResults.imports) {
|
|
561
|
+
const sourceFile = factory._path;
|
|
562
|
+
if (!sourceFile) continue;
|
|
563
|
+
for (const spec of factory._current) {
|
|
564
|
+
try {
|
|
565
|
+
const { rule } = resolveImport(spec, sourceFile, destDir);
|
|
566
|
+
importRules.push(rule);
|
|
567
|
+
} catch (e) {
|
|
568
|
+
const url = typeof spec === "string" ? spec : spec.url;
|
|
569
|
+
logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
fs.writeFileSync(importsPath, importRules.join("\n"));
|
|
518
574
|
const configTemplateFactories = config.templates ? [defineTemplates.defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
|
|
519
575
|
const templateFactories = css_merge.mergeFactories(generationResults.templates, configTemplateFactories);
|
|
520
576
|
configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
|
|
@@ -569,7 +625,7 @@ ${css}
|
|
|
569
625
|
const rcProject = await this.getRCProjectConfig(this.projectRootDir);
|
|
570
626
|
const coreConfigPath = path.join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
|
|
571
627
|
const externalModules = this.getExternalModules(coreConfigPath);
|
|
572
|
-
const moduleType = await detectCurrentModuleType(this.projectRootDir);
|
|
628
|
+
const moduleType$1 = await moduleType.detectCurrentModuleType(this.projectRootDir);
|
|
573
629
|
await esbuild__namespace.build({
|
|
574
630
|
stdin: {
|
|
575
631
|
contents: currentFile,
|
|
@@ -581,7 +637,7 @@ ${css}
|
|
|
581
637
|
treeShaking: true,
|
|
582
638
|
bundle: true,
|
|
583
639
|
outfile: outputFilePath,
|
|
584
|
-
format: moduleType,
|
|
640
|
+
format: moduleType$1,
|
|
585
641
|
target: ["node20"],
|
|
586
642
|
keepNames: true,
|
|
587
643
|
external: externalModules,
|
|
@@ -2,19 +2,20 @@ 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";
|
|
5
|
+
import { resolve, dirname, relative, join, basename, parse } from "path";
|
|
6
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
10
|
import { isSaltyFile, resolveExportValue, getCorePackageRoot, saltyFileExtensions } from "./helpers.js";
|
|
11
11
|
import { d as dashCase } from "../dash-case-DblXvymC.js";
|
|
12
12
|
import { t as toHash } from "../to-hash-DAN2LcHK.js";
|
|
13
13
|
import { d as defineTemplates } from "../define-templates-CVhhgPnd.js";
|
|
14
|
+
import { createRequire } from "module";
|
|
14
15
|
import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles--vHKY6Mw.js";
|
|
15
16
|
import { mergeObjects, mergeFactories } from "../css/merge.js";
|
|
16
17
|
import { parseTemplates, getTemplateTypes } from "../parsers/index.js";
|
|
17
|
-
import {
|
|
18
|
+
import { detectCurrentModuleType } from "../util/module-type";
|
|
18
19
|
import console from "console";
|
|
19
20
|
const logger = createLogger({
|
|
20
21
|
level: "debug",
|
|
@@ -24,19 +25,53 @@ const logger = createLogger({
|
|
|
24
25
|
const logError = (message) => {
|
|
25
26
|
logger.error(message);
|
|
26
27
|
};
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
28
|
+
const EXTERNAL_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i;
|
|
29
|
+
const normaliseSpec = (spec) => {
|
|
30
|
+
if (typeof spec === "string") return { url: spec };
|
|
31
|
+
return spec;
|
|
31
32
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
const ensureRelativePrefix = (path) => {
|
|
34
|
+
if (path.startsWith(".") || path.startsWith("/")) return path;
|
|
35
|
+
return `./${path}`;
|
|
36
|
+
};
|
|
37
|
+
const toPosix = (path) => path.split("\\").join("/");
|
|
38
|
+
const defaultResolveModule = (specifier, sourceFile) => {
|
|
39
|
+
return createRequire(sourceFile).resolve(specifier);
|
|
40
|
+
};
|
|
41
|
+
const defaultCopyAsset = (from, to) => {
|
|
42
|
+
const dir = dirname(to);
|
|
43
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
44
|
+
copyFileSync(from, to);
|
|
45
|
+
};
|
|
46
|
+
const buildRule = (url, { media, supports }) => {
|
|
47
|
+
let rule = `@import url('${url}')`;
|
|
48
|
+
if (supports) rule += ` supports(${supports})`;
|
|
49
|
+
if (media) rule += ` ${media}`;
|
|
50
|
+
return `${rule};`;
|
|
51
|
+
};
|
|
52
|
+
const resolveImport = (spec, sourceFile, destDir, options = {}) => {
|
|
53
|
+
const opts = normaliseSpec(spec);
|
|
54
|
+
const { url } = opts;
|
|
55
|
+
const resolveModule = options.resolveModule ?? defaultResolveModule;
|
|
56
|
+
const copyAsset = options.copyAsset ?? defaultCopyAsset;
|
|
57
|
+
if (EXTERNAL_URL.test(url)) {
|
|
58
|
+
return { rule: buildRule(url, opts) };
|
|
59
|
+
}
|
|
60
|
+
if (url.startsWith("/")) {
|
|
61
|
+
return { rule: buildRule(url, opts) };
|
|
62
|
+
}
|
|
63
|
+
if (url.startsWith("./") || url.startsWith("../")) {
|
|
64
|
+
const absolute2 = resolve(dirname(sourceFile), url);
|
|
65
|
+
const fromImportsFile = relative(join(destDir, "css"), absolute2);
|
|
66
|
+
return { rule: buildRule(ensureRelativePrefix(toPosix(fromImportsFile)), opts) };
|
|
67
|
+
}
|
|
68
|
+
const specifier = url.startsWith("~") ? url.slice(1) : url;
|
|
69
|
+
const absolute = resolveModule(specifier, sourceFile);
|
|
70
|
+
const hash = toHash(absolute, 6);
|
|
71
|
+
const fileName = `${hash}-${basename(absolute)}`;
|
|
72
|
+
const destPath = join(destDir, "imports", fileName);
|
|
73
|
+
copyAsset(absolute, destPath);
|
|
74
|
+
return { rule: buildRule(`../imports/${fileName}`, opts) };
|
|
40
75
|
};
|
|
41
76
|
function dotCase(str) {
|
|
42
77
|
if (!str) return "";
|
|
@@ -121,10 +156,10 @@ class SaltyCompiler {
|
|
|
121
156
|
* Get the project configuration from the .saltyrc.json file based on the current directory.
|
|
122
157
|
* If no specific project configuration is found, it falls back to the default project.
|
|
123
158
|
*/
|
|
124
|
-
__publicField(this, "getRCProjectConfig", async (
|
|
159
|
+
__publicField(this, "getRCProjectConfig", async (dirname2) => {
|
|
125
160
|
var _a, _b;
|
|
126
|
-
const rcFile = await this.readRCFile(
|
|
127
|
-
const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) =>
|
|
161
|
+
const rcFile = await this.readRCFile(dirname2);
|
|
162
|
+
const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) => dirname2.endsWith(project.dir || ""));
|
|
128
163
|
if (!projectConfig) return (_b = rcFile.projects) == null ? void 0 : _b.find((project) => project.dir === rcFile.defaultProject);
|
|
129
164
|
return projectConfig;
|
|
130
165
|
});
|
|
@@ -213,6 +248,7 @@ ${currentFile}`;
|
|
|
213
248
|
mkdirSync(join(destDir, "types"));
|
|
214
249
|
mkdirSync(join(destDir, "js"));
|
|
215
250
|
mkdirSync(join(destDir, "cache"));
|
|
251
|
+
mkdirSync(join(destDir, "imports"));
|
|
216
252
|
};
|
|
217
253
|
if (clean) clearDistDir();
|
|
218
254
|
const files = /* @__PURE__ */ new Set();
|
|
@@ -328,7 +364,7 @@ ${currentFile}`;
|
|
|
328
364
|
});
|
|
329
365
|
}
|
|
330
366
|
const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
|
|
331
|
-
const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css", "_fonts.css"];
|
|
367
|
+
const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css", "_fonts.css"];
|
|
332
368
|
const importsWithData = globalCssFilenames.filter((file) => {
|
|
333
369
|
try {
|
|
334
370
|
const data = readFileSync(join(destDir, "css", file), "utf8");
|
|
@@ -337,9 +373,12 @@ ${currentFile}`;
|
|
|
337
373
|
return false;
|
|
338
374
|
}
|
|
339
375
|
});
|
|
340
|
-
const globalImports = importsWithData.map((file) =>
|
|
376
|
+
const globalImports = importsWithData.map((file) => {
|
|
377
|
+
const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
|
|
378
|
+
return `@import url('./css/${file}')${layerSuffix};`;
|
|
379
|
+
});
|
|
341
380
|
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, fonts, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
381
|
+
let cssContent = `${generatorText}@layer imports, reset, global, templates, fonts, l0, l1, l2, l3, l4, l5, l6, l7, l8;
|
|
343
382
|
|
|
344
383
|
${globalImports.join(
|
|
345
384
|
"\n"
|
|
@@ -386,6 +425,7 @@ ${css}
|
|
|
386
425
|
globalStyles: [],
|
|
387
426
|
variables: [],
|
|
388
427
|
templates: [],
|
|
428
|
+
imports: [],
|
|
389
429
|
fonts: []
|
|
390
430
|
};
|
|
391
431
|
await Promise.all(
|
|
@@ -396,6 +436,7 @@ ${css}
|
|
|
396
436
|
else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
|
|
397
437
|
else if (value.isDefineVariables) generationResults.variables.push(value);
|
|
398
438
|
else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
|
|
439
|
+
else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
|
|
399
440
|
else if (value.isDefineFont) generationResults.fonts.push(value);
|
|
400
441
|
});
|
|
401
442
|
})
|
|
@@ -495,6 +536,22 @@ ${css}
|
|
|
495
536
|
const templateTokens = getTemplateTypes(templates);
|
|
496
537
|
writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
|
|
497
538
|
configCacheContent.templates = templates;
|
|
539
|
+
const importsPath = join(destDir, "css/_imports.css");
|
|
540
|
+
const importRules = [];
|
|
541
|
+
for (const factory of generationResults.imports) {
|
|
542
|
+
const sourceFile = factory._path;
|
|
543
|
+
if (!sourceFile) continue;
|
|
544
|
+
for (const spec of factory._current) {
|
|
545
|
+
try {
|
|
546
|
+
const { rule } = resolveImport(spec, sourceFile, destDir);
|
|
547
|
+
importRules.push(rule);
|
|
548
|
+
} catch (e) {
|
|
549
|
+
const url = typeof spec === "string" ? spec : spec.url;
|
|
550
|
+
logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
writeFileSync(importsPath, importRules.join("\n"));
|
|
498
555
|
const configTemplateFactories = config.templates ? [defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
|
|
499
556
|
const templateFactories = mergeFactories(generationResults.templates, configTemplateFactories);
|
|
500
557
|
configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
|
package/config/index.cjs
CHANGED
|
@@ -7,9 +7,11 @@ const defineConfig = (config) => {
|
|
|
7
7
|
};
|
|
8
8
|
exports.FontFactory = factories_index.FontFactory;
|
|
9
9
|
exports.GlobalStylesFactory = factories_index.GlobalStylesFactory;
|
|
10
|
+
exports.ImportFactory = factories_index.ImportFactory;
|
|
10
11
|
exports.VariablesFactory = factories_index.VariablesFactory;
|
|
11
12
|
exports.defineFont = factories_index.defineFont;
|
|
12
13
|
exports.defineGlobalStyles = factories_index.defineGlobalStyles;
|
|
14
|
+
exports.defineImport = factories_index.defineImport;
|
|
13
15
|
exports.defineMediaQuery = factories_index.defineMediaQuery;
|
|
14
16
|
exports.defineVariables = factories_index.defineVariables;
|
|
15
17
|
exports.TemplateFactory = defineTemplates.TemplateFactory;
|
package/config/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FontFactory, GlobalStylesFactory, VariablesFactory, defineFont, 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;
|
|
@@ -6,12 +6,14 @@ const defineConfig = (config) => {
|
|
|
6
6
|
export {
|
|
7
7
|
FontFactory,
|
|
8
8
|
GlobalStylesFactory,
|
|
9
|
+
ImportFactory,
|
|
9
10
|
T as TemplateFactory,
|
|
10
11
|
a as TemplatesFactory,
|
|
11
12
|
VariablesFactory,
|
|
12
13
|
defineConfig,
|
|
13
14
|
defineFont,
|
|
14
15
|
defineGlobalStyles,
|
|
16
|
+
defineImport,
|
|
15
17
|
defineMediaQuery,
|
|
16
18
|
d as defineTemplates,
|
|
17
19
|
defineVariables
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ImportSpecOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
media?: string;
|
|
4
|
+
supports?: string;
|
|
5
|
+
}
|
|
6
|
+
export type ImportSpec = string | ImportSpecOptions;
|
|
7
|
+
export declare class ImportFactory {
|
|
8
|
+
_current: ImportSpec[];
|
|
9
|
+
_path?: string;
|
|
10
|
+
constructor(_current: ImportSpec[]);
|
|
11
|
+
get isDefineImport(): boolean;
|
|
12
|
+
_setPath(path: string): this;
|
|
13
|
+
}
|
|
14
|
+
export declare const defineImport: (...specs: ImportSpec[]) => ImportFactory;
|
package/factories/index.cjs
CHANGED
|
@@ -136,6 +136,20 @@ class GlobalStylesFactory {
|
|
|
136
136
|
const defineGlobalStyles = (styles) => {
|
|
137
137
|
return new GlobalStylesFactory(styles);
|
|
138
138
|
};
|
|
139
|
+
class ImportFactory {
|
|
140
|
+
constructor(_current) {
|
|
141
|
+
__publicField(this, "_path");
|
|
142
|
+
this._current = _current;
|
|
143
|
+
}
|
|
144
|
+
get isDefineImport() {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
_setPath(path) {
|
|
148
|
+
this._path = path;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const defineImport = (...specs) => new ImportFactory(specs);
|
|
139
153
|
const defineMediaQuery = (mediaFactory) => {
|
|
140
154
|
return mediaFactory(css_media.media);
|
|
141
155
|
};
|
|
@@ -155,8 +169,10 @@ exports.TemplatesFactory = defineTemplates.TemplatesFactory;
|
|
|
155
169
|
exports.defineTemplates = defineTemplates.defineTemplates;
|
|
156
170
|
exports.FontFactory = FontFactory;
|
|
157
171
|
exports.GlobalStylesFactory = GlobalStylesFactory;
|
|
172
|
+
exports.ImportFactory = ImportFactory;
|
|
158
173
|
exports.VariablesFactory = VariablesFactory;
|
|
159
174
|
exports.defineFont = defineFont;
|
|
160
175
|
exports.defineGlobalStyles = defineGlobalStyles;
|
|
176
|
+
exports.defineImport = defineImport;
|
|
161
177
|
exports.defineMediaQuery = defineMediaQuery;
|
|
162
178
|
exports.defineVariables = defineVariables;
|
package/factories/index.d.ts
CHANGED
package/factories/index.js
CHANGED
|
@@ -134,6 +134,20 @@ class GlobalStylesFactory {
|
|
|
134
134
|
const defineGlobalStyles = (styles) => {
|
|
135
135
|
return new GlobalStylesFactory(styles);
|
|
136
136
|
};
|
|
137
|
+
class ImportFactory {
|
|
138
|
+
constructor(_current) {
|
|
139
|
+
__publicField(this, "_path");
|
|
140
|
+
this._current = _current;
|
|
141
|
+
}
|
|
142
|
+
get isDefineImport() {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
_setPath(path) {
|
|
146
|
+
this._path = path;
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const defineImport = (...specs) => new ImportFactory(specs);
|
|
137
151
|
const defineMediaQuery = (mediaFactory) => {
|
|
138
152
|
return mediaFactory(media);
|
|
139
153
|
};
|
|
@@ -151,11 +165,13 @@ const defineVariables = (variables) => {
|
|
|
151
165
|
export {
|
|
152
166
|
FontFactory,
|
|
153
167
|
GlobalStylesFactory,
|
|
168
|
+
ImportFactory,
|
|
154
169
|
T as TemplateFactory,
|
|
155
170
|
a as TemplatesFactory,
|
|
156
171
|
VariablesFactory,
|
|
157
172
|
defineFont,
|
|
158
173
|
defineGlobalStyles,
|
|
174
|
+
defineImport,
|
|
159
175
|
defineMediaQuery,
|
|
160
176
|
d as defineTemplates,
|
|
161
177
|
defineVariables
|