UNPKG

@wordpress/editor

Version:
157 lines (155 loc) 4.97 kB
// packages/editor/src/components/error-boundary/index.js import { Component } from "@wordpress/element"; import { __ } from "@wordpress/i18n"; import { Card, CollapsibleCard, Notice, Stack, Text } from "@wordpress/ui"; import { select } from "@wordpress/data"; import { useCopyToClipboard } from "@wordpress/compose"; import { doAction } from "@wordpress/hooks"; import { store as editorStore } from "../../store/index.mjs"; import { jsx, jsxs } from "react/jsx-runtime"; function getContent() { try { return select(editorStore).getEditedPostContent(); } catch { } } function getErrorName(error) { return error instanceof Error && error.name || "Error"; } function getErrorMessage(error) { if (typeof error === "string" && error) { return error; } if (typeof error?.message === "string" && error.message) { return error.message; } return "An unknown error occurred."; } function getErrorSections(error, componentStack) { const sections = [ { label: getErrorName(error), content: getErrorMessage(error) } ]; if (error?.stack) { sections.push({ label: "Stack", content: error.stack.trim(), preformatted: true }); } if (componentStack) { sections.push({ label: "Component stack", content: componentStack.trim(), preformatted: true }); } sections.push({ label: "Environment", content: `User agent: ${window.navigator.userAgent}`, preformatted: true }); return sections; } function getErrorReport(error, componentStack) { const sections = getErrorSections(error, componentStack).map( ({ label, content, preformatted }) => `**${label}** ${preformatted ? `\`\`\` ${content} \`\`\`` : content}` ); return ["### Error report", ...sections].join("\n\n"); } function CopyButton({ text, children, variant = "outline" }) { const ref = useCopyToClipboard(text); return /* @__PURE__ */ jsx(Notice.ActionButton, { variant, ref, children }); } function ErrorReport({ error, componentStack }) { return /* @__PURE__ */ jsx( Stack, { className: "editor-error-boundary__report", direction: "column", gap: "md", children: getErrorSections(error, componentStack).map( ({ label, content }) => /* @__PURE__ */ jsxs(Stack, { direction: "column", gap: "xs", children: [ /* @__PURE__ */ jsx(Text, { variant: "heading-md", children: label }), /* @__PURE__ */ jsx("pre", { className: "editor-error-boundary__report-section", children: content }) ] }, label) ) } ); } function ErrorDetails({ error, componentStack }) { return /* @__PURE__ */ jsxs(CollapsibleCard.Root, { className: "editor-error-boundary__details", children: [ /* @__PURE__ */ jsx(CollapsibleCard.Header, { children: /* @__PURE__ */ jsx(Card.Title, { children: __("Error details") }) }), /* @__PURE__ */ jsx(CollapsibleCard.Content, { children: /* @__PURE__ */ jsx( ErrorReport, { error, componentStack } ) }) ] }); } var ErrorBoundary = class extends Component { constructor() { super(...arguments); this.state = { error: null, componentStack: null }; } componentDidCatch(error, errorInfo) { this.setState({ componentStack: errorInfo?.componentStack }); doAction("editor.ErrorBoundary.errorLogged", error, errorInfo); } static getDerivedStateFromError(error) { return { error }; } render() { const { error, componentStack } = this.state; const { canCopyContent = false } = this.props; if (!error) { return this.props.children; } return /* @__PURE__ */ jsxs( Stack, { className: "editor-error-boundary", direction: "column", gap: "lg", children: [ /* @__PURE__ */ jsxs(Notice.Root, { intent: "error", children: [ /* @__PURE__ */ jsx(Notice.Title, { children: __("The editor has crashed") }), /* @__PURE__ */ jsx(Notice.Description, { children: __( "An unknown error occurred. Reload your browser to try again, or copy the error to report the problem or search." ) }), /* @__PURE__ */ jsxs(Notice.Actions, { children: [ canCopyContent && /* @__PURE__ */ jsx(CopyButton, { text: getContent, children: __("Copy contents") }), /* @__PURE__ */ jsx( CopyButton, { variant: "solid", text: () => getErrorReport(error, componentStack), children: __("Copy error") } ) ] }) ] }), globalThis.SCRIPT_DEBUG ? /* @__PURE__ */ jsx( ErrorDetails, { error, componentStack } ) : null ] } ); } }; var error_boundary_default = ErrorBoundary; export { error_boundary_default as default }; //# sourceMappingURL=index.mjs.map