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,