mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Enable remarkNpm by default, replace remarkInstall with it.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'fumadocs-docgen': minor
|
||||
'fumadocs-core': patch
|
||||
'fumadocs-mdx': patch
|
||||
'@fumadocs/mdx-remote': patch
|
||||
---
|
||||
|
||||
Enable `remarkNpm` by default, replace `remarkInstall` with it.
|
||||
@@ -101,6 +101,7 @@
|
||||
"hast-util-to-jsx-runtime": "^2.3.6",
|
||||
"image-size": "^2.0.2",
|
||||
"negotiator": "^1.0.0",
|
||||
"npm-to-yarn": "^3.0.1",
|
||||
"react-remove-scroll": "^2.7.1",
|
||||
"remark": "^15.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
|
||||
@@ -10,3 +10,4 @@ export * from './remark-admonition';
|
||||
export * from './rehype-toc';
|
||||
export * from './remark-code-tab';
|
||||
export * from './remark-steps';
|
||||
export * from './remark-npm';
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import type { Root } from 'mdast';
|
||||
import type { Transformer } from 'unified';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import convert from 'npm-to-yarn';
|
||||
import type { MdxJsxAttribute, MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
||||
|
||||
interface PackageManager {
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Convert from npm to another package manager
|
||||
*/
|
||||
command: (command: string) => string;
|
||||
}
|
||||
|
||||
export interface RemarkNpmOptions {
|
||||
/**
|
||||
* Persist Tab value (Fumadocs UI only)
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
persist?:
|
||||
| {
|
||||
id: string;
|
||||
}
|
||||
| false;
|
||||
|
||||
packageManagers?: PackageManager[];
|
||||
}
|
||||
|
||||
const aliases = ['npm', 'package-install'];
|
||||
|
||||
/**
|
||||
* It generates multiple tabs of codeblocks for different package managers from a npm command codeblock.
|
||||
*/
|
||||
export function remarkNpm({
|
||||
persist = false,
|
||||
packageManagers = [
|
||||
{ command: (cmd) => convert(cmd, 'npm'), name: 'npm' },
|
||||
{ command: (cmd) => convert(cmd, 'pnpm'), name: 'pnpm' },
|
||||
{ command: (cmd) => convert(cmd, 'yarn'), name: 'yarn' },
|
||||
{ command: (cmd) => convert(cmd, 'bun'), name: 'bun' },
|
||||
],
|
||||
}: RemarkNpmOptions = {}): Transformer<Root, Root> {
|
||||
return (tree) => {
|
||||
visit(tree, 'code', (node) => {
|
||||
if (!node.lang || !aliases.includes(node.lang)) return 'skip';
|
||||
|
||||
const value =
|
||||
node.value.startsWith('npm') || node.value.startsWith('npx')
|
||||
? node.value
|
||||
: `npm install ${node.value}`;
|
||||
const attributes: MdxJsxAttribute[] = [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'defaultValue',
|
||||
value: packageManagers[0].name,
|
||||
},
|
||||
];
|
||||
|
||||
if (typeof persist === 'object') {
|
||||
attributes.push(
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'groupId',
|
||||
value: persist.id,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'persist',
|
||||
value: null,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const children: MdxJsxFlowElement[] = [
|
||||
{
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTabsList',
|
||||
attributes: [],
|
||||
children: packageManagers.map(
|
||||
({ name }) =>
|
||||
({
|
||||
type: 'mdxJsxFlowElement',
|
||||
attributes: [
|
||||
{ type: 'mdxJsxAttribute', name: 'value', value: name },
|
||||
],
|
||||
name: 'CodeBlockTabsTrigger',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
value: name,
|
||||
} as unknown,
|
||||
],
|
||||
}) as MdxJsxFlowElement,
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
for (const { name, command } of packageManagers) {
|
||||
children.push({
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTab',
|
||||
attributes: [{ type: 'mdxJsxAttribute', name: 'value', value: name }],
|
||||
children: [
|
||||
{
|
||||
type: 'code',
|
||||
lang: 'bash',
|
||||
meta: node.meta,
|
||||
value: command(value),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const tab: MdxJsxFlowElement = {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTabs',
|
||||
attributes,
|
||||
children,
|
||||
};
|
||||
|
||||
Object.assign(node, tab);
|
||||
return;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import type { Transformer } from 'unified';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import convert from 'npm-to-yarn';
|
||||
import { createElement, expressionToAttribute } from './utils';
|
||||
import { MdxJsxAttribute, MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
||||
|
||||
interface PackageManager {
|
||||
name: string;
|
||||
@@ -14,7 +13,10 @@ interface PackageManager {
|
||||
command: (command: string) => string;
|
||||
}
|
||||
|
||||
interface BaseOptions {
|
||||
export type RemarkInstallOptions = {
|
||||
Tabs?: string;
|
||||
Tab?: string;
|
||||
|
||||
/**
|
||||
* Persist Tab value (Fumadocs UI only)
|
||||
*
|
||||
@@ -27,19 +29,7 @@ interface BaseOptions {
|
||||
| false;
|
||||
|
||||
packageManagers?: PackageManager[];
|
||||
}
|
||||
|
||||
export type RemarkInstallOptions = BaseOptions &
|
||||
(
|
||||
| {
|
||||
mode?: 'legacy';
|
||||
Tabs?: string;
|
||||
Tab?: string;
|
||||
}
|
||||
| {
|
||||
mode: 'auto';
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* It generates the following structure from a code block with `package-install` as language
|
||||
@@ -51,8 +41,12 @@ export type RemarkInstallOptions = BaseOptions &
|
||||
* ...
|
||||
* </Tabs>
|
||||
* ```
|
||||
*
|
||||
* @deprecated Use `remarkNpm` from `fumadocs-core/mdx-plugins` instead, it's a drop-in replacement.
|
||||
*/
|
||||
export function remarkInstall({
|
||||
Tab = 'Tab',
|
||||
Tabs = 'Tabs',
|
||||
persist = false,
|
||||
packageManagers = [
|
||||
{ command: (cmd) => convert(cmd, 'npm'), name: 'npm' },
|
||||
@@ -60,105 +54,41 @@ export function remarkInstall({
|
||||
{ command: (cmd) => convert(cmd, 'yarn'), name: 'yarn' },
|
||||
{ command: (cmd) => convert(cmd, 'bun'), name: 'bun' },
|
||||
],
|
||||
...options
|
||||
}: RemarkInstallOptions = {}): Transformer<Root, Root> {
|
||||
return (tree) => {
|
||||
visit(tree, 'code', (node) => {
|
||||
if (node.lang !== 'package-install') return 'skip';
|
||||
|
||||
const value =
|
||||
node.value.startsWith('npm') || node.value.startsWith('npx')
|
||||
? node.value
|
||||
: `npm install ${node.value}`;
|
||||
const attributes: MdxJsxAttribute[] = [];
|
||||
if (typeof persist === 'object') {
|
||||
attributes.push(
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'groupId',
|
||||
value: persist.id,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'persist',
|
||||
value: null,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (options.mode === 'auto') {
|
||||
attributes.push({
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'defaultValue',
|
||||
value: packageManagers[0].name,
|
||||
});
|
||||
|
||||
const children: MdxJsxFlowElement[] = [
|
||||
{
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTabsList',
|
||||
attributes: [],
|
||||
children: packageManagers.map(
|
||||
({ name }) =>
|
||||
({
|
||||
type: 'mdxJsxFlowElement',
|
||||
attributes: [
|
||||
{ type: 'mdxJsxAttribute', name: 'value', value: name },
|
||||
],
|
||||
name: 'CodeBlockTabsTrigger',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
value: name,
|
||||
} as unknown,
|
||||
],
|
||||
}) as MdxJsxFlowElement,
|
||||
),
|
||||
},
|
||||
...packageManagers.map(
|
||||
({ command, name }) =>
|
||||
({
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTab',
|
||||
attributes: [
|
||||
{ type: 'mdxJsxAttribute', name: 'value', value: name },
|
||||
],
|
||||
children: [
|
||||
{
|
||||
type: 'code',
|
||||
lang: 'bash',
|
||||
meta: node.meta,
|
||||
value: command(value),
|
||||
},
|
||||
],
|
||||
}) as MdxJsxFlowElement,
|
||||
),
|
||||
];
|
||||
|
||||
const tab: MdxJsxFlowElement = {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'CodeBlockTabs',
|
||||
attributes,
|
||||
children,
|
||||
};
|
||||
|
||||
Object.assign(node, tab);
|
||||
return;
|
||||
}
|
||||
|
||||
const { Tabs = 'Tabs', Tab = 'Tab' } = options;
|
||||
attributes.push(
|
||||
expressionToAttribute('items', {
|
||||
type: 'ArrayExpression',
|
||||
elements: packageManagers.map(({ name }) => ({
|
||||
type: 'Literal',
|
||||
value: name,
|
||||
})),
|
||||
}),
|
||||
);
|
||||
|
||||
const insert = createElement(
|
||||
Tabs,
|
||||
attributes,
|
||||
[
|
||||
...(typeof persist === 'object'
|
||||
? [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'groupId',
|
||||
value: persist.id,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'persist',
|
||||
value: null,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
expressionToAttribute('items', {
|
||||
type: 'ArrayExpression',
|
||||
elements: packageManagers.map(({ name }) => ({
|
||||
type: 'Literal',
|
||||
value: name,
|
||||
})),
|
||||
}),
|
||||
],
|
||||
packageManagers.map(({ command, name }) => ({
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: Tab,
|
||||
|
||||
@@ -18,6 +18,7 @@ export type MDXOptions = Omit<
|
||||
rehypeCodeOptions?: Plugins.RehypeCodeOptions | false;
|
||||
rehypeTocOptions?: Plugins.RehypeTocOptions | false;
|
||||
remarkCodeTabOptions?: Plugins.RemarkCodeTabOptions | false;
|
||||
remarkNpmOptions?: Plugins.RemarkNpmOptions | false;
|
||||
|
||||
/**
|
||||
* The directory to find image sizes
|
||||
@@ -142,6 +143,7 @@ function getCompileOptions({
|
||||
rehypeTocOptions,
|
||||
remarkHeadingOptions,
|
||||
remarkCodeTabOptions,
|
||||
remarkNpmOptions,
|
||||
imageDir = './public',
|
||||
...options
|
||||
}: MDXOptions = {}): CompileOptions {
|
||||
@@ -153,6 +155,7 @@ function getCompileOptions({
|
||||
const remarkGfm = getPlugin('remarkGfm');
|
||||
const remarkHeading = getPlugin('remarkHeading');
|
||||
const remarkCodeTab = getPlugin('remarkCodeTab');
|
||||
const remarkNpm = getPlugin('remarkNpm');
|
||||
const remarkImage = getPlugin('remarkImage');
|
||||
const rehypeCode = getPlugin('rehypeCode');
|
||||
const rehypeToc = getPlugin('rehypeToc');
|
||||
@@ -179,6 +182,9 @@ function getCompileOptions({
|
||||
remarkCodeTab && remarkCodeTabOptions !== false
|
||||
? [remarkCodeTab, remarkCodeTabOptions]
|
||||
: null,
|
||||
remarkNpm && remarkNpmOptions !== false
|
||||
? [remarkNpm, remarkNpmOptions]
|
||||
: null,
|
||||
...v,
|
||||
],
|
||||
options.remarkPlugins,
|
||||
|
||||
@@ -22,6 +22,7 @@ export type DefaultMDXOptions = Omit<
|
||||
remarkHeadingOptions?: plugins.RemarkHeadingOptions;
|
||||
remarkImageOptions?: plugins.RemarkImageOptions | false;
|
||||
remarkCodeTabOptions?: plugins.RemarkCodeTabOptions | false;
|
||||
remarkNpmOptions?: plugins.RemarkNpmOptions | false;
|
||||
rehypeCodeOptions?: plugins.RehypeCodeOptions | false;
|
||||
};
|
||||
|
||||
@@ -47,6 +48,7 @@ export function getDefaultMDXOptions({
|
||||
remarkHeadingOptions,
|
||||
remarkStructureOptions,
|
||||
remarkCodeTabOptions,
|
||||
remarkNpmOptions,
|
||||
...mdxOptions
|
||||
}: DefaultMDXOptions): ProcessorOptions {
|
||||
const mdxExports = [
|
||||
@@ -67,12 +69,13 @@ export function getDefaultMDXOptions({
|
||||
},
|
||||
],
|
||||
remarkImageOptions !== false && [plugins.remarkImage, remarkImageOptions],
|
||||
// Fumadocs 14 compatibility
|
||||
'remarkCodeTab' in plugins &&
|
||||
remarkCodeTabOptions !== false && [
|
||||
plugins.remarkCodeTab,
|
||||
remarkCodeTabOptions,
|
||||
],
|
||||
'remarkNpm' in plugins &&
|
||||
remarkNpmOptions !== false && [plugins.remarkNpm, remarkNpmOptions],
|
||||
...v,
|
||||
remarkStructureOptions !== false && [
|
||||
plugins.remarkStructure,
|
||||
|
||||
Generated
+3
@@ -796,6 +796,9 @@ importers:
|
||||
negotiator:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
npm-to-yarn:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
react:
|
||||
specifier: 18.x.x || 19.x.x
|
||||
version: 19.1.0
|
||||
|
||||
Reference in New Issue
Block a user