feat(cli): Add docs error link to errors in the CLI (#8251)

This commit is contained in:
Erika 2023-08-28 15:15:14 +02:00 committed by GitHub
parent ed39fbf168
commit 46c4c0e053
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 15 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Adds a link to the error reference in the CLI when an error occurs

View file

@ -9,6 +9,7 @@ import { normalizePath } from 'vite';
import type { SSRError } from '../../../@types/astro.js'; import type { SSRError } from '../../../@types/astro.js';
import { removeLeadingForwardSlashWindows } from '../../path.js'; import { removeLeadingForwardSlashWindows } from '../../path.js';
import { AggregateError, type ErrorWithMetadata } from '../errors.js'; import { AggregateError, type ErrorWithMetadata } from '../errors.js';
import { AstroErrorData } from '../index.js';
import { codeFrame } from '../printer.js'; import { codeFrame } from '../printer.js';
import { normalizeLF } from '../utils.js'; import { normalizeLF } from '../utils.js';
@ -206,13 +207,29 @@ function cleanErrorStack(stack: string) {
.join('\n'); .join('\n');
} }
export function getDocsForError(err: ErrorWithMetadata): string | undefined {
if (err.name in AstroErrorData) {
return `https://docs.astro.build/en/reference/errors/${getKebabErrorName(err.name)}/`;
}
return undefined;
/**
* The docs has kebab-case urls for errors, so we need to convert the error name
* @param errorName
*/
function getKebabErrorName(errorName: string): string {
return errorName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
}
/** /**
* Render a subset of Markdown to HTML or a CLI output * Render a subset of Markdown to HTML or a CLI output
*/ */
export function renderErrorMarkdown(markdown: string, target: 'html' | 'cli') { export function renderErrorMarkdown(markdown: string, target: 'html' | 'cli') {
const linkRegex = /\[(.+)\]\((.+)\)/gm; const linkRegex = /\[(.+)\]\((.+)\)/gm;
const boldRegex = /\*\*(.+)\*\*/gm; const boldRegex = /\*\*(.+)\*\*/gm;
const urlRegex = / (\b(https?|ftp):\/\/[-A-Z0-9+&@#\\/%?=~_|!:,.;]*[-A-Z0-9+&@#\\/%=~_|]) /gim; const urlRegex = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\\/%?=~_|!:,.;]*[-A-Z0-9+&@#\\/%=~_|])/gim;
const codeRegex = /`([^`]+)`/gim; const codeRegex = /`([^`]+)`/gim;
if (target === 'html') { if (target === 'html') {

View file

@ -7,7 +7,7 @@ import { FailedToLoadModuleSSR, InvalidGlob, MdxIntegrationMissingError } from '
import { AstroError, type ErrorWithMetadata } from '../errors.js'; import { AstroError, type ErrorWithMetadata } from '../errors.js';
import { createSafeError } from '../utils.js'; import { createSafeError } from '../utils.js';
import type { SSRLoadedRenderer } from './../../../@types/astro.js'; import type { SSRLoadedRenderer } from './../../../@types/astro.js';
import { renderErrorMarkdown } from './utils.js'; import { getDocsForError, renderErrorMarkdown } from './utils.js';
export function enhanceViteSSRError({ export function enhanceViteSSRError({
error, error,
@ -137,10 +137,7 @@ export async function getViteErrorPayload(err: ErrorWithMetadata): Promise<Astro
const message = renderErrorMarkdown(err.message.trim(), 'html'); const message = renderErrorMarkdown(err.message.trim(), 'html');
const hint = err.hint ? renderErrorMarkdown(err.hint.trim(), 'html') : undefined; const hint = err.hint ? renderErrorMarkdown(err.hint.trim(), 'html') : undefined;
const hasDocs = !!err.name; const docslink = getDocsForError(err);
const docslink = hasDocs
? `https://docs.astro.build/en/reference/errors/${getKebabErrorName(err.name)}/`
: undefined;
const highlighter = await getHighlighter({ theme: 'css-variables' }); const highlighter = await getHighlighter({ theme: 'css-variables' });
let highlighterLang = err.loc?.file?.split('.').pop(); let highlighterLang = err.loc?.file?.split('.').pop();
@ -178,12 +175,4 @@ export async function getViteErrorPayload(err: ErrorWithMetadata): Promise<Astro
cause: err.cause, cause: err.cause,
}, },
}; };
/**
* The docs has kebab-case urls for errors, so we need to convert the error name
* @param errorName
*/
function getKebabErrorName(errorName: string): string {
return errorName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
} }

View file

@ -16,7 +16,7 @@ import {
} from 'kleur/colors'; } from 'kleur/colors';
import type { ResolvedServerUrls } from 'vite'; import type { ResolvedServerUrls } from 'vite';
import type { ZodError } from 'zod'; import type { ZodError } from 'zod';
import { renderErrorMarkdown } from './errors/dev/utils.js'; import { getDocsForError, renderErrorMarkdown } from './errors/dev/utils.js';
import { import {
AstroError, AstroError,
AstroUserError, AstroUserError,
@ -216,6 +216,11 @@ export function formatErrorMessage(err: ErrorWithMetadata, args: string[] = []):
yellow(padMultilineString(isOurError ? renderErrorMarkdown(err.hint, 'cli') : err.hint, 4)) yellow(padMultilineString(isOurError ? renderErrorMarkdown(err.hint, 'cli') : err.hint, 4))
); );
} }
const docsLink = getDocsForError(err);
if (docsLink) {
args.push(` ${bold('Error reference:')}`);
args.push(` ${underline(docsLink)}`);
}
if (err.id || err.loc?.file) { if (err.id || err.loc?.file) {
args.push(` ${bold('File:')}`); args.push(` ${bold('File:')}`);
args.push( args.push(