feat(cli): Add docs error link to errors in the CLI (#8251)
This commit is contained in:
parent
ed39fbf168
commit
46c4c0e053
4 changed files with 31 additions and 15 deletions
5
.changeset/chatty-ways-hunt.md
Normal file
5
.changeset/chatty-ways-hunt.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Adds a link to the error reference in the CLI when an error occurs
|
|
@ -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') {
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue