UNPKG

@windicss/plugin-utils

Version:

Common utils for building integrations of Windi CSS

1,047 lines (1,027 loc) 29.6 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); // src/index.ts var src_exports = {}; __export(src_exports, { DefaultExtractor: () => DefaultExtractor, PugExtractor: () => PugExtractor, SupportedLayers: () => SupportedLayers, SvelteExtractor: () => SvelteExtractor, applyExtractors: () => applyExtractors, buildAliasTransformer: () => buildAliasTransformer, createUtils: () => createUtils, defaultAlias: () => defaultAlias, defineConfig: () => defineConfig, escapeRegExp: () => escapeRegExp, exclude: () => exclude, flattenArray: () => flattenArray, getDefaultExtractors: () => getDefaultExtractors, getPug: () => getPug, htmlTags: () => htmlTags, include: () => include, isResolvedOptions: () => isResolvedOptions, kebabCase: () => kebabCase, mergeArrays: () => mergeArrays, mergeWindicssConfig: () => mergeWindicssConfig, partition: () => partition, preflightTags: () => preflightTags, resolveOptions: () => resolveOptions, setPug: () => setPug, slash: () => slash, toArray: () => toArray2, transformGroups: () => transformGroups }); // src/constants.ts var defaultAlias = { "router-link": "a" }; var preflightTags = ["html", "body", "div"]; var htmlTags = [ "html", "body", "div", "a", "abbr", "address", "area", "article", "aside", "audio", "base", "basefont", "bdo", "blink", "blockquote", "br", "button", "canvas", "caption", "center", "col", "colgroup", "command", "comment", "datalist", "dd", "del", "details", "dir", "dl", "dt", "embed", "fieldset", "figure", "b", "big", "i", "small", "tt", "font", "footer", "form", "frame", "frameset", "head", "header", "hgroup", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "isindex", "iframe", "ilayer", "img", "input", "ins", "keygen", "keygen", "label", "layer", "legend", "li", "link", "map", "mark", "marquee", "menu", "meta", "meter", "multicol", "nav", "nobr", "noembed", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "cite", "code", "dfn", "em", "kbd", "samp", "strong", "var", "plaintext", "pre", "progress", "q", "ruby", "script", "section", "select", "spacer", "span", "s", "strike", "style", "sub", "sup", "svg", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "u", "ul", "video", "wbr", "wbr", "xmp" ]; // src/defineConfig.ts function defineConfig(config) { return config; } // src/createUtils.ts import fs from "node:fs"; import { StyleSheet } from "windicss/utils/style"; import { CSSParser } from "windicss/utils/parser"; import { generateCompletions } from "windicss/utils"; import { createSingletonPromise } from "@antfu/utils"; import fg from "fast-glob"; import _debug2 from "debug"; import micromatch from "micromatch"; import Processor from "windicss"; // src/resolveOptions.ts var resolveOptions_exports = {}; __export(resolveOptions_exports, { isResolvedOptions: () => isResolvedOptions, resolveOptions: () => resolveOptions }); import path from "node:path"; import _debug from "debug"; import { loadConfiguration } from "@windicss/config"; // src/utils.ts import { toArray } from "@antfu/utils"; import { toArray as toArray2, partition, slash } from "@antfu/utils"; function flattenArray(v) { return toArray(v).flat(); } function mergeArrays(...args) { return args.flatMap((i) => flattenArray(i || [])); } function kebabCase(str) { return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(); } function include(set, v) { for (const i of v) set.add(i); } function exclude(set, v) { for (const i of v) set.delete(i); } function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // src/extractors/helper.ts import { extname } from "node:path"; import { uniq } from "@antfu/utils"; // src/regexes.ts var regexHtmlTag = /<(\w[\w-]*)([\S\s]*?)\/?>/mg; var regexClassSplitter = /[\s'"`{}]/g; var regexClassGroup = /([!\w+-<@][\w+:_/-]*?\w):\(((?:[!\w\s:/\\,%#.$-]|\[.*?\])*?)\)/gm; var regexAttributifyItem = /(?:\s|^)([\w+:_/-]+)\s*=\s*(['"{])((?:\\\2|\\\\|\n|\r|.)*?)(?:\2|\})/gm; var regexClassCheck1 = /^!?[a-z\d@<>.+-](?:\([\w,.%#\(\)+-]*\)|[\w:/\\,%#\[\].$-])*$/; var regexClassCheck2 = /[a-z].*[\w)\]]$/; var regexClassChecks = [ regexClassCheck1, regexClassCheck2 ]; var regexSvelteClass = /class:([\w!:/\\,%#\[\].$-]+?)=["']?\{/g; function validClassName(i) { return regexClassChecks.every((r) => i.length > 2 && i.match(r)); } // src/extractors/default.ts function DefaultExtractor(code, id) { if (id?.endsWith(".css") || id?.endsWith(".postcss")) { return { classes: [], tags: [] }; } const tags = Array.from(code.matchAll(regexHtmlTag)); const tagNames = tags.map((i) => i[1]); return { tags: tagNames, get classes() { return code.split(regexClassSplitter).filter(validClassName); }, get attributes() { const attrRanges = []; const attributes = { names: [], values: [] }; const attributesBlocklist = ["class", "className"]; const tagsBlocklist = ["meta", "script", "style", "link"]; tags.filter((i) => !tagsBlocklist.includes(i[1])).forEach((i) => { return Array.from(i[2].matchAll(regexAttributifyItem) || []).forEach((match) => { let name = match[1]; const [full, , , value] = match; name = name.replace(/^(:|v-bind:)/, ""); if (attributesBlocklist.includes(name)) return; attributes.names.push(name); attributes.values.push(value); if (match.index != null) attrRanges.push([match.index, match.index + full.length]); }); }); return attributes; } }; } // src/extractors/pug.ts var regexTemplate = /<template.*?lang=['"]pug['"][^>]*?>\n([\s\S]*?\n)<\/template>/gm; var pug; function getPug() { return pug; } function setPug(_pug) { pug = _pug; } function PugExtractor(code, id) { if (!pug) return DefaultExtractor(code); const compile = (code2) => { try { return pug.compile(code2, { filename: id })(); } catch { } }; let compiled; if (id && id.match(/\.vue$/)) { const matches = Array.from(code.matchAll(regexTemplate)); let tail = ""; for (const match of matches) { if (match && match[1]) tail += ` ${compile(match[1])}`; } if (tail) compiled = `${code} ${tail}`; } else { compiled = compile(code); } return DefaultExtractor(compiled || code); } // src/extractors/svelte.ts function SvelteExtractor(code, id) { const result = DefaultExtractor(code, id); return { tags: result.tags, get classes() { return [ ...result.classes, ...Array.from(code.matchAll(regexSvelteClass)).map((i) => i[1]).filter(Boolean) ]; }, get attributes() { return result.attributes; } }; } // src/extractors/helper.ts function getDefaultExtractors() { const extractors = [ { extractor: SvelteExtractor, extensions: ["svelte"] } ]; if (getPug()) { extractors.push({ extractor: PugExtractor, extensions: ["vue", "pug"] }); } return extractors; } async function applyExtractors(code, id, extractors = [], defaultExtract = DefaultExtractor) { let ext = id ? extname(id) : "*"; if (ext[0] === ".") ext = ext.slice(1); const matchingExtractors = extractors.filter((extractor) => extractor.extensions.includes(ext)).map((extractor) => extractor.extractor); return Promise.all((matchingExtractors.length ? matchingExtractors : [defaultExtract]).map((extractor) => extractor(code, id))).then((results) => { const attributesNames = results.flatMap((v) => v.attributes?.names ?? []); const attributesValues = results.flatMap((v) => v.attributes?.values ?? []); return { tags: uniq(results.flatMap((v) => v.tags ?? [])), ids: uniq(results.flatMap((v) => v.ids ?? [])), classes: uniq(results.flatMap((v) => v.classes ?? [])), attributes: attributesNames.length || attributesValues.length ? { names: attributesNames, values: attributesValues } : void 0 }; }); } // src/resolveOptions.ts __reExport(resolveOptions_exports, config_star); import * as config_star from "@windicss/config"; function isResolvedOptions(options) { return options.__windi_resolved; } function buildGlobs(dirs, fileExtensions) { dirs = toArray2(dirs); const exts = toArray2(fileExtensions); const globs = exts.length ? dirs.map( (i) => path.posix.join( i, exts.length > 1 ? `**/*.{${exts.join(",")}}` : `**/*.${exts[0]}` ) ) : []; globs.push("index.html"); return globs; } async function resolveOptions(options = {}, utilsOptions = {}, loadConfigFile = false) { if (isResolvedOptions(options)) return options; const { name = "windicss-plugin-utils" } = utilsOptions; const debugOptions = _debug(`${name}:options`); const root = options.root || utilsOptions.root || process.cwd(); let { config, filepath: configFilePath } = loadConfigFile ? loadConfiguration({ onConfigurationError: (error) => console.error(error), ...utilsOptions, root, config: options.config, configFiles: options.configFiles }) : { config: {}, filepath: void 0 }; const modifiedConfigs = await options.onConfigResolved?.(config, configFilePath); if (modifiedConfigs != null) config = modifiedConfigs; const { scan = true, preflight = true, transformCSS = true, transformGroups: transformGroups2 = true, sortUtilities = true } = options; const preflightOptions = Object.assign( { includeBase: true, includeGlobal: true, includePlugin: true, enableAll: false, includeAll: false, safelist: [], blocklist: [], alias: {} }, typeof config.preflight === "boolean" ? {} : config.preflight, typeof preflight === "boolean" ? {} : preflight ); preflightOptions.includeAll = preflightOptions.includeAll || preflightOptions.enableAll; const scanOptions = Object.assign( { fileExtensions: ["html", "vue", "md", "mdx", "pug", "jsx", "tsx", "svelte", "ts", "js", "css", "postcss", "pcss"], dirs: ["src"], exclude: [], include: [], runOnStartup: true, transformers: [], extractors: [], extraTransformTargets: { css: [], detect: [] } }, typeof scan === "boolean" ? {} : scan ); function resolveGlob(glob) { if (glob.startsWith("!")) return `!${slash(path.resolve(root, glob.slice(1)))}`; return slash(path.resolve(root, glob)); } scanOptions.exclude = mergeArrays( config.extract?.exclude, scanOptions.exclude, // only set default value when exclude is not provided config.extract?.exclude ? [] : [ "node_modules", ".git", "windi.config.{ts,js}", "tailwind.config.{ts,js}" ] ).map(resolveGlob); scanOptions.include = mergeArrays( config.extract?.include, scanOptions.include, // only set default value when include is not provided config.extract?.include ? [] : buildGlobs(scanOptions.dirs, scanOptions.fileExtensions) ).map(resolveGlob); scanOptions.extractors = mergeArrays(getDefaultExtractors(), config.extract?.extractors); const safelist = new Set(mergeArrays(config.safelist, options.safelist).flatMap((i) => i.split(" "))); const blocklist = new Set(mergeArrays(config.blocklist, options.blocklist).flatMap((i) => i.split(" "))); const configPreflightOptions = (typeof config.preflight === "boolean" ? {} : config.preflight) || {}; preflightOptions.safelist = new Set( mergeArrays( configPreflightOptions?.safelist, Array.from(preflightOptions.safelist) ).flatMap((i) => i.split(" ")).map((i) => { const match = i.match(/^\[(.*?)\]$/)?.[1]; if (match) return `div ${match}`; return i; }) ); preflightOptions.blocklist = new Set( mergeArrays( configPreflightOptions?.blocklist, Array.from(preflightOptions.blocklist) ).flatMap((i) => i.split(" ")) ); preflightOptions.alias = Object.fromEntries( Object.entries({ ...defaultAlias, ...configPreflightOptions.alias, ...preflightOptions.alias }).filter(([k, v]) => [kebabCase(k), v]) ); let resolvedOptions = { ...options, root, config, configFilePath, enableScan: Boolean(scan), scanOptions, enablePreflight: config.preflight !== false && Boolean(preflight), preflightOptions, transformCSS, transformGroups: transformGroups2, sortUtilities, safelist, blocklist, __windi_resolved: true }; const modifiedOptions = await resolvedOptions.onOptionsResolved?.(resolvedOptions); if (modifiedOptions != null && modifiedOptions !== resolvedOptions) resolvedOptions = Object.assign(resolvedOptions, modifiedOptions); debugOptions(resolvedOptions); return resolvedOptions; } // src/transforms.ts import MagicString from "magic-string"; function transformGroups(code, sourcemap = true) { const s = new MagicString(code); let hasReplaced = false; let match; regexClassGroup.lastIndex = 0; while (match = regexClassGroup.exec(code)) { hasReplaced = true; const start = match.index; const end = start + match[0].length; const a = match[1]; const b = match[2]; const replacement = b.split(/\s+/g).filter(Boolean).map((i) => i.replace(/^(!?)(.*)/, `$1${a}:$2`)).join(" "); s.overwrite(start, end, replacement); } if (!hasReplaced) return null; return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } function buildAliasTransformer(alias) { if (!alias || !Object.keys(alias).length) return () => null; const keys = Object.keys(alias).sort((a, b) => b.length - a.length).map((i) => escapeRegExp(i)).join("|"); const regexText = `\\*(?:${keys})(?<=[^w-])`; const regex = new RegExp(regexText, "g"); return function transformAlias(code, sourcemap = true) { const s = new MagicString(code); let hasReplaced = false; let match; regex.lastIndex = 0; while (match = regex.exec(code)) { hasReplaced = true; const start = match.index; const end = start + match[0].length; const name = code.slice(start + 1, end); const replacement = alias[name]; s.overwrite(start, end, replacement); } if (!hasReplaced) return null; return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; }; } // src/createUtils.ts var SupportedLayers = ["base", "utilities", "components"]; function createUtils(userOptions = {}, utilsOptions = { name: "windicss-plugin-utils" }) { let options = {}; const name = utilsOptions.name; const debug = { config: _debug2(`${name}:config`), debug: _debug2(`${name}:debug`), compile: _debug2(`${name}:compile`), scan: _debug2(`${name}:scan`), scanGlob: _debug2(`${name}:scan:glob`), scanTransform: _debug2(`${name}:scan:transform`), detectClass: _debug2(`${name}:detect:class`), detectTag: _debug2(`${name}:detect:tag`), detectAttrs: _debug2(`${name}:detect:attrs`), compileLayer: _debug2(`${name}:compile:layer`) }; let processor; let completions; let files = []; const classesGenerated = /* @__PURE__ */ new Set(); const classesPending = /* @__PURE__ */ new Set(); const tagsGenerated = /* @__PURE__ */ new Set(); const tagsPending = /* @__PURE__ */ new Set(); const attrsGenerated = /* @__PURE__ */ new Set(); const tagsAvailable = /* @__PURE__ */ new Set(); const attributes = []; let _transformAlias = () => null; const _locks = []; function getCompletions() { if (!completions) completions = generateCompletions(processor); return completions; } async function getFiles() { await ensureInit(); debug.scanGlob("include", options.scanOptions.include); debug.scanGlob("exclude", options.scanOptions.exclude); const files2 = await fg( options.scanOptions.include, { cwd: options.root, ignore: options.scanOptions.exclude, onlyFiles: true, absolute: true } ); files2.sort(); debug.scanGlob("files", files2); return files2; } let scanned = false; const scan = createSingletonPromise(async () => { await ensureInit(); debug.scan("started"); files.push(...await getFiles()); const contents = await Promise.all( files.filter((id) => isDetectTarget(id)).map(async (id) => [await fs.promises.readFile(id, "utf-8"), id]) ); await Promise.all(contents.map( async ([content, id]) => { if (isCssTransformTarget(id)) return transformCSS(content, id); else return extractFile(content, id, true); } )); scanned = true; debug.scan("finished"); }); function isExcluded(id) { return micromatch.contains(slash(id), options.scanOptions.exclude, { dot: true }); } function isIncluded(id) { return micromatch.isMatch(slash(id), options.scanOptions.include); } function isDetectTarget(id) { if (options.scanOptions.extraTransformTargets.detect.some((i) => typeof i === "string" ? i === id : i(id))) return true; if (files.includes(id) || files.includes(id.slice(0, id.indexOf("?")))) return true; return isIncluded(id) && !isExcluded(id); } function isScanTarget(id) { return options.enableScan ? files.some((file) => id.startsWith(file)) : isDetectTarget(id); } function isCssTransformTarget(id) { if (options.scanOptions.extraTransformTargets.css.some((i) => typeof i === "string" ? i === id : i(id))) return true; if (id.match(/\.(?:postcss|pcss|scss|sass|css|stylus|less)(?:$|\?)/i) && !isExcluded(id)) return true; return false; } function addClasses(classes) { let changed = false; classes.forEach((i) => { if (!i || classesGenerated.has(i) || classesPending.has(i) || options.blocklist.has(i)) return; classesPending.add(i); changed = true; }); return changed; } function addTags(tags) { if (options.preflightOptions.includeAll) return false; let changed = false; tags.forEach((tag) => { if (!tagsAvailable.has(tag)) tag = options.preflightOptions.alias[kebabCase(tag)]; if (options.preflightOptions.blocklist.has(tag)) return; if (tagsAvailable.has(tag) && !tagsPending.has(tag)) { tagsPending.add(tag); tagsAvailable.delete(tag); changed = true; } }); return changed; } async function applyExtractors2(code, id) { return await applyExtractors(code, id, options.scanOptions.extractors); } async function extractFile(code, id, applyTransform = true) { if (applyTransform) { code = _transformAlias(code, false)?.code ?? code; if (options.transformGroups) code = transformGroups(code, false)?.code ?? code; } if (id) { debug.scanTransform(id); for (const trans of options.scanOptions.transformers) { const result = trans(code, id); if (result != null) code = result; } } const extractResult = await applyExtractors2(code, id); let changed = false; if (options.enablePreflight && !options.preflightOptions.includeAll) { changed = addTags(extractResult.tags || []) || changed; } if (options.config.attributify) { const extractedAttrs = extractResult.attributes; if (extractedAttrs?.names.length) { extractedAttrs.names.forEach((name2, i) => { attributes.push([name2, extractedAttrs.values[i]]); }); changed = true; } changed = addClasses(extractedAttrs?.classes || extractResult.classes || []) || changed; } else { changed = addClasses(extractResult.classes || []) || changed; } if (changed) { debug.detectClass(classesPending); debug.detectTag(tagsPending); debug.detectAttrs(attributes); } return changed; } function transformCSS(css, id, transformOptions) { if (!options.transformCSS) return css; const style = new CSSParser(css, processor).parse(); if (transformOptions?.globaliseKeyframes) { const [nonKeyframeBlocks, keyframeBlocks] = partition( style.children, (i) => !i.atRules || !i.atRules[0].match(/keyframes (pulse|spin|ping|bounce)/) ); updateLayers(keyframeBlocks, "__classes", false); style.children = nonKeyframeBlocks; } const [layerBlocks, blocks] = partition(style.children, (i) => i.meta.group === "layer-block" && SupportedLayers.includes(i.meta.type)); if (layerBlocks.length) { updateLayers(layerBlocks, id); style.children = blocks; } const transformed = style.build(); if (layerBlocks.length) transformOptions?.onLayerUpdated?.(); return transformed; } const layers = { base: {}, utilities: {}, components: {} }; const layerStylesMap = /* @__PURE__ */ new Map(); function updateLayers(styles, filepath, replace = true) { const timestamp = +Date.now(); debug.compileLayer("update", filepath); const changedLayers = /* @__PURE__ */ new Set(); styles.forEach((i) => changedLayers.add(i.meta.type)); if (replace) { layerStylesMap.get(filepath)?.forEach((i) => changedLayers.add(i.meta.type)); layerStylesMap.set(filepath, styles); } else { const prevStyles = layerStylesMap.get(filepath) || []; layerStylesMap.set(filepath, prevStyles.concat(styles)); } for (const name2 of changedLayers) { const layer = layers[name2]; if (layer) { layer.timestamp = timestamp; layer.cssCache = void 0; } } } function buildLayerCss(name2) { const layer = layers[name2]; if (layer.cssCache == null) { const style = new StyleSheet(Array.from(layerStylesMap.values()).flatMap((i) => i).filter((i) => i.meta.type === name2)); style.prefixer = options.config.prefixer ?? true; debug.compileLayer(name2, style.children.length); if (options.sortUtilities) style.sort(); layer.cssCache = `/* windicss layer ${name2} */ ${style.build()}`; } return layer.cssCache; } function buildPendingStyles() { options.onBeforeGenerate?.({ classesPending, tagsPending }); if (classesPending.size) { const result = processor.interpret(Array.from(classesPending).join(" ")); if (result.success.length) { debug.compile(`compiled ${result.success.length} classes out of ${classesPending.size}`); debug.compile(result.success); updateLayers(result.styleSheet.children, "__classes", false); include(classesGenerated, result.success); classesPending.clear(); } } if (options.enablePreflight) { if (options.preflightOptions.includeAll) { if (!layerStylesMap.has("__preflights")) { const preflightStyle = processor.preflight( void 0, options.preflightOptions.includeBase, options.preflightOptions.includeGlobal, options.preflightOptions.includePlugin ); updateLayers(preflightStyle.children, "__preflights", true); } } else if (tagsPending.size) { const preflightStyle = processor.preflight( Array.from(tagsPending).map((i) => `<${i}/>`).join(" "), options.preflightOptions.includeBase, options.preflightOptions.includeGlobal, options.preflightOptions.includePlugin ); updateLayers(preflightStyle.children, "__preflights", false); include(tagsGenerated, tagsPending); tagsPending.clear(); } } if (options.config.attributify) { if (attributes.length) { const attributesObject = {}; attributes.filter((i) => i[0] && i[1]).forEach(([name2, value]) => { if (!attributesObject[name2]) attributesObject[name2] = []; attributesObject[name2].push( ...String(value).split(regexClassSplitter).filter(Boolean) ); }); const attributifyStyle = processor.attributify( attributesObject ); updateLayers(attributifyStyle.styleSheet.children, "__attributify", false); attributes.length = 0; } } options.onGenerated?.({ classes: classesGenerated, tags: tagsGenerated }); } async function generateCSS(layer) { await ensureInit(); if (options.enableScan && options.scanOptions.runOnStartup) await scan(); buildPendingStyles(); return layer ? buildLayerCss(layer) : [ buildLayerCss("base"), buildLayerCss("components"), buildLayerCss("utilities") ].join("\n").trim(); } function clearCache(clearAll = false) { layers.base = {}; layers.utilities = {}; layers.components = {}; layerStylesMap.clear(); completions = void 0; if (clearAll) { classesPending.clear(); tagsPending.clear(); tagsAvailable.clear(); } else { include(classesPending, classesGenerated); include(tagsPending, tagsGenerated); include(tagsPending, preflightTags); } include(tagsAvailable, htmlTags); include(classesPending, options.safelist); include(tagsPending, options.preflightOptions.safelist); exclude(tagsAvailable, preflightTags); exclude(tagsAvailable, options.preflightOptions.safelist); classesGenerated.clear(); tagsGenerated.clear(); attrsGenerated.clear(); } async function lock(fn) { const p = fn(); _locks.push(p); await p; const i = _locks.indexOf(p); if (i >= 0) _locks.splice(i, 1); } async function waitLocks() { await Promise.all(_locks); } const utils = { init, ensureInit, extractFile, applyExtractors: applyExtractors2, generateCSS, getFiles, clearCache, transformCSS, transformGroups, get transformAlias() { return _transformAlias; }, buildPendingStyles, isDetectTarget, isScanTarget, isCssTransformTarget, isExcluded, scan, classesGenerated, classesPending, tagsGenerated, tagsPending, tagsAvailable, layersMeta: layers, addClasses, addTags, getCompletions, lock, waitLocks, get initialized() { return !!processor; }, get options() { return options; }, get files() { return files; }, get globs() { return options.scanOptions.include; }, get processor() { return processor; }, get scanned() { return scanned; }, get configFilePath() { return options.configFilePath; }, get hasPending() { return Boolean(tagsPending.size || classesPending.size); } }; async function _init() { try { setPug((await import("pug")).default); } catch (e) { } options = await resolveOptions(userOptions, utilsOptions, true); files = []; processor = new Processor(options.config); clearCache(false); options.onInitialized?.(utils); _transformAlias = buildAliasTransformer(options.config.alias); return processor; } let _promise_init; async function init() { _promise_init = _init(); return _promise_init; } async function ensureInit() { if (processor) return processor; if (!_promise_init) _promise_init = _init(); return _promise_init; } return utils; } // src/index.ts __reExport(src_exports, resolveOptions_exports); // src/merge.ts var isObject = (val) => toString.call(val) === "[object Object]"; function deepMerge(a, b, rootPath) { a = { ...a }; Object.keys(b).forEach((key) => { if (isObject(a[key])) a[key] = deepMerge(a[key], b[key], rootPath ? `${rootPath}.${key}` : key); else if (Array.isArray(a[key])) a[key] = [...a[key], ...b[key]]; else a[key] = b[key]; }); return a; } function mergeWindicssConfig(a, b) { return deepMerge(a, b, ""); } export { DefaultExtractor, PugExtractor, SupportedLayers, SvelteExtractor, applyExtractors, buildAliasTransformer, createUtils, defaultAlias, defineConfig, escapeRegExp, exclude, flattenArray, getDefaultExtractors, getPug, htmlTags, include, isResolvedOptions, kebabCase, mergeArrays, mergeWindicssConfig, partition, preflightTags, resolveOptions, setPug, slash, toArray2 as toArray, transformGroups };