Merge branch 'main' of https://github.com/lucide-icons/lucide into better-contribution-guide

This commit is contained in:
Eric Fennis
2026-08-05 13:59:28 +02:00
871 changed files with 19376 additions and 2301 deletions

View File

@@ -9,3 +9,4 @@ strikethrough
touchpad
ungroup
toc
sunlounger

View File

@@ -13,7 +13,7 @@ The `contributors` property is a required array of GitHub usernames for the peop
The `tags` property is an array of strings that describe the icon and can be used for searching.
Validate the tags against the `icon.schema.json` to ensure they are correctly formatted and adhere to the defined structure.
Provide tag suggestions based on the name of the icon and the use cases provided in the PR description. Use the existing tags in the repository as a reference for consistency and to avoid duplicates. Don't suggest words like: 'icon' and preferably use single words. Tags should always be in lowercase and should not contain spaces. The name of icon should not be included in the tags, as it is already specified.
Provide tag suggestions based on the name of the icon and the use cases provided in the PR description. Use the existing tags in the repository as a reference for consistency and to avoid duplicates. Don't suggest words like: 'icon' and preferably use single words. Tags should always be in lowercase, and may also contain spaces (e.g. `magnifying glass`). The name of icon should not be included in the tags, as it is already specified.
## Categories

View File

@@ -47,7 +47,9 @@ Common scopes: icons, docs, studio, site, dev
### Design <!-- ONLY for new icons -->
<!-- All of these requirements must be fulfilled. -->
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/contribute/icon-design-guide)
- [ ] I've made sure that the icons don't [already exist](https://lucide.dev/icons), including the [Lab directory](https://github.com/lucide-icons/lucide/tree/main/lab).
- [ ] I've made sure that the icons look sharp on low DPI displays.
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
- [ ] I've made sure that the icons are visually centered.

View File

@@ -27,10 +27,6 @@ permissions:
id-token: write # Required for OIDC
contents: write
# This is added to make sure we wait until last release is done, this is needed for the font-build process
concurrency:
group: continuous-integration
jobs:
check-dispatch-gate:
if: github.repository == 'lucide-icons/lucide' &&

View File

@@ -1,9 +1,7 @@
name: Linting PR
name: Linting PR code
on:
pull_request:
paths-ignore:
- icons/*.svg
jobs:
lint-code:

View File

@@ -1,4 +1,4 @@
name: Linting PR
name: Linting PR title
on:
pull_request:

View File

@@ -7,6 +7,7 @@ on:
pull_request:
paths:
- 'icons/*'
- 'lab/*'
jobs:
lint-filenames:
@@ -17,20 +18,47 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
files: icons/*
files: |
icons/*
lab/*
- name: Generate annotations
run: node ./scripts/lintFilenames.mts
env:
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
check-lab-icons:
name: Check Lab Icons
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check lab icons do not already exist in icons
run: node ./scripts/checkLabIcons.mts
lint-aliases:
name: Check Uniqueness of Aliases
runs-on: ubuntu-latest

30
.github/workflows/lucide-lab.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Lucide Lab checks
on:
pull_request:
paths:
- packages/lab/**
- packages/shared/**
- tools/build-icons/**
- tools/rollup-plugins/**
- pnpm-lock.yaml
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm --filter @lucide/lab build

View File

@@ -1,6 +1,6 @@
name: 'Request Review'
name: Request Review
on:
pull_request_target:
pull_request:
types: [opened]
paths:
- icons/*.svg

4
.gitignore vendored
View File

@@ -54,8 +54,10 @@ docs/.vitepress/data/iconDetails
docs/.vitepress/data/relatedIcons.json
docs/.vitepress/data/brandStopwords.json
docs/.vitepress/data/iconPopularity
docs/.vitepress/data/lab/iconNodes
docs/.vitepress/data/lab/iconMetaData.ts
docs/.vitepress/data/lab/iconPopularity
docs/.vercel
docs/.nitro
docs/public/og/**
!docs/public/og/general.png
.gitignore

View File

@@ -30,7 +30,7 @@ Read it here: [ICON_GUIDELINES](https://lucide.dev/contribute/icon-design-guide)
#### Lucide Studio
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/?utm_source=lucide.dev&utm_medium=contributing-guide). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
#### Editor guides

View File

@@ -56,7 +56,6 @@
"kubernetes": "Kubernetes",
"leetcode": "LeetCode",
"leet-code": "LeetCode",
"line": "LINE",
"linkedin": "LinkedIn",
"lua": "Lua",
"mariadb": "MariaDB",
@@ -69,7 +68,7 @@
"nestjs": "NestJS",
"netflix": "Netflix",
"netlify": "Netlify",
"next": "Next.js",
"nextjs": "Next.js",
"nodejs": "Node.js",
"notion": "Notion",
"nostr": "Nostr",
@@ -105,7 +104,8 @@
"shopify": "Shopify",
"skype": "Skype",
"slack": "Slack",
"solid": "SolidJS",
"snapchat": "Snapchat",
"solidjs": "SolidJS",
"soundcloud": "SoundCloud",
"spotify": "Spotify",
"sqlite": "SQLite",
@@ -144,6 +144,5 @@
"xbox": "Xbox",
"yarn": "Yarn",
"youtube": "YouTube",
"zig": "Zig",
"zoom": "Zoom"
"zig": "Zig"
}

View File

@@ -0,0 +1,25 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../../data/lab/iconMetaData';
import iconPopularity from '../../../data/lab/iconPopularity';
import iconNodes from '../../../data/lab/iconNodes';
export default eventHandler((event) => {
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
return Object.fromEntries(
Object.entries(iconMetaData).map(([iconName, iconData]) => {
// Remove $schema from the response
delete iconData['$schema'];
return [
iconName,
{
name: iconName,
iconNode: iconNodes[iconName],
popularity: iconPopularity[iconName]?.count ?? 0,
...iconData,
},
];
}),
);
});

View File

@@ -0,0 +1,14 @@
import { eventHandler, setResponseHeader } from 'h3';
import iconMetaData from '../../../data/lab/iconMetaData';
export default eventHandler((event) => {
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
for (const iconDetail in iconMetaData) {
// Remove $schema from the response
delete iconMetaData[iconDetail]['$schema'];
}
return iconMetaData;
});

View File

@@ -0,0 +1,30 @@
import { eventHandler, getQuery, setResponseHeader } from 'h3';
import iconNodes from '../../../data/lab/iconNodes';
type IconNodeWithKeys = [elementName: string, attrs: Record<string, string> & { key?: string }][];
export default eventHandler((event) => {
const query = getQuery(event);
const withUniqueKeys = query.withUniqueKeys === 'true';
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
if (withUniqueKeys) {
return iconNodes;
}
return Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
if (withUniqueKeys) {
return [name, iconNode];
}
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
return [name, attrs];
});
acc[name] = newIconNode;
return acc;
}, {});
});

View File

@@ -46,21 +46,5 @@
"light": "/company-logos/open-collective-light.svg",
"dark": "/company-logos/open-collective-dark.svg"
}
},
{
"name": "Super",
"url": "https://super.so",
"image": {
"light": "/company-logos/super-light.svg",
"dark": "/company-logos/super-dark.svg"
}
},
{
"name": "Noodle",
"url": "https://noodle.run/",
"image": {
"light": "/company-logos/noodle-light.svg",
"dark": "/company-logos/noodle-dark.svg"
}
}
]

View File

View File

@@ -84,7 +84,7 @@ const base64InnerSvg = computed(() => {
</g>
</svg>
<a
:href="`https://studio.lucide.dev/edit?value=${encodeURIComponent(base64InnerSvg)}&name=${name}`"
:href="`https://studio.lucide.dev/edit?value=${encodeURIComponent(base64InnerSvg)}&name=${name}&utm_source=lucide.dev&utm_medium=icon-detail-preview`"
target="_blank"
rel="noopener noreferrer"
class="studio-button"

View File

@@ -16,7 +16,7 @@ export const externalLibContext = {
};
const externalLibIconNodesAPI = {
lab: 'https://lab.lucide.dev/api/icon-details',
lab: `${import.meta.env.DEV ? 'http://localhost:3000' : ''}/api/lab/icon-details`,
};
export function useExternalLibs(): ExternalLibContext {
@@ -32,13 +32,15 @@ export function useExternalLibs(): ExternalLibContext {
newExternalIconNodes[lib] = savedIconNodes[lib];
} else {
const response = await fetch(externalLibIconNodesAPI[lib]);
const iconNodes = await response.json();
const iconDetails = await response.json();
if (iconNodes) {
newExternalIconNodes[lib] = Object.values(iconNodes).map((iconEntity: IconEntity) => ({
...iconEntity,
externalLibrary: lib,
}));
if (iconDetails) {
newExternalIconNodes[lib] = Object.values(iconDetails).map((iconEntity: IconEntity) => {
return {
...iconEntity,
externalLibrary: lib,
};
});
}
}
}

View File

@@ -1,15 +1,10 @@
---
title: SVG Code Conventions
description: SVG code conventions for icons in the Lucide icon library.
---
# SVG Code Conventions
## Code Conventions
Before an icon is added to the library, we like to have readable and optimized SVG code.
## Global Attributes
### Global Attributes
For each icon these attributes are applied, corresponding to the design principles.
For each icon these attributes are applied, corresponding to the above rules.
```xml
<svg
@@ -27,24 +22,47 @@ For each icon these attributes are applied, corresponding to the design principl
</svg>
```
## Minify paths
### Minify paths
The code of paths can sometimes get quite large. To reduce file size we like to minify the code.
We recommend to use [Lucide Studio](https://studio.lucide.dev/) to tidy paths to 3 points of precision.
We recommend to use [Lucide Studio](https://studio.lucide.dev/?utm_source=lucide.dev&utm_medium=design-guide) to tidy paths to 3 points of precision.
## Allowed elements
### Allowed elements
SVG files may only contain simple path and shape elements, which may not have any attributes other than sizing and spacing.\
In practice only the following elements and attributes are allowed:
- `<path d>`
- `<line x1 x2>`
- `<polygon points>`
- `<polyline points>`
- `<circle cx cy r>`
- `<ellipse cx cy rx ry>`
- `<rect x y width height rx>`
* `<path d>`
* `<line x1 x2>`
* `<polygon points>`
* `<polyline points>`
* `<circle cx cy r>`
* `<ellipse cx cy rx ry>`
* `<rect x y width height rx>`
This also means that no transforms, filters, fills or explicit strokes are allowed.
Never use [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use). While it may sometimes seem like a good way to optimize file size, there's no way to ensure that the referenced element IDs will be unique once the SVGs are embedded in HTML documents.
Never use [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use). While it may sometimes seem like a good way to optimize file size, there's no way to ensure that the referenced element IDs will be unique once the SVGs are embedded in HTML documents.
## JSON metadata descriptor
<!-- TODO: Add use-case explanation -->
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",
"contributors": [
"github-username",
"another-github-username"
],
"tags": [
"foo",
"bar"
],
"categories": [
"devices"
]
}
```

View File

@@ -12,6 +12,10 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackAngular.vue'
While they aren't provided as standalone components, they can be still be passed to the `LucideIcon` component the same way as official icons:
::: info Limitation
Only custom icons that follow Lucide's [code conventions](../../../contribute/icon-design-guide.md#code-conventions) are supported.
:::
### Directly as LucideIconData
::: sandpack {template=angular showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/angular,@lucide/lab"}

View File

@@ -1,24 +1,26 @@
import { IconEntity } from '../../.vitepress/theme/types';
import iconNodes from '../../.vitepress/data/lab/iconNodes';
import iconPopularity from '../../.vitepress/data/lab/iconPopularity';
import iconMetaData from '../../.vitepress/data/lab/iconMetaData';
import { type IconEntity } from '../../.vitepress/theme/types';
export default {
paths: async () => {
try {
const iconDetailsResponse = await fetch('https://lab.lucide.dev/api/icon-details');
const iconDetails = (await iconDetailsResponse.json()) as Record<string, IconEntity>;
return (Object.entries(iconNodes) as unknown as IconEntity[]).map(([name, iconNode]) => {
const iconDetails = iconMetaData[name];
return Object.values(iconDetails).map((iconEntity) => {
const params = {
externalLibrary: 'lab',
...iconEntity,
};
delete iconDetails['$schema'];
return {
params,
};
});
} catch (error) {
console.error('Error fetching icon details:', error);
return [];
}
const params = {
name,
iconNode,
externalLibrary: 'lab',
popularity: iconPopularity[name]?.count ?? 0,
...iconDetails,
};
return {
params,
};
});
},
};

View File

@@ -8,19 +8,21 @@
"docs:dev": "pnpm run /^prebuild:.*/ && vitepress dev",
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
"docs:preview": "vitepress preview",
"build:docs": "vitepress build",
"build:docs": "NODE_OPTIONS=--max-old-space-size=8192 vitepress build",
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mts",
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mts",
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mts",
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mts",
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mts",
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mts",
"prebuild:iconPopularity": "node ./scripts/writeiconPopularity.mts",
"prebuild:iconPopularity": "node ./scripts/writeiconPopularity.mts && node ./scripts/writeiconPopularityIndex.mts",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
"prebuild:writeLabIconNodes": "node ./scripts/writeLabIconNodes.mts",
"prebuild:writeLabIconMetaIndex": "node ./scripts/writeLabIconMetaIndex.mts",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
"dev": "npx nitropack dev",
"prebuild:api": "npx nitropack prepare",
"build:api": "npx nitropack build",
"dev": "nitropack dev",
"prebuild:api": "nitropack prepare",
"build:api": "NODE_OPTIONS=--max-old-space-size=8192 nitropack build",
"build": "pnpm run /^prebuild:.*/ && pnpm run build:api && pnpm run build:docs && pnpm postbuild:vercelJson",
"preview": "node .output/server/index.mjs"
},

View File

@@ -1,28 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="10 -10 304 120">
<g clip-path="url(#a)">
<g clip-path="url(#b)">
<path fill="url(#c)" d="M72 0H28A28 28 0 0 0 0 28v44a28 28 0 0 0 28 28h44a28 28 0 0 0 28-28V28A28 28 0 0 0 72 0Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m47.81 54.34 26.63-6.66-19.73-19.1-26.63 6.67 19.73 19.1Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m47.81 54.34 18.23-4.56c.67 5.86-.29 11.8-2.76 17.15a31.87 31.87 0 0 0-19.65 3.01 31.87 31.87 0 0 0-15.5-12.43 32.2 32.2 0 0 1 6.18-16.23l13.5 13.06Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m33.37 67.04 5.17-19.32 11.84-2.96m-2.57 9.58 26.63-6.66-19.73-19.1-26.63 6.67 19.73 19.1Zm0 0 18.23-4.56c.67 5.86-.29 11.8-2.76 17.15a31.87 31.87 0 0 0-19.65 3.01 31.87 31.87 0 0 0-15.5-12.43 32.2 32.2 0 0 1 6.18-16.23l13.5 13.06Z"/>
</g>
<path fill="#161616" d="M281.5 67.51c-2.63 0-4.9-.54-6.8-1.64a11.08 11.08 0 0 1-4.39-4.67 15.64 15.64 0 0 1-1.53-7.14c0-2.7.51-5.05 1.53-7.09a11.6 11.6 0 0 1 4.33-4.77 12.14 12.14 0 0 1 6.53-1.72c1.62 0 3.14.26 4.57.78 1.44.51 2.72 1.3 3.82 2.39a11.18 11.18 0 0 1 2.62 4.12c.64 1.66.96 3.64.96 5.93v1.9h-21.46v-4.16h15.54a6.63 6.63 0 0 0-.76-3.16 5.58 5.58 0 0 0-2.1-2.2 5.9 5.9 0 0 0-3.1-.8c-1.26 0-2.37.31-3.33.92-.95.6-1.7 1.4-2.23 2.4a6.88 6.88 0 0 0-.8 3.21v3.63c0 1.53.28 2.83.83 3.92a5.96 5.96 0 0 0 2.34 2.5c1 .56 2.17.84 3.51.84.9 0 1.71-.12 2.44-.37a5.4 5.4 0 0 0 1.89-1.14c.53-.5.94-1.12 1.21-1.86l5.76.65a9 9 0 0 1-2.08 3.99c-1 1.12-2.3 2-3.88 2.62-1.58.61-3.39.92-5.42.92Z"/>
<path fill="#161616" d="M263.56 32.1V67h-6.17V32.1h6.17Z"/>
<path fill="#161616" d="M236.87 67.46a9.9 9.9 0 0 1-5.52-1.58 10.77 10.77 0 0 1-3.85-4.6 17.18 17.18 0 0 1-1.42-7.34c0-2.9.48-5.36 1.43-7.36a10.6 10.6 0 0 1 3.9-4.55 10.03 10.03 0 0 1 5.48-1.55c1.53 0 2.8.26 3.78.78a7.13 7.13 0 0 1 2.35 1.86c.58.72 1.03 1.4 1.35 2.03h.26V32.09h6.18V67h-6.06v-4.13h-.38c-.32.64-.78 1.32-1.38 2.03a7.6 7.6 0 0 1-6.12 2.56Zm1.72-5.06c1.3 0 2.42-.35 3.34-1.06a6.6 6.6 0 0 0 2.1-2.98c.48-1.27.72-2.76.72-4.45 0-1.7-.24-3.17-.72-4.42a6.28 6.28 0 0 0-2.08-2.91 5.38 5.38 0 0 0-3.36-1.04c-1.37 0-2.52.36-3.44 1.07a6.5 6.5 0 0 0-2.08 2.97c-.47 1.26-.7 2.7-.7 4.33 0 1.64.23 3.1.7 4.38a6.84 6.84 0 0 0 2.1 3.02 5.4 5.4 0 0 0 3.42 1.09Z"/>
<path fill="#161616" d="M209.37 67.51c-2.56 0-4.77-.56-6.65-1.69a11.46 11.46 0 0 1-4.36-4.72 15.52 15.52 0 0 1-1.53-7.09c0-2.7.5-5.07 1.53-7.1a11.43 11.43 0 0 1 4.36-4.75 12.68 12.68 0 0 1 6.65-1.68c2.56 0 4.78.56 6.65 1.68a11.32 11.32 0 0 1 4.35 4.74 15.47 15.47 0 0 1 1.55 7.11c0 2.7-.52 5.07-1.55 7.1a11.34 11.34 0 0 1-4.35 4.71 12.68 12.68 0 0 1-6.65 1.7Zm.04-4.94c1.38 0 2.54-.38 3.47-1.14a6.89 6.89 0 0 0 2.08-3.1c.47-1.3.7-2.74.7-4.34 0-1.6-.23-3.05-.7-4.34a6.88 6.88 0 0 0-2.08-3.12 5.27 5.27 0 0 0-3.47-1.16c-1.42 0-2.6.39-3.55 1.16a7 7 0 0 0-2.1 3.12c-.45 1.3-.68 2.74-.68 4.34 0 1.6.23 3.04.68 4.33a7 7 0 0 0 2.1 3.1 5.46 5.46 0 0 0 3.55 1.15Z"/>
<path fill="#161616" d="M180.17 67.51c-2.56 0-4.77-.56-6.65-1.69a11.46 11.46 0 0 1-4.36-4.72 15.52 15.52 0 0 1-1.54-7.09c0-2.7.51-5.07 1.54-7.1a11.43 11.43 0 0 1 4.36-4.75 12.68 12.68 0 0 1 6.65-1.68c2.56 0 4.77.56 6.65 1.68a11.32 11.32 0 0 1 4.34 4.74 15.49 15.49 0 0 1 1.55 7.11c0 2.7-.51 5.07-1.55 7.1a11.34 11.34 0 0 1-4.34 4.71 12.68 12.68 0 0 1-6.65 1.7Zm.03-4.94c1.39 0 2.55-.38 3.48-1.14a6.89 6.89 0 0 0 2.08-3.1c.47-1.3.7-2.74.7-4.34 0-1.6-.23-3.05-.7-4.34a6.88 6.88 0 0 0-2.08-3.12 5.26 5.26 0 0 0-3.48-1.16c-1.42 0-2.6.39-3.54 1.16a7 7 0 0 0-2.1 3.12c-.45 1.3-.68 2.74-.68 4.34 0 1.6.23 3.04.68 4.33a7 7 0 0 0 2.1 3.1 5.46 5.46 0 0 0 3.54 1.15Z"/>
<path fill="#161616" d="M162.13 32.1V67h-5.62l-16.45-23.78h-.3V67h-6.32V32.1h5.66l16.43 23.79h.31v-23.8h6.3Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#161616" d="M0 0h293.14v100H0z"/>
</clipPath>
<clipPath id="b">
<path fill="#161616" d="M0 0h100v100H0z"/>
</clipPath>
<linearGradient id="c" x1="0" x2="100" y1="50" y2="50" gradientUnits="userSpaceOnUse">
<stop stop-color="#F77062"/>
<stop offset="1" stop-color="#FE5196"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,28 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="10 -10 304 120">
<g clip-path="url(#a)">
<g clip-path="url(#b)">
<path fill="url(#c)" d="M72 0H28A28 28 0 0 0 0 28v44a28 28 0 0 0 28 28h44a28 28 0 0 0 28-28V28A28 28 0 0 0 72 0Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m47.81 54.34 26.63-6.66-19.73-19.1-26.63 6.67 19.73 19.1Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m47.81 54.34 18.23-4.56c.67 5.86-.29 11.8-2.76 17.15a31.87 31.87 0 0 0-19.65 3.01 31.87 31.87 0 0 0-15.5-12.43 32.2 32.2 0 0 1 6.18-16.23l13.5 13.06Z"/>
<path stroke="#161616" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="m33.37 67.04 5.17-19.32 11.84-2.96m-2.57 9.58 26.63-6.66-19.73-19.1-26.63 6.67 19.73 19.1Zm0 0 18.23-4.56c.67 5.86-.29 11.8-2.76 17.15a31.87 31.87 0 0 0-19.65 3.01 31.87 31.87 0 0 0-15.5-12.43 32.2 32.2 0 0 1 6.18-16.23l13.5 13.06Z"/>
</g>
<path fill="#fff" d="M281.5 67.51c-2.63 0-4.9-.54-6.8-1.64a11.08 11.08 0 0 1-4.39-4.67 15.64 15.64 0 0 1-1.53-7.14c0-2.7.51-5.05 1.53-7.09a11.6 11.6 0 0 1 4.33-4.77 12.14 12.14 0 0 1 6.53-1.72c1.62 0 3.14.26 4.57.78 1.44.51 2.72 1.3 3.82 2.39a11.18 11.18 0 0 1 2.62 4.12c.64 1.66.96 3.64.96 5.93v1.9h-21.46v-4.16h15.54a6.63 6.63 0 0 0-.76-3.16 5.58 5.58 0 0 0-2.1-2.2 5.9 5.9 0 0 0-3.1-.8c-1.26 0-2.37.31-3.33.92-.95.6-1.7 1.4-2.23 2.4a6.88 6.88 0 0 0-.8 3.21v3.63c0 1.53.28 2.83.83 3.92a5.96 5.96 0 0 0 2.34 2.5c1 .56 2.17.84 3.51.84.9 0 1.71-.12 2.44-.37a5.4 5.4 0 0 0 1.89-1.14c.53-.5.94-1.12 1.21-1.86l5.76.65a9 9 0 0 1-2.08 3.99c-1 1.12-2.3 2-3.88 2.62-1.58.61-3.39.92-5.42.92Z"/>
<path fill="#fff" d="M263.56 32.1V67h-6.17V32.1h6.17Z"/>
<path fill="#fff" d="M236.87 67.46a9.9 9.9 0 0 1-5.52-1.58 10.77 10.77 0 0 1-3.85-4.6 17.18 17.18 0 0 1-1.42-7.34c0-2.9.48-5.36 1.43-7.36a10.6 10.6 0 0 1 3.9-4.55 10.03 10.03 0 0 1 5.48-1.55c1.53 0 2.8.26 3.78.78a7.13 7.13 0 0 1 2.35 1.86c.58.72 1.03 1.4 1.35 2.03h.26V32.09h6.18V67h-6.06v-4.13h-.38c-.32.64-.78 1.32-1.38 2.03a7.6 7.6 0 0 1-6.12 2.56Zm1.72-5.06c1.3 0 2.42-.35 3.34-1.06a6.6 6.6 0 0 0 2.1-2.98c.48-1.27.72-2.76.72-4.45 0-1.7-.24-3.17-.72-4.42a6.28 6.28 0 0 0-2.08-2.91 5.38 5.38 0 0 0-3.36-1.04c-1.37 0-2.52.36-3.44 1.07a6.5 6.5 0 0 0-2.08 2.97c-.47 1.26-.7 2.7-.7 4.33 0 1.64.23 3.1.7 4.38a6.84 6.84 0 0 0 2.1 3.02 5.4 5.4 0 0 0 3.42 1.09Z"/>
<path fill="#fff" d="M209.37 67.51c-2.56 0-4.77-.56-6.65-1.69a11.46 11.46 0 0 1-4.36-4.72 15.52 15.52 0 0 1-1.53-7.09c0-2.7.5-5.07 1.53-7.1a11.43 11.43 0 0 1 4.36-4.75 12.68 12.68 0 0 1 6.65-1.68c2.56 0 4.78.56 6.65 1.68a11.32 11.32 0 0 1 4.35 4.74 15.47 15.47 0 0 1 1.55 7.11c0 2.7-.52 5.07-1.55 7.1a11.34 11.34 0 0 1-4.35 4.71 12.68 12.68 0 0 1-6.65 1.7Zm.04-4.94c1.38 0 2.54-.38 3.47-1.14a6.89 6.89 0 0 0 2.08-3.1c.47-1.3.7-2.74.7-4.34 0-1.6-.23-3.05-.7-4.34a6.88 6.88 0 0 0-2.08-3.12 5.27 5.27 0 0 0-3.47-1.16c-1.42 0-2.6.39-3.55 1.16a7 7 0 0 0-2.1 3.12c-.45 1.3-.68 2.74-.68 4.34 0 1.6.23 3.04.68 4.33a7 7 0 0 0 2.1 3.1 5.46 5.46 0 0 0 3.55 1.15Z"/>
<path fill="#fff" d="M180.17 67.51c-2.56 0-4.77-.56-6.65-1.69a11.46 11.46 0 0 1-4.36-4.72 15.52 15.52 0 0 1-1.54-7.09c0-2.7.51-5.07 1.54-7.1a11.43 11.43 0 0 1 4.36-4.75 12.68 12.68 0 0 1 6.65-1.68c2.56 0 4.77.56 6.65 1.68a11.32 11.32 0 0 1 4.34 4.74 15.49 15.49 0 0 1 1.55 7.11c0 2.7-.51 5.07-1.55 7.1a11.34 11.34 0 0 1-4.34 4.71 12.68 12.68 0 0 1-6.65 1.7Zm.03-4.94c1.39 0 2.55-.38 3.48-1.14a6.89 6.89 0 0 0 2.08-3.1c.47-1.3.7-2.74.7-4.34 0-1.6-.23-3.05-.7-4.34a6.88 6.88 0 0 0-2.08-3.12 5.26 5.26 0 0 0-3.48-1.16c-1.42 0-2.6.39-3.54 1.16a7 7 0 0 0-2.1 3.12c-.45 1.3-.68 2.74-.68 4.34 0 1.6.23 3.04.68 4.33a7 7 0 0 0 2.1 3.1 5.46 5.46 0 0 0 3.54 1.15Z"/>
<path fill="#fff" d="M162.13 32.1V67h-5.62l-16.45-23.78h-.3V67h-6.32V32.1h5.66l16.43 23.79h.31v-23.8h6.3Z"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h293.14v100H0z"/>
</clipPath>
<clipPath id="b">
<path fill="#fff" d="M0 0h100v100H0z"/>
</clipPath>
<linearGradient id="c" x1="0" x2="100" y1="50" y2="50" gradientUnits="userSpaceOnUse">
<stop stop-color="#F77062"/>
<stop offset="1" stop-color="#FE5196"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 151 31">
<path fill="#111" d="M49.37 7.6c-8.39 0-10.49 1.8-11.13 5.39-.62 3.58.93 5.06 8.1 5.06 4.2 0 5.39 0 5.2 1.04-.2 1.06-1.4 1.06-4.4 1.06-3 0-4.19 0-3.96-1.2H36.9c-.74 4.2 1.13 5.4 9.53 5.4 8.39 0 10.68-1.2 11.42-5.4.65-3.58-1.2-5.1-8.39-5.1-4.2 0-5.39-.02-5.2-1.03.2-1.06 1.4-1.06 4.4-1.06 2.38 0 4.19 0 3.96 1.2h5.97c.65-3.69-.83-5.36-9.23-5.36Z"/>
<path fill="#FFC158" d="M.84 15.81C.84 4.45 4.63.66 16 .66c11.37 0 15.15 3.79 15.15 15.15S27.36 30.96 16 30.96C4.63 30.96.84 27.17.84 15.81Z"/>
<path fill="#fff" fill-rule="evenodd" d="m16.16 8.37-5.8 8.87c-.18.28.02.65.36.65h5.32l-.99 5.37c-.08.46.52.7.77.31l5.8-8.86a.42.42 0 0 0-.36-.66H15.94l1-5.37c.08-.46-.52-.7-.78-.31Z" clip-rule="evenodd"/>
<path fill="#111" d="m77.04 8.18-1.38 7.78c-.53 3-2.9 4.2-5.33 4.2s-4.37-1.2-3.82-4.2l1.39-7.78h-6.71l-1.42 7.78c-1.08 5.97 2.14 8.39 7.63 8.39 4.28 0 7.04-1.81 7.04-1.81l.4 1.2h6.08l2.8-15.56h-6.68Z"/>
<path fill="#111" d="M98.83 7.6c-4.27 0-6.41 1.8-6.41 1.8l.23-1.19h-6.7l-4.09 22.75h6.71l1.51-8.39s1.52 1.8 5.8 1.8c5.48 0 10.05-1.8 11.24-8.38 1.15-6.62-2.8-8.4-8.29-8.4Zm1.55 8.36c-.53 3-2.9 4.2-5.33 4.2s-4.37-1.2-3.82-4.2c.53-3 2.9-4.2 5.33-4.2s4.34 1.2 3.82 4.2Z"/>
<path fill="#111" d="M121.08 7.6c-7.3 0-11.67 2.26-12.76 8.23-1.08 5.97 2.47 8.52 9.77 8.52 5.13 0 7.92-.9 10.55-3.23l-3.91-2.49c-.86.52-1.78 1.52-5.89 1.52-2.76 0-4-1.03-3.94-3.13h15.72c.1-.39.2-.77.26-1.2 1.05-6-2.5-8.22-9.8-8.22Zm-5.52 6.42c.78-1.68 2-2.26 4.76-2.26 2.73 0 3.78.55 3.95 2.26h-8.71Z"/>
<path fill="#111" d="m140.33 9.37.23-1.2h-6.7l-2.8 15.56h6.7l1.19-6.58c.76-4.2 3.91-4.78 6.35-4.78 2.4 0 3.19.26 4.76.62l.86-4.78c-.86-.26-2.9-.61-4.77-.61-4.27 0-5.82 1.77-5.82 1.77Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 151 31">
<path fill="#fff" d="M49.37 7.6c-8.39 0-10.49 1.8-11.13 5.39-.62 3.58.93 5.06 8.1 5.06 4.2 0 5.39 0 5.2 1.04-.2 1.06-1.4 1.06-4.4 1.06-3 0-4.19 0-3.96-1.2H36.9c-.74 4.2 1.13 5.4 9.53 5.4 8.39 0 10.68-1.2 11.42-5.4.65-3.58-1.2-5.1-8.39-5.1-4.2 0-5.39-.02-5.2-1.03.2-1.06 1.4-1.06 4.4-1.06 2.38 0 4.19 0 3.96 1.2h5.97c.65-3.69-.83-5.36-9.23-5.36Z"/>
<path fill="#FFC158" d="M.84 15.81C.84 4.45 4.63.66 16 .66c11.37 0 15.15 3.79 15.15 15.15S27.36 30.96 16 30.96C4.63 30.96.84 27.17.84 15.81Z"/>
<path fill="#fff" fill-rule="evenodd" d="m16.16 8.37-5.8 8.87c-.18.28.02.65.36.65h5.32l-.99 5.37c-.08.46.52.7.77.31l5.8-8.86a.42.42 0 0 0-.36-.66H15.94l1-5.37c.08-.46-.52-.7-.78-.31Z" clip-rule="evenodd"/>
<path fill="#fff" d="m77.04 8.18-1.38 7.78c-.53 3-2.9 4.2-5.33 4.2s-4.37-1.2-3.82-4.2l1.39-7.78h-6.71l-1.42 7.78c-1.08 5.97 2.14 8.39 7.63 8.39 4.28 0 7.04-1.81 7.04-1.81l.4 1.2h6.08l2.8-15.56h-6.68Z"/>
<path fill="#fff" d="M98.83 7.6c-4.27 0-6.41 1.8-6.41 1.8l.23-1.19h-6.7l-4.09 22.75h6.71l1.51-8.39s1.52 1.8 5.8 1.8c5.48 0 10.05-1.8 11.24-8.38 1.15-6.62-2.8-8.4-8.29-8.4Zm1.55 8.36c-.53 3-2.9 4.2-5.33 4.2s-4.37-1.2-3.82-4.2c.53-3 2.9-4.2 5.33-4.2s4.34 1.2 3.82 4.2Z"/>
<path fill="#fff" d="M121.08 7.6c-7.3 0-11.67 2.26-12.76 8.23-1.08 5.97 2.47 8.52 9.77 8.52 5.13 0 7.92-.9 10.55-3.23l-3.91-2.49c-.86.52-1.78 1.52-5.89 1.52-2.76 0-4-1.03-3.94-3.13h15.72c.1-.39.2-.77.26-1.2 1.05-6-2.5-8.22-9.8-8.22Zm-5.52 6.42c.78-1.68 2-2.26 4.76-2.26 2.73 0 3.78.55 3.95 2.26h-8.71Z"/>
<path fill="#fff" d="m140.33 9.37.23-1.2h-6.7l-2.8 15.56h6.7l1.19-6.58c.76-4.2 3.91-4.78 6.35-4.78 2.4 0 3.19.26 4.76.62l.86-4.78c-.86-.26-2.9-.61-4.77-.61-4.27 0-5.82 1.77-5.82 1.77Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -23,12 +23,12 @@ const writeIconFiles = icons.map(async (iconFileName) => {
const location = path.resolve(iconDetailsDirectory, `${iconName}.ts`);
const contents = `\
import iconNode from '../iconNodes/${iconName}.node.json'
import metaData from '../../../../icons/${iconName}.json'
import releaseData from '../releaseMetadata/${iconName}.json'
import popularity from '../iconPopularity/${iconName}.json'
import iconNode from '../iconNodes/${iconName}.node.json' with { type: 'json' };
import metaData from '../../../../icons/${iconName}.json' with { type: 'json' };
import releaseData from '../releaseMetadata/${iconName}.json' with { type: 'json' };
import popularity from '../iconPopularity/${iconName}.json' with { type: 'json' };
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData;
const iconDetails = {
name: '${iconName}',
@@ -42,9 +42,9 @@ const iconDetails = {
deprecationReason,
toBeRemovedInVersion,
...releaseData,
}
};
export default iconDetails
export default iconDetails;
`;
await fs.promises.writeFile(location, contents, 'utf-8');

View File

@@ -0,0 +1,49 @@
import fs from 'fs';
import path from 'path';
import { readSvgDirectory, toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../lab');
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
const labDirectory = path.resolve(currentDir, '.vitepress/data/lab');
const location = path.resolve(currentDir, labDirectory, 'iconMetaData.ts');
if (fs.existsSync(location)) {
fs.unlinkSync(location);
}
if (!fs.existsSync(labDirectory)) {
fs.mkdirSync(labDirectory);
}
const iconMetaIndexFileImports = [];
const iconMetaIndexFileExports = [];
iconJsonFiles.forEach((iconJsonFile) => {
const iconName = path.basename(iconJsonFile, '.json');
iconMetaIndexFileImports.push(
`import ${toCamelCase(iconName)}Metadata from '../../../../lab/${iconName}.json';`,
);
iconMetaIndexFileExports.push(` '${iconName}': ${toCamelCase(iconName)}Metadata,`);
});
try {
await fs.promises.writeFile(
location,
`\
${iconMetaIndexFileImports.join('\n')}
export default {
${iconMetaIndexFileExports.join('\n')}
}
`,
'utf-8',
);
console.log('Successfully write icon json file index');
} catch (error) {
throw new Error(`Something went wrong generating icon json file index file,\n ${error}`);
}

View File

@@ -0,0 +1,62 @@
import fs from 'fs';
import path from 'path';
import { renderIconsObject } from '@lucide/build-icons';
import { readSvgDirectory, toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../lab');
const svgFiles = await readSvgDirectory(ICONS_DIR);
const icons = await renderIconsObject(svgFiles, ICONS_DIR, true);
const iconNodesDirectory = path.resolve(currentDir, '.vitepress/data/lab', 'iconNodes');
if (fs.existsSync(iconNodesDirectory)) {
fs.rmSync(iconNodesDirectory, { recursive: true, force: true });
}
if (!fs.existsSync(iconNodesDirectory)) {
fs.mkdirSync(iconNodesDirectory);
}
const iconIndexFile = path.resolve(iconNodesDirectory, `index.ts`);
const iconIndexFileImports: string[] = [];
const iconIndexFileExports: string[] = [];
const iconIndexFileDefaultExports: string[] = [];
const writeIconFiles = Object.entries(icons).map(async ([iconName, { children }]) => {
// We need to use .node.json because the there is a file called package, which is a reserved word for packages.
const location = path.resolve(iconNodesDirectory, `${iconName}.node.json`);
const iconNode = children.map(({ name, attributes }) => [name, attributes]);
const output = JSON.stringify(iconNode, null, 2);
await fs.promises.writeFile(location, output, 'utf-8');
iconIndexFileImports.push(
`import ${toCamelCase(iconName)}Node from './${iconName}.node.json' with { type: "json" };`,
);
iconIndexFileExports.push(` ${toCamelCase(iconName)}Node as ${toCamelCase(iconName)},`);
iconIndexFileDefaultExports.push(` '${iconName}': ${toCamelCase(iconName)}Node,`);
});
try {
await Promise.all(writeIconFiles);
await fs.promises.writeFile(
iconIndexFile,
`\
${iconIndexFileImports.join('\n')}
export {
${iconIndexFileExports.join('\n')}
}
export default {
${iconIndexFileDefaultExports.join('\n')}
}
`,
'utf-8',
);
console.log('Successfully write', writeIconFiles.length, 'iconNodes.');
} catch (error) {
throw new Error(`Something went wrong generating iconNode files,\n ${error}`);
}

View File

@@ -5,27 +5,59 @@ import { loadEnvFile } from 'node:process';
import { readSvgDirectory } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../icons');
const iconPopularityDirectory = path.resolve(currentDir, '.vitepress/data', 'iconPopularity');
const dataDirectory = path.resolve(currentDir, '.vitepress/data');
try {
// Load environment variables from .env file, if it exists.
loadEnvFile(`${currentDir}/.env`);
} catch (error) {}
if (fs.existsSync(iconPopularityDirectory)) {
fs.rmSync(iconPopularityDirectory, { recursive: true, force: true });
interface IconCollection {
/** Human readable name, used for logging. */
name: string;
/** Directory containing the icon `.json` files. */
iconsDir: string;
/** Directory the `${iconName}.json` popularity files are written to. */
outputDir: string;
/** Matches an analytics route and captures the icon name in group 1. */
routePattern: RegExp;
}
if (!fs.existsSync(iconPopularityDirectory)) {
fs.mkdirSync(iconPopularityDirectory);
// Lab must come before the default collection because `/icons/lab/foo` also
// matches the default `/icons/(...)` pattern; the first match wins per route.
const iconCollections: IconCollection[] = [
{
name: 'lab',
iconsDir: path.resolve(currentDir, '../lab'),
outputDir: path.resolve(dataDirectory, 'lab', 'iconPopularity'),
// e.g. /icons/lab/burger, /icons/lab/burger/ or /icons/lab/burger?ref=homepage
routePattern: /^\/icons\/lab\/([^\/\?]+)(?:[\/\?]|$)/,
},
{
name: 'default',
iconsDir: path.resolve(currentDir, '../icons'),
outputDir: path.resolve(dataDirectory, 'iconPopularity'),
// e.g. /icons/activity, /icons/activity/ or /icons/activity?ref=homepage
routePattern: /^\/icons\/([^\/\?]+)(?:[\/\?]|$)/,
},
];
interface CollectionData extends IconCollection {
iconNames: string[];
counts: Record<string, number>;
}
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
const collections: CollectionData[] = await Promise.all(
iconCollections.map(async (collection) => {
const iconJsonFiles = await readSvgDirectory(collection.iconsDir, '.json');
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
const defaultIconNamePopularity: Record<string, number> = Object.fromEntries(
iconNames.map((iconName) => [iconName, 0])
return {
...collection,
iconNames,
counts: Object.fromEntries(iconNames.map((iconName) => [iconName, 0])),
};
}),
);
interface AnalyticsResponse {
@@ -35,19 +67,30 @@ interface AnalyticsResponse {
}[];
}
const writeIconPopularity = async (iconVisitCounts: Record<string, number>) => {
const writePopularityPromises = Object.entries(iconVisitCounts).map(([iconName, count]) => {
const location = path.resolve(iconPopularityDirectory, `${iconName}.json`);
const writeIconPopularity = async ({ name, outputDir, counts }: CollectionData) => {
if (fs.existsSync(outputDir)) {
fs.rmSync(outputDir, { recursive: true, force: true });
}
fs.mkdirSync(outputDir, { recursive: true });
const writePopularityPromises = Object.entries(counts).map(([iconName, count]) => {
const location = path.resolve(outputDir, `${iconName}.json`);
return fs.promises.writeFile(location, JSON.stringify({ count }, null, 2), 'utf-8');
});
await Promise.all(writePopularityPromises);
console.log('Successfully written icon popularity data for', writePopularityPromises.length, 'icons.');
console.log(
'Successfully written icon popularity data for',
writePopularityPromises.length,
`${name} icons.`,
);
};
const writeAllIconPopularity = () => Promise.all(collections.map(writeIconPopularity));
if (process.env.LUCIDE_ANALYTICS_TOKEN === undefined) {
console.warn('LUCIDE_ANALYTICS_TOKEN environment variable is not set. Writing default icon popularity data.');
await writeIconPopularity(defaultIconNamePopularity);
await writeAllIconPopularity();
process.exit(0);
}
@@ -76,29 +119,34 @@ try {
const analyticsData: AnalyticsResponse = await response.json();
const iconVisitCounts = analyticsData.results.reduce((acc, { dimensions, metrics }) => {
for (const { dimensions, metrics } of analyticsData.results) {
const [route] = dimensions;
const [count] = metrics;
if (!route.startsWith('/icons')) {
return acc
continue;
}
// Only match routes that start with /icons/ and end with an icon name, e.g. /icons/activity, /icons/activity/ or /icons/activity?ref=homepage
const match = route.match(/^\/icons\/([^\/\?]+)(?:[\/\?]|$)/);
if (match) {
const iconName = match[1];
if (iconNames.includes(iconName)) {
acc[iconName] = (acc[iconName] || 0) + count;
// Route each visit to the first collection whose pattern matches. Lab is
// checked first so `/icons/lab/foo` is not swallowed by the default pattern.
for (const collection of collections) {
const match = route.match(collection.routePattern);
if (!match) {
continue;
}
const iconName = match[1];
if (collection.iconNames.includes(iconName)) {
collection.counts[iconName] += count;
}
break;
}
}
return acc;
}, defaultIconNamePopularity);
await writeIconPopularity(iconVisitCounts);
await writeAllIconPopularity();
} catch (error) {
console.error('Error fetching analytics data:', error);
await writeIconPopularity(defaultIconNamePopularity);
await writeAllIconPopularity();
}

View File

@@ -0,0 +1,49 @@
import fs from 'fs';
import path from 'path';
import { readSvgDirectory, toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../lab');
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
const labIconPopularityDirectory = path.resolve(currentDir, '.vitepress/data/lab/iconPopularity');
const location = path.resolve(currentDir, labIconPopularityDirectory, 'index.ts');
if (fs.existsSync(location)) {
fs.unlinkSync(location);
}
if (!fs.existsSync(labIconPopularityDirectory)) {
fs.mkdirSync(labIconPopularityDirectory);
}
const iconMetaIndexFileImports = [];
const iconMetaIndexFileExports = [];
iconJsonFiles.forEach((iconJsonFile) => {
const iconName = path.basename(iconJsonFile, '.json');
iconMetaIndexFileImports.push(
`import ${toCamelCase(iconName)}Popularity from './${iconName}.json' with { type: 'json' };`,
);
iconMetaIndexFileExports.push(` '${iconName}': ${toCamelCase(iconName)}Popularity,`);
});
try {
await fs.promises.writeFile(
location,
`\
${iconMetaIndexFileImports.join('\n')}
export default {
${iconMetaIndexFileExports.join('\n')}
}
`,
'utf-8',
);
console.log('Successfully write icon json file index');
} catch (error) {
throw new Error(`Something went wrong generating icon json file index file,\n ${error}`);
}

View File

@@ -13,4 +13,4 @@
<path d="M15.697 14h5.606" />
<path d="m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16" />
<path d="M3.304 13h6.392" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 391 B

View File

@@ -21,10 +21,15 @@
"paid",
"partner",
"promo",
"sponsor"
"sponsor",
"audio description",
"video description",
"described video",
"visual description"
],
"categories": [
"multimedia",
"accessibility",
"notifications"
]
}

View File

@@ -11,10 +11,9 @@
>
<path d="M10 10H6" />
<path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2" />
<path
d="M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14" />
<path d="M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14" />
<path d="M8 8v4" />
<path d="M9 18h6" />
<circle cx="17" cy="18" r="2" />
<circle cx="7" cy="18" r="2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 550 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10 3a41 41 0 0 0 0 18" />
<path d="M14 3a41 41 0 0 1 0 18" />
<path d="M17 3a2 2 0 0 1 1.68.92 15.25 15.25 0 0 1 0 16.16A2 2 0 0 1 17 21H7a2 2 0 0 1-1.68-.92 15.25 15.25 0 0 1 0-16.16A2 2 0 0 1 7 3z" />
<path d="M3.84 17h16.32" />
<path d="M3.84 7h16.32" />
<path d="M10 3a41 41 0 000 18" />
<path d="M14 3a41 41 0 010 18" />
<path d="M16.997 21a2 2 0 001.68-.92 15.25 15.25 0 000-16.16 2 2 0 00-1.68-.92h-10a2 2 0 00-1.681.92 15.25 15.25 0 000 16.16 2 2 0 001.681.92z" />
<path d="M3.54 16h16.914" />
<path d="M3.54 8h16.914" />
</svg>

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -15,4 +15,4 @@
<path d="m4 8 2 1" />
<path d="m8 4 1 2" />
<path d="M9.698 14.19a.15.15 0 0 0 .112.112l2.074.489a.15.15 0 0 1 .072.252L10 17c-.7.7 0 1.69 0 2.5a1 1 0 0 1-5 0 .495.495 0 0 0-.5-.5 1 1 0 0 1 0-5c.81 0 1.8.7 2.5 0l1.956-1.957a.15.15 0 0 1 .252.072z" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 732 B

After

Width:  |  Height:  |  Size: 733 B

View File

@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 21V7" />
<path d="M12 5v16" />
<path d="m16 12 2 2 4-4" />
<path d="M22 6V4a1 1 0 0 0-1-1h-5a4 4 0 0 0-4 4 4 4 0 0 0-4-4H3a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h6a3 3 0 0 1 3 3 3 3 0 0 1 3-3h6a1 1 0 0 0 1-1v-1.3" />
<path d="M22 6V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2h4.001A2 2 0 0022 17v-1.344" />
</svg>

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 424 B

View File

@@ -1,7 +1,8 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"danielbayley"
"danielbayley",
"karsa-mistmere"
],
"use-cases": [],
"tags": [

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 7v14" />
<path d="M16 12h2" />
<path d="M16 8h2" />
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
<path d="M6 12h2" />
<path d="M6 8h2" />
<path d="M12 5v16" />
<path d="M16 13h2" />
<path d="M16 9h2" />
<path d="M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z" />
<path d="M6 13h2" />
<path d="M6 9h2" />
</svg>

Before

Width:  |  Height:  |  Size: 470 B

After

Width:  |  Height:  |  Size: 479 B

View File

@@ -3,7 +3,8 @@
"contributors": [
"colebemis",
"csandman",
"ericfennis"
"ericfennis",
"karsa-mistmere"
],
"use-cases": [],
"tags": [

View File

@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 7v14" />
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
<path d="M12 5v16" />
<path d="M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z" />
</svg>

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 387 B

View File

@@ -16,4 +16,4 @@
<path d="M8 8H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 1.414-.586" />
<path d="M9 13v2" />
<path d="M9.67 4H12v2.33" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 457 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M11 14h1v4" />
<path d="M16 2v4" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<rect x="3" y="4" width="18" height="18" rx="2" />
<path d="M11 13h1v4" />
<path d="M16 2v3" />
<path d="M3 9h18" />
<path d="M8 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 355 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m14 18 4 4 4-4" />
<path d="M16 2v4" />
<path d="M18 14v8" />
<path d="M21 11.354V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.343" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="m14 17 4 4 4-4" />
<path d="M16 2v3" />
<path d="M18 13v8" />
<path d="M21 10.354V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h7.343" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 407 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m14 18 4-4 4 4" />
<path d="M16 2v4" />
<path d="M18 22v-8" />
<path d="M21 11.343V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="m14 17 4-4 4 4" />
<path d="M16 2v3" />
<path d="M18 21v-8" />
<path d="M21 10.343V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h9" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 409 B

After

Width:  |  Height:  |  Size: 404 B

View File

@@ -9,9 +9,15 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<path d="M21 14V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8" />
<path d="M3 10h18" />
<path d="m16 20 2 2 4-4" />
<path d="M 19 3 L 5 3" />
<path d="M 21 13 L 21 5" />
<path d="M 21 5 A2 2 0 0 0 19 3" />
<path d="M 3 19 A2 2 0 0 0 5 21" />
<path d="M 3 5 L 3 19" />
<path d="M 5 3 A2 2 0 0 0 3 5" />
<path d="m16 19 2 2 4-4" />
<path d="M16 2v3" />
<path d="M3 9h18" />
<path d="M5 21 L12.5 21" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 534 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="m9 16 2 2 4-4" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
<path d="m9 15 2 2 4-4" />
</svg>

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 358 B

View File

@@ -10,9 +10,9 @@
stroke-linejoin="round"
>
<path d="M16 14v2.2l1.6 1" />
<path d="M16 2v4" />
<path d="M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5" />
<path d="M3 10h5" />
<path d="M8 2v4" />
<path d="M16 2v3" />
<path d="M21 7.338V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h2.338" />
<path d="M3 9h5.859" />
<path d="M8 2v3" />
<circle cx="16" cy="16" r="6" />
</svg>

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 422 B

View File

@@ -11,15 +11,15 @@
>
<path d="m15.228 16.852-.923-.383" />
<path d="m15.228 19.148-.923.383" />
<path d="M16 2v4" />
<path d="M16 2v3" />
<path d="m16.47 14.305.382.923" />
<path d="m16.852 20.772-.383.924" />
<path d="m19.148 15.228.383-.923" />
<path d="m19.53 21.696-.382-.924" />
<path d="m20.772 16.852.924-.383" />
<path d="m20.772 19.148.924.383" />
<path d="M21 10.592V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="m20.773 16.852.924-.383" />
<path d="m20.773 19.148.924.383" />
<path d="M21 10.5V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h5.5" />
<path d="M3 9h18" />
<path d="M8 2v3" />
<circle cx="18" cy="18" r="3" />
</svg>

Before

Width:  |  Height:  |  Size: 699 B

After

Width:  |  Height:  |  Size: 694 B

View File

@@ -9,14 +9,14 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="M8 14h.01" />
<path d="M12 14h.01" />
<path d="M16 14h.01" />
<path d="M8 18h.01" />
<path d="M12 18h.01" />
<path d="M16 18h.01" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
<path d="M8 13h.01" />
<path d="M12 13h.01" />
<path d="M16 13h.01" />
<path d="M8 17h.01" />
<path d="M12 17h.01" />
<path d="M16 17h.01" />
</svg>

Before

Width:  |  Height:  |  Size: 484 B

After

Width:  |  Height:  |  Size: 483 B

View File

@@ -9,9 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M3 20a2 2 0 0 0 2 2h10a2.4 2.4 0 0 0 1.706-.706l3.588-3.588A2.4 2.4 0 0 0 21 16V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" />
<path d="M15 22v-5a1 1 0 0 1 1-1h5" />
<path d="M8 2v4" />
<path d="M16 2v4" />
<path d="M3 10h18" />
<path d="M16 2v3" />
<path d="M21 15V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h10v-5a1 1 0 011-1za2.4 2.4 0 01-.706 1.706l-3.588 3.588A2.4 2.4 0 0115 21" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 417 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12.127 22H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5.125" />
<path d="M14.62 18.8A2.25 2.25 0 1 1 18 15.836a2.25 2.25 0 1 1 3.38 2.966l-2.626 2.856a.998.998 0 0 1-1.507 0z" />
<path d="M16 2v4" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="M12.127 21H5a2 2 0 01-2-2V5a2 2 0 012-2h14a2 2 0 012 2v5.125" />
<path d="M14.62 17.8A2.25 2.25 0 1118 14.836a2.25 2.25 0 113.38 2.966l-2.626 2.856a.998.998 0 01-1.507 0z" />
<path d="M16 2v3" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 464 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="M10 16h4" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
<path d="M10 15h4" />
</svg>

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 353 B

View File

@@ -9,9 +9,9 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M16 19h6" />
<path d="M16 2v4" />
<path d="M21 15V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8.5" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="M16 18h6" />
<path d="M16 2v3" />
<path d="M21 14V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h8.3" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 371 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4.2 4.2A2 2 0 0 0 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 1.82-1.18" />
<path d="M21 15.5V6a2 2 0 0 0-2-2H9.5" />
<path d="M16 2v4" />
<path d="M3 10h7" />
<path d="M21 10h-5.5" />
<path d="M16 2v3" />
<path d="m2 2 20 20" />
<path d="M21 9h-5.5" />
<path d="M3 9h6" />
<path d="M3.586 3.586A2 2 0 003 5v14a2 2 0 002 2h14a2 2 0 001.414-.586" />
<path d="M8.656 3H19a2 2 0 012 2v10.344" />
</svg>

Before

Width:  |  Height:  |  Size: 429 B

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="M10 16h4" />
<path d="M12 14v4" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
<path d="M10 15h4" />
<path d="M12 13v4" />
</svg>

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 377 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M16 19h6" />
<path d="M16 2v4" />
<path d="M19 16v6" />
<path d="M21 12.598V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8.5" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="M16 18h6" />
<path d="M16 2v3" />
<path d="M19 15v6" />
<path d="M21 11.5V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h8.3" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 397 B

View File

@@ -9,12 +9,12 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M16 2v4" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<path d="M17 14h-6" />
<path d="M13 18H7" />
<path d="M7 14h.01" />
<path d="M17 18h.01" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M16 2v3" />
<path d="M3 9h18" />
<path d="M8 2v3" />
<path d="M17 13h-6" />
<path d="M13 17H7" />
<path d="M7 13h.01" />
<path d="M17 17h.01" />
</svg>

Before

Width:  |  Height:  |  Size: 430 B

After

Width:  |  Height:  |  Size: 429 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M16 2v4" />
<path d="M21 11.75V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.25" />
<path d="m22 22-1.875-1.875" />
<path d="M3 10h18" />
<path d="M8 2v4" />
<circle cx="18" cy="18" r="3" />
<path d="M16 2v3" />
<path d="M21 10.69V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h7.25" />
<path d="m22 21-1.875-1.875" />
<path d="M3 9h18" />
<path d="M8 2v3" />
<circle cx="18" cy="17" r="3" />
</svg>

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 420 B

View File

@@ -10,11 +10,11 @@
stroke-linejoin="round"
>
<path d="M11 10v4h4" />
<path d="m11 14 1.535-1.605a5 5 0 0 1 8 1.5" />
<path d="M16 2v4" />
<path d="m21 18-1.535 1.605a5 5 0 0 1-8-1.5" />
<path d="m11 14 1.535-1.605a5 5 0 018 1.5" />
<path d="M16 2v3" />
<path d="m21 18-1.535 1.605a5 5 0 01-8-1.5" />
<path d="M21 22v-4h-4" />
<path d="M21 8.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h4.3" />
<path d="M3 10h4" />
<path d="M8 2v4" />
<path d="M21 8.517V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h3.517" />
<path d="M3 9h4" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<path d="M21 13V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8" />
<path d="M3 10h18" />
<path d="m17 22 5-5" />
<path d="m17 17 5 5" />
<path d="M16 2v3" />
<path d="m17 16 5 5" />
<path d="m17 21 5-5" />
<path d="M21 12V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h8" />
<path d="M3 9h18" />
<path d="M8 2v3" />
</svg>

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 397 B

View File

@@ -9,10 +9,10 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="m14 14-4 4" />
<path d="m10 14 4 4" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
<path d="m14 13-4 4" />
<path d="m10 13 4 4" />
</svg>

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 381 B

View File

@@ -9,8 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 2v4" />
<path d="M16 2v4" />
<rect width="18" height="18" x="3" y="4" rx="2" />
<path d="M3 10h18" />
<path d="M8 2v3" />
<path d="M16 2v3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
<path d="M3 9h18" />
</svg>

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 329 B

View File

@@ -11,4 +11,4 @@
>
<rect width="18" height="14" x="3" y="5" rx="2" ry="2" />
<path d="M7 15h4M15 15h2M7 11h2M13 11h4" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 314 B

View File

@@ -7,9 +7,18 @@
],
"use-cases": [],
"tags": [
"chromecast",
"airplay",
"screen"
"stream",
"streaming",
"screen",
"display",
"wireless",
"broadcast",
"transmit",
"media",
"receiver",
"remote display",
"screen sharing",
"media streaming"
],
"categories": [
"devices",

View File

@@ -8,10 +8,6 @@
"tags": [
"stories",
"social media",
"instagram",
"facebook",
"meta",
"snapchat",
"sharing",
"content"
],

View File

@@ -16,4 +16,4 @@
<path d="M2.83 16a10 10 0 0 0 2.43 3.4" />
<path d="M4.636 5.235a10 10 0 0 1 .891-.857" />
<path d="M8.644 21.42a10 10 0 0 0 7.631-.38" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 487 B

View File

@@ -3,7 +3,8 @@
"contributors": [
"irvineacosta",
"danielbayley",
"karsa-mistmere"
"karsa-mistmere",
"kamilasw"
],
"use-cases": [],
"tags": [

View File

@@ -9,16 +9,16 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10.5 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5.5" />
<path d="m14.3 19.6 1-.4" />
<path d="M15 3v7.5" />
<path d="m15.2 16.9-.9-.3" />
<path d="m16.6 21.7.3-.9" />
<path d="m16.8 15.3-.4-1" />
<path d="m19.1 15.2.3-.9" />
<path d="m19.6 21.7-.4-1" />
<path d="m20.7 16.8 1-.4" />
<path d="m21.7 19.4-.9-.3" />
<path d="M10.6 21H5a2 2 0 01-2-2V5a2 2 0 012-2h14a2 2 0 012 2v5.6" />
<path d="m14.305 19.53.923-.382" />
<path d="M15 3v7.6" />
<path d="m15.229 16.852-.924-.383" />
<path d="m16.852 15.228-.383-.923" />
<path d="m16.852 20.772-.383.924" />
<path d="m19.148 15.228.383-.923" />
<path d="m19.53 21.696-.382-.924" />
<path d="m20.773 16.852.922-.383" />
<path d="m20.773 19.148.922.383" />
<path d="M9 3v18" />
<circle cx="18" cy="18" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 617 B

After

Width:  |  Height:  |  Size: 675 B

View File

@@ -11,7 +11,6 @@
"east",
"south",
"west",
"safari",
"browser"
],
"categories": [

View File

@@ -7,8 +7,7 @@
"tags": [
"pc",
"chassis",
"codespaces",
"github"
"codespaces"
],
"categories": [
"devices",

View File

@@ -10,8 +10,8 @@
stroke-linejoin="round"
>
<path d="M16 2v2" />
<path d="M17.915 22a6 6 0 0 0-12 0" />
<path d="M17.915 21a6 6 0 10-12 0" />
<path d="M8 2v2" />
<circle cx="12" cy="12" r="4" />
<rect x="3" y="4" width="18" height="18" rx="2" />
<circle cx="12" cy="11" r="4" />
<rect x="3" y="3" width="18" height="18" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 382 B

After

Width:  |  Height:  |  Size: 381 B

View File

@@ -10,8 +10,8 @@
stroke-linejoin="round"
>
<path d="M16 2v2" />
<path d="M7 22v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2" />
<path d="M7 21v-2a2 2 0 012-2h6a2 2 0 012 2v2" />
<path d="M8 2v2" />
<circle cx="12" cy="11" r="3" />
<rect x="3" y="4" width="18" height="18" rx="2" />
<circle cx="12" cy="10" r="3" />
<rect x="3" y="3" width="18" height="18" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 393 B

View File

@@ -9,7 +9,6 @@
"shipping",
"freight",
"supply chain",
"docker",
"environment",
"devops",
"code",

View File

@@ -11,4 +11,4 @@
>
<path d="M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z" />
<path d="M8 12h8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 379 B

View File

@@ -12,4 +12,4 @@
<path d="M12 8v8" />
<path d="M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z" />
<path d="M8 12h8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 402 B

View File

@@ -3,13 +3,33 @@
"contributors": [
"colebemis",
"csandman",
"ericfennis"
"ericfennis",
"karsa-mistmere"
],
"use-cases": [
"Representing writing, authorship, or creative composition",
"Representing literature, poetry, publishing, or editorial content",
"Representing quills, manuscripts, or historical writing",
"Representing birds, plumage, wildlife, or nature",
"Representing lightness, softness, delicacy, or weight"
],
"use-cases": [],
"tags": [
"logo"
"quill",
"plume",
"writing",
"author",
"literature",
"poetry",
"manuscript",
"bird",
"plumage",
"lightweight",
"soft"
],
"categories": [
"gaming"
"nature",
"animals",
"gaming",
"text"
]
}

View File

@@ -9,7 +9,7 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z" />
<path d="M14.086 18.412A2 2 0 0112.67 19H5v-7.672a2 2 0 01.586-1.414L11.75 3.75a6 6 0 118.49 8.49z" />
<path d="M16 8 2 22" />
<path d="M17.5 15H9" />
<path d="M17.488 15H9" />
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 367 B

View File

@@ -10,4 +10,4 @@
stroke-linejoin="round"
>
<path d="M18 22V2.8a.8.8 0 0 0-1.17-.71L5.45 7.78a.8.8 0 0 0 0 1.44L18 15.5" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 290 B

View File

@@ -9,12 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M11.146 15.854a1.207 1.207 0 0 1 1.708 0l1.56 1.56A2 2 0 0 1 15 18.828V21a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-2.172a2 2 0 0 1 .586-1.414z" />
<path
d="M18.828 15a2 2 0 0 1-1.414-.586l-1.56-1.56a1.207 1.207 0 0 1 0-1.708l1.56-1.56A2 2 0 0 1 18.828 9H21a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1z" />
<path
d="M6.586 14.414A2 2 0 0 1 5.172 15H3a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2.172a2 2 0 0 1 1.414.586l1.56 1.56a1.207 1.207 0 0 1 0 1.708z" />
<path
d="M9 3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2.172a2 2 0 0 1-.586 1.414l-1.56 1.56a1.207 1.207 0 0 1-1.708 0l-1.56-1.56A2 2 0 0 1 9 5.172z" />
<path d="M11.146 15.854a1.207 1.207 0 0 1 1.708 0l1.56 1.56A2 2 0 0 1 15 18.828V21a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-2.172a2 2 0 0 1 .586-1.414z" />
<path d="M18.828 15a2 2 0 0 1-1.414-.586l-1.56-1.56a1.207 1.207 0 0 1 0-1.708l1.56-1.56A2 2 0 0 1 18.828 9H21a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1z" />
<path d="M6.586 14.414A2 2 0 0 1 5.172 15H3a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2.172a2 2 0 0 1 1.414.586l1.56 1.56a1.207 1.207 0 0 1 0 1.708z" />
<path d="M9 3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2.172a2 2 0 0 1-.586 1.414l-1.56 1.56a1.207 1.207 0 0 1-1.708 0l-1.56-1.56A2 2 0 0 1 9 5.172z" />
</svg>

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 792 B

View File

@@ -14,4 +14,4 @@
<path d="M9 3 3 9" />
<path d="M9 9 3 3" />
<circle cx="18" cy="18" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 352 B

After

Width:  |  Height:  |  Size: 353 B

View File

@@ -1,26 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"ericfennis",
"danielbayley",
"jguddas",
"karsa-mistmere"
],
"use-cases": [],
"tags": [
"time",
"redo",
"undo",
"rewind",
"timeline",
"version",
"time machine",
"backup",
"rotate",
"ccw"
],
"categories": [
"arrows",
"time"
]
}

View File

@@ -14,4 +14,4 @@
<path d="M16.899 22A5 5 0 0 0 7.1 22" />
<path d="m9 2 3 6" />
<circle cx="12" cy="15" r="3" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 427 B

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -19,4 +19,4 @@
<path d="M20 20H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2" />
<path d="M6 8h.01" />
<path d="M8 12h.01" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 518 B

After

Width:  |  Height:  |  Size: 519 B

View File

@@ -14,4 +14,4 @@
<path d="M19 14v6" />
<path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 .825.178" />
<path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l2.116-.962" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 540 B

View File

@@ -0,0 +1,31 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"samuelalake"
],
"use-cases": [
"turning off auto layout in a design inspector",
"switching a dashboard section to free drag-and-drop placement",
"selecting freeform arrangement in a page builder",
"indicating unstructured layout mode in a whiteboard or canvas app",
"representing elements not aligned to a grid"
],
"tags": [
"layout",
"freeform",
"free",
"absolute",
"position",
"auto layout",
"unaligned",
"scattered",
"arrange",
"blocks",
"canvas",
"frame"
],
"categories": [
"design",
"layout"
]
}

15
icons/layout-freeform.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"
>
<rect width="7" height="7" x="3" y="3" rx="1" />
<rect width="7" height="7" x="14" y="4" rx="1" />
<rect width="7" height="7" x="4" y="14" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 363 B

View File

@@ -9,6 +9,5 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M13.433 2a1 1 0 0 1 .824.448 18 18 0 0 1 0 19.104 1 1 0 0 1-.824.448h-2.866a1 1 0 0 1-.824-.448 18 18 0 0 1 0-19.104A1 1 0 0 1 10.567 2z" />
<path d="M13.433 2a1 1 0 0 1 .824.448 18 18 0 0 1 0 19.104 1 1 0 0 1-.824.448h-2.866a1 1 0 0 1-.824-.448 18 18 0 0 1 0-19.104A1 1 0 0 1 10.567 2z" />
</svg>

Before

Width:  |  Height:  |  Size: 364 B

After

Width:  |  Height:  |  Size: 360 B

View File

@@ -10,4 +10,4 @@
stroke-linejoin="round"
>
<path d="M7 3.5c5-2 7 2.5 3 4C1.5 10 2 15 5 16c5 2 9-10 14-7s.5 13.5-4 12c-5-2.5.5-11 6-2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 304 B

View File

@@ -0,0 +1,36 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere",
"jguddas"
],
"use-cases": [
"representing recorded speech with visible audio activity",
"indicating podcast, voice note, or narration recording tools",
"showing voice input for transcription, dictation, or AI assistants",
"marking features that analyze, clean up, or enhance microphone audio",
"identifying controls for speech capture and sound processing workflows"
],
"tags": [
"podcast",
"audio",
"waveform",
"sound waves",
"microphone",
"talk",
"voice",
"speech",
"stream",
"recording",
"transcription",
"dictation",
"voice assistant",
"noise cancellation",
"sound processing"
],
"categories": [
"devices",
"communication",
"multimedia"
]
}

21
icons/mic-audio-lines.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"
>
<path d="M10 3v2.341" />
<path d="M12 17v4" />
<path d="M14 5v.341" />
<path d="M18 5v13" />
<path d="M2 10v3" />
<path d="M22 10v3" />
<path d="M6 6v11" />
<path d="M9 21h6" />
<rect width="4" height="8" x="10" y="9" rx="2" />
</svg>

After

Width:  |  Height:  |  Size: 454 B

46
icons/mic-signal.json Normal file
View File

@@ -0,0 +1,46 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere",
"jguddas"
],
"use-cases": [
"representing a microphone actively broadcasting or transmitting voice",
"indicating live podcast, radio, streaming, or voice channel features",
"showing wireless microphone connections or remote audio capture",
"marking push-to-talk, voice chat, or walkie-talkie communication controls",
"identifying features that send spoken audio across a network or airwaves"
],
"tags": [
"podcast",
"audio",
"broadcast",
"signal",
"wireless",
"radio",
"airwaves",
"microphone",
"talk",
"voice",
"speech",
"stream",
"live",
"voice chat",
"push to talk",
"transmission"
],
"categories": [
"devices",
"communication",
"connectivity",
"multimedia"
],
"aliases": [
{
"name": "podcast",
"deprecated": true,
"deprecationReason": "alias.name",
"toBeRemovedInVersion": "v1.0"
}
]
}

19
icons/mic-signal.svg Normal file
View File

@@ -0,0 +1,19 @@
<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="M12 17v4" />
<path d="M18 11a6 6 0 00-3-5.197" />
<path d="M2 11a10 10 0 015-8.662" />
<path d="M22 11a10 10 0 00-5-8.662" />
<path d="M6 11a6 6 0 013-5.197" />
<path d="M9 21h6" />
<rect x="10" y="9" width="4" height="8" rx="2" />
</svg>

After

Width:  |  Height:  |  Size: 463 B

View File

@@ -12,4 +12,4 @@
<path d="M11 6 8 9" />
<path d="m16 7-8 8" />
<rect x="4" y="2" width="16" height="20" rx="2" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 311 B

View File

@@ -14,4 +14,4 @@
<path d="M15 7.5 9.5 13" />
<path d="M7 22h10" />
<circle cx="12" cy="10" r="8" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 350 B

40
icons/mosque.json Normal file
View File

@@ -0,0 +1,40 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"rrod497",
"iskepr"
],
"use-cases": [
"Representing a mosque as a building type or place of worship",
"Categorizing religious and spiritual points of interest on a map"
],
"tags": [
"mosque",
"masjid",
"islam",
"muslim",
"ramadan",
"eid",
"prayer",
"worship",
"building",
"minaret",
"dome",
"architecture",
"faith",
"religion",
"holy",
"sacred",
"landmark",
"community",
"spiritual",
"tourism",
"map",
"heritage"
],
"categories": [
"buildings",
"navigation",
"travel"
]
}

18
icons/mosque.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"
>
<path d="M12.268 2a2 2 0 003.465 2" />
<path d="M14 5 L14 8" />
<path d="M16 22v-3a2 2 0 00-4 0v3" />
<path d="M21 13c-.662-1.497-1.666-2.753-2.9-3.63C16.825 8.47 15.422 8 14 8s-2.826.47-4.1 1.37C8.668 10.248 7.663 11.504 7 13z" />
<path d="M3 9h4" />
<path d="M7 22V6a5 5 0 00-2-4 5 5 0 00-2 4v14a2 2 0 002 2h14a2 2 0 002-2v-7" />
</svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@@ -14,4 +14,4 @@
<path d="M14 3v11" />
<path d="m18 14 4 4H2" />
<path d="m22 18-4 4" />
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 349 B

View File

@@ -1,24 +0,0 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"iiaishwarya",
"ericfennis",
"karsa-mistmere",
"jguddas"
],
"use-cases": [],
"tags": [
"audio",
"music",
"mic",
"talk",
"voice",
"subscribe",
"subscription",
"stream"
],
"categories": [
"multimedia",
"social"
]
}

Some files were not shown because too many files have changed in this diff Show More