mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 23:49:51 +00:00
Zeta: Support generating package install commands
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'next-docs-zeta': patch
|
||||
---
|
||||
|
||||
Support generating package install codeblocks automatically
|
||||
@@ -20,8 +20,8 @@ It's recommended to use Next Docs with [Tailwind CSS](https://tailwindcss.com) +
|
||||
For normal usages, you can use [Next Docs UI](/docs/ui) instead.
|
||||
</Callout>
|
||||
|
||||
```bash
|
||||
npm install next-docs-zeta shiki
|
||||
```package-install
|
||||
next-docs-zeta shiki
|
||||
```
|
||||
|
||||
### Demo
|
||||
|
||||
@@ -22,8 +22,8 @@ paragraphs are all indexed as a record, and the attribute for distinct is
|
||||
|
||||
1. Install `algoliasearch`
|
||||
|
||||
```bash
|
||||
npm install algoliasearch
|
||||
```package-install
|
||||
algoliasearch
|
||||
```
|
||||
|
||||
2. Sign up and obtain the required API keys for your search. Store these
|
||||
|
||||
@@ -17,8 +17,8 @@ plugins for building a good documentation site.
|
||||
|
||||
Notice that the package doesn't include loader by default.
|
||||
|
||||
```bash
|
||||
npm install next-docs-mdx @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
|
||||
```package-install
|
||||
next-docs-mdx @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
@@ -10,8 +10,8 @@ detected, it will throw an error immediately.
|
||||
|
||||
To customise the schemas, you have to install `zod`.
|
||||
|
||||
```bash
|
||||
npm install zod
|
||||
```package-install
|
||||
zod
|
||||
```
|
||||
|
||||
Now you can override or extend the default zod schemas by passing a `validate`
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Generate documentation sites with a command
|
||||
|
||||
No arguments needed.
|
||||
|
||||
<Tabs items={["npm", "pnpm", "yarn"]} defaultValue="npm">
|
||||
<InstallTabs>
|
||||
<Tab value="npm">
|
||||
|
||||
```bash
|
||||
@@ -29,7 +29,7 @@ yarn create next-docs-app
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</InstallTabs>
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ yarn create next-docs-app
|
||||
|
||||
Install required dependencies
|
||||
|
||||
```bash
|
||||
npm install next-docs-ui next-docs-zeta
|
||||
```package-install
|
||||
next-docs-ui next-docs-zeta
|
||||
```
|
||||
|
||||
<h3>Configuration</h3>
|
||||
@@ -52,8 +52,8 @@ Next Docs UI doesn't provide static generation directly. You can use a source
|
||||
you prefer, such as [Contentlayer](https://www.contentlayer.dev) which is
|
||||
supported by default. **This guide is written for Contentlayer.**
|
||||
|
||||
```bash
|
||||
npm install contentlayer next-contentlayer
|
||||
```package-install
|
||||
contentlayer next-contentlayer
|
||||
```
|
||||
|
||||
1. **Configure Contentlayer**
|
||||
|
||||
@@ -10,8 +10,8 @@ import 'katex/dist/katex.min.css'
|
||||
Next Docs UI doesn't bundle with other plugins, you have to manually install
|
||||
those plugins.
|
||||
|
||||
```bash
|
||||
npm install remark-math rehype-katex katex
|
||||
```package-install
|
||||
remark-math rehype-katex katex
|
||||
```
|
||||
|
||||
### Add Plugins
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Callout } from 'next-docs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'next-docs-ui/components/tabs'
|
||||
import { TypeTable } from 'next-docs-ui/components/type-table'
|
||||
import defaultComponents from 'next-docs-ui/mdx-server'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
return {
|
||||
@@ -20,6 +21,19 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
Accordion: (p => <Accordion {...p} />) as typeof Accordion,
|
||||
Accordions: (p => <Accordions {...p} />) as typeof Accordions,
|
||||
Wrapper,
|
||||
InstallTabs: ({
|
||||
items,
|
||||
children
|
||||
}: {
|
||||
items: string[]
|
||||
children: ReactNode
|
||||
}) => {
|
||||
return (
|
||||
<Tabs items={items} id="package-manager" persist>
|
||||
{children}
|
||||
</Tabs>
|
||||
)
|
||||
},
|
||||
blockquote: props => <Callout className="my-4">{props.children}</Callout>,
|
||||
...components
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import createBundleAnalyzer from '@next/bundle-analyzer'
|
||||
import createNextDocs from 'next-docs-mdx/config'
|
||||
import { remarkDynamicContent } from 'next-docs-zeta/mdx-plugins'
|
||||
import { remarkDynamicContent, remarkInstall } from 'next-docs-zeta/mdx-plugins'
|
||||
import rehypeKatex from 'rehype-katex'
|
||||
import remarkMath from 'remark-math'
|
||||
|
||||
@@ -20,7 +20,11 @@ const config = {
|
||||
|
||||
const withNextDocs = createNextDocs({
|
||||
mdxOptions: {
|
||||
remarkPlugins: [remarkMath, remarkDynamicContent],
|
||||
remarkPlugins: [
|
||||
remarkMath,
|
||||
remarkDynamicContent,
|
||||
[remarkInstall, { Tabs: 'InstallTabs' }]
|
||||
],
|
||||
rehypePlugins: [rehypeKatex]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -13,3 +13,4 @@ export {
|
||||
} from './mdx-plugins/remark-dynamic-content'
|
||||
export * from './mdx-plugins/remark-structure'
|
||||
export { remarkToc } from './mdx-plugins/remark-toc'
|
||||
export * from './mdx-plugins/remark-install'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import type { Root } from 'mdast'
|
||||
import type { Content, Root } from 'mdast'
|
||||
import type { Transformer } from 'unified'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { visit } from './unist-visit'
|
||||
|
||||
const regex = /^\|reference:(.+)\|/
|
||||
|
||||
@@ -35,7 +35,7 @@ export function remarkDynamicContent(
|
||||
} = options
|
||||
|
||||
return tree => {
|
||||
visit(tree, filter, node => {
|
||||
visit(tree, filter, (node: Content) => {
|
||||
if (!('value' in node) || typeof node.value !== 'string') return
|
||||
const result = regex.exec(node.value)
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import type { Code, Root } from 'mdast'
|
||||
import type { Transformer } from 'unified'
|
||||
import { visit } from './unist-visit'
|
||||
|
||||
type PackageManager = (name: string) => {
|
||||
packageManager: string
|
||||
command: string
|
||||
}
|
||||
|
||||
export type RemarkInstallOptions = {
|
||||
Tabs: string
|
||||
Tab: string
|
||||
packageManagers: PackageManager[]
|
||||
}
|
||||
|
||||
export function remarkInstall({
|
||||
Tab = 'Tab',
|
||||
Tabs = 'Tabs',
|
||||
packageManagers = [
|
||||
name => ({ command: `npm install ${name}`, packageManager: 'npm' }),
|
||||
name => ({ command: `pnpm add ${name}`, packageManager: 'pnpm' }),
|
||||
name => ({ command: `yarn add ${name}`, packageManager: 'yarn' })
|
||||
]
|
||||
}: Partial<RemarkInstallOptions> = {}): Transformer<Root, Root> {
|
||||
return tree => {
|
||||
visit(tree, ['code'], (node: Code) => {
|
||||
if (node.lang !== 'package-install') return 'skip'
|
||||
|
||||
const managers = packageManagers.map(manager => manager(node.value))
|
||||
|
||||
const insert = {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: Tabs,
|
||||
attributes: [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'items',
|
||||
value: {
|
||||
type: 'mdxJsxAttributeValueExpression',
|
||||
data: {
|
||||
estree: {
|
||||
body: [
|
||||
{
|
||||
type: 'ExpressionStatement',
|
||||
expression: {
|
||||
type: 'ArrayExpression',
|
||||
elements: managers.map(({ packageManager }) => ({
|
||||
type: 'Literal',
|
||||
value: packageManager
|
||||
}))
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
children: managers.map(({ command, packageManager }) => ({
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: Tab,
|
||||
attributes: [
|
||||
{ type: 'mdxJsxAttribute', name: 'value', value: packageManager }
|
||||
],
|
||||
children: [
|
||||
{
|
||||
type: 'code',
|
||||
lang: 'bash',
|
||||
value: command
|
||||
} satisfies Code
|
||||
]
|
||||
}))
|
||||
}
|
||||
|
||||
Object.assign(node, insert)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import Slugger from 'github-slugger'
|
||||
import type { Root } from 'mdast'
|
||||
import type { Content as MdastContent, Root } from 'mdast'
|
||||
import { remark } from 'remark'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import remarkMdx from 'remark-mdx'
|
||||
import type { PluggableList, Transformer } from 'unified'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { flattenNode } from './remark-utils'
|
||||
import { visit } from './unist-visit'
|
||||
|
||||
type Heading = {
|
||||
id: string
|
||||
@@ -47,9 +47,7 @@ export function remarkStructure({
|
||||
const data: StructuredData = { contents: [], headings: [] }
|
||||
let lastHeading: string | undefined = ''
|
||||
|
||||
visit(node, types, element => {
|
||||
if (element.type === 'root') return
|
||||
|
||||
visit(node, types, (element: MdastContent) => {
|
||||
if (element.type === 'heading') {
|
||||
const heading = flattenNode(element)
|
||||
const slug = slugger.slug(heading)
|
||||
|
||||
@@ -2,8 +2,8 @@ import type { TOCItemType } from '@/server/types'
|
||||
import Slugger from 'github-slugger'
|
||||
import type { Heading, Root } from 'mdast'
|
||||
import type { Transformer } from 'unified'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { flattenNode } from './remark-utils'
|
||||
import { visit } from './unist-visit'
|
||||
|
||||
const slugger = new Slugger()
|
||||
|
||||
@@ -15,8 +15,7 @@ export function remarkToc(): Transformer<Root, Root> {
|
||||
const toc: TOCItemType[] = []
|
||||
slugger.reset()
|
||||
|
||||
visit(node, ['heading'], child => {
|
||||
const heading = child as Heading
|
||||
visit(node, ['heading'], (heading: Heading) => {
|
||||
const text = flattenNode(heading)
|
||||
|
||||
toc.push({
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { Content, Literal } from 'mdast'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { visit } from './unist-visit'
|
||||
|
||||
const textTypes = ['text', 'inlineCode', 'code']
|
||||
|
||||
export function flattenNode(node: Content): string {
|
||||
const p: string[] = []
|
||||
|
||||
visit(node, textTypes, child => {
|
||||
p.push((child as Literal).value)
|
||||
visit(node, textTypes, (child: Literal) => {
|
||||
p.push(child.value)
|
||||
})
|
||||
|
||||
return p.join('')
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { visit as original } from 'unist-util-visit'
|
||||
|
||||
type SimpleVisit = {
|
||||
<R, T>(node: R, callback: (v: T) => void): void | 'skip'
|
||||
<R, T>(node: R, check: string[], callback: (v: T) => void): void | 'skip'
|
||||
}
|
||||
|
||||
/**
|
||||
* The default type binding is too complicated, it slows the whole Typescript language server
|
||||
*/
|
||||
export const visit: SimpleVisit = original as unknown as SimpleVisit
|
||||
Reference in New Issue
Block a user