Skip to content

Commit 20e4c24

Browse files
authored
feat: handle loader error (#1718)
1 parent 1b5f768 commit 20e4c24

File tree

6 files changed

+57
-24
lines changed

6 files changed

+57
-24
lines changed

packages/parser/fs.d.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/parser/package.json

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,21 @@
1313
"bugs": "https://github.com/slidevjs/slidev/issues",
1414
"exports": {
1515
".": {
16-
"types": "./dist/index.d.ts",
17-
"import": "./dist/index.mjs",
18-
"require": "./dist/index.js"
16+
"types": "./dist/index.d.mts",
17+
"import": "./dist/index.mjs"
1918
},
2019
"./core": {
21-
"types": "./dist/core.d.ts",
22-
"import": "./dist/core.mjs",
23-
"require": "./dist/core.js"
20+
"types": "./dist/core.d.mts",
21+
"import": "./dist/core.mjs"
2422
},
2523
"./fs": {
26-
"types": "./fs.d.ts",
27-
"import": "./dist/fs.mjs",
28-
"require": "./dist/fs.js"
24+
"types": "./dist/fs.d.mts",
25+
"import": "./dist/fs.mjs"
2926
}
3027
},
31-
"main": "dist/index.js",
28+
"main": "dist/index.mjs",
3229
"module": "dist/index.mjs",
33-
"types": "dist/index.d.ts",
30+
"types": "dist/index.d.mts",
3431
"files": [
3532
"*.d.ts",
3633
"dist"

packages/parser/src/fs.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { promises as fs } from 'node:fs'
1+
import fs from 'node:fs'
22
import { dirname, resolve } from 'node:path'
33
import YAML from 'yaml'
44
import { slash } from '@antfu/utils'
@@ -20,7 +20,7 @@ export function injectPreparserExtensionLoader(fn: PreparserExtensionLoader) {
2020
export type LoadedSlidevData = Omit<SlidevData, 'config' | 'themeMeta'>
2121

2222
export async function load(userRoot: string, filepath: string, content?: string, mode?: string): Promise<LoadedSlidevData> {
23-
const markdown = content ?? await fs.readFile(filepath, 'utf-8')
23+
const markdown = content ?? fs.readFileSync(filepath, 'utf-8')
2424

2525
let extensions: SlidevPreparserExtension[] | undefined
2626
if (preparserExtensionLoader) {
@@ -45,23 +45,33 @@ export async function load(userRoot: string, filepath: string, content?: string,
4545
async function loadMarkdown(path: string, range?: string, frontmatterOverride?: Record<string, unknown>, importers?: SourceSlideInfo[]) {
4646
let md = markdownFiles[path]
4747
if (!md) {
48-
const raw = await fs.readFile(path, 'utf-8')
48+
const raw = fs.readFileSync(path, 'utf-8')
4949
md = await parse(raw, path, extensions)
5050
markdownFiles[path] = md
5151
}
5252

5353
const directImporter = importers?.at(-1)
5454
for (const index of parseRangeString(md.slides.length, range)) {
5555
const subSlide = md.slides[index - 1]
56-
await loadSlide(subSlide, frontmatterOverride, importers)
56+
try {
57+
await loadSlide(md, subSlide, frontmatterOverride, importers)
58+
}
59+
catch (e) {
60+
md.errors ??= []
61+
md.errors.push({
62+
row: subSlide.start,
63+
message: `Error when loading slide: ${e}`,
64+
})
65+
continue
66+
}
5767
if (directImporter)
5868
(directImporter.imports ??= []).push(subSlide)
5969
}
6070

6171
return md
6272
}
6373

64-
async function loadSlide(slide: SourceSlideInfo, frontmatterOverride?: Record<string, unknown>, importChain?: SourceSlideInfo[]) {
74+
async function loadSlide(md: SlidevMarkdown, slide: SourceSlideInfo, frontmatterOverride?: Record<string, unknown>, importChain?: SourceSlideInfo[]) {
6575
if (slide.frontmatter.disabled || slide.frontmatter.hide)
6676
return
6777
if (slide.frontmatter.src) {
@@ -78,7 +88,16 @@ export async function load(userRoot: string, filepath: string, content?: string,
7888
}
7989
delete frontmatterOverride.src
8090

81-
await loadMarkdown(path, rangeRaw, frontmatterOverride, importChain ? [...importChain, slide] : [slide])
91+
if (!fs.existsSync(path)) {
92+
md.errors ??= []
93+
md.errors.push({
94+
row: slide.start,
95+
message: `Imported markdown file not found: ${path}`,
96+
})
97+
}
98+
else {
99+
await loadMarkdown(path, rangeRaw, frontmatterOverride, importChain ? [...importChain, slide] : [slide])
100+
}
82101
}
83102
else {
84103
slides.push({
@@ -112,6 +131,6 @@ export async function load(userRoot: string, filepath: string, content?: string,
112131

113132
export async function save(markdown: SlidevMarkdown) {
114133
const fileContent = stringify(markdown)
115-
await fs.writeFile(markdown.filepath, fileContent, 'utf-8')
134+
fs.writeFileSync(markdown.filepath, fileContent, 'utf-8')
116135
return fileContent
117136
}

packages/types/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export interface SlidevMarkdown {
9797
* All slides in this markdown file
9898
*/
9999
slides: SourceSlideInfo[]
100+
errors?: { row: number, message: string }[]
100101
}
101102

102103
export interface SlidevData {

packages/vscode/src/views/annotations.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { clamp } from '@antfu/utils'
1+
import { clamp, ensurePrefix } from '@antfu/utils'
22
import type { SourceSlideInfo } from '@slidev/types'
33
import { computed, watch } from '@vue/runtime-core'
44
import type { DecorationOptions } from 'vscode'
@@ -29,6 +29,9 @@ const frontmatterContentDecoration = window.createTextEditorDecorationType({
2929
backgroundColor: '#8881',
3030
})
3131
const frontmatterEndDecoration = window.createTextEditorDecorationType(dividerCommonOptions)
32+
const errorDecoration = window.createTextEditorDecorationType({
33+
isWholeLine: true,
34+
})
3235

3336
function mergeSlideNumbers(slides: { index: number }[]): string {
3437
const indexes = slides.map(s => s.index + 1)
@@ -56,6 +59,7 @@ export const useAnnotations = createSingletonComposable(() => {
5659
editor.setDecorations(firstLineDecoration, [])
5760
editor.setDecorations(dividerDecoration, [])
5861
editor.setDecorations(frontmatterContentDecoration, [])
62+
editor.setDecorations(errorDecoration, [])
5963
return
6064
}
6165

@@ -83,7 +87,6 @@ export const useAnnotations = createSingletonComposable(() => {
8387
const dividerRanges: DecorationOptions[] = []
8488
const frontmatterContentRanges: DecorationOptions[] = []
8589
const frontmatterEndRanges: DecorationOptions[] = []
86-
8790
for (const slide of md.slides) {
8891
const lineNo = slide.frontmatterStyle === 'frontmatter' ? slide.start : slide.start - 1
8992
const line = doc.lineAt(clamp(lineNo, 0, doc.lineCount))
@@ -121,11 +124,25 @@ export const useAnnotations = createSingletonComposable(() => {
121124
}
122125
}
123126
}
124-
125127
editor.setDecorations(firstLineDecoration, firstLineRanges)
126128
editor.setDecorations(dividerDecoration, dividerRanges)
127129
editor.setDecorations(frontmatterContentDecoration, frontmatterContentRanges)
128130
editor.setDecorations(frontmatterEndDecoration, frontmatterEndRanges)
131+
132+
const errors: DecorationOptions[] = []
133+
for (const error of md.errors ?? []) {
134+
errors.push({
135+
range: new Range(error.row, 0, error.row, 0),
136+
renderOptions: {
137+
after: {
138+
contentText: ensurePrefix(error.message, ' '),
139+
color: new ThemeColor('editorError.foreground'),
140+
backgroundColor: new ThemeColor('editorError.background'),
141+
},
142+
},
143+
})
144+
}
145+
editor.setDecorations(errorDecoration, errors)
129146
},
130147
{ immediate: true },
131148
)

packages/vscode/src/views/slidesTree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export const useSlidesTree = createSingletonComposable(() => {
117117
const sourcesInEntry = elements.map(element => element.slide).filter(s => s.filepath === data.entry.filepath)
118118
dataTransfer.set(slideMineType, new DataTransferItem(sourcesInEntry))
119119
},
120-
handleDrop(target, dataTransfer) {
120+
async handleDrop(target, dataTransfer) {
121121
const slides: SourceSlideInfo[] = dataTransfer.get(slideMineType)?.value
122122
if (!slides || !target)
123123
return
@@ -133,7 +133,7 @@ export const useSlidesTree = createSingletonComposable(() => {
133133
...slides,
134134
...oldSlides.slice(targetIndex + 1),
135135
].filter(Boolean) as SourceSlideInfo[]
136-
slidevSave(data.entry)
136+
await slidevSave(data.entry)
137137
},
138138
},
139139
showCollapseAll: true,

0 commit comments

Comments
 (0)