Skip to content

Commit

Permalink
Improves YAML error handling consistency (#9882)
Browse files Browse the repository at this point in the history
* fix: improves yaml error handling consistency

* chore: add changeset
  • Loading branch information
natemoo-re committed Jan 30, 2024
1 parent 70ae19d commit 13c3b71
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .changeset/twelve-humans-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Improves handling of YAML parsing errors
36 changes: 25 additions & 11 deletions packages/astro/src/content/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}
}

Expand Down
7 changes: 4 additions & 3 deletions packages/astro/src/vite-plugin-markdown/content-entry-type.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
33 changes: 3 additions & 30 deletions packages/astro/src/vite-plugin-markdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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))
);
Expand All @@ -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);

Expand Down

0 comments on commit 13c3b71

Please sign in to comment.