// @ts-check "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "createProcessor", { enumerable: true, get: ()=>createProcessor }); const _path = /*#__PURE__*/ _interopRequireDefault(require("path")); const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs")); const _postcssLoadConfig = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config")); const _lilconfig = require("lilconfig"); const _plugins = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config/src/plugins" // Little bit scary, looking at private/internal API )); const _options = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config/src/options" // Little bit scary, looking at private/internal API )); const _processTailwindFeatures = /*#__PURE__*/ _interopRequireDefault(require("../../processTailwindFeatures")); const _deps = require("./deps"); const _utils = require("./utils"); const _shared = require("../shared"); const _resolveConfigJs = /*#__PURE__*/ _interopRequireDefault(require("../../../resolveConfig.js")); const _getModuleDependenciesJs = /*#__PURE__*/ _interopRequireDefault(require("../../lib/getModuleDependencies.js")); const _contentJs = require("../../lib/content.js"); const _watchingJs = require("./watching.js"); const _fastGlob = /*#__PURE__*/ _interopRequireDefault(require("fast-glob")); const _findAtConfigPathJs = require("../../lib/findAtConfigPath.js"); const _log = /*#__PURE__*/ _interopRequireDefault(require("../../util/log")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * * @param {string} [customPostCssPath ] * @returns */ async function loadPostCssPlugins(customPostCssPath) { let config = customPostCssPath ? await (async ()=>{ let file = _path.default.resolve(customPostCssPath); // Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js // @ts-ignore let { config ={} } = await (0, _lilconfig.lilconfig)("postcss").load(file); if (typeof config === "function") { config = config(); } else { config = Object.assign({}, config); } if (!config.plugins) { config.plugins = []; } return { file, plugins: (0, _plugins.default)(config, file), options: (0, _options.default)(config, file) }; })() : await (0, _postcssLoadConfig.default)(); let configPlugins = config.plugins; let configPluginTailwindIdx = configPlugins.findIndex((plugin)=>{ if (typeof plugin === "function" && plugin.name === "tailwindcss") { return true; } if (typeof plugin === "object" && plugin !== null && plugin.postcssPlugin === "tailwindcss") { return true; } return false; }); let beforePlugins = configPluginTailwindIdx === -1 ? [] : configPlugins.slice(0, configPluginTailwindIdx); let afterPlugins = configPluginTailwindIdx === -1 ? configPlugins : configPlugins.slice(configPluginTailwindIdx + 1); return [ beforePlugins, afterPlugins, config.options ]; } function loadBuiltinPostcssPlugins() { let postcss = (0, _deps.loadPostcss)(); let IMPORT_COMMENT = "__TAILWIND_RESTORE_IMPORT__: "; return [ [ (root)=>{ root.walkAtRules("import", (rule)=>{ if (rule.params.slice(1).startsWith("tailwindcss/")) { rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params })); rule.remove(); } }); }, (0, _deps.loadPostcssImport)(), (root)=>{ root.walkComments((rule)=>{ if (rule.text.startsWith(IMPORT_COMMENT)) { rule.after(postcss.atRule({ name: "import", params: rule.text.replace(IMPORT_COMMENT, "") })); rule.remove(); } }); } ], [], {} ]; } let state = { /** @type {any} */ context: null, /** @type {ReturnType | null} */ watcher: null, /** @type {{content: string, extension: string}[]} */ changedContent: [], configDependencies: new Set(), contextDependencies: new Set(), /** @type {import('../../lib/content.js').ContentPath[]} */ contentPaths: [], refreshContentPaths () { var ref; this.contentPaths = (0, _contentJs.parseCandidateFiles)(this.context, (ref = this.context) === null || ref === void 0 ? void 0 : ref.tailwindConfig); }, get config () { return this.context.tailwindConfig; }, get contentPatterns () { return { all: this.contentPaths.map((contentPath)=>contentPath.pattern), dynamic: this.contentPaths.filter((contentPath)=>contentPath.glob !== undefined).map((contentPath)=>contentPath.pattern) }; }, loadConfig (configPath, content) { if (this.watcher && configPath) { this.refreshConfigDependencies(configPath); } let config = configPath ? require(configPath) : {}; // @ts-ignore config = (0, _resolveConfigJs.default)(config, { content: { files: [] } }); // Override content files if `--content` has been passed explicitly if ((content === null || content === void 0 ? void 0 : content.length) > 0) { config.content.files = content; } return config; }, refreshConfigDependencies (configPath) { _shared.env.DEBUG && console.time("Module dependencies"); for (let file of this.configDependencies){ delete require.cache[require.resolve(file)]; } if (configPath) { let deps = (0, _getModuleDependenciesJs.default)(configPath).map(({ file })=>file); for (let dependency of deps){ this.configDependencies.add(dependency); } } _shared.env.DEBUG && console.timeEnd("Module dependencies"); }, readContentPaths () { let content = []; // Resolve globs from the content config // TODO: When we make the postcss plugin async-capable this can become async let files = _fastGlob.default.sync(this.contentPatterns.all); for (let file of files){ content.push({ content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"), extension: _path.default.extname(file).slice(1) }); } // Resolve raw content in the tailwind config let rawContent = this.config.content.files.filter((file)=>{ return file !== null && typeof file === "object"; }); for (let { raw: content1 , extension ="html" } of rawContent){ content1.push({ content: content1, extension }); } return content; }, getContext ({ createContext , cliConfigPath , root , result , content }) { if (this.context) { this.context.changedContent = this.changedContent.splice(0); return this.context; } _shared.env.DEBUG && console.time("Searching for config"); var ref; let configPath = (ref = (0, _findAtConfigPathJs.findAtConfigPath)(root, result)) !== null && ref !== void 0 ? ref : cliConfigPath; _shared.env.DEBUG && console.timeEnd("Searching for config"); _shared.env.DEBUG && console.time("Loading config"); let config = this.loadConfig(configPath, content); _shared.env.DEBUG && console.timeEnd("Loading config"); _shared.env.DEBUG && console.time("Creating context"); this.context = createContext(config, []); Object.assign(this.context, { userConfigPath: configPath }); _shared.env.DEBUG && console.timeEnd("Creating context"); _shared.env.DEBUG && console.time("Resolving content paths"); this.refreshContentPaths(); _shared.env.DEBUG && console.timeEnd("Resolving content paths"); if (this.watcher) { _shared.env.DEBUG && console.time("Watch new files"); this.watcher.refreshWatchedFiles(); _shared.env.DEBUG && console.timeEnd("Watch new files"); } _shared.env.DEBUG && console.time("Reading content files"); for (let file of this.readContentPaths()){ this.context.changedContent.push(file); } _shared.env.DEBUG && console.timeEnd("Reading content files"); return this.context; } }; async function createProcessor(args, cliConfigPath) { var ref; let postcss = (0, _deps.loadPostcss)(); let input = args["--input"]; let output = args["--output"]; let includePostCss = args["--postcss"]; let customPostCssPath = typeof args["--postcss"] === "string" ? args["--postcss"] : undefined; let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins(customPostCssPath) : loadBuiltinPostcssPlugins(); if (args["--purge"]) { _log.default.warn("purge-flag-deprecated", [ "The `--purge` flag has been deprecated.", "Please use `--content` instead." ]); if (!args["--content"]) { args["--content"] = args["--purge"]; } } var ref1; let content = (ref1 = (ref = args["--content"]) === null || ref === void 0 ? void 0 : ref.split(/(?{ return { postcssPlugin: "tailwindcss", Once (root, { result }) { _shared.env.DEBUG && console.time("Compiling CSS"); (0, _processTailwindFeatures.default)(({ createContext })=>{ console.error(); console.error("Rebuilding..."); return ()=>{ return state.getContext({ createContext, cliConfigPath, root, result, content }); }; })(root, result); _shared.env.DEBUG && console.timeEnd("Compiling CSS"); } }; }; tailwindPlugin.postcss = true; let plugins = [ ...beforePlugins, tailwindPlugin, !args["--minify"] && _utils.formatNodes, ...afterPlugins, !args["--no-autoprefixer"] && (0, _deps.loadAutoprefixer)(), args["--minify"] && (0, _deps.loadCssNano)() ].filter(Boolean); /** @type {import('postcss').Processor} */ // @ts-ignore let processor = postcss(plugins); async function readInput() { // Piping in data, let's drain the stdin if (input === "-") { return (0, _utils.drainStdin)(); } // Input file has been provided if (input) { return _fs.default.promises.readFile(_path.default.resolve(input), "utf8"); } // No input file provided, fallback to default atrules return "@tailwind base; @tailwind components; @tailwind utilities"; } async function build() { let start = process.hrtime.bigint(); return readInput().then((css)=>processor.process(css, { ...postcssOptions, from: input, to: output })).then((result)=>{ if (!state.watcher) { return result; } _shared.env.DEBUG && console.time("Recording PostCSS dependencies"); for (let message of result.messages){ if (message.type === "dependency") { state.contextDependencies.add(message.file); } } _shared.env.DEBUG && console.timeEnd("Recording PostCSS dependencies"); // TODO: This needs to be in a different spot _shared.env.DEBUG && console.time("Watch new files"); state.watcher.refreshWatchedFiles(); _shared.env.DEBUG && console.timeEnd("Watch new files"); return result; }).then((result)=>{ if (!output) { process.stdout.write(result.css); return; } return Promise.all([ (0, _utils.outputFile)(output, result.css), result.map && (0, _utils.outputFile)(output + ".map", result.map.toString()) ]); }).then(()=>{ let end = process.hrtime.bigint(); console.error(); console.error("Done in", (end - start) / BigInt(1e6) + "ms."); }); } /** * @param {{file: string, content(): Promise, extension: string}[]} changes */ async function parseChanges(changes) { return Promise.all(changes.map(async (change)=>({ content: await change.content(), extension: change.extension }))); } if (input !== undefined && input !== "-") { state.contextDependencies.add(_path.default.resolve(input)); } return { build, watch: async ()=>{ state.watcher = (0, _watchingJs.createWatcher)(args, { state, /** * @param {{file: string, content(): Promise, extension: string}[]} changes */ async rebuild (changes) { let needsNewContext = changes.some((change)=>{ return state.configDependencies.has(change.file) || state.contextDependencies.has(change.file); }); if (needsNewContext) { state.context = null; } else { for (let change of (await parseChanges(changes))){ state.changedContent.push(change); } } return build(); } }); await build(); } }; }