@salty-css/core 0.1.0-alpha.9 → 0.1.0-feat-define-import.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +44 -0
  2. package/bin/confirm-install.d.ts +34 -0
  3. package/bin/context.d.ts +3 -0
  4. package/bin/integrations/index.d.ts +11 -3
  5. package/bin/integrations/types.d.ts +14 -2
  6. package/bin/main.cjs +149 -48
  7. package/bin/main.js +149 -48
  8. package/{class-name-generator-YeSQe_Ik.js → class-name-generator-CMWY5KTJ.js} +1 -1
  9. package/{class-name-generator-B2Pb2obX.cjs → class-name-generator-DB5aQwC_.cjs} +1 -1
  10. package/compiler/resolve-import.d.ts +17 -0
  11. package/compiler/salty-compiler.cjs +85 -26
  12. package/compiler/salty-compiler.d.ts +7 -1
  13. package/compiler/salty-compiler.js +86 -26
  14. package/config/index.cjs +2 -0
  15. package/config/index.js +3 -1
  16. package/css/dynamic-styles.cjs +1 -1
  17. package/css/dynamic-styles.js +1 -1
  18. package/css/keyframes.cjs +1 -1
  19. package/css/keyframes.js +1 -1
  20. package/factories/define-import.d.ts +14 -0
  21. package/factories/index.cjs +19 -0
  22. package/factories/index.d.ts +1 -0
  23. package/factories/index.js +19 -0
  24. package/generators/index.cjs +1 -1
  25. package/generators/index.js +2 -2
  26. package/instances/classname-instance.cjs +1 -1
  27. package/instances/classname-instance.js +1 -1
  28. package/package.json +1 -1
  29. package/{parse-styles-CA3TP5n1.cjs → parse-styles-C54MOrPg.cjs} +106 -7
  30. package/{parse-styles-BTIoYnBr.js → parse-styles-CLMTHo2H.js} +107 -8
  31. package/parsers/index.cjs +2 -1
  32. package/parsers/index.d.ts +1 -0
  33. package/parsers/index.js +4 -3
  34. package/parsers/parser-regexes.d.ts +3 -0
  35. package/parsers/strict.d.ts +2 -0
  36. package/runtime/index.cjs +1 -1
  37. package/runtime/index.js +1 -1
  38. package/{salty.config-cqavVm2t.cjs → salty.config-DogY_sSQ.cjs} +1 -1
  39. package/salty.config-GV37Q-D2.js +4 -0
  40. package/types/config-types.d.ts +9 -0
  41. package/salty.config-DjosWdPw.js +0 -4
@@ -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 { readFileSync, existsSync, mkdirSync, statSync, readdirSync, writeFileSync } from "fs";
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 defineTemplates } from "../define-templates-CVhhgPnd.js";
12
- import { d as dashCase } from "../dash-case-DblXvymC.js";
12
+ import { createRequire } from "module";
13
13
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
14
- import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles-BTIoYnBr.js";
14
+ import { d as dashCase } from "../dash-case-DblXvymC.js";
15
+ import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles-CLMTHo2H.js";
15
16
  import { mergeObjects, mergeFactories } from "../css/merge.js";
16
17
  import { parseTemplates, getTemplateTypes } from "../parsers/index.js";
17
- import { getPackageJson } from "./get-files.js";
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 readPackageJsonModule = async (dirname) => {
28
- const packageJsonContent = await getPackageJson(dirname);
29
- if (!packageJsonContent) return void 0;
30
- return packageJsonContent.type;
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;
32
+ };
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);
31
40
  };
32
- let cachedModuleType;
33
- const detectCurrentModuleType = async (dirname) => {
34
- if (cachedModuleType) return cachedModuleType;
35
- const packageJsonModule = await readPackageJsonModule(dirname);
36
- if (packageJsonModule === "module") cachedModuleType = "esm";
37
- else if (packageJsonModule === "commonjs") cachedModuleType = "cjs";
38
- else if (import.meta.url.endsWith(".cjs")) cachedModuleType = "cjs";
39
- return cachedModuleType || "esm";
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 "";
@@ -91,7 +126,7 @@ const saltyReset = {
91
126
  }
92
127
  };
