0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-31 23:31:30 -05:00

Improves YAML error handling consistency (#9882)

* fix: improves yaml error handling consistency

* chore: add changeset
This commit is contained in:
Nate Moore 2024-01-30 17:16:31 -06:00 committed by GitHub
parent 70ae19d500
commit 13c3b712c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 37 additions and 44 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Improves handling of YAML parsing errors

View file

@ -14,7 +14,8 @@ import type {
} from '../@types/astro.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { formatYAMLException, isYAMLException } from '../core/errors/utils.js';
import { MarkdownError } from '../core/errors/index.js';
import { isYAMLException } from '../core/errors/utils.js';
import { CONTENT_FLAGS, CONTENT_TYPES_FILE } from './consts.js';
import { errorMap } from './error-map.js';
import { createImage } from './runtime-assets.js';
@ -287,18 +288,31 @@ function getYAMLErrorLine(rawData: string | undefined, objectKey: string) {
return numNewlinesBeforeKey;
}
export function parseFrontmatter(fileContents: string) {
export function safeParseFrontmatter(source: string, id?: string) {
try {
// `matter` is empty string on cache results
// clear cache to prevent this
(matter as any).clearCache();
return matter(fileContents);
} catch (e) {
if (isYAMLException(e)) {
throw formatYAMLException(e);
} else {
throw e;
return matter(source);
} catch (err: any) {
const markdownError = new MarkdownError({
name: 'MarkdownError',
message: err.message,
stack: err.stack,
location: id ? {
file: id,
} : undefined,
});
if (isYAMLException(err)) {
markdownError.setLocation({
file: id,
line: err.mark.line,
column: err.mark.column,
});
markdownError.setMessage(err.reason);
}
throw markdownError;
}
}

View file

@ -1,10 +1,11 @@
import { fileURLToPath } from 'node:url';
import type { ContentEntryType } from '../@types/astro.js';
import { parseFrontmatter } from '../content/utils.js';
import { safeParseFrontmatter } from '../content/utils.js';
export const markdownContentEntryType: ContentEntryType = {
extensions: ['.md'],
async getEntryInfo({ contents }: { contents: string }) {
const parsed = parseFrontmatter(contents);
async getEntryInfo({ contents, fileUrl }: { contents: string, fileUrl: URL }) {
const parsed = safeParseFrontmatter(contents, fileURLToPath(fileUrl));
return {
data: parsed.data,
body: parsed.content,

View file

@ -3,14 +3,14 @@ import {
InvalidAstroDataError,
type MarkdownProcessor,
} from '@astrojs/markdown-remark';
import matter from 'gray-matter';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import type { Plugin } from 'vite';
import { normalizePath } from 'vite';
import type { AstroSettings } from '../@types/astro.js';
import { AstroError, AstroErrorData, MarkdownError } from '../core/errors/index.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { safeParseFrontmatter } from '../content/utils.js';
import type { Logger } from '../core/logger/core.js';
import { isMarkdownFile } from '../core/util.js';
import { shorthash } from '../runtime/server/shorthash.js';
@ -23,33 +23,6 @@ interface AstroPluginOptions {
logger: Logger;
}
function safeMatter(source: string, id: string) {
try {
return matter(source);
} catch (err: any) {
const markdownError = new MarkdownError({
name: 'MarkdownError',
message: err.message,
stack: err.stack,
location: {
file: id,
},
});
if (err.name === 'YAMLException') {
markdownError.setLocation({
file: id,
line: err.mark.line,
column: err.mark.column,
});
markdownError.setMessage(err.reason);
}
throw markdownError;
}
}
const astroServerRuntimeModulePath = normalizePath(
fileURLToPath(new URL('../runtime/server/index.js', import.meta.url))
);
@ -75,7 +48,7 @@ export default function markdown({ settings, logger }: AstroPluginOptions): Plug
if (isMarkdownFile(id)) {
const { fileId, fileUrl } = getFileInfo(id, settings.config);
const rawFile = await fs.promises.readFile(fileId, 'utf-8');
const raw = safeMatter(rawFile, id);
const raw = safeParseFrontmatter(rawFile, id);
const fileURL = pathToFileURL(fileId);