From 5c0df4a3ef3a54576d1dc9d68e3492215943a686 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Fri, 30 Jan 2026 12:26:07 +0800 Subject: [PATCH] chore: Revert "refactor: prefer css icon" (#31733) --- web/eslint-rules/index.js | 4 +- .../rules/prefer-tailwind-icon.js | 384 ------------------ web/eslint.config.mjs | 44 +- web/package.json | 8 +- web/pnpm-lock.yaml | 269 ++---------- web/tailwind-common-config.ts | 139 +------ 6 files changed, 65 insertions(+), 783 deletions(-) delete mode 100644 web/eslint-rules/rules/prefer-tailwind-icon.js diff --git a/web/eslint-rules/index.js b/web/eslint-rules/index.js index 1559590328..8eda0caaa6 100644 --- a/web/eslint-rules/index.js +++ b/web/eslint-rules/index.js @@ -3,14 +3,13 @@ import noAsAnyInT from './rules/no-as-any-in-t.js' import noExtraKeys from './rules/no-extra-keys.js' import noLegacyNamespacePrefix from './rules/no-legacy-namespace-prefix.js' import noVersionPrefix from './rules/no-version-prefix.js' -import preferTailwindIcon from './rules/prefer-tailwind-icon.js' import requireNsOption from './rules/require-ns-option.js' import validI18nKeys from './rules/valid-i18n-keys.js' /** @type {import('eslint').ESLint.Plugin} */ const plugin = { meta: { - name: 'dify', + name: 'dify-i18n', version: '1.0.0', }, rules: { @@ -19,7 +18,6 @@ const plugin = { 'no-extra-keys': noExtraKeys, 'no-legacy-namespace-prefix': noLegacyNamespacePrefix, 'no-version-prefix': noVersionPrefix, - 'prefer-tailwind-icon': preferTailwindIcon, 'require-ns-option': requireNsOption, 'valid-i18n-keys': validI18nKeys, }, diff --git a/web/eslint-rules/rules/prefer-tailwind-icon.js b/web/eslint-rules/rules/prefer-tailwind-icon.js deleted file mode 100644 index ed5e111316..0000000000 --- a/web/eslint-rules/rules/prefer-tailwind-icon.js +++ /dev/null @@ -1,384 +0,0 @@ -/** - * Default prop-to-class mappings - * Maps component props to Tailwind class prefixes - */ -const DEFAULT_PROP_MAPPINGS = { - size: 'size', - width: 'w', - height: 'h', -} - -/** - * Convert PascalCase/camelCase to kebab-case - * @param {string} name - * @returns {string} The kebab-case string - */ -function camelToKebab(name) { - return name - .replace(/([a-z])(\d)/g, '$1-$2') - .replace(/(\d)([a-z])/gi, '$1-$2') - .replace(/([a-z])([A-Z])/g, '$1-$2') - .toLowerCase() -} - -/** - * Default icon library configurations - * - * Config options: - * - pattern: string | RegExp - Pattern to match import source - * - prefix: string | ((match: RegExpMatchArray) => string) - Icon class prefix - * - suffix: string | ((match: RegExpMatchArray) => string) - Icon class suffix - * - extractSubPath: boolean - Extract subdirectory path and add to prefix - * - iconFilter: (name: string) => boolean - Filter which imports to process - * - stripPrefix: string - Prefix to remove from icon name before transform - * - stripSuffix: string - Suffix to remove from icon name before transform - */ -const DEFAULT_ICON_CONFIGS = [ - { - // @/app/components/base/icons/src/public/* and vender/* - pattern: /^@\/app\/components\/base\/icons\/src\/(public|vender)/, - prefix: match => `i-custom-${match[1]}-`, - extractSubPath: true, - }, - { - // @remixicon/react - pattern: '@remixicon/react', - prefix: 'i-ri-', - iconFilter: name => name.startsWith('Ri'), - stripPrefix: 'Ri', - }, - { - // @heroicons/react/{size}/{variant} - pattern: /^@heroicons\/react\/(\d+)\/(solid|outline)$/, - prefix: 'i-heroicons-', - suffix: match => `-${match[1]}-${match[2]}`, - iconFilter: name => name.endsWith('Icon'), - stripSuffix: 'Icon', - }, -] - -/** - * Convert pixel value to Tailwind class - * @param {number} pixels - * @param {string} classPrefix - e.g., 'size', 'w', 'h' - * @returns {string} The Tailwind class string - */ -function pixelToClass(pixels, classPrefix) { - if (pixels % 4 === 0) { - const units = pixels / 4 - return `${classPrefix}-${units}` - } - // For non-standard sizes, use Tailwind arbitrary value syntax - return `${classPrefix}-[${pixels}px]` -} - -/** - * Match source against config pattern - * @param {string} source - The import source path - * @param {object} config - The icon config - * @returns {{ matched: boolean, match: RegExpMatchArray | null, basePath: string }} Match result - */ -function matchPattern(source, config) { - const { pattern } = config - if (pattern instanceof RegExp) { - const match = source.match(pattern) - if (match) { - return { matched: true, match, basePath: match[0] } - } - return { matched: false, match: null, basePath: '' } - } - // String pattern: exact match or prefix match - if (source === pattern || source.startsWith(`${pattern}/`)) { - return { matched: true, match: null, basePath: pattern } - } - return { matched: false, match: null, basePath: '' } -} - -/** - * Get icon class from config - * @param {string} iconName - * @param {object} config - * @param {string} source - The import source path - * @param {RegExpMatchArray | null} match - The regex match result - * @returns {string} The full Tailwind icon class string - */ -function getIconClass(iconName, config, source, match) { - // Strip prefix/suffix from icon name if configured - let name = iconName - if (config.stripPrefix && name.startsWith(config.stripPrefix)) { - name = name.slice(config.stripPrefix.length) - } - if (config.stripSuffix && name.endsWith(config.stripSuffix)) { - name = name.slice(0, -config.stripSuffix.length) - } - - // Transform name (use custom or default camelToKebab) - const transformed = config.transformName ? config.transformName(name, source) : camelToKebab(name) - - // Get prefix (can be string or function) - const prefix = typeof config.prefix === 'function' ? config.prefix(match) : config.prefix - - // Get suffix (can be string or function) - const suffix = typeof config.suffix === 'function' ? config.suffix(match) : (config.suffix || '') - - // Extract subdirectory path after the pattern to include in prefix (only if extractSubPath is enabled) - let subPrefix = '' - if (config.extractSubPath) { - const basePath = match ? match[0] : config.pattern - if (source.startsWith(`${basePath}/`)) { - const subPath = source.slice(basePath.length + 1) - if (subPath) { - subPrefix = `${subPath.replace(/\//g, '-')}-` - } - } - } - - return `${prefix}${subPrefix}${transformed}${suffix}` -} - -/** @type {import('eslint').Rule.RuleModule} */ -export default { - meta: { - type: 'suggestion', - docs: { - description: 'Prefer Tailwind CSS icon classes over icon library components', - }, - hasSuggestions: true, - schema: [ - { - type: 'object', - properties: { - libraries: { - type: 'array', - items: { - type: 'object', - properties: { - pattern: { type: 'string' }, - prefix: { type: 'string' }, - suffix: { type: 'string' }, - extractSubPath: { type: 'boolean' }, - }, - required: ['pattern', 'prefix'], - }, - }, - propMappings: { - type: 'object', - additionalProperties: { type: 'string' }, - description: 'Maps component props to Tailwind class prefixes, e.g., { size: "size", width: "w", height: "h" }', - }, - }, - additionalProperties: false, - }, - ], - messages: { - preferTailwindIcon: - 'Prefer using Tailwind CSS icon class "{{iconClass}}" over "{{componentName}}" from "{{source}}"', - preferTailwindIconImport: - 'Icon "{{importedName}}" from "{{source}}" can be replaced with Tailwind CSS class "{{iconClass}}"', - }, - }, - create(context) { - const options = context.options[0] || {} - const iconConfigs = options.libraries || DEFAULT_ICON_CONFIGS - const propMappings = options.propMappings || DEFAULT_PROP_MAPPINGS - - // Track imports: localName -> { node, importedName, config, source, match, used } - const iconImports = new Map() - - return { - ImportDeclaration(node) { - const source = node.source.value - - // Find matching config - let matchedConfig = null - let matchResult = null - for (const config of iconConfigs) { - const result = matchPattern(source, config) - if (result.matched) { - matchedConfig = config - matchResult = result.match - break - } - } - if (!matchedConfig) - return - - // Use default filter if not provided (for user-configured libraries) - const iconFilter = matchedConfig.iconFilter || (() => true) - - for (const specifier of node.specifiers) { - if (specifier.type === 'ImportSpecifier') { - const importedName = specifier.imported.name - const localName = specifier.local.name - - if (iconFilter(importedName)) { - iconImports.set(localName, { - node: specifier, - importedName, - localName, - config: matchedConfig, - source, - match: matchResult, - used: false, - }) - } - } - } - }, - - JSXOpeningElement(node) { - if (node.name.type !== 'JSXIdentifier') - return - - const componentName = node.name.name - const iconInfo = iconImports.get(componentName) - - if (!iconInfo) - return - - iconInfo.used = true - - const iconClass = getIconClass(iconInfo.importedName, iconInfo.config, iconInfo.source, iconInfo.match) - - // Find className attribute - const classNameAttr = node.attributes.find( - attr => attr.type === 'JSXAttribute' && attr.name.name === 'className', - ) - - // Process prop mappings (size, width, height, etc.) - const mappedClasses = [] - const mappedPropNames = Object.keys(propMappings) - - for (const propName of mappedPropNames) { - const attr = node.attributes.find( - a => a.type === 'JSXAttribute' && a.name.name === propName, - ) - - if (attr && attr.value) { - let pixelValue = null - - if (attr.value.type === 'JSXExpressionContainer' - && attr.value.expression.type === 'Literal' - && typeof attr.value.expression.value === 'number') { - pixelValue = attr.value.expression.value - } - else if (attr.value.type === 'Literal' - && typeof attr.value.value === 'number') { - pixelValue = attr.value.value - } - - if (pixelValue !== null) { - mappedClasses.push(pixelToClass(pixelValue, propMappings[propName])) - } - } - } - - // Build new className - const sourceCode = context.sourceCode - let newClassName - const classesToAdd = [iconClass, ...mappedClasses].filter(Boolean).join(' ') - - if (classNameAttr && classNameAttr.value) { - if (classNameAttr.value.type === 'Literal') { - newClassName = `${classesToAdd} ${classNameAttr.value.value}` - } - else if (classNameAttr.value.type === 'JSXExpressionContainer') { - const expression = sourceCode.getText(classNameAttr.value.expression) - newClassName = `\`${classesToAdd} \${${expression}}\`` - } - } - else { - newClassName = classesToAdd - } - - const parent = node.parent - const isSelfClosing = node.selfClosing - const excludedAttrs = ['className', ...mappedPropNames] - - context.report({ - node, - messageId: 'preferTailwindIcon', - data: { - iconClass, - componentName, - source: iconInfo.source, - }, - suggest: [ - { - messageId: 'preferTailwindIcon', - data: { - iconClass, - componentName, - source: iconInfo.source, - }, - fix(fixer) { - const fixes = [] - - const classValue = newClassName.startsWith('`') - ? `{${newClassName}}` - : `"${newClassName}"` - - const otherAttrs = node.attributes - .filter(attr => !(attr.type === 'JSXAttribute' && excludedAttrs.includes(attr.name.name))) - .map(attr => sourceCode.getText(attr)) - .join(' ') - - const attrsStr = otherAttrs - ? `className=${classValue} ${otherAttrs}` - : `className=${classValue}` - - if (isSelfClosing) { - fixes.push(fixer.replaceText(parent, ``)) - } - else { - const closingElement = parent.closingElement - fixes.push(fixer.replaceText(node, ``)) - if (closingElement) { - fixes.push(fixer.replaceText(closingElement, '')) - } - } - - return fixes - }, - }, - ], - }) - }, - - 'Program:exit': function () { - const sourceCode = context.sourceCode - - // Report icons that were imported but not found in JSX - for (const [, iconInfo] of iconImports) { - if (!iconInfo.used) { - // Verify the import is still referenced somewhere in the file (besides the import itself) - try { - const variables = sourceCode.getDeclaredVariables(iconInfo.node) - const variable = variables[0] - // Check if there are any references besides the import declaration - const hasReferences = variable && variable.references.some( - ref => ref.identifier !== iconInfo.node.local, - ) - if (!hasReferences) - continue - } - catch { - continue - } - - const iconClass = getIconClass(iconInfo.importedName, iconInfo.config, iconInfo.source, iconInfo.match) - context.report({ - node: iconInfo.node, - messageId: 'preferTailwindIconImport', - data: { - importedName: iconInfo.importedName, - source: iconInfo.source, - iconClass, - }, - }) - } - } - }, - } - }, -} diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs index 9d582828fd..9ef3f8d04f 100644 --- a/web/eslint.config.mjs +++ b/web/eslint.config.mjs @@ -4,7 +4,7 @@ import pluginQuery from '@tanstack/eslint-plugin-query' import sonar from 'eslint-plugin-sonarjs' import storybook from 'eslint-plugin-storybook' import tailwind from 'eslint-plugin-tailwindcss' -import dify from './eslint-rules/index.js' +import difyI18n from './eslint-rules/index.js' export default antfu( { @@ -104,34 +104,44 @@ export default antfu( 'tailwindcss/migration-from-tailwind-2': 'warn', }, }, - // Dify custom rules - { - plugins: { - dify, - }, - }, - { - files: ['**/*.tsx'], - rules: { - 'dify/prefer-tailwind-icon': 'warn', - }, - }, + // dify i18n namespace migration + // { + // files: ['**/*.ts', '**/*.tsx'], + // ignores: ['eslint-rules/**', 'i18n/**', 'i18n-config/**'], + // plugins: { + // 'dify-i18n': difyI18n, + // }, + // rules: { + // // 'dify-i18n/no-as-any-in-t': ['error', { mode: 'all' }], + // 'dify-i18n/no-as-any-in-t': 'error', + // // 'dify-i18n/no-legacy-namespace-prefix': 'error', + // // 'dify-i18n/require-ns-option': 'error', + // }, + // }, + // i18n JSON validation rules { files: ['i18n/**/*.json'], + plugins: { + 'dify-i18n': difyI18n, + }, rules: { 'sonarjs/max-lines': 'off', 'max-lines': 'off', 'jsonc/sort-keys': 'error', - 'dify/valid-i18n-keys': 'error', - 'dify/no-extra-keys': 'error', - 'dify/consistent-placeholders': 'error', + 'dify-i18n/valid-i18n-keys': 'error', + 'dify-i18n/no-extra-keys': 'error', + 'dify-i18n/consistent-placeholders': 'error', }, }, + // package.json version prefix validation { files: ['**/package.json'], + plugins: { + 'dify-i18n': difyI18n, + }, rules: { - 'dify/no-version-prefix': 'error', + 'dify-i18n/no-version-prefix': 'error', }, }, ) diff --git a/web/package.json b/web/package.json index f66e4ceb5b..0096c6b58a 100644 --- a/web/package.json +++ b/web/package.json @@ -162,13 +162,7 @@ "devDependencies": { "@antfu/eslint-config": "7.0.1", "@chromatic-com/storybook": "5.0.0", - "@egoist/tailwindcss-icons": "1.9.0", "@eslint-react/eslint-plugin": "2.7.0", - "@iconify-json/heroicons": "1.2.3", - "@iconify-json/ri": "1.2.7", - "@iconify/tools": "5.0.2", - "@iconify/types": "2.0.0", - "@iconify/utils": "3.1.0", "@mdx-js/loader": "3.1.1", "@mdx-js/react": "3.1.1", "@next/bundle-analyzer": "16.1.5", @@ -211,7 +205,7 @@ "@vitejs/plugin-react": "5.1.2", "@vitest/coverage-v8": "4.0.17", "autoprefixer": "10.4.21", - "code-inspector-plugin": "1.4.1", + "code-inspector-plugin": "1.3.6", "cross-env": "10.1.0", "esbuild-wasm": "0.27.2", "eslint": "9.39.2", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index da5ec2b627..e79dee6936 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -372,27 +372,9 @@ importers: '@chromatic-com/storybook': specifier: 5.0.0 version: 5.0.0(storybook@10.2.0(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) - '@egoist/tailwindcss-icons': - specifier: 1.9.0 - version: 1.9.0(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2)) '@eslint-react/eslint-plugin': specifier: 2.7.0 version: 2.7.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@iconify-json/heroicons': - specifier: 1.2.3 - version: 1.2.3 - '@iconify-json/ri': - specifier: 1.2.7 - version: 1.2.7 - '@iconify/tools': - specifier: 5.0.2 - version: 5.0.2 - '@iconify/types': - specifier: 2.0.0 - version: 2.0.0 - '@iconify/utils': - specifier: 3.1.0 - version: 3.1.0 '@mdx-js/loader': specifier: 3.1.1 version: 3.1.1(webpack@5.104.1(esbuild@0.27.2)(uglify-js@3.19.3)) @@ -520,8 +502,8 @@ importers: specifier: 10.4.21 version: 10.4.21(postcss@8.5.6) code-inspector-plugin: - specifier: 1.4.1 - version: 1.4.1 + specifier: 1.3.6 + version: 1.3.6 cross-env: specifier: 10.1.0 version: 10.1.0 @@ -748,9 +730,6 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@antfu/utils@8.1.1': - resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==} - '@asamuzakjp/css-color@4.1.1': resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} @@ -887,23 +866,23 @@ packages: '@clack/prompts@0.8.2': resolution: {integrity: sha512-6b9Ab2UiZwJYA9iMyboYyW9yJvAO9V753ZhS+DHKEjZRKAxPPOb7MXXu84lsPFG+vZt6FRFniZ8rXi+zCIw4yQ==} - '@code-inspector/core@1.4.1': - resolution: {integrity: sha512-k5iLYvrBBPBPODcwuzgEcAZnXU4XTnEO1jOmNQBHCehN6nrMO1m5Efjz35KPkSX+8T4IWvXvLoXR5XPfhDlxug==} + '@code-inspector/core@1.3.6': + resolution: {integrity: sha512-bSxf/PWDPY6rv9EFf0mJvTnLnz3927PPrpX6BmQcRKQab+Ez95yRqrVZY8IcBUpaqA/k3etA5rZ1qkN0V4ERtw==} - '@code-inspector/esbuild@1.4.1': - resolution: {integrity: sha512-0tf73j0wgsu1Rl5CNe5o5L/GB/lGvQQVjuLTbAB/but+Bw//nHRnlrA29lBzNM6cyBDZzwofa71Q+TH8Fu4aZQ==} + '@code-inspector/esbuild@1.3.6': + resolution: {integrity: sha512-s35dseBXI2yqfX6ZK29Ix941jaE/4KPlZZeMk6B5vDahj75FDUfVxQ7ORy4cX2hyz8CmlOycsY/au5mIvFpAFg==} - '@code-inspector/mako@1.4.1': - resolution: {integrity: sha512-inpiJbc8J+qaEYcMgzyAFusuyryZ9i0wUQhLJRbWl1WrUdWTE8xNHDjhPeTVaMav42NTGDnVKJhhKD6tNaxyFA==} + '@code-inspector/mako@1.3.6': + resolution: {integrity: sha512-FJvuTElOi3TUCWTIaYTFYk2iTUD6MlO51SC8SYfwmelhuvnOvTMa2TkylInX16OGb4f7sGNLRj2r+7NNx/gqpw==} - '@code-inspector/turbopack@1.4.1': - resolution: {integrity: sha512-xVefk907E39U/oywR9YiEqJn1VlNBHIcIsYkjNnFp0U3qBb3A40VqivlCqkWaP9xHAwEH8/UT3Sfh3aoUPC9/Q==} + '@code-inspector/turbopack@1.3.6': + resolution: {integrity: sha512-pfXgvZCn4/brpTvqy8E0HTe6V/ksVKEPQo697Nt5k22kBnlEM61UT3rI2Art+fDDEMPQTxVOFpdbwCKSLwMnmQ==} - '@code-inspector/vite@1.4.1': - resolution: {integrity: sha512-ptbGkmtw5mvuFse6Kjmd6bCgm+isHrBq+HumWlAMBH//Qb2frHkEV7kWjO6/AkBXfm/ccNJy+jNwWq0632ChDg==} + '@code-inspector/vite@1.3.6': + resolution: {integrity: sha512-vXYvzGc0S1NR4p3BeD1Xx2170OnyecZD0GtebLlTiHw/cetzlrBHVpbkIwIEzzzpTYYshwwDt8ZbuvdjmqhHgw==} - '@code-inspector/webpack@1.4.1': - resolution: {integrity: sha512-UkqC5MsWRVJT2y10GM7tIZdQmFuGAlArJSfq2hq727eXMDV3otY5d1UCQopYvUIEC90QQNHJDeK4e+UQipF6AQ==} + '@code-inspector/webpack@1.3.6': + resolution: {integrity: sha512-bi/+vsym9d6NXQQ++Phk74VLMiVoGKjgPHr445j/D43URG8AN8yYa+gRDBEDcZx4B128dihrVMxEO8+OgWGjTw==} '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} @@ -936,18 +915,10 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} - '@cyberalien/svg-utils@1.0.11': - resolution: {integrity: sha512-qEE9mnyI+avfGT3emKuRs3ucYkITeaV0Xi7VlYN41f+uGnZBecQP3jwz/AF437H9J4Q7qPClHKm4NiTYpNE6hA==} - '@discoveryjs/json-ext@0.5.7': resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@egoist/tailwindcss-icons@1.9.0': - resolution: {integrity: sha512-xWA9cUy6hzlK7Y6TaoRIcwmilSXiTJ8rbXcEdf9uht7yzDgw/yIgF4rThIQMrpD2Y2v4od51+r2y6Z7GStanDQ==} - peerDependencies: - tailwindcss: '*' - '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1321,21 +1292,9 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@iconify-json/heroicons@1.2.3': - resolution: {integrity: sha512-n+vmCEgTesRsOpp5AB5ILB6srsgsYK+bieoQBNlafvoEhjVXLq8nIGN4B0v/s4DUfa0dOrjwE/cKJgIKdJXOEg==} - - '@iconify-json/ri@1.2.7': - resolution: {integrity: sha512-j/Fkb8GlWY5y/zLj1BGxWRtDzuJFrI7562zLw+iQVEykieBgew43+r8qAvtSajvb75MfUIHjsNOYQPRD8FfLfw==} - - '@iconify/tools@5.0.2': - resolution: {integrity: sha512-esoFiH0LYpiqqVAO+RTenh6qqGKf0V8T0T6IG7dFLCw26cjcYGG34UMHjkbuq+MMl23U39FtkzhWZsCDDtOhew==} - '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@2.3.0': - resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} - '@iconify/utils@3.1.0': resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} @@ -3920,8 +3879,8 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc - code-inspector-plugin@1.4.1: - resolution: {integrity: sha512-DuOEoOWtkz3Mq6JTogJjSfXkVnXuGy6Gjfi+eBYtgRFlZmQ5sw1/LacsPnTK89O4Oz6gZj+zjxpwNfpWg3htpA==} + code-inspector-plugin@1.3.6: + resolution: {integrity: sha512-ddTg8embDqLZxKEdSNOm+/0YnVVgWKr10+Bu2qFqQDObj/3twGh0Z23TIz+5/URxfRhTPbp2sUSpWlw78piJbQ==} collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -3949,10 +3908,6 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - commander@13.1.0: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} @@ -4024,21 +3979,10 @@ packages: css-mediaquery@0.1.2: resolution: {integrity: sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==} - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - - css-tree@2.2.1: - resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - css-tree@3.1.0: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} - css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} @@ -4047,10 +3991,6 @@ packages: engines: {node: '>=4'} hasBin: true - csso@5.0.5: - resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - cssstyle@5.3.7: resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} engines: {node: '>=20'} @@ -4309,25 +4249,12 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dompurify@3.2.7: resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} dompurify@3.3.0: resolution: {integrity: sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==} - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -4385,10 +4312,6 @@ packages: resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} engines: {node: '>=10.13.0'} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} @@ -4822,9 +4745,6 @@ packages: fflate@0.4.8: resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -5626,9 +5546,6 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdn-data@2.0.28: - resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} @@ -5816,10 +5733,6 @@ packages: mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} - modern-tar@0.7.3: - resolution: {integrity: sha512-4W79zekKGyYU4JXVmB78DOscMFaJth2gGhgfTl2alWE4rNe3nf4N2pqenQ0rEtIewrnD79M687Ouba3YGTLOvg==} - engines: {node: '>=18.0.0'} - module-alias@2.2.3: resolution: {integrity: sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==} @@ -6620,10 +6533,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - sax@1.4.4: - resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} - engines: {node: '>=11.0.0'} - saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -6893,11 +6802,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svgo@4.0.0: - resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==} - engines: {node: '>=16'} - hasBin: true - symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -7808,8 +7712,6 @@ snapshots: package-manager-detector: 1.6.0 tinyexec: 1.0.2 - '@antfu/utils@8.1.1': {} - '@asamuzakjp/css-color@4.1.1': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) @@ -7997,7 +7899,7 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 - '@code-inspector/core@1.4.1': + '@code-inspector/core@1.3.6': dependencies: '@vue/compiler-dom': 3.5.27 chalk: 4.1.2 @@ -8007,35 +7909,35 @@ snapshots: transitivePeerDependencies: - supports-color - '@code-inspector/esbuild@1.4.1': + '@code-inspector/esbuild@1.3.6': dependencies: - '@code-inspector/core': 1.4.1 + '@code-inspector/core': 1.3.6 transitivePeerDependencies: - supports-color - '@code-inspector/mako@1.4.1': + '@code-inspector/mako@1.3.6': dependencies: - '@code-inspector/core': 1.4.1 + '@code-inspector/core': 1.3.6 transitivePeerDependencies: - supports-color - '@code-inspector/turbopack@1.4.1': + '@code-inspector/turbopack@1.3.6': dependencies: - '@code-inspector/core': 1.4.1 - '@code-inspector/webpack': 1.4.1 + '@code-inspector/core': 1.3.6 + '@code-inspector/webpack': 1.3.6 transitivePeerDependencies: - supports-color - '@code-inspector/vite@1.4.1': + '@code-inspector/vite@1.3.6': dependencies: - '@code-inspector/core': 1.4.1 + '@code-inspector/core': 1.3.6 chalk: 4.1.1 transitivePeerDependencies: - supports-color - '@code-inspector/webpack@1.4.1': + '@code-inspector/webpack@1.3.6': dependencies: - '@code-inspector/core': 1.4.1 + '@code-inspector/core': 1.3.6 transitivePeerDependencies: - supports-color @@ -8061,19 +7963,8 @@ snapshots: '@csstools/css-tokenizer@3.0.4': {} - '@cyberalien/svg-utils@1.0.11': - dependencies: - '@iconify/types': 2.0.0 - '@discoveryjs/json-ext@0.5.7': {} - '@egoist/tailwindcss-icons@1.9.0(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2))': - dependencies: - '@iconify/utils': 2.3.0 - tailwindcss: 3.4.18(tsx@4.21.0)(yaml@2.8.2) - transitivePeerDependencies: - - supports-color - '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -8437,39 +8328,8 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@iconify-json/heroicons@1.2.3': - dependencies: - '@iconify/types': 2.0.0 - - '@iconify-json/ri@1.2.7': - dependencies: - '@iconify/types': 2.0.0 - - '@iconify/tools@5.0.2': - dependencies: - '@cyberalien/svg-utils': 1.0.11 - '@iconify/types': 2.0.0 - '@iconify/utils': 3.1.0 - fflate: 0.8.2 - modern-tar: 0.7.3 - pathe: 2.0.3 - svgo: 4.0.0 - '@iconify/types@2.0.0': {} - '@iconify/utils@2.3.0': - dependencies: - '@antfu/install-pkg': 1.1.0 - '@antfu/utils': 8.1.1 - '@iconify/types': 2.0.0 - debug: 4.4.3 - globals: 15.15.0 - kolorist: 1.8.0 - local-pkg: 1.1.2 - mlly: 1.8.0 - transitivePeerDependencies: - - supports-color - '@iconify/utils@3.1.0': dependencies: '@antfu/install-pkg': 1.1.0 @@ -11283,14 +11143,14 @@ snapshots: - '@types/react' - '@types/react-dom' - code-inspector-plugin@1.4.1: + code-inspector-plugin@1.3.6: dependencies: - '@code-inspector/core': 1.4.1 - '@code-inspector/esbuild': 1.4.1 - '@code-inspector/mako': 1.4.1 - '@code-inspector/turbopack': 1.4.1 - '@code-inspector/vite': 1.4.1 - '@code-inspector/webpack': 1.4.1 + '@code-inspector/core': 1.3.6 + '@code-inspector/esbuild': 1.3.6 + '@code-inspector/mako': 1.3.6 + '@code-inspector/turbopack': 1.3.6 + '@code-inspector/vite': 1.3.6 + '@code-inspector/webpack': 1.3.6 chalk: 4.1.1 transitivePeerDependencies: - supports-color @@ -11319,8 +11179,6 @@ snapshots: comma-separated-tokens@2.0.3: {} - commander@11.1.0: {} - commander@13.1.0: {} commander@2.20.3: @@ -11379,34 +11237,15 @@ snapshots: css-mediaquery@0.1.2: {} - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-tree@2.2.1: - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.2.1 - css-tree@3.1.0: dependencies: mdn-data: 2.12.2 source-map-js: 1.2.1 - css-what@6.2.2: {} - css.escape@1.5.1: {} cssesc@3.0.0: {} - csso@5.0.5: - dependencies: - css-tree: 2.2.1 - cssstyle@5.3.7: dependencies: '@asamuzakjp/css-color': 4.1.1 @@ -11672,18 +11511,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - dompurify@3.2.7: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -11692,12 +11519,6 @@ snapshots: optionalDependencies: '@types/trusted-types': 2.0.7 - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dotenv@16.6.1: {} duplexer@0.1.2: {} @@ -11750,8 +11571,6 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 - entities@4.5.0: {} - entities@6.0.1: {} entities@7.0.1: {} @@ -12401,8 +12220,6 @@ snapshots: fflate@0.4.8: {} - fflate@0.8.2: {} - file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -13354,8 +13171,6 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdn-data@2.0.28: {} - mdn-data@2.12.2: {} memoize-one@5.2.1: {} @@ -13720,8 +13535,6 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.3 - modern-tar@0.7.3: {} - module-alias@2.2.3: {} monaco-editor@0.55.1: @@ -14651,8 +14464,6 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.5.6 - sax@1.4.4: {} - saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -14961,16 +14772,6 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svgo@4.0.0: - dependencies: - commander: 11.1.0 - css-select: 5.2.2 - css-tree: 3.1.0 - css-what: 6.2.2 - csso: 5.0.5 - picocolors: 1.1.1 - sax: 1.4.4 - symbol-tree@3.2.4: {} synckit@0.11.12: diff --git a/web/tailwind-common-config.ts b/web/tailwind-common-config.ts index 59ae5e730f..2fd568edd1 100644 --- a/web/tailwind-common-config.ts +++ b/web/tailwind-common-config.ts @@ -1,131 +1,8 @@ -import type { IconifyJSON } from '@iconify/types' -import fs from 'node:fs' -import path from 'node:path' -import { fileURLToPath } from 'node:url' -import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons' -import { cleanupSVG, deOptimisePaths, importDirectorySync, isEmptyColor, parseColors, runSVGO } from '@iconify/tools' -import { compareColors, stringToColor } from '@iconify/utils/lib/colors' import tailwindTypography from '@tailwindcss/typography' // @ts-expect-error workaround for turbopack issue import tailwindThemeVarDefine from './themes/tailwind-theme-var-define.ts' import typography from './typography.js' -const _dirname = typeof __dirname !== 'undefined' - ? __dirname - : path.dirname(fileURLToPath(import.meta.url)) - -// https://iconify.design/docs/articles/cleaning-up-icons/ -function getIconSetFromDir(dir: string, prefix: string) { - // Import icons - const iconSet = importDirectorySync(dir, { - prefix, - ignoreImportErrors: 'warn', - }) - - // Validate, clean up, fix palette and optimise - iconSet.forEachSync((name, type) => { - if (type !== 'icon') - return - - const svg = iconSet.toSVG(name) - if (!svg) { - // Invalid icon - iconSet.remove(name) - return - } - - // Clean up and optimise icons - try { - // Clean up icon code - cleanupSVG(svg) - - // Change color to `currentColor` - // Skip this step if icon has hardcoded palette - const blackColor = stringToColor('black')! - const whiteColor = stringToColor('white')! - parseColors(svg, { - defaultColor: 'currentColor', - callback: (attr, colorStr, color) => { - if (!color) { - // Color cannot be parsed! - throw new Error(`Invalid color: "${colorStr}" in attribute ${attr}`) - } - - if (isEmptyColor(color)) { - // Color is empty: 'none' or 'transparent'. Return as is - return color - } - - // Change black to 'currentColor' - if (compareColors(color, blackColor)) - return 'currentColor' - - // Remove shapes with white color - if (compareColors(color, whiteColor)) - return 'remove' - - // Icon is not monotone - return color - }, - }) - - // Optimise - runSVGO(svg) - - // Update paths for compatibility with old software - deOptimisePaths(svg) - } - catch (err) { - // Invalid icon - console.error(`Error parsing ${name}:`, err) - iconSet.remove(name) - return - } - - // Update icon - iconSet.fromSVG(name, svg) - }) - - // Export - return iconSet.export() -} - -function getCollectionsFromSubDirs(baseDir: string, prefixBase: string): Record { - const collections: Record = {} - - function processDir(dir: string, prefix: string): void { - const entries = fs.readdirSync(dir, { withFileTypes: true }) - const subDirs = entries.filter(e => e.isDirectory()) - const svgFiles = entries.filter(e => e.isFile() && e.name.endsWith('.svg')) - - // Process SVG files in current directory if any - if (svgFiles.length > 0) { - collections[prefix] = getIconSetFromDir(dir, prefix) - } - - // Recurse into subdirectories if any - if (subDirs.length > 0) { - for (const subDir of subDirs) { - const subDirPath = path.join(dir, subDir.name) - const subPrefix = `${prefix}-${subDir.name}` - processDir(subDirPath, subPrefix) - } - } - } - - // Read top-level subdirectories and process each - const entries = fs.readdirSync(baseDir, { withFileTypes: true }) - for (const entry of entries) { - if (entry.isDirectory()) { - const subDirPath = path.join(baseDir, entry.name) - const prefix = `${prefixBase}-${entry.name}` - processDir(subDirPath, prefix) - } - } - - return collections -} - const config = { theme: { typography, @@ -271,21 +148,7 @@ const config = { }, }, }, - plugins: [ - tailwindTypography, - iconsPlugin({ - collections: { - ...getCollectionsFromSubDirs(path.resolve(_dirname, 'app/components/base/icons/assets/public'), 'custom-public'), - ...getCollectionsFromSubDirs(path.resolve(_dirname, 'app/components/base/icons/assets/vender'), 'custom-vender'), - ...getIconCollections(['heroicons', 'ri']), - }, - extraProperties: { - width: '1rem', - height: '1rem', - display: 'block', - }, - }), - ], + plugins: [tailwindTypography], // https://github.com/tailwindlabs/tailwindcss/discussions/5969 corePlugins: { preflight: false,