Skip to content

Commit 747bdbc

Browse files
committed
Core: Support lucide react icons plugin for loader()
1 parent e19f009 commit 747bdbc

File tree

8 files changed

+58
-14
lines changed

8 files changed

+58
-14
lines changed

.changeset/quiet-bags-open.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'fumadocs-core': patch
3+
---
4+
5+
Support lucide react icons plugin for `loader()`

apps/docs/lib/source.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import { createMDXSource } from 'fumadocs-mdx/runtime/next';
2-
import type { InferMetaType, InferPageType } from 'fumadocs-core/source';
3-
import { loader } from 'fumadocs-core/source';
4-
import { icons } from 'lucide-react';
2+
import {
3+
type InferMetaType,
4+
type InferPageType,
5+
loader,
6+
} from 'fumadocs-core/source';
57
import { openapiPlugin } from 'fumadocs-openapi/server';
6-
import { createElement } from 'react';
78
import { blog as blogPosts, docs } from '@/.source';
9+
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
810

911
export const source = loader({
1012
baseUrl: '/docs',
11-
icon(icon) {
12-
if (icon && icon in icons)
13-
return createElement(icons[icon as keyof typeof icons]);
14-
},
1513
source: docs.toFumadocsSource(),
16-
plugins: [openapiPlugin()],
14+
plugins: [lucideIconsPlugin(), openapiPlugin()],
1715
});
1816

1917
export const blog = loader({

packages/core/package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
"import": "./dist/source/index.js",
6161
"types": "./dist/source/index.d.ts"
6262
},
63+
"./source/*": {
64+
"import": "./dist/source/plugins/*.js",
65+
"types": "./dist/source/plugins/*.d.ts"
66+
},
6367
"./utils/*": {
6468
"import": "./dist/utils/*.js",
6569
"types": "./dist/utils/*.d.ts"
@@ -146,6 +150,7 @@
146150
"@types/react-dom": "^19.1.9",
147151
"algoliasearch": "5.39.0",
148152
"eslint-config-custom": "workspace:*",
153+
"lucide-react": "^0.544.0",
149154
"mdast-util-mdx-jsx": "^3.2.0",
150155
"mdast-util-mdxjs-esm": "^2.0.1",
151156
"next": "^15.5.4",
@@ -168,7 +173,8 @@
168173
"react": "18.x.x || 19.x.x",
169174
"react-dom": "18.x.x || 19.x.x",
170175
"react-router": "7.x.x",
171-
"waku": "^0.26.0"
176+
"waku": "^0.26.0",
177+
"lucide-react": "*"
172178
},
173179
"peerDependenciesMeta": {
174180
"@mixedbread/sdk": {
@@ -200,6 +206,9 @@
200206
},
201207
"@tanstack/react-router": {
202208
"optional": true
209+
},
210+
"lucide-react": {
211+
"optional": true
203212
}
204213
},
205214
"publishConfig": {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { LoaderPlugin } from '@/source';
2+
import { iconPlugin } from '@/source/plugins/icon';
3+
import { icons } from 'lucide-react';
4+
import { createElement } from 'react';
5+
6+
/**
7+
* Convert icon names into Lucide Icons, requires `lucide-react` to be installed.
8+
*/
9+
export function lucideIconsPlugin(
10+
options: {
11+
defaultIcon?: keyof typeof icons;
12+
} = {},
13+
): LoaderPlugin {
14+
const { defaultIcon } = options;
15+
return iconPlugin((icon = defaultIcon) => {
16+
if (icon === undefined) return;
17+
const Icon = icons[icon as keyof typeof icons];
18+
if (!icon) {
19+
console.warn(`[lucide-icons-plugin] Unknown icon detected: ${icon}.`);
20+
return;
21+
}
22+
23+
return createElement(Icon);
24+
});
25+
}

packages/core/tsup.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export default defineConfig({
1212
entry: [
1313
'src/{toc,link,breadcrumb,sidebar,dynamic-link,hide-if-empty}.tsx',
1414
'src/{server,source,mdx-plugins,page-tree}/index.ts',
15-
'src/negotiation/*.ts',
16-
'src/content/*.ts',
15+
'src/{negotiation,content}/*',
16+
'src/source/plugins/lucide-icons.ts',
1717
'src/search/{index,client,server,algolia,orama-cloud}.ts',
1818
'src/utils/use-on-change.ts',
1919
'src/utils/use-effect-event.ts',

packages/create-app-versions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"version": "0.0.0",
44
"private": true,
55
"description": "Used to track dependency versions in create-fumadocs-app",
6-
"license": "MIT",
76
"dependencies": {
87
"@biomejs/biome": "^2.2.4",
98
"@content-collections/core": "^0.11.1",
@@ -23,6 +22,7 @@
2322
"@vitejs/plugin-react": "^5.0.3",
2423
"gray-matter": "^4.0.3",
2524
"isbot": "^5.1.31",
25+
"lucide-react": "^0.544.0",
2626
"next": "15.5.4",
2727
"postcss": "^8.5.6",
2828
"react": "^19.1.1",

packages/create-app/src/create-app.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,12 @@ async function createNextPackageJson(
233233
}[lint]),
234234
},
235235
dependencies: {
236-
...pick(versionPkg.dependencies, ['next', 'react', 'react-dom']),
236+
...pick(versionPkg.dependencies, [
237+
'next',
238+
'react',
239+
'react-dom',
240+
'lucide-react',
241+
]),
237242
...pick(localVersions, ['fumadocs-ui', 'fumadocs-core']),
238243
...{
239244
'+next+content-collections': {

packages/create-app/template/+next+fuma-docs-mdx/lib/source.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { docs } from '@/.source';
22
import { type InferPageType, loader } from 'fumadocs-core/source';
3+
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
34

45
// See https://fumadocs.dev/docs/headless/source-api for more info
56
export const source = loader({
67
baseUrl: '/docs',
78
source: docs.toFumadocsSource(),
9+
plugins: [lucideIconsPlugin()],
810
});
911

1012
export function getPageImage(page: InferPageType<typeof source>) {

0 commit comments

Comments
 (0)