mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-16 22:27:43 +01:00
fix(packages/icons): trying some other variations
This commit is contained in:
@@ -15,19 +15,14 @@ export default defineExportTemplate(async ({
|
|||||||
const svgBase64 = base64SVG(svgContents);
|
const svgBase64 = base64SVG(svgContents);
|
||||||
const angularComponentName = `Lucide${componentName}Component`;
|
const angularComponentName = `Lucide${componentName}Component`;
|
||||||
const selectors = [`svg[lucide-${iconName}]`];
|
const selectors = [`svg[lucide-${iconName}]`];
|
||||||
const aliasExports: {[aliasComponentName: string]: string[]} = {};
|
const aliasExports: {[aliasComponentName: string]: boolean} = {};
|
||||||
for (const alias of aliases) {
|
for (const alias of aliases) {
|
||||||
const aliasName = typeof alias === 'string' ? alias : alias.name;
|
const aliasName = typeof alias === 'string' ? alias : alias.name;
|
||||||
const aliasComponentName = `Lucide${toPascalCase(aliasName)}Component`;
|
const aliasComponentName = `Lucide${toPascalCase(aliasName)}Component`;
|
||||||
const aliasSelector = `svg[lucide-${aliasName}]`;
|
const aliasSelector = `svg[lucide-${aliasName}]`;
|
||||||
if (aliasComponentName === angularComponentName) {
|
selectors.push(aliasSelector);
|
||||||
selectors.push(aliasSelector);
|
if (aliasComponentName !== angularComponentName && !(aliasComponentName in aliasExports)) {
|
||||||
} else {
|
aliasExports[aliasComponentName] = true;
|
||||||
if (aliasComponentName in aliasExports) {
|
|
||||||
aliasExports[aliasComponentName] = [aliasSelector];
|
|
||||||
} else {
|
|
||||||
aliasExports[aliasComponentName].push(aliasSelector);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,19 +51,13 @@ export class ${angularComponentName} extends LucideAngularComponent {
|
|||||||
override name = '${iconName}';
|
override name = '${iconName}';
|
||||||
}
|
}
|
||||||
|
|
||||||
${Object.entries(aliasExports).map(([aliasComponentName, aliasSelectors]) => {
|
${Object.entries(aliasExports).map(([aliasComponentName]) => {
|
||||||
return `
|
return `
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @see ${angularComponentName}
|
* @see ${angularComponentName}
|
||||||
*/
|
*/
|
||||||
@Component({
|
export const ${aliasComponentName} = ${angularComponentName};
|
||||||
selector: '${aliasSelectors.join(', ')}',
|
|
||||||
template: '',
|
|
||||||
standalone: true,
|
|
||||||
})
|
|
||||||
export class ${aliasComponentName} extends ${angularComponentName} {
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}).join(`\n\n`)}
|
}).join(`\n\n`)}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { LucideAngularModule } from './lucide-angular.module';
|
|
||||||
import { formatFixed, LucideAngularComponent } from './lucide-angular.component';
|
import { formatFixed, LucideAngularComponent } from './lucide-angular.component';
|
||||||
import defaultAttributes from '../icons/constants/default-attributes';
|
import defaultAttributes from '../icons/constants/default-attributes';
|
||||||
import { LucideIcons } from '../icons/types';
|
import { LucideIconData } from '../icons/types';
|
||||||
|
|
||||||
describe('LucideAngularComponent', () => {
|
describe('LucideAngularComponent', () => {
|
||||||
let testHostComponent: TestHostComponent;
|
let testHostComponent: TestHostComponent;
|
||||||
let testHostFixture: ComponentFixture<TestHostComponent>;
|
let testHostFixture: ComponentFixture<TestHostComponent>;
|
||||||
const getSvgAttribute = (attr: string) =>
|
const getSvgAttribute = (attr: string) =>
|
||||||
testHostFixture.nativeElement.querySelector('svg').getAttribute(attr);
|
testHostFixture.nativeElement.querySelector('svg').getAttribute(attr);
|
||||||
const testIcons: LucideIcons = {
|
const testIcon: LucideIconData = [['polyline', { points: '1 1 22 22' }]];
|
||||||
Demo: [['polyline', { points: '1 1 22 22' }]],
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [LucideAngularComponent, TestHostComponent],
|
declarations: [LucideAngularComponent, TestHostComponent],
|
||||||
imports: [LucideAngularModule.pick(testIcons)],
|
imports: [],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
testHostFixture = TestBed.createComponent(TestHostComponent);
|
testHostFixture = TestBed.createComponent(TestHostComponent);
|
||||||
testHostComponent = testHostFixture.componentInstance;
|
testHostComponent = testHostFixture.componentInstance;
|
||||||
@@ -63,7 +59,7 @@ describe('LucideAngularComponent', () => {
|
|||||||
testHostComponent.setAbsoluteStrokeWidth(true);
|
testHostComponent.setAbsoluteStrokeWidth(true);
|
||||||
testHostFixture.detectChanges();
|
testHostFixture.detectChanges();
|
||||||
expect(getSvgAttribute('stroke-width')).toBe(
|
expect(getSvgAttribute('stroke-width')).toBe(
|
||||||
formatFixed(strokeWidth / (size / defaultAttributes.height)),
|
formatFixed(strokeWidth / (size / defaultAttributes.height))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,6 +67,7 @@ describe('LucideAngularComponent', () => {
|
|||||||
selector: 'lucide-spec-host-component',
|
selector: 'lucide-spec-host-component',
|
||||||
template: ` <i-lucide
|
template: ` <i-lucide
|
||||||
name="demo"
|
name="demo"
|
||||||
|
[img]="testIcon"
|
||||||
class="my-icon"
|
class="my-icon"
|
||||||
[color]="color"
|
[color]="color"
|
||||||
[size]="size"
|
[size]="size"
|
||||||
@@ -83,6 +80,7 @@ describe('LucideAngularComponent', () => {
|
|||||||
size?: number;
|
size?: number;
|
||||||
strokeWidth?: number;
|
strokeWidth?: number;
|
||||||
absoluteStrokeWidth = true;
|
absoluteStrokeWidth = true;
|
||||||
|
readonly testIcon = testIcon;
|
||||||
|
|
||||||
setColor(color: string): void {
|
setColor(color: string): void {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type SvgAttributes = { [key: string]: string | number };
|
|||||||
|
|
||||||
type LucideAngularComponentChanges = {
|
type LucideAngularComponentChanges = {
|
||||||
name?: TypedChange<string | LucideIconData>;
|
name?: TypedChange<string | LucideIconData>;
|
||||||
img?: TypedChange<LucideIconData | undefined>;
|
icon?: TypedChange<LucideIconData | undefined>;
|
||||||
color?: TypedChange<string>;
|
color?: TypedChange<string>;
|
||||||
size?: TypedChange<number>;
|
size?: TypedChange<number>;
|
||||||
strokeWidth?: TypedChange<number>;
|
strokeWidth?: TypedChange<number>;
|
||||||
@@ -35,14 +35,15 @@ export function formatFixed(number: number, decimals = 3): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'lucide-angular, lucide-icon, i-lucide, span-lucide',
|
// eslint-disable-next-line @angular-eslint/component-selector
|
||||||
|
selector: 'svg[lucideIcon]',
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
})
|
})
|
||||||
export class LucideAngularComponent implements OnInit, OnChanges {
|
export class LucideAngularComponent implements OnInit, OnChanges {
|
||||||
@Input() class?: string;
|
@Input() class?: string;
|
||||||
@Input() name?: string;
|
@Input() name?: string;
|
||||||
@Input() icon?: LucideIconData;
|
@Input('lucideIcon') icon?: LucideIconData;
|
||||||
@Input() color?: string;
|
@Input() color?: string;
|
||||||
@Input() absoluteStrokeWidth = false;
|
@Input() absoluteStrokeWidth = false;
|
||||||
defaultSize: number;
|
defaultSize: number;
|
||||||
@@ -51,7 +52,7 @@ export class LucideAngularComponent implements OnInit, OnChanges {
|
|||||||
@Inject(ElementRef) protected elem: ElementRef,
|
@Inject(ElementRef) protected elem: ElementRef,
|
||||||
@Inject(Renderer2) protected renderer: Renderer2,
|
@Inject(Renderer2) protected renderer: Renderer2,
|
||||||
@Inject(ChangeDetectorRef) protected changeDetector: ChangeDetectorRef,
|
@Inject(ChangeDetectorRef) protected changeDetector: ChangeDetectorRef,
|
||||||
@Inject(LucideIconConfig) protected iconConfig: LucideIconConfig,
|
@Inject(LucideIconConfig) protected iconConfig: LucideIconConfig
|
||||||
) {
|
) {
|
||||||
this.defaultSize = defaultAttributes.height;
|
this.defaultSize = defaultAttributes.height;
|
||||||
console.log(this.name, this.icon);
|
console.log(this.name, this.icon);
|
||||||
@@ -92,7 +93,7 @@ export class LucideAngularComponent implements OnInit, OnChanges {
|
|||||||
ngOnChanges(changes: LucideAngularComponentChanges): void {
|
ngOnChanges(changes: LucideAngularComponentChanges): void {
|
||||||
if (
|
if (
|
||||||
changes.name ||
|
changes.name ||
|
||||||
changes.img ||
|
changes.icon ||
|
||||||
changes.color ||
|
changes.color ||
|
||||||
changes.size ||
|
changes.size ||
|
||||||
changes.absoluteStrokeWidth ||
|
changes.absoluteStrokeWidth ||
|
||||||
@@ -126,7 +127,10 @@ export class LucideAngularComponent implements OnInit, OnChanges {
|
|||||||
? formatFixed(this.strokeWidth / (this.size / this.defaultSize))
|
? formatFixed(this.strokeWidth / (this.size / this.defaultSize))
|
||||||
: this.strokeWidth.toString(10),
|
: this.strokeWidth.toString(10),
|
||||||
};
|
};
|
||||||
const icoElement = this.createElement(['svg', attributes, img]);
|
const icoElement = this.elem.nativeElement;
|
||||||
|
for (const [name, value] of Object.entries(attributes)) {
|
||||||
|
icoElement.setAttribute(name, value);
|
||||||
|
}
|
||||||
icoElement.classList.add('lucide');
|
icoElement.classList.add('lucide');
|
||||||
if (typeof this.name === 'string') {
|
if (typeof this.name === 'string') {
|
||||||
icoElement.classList.add(`lucide-${this.name.replace('_', '-')}`);
|
icoElement.classList.add(`lucide-${this.name.replace('_', '-')}`);
|
||||||
@@ -136,14 +140,16 @@ export class LucideAngularComponent implements OnInit, OnChanges {
|
|||||||
...this.class
|
...this.class
|
||||||
.split(/ /)
|
.split(/ /)
|
||||||
.map((a) => a.trim())
|
.map((a) => a.trim())
|
||||||
.filter((a) => a.length > 0),
|
.filter((a) => a.length > 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const childElements = this.elem.nativeElement.childNodes;
|
for (const child of icoElement.children) {
|
||||||
for (const child of childElements) {
|
|
||||||
this.renderer.removeChild(this.elem.nativeElement, child);
|
this.renderer.removeChild(this.elem.nativeElement, child);
|
||||||
}
|
}
|
||||||
this.renderer.appendChild(this.elem.nativeElement, icoElement);
|
for (const node of img) {
|
||||||
|
const childElement = this.createElement(node);
|
||||||
|
this.renderer.appendChild(icoElement, childElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected parseNumber(value: string | number): number {
|
protected parseNumber(value: string | number): number {
|
||||||
@@ -160,7 +166,7 @@ export class LucideAngularComponent implements OnInit, OnChanges {
|
|||||||
protected createElement([tag, attrs, children = []]: readonly [
|
protected createElement([tag, attrs, children = []]: readonly [
|
||||||
string,
|
string,
|
||||||
SvgAttributes,
|
SvgAttributes,
|
||||||
LucideIconData?,
|
LucideIconData?
|
||||||
]) {
|
]) {
|
||||||
const element = this.renderer.createElement(tag, 'http://www.w3.org/2000/svg');
|
const element = this.renderer.createElement(tag, 'http://www.w3.org/2000/svg');
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
stats
|
|
||||||
node_modules
|
|
||||||
tests
|
|
||||||
scripts
|
|
||||||
build
|
|
||||||
src
|
|
||||||
babel.config.js
|
|
||||||
jest.config.js
|
|
||||||
rollup.config.js
|
|
||||||
yarn.error.log
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<p align="center">
|
|
||||||
<a href="https://github.com/lucide-icons/lucide">
|
|
||||||
<img src="https://lucide.dev/package-logos/lucide.svg" alt="Lucide icon library for web applications." width="540">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
Lucide icon library for web applications.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/lucide)
|
|
||||||

|
|
||||||
[](https://lucide.dev/license)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://lucide.dev/guide/">About</a>
|
|
||||||
·
|
|
||||||
<a href="https://lucide.dev/icons/">Icons</a>
|
|
||||||
·
|
|
||||||
<a href="https://lucide.dev/guide/packages/lucide">Documentation</a>
|
|
||||||
·
|
|
||||||
<a href="https://lucide.dev/license">License</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# Lucide
|
|
||||||
|
|
||||||
Implementation of the lucide icon library for web applications.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```sh
|
|
||||||
pnpm add lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bun add lucide
|
|
||||||
```
|
|
||||||
|
|
||||||
### CDN
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!-- Development version -->
|
|
||||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
|
||||||
|
|
||||||
<!-- Production version -->
|
|
||||||
<script src="https://unpkg.com/lucide@latest"></script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
For full documentation, visit [lucide.dev](https://lucide.dev/guide/packages/lucide)
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
|
||||||
|
|
||||||
## Sponsors
|
|
||||||
|
|
||||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
|
||||||
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
|
||||||
|
|
||||||
### Awesome backers 🍺
|
|
||||||
|
|
||||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
|
||||||
<a href="https://github.com/pdfme/pdfme"><img src="../../docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@lucide/icons",
|
|
||||||
"description": "A Lucide icon library that contains icon data in a standard Lucide format.",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"license": "ISC",
|
|
||||||
"homepage": "https://lucide.dev",
|
|
||||||
"bugs": "https://github.com/lucide-icons/lucide/issues",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/lucide-icons/lucide.git",
|
|
||||||
"directory": "packages/lucide"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"Lucide",
|
|
||||||
"HTML",
|
|
||||||
"Feather",
|
|
||||||
"Icons",
|
|
||||||
"Icon",
|
|
||||||
"SVG",
|
|
||||||
"Feather Icons",
|
|
||||||
"Fontawesome",
|
|
||||||
"Font Awesome"
|
|
||||||
],
|
|
||||||
"amdName": "lucide-icons",
|
|
||||||
"source": "src/lucide-icons.js",
|
|
||||||
"main": "dist/cjs/lucide-icons.js",
|
|
||||||
"main:umd": "dist/umd/lucide-icons.js",
|
|
||||||
"module": "dist/esm/lucide-icons.js",
|
|
||||||
"unpkg": "dist/umd/lucide-icons.min.js",
|
|
||||||
"typings": "dist/lucide-icons.d.ts",
|
|
||||||
"sideEffects": false,
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundle",
|
|
||||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
|
||||||
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts",
|
|
||||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --withDynamicImports --separateAliasesFile --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
|
|
||||||
"build:bundle": "rollup -c rollup.config.mjs",
|
|
||||||
"test": "pnpm build:icons && vitest run",
|
|
||||||
"test:watch": "vitest watch",
|
|
||||||
"version": "pnpm version --git-tag-version=false"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@lucide/build-icons": "workspace:*",
|
|
||||||
"@lucide/rollup-plugins": "workspace:*",
|
|
||||||
"@rollup/plugin-replace": "^6.0.1",
|
|
||||||
"@testing-library/jest-dom": "^6.1.6",
|
|
||||||
"jest-serializer-html": "^7.1.0",
|
|
||||||
"rollup": "^4.22.4",
|
|
||||||
"rollup-plugin-dts": "^6.1.0",
|
|
||||||
"typescript": "^4.9.3",
|
|
||||||
"vite": "5.4.14",
|
|
||||||
"vitest": "^1.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
import plugins from '@lucide/rollup-plugins';
|
|
||||||
import replace from '@rollup/plugin-replace';
|
|
||||||
import dts from 'rollup-plugin-dts';
|
|
||||||
import pkg from './package.json' with { type: 'json' };
|
|
||||||
|
|
||||||
const outputFileName = pkg.name;
|
|
||||||
const outputDir = 'dist';
|
|
||||||
const inputs = ['src/lucide.ts'];
|
|
||||||
const bundles = [
|
|
||||||
{
|
|
||||||
format: 'umd',
|
|
||||||
inputs,
|
|
||||||
outputDir,
|
|
||||||
minify: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
format: 'umd',
|
|
||||||
inputs,
|
|
||||||
outputDir,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
format: 'cjs',
|
|
||||||
inputs,
|
|
||||||
outputDir,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
format: 'esm',
|
|
||||||
inputs,
|
|
||||||
outputDir,
|
|
||||||
preserveModules: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const configs = bundles
|
|
||||||
.map(({ inputs, outputDir, format, minify, preserveModules }) =>
|
|
||||||
inputs.map((input) => ({
|
|
||||||
input,
|
|
||||||
plugins: [
|
|
||||||
// This is for lucide plugin to replace an argument in createIcons so it is easier to use with UMD.
|
|
||||||
...(format === 'umd'
|
|
||||||
? [
|
|
||||||
replace({
|
|
||||||
'icons = {}': 'icons = iconAndAliases',
|
|
||||||
delimiters: ['', ''],
|
|
||||||
preventAssignment: false,
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
...plugins({ pkg, minify }),
|
|
||||||
],
|
|
||||||
output: {
|
|
||||||
name: outputFileName,
|
|
||||||
...(preserveModules
|
|
||||||
? {
|
|
||||||
dir: `${outputDir}/${format}`,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
|
|
||||||
}),
|
|
||||||
format,
|
|
||||||
sourcemap: true,
|
|
||||||
preserveModules,
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
.flat();
|
|
||||||
|
|
||||||
const typesFileConfig = {
|
|
||||||
input: inputs[0],
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
file: `${outputDir}/${outputFileName}.d.ts`,
|
|
||||||
format: 'esm',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
dts({
|
|
||||||
include: ['src'],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default [...configs, typesFileConfig];
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import base64SVG from '@lucide/build-icons/utils/base64SVG.mjs';
|
|
||||||
|
|
||||||
export default async ({
|
|
||||||
componentName,
|
|
||||||
iconName,
|
|
||||||
children,
|
|
||||||
getSvg,
|
|
||||||
deprecated,
|
|
||||||
deprecationReason,
|
|
||||||
}) => {
|
|
||||||
const svgContents = await getSvg();
|
|
||||||
const svgBase64 = base64SVG(svgContents);
|
|
||||||
|
|
||||||
return `
|
|
||||||
import type { LucideIconData } from '../types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name ${iconName}
|
|
||||||
* @description Lucide SVG icon node.
|
|
||||||
*
|
|
||||||
* @preview  - https://lucide.dev/icons/${iconName}
|
|
||||||
* @see https://lucide.dev/guide/packages/lucide - Documentation
|
|
||||||
*
|
|
||||||
* @returns {Array}
|
|
||||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
|
||||||
*/
|
|
||||||
const ${componentName}: LucideIconData = ${JSON.stringify({
|
|
||||||
name: iconName,
|
|
||||||
size: 24,
|
|
||||||
node: children,
|
|
||||||
})}
|
|
||||||
|
|
||||||
export default ${componentName};
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export * from './aliases';
|
|
||||||
export * from './prefixed';
|
|
||||||
export * from './suffixed';
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { SVGProps } from './types';
|
|
||||||
|
|
||||||
const defaultAttributes: SVGProps = {
|
|
||||||
xmlns: 'http://www.w3.org/2000/svg',
|
|
||||||
fill: 'none',
|
|
||||||
stroke: 'currentColor',
|
|
||||||
'stroke-width': 2,
|
|
||||||
'stroke-linecap': 'round',
|
|
||||||
'stroke-linejoin': 'round',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defaultAttributes;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Folder for generated icons
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './icons';
|
|
||||||
export * from './aliases';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export * as icons from './icons';
|
|
||||||
export * from './aliases/prefixed';
|
|
||||||
export * from './types';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export * as icons from './icons';
|
|
||||||
export * from './aliases/suffixed';
|
|
||||||
export * from './types';
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from './icons';
|
|
||||||
export * as icons from './icons';
|
|
||||||
export * from './aliases';
|
|
||||||
export * from './types';
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
export type SVGProps = Record<string, string | number>;
|
|
||||||
|
|
||||||
export type LucideIconNode = [tag: string, attrs: SVGProps][];
|
|
||||||
|
|
||||||
export type LucideIconData = {
|
|
||||||
name: string;
|
|
||||||
node: LucideIconNode;
|
|
||||||
} & ({ size: number } | { width: number; height: number });
|
|
||||||
|
|
||||||
export type Icons = { [key: string]: LucideIconData };
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`createElement > should match the snapshot 1`] = `
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewbox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8">
|
|
||||||
</path>
|
|
||||||
<path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`createIcons > should add custom attributes 1`] = `
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewbox="0 0 24 24"
|
|
||||||
fill="black"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
data-lucide="volume-2"
|
|
||||||
class="lucide lucide-volume-2 icon custom-class"
|
|
||||||
>
|
|
||||||
<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z">
|
|
||||||
</path>
|
|
||||||
<path d="M16 9a5 5 0 0 1 0 6">
|
|
||||||
</path>
|
|
||||||
<path d="M19.364 18.364a9 9 0 0 0 0-12.728">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`createIcons > should read elements from DOM and replace icon with alias name 1`] = `
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewbox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
data-lucide="grid"
|
|
||||||
class="lucide lucide-grid"
|
|
||||||
>
|
|
||||||
<rect width="18"
|
|
||||||
height="18"
|
|
||||||
x="3"
|
|
||||||
y="3"
|
|
||||||
rx="2"
|
|
||||||
>
|
|
||||||
</rect>
|
|
||||||
<path d="M3 9h18">
|
|
||||||
</path>
|
|
||||||
<path d="M3 15h18">
|
|
||||||
</path>
|
|
||||||
<path d="M9 3v18">
|
|
||||||
</path>
|
|
||||||
<path d="M15 3v18">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`createIcons > should read elements from DOM and replace it with icons 1`] = `
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewbox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
data-lucide="volume-2"
|
|
||||||
class="lucide lucide-volume-2"
|
|
||||||
>
|
|
||||||
<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z">
|
|
||||||
</path>
|
|
||||||
<path d="M16 9a5 5 0 0 1 0 6">
|
|
||||||
</path>
|
|
||||||
<path d="M19.364 18.364a9 9 0 0 0 0-12.728">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`combineClassNames > should returns a string of classNames 1`] = `"item item1 item2 item3 item4 item5 item6 item7 item8 item9"`;
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
import { createElement, House } from '../src/lucide-icons';
|
|
||||||
import { getOriginalSvg } from './helpers';
|
|
||||||
|
|
||||||
describe('createElement', () => {
|
|
||||||
it('should create SVG Element', () => {
|
|
||||||
const HomeSVG = createElement(House);
|
|
||||||
|
|
||||||
expect(HomeSVG.tagName).toBe('svg');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should match the snapshot', () => {
|
|
||||||
const HomeSVG = createElement(House);
|
|
||||||
|
|
||||||
expect(HomeSVG.outerHTML).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create SVG Element with attributes', () => {
|
|
||||||
const HomeSVG = createElement(House, { fill: 'red' });
|
|
||||||
|
|
||||||
expect(HomeSVG.getAttribute('fill')).toBe('red');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create SVG Element with class name', () => {
|
|
||||||
const HomeSVG = createElement(House, { class: 'icon' });
|
|
||||||
|
|
||||||
expect(HomeSVG.getAttribute('class')).toBe('icon');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create the correct svg element', () => {
|
|
||||||
const HomeSVG = createElement(House);
|
|
||||||
|
|
||||||
const svg = getOriginalSvg('house', undefined, false);
|
|
||||||
|
|
||||||
expect(HomeSVG.outerHTML).toBe(svg);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { parseSync, stringify } from 'svgson';
|
|
||||||
|
|
||||||
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
|
|
||||||
|
|
||||||
export const getOriginalSvg = (iconName: string, aliasName?: string, setAttrs = true) => {
|
|
||||||
const svgContent = fs.readFileSync(path.join(ICONS_DIR, `${iconName}.svg`), 'utf8');
|
|
||||||
const svgParsed = parseSync(svgContent);
|
|
||||||
|
|
||||||
if (setAttrs) {
|
|
||||||
svgParsed.attributes['data-lucide'] = aliasName ?? iconName;
|
|
||||||
svgParsed.attributes['class'] = `lucide lucide-${aliasName ?? iconName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringify(svgParsed, { selfClose: false });
|
|
||||||
};
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
import { createIcons, icons } from '../src/lucide-icons';
|
|
||||||
import { getOriginalSvg } from './helpers';
|
|
||||||
|
|
||||||
describe('createIcons', () => {
|
|
||||||
it('should read elements from DOM and replace it with icons', () => {
|
|
||||||
document.body.innerHTML = `<i data-lucide="volume-2"></i>`;
|
|
||||||
|
|
||||||
createIcons({ icons });
|
|
||||||
|
|
||||||
const svg = getOriginalSvg('volume-2');
|
|
||||||
|
|
||||||
expect(document.body.innerHTML).toBe(svg);
|
|
||||||
expect(document.body.innerHTML).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should customize the name attribute', () => {
|
|
||||||
document.body.innerHTML = `<i data-custom-name="volume-2"></i>`;
|
|
||||||
|
|
||||||
createIcons({
|
|
||||||
icons,
|
|
||||||
nameAttr: 'data-custom-name',
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasSvg = !!document.querySelector('svg');
|
|
||||||
|
|
||||||
expect(hasSvg).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add custom attributes', () => {
|
|
||||||
document.body.innerHTML = `<i data-lucide="volume-2" class="lucide"></i>`;
|
|
||||||
|
|
||||||
const attrs = {
|
|
||||||
class: 'lucide lucide-volume-2 icon custom-class',
|
|
||||||
fill: 'black',
|
|
||||||
};
|
|
||||||
|
|
||||||
createIcons({ icons, attrs });
|
|
||||||
|
|
||||||
const element = document.querySelector('svg') as SVGSVGElement;
|
|
||||||
const attributes = element.getAttributeNames();
|
|
||||||
|
|
||||||
const attributesAndValues = attributes.reduce(
|
|
||||||
(acc, item) => {
|
|
||||||
acc[item] = element.getAttribute(item);
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, string | null>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(document.body.innerHTML).toMatchSnapshot();
|
|
||||||
|
|
||||||
expect(attributesAndValues).toEqual(expect.objectContaining(attrs));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should inherit elements attributes', () => {
|
|
||||||
document.body.innerHTML = `<i data-lucide="sun" data-theme-switcher="light"></i>`;
|
|
||||||
|
|
||||||
const attrs = {
|
|
||||||
'data-theme-switcher': 'light',
|
|
||||||
};
|
|
||||||
|
|
||||||
createIcons({ icons });
|
|
||||||
|
|
||||||
const element = document.querySelector('svg') as SVGSVGElement;
|
|
||||||
const attributes = element.getAttributeNames();
|
|
||||||
|
|
||||||
const attributesAndValues = attributes.reduce(
|
|
||||||
(acc, item) => {
|
|
||||||
acc[item] = element.getAttribute(item);
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, string | null>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(attributesAndValues).toEqual(expect.objectContaining(attrs));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should read elements from DOM and replace icon with alias name', () => {
|
|
||||||
document.body.innerHTML = `<i data-lucide="grid"></i>`;
|
|
||||||
|
|
||||||
createIcons({ icons });
|
|
||||||
|
|
||||||
const svg = getOriginalSvg('grid-3x3', 'grid');
|
|
||||||
|
|
||||||
expect(document.body.innerHTML).toBe(svg);
|
|
||||||
expect(document.body.innerHTML).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
import { getAttrs, getClassNames, combineClassNames } from '../src/replaceElement';
|
|
||||||
|
|
||||||
describe('getAtts', () => {
|
|
||||||
it('should returns attrbrutes of an element', () => {
|
|
||||||
const element = {
|
|
||||||
attributes: [
|
|
||||||
{
|
|
||||||
name: 'class',
|
|
||||||
value: 'item1 item2 item4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'date-name',
|
|
||||||
value: 'volume',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const attrs = getAttrs(element as unknown as Element);
|
|
||||||
|
|
||||||
expect(attrs.class).toBe(element.attributes[0].value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getClassNames', () => {
|
|
||||||
it('should returns an array when giving class property of string', () => {
|
|
||||||
const elementAttrs = {
|
|
||||||
class: 'item1 item2 item3',
|
|
||||||
};
|
|
||||||
|
|
||||||
const attrs = getClassNames(elementAttrs);
|
|
||||||
expect(JSON.stringify(attrs)).toBe(JSON.stringify(['item1', 'item2', 'item3']));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should returns an array when givind class property with an array', () => {
|
|
||||||
const elementAttrs = {
|
|
||||||
class: ['item1', 'item2', 'item3'],
|
|
||||||
};
|
|
||||||
|
|
||||||
const attrs = getClassNames(elementAttrs);
|
|
||||||
expect(JSON.stringify(attrs)).toBe(JSON.stringify(['item1', 'item2', 'item3']));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('combineClassNames', () => {
|
|
||||||
it('should returns a string of classNames', () => {
|
|
||||||
const arrayOfClassnames: (string | Record<string, string[]>)[] = [
|
|
||||||
'item',
|
|
||||||
{
|
|
||||||
class: ['item1', 'item2', 'item3'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
class: ['item4', 'item5', 'item6'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
class: ['item7', 'item8', 'item9'],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const combinedClassNames = combineClassNames(arrayOfClassnames);
|
|
||||||
|
|
||||||
expect(combinedClassNames).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { expect } from 'vitest';
|
|
||||||
import '@testing-library/jest-dom/vitest';
|
|
||||||
import htmlSerializer from 'jest-serializer-html';
|
|
||||||
|
|
||||||
expect.addSnapshotSerializer(htmlSerializer);
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"strict": true,
|
|
||||||
"declaration": true,
|
|
||||||
"noEmitOnError": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"module": "ESNext",
|
|
||||||
"target": "ESNext",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"lib": ["esnext", "dom"],
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "./dist",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { defineConfig } from 'vitest/config';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
setupFiles: './tests/setupVitest.js',
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user