93
128
  class SaltyCompiler {
94
- constructor(projectRootDir) {
129
+ constructor(projectRootDir, options = {}) {
95
130
  __publicField(this, "importFile", (path) => {
96
131
  const now = Date.now();
97
132
  return import(
@@ -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 (dirname) => {
159
+ __publicField(this, "getRCProjectConfig", async (dirname2) => {
125
160
  var _a, _b;
126
- const rcFile = await this.readRCFile(dirname);
127
- const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) => dirname.endsWith(project.dir || ""));
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"];
367
+ const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.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) => `@import url('./css/${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, l0, l1, l2, l3, l4, l5, l6, l7, l8;
381
+ let cssContent = `${generatorText}@layer imports, reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
343
382
 
344
383
  ${globalImports.join(
345
384
  "\n"
@@ -385,7 +424,8 @@ ${css}
385
424
  mediaQueries: [],
386
425
  globalStyles: [],
387
426
  variables: [],
388
- templates: []
427
+ templates: [],
428
+ imports: []
389
429
  };
390
430
  await Promise.all(
391
431
  [...configFiles].map(async (src) => {
@@ -395,6 +435,7 @@ ${css}
395
435
  else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
396
436
  else if (value.isDefineVariables) generationResults.variables.push(value);
397
437
  else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
438
+ else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
398
439
  });
399
440
  })
400
441
  );
@@ -493,6 +534,22 @@ ${css}
493
534
  const templateTokens = getTemplateTypes(templates);
494
535
  writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
495
536
  configCacheContent.templates = templates;
537
+ const importsPath = join(destDir, "css/_imports.css");
538
+ const importRules = [];
539
+ for (const factory of generationResults.imports) {
540
+ const sourceFile = factory._path;
541
+ if (!sourceFile) continue;
542
+ for (const spec of factory._current) {
543
+ try {
544
+ const { rule } = resolveImport(spec, sourceFile, destDir);
545
+ importRules.push(rule);
546
+ } catch (e) {
547
+ const url = typeof spec === "string" ? spec : spec.url;
548
+ logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
549
+ }
550
+ }
551
+ }
552
+ writeFileSync(importsPath, importRules.join("\n"));
496
553
  const configTemplateFactories = config.templates ? [defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
497
554
  const templateFactories = mergeFactories(generationResults.templates, configTemplateFactories);
498
555
  configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
@@ -526,7 +583,8 @@ ${css}
526
583
  let currentFile = readFileSync(sourceFilePath, "utf8");
527
584
  currentFile = this.replaceStyledTag(currentFile);
528
585
  currentFile = this.addConfigCache(currentFile);
529
- const outputFilePath = join(outputDirectory, "js", hashedName + ".js");
586
+ const currentFileHash = toHash(currentFile);
587
+ const outputFilePath = join(outputDirectory, "js", `${hashedName}-${currentFileHash}.js`);
530
588
  const rcProject = await this.getRCProjectConfig(this.projectRootDir);
531
589
  const coreConfigPath = join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
532
590
  const externalModules = this.getExternalModules(coreConfigPath);
@@ -670,11 +728,13 @@ ${newContent}
670
728
  });
671
729
  });
672
730
  this.projectRootDir = projectRootDir;
731
+ this.options = options;
673
732
  if (typeof process === "undefined") {
674
733
  throw new Error("SaltyServer can only be used in a Node.js environment.");
675
734
  }
676
735
  }
677
736
  get isProduction() {
737
+ if (this.options.mode) return this.options.mode === "production";
678
738
  try {
679
739
  return process.env["NODE_ENV"] !== "development";
680
740
  } catch {
package/config/index.cjs CHANGED
@@ -6,8 +6,10 @@ const defineConfig = (config) => {
6
6
  return config;
7
7
  };
8
8
  exports.GlobalStylesFactory = factories_index.GlobalStylesFactory;
9
+ exports.ImportFactory = factories_index.ImportFactory;
9
10
  exports.VariablesFactory = factories_index.VariablesFactory;
10
11
  exports.defineGlobalStyles = factories_index.defineGlobalStyles;
12
+ exports.defineImport = factories_index.defineImport;
11
13
  exports.defineMediaQuery = factories_index.defineMediaQuery;
12
14
  exports.defineVariables = factories_index.defineVariables;
13
15
  exports.TemplateFactory = defineTemplates.TemplateFactory;
package/config/index.js CHANGED
@@ -1,15 +1,17 @@
1
- import { GlobalStylesFactory, VariablesFactory, defineGlobalStyles, defineMediaQuery, defineVariables } from "../factories/index.js";
1
+ import { GlobalStylesFactory, ImportFactory, VariablesFactory, 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
7
  GlobalStylesFactory,
8
+ ImportFactory,
8
9
  T as TemplateFactory,
9
10
  a as TemplatesFactory,
10
11
  VariablesFactory,
11
12
  defineConfig,
12
13
  defineGlobalStyles,
14
+ defineImport,
13
15
  defineMediaQuery,
14
16
  d as defineTemplates,
15
17
  defineVariables
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-CA3TP5n1.cjs");
3
+ const parseStyles = require("../parse-styles-C54MOrPg.cjs");
4
4
  const toHash = require("../to-hash-C05Y906F.cjs");
5
5
  const cache_resolveDynamicConfigCache = require("../cache/resolve-dynamic-config-cache.cjs");
6
6
  const getDynamicStylesClassName = (styles) => {
@@ -1,4 +1,4 @@
1
- import { a as parseStyles } from "../parse-styles-BTIoYnBr.js";
1
+ import { a as parseStyles } from "../parse-styles-CLMTHo2H.js";
2
2
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
3
3
  import { resolveDynamicConfigCache } from "../cache/resolve-dynamic-config-cache.js";
4
4
  const getDynamicStylesClassName = (styles) => {
package/css/keyframes.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-CA3TP5n1.cjs");
3
+ const parseStyles = require("../parse-styles-C54MOrPg.cjs");
4
4
  const toHash = require("../to-hash-C05Y906F.cjs");
5
5
  const keyframes = ({ animationName: _name, params: _params, appendInitialStyles, ...keyframes2 }) => {
6
6
  const modifyKeyframes = async (params = {}) => {
package/css/keyframes.js CHANGED
@@ -1,4 +1,4 @@
1
- import { p as parseAndJoinStyles } from "../parse-styles-BTIoYnBr.js";
1
+ import { p as parseAndJoinStyles } from "../parse-styles-CLMTHo2H.js";
2
2
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
3
3
  const keyframes = ({ animationName: _name, params: _params, appendInitialStyles, ...keyframes2 }) => {
4
4
  const modifyKeyframes = async (params = {}) => {
@@ -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;
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2
5
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
6
  const css_media = require("../css/media.cjs");
4
7
  const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
@@ -13,6 +16,20 @@ class GlobalStylesFactory {
13
16
  const defineGlobalStyles = (styles) => {
14
17
  return new GlobalStylesFactory(styles);
15
18
  };
19
+ class ImportFactory {
20
+ constructor(_current) {
21
+ __publicField(this, "_path");
22
+ this._current = _current;
23
+ }
24
+ get isDefineImport() {
25
+ return true;
26
+ }
27
+ _setPath(path) {
28
+ this._path = path;
29
+ return this;
30
+ }
31
+ }
32
+ const defineImport = (...specs) => new ImportFactory(specs);
16
33
  const defineMediaQuery = (mediaFactory) => {
17
34
  return mediaFactory(css_media.media);
18
35
  };
@@ -31,7 +48,9 @@ exports.TemplateFactory = defineTemplates.TemplateFactory;
31
48
  exports.TemplatesFactory = defineTemplates.TemplatesFactory;
32
49
  exports.defineTemplates = defineTemplates.defineTemplates;
33
50
  exports.GlobalStylesFactory = GlobalStylesFactory;
51
+ exports.ImportFactory = ImportFactory;
34
52
  exports.VariablesFactory = VariablesFactory;
35
53
  exports.defineGlobalStyles = defineGlobalStyles;
54
+ exports.defineImport = defineImport;
36
55
  exports.defineMediaQuery = defineMediaQuery;
37
56
  exports.defineVariables = defineVariables;
@@ -1,4 +1,5 @@
1
1
  export * from './define-global-styles';
2
+ export * from './define-import';
2
3
  export * from './define-media-query';
3
4
  export * from './define-variables';
4
5
  export * from './define-templates';
@@ -1,3 +1,6 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1
4
  import { media } from "../css/media.js";
2
5
  import { T, a, d } from "../define-templates-CVhhgPnd.js";
3
6
  class GlobalStylesFactory {
@@ -11,6 +14,20 @@ class GlobalStylesFactory {
11
14
  const defineGlobalStyles = (styles) => {
12
15
  return new GlobalStylesFactory(styles);
13
16
  };
17
+ class ImportFactory {
18
+ constructor(_current) {
19
+ __publicField(this, "_path");
20
+ this._current = _current;
21
+ }
22
+ get isDefineImport() {
23
+ return true;
24
+ }
25
+ _setPath(path) {
26
+ this._path = path;
27
+ return this;
28
+ }
29
+ }
30
+ const defineImport = (...specs) => new ImportFactory(specs);
14
31
  const defineMediaQuery = (mediaFactory) => {
15
32
  return mediaFactory(media);
16
33
  };
@@ -27,10 +44,12 @@ const defineVariables = (variables) => {
27
44
  };
28
45
  export {
29
46
  GlobalStylesFactory,
47
+ ImportFactory,
30
48
  T as TemplateFactory,
31
49
  a as TemplatesFactory,
32
50
  VariablesFactory,
33
51
  defineGlobalStyles,
52
+ defineImport,
34
53
  defineMediaQuery,
35
54
  d as defineTemplates,
36
55
  defineVariables
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const classNameGenerator = require("../class-name-generator-B2Pb2obX.cjs");
3
+ const classNameGenerator = require("../class-name-generator-DB5aQwC_.cjs");
4
4
  const dashCase = require("../dash-case-DIwKaYgE.cjs");
5
5
  class StyledGenerator extends classNameGenerator.StylesGenerator {
6
6
  constructor(tagName, _params) {
@@ -1,5 +1,5 @@
1
- import { S as StylesGenerator } from "../class-name-generator-YeSQe_Ik.js";
2
- import { C } from "../class-name-generator-YeSQe_Ik.js";
1
+ import { S as StylesGenerator } from "../class-name-generator-CMWY5KTJ.js";
2
+ import { C } from "../class-name-generator-CMWY5KTJ.js";
3
3
  import { d as dashCase } from "../dash-case-DblXvymC.js";
4
4
  class StyledGenerator extends StylesGenerator {
5
5
  constructor(tagName, _params) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const classNameGenerator = require("../class-name-generator-B2Pb2obX.cjs");
3
+ const classNameGenerator = require("../class-name-generator-DB5aQwC_.cjs");
4
4
  const classNameInstance = (params) => {
5
5
  const generator = new classNameGenerator.ClassNameGenerator(params);
6
6
  const createClass = (classNameStr) => {
@@ -1,4 +1,4 @@
1
- import { C as ClassNameGenerator } from "../class-name-generator-YeSQe_Ik.js";
1
+ import { C as ClassNameGenerator } from "../class-name-generator-CMWY5KTJ.js";
2
2
  const classNameInstance = (params) => {
3
3
  const generator = new ClassNameGenerator(params);
4
4
  const createClass = (classNameStr) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salty-css/core",
3
- "version": "0.1.0-alpha.9",
3
+ "version": "0.1.0-feat-define-import.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "typings": "./dist/index.d.ts",
@@ -21,7 +21,7 @@ const parseValueTokens = (tokenNames) => (value) => {
21
21
  const hasToken = /\{[^{}]+\}/g.test(value);
22
22
  if (!hasToken) return void 0;
23
23
  const transformed = value.replace(/\{([^{}]+)\}/g, (...args) => {
24
- const variable = dashCase.dashCase(args[1].replaceAll(".", "-"));
24
+ const variable = dashCase.dashCase(args[1].trim().replaceAll(".", "-"));
25
25
  if (tokenNames && !tokenNames.includes(variable)) console.warn(`Token ${variable} might not exist`);
26
26
  if (variable.startsWith("-")) return `-${variable}`;
27
27
  return `var(--${variable})`;
@@ -75,22 +75,44 @@ const addUnit = (key, value, config) => {
75
75
  return `${value}`;
76
76
  };
77
77
  const vendorPrefixes = ["Webkit", "Moz", "ms", "O"];
78
+ const isVendorPrefixed = (key) => {
79
+ return vendorPrefixes.some((prefix) => {
80
+ if (!key.startsWith(prefix)) return false;
81
+ const next = key.charAt(prefix.length);
82
+ return next >= "A" && next <= "Z";
83
+ });
84
+ };
78
85
  const propertyNameCheck = (key) => {
79
86
  if (key.startsWith("-")) return key;
80
- if (vendorPrefixes.some((prefix) => key.startsWith(prefix))) return `-${dashCase.dashCase(key)}`;
87
+ if (isVendorPrefixed(key)) return `-${dashCase.dashCase(key)}`;
81
88
  return dashCase.dashCase(key);
82
89
  };
90
+ const reportParserIssue = (strict, message) => {
91
+ if (strict === true) throw new Error(`[salty-css] ${message}`);
92
+ if (strict === "warn") console.warn(`[salty-css] ${message}`);
93
+ };
94
+ const pseudoTypoRegex = /^&(hover|focus(-(visible|within))?|active|visited|checked|disabled|enabled|empty|target|first-child|last-child|first-of-type|last-of-type|placeholder|placeholder-shown|root)\b/;
95
+ const templateLiteralLeftoverRegex = /\$\{[^}]+\}/;
96
+ const bareAtRuleRegex = /^@(media|supports|container|layer)\s*$/;
83
97
  const parseStyles = async (styles, currentScope = "", config, omitTemplates = false) => {
84
98
  if (!styles) throw new Error("No styles provided to parseStyles function!");
85
99
  const cssStyles = /* @__PURE__ */ new Set();
86
100
  const entries = Object.entries(styles);
101
+ const strict = config == null ? void 0 : config.strict;
87
102
  const processStyleEntry = async ([key, value]) => {
88
103
  var _a, _b;
89
104
  const _key = key.trim().replace(/^\?+/g, "");
90
105
  const propertyName = propertyNameCheck(_key);
91
106
  const toString = (val, eol = ";") => `${propertyName}:${val}${eol}`;
92
107
  const context = { scope: currentScope, config };
93
- if (typeof value === "function") return processStyleEntry([key, value(context)]);
108
+ if (typeof value === "function") {
109
+ try {
110
+ return await processStyleEntry([key, value(context)]);
111
+ } catch (error) {
112
+ reportParserIssue(strict, `Function value for "${_key}" threw: ${(error == null ? void 0 : error.message) ?? error}`);
113
+ return void 0;
114
+ }
115
+ }
94
116
  if (value instanceof Promise) return processStyleEntry([key, await value]);
95
117
  if ((config == null ? void 0 : config.templates) && ((_a = config.templatePaths) == null ? void 0 : _a[_key])) {
96
118
  try {
@@ -124,6 +146,11 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
124
146
  console.warn(`Template "${_key}" with path of "${value}" was not found in config!`);
125
147
  return void 0;
126
148
  }
149
+ const isVariantArrayKey = _key === "compoundVariants" || _key === "anyOfVariants";
150
+ if (!isVariantArrayKey && Array.isArray(value)) {
151
+ if (value.length === 0) return void 0;
152
+ return processStyleEntry([key, value.join(", ")]);
153
+ }
127
154
  if (typeof value === "object") {
128
155
  if (!value) return void 0;
129
156
  if (value.isColor) return toString(value.toString());
@@ -160,31 +187,62 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
160
187
  return `.${prop}-${val}`;
161
188
  });
162
189
  const scope2 = `${currentScope}:where(${scopes.join(", ")})`;
163
- console.log(`Union variant scope: ${scope2}`);
164
190
  const results2 = await parseStyles(css2, scope2, config);
165
191
  results2.forEach((res) => cssStyles.add(res));
166
192
  }
167
193
  return void 0;
168
194
  }
169
195
  if (_key.startsWith("@")) {
196
+ if (bareAtRuleRegex.test(_key)) reportParserIssue(strict, `At-rule "${_key}" is missing its condition (e.g. "@media (min-width: 600px)").`);
170
197
  const mediaQuery = ((_b = config == null ? void 0 : config.mediaQueries) == null ? void 0 : _b[_key]) || _key;
171
198
  const results2 = await parseAndJoinStyles(value, currentScope, config);
172
199
  const query = `${mediaQuery} { ${results2} }`;
173
200
  cssStyles.add(query);
174
201
  return void 0;
175
202
  }
176
- const scope = key.includes("&") ? _key.replaceAll("&", currentScope) : _key.startsWith(":") ? `${currentScope}${_key}` : `${currentScope} ${_key}`;
203
+ if (Object.keys(value).length === 0) return void 0;
204
+ if (pseudoTypoRegex.test(_key)) {
205
+ reportParserIssue(strict, `Selector "${_key}" looks like a missing-colon typo (did you mean "&:${_key.slice(1)}"?).`);
206
+ }
207
+ const scope = combineSelectors(currentScope, _key);
177
208
  const results = await parseStyles(value, scope, config);
178
209
  results.forEach((result) => cssStyles.add(result));
179
210
  return void 0;
180
211
  }
212
+ if (_key.startsWith("$")) {
213
+ reportParserIssue(strict, `Property key "${_key}" looks like a SCSS variable — Salty does not support those.`);
214
+ return void 0;
215
+ }
216
+ if (_key.includes(":")) {
217
+ reportParserIssue(strict, `Property key "${_key}" contains a colon — did you accidentally paste a whole declaration as a key?`);
218
+ return void 0;
219
+ }
220
+ if (value === void 0 || value === null) {
221
+ reportParserIssue(strict, `Property "${_key}" has a ${value === void 0 ? "undefined" : "null"} value — skipping.`);
222
+ return void 0;
223
+ }
224
+ if (typeof value === "boolean") {
225
+ reportParserIssue(strict, `Property "${_key}" has a boolean value (${value}) — skipping.`);
226
+ return void 0;
227
+ }
228
+ if (value === "") return void 0;
181
229
  if (typeof value === "number") {
230
+ if (!Number.isFinite(value)) {
231
+ reportParserIssue(strict, `Property "${_key}" has a non-finite numeric value (${value}) — skipping.`);
232
+ return void 0;
233
+ }
182
234
  const withUnit = addUnit(propertyName, value, config);
183
235
  return toString(withUnit);
184
236
  }
185
237
  if (typeof value !== "string") {
186
- if ("toString" in value) value = value.toString();
187
- else throw new Error(`Invalid value type for property ${propertyName}`);
238
+ if (value && typeof value === "object" && "toString" in value) value = value.toString();
239
+ else {
240
+ reportParserIssue(strict, `Property "${_key}" has an unsupported value type (${typeof value}) — skipping.`);
241
+ return void 0;
242
+ }
243
+ }
244
+ if (typeof value === "string" && templateLiteralLeftoverRegex.test(value)) {
245
+ reportParserIssue(strict, `Property "${_key}" value "${value}" contains an unresolved \`\${...}\` — did you forget to interpolate?`);
188
246
  }
189
247
  return toString(value);
190
248
  };
@@ -224,8 +282,49 @@ const parseAndJoinStyles = async (styles, currentClass, config, omitTemplates =
224
282
  const css = await parseStyles(styles, currentClass, config, omitTemplates);
225
283
  return css.join("\n");
226
284
  };
285
+ const splitTopLevelCommas = (selector) => {
286
+ const parts = [];
287
+ let depth = 0;
288
+ let buf = "";
289
+ for (const ch of selector) {
290
+ if (ch === "(" || ch === "[") depth++;
291
+ else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
292
+ if (ch === "," && depth === 0) {
293
+ const trimmed2 = buf.trim();
294
+ if (trimmed2) parts.push(trimmed2);
295
+ buf = "";
296
+ } else {
297
+ buf += ch;
298
+ }
299
+ }
300
+ const trimmed = buf.trim();
301
+ if (trimmed) parts.push(trimmed);
302
+ return parts;
303
+ };
304
+ const joinSelector = (parent, child) => {
305
+ if (child.includes("&")) return child.replaceAll("&", parent);
306
+ if (child.startsWith(":")) return `${parent}${child}`;
307
+ return `${parent} ${child}`;
308
+ };
309
+ const combineSelectors = (currentScope, key) => {
310
+ if (!currentScope) return key;
311
+ const parents = splitTopLevelCommas(currentScope);
312
+ const children = splitTopLevelCommas(key);
313
+ if (!children.length) return currentScope;
314
+ if (parents.length <= 1 && children.length <= 1) {
315
+ return joinSelector(parents[0] ?? currentScope, children[0]);
316
+ }
317
+ const combos = [];
318
+ for (const p of parents) {
319
+ for (const c of children) {
320
+ combos.push(joinSelector(p, c));
321
+ }
322
+ }
323
+ return combos.join(", ");
324
+ };
227
325
  exports.parseAndJoinStyles = parseAndJoinStyles;
228
326
  exports.parseStyles = parseStyles;
229
327
  exports.parseValueModifiers = parseValueModifiers;
230
328
  exports.parseValueTokens = parseValueTokens;
231
329
  exports.parseVariableTokens = parseVariableTokens;
330
+ exports.reportParserIssue = reportParserIssue;