Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f732b411d | ||
|
|
ce09c31f08 | ||
|
|
c2b059fb60 | ||
|
|
b3c80d027a | ||
|
|
20f30bb5ea | ||
|
|
c47ae67a3b | ||
|
|
7866a5a5c6 | ||
|
|
92bc88b001 | ||
|
|
e75fbcdec4 | ||
|
|
4cef8283a7 | ||
|
|
330f4b37db | ||
|
|
fd31cb44a8 | ||
|
|
790d30dbfa | ||
|
|
e7c075785f | ||
|
|
6d4c91707d | ||
|
|
c0ea92ebe7 | ||
|
|
42dc5508dd | ||
|
|
4dda432471 | ||
|
|
0775d8647e | ||
|
|
83ef8fc98d | ||
|
|
5b56ef705d | ||
|
|
dafe529892 | ||
|
|
151c5b145c | ||
|
|
d6f9043096 | ||
|
|
b4405f05ab | ||
|
|
9076da5f1b | ||
|
|
2e7d806282 | ||
|
|
c4e5730bc4 | ||
|
|
02b35e2518 | ||
|
|
f183c3ba20 | ||
|
|
67e9efb801 | ||
|
|
2e4c9a65be | ||
|
|
de4e8d0acd | ||
|
|
1f113d4274 | ||
|
|
dffffc7aff | ||
|
|
f78061b488 | ||
|
|
076e0bbcd9 | ||
|
|
33bb95edcd | ||
|
|
4c8650a7bf | ||
|
|
ebf400befd | ||
|
|
0f6dc52a8a | ||
|
|
83d5ccc3e8 | ||
|
|
a3886eb829 | ||
|
|
86957f0205 | ||
|
|
465b98df74 | ||
|
|
d3b2255c0a | ||
|
|
a4beac39a3 | ||
|
|
53311befff | ||
|
|
156b3379e4 | ||
|
|
8dd82dd592 | ||
|
|
80d6f737e0 | ||
|
|
a94044cc3a | ||
|
|
2c46ea9948 | ||
|
|
190e8372af | ||
|
|
d3826ce952 | ||
|
|
ee66dd258d | ||
|
|
265770857f | ||
|
|
1c20fc66d7 | ||
|
|
c34c5f2aea | ||
|
|
6432dddfe0 | ||
|
|
028fc12657 | ||
|
|
2e794a296a | ||
|
|
be59e647c1 |
62
.github/workflows/ci.yml
vendored
@@ -7,6 +7,10 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- icons/**/*.svg
|
- icons/**/*.svg
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write # Required for OIDC
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create-release:
|
create-release:
|
||||||
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)')
|
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)')
|
||||||
@@ -15,9 +19,9 @@ jobs:
|
|||||||
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -32,25 +36,19 @@ jobs:
|
|||||||
id: latest-tag
|
id: latest-tag
|
||||||
run: echo "LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_OUTPUT
|
run: echo "LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Log latest tag
|
||||||
|
run: echo '${{ steps.latest-tag.outputs.LATEST_TAG }}'
|
||||||
|
|
||||||
- name: Check if we can patch
|
- name: Check if we can patch
|
||||||
run: .github/workflows/version-up.sh --minor
|
run: pnpm semver $LATEST_TAG -i minor
|
||||||
|
env:
|
||||||
|
LATEST_TAG: ${{ steps.latest-tag.outputs.LATEST_TAG }}
|
||||||
|
|
||||||
- name: Create new version
|
- name: Create new version
|
||||||
id: new-version
|
id: new-version
|
||||||
run: echo "NEW_VERSION=$(.github/workflows/version-up.sh --minor)" >> $GITHUB_OUTPUT
|
run: echo "NEW_VERSION=$(pnpm semver $LATEST_TAG -i minor)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Create change log
|
|
||||||
id: change-log
|
|
||||||
run: |
|
|
||||||
CHANGE_LOG=$(pnpm run generate:changelog --old-tag=${{ steps.latest-tag.outputs.LATEST_TAG }})
|
|
||||||
CHANGE_LOG=$(tail -n +5 <<< $CHANGE_LOG)
|
|
||||||
echo $CHANGE_LOG
|
|
||||||
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
|
|
||||||
echo "CHANGE_LOG<<$EOF" >> $GITHUB_OUTPUT
|
|
||||||
echo "$CHANGE_LOG" >> $GITHUB_OUTPUT
|
|
||||||
echo "$EOF" >> $GITHUB_OUTPUT
|
|
||||||
env:
|
env:
|
||||||
GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
|
LATEST_TAG: ${{ steps.latest-tag.outputs.LATEST_TAG }}
|
||||||
|
|
||||||
- name: Check output
|
- name: Check output
|
||||||
run: |
|
run: |
|
||||||
@@ -64,38 +62,6 @@ jobs:
|
|||||||
name: Version ${{ steps.new-version.outputs.NEW_VERSION }}
|
name: Version ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
|
|
||||||
test-semantic-release:
|
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Semantic Release
|
|
||||||
id: semantic
|
|
||||||
uses: cycjimmy/semantic-release-action@v4
|
|
||||||
with:
|
|
||||||
tag_format: ${version}
|
|
||||||
branches: |
|
|
||||||
['new-release-workflow']
|
|
||||||
extends: |
|
|
||||||
semantic-release-monorepo
|
|
||||||
extra_plugins: |
|
|
||||||
@semantic-release/github
|
|
||||||
@semantic-release/git
|
|
||||||
@semantic-release/release-notes-generator
|
|
||||||
conventional-changelog-conventionalcommits
|
|
||||||
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Log output
|
|
||||||
if: steps.semantic.outputs.new_release_published == 'true'
|
|
||||||
run: |
|
|
||||||
echo ${{ steps.semantic.outputs.new_release_version }}
|
|
||||||
echo ${{ steps.semantic.outputs.new_release_major_version }}
|
|
||||||
echo ${{ steps.semantic.outputs.new_release_minor_version }}
|
|
||||||
echo ${{ steps.semantic.outputs.new_release_patch_version }}
|
|
||||||
|
|
||||||
start-release:
|
start-release:
|
||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
needs: create-release
|
needs: create-release
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Close Issue with Banned Phrases
|
name: Close Icon Requests with Brand Terms
|
||||||
|
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
@@ -11,25 +11,38 @@ jobs:
|
|||||||
issues: write
|
issues: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Check for blocked phrases in issue title
|
- name: Load stopwords from JSON & check issue title & body
|
||||||
|
if: contains(github.event.issue.labels.*.name, '🙌 icon request')
|
||||||
run: |
|
run: |
|
||||||
ISSUE_TITLE=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
|
ISSUE_TITLE=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
|
||||||
BLOCKED_PHRASES=("twitter" "whatsapp" "logo" "google" "tiktok" "facebook" "slack" "discord" "bluesky" "spotify" "behance" "pix" "x.com" "telegram")
|
ISSUE_BODY=$(jq -r '.issue.body // ""' "$GITHUB_EVENT_PATH")
|
||||||
|
ICON_NAME_SECTION=$(printf '%s\n' "$ISSUE_BODY" | awk '/### Icon name/{flag=1; next} /^### /{flag=0} flag')
|
||||||
|
|
||||||
# Check title and body for blocked phrases
|
jq -r 'to_entries[] | "\(.key) \(.value)"' brand-stopwords.json | while read -r KEY VALUE; do
|
||||||
for PHRASE in "${BLOCKED_PHRASES[@]}"
|
SAFE_KEY=$(printf '%s\n' "$KEY" | sed 's/[][\.^$*]/\\&/g')
|
||||||
do
|
SAFE_VALUE=$(printf '%s\n' "$VALUE" | sed 's/[][\.^$*]/\\&/g')
|
||||||
if echo "$ISSUE_TITLE" | grep -i "$PHRASE"; then
|
|
||||||
gh issue close ${{ github.event.issue.number }} --reason "not planned" --comment "This looks like a duplicate, use the [search](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+$PHRASE) to find similar issues.
|
|
||||||
|
|
||||||
Read [our official statement about brand logos in Lucide](https://github.com/lucide-icons/lucide/blob/main/BRAND_LOGOS_STATEMENT.md).
|
if echo "$ISSUE_TITLE" | grep -iqE "$SAFE_KEY|$SAFE_VALUE" || \
|
||||||
|
{ [ -n "$ICON_NAME_SECTION" ] && echo "$ICON_NAME_SECTION" | grep -iqE "$SAFE_KEY|$SAFE_VALUE"; }; then
|
||||||
|
|
||||||
|
gh issue close ${{ github.event.issue.number }} \
|
||||||
|
--reason "not_planned" \
|
||||||
|
--comment "It looks like this request is about **${VALUE}**, which is a brand logo.
|
||||||
|
|
||||||
|
Lucide **does not accept** brand logos, and we do not plan to add them in the future. This is due to a combination of **legal restrictions**, **design consistency concerns**, and **practical maintenance reasons**.
|
||||||
|
|
||||||
|
[Click here to read our official statement about brand logos in Lucide.](./BRAND_LOGOS_STATEMENT.md)
|
||||||
|
|
||||||
|
You can [search for similar issues.](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+${VALUE})
|
||||||
|
|
||||||
|
We’re always happy to help on [Discord](https://discord.gg/EH6nSts)."
|
||||||
|
|
||||||
Always happy to help on [Discord](https://discord.gg/EH6nSts)."
|
|
||||||
gh issue lock ${{ github.event.issue.number }} --reason spam
|
gh issue lock ${{ github.event.issue.number }} --reason spam
|
||||||
exit 1
|
exit 0
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
|||||||
2
.github/workflows/labeler.yml
vendored
@@ -9,5 +9,5 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/labeler@v5
|
- uses: actions/labeler@v5
|
||||||
|
|||||||
4
.github/workflows/lint-code.yml
vendored
@@ -9,9 +9,9 @@ jobs:
|
|||||||
lint-code:
|
lint-code:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
6
.github/workflows/linting-icons.yml
vendored
@@ -13,8 +13,8 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
- name: Get changed files
|
- name: Get changed files
|
||||||
@@ -34,6 +34,6 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Check Uniqueness of Aliases
|
- name: Check Uniqueness of Aliases
|
||||||
run: "! cat <(printf \"%s\\n\" icons/*.json | while read -r name; do basename \"$name\" .json; done) <(jq -cr 'select(.aliases) | .aliases[] | if type==\"string\" then . else .name end' icons/*.json) | sort | uniq -c | grep -ve '^\\s*1 '"
|
run: "! cat <(printf \"%s\\n\" icons/*.json | while read -r name; do basename \"$name\" .json; done) <(jq -cr 'select(.aliases) | .aliases[] | if type==\"string\" then . else .name end' icons/*.json) | sort | uniq -c | grep -ve '^\\s*1 '"
|
||||||
|
|||||||
8
.github/workflows/lucide-angular.yml
vendored
@@ -11,9 +11,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -27,9 +27,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
4
.github/workflows/lucide-astro.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|||||||
4
.github/workflows/lucide-font.yml
vendored
@@ -10,9 +10,9 @@ jobs:
|
|||||||
lucide-font:
|
lucide-font:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
4
.github/workflows/lucide-preact.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
lucide-preact:
|
lucide-preact:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-react-native.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-react.yml
vendored
@@ -14,9 +14,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -30,9 +30,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
4
.github/workflows/lucide-shared.yml
vendored
@@ -10,9 +10,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-solid.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
4
.github/workflows/lucide-static.yml
vendored
@@ -11,9 +11,9 @@ jobs:
|
|||||||
lucide-static:
|
lucide-static:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-svelte-5.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-svelte.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide-vue-next.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
8
.github/workflows/lucide.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -28,9 +28,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: icons/*.svg
|
files: icons/*.svg
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
- name: Install svgson for code preview (safer and faster than installing all deps)
|
- name: Install svgson for code preview (safer and faster than installing all deps)
|
||||||
run: npm install svgson@5.3.1 --force
|
run: npm install svgson@5.3.1 --force
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# We checkout the main branch of main repository for security reasons.
|
# We checkout the main branch of main repository for security reasons.
|
||||||
# This is to prevent the workflow from running on a forked repository.
|
# This is to prevent the workflow from running on a forked repository.
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
repository: lucide-icons/lucide
|
repository: lucide-icons/lucide
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
|
|||||||
37
.github/workflows/release.yml
vendored
@@ -18,9 +18,13 @@ on:
|
|||||||
description: Version
|
description: Version
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write # Required for OIDC
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-release:
|
pre-release:
|
||||||
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere"]', github.actor)
|
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere", "jguddas"]', github.actor)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
VERSION: ${{ steps.get_version.outputs.VERSION }}
|
VERSION: ${{ steps.get_version.outputs.VERSION }}
|
||||||
@@ -39,7 +43,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre-release
|
needs: pre-release
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write # Required for OIDC
|
||||||
|
contents: read
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -57,9 +62,9 @@ jobs:
|
|||||||
'@lucide/svelte',
|
'@lucide/svelte',
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -67,9 +72,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ inputs.NPM_TOKEN || secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set new version
|
- name: Set new version
|
||||||
run: pnpm --filter ${{ matrix.package }} version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
run: pnpm --filter ${{ matrix.package }} version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
||||||
|
|
||||||
@@ -89,12 +91,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [pre-release, lucide-font]
|
needs: [pre-release, lucide-font]
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write # Required for OIDC
|
||||||
|
contents: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -102,9 +106,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Set Auth Token
|
|
||||||
run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set new version
|
- name: Set new version
|
||||||
run: pnpm --filter lucide-static version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
run: pnpm --filter lucide-static version --new-version ${{ needs.pre-release.outputs.VERSION }} --no-git-tag-version
|
||||||
|
|
||||||
@@ -124,9 +125,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre-release
|
needs: pre-release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
node-version-file: 'package.json'
|
node-version-file: 'package.json'
|
||||||
@@ -150,9 +151,11 @@ jobs:
|
|||||||
if: github.repository == 'lucide-icons/lucide'
|
if: github.repository == 'lucide-icons/lucide'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [pre-release, lucide-font]
|
needs: [pre-release, lucide-font]
|
||||||
|
permissions:
|
||||||
|
id-token: write # Required for OIDC
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
- name: Zip font and icons
|
- name: Zip font and icons
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
5
.github/workflows/request-review.yml
vendored
@@ -2,7 +2,8 @@ name: 'Request Review'
|
|||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened]
|
types: [opened]
|
||||||
paths: icons/*.svg
|
paths:
|
||||||
|
- icons/*.svg
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
request-review:
|
request-review:
|
||||||
@@ -12,7 +13,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||||
|
|||||||
284
.github/workflows/version-up.sh
vendored
@@ -1,284 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
## Copyright (C) 2017, Oleksandr Kucherenko
|
|
||||||
## Last revisit: 2017-09-29
|
|
||||||
|
|
||||||
## get highest version tag for all branches
|
|
||||||
function highest_tag(){
|
|
||||||
local TAG=$(git describe --tags `git rev-list --tags --max-count=1`)
|
|
||||||
echo "$TAG"
|
|
||||||
}
|
|
||||||
|
|
||||||
## extract current branch name
|
|
||||||
function current_branch(){
|
|
||||||
## expected: heads/{branch_name}
|
|
||||||
## expected: {branch_name}
|
|
||||||
local BRANCH=$(git rev-parse --abbrev-ref HEAD | cut -d"/" -f2)
|
|
||||||
echo "$BRANCH"
|
|
||||||
}
|
|
||||||
|
|
||||||
## get latest/head commit hash number
|
|
||||||
function head_hash(){
|
|
||||||
local COMMIT_HASH=$(git rev-parse --verify HEAD)
|
|
||||||
echo "$COMMIT_HASH"
|
|
||||||
}
|
|
||||||
|
|
||||||
## extract tag commit hash code, tag name provided by argument
|
|
||||||
function tag_hash(){
|
|
||||||
local TAG_HASH=$(git log -1 --format=format:"%H" $1 2>/dev/null | tail -n1)
|
|
||||||
echo "$TAG_HASH"
|
|
||||||
}
|
|
||||||
|
|
||||||
## get latest revision number
|
|
||||||
function latest_revision(){
|
|
||||||
local REV=$(git rev-list --count HEAD 2>/dev/null)
|
|
||||||
echo "$REV"
|
|
||||||
}
|
|
||||||
|
|
||||||
## parse last found tag, extract it PARTS
|
|
||||||
function parse_last(){
|
|
||||||
local position=$(($1-1))
|
|
||||||
|
|
||||||
# two parts found only
|
|
||||||
local SUBS=( ${PARTS[$position]//-/ } )
|
|
||||||
#echo ${SUBS[@]}, size: ${#SUBS}
|
|
||||||
|
|
||||||
# found NUMBER
|
|
||||||
PARTS[$position]=${SUBS[0]}
|
|
||||||
#echo ${PARTS[@]}
|
|
||||||
|
|
||||||
# found SUFFIX
|
|
||||||
if [[ ${#SUBS} -ge 1 ]]; then
|
|
||||||
PARTS[4]=${SUBS[1],,} #lowercase
|
|
||||||
#echo ${PARTS[@]}, ${SUBS[@]}
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
## increment REVISION part, don't touch STAGE
|
|
||||||
function increment_revision(){
|
|
||||||
PARTS[3]=$(( PARTS[3] + 1 ))
|
|
||||||
IS_DIRTY=1
|
|
||||||
}
|
|
||||||
|
|
||||||
## increment PATCH part, reset all other lower PARTS, don't touch STAGE
|
|
||||||
function increment_patch(){
|
|
||||||
PARTS[2]=$(( PARTS[2] + 1 ))
|
|
||||||
PARTS[3]=0
|
|
||||||
IS_DIRTY=1
|
|
||||||
}
|
|
||||||
|
|
||||||
## increment MINOR part, reset all other lower PARTS, don't touch STAGE
|
|
||||||
function increment_minor(){
|
|
||||||
PARTS[1]=$(( PARTS[1] + 1 ))
|
|
||||||
PARTS[2]=0
|
|
||||||
PARTS[3]=0
|
|
||||||
IS_DIRTY=1
|
|
||||||
}
|
|
||||||
|
|
||||||
## increment MAJOR part, reset all other lower PARTS, don't touch STAGE
|
|
||||||
function incremet_major(){
|
|
||||||
PARTS[0]="v$(( PARTS[0] + 1 ))"
|
|
||||||
PARTS[1]=0
|
|
||||||
PARTS[2]=0
|
|
||||||
PARTS[3]=0
|
|
||||||
IS_DIRTY=1
|
|
||||||
}
|
|
||||||
|
|
||||||
## increment the number only of last found PART: REVISION --> PATCH --> MINOR. don't touch STAGE
|
|
||||||
function increment_last_found(){
|
|
||||||
if [[ "${#PARTS[3]}" == 0 || "${PARTS[3]}" == "0" ]]; then
|
|
||||||
if [[ "${#PARTS[2]}" == 0 || "${PARTS[2]}" == "0" ]]; then
|
|
||||||
increment_minor
|
|
||||||
else
|
|
||||||
increment_patch
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
increment_revision
|
|
||||||
fi
|
|
||||||
|
|
||||||
# stage part is not EMPTY
|
|
||||||
if [[ "${#PARTS[4]}" != 0 ]]; then
|
|
||||||
IS_SHIFT=1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
## compose version from PARTS
|
|
||||||
function compose(){
|
|
||||||
MAJOR="${PARTS[0]}"
|
|
||||||
MINOR=".${PARTS[1]}"
|
|
||||||
PATCH=".${PARTS[2]}"
|
|
||||||
REVISION=".${PARTS[3]}"
|
|
||||||
SUFFIX="-${PARTS[4]}"
|
|
||||||
|
|
||||||
if [[ "${#PATCH}" == 1 ]]; then # if empty {PATCH}
|
|
||||||
PATCH=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${#REVISION}" == 1 ]]; then # if empty {REVISION}
|
|
||||||
REVISION=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${PARTS[3]}" == "0" ]]; then # if revision is ZERO
|
|
||||||
REVISION=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# shrink patch and revision
|
|
||||||
if [[ -z "${REVISION// }" ]]; then
|
|
||||||
if [[ "${PARTS[2]}" == "0" ]]; then
|
|
||||||
PATCH=".0"
|
|
||||||
fi
|
|
||||||
else # revision is not EMPTY
|
|
||||||
if [[ "${#PATCH}" == 0 ]]; then
|
|
||||||
PATCH=".0"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# remove suffix if we don't have a alpha/beta/rc
|
|
||||||
if [[ "${#SUFFIX}" == 1 ]]; then
|
|
||||||
SUFFIX=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo "${MAJOR}${MINOR}${PATCH}${REVISION}${SUFFIX}" #full format
|
|
||||||
}
|
|
||||||
|
|
||||||
# initial version used for repository without tags
|
|
||||||
INIT_VERSION=0.0.0.0-alpha
|
|
||||||
|
|
||||||
# do GIT data extracting
|
|
||||||
TAG=$(highest_tag)
|
|
||||||
REVISION=$(latest_revision)
|
|
||||||
BRANCH=$(current_branch)
|
|
||||||
TAG_HASH=$(tag_hash $TAG)
|
|
||||||
HEAD_HASH=$(head_hash)
|
|
||||||
|
|
||||||
# if tag and branch commit hashes are different, than print info about that
|
|
||||||
#echo $HEAD_HASH vs $TAG_HASH
|
|
||||||
if [[ "$@" == "" ]]; then
|
|
||||||
if [[ "$TAG_HASH" == "$HEAD_HASH" ]]; then
|
|
||||||
echo "Tag $TAG and HEAD are aligned. We will stay on the TAG version."
|
|
||||||
echo ""
|
|
||||||
NO_ARGS_VALUE='--stay'
|
|
||||||
else
|
|
||||||
PATTERN="^[0-9]+.[0-9]+(.[0-9]+)*(-(alpha|beta|rc))*$"
|
|
||||||
|
|
||||||
if [[ "$BRANCH" =~ $PATTERN ]]; then
|
|
||||||
echo "Detected version branch '$BRANCH'. We will auto-increment the last version PART."
|
|
||||||
echo ""
|
|
||||||
NO_ARGS_VALUE='--default'
|
|
||||||
else
|
|
||||||
echo "Detected branch name '$BRANCH' than does not match version pattern. We will increase MINOR."
|
|
||||||
echo ""
|
|
||||||
NO_ARGS_VALUE='--minor'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# {MAJOR}.{MINOR}[.{PATCH}[.{REVISION}][-(.*)]
|
|
||||||
#
|
|
||||||
# Suffix: alpha, beta, rc
|
|
||||||
# No Suffix --> {NEW_VERSION}-alpha
|
|
||||||
# alpha --> beta
|
|
||||||
# beta --> rc
|
|
||||||
# rc --> {VERSION}
|
|
||||||
#
|
|
||||||
PARTS=( ${TAG//./ } )
|
|
||||||
parse_last ${#PARTS[@]} # array size as argument
|
|
||||||
#echo ${PARTS[@]}
|
|
||||||
|
|
||||||
# if no parameters than emulate --default parameter
|
|
||||||
if [[ "$@" == "" ]]; then
|
|
||||||
set -- $NO_ARGS_VALUE
|
|
||||||
fi
|
|
||||||
|
|
||||||
# parse input parameters
|
|
||||||
for i in "$@"
|
|
||||||
do
|
|
||||||
key="$i"
|
|
||||||
|
|
||||||
case $key in
|
|
||||||
-a|--alpha) # switched to ALPHA
|
|
||||||
PARTS[4]="alpha"
|
|
||||||
IS_SHIFT=1
|
|
||||||
;;
|
|
||||||
-b|--beta) # switched to BETA
|
|
||||||
PARTS[4]="beta"
|
|
||||||
IS_SHIFT=1
|
|
||||||
;;
|
|
||||||
-c|--release-candidate) # switched to RC
|
|
||||||
PARTS[4]="rc"
|
|
||||||
IS_SHIFT=1
|
|
||||||
;;
|
|
||||||
-r|--release) # switched to RELEASE
|
|
||||||
PARTS[4]=""
|
|
||||||
IS_SHIFT=1
|
|
||||||
;;
|
|
||||||
-p|--patch) # increment of PATCH
|
|
||||||
increment_patch
|
|
||||||
;;
|
|
||||||
-e|--revision) # increment of REVISION
|
|
||||||
increment_revision
|
|
||||||
;;
|
|
||||||
-g|--git-revision) # use git revision number as a revision part§
|
|
||||||
PARTS[3]=$(( REVISION ))
|
|
||||||
IS_DIRTY=1
|
|
||||||
;;
|
|
||||||
-i|--minor) # increment of MINOR by default
|
|
||||||
increment_minor
|
|
||||||
;;
|
|
||||||
--default) # stay on the same stage, but increment only last found PART of version code
|
|
||||||
increment_last_found
|
|
||||||
;;
|
|
||||||
-m|--major) # increment of MAJOR
|
|
||||||
incremet_major
|
|
||||||
;;
|
|
||||||
-s|--stay) # extract version info
|
|
||||||
IS_DIRTY=1
|
|
||||||
NO_APPLY_MSG=1
|
|
||||||
;;
|
|
||||||
-t|--tag-only) # extract version info
|
|
||||||
TAG_ONLY=1
|
|
||||||
;;
|
|
||||||
--apply)
|
|
||||||
DO_APPLY=1
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
help
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
# detected shift, but no increment
|
|
||||||
if [[ "$IS_SHIFT" == "1" ]]; then
|
|
||||||
# temporary disable stage shift
|
|
||||||
stage=${PARTS[4]}
|
|
||||||
PARTS[4]=''
|
|
||||||
|
|
||||||
# detect first run on repository, INIT_VERSION was used
|
|
||||||
if [[ "$(compose)" == "0.0" ]]; then
|
|
||||||
increment_minor
|
|
||||||
fi
|
|
||||||
|
|
||||||
PARTS[4]=$stage
|
|
||||||
fi
|
|
||||||
|
|
||||||
# no increment applied yet and no shift of state, do minor increase
|
|
||||||
if [[ "$IS_DIRTY$IS_SHIFT" == "" ]]; then
|
|
||||||
increment_minor
|
|
||||||
fi
|
|
||||||
|
|
||||||
compose
|
|
||||||
|
|
||||||
# is proposed tag in conflict with any other TAG
|
|
||||||
PROPOSED_HASH=$(tag_hash $(compose))
|
|
||||||
if [[ "${#PROPOSED_HASH}" -gt 0 && "$NO_APPLY_MSG" == "" ]]; then
|
|
||||||
echo -e "\033[31mERROR:\033[0m "
|
|
||||||
echo -e "\033[31mERROR:\033[0m Found conflict with existing tag \033[32m$(compose)\033[0m / $PROPOSED_HASH"
|
|
||||||
echo -e "\033[31mERROR:\033[0m Only manual resolving is possible now."
|
|
||||||
echo -e "\033[31mERROR:\033[0m "
|
|
||||||
echo -e "\033[31mERROR:\033[0m To Resolve try to add --revision or --patch modifier."
|
|
||||||
echo -e "\033[31mERROR:\033[0m "
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
2
.gitignore
vendored
@@ -44,7 +44,7 @@ docs/.vitepress/data/releaseMetaData
|
|||||||
docs/.vitepress/data/categoriesData.json
|
docs/.vitepress/data/categoriesData.json
|
||||||
docs/.vitepress/data/iconDetails
|
docs/.vitepress/data/iconDetails
|
||||||
docs/.vitepress/data/relatedIcons.json
|
docs/.vitepress/data/relatedIcons.json
|
||||||
|
docs/.vitepress/data/brandStopwords.json
|
||||||
docs/.vercel
|
docs/.vercel
|
||||||
docs/.nitro
|
docs/.nitro
|
||||||
.gitignore
|
.gitignore
|
||||||
|
|
||||||
|
|||||||
149
brand-stopwords.json
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
{
|
||||||
|
"adobe": "Adobe",
|
||||||
|
"airplay": "AirPlay",
|
||||||
|
"amazon": "Amazon",
|
||||||
|
"angular": "Angular",
|
||||||
|
"aws": "AWS",
|
||||||
|
"azure": "Azure",
|
||||||
|
"bandcamp": "Bandcamp",
|
||||||
|
"behance": "Behance",
|
||||||
|
"bitbucket": "Bitbucket",
|
||||||
|
"blender": "Blender",
|
||||||
|
"bluesky": "BlueSky",
|
||||||
|
"bootstrap": "Bootstrap",
|
||||||
|
"brave": "Brave",
|
||||||
|
"chakra": "Chakra UI",
|
||||||
|
"chrome": "Chrome",
|
||||||
|
"codepen": "Codepen",
|
||||||
|
"codesandbox": "CodeSandbox",
|
||||||
|
"csharp": "C#",
|
||||||
|
"cypress": "Cypress",
|
||||||
|
"dart": "Dart",
|
||||||
|
"deezer": "Deezer",
|
||||||
|
"deno": "Deno",
|
||||||
|
"discord": "Discord",
|
||||||
|
"docker": "Docker",
|
||||||
|
"dribbble": "Dribbble",
|
||||||
|
"dropbox": "Dropbox",
|
||||||
|
"edge": "Edge",
|
||||||
|
"ember": "Ember",
|
||||||
|
"epic": "Epic Games",
|
||||||
|
"erlang": "Erlang",
|
||||||
|
"esbuild": "esbuild",
|
||||||
|
"eslint": "ESLint",
|
||||||
|
"facebook": "Facebook",
|
||||||
|
"figjam": "FigJam",
|
||||||
|
"figma": "Figma",
|
||||||
|
"firebase": "Firebase",
|
||||||
|
"firefox": "Firefox",
|
||||||
|
"framer": "Framer",
|
||||||
|
"gatsby": "Gatsby",
|
||||||
|
"gcp": "Google Cloud",
|
||||||
|
"github": "GitHub",
|
||||||
|
"gitlab": "GitLab",
|
||||||
|
"golang": "GoLang",
|
||||||
|
"google": "Google",
|
||||||
|
"gmail": "Gmail",
|
||||||
|
"gravatar": "Gravatar",
|
||||||
|
"haskell": "Haskell",
|
||||||
|
"instagram": "Instagram",
|
||||||
|
"java": "Java",
|
||||||
|
"javascript": "JavaScript",
|
||||||
|
"jest": "Jest",
|
||||||
|
"jira": "Jira",
|
||||||
|
"kotlin": "Kotlin",
|
||||||
|
"kubernetes": "Kubernetes",
|
||||||
|
"less": "Less",
|
||||||
|
"leetcode": "LeetCode",
|
||||||
|
"leet-code": "LeetCode",
|
||||||
|
"line": "LINE",
|
||||||
|
"linkedin": "LinkedIn",
|
||||||
|
"lua": "Lua",
|
||||||
|
"mariadb": "MariaDB",
|
||||||
|
"mcp": "MCP",
|
||||||
|
"messenger": "Messenger",
|
||||||
|
"microsoft": "Microsoft",
|
||||||
|
"mongodb": "MongoDB",
|
||||||
|
"mui": "Material UI",
|
||||||
|
"mysql": "MySQL",
|
||||||
|
"nestjs": "NestJS",
|
||||||
|
"netflix": "Netflix",
|
||||||
|
"netlify": "Netlify",
|
||||||
|
"next": "Next.js",
|
||||||
|
"nodejs": "Node.js",
|
||||||
|
"notion": "Notion",
|
||||||
|
"nostr": "Nostr",
|
||||||
|
"npm": "npm",
|
||||||
|
"nuxt": "Nuxt",
|
||||||
|
"opera": "Opera",
|
||||||
|
"oracle": "Oracle",
|
||||||
|
"patreon": "Patreon",
|
||||||
|
"paypal": "PayPal",
|
||||||
|
"perl": "Perl",
|
||||||
|
"php": "PHP",
|
||||||
|
"pinterest": "Pinterest",
|
||||||
|
"pix": "PiX",
|
||||||
|
"playstation": "PlayStation",
|
||||||
|
"playwright": "Playwright",
|
||||||
|
"pnpm": "pnpm",
|
||||||
|
"postcss": "PostCSS",
|
||||||
|
"postgresql": "PostgreSQL",
|
||||||
|
"prettier": "Prettier",
|
||||||
|
"prisma": "Prisma",
|
||||||
|
"python": "Python",
|
||||||
|
"qwik": "Qwik",
|
||||||
|
"react": "React",
|
||||||
|
"reddit": "Reddit",
|
||||||
|
"redis": "Redis",
|
||||||
|
"rollup": "Rollup",
|
||||||
|
"rust": "Rust",
|
||||||
|
"safari": "Safari",
|
||||||
|
"sass": "Sass",
|
||||||
|
"scala": "Scala",
|
||||||
|
"scss": "Sass",
|
||||||
|
"semantic": "Semantic UI",
|
||||||
|
"shopify": "Shopify",
|
||||||
|
"skype": "Skype",
|
||||||
|
"slack": "Slack",
|
||||||
|
"solid": "SolidJS",
|
||||||
|
"soundcloud": "SoundCloud",
|
||||||
|
"spotify": "Spotify",
|
||||||
|
"sqlite": "SQLite",
|
||||||
|
"squarespace": "Squarespace",
|
||||||
|
"steam": "Steam",
|
||||||
|
"stripe": "Stripe",
|
||||||
|
"substack": "Substack",
|
||||||
|
"supabase": "Supabase",
|
||||||
|
"surge": "Surge",
|
||||||
|
"svelte": "Svelte",
|
||||||
|
"swift": "Swift",
|
||||||
|
"tailwind": "Tailwind CSS",
|
||||||
|
"telegram": "Telegram",
|
||||||
|
"terraform": "Terraform",
|
||||||
|
"tesla": "Tesla",
|
||||||
|
"tidal": "Tidal",
|
||||||
|
"tiktok": "TikTok",
|
||||||
|
"trello": "Trello",
|
||||||
|
"twitch": "Twitch",
|
||||||
|
"twitter": "Twitter",
|
||||||
|
"typescript": "TypeScript",
|
||||||
|
"unity": "Unity",
|
||||||
|
"unreal": "Unreal Engine",
|
||||||
|
"vercel": "Vercel",
|
||||||
|
"vimeo": "Vimeo",
|
||||||
|
"vite": "Vite",
|
||||||
|
"vitest": "Vitest",
|
||||||
|
"vue": "Vue",
|
||||||
|
"webpack": "Webpack",
|
||||||
|
"wechat": "WeChat",
|
||||||
|
"whatsapp": "WhatsApp",
|
||||||
|
"windows": "Windows",
|
||||||
|
"wix": "Wix",
|
||||||
|
"x.com": "X.com",
|
||||||
|
"x-social": "X.com",
|
||||||
|
"xbox": "Xbox",
|
||||||
|
"yarn": "Yarn",
|
||||||
|
"youtube": "YouTube",
|
||||||
|
"zig": "Zig",
|
||||||
|
"zoom": "Zoom"
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../category.schema.json",
|
"$schema": "../category.schema.json",
|
||||||
"title": "Navigation",
|
"title": "Navigation, Maps, and POIs",
|
||||||
"icon": "compass"
|
"icon": "compass"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ if (process.env.NODE_ENV === 'development') {
|
|||||||
|
|
||||||
wasm = fs.readFileSync(require.resolve('@resvg/resvg-wasm/index_bg.wasm'));
|
wasm = fs.readFileSync(require.resolve('@resvg/resvg-wasm/index_bg.wasm'));
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
wasm = resvg_wasm;
|
wasm = resvg_wasm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
docs/.vitepress/api/gh-icon/symmetry/[...data].get.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||||
|
import { renderToString } from 'react-dom/server';
|
||||||
|
import { createElement } from 'react';
|
||||||
|
import Diff from '../../../lib/SvgPreview/Diff.tsx';
|
||||||
|
|
||||||
|
export default eventHandler((event) => {
|
||||||
|
const { params } = event.context;
|
||||||
|
|
||||||
|
const pathData = params.data.split('/');
|
||||||
|
const data = pathData.at(-1).slice(0, -4);
|
||||||
|
const [operation] = pathData;
|
||||||
|
|
||||||
|
const newSrc = Buffer.from(data, 'base64')
|
||||||
|
.toString('utf8')
|
||||||
|
.replaceAll('\n', '')
|
||||||
|
.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||||
|
|
||||||
|
const width = parseInt(
|
||||||
|
(newSrc.includes('<svg ') ? newSrc.match(/width="(\d+)"/)?.[1] : null) ?? '24',
|
||||||
|
);
|
||||||
|
const height = parseInt(
|
||||||
|
(newSrc.includes('<svg ') ? newSrc.match(/height="(\d+)"/)?.[1] : null) ?? '24',
|
||||||
|
);
|
||||||
|
|
||||||
|
const children = [];
|
||||||
|
|
||||||
|
let oldSrc = '';
|
||||||
|
if (operation.startsWith('rotate-')) {
|
||||||
|
const degrees = parseInt(operation.replace('rotate-', ''));
|
||||||
|
if (isNaN(degrees)) return '';
|
||||||
|
oldSrc = `<g transform="rotate(${degrees} ${width / 2} ${height / 2})">${newSrc}</g>`;
|
||||||
|
} else if (operation === 'flip-horizontal') {
|
||||||
|
oldSrc = `<g transform="scale(1, -1) translate(0, -${height})">${newSrc}</g>`;
|
||||||
|
} else if (operation === 'flip-vertical') {
|
||||||
|
oldSrc = `<g transform="scale(-1, 1) translate(-${width}, 0)">${newSrc}</g>`;
|
||||||
|
} else if (operation === 'flip-backslash') {
|
||||||
|
oldSrc = `<g transform="rotate(90, ${width / 2}, ${height / 2}) scale(1, -1) translate(0, -${height})">${newSrc}</g>`;
|
||||||
|
} else if (operation === 'flip-slash') {
|
||||||
|
oldSrc = `<g transform="rotate(90, ${width / 2}, ${height / 2}) scale(-1, 1) translate(-${width}, 0)">${newSrc}</g>`;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const svg = Buffer.from(
|
||||||
|
// We can't use jsx here, is not supported here by nitro.
|
||||||
|
renderToString(
|
||||||
|
createElement(Diff, { oldSrc, newSrc, showGrid: true, height, width }, children),
|
||||||
|
),
|
||||||
|
).toString('utf8');
|
||||||
|
|
||||||
|
defaultContentType(event, 'image/svg+xml');
|
||||||
|
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
});
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "navigation",
|
"name": "navigation",
|
||||||
"title": "Navigation"
|
"title": "Navigation, Maps, and POIs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "notifications",
|
"name": "notifications",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
"documentation": "https://github.com/swisnl/nuxt-lucide-icons/blob/main/README.md"
|
"documentation": "https://github.com/swisnl/nuxt-lucide-icons/blob/main/README.md"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "lucide-lustre",
|
"name": "lucide_lustre",
|
||||||
"description": "A library providing https://lucide.dev icons to lustre.",
|
"description": "A library providing https://lucide.dev icons to lustre.",
|
||||||
"icon": "/framework-logos/lustre.webp",
|
"icon": "/framework-logos/lustre.webp",
|
||||||
"shields": [
|
"shields": [
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "lucide_icons_flutter",
|
"name": "lucide_icons_flutter",
|
||||||
"description": "A library providing https://lucide.dev icons to lustre.",
|
"description": "A library providing https://lucide.dev icons to Flutter.",
|
||||||
"icon": "/framework-logos/flutter.svg",
|
"icon": "/framework-logos/flutter.svg",
|
||||||
"shields": [
|
"shields": [
|
||||||
{
|
{
|
||||||
@@ -133,5 +133,43 @@
|
|||||||
],
|
],
|
||||||
"source": "https://github.com/cnlancehu/lucide-slint",
|
"source": "https://github.com/cnlancehu/lucide-slint",
|
||||||
"documentation": "https://github.com/cnlancehu/lucide-slint/blob/main/README.md"
|
"documentation": "https://github.com/cnlancehu/lucide-slint/blob/main/README.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lucide-go",
|
||||||
|
"description": "Implementation of Lucide icons for Go's html/template package.",
|
||||||
|
"icon": "/framework-logos/go.svg",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "Latest Stable Version",
|
||||||
|
"src": "https://img.shields.io/github/v/release/kaugesaar/lucide-go",
|
||||||
|
"href": "https://github.com/kaugesaar/lucide-go/releases"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "Go Reference",
|
||||||
|
"src": "https://pkg.go.dev/badge/github.com/kaugesaar/lucide-go.svg",
|
||||||
|
"href": "https://pkg.go.dev/github.com/kaugesaar/lucide-go"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "https://github.com/kaugesaar/lucide-go",
|
||||||
|
"documentation": "https://github.com/kaugesaar/lucide-go/blob/master/README.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lucide-rails",
|
||||||
|
"description": "Ruby on Rails views helper method for rendering Lucide icons.",
|
||||||
|
"icon": "/framework-logos/rails.svg",
|
||||||
|
"shields": [
|
||||||
|
{
|
||||||
|
"alt": "Latest Stable Version",
|
||||||
|
"src": "https://img.shields.io/gem/v/lucide-rails",
|
||||||
|
"href": "https://rubygems.org/gems/lucide-rails"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alt": "Total Downloads",
|
||||||
|
"src": "https://img.shields.io/gem/dt/lucide-rails",
|
||||||
|
"href": "https://rubygems.org/gems/lucide-rails"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": "https://github.com/heyvito/lucide-rails",
|
||||||
|
"documentation": "https://github.com/heyvito/lucide-rails/blob/master/README.md"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { bundledLanguages, getHighlighter, type ThemeRegistration } from 'shikiji';
|
import { bundledLanguages, createHighlighter, type ThemeRegistration } from 'shiki';
|
||||||
|
|
||||||
type CodeExampleType = {
|
type CodeExampleType = {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -9,14 +9,20 @@ type CodeExampleType = {
|
|||||||
const getIconCodes = (): CodeExampleType => {
|
const getIconCodes = (): CodeExampleType => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
language: 'js',
|
language: 'html',
|
||||||
title: 'Vanilla',
|
title: 'Vanilla',
|
||||||
code: `\
|
code: `\
|
||||||
import { createIcons, icons } from 'lucide';
|
<script>
|
||||||
|
import { createIcons, $CamelCase } from 'lucide';
|
||||||
|
|
||||||
createIcons({ icons });
|
createIcons({
|
||||||
|
icons: {
|
||||||
|
$CamelCase
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
document.body.append('<i data-lucide="$Name"></i>');\
|
<i data-lucide="$Name"></i>\
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -112,7 +118,7 @@ export type ThemeOptions =
|
|||||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||||
|
|
||||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||||
const highlighter = await getHighlighter({
|
const highlighter = await createHighlighter({
|
||||||
themes: ['github-light', 'github-dark'],
|
themes: ['github-light', 'github-dark'],
|
||||||
langs: Object.keys(bundledLanguages),
|
langs: Object.keys(bundledLanguages),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
import { bundledLanguages, type ThemeRegistration } from 'shiki';
|
||||||
import { getHighlighter } from 'shikiji';
|
import { createHighlighter } from 'shiki';
|
||||||
|
|
||||||
type CodeExampleType = {
|
type CodeExampleType = {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -10,10 +10,11 @@ type CodeExampleType = {
|
|||||||
const getIconCodes = (): CodeExampleType => {
|
const getIconCodes = (): CodeExampleType => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
language: 'js',
|
language: 'html',
|
||||||
title: 'Vanilla',
|
title: 'Vanilla',
|
||||||
code: `\
|
code: `\
|
||||||
import { createIcons, icons } from 'lucide';
|
<script>
|
||||||
|
import { createIcons } from 'lucide';
|
||||||
import { $CamelCase } from '@lucide/lab';
|
import { $CamelCase } from '@lucide/lab';
|
||||||
|
|
||||||
createIcons({
|
createIcons({
|
||||||
@@ -21,8 +22,9 @@ createIcons({
|
|||||||
$CamelCase
|
$CamelCase
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
document.body.append('<i data-lucide="$Name"></i>');\
|
<i data-lucide="$Name"></i>\
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -119,7 +121,7 @@ export type ThemeOptions =
|
|||||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||||
|
|
||||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||||
const highlighter = await getHighlighter({
|
const highlighter = await createHighlighter({
|
||||||
themes: ['github-light', 'github-dark'],
|
themes: ['github-light', 'github-dark'],
|
||||||
langs: Object.keys(bundledLanguages),
|
langs: Object.keys(bundledLanguages),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
import { bundledLanguages, type ThemeRegistration } from 'shiki';
|
||||||
import { getHighlighter } from 'shikiji';
|
import { createHighlighter } from 'shiki';
|
||||||
|
|
||||||
export type ThemeOptions =
|
export type ThemeOptions =
|
||||||
| ThemeRegistration
|
| ThemeRegistration
|
||||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||||
|
|
||||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||||
const highlighter = await getHighlighter({
|
const highlighter = await createHighlighter({
|
||||||
themes: ['github-light', 'github-dark'],
|
themes: ['github-light', 'github-dark'],
|
||||||
langs: Object.keys(bundledLanguages),
|
langs: Object.keys(bundledLanguages),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,20 @@ import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
|||||||
import { search } from '../../../data/iconNodes'
|
import { search } from '../../../data/iconNodes'
|
||||||
|
|
||||||
const SearchIcon = createLucideIcon('search', search)
|
const SearchIcon = createLucideIcon('search', search)
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
shortcut: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button class="fake-input">
|
<button class="fake-input">
|
||||||
<component :is="SearchIcon" class="search-icon"/>
|
<component :is="SearchIcon" class="search-icon"/>
|
||||||
<slot/>
|
<slot/>
|
||||||
|
<kbd v-if="shortcut" class="shortcut">{{ shortcut }}</kbd>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -33,4 +41,23 @@ const SearchIcon = createLucideIcon('search', search)
|
|||||||
border-color: var(--vp-c-brand);
|
border-color: var(--vp-c-brand);
|
||||||
background: var(--vp-c-bg-alt);
|
background: var(--vp-c-bg-alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shortcut {
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
background: var(--vp-c-default-soft);
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: none) {
|
||||||
|
.shortcut {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,20 +6,35 @@ export default {
|
|||||||
export interface InputProps {
|
export interface InputProps {
|
||||||
type: string
|
type: string
|
||||||
modelValue: string
|
modelValue: string
|
||||||
|
shortcut?: string
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, onMounted, nextTick, watch } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<InputProps>(), {
|
const props = withDefaults(defineProps<InputProps>(), {
|
||||||
type: 'text'
|
type: 'text'
|
||||||
})
|
})
|
||||||
|
|
||||||
const input = ref()
|
const input = ref()
|
||||||
|
const wrapperEl = ref()
|
||||||
|
const shortcutEl = ref()
|
||||||
|
|
||||||
defineEmits(['change', 'input', 'update:modelValue'])
|
defineEmits(['change', 'input', 'update:modelValue'])
|
||||||
|
|
||||||
|
const updateShortcutSpacing = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (shortcutEl.value && wrapperEl.value) {
|
||||||
|
const shortcutWidth = shortcutEl.value.offsetWidth
|
||||||
|
wrapperEl.value.style.setProperty('--shortcut-width', `${shortcutWidth}px`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(updateShortcutSpacing)
|
||||||
|
watch(() => props.shortcut, updateShortcutSpacing)
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
focus: () => {
|
focus: () => {
|
||||||
input.value.focus()
|
input.value.focus()
|
||||||
@@ -28,17 +43,18 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper" ref="wrapperEl">
|
||||||
<slot name="icon" class="icon" />
|
<slot name="icon" class="icon" />
|
||||||
<input
|
<input
|
||||||
:type="type"
|
:type="type"
|
||||||
class="input"
|
class="input"
|
||||||
:class="{'has-icon': $slots.icon}"
|
:class="{'has-icon': $slots.icon, 'has-shortcut': shortcut}"
|
||||||
ref="input"
|
ref="input"
|
||||||
:value="modelValue"
|
:value="modelValue"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@input="$emit('update:modelValue', $event.target.value)"
|
@input="$emit('update:modelValue', $event.target.value)"
|
||||||
/>
|
/>
|
||||||
|
<kbd v-if="shortcut" class="shortcut" ref="shortcutEl">{{ shortcut }}</kbd>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -57,6 +73,10 @@ defineExpose({
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input.has-shortcut {
|
||||||
|
padding-right: calc(var(--shortcut-width, 40px) + 22px);
|
||||||
|
}
|
||||||
|
|
||||||
.input:hover, .input:focus {
|
.input:hover, .input:focus {
|
||||||
border-color: var(--vp-c-brand);
|
border-color: var(--vp-c-brand);
|
||||||
background: var(--vp-c-bg-alt);
|
background: var(--vp-c-bg-alt);
|
||||||
@@ -66,7 +86,28 @@ defineExpose({
|
|||||||
padding-left: 52px;
|
padding-left: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shortcut {
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--vp-c-text-3);
|
||||||
|
background: var(--vp-c-default-soft);
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 4px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: none) {
|
||||||
|
.shortcut {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const SearchIcon = createLucideIcon('search', search)
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string
|
modelValue: string
|
||||||
|
shortcut?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
@@ -39,6 +40,7 @@ const value = computed({
|
|||||||
ref="input"
|
ref="input"
|
||||||
type="search"
|
type="search"
|
||||||
autofocus
|
autofocus
|
||||||
|
:shortcut="shortcut"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
@@ -71,5 +73,4 @@ const value = computed({
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,10 +5,15 @@ import LucideIcon from '../base/LucideIcon.vue'
|
|||||||
import { useRouter } from 'vitepress';
|
import { useRouter } from 'vitepress';
|
||||||
import { random } from 'lodash-es'
|
import { random } from 'lodash-es'
|
||||||
import FakeInput from '../base/FakeInput.vue'
|
import FakeInput from '../base/FakeInput.vue'
|
||||||
|
import useSearchShortcut from '../../utils/useSearchShortcut'
|
||||||
|
|
||||||
const { go } = useRouter()
|
const { go } = useRouter()
|
||||||
const intervalTime = shallowRef()
|
const intervalTime = shallowRef()
|
||||||
|
|
||||||
|
const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
|
||||||
|
go('/icons/?focus')
|
||||||
|
})
|
||||||
|
|
||||||
const getInitialItems = () => data.icons.slice(0, 48)
|
const getInitialItems = () => data.icons.slice(0, 48)
|
||||||
const items = ref(getInitialItems())
|
const items = ref(getInitialItems())
|
||||||
let id = items.value.length + 1
|
let id = items.value.length + 1
|
||||||
@@ -64,7 +69,11 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
<FakeInput @click="go('/icons/?focus')" class="search-box">
|
<FakeInput
|
||||||
|
@click="go('/icons/?focus')"
|
||||||
|
:shortcut="kbdSearchShortcut"
|
||||||
|
class="search-box"
|
||||||
|
>
|
||||||
Search {{ data.iconsCount }} icons...
|
Search {{ data.iconsCount }} icons...
|
||||||
</FakeInput>
|
</FakeInput>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, defineAsyncComponent, onMounted, watch, watchEffect } from 'vue';
|
import { ref, computed, defineAsyncComponent, onMounted } from 'vue';
|
||||||
import type { IconEntity, Category } from '../../types';
|
import type { IconEntity, Category } from '../../types';
|
||||||
import useSearch from '../../composables/useSearch';
|
import useSearch from '../../composables/useSearch';
|
||||||
import InputSearch from '../base/InputSearch.vue';
|
import InputSearch from '../base/InputSearch.vue';
|
||||||
import useSearchInput from '../../composables/useSearchInput';
|
import useSearchInput from '../../composables/useSearchInput';
|
||||||
|
import useSearchShortcut from '../../utils/useSearchShortcut';
|
||||||
import StickyBar from './StickyBar.vue';
|
import StickyBar from './StickyBar.vue';
|
||||||
import IconsCategory from './IconsCategory.vue';
|
import IconsCategory, { CategoryRow } from './IconsCategory.vue';
|
||||||
import useFetchTags from '../../composables/useFetchTags';
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
import useFetchCategories from '../../composables/useFetchCategories';
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||||
import chunkArray from '../../utils/chunkArray';
|
import chunkArray from '../../utils/chunkArray';
|
||||||
import { CategoryRow } from './IconsCategory.vue';
|
|
||||||
import useScrollToCategory from '../../composables/useScrollToCategory';
|
import useScrollToCategory from '../../composables/useScrollToCategory';
|
||||||
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
|
||||||
|
|
||||||
const ICON_SIZE = 56;
|
const ICON_SIZE = 56;
|
||||||
const ICON_GRID_GAP = 8;
|
const ICON_GRID_GAP = 8;
|
||||||
@@ -27,6 +28,10 @@ const activeIconName = ref(null);
|
|||||||
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
const isSearching = computed(() => !!searchQuery.value);
|
const isSearching = computed(() => !!searchQuery.value);
|
||||||
|
|
||||||
|
const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
|
||||||
|
searchInput.value?.focus();
|
||||||
|
});
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
activeIconName.value = name;
|
activeIconName.value = name;
|
||||||
}
|
}
|
||||||
@@ -35,10 +40,10 @@ const { execute: fetchTags, data: tags } = useFetchTags();
|
|||||||
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
||||||
|
|
||||||
const overviewEl = ref<HTMLElement | null>(null);
|
const overviewEl = ref<HTMLElement | null>(null);
|
||||||
const { width: containerWidth } = useElementSize(overviewEl)
|
const { width: containerWidth } = useElementSize(overviewEl);
|
||||||
|
|
||||||
const columnSize = computed(() => {
|
const columnSize = computed(() => {
|
||||||
return Math.floor((containerWidth.value) / ((ICON_SIZE + ICON_GRID_GAP)));
|
return Math.floor(containerWidth.value / (ICON_SIZE + ICON_GRID_GAP));
|
||||||
});
|
});
|
||||||
|
|
||||||
const mappedIcons = computed(() => {
|
const mappedIcons = computed(() => {
|
||||||
@@ -66,26 +71,27 @@ const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
|||||||
const categories = computed(() => {
|
const categories = computed(() => {
|
||||||
if (!props.categories?.length || !props.icons?.length) return [];
|
if (!props.categories?.length || !props.icons?.length) return [];
|
||||||
|
|
||||||
return props.categories
|
return props.categories.map(({ name, title }) => {
|
||||||
.map(({ name, title }) => {
|
const categoryIcons = props.icons.filter((icon) => {
|
||||||
const categoryIcons = props.icons.filter((icon) => {
|
const iconCategories = icon?.externalLibrary
|
||||||
const iconCategories = icon?.externalLibrary ? icon.categories : props.iconCategories[icon.name]
|
? icon.categories
|
||||||
|
: props.iconCategories[icon.name];
|
||||||
|
|
||||||
return iconCategories?.includes(name);
|
return iconCategories?.includes(name);
|
||||||
});
|
});
|
||||||
|
|
||||||
const searchedCategoryIcons = isSearching
|
const searchedCategoryIcons = isSearching
|
||||||
? categoryIcons.filter((icon) =>
|
? categoryIcons.filter((icon) =>
|
||||||
searchResults.value.some((item) => item?.name === icon?.name)
|
searchResults.value.some((item) => item?.name === icon?.name),
|
||||||
)
|
)
|
||||||
: categoryIcons;
|
: categoryIcons;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
name,
|
name,
|
||||||
icons: searchedCategoryIcons,
|
icons: searchedCategoryIcons,
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const categoriesList = computed(() => {
|
const categoriesList = computed(() => {
|
||||||
@@ -102,26 +108,24 @@ const categoriesList = computed(() => {
|
|||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
});
|
});
|
||||||
|
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
|
||||||
|
|
||||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(categoriesList, {
|
||||||
categoriesList,
|
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
||||||
{
|
overscan: 10,
|
||||||
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
});
|
||||||
overscan: 10
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
useScrollToCategory({
|
useScrollToCategory({
|
||||||
categories,
|
categories,
|
||||||
categoriesList,
|
categoriesList,
|
||||||
scrollTo,
|
scrollTo,
|
||||||
searchQueryDebounced,
|
searchQueryDebounced,
|
||||||
})
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
containerProps.ref.value = document.documentElement;
|
containerProps.ref.value = document.documentElement;
|
||||||
useEventListener(window, 'scroll', containerProps.onScroll)
|
useEventListener(window, 'scroll', containerProps.onScroll);
|
||||||
})
|
});
|
||||||
|
|
||||||
function onFocusSearchInput() {
|
function onFocusSearchInput() {
|
||||||
if (tags.value == null) {
|
if (tags.value == null) {
|
||||||
@@ -140,28 +144,27 @@ function handleCloseDrawer() {
|
|||||||
|
|
||||||
window.history.pushState({}, '', '/icons/categories');
|
window.history.pushState({}, '', '/icons/categories');
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
|
|
||||||
console.log(props.icons.find((icon) => icon.name === 'burger'));
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="overviewEl" class="overview-container">
|
<div
|
||||||
|
ref="overviewEl"
|
||||||
|
class="overview-container"
|
||||||
|
>
|
||||||
<StickyBar class="category-search">
|
<StickyBar class="category-search">
|
||||||
<InputSearch
|
<InputSearch
|
||||||
:placeholder="`Search ${icons.length} icons ...`"
|
:placeholder="`Search ${icons.length} icons ...`"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
|
:shortcut="kbdSearchShortcut"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
ref="searchInput"
|
ref="searchInput"
|
||||||
@focus="onFocusSearchInput"
|
@focus="onFocusSearchInput"
|
||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults
|
||||||
v-if="categories.length === 0"
|
v-if="searchPlaceholder.isNoResults"
|
||||||
:searchQuery="searchQuery"
|
:searchQuery="searchPlaceholder.query"
|
||||||
|
:isBrandSearch="searchPlaceholder.isBrand"
|
||||||
@clear="searchQuery = ''"
|
@clear="searchQuery = ''"
|
||||||
/>
|
/>
|
||||||
<div v-bind="wrapperProps">
|
<div v-bind="wrapperProps">
|
||||||
@@ -202,8 +205,4 @@ watchEffect(() => {
|
|||||||
.icons {
|
.icons {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview-container {
|
|
||||||
padding-bottom: 288px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,26 +2,29 @@
|
|||||||
import { ref, computed, defineAsyncComponent, onMounted, watch } from 'vue';
|
import { ref, computed, defineAsyncComponent, onMounted, watch } from 'vue';
|
||||||
import type { IconEntity } from '../../types';
|
import type { IconEntity } from '../../types';
|
||||||
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||||
|
import { useRoute } from 'vitepress';
|
||||||
import IconGrid from './IconGrid.vue';
|
import IconGrid from './IconGrid.vue';
|
||||||
import InputSearch from '../base/InputSearch.vue';
|
import InputSearch from '../base/InputSearch.vue';
|
||||||
import useSearch from '../../composables/useSearch';
|
import useSearch from '../../composables/useSearch';
|
||||||
import useSearchInput from '../../composables/useSearchInput';
|
import useSearchInput from '../../composables/useSearchInput';
|
||||||
|
import useSearchShortcut from '../../utils/useSearchShortcut';
|
||||||
import StickyBar from './StickyBar.vue';
|
import StickyBar from './StickyBar.vue';
|
||||||
import useFetchTags from '../../composables/useFetchTags';
|
import useFetchTags from '../../composables/useFetchTags';
|
||||||
import useFetchCategories from '../../composables/useFetchCategories';
|
import useFetchCategories from '../../composables/useFetchCategories';
|
||||||
import chunkArray from '../../utils/chunkArray';
|
import chunkArray from '../../utils/chunkArray';
|
||||||
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||||
|
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
|
||||||
|
|
||||||
const ICON_SIZE = 56;
|
const ICON_SIZE = 56;
|
||||||
const ICON_GRID_GAP = 8;
|
const ICON_GRID_GAP = 8;
|
||||||
|
|
||||||
const initialGridItems = computed(() => {
|
const initialGridItems = computed(() => {
|
||||||
if (containerWidth.value === 0) return 120;
|
if (containerWidth.value === 0) return 120;
|
||||||
|
|
||||||
const itemsPerRow = columnSize.value || 10;
|
const itemsPerRow = columnSize.value || 10;
|
||||||
const visibleRows = Math.ceil(window.innerHeight / (ICON_SIZE + ICON_GRID_GAP));
|
const visibleRows = Math.ceil(window.innerHeight / (ICON_SIZE + ICON_GRID_GAP));
|
||||||
|
|
||||||
return Math.min(itemsPerRow * (visibleRows + 2), 200);
|
return Math.min(itemsPerRow * (visibleRows + 2), 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -34,10 +37,10 @@ const { execute: fetchTags, data: tags } = useFetchTags();
|
|||||||
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
||||||
|
|
||||||
const overviewEl = ref<HTMLElement | null>(null);
|
const overviewEl = ref<HTMLElement | null>(null);
|
||||||
const { width: containerWidth } = useElementSize(overviewEl)
|
const { width: containerWidth } = useElementSize(overviewEl);
|
||||||
|
|
||||||
const columnSize = computed(() => {
|
const columnSize = computed(() => {
|
||||||
return Math.floor((containerWidth.value) / ((ICON_SIZE + ICON_GRID_GAP)));
|
return Math.floor(containerWidth.value / (ICON_SIZE + ICON_GRID_GAP));
|
||||||
});
|
});
|
||||||
|
|
||||||
const mappedIcons = computed(() => {
|
const mappedIcons = computed(() => {
|
||||||
@@ -58,30 +61,38 @@ const mappedIcons = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
|
||||||
|
|
||||||
|
const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
|
||||||
|
searchInput.value?.focus();
|
||||||
|
});
|
||||||
|
|
||||||
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
||||||
{ name: 'name', weight: 3 },
|
{ name: 'name', weight: 3 },
|
||||||
{ name: 'aliases', weight: 3 },
|
{ name: 'aliases', weight: 3 },
|
||||||
{ name: 'tags', weight: 2 },
|
{ name: 'tags', weight: 2 },
|
||||||
{ name: 'categories', weight: 1 },
|
{ name: 'categories', weight: 1 },
|
||||||
]);
|
]);
|
||||||
|
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
|
||||||
|
|
||||||
const chunkedIcons = computed(() => {
|
const chunkedIcons = computed(() => {
|
||||||
return chunkArray(searchResults.value, columnSize.value);
|
return chunkArray(searchResults.value, columnSize.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(
|
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(chunkedIcons, {
|
||||||
chunkedIcons,
|
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
||||||
{
|
overscan: 10,
|
||||||
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
});
|
||||||
overscan: 10
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
containerProps.ref.value = document.documentElement;
|
containerProps.ref.value = document.documentElement;
|
||||||
useEventListener(window, 'scroll', containerProps.onScroll)
|
useEventListener(window, 'scroll', containerProps.onScroll);
|
||||||
})
|
|
||||||
|
|
||||||
|
// Check if we should focus the search input from URL parameter
|
||||||
|
const route = useRoute();
|
||||||
|
if (route.data?.relativePath && window.location.search.includes('focus')) {
|
||||||
|
searchInput.value?.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function setActiveIconName(name: string) {
|
function setActiveIconName(name: string) {
|
||||||
activeIconName.value = name;
|
activeIconName.value = name;
|
||||||
@@ -101,8 +112,8 @@ const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
|||||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||||
|
|
||||||
watch(searchQueryDebounced, () => {
|
watch(searchQueryDebounced, () => {
|
||||||
scrollTo(0)
|
scrollTo(0);
|
||||||
})
|
});
|
||||||
|
|
||||||
function handleCloseDrawer() {
|
function handleCloseDrawer() {
|
||||||
setActiveIconName('');
|
setActiveIconName('');
|
||||||
@@ -112,19 +123,24 @@ function handleCloseDrawer() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="overviewEl" class="overview-container">
|
<div
|
||||||
|
ref="overviewEl"
|
||||||
|
class="overview-container"
|
||||||
|
>
|
||||||
<StickyBar>
|
<StickyBar>
|
||||||
<InputSearch
|
<InputSearch
|
||||||
:placeholder="`Search ${icons.length} icons ...`"
|
:placeholder="`Search ${icons.length} icons ...`"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
ref="searchInput"
|
ref="searchInput"
|
||||||
|
:shortcut="kbdSearchShortcut"
|
||||||
class="input-wrapper"
|
class="input-wrapper"
|
||||||
@focus="onFocusSearchInput"
|
@focus="onFocusSearchInput"
|
||||||
/>
|
/>
|
||||||
</StickyBar>
|
</StickyBar>
|
||||||
<NoResults
|
<NoResults
|
||||||
v-if="searchResults.length === 0 && searchQuery !== ''"
|
v-if="searchPlaceholder.isNoResults"
|
||||||
:searchQuery="searchQuery"
|
:searchQuery="searchPlaceholder.query"
|
||||||
|
:isBrandSearch="searchPlaceholder.isBrand"
|
||||||
@clear="searchQuery = ''"
|
@clear="searchQuery = ''"
|
||||||
/>
|
/>
|
||||||
<IconGrid
|
<IconGrid
|
||||||
@@ -170,8 +186,4 @@ function handleCloseDrawer() {
|
|||||||
.input-wrapper {
|
.input-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview-container {
|
|
||||||
padding-bottom: 288px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,56 +1,218 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, computed, markRaw, shallowReadonly, watch } from 'vue';
|
||||||
import { bird, squirrel, rabbit } from '../../../data/iconNodes'
|
import {
|
||||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
bird,
|
||||||
import {useEventListener} from '@vueuse/core'
|
squirrel,
|
||||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue'
|
rabbit,
|
||||||
import { IconNode } from '../../types'
|
ghost,
|
||||||
|
castle,
|
||||||
|
drama,
|
||||||
|
dog,
|
||||||
|
cat,
|
||||||
|
wandSparkles,
|
||||||
|
save,
|
||||||
|
snowflake,
|
||||||
|
cake,
|
||||||
|
fish,
|
||||||
|
turtle,
|
||||||
|
rat,
|
||||||
|
worm,
|
||||||
|
testTubeDiagonal,
|
||||||
|
sword,
|
||||||
|
} from '../../../data/iconNodes';
|
||||||
|
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
|
||||||
|
import { useEventListener } from '@vueuse/core';
|
||||||
|
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||||
|
import { IconNode } from '../../types';
|
||||||
|
|
||||||
defineProps<{
|
const { searchQuery, isBrandSearch } = defineProps<{
|
||||||
searchQuery: string
|
searchQuery: string;
|
||||||
}>()
|
isBrandSearch: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
defineEmits(['clear'])
|
defineEmits(['clear']);
|
||||||
|
|
||||||
const animalIcon = ref<HTMLElement>()
|
interface Placeholder {
|
||||||
const randomAnimal = computed<IconNode>(() => {
|
title: string;
|
||||||
return Math.random() > 0.5 ? squirrel : Math.random() > 0.5 ? rabbit : bird
|
message: string;
|
||||||
})
|
icon: IconNode;
|
||||||
const animalComponent = computed(() => createLucideIcon('animal', randomAnimal.value))
|
finePrint?: string;
|
||||||
const flip = ref(false)
|
}
|
||||||
|
|
||||||
|
const brandPlaceholders: Placeholder[] = shallowReadonly([
|
||||||
|
{
|
||||||
|
title: 'Boooo! What a scary brand logo!',
|
||||||
|
message:
|
||||||
|
'[name] and its friends often haunt this search box, but you won’t ever find them here.',
|
||||||
|
icon: markRaw(ghost),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Thank You Mario!',
|
||||||
|
message: 'But [name] is in another castle!',
|
||||||
|
icon: markRaw(castle),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '[name] did audition for our icon set',
|
||||||
|
message: '...but didn’t make the callback.',
|
||||||
|
icon: markRaw(drama),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Such Search. Very [name].',
|
||||||
|
message: 'Much not here. So Wow.',
|
||||||
|
icon: markRaw(dog),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'I Can Has [name]?',
|
||||||
|
message: 'No [name] for you in here.',
|
||||||
|
icon: markRaw(cat),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Loading [name]...',
|
||||||
|
message: 'Fatal error: our cartridge contains only open-source pixels.',
|
||||||
|
icon: markRaw(save),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '[name] Shall Not Pass',
|
||||||
|
message: 'Do not look to its coming at first light of any day.',
|
||||||
|
icon: markRaw(wandSparkles),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Winter is coming',
|
||||||
|
message: 'But [name] sure isn’t.',
|
||||||
|
icon: markRaw(snowflake),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'The cake is a lie',
|
||||||
|
message: 'And so is the promise of an icon for [name] at Lucide.',
|
||||||
|
icon: markRaw(cake),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'It’s not a bug',
|
||||||
|
message: 'Having no [name] icon around is a feature.',
|
||||||
|
icon: markRaw(worm),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'The lab exploded',
|
||||||
|
message: 'We tried mixing [name] with open-source icons.',
|
||||||
|
icon: markRaw(testTubeDiagonal),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'It’s Dangerous to Go Alone',
|
||||||
|
message: 'Take this icon instead — it’s not [name], but it might help.',
|
||||||
|
icon: markRaw(sword),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const notFoundPlaceholders: Omit<Placeholder, 'title'>[] = shallowReadonly([
|
||||||
|
{
|
||||||
|
message: 'We’ve looked for this icon for a bird’s eye view, but could not find it.',
|
||||||
|
icon: markRaw(bird),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'We checked every tree. Only acorns, no results.',
|
||||||
|
icon: markRaw(squirrel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'You’ve gone too deep into the rabbit hole — this icon doesn’t exist.',
|
||||||
|
icon: markRaw(rabbit),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'This icon seems to have slipped through the net.',
|
||||||
|
icon: markRaw(fish),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'This icon might exist in the future… but it hasn’t arrived yet.',
|
||||||
|
icon: markRaw(turtle),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'Rats! This icon seems to have slipped through the cracks.',
|
||||||
|
icon: markRaw(rat),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
function randomItem<T>(arr: T[]): T {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const placeholderIcon = ref<HTMLElement>();
|
||||||
|
const placeholder = ref<Placeholder>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => isBrandSearch,
|
||||||
|
() => {
|
||||||
|
placeholder.value = isBrandSearch
|
||||||
|
? {
|
||||||
|
...randomItem(brandPlaceholders),
|
||||||
|
finePrint:
|
||||||
|
'Lucide does not accept brand logos, and we do not plan to add them in the future. This is due to a combination of legal restrictions, design consistency concerns, and practical maintenance reasons.',
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
title: `No results for “[name]”`,
|
||||||
|
finePrint:
|
||||||
|
'This icon doesn’t seem to exist… yet. Try searching similar terms, browsing existing requests, or opening a new one.',
|
||||||
|
...randomItem(notFoundPlaceholders),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
const iconComponent = computed(() => createLucideIcon('placeholder', placeholder.value.icon));
|
||||||
|
const flip = ref(false);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
useEventListener(document, 'mousemove', (mouseEvent) => {
|
useEventListener(document, 'mousemove', (mouseEvent) => {
|
||||||
const {width, height, x, y} = animalIcon.value.getBoundingClientRect()
|
const { width, x } = placeholderIcon.value.getBoundingClientRect();
|
||||||
|
|
||||||
const centerX = (width / 2) + x
|
const centerX = width / 2 + x;
|
||||||
|
|
||||||
flip.value = mouseEvent.x < centerX
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
flip.value = !isBrandSearch && mouseEvent.x < centerX;
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="no-results">
|
<div class="no-results">
|
||||||
<component
|
<component
|
||||||
:is="animalComponent"
|
:is="iconComponent"
|
||||||
class="animal-icon"
|
class="placeholder-icon"
|
||||||
ref="animalIcon"
|
ref="placeholderIcon"
|
||||||
:class="{ flip }"
|
:class="{ flip }"
|
||||||
:strokeWidth="1"
|
:strokeWidth="1"
|
||||||
/>
|
/>
|
||||||
<h2 class="no-results-text">
|
<h2 class="no-results-text">{{ placeholder.title.replace('[name]', searchQuery) }}</h2>
|
||||||
No icons found for '{{ searchQuery }}'
|
<p class="no-results-message">
|
||||||
</h2>
|
{{ placeholder.message.replace('[name]', searchQuery) }}
|
||||||
|
</p>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<p
|
||||||
|
v-if="placeholder.finePrint"
|
||||||
|
class="no-results-fine-print"
|
||||||
|
>
|
||||||
|
{{ placeholder.finePrint }}
|
||||||
|
</p>
|
||||||
<VPButton
|
<VPButton
|
||||||
text="Clear your search and try again"
|
v-if="isBrandSearch"
|
||||||
theme="alt"
|
text="Head over to Simple Icons"
|
||||||
|
theme="brand"
|
||||||
|
:href="`https://simpleicons.org/?q=${searchQuery}`"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
<VPButton
|
||||||
|
v-else
|
||||||
|
text="Clear search & try again"
|
||||||
|
theme="brand"
|
||||||
@click="$emit('clear')"
|
@click="$emit('clear')"
|
||||||
/>
|
/>
|
||||||
<span class="text-divider">or</span>
|
<span class="text-divider">or</span>
|
||||||
<VPButton
|
<VPButton
|
||||||
text="Search on Github issues"
|
v-if="isBrandSearch"
|
||||||
|
text="Read our statement on brand logos"
|
||||||
|
theme="alt"
|
||||||
|
href="https://github.com/lucide-icons/lucide/blob/main/BRAND_LOGOS_STATEMENT.md"
|
||||||
|
target="_blank"
|
||||||
|
/>
|
||||||
|
<VPButton
|
||||||
|
v-else
|
||||||
|
text="Search GitHub issues"
|
||||||
theme="alt"
|
theme="alt"
|
||||||
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
:href="`https://github.com/lucide-icons/lucide/issues?q=is%3Aopen+${searchQuery}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -63,33 +225,38 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding-block: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.animal-icon {
|
.placeholder-icon {
|
||||||
width: 160px;
|
width: 96px;
|
||||||
height: 160px;
|
height: 96px;
|
||||||
color: var(--vp-c-neutral);
|
color: var(--vp-c-text-1);
|
||||||
opacity: 0.8;
|
|
||||||
margin-top: 72px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.animal-icon.flip {
|
.placeholder-icon.flip {
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 960px) {
|
|
||||||
.animal-icon {
|
|
||||||
width: 240px;
|
|
||||||
height: 240px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-results-text {
|
.no-results-text {
|
||||||
line-height: 40px;
|
line-height: 1.35;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-results-message {
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-results-fine-print {
|
||||||
|
max-inline-size: 60ch;
|
||||||
|
font-size: 14px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
text-align: center;
|
color: var(--vp-c-text-2);
|
||||||
|
text-wrap: balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-divider {
|
.text-divider {
|
||||||
@@ -97,4 +264,10 @@ onMounted(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--vp-c-neutral);
|
color: var(--vp-c-neutral);
|
||||||
}
|
}
|
||||||
|
.divider {
|
||||||
|
margin: 24px auto 18px;
|
||||||
|
width: 64px;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--vp-c-divider);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
41
docs/.vitepress/theme/utils/useSearchPlaceholder.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { ref, Ref, watch } from 'vue';
|
||||||
|
import BRAND_STOPWORDS from '../../data/brandStopwords.json' with { type: 'json' };
|
||||||
|
|
||||||
|
export default function useSearchPlaceholder(
|
||||||
|
searchQuery: Ref<string, string>,
|
||||||
|
results: Ref<{ name: string }[]>,
|
||||||
|
) {
|
||||||
|
const state = ref({
|
||||||
|
isNoResults: false,
|
||||||
|
isBrand: false,
|
||||||
|
query: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
results,
|
||||||
|
() => {
|
||||||
|
const query = searchQuery.value;
|
||||||
|
const searchResults = results.value;
|
||||||
|
if (query.length > 0 && searchResults.length === 0) {
|
||||||
|
for (const stopword of Object.keys(BRAND_STOPWORDS)) {
|
||||||
|
if (stopword.startsWith(query)) {
|
||||||
|
state.value = {
|
||||||
|
isNoResults: true,
|
||||||
|
isBrand: true,
|
||||||
|
query: BRAND_STOPWORDS[stopword],
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.value = {
|
||||||
|
isNoResults: query in BRAND_STOPWORDS && searchResults.length === 0 && query !== '',
|
||||||
|
isBrand: query in BRAND_STOPWORDS,
|
||||||
|
query: BRAND_STOPWORDS[query] ?? query,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
35
docs/.vitepress/theme/utils/useSearchShortcut.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable for handling search keyboard shortcuts.
|
||||||
|
* Listens for Cmd/Ctrl+K and "/" keys to trigger a search action.
|
||||||
|
*
|
||||||
|
* @param callback - Function to execute when shortcut is triggered
|
||||||
|
* @returns Object containing the platform-specific shortcut display text
|
||||||
|
*/
|
||||||
|
export default function useSearchShortcut(callback: () => void) {
|
||||||
|
const shortcutText = ref('');
|
||||||
|
|
||||||
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
|
// Check for Cmd+K (Mac), Ctrl+K (Windows/Linux), or forward slash
|
||||||
|
if (((event.metaKey || event.ctrlKey) && event.key === 'k') || event.key === '/') {
|
||||||
|
event.preventDefault();
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Detect platform and set appropriate keyboard shortcut for search focus
|
||||||
|
const isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
|
||||||
|
shortcutText.value = isMac ? '⌘K' : 'Ctrl+K';
|
||||||
|
|
||||||
|
// Add keyboard shortcut listener
|
||||||
|
window.addEventListener('keydown', handleKeydown);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', handleKeydown);
|
||||||
|
});
|
||||||
|
|
||||||
|
return { shortcutText };
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ Implementation of the lucide icon library for web applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide
|
pnpm add lucide
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -37,7 +37,7 @@ Implementation of the lucide icon library for React applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-react
|
pnpm add lucide-react
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -64,7 +64,7 @@ Implementation of the lucide icon library for Vue applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-vue-next
|
pnpm add lucide-vue-next
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -91,7 +91,7 @@ Implementation of the lucide icon library for Svelte applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-svelte
|
pnpm add lucide-svelte
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -117,7 +117,7 @@ Implementation of the lucide icon library for Solid applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-solid
|
pnpm add lucide-solid
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -143,7 +143,7 @@ Implementation of the lucide icon library for Angular applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-angular
|
pnpm add lucide-angular
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -169,7 +169,7 @@ Implementation of the lucide icon library for preact applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-preact
|
pnpm add lucide-preact
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -196,7 +196,7 @@ Implementation of the lucide icon library for Astro applications.
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install @lucide/astro
|
pnpm add @lucide/astro
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
@@ -222,7 +222,7 @@ Implementation of the lucide icon library for multiple usages that like to use:
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-static
|
pnpm add lucide-static
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Angular components and services for Lucide icons that integrate with Angular's d
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-angular
|
pnpm add lucide-angular
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Preact components for Lucide icons that provide React-like development experienc
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-preact
|
pnpm add lucide-preact
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ First, ensure that you have `react-native-svg` (version between 12 and 15) insta
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-react-native
|
pnpm add lucide-react-native
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ React components for Lucide icons that integrate seamlessly into your React appl
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-react
|
pnpm add lucide-react
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ SolidJS components for Lucide icons that leverage Solid's fine-grained reactivit
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-solid
|
pnpm add lucide-solid
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ For production environments, we recommend using a bundler with tree-shaking supp
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-static
|
pnpm add lucide-static
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Vue 3 components for Lucide icons that leverage the Composition API and modern V
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-vue-next
|
pnpm add lucide-vue-next
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This package is deprecated. Vue 2 is EOF See [Announcement](https://v2.vuejs.or
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide-vue
|
pnpm add lucide-vue
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ The core Lucide package for vanilla JavaScript applications. This package allows
|
|||||||
::: code-group
|
::: code-group
|
||||||
|
|
||||||
```sh [pnpm]
|
```sh [pnpm]
|
||||||
pnpm install lucide
|
pnpm add lucide
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh [yarn]
|
```sh [yarn]
|
||||||
|
|||||||
@@ -2,18 +2,23 @@ import { IconEntity } from '../../.vitepress/theme/types';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
paths: async () => {
|
paths: async () => {
|
||||||
const iconDetailsResponse = await fetch('https://lab.lucide.dev/api/icon-details');
|
try {
|
||||||
const iconDetails = (await iconDetailsResponse.json()) as Record<string, IconEntity>;
|
const iconDetailsResponse = await fetch('https://lab.lucide.dev/api/icon-details');
|
||||||
|
const iconDetails = (await iconDetailsResponse.json()) as Record<string, IconEntity>;
|
||||||
|
|
||||||
return Object.values(iconDetails).map((iconEntity) => {
|
return Object.values(iconDetails).map((iconEntity) => {
|
||||||
const params = {
|
const params = {
|
||||||
externalLibrary: 'lab',
|
externalLibrary: 'lab',
|
||||||
...iconEntity,
|
...iconEntity,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
params,
|
params,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching icon details:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,13 +9,14 @@
|
|||||||
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
|
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
|
||||||
"docs:preview": "vitepress preview",
|
"docs:preview": "vitepress preview",
|
||||||
"build:docs": "vitepress build",
|
"build:docs": "vitepress build",
|
||||||
"prebuild:iconNodes": "node --experimental-strip-types ./scripts/writeIconNodes.mjs",
|
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mjs",
|
||||||
"prebuild:metaJson": "node --experimental-strip-types ./scripts/writeIconMetaIndex.mjs",
|
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mjs",
|
||||||
"prebuild:releaseJson": "node --experimental-strip-types ./scripts/writeReleaseMetadata.mjs",
|
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mjs",
|
||||||
"prebuild:categoriesJson": "node --experimental-strip-types ./scripts/writeCategoriesMetadata.mjs",
|
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mjs",
|
||||||
"prebuild:relatedIcons": "node --experimental-strip-types ./scripts/writeIconRelatedIcons.mjs",
|
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mjs",
|
||||||
"prebuild:iconDetails": "node --experimental-strip-types ./scripts/writeIconDetails.mjs",
|
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mjs",
|
||||||
"postbuild:vercelJson": "node --experimental-strip-types ./scripts/writeVercelOutput.mjs",
|
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mjs",
|
||||||
|
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mjs",
|
||||||
"dev": "npx nitropack dev",
|
"dev": "npx nitropack dev",
|
||||||
"prebuild:api": "npx nitropack prepare",
|
"prebuild:api": "npx nitropack prepare",
|
||||||
"build:api": "npx nitropack build",
|
"build:api": "npx nitropack build",
|
||||||
@@ -28,35 +29,35 @@
|
|||||||
"@lucide/build-icons": "workspace:*",
|
"@lucide/build-icons": "workspace:*",
|
||||||
"@lucide/helpers": "workspace:*",
|
"@lucide/helpers": "workspace:*",
|
||||||
"@lucide/shared": "workspace:*",
|
"@lucide/shared": "workspace:*",
|
||||||
"@rollup/plugin-replace": "^6.0.2",
|
"@rollup/plugin-replace": "^6.0.3",
|
||||||
"@types/semver": "^7.5.3",
|
"@types/semver": "^7.7.1",
|
||||||
"nitropack": "2.8.1",
|
"nitropack": "2.8.1",
|
||||||
"rollup-plugin-copy": "^3.5.0",
|
"rollup-plugin-copy": "^3.5.0",
|
||||||
"vitepress": "^1.6.3",
|
"svg-path-commander": "^2.1.11",
|
||||||
"svg-path-commander": "^2.1.11"
|
"vitepress": "^1.6.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/vue": "^1.0.3",
|
"@floating-ui/vue": "^1.1.9",
|
||||||
"@headlessui/vue": "^1.7.17",
|
"@headlessui/vue": "^1.7.23",
|
||||||
"@resvg/resvg-wasm": "^2.6.2",
|
"@resvg/resvg-wasm": "^2.6.2",
|
||||||
"@vueuse/components": "^12.0.0",
|
"@vueuse/components": "^14.0.0",
|
||||||
"@vueuse/core": "^12.0.0",
|
"@vueuse/core": "^14.0.0",
|
||||||
"element-to-path": "^1.2.1",
|
"element-to-path": "^1.2.1",
|
||||||
"fuse.js": "^6.5.3",
|
"fuse.js": "^7.1.0",
|
||||||
"jszip": "^3.7.0",
|
"jszip": "^3.10.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.21",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lucide-react": "workspace:*",
|
"lucide-react": "workspace:*",
|
||||||
"lucide-vue-next": "workspace:*",
|
"lucide-vue-next": "workspace:*",
|
||||||
"react": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.3.1",
|
||||||
"sandpack-vue3": "3.1.11",
|
"sandpack-vue3": "3.1.11",
|
||||||
"semver": "^7.5.2",
|
"semver": "^7.7.3",
|
||||||
"shikiji": "^0.7.4",
|
"shiki": "^3.15.0",
|
||||||
"simple-git": "^3.18.0",
|
"simple-git": "^3.30.0",
|
||||||
"sitemap": "^7.1.1",
|
"sitemap": "^7.1.2",
|
||||||
"svg-pathdata": "^6.0.3",
|
"svg-pathdata": "^6.0.3",
|
||||||
"svgson": "^5.2.1",
|
"svgson": "^5.3.1",
|
||||||
"vue": "^3.5.18"
|
"vue": "^3.5.24"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
docs/public/framework-logos/go.svg
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 205.4 76.7" style="enable-background:new 0 0 205.4 76.7;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#00ACD7;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M15.5,23.2c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5h35.7c0.4,0,0.5,0.3,0.3,0.6l-1.7,2.6
|
||||||
|
c-0.2,0.3-0.7,0.6-1,0.6L15.5,23.2z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M0.4,32.4c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5h45.6c0.4,0,0.6,0.3,0.5,0.6l-0.8,2.4
|
||||||
|
c-0.1,0.4-0.5,0.6-0.9,0.6L0.4,32.4z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M24.6,41.6c-0.4,0-0.5-0.3-0.3-0.6l1.4-2.5c0.2-0.3,0.6-0.6,1-0.6h20c0.4,0,0.6,0.3,0.6,0.7L47.1,41
|
||||||
|
c0,0.4-0.4,0.7-0.7,0.7L24.6,41.6z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g id="CXHf1q_3_">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M128.4,21.4c-6.3,1.6-10.6,2.8-16.8,4.4c-1.5,0.4-1.6,0.5-2.9-1c-1.5-1.7-2.6-2.8-4.7-3.8
|
||||||
|
c-6.3-3.1-12.4-2.2-18.1,1.5c-6.8,4.4-10.3,10.9-10.2,19c0.1,8,5.6,14.6,13.5,15.7c6.8,0.9,12.5-1.5,17-6.6
|
||||||
|
c0.9-1.1,1.7-2.3,2.7-3.7c-3.6,0-8.1,0-19.3,0c-2.1,0-2.6-1.3-1.9-3c1.3-3.1,3.7-8.3,5.1-10.9c0.3-0.6,1-1.6,2.5-1.6
|
||||||
|
c5.1,0,23.9,0,36.4,0c-0.2,2.7-0.2,5.4-0.6,8.1c-1.1,7.2-3.8,13.8-8.2,19.6c-7.2,9.5-16.6,15.4-28.5,17
|
||||||
|
c-9.8,1.3-18.9-0.6-26.9-6.6c-7.4-5.6-11.6-13-12.7-22.2c-1.3-10.9,1.9-20.7,8.5-29.3c7.1-9.3,16.5-15.2,28-17.3
|
||||||
|
c9.4-1.7,18.4-0.6,26.5,4.9c5.3,3.5,9.1,8.3,11.6,14.1C130,20.6,129.6,21.1,128.4,21.4z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M161.5,76.7c-9.1-0.2-17.4-2.8-24.4-8.8c-5.9-5.1-9.6-11.6-10.8-19.3c-1.8-11.3,1.3-21.3,8.1-30.2
|
||||||
|
c7.3-9.6,16.1-14.6,28-16.7c10.2-1.8,19.8-0.8,28.5,5.1c7.9,5.4,12.8,12.7,14.1,22.3c1.7,13.5-2.2,24.5-11.5,33.9
|
||||||
|
c-6.6,6.7-14.7,10.9-24,12.8C166.8,76.3,164.1,76.4,161.5,76.7z M185.3,36.3c-0.1-1.3-0.1-2.3-0.3-3.3
|
||||||
|
c-1.8-9.9-10.9-15.5-20.4-13.3c-9.3,2.1-15.3,8-17.5,17.4c-1.8,7.8,2,15.7,9.2,18.9c5.5,2.4,11,2.1,16.3-0.6
|
||||||
|
C180.5,51.3,184.8,44.9,185.3,36.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
10
docs/public/framework-logos/rails.svg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 -166 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||||
|
<g fill="#CC0000">
|
||||||
|
<path d="M219.115365,150.633753 C219.115365,150.633753 241.684635,148.699244 241.684635,119.552645 C241.684635,90.4060453 214.343577,87.697733 214.343577,87.697733 L165.078086,87.697733 L165.078086,179.651385 L189.839798,179.651385 L189.839798,157.469018 L211.248363,179.651385 L247.875063,179.651385 L219.115365,150.633753 Z M209.571788,131.804534 L189.839798,131.804534 L189.839798,110.782872 L209.700756,110.782872 C209.700756,110.782872 215.246348,112.846348 215.246348,121.229219 C215.246348,129.612091 209.571788,131.804534 209.571788,131.804534 Z M302.815113,88.3425693 L277.666499,88.3425693 C259.74005,88.3425693 253.678589,104.592443 253.678589,112.330479 L253.678589,179.651385 L278.827204,179.651385 L278.827204,163.530479 L302.428212,163.530479 L302.428212,179.651385 L326.803023,179.651385 L326.803023,112.330479 C326.803023,92.7274559 309.005542,88.3425693 302.815113,88.3425693 Z M302.428212,137.479093 L278.698237,137.479093 L278.698237,115.167758 C278.698237,115.167758 278.698237,110.138035 286.565239,110.138035 L295.206045,110.138035 C302.170277,110.138035 302.299244,115.167758 302.299244,115.167758 L302.299244,137.479093 L302.428212,137.479093 Z M338.281108,88.3425693 L364.461461,88.3425693 L364.461461,179.651385 L338.281108,179.651385 L338.281108,88.3425693 Z M401.217128,156.050378 L401.217128,88.3425693 L375.165743,88.3425693 L375.165743,156.050378 L375.165743,179.651385 L401.217128,179.651385 L436.425189,179.651385 L436.425189,156.050378 L401.217128,156.050378 Z M445.065995,156.308312 L445.065995,179.651385 L487.238287,179.651385 C495.879093,179.651385 510.710327,173.33199 511.226196,155.663476 L511.226196,146.635768 C511.226196,131.546599 498.84534,122.647859 487.238287,122.647859 L466.216625,122.647859 L466.216625,111.81461 L507.873048,111.81461 L507.873048,88.3425693 L467.893199,88.3425693 C457.575819,88.3425693 443.776322,96.8544081 443.776322,112.71738 L443.776322,120.842317 C443.776322,136.70529 457.446851,144.830227 467.893199,144.830227 C496.910831,144.959194 460.928967,144.830227 487.754156,144.830227 L487.754156,156.179345 L445.065995,156.308312 Z">
|
||||||
|
|
||||||
|
</path>
|
||||||
|
<path d="M9.02770781,179.522418 L110.911839,179.522418 C110.911839,179.522418 91.4377834,90.6639798 155.921411,54.6821159 C169.978841,47.8468514 214.730479,22.311335 287.983879,76.4775819 C290.30529,74.543073 292.497733,72.995466 292.497733,72.995466 C292.497733,72.995466 225.434761,6.06146096 150.76272,13.5415617 C113.233249,16.8947103 67.0629723,51.0710327 39.9798489,96.2095718 C12.8967254,141.348111 9.02770781,179.522418 9.02770781,179.522418 Z M221.307809,20.763728 L221.823678,12.1229219 C220.662972,11.4780856 217.438791,9.93047859 209.313854,7.60906801 L208.797985,16.1209068 C213.053904,17.5395466 217.180856,19.0871537 221.307809,20.763728 Z M209.055919,48.1047859 L208.54005,56.2297229 C212.79597,56.3586902 217.051889,56.8745592 221.307809,57.77733 L221.823678,49.7813602 C217.438791,48.8785894 213.182872,48.3627204 209.055919,48.1047859 Z M161.338035,7.86700252 L162.627708,7.86700252 L160.048363,-7.10542736e-15 C156.050378,-7.10542736e-15 151.923426,0.257934509 147.667506,0.773803526 L150.117884,8.38287154 C153.857935,7.99596977 157.597985,7.86700252 161.338035,7.86700252 Z M167.528463,55.3269521 L170.49471,64.2256927 C174.234761,62.4201511 177.974811,60.8725441 181.714861,59.7118388 L178.877582,51.2 C174.492695,52.4896725 170.752645,53.9083123 167.528463,55.3269521 Z M108.97733,21.4085642 L103.173804,12.5098237 C99.9496222,14.186398 96.5964736,15.9919395 93.1143577,18.0554156 L99.0468514,27.0831234 C102.4,25.0196474 105.624181,23.0851385 108.97733,21.4085642 Z M135.415617,79.4438287 L141.606045,88.729471 C143.798489,85.5052897 146.377834,82.5390428 149.215113,79.572796 L143.411587,70.8030227 C140.44534,73.511335 137.737028,76.4775819 135.415617,79.4438287 Z M116.715365,120.971285 L127.161713,129.225189 C127.677582,124.195466 128.580353,119.165743 129.870025,114.13602 L120.584383,106.784887 C118.907809,111.556675 117.747103,116.328463 116.715365,120.971285 Z M60.2277078,59.7118388 L51.0710327,51.715869 C47.7178841,54.9400504 44.4937028,58.1642317 41.5274559,61.3884131 L51.4579345,69.9002519 C54.1662469,66.418136 57.1324937,62.9360202 60.2277078,59.7118388 Z M21.279597,117.360202 L6.44836272,111.943577 C3.99798489,117.489169 1.28967254,123.937531 0,127.419647 L14.8312343,132.836272 C16.5078086,128.451385 19.2161209,122.13199 21.279597,117.360202 Z M114.780856,153.728967 C115.038791,160.564232 115.683627,166.109824 116.328463,169.978841 L131.804534,175.524433 C130.643829,170.49471 129.483123,164.820151 128.70932,158.75869 L114.780856,153.728967 Z">
|
||||||
|
|
||||||
|
</path>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
15
docs/scripts/writeBrandStopwords.mjs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
const currentDir = process.cwd();
|
||||||
|
const dataDirectory = path.resolve(currentDir, '.vitepress/data');
|
||||||
|
const stopwordsSource = path.resolve(currentDir, `../brand-stopwords.json`);
|
||||||
|
const stopwordsFile = path.resolve(dataDirectory, `brandStopwords.json`);
|
||||||
|
|
||||||
|
fs.copyFile(stopwordsSource, stopwordsFile)
|
||||||
|
.then(() => {
|
||||||
|
console.log('Successfully copied brandStopwords.json file');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
throw new Error(`Something went wrong generating the brandStopwords.json file,\n ${error}`);
|
||||||
|
});
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
"$schema": "../icon.schema.json",
|
"$schema": "../icon.schema.json",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"danielbayley",
|
"danielbayley",
|
||||||
"karsa-mistmere"
|
"karsa-mistmere",
|
||||||
|
"jguddas"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"and",
|
"and",
|
||||||
|
|||||||
@@ -9,6 +9,6 @@
|
|||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<path d="M17.5 12c0 4.4-3.6 8-8 8A4.5 4.5 0 0 1 5 15.5c0-6 8-4 8-8.5a3 3 0 1 0-6 0c0 3 2.5 8.5 12 13" />
|
|
||||||
<path d="M16 12h3" />
|
<path d="M16 12h3" />
|
||||||
|
<path d="M17.5 12a8 8 0 0 1-8 8A4.5 4.5 0 0 1 5 15.5c0-6 8-4 8-8.5a3 3 0 1 0-6 0c0 3 2.5 8.5 12 13" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 339 B After Width: | Height: | Size: 337 B |
@@ -3,7 +3,8 @@
|
|||||||
"contributors": [
|
"contributors": [
|
||||||
"colebemis",
|
"colebemis",
|
||||||
"csandman",
|
"csandman",
|
||||||
"ericfennis"
|
"ericfennis",
|
||||||
|
"karsa-mistmere"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"ship"
|
"ship"
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<path d="M12 22V8" />
|
<path d="M12 6v16" />
|
||||||
<path d="M5 12H2a10 10 0 0 0 20 0h-3" />
|
<path d="m19 13 2-1a9 9 0 0 1-18 0l2 1" />
|
||||||
<circle cx="12" cy="5" r="3" />
|
<path d="M9 11h6" />
|
||||||
|
<circle cx="12" cy="4" r="2" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 334 B |
@@ -15,7 +15,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming",
|
"gaming",
|
||||||
"files"
|
"files"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming"
|
"gaming"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming"
|
"gaming"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming"
|
"gaming"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming"
|
"gaming"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"gaming"
|
"gaming"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"text",
|
"text",
|
||||||
"development",
|
"development",
|
||||||
"gaming"
|
"gaming"
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"text",
|
"text",
|
||||||
"development",
|
"development",
|
||||||
"gaming"
|
"gaming"
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"files"
|
"files"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"diagonal"
|
"diagonal"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"diagonal"
|
"diagonal"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"into"
|
"into"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"files",
|
"files",
|
||||||
"development"
|
"development"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
"move"
|
"move"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
"south"
|
"south"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"<-|"
|
"<-|"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"->"
|
"->"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"|<-"
|
"|<-"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"<-"
|
"<-"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
"|->"
|
"|->"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
"->"
|
"->"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"development"
|
"development"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"->"
|
"->"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
"move"
|
"move"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"out"
|
"out"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"files",
|
"files",
|
||||||
"development"
|
"development"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"diagonal"
|
"diagonal"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"diagonal"
|
"diagonal"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows",
|
||||||
"navigation",
|
|
||||||
"files"
|
"files"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"north"
|
"north"
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
"arrows",
|
"arrows"
|
||||||
"navigation"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
22
icons/balloon.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../icon.schema.json",
|
||||||
|
"contributors": [
|
||||||
|
"peteruithoven"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"party",
|
||||||
|
"festival",
|
||||||
|
"congratulations",
|
||||||
|
"celebration",
|
||||||
|
"decoration",
|
||||||
|
"colorful",
|
||||||
|
"floating",
|
||||||
|
"fun",
|
||||||
|
"birthday",
|
||||||
|
"event",
|
||||||
|
"entertainment"
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
"emoji"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -9,8 +9,7 @@
|
|||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<path d="M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4" />
|
<path d="M12 16v1a2 2 0 0 0 2 2h1a2 2 0 0 1 2 2v1" />
|
||||||
<path d="M14 2v4a2 2 0 0 0 2 2h4" />
|
<path d="M12 6a2 2 0 0 1 2 2" />
|
||||||
<path d="M3 15h6" />
|
<path d="M18 8c0 4-3.5 8-6 8s-6-4-6-8a6 6 0 0 1 12 0" />
|
||||||
<path d="M6 12v6" />
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 356 B After Width: | Height: | Size: 358 B |
25
icons/book-search.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../icon.schema.json",
|
||||||
|
"contributors": [
|
||||||
|
"karsa-mistmere",
|
||||||
|
"Muhammad-Aqib-Bashir"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"reading",
|
||||||
|
"library",
|
||||||
|
"study",
|
||||||
|
"education",
|
||||||
|
"research",
|
||||||
|
"knowledge",
|
||||||
|
"discover",
|
||||||
|
"browsing",
|
||||||
|
"lookup",
|
||||||
|
"finding",
|
||||||
|
"scanning"
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
"text",
|
||||||
|
"development",
|
||||||
|
"gaming"
|
||||||
|
]
|
||||||
|
}
|
||||||
16
icons/book-search.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<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="M11 22H5.5a1 1 0 0 1 0-5h4.501" />
|
||||||
|
<path d="m21 22-1.879-1.878" />
|
||||||
|
<path d="M3 19.5v-15A2.5 2.5 0 0 1 5.5 2H18a1 1 0 0 1 1 1v8" />
|
||||||
|
<circle cx="17" cy="18" r="3" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 389 B |
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../icon.schema.json",
|
"$schema": "../icon.schema.json",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"karsa-mistmere"
|
"karsa-mistmere",
|
||||||
|
"jguddas"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"cleaning",
|
"cleaning",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<path d="m16 22-1-4" />
|
<path d="m16 22-1-4" />
|
||||||
<path d="M19 13.99a1 1 0 0 0 1-1V12a2 2 0 0 0-2-2h-3a1 1 0 0 1-1-1V4a2 2 0 0 0-4 0v5a1 1 0 0 1-1 1H6a2 2 0 0 0-2 2v.99a1 1 0 0 0 1 1" />
|
<path d="M19 14a1 1 0 0 0 1-1v-1a2 2 0 0 0-2-2h-3a1 1 0 0 1-1-1V4a2 2 0 0 0-4 0v5a1 1 0 0 1-1 1H6a2 2 0 0 0-2 2v1a1 1 0 0 0 1 1" />
|
||||||
<path d="M5 14h14l1.973 6.767A1 1 0 0 1 20 22H4a1 1 0 0 1-.973-1.233z" />
|
<path d="M19 14H5l-1.973 6.767A1 1 0 0 0 4 22h16a1 1 0 0 0 .973-1.233z" />
|
||||||
<path d="m8 22 1-4" />
|
<path d="m8 22 1-4" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 470 B |
@@ -2,7 +2,8 @@
|
|||||||
"$schema": "../icon.schema.json",
|
"$schema": "../icon.schema.json",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"vqh2602",
|
"vqh2602",
|
||||||
"jguddas"
|
"jguddas",
|
||||||
|
"karsa-mistmere"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"water",
|
"water",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
<path d="M7.2 14.8a2 2 0 0 1 2 2" />
|
<path d="M7.001 15.085A1.5 1.5 0 0 1 9 16.5" />
|
||||||
<circle cx="18.5" cy="8.5" r="3.5" />
|
<circle cx="18.5" cy="8.5" r="3.5" />
|
||||||
<circle cx="7.5" cy="16.5" r="5.5" />
|
<circle cx="7.5" cy="16.5" r="5.5" />
|
||||||
<circle cx="7.5" cy="4.5" r="2.5" />
|
<circle cx="7.5" cy="4.5" r="2.5" />
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 377 B |