feat: add markdown file inclusion

This commit is contained in:
YunYouJun 2023-10-07 02:19:59 +08:00
parent a786208a9e
commit a8757de39e
3 changed files with 82 additions and 16 deletions

View File

@ -425,19 +425,24 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$
## Markdown File Inclusion
::: tip
You can also prefix the markdown path with `@`, it will act as the source root. By default, it's the Valaxy project root.
:::
**Input**
```md
# Docs
## Basics
## Docs
<!--@include: @/TEST.md-->
<!--@include: ./parts/basics.md-->
```
**Part file** (`parts/basics.md`)
**Part file**
```md
::: code-group
```md [parts/basics.md]
Some getting started stuff.
### Configuration
@ -445,13 +450,18 @@ Some getting started stuff.
Can be created using `.foorc.json`.
```
```md [TEST.md]
I'm a TEST.
```
:::
**Equivalent code**
```md
# Docs
## Basics
## Docs
I'm a TEST.
Some getting started stuff.
### Configuration
@ -464,16 +474,17 @@ It also supports selecting a line range:
**Input**
```md
# Docs
## Basics
## Docs
<!--@include: @/TEST.md-->
<!--@include: ./parts/basics.md{3,}-->
```
**Part file** (`parts/basics.md`)
**Part file**
```md
::: code-group
```md [parts/basics.md]
Some getting started stuff.
### Configuration
@ -481,13 +492,18 @@ Some getting started stuff.
Can be created using `.foorc.json`.
```
```md [TEST.md]
I'm a TEST.
```
:::
**Equivalent code**
```md
# Docs
## Basics
## Docs
I'm a TEST.
### Configuration
Can be created using `.foorc.json`.

View File

@ -10,6 +10,7 @@ import { getGitTimestamp, slash, transformObject } from '../utils'
import type { CleanUrlsMode, HeadConfig, PageData } from '../../types'
import type { ResolvedValaxyOptions } from '../options'
import { encryptContent } from '../utils/encrypt'
import { processIncludes } from './utils/processInclude'
import { createMarkdownRenderer } from '.'
import type { MarkdownEnv, MarkdownRenderer } from '.'
@ -130,6 +131,7 @@ export async function createMarkdownToVueRenderFn(
// resolve includes
const includes: string[] = []
src = processIncludes(srcDir, src, fileOrig, includes)
src = src.replace(includesRE, (m, m1) => {
try {
const includePath = path.join(dir, m1)

View File

@ -0,0 +1,48 @@
/**
* @file Utility function to process includes in markdown files
* @description ref vitepress/packages/vitepress/src/node/markdown/utils/processInclude.ts
*/
import path from 'node:path'
import fs from 'fs-extra'
import { slash } from '@antfu/utils'
export function processIncludes(
srcDir: string,
src: string,
file: string,
includes: string[],
): string {
const includesRE = /<!--\s*@include:\s*(.*?)\s*-->/g
const rangeRE = /\{(\d*),(\d*)\}$/
return src.replace(includesRE, (m: string, m1: string) => {
if (!m1.length)
return m
const range = m1.match(rangeRE)
range && (m1 = m1.slice(0, -range[0].length))
const atPresent = m1[0] === '@'
try {
const includePath = atPresent
? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1))
: path.join(path.dirname(file), m1)
let content = fs.readFileSync(includePath, 'utf-8')
if (range) {
const [, startLine, endLine] = range
const lines = content.split(/\r?\n/)
content = lines
.slice(
startLine ? Number.parseInt(startLine, 10) - 1 : undefined,
endLine ? Number.parseInt(endLine, 10) : undefined,
)
.join('\n')
}
includes.push(slash(includePath))
// recursively process includes in the content
return processIncludes(srcDir, content, includePath, includes)
}
catch (error) {
return m // silently ignore error if file is not present
}
})
}