Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: icons 的替换方案优化,支持无法可用 icon 映射的情况 #2922

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@
"dev:jdtaro:jdharmonycpp": "pnpm run clone:jdharmony cpp &&pnpm run update:taro:entry && JD=1 pnpm --dir ./packages/nutui-taro-demo dev:jdharmonycpp",
"dev:jdtaro:jdharmony": "pnpm run clone:jdharmony && pnpm run update:taro:entry && JD=1 pnpm --dir ./packages/nutui-taro-demo dev:jdharmony",
"dev:taro:jmapp": "pnpm run update:taro:entry && JD=1 pnpm --dir ./packages/nutui-taro-demo dev:jmapp",
"build": "npm run checked && node scripts/build.mjs",
"build:taro": "npm run checked:taro && node scripts/build-taro.mjs",
"build": "node ./scripts/replace-css-var.js && npm run checked && node scripts/build.mjs",
"build:taro": "node ./scripts/replace-css-var.js && npm run checked:taro && node scripts/build-taro.mjs",
"build:taro:jmapp": "npm run checked:taro && VITE_APP_PROJECT_ID=jmapp node scripts/build-taro.mjs",
"build:site": "npm run checked && vite build --config vite.config.site.ts",
"build:site:jmapp": "npm run checked && VITE_APP_PROJECT_ID=jmapp vite build",
Expand Down
72 changes: 57 additions & 15 deletions packages/nutui-replace-icons/src/replace-icons.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,77 @@
import { IOptions } from './type'

function replace(options: IOptions) {
const sourceLibrary = options.sourceLibrary || []
interface ReplaceOptions extends Omit<IOptions, 'exclude'> {
exclude: { [key: string]: boolean }
}

const skip = new Set()

function replace(options: ReplaceOptions) {
const sourceLibraries = options.sourceLibrary || []
const targetLibrary = options.targetLibrary
return {
return ({ types: t }) => ({
visitor: {
ImportDeclaration(path) {
if (sourceLibrary.indexOf(path.node.source.value) > -1) {
// 替换包名称
path.node.source.value = targetLibrary
path.node.specifiers.forEach((specifier) => {
// 根据 iconMappings 进行替换
const iconMappings = options.iconMappings
if (iconMappings && iconMappings[specifier.imported.name]) {
specifier.imported.name = iconMappings[specifier.imported.name]
}
})
if (
sourceLibraries.indexOf(path.node.source.value) > -1 &&
!skip.has(path.node)
) {
try {
const updatedImports: Array<any> = []
path.node.specifiers.forEach((specifier) => {
const localIdentifier =
specifier.local.name || specifier.local.value
const importedIdentifier =
specifier.imported.name || specifier.imported.value
const iconMappings = options.iconMappings
// delete this and build new segmentent
const newLibraryName = options.exclude[importedIdentifier]
? path.node.source.value
: targetLibrary
const finalImportedName =
iconMappings && iconMappings[importedIdentifier]
? iconMappings[importedIdentifier]
: importedIdentifier
const newImport = t.ImportDeclaration(
[
t.ImportSpecifier(
t.identifier(localIdentifier),
t.identifier(finalImportedName)
),
],
t.StringLiteral(newLibraryName)
)
updatedImports.push(newImport)
skip.add(newImport)
})
const programPath = path.findParent((path) => path.isProgram())
updatedImports.forEach((imported) => {
programPath.unshiftContainer('body', imported)
})
path.remove()
} catch (e) {
console.log(e)
}
}
},
},
}
})
}

export function replaceIcons(
options: IOptions = {
sourceLibrary: ['@nutui/icons-react', '@nutui/icons-react-taro'],
targetLibrary: '',
exclude: [],
}
) {
if (!options.targetLibrary) {
return {}
}
return replace(options)
// options exclude covert to object
const excludeHashMap = {}
options.exclude?.forEach((exc) => {
excludeHashMap[exc] = true
})
return replace({ ...options, exclude: excludeHashMap })
}
1 change: 1 addition & 0 deletions packages/nutui-replace-icons/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export interface IOptions {
sourceLibrary: string[]
targetLibrary: string
iconMappings?: { [key: string]: string }
exclude?: Array<string>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`replace Loading icons with Star 1`] = `
"import { Loading1 } from "@nutui/icons-react";
import { Star as Loading } from "@test/aa";
import { ArrowSize6 as Arrow } from "@nutui/icons-react";
const ReplaceOne = () => {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Loading, null), " ", /*#__PURE__*/React.createElement(Arrow, null));
};"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`replace Loading icons with Star 1`] = `
"import { ArrowSize6 as Arrow } from "@nutui/icons-react";
import { Loading1 } from "@nutui/icons-react";
import { Star as Loading } from "@test/aa";
const ReplaceOne = () => {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Loading, null), " ", /*#__PURE__*/React.createElement(Arrow, null));
};"
`;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`replace Loading icons with Star 1`] = `
"import { Star as Loading } from "@test/aa";
import { ArrowSize6 as Arrow } from "@test/aa";
"import { ArrowSize6 as Arrow } from "@test/aa";
import { Star as Loading } from "@test/aa";
const ReplaceOne = () => {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Loading, null), " ", /*#__PURE__*/React.createElement(Arrow, null));
};"
Expand Down
30 changes: 30 additions & 0 deletions packages/nutui-replace-icons/test/exclude-case-inline.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import babel from '@babel/core'
import { describe, expect, it } from 'vitest'
import { replaceIcons } from '../src/replace-icons'

const plugin = replaceIcons({
targetLibrary: '@test/aa',
sourceLibrary: ['@nutui/icons-react'],
iconMappings: {
Loading: 'Star',
},
exclude: ['Loading1', 'ArrowSize6'],
})

const babelOptions = {
presets: ['@babel/preset-react'],
plugins: [plugin],
}
const caseIns = `
import { ArrowSize6 as Arrow, Loading, Loading1 } from '@nutui/icons-react'
const ReplaceOne = () => {
return <><Loading /> <Arrow /></>
}
`
describe('', () => {
it('replace Loading icons with Star', () => {
const ast = babel.transformSync(caseIns, babelOptions)
// @ts-ignore
expect(ast.code).toMatchSnapshot()
})
})
32 changes: 32 additions & 0 deletions packages/nutui-replace-icons/test/exclude-case.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import babel from '@babel/core'
import { describe, expect, it } from 'vitest'
import { replaceIcons } from '../src/replace-icons'

const plugin = replaceIcons({
targetLibrary: '@test/aa',
sourceLibrary: ['@nutui/icons-react'],
iconMappings: {
Loading: 'Star',
},
exclude: ['Loading1', 'ArrowSize6'],
})

const babelOptions = {
presets: ['@babel/preset-react'],
plugins: [plugin],
}
const caseIns = `
import { Loading } from '@nutui/icons-react'
import { Loading1 } from '@nutui/icons-react'
import { ArrowSize6 as Arrow } from '@nutui/icons-react'
const ReplaceOne = () => {
return <><Loading /> <Arrow /></>
}
`
describe('', () => {
it('replace Loading icons with Star', () => {
const ast = babel.transformSync(caseIns, babelOptions)
// @ts-ignore
expect(ast.code).toMatchSnapshot()
})
})
1 change: 1 addition & 0 deletions packages/nutui-replace-icons/test/replace-case.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { replaceIcons } from '../src/replace-icons'

const plugin = replaceIcons({
targetLibrary: '@test/aa',
sourceLibrary: ['@nutui/icons-react'],
iconMappings: {
Loading: 'Star',
},
Expand Down
7 changes: 7 additions & 0 deletions packages/nutui-replace-icons/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
// ... Specify options here.
},
})
Loading
Loading