mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-08-29 08:48:22 +02:00
chore(dev): upgrade ESLint to latest compatible stack (v10) (#4378)
* chore: upgrade eslint to v9 latest with compatible lint deps Agent-Logs-Url: https://github.com/lucide-icons/lucide/sessions/f7c1f1b5-d213-4afa-91a8-b799a16397ec * Fix eslint config * Fix a lot of eslint errors * Fix eslint * Fix eslint errors * Fix eslint errors * Fix types * Fix eslint warning * Format code * Add eslint 10 * Remove unused vars * Update pnpm * Update deps --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
dist
|
||||
build
|
||||
coverage
|
||||
lib
|
||||
tests
|
||||
node_modules
|
||||
.eslintrc.js
|
||||
docs/images
|
||||
docs/**/examples/
|
||||
packages/lucide-react/dynamicIconImports.js
|
||||
packages/angular/.angular
|
||||
75
.eslintrc.js
75
.eslintrc.js
@@ -1,75 +0,0 @@
|
||||
const DEFAULT_ATTRS = require('./tools/build-icons/render/default-attrs.json');
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
},
|
||||
extends: ['airbnb-base', 'prettier'],
|
||||
plugins: ['import', '@html-eslint'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: ['**/*.test.js', '**/*.spec.js', '**/scripts/**'],
|
||||
},
|
||||
],
|
||||
'import/extensions': [
|
||||
'error',
|
||||
{
|
||||
pattern: {
|
||||
mjs: 'always',
|
||||
json: 'always',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./docs/tsconfig.json', './packages/*/tsconfig.json'],
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['./icons/*.svg'],
|
||||
parser: '@html-eslint/parser',
|
||||
rules: {
|
||||
'@html-eslint/require-doctype': 'off',
|
||||
'@html-eslint/no-duplicate-attrs': 'error',
|
||||
'@html-eslint/no-inline-styles': 'error',
|
||||
'@html-eslint/require-attrs': [
|
||||
'error',
|
||||
...Object.entries(DEFAULT_ATTRS).map(([attr, value]) => ({
|
||||
tag: 'svg',
|
||||
attr,
|
||||
value: String(value),
|
||||
})),
|
||||
],
|
||||
'@html-eslint/indent': ['error', 2],
|
||||
'@html-eslint/no-multiple-empty-lines': ['error', { max: 0 }],
|
||||
'@html-eslint/no-extra-spacing-attrs': [
|
||||
'error',
|
||||
{
|
||||
enforceBeforeSelfClose: true,
|
||||
},
|
||||
],
|
||||
'@html-eslint/require-closing-tags': [
|
||||
'error',
|
||||
{
|
||||
selfClosing: 'always',
|
||||
allowSelfClosingCustom: true,
|
||||
},
|
||||
],
|
||||
'@html-eslint/element-newline': 'error',
|
||||
'@html-eslint/no-trailing-spaces': 'error',
|
||||
'@html-eslint/quotes': 'error',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -78,8 +78,10 @@ updates:
|
||||
- 'vite-plugin-*'
|
||||
linting-deps:
|
||||
patterns:
|
||||
- '@eslint/*'
|
||||
- '@html-eslint/*'
|
||||
- '@typescript-eslint/*'
|
||||
- 'angular-eslint'
|
||||
- 'cspell'
|
||||
- 'eslint'
|
||||
- 'eslint-*'
|
||||
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"cSpell.words": ["devs", "preact", "Preact"],
|
||||
"cSpell.words": ["devs", "linecap", "linejoin", "preact", "Preact"],
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": ["javascript", "svg"],
|
||||
"svg.preview.background": "editor"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
interface BackdropProps {
|
||||
src: string;
|
||||
|
||||
@@ -3,7 +3,6 @@ import pathToPoints from './path-to-points';
|
||||
import { Path, PathProps } from './types';
|
||||
|
||||
export const GapViolationHighlight = ({
|
||||
radius,
|
||||
stroke,
|
||||
strokeWidth,
|
||||
strokeOpacity,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import { PathProps, Path } from './types';
|
||||
import getPaths, { assert } from './utils';
|
||||
import { GapViolationHighlight } from './GapViolationHighlight.tsx';
|
||||
@@ -293,7 +293,7 @@ const Radii = ({
|
||||
...props
|
||||
}: { paths: Path[] } & PathProps<
|
||||
'strokeWidth' | 'stroke' | 'strokeDasharray' | 'strokeOpacity',
|
||||
any
|
||||
never
|
||||
>) => {
|
||||
return (
|
||||
<g
|
||||
@@ -361,12 +361,12 @@ const Radii = ({
|
||||
const Handles = ({
|
||||
paths,
|
||||
...props
|
||||
}: { paths: Path[] } & PathProps<'strokeWidth' | 'stroke' | 'strokeOpacity', any>) => (
|
||||
}: { paths: Path[] } & PathProps<'strokeWidth' | 'stroke' | 'strokeOpacity', never>) => (
|
||||
<g
|
||||
className="svg-preview-handles-group"
|
||||
{...props}
|
||||
>
|
||||
{paths.map(({ c, prev, next, cp1, cp2 }, i) => (
|
||||
{paths.map(({ prev, next, cp1, cp2 }, i) => (
|
||||
<React.Fragment key={i}>
|
||||
{cp1 && <path d={`M${prev.x} ${prev.y} ${cp1.x} ${cp1.y}`} />}
|
||||
{cp1 && (
|
||||
|
||||
@@ -12,7 +12,9 @@ function pathToPoints({ d, prev, next }: Path, interval = 1) {
|
||||
points.push(commander.getPointAtLength(i));
|
||||
}
|
||||
points.push(next);
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
console.warn(`Failed to convert path to points for d="${d}": ${err}`);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export const getCommands = (src: string) =>
|
||||
.flatMap(({ d, name }, idx) =>
|
||||
new SVGPathData(d)
|
||||
.toAbs()
|
||||
// @ts-ignore
|
||||
// @ts-expect-error `commands` is typed as a union of command types svgson does not narrow
|
||||
.commands.map((c, cIdx) => ({ ...c, id: idx, idx: cIdx, name })),
|
||||
);
|
||||
|
||||
@@ -242,7 +242,7 @@ const getPaths = (src: string) => {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error every command type is handled above, so `c` is not `never` here
|
||||
assertNever(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,9 @@ export const hash = (string: string, seed = 5381) => {
|
||||
let i = string.length;
|
||||
|
||||
while (i) {
|
||||
// eslint-disable-next-line no-bitwise, no-plusplus
|
||||
seed = (seed * 33) ^ string.charCodeAt(--i);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return (seed >>> 0).toString(36).substr(0, 6);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type MarkdownIt from 'markdown-it';
|
||||
import type { RenderRule } from 'markdown-it/lib/renderer.mjs';
|
||||
import type Token from 'markdown-it/lib/token.mjs';
|
||||
import container from 'markdown-it-container';
|
||||
import sandpackTheme from '../theme/sandpackTheme.json';
|
||||
|
||||
@@ -21,14 +22,10 @@ export default function sandpackPlugin(md: MarkdownIt, pluginOptions: SnackParam
|
||||
throw new Error('MarkdownIt instance is required for sandpackPlugin');
|
||||
}
|
||||
const escapeHtml = md?.utils?.escapeHtml;
|
||||
const defaultFence =
|
||||
md.renderer.rules.fence ||
|
||||
((tokens, idx, options, env, self) => self.renderToken(tokens, idx, options));
|
||||
|
||||
const renderSandbox = (tokenList: any[], index: number) => {
|
||||
const renderFunc = (tokens: any[], idx: number) => {
|
||||
const renderSandbox = (tokenList: Token[], index: number) => {
|
||||
const renderFunc = (tokens: Token[], idx: number) => {
|
||||
if (tokens[idx].nesting === 1) {
|
||||
const fileAttr: string[] = [];
|
||||
const attrs = Object.fromEntries(tokens[idx].attrs || []);
|
||||
|
||||
const files: Record<
|
||||
@@ -47,7 +44,7 @@ export default function sandpackPlugin(md: MarkdownIt, pluginOptions: SnackParam
|
||||
) {
|
||||
if (tokens[i].type === 'fence' && tokens[i].tag === 'code') {
|
||||
const info = tokens[i].info ?? '';
|
||||
const [lang, fileName, params = ''] = info.split(' ');
|
||||
const [, fileName, params = ''] = info.split(' ');
|
||||
|
||||
const active = params.includes('[active]');
|
||||
const hidden = params.includes('[hidden]');
|
||||
@@ -57,15 +54,9 @@ export default function sandpackPlugin(md: MarkdownIt, pluginOptions: SnackParam
|
||||
if (fileName && code) {
|
||||
files[fileName] = {
|
||||
code,
|
||||
...(active && { active: true }),
|
||||
...(hidden && { hidden: true }),
|
||||
};
|
||||
|
||||
if (active) {
|
||||
(files[fileName] as any).active = true;
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
(files[fileName] as any).hidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +113,7 @@ export default function sandpackPlugin(md: MarkdownIt, pluginOptions: SnackParam
|
||||
return renderFunc(tokenList, index);
|
||||
};
|
||||
|
||||
function createCodeGroup(md: MarkdownIt): ContainerArgs {
|
||||
function createCodeGroup(): ContainerArgs {
|
||||
return [
|
||||
container,
|
||||
'sandpack',
|
||||
@@ -134,5 +125,5 @@ export default function sandpackPlugin(md: MarkdownIt, pluginOptions: SnackParam
|
||||
];
|
||||
}
|
||||
|
||||
md.use(...createCodeGroup(md));
|
||||
md.use(...createCodeGroup());
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ export default function snackPlayerPlugin(md: MarkdownIt) {
|
||||
'react-native-safe-area-context' + (params.dependencies ? `,${params.dependencies}` : '');
|
||||
const platform = params.platform ?? 'web';
|
||||
const supportedPlatforms = params.supportedPlatforms ?? 'ios,android,web';
|
||||
const theme = params.theme ?? 'light';
|
||||
const preview = params.preview ?? 'true';
|
||||
const loading = params.loading ?? 'lazy';
|
||||
const deviceAppearance = params.deviceAppearance ?? 'dark';
|
||||
@@ -88,7 +87,7 @@ export default function snackPlayerPlugin(md: MarkdownIt) {
|
||||
` data-snack-dependencies="${escapeHtml(dependencies)}"` +
|
||||
` data-snack-platform="${escapeHtml(platform)}"` +
|
||||
` data-snack-supported-platforms="${escapeHtml(supportedPlatforms)}"` +
|
||||
// ` data-snack-theme="${escapeHtml(theme)}"` +
|
||||
// ` data-snack-theme="${escapeHtml(params.theme ?? 'light')}"` +
|
||||
` data-snack-preview="${escapeHtml(preview)}"` +
|
||||
` data-snack-loading="${escapeHtml(loading)}"` +
|
||||
` data-snack-device-appearance="${escapeHtml(deviceAppearance)}"` +
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { getAllData } from '../../../lib/icons';
|
||||
import { getAllCategoryFiles, mapCategoryIconCount } from '../../../lib/categories';
|
||||
import iconsMetaData from '../../../data/iconMetaData';
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { ref, inject, Ref } from 'vue';
|
||||
|
||||
export const ICON_STYLE_CONTEXT = Symbol('style');
|
||||
|
||||
6
docs/.vitepress/types.d.ts
vendored
6
docs/.vitepress/types.d.ts
vendored
@@ -6,13 +6,13 @@ declare module '*.vue' {
|
||||
}
|
||||
|
||||
declare module '*.data.ts' {
|
||||
const data: any;
|
||||
const data: unknown;
|
||||
|
||||
export { data };
|
||||
}
|
||||
|
||||
declare module '*.data' {
|
||||
const data: any;
|
||||
const data: unknown;
|
||||
|
||||
export { data };
|
||||
}
|
||||
@@ -75,7 +75,7 @@ declare global {
|
||||
doNotShowAfterSubmit?: boolean;
|
||||
customFormUrl?: string; // when you want to load the form via it's custom domain URL
|
||||
hiddenFields?: {
|
||||
[key: string]: any;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
onOpen?: () => void;
|
||||
onClose?: () => void;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { simpleGit } from 'simple-git';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { loadEnvFile } from 'node:process';
|
||||
@@ -10,7 +9,9 @@ const dataDirectory = path.resolve(currentDir, '.vitepress/data');
|
||||
try {
|
||||
// Load environment variables from .env file, if it exists.
|
||||
loadEnvFile(`${currentDir}/.env`);
|
||||
} catch (error) {}
|
||||
} catch {
|
||||
// No .env file, so rely on the environment as-is.
|
||||
}
|
||||
|
||||
interface IconCollection {
|
||||
/** Human readable name, used for logging. */
|
||||
|
||||
154
eslint.config.js
Normal file
154
eslint.config.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import path from 'node:path';
|
||||
import js from '@eslint/js';
|
||||
import { includeIgnoreFile } from '@eslint/compat';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import prettier from 'eslint-config-prettier';
|
||||
import importX, { createNodeResolver } from 'eslint-plugin-import-x';
|
||||
import htmlEslint from '@html-eslint/eslint-plugin';
|
||||
import htmlParser from '@html-eslint/parser';
|
||||
import defaultAttrs from './tools/build-icons/render/default-attrs.json' with { type: 'json' };
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
const gitignorePath = path.join(import.meta.dirname, '.gitignore');
|
||||
|
||||
export default defineConfig([
|
||||
tseslint.configs.recommended,
|
||||
{
|
||||
// `packages/angular` has its own config with its own tsconfig, so a single `eslint .` run sees
|
||||
// two candidate roots and typescript-eslint refuses to guess between them.
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Everything git ignores (generated icon sources, build output, caches) is ignored here too.
|
||||
includeIgnoreFile(gitignorePath),
|
||||
{
|
||||
// Ignores that are not in .gitignore, because these files are committed.
|
||||
ignores: [
|
||||
'lib',
|
||||
'**/tests',
|
||||
'packages/**/tests/*',
|
||||
'docs/images',
|
||||
'docs/**/examples/',
|
||||
'docs/.vitepress/theme/components/editors/preact/index.js',
|
||||
'packages/svelte/.svelte-kit',
|
||||
// Tracked in git despite matching a .gitignore pattern, so lint it.
|
||||
'!packages/lucide-react/dynamicIconImports.mjs',
|
||||
],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
console: 'readonly',
|
||||
process: 'readonly',
|
||||
global: 'readonly',
|
||||
__dirname: 'readonly',
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'import-x': importX,
|
||||
},
|
||||
settings: {
|
||||
'import-x/resolver-next': [createNodeResolver()],
|
||||
},
|
||||
rules: {
|
||||
...js.configs.recommended.rules,
|
||||
...prettier.rules,
|
||||
'no-console': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'import-x/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: [
|
||||
'**/*.test.js',
|
||||
'**/*.spec.js',
|
||||
'**/scripts/**',
|
||||
'eslint.config.js',
|
||||
'packages/**/tests/**',
|
||||
],
|
||||
},
|
||||
],
|
||||
'import-x/extensions': [
|
||||
'error',
|
||||
{
|
||||
pattern: {
|
||||
mjs: 'always',
|
||||
json: 'always',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
// Omitting a property by destructuring it away (`const { key, ...attrs } = node`) leaves the
|
||||
// omitted binding unused on purpose, so don't report it.
|
||||
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['./icons/*.svg'],
|
||||
languageOptions: {
|
||||
parser: htmlParser,
|
||||
},
|
||||
plugins: {
|
||||
'@html-eslint': htmlEslint,
|
||||
},
|
||||
rules: {
|
||||
'@html-eslint/require-doctype': 'off',
|
||||
'@html-eslint/no-duplicate-attrs': 'error',
|
||||
'@html-eslint/no-inline-styles': 'error',
|
||||
'@html-eslint/require-attrs': [
|
||||
'error',
|
||||
...Object.entries(defaultAttrs).map(([attr, value]) => ({
|
||||
tag: 'svg',
|
||||
attr,
|
||||
value: String(value),
|
||||
})),
|
||||
],
|
||||
'@html-eslint/indent': ['error', 2],
|
||||
'@html-eslint/no-multiple-empty-lines': ['error', { max: 0 }],
|
||||
'@html-eslint/no-extra-spacing-attrs': [
|
||||
'error',
|
||||
{
|
||||
enforceBeforeSelfClose: true,
|
||||
},
|
||||
],
|
||||
'@html-eslint/attrs-newline': [
|
||||
'error',
|
||||
{
|
||||
inline: ['path', 'line', 'polyline', 'polygon', 'rect', 'circle', 'ellipse'],
|
||||
},
|
||||
],
|
||||
'@html-eslint/require-closing-tags': [
|
||||
'error',
|
||||
{
|
||||
selfClosing: 'always',
|
||||
// Inside <svg> every tag counts as "foreign", where the rule only checks that a tag
|
||||
// already written `/>` stays that way. Listing the shapes here is what actually forces
|
||||
// `<path ...></path>` to become `<path ... />`.
|
||||
selfClosingCustomPatterns: ['^(path|line|polyline|polygon|rect|circle|ellipse)$'],
|
||||
},
|
||||
],
|
||||
'@html-eslint/no-restricted-attr-values': [
|
||||
'error',
|
||||
{
|
||||
attrPatterns: ['^(fill|stroke)$'],
|
||||
attrValuePatterns: ['^(?!(none|currentColor)$).*$'],
|
||||
message:
|
||||
'Icons must inherit their colors: `fill` and `stroke` may only be `none` or `currentColor`.',
|
||||
},
|
||||
],
|
||||
'@html-eslint/element-newline': 'error',
|
||||
'@html-eslint/no-trailing-spaces': 'error',
|
||||
'@html-eslint/quotes': 'error',
|
||||
},
|
||||
},
|
||||
]);
|
||||
27
package.json
27
package.json
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm -r --filter './packages/**' build",
|
||||
"test": "pnpm -r --filter './packages/**' test",
|
||||
@@ -22,7 +23,6 @@
|
||||
"addjsons": "node ./scripts/addMissingIconJsonFiles.mts",
|
||||
"checkIcons": "node ./scripts/checkIconsAndCategories.mts",
|
||||
"checkLabIcons": "node ./scripts/checkLabIcons.mts",
|
||||
"generate:changelog": "node ./scripts/generateChangelog.mts",
|
||||
"generate:sponsors": "node scripts/updateSponsors.mts",
|
||||
"generate:contributors": "node ./scripts/updateContributors.mts icons/*.svg",
|
||||
"generate:nextJSAliases": "node ./scripts/generateNextJSAliases.mts",
|
||||
@@ -47,25 +47,22 @@
|
||||
"devDependencies": {
|
||||
"@actions/core": "^3.0.1",
|
||||
"@actions/github": "^9.1.1",
|
||||
"@html-eslint/eslint-plugin": "^0.19.1",
|
||||
"@html-eslint/parser": "^0.19.1",
|
||||
"@eslint/compat": "^2.1.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@html-eslint/eslint-plugin": "^0.60.0",
|
||||
"@html-eslint/parser": "^0.60.0",
|
||||
"@octokit/rest": "^19.0.13",
|
||||
"@types/yargs": "^17.0.35",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.59.3",
|
||||
"@typescript-eslint/parser": "^8.59.3",
|
||||
"@vitest/coverage-v8": "4.1.10",
|
||||
"@vitest/ui": "4.1.10",
|
||||
"ajv-cli": "^5.0.0",
|
||||
"cspell": "^10.0.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-config-prettier": "^8.10.2",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-custom-alias": "^1.3.2",
|
||||
"eslint-import-resolver-typescript": "^3.10.1",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint": "^10.8.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-import-x": "^4.17.1",
|
||||
"husky": "^8.0.3",
|
||||
"jsdom": "^27.4.0",
|
||||
"lint-staged": "^17.0.8",
|
||||
@@ -78,6 +75,8 @@
|
||||
"simple-git": "^3.36.0",
|
||||
"svgo": "^3.3.4",
|
||||
"svgson": "^5.3.1",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.4",
|
||||
"vitest": "4.1.10",
|
||||
"yargs": "^17.7.3",
|
||||
"zod": "^3.25.76"
|
||||
@@ -85,5 +84,5 @@
|
||||
"engines": {
|
||||
"node": ">=24.11.1"
|
||||
},
|
||||
"packageManager": "pnpm@11.16.0+sha512.b767e9a98fc87aec0f42daefcd0e84941c2cdb45d73c4e1e68860fb2bdfdbe032ab592105479e5e05c237f740c8a5ffdbbb52385797ddc2296745a1bbb883e8d"
|
||||
"packageManager": "pnpm@11.22.0+sha512.1ff870c4c6133dfd88fb2afc46dd13d47f09c9794b438c6fdb47ca98caf3bc16381ee0be93a091b8e3824cf01f889f46d7d9e20910fb0be1ab0fb5baa80dd621"
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
1
packages/angular/.angular/cache/21.2.19/ng-packagr/tsbuildinfo/lucide-angular.tsbuildinfo
vendored
Normal file
1
packages/angular/.angular/cache/21.2.19/ng-packagr/tsbuildinfo/lucide-angular.tsbuildinfo
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,38 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@angular-eslint/recommended',
|
||||
'plugin:@angular-eslint/template/process-inline-templates',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'lucide',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: ['lucide'],
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.html'],
|
||||
extends: ['plugin:@angular-eslint/template/recommended'],
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
68
packages/angular/eslint.config.mjs
Normal file
68
packages/angular/eslint.config.mjs
Normal file
@@ -0,0 +1,68 @@
|
||||
import tseslint from 'typescript-eslint';
|
||||
import angular from 'angular-eslint';
|
||||
import prettier from 'eslint-config-prettier';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
// ESLint resolves a config per linted file by walking up from that file, so this config — not
|
||||
// the workspace root one — owns everything under `packages/angular`. That means the root's
|
||||
// `.gitignore`-derived ignores do not apply here and generated output must be listed by hand.
|
||||
ignores: [
|
||||
'dist',
|
||||
'build',
|
||||
'coverage',
|
||||
'out-tsc',
|
||||
'.angular',
|
||||
'src/icons', // Generated by `pnpm build:icons`.
|
||||
'eslint.config.mjs',
|
||||
],
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
extends: [tseslint.configs.recommended, angular.configs.tsRecommended],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
// `tsconfig.json` here is solution-style (`files: []` plus `references`), so `project: true`
|
||||
// resolves to a project that contains no source file. The project service follows the
|
||||
// references the way `tsc` and the editor do.
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
...prettier.rules,
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'lucide',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: ['lucide'],
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
// Build scripts belong to no tsconfig, so they get the untyped ruleset.
|
||||
files: ['**/*.mts', '**/*.cts'],
|
||||
extends: [tseslint.configs.recommended],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: prettier.rules,
|
||||
},
|
||||
{
|
||||
files: ['**/*.html'],
|
||||
extends: [angular.configs.templateRecommended],
|
||||
},
|
||||
]);
|
||||
@@ -25,7 +25,7 @@
|
||||
"build:ng": "ng build --configuration production",
|
||||
"test": "pnpm build:icons && ng test --no-watch",
|
||||
"test:watch": "ng test",
|
||||
"lint": "npx eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
|
||||
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"prettier": {
|
||||
@@ -41,11 +41,8 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-eslint/builder": "~21.1.0",
|
||||
"@angular-eslint/eslint-plugin": "~21.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "~21.1.0",
|
||||
"@angular-eslint/schematics": "~21.1.0",
|
||||
"@angular-eslint/template-parser": "~21.1.0",
|
||||
"@angular-eslint/builder": "~21.4.0",
|
||||
"@angular-eslint/schematics": "~21.4.0",
|
||||
"@angular/build": "^21.2.19",
|
||||
"@angular/cli": "^21.2.19",
|
||||
"@angular/common": "^21.2.19",
|
||||
|
||||
@@ -8,7 +8,6 @@ import { lucideIconTemplate } from './lucide-icon-template';
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: 'svg[lucideIcon]',
|
||||
template: lucideIconTemplate,
|
||||
host: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { toKebabCase } from './utils/toKebabCase';
|
||||
|
||||
export default (iconName: string, iconNode: IconNode): AstroComponentFactory => {
|
||||
const Component = createComponent(
|
||||
($$result, $$props: Record<string, any>, $$slots) => {
|
||||
($$result, $$props: Record<string, unknown>, $$slots) => {
|
||||
const { class: className, ...restProps } = $$props;
|
||||
return render`${renderComponent(
|
||||
$$result,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
|
||||
// Type that the Astro language server needs to infer component props in Astro files
|
||||
export type AstroComponent = (_props: IconProps) => any;
|
||||
export type AstroComponent = (_props: IconProps) => unknown;
|
||||
|
||||
export interface IconProps extends SVGAttributes {
|
||||
color?: string;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
|
||||
export default async ({
|
||||
|
||||
@@ -16,7 +16,7 @@ export default async function copyIcons(
|
||||
if (!existsSync(iconsDirectory)) {
|
||||
mkdirSync(iconsDirectory);
|
||||
}
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
|
||||
const writeIconPromises = parsedSvgs.map(({ name, contents }) => {
|
||||
let content = `<!-- ${license} -->\n${contents}`;
|
||||
content = content.replace('<svg', `<svg\n class="lucide lucide-${name}"`);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/// <reference types="node" />
|
||||
import { basename } from 'path';
|
||||
import { readSvg } from '@lucide/helpers';
|
||||
import { type INode, parseSync } from 'svgson';
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface LucideProps extends Partial<React.SVGProps<SVGSVGElement>> {
|
||||
|
||||
export declare const createLucideIcon: (
|
||||
iconName: string,
|
||||
iconNode: any[],
|
||||
iconNode: [elementName: string, attrs: Record<string, string>][],
|
||||
) => (props: LucideProps) => JSX.Element;
|
||||
|
||||
export type Icon = React.FC<LucideProps>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// eslint-disable
|
||||
// This file is make sure that we can import from "lucide-react/dynamic" without having to specify the extension. This is a workaround for the fact that some bundlers (like Webpack) don't support importing from "lucide-react/dynamic.mjs" without specifying the extension.
|
||||
// Unfortunately, we can't use exports field in package.json because it breaks some runtime environments. See https://github.com/lucide-icons/lucide/issues/2743#issuecomment-2626784300
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
export * from './dynamic.mjs';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { JSX } from 'solid-js/jsx-runtime';
|
||||
import { SVGAttributes } from './types';
|
||||
|
||||
const defaultAttributes: SVGAttributes = {
|
||||
|
||||
@@ -2,8 +2,6 @@ import { defineConfig } from 'vitest/config'
|
||||
import solidPlugin from 'vite-plugin-solid';
|
||||
|
||||
export default defineConfig({
|
||||
// TODO: Remove this when Solid testing library has support for Vitest 1.0, see: https://github.com/solidjs/solid-testing-library/issues/52
|
||||
// @ts-ignore
|
||||
plugins: [solidPlugin()],
|
||||
test: {
|
||||
globals: true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { parseSync } from 'svgson';
|
||||
|
||||
import { readSvgDirectory, getCurrentDirPath } from '@lucide/helpers';
|
||||
import readSvgs from './readSvgs.mts';
|
||||
|
||||
@@ -16,7 +16,7 @@ export default async function copyIcons(
|
||||
if (!existsSync(iconsDirectory)) {
|
||||
mkdirSync(iconsDirectory);
|
||||
}
|
||||
// eslint-disable-next-line arrow-body-style
|
||||
|
||||
const writeIconPromises = parsedSvgs.map(({ name, contents }) => {
|
||||
let content = `<!-- ${license} -->\n${contents}`;
|
||||
content = content.replace('<svg', `<svg\n class="lucide lucide-${name}"`);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import { type INode, stringify } from 'svgson';
|
||||
import { format } from 'prettier';
|
||||
import { appendFile } from '@lucide/helpers';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/// <reference types="node" />
|
||||
import { basename } from 'path';
|
||||
import { readSvg } from '@lucide/helpers';
|
||||
import { type INode, parseSync } from 'svgson';
|
||||
|
||||
@@ -13,7 +13,6 @@ export default defineExportTemplate(async ({
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `
|
||||
import defaultAttributes from '../defaultAttributes';
|
||||
import type { IconNode } from '../types';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
type Booleanish = boolean | 'true' | 'false';
|
||||
|
||||
interface AriaAttributes {
|
||||
export interface AriaAttributes {
|
||||
'aria-activedescendant'?: string | undefined;
|
||||
'aria-atomic'?: Booleanish | undefined;
|
||||
'aria-autocomplete'?: 'none' | 'inline' | 'list' | 'both' | undefined;
|
||||
|
||||
@@ -3,7 +3,7 @@ import defaultAttributes from './defaultAttributes';
|
||||
import { Icons, SVGProps } from './types';
|
||||
import { hasA11yProp, mergeClasses, toPascalCase } from '@lucide/shared';
|
||||
|
||||
export type CustomAttrs = { [attr: string]: any };
|
||||
export type CustomAttrs = { [attr: string]: unknown };
|
||||
|
||||
/**
|
||||
* Get the attributes of an HTML element.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @param {object} props
|
||||
* @returns {boolean} Whether the component has an accessibility prop
|
||||
*/
|
||||
export const hasA11yProp = (props: Record<string, any>) => {
|
||||
export const hasA11yProp = (props: object) => {
|
||||
for (const prop in props) {
|
||||
if (prop.startsWith('aria-') || prop === 'role' || prop === 'title') {
|
||||
return true;
|
||||
|
||||
@@ -14,20 +14,20 @@ const files = await readdir(targetDirectory, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
for (const file of files) {
|
||||
const filepath = path.join(targetDirectory, file);
|
||||
const filestat = lstatSync(filepath);
|
||||
|
||||
// eslint-disable-next-line no-continue
|
||||
|
||||
if (filestat.isFile() === false || filestat.isDirectory()) continue;
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
|
||||
const contents = (await readFile(filepath, { encoding: 'utf-8' })) as unknown as string;
|
||||
const ext = path.extname(filepath);
|
||||
|
||||
if (/\.(js|mjs|cjs|ts)/.test(ext)) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
|
||||
await writeFile(filepath, jsBanner + contents, { encoding: 'utf-8' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import pkg from '../package.json' with { type: 'json' };
|
||||
|
||||
const license = fs.readFileSync('LICENSE', 'utf-8');
|
||||
|
||||
export function getHTMLBanner() {
|
||||
return `\
|
||||
<!--
|
||||
|
||||
@@ -30,9 +30,10 @@ export type IconProps = LucideProps;
|
||||
export type LucideIcon = Component<LucideProps>;
|
||||
|
||||
export type IconEvents = {
|
||||
[evt: string]: CustomEvent<any>;
|
||||
[evt: string]: CustomEvent<unknown>;
|
||||
};
|
||||
|
||||
export type IconSlots = {
|
||||
default: {};
|
||||
// The default slot does not expose any slot props.
|
||||
default: Record<string, never>;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
// eslint-disable-next-line import-x/no-extraneous-dependencies
|
||||
import { sveltePreprocess } from 'svelte-preprocess';
|
||||
|
||||
export default {
|
||||
|
||||
1588
pnpm-lock.yaml
generated
1588
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,101 +0,0 @@
|
||||
import getArgumentOptions from 'minimist';
|
||||
import githubApi from './githubApi.mts';
|
||||
|
||||
const fetchCompareTags = (oldTag: string) =>
|
||||
githubApi(`https://api.github.com/repos/lucide-icons/lucide/compare/${oldTag}...main`);
|
||||
|
||||
const iconRegex = /icons\/(.*)\.svg/g;
|
||||
const iconTemplate = ({ name, pullNumber, author }: { name: string, pullNumber: number, author: string }) =>
|
||||
`- \`${name}\` (${pullNumber}) by @${author}`;
|
||||
|
||||
const topics = [
|
||||
{
|
||||
title: 'New icons 🎨',
|
||||
template: iconTemplate,
|
||||
filter: ({ status, filename }) => status === 'added' && filename.match(iconRegex),
|
||||
},
|
||||
{
|
||||
title: 'Modified Icons 🔨',
|
||||
template: iconTemplate,
|
||||
filter: ({ status, filename }) => status === 'modified' && filename.match(iconRegex),
|
||||
},
|
||||
{
|
||||
title: 'Code improvements ⚡',
|
||||
template: ({ title, pullNumber, author }) => `- ${title} (${pullNumber}) by @${author}`,
|
||||
filter: ({ filename }, index, self) =>
|
||||
!filename.match(iconRegex) && self.indexOf(filename) === index,
|
||||
},
|
||||
];
|
||||
|
||||
const fetchCommits = async (file) => {
|
||||
const commits = await githubApi(
|
||||
`https://api.github.com/repos/lucide-icons/lucide/commits?path=${file.filename}`,
|
||||
);
|
||||
|
||||
return { ...file, commits };
|
||||
};
|
||||
|
||||
const cliArguments = getArgumentOptions(process.argv.slice(2));
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
(async function () {
|
||||
try {
|
||||
const output = await fetchCompareTags(cliArguments['old-tag']);
|
||||
|
||||
if (output?.files == null) {
|
||||
throw new Error('Tag not found!');
|
||||
}
|
||||
|
||||
const changedFiles = output.files.filter(
|
||||
({ filename }: { filename: string }) => !filename.match(/docs\/(.*)|(.*)package\.json|tags.json/g),
|
||||
);
|
||||
|
||||
const commits = await Promise.all(changedFiles.map(fetchCommits));
|
||||
|
||||
if (!commits.length) {
|
||||
throw new Error('No commits found');
|
||||
}
|
||||
|
||||
const mappedCommits = commits
|
||||
.map(({ commits: [pr], filename, sha, status }) => {
|
||||
const pullNumber = /(.*)\((#[0-9]*)\)/gm.exec(pr.commit.message);
|
||||
const nameRegex = /^\/?(.+\/)*(.+)\.(.+)$/g.exec(filename);
|
||||
|
||||
if (!pr.author) {
|
||||
// Most likely bot commit
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
filename,
|
||||
name: nameRegex && nameRegex[2] ? nameRegex[2] : null,
|
||||
title: pullNumber && pullNumber[1] ? pullNumber[1].trim() : null,
|
||||
pullNumber: pullNumber && pullNumber[2] ? pullNumber[2].trim() : null,
|
||||
author: pr.author?.login || 'unknown',
|
||||
sha,
|
||||
status,
|
||||
};
|
||||
})
|
||||
.filter((commit): commit is NonNullable<typeof commit> => Boolean(commit))
|
||||
.filter(({ pullNumber }) => !!pullNumber);
|
||||
|
||||
const changelog = topics.map(({ title, filter, template }) => {
|
||||
const lines = mappedCommits.filter(filter).map<string>(template);
|
||||
|
||||
if (lines.length) {
|
||||
return [`## ${title}`, ' ', ...lines, ' '];
|
||||
}
|
||||
|
||||
return [''];
|
||||
});
|
||||
|
||||
const changelogMarkown = changelog.flat().join('\n');
|
||||
|
||||
console.log(changelogMarkown);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
})().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -11,7 +11,7 @@ async function main() {
|
||||
const svgFiles = await readSvgDirectory(ICONS_DIR);
|
||||
const iconNames = svgFiles.map((icon) => icon.split('.')[0]).reverse();
|
||||
const argv = (yargs(hideBin(process.argv))
|
||||
// @ts-ignore
|
||||
// @ts-expect-error the builder callback overload is not picked up for a default command
|
||||
.usage('$0 <pattern> <replacement>', 'Renames all icons matching a pattern', (yargs) => {
|
||||
yargs
|
||||
.positional('pattern', {
|
||||
|
||||
@@ -59,7 +59,7 @@ const getContributors = async (file: string, includeCoAuthors?: boolean) => {
|
||||
const matches = commit.body.matchAll(
|
||||
/(^Author:|^Co-authored-by:)\s+(?<author>[^<]+)\s+<(?<email>[^>]+)>/gm,
|
||||
);
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
for (const match of matches) {
|
||||
if (!emails.has(match.groups?.email) && cache.has(match.groups?.email)) {
|
||||
emails.set(match.groups?.email, Promise.resolve(cache.get(match.groups?.email)));
|
||||
|
||||
@@ -27,8 +27,8 @@ export async function allocateCodePoints({
|
||||
const latestCodePoints = await getLatestCodePoints();
|
||||
|
||||
let maxCodePoint = Math.max(...Object.values(latestCodePoints));
|
||||
let codePointMap = new Map<number, string>();
|
||||
let newCodePoints: CodePoints = {};
|
||||
const codePointMap = new Map<number, string>();
|
||||
const newCodePoints: CodePoints = {};
|
||||
|
||||
for (const [iconName, aliases] of iconsWithAliases) {
|
||||
let codePoint: number | null = null;
|
||||
|
||||
@@ -14,7 +14,9 @@ export async function outlineSVG({ iconsDir, outlinedDir, iconsWithAliases }: Ou
|
||||
try {
|
||||
try {
|
||||
await fs.mkdir(outlinedDir);
|
||||
} catch (error) {} // eslint-disable-line no-empty
|
||||
} catch (err) {
|
||||
console.warn(`Directory ${outlinedDir} already exists. Skipping creation.`, err);
|
||||
}
|
||||
|
||||
await SVGFixer(iconsDir, outlinedDir, {
|
||||
showProgressBar: true,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { hash } from './hash.ts';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { generateHashedKey } from './generateHashedKey.ts';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* djb2 hashing function
|
||||
*
|
||||
@@ -10,10 +9,8 @@ export const hash = (string: string, seed: number = 5381): string => {
|
||||
let i = string.length;
|
||||
|
||||
while (i) {
|
||||
// eslint-disable-next-line no-bitwise, no-plusplus
|
||||
seed = (seed * 33) ^ string.charCodeAt(--i);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return (seed >>> 0).toString(36).substr(0, 6);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* Merge two arrays and remove duplicates
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* Minifies SVG
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { type PathLike } from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* @param {array} array
|
||||
* @returns {array}
|
||||
*/
|
||||
export const shuffleArray = <T>(array: T[]): T[] => {
|
||||
// eslint-disable-next-line no-plusplus
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* Converts string to CamelCase
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
/**
|
||||
* Converts string to KebabCase
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { toCamelCase } from './toCamelCase.ts';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { writeFile } from './writeFile.ts';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"target": "ESNext",
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"types": ["node"],
|
||||
"resolveJsonModule": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { toPascalCase, resetFile, appendFile } from '@lucide/helpers';
|
||||
import deprecationReasonTemplate from '../../utils/deprecationReasonTemplate.ts';
|
||||
import getExportString from './getExportString.ts';
|
||||
|
||||
@@ -9,7 +9,6 @@ import generateIconFiles from './building/generateIconFiles.ts';
|
||||
import generateExportsFile from './building/generateExportsFile.ts';
|
||||
|
||||
import generateAliasesFiles from './building/aliases/generateAliasesFiles.ts';
|
||||
// eslint-disable-next-line import/no-named-as-default, import/no-named-as-default-member
|
||||
import getIconMetaData from './utils/getIconMetaData.ts';
|
||||
import generateDynamicImports from './building/generateDynamicImports.ts';
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"target": "ESNext",
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"types": ["node"],
|
||||
"resolveJsonModule": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { type INode } from 'svgson';
|
||||
|
||||
export type SVGProps = Record<string, string | number>;
|
||||
|
||||
export type IconNode = [tag: string, attrs: SVGProps][];
|
||||
|
||||
@@ -9,8 +9,6 @@ export default function deprecationReasonTemplate(
|
||||
iconName: string;
|
||||
},
|
||||
) {
|
||||
const resourceName = deprecationReason.startsWith('icon') ? 'icon' : 'alias';
|
||||
|
||||
switch (deprecationReason) {
|
||||
case 'alias.typo':
|
||||
return `Renamed because of typo, use {@link ${componentName}} instead.`;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
import license from 'rollup-plugin-license';
|
||||
|
||||
Reference in New Issue
Block a user