@bamboocss/config
Advanced tools
+186
-2
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| const require_diff_config = require("./diff-config-Co_3mDXE.cjs"); | ||
| exports.diffConfigs = require_diff_config.diffConfigs; | ||
| //#region \0rolldown/runtime.js | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| let _bamboocss_shared = require("@bamboocss/shared"); | ||
| let microdiff = require("microdiff"); | ||
| microdiff = __toESM(microdiff); | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = (0, microdiff.default)(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| exports.diffConfigs = diffConfigs; |
+162
-1
@@ -1,2 +0,163 @@ | ||
| import { t as diffConfigs } from "./diff-config-KDQWMnQN.mjs"; | ||
| import { dashCase } from "@bamboocss/shared"; | ||
| import microdiff from "microdiff"; | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = microdiff(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = dashCase(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = dashCase(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| export { diffConfigs }; |
+492
-27
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| const require_diff_config = require("./diff-config-Co_3mDXE.cjs"); | ||
| const require_resolve_ts_path_pattern = require("./resolve-ts-path-pattern.cjs"); | ||
| const require_merge_config = require("./merge-config-CcNpHJit.cjs"); | ||
| //#region \0rolldown/runtime.js | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| let _bamboocss_logger = require("@bamboocss/logger"); | ||
@@ -9,9 +28,11 @@ let _bamboocss_shared = require("@bamboocss/shared"); | ||
| let escalade_sync = require("escalade/sync"); | ||
| escalade_sync = require_diff_config.__toESM(escalade_sync); | ||
| escalade_sync = __toESM(escalade_sync); | ||
| let path = require("path"); | ||
| path = require_diff_config.__toESM(path); | ||
| path = __toESM(path); | ||
| let microdiff = require("microdiff"); | ||
| microdiff = __toESM(microdiff); | ||
| let fs = require("fs"); | ||
| fs = require_diff_config.__toESM(fs); | ||
| fs = __toESM(fs); | ||
| let typescript = require("typescript"); | ||
| typescript = require_diff_config.__toESM(typescript); | ||
| typescript = __toESM(typescript); | ||
| let _bamboocss_preset_base = require("@bamboocss/preset-base"); | ||
@@ -69,2 +90,179 @@ let _bamboocss_preset_bamboo = require("@bamboocss/preset-bamboo"); | ||
| //#endregion | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = (0, microdiff.default)(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| //#region src/resolve-ts-path-pattern.ts | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/index.ts#LL231C57-L231C57 | ||
| */ | ||
| const resolveTsPathPattern = (pathMappings, moduleSpecifier) => { | ||
| for (const mapping of pathMappings) { | ||
| const match = moduleSpecifier.match(mapping.pattern); | ||
| if (!match) continue; | ||
| for (const pathTemplate of mapping.paths) { | ||
| let starCount = 0; | ||
| return pathTemplate.replace(/\*/g, () => { | ||
| return match[Math.min(++starCount, match.length - 1)]; | ||
| }).split(path.sep).join(path.posix.sep); | ||
| } | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/ts-config-paths.ts | ||
@@ -175,3 +373,3 @@ /** | ||
| if (!opts.pathMappings) return; | ||
| const filename = require_resolve_ts_path_pattern.resolveTsPathPattern(opts.pathMappings, mod); | ||
| const filename = resolveTsPathPattern(opts.pathMappings, mod); | ||
| if (!filename) return; | ||
@@ -206,2 +404,269 @@ getDeps(Object.assign({}, nextOpts, { filename }), mod); | ||
| //#endregion | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| _bamboocss_logger.logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const REFERENCE_REGEX = /({([^}]*)})/g; | ||
| const curlyBracketRegex = /[{}]/g; | ||
| const isValidToken = (token) => (0, _bamboocss_shared.isObject)(token) && Object.hasOwnProperty.call(token, "value"); | ||
| const isTokenReference = (value) => typeof value === "string" && REFERENCE_REGEX.test(value); | ||
| const formatPath = (path) => path; | ||
| function getReferences(value) { | ||
| if (typeof value !== "string") return []; | ||
| const matches = value.match(REFERENCE_REGEX); | ||
| if (!matches) return []; | ||
| return matches.map((match) => match.replace(curlyBracketRegex, "")).map((value) => { | ||
| return value.trim().split("/")[0]; | ||
| }); | ||
| } | ||
| const serializeTokenValue = (value) => { | ||
| if ((0, _bamboocss_shared.isString)(value)) return value; | ||
| if ((0, _bamboocss_shared.isObject)(value)) return Object.values(value).map((v) => serializeTokenValue(v)).join(" "); | ||
| if (Array.isArray(value)) return value.map((v) => serializeTokenValue(v)).join(" "); | ||
| return value.toString(); | ||
| }; | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return (0, _bamboocss_shared.mergeWith)(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => (0, _bamboocss_shared.assign)(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return (0, _bamboocss_shared.mergeWith)(restProps, extend, (obj, extensions) => { | ||
| return (0, _bamboocss_shared.mergeAndConcat)({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: _bamboocss_shared.BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact((0, _bamboocss_shared.assign)({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) (0, _bamboocss_shared.walkObject)(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| //#region src/get-resolved-config.ts | ||
@@ -244,3 +709,3 @@ const hookUtils$1 = { | ||
| } | ||
| const merged = require_merge_config.mergeConfigs(configs); | ||
| const merged = mergeConfigs(configs); | ||
| merged.presets = configs.slice(0, -1); | ||
@@ -360,3 +825,3 @@ return merged; | ||
| } | ||
| if (require_merge_config.isTokenReference(value) && !refsByPath.has(value)) addError("tokens", `Unknown token reference: \`${currentPath}\` used in \`${value}\``); | ||
| if (isTokenReference(value) && !refsByPath.has(value)) addError("tokens", `Unknown token reference: \`${currentPath}\` used in \`${value}\``); | ||
| const deps = refsByPath.get(currentPath); | ||
@@ -388,8 +853,8 @@ if (!deps) continue; | ||
| if (path.includes("DEFAULT")) valueAtPath.set(path.replace(".DEFAULT", ""), value); | ||
| }, { stop: require_merge_config.isValidToken }); | ||
| }, { stop: isValidToken }); | ||
| tokenPaths.forEach((path) => { | ||
| const itemValue = valueAtPath.get(path); | ||
| const formattedPath = require_merge_config.formatPath(path); | ||
| const formattedPath = formatPath(path); | ||
| typeByPath.set(formattedPath, "tokens"); | ||
| if (!require_merge_config.isValidToken(itemValue)) { | ||
| if (!isValidToken(itemValue)) { | ||
| addError("tokens", `Token must contain 'value': \`theme.tokens.${formattedPath}\``); | ||
@@ -402,7 +867,7 @@ return; | ||
| } | ||
| const valueStr = require_merge_config.serializeTokenValue(itemValue.value || itemValue); | ||
| if (require_merge_config.isTokenReference(valueStr)) refsByPath.set(formattedPath, /* @__PURE__ */ new Set([])); | ||
| const valueStr = serializeTokenValue(itemValue.value || itemValue); | ||
| if (isTokenReference(valueStr)) refsByPath.set(formattedPath, /* @__PURE__ */ new Set([])); | ||
| const references = refsByPath.get(formattedPath); | ||
| if (!references) return; | ||
| require_merge_config.getReferences(valueStr).forEach((reference) => { | ||
| getReferences(valueStr).forEach((reference) => { | ||
| references.add(reference); | ||
@@ -420,15 +885,15 @@ }); | ||
| if (path.includes("DEFAULT")) valueAtPath.set(path.replace(".DEFAULT", ""), value); | ||
| if (!require_merge_config.isValidToken(value)) return; | ||
| if (!isValidToken(value)) return; | ||
| (0, _bamboocss_shared.walkObject)(value, (itemValue, paths) => { | ||
| const valuePath = paths.join("."); | ||
| const formattedPath = require_merge_config.formatPath(path); | ||
| const formattedPath = formatPath(path); | ||
| typeByPath.set(formattedPath, "semanticTokens"); | ||
| const fullPath = formattedPath + "." + paths.join("."); | ||
| if (valuePath.includes("value.value")) addError("tokens", `You used \`value\` twice resulting in an invalid token \`theme.tokens.${fullPath}\``); | ||
| const valueStr = require_merge_config.serializeTokenValue(itemValue.value || itemValue); | ||
| if (require_merge_config.isTokenReference(valueStr)) { | ||
| const valueStr = serializeTokenValue(itemValue.value || itemValue); | ||
| if (isTokenReference(valueStr)) { | ||
| if (!refsByPath.has(formattedPath)) refsByPath.set(formattedPath, /* @__PURE__ */ new Set()); | ||
| const references = refsByPath.get(formattedPath); | ||
| if (!references) return; | ||
| require_merge_config.getReferences(valueStr).forEach((reference) => { | ||
| getReferences(valueStr).forEach((reference) => { | ||
| references.add(reference); | ||
@@ -438,5 +903,5 @@ }); | ||
| }); | ||
| }, { stop: require_merge_config.isValidToken }); | ||
| }, { stop: isValidToken }); | ||
| tokenPaths.forEach((path) => { | ||
| const formattedPath = require_merge_config.formatPath(path); | ||
| const formattedPath = formatPath(path); | ||
| const value = valueAtPath.get(path); | ||
@@ -537,3 +1002,3 @@ if (path.includes(" ")) { | ||
| }); | ||
| const earlyHooks = require_merge_config.mergeHooks(pluginHooks); | ||
| const earlyHooks = mergeHooks(pluginHooks); | ||
| const mergedConfig = await getResolvedConfig(result.config, cwd, earlyHooks); | ||
@@ -579,3 +1044,3 @@ const hooks = mergedConfig.hooks ?? {}; | ||
| exports.convertTsPathsToRegexes = convertTsPathsToRegexes; | ||
| exports.diffConfigs = require_diff_config.diffConfigs; | ||
| exports.diffConfigs = diffConfigs; | ||
| exports.findConfig = findConfig; | ||
@@ -585,4 +1050,4 @@ exports.getConfigDependencies = getConfigDependencies; | ||
| exports.loadConfig = loadConfig; | ||
| exports.mergeConfigs = require_merge_config.mergeConfigs; | ||
| exports.mergeHooks = require_merge_config.mergeHooks; | ||
| exports.mergeConfigs = mergeConfigs; | ||
| exports.mergeHooks = mergeHooks; | ||
| exports.resolveConfig = resolveConfig; |
+34
-7
@@ -1,5 +0,2 @@ | ||
| import { diffConfigs } from "./diff-config.cjs"; | ||
| import { n as convertTsPathsToRegexes, t as PathMapping } from "./ts-config-paths-wVx39QZ0.cjs"; | ||
| import { n as mergeHooks, t as mergeConfigs } from "./merge-config-DVOlBQJY.cjs"; | ||
| import { BambooHooks, Config, ConfigTsOptions, LoadConfigResult as LoadConfigResult$1 } from "@bamboocss/types"; | ||
| import { BambooHooks as BambooHooks$1, BambooPlugin, Config, ConfigTsOptions, DiffConfigResult, LoadConfigResult as LoadConfigResult$1 } from "@bamboocss/types"; | ||
| import { CompilerOptions, TypeAcquisition } from "typescript"; | ||
@@ -21,2 +18,9 @@ | ||
| //#endregion | ||
| //#region src/diff-config.d.ts | ||
| type ConfigOrFn = Config | (() => Config); | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| declare function diffConfigs(config: ConfigOrFn, prevConfig: Config | undefined): DiffConfigResult; | ||
| //#endregion | ||
| //#region src/find-config.d.ts | ||
@@ -45,2 +49,12 @@ declare function findConfig(options: Partial<ConfigFileOptions>): string; | ||
| //#endregion | ||
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/mappings.ts | ||
| */ | ||
| declare function convertTsPathsToRegexes(paths: Record<string, string[]>, baseUrl: string): PathMapping[]; | ||
| //#endregion | ||
| //#region src/get-mod-deps.d.ts | ||
@@ -63,10 +77,10 @@ interface GetDepsOptions { | ||
| //#region src/get-resolved-config.d.ts | ||
| type Extendable<T> = T & { | ||
| type Extendable$1<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| type ExtendableConfig$1 = Extendable$1<Config>; | ||
| /** | ||
| * Recursively merge all presets into a single config (depth-first using stack) | ||
| */ | ||
| declare function getResolvedConfig(config: ExtendableConfig, cwd: string, hooks?: Partial<BambooHooks>): Promise<Config>; | ||
| declare function getResolvedConfig(config: ExtendableConfig$1, cwd: string, hooks?: Partial<BambooHooks$1>): Promise<Config>; | ||
| //#endregion | ||
@@ -87,2 +101,15 @@ //#region src/load-config.d.ts | ||
| //#endregion | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { type BundleConfigResult, type GetDepsOptions, bundleConfig, convertTsPathsToRegexes, diffConfigs, findConfig, getConfigDependencies, getResolvedConfig, loadConfig, mergeConfigs, mergeHooks, resolveConfig }; |
+34
-7
@@ -1,6 +0,3 @@ | ||
| import { diffConfigs } from "./diff-config.mjs"; | ||
| import { n as convertTsPathsToRegexes, t as PathMapping } from "./ts-config-paths-CvGId8kq.mjs"; | ||
| import { n as mergeHooks, t as mergeConfigs } from "./merge-config-oEiBYbfB.mjs"; | ||
| import { CompilerOptions, TypeAcquisition } from "typescript"; | ||
| import { BambooHooks, Config, ConfigTsOptions, LoadConfigResult as LoadConfigResult$1 } from "@bamboocss/types"; | ||
| import { BambooHooks as BambooHooks$1, BambooPlugin, Config, ConfigTsOptions, DiffConfigResult, LoadConfigResult as LoadConfigResult$1 } from "@bamboocss/types"; | ||
@@ -21,2 +18,9 @@ //#region src/types.d.ts | ||
| //#endregion | ||
| //#region src/diff-config.d.ts | ||
| type ConfigOrFn = Config | (() => Config); | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| declare function diffConfigs(config: ConfigOrFn, prevConfig: Config | undefined): DiffConfigResult; | ||
| //#endregion | ||
| //#region src/find-config.d.ts | ||
@@ -45,2 +49,12 @@ declare function findConfig(options: Partial<ConfigFileOptions>): string; | ||
| //#endregion | ||
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/mappings.ts | ||
| */ | ||
| declare function convertTsPathsToRegexes(paths: Record<string, string[]>, baseUrl: string): PathMapping[]; | ||
| //#endregion | ||
| //#region src/get-mod-deps.d.ts | ||
@@ -63,10 +77,10 @@ interface GetDepsOptions { | ||
| //#region src/get-resolved-config.d.ts | ||
| type Extendable<T> = T & { | ||
| type Extendable$1<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| type ExtendableConfig$1 = Extendable$1<Config>; | ||
| /** | ||
| * Recursively merge all presets into a single config (depth-first using stack) | ||
| */ | ||
| declare function getResolvedConfig(config: ExtendableConfig, cwd: string, hooks?: Partial<BambooHooks>): Promise<Config>; | ||
| declare function getResolvedConfig(config: ExtendableConfig$1, cwd: string, hooks?: Partial<BambooHooks$1>): Promise<Config>; | ||
| //#endregion | ||
@@ -87,2 +101,15 @@ //#region src/load-config.d.ts | ||
| //#endregion | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { type BundleConfigResult, type GetDepsOptions, bundleConfig, convertTsPathsToRegexes, diffConfigs, findConfig, getConfigDependencies, getResolvedConfig, loadConfig, mergeConfigs, mergeHooks, resolveConfig }; |
+447
-5
@@ -1,9 +0,7 @@ | ||
| import { t as diffConfigs } from "./diff-config-KDQWMnQN.mjs"; | ||
| import { resolveTsPathPattern } from "./resolve-ts-path-pattern.mjs"; | ||
| import { a as isValidToken, i as isTokenReference, n as formatPath, o as serializeTokenValue, r as getReferences, s as mergeHooks, t as mergeConfigs } from "./merge-config-DI__LOWx.mjs"; | ||
| import { logger } from "@bamboocss/logger"; | ||
| import { BAMBOO_CONFIG_NAME, BambooError, getUnit, isObject, isString, omit, parseJson, pick, stringifyJson, traverse, walkObject } from "@bamboocss/shared"; | ||
| import { BAMBOO_CONFIG_NAME, BambooError, assign, dashCase, getUnit, isObject, isString, mergeAndConcat, mergeWith, omit, parseJson, pick, stringifyJson, traverse, walkObject } from "@bamboocss/shared"; | ||
| import { bundleNRequire } from "bundle-n-require"; | ||
| import findUp from "escalade/sync"; | ||
| import path, { resolve } from "path"; | ||
| import path, { posix, resolve, sep } from "path"; | ||
| import microdiff from "microdiff"; | ||
| import fs from "fs"; | ||
@@ -63,2 +61,179 @@ import ts from "typescript"; | ||
| //#endregion | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = microdiff(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = dashCase(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = dashCase(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| //#region src/resolve-ts-path-pattern.ts | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/index.ts#LL231C57-L231C57 | ||
| */ | ||
| const resolveTsPathPattern = (pathMappings, moduleSpecifier) => { | ||
| for (const mapping of pathMappings) { | ||
| const match = moduleSpecifier.match(mapping.pattern); | ||
| if (!match) continue; | ||
| for (const pathTemplate of mapping.paths) { | ||
| let starCount = 0; | ||
| return pathTemplate.replace(/\*/g, () => { | ||
| return match[Math.min(++starCount, match.length - 1)]; | ||
| }).split(sep).join(posix.sep); | ||
| } | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/ts-config-paths.ts | ||
@@ -199,2 +374,269 @@ /** | ||
| //#endregion | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const REFERENCE_REGEX = /({([^}]*)})/g; | ||
| const curlyBracketRegex = /[{}]/g; | ||
| const isValidToken = (token) => isObject(token) && Object.hasOwnProperty.call(token, "value"); | ||
| const isTokenReference = (value) => typeof value === "string" && REFERENCE_REGEX.test(value); | ||
| const formatPath = (path) => path; | ||
| function getReferences(value) { | ||
| if (typeof value !== "string") return []; | ||
| const matches = value.match(REFERENCE_REGEX); | ||
| if (!matches) return []; | ||
| return matches.map((match) => match.replace(curlyBracketRegex, "")).map((value) => { | ||
| return value.trim().split("/")[0]; | ||
| }); | ||
| } | ||
| const serializeTokenValue = (value) => { | ||
| if (isString(value)) return value; | ||
| if (isObject(value)) return Object.values(value).map((v) => serializeTokenValue(v)).join(" "); | ||
| if (Array.isArray(value)) return value.map((v) => serializeTokenValue(v)).join(" "); | ||
| return value.toString(); | ||
| }; | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return mergeWith(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => assign(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return mergeWith(restProps, extend, (obj, extensions) => { | ||
| return mergeAndConcat({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact(assign({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) walkObject(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| //#region src/get-resolved-config.ts | ||
@@ -201,0 +643,0 @@ const hookUtils$1 = { |
+253
-3
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| const require_merge_config = require("./merge-config-CcNpHJit.cjs"); | ||
| exports.mergeConfigs = require_merge_config.mergeConfigs; | ||
| exports.mergeHooks = require_merge_config.mergeHooks; | ||
| let _bamboocss_shared = require("@bamboocss/shared"); | ||
| let _bamboocss_logger = require("@bamboocss/logger"); | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| _bamboocss_logger.logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const isValidToken = (token) => (0, _bamboocss_shared.isObject)(token) && Object.hasOwnProperty.call(token, "value"); | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return (0, _bamboocss_shared.mergeWith)(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => (0, _bamboocss_shared.assign)(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return (0, _bamboocss_shared.mergeWith)(restProps, extend, (obj, extensions) => { | ||
| return (0, _bamboocss_shared.mergeAndConcat)({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: _bamboocss_shared.BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact((0, _bamboocss_shared.assign)({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) (0, _bamboocss_shared.walkObject)(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| exports.mergeConfigs = mergeConfigs; | ||
| exports.mergeHooks = mergeHooks; |
@@ -1,2 +0,16 @@ | ||
| import { n as mergeHooks, t as mergeConfigs } from "./merge-config-DVOlBQJY.cjs"; | ||
| import { BambooPlugin, Config } from "@bamboocss/types"; | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { mergeConfigs, mergeHooks }; |
@@ -1,2 +0,16 @@ | ||
| import { n as mergeHooks, t as mergeConfigs } from "./merge-config-oEiBYbfB.mjs"; | ||
| import { BambooPlugin, Config } from "@bamboocss/types"; | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { mergeConfigs, mergeHooks }; |
+251
-1
@@ -1,2 +0,252 @@ | ||
| import { s as mergeHooks, t as mergeConfigs } from "./merge-config-DI__LOWx.mjs"; | ||
| import { BAMBOO_CONFIG_NAME, assign, isObject, mergeAndConcat, mergeWith, walkObject } from "@bamboocss/shared"; | ||
| import { logger } from "@bamboocss/logger"; | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const isValidToken = (token) => isObject(token) && Object.hasOwnProperty.call(token, "value"); | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return mergeWith(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => assign(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return mergeWith(restProps, extend, (obj, extensions) => { | ||
| return mergeAndConcat({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact(assign({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) walkObject(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| export { mergeConfigs, mergeHooks }; |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| require("./diff-config-Co_3mDXE.cjs"); | ||
| let path = require("path"); | ||
@@ -4,0 +3,0 @@ //#region src/resolve-ts-path-pattern.ts |
@@ -1,3 +0,7 @@ | ||
| import { t as PathMapping } from "./ts-config-paths-wVx39QZ0.cjs"; | ||
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| //#endregion | ||
| //#region src/resolve-ts-path-pattern.d.ts | ||
@@ -4,0 +8,0 @@ /** |
@@ -1,3 +0,7 @@ | ||
| import { t as PathMapping } from "./ts-config-paths-CvGId8kq.mjs"; | ||
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| //#endregion | ||
| //#region src/resolve-ts-path-pattern.d.ts | ||
@@ -4,0 +8,0 @@ /** |
+6
-6
| { | ||
| "name": "@bamboocss/config", | ||
| "version": "1.11.4", | ||
| "version": "1.12.0", | ||
| "description": "Find and load bamboo config", | ||
@@ -67,7 +67,7 @@ "homepage": "https://bamboo-css.com", | ||
| "typescript": "6.0.2", | ||
| "@bamboocss/preset-bamboo": "1.11.4", | ||
| "@bamboocss/shared": "1.11.4", | ||
| "@bamboocss/logger": "1.11.4", | ||
| "@bamboocss/preset-base": "1.11.4", | ||
| "@bamboocss/types": "1.11.4" | ||
| "@bamboocss/logger": "1.12.0", | ||
| "@bamboocss/preset-bamboo": "1.12.0", | ||
| "@bamboocss/preset-base": "1.12.0", | ||
| "@bamboocss/shared": "1.12.0", | ||
| "@bamboocss/types": "1.12.0" | ||
| }, | ||
@@ -74,0 +74,0 @@ "devDependencies": { |
| //#region \0rolldown/runtime.js | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| let _bamboocss_shared = require("@bamboocss/shared"); | ||
| let microdiff = require("microdiff"); | ||
| microdiff = __toESM(microdiff); | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = (0, microdiff.default)(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = (0, _bamboocss_shared.dashCase)(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, "__toESM", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return __toESM; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "diffConfigs", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return diffConfigs; | ||
| } | ||
| }); |
| import { dashCase } from "@bamboocss/shared"; | ||
| import microdiff from "microdiff"; | ||
| //#region src/create-matcher.ts | ||
| /** | ||
| * Acts like a .gitignore matcher | ||
| * e.g a list of string to search for nested path with glob and exclusion allowed | ||
| * ["outdir", "theme.recipes", '*.css', '!aaa.*.bbb'] | ||
| */ | ||
| function createMatcher(id, patterns) { | ||
| if (!patterns?.length) return () => void 0; | ||
| const includePatterns = []; | ||
| const excludePatterns = []; | ||
| new Set(patterns).forEach((pattern) => { | ||
| const regexString = pattern.replace(/\*/g, ".*"); | ||
| if (pattern.startsWith("!")) excludePatterns.push(regexString.slice(1)); | ||
| else includePatterns.push(regexString); | ||
| }); | ||
| const include = new RegExp(includePatterns.join("|")); | ||
| const exclude = new RegExp(excludePatterns.join("|")); | ||
| return (path) => { | ||
| if (excludePatterns.length && exclude.test(path)) return; | ||
| return include.test(path) ? id : void 0; | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/config-deps.ts | ||
| const all = [ | ||
| "clean", | ||
| "cwd", | ||
| "eject", | ||
| "outdir", | ||
| "forceConsistentTypeExtension", | ||
| "outExtension", | ||
| "emitTokensOnly", | ||
| "presets", | ||
| "plugins", | ||
| "hooks" | ||
| ]; | ||
| const format = [ | ||
| "syntax", | ||
| "hash", | ||
| "prefix", | ||
| "separator", | ||
| "strictTokens", | ||
| "strictPropertyValues", | ||
| "shorthands" | ||
| ]; | ||
| const tokens = [ | ||
| "utilities", | ||
| "conditions", | ||
| "theme.tokens", | ||
| "theme.semanticTokens", | ||
| "theme.breakpoints", | ||
| "theme.containerNames", | ||
| "theme.containerSizes" | ||
| ]; | ||
| const jsx = [ | ||
| "jsxFramework", | ||
| "jsxFactory", | ||
| "jsxStyleProps", | ||
| "syntax" | ||
| ]; | ||
| const common = tokens.concat(jsx, format); | ||
| const artifactConfigDeps = { | ||
| helpers: ["syntax", "jsxFramework"], | ||
| keyframes: ["theme.keyframes", "layers"], | ||
| "design-tokens": ["layers", "!utilities.*.className"].concat(tokens), | ||
| types: ["!utilities.*.className"].concat(common), | ||
| "css-fn": common, | ||
| cva: ["syntax"], | ||
| sva: ["syntax"], | ||
| cx: [], | ||
| "create-recipe": [ | ||
| "separator", | ||
| "prefix", | ||
| "hash" | ||
| ], | ||
| "recipes-index": ["theme.recipes", "theme.slotRecipes"], | ||
| recipes: ["theme.recipes", "theme.slotRecipes"], | ||
| "patterns-index": ["syntax", "patterns"], | ||
| patterns: ["syntax", "patterns"], | ||
| "jsx-is-valid-prop": common, | ||
| "jsx-factory": jsx, | ||
| "jsx-helpers": jsx, | ||
| "jsx-patterns": jsx.concat("patterns"), | ||
| "jsx-patterns-index": jsx.concat("patterns"), | ||
| "jsx-create-style-context": jsx, | ||
| "css-index": ["syntax"], | ||
| "package.json": ["forceConsistentTypeExtension", "outExtension"], | ||
| "types-styles": ["shorthands"], | ||
| "types-conditions": ["conditions"], | ||
| "types-jsx": jsx, | ||
| "types-entry": [], | ||
| "types-gen": [], | ||
| "types-gen-system": [], | ||
| themes: ["themes"].concat(tokens), | ||
| "static-css": [ | ||
| "staticCss", | ||
| "patterns", | ||
| "theme.recipes", | ||
| "theme.slotRecipes" | ||
| ].concat(tokens), | ||
| styles: [], | ||
| "styles.css": [] | ||
| }; | ||
| const artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => { | ||
| if (!paths.length) return () => void 0; | ||
| return createMatcher(key, paths.concat(all)); | ||
| }); | ||
| //#endregion | ||
| //#region src/diff-config.ts | ||
| const runIfFn = (fn) => typeof fn === "function" ? fn() : fn; | ||
| /** | ||
| * Check if recipes were empty before and non-empty now (or vice versa) | ||
| */ | ||
| const hasRecipeStateTransition = (prevConfig, nextConfig) => { | ||
| const prevRecipes = prevConfig.theme?.recipes ?? {}; | ||
| const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {}; | ||
| const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0; | ||
| const nextRecipes = nextConfig.theme?.recipes ?? {}; | ||
| const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {}; | ||
| return prevHasRecipes !== (Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0); | ||
| }; | ||
| /** | ||
| * Diff the two config objects and return the list of affected properties | ||
| */ | ||
| function diffConfigs(config, prevConfig) { | ||
| const affected = { | ||
| artifacts: /* @__PURE__ */ new Set(), | ||
| hasConfigChanged: false, | ||
| diffs: [] | ||
| }; | ||
| if (!prevConfig) { | ||
| affected.hasConfigChanged = true; | ||
| return affected; | ||
| } | ||
| const configDiff = microdiff(prevConfig, runIfFn(config)); | ||
| if (!configDiff.length) return affected; | ||
| affected.hasConfigChanged = true; | ||
| affected.diffs = configDiff; | ||
| configDiff.forEach((change) => { | ||
| const changePath = change.path.join("."); | ||
| artifactMatchers.forEach((matcher) => { | ||
| const id = matcher(changePath); | ||
| if (!id) return; | ||
| if (id === "recipes") { | ||
| const name = dashCase(change.path.slice(1, 3).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| if (id === "patterns") { | ||
| const name = dashCase(change.path.slice(0, 2).join(".")); | ||
| affected.artifacts.add(name); | ||
| } | ||
| affected.artifacts.add(id); | ||
| }); | ||
| }); | ||
| if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) { | ||
| if (hasRecipeStateTransition(prevConfig, runIfFn(config))) affected.artifacts.add("create-recipe"); | ||
| } | ||
| return affected; | ||
| } | ||
| //#endregion | ||
| export { diffConfigs as t }; |
| require("./diff-config-Co_3mDXE.cjs"); | ||
| let _bamboocss_logger = require("@bamboocss/logger"); | ||
| let _bamboocss_shared = require("@bamboocss/shared"); | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| _bamboocss_logger.logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const REFERENCE_REGEX = /({([^}]*)})/g; | ||
| const curlyBracketRegex = /[{}]/g; | ||
| const isValidToken = (token) => (0, _bamboocss_shared.isObject)(token) && Object.hasOwnProperty.call(token, "value"); | ||
| const isTokenReference = (value) => typeof value === "string" && REFERENCE_REGEX.test(value); | ||
| const formatPath = (path) => path; | ||
| function getReferences(value) { | ||
| if (typeof value !== "string") return []; | ||
| const matches = value.match(REFERENCE_REGEX); | ||
| if (!matches) return []; | ||
| return matches.map((match) => match.replace(curlyBracketRegex, "")).map((value) => { | ||
| return value.trim().split("/")[0]; | ||
| }); | ||
| } | ||
| const serializeTokenValue = (value) => { | ||
| if ((0, _bamboocss_shared.isString)(value)) return value; | ||
| if ((0, _bamboocss_shared.isObject)(value)) return Object.values(value).map((v) => serializeTokenValue(v)).join(" "); | ||
| if (Array.isArray(value)) return value.map((v) => serializeTokenValue(v)).join(" "); | ||
| return value.toString(); | ||
| }; | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return (0, _bamboocss_shared.mergeWith)(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => (0, _bamboocss_shared.assign)(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return (0, _bamboocss_shared.mergeWith)(restProps, extend, (obj, extensions) => { | ||
| return (0, _bamboocss_shared.mergeAndConcat)({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: _bamboocss_shared.BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact((0, _bamboocss_shared.assign)({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) (0, _bamboocss_shared.walkObject)(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, "formatPath", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return formatPath; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "getReferences", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return getReferences; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "isTokenReference", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return isTokenReference; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "isValidToken", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return isValidToken; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "mergeConfigs", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return mergeConfigs; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "mergeHooks", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return mergeHooks; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, "serializeTokenValue", { | ||
| enumerable: true, | ||
| get: function() { | ||
| return serializeTokenValue; | ||
| } | ||
| }); |
| import { logger } from "@bamboocss/logger"; | ||
| import { BAMBOO_CONFIG_NAME, assign, isObject, isString, mergeAndConcat, mergeWith, walkObject } from "@bamboocss/shared"; | ||
| //#region src/merge-hooks.ts | ||
| const mergeHooks = (plugins) => { | ||
| const hooksFns = {}; | ||
| plugins.forEach(({ name, hooks }) => { | ||
| Object.entries(hooks ?? {}).forEach(([key, value]) => { | ||
| if (!hooksFns[key]) hooksFns[key] = []; | ||
| hooksFns[key].push([name, value]); | ||
| }); | ||
| }); | ||
| return Object.fromEntries(Object.entries(hooksFns).map(([key, entries]) => { | ||
| const fns = entries.map(([name, fn]) => tryCatch(name, fn)); | ||
| const reducer = key in reducers ? reducers[key] : void 0; | ||
| if (reducer) return [key, reducer(fns)]; | ||
| return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)]; | ||
| })); | ||
| }; | ||
| const createReducer = (reducer) => reducer; | ||
| const reducers = { | ||
| "config:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.config; | ||
| let config = args.config; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| config, | ||
| original | ||
| })); | ||
| if (result !== void 0) config = result; | ||
| } | ||
| return config; | ||
| }), | ||
| "parser:before": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "parser:preprocess": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.data; | ||
| let data = args.data; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| data, | ||
| original | ||
| })); | ||
| if (result !== void 0) data = result; | ||
| } | ||
| return data; | ||
| }), | ||
| "cssgen:done": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.content; | ||
| let content = args.content; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| content, | ||
| original | ||
| })); | ||
| if (result !== void 0) content = result; | ||
| } | ||
| return content; | ||
| }), | ||
| "codegen:prepare": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.artifacts; | ||
| let artifacts = args.artifacts; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| artifacts, | ||
| original | ||
| })); | ||
| if (result) artifacts = result; | ||
| } | ||
| return artifacts; | ||
| }), | ||
| "preset:resolved": createReducer((fns) => async (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.preset; | ||
| let preset = args.preset; | ||
| for (const hookFn of fns) { | ||
| const result = await hookFn(Object.assign(args, { | ||
| preset, | ||
| original | ||
| })); | ||
| if (result !== void 0) preset = result; | ||
| } | ||
| return preset; | ||
| }), | ||
| "css:optimize": createReducer((fns) => (_args) => { | ||
| const args = Object.assign({}, _args); | ||
| const original = _args.css; | ||
| let css = args.css; | ||
| for (const hookFn of fns) { | ||
| const result = hookFn(Object.assign(args, { | ||
| css, | ||
| original | ||
| })); | ||
| if (result !== void 0) css = result; | ||
| } | ||
| return css; | ||
| }) | ||
| }; | ||
| const syncHooks = [ | ||
| "context:created", | ||
| "parser:before", | ||
| "parser:preprocess", | ||
| "parser:after", | ||
| "cssgen:done", | ||
| "css:optimize" | ||
| ]; | ||
| const callAllAsync = (...fns) => async (...a) => { | ||
| for (const fn of fns) await fn?.(...a); | ||
| }; | ||
| const callAll = (...fns) => (...a) => { | ||
| fns.forEach((fn) => fn?.(...a)); | ||
| }; | ||
| const tryCatch = (name, fn) => { | ||
| return (...args) => { | ||
| try { | ||
| return fn(...args); | ||
| } catch (e) { | ||
| logger.caughtError("hooks", `Error in plugin "${name}"`, e); | ||
| } | ||
| }; | ||
| }; | ||
| //#endregion | ||
| //#region src/validation/utils.ts | ||
| const REFERENCE_REGEX = /({([^}]*)})/g; | ||
| const curlyBracketRegex = /[{}]/g; | ||
| const isValidToken = (token) => isObject(token) && Object.hasOwnProperty.call(token, "value"); | ||
| const isTokenReference = (value) => typeof value === "string" && REFERENCE_REGEX.test(value); | ||
| const formatPath = (path) => path; | ||
| function getReferences(value) { | ||
| if (typeof value !== "string") return []; | ||
| const matches = value.match(REFERENCE_REGEX); | ||
| if (!matches) return []; | ||
| return matches.map((match) => match.replace(curlyBracketRegex, "")).map((value) => { | ||
| return value.trim().split("/")[0]; | ||
| }); | ||
| } | ||
| const serializeTokenValue = (value) => { | ||
| if (isString(value)) return value; | ||
| if (isObject(value)) return Object.values(value).map((v) => serializeTokenValue(v)).join(" "); | ||
| if (Array.isArray(value)) return value.map((v) => serializeTokenValue(v)).join(" "); | ||
| return value.toString(); | ||
| }; | ||
| //#endregion | ||
| //#region src/merge-config.ts | ||
| /** | ||
| * Collect all `extend` properties into an array (to avoid mutation) | ||
| */ | ||
| function getExtends(items) { | ||
| return items.reduce((merged, { extend }) => { | ||
| if (!extend) return merged; | ||
| return mergeWith(merged, extend, (originalValue, newValue) => { | ||
| if (newValue === void 0) return originalValue ?? []; | ||
| if (originalValue === void 0) return [newValue]; | ||
| if (Array.isArray(originalValue)) return [newValue, ...originalValue]; | ||
| return [newValue, originalValue]; | ||
| }); | ||
| }, {}); | ||
| } | ||
| /** | ||
| * Separate the `extend` properties from the rest of the object | ||
| */ | ||
| function mergeRecords(records) { | ||
| return { | ||
| ...records.reduce((acc, record) => assign(acc, record), {}), | ||
| extend: getExtends(records) | ||
| }; | ||
| } | ||
| /** | ||
| * Merge all `extend` properties into the rest of the object | ||
| */ | ||
| function mergeExtensions(records) { | ||
| const { extend = [], ...restProps } = mergeRecords(records); | ||
| return mergeWith(restProps, extend, (obj, extensions) => { | ||
| return mergeAndConcat({}, obj, ...extensions); | ||
| }); | ||
| } | ||
| const isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0; | ||
| const compact = (obj) => { | ||
| return Object.keys(obj).reduce((acc, key) => { | ||
| if (obj[key] !== void 0 && !isEmptyObject(obj[key])) acc[key] = obj[key]; | ||
| return acc; | ||
| }, {}); | ||
| }; | ||
| const tokenKeys = [ | ||
| "description", | ||
| "extensions", | ||
| "type", | ||
| "value", | ||
| "deprecated" | ||
| ]; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| function mergeConfigs(configs) { | ||
| const userConfig = configs.at(-1); | ||
| const pluginHooks = userConfig.plugins ?? []; | ||
| if (userConfig.hooks) pluginHooks.push({ | ||
| name: BAMBOO_CONFIG_NAME, | ||
| hooks: userConfig.hooks | ||
| }); | ||
| const reversed = Array.from(configs).reverse(); | ||
| const withoutEmpty = compact(assign({ | ||
| conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})), | ||
| theme: mergeExtensions(reversed.map((config) => config.theme ?? {})), | ||
| patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})), | ||
| utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})), | ||
| globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})), | ||
| globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})), | ||
| globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})), | ||
| globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})), | ||
| staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})), | ||
| themes: mergeExtensions(reversed.map((config) => config.themes ?? {})), | ||
| hooks: mergeHooks(pluginHooks) | ||
| }, ...reversed)); | ||
| /** | ||
| * Properly merge tokens between flat/nested forms by setting the flat form as the default | ||
| * preset: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * value: "black" | ||
| * } | ||
| * } | ||
| * // color: "black" | ||
| * ``` | ||
| * | ||
| * config: | ||
| * ``` | ||
| * tokens: { | ||
| * black: { | ||
| * 0: { value: "black" }, | ||
| * 10: { value: "black/10" }, | ||
| * 20: { value: "black/20" }, | ||
| * // ... | ||
| * } | ||
| * } | ||
| * | ||
| * // color: "black.20" | ||
| * ``` | ||
| */ | ||
| if (withoutEmpty.theme?.tokens) walkObject(withoutEmpty.theme.tokens, (args) => args, { stop(token) { | ||
| if (!isValidToken(token)) return false; | ||
| if (Object.keys(token).filter((k) => !tokenKeys.includes(k)).length > 0) { | ||
| token.DEFAULT ||= {}; | ||
| tokenKeys.forEach((key) => { | ||
| if (token[key] == null) return; | ||
| token.DEFAULT[key] ||= token[key]; | ||
| delete token[key]; | ||
| }); | ||
| } | ||
| return true; | ||
| } }); | ||
| return withoutEmpty; | ||
| } | ||
| //#endregion | ||
| export { isValidToken as a, isTokenReference as i, formatPath as n, serializeTokenValue as o, getReferences as r, mergeHooks as s, mergeConfigs as t }; |
| import { BambooPlugin, Config } from "@bamboocss/types"; | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { mergeHooks as n, mergeConfigs as t }; |
| import { BambooPlugin, Config } from "@bamboocss/types"; | ||
| //#region src/merge-hooks.d.ts | ||
| declare const mergeHooks: (plugins: BambooPlugin[]) => BambooHooks; | ||
| //#endregion | ||
| //#region src/merge-config.d.ts | ||
| type Extendable<T> = T & { | ||
| extend?: T; | ||
| }; | ||
| type ExtendableConfig = Extendable<Config>; | ||
| /** | ||
| * Merge all configs into a single config | ||
| */ | ||
| declare function mergeConfigs(configs: ExtendableConfig[]): any; | ||
| //#endregion | ||
| export { mergeHooks as n, mergeConfigs as t }; |
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/mappings.ts | ||
| */ | ||
| declare function convertTsPathsToRegexes(paths: Record<string, string[]>, baseUrl: string): PathMapping[]; | ||
| //#endregion | ||
| export { convertTsPathsToRegexes as n, PathMapping as t }; |
| //#region src/ts-config-paths.d.ts | ||
| interface PathMapping { | ||
| pattern: RegExp; | ||
| paths: string[]; | ||
| } | ||
| /** | ||
| * @see https://github.com/aleclarson/vite-tsconfig-paths/blob/e8f0acf7adfcfbf77edbe937f64b4e5d39557ad0/src/mappings.ts | ||
| */ | ||
| declare function convertTsPathsToRegexes(paths: Record<string, string[]>, baseUrl: string): PathMapping[]; | ||
| //#endregion | ||
| export { convertTsPathsToRegexes as n, PathMapping as t }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
107046
28.87%2938
38%18
-30.77%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated