fix: `processIncludes` no longer swallows errors

**BREAKING CHANGE:**
The previous `<!-- @include: ./path/to/file -->` syntax silently ignored errors when files did not exist. This behavior was originally intended as an escape hatch while documenting includes, but better solutions now exist using Shiki transformers.

For most users, no code changes are required. If you now see errors, it means your includes are broken and were previously not being reported.

Users who intentionally reference non-existent files or want to document includes without resolving them can configure `markdown.codeTransformers` with a `postprocess` hook. See `docs/.vitepress/config.ts` in this repo for an example.
pull/5113/head
Divyansh Singh 8 months ago
parent 5e12ef7f13
commit fb21fdf675

@ -26,10 +26,13 @@ export default defineConfig({
markdown: { markdown: {
math: true, math: true,
codeTransformers: [ codeTransformers: [
// We use `[!!code` in demo to prevent transformation, here we revert it back. // We use `[!!code` and `@@include` in demo to prevent transformation,
// here we revert it back.
{ {
postprocess(code) { postprocess(code) {
return code.replace(/\[\!\!code/g, '[!code') return code
.replace(/\[\!\!code/g, '[!code')
.replace('@@include', '@include')
} }
} }
], ],

@ -793,7 +793,7 @@ For example, you can include a relative markdown file using this:
## Basics ## Basics
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**Part file** (`parts/basics.md`) **Part file** (`parts/basics.md`)
@ -829,7 +829,7 @@ It also supports selecting a line range:
## Basics ## Basics
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**Part file** (`parts/basics.md`) **Part file** (`parts/basics.md`)
@ -865,8 +865,8 @@ You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/co
## Basics ## Basics
<!--@include: ./parts/basics.md#basic-usage{,2}--> <!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**Part file** (`parts/basics.md`) **Part file** (`parts/basics.md`)
@ -917,7 +917,7 @@ You can include the `My Base Section` section like this:
```md ```md
## My Extended Section ## My Extended Section
<!--@include: ./parts/basics.md#my-base-section--> <!--@@include: ./parts/basics.md#my-base-section-->
``` ```
**Equivalent code** **Equivalent code**
@ -941,7 +941,7 @@ Here, `my-base-section` is the generated id of the heading element. In case it's
and include it like this: and include it like this:
```md ```md
<!--@include: ./parts/basics.md#custom-id--> <!--@@include: ./parts/basics.md#custom-id-->
``` ```
## Math Equations ## Math Equations

@ -773,7 +773,7 @@ Por ejemplo, puede incluir un archivo markdown relativo usando esto:
## Conceptos Básicos ## Conceptos Básicos
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**Archivo de Parte** (`parts/basics.md`) **Archivo de Parte** (`parts/basics.md`)
@ -809,7 +809,7 @@ También soporta la selección de un intervalo de lineas:
## Conceptos Básicos ## Conceptos Básicos
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**Archivo de Parte** (`parts/basics.md`) **Archivo de Parte** (`parts/basics.md`)

@ -724,7 +724,7 @@ export default config
## مبانی ## مبانی
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**قسمت فایل** (`parts/basics.md`) **قسمت فایل** (`parts/basics.md`)
@ -760,7 +760,7 @@ export default config
## مبانی ## مبانی
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**قسمت فایل** (`parts/basics.md`) **قسمت فایل** (`parts/basics.md`)
@ -796,8 +796,8 @@ export default config
## مبانی ## مبانی
<!--@include: ./parts/basics.md#basic-usage{,2}--> <!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**قسمت فایل** (`parts/basics.md`) **قسمت فایل** (`parts/basics.md`)

@ -794,7 +794,7 @@ Markdown パスの先頭に `@` を付けることもでき、その場合はソ
## 基本 ## 基本
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**パートファイル**(`parts/basics.md`) **パートファイル**(`parts/basics.md`)
@ -830,7 +830,7 @@ Markdown パスの先頭に `@` を付けることもでき、その場合はソ
## 基本 ## 基本
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**パートファイル**(`parts/basics.md`) **パートファイル**(`parts/basics.md`)
@ -866,8 +866,8 @@ Markdown パスの先頭に `@` を付けることもでき、その場合はソ
## 基本 ## 基本
<!--@include: ./parts/basics.md#basic-usage{,2}--> <!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**パートファイル**(`parts/basics.md`) **パートファイル**(`parts/basics.md`)
@ -919,7 +919,7 @@ VS Code のリージョンの代わりに、ヘッダーアンカーを使って
```md ```md
## 拡張セクション ## 拡張セクション
<!--@include: ./parts/basics.md#my-base-section--> <!--@@include: ./parts/basics.md#my-base-section-->
``` ```
**等価なコード** **等価なコード**
@ -943,7 +943,7 @@ VS Code のリージョンの代わりに、ヘッダーアンカーを使って
そして次のように取り込みます: そして次のように取り込みます:
```md ```md
<!--@include: ./parts/basics.md#custom-id--> <!--@@include: ./parts/basics.md#custom-id-->
``` ```
## 数式 {#math-equations} ## 数式 {#math-equations}

@ -771,7 +771,7 @@ export default config
## Basics ## Basics
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**해당 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)
@ -807,7 +807,7 @@ Can be created using `.foorc.json`.
## Basics ## Basics
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**해당 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)
@ -843,8 +843,8 @@ Can be created using `.foorc.json`.
## Basics ## Basics
<!--@include: ./parts/basics.md#basic-usage{,2}--> <!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**해당 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)

@ -771,7 +771,7 @@ Por exemplo, você pode incluir um arquivo markdown relativo usando isto:
## Conceitos Básicos ## Conceitos Básicos
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**Arquivo da Parte** (`parts/basics.md`) **Arquivo da Parte** (`parts/basics.md`)
@ -807,7 +807,7 @@ Também suporta a seleção de um intervalo de linhas:
## Conceitos Básicos ## Conceitos Básicos
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**Arquivo da Parte** (`parts/basics.md`) **Arquivo da Parte** (`parts/basics.md`)

@ -795,7 +795,7 @@ export default config
## Основы ## Основы
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**Файл части** (`parts/basics.md`) **Файл части** (`parts/basics.md`)
@ -831,7 +831,7 @@ export default config
## Основы ## Основы
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**Файл части** (`parts/basics.md`) **Файл части** (`parts/basics.md`)
@ -867,8 +867,8 @@ export default config
## Основы ## Основы
<!--@include: ./parts/basics.md#basic-usage{,2}--> <!--@@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**Часть файла** (`parts/basics.md`) **Часть файла** (`parts/basics.md`)
@ -919,7 +919,7 @@ export default config
```md ```md
## Мой дополнительный раздел ## Мой дополнительный раздел
<!--@include: ./parts/basics.md#мои-основнои-раздел--> <!--@@include: ./parts/basics.md#мои-основнои-раздел-->
``` ```
**Соответствующий код** **Соответствующий код**
@ -943,7 +943,7 @@ export default config
и включить его следующим образом: и включить его следующим образом:
```md ```md
<!--@include: ./parts/basics.md#custom-id--> <!--@@include: ./parts/basics.md#custom-id-->
``` ```
## Математические уравнения {#math-equations} ## Математические уравнения {#math-equations}

@ -771,7 +771,7 @@ export default config
## Basics ## Basics
<!--@include: ./parts/basics.md--> <!--@@include: ./parts/basics.md-->
``` ```
**Part file** (`parts/basics.md`) **Part file** (`parts/basics.md`)
@ -807,7 +807,7 @@ Can be created using `.foorc.json`.
## Basics ## Basics
<!--@include: ./parts/basics.md{3,}--> <!--@@include: ./parts/basics.md{3,}-->
``` ```
**Part file** (`parts/basics.md`) **Part file** (`parts/basics.md`)

@ -1,8 +1,7 @@
import fs from 'fs-extra'
import matter from 'gray-matter' import matter from 'gray-matter'
import type { MarkdownItAsync } from 'markdown-it-async' import type { MarkdownItAsync } from 'markdown-it-async'
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import c from 'picocolors'
import { findRegion } from '../markdown/plugins/snippet' import { findRegion } from '../markdown/plugins/snippet'
import { slash, type MarkdownEnv } from '../shared' import { slash, type MarkdownEnv } from '../shared'
@ -33,78 +32,70 @@ export function processIncludes(
const atPresent = m1[0] === '@' const atPresent = m1[0] === '@'
try { const includePath = atPresent
const includePath = atPresent ? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1))
? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1)) : path.join(path.dirname(file), m1)
: path.join(path.dirname(file), m1)
let content = fs.readFileSync(includePath, 'utf-8')
if (region) { let content = fs.readFileSync(includePath, 'utf-8')
const [regionName] = region
const lines = content.split(/\r?\n/)
let { start, end } = findRegion(lines, regionName.slice(1)) ?? {}
if (start === undefined) { if (region) {
// region not found, it might be a header const [regionName] = region
const tokens = md const lines = content.split(/\r?\n/)
.parse(content, { let { start, end } = findRegion(lines, regionName.slice(1)) ?? {}
path: includePath,
relativePath: slash(path.relative(srcDir, includePath)), if (start === undefined) {
cleanUrls // region not found, it might be a header
} satisfies MarkdownEnv) const tokens = md
.filter((t) => t.type === 'heading_open' && t.map) .parse(content, {
const idx = tokens.findIndex( path: includePath,
(t) => t.attrGet('id') === regionName.slice(1) relativePath: slash(path.relative(srcDir, includePath)),
) cleanUrls
const token = tokens[idx] } satisfies MarkdownEnv)
if (token) { .filter((t) => t.type === 'heading_open' && t.map)
start = token.map![1] const idx = tokens.findIndex(
const level = parseInt(token.tag.slice(1)) (t) => t.attrGet('id') === regionName.slice(1)
for (let i = idx + 1; i < tokens.length; i++) { )
if (parseInt(tokens[i].tag.slice(1)) <= level) { const token = tokens[idx]
end = tokens[i].map![0] if (token) {
break start = token.map![1]
} const level = parseInt(token.tag.slice(1))
for (let i = idx + 1; i < tokens.length; i++) {
if (parseInt(tokens[i].tag.slice(1)) <= level) {
end = tokens[i].map![0]
break
} }
} }
} }
content = lines.slice(start, end).join('\n')
} }
if (range) { content = lines.slice(start, end).join('\n')
const [, startLine, endLine] = range }
const lines = content.split(/\r?\n/)
content = lines
.slice(
startLine ? parseInt(startLine) - 1 : undefined,
endLine ? parseInt(endLine) : undefined
)
.join('\n')
}
if (!hasMeta && path.extname(includePath) === '.md') { if (range) {
content = matter(content).content const [, startLine, endLine] = range
} const lines = content.split(/\r?\n/)
content = lines
.slice(
startLine ? parseInt(startLine) - 1 : undefined,
endLine ? parseInt(endLine) : undefined
)
.join('\n')
}
includes.push(slash(includePath)) if (!hasMeta && path.extname(includePath) === '.md') {
// recursively process includes in the content content = matter(content).content
return processIncludes( }
md,
srcDir,
content,
includePath,
includes,
cleanUrls
)
// includes.push(slash(includePath))
} catch (error) {
if (process.env.DEBUG) {
process.stderr.write(c.yellow(`\nInclude file not found: ${m1}`))
}
return m // silently ignore error if file is not present // recursively process includes in the content
} return processIncludes(
md,
srcDir,
content,
includePath,
includes,
cleanUrls
)
}) })
} }

Loading…
Cancel
Save