diff --git a/.cnb/Dockerfile b/.cnb/Dockerfile index 1e341458..38a94822 100644 --- a/.cnb/Dockerfile +++ b/.cnb/Dockerfile @@ -16,7 +16,12 @@ RUN curl -fsSL https://code-server.dev/install.sh | sh \ && echo done RUN npm install -g pnpm +RUN npm install -g @tencent-ai/codebuddy-code + +RUN apt install -y libxcb-shm0 libx11-xcb1 libx11-6 libxcb1 libxext6 libxrandr2 libxcomposite1 libxcursor1 libxdamage1 libxfixes3 libxi6 libgtk-3-0 libpangocairo-1.0-0 libpango-1.0-0 libatk1.0-0 libcairo-gobject2 libcairo2 libgdk-pixbuf-2.0-0 libxrender1 libasound2 libfreetype6 libfontconfig1 libdbus-1-3 libnss3 libnspr4 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libatspi2.0-0 libcups2 libxshmfence1 libgbm1 fonts-noto-color-emoji fonts-noto-cjk fonts-freefont-ttf +RUN npm install -g agent-browser +RUN agent-browser install --with-deps # 指定字符集支持命令行输入中文(根据需要选择字符集) ENV LANG=C.UTF-8 -ENV LANGUAGE=C.UTF-8 \ No newline at end of file +ENV LANGUAGE=C.UTF-8 diff --git a/.github/workflows/pkg-pr-new.yml b/.github/workflows/pkg-pr-new.yml index b217088f..8cb7ef59 100644 --- a/.github/workflows/pkg-pr-new.yml +++ b/.github/workflows/pkg-pr-new.yml @@ -276,6 +276,10 @@ jobs: - run: pnpm -C packages/tdesign-uniapp/site site:preview + - run: pnpm uniapp build:npm + + - run: pnpm -C packages/tdesign-uniapp/example build:h5 --mode preview + - uses: actions/upload-artifact@v7 with: name: tdesign-uniapp-site diff --git a/packages/theme-generator/.eslintrc.js b/packages/theme-generator/.eslintrc.js index 31733bfd..1f4651ea 100644 --- a/packages/theme-generator/.eslintrc.js +++ b/packages/theme-generator/.eslintrc.js @@ -1,13 +1,15 @@ -const path = require('path'); - module.exports = { root: true, - extends: ['plugin:vue/essential', './../../.eslintrc.js'], + parser: 'vue-eslint-parser', parserOptions: { - parser: '@babel/eslint-parser', - babelOptions: { - configFile: path.resolve(__dirname, './babel.config.js'), - }, + ecmaVersion: 2021, + sourceType: 'module', + }, + plugins: ['vue'], + // 根配置在前,vue 配置在后(确保 vue 的 script-setup-uses-vars 等规则优先生效) + extends: ['./../../.eslintrc.js', 'plugin:vue/vue3-essential'], + rules: { + // 让 no-unused-vars 识别 + + + + diff --git a/packages/theme-generator/jsconfig.json b/packages/theme-generator/jsconfig.json index b6bd4c8d..2bbea9ba 100644 --- a/packages/theme-generator/jsconfig.json +++ b/packages/theme-generator/jsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "esnext", "module": "esnext", "baseUrl": "./", "moduleResolution": "node", diff --git a/packages/theme-generator/package.json b/packages/theme-generator/package.json index 7415ab3c..5f4363ec 100644 --- a/packages/theme-generator/package.json +++ b/packages/theme-generator/package.json @@ -4,10 +4,13 @@ "license": "MIT", "description": "TDesign主题配置生成器挂件", "scripts": { - "dev": "vue-cli-service serve", - "build": "vue-cli-service build --target wc --inline-vue --name td-theme-generator src/Generator.vue", - "build:watch": "vue-cli-service build --target wc --inline-vue --name td-theme-generator src/Generator.vue --watch", - "lint": "vue-cli-service lint" + "dev": "vite", + "build:css": "node scripts/build-tdesign-css.mjs", + "build": "npm run build:css && vite build", + "build:watch": "vite build --watch", + "test": "vitest run", + "test:watch": "vitest", + "lint": "eslint src --ext .vue,.js --fix" }, "main": "dist/td-theme-generator.js", "files": [ @@ -29,27 +32,23 @@ }, "homepage": "https://github.com/Tencent/tdesign/blob/main/packages/theme-generator/README.md", "dependencies": { - "core-js": "^3.8.3", "cssbeautify": "^0.3.1", "lodash": "^4.17.21", - "tdesign-icons-vue": "^0.0.8", - "tdesign-vue": "1.13.1-naruto", + "tdesign-icons-vue-next": "^0.4.4", + "tdesign-vue-next": "https://pkg.pr.new/tdesign-vue-next@6779", "tvision-color": "^1.6.0", - "vue": "2.7.14" + "vue": "^3.5.25" }, "devDependencies": { - "@babel/core": "^7.20.12", - "@babel/eslint-parser": "^7.12.16", - "@vue/cli-plugin-babel": "~5.0.0", - "@vue/cli-plugin-eslint": "~5.0.0", - "@vue/cli-service": "~5.0.0", - "eslint-plugin-vue": "^8.0.3", - "less": "^4.1.2", - "less-loader": "^10.2.0", - "raw-loader": "^4.0.2", - "vue-loader": "^17.0.0", - "vue-svg-loader": "^0.17.0-beta.2", - "vue-template-compiler": "2.7.14" + "@vitejs/plugin-vue": "^5.2.1", + "@vitest/coverage-v8": "^2.1.8", + "@vue/test-utils": "^2.4.6", + "eslint-plugin-vue": "^9.32.0", + "happy-dom": "^15.11.7", + "less": "^4.2.0", + "vite": "^6.3.1", + "vitest": "^2.1.8", + "vue-eslint-parser": "^9.4.2" }, "browserslist": [ "> 1%", diff --git a/packages/theme-generator/public/index.html b/packages/theme-generator/public/index.html deleted file mode 100644 index 3e5a1396..00000000 --- a/packages/theme-generator/public/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - <%= htmlWebpackPlugin.options.title %> - - - -
- - - diff --git a/packages/theme-generator/scripts/build-tdesign-css.mjs b/packages/theme-generator/scripts/build-tdesign-css.mjs new file mode 100644 index 00000000..10557697 --- /dev/null +++ b/packages/theme-generator/scripts/build-tdesign-css.mjs @@ -0,0 +1,120 @@ +/* eslint-disable */ + +// 重新生成 packages/theme-generator/src/styles/ 下的两个 CSS 文件: +// 1. tdesign.min.css —— 全量组件 + token CSS,定制 :host 变体 + 移除 brand-color token +// 2. reset.min.css —— normalize.css 重置样式,仅压缩,无定制 +// +// 数据来源:上游 tdesign-vue-next 的 dist 目录。 +// tdesign.min.css 上游已压缩,reset.css 上游未压缩,本脚本对后者做压缩。 +// +// 运行:npm run build:css +// 升级 tdesign-vue-next 后需重新运行以从新上游重新生成。 +import { readFileSync, writeFileSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const PKG = resolve(__dirname, '..'); +const DIST = resolve(PKG, 'node_modules/tdesign-vue-next/dist'); +const STYLES = resolve(PKG, 'src/styles'); + +// ========== tdesign.min.css ========== +let tdesignCss = readFileSync(resolve(DIST, 'tdesign.min.css'), 'utf8'); + +// --- (1) 为每个选择器组中的 :root 选择器追加 :host 变体 --- +// 上游压缩后的 CSS 使用形如 `:root,:root[theme-mode='light']{...}` 的选择器组。 +// 对每个以 :root 开头的选择器,追加并行的 :host 变体,使用函数式 `:host()`。 +// Chrome 不会匹配复合形式 `:host[attr]` 或 `:host.class`, +// 只有 `:host([attr])` / `:host(.class)` 才能命中 host 的属性/类。 +// 裸 `:root` 转为裸 `:host`(无括号)。上游不存在 `:root <后代>` 规则。 +// @-moz-document url-prefix() 等 at-rule 没有 :root 选择器,原样透传。 +tdesignCss = tdesignCss.replace(/([^{}]+)\{/g, (m, selectors) => { + const list = selectors.split(',').map((s) => s.trim()).filter(Boolean); + const hostVariants = list + .filter((s) => /^:root(?=[[\].\s,:]|$)/.test(s)) + .map((s) => { + const tail = s.slice(':root'.length); + return tail ? `:host(${tail})` : ':host'; + }); + if (hostVariants.length === 0) return m; + return `${list.join(',')},${hostVariants.join(',')}{`; +}); + +// --- (2) 移除 --td-brand-color* 自定义属性声明 --- +// 匹配基础名(--td-brand-color)和派生/编号系列 +// (--td-brand-color-1、--td-brand-color-hover ...)。 +// 不会匹配 --td-text-color-brand / --td-text-color-link(前缀不同)。 +// 上游压缩形态为 `--td-brand-color-1:#f2f3ff;`(无空格,分号结尾)。 +// [^;}]* 在下一个 ; 或 } 处停止,因此不会越过下一条声明。 +tdesignCss = tdesignCss.replace(/--td-brand-color[a-z0-9-]*\s*:[^;}]*;?/g, ''); + +// --- (3) 移除 source-map 注释(不发布 .map 文件) --- +tdesignCss = tdesignCss.replace(/\/\*# sourceMappingURL=[^*]*\*\//g, ''); + +writeFileSync(resolve(STYLES, 'tdesign.min.css'), tdesignCss + '\n', 'utf8'); + +// ========== reset.min.css ========== +// 上游 reset.css 是带注释的未压缩 normalize.css,无 :root 选择器、无 brand-color token, +// 因此不需要 tdesign.min.css 的两步定制,仅做压缩。 +const resetCss = minifyCss(readFileSync(resolve(DIST, 'reset.css'), 'utf8')); +writeFileSync(resolve(STYLES, 'reset.min.css'), resetCss + '\n', 'utf8'); + +// ========== generator-vars.css ========== +// 生成器专用变量(vars.css)原通过 initGeneratorVars 注入 document.head(Light DOM), +// 但生成器 UI 运行在 Shadow DOM 中,CSS 自定义属性不穿透 Shadow Boundary。 +// 这里把 vars.css 的 :root 选择器转为 :host 变体,生成 generator-vars.css, +// 由 wc-entry.js 以 ?inline 导入并注入 Shadow Root。 +// 转换规则与 tdesign.min.css 的 :host 变体逻辑一致: +// :root → :host +// :root[theme-mode='x'] → :host([theme-mode='x']) +// :root.dark → :host(.dark) +const VARS_SRC = resolve(PKG, 'src/common/themes/built-in/css/vars.css'); +let generatorVars = readFileSync(VARS_SRC, 'utf8'); +generatorVars = generatorVars.replace(/([^{}]+)\{/g, (m, selectors) => { + const list = selectors.split(',').map((s) => s.trim()).filter(Boolean); + const hostVariants = list + .filter((s) => /^:root(?=[[\].\s,:]|$)/.test(s)) + .map((s) => { + const tail = s.slice(':root'.length); + return tail ? `:host(${tail})` : ':host'; + }); + if (hostVariants.length === 0) return m; + return `${list.join(',')},${hostVariants.join(',')}{`; +}); +writeFileSync(resolve(STYLES, 'generator-vars.css'), generatorVars + '\n', 'utf8'); + +// --- 压缩 CSS(仅用于 reset.css) --- +// 移除注释 → 折叠空白 → 压缩标点周围空白 → 移除 } 前的分号。 +// 不改动选择器与值本身(保留 -webkit- 前缀、字体名引号等上游原始形态)。 +function minifyCss(css) { + return css + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/\s+/g, ' ') + .replace(/\s*([{};:,])\s*/g, '$1') + .replace(/;}/g, '}') + .trim(); +} + +// ========== 校验输出 ========== +const brandColorDefs = (tdesignCss.match(/--td-brand-color[a-z0-9-]*\s*:/g) || []).length; +const hostCount = (tdesignCss.match(/:host/g) || []).length; +const rootCount = (tdesignCss.match(/:root/g) || []).length; +const textColorBrand = /--td-text-color-brand\s*:/.test(tdesignCss); +const varsHostCount = (generatorVars.match(/:host/g) || []).length; +console.log(JSON.stringify({ + tdesignMinCss: { + outBytes: tdesignCss.length, + brandColorDefsRemoved: brandColorDefs === 0, + brandColorDefsRemaining: brandColorDefs, + hostSelectors: hostCount, + rootSelectors: rootCount, + textColorBrandKept: textColorBrand, + }, + resetMinCss: { + outBytes: resetCss.length, + }, + generatorVarsCss: { + outBytes: generatorVars.length, + hostSelectors: varsHostCount, + }, +}, null, 2)); diff --git a/packages/theme-generator/src/Generator.vue b/packages/theme-generator/src/Generator.vue index 6cccf975..9974a41a 100644 --- a/packages/theme-generator/src/Generator.vue +++ b/packages/theme-generator/src/Generator.vue @@ -10,63 +10,69 @@ - diff --git a/packages/theme-generator/src/radius-panel/index.vue b/packages/theme-generator/src/radius-panel/index.vue index 60d82998..e92d8ab7 100644 --- a/packages/theme-generator/src/radius-panel/index.vue +++ b/packages/theme-generator/src/radius-panel/index.vue @@ -9,7 +9,7 @@ >
-

{{ lang.borerRadius.radiusSize }}

+

{{ lang.borderRadius.radiusSize }}

-