diff --git a/.prettierignore b/.prettierignore
index c150f271b..d60d00b9b 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -17,6 +17,7 @@ packages/lucide-static/sprite.svg
packages/lucide-static/tags.json
packages/lucide-static/icon-nodes.json
packages/lucide-static/font
+packages/svelte/.svelte-kit
# lucide-svelte
packages/lucide-svelte/src/icons/*.svelte
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 78f48ba66..acb6738d9 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -1,14 +1,14 @@
import { fileURLToPath, URL } from 'node:url';
-import { defineConfig } from 'vitepress';
+import { defineConfig, UserConfig } from 'vitepress';
import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons';
import sidebar from './sidebar';
import snackPlayer from './markdown/snackPlayer';
import sandpackPlugin from './markdown/sandpack';
import { readFile } from 'node:fs/promises';
import { resourcesSidebar } from './sidebar/resources';
-import getStructuredData from './getStructuredData';
-import { createGeneralOGImage, createIconOGImage } from './createOGImage';
import llmstxt from 'vitepress-plugin-llms';
+import { transformPageData } from './transformPageData';
+import getHeadConfig from './getHeadConfig';
const defaultSandpackCSS = await readFile(
fileURLToPath(new URL('./theme/sandpack-default.css', import.meta.url)),
@@ -56,6 +56,12 @@ export default defineConfig({
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
),
},
+ {
+ find: /^.*\/VPCarbonAds\.vue$/,
+ replacement: fileURLToPath(
+ new URL('./theme/components/overrides/VPCarbonAds.vue', import.meta.url),
+ ),
+ },
{
find: '~/.vitepress',
replacement: fileURLToPath(new URL('./', import.meta.url)),
@@ -73,199 +79,11 @@ export default defineConfig({
'brand-logo-statement.md',
'icons/**', // Not working, need investigation
],
- }),
+ }) as unknown as UserConfig['vite']['plugins'][0],
],
},
- head: [
- [
- 'link',
- {
- rel: 'preconnect',
- href: 'https://analytics.lucide.dev',
- },
- ],
- [
- 'script',
- {
- src: 'https://analytics.lucide.dev/js/script.js',
- 'data-domain': 'lucide.dev',
- defer: '',
- },
- ],
- [
- 'meta',
- {
- property: 'og:locale',
- content: 'en_US',
- },
- ],
- [
- 'meta',
- {
- property: 'og:type',
- content: 'website',
- },
- ],
- [
- 'meta',
- {
- property: 'og:site_name',
- content: title,
- },
- ],
- [
- 'meta',
- {
- property: 'og:title',
- content: socialTitle,
- },
- ],
- [
- 'meta',
- {
- property: 'og:description',
- content: description,
- },
- ],
- [
- 'meta',
- {
- property: 'og:url',
- content: 'https://lucide.dev',
- },
- ],
- [
- 'meta',
- {
- property: 'og:image',
- content: 'https://lucide.dev/og.png',
- },
- ],
- [
- 'meta',
- {
- property: 'og:image:width',
- content: '1200',
- },
- ],
- [
- 'meta',
- {
- property: 'og:image:height',
- content: '630',
- },
- ],
- [
- 'meta',
- {
- property: 'og:image:type',
- content: 'image/png',
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:card',
- content: 'summary_large_image',
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:title',
- content: socialTitle,
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:description',
- content: description,
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:image',
- content: 'https://lucide.dev/og.png',
- },
- ],
- ],
- async transformPageData(pageData) {
- pageData.frontmatter.head ??= [];
- if (
- pageData.relativePath.startsWith('icons/') &&
- !pageData.relativePath.startsWith('icons/lab/') &&
- pageData.params?.name
- ) {
- const iconName = pageData.params.name;
- pageData.title = `${iconName} icon details`;
-
- const taggedAs = pageData.params?.tags?.length
- ? `Tagged as: ${pageData.params.tags.join(', ')}.`
- : '';
- const categorizedIn = pageData.params?.category?.length
- ? `Categorized in: ${pageData.params.category.join(', ')}.`
- : '';
-
- pageData.description =
- `Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
-
- const structuredData = await getStructuredData(iconName, pageData);
-
- const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
-
- if (ogPath) {
- const content = `https://lucide.dev${ogPath}`;
- pageData.frontmatter.head.push(
- [
- 'meta',
- {
- property: 'og:image',
- content,
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:image',
- content,
- },
- ],
- );
- }
-
- pageData.frontmatter.head.push([
- 'script',
- { type: 'application/ld+json' },
- JSON.stringify(structuredData),
- ]);
- }
-
- if (pageData.relativePath.startsWith('guide/')) {
- const ogPath = await createGeneralOGImage(pageData);
-
- if (ogPath) {
- const content = `https://lucide.dev${ogPath}`;
- pageData.frontmatter.head.push(
- [
- 'meta',
- {
- property: 'og:image',
- content,
- },
- ],
- [
- 'meta',
- {
- property: 'twitter:image',
- content,
- },
- ],
- );
- }
- }
- },
+ head: getHeadConfig({ title, description, socialTitle }),
+ transformPageData,
themeConfig: {
logo: {
light: '/logo.light.svg',
diff --git a/docs/.vitepress/getHeadConfig.ts b/docs/.vitepress/getHeadConfig.ts
new file mode 100644
index 000000000..95ebe50f0
--- /dev/null
+++ b/docs/.vitepress/getHeadConfig.ts
@@ -0,0 +1,127 @@
+import { HeadConfig } from 'vitepress';
+
+const getHeadConfig = ({
+ title,
+ description,
+ socialTitle,
+}: {
+ title: string;
+ description: string;
+ socialTitle?: string;
+}): HeadConfig[] => [
+ [
+ 'link',
+ {
+ rel: 'preconnect',
+ href: 'https://analytics.lucide.dev',
+ },
+ ],
+ [
+ 'script',
+ {
+ src: 'https://analytics.lucide.dev/js/script.js',
+ 'data-domain': 'lucide.dev',
+ defer: '',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:locale',
+ content: 'en_US',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:type',
+ content: 'website',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:site_name',
+ content: title,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:title',
+ content: socialTitle,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:description',
+ content: description,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:url',
+ content: 'https://lucide.dev',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:image',
+ content: 'https://lucide.dev/og.png',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:image:width',
+ content: '1200',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:image:height',
+ content: '630',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'og:image:type',
+ content: 'image/png',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:card',
+ content: 'summary_large_image',
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:title',
+ content: socialTitle,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:description',
+ content: description,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:image',
+ content: 'https://lucide.dev/og.png',
+ },
+ ],
+];
+
+export default getHeadConfig;
diff --git a/docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue b/docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue
index ba80e8257..4c5b60f08 100644
--- a/docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue
+++ b/docs/.vitepress/theme/components/icons/CarbonAdOverlay.vue
@@ -50,7 +50,7 @@ onMounted(() => {
absoluteStrokeWidth
/>
-
+
diff --git a/docs/.vitepress/theme/components/icons/StickyBar.vue b/docs/.vitepress/theme/components/icons/StickyBar.vue
index 8c0350409..8f1440225 100644
--- a/docs/.vitepress/theme/components/icons/StickyBar.vue
+++ b/docs/.vitepress/theme/components/icons/StickyBar.vue
@@ -9,9 +9,7 @@
margin-bottom: 16px;
position: sticky;
z-index: 10;
- top: 48px;
- padding-top: 24px;
- margin-top: -32px;
+ top: var(--vp-layout-top-height);
width: 100%;
display: flex;
margin-bottom: 32px;
@@ -22,7 +20,8 @@
@media (min-width: 960px) {
.search-bar {
padding-top: 32px;
- top: 64px;
+ margin-top: calc((var(--vp-layout-top-height, 0px) + 32px) * -1);
+ top: calc(var(--vp-layout-top-height, 0px) + 64px);
}
}
diff --git a/docs/.vitepress/theme/components/overrides/VPCarbonAds.vue b/docs/.vitepress/theme/components/overrides/VPCarbonAds.vue
new file mode 100644
index 000000000..494c28a84
--- /dev/null
+++ b/docs/.vitepress/theme/components/overrides/VPCarbonAds.vue
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
index 8a524bd2b..861e94324 100644
--- a/docs/.vitepress/theme/index.ts
+++ b/docs/.vitepress/theme/index.ts
@@ -23,7 +23,8 @@ const theme: Partial = {
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
'home-hero-image': () => h(HomeHeroIconsCard),
'home-hero-actions-after': () => h(HomeHeroAfter),
- 'layout-top': () => h(LayoutTop),
+ // Keep this here for now, we might want to add more things to the top bar in the future
+ // 'layout-top': () => h(LayoutTop),
});
},
enhanceApp({ app }) {
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
index 2f67541ec..22a1ee5de 100644
--- a/docs/.vitepress/theme/style.css
+++ b/docs/.vitepress/theme/style.css
@@ -144,6 +144,14 @@
.VPHomeHero .container {
flex-direction: row;
}
+
+ html.has-bb-banner {
+ --vp-layout-top-height: 72px;
+ }
+
+ html.has-bb-banner {
+ --Dark-Background: #161618;
+ }
}
.VPNavBarHamburger .container > span {
diff --git a/docs/.vitepress/transformPageData.ts b/docs/.vitepress/transformPageData.ts
new file mode 100644
index 000000000..a57c023d6
--- /dev/null
+++ b/docs/.vitepress/transformPageData.ts
@@ -0,0 +1,79 @@
+import { type PageData } from 'vitepress';
+import getStructuredData from './getStructuredData';
+import { createGeneralOGImage, createIconOGImage } from './createOGImage';
+
+export async function transformPageData(pageData: PageData) {
+ pageData.frontmatter.head ??= [];
+ if (
+ pageData.relativePath.startsWith('icons/') &&
+ !pageData.relativePath.startsWith('icons/lab/') &&
+ pageData.params?.name
+ ) {
+ const iconName = pageData.params.name;
+ pageData.title = `${iconName} icon details`;
+
+ const taggedAs = pageData.params?.tags?.length
+ ? `Tagged as: ${pageData.params.tags.join(', ')}.`
+ : '';
+ const categorizedIn = pageData.params?.category?.length
+ ? `Categorized in: ${pageData.params.category.join(', ')}.`
+ : '';
+
+ pageData.description =
+ `Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
+
+ const structuredData = await getStructuredData(iconName, pageData);
+
+ const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
+
+ if (ogPath) {
+ const content = `https://lucide.dev${ogPath}`;
+ pageData.frontmatter.head.push(
+ [
+ 'meta',
+ {
+ property: 'og:image',
+ content,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:image',
+ content,
+ },
+ ],
+ );
+ }
+
+ pageData.frontmatter.head.push([
+ 'script',
+ { type: 'application/ld+json' },
+ JSON.stringify(structuredData),
+ ]);
+ }
+
+ if (pageData.relativePath.startsWith('guide/')) {
+ const ogPath = await createGeneralOGImage(pageData);
+
+ if (ogPath) {
+ const content = `https://lucide.dev${ogPath}`;
+ pageData.frontmatter.head.push(
+ [
+ 'meta',
+ {
+ property: 'og:image',
+ content,
+ },
+ ],
+ [
+ 'meta',
+ {
+ property: 'twitter:image',
+ content,
+ },
+ ],
+ );
+ }
+ }
+}