From a249190d370e87ce6bc548bdede52b4412bea4fd Mon Sep 17 00:00:00 2001 From: dengfuping Date: Wed, 25 Oct 2023 17:34:36 +0800 Subject: [PATCH] feat(codemod): Add less-to-token transform --- packages/codemod/bin/cli.js | 15 ++-- packages/codemod/package.json | 2 + .../antd-v4-less-to-token.input.less | 12 +++ .../antd-v4-less-to-token.output.less | 13 +++ .../obui-less-to-token.input.less | 14 +++ .../obui-less-to-token.output.less | 13 +++ .../__tests__/less-to-token.test.ts | 16 ++++ packages/codemod/transforms/less-to-token.js | 86 +++++++++++++++++++ packages/codemod/transforms/style-to-token.js | 50 +---------- packages/codemod/transforms/utils/token.js | 38 ++++++++ pnpm-lock.yaml | 35 ++++---- 11 files changed, 224 insertions(+), 70 deletions(-) create mode 100644 packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less create mode 100644 packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less create mode 100644 packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less create mode 100644 packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less create mode 100644 packages/codemod/transforms/__tests__/less-to-token.test.ts create mode 100644 packages/codemod/transforms/less-to-token.js create mode 100644 packages/codemod/transforms/utils/token.js diff --git a/packages/codemod/bin/cli.js b/packages/codemod/bin/cli.js index 21b732718..642e771a1 100644 --- a/packages/codemod/bin/cli.js +++ b/packages/codemod/bin/cli.js @@ -17,6 +17,7 @@ const commandExistsSync = require('command-exists').sync; const pkg = require('../package.json'); const pkgUpgradeList = require('./upgrade-list'); const { getDependencies } = require('../transforms/utils/marker'); +const { lessToToken } = require('../transforms/less-to-token'); // jscodeshift codemod scripts dir const transformersDir = path.join(__dirname, '../transforms'); @@ -31,6 +32,7 @@ const transformers = [ 'obutil-to-oceanbase-util', 'page-container-to-oceanbase-ui', 'style-to-token', + 'less-to-token', ]; const dependencyProperties = [ @@ -113,12 +115,15 @@ async function transform(transformer, parser, filePath, options) { }); try { - if (process.env.NODE_ENV === 'local') { - console.log(`Running jscodeshift with: ${JSON.stringify(args)}`); + if (transformer === 'less-to-token') { + await lessToToken(filePath); + } else { + if (process.env.NODE_ENV === 'local') { + console.log(`Running jscodeshift with: ${JSON.stringify(args)}`); + } + // js part + await jscodeshift(transformerPath, [filePath], args); } - - // js part - await jscodeshift(transformerPath, [filePath], args); console.log(); } catch (err) { console.error(err); diff --git a/packages/codemod/package.json b/packages/codemod/package.json index 3e88336b0..c55fd2aa6 100644 --- a/packages/codemod/package.json +++ b/packages/codemod/package.json @@ -32,6 +32,8 @@ "is-git-clean": "^1.1.0", "jscodeshift": "^0.15.0", "lodash": "^4.17.21", + "postcss": "^8.4.31", + "postcss-less": "^6.0.0", "prettier": "^3.0.3", "read-pkg-up": "^10.1.0", "semver": "^7.5.4", diff --git a/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less b/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less new file mode 100644 index 000000000..1c8cb4539 --- /dev/null +++ b/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less @@ -0,0 +1,12 @@ +.container { + color: #1890ff; + background: #52c41a; + background-color: #faad14; + border-color: #ff4D4F; + .content { + color: rgba(0, 0, 0, 0.85); + background: rgba(0, 0, 0,0.65); + background-color: rgba(0,0,0,0.45); + border-color: #fafafa; + } +} diff --git a/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less b/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less new file mode 100644 index 000000000..f8870a7d9 --- /dev/null +++ b/packages/codemod/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less @@ -0,0 +1,13 @@ +@import '~@oceanbase/design/es/theme/index.less'; +.container { + color: @colorInfo; + background: @colorSuccess; + background-color: @colorWarning; + border-color: @colorError; + .content { + color: @colorText; + background: @colorTextSecondary; + background-color: @colorTextTertiary; + border-color: @colorBgLayout; + } +} diff --git a/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less b/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less new file mode 100644 index 000000000..8009590fc --- /dev/null +++ b/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less @@ -0,0 +1,14 @@ +@import '~@alipay/ob-ui/es/theme/index.less'; + +.container { + color: @colorInfo; + background: @colorSuccess; + background-color: @colorWarning; + border-color: @colorError; + .content { + color: rgba(0, 0, 0, 0.85); + background: rgba(0, 0, 0,0.65); + background-color: rgba(0,0,0,0.45); + border-color: #fafafa; + } +} diff --git a/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less b/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less new file mode 100644 index 000000000..f8870a7d9 --- /dev/null +++ b/packages/codemod/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less @@ -0,0 +1,13 @@ +@import '~@oceanbase/design/es/theme/index.less'; +.container { + color: @colorInfo; + background: @colorSuccess; + background-color: @colorWarning; + border-color: @colorError; + .content { + color: @colorText; + background: @colorTextSecondary; + background-color: @colorTextTertiary; + border-color: @colorBgLayout; + } +} diff --git a/packages/codemod/transforms/__tests__/less-to-token.test.ts b/packages/codemod/transforms/__tests__/less-to-token.test.ts new file mode 100644 index 000000000..0423e2a38 --- /dev/null +++ b/packages/codemod/transforms/__tests__/less-to-token.test.ts @@ -0,0 +1,16 @@ +import fs from 'fs'; +import path from 'path'; +import { transform } from '../less-to-token'; + +const testUnit = 'less-to-token'; +const tests = ['antd-v4-less-to-token', 'obui-less-to-token']; + +describe(testUnit, () => { + tests.forEach(test => { + it(test, async () => { + const result = await transform(path.join(__dirname, `../__testfixtures__/less-to-token/${test}.input.less`)) + const output = fs.readFileSync(path.join(__dirname, `../__testfixtures__/less-to-token/${test}.output.less`), 'utf-8'); + expect(result).toEqual(output); + }) + }); +}); diff --git a/packages/codemod/transforms/less-to-token.js b/packages/codemod/transforms/less-to-token.js new file mode 100644 index 000000000..97f7b1100 --- /dev/null +++ b/packages/codemod/transforms/less-to-token.js @@ -0,0 +1,86 @@ +const path = require('path'); +const fs = require('fs'); +const postcss = require('postcss'); +const postcssLess = require('postcss-less'); +const isDirectory = require('is-directory'); +const { TOKEN_MAP, formatValue } = require('./utils/token'); + +/** + * 搜索目录下所有的less文件 + * @param dir + * @returns + */ +const findAllLessFiles = dir => { + const lessFiles = []; + const isDir = isDirectory.sync(dir); + if (isDir) { + const files = fs.readdirSync(dir); + files.forEach(file => { + const filePath = path.join(dir, file); + if (isDirectory.sync(filePath)) { + if (filePath.includes('.umi')) { + return; + } + lessFiles.push(...findAllLessFiles(filePath)); + } else if (file.endsWith('.less')) { + lessFiles.push(filePath); + } + }); + } else { + lessFiles.push(dir); + } + return lessFiles; +}; + +/** + * 将 lesscode 转化为 ast + * @returns ASR + */ +const less2AST = code => + postcss([]) + .process(code, { + parser: postcssLess.parse, + from: undefined, + }) + .then(result => result.root); + +async function transform(file) { + const content = fs.readFileSync(file, 'utf-8'); + const ast = await less2AST(content); + let modified = false; + let tokenLessImported = false; + // 遍历 AST + ast.walk(node => { + if (node.type === 'decl' && TOKEN_MAP[formatValue(node.value)]) { + node.value = `@${TOKEN_MAP[formatValue(node.value)]}`; + modified = true; + } else if (node.type === 'atrule' && node.name === 'import') { + if (node.params === "'~@oceanbase/design/es/theme/index.less'") { + tokenLessImported = true; + } else if (node.params === "'~@alipay/ob-ui/es/theme/index.less'") { + node.remove(); + } + } + }); + // prepend @import '~@oceanbase/design/es/theme/index.less'; + if (modified && !tokenLessImported) { + ast.prepend({ + name: 'import', + params: "'~@oceanbase/design/es/theme/index.less'", + }); + } + return ast.toString(); +} + +async function lessToToken(file) { + const allLessFiles = findAllLessFiles(file); + for await (const item of allLessFiles) { + const content = await transform(item); + fs.writeFileSync(file, content); + } +} + +module.exports = { + transform, + lessToToken, +}; diff --git a/packages/codemod/transforms/style-to-token.js b/packages/codemod/transforms/style-to-token.js index c3fef5d7d..61f96463e 100644 --- a/packages/codemod/transforms/style-to-token.js +++ b/packages/codemod/transforms/style-to-token.js @@ -1,38 +1,7 @@ -const { toLower } = require('lodash'); const { addSubmoduleImport } = require('./utils'); +const { TOKEN_MAP, formatValue } = require('./utils/token'); const { printOptions } = require('./utils/config'); -const TOKEN_MAP = { - // antd fixed style => antd v5 token - '#f0f2f5': 'colorBgLayout', - '#fafafa': 'colorBgLayout', - '#fff': 'colorBgContainer', - '#ffffff': 'colorBgContainer', - '#1890ff': 'colorInfo', - '#52c41a': 'colorSuccess', - '#73d13d': 'colorSuccess', - '#faad14': 'colorWarning', - '#ff4d4f': 'colorError', - '#F5222D': 'colorError', - '#F8636B': 'colorError', - '#d9d9d9': 'colorBorder', - '#bfbfbf': 'colorBorder', - 'rgba(0,0,0,0.85)': 'colorText', - 'rgba(0,0,0,0.65)': 'colorTextSecondary', - 'rgba(0,0,0,0.45)': 'colorTextTertiary', - 'rgba(0,0,0,0.25)': 'colorTextQuaternary', - 'rgba(0,0,0,0.2)': 'colorFillQuaternary', - 'rgba(0,0,0,0.04)': 'colorBgLayout', -}; - -function trimAll(str) { - return str?.replace(/(\s)*/g, ''); -} - -function formatValue(value) { - return trimAll(toLower(value)); -} - function importComponent(j, root, options) { let hasChanged = false; @@ -76,23 +45,6 @@ function importComponent(j, root, options) { }); } } - - // const name = path.value.declarations[0].id.name; - // if (/^[A-Z]/.test(name)) { - // const init = path.value.declarations[0].init; - // const initCode = generate(path.value).code; - // if ( - // init && - // initCode.includes('token.') && - // // avoid duplicate statement - // !initCode.includes('useToken()') && - // init.type === 'ArrowFunctionExpression' - // ) { - // const codeBody = init.body; - // const importStyleString = `const { token } = theme.useToken();`; - // codeBody.body.unshift(j.blockStatement(importStyleString).program.body[0]); - // } - // } }); } diff --git a/packages/codemod/transforms/utils/token.js b/packages/codemod/transforms/utils/token.js new file mode 100644 index 000000000..a1d5f3380 --- /dev/null +++ b/packages/codemod/transforms/utils/token.js @@ -0,0 +1,38 @@ +const { toLower } = require('lodash'); + +const TOKEN_MAP = { + // antd fixed style => antd v5 token + '#f0f2f5': 'colorBgLayout', + '#fafafa': 'colorBgLayout', + '#fff': 'colorBgContainer', + '#ffffff': 'colorBgContainer', + '#1890ff': 'colorInfo', + '#52c41a': 'colorSuccess', + '#73d13d': 'colorSuccess', + '#faad14': 'colorWarning', + '#ff4d4f': 'colorError', + '#F5222D': 'colorError', + '#F8636B': 'colorError', + '#d9d9d9': 'colorBorder', + '#bfbfbf': 'colorBorder', + 'rgba(0,0,0,0.85)': 'colorText', + 'rgba(0,0,0,0.65)': 'colorTextSecondary', + 'rgba(0,0,0,0.45)': 'colorTextTertiary', + 'rgba(0,0,0,0.25)': 'colorTextQuaternary', + 'rgba(0,0,0,0.2)': 'colorFillQuaternary', + 'rgba(0,0,0,0.04)': 'colorBgLayout', +}; + +function trimAll(str) { + return str?.replace(/(\s)*/g, ''); +} + +function formatValue(value) { + return trimAll(toLower(value)); +} + +module.exports = { + TOKEN_MAP, + trimAll, + formatValue, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b898bd13b..3e5483410 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.1' +lockfileVersion: '6.0' settings: autoInstallPeers: true @@ -300,6 +300,12 @@ importers: lodash: specifier: ^4.17.21 version: 4.17.21 + postcss: + specifier: ^8.4.31 + version: 8.4.31 + postcss-less: + specifier: ^6.0.0 + version: 6.0.0(postcss@8.4.31) prettier: specifier: ^3.0.3 version: 3.0.3 @@ -5399,7 +5405,7 @@ packages: dependencies: '@babel/core': 7.23.2 postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) transitivePeerDependencies: - supports-color dev: true @@ -5413,7 +5419,7 @@ packages: dependencies: '@babel/core': 7.23.2 postcss: 8.4.31 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) transitivePeerDependencies: - supports-color dev: true @@ -5426,7 +5432,7 @@ packages: postcss-syntax: '>=0.36.2' dependencies: postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) remark: 13.0.0 unist-util-find-all-after: 3.0.2 transitivePeerDependencies: @@ -6894,7 +6900,7 @@ packages: eslint-plugin-react: 7.33.2(eslint@8.51.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.51.0) postcss: 8.4.31 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) stylelint-config-standard: 25.0.0(stylelint@14.16.1) transitivePeerDependencies: - eslint @@ -15509,6 +15515,7 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -15518,6 +15525,7 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -15527,6 +15535,7 @@ packages: engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -15536,6 +15545,7 @@ packages: engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -17054,7 +17064,6 @@ packages: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /nanomatch@1.2.13: resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} @@ -18644,7 +18653,7 @@ packages: dependencies: htmlparser2: 3.10.1 postcss: 7.0.39 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) dev: true /postcss-image-set-function@4.0.7(postcss@8.4.31): @@ -18697,7 +18706,6 @@ packages: postcss: ^8.3.5 dependencies: postcss: 8.4.31 - dev: true /postcss-logical@5.0.4(postcss@8.4.31): resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} @@ -18956,7 +18964,7 @@ packages: postcss: 5.2.18 dev: true - /postcss-syntax@0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39): + /postcss-syntax@0.36.2(postcss@8.4.31): resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} peerDependencies: postcss: '>=5.0.0' @@ -18977,10 +18985,7 @@ packages: postcss-scss: optional: true dependencies: - postcss: 7.0.39 - postcss-html: 0.36.0(postcss-syntax@0.36.2)(postcss@7.0.39) - postcss-less: 3.1.4 - postcss-scss: 2.1.1 + postcss: 8.4.31 dev: true /postcss-value-parser@4.2.0: @@ -19012,7 +19017,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /potpack@1.0.2: resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} @@ -22117,7 +22121,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-resolve@0.5.3: resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} @@ -22827,7 +22830,7 @@ packages: postcss-sass: 0.4.4 postcss-scss: 2.1.1 postcss-selector-parser: 6.0.13 - postcss-syntax: 0.36.2(postcss-html@0.36.0)(postcss-less@3.1.4)(postcss-scss@2.1.1)(postcss@7.0.39) + postcss-syntax: 0.36.2(postcss@8.4.31) postcss-value-parser: 4.2.0 resolve-from: 5.0.0 slash: 3.0.0