UNPKG

@xmipra/plugins

Version:
1,708 lines (1,647 loc) 55 kB
// src/plugin.ts import path2 from "path"; import fs7 from "fs-extra"; import kleur5 from "kleur"; import { isNil as isNil3, isPlainObject as isPlainObject3, isFunction } from "@txjs/bool"; import { pick as pick4 } from "@txjs/shared"; import { cosmiconfig } from "cosmiconfig"; import { TypeScriptLoader } from "cosmiconfig-typescript-loader"; // src/plugins/env/index.ts import kleur2 from "kleur"; import { shallowMerge as shallowMerge2 } from "@txjs/shared"; // src/shared/define-plugin.ts import { isPlainObject } from "@txjs/bool"; // src/shared/logger.ts import kleur from "kleur"; import dayjs from "dayjs"; // src/shared/constant.ts var XMIPRA = "xmipra"; var CONFIG_CHANGE = "onConfigChange"; var ENV_CONFIG_CHANGE = "onEnvConfigChange"; // src/shared/logger.ts var DAYJS_FORMAT = "YYYY/MM/DD HH:mm:ss"; var Logger = class { pluginName; constructor(pluginName) { this.pluginName = pluginName ? `${kleur.cyan(pluginName)} ` : ""; } log(text) { console.log( `${kleur.green(`✔ [${XMIPRA}]`)} ${kleur.gray( `→ ${this.pluginName}${text} [${dayjs().format(DAYJS_FORMAT)}]` )} ` ); } warn(...args) { console.log( `${kleur.red(`⚠️ [${XMIPRA}]`)} ${kleur.gray( `→ ${this.pluginName}Warning... [${dayjs().format(DAYJS_FORMAT)}]` )} `, ...args, "\n" ); } }; // src/shared/define-plugin.ts function defaultPlugin(name, callback) { name = `${name}-plugin`; const logger = new Logger(name); return (ctx, props) => { if (!isPlainObject(props)) { props = {}; } callback.apply(null, [ ctx, { name, props, logger } ]); }; } // src/shared/utils.ts import path from "path"; import minimist from "minimist"; import fs from "fs-extra"; import { isNonEmptyString, isNil } from "@txjs/bool"; var ciArgs = minimist(process.argv.slice(2), { string: ["type", "mode"], boolean: ["watch"] }); var platforms = ["weapp", "alipay", "tt"]; function isWatch() { return !!ciArgs.watch; } function platformOf(platform) { return platforms.includes(platform); } function getNodeEnv() { return isNonEmptyString(ciArgs.mode) ? ciArgs.mode : process.env.NODE_ENV || "development"; } function getTaroEnv() { const type = isNonEmptyString(ciArgs.type) ? ciArgs.type : process.env.TARO_ENV; if (platformOf(type)) { return type; } } function resolve(...dir) { return path.resolve(...dir); } var CWD = process.cwd(); var pkg; function getPkgConfig(cache = true) { if (isNil(pkg) || !cache) { const path3 = resolve(CWD, "package.json"); pkg = fs.readJSONSync(path3); } return pkg; } // src/plugins/env/env-helper.ts import dotenv from "dotenv"; import extend from "extend"; import { isNonEmptyString as isNonEmptyString2 } from "@txjs/bool"; function envPath(...dir) { return resolve(CWD, [".env", ...dir].join(".")); } var EnvHelper = class { NODE_ENV = getNodeEnv(); TARO_ENV = getTaroEnv(); constructor() { } loadEnv() { const envObject = {}; const globalConfig = dotenv.config({ path: envPath() }); const globalConfigLocal = dotenv.config({ path: envPath("local") }); const nodeConfig = dotenv.config({ path: envPath(this.NODE_ENV) }); const nodeConfigLocal = dotenv.config({ path: envPath(this.NODE_ENV, "local") }); const platformConfig = dotenv.config({ path: envPath(this.TARO_ENV) }); const platformConfigLocal = dotenv.config({ path: envPath(this.TARO_ENV, "local") }); extend( true, envObject, !globalConfig.error && globalConfig.parsed, !nodeConfig.error && nodeConfig.parsed, !platformConfig.error && platformConfig.parsed, !globalConfigLocal.error && globalConfigLocal.parsed, !nodeConfigLocal.error && nodeConfigLocal.parsed, !platformConfigLocal.error && platformConfigLocal.parsed ); return Object.keys(envObject).reduce((prev, key) => { if (this.startsWith(key)) { const value = this.parsed(Reflect.get(envObject, key), envObject); Reflect.set(envObject, key, JSON.parse(value)); Reflect.set(prev, key, value); } return prev; }, {}); } object() { const envObject = this.loadEnv(); return Object.keys(envObject).reduce( (ret, key) => { const value = Reflect.get(envObject, key); Reflect.set(ret, this.generateKey(key), value); return ret; }, {} ); } parsed(input, envObject) { if (input.startsWith("@")) { const strArr = input.split("@"); input = strArr.reduce((chunks, str) => { if (Reflect.has(envObject, str)) { chunks.push(Reflect.get(envObject, str)); } return chunks; }, []).join(""); } return JSON.stringify(input); } startsWith(key) { return key.startsWith("XMIPRA_"); } generateKey(name) { return isNonEmptyString2(name) ? `process.env.${name}` : ""; } cleanKey(name) { return isNonEmptyString2(name) ? name.replace(/^process\.env\./, "") : ""; } cleanValue(value) { return isNonEmptyString2(value) ? JSON.parse(value) : ""; } isTruly(value) { return isNonEmptyString2(value) ? /^true$/i.test(value) : false; } }; var envHelper = new EnvHelper(); // src/plugins/env/watch.ts import { shallowMerge } from "@txjs/shared"; // src/shared/watch-file.ts import { watch } from "chokidar"; import fs2 from "fs"; import { createHash } from "crypto"; import { globSync } from "glob"; var WatchFile = class { options; constructor(options) { this.options = options; } #cache = /* @__PURE__ */ new Map(); watcher = null; #getHash(path3) { const buffer = fs2.readFileSync(path3); return createHash("sha256").update(buffer).digest("hex"); } apply(compiler) { if (!this.options.monitor) return; compiler.hooks.initialize.tap(this.name, () => { if (!this.watcher) { this.watcher = watch(globSync(this.options.path), { ignored: "node_modules/**", persistent: true, ignoreInitial: true, cwd: CWD }); } this.watcher.on("all", (event, path3) => { if (event === "addDir") return; if (event === "unlink") { this.#cache.delete(path3); this.update(event, path3, compiler); } else if (event === "unlinkDir") { Array.from(this.#cache.values()).forEach((el) => { if (el.startsWith(path3)) { this.#cache.delete(el); } }); this.update(event, path3, compiler); } else { const cache = this.#cache.get(path3); const hash = this.#getHash(path3); if (cache && hash === cache) return; this.update(event, path3, compiler); this.#cache.set(path3, hash); } }); process.on("SIGINT", () => { this.#signal(compiler); }); process.on("SIGALRM", () => { this.#signal(compiler); }); }); } async #signal(compiler) { await this.watcher.close(); compiler.close(() => { this.#cache.clear(); this.watcher = null; this.close(); process.exit(0); }); } }; // src/plugins/env/watch.ts var WatchFileEnvPlugin = class extends WatchFile { constructor(options) { super(options); } name = "watchFileEnvPlugin"; close() { this.options.close?.(); } update(event, path3, compiler) { compiler.options.plugins.forEach((plugin2) => { if (plugin2 && plugin2.constructor.name === "DefinePlugin") { const definitions = plugin2.definitions; const envObject = envHelper.object(); Object.keys(definitions).forEach((key) => { if (envHelper.startsWith(envHelper.cleanKey(key)) && !(key in envObject)) { delete plugin2.definitions[key]; } }); plugin2.definitions = shallowMerge(plugin2.definitions, envObject); this.options?.change(path3); } }); } }; // src/plugins/env/index.ts var env_default = defaultPlugin( "env", (ctx, { logger, props }) => { props.monitor ??= ctx.isWatch; ctx.modifyWebpackChain(({ chain }) => { chain.plugin("definePlugin").tap((args) => { shallowMerge2(args[0], envHelper.object()); return args; }).end(); chain.plugin("watchFileEnvPlugin").use(WatchFileEnvPlugin, [ { monitor: props.monitor ?? ctx.isWatch, path: resolve(CWD, ".env*"), change(path3) { ctx.applyPlugins({ name: ENV_CONFIG_CHANGE, opts: { path: path3 } }); logger.log(`Update injection ${kleur2.blue(path3)}`); } } ]).end(); }); } ); // src/plugins/declaration/index.ts import kleur3 from "kleur"; import fs3 from "fs-extra"; // src/plugins/declaration/internal/env.ts import { json2tsMulti } from "json-ts"; // src/plugins/declaration/declaration.ts import { format } from "prettier"; var Declaration = class { option; constructor(option) { this.option = option; } get filename() { return `${this.name}.d.ts`; } async output(ctx) { let sourceString = this.build(ctx); if (sourceString) { sourceString = `declare global{ ${sourceString} } export {}`; return await format(sourceString, { parser: "typescript", semi: false, tabWidth: 2, useTabs: false, singleQuote: true, printWidth: 80, endOfLine: "auto" }); } } }; // src/plugins/declaration/internal/env.ts var EnvDeclaration = class extends Declaration { constructor(options) { super(options); } name = "env"; event = ENV_CONFIG_CHANGE; build() { const envInterface = json2tsMulti( [JSON.stringify({ TARO_ENV: "" }), JSON.stringify(envHelper.loadEnv())], { prefix: "", rootName: "ProcessEnv" } ).replace( /(\n\s+TARO_ENV\?:\s+)(\w+);\n/, `$1${platforms.map((platform) => `'${platform}'`).join(" | ")}; ` ); return `namespace NodeJS { ${envInterface} }`; } }; // src/plugins/declaration/index.ts var declaration_default = defaultPlugin( "declaration", (ctx, { logger, props }) => { props.outDir ||= "types"; props.plugins ||= []; const outDir = resolve(CWD, ctx.rootDir, props.outDir); const plugins = [new EnvDeclaration()]; props.plugins.forEach((declaration) => { const flag = plugins.some((el) => el.name === declaration.name); if (!flag) { plugins.push(declaration); } }); async function build(callback) { try { if (!fs3.existsSync(outDir)) { fs3.mkdirSync(outDir); } for (let i = 0, len = plugins.length; i < len; i++) { const declaration = plugins[i]; const sourceString = await declaration.output(ctx); if (sourceString) { fs3.outputFileSync( resolve(CWD, outDir, declaration.filename), sourceString ); } } callback?.(); } catch (error) { logger.warn(error); } } ctx.onBuildComplete(async () => { build(() => { logger.log("Build completed"); }); }); plugins.forEach((declaration) => { if (declaration.event) { ctx.register({ name: declaration.event, async fn({ path: path3 }) { try { const sourceString = await declaration.output(ctx); if (sourceString) { fs3.outputFileSync( resolve(CWD, outDir, declaration.filename), sourceString ); } logger.log( `Dependency ${kleur3.white(declaration.event)} update ${kleur3.blue(path3)}` ); } catch (error) { logger.warn(error); } } }); } }); } ); // src/plugins/project-config/index.ts import fs4 from "fs-extra"; import extend4 from "extend"; import kleur4 from "kleur"; import _path from "path"; import { notNil } from "@txjs/bool"; // src/plugins/project-config/mp/alipay-config.ts function alipayConfig(config = {}) { for (const key in config) { const tempValue = Reflect.get(config, key) || {}; const tempContent = Reflect.get(tempValue, "content"); if (!tempContent) continue; if (key === "app.config") { const windowConfig = Reflect.get(tempContent, "window") || {}; if (windowConfig.navigationStyle === "custom") { Reflect.deleteProperty(windowConfig, "navigationStyle"); Reflect.set(windowConfig, "transparentTitle", "always"); Reflect.set(windowConfig, "titlePenetrate", "YES"); Reflect.set(tempContent, "window", windowConfig); } } else if (tempContent.navigationStyle === "default") { Reflect.deleteProperty(tempContent, "navigationStyle"); Reflect.set(tempContent, "transparentTitle", "none"); Reflect.set(tempContent, "titlePenetrate", "no"); } Reflect.set(tempValue, "content", tempContent); } } // src/plugins/project-config/mp/alipay.ts import extend2 from "extend"; import { pick } from "@txjs/shared"; var baseConfigKeys = [ "format", "compileType", "miniprogramRoot", "pluginRoot", "compileOptions", "uploadExclude", "assetsInclude", "developOptions", "pluginResolution", "scripts" ]; var compileOptionKeys = [ "component2", "typescript", "less", "treeShaking", "resolveAlias", "globalObjectMode", "transpile" ]; function alipay(config = {}) { const { compileOptions = {}, ...partial } = pick(config, baseConfigKeys, true); return extend2(partial, { compileOptions: pick(compileOptions, compileOptionKeys, true) }); } // src/plugins/project-config/mp/tt.ts import extend3 from "extend"; import { pick as pick2 } from "@txjs/shared"; var baseConfigKeys2 = ["appid", "miniprogramRoot", "setting", "projectname"]; var settingConfigKeys = [ "es6", "urlCheck", "autoCompile", "mockUpdate", "scripts", "mockLogin" ]; function tt(config = {}) { const { setting = {}, ...partial } = pick2(config, baseConfigKeys2, true); return extend3(partial, { setting: pick2(setting, settingConfigKeys, true) }); } // src/plugins/project-config/watch.ts var WatchFileProjectConfigPlugin = class extends WatchFile { constructor(options) { super(options); } name = "watchFileProjectConfigPlugin"; close() { this.options.close?.(); } update(path3, event) { this.options.change(event, path3); } }; // src/plugins/project-config/utils.ts var configFileNameMap = { weapp: "project.config.json", tt: "project.config.json", alipay: "mini.project.json" }; var envVariableMap = { XMIPRA_MP_ID: "appid", XMIPRA_PROJECT_NAME: "projectname" }; // src/plugins/project-config/index.ts var mpCli = { alipay, tt }; function defaultMerged(config) { return config; } var project_config_default = defaultPlugin( "project-config", (ctx, { logger, props }) => { let merged = defaultMerged; if (Reflect.has(mpCli, ctx.TARO_ENV)) { merged = Reflect.get(mpCli, ctx.TARO_ENV); } const pkg2 = getPkgConfig(); const configFilename = Reflect.get(configFileNameMap, ctx.TARO_ENV); const mpConfigDir = resolve(CWD, ctx.outDir, ctx.TARO_ENV); const mpConfigPath = resolve(mpConfigDir, configFilename); const configPath = resolve(CWD, ctx.outputDir, configFilename); const independentConfig = Reflect.get(props, ctx.TARO_ENV); const globalConfig = Reflect.get(props, "global"); const envVariableKeys = Object.keys(envVariableMap); const getPrivateEnv = () => { const newObject = {}; envVariableKeys.forEach((key) => { const name = Reflect.get(envVariableMap, key); const value = Reflect.get(envHelper.loadEnv(), key); if (notNil(value)) { Reflect.set(newObject, name, envHelper.cleanValue(value)); } else if (name === "projectname") { Reflect.set(newObject, name, pkg2.name || "unknown-name"); } }); return newObject; }; async function build(callback) { try { let mpConfig; if (fs4.pathExistsSync(mpConfigPath)) { mpConfig = fs4.readJSONSync(mpConfigPath); } cacheConfig = getPrivateEnv(); const mergeConfig = extend4( true, {}, cacheConfig, globalConfig, independentConfig ); const finalConfig = extend4(true, mpConfig, merged(mergeConfig)); await fs4.outputJSON(configPath, finalConfig, { spaces: 2 }); callback?.(); } catch (error) { logger.warn(error); } } ctx.modifyMiniConfigs(({ configMap }) => { if (ctx.TARO_ENV === "alipay") { alipayConfig(configMap); } }); ctx.onBuildComplete(async () => { if (!fs4.existsSync(mpConfigDir)) return; try { await fs4.copy(mpConfigDir, ctx.outputDir, { overwrite: true, filter: (src) => !src.endsWith(configFilename) }); } catch (error) { logger.warn(error); } build(() => { logger.log("Build completed"); }); }); ctx.modifyWebpackChain(({ chain }) => { chain.plugin("watchFileProjectConfigPlugin").use(WatchFileProjectConfigPlugin, [ { monitor: props.monitor ?? ctx.isWatch, path: mpConfigDir, async change(path3, event) { if (path3.endsWith(configFilename)) { build(() => { logger.log(`Update ${kleur4.blue(path3)}`); }); } else { try { const dest = _path.join( resolve(CWD, ctx.outputDir), path3.slice(_path.join(ctx.outDir, ctx.TARO_ENV).length) ); if (event === "unlink" || event === "unlinkDir") { await fs4.remove(dest); logger.log(`Remove ${kleur4.blue(path3)}`); } else { await fs4.copy(resolve(CWD, path3), dest, { overwrite: true }); logger.log(`Copy ${kleur4.blue(path3)}`); } } catch (error) { logger.warn(error); } } } } ]).end(); }); let cacheConfig; ctx.register({ name: ENV_CONFIG_CHANGE, fn(opts) { const newCacheConfig = getPrivateEnv(); if (JSON.stringify(newCacheConfig) !== JSON.stringify(cacheConfig)) { build(() => { logger.log(`Dependency env update ${kleur4.blue(opts.path)}`); }); cacheConfig = newCacheConfig; } } }); } ); // src/plugins/condition/index.ts import fs5 from "fs-extra"; import { isNil as isNil2, isArray } from "@txjs/bool"; import { toArray, shallowMerge as shallowMerge3 } from "@txjs/shared"; // src/plugins/condition/utils.ts var configFileNameMap2 = { weapp: "project.private.config.json", alipay: ".mini-ide/compileMode.json", tt: "project.private.config.json" }; var fieldNameMap = { weapp: { title: "name", page: "pathName", query: "query", launchMode: "launchMode", scene: "scene", extraInfo: "referrerInfo" }, alipay: { title: "title", page: "page", query: "pageQuery", launchMode: "launchMode", scene: "scene", extraQuery: "page" }, tt: { title: "name", page: "pathName", query: "query", launchMode: "launchFrom", scene: "scene" } }; // src/plugins/condition/index.ts var condition_default = defaultPlugin("condition", (ctx, { logger }) => { const configFileName = Reflect.get(configFileNameMap2, ctx.TARO_ENV); const fields = Reflect.get(fieldNameMap, ctx.TARO_ENV); const fieldKeys = Object.keys(fields); const configPath = resolve(CWD, ctx.outputDir, configFileName); const transformer = (options) => { const newObject = {}; fieldKeys.forEach((key) => { const name = Reflect.get(fields, key); let value = Reflect.get(options, key); if (ctx.TARO_ENV === "tt") { if (key === "page" && value) { value = value.slice(1); } } if (name && value) { Reflect.set(newObject, name, value); } }); return newObject; }; const getNodeEnv2 = (env) => { switch (env) { case "dev": return "development"; case "prod": return "production"; default: return env; } }; const generate5 = (list) => { return list.filter((el) => { const allEnv = isNil2(el.env); const allTaro = isNil2(el.taro); if (allEnv && allTaro) { return true; } const env = toArray(allEnv ? "*" : el.env).map(getNodeEnv2); const taro = toArray(allTaro ? "*" : el.taro); return (env.includes("*") || env.includes(ctx.NODE_ENV)) && (taro.includes("*") || taro.includes(ctx.TARO_ENV)); }).map(transformer); }; function mpConfig(compiles) { switch (ctx.TARO_ENV) { case "alipay": return { modes: compiles }; case "weapp": case "tt": return { condition: { miniprogram: { list: compiles } } }; } } async function build(callback) { const condition = ctx.pluginConfig.condition || []; try { const compiles = generate5(condition); if (compiles.length) { let tempCompiles; if (fs5.pathExistsSync(configPath)) { tempCompiles = fs5.readJSONSync(configPath); } const finalConfig = shallowMerge3({}, tempCompiles, mpConfig(compiles)); await fs5.outputJSON(configPath, finalConfig, { spaces: 2 }); callback?.(); } } catch (error) { logger.warn(error); } } ctx.onBuildComplete(() => { build(() => { logger.log("Build completed"); }); }); ctx.onConfigChange((from) => { if (from === "watchChange" && isArray(ctx.pluginConfig.condition)) { build(() => { logger.log("Build update"); }); } }); }); // src/plugins/theme/index.ts import fs6 from "fs-extra"; import postcss from "postcss"; import pxtorem from "postcss-pxtransform"; import cleanCSS from "clean-css"; import webpack from "webpack"; import { pick as pick3, shallowMerge as shallowMerge6 } from "@txjs/shared"; import { isPlainObject as isPlainObject2 } from "@txjs/bool"; // src/plugins/theme/themes/index.ts import { shallowMerge as shallowMerge4 } from "@txjs/shared"; // src/plugins/theme/themes/seed.ts var defaultPresetColors = { blue: "#1677ff", purple: "#722ED1", cyan: "#13C2C2", green: "#52C41A", magenta: "#EB2F96", pink: "#eb2f96", red: "#F5222D", orange: "#FA8C16", yellow: "#FADB14", volcano: "#FA541C", geekblue: "#2F54EB", gold: "#FAAD14", lime: "#A0D911" }; var defaultFunctionalColors = { colorPrimary: "#1677ff", colorSuccess: "#52c41a", colorWarning: "#faad14", colorError: "#ff4d4f", colorInfo: "#1677ff" }; var seedToken = { // preset color palettes ...defaultPresetColors, // Color ...defaultFunctionalColors, colorTextBase: "", colorBgBase: "", // Font fontFamily: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'`, fontSize: 14, // Motion motionUnit: 0.1, motionBase: 0, motionEaseOutCirc: "cubic-bezier(0.08, 0.82, 0.17, 1)", motionEaseInOutCirc: "cubic-bezier(0.78, 0.14, 0.15, 0.86)", motionEaseOut: "cubic-bezier(0.215, 0.61, 0.355, 1)", motionEaseInOut: "cubic-bezier(0.645, 0.045, 0.355, 1)", motionEaseOutBack: "cubic-bezier(0.12, 0.4, 0.29, 1.46)", motionEaseInBack: "cubic-bezier(0.71, -0.46, 0.88, 0.6)", motionEaseInQuint: "cubic-bezier(0.755, 0.05, 0.855, 0.06)", motionEaseOutQuint: "cubic-bezier(0.23, 1, 0.32, 1)", // Radius borderRadius: 6 }; var seed_default = seedToken; // src/plugins/theme/themes/default/index.ts import { generate as generate2 } from "@ant-design/colors"; // src/plugins/theme/themes/shared/genColorMapToken.ts import { TinyColor } from "@ctrl/tinycolor"; function genColorMapToken(seed, { generateColorPalettes: generateColorPalettes3, generateNeutralColorPalettes: generateNeutralColorPalettes3 }) { const { colorSuccess: colorSuccessBase, colorWarning: colorWarningBase, colorError: colorErrorBase, colorInfo: colorInfoBase, colorPrimary: colorPrimaryBase, colorBgBase, colorTextBase } = seed; const primaryColors = generateColorPalettes3(colorPrimaryBase); const successColors = generateColorPalettes3(colorSuccessBase); const warningColors = generateColorPalettes3(colorWarningBase); const errorColors = generateColorPalettes3(colorErrorBase); const infoColors = generateColorPalettes3(colorInfoBase); const neutralColors = generateNeutralColorPalettes3(colorBgBase, colorTextBase); return { ...neutralColors, colorPrimaryBg: primaryColors[1], colorPrimaryBgHover: primaryColors[2], colorPrimaryBorder: primaryColors[3], colorPrimaryBorderHover: primaryColors[4], colorPrimaryHover: primaryColors[5], colorPrimary: primaryColors[6], colorPrimaryActive: primaryColors[7], colorPrimaryTextHover: primaryColors[8], colorPrimaryText: primaryColors[9], colorPrimaryTextActive: primaryColors[10], colorSuccessBg: successColors[1], colorSuccessBgHover: successColors[2], colorSuccessBorder: successColors[3], colorSuccessBorderHover: successColors[4], colorSuccessHover: successColors[4], colorSuccess: successColors[6], colorSuccessActive: successColors[7], colorSuccessTextHover: successColors[8], colorSuccessText: successColors[9], colorSuccessTextActive: successColors[10], colorErrorBg: errorColors[1], colorErrorBgHover: errorColors[2], colorErrorBorder: errorColors[3], colorErrorBorderHover: errorColors[4], colorErrorHover: errorColors[5], colorError: errorColors[6], colorErrorActive: errorColors[7], colorErrorTextHover: errorColors[8], colorErrorText: errorColors[9], colorErrorTextActive: errorColors[10], colorWarningBg: warningColors[1], colorWarningBgHover: warningColors[2], colorWarningBorder: warningColors[3], colorWarningBorderHover: warningColors[4], colorWarningHover: warningColors[4], colorWarning: warningColors[6], colorWarningActive: warningColors[7], colorWarningTextHover: warningColors[8], colorWarningText: warningColors[9], colorWarningTextActive: warningColors[10], colorInfoBg: infoColors[1], colorInfoBgHover: infoColors[2], colorInfoBorder: infoColors[3], colorInfoBorderHover: infoColors[4], colorInfoHover: infoColors[4], colorInfo: infoColors[6], colorInfoActive: infoColors[7], colorInfoTextHover: infoColors[8], colorInfoText: infoColors[9], colorInfoTextActive: infoColors[10], colorBgMask: new TinyColor("#000").setAlpha(0.45).toRgbString(), colorWhite: "#fff" }; } // src/plugins/theme/themes/shared/genRadius.ts var genRadius = (radiusBase) => { let radiusLG = radiusBase; let radiusSM = radiusBase; let radiusXS = radiusBase; let radiusOuter = radiusBase; if (radiusBase < 6 && radiusBase >= 5) { radiusLG = radiusBase + 1; } else if (radiusBase < 16 && radiusBase >= 6) { radiusLG = radiusBase + 2; } else if (radiusBase >= 16) { radiusLG = 16; } if (radiusBase < 7 && radiusBase >= 5) { radiusSM = 4; } else if (radiusBase < 8 && radiusBase >= 7) { radiusSM = 5; } else if (radiusBase < 14 && radiusBase >= 8) { radiusSM = 6; } else if (radiusBase < 16 && radiusBase >= 14) { radiusSM = 7; } else if (radiusBase >= 16) { radiusSM = 8; } if (radiusBase < 6 && radiusBase >= 2) { radiusXS = 1; } else if (radiusBase >= 6) { radiusXS = 2; } if (radiusBase > 4 && radiusBase < 8) { radiusOuter = 4; } else if (radiusBase >= 8) { radiusOuter = 6; } return { borderRadius: radiusBase > 16 ? 16 : radiusBase, borderRadiusXS: radiusXS, borderRadiusSM: radiusSM, borderRadiusLG: radiusLG, borderRadiusOuter: radiusOuter }; }; var genRadius_default = genRadius; // src/plugins/theme/themes/shared/genCommonMapToken.ts function genCommonMapToken(token) { const { motionUnit, motionBase, borderRadius } = token; return { // motion motionDurationFast: `${(motionBase + motionUnit).toFixed(1)}s`, motionDurationMid: `${(motionBase + motionUnit * 2).toFixed(1)}s`, motionDurationSlow: `${(motionBase + motionUnit * 3).toFixed(1)}s`, // radius ...genRadius_default(borderRadius) }; } // src/plugins/theme/themes/default/colors.ts import { generate } from "@ant-design/colors"; // src/plugins/theme/themes/default/colorAlgorithm.ts import { TinyColor as TinyColor2 } from "@ctrl/tinycolor"; var getAlphaColor = (baseColor, alpha) => new TinyColor2(baseColor).setAlpha(alpha).toRgbString(); var getSolidColor = (baseColor, brightness) => { const instance = new TinyColor2(baseColor); return instance.darken(brightness).toHexString(); }; // src/plugins/theme/themes/default/colors.ts var generateColorPalettes = (baseColor) => { const colors = generate(baseColor); return { 1: colors[0], 2: colors[1], 3: colors[2], 4: colors[3], 5: colors[4], 6: colors[5], 7: colors[6], 8: colors[4], 9: colors[5], 10: colors[6] }; }; var generateNeutralColorPalettes = (bgBaseColor, textBaseColor) => { const colorBgBase = bgBaseColor || "#fff"; const colorTextBase = textBaseColor || "#000"; return { colorBgBase, colorTextBase, colorText: getAlphaColor(colorTextBase, 0.88), colorTextSecondary: getAlphaColor(colorTextBase, 0.65), colorTextTertiary: getAlphaColor(colorTextBase, 0.45), colorTextQuaternary: getAlphaColor(colorTextBase, 0.25), colorFill: getAlphaColor(colorTextBase, 0.15), colorFillSecondary: getAlphaColor(colorTextBase, 0.06), colorFillTertiary: getAlphaColor(colorTextBase, 0.04), colorFillQuaternary: getAlphaColor(colorTextBase, 0.02), colorBgLayout: getSolidColor(colorBgBase, 4), colorBgContainer: getSolidColor(colorBgBase, 0), colorBgElevated: getSolidColor(colorBgBase, 0), colorBgSpotlight: getAlphaColor(colorTextBase, 0.85), colorBorder: getSolidColor(colorBgBase, 15), colorBorderSecondary: getSolidColor(colorBgBase, 6) }; }; // src/plugins/theme/themes/shared/genFontSizes.ts function getFontSizes(base) { const fontSizes = new Array(10).fill(null).map((_, index) => { const i = index - 1; const baseSize = base * 2.71828 ** (i / 5); const intSize = index > 1 ? Math.floor(baseSize) : Math.ceil(baseSize); return Math.floor(intSize / 2) * 2; }); fontSizes[1] = base; return fontSizes.map((size) => { const height = size + 8; return { size, lineHeight: height / size }; }); } // src/plugins/theme/themes/shared/genFontMapToken.ts var genFontMapToken = (fontSize) => { const fontSizePairs = getFontSizes(fontSize); const fontSizes = fontSizePairs.map((pair) => pair.size); const lineHeights = fontSizePairs.map((pair) => pair.lineHeight); return { fontSizeSM: fontSizes[0], fontSize: fontSizes[1], fontSizeLG: fontSizes[2], fontSizeXL: fontSizes[3], fontSizeHeading1: fontSizes[6], fontSizeHeading2: fontSizes[5], fontSizeHeading3: fontSizes[4], fontSizeHeading4: fontSizes[3], fontSizeHeading5: fontSizes[2], lineHeight: lineHeights[1], lineHeightLG: lineHeights[2], lineHeightSM: lineHeights[0], lineHeightHeading1: lineHeights[6], lineHeightHeading2: lineHeights[5], lineHeightHeading3: lineHeights[4], lineHeightHeading4: lineHeights[3], lineHeightHeading5: lineHeights[2] }; }; var genFontMapToken_default = genFontMapToken; // src/plugins/theme/themes/default/index.ts function derivative(token) { const colorPalettes = Object.keys(defaultPresetColors).map((colorKey) => { const colors = generate2(token[colorKey]); return new Array(10).fill(1).reduce((prev, _, i) => { prev[`${colorKey}-${i + 1}`] = colors[i]; return prev; }, {}); }).reduce((prev, cur) => { prev = { ...prev, ...cur }; return prev; }, {}); return { ...token, ...colorPalettes, // Colors ...genColorMapToken(token, { generateColorPalettes, generateNeutralColorPalettes }), // Font ...genFontMapToken_default(token.fontSize), // Others ...genCommonMapToken(token) }; } // src/plugins/theme/themes/dark/index.ts import { generate as generate4 } from "@ant-design/colors"; // src/plugins/theme/themes/dark/colors.ts import { generate as generate3 } from "@ant-design/colors"; // src/plugins/theme/themes/dark/colorAlgorithm.ts import { TinyColor as TinyColor3 } from "@ctrl/tinycolor"; var getAlphaColor2 = (baseColor, alpha) => new TinyColor3(baseColor).setAlpha(alpha).toRgbString(); var getSolidColor2 = (baseColor, brightness) => { const instance = new TinyColor3(baseColor); return instance.lighten(brightness).toHexString(); }; // src/plugins/theme/themes/dark/colors.ts var generateColorPalettes2 = (baseColor) => { const colors = generate3(baseColor, { theme: "dark" }); return { 1: colors[0], 2: colors[1], 3: colors[2], 4: colors[3], 5: colors[6], 6: colors[5], 7: colors[4], 8: colors[6], 9: colors[5], 10: colors[4] }; }; var generateNeutralColorPalettes2 = (bgBaseColor, textBaseColor) => { const colorBgBase = bgBaseColor || "#000"; const colorTextBase = textBaseColor || "#fff"; return { colorBgBase, colorTextBase, colorText: getAlphaColor2(colorTextBase, 0.85), colorTextSecondary: getAlphaColor2(colorTextBase, 0.65), colorTextTertiary: getAlphaColor2(colorTextBase, 0.45), colorTextQuaternary: getAlphaColor2(colorTextBase, 0.25), colorFill: getAlphaColor2(colorTextBase, 0.18), colorFillSecondary: getAlphaColor2(colorTextBase, 0.12), colorFillTertiary: getAlphaColor2(colorTextBase, 0.08), colorFillQuaternary: getAlphaColor2(colorTextBase, 0.04), colorBgElevated: getSolidColor2(colorBgBase, 12), colorBgContainer: getSolidColor2(colorBgBase, 8), colorBgLayout: getSolidColor2(colorBgBase, 0), colorBgSpotlight: getSolidColor2(colorBgBase, 26), colorBorder: getSolidColor2(colorBgBase, 26), colorBorderSecondary: getSolidColor2(colorBgBase, 19) }; }; // src/plugins/theme/themes/dark/index.ts function derivative2(token, mapToken) { const colorPalettes = Object.keys(defaultPresetColors).map((colorKey) => { const colors = generate4(token[colorKey], { theme: "dark" }); return new Array(10).fill(1).reduce((prev, _, i) => { prev[`${colorKey}-${i + 1}`] = colors[i]; return prev; }, {}); }).reduce((prev, cur) => { prev = { ...prev, ...cur }; return prev; }, {}); const mergedMapToken = mapToken ?? derivative(token); return { ...mergedMapToken, // Dark tokens ...colorPalettes, // Colors ...genColorMapToken(token, { generateColorPalettes: generateColorPalettes2, generateNeutralColorPalettes: generateNeutralColorPalettes2 }) }; } // src/plugins/theme/themes/index.ts var genLegacyToken = (token) => { const seedToken2 = shallowMerge4({}, seed_default, token); const lightToken = derivative(seedToken2); const darkToken = derivative2(seedToken2, lightToken); return { lightToken, darkToken }; }; // src/plugins/theme/themes/shared/genCSSMapToken.ts import { camelToKebab } from "@txjs/shared"; // src/plugins/theme/themes/interface/presetColors.ts var PresetColors = [ "blue", "purple", "cyan", "green", "magenta", "pink", "red", "orange", "yellow", "volcano", "geekblue", "lime", "gold" ]; // src/plugins/theme/themes/interface/functionalColors.ts var FunctionalColors = [ "colorPrimary", "colorSuccess", "colorWarning", "colorError", "colorInfo" ]; // src/plugins/theme/themes/utils/index.ts var findPresetColor = (colorKey) => { return PresetColors.find((el) => colorKey.startsWith(el)); }; var includePresetColor = (colorKey) => { return PresetColors.includes(colorKey); }; var findFunctionalColor = (colorKey) => { return FunctionalColors.find((el) => colorKey.startsWith(el)); }; var findColorPrefix = (colorKey) => { return colorKey.startsWith("color"); }; var includeFunctoinalColor = (colorKey) => { return FunctionalColors.includes(colorKey); }; // src/plugins/theme/themes/utils/getRgbColor.ts import { TinyColor as TinyColor4 } from "@ctrl/tinycolor"; function getRgbColor(color) { const instance = new TinyColor4(color); if (instance.isValid) { const rgb = instance.toRgb(); return [rgb.r, rgb.g, rgb.b].join(" "); } return color; } // src/plugins/theme/themes/utils/getHexColor.ts import { TinyColor as TinyColor5 } from "@ctrl/tinycolor"; function blendChannelWithWhite(colorChannel, alpha) { return Math.floor(alpha * colorChannel + 255 * (1 - alpha)); } function toHex2(input) { return `0${input.toString(16).toUpperCase()}`.slice(-2); } function toHex(input) { const instance = new TinyColor5(input); if (instance.isValid) { const rgb = instance.toRgb(); const aplha = parseFloat(rgb.a.toString()); return `#${[rgb.r, rgb.g, rgb.b].map((el) => toHex2(blendChannelWithWhite(el, aplha))).join("")}`; } return input; } // src/plugins/theme/themes/utils/getPickColors.ts function getPickColors(token) { return Object.keys(token).reduce( (prev, cur) => { if (findPresetColor(cur) || findColorPrefix(cur)) { prev[cur] = token[cur]; } return prev; }, {} ); } // src/plugins/theme/themes/shared/genCSSMapToken.ts var BAN_LIST = [ "motionUnit", "motionBase", "colorWhite", "colorTextBase", "colorBgBase" ]; var FONT_SIZE_LIST = [ "fontSize", "fontSizeSM", "fontSizeLG", "fontSizeXL", "fontSizeHeading1", "fontSizeHeading2", "fontSizeHeading3", "fontSizeHeading4", "fontSizeHeading5" ]; var RADIUS_LIST = [ "borderRadius", "borderRadiusXS", "borderRadiusSM", "borderRadiusLG", "borderRadiusOuter" ]; var TEXT_COLOR_LIST = [ "colorText", "colorTextSecondary", "colorTextTertiary", "colorTextQuaternary" ]; var getSeedTokenValue = (key, value) => { let tempValue = value; if (FONT_SIZE_LIST.includes(key) || RADIUS_LIST.includes(key)) { tempValue = `${value}px`; } else if (includePresetColor(key) || includeFunctoinalColor(key)) { tempValue = getRgbColor(value); } else if (TEXT_COLOR_LIST.includes(key)) { tempValue = toHex(value); } return tempValue.toString(); }; var getCSSVarValue = (key, value) => { let tempValue = value; if (FONT_SIZE_LIST.includes(key) || RADIUS_LIST.includes(key)) { tempValue = `${value}px`; } else if (includePresetColor(key) || includeFunctoinalColor(key)) { tempValue = getRgbColor(value); } return tempValue.toString(); }; function genCSSVarMapToken(token, opts = {}) { let tempObject = token; if (opts?.dark) { tempObject = getPickColors(token); } return Object.keys(tempObject).reduce((prev, cur) => { if (!BAN_LIST.includes(cur)) { prev.push( `--${camelToKebab(cur)}: ${getCSSVarValue(cur, tempObject[cur])}` ); } return prev; }, []).join(";"); } // src/plugins/theme/tailwindcss/alias.ts import theme from "tailwindcss/defaultTheme"; import { shallowMerge as shallowMerge5, camelToKebab as camelToKebab3 } from "@txjs/shared"; // src/plugins/theme/tailwindcss/shared/genPresetColors.ts function genPresetColors(mapToken) { return Object.keys(mapToken).reduce( (prev, cur) => { const colorKey = findPresetColor(cur); if (colorKey) { const foundAt = cur.indexOf("-"); const partralMapToken = prev[colorKey] ??= {}; const value = `rgb(var(--${cur}) / <alpha-value>) /* ${mapToken[cur]} */`; if (foundAt >= 0) { const idx = parseInt(cur.slice(foundAt + 1)); partralMapToken[idx === 1 ? idx * 50 : (idx - 1) * 100] = value; } else { partralMapToken["DEFAULT"] = value; } prev[colorKey] = partralMapToken; } return prev; }, {} ); } // src/plugins/theme/tailwindcss/shared/genFunctionalColors.ts import { camelToKebab as camelToKebab2 } from "@txjs/shared"; var themeColorKey = "colors"; var themeAlias = { text: "textColor", border: "borderColor", bg: "backgroundColor" }; var defaultTheme = { colors: {}, textColor: {}, borderColor: {}, backgroundColor: {} }; function genFunctionalColors(mapToken) { return Object.keys(mapToken).reduce((prev, cur) => { const colorKey = findFunctionalColor(cur); if (colorKey) { let value; if (includeFunctoinalColor(cur)) { value = `rgb(var(--${camelToKebab2(cur)}) / <alpha-value>) /* ${mapToken[cur]} */`; } else { value = `var(--${camelToKebab2(cur)}) /* ${mapToken[cur]} */`; } const [key, key2] = camelToKebab2(cur.slice(colorKey.length)).split("-"); const themeKey = themeAlias[key] || themeColorKey; const partralMapToken = prev[themeKey][colorKey.slice(5).toLowerCase()] ??= {}; if (key2) { partralMapToken[key2] = value; } else if (key && themeKey === themeColorKey) { partralMapToken[key] = value; } else { partralMapToken["DEFAULT"] = value; } } return prev; }, defaultTheme); } // src/plugins/theme/tailwindcss/alias.ts function genColors(mapToken) { const theme2 = genFunctionalColors(mapToken); shallowMerge5(theme2.colors, genPresetColors(mapToken)); return theme2; } function genVariables(mapToken) { return Object.keys(mapToken).reduce( (prev, cur) => { const value = getSeedTokenValue(cur, mapToken[cur]); prev[cur] = `var(--${camelToKebab3(cur)}) /* ${value} */`; return prev; }, {} ); } function formatTailwindConfig(mapToken) { const variable = genVariables(mapToken); return { ...genColors(mapToken), lineHeight: { DEFAULT: variable.lineHeight, sm: variable.lineHeightSM, lg: variable.lineHeightLG, heading1: variable.lineHeightHeading1, heading2: variable.lineHeightHeading2, heading3: variable.lineHeightHeading3, heading4: variable.lineHeightHeading4, heading5: variable.lineHeightHeading5 }, transitionTimingFunction: { "out-circ": variable.motionEaseOutCirc, "in-out-circ": variable.motionEaseInOutCirc, out: variable.motionEaseOut, "in-out": variable.motionEaseInOut, "out-back": variable.motionEaseOutBack, "in-back": variable.motionEaseInBack, "in-quint": variable.motionEaseInQuint, "out-quint": variable.motionEaseOutQuint }, transitionDuration: { fast: variable.motionDurationFast, mid: variable.motionDurationMid, slow: variable.motionDurationSlow }, fontSize: { sm: [variable.fontSizeSM, variable.lineHeightSM], md: [variable.fontSize, variable.lineHeight], lg: [variable.fontSizeLG, variable.lineHeightLG], xl: [variable.fontSizeXL, variable.lineHeightLG], h1: [ variable.fontSizeHeading1, { lineHeight: variable.lineHeightHeading1, fontWeight: theme.fontWeight.semibold } ], h2: [ variable.fontSizeHeading2, { lineHeight: variable.lineHeightHeading2, fontWeight: theme.fontWeight.semibold } ], h3: [ variable.fontSizeHeading3, { lineHeight: variable.lineHeightHeading3, fontWeight: theme.fontWeight.semibold } ], h4: [ variable.fontSizeHeading4, { lineHeight: variable.lineHeightHeading4, fontWeight: theme.fontWeight.semibold } ], h5: [ variable.fontSizeHeading5, { lineHeight: variable.lineHeightHeading5, fontWeight: theme.fontWeight.semibold } ] }, borderColor: { base: variable.colorBorder, secondary: variable.colorBorderSecondary }, borderRadius: { DEFAULT: variable.borderRadius, xs: variable.borderRadiusSM, sm: variable.borderRadiusSM, lg: variable.borderRadiusLG, outer: variable.borderRadiusOuter }, fontFamily: { system: variable.fontFamily }, textColor: { DEFAULT: variable.colorText, secondary: variable.colorTextSecondary, tertiary: variable.colorTextTertiary, quaternary: variable.colorTextQuaternary }, backgroundColor: { container: variable.colorBgContainer, elevated: variable.colorBgElevated, layout: variable.colorBgLayout, spotlight: variable.colorBgSpotlight, mask: variable.colorBgMask, fill: { DEFAULT: variable.colorFill, secondary: variable.colorFillSecondary, tertiary: variable.colorFillTertiary, quaternary: variable.colorFillQuaternary } } }; } // src/plugins/theme/tailwindcss/generate.ts import { format as format2 } from "prettier"; import dayjs2 from "dayjs"; async function generateConfig(theme2, plugins) { return await format2( ` /** * This is the automatically generated tailwindcss configuration file. * https://v3.tailwindcss.com/docs/presets#extending-multiple-presets * generated form [@xmipra/plugins] * @date ${dayjs2().format("YYYY-MM-DD HH:mm:ss").toString()} */ ${plugins ? `import plugin from 'tailwindcss/plugin'` : ""} import colors from 'tailwindcss/colors' /** @type import('tailwindcss').Config */ export default { darkMode: 'media', content: ['./src/**/*.{html,vue,js,ts,jsx,tsx}'], corePlugins: { preflight: false, }, theme: { colors: { inherit: colors.inherit, transparent: colors.transparent, current: colors.current, white: colors.white, black: colors.black, gray: colors.gray }, extend: ${JSON.stringify(theme2)} }, ${plugins ? `plugins: ${plugins}` : ""} } `, { parser: "typescript", semi: false, tabWidth: 2, useTabs: false, singleQuote: true, printWidth: 80, endOfLine: "auto" } ); } // src/plugins/theme/index.ts function getStyleExt(env) { switch (env) { case "weapp": return "wxss"; case "alipay": return "acss"; case "tt": return "ttss"; } } var theme_default = defaultPlugin( "theme", (ctx, { logger, props }) => { props.esm ??= "mjs"; props.darkmode ??= false; const { designWidth, deviceRatio } = ctx.initialConfig; const { enable: pxtransformEnable, config: pxtransformConfig } = ctx.initialConfig.mini?.postcss?.pxtransform || {}; const themeFileName = `theme.${getStyleExt(ctx.TARO_ENV)}`; const themePath = resolve(CWD, ctx.outputDir, themeFileName); async function build(callback) { try { const { seedToken: seedToken2 = {}, ...themes } = ctx.pluginConfig.theme || {}; const partialSeed = pick3( seedToken2, Object.keys(seed_default), true ); const mpSeed = seedToken2[ctx.TARO_ENV] || {}; const finalSeed = shallowMerge6( {}, partialSeed, pick3(mpSeed, Object.keys(seed_default), true) ); const partialTheme = pick3(themes, ["light", "dark"], true); const mpTheme = themes[ctx.TARO_ENV] || {}; const lightTheme = shallowMerge6( {}, partialTheme.light, mpTheme.light, true ); const darkTheme = shallowMerge6( {}, partialTheme.dark, mpTheme.dark, true ); const { lightToken, darkToken } = genLegacyToken(finalSeed); shallowMerge6( lightToken, pick3(lightTheme, Object.keys(lightToken), true) ); shallowMerge6(darkToken, pick3(darkTheme, Object.keys(darkToken), true)); let styles = new cleanCSS().minify(` page {${genCSSVarMapToken(lightToken)}} ${props.darkmode ? `@media (prefers-color-scheme: dark) { page {${genCSSVarMapToken(darkToken, { dark: true })}} }` : ""} `).styles; if (pxtransformEnable) { styles = postcss( pxtorem({ platform: "weapp", designWidth, deviceRatio, ...pxtransformConfig || {} }) ).process(styles).css; } await fs6.outputFile(themePath, styles); const tailwindExtend = formatTailwindConfig(lightToken); await fs6.outputFile( resolve(CWD, `tailwind.xmipra.${props.esm}`), await generateConfig( tailwindExtend, `[ plugin(({ addVariant }) => { ${JSON.stringify(platforms)}.forEach((platform) => { if ('${ctx.TARO_ENV}' === platform) { addVariant(platform, '&') } ${ctx.NODE_ENV !== "production" ? `else { addVariant(platform, '&:not(&)') }` : ""} }) }) ]` ) ); callback?.(); } catch (error) { logger.warn(e