Compare commits

...

28 Commits

Author SHA1 Message Date
Karsa
36f84a74f6 adds construction icon (#959)
Co-authored-by: Karsa <karsa@karsa.org>
2023-02-28 17:25:08 +01:00
Karsa
1479a9dbd8 Fixes pre-commit git hook to ensure the optimisation of staged icons (#958)
* testing

* Fixes pre-commit hook

* Removing checkIcons from pre commit hook because it might result in false positives and negatives on an unclean local repository

* Added checkIcons Github action

---------

Co-authored-by: Karsa <karsa@karsa.org>
2023-02-28 17:24:17 +01:00
gubser
2485f6117a Added filter-x icon (#954)
* Added filter-off icon

* Renamed filter-off to filter-x

* Update icons/filter-x.svg

---------

Co-authored-by: Elio Gubser <3030498-gubser@users.noreply.gitlab.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2023-02-22 22:29:14 +01:00
Eric Fennis
0bbaaa8abd Fix site build (#955)
* Fix prebuild

* remove env file
2023-02-21 17:33:29 +01:00
Patchethium
a82af02687 Add split-square icon (#952)
* add split-square

* add horizontal icon

* rename vertical icon

* split path
2023-02-21 08:14:27 +01:00
Lucide Bot
a5be1b4101 📦 Bump lucide package versions to 0.115.0 2023-02-16 11:51:55 +00:00
Eric Fennis
639c0e8d85 Add creative commons icon (#945) 2023-02-16 12:45:45 +01:00
Eric Fennis
b863445492 Add remove formatting icon (#944) 2023-02-16 12:44:43 +01:00
Karsa
8c4a41035b Deprecate tags.json (#896)
* Deprecates tags.json and icons.json

* Removed tags.json dependency from Figma plugin

* Add JSON descriptor information to readme

* Restore packages/index.tsx

* Update packages/lucide-figma/src/api/fetchIcons.ts

Add multiple fetches to `Promise.all`

* Added caching to API endpoints

* Updates pnpm-lock.yaml

* Add tags to static

* Trigger site build

* Added prebuild script to generate api caches at build time

* Migrated NextCache function from arrow to regular to simplify markup

* test if contents are read from cache

* Add cache clear to prebuild

* removes debug object

---------

Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2023-02-16 08:26:29 +01:00
Lucide Bot
4a55ae4b91 📦 Bump lucide package versions to 0.114.0 2023-02-14 06:17:46 +00:00
Karsa
30f683a192 Fixes outline path joins in cat (#947) 2023-02-14 07:11:42 +01:00
Lucide Bot
25e0aaf33c 📦 Bump lucide package versions to 0.113.0 2023-02-12 22:09:06 +00:00
Leon Koole
3cd84c8adf Add grip and make all grip tags consistent (#941)
* Add grip and make all grip tags consistent

* Update icons/grip.svg

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Update icons/grip.json

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2023-02-12 23:03:16 +01:00
Ali
096ce92866 add title attr for "Available for" icons on home (#942) 2023-02-12 18:57:00 +01:00
Lucide Bot
57abe654b1 📦 Bump lucide package versions to 0.112.0 2023-02-07 08:40:49 +00:00
Jakob Guddas
852da97d46 Add fish-off icon (#923)
Co-authored-by: Kemie <kemie@monolinea.com>
2023-02-07 09:35:00 +01:00
Cd16d
ba86ca5ef0 add picture-in-picture icon (#930) 2023-02-07 09:31:44 +01:00
Petros Gasteratos
f2e325264f Add vote icon (#898) (#931)
* Add vote icon (#898)
* Update icons/vote.svg

Co-authored-by: Karsa <contact@karsa.org>
2023-02-07 09:27:06 +01:00
Lucide Bot
de366a1cb0 📦 Bump lucide package versions to 0.109.0 2023-02-02 07:46:11 +00:00
Karsa
5f5cec5b58 Fixes globe-2 icon (#933)
Co-authored-by: Karsa <karsa@karsa.org>
2023-02-02 08:40:52 +01:00
Wojciech Maj
2ccd5b7422 Add more tags to icons (#932) 2023-02-02 08:40:34 +01:00
Luca
e38137822d Svelte: Allow strings for size and strokeWidth (#913)
* Svelte: Allow strings for `size` and `strokeWidth`

* Svelte: Add missing types for building
2023-02-02 08:37:26 +01:00
Karsa
a9fef9f6b0 Fixes toggle-left & toggle-right (#584)
* Fixes toggle-left & toggle-right

* Update icons/toggle-left.svg

* Update icons/toggle-right.svg

* Update icons/toggle-left.svg

* Update icons/toggle-right.svg

---------

Co-authored-by: Karsa <karsa@karsa.org>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2023-01-29 20:16:15 +01:00
Lucide Bot
f646d84559 📦 Bump lucide package versions to 0.108.0 2023-01-29 10:44:23 +00:00
Kaladii
6f6ffa2478 add battery-warning icon (#927)
* add battery-warning icon

* add battery-warning to to tags.json
2023-01-29 11:38:20 +01:00
Lucide Bot
76326cb289 📦 Bump lucide package versions to 0.107.0 2023-01-26 08:57:04 +00:00
Eric Fennis
13a3f565b6 Add database-backup icon (#918) 2023-01-26 09:51:01 +01:00
Lucide Bot
b0f2e084d8 📦 Bump lucide package versions to 0.106.0 2023-01-26 08:49:45 +00:00
98 changed files with 1052 additions and 16204 deletions

View File

@@ -1,4 +0,0 @@
#!/bin/sh
pnpm run checkIcons
exit $?

View File

@@ -9,7 +9,7 @@ at https://github.com/lucide-icons/lucide/blob/main/docs/ICON_DESIGN_GUIDE.md be
and please fill everything below. -->
- **Name of the icon** : <!-- `icon` -->
- **Tags (alternative names for this icon)** (add them in tags.json) :
- **Tags (alternative names for this icon)** (add them in as a separate json file using the same icon name) :
- **What is the purpose of this icon?** : <!-- Shows that one can click it to... / Is used to denote or label... -->
- **100% scale preview** : <!-- upload an image -->
- **Have you considered alternative possibilities** for its naming or design? :
- **Have you considered alternative possibilities** for its naming or design? :

41
.github/actions/check-icons.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: "Check icons"
description: "Cross-checks icon and category references in JSON descriptors"
inputs:
name:
description: “Name of the package”
required: true
runs:
using: "composite"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: pnpm/action-setup@v2.0.1
name: Install pnpm
id: pnpm-install
with:
version: 7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-lucide-preact-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-lucide-preact-pnpm-store-
- name: Install dependencies
run: pnpm install --filter .
- name: Check icons and categories
run: pnpm checkIcons

2
.gitignore vendored
View File

@@ -18,3 +18,5 @@ packages/**/src/icons/*.ts
packages/**/src/icons/*.tsx
packages/**/src/aliases.ts
packages/**/LICENSE
categories.json
tags.json

5
.husky/pre-commit Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm lint-staged
pnpm checkIcons

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
"type": "string"
},
"icon": {
"$ref": "#/$defs/types/icon-reference"
"type": "string"
},
"weight": {
"type": "integer"

View File

@@ -80,3 +80,21 @@ For each icon these attributes are applied, corresponding to the above rules.
Code of paths can get really big.
To reduce file size we like to minify the code.
We recommend to use the [SVGOMG](https://jakearchibald.github.io/svgomg/) to minify paths.
### JSON metadata descriptor
Each icon added must also come with a matching JSON file listing tags and categories for the icon.
Please use the following template:
```json
{
"$schema": "../icon.schema.json",
"tags": [
"foo",
"bar"
],
"categories": [
"devices"
]
}
```

9682
icons.json

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +0,0 @@
{
"$id": "https://lucide.dev/icons.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
"https://json-schema.org/draft/2020-12/vocab/content": true
},
"title": "Lucide Icons schema",
"type": "object",
"properties": {
"icons": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/types/icon"
}
},
"categories": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/types/category"
}
}
},
"$defs": {
"types": {
"icon": {
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"categories": {
"type": "array",
"items": {
"$ref": "#/$defs/types/category-reference"
},
"uniqueItems": true
}
}
},
"category": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"icon": {
"$ref": "#/$defs/types/icon-reference"
},
"weight": {
"type": "integer"
}
},
"required": [
"title",
"icon"
]
},
"icon-reference": {
"type": "string",
"format": "uri-reference"
},
"category-reference": {
"type": "string",
"format": "uri-reference"
}
}
},
"description": "A JSON Schema for icons, tags & categories defined by Lucide Icons."
}

View File

@@ -3,10 +3,11 @@
"tags": [
"warning",
"alert",
"danger"
"danger",
"exclamation mark"
],
"categories": [
"notifications",
"shapes"
]
}
}

View File

@@ -3,10 +3,11 @@
"tags": [
"warning",
"alert",
"danger"
"danger",
"exclamation mark"
],
"categories": [
"notifications",
"shapes"
]
}
}

View File

@@ -3,10 +3,11 @@
"tags": [
"warning",
"alert",
"danger"
"danger",
"exclamation mark"
],
"categories": [
"notifications",
"shapes"
]
}
}

View File

@@ -2,10 +2,12 @@
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity"
"electricity",
"accumulator",
"charge"
],
"categories": [
"connectivity",
"devices"
]
}
}

View File

@@ -2,10 +2,12 @@
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity"
"electricity",
"accumulator",
"charge"
],
"categories": [
"connectivity",
"devices"
]
}
}

View File

@@ -2,10 +2,12 @@
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity"
"electricity",
"accumulator",
"charge"
],
"categories": [
"connectivity",
"devices"
]
}
}

View File

@@ -2,10 +2,12 @@
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity"
"electricity",
"accumulator",
"charge"
],
"categories": [
"connectivity",
"devices"
]
}
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity",
"accumulator",
"charge",
"exclamation mark"
],
"categories": [
"connectivity",
"devices"
]
}

17
icons/battery-warning.svg Normal file
View File

@@ -0,0 +1,17 @@
<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="M14 7h2a2 2 0 0 1 2 2v6c0 1 -1 2 -2 2h-2" />
<path d="M6 7h-2a2 2 0 0 0-2 2v6c0 1 1 2 2 2h2" />
<line x1="22" x2="22" y1="11" y2="13" />
<line x1="10" x2="10" y1="7" y2="13" />
<line x1="10" x2="10" y1="17" y2="17.01" />
</svg>

After

Width:  |  Height:  |  Size: 448 B

View File

@@ -2,10 +2,12 @@
"$schema": "../icon.schema.json",
"tags": [
"power",
"electricity"
"electricity",
"accumulator",
"charge"
],
"categories": [
"connectivity",
"devices"
]
}
}

View File

@@ -9,9 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14 5.256A8.148 8.148 0 0 0 12 5a9.04 9.04 0 0 0-2 .227M20.098 10c.572 1.068.902 2.24.902 3.444C21 17.89 16.97 21 12 21s-9-3-9-7.556c0-1.251.288-2.41.792-3.444" />
<path d="M3.75 10S2.11 3.58 3.5 3C4.89 2.42 8 3 9.781 5" />
<path d="M20.172 10.002s1.64-6.42.25-7c-1.39-.58-4.5 0-6.282 2" />
<path d="M12 5c.67 0 1.35.09 2 .26 1.78-2 5.03-2.84 6.42-2.26 1.4.58-.42 7-.42 7 .57 1.07 1 2.24 1 3.44C21 17.9 16.97 21 12 21s-9-3-9-7.56c0-1.25.5-2.4 1-3.44 0 0-1.89-6.42-.5-7 1.39-.58 4.72.23 6.5 2.23A9.04 9.04 0 0 1 12 5Z" />
<path d="M8 14v.5" />
<path d="M16 14v.5" />
<path d="M11.25 16.25h1.5L12 17l-.75-.75Z" />

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 537 B

View File

@@ -4,8 +4,7 @@
"arrow",
"expand",
"horizontal",
"unfold",
"horizonal"
"unfold"
],
"categories": [
"arrows"

View File

@@ -4,8 +4,7 @@
"arrow",
"collapse",
"fold",
"horizontal",
"horizonal"
"horizontal"
],
"categories": [
"arrows"

12
icons/construction.json Normal file
View File

@@ -0,0 +1,12 @@
{
"$schema": "../icon.schema.json",
"tags": [
"roadwork",
"maintenance",
"blockade",
"barricade"
],
"categories": [
"development"
]
}

20
icons/construction.svg Normal file
View File

@@ -0,0 +1,20 @@
<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="M21 6H3C2.44772 6 2 6.44772 2 7V13C2 13.5523 2.44772 14 3 14H21C21.5523 14 22 13.5523 22 13V7C22 6.44772 21.5523 6 21 6Z"/>
<path d="M17 14V21" />
<path d="M7 14V21" />
<path d="M17 3V6" />
<path d="M7 3V6" />
<path d="M2.5 6.5L10 14" />
<path d="M8 6L16 14" />
<path d="M14 6L21.5 13.5" />
</svg>

After

Width:  |  Height:  |  Size: 524 B

View File

@@ -1,7 +1,8 @@
{
"$schema": "../icon.schema.json",
"tags": [
"licence"
"licence",
"license"
],
"categories": []
}
}

View File

@@ -0,0 +1,8 @@
{
"$schema": "../icon.schema.json",
"tags": [
"licence",
"license"
],
"categories": []
}

View File

@@ -0,0 +1,15 @@
<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"
>
<circle cx="12" cy="12" r="10" />
<path d="M10 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1" />
<path d="M17 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1" />
</svg>

After

Width:  |  Height:  |  Size: 410 B

View File

@@ -0,0 +1,18 @@
{
"$schema": "../icon.schema.json",
"tags": [
"storage",
"memory",
"backup",
"timemachine",
"rotate",
"arrow",
"left"
],
"categories": [
"devices",
"arrows",
"design",
"photography"
]
}

18
icons/database-backup.svg Normal file
View File

@@ -0,0 +1,18 @@
<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"
>
<ellipse cx="12" cy="5" rx="9" ry="3" />
<path d="M3 12c0 1.18 2.03 2.2 5 2.7" />
<path d="M21 5v4.5" />
<path d="m12 16 1.27-1.35a4.75 4.75 0 1 1 .41 5.74" />
<path d="M12 12v4h4" />
<path d="M3 5v14c0 1.43 2.97 2.63 7 2.93" />
</svg>

After

Width:  |  Height:  |  Size: 449 B

View File

@@ -5,10 +5,11 @@
"warning",
"alert",
"danger",
"protected"
"protected",
"exclamation mark"
],
"categories": [
"files",
"notifications"
]
}
}

10
icons/filter-x.json Normal file
View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"funnel",
"hopper"
],
"categories": [
"layout"
]
}

15
icons/filter-x.svg Normal file
View File

@@ -0,0 +1,15 @@
<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="m13.013 3h-11.013l8 9.46v6.54l4 2v-8.54l0.89973-1.0554" />
<path d="m22 3-5 5" />
<path d="m17 3 5 5" />
</svg>

After

Width:  |  Height:  |  Size: 328 B

22
icons/fish-off.json Normal file
View File

@@ -0,0 +1,22 @@
{
"$schema": "../icon.schema.json",
"tags": [
"food",
"dish",
"restaurant",
"course",
"meal",
"seafood",
"animal",
"pet",
"sea",
"marine",
"allergy",
"intolerance",
"diet"
],
"categories": [
"food-beverage",
"animals"
]
}

1
icons/fish-off.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M18 12.47v.03M18 12v.47M17.525 17.526A6.744 6.744 0 0 1 15 18c-3.56 0-7.56-2.53-8.5-6 .348-1.28 1.114-2.433 2.121-3.38M12.065 6.532A8.802 8.802 0 0 1 15 6c3.56 0 6.06 2.54 7 6-.309 1.14-.786 2.177-1.413 3.058"/><path d="M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33M14.48 8.958A9.77 9.77 0 0 1 16 6.07M16 17.93a9.77 9.77 0 0 1-1.728-3.618"/><path d="m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98M8.53 3h5.27a2 2 0 0 1 1.98 1.67l.23 1.4M2 2l20 20"/></svg>

After

Width:  |  Height:  |  Size: 701 B

View File

@@ -9,8 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15 21v-4a2 2 0 0 1 2-2h4" />
<path d="M7 4v2a3 3 0 0 0 3 2h0a2 2 0 0 1 2 2 2 2 0 0 0 4 0 2 2 0 0 1 2-2h3" />
<path d="M3 11h2a2 2 0 0 1 2 2v1a2 2 0 0 0 2 2 2 2 0 0 1 2 2v4" />
<path d="M21.54 15H17a2 2 0 0 0-2 2v4.54" />
<path d="M7 3.34V5a3 3 0 0 0 3 3v0a2 2 0 0 1 2 2v0c0 1.1.9 2 2 2v0a2 2 0 0 0 2-2v0c0-1.1.9-2 2-2h3.17" />
<path d="M11 21.95V18a2 2 0 0 0-2-2v0a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05" />
<circle cx="12" cy="12" r="10" />
</svg>

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 479 B

View File

@@ -3,7 +3,9 @@
"tags": [
"grab",
"dots",
"handle"
"handle",
"move",
"drag"
],
"categories": [
"layout"

13
icons/grip.json Normal file
View File

@@ -0,0 +1,13 @@
{
"$schema": "../icon.schema.json",
"tags": [
"grab",
"dots",
"handle",
"move",
"drag"
],
"categories": [
"layout"
]
}

21
icons/grip.svg Normal file
View File

@@ -0,0 +1,21 @@
<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"
>
<circle cx="12" cy="5" r="1" />
<circle cx="19" cy="5" r="1" />
<circle cx="5" cy="5" r="1" />
<circle cx="12" cy="12" r="1" />
<circle cx="19" cy="12" r="1" />
<circle cx="5" cy="12" r="1" />
<circle cx="12" cy="19" r="1" />
<circle cx="19" cy="19" r="1" />
<circle cx="5" cy="19" r="1" />
</svg>

After

Width:  |  Height:  |  Size: 517 B

View File

@@ -4,9 +4,10 @@
"email",
"message",
"letter",
"delivery error"
"delivery error",
"exclamation mark"
],
"categories": [
"mail"
]
}
}

View File

@@ -10,6 +10,6 @@
stroke-linejoin="round"
>
<path d="M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6Z" />
<path d="M12 13v9" />
<path d="M12 2v4" />
<path d="M12 13v8" />
<path d="M12 3v3" />
</svg>

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1,16 @@
{
"$schema": "../icon.schema.json",
"tags": [
"display",
"play",
"video",
"pop out",
"always on top",
"window",
"inset",
"multitask"
],
"categories": [
"multimedia"
]
}

View File

@@ -0,0 +1,14 @@
<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="M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4" />
<rect x="12" y="13" width="10" height="7" rx="2" />
</svg>

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -0,0 +1,16 @@
{
"$schema": "../icon.schema.json",
"tags": [
"display",
"play",
"video",
"pop out",
"always on top",
"window",
"inset",
"multitask"
],
"categories": [
"multimedia"
]
}

View File

@@ -0,0 +1,14 @@
<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="M8 4.5v5H3m-1-6 6 6m13 0v-3c0-1.16-.84-2-2-2h-7m-9 9v2c0 1.05.95 2 2 2h3"/>
<rect width="10" height="7" x="12" y="13.5" ry="2"/>
</svg>

After

Width:  |  Height:  |  Size: 350 B

View File

@@ -1,9 +1,12 @@
{
"$schema": "../icon.schema.json",
"tags": [
"device"
"on",
"off",
"device",
"switch"
],
"categories": [
"connectivity"
]
}
}

View File

@@ -3,9 +3,10 @@
"tags": [
"on",
"off",
"device"
"device",
"switch"
],
"categories": [
"connectivity"
]
}
}

View File

@@ -0,0 +1,17 @@
{
"$schema": "../icon.schema.json",
"tags": [
"text",
"font",
"typography",
"format",
"x",
"remove",
"delete",
"times",
"clear"
],
"categories": [
"text"
]
}

View File

@@ -0,0 +1,17 @@
<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="M4 7V4h16v3" />
<path d="M5 20h6" />
<path d="M13 4 8 20" />
<path d="m15 15 5 5" />
<path d="m20 15-5 5" />
</svg>

After

Width:  |  Height:  |  Size: 336 B

View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"split",
"divide"
],
"categories": [
"layout"
]
}

View File

@@ -0,0 +1,14 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
>
<path d="M 8,19 H 5 C 4,19 3,18 3,17 V 7 C 3,6 4,5 5,5 h 3" />
<path d="m 16,5 h 3 c 1,0 2,1 2,2 v 10 c 0,1 -1,2 -2,2 h -3" />
<line x1="12" y1="4" x2="12" y2="20" />
</svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@@ -0,0 +1,10 @@
{
"$schema": "../icon.schema.json",
"tags": [
"split",
"divide"
],
"categories": [
"layout"
]
}

View File

@@ -0,0 +1,15 @@
<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="M 5,8 V 5 C 5,4 6,3 7,3 h 10 c 1,0 2,1 2,2 v 3" />
<path d="m 19,16 v 3 c 0,1 -1,2 -2,2 H 7 C 6,21 5,20 5,19 v -3" />
<line x1="4" y1="12" x2="20" y2="12" />
</svg>

After

Width:  |  Height:  |  Size: 381 B

9
icons/subtitles.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "../icon.schema.json",
"tags": [
"captions",
"closed captions",
"accessibility"
],
"categories": []
}

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="1" y="5" width="22" height="14" rx="7" ry="7" />
<circle cx="8" cy="12" r="3" />
<rect x="2" y="6" width="20" height="12" rx="6" ry="6" />
<circle cx="8" cy="12" r="2" />
</svg>

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 302 B

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="1" y="5" width="22" height="14" rx="7" ry="7" />
<circle cx="16" cy="12" r="3" />
<rect x="2" y="6" width="20" height="12" rx="6" ry="6" />
<circle cx="16" cy="12" r="2" />
</svg>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 303 B

13
icons/vote.json Normal file
View File

@@ -0,0 +1,13 @@
{
"$schema": "../icon.schema.json",
"tags": [
"vote",
"poll",
"ballot",
"political",
"social"
],
"categories": [
"social"
]
}

15
icons/vote.svg Executable file
View File

@@ -0,0 +1,15 @@
<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="m9 12 2 2 4-4" />
<path d="M5 7c0-1.1.9-2 2-2h10a2 2 0 0 1 2 2v12H5V7Z" />
<path d="M22 19H2" />
</svg>

After

Width:  |  Height:  |  Size: 320 B

View File

@@ -16,16 +16,16 @@
"build:outline-icons": "pnpm --filter outline-svg start",
"generate:supersprite": "node ./scripts/generateSuperSVG.mjs",
"optimize": "node ./scripts/optimizeSvgs.mjs",
"addtags": "node ./scripts/addMissingKeysToTags.mjs",
"addjsons": "node scripts/addMissingIconJsonFiles.mjs",
"checkIcons": "node scripts/checkIconsAndCategories.mjs --presets @babel/env",
"tags2icons": "node scripts/migrateTagsToIcons.mjs --presets @babel/env",
"icons2tags": "node scripts/migrateIconsToTags.mjs --presets @babel/env",
"icons2categories": "node scripts/migrateIconsToCategories.mjs --presets @babel/env",
"categories2icons": "node scripts/migrateCategoriesToIcons.mjs --presets @babel/env",
"icons2files": "node scripts/migrateIconsToJsonFiles.mjs --presets @babel/env",
"generate:changelog": "node ./scripts/generateChangelog.mjs",
"postinstall": "husky install",
"lint": "eslint --ext .ts,.js,.mjs ./{packages/lucide,scripts}"
"lint": "eslint --ext .ts,.js,.mjs ./{packages/lucide,scripts}",
"prepare": "husky install"
},
"devDependencies": {
"eslint": "^8.26.0",
@@ -41,11 +41,6 @@
"svgo": "^3.0.0",
"svgson": "^5.2.1"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"icons/*.svg": "node ./scripts/optimizeStagedSvgs.mjs"
},

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-angular",
"description": "A Lucide icon library package for Angular applications",
"version": "0.105.0",
"version": "0.115.0",
"author": "SMAH1",
"license": "ISC",
"homepage": "https://lucide.dev",

View File

@@ -23,8 +23,10 @@ export const fetchIcons = async (cachedIcons? : LucideIcons): Promise<LucideIcon
return cachedIcons
}
const iconNodesResponse = await fetch(`https://unpkg.com/lucide-static@${packageJson.version}/icon-nodes.json`)
const tagsResponse = await fetch('https://unpkg.com/lucide-static@latest/tags.json')
const [iconNodesResponse, tagsResponse] = await Promise.all([
fetch('https://lucide.dev/api/icon-nodes'),
fetch('https://lucide.dev/api/tags')
])
const iconNodes = await iconNodesResponse.json();
const tags = await tagsResponse.json();

View File

@@ -1,6 +1,6 @@
name: lucide_icons
description: A Lucide icon library package for Flutter applications. Fork of Feather Icons, open for anyone to contribute icons.
version: 0.105.0
version: 0.115.0
homepage: https://lucide.dev
repository: https://github.com/lucide-icons/lucide

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-preact",
"description": "A Lucide icon library package for Preact applications",
"version": "0.105.0",
"version": "0.115.0",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-react-native",
"description": "A Lucide icon library package for React Native applications",
"version": "0.105.1",
"version": "0.115.0",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-react",
"description": "A Lucide icon library package for React applications",
"version": "0.105.0",
"version": "0.115.0",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -12,11 +12,11 @@
"main": "lib/index.js",
"scripts": {
"copy:icons": "cp -r ../../icons icons",
"copy:tags": "cp ../../tags.json tags.json",
"copy:license": "cp ../../LICENSE ./LICENSE",
"build": "pnpm clean && pnpm copy:license && pnpm copy:icons && pnpm copy:tags && pnpm build:lib",
"build:tags": "node ../../scripts/migrateIconsToTags.mjs",
"build": "pnpm clean && pnpm copy:license && pnpm copy:icons && pnpm build:lib && pnpm build:tags",
"build:lib": "node ./scripts/buildLib.mjs",
"clean": "rm -rf lib && rm -rf build && rm -rf icons && rm -f sprite.svg && rm -f tags.json",
"clean": "rm -rf lib && rm -rf build && rm -rf icons && rm -f sprite.svg",
"version": "pnpm version --git-tag-version=false"
},
"devDependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "lucide-svelte",
"description": "A Lucide icon library package for Svelte applications",
"version": "0.105.0",
"version": "0.115.0",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",

View File

@@ -31,8 +31,8 @@ import { SvelteComponentTyped } from "svelte";
interface IconProps extends Partial<svelte.JSX.SVGProps<SVGSVGElement>> {
color?: string
size?: number,
strokeWidth?: number,
size?: number|string,
strokeWidth?: number|string,
class?: string
}

View File

@@ -4,8 +4,8 @@
export let name: string
export let color = 'currentColor'
export let size = 24
export let strokeWidth = 2
export let size: number|string = 24
export let strokeWidth: number|string = 2
export let iconNode: IconNode
</script>

View File

@@ -1,6 +1,6 @@
{
"name": "lucide-vue-next",
"version": "0.105.0",
"version": "0.115.0",
"author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 3 applications",
"license": "ISC",

View File

@@ -1,6 +1,6 @@
{
"name": "lucide-vue",
"version": "0.105.0",
"version": "0.115.0",
"author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 2 applications",
"license": "ISC",

View File

@@ -1,7 +1,7 @@
{
"name": "lucide",
"description": "A Lucide icon library package for web and javascript applications.",
"version": "0.105.0",
"version": "0.115.0",
"license": "ISC",
"homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues",

281
pnpm-lock.yaml generated
View File

@@ -375,6 +375,7 @@ importers:
'@next/eslint-plugin-next': ^12.2.5
'@next/mdx': ^11.0.0
'@svgr/webpack': ^6.3.1
'@swc/core': ^1.3.35
'@testing-library/dom': ^7.31.2
'@testing-library/jest-dom': ^5.16.5
'@testing-library/react': ^11.2.7
@@ -400,6 +401,7 @@ importers:
lucide-react: ^0.94.0
next: '12'
next-mdx-remote: ^3.0.2
node-fetch: '2'
prettier: ^2.3.2
prism-react-renderer: ^1.2.1
react: 17.0.2
@@ -407,6 +409,9 @@ importers:
react-dom: 17.0.2
react-svg-loader: ^3.0.3
react-test-renderer: 17.0.2
svgson: ^5.2.1
ts-node: ~10.9.1
tslib: ^2.4.0
typescript: ^4.3.5
dependencies:
'@chakra-ui/react': 1.8.8_vt5jn3lkv6hocyebmjm7gusm6e
@@ -431,8 +436,10 @@ importers:
react-color: 2.19.3_react@17.0.2
react-dom: 17.0.2_react@17.0.2
react-svg-loader: 3.0.3
svgson: 5.2.1
devDependencies:
'@next/eslint-plugin-next': 12.2.5
'@swc/core': 1.3.35
'@testing-library/dom': 7.31.2
'@testing-library/jest-dom': 5.16.5
'@testing-library/react': 11.2.7_sfoxds7t5ydpegc3knd667wn6m
@@ -447,9 +454,12 @@ importers:
babel-loader: 8.2.5_webpack@5.74.0
eslint: 8.22.0
eslint-config-prettier: 8.5.0_eslint@8.22.0
jest: 26.6.3
jest: 26.6.3_ts-node@10.9.1
node-fetch: 2.6.7
prettier: 2.7.1
react-test-renderer: 17.0.2_react@17.0.2
ts-node: 10.9.1_iuagarv54md6u2z4nbxsm6bl6u
tslib: 2.4.0
typescript: 4.8.4
tools/build-icons:
@@ -7487,7 +7497,7 @@ packages:
slash: 3.0.0
dev: true
/@jest/core/26.6.3:
/@jest/core/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==}
engines: {node: '>= 10.14.2'}
dependencies:
@@ -7502,14 +7512,14 @@ packages:
exit: 0.1.2
graceful-fs: 4.2.10
jest-changed-files: 26.6.2
jest-config: 26.6.3
jest-config: 26.6.3_ts-node@10.9.1
jest-haste-map: 26.6.2
jest-message-util: 26.6.2
jest-regex-util: 26.0.0
jest-resolve: 26.6.2
jest-resolve-dependencies: 26.6.3
jest-runner: 26.6.3
jest-runtime: 26.6.3
jest-runner: 26.6.3_ts-node@10.9.1
jest-runtime: 26.6.3_ts-node@10.9.1
jest-snapshot: 26.6.2
jest-util: 26.6.2
jest-validate: 26.6.2
@@ -7632,15 +7642,15 @@ packages:
collect-v8-coverage: 1.0.1
dev: true
/@jest/test-sequencer/26.6.3:
/@jest/test-sequencer/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==}
engines: {node: '>= 10.14.2'}
dependencies:
'@jest/test-result': 26.6.2
graceful-fs: 4.2.10
jest-haste-map: 26.6.2
jest-runner: 26.6.3
jest-runtime: 26.6.3
jest-runner: 26.6.3_ts-node@10.9.1
jest-runtime: 26.6.3_ts-node@10.9.1
transitivePeerDependencies:
- bufferutil
- canvas
@@ -9106,6 +9116,113 @@ packages:
- supports-color
dev: false
/@swc/core-darwin-arm64/1.3.35:
resolution: {integrity: sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@swc/core-darwin-x64/1.3.35:
resolution: {integrity: sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-arm-gnueabihf/1.3.35:
resolution: {integrity: sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-arm64-gnu/1.3.35:
resolution: {integrity: sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-arm64-musl/1.3.35:
resolution: {integrity: sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-x64-gnu/1.3.35:
resolution: {integrity: sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-x64-musl/1.3.35:
resolution: {integrity: sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-win32-arm64-msvc/1.3.35:
resolution: {integrity: sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@swc/core-win32-ia32-msvc/1.3.35:
resolution: {integrity: sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@swc/core-win32-x64-msvc/1.3.35:
resolution: {integrity: sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@swc/core/1.3.35:
resolution: {integrity: sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w==}
engines: {node: '>=10'}
requiresBuild: true
optionalDependencies:
'@swc/core-darwin-arm64': 1.3.35
'@swc/core-darwin-x64': 1.3.35
'@swc/core-linux-arm-gnueabihf': 1.3.35
'@swc/core-linux-arm64-gnu': 1.3.35
'@swc/core-linux-arm64-musl': 1.3.35
'@swc/core-linux-x64-gnu': 1.3.35
'@swc/core-linux-x64-musl': 1.3.35
'@swc/core-win32-arm64-msvc': 1.3.35
'@swc/core-win32-ia32-msvc': 1.3.35
'@swc/core-win32-x64-msvc': 1.3.35
dev: true
/@swc/helpers/0.4.3:
resolution: {integrity: sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==}
dependencies:
@@ -10147,14 +10264,6 @@ packages:
acorn: 8.8.1
dev: true
/acorn-jsx/5.3.2_acorn@8.8.0:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
acorn: 8.8.0
dev: true
/acorn-jsx/5.3.2_acorn@8.8.1:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -10702,7 +10811,7 @@ packages:
loader-utils: 2.0.2
make-dir: 3.1.0
schema-utils: 2.7.1
webpack: 5.74.0
webpack: 5.74.0_@swc+core@1.3.35
dev: true
/babel-loader/8.2.5_xc6oct4hcywdrbo4ned6ytbybm:
@@ -14113,8 +14222,8 @@ packages:
resolution: {integrity: sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.8.0
acorn-jsx: 5.3.2_acorn@8.8.0
acorn: 8.8.1
acorn-jsx: 5.3.2_acorn@8.8.1
eslint-visitor-keys: 3.3.0
dev: true
@@ -16097,12 +16206,12 @@ packages:
throat: 5.0.0
dev: true
/jest-cli/26.6.3:
/jest-cli/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==}
engines: {node: '>= 10.14.2'}
hasBin: true
dependencies:
'@jest/core': 26.6.3
'@jest/core': 26.6.3_ts-node@10.9.1
'@jest/test-result': 26.6.2
'@jest/types': 26.6.2
chalk: 4.1.2
@@ -16110,7 +16219,7 @@ packages:
graceful-fs: 4.2.10
import-local: 3.1.0
is-ci: 2.0.0
jest-config: 26.6.3
jest-config: 26.6.3_ts-node@10.9.1
jest-util: 26.6.2
jest-validate: 26.6.2
prompts: 2.4.2
@@ -16123,7 +16232,7 @@ packages:
- utf-8-validate
dev: true
/jest-config/26.6.3:
/jest-config/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==}
engines: {node: '>= 10.14.2'}
peerDependencies:
@@ -16133,7 +16242,7 @@ packages:
optional: true
dependencies:
'@babel/core': 7.20.2
'@jest/test-sequencer': 26.6.3
'@jest/test-sequencer': 26.6.3_ts-node@10.9.1
'@jest/types': 26.6.2
babel-jest: 26.6.3_@babel+core@7.20.2
chalk: 4.1.2
@@ -16143,13 +16252,14 @@ packages:
jest-environment-jsdom: 26.6.2
jest-environment-node: 26.6.2
jest-get-type: 26.3.0
jest-jasmine2: 26.6.3
jest-jasmine2: 26.6.3_ts-node@10.9.1
jest-regex-util: 26.0.0
jest-resolve: 26.6.2
jest-util: 26.6.2
jest-validate: 26.6.2
micromatch: 4.0.5
pretty-format: 26.6.2
ts-node: 10.9.1_iuagarv54md6u2z4nbxsm6bl6u
transitivePeerDependencies:
- bufferutil
- canvas
@@ -16278,7 +16388,7 @@ packages:
fsevents: 2.3.2
dev: true
/jest-jasmine2/26.6.3:
/jest-jasmine2/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==}
engines: {node: '>= 10.14.2'}
dependencies:
@@ -16295,7 +16405,7 @@ packages:
jest-each: 26.6.2
jest-matcher-utils: 26.6.2
jest-message-util: 26.6.2
jest-runtime: 26.6.3
jest-runtime: 26.6.3_ts-node@10.9.1
jest-snapshot: 26.6.2
jest-util: 26.6.2
pretty-format: 26.6.2
@@ -16421,7 +16531,7 @@ packages:
slash: 3.0.0
dev: true
/jest-runner/26.6.3:
/jest-runner/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==}
engines: {node: '>= 10.14.2'}
dependencies:
@@ -16434,13 +16544,13 @@ packages:
emittery: 0.7.2
exit: 0.1.2
graceful-fs: 4.2.10
jest-config: 26.6.3
jest-config: 26.6.3_ts-node@10.9.1
jest-docblock: 26.0.0
jest-haste-map: 26.6.2
jest-leak-detector: 26.6.2
jest-message-util: 26.6.2
jest-resolve: 26.6.2
jest-runtime: 26.6.3
jest-runtime: 26.6.3_ts-node@10.9.1
jest-util: 26.6.2
jest-worker: 26.6.2
source-map-support: 0.5.21
@@ -16453,7 +16563,7 @@ packages:
- utf-8-validate
dev: true
/jest-runtime/26.6.3:
/jest-runtime/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==}
engines: {node: '>= 10.14.2'}
hasBin: true
@@ -16473,7 +16583,7 @@ packages:
exit: 0.1.2
glob: 7.2.3
graceful-fs: 4.2.10
jest-config: 26.6.3
jest-config: 26.6.3_ts-node@10.9.1
jest-haste-map: 26.6.2
jest-message-util: 26.6.2
jest-mock: 26.6.2
@@ -16618,14 +16728,14 @@ packages:
supports-color: 8.1.1
dev: true
/jest/26.6.3:
/jest/26.6.3_ts-node@10.9.1:
resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==}
engines: {node: '>= 10.14.2'}
hasBin: true
dependencies:
'@jest/core': 26.6.3
'@jest/core': 26.6.3_ts-node@10.9.1
import-local: 3.1.0
jest-cli: 26.6.3
jest-cli: 26.6.3_ts-node@10.9.1
transitivePeerDependencies:
- bufferutil
- canvas
@@ -22223,6 +22333,31 @@ packages:
supports-hyperlinks: 2.2.0
dev: true
/terser-webpack-plugin/5.3.5_oogp7xv4rppobi5ktio24rc7mq:
resolution: {integrity: sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==}
engines: {node: '>= 10.13.0'}
peerDependencies:
'@swc/core': '*'
esbuild: '*'
uglify-js: '*'
webpack: ^5.1.0
peerDependenciesMeta:
'@swc/core':
optional: true
esbuild:
optional: true
uglify-js:
optional: true
dependencies:
'@jridgewell/trace-mapping': 0.3.15
'@swc/core': 1.3.35
jest-worker: 27.5.1
schema-utils: 3.1.1
serialize-javascript: 6.0.0
terser: 5.16.1
webpack: 5.74.0_@swc+core@1.3.35
dev: true
/terser-webpack-plugin/5.3.5_webpack@5.74.0:
resolution: {integrity: sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==}
engines: {node: '>= 10.13.0'}
@@ -22243,7 +22378,7 @@ packages:
jest-worker: 27.5.1
schema-utils: 3.1.1
serialize-javascript: 6.0.0
terser: 5.14.2
terser: 5.16.1
webpack: 5.74.0
dev: true
@@ -22484,7 +22619,39 @@ packages:
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
'@types/node': 18.11.4
acorn: 8.8.0
acorn: 8.8.1
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 4.8.4
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
/ts-node/10.9.1_iuagarv54md6u2z4nbxsm6bl6u:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@swc/core': 1.3.35
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
'@types/node': 14.18.25
acorn: 8.8.1
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
@@ -23620,6 +23787,46 @@ packages:
- uglify-js
dev: true
/webpack/5.74.0_@swc+core@1.3.35:
resolution: {integrity: sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==}
engines: {node: '>=10.13.0'}
hasBin: true
peerDependencies:
webpack-cli: '*'
peerDependenciesMeta:
webpack-cli:
optional: true
dependencies:
'@types/eslint-scope': 3.7.4
'@types/estree': 0.0.51
'@webassemblyjs/ast': 1.11.1
'@webassemblyjs/wasm-edit': 1.11.1
'@webassemblyjs/wasm-parser': 1.11.1
acorn: 8.8.1
acorn-import-assertions: 1.8.0_acorn@8.8.1
browserslist: 4.21.4
chrome-trace-event: 1.0.3
enhanced-resolve: 5.10.0
es-module-lexer: 0.9.3
eslint-scope: 5.1.1
events: 3.3.0
glob-to-regexp: 0.4.1
graceful-fs: 4.2.10
json-parse-even-better-errors: 2.3.1
loader-runner: 4.3.0
mime-types: 2.1.35
neo-async: 2.6.2
schema-utils: 3.1.1
tapable: 2.2.1
terser-webpack-plugin: 5.3.5_oogp7xv4rppobi5ktio24rc7mq
watchpack: 2.4.0
webpack-sources: 3.2.3
transitivePeerDependencies:
- '@swc/core'
- esbuild
- uglify-js
dev: true
/websocket-driver/0.7.4:
resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
engines: {node: '>=0.8.0'}

View File

@@ -0,0 +1,21 @@
import path from 'path';
import {getCurrentDirPath, readAllMetadata, readSvgDirectory, writeFile} from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url);
const ICONS_DIR = path.resolve(currentDir, '../icons');
const icons = readAllMetadata(ICONS_DIR);
const svgFiles = readSvgDirectory(ICONS_DIR);
const iconNames = svgFiles.map((icon) => icon.split('.')[0]);
iconNames.forEach(iconName => {
if (typeof icons[iconName] === 'undefined') {
const iconContent = JSON.stringify({
"$schema": "../icon.schema.json",
"tags": [],
"categories": []
}, null, 2);
writeFile(iconContent, `${iconName}.json`, path.resolve(currentDir, '..'));
}
});

View File

@@ -1,42 +0,0 @@
import path from 'path';
import tags from '../tags.json' assert { type: 'json' };
import { readSvgDirectory, writeFile, getCurrentDirPath } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url);
const ICONS_DIR = path.resolve(currentDir, '../icons');
console.log(`Read all tags`);
const svgFiles = readSvgDirectory(ICONS_DIR);
const iconNames = svgFiles.map((icon) => icon.split('.')[0]);
const iconTags = iconNames
.map((iconName) => ({
name: iconName,
tags: tags[iconName] || [],
}))
.sort((a, b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
const newTags = iconTags.reduce((acc, { name, tags }) => {
acc[name] = tags;
return acc;
}, {});
const tagsContent = JSON.stringify(newTags, null, 2);
writeFile(tagsContent, 'tags.json', path.resolve(currentDir, '..'));

View File

@@ -1,50 +1,52 @@
import path from 'path';
import icons from '../icons.json' assert { type: 'json' };
import { readSvgDirectory, getCurrentDirPath } from './helpers.mjs';
import { readSvgDirectory, getCurrentDirPath, readAllMetadata } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
const ICONS_DIR = path.resolve(currentDir, '../icons');
const icons = readAllMetadata(ICONS_DIR);
const CATEGORIES_DIR = path.resolve(currentDir, '../categories');
const categories = readAllMetadata(CATEGORIES_DIR);
console.log(`Read all icons`);
console.log('Reading all icons')
const svgFiles = readSvgDirectory(ICONS_DIR);
const iconNames = svgFiles.map(icon => icon.split('.')[0]);
let error = false;
iconNames.forEach(iconName => {
if (typeof icons.icons[iconName] === 'undefined') {
console.error(`'${iconName}.svg' is not present in 'icons.json'.`);
if (typeof icons[iconName] === 'undefined') {
console.error(`'${iconName}.svg' does not have a matching JSON file.`);
error = true;
}
});
Object.keys(icons.icons).forEach(iconName => {
const icon = icons.icons[iconName];
Object.keys(icons).forEach(iconName => {
const icon = icons[iconName];
if (iconNames.indexOf(iconName) === -1) {
console.error(`'${iconName}.svg' does not exist.`);
error = true;
}
icon.categories.forEach(categoryName => {
if (typeof icons.categories[categoryName] === 'undefined') {
if (typeof categories[categoryName] === 'undefined') {
console.error(`Icon '${iconName}' refers to the non-existing category '${categoryName}'.`);
error = true;
}
});
});
Object.keys(icons.categories).forEach(categoryName => {
const category = icons.categories[categoryName];
Object.keys(categories).forEach(categoryName => {
const category = categories[categoryName];
if (!category.icon) {
console.error(`Category '${categoryName}' does not use an icon '${category.icon}'.`);
error = true;
} else if (typeof icons.icons[category.icon] === 'undefined') {
} else if (typeof icons[category.icon] === 'undefined') {
console.error(`Category '${categoryName}' uses the non-existing icon '${category.icon}'.`);
error = true;
}
});
if (error) {
throw new Error('At least one error in icons.json prevents from committing changes.');
console.error('At least one error in icon JSONs prevents from committing changes.');
process.exit(1);
}

View File

@@ -70,6 +70,30 @@ export const appendFile = (content, fileName, outputDirectory) =>
export const writeFile = (content, fileName, outputDirectory) =>
fs.writeFileSync(path.join(outputDirectory, fileName), content, 'utf-8');
/**
* Reads metadata from the icons/categories directories
*
* @param {string} directory
* @returns {object} A map of icon or category metadata
*/
export const readAllMetadata = (directory) =>
fs.readdirSync(directory).filter((file) => path.extname(file) === '.json').reduce(
(acc, fileName, i) => {
acc[path.basename(fileName, '.json')] = readMetadata(fileName, directory);
return acc;
}, {}
);
/**
* Reads metadata for an icon or category
*
* @param {string} fileName
* @param {string} directory
* @returns {object} The metadata for the icon or category
*/
export const readMetadata = (fileName, directory) =>
JSON.parse(fs.readFileSync(path.join(directory, fileName), 'utf-8'));
/**
* reads the icon directory
*

View File

@@ -1,16 +1,19 @@
import path from 'path';
import icons from '../icons.json' assert { type: 'json' };
import categories from '../categories.json' assert { type: 'json' };
import { mergeArrays, writeFile, getCurrentDirPath } from './helpers.mjs';
import { mergeArrays, writeFile, readAllMetadata, getCurrentDirPath } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
const ICONS_DIR = path.resolve(currentDir, '../icons');
const icons = readAllMetadata(ICONS_DIR);
Object.keys(categories).forEach(categoryName => {
categories[categoryName].forEach(iconName => {
mergeArrays(icons.icons[iconName].categories, [categoryName]);
icons[iconName].categories = mergeArrays(icons[iconName].categories, [categoryName]);
});
});
const iconsContent = JSON.stringify(icons, null, 2);
Object.keys(icons).forEach(iconName => {
const iconContent = JSON.stringify(icons[iconName], null, 2);
writeFile(iconContent, `${iconName}.json`, path.resolve(currentDir, '../icons'));
})
writeFile(iconsContent, 'icons.json', path.resolve(currentDir, '..'));

View File

@@ -1,12 +1,13 @@
import path from 'path';
import icons from '../icons.json' assert { type: 'json' };
import { writeFile, getCurrentDirPath } from './helpers.mjs';
import { writeFile, getCurrentDirPath, readAllMetadata } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
const ICONS_DIR = path.resolve(currentDir, '../icons');
const icons = readAllMetadata(ICONS_DIR);
const newCategories = {};
Object.keys(icons.icons).forEach(iconName => {
icons.icons[iconName].categories.forEach(categoryName => {
Object.keys(icons).forEach(iconName => {
icons[iconName].categories.forEach(categoryName => {
newCategories[categoryName] = newCategories[categoryName] || [];
newCategories[categoryName].push(iconName);
});

View File

@@ -1,23 +0,0 @@
import path from 'path';
import icons from '../icons.json' assert { type: 'json' };
import { writeFile, getCurrentDirPath } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
Object.keys(icons.icons).forEach(iconName => {
const icon = {
"$schema": "../icon.schema.json",
...icons.icons[iconName]
};
const iconContent = JSON.stringify(icon, null, 2);
writeFile(iconContent, 'icons/'+iconName+'.json', path.resolve(currentDir, '..'));
});
Object.keys(icons.categories).forEach(categoryName => {
const category = {
"$schema": "../category.schema.json",
...icons.categories[categoryName]
};
const categoryContent = JSON.stringify(category, null, 2);
writeFile(categoryContent, 'categories/'+categoryName+'.json', path.resolve(currentDir, '..'));
});

View File

@@ -1,44 +1,17 @@
import path from 'path';
import tags from '../tags.json' assert { type: 'json' };
import icons from '../icons.json' assert { type: 'json' };
import { readSvgDirectory, writeFile, mergeArrays, getCurrentDirPath } from './helpers.mjs';
import { writeFile, getCurrentDirPath, readAllMetadata } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
const currentDir = getCurrentDirPath(import.meta.url);
const ICONS_DIR = path.resolve(currentDir, '../icons');
const icons = readAllMetadata(ICONS_DIR);
console.log(`Read all icons`);
const tags = Object.keys(icons)
.sort()
.reduce((acc, iconName) => {
acc[iconName] = icons[iconName].tags;
return acc;
}, {});
const svgFiles = readSvgDirectory(ICONS_DIR);
const tagsContent = JSON.stringify(tags, null, 2);
const iconNames = svgFiles.map(icon => icon.split('.')[0]);
const iconList = iconNames
.map(iconName => ({
name: iconName,
icon: icons.icons[iconName] || { tags: [] },
tags: tags[iconName] || [],
}))
.sort((a, b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
const newTags = iconList.reduce((acc, { name, icon, tags }) => {
acc[name] = mergeArrays(icon.tags, tags);
return acc;
}, {});
const tagsContent = JSON.stringify(newTags, null, 2);
writeFile(tagsContent, 'tags.json', path.resolve(currentDir, '..'));
writeFile(tagsContent, 'tags.json', path.resolve(process.cwd()));

View File

@@ -1,47 +1,21 @@
import path from 'path';
import tags from '../tags.json' assert { type: 'json' };
import icons from '../icons.json' assert { type: 'json' };
import { readSvgDirectory, writeFile, mergeArrays, getCurrentDirPath } from './helpers.mjs';
import { readSvgDirectory, readAllMetadata, writeFile, mergeArrays, getCurrentDirPath } from './helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url)
const ICONS_DIR = path.resolve(currentDir, '../icons');
console.log(`Read all icons`);
const icons = readAllMetadata(ICONS_DIR);
const svgFiles = readSvgDirectory(ICONS_DIR);
const iconNames = svgFiles.map(icon => icon.split('.')[0]);
const iconNames = svgFiles.map((icon) => icon.split('.')[0]);
const iconList = iconNames
.map(iconName => ({
name: iconName,
icon: icons.icons[iconName] || { tags: [], categories: [] },
tags: tags[iconName] || [],
}))
.sort((a, b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
const newIcons = icons;
newIcons.icons = iconList.reduce((acc, { name, icon, tags }) => {
acc[name] = icon;
acc[name].tags = mergeArrays(icon.tags, tags);
return acc;
}, {});
const iconsContent = JSON.stringify(newIcons, null, 2);
writeFile(iconsContent, 'icons.json', path.resolve(currentDir, '..'));
iconNames.forEach(iconName => {
icons[iconName] = icons[iconName] || {
"$schema": "../icon.schema.json",
"tags": [],
"categories": []
};
icons[iconName].tags = mergeArrays(icons[iconName].tags, tags[iconName]);
const iconContent = JSON.stringify(icons[iconName], null, 2);
writeFile(iconContent, `${iconName}.json`, path.resolve(currentDir, '../icons'));
})

View File

@@ -1,10 +1,11 @@
import fs from 'fs';
import processSvg from './render/processSvg.mjs';
const svgFiles = process.argv.slice(4);
const svgFiles = process.argv.slice(2);
svgFiles.forEach(async (svgFile) => {
console.log('Optimizing staged SVG file:', svgFile)
const content = fs.readFileSync(svgFile);
const svg = await processSvg(content);
const svg = await processSvg(content, svgFile);
fs.writeFileSync(svgFile, svg, 'utf-8');
});

View File

@@ -11,5 +11,5 @@ const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach((svgFile) => {
const content = fs.readFileSync(path.join(ICONS_DIR, svgFile));
processSvg(content).then((svg) => writeSvgFile(svgFile, ICONS_DIR, svg));
processSvg(content, svgFile).then((svg) => writeSvgFile(svgFile, ICONS_DIR, svg));
});

View File

@@ -1,6 +1,6 @@
import { optimize } from 'svgo';
import {optimize} from 'svgo';
import prettier from 'prettier';
import { parseSync, stringify } from 'svgson';
import {parseSync, stringify} from 'svgson';
import DEFAULT_ATTRS from './default-attrs.json' assert { type: 'json' };
/**
@@ -8,8 +8,9 @@ import DEFAULT_ATTRS from './default-attrs.json' assert { type: 'json' };
* @param {string} svg - An SVG string.
* @returns {Promise<string>} An optimized svg
*/
async function optimizeSvg(svg) {
async function optimizeSvg(svg, path) {
const result = optimize(svg, {
path,
plugins: [
{
name: 'preset-default',
@@ -17,12 +18,15 @@ async function optimizeSvg(svg) {
overrides: {
convertShapeToPath: false,
mergePaths: false,
removeAttrs: {
attrs: '(fill|stroke.*)',
},
},
},
},
{
name: 'removeAttrs',
params: {
attrs: '(fill|stroke.*)',
}
}
],
});
@@ -47,12 +51,12 @@ function setAttrs(svg) {
* @param {string} svg An SVG string.
* @returns {Promise<string>} An optimized svg
*/
function processSvg(svg) {
function processSvg(svg, path) {
return (
optimizeSvg(svg)
optimizeSvg(svg, path)
.then(setAttrs)
.then((optimizedSvg) =>
prettier.format(optimizedSvg, { parser: 'babel' }),
prettier.format(optimizedSvg, {parser: 'babel'}),
)
// remove semicolon inserted by prettier
// because prettier thinks it's formatting JSX not HTML

2
site/.gitignore vendored
View File

@@ -1,2 +1,4 @@
.idea
public/docs/images
.vercel
.env

View File

@@ -1,12 +1,13 @@
{
"name": "@lucide/site",
"private": true,
"name": "site",
"version": "1.0.0",
"author": "John Letey",
"scripts": {
"dev": "next dev",
"copy-assets": "mkdir -p ./public/docs/images && cp -rf ../docs/images ./public/docs",
"build": "pnpm copy-assets && next build",
"prebuild": "ts-node --swc scripts/preBuild.ts",
"build": "pnpm copy-assets && pnpm prebuild && next build",
"export": "next export -o build",
"deploy": "pnpm build && pnpm export",
"lint": "eslint .",
@@ -36,10 +37,12 @@
"react": "17.0.2",
"react-color": "^2.19.3",
"react-dom": "17.0.2",
"react-svg-loader": "^3.0.3"
"react-svg-loader": "^3.0.3",
"svgson": "^5.2.1"
},
"devDependencies": {
"@next/eslint-plugin-next": "^12.2.5",
"@swc/core": "^1.3.35",
"@testing-library/dom": "^7.31.2",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^11.2.7",
@@ -55,8 +58,11 @@
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"jest": "^26.5.2",
"node-fetch": "2",
"prettier": "^2.3.2",
"react-test-renderer": "17.0.2",
"ts-node": "~10.9.1",
"tslib": "^2.4.0",
"typescript": "^4.3.5"
}
}

17
site/scripts/preBuild.ts Normal file
View File

@@ -0,0 +1,17 @@
import {fetchTags} from "../src/lib/fetchTags";
import {fetchIconNodes} from "../src/lib/fetchIconNodes";
import NextCache from "../src/lib/nextCache";
const clearCache = async () => {
await NextCache.clear('api-tags', 'api-icon-nodes')
}
const buildCache = async () => {
await Promise.all([fetchTags(), fetchIconNodes()])
}
const rebuildCache = async () => {
await Promise.all([clearCache(), buildCache()])
}
rebuildCache().then(() => null)

View File

@@ -40,7 +40,6 @@ const Header = ({ data }: HeaderProps) => {
const { iconsRef } = useCustomizeIconContext();
const downloadAllIcons = async () => {
console.log(iconsRef);
setZippingIcons(true);
let iconEntries: IconContent[] = Object.entries(iconsRef.current).map(([name, svgEl]) => [
@@ -153,7 +152,7 @@ const Header = ({ data }: HeaderProps) => {
{packages.map(({ name, href, Logo, label }) => (
<WrapItem key={name}>
<NextLink href={href} key={name} passHref>
<Link _hover={{ opacity: 0.8 }} aria-label={label}>
<Link _hover={{ opacity: 0.8 }} aria-label={label} title={label}>
<Logo />
</Link>
</NextLink>

View File

@@ -2,6 +2,7 @@ import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import { Contributor } from '../types';
import fetch, { Headers } from 'node-fetch'
const IGNORE_COMMIT_MESSAGES = ['fork', 'optimize'];

View File

@@ -0,0 +1,15 @@
import NextCache from './nextCache';
import {parseSync} from 'svgson';
import {getAllData} from './icons';
export type IconNode = [string, object, IconNode[]];
export type IconNodes = {[iconName: string]: IconNode};
export function fetchIconNodes(writeCache = true): Promise<IconNodes> {
return NextCache.resolve('api-icon-nodes', async () => {
return (await getAllData()).reduce((acc, icon) => {
acc[icon.name] = parseSync(icon.src).children.map(({name, attributes}) => [name, attributes]);
return acc;
}, {});
}, writeCache);
}

View File

@@ -0,0 +1,13 @@
import NextCache from './nextCache';
import {getAllData} from './icons';
export type Tags = {[iconName: string]: string[]};
export function fetchTags(writeCache = true): Promise<Tags> {
return NextCache.resolve('api-tags', async () => {
return (await getAllData()).reduce((acc, icon) => {
acc[icon.name] = icon.tags;
return acc;
}, {});
}, writeCache);
}

View File

@@ -1,31 +1,32 @@
import fs from "fs";
import path from "path";
import { parseSync } from 'svgson';
import tags from '../../../tags.json';
import { IconEntity } from "../types";
import { getContributors } from "./fetchAllContributors";
const directory = path.join(process.cwd(), "../icons");
export function getAllNames() {
const fileNames = fs.readdirSync(directory).filter((file) => path.extname(file) === '.svg');
const fileNames = fs.readdirSync(directory).filter((file) => path.extname(file) === '.json');
return fileNames.map((fileName) => {
return fileName.replace(/\.svg$/, "");
});
return fileNames
.filter((fileName) => fs.existsSync(directory + '/' + path.basename(fileName, '.json') + '.svg'))
.map((fileName) => path.basename(fileName, '.json'));
}
export async function getData(name: string) {
const fullPath = path.join(directory, `${name}.svg`);
const fileContent = fs.readFileSync(fullPath, "utf8");
const svgPath = path.join(directory, `${name}.svg`);
const svgContent = fs.readFileSync(svgPath, "utf8");
const jsonPath = path.join(directory, `${name}.json`);
const jsonContent = fs.readFileSync(jsonPath, "utf8");
const iconJson = JSON.parse(jsonContent);
const contributors = await getContributors(name);
return {
...iconJson,
name,
tags: tags[name] || [],
contributors,
src: fileContent
src: svgContent
};
}

64
site/src/lib/nextCache.ts Normal file
View File

@@ -0,0 +1,64 @@
import path from 'path';
import fs from 'fs';
const cacheDir = path.join(process.cwd(), '.next/cache');
const nextDir = path.join(process.cwd(), '.next');
const cachePath = (cacheKey: string) => path.join(cacheDir, `${cacheKey}.json`);
type AtomicCacheable = object|string|number|boolean|null;
type Cacheable = AtomicCacheable|AtomicCacheable[];
if (!fs.existsSync(nextDir)) {
fs.mkdirSync(nextDir)
}
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir)
}
function read<T extends Cacheable>(cacheKey: string): T {
if (fs.existsSync(cachePath(cacheKey))) {
const iconCache = fs.readFileSync(cachePath(cacheKey), "utf8")
return JSON.parse(iconCache)
}
return null
}
function write<T extends Cacheable>(cacheKey: string, content: T): void {
if (!fs.existsSync(path.join(cacheDir, cacheKey))) {
fs.mkdirSync(path.join(cacheDir, cacheKey))
}
fs.writeFileSync(cachePath(cacheKey), JSON.stringify(content), 'utf-8')
}
function clear(...cacheKeys: string[]) {
for (const cacheKey of cacheKeys) {
const itemCachePath = cachePath(cacheKey)
if (fs.existsSync(itemCachePath)) {
fs.unlinkSync(itemCachePath)
}
}
}
async function resolve<T extends Cacheable>(cacheKey: string, contentResolver: () => Promise<T>|T, writeCache = true): Promise<T> {
try {
let cacheItem = await read<T>(cacheKey)
if (cacheItem === null) {
cacheItem = await contentResolver()
if (writeCache) {
write(cacheKey, cacheItem)
}
}
return cacheItem;
} catch (error) {
throw new Error(error)
}
}
const NextCache = {read, write, resolve, clear}
export default NextCache

View File

@@ -0,0 +1,8 @@
import {fetchIconNodes} from '../../../lib/fetchIconNodes';
export default async function handler(req, res) {
res.setHeader(
'Cache-Control',
'public, max-age=86400'
).status(200).json(await fetchIconNodes(false));
}

View File

@@ -0,0 +1,8 @@
import {fetchTags} from '../../../lib/fetchTags';
export default async function handler(req, res) {
res.setHeader(
'Cache-Control',
'public, max-age=86400'
).status(200).json(await fetchTags(false));
}

View File

@@ -1,5 +1,13 @@
{
"ts-node": {
"esm": true,
"compilerOptions": {
"baseUrl": ".",
"module": "nodenext",
}
},
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": [
"dom",

4576
tags.json

File diff suppressed because it is too large Load Diff