diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts
index 0f172b930437..a905e91ff892 100644
--- a/packages/docusaurus-module-type-aliases/src/index.d.ts
+++ b/packages/docusaurus-module-type-aliases/src/index.d.ts
@@ -74,6 +74,14 @@ declare module '@generated/codeTranslations' {
declare module '@theme-original/*';
+declare module '@theme/Error' {
+ export interface Props {
+ readonly error: Error;
+ readonly tryAgain: () => void;
+ }
+ export default function Error(props: Props): JSX.Element;
+}
+
declare module '@theme/Layout' {
import type {ReactNode} from 'react';
@@ -108,6 +116,17 @@ declare module '@docusaurus/constants' {
export const DEFAULT_PLUGIN_ID: 'default';
}
+declare module '@docusaurus/ErrorBoundary' {
+ import type {ReactNode} from 'react';
+ import ErrorComponent from '@theme/Error';
+
+ export interface Props {
+ readonly fallback?: typeof ErrorComponent;
+ readonly children: ReactNode;
+ }
+ export default function ErrorBoundary(props: Props): JSX.Element;
+}
+
declare module '@docusaurus/Head' {
import type {HelmetProps} from 'react-helmet';
import type {ReactNode} from 'react';
diff --git a/packages/docusaurus-theme-classic/codeTranslations/ar.json b/packages/docusaurus-theme-classic/codeTranslations/ar.json
index 32030b7c9e0c..faa8166942c0 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/ar.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/ar.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "تم النسخ",
"theme.CodeBlock.copy": "نسخ",
"theme.CodeBlock.copyButtonAriaLabel": "نسخ الرمز إلى الحافظة",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "لم نتمكن من العثور على ما كنت تبحث عنه.",
"theme.NotFound.p2": "يرجى الاتصال بمالك الموقع الذي ربطك بعنوان URL الأصلي وإخباره بأن الارتباط الخاص به معطل.",
"theme.NotFound.title": "الصفحة غير موجودة",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/base.json b/packages/docusaurus-theme-classic/codeTranslations/base.json
index 9583f1c87fe3..6a02a7d8237d 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/base.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/base.json
@@ -9,6 +9,10 @@
"theme.CodeBlock.copy___DESCRIPTION": "The copy button label on code blocks",
"theme.CodeBlock.copyButtonAriaLabel": "Copy code to clipboard",
"theme.CodeBlock.copyButtonAriaLabel___DESCRIPTION": "The ARIA label for copy code blocks button",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.title___DESCRIPTION": "The title of the fallback page when the page crashed",
+ "theme.ErrorPageContent.tryAgain": "Try again",
+ "theme.ErrorPageContent.tryAgain___DESCRIPTION": "The label of the button to try again when the page crashed",
"theme.NotFound.p1": "We could not find what you were looking for.",
"theme.NotFound.p1___DESCRIPTION": "The first paragraph of the 404 page",
"theme.NotFound.p2": "Please contact the owner of the site that linked you to the original URL and let them know their link is broken.",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/bn.json b/packages/docusaurus-theme-classic/codeTranslations/bn.json
index e09538899978..b45e9b4f9bde 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/bn.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/bn.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "কপিড",
"theme.CodeBlock.copy": "কপি",
"theme.CodeBlock.copyButtonAriaLabel": "ক্লিপবোর্ডে কোড কপি করুন",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "আপনি যা খুঁজছিলেন তা আমরা খুঁজে পাইনি।",
"theme.NotFound.p2": "দয়া করে সাইটের মালিকের সাথে যোগাযোগ করুন যা আপনাকে মূল URL এর সাথে যুক্ত করেছে এবং তাদের লিঙ্কটি ভাঙ্গা রয়েছে তা তাদের জানান।",
"theme.NotFound.title": "পেজটি খুঁজে পাওয়া যায়নি",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/cs.json b/packages/docusaurus-theme-classic/codeTranslations/cs.json
index 5778e9acaa28..41c8123537ec 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/cs.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/cs.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Zkopírováno",
"theme.CodeBlock.copy": "Zkopírovat",
"theme.CodeBlock.copyButtonAriaLabel": "Zkopírovat kód do schránky",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Nepodařilo se nám najít co jste hledal(a).",
"theme.NotFound.p2": "Kontaktujte prosím vlastníka webu, který vás odkázal na původní URL a upozorněte ho, že jejich odkaz nefunguje.",
"theme.NotFound.title": "Stránka nenalezena",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/da.json b/packages/docusaurus-theme-classic/codeTranslations/da.json
index 305c871b8006..cb46ce376ef8 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/da.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/da.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Kopieret",
"theme.CodeBlock.copy": "Kopier",
"theme.CodeBlock.copyButtonAriaLabel": "Kopier kode til udklipsholder",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Vi kunne ikke finde det, du søgte.",
"theme.NotFound.p2": "Venligst kontakt ejeren til webstedet, som førte dig frem denne URL, og informer dem om at linket ikke virker.",
"theme.NotFound.title": "Siden blev ikke fundet",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/de.json b/packages/docusaurus-theme-classic/codeTranslations/de.json
index 56c63138c65f..a8e991b056cc 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/de.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/de.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Kopiert",
"theme.CodeBlock.copy": "Kopieren",
"theme.CodeBlock.copyButtonAriaLabel": "In die Zwischenablage kopieren",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Wir konnten nicht finden, wonach Sie gesucht haben.",
"theme.NotFound.p2": "Bitte kontaktieren Sie den Besitzer der Seite, die Sie mit der ursprünglichen URL verlinkt hat, und teilen Sie ihm mit, dass der Link nicht mehr funktioniert.",
"theme.NotFound.title": "Seite nicht gefunden",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/es.json b/packages/docusaurus-theme-classic/codeTranslations/es.json
index 63018fff842e..700ebed3f16a 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/es.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/es.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Copiado",
"theme.CodeBlock.copy": "Copiar",
"theme.CodeBlock.copyButtonAriaLabel": "Copiar código al portapapeles",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "No pudimos encontrar lo que buscaba.",
"theme.NotFound.p2": "Comuníquese con el dueño del sitio que lo vinculó a la URL original y hágale saber que su vínculo está roto.",
"theme.NotFound.title": "Página No Encontrada",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/fa.json b/packages/docusaurus-theme-classic/codeTranslations/fa.json
index 093dca5287fc..18c5923e11ed 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/fa.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/fa.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "کپی شد",
"theme.CodeBlock.copy": "کپی",
"theme.CodeBlock.copyButtonAriaLabel": "کپی به کلیپ بورد",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "صفحه ای که دنبال آن بودید پیدا نشد.",
"theme.NotFound.p2": "لطفا با صاحب وبسایت تماس بگیرید و ایشان را از مشکل پیش آمده مطلع کنید.",
"theme.NotFound.title": "صفحه ای که دنبال آن بودید پیدا نشد.",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/fil.json b/packages/docusaurus-theme-classic/codeTranslations/fil.json
index b533a0438617..8cff6b70206a 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/fil.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/fil.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Kinopya",
"theme.CodeBlock.copy": "Kopyahin",
"theme.CodeBlock.copyButtonAriaLabel": "Kopyahin ang code sa clipboard",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Hindi namin mahanap ang iyong hinananap.",
"theme.NotFound.p2": "Mangyaring makipag-ugnayan sa may-ari ng site na nag-link sa iyo sa orihinal na URL at sabihin sa kanila na ang kanilang link ay putol.",
"theme.NotFound.title": "Hindi Nahanap ang Pahina",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/fr.json b/packages/docusaurus-theme-classic/codeTranslations/fr.json
index 811c9c429c13..ad335b1ffd05 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/fr.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/fr.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Copié",
"theme.CodeBlock.copy": "Copier",
"theme.CodeBlock.copyButtonAriaLabel": "Copier le code",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Nous n'avons pas trouvé ce que vous recherchez.",
"theme.NotFound.p2": "Veuillez contacter le propriétaire du site qui vous a lié à l'URL d'origine et leur faire savoir que leur lien est cassé.",
"theme.NotFound.title": "Page introuvable",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/he.json b/packages/docusaurus-theme-classic/codeTranslations/he.json
index bc11e01546a5..f1c6e2e52bea 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/he.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/he.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "הועתק",
"theme.CodeBlock.copy": "העתק",
"theme.CodeBlock.copyButtonAriaLabel": "העתק קוד ללוח העריכה",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "אנחנו לא מוצאים את מה שאתה מנסה לחפש.",
"theme.NotFound.p2": "הקישור אינו תקין, אנא פנה למנהל האתר ממנו קיבלת קישור זה.",
"theme.NotFound.title": "דף לא נמצא",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/hi.json b/packages/docusaurus-theme-classic/codeTranslations/hi.json
index 12d9fa649335..1c7792160dab 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/hi.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/hi.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "कॉपीड",
"theme.CodeBlock.copy": "कॉपी",
"theme.CodeBlock.copyButtonAriaLabel": "क्लिपबोर्ड पर कोड कॉपी करें",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "हमें वह नहीं मिला, जिसकी आपको तलाश थी।",
"theme.NotFound.p2": "कृपया उस साइट के मालिक से संपर्क करें जिसने आपको मूल URL से जोड़ा है और उन्हें बताएं कि उनका लिंक टूट गया है।",
"theme.NotFound.title": "पेज नहीं मिला",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/ja.json b/packages/docusaurus-theme-classic/codeTranslations/ja.json
index 7857fa7db283..fb8af4b70381 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/ja.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/ja.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "コピーしました",
"theme.CodeBlock.copy": "コピー",
"theme.CodeBlock.copyButtonAriaLabel": "クリップボードにコードをコピー",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "お探しのページが見つかりませんでした。",
"theme.NotFound.p2": "このページにリンクしているサイトの所有者に連絡をしてリンクが壊れていることを伝えてください。",
"theme.NotFound.title": "ページが見つかりません",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/ko.json b/packages/docusaurus-theme-classic/codeTranslations/ko.json
index 74e5c8fed624..bbcd0272fcb7 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/ko.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/ko.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "복사했습니다",
"theme.CodeBlock.copy": "복사",
"theme.CodeBlock.copyButtonAriaLabel": "클립보드에 코드 복사",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "원하는 페이지를 찾을 수 없습니다.",
"theme.NotFound.p2": "사이트 관리자에게 링크가 깨진 것을 알려주세요.",
"theme.NotFound.title": "페이지를 찾을 수 없습니다.",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/pl.json b/packages/docusaurus-theme-classic/codeTranslations/pl.json
index 31cf68e1096b..c30247a3ac30 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/pl.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/pl.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Skopiowano!",
"theme.CodeBlock.copy": "Kopiuj",
"theme.CodeBlock.copyButtonAriaLabel": "Kopiuj do schowka",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Nie mogliśmy znaleźć strony której szukasz.",
"theme.NotFound.p2": "Proszę skontaktuj się z właścielem strony, z której link doprowadził Cię tutaj i poinformuj ich, że odnośnik jest nieprawidłowy.",
"theme.NotFound.title": "Strona nie została znaleziona",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/pt-BR.json b/packages/docusaurus-theme-classic/codeTranslations/pt-BR.json
index 576ef39c9b7d..1bbe32202428 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/pt-BR.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/pt-BR.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Copiado",
"theme.CodeBlock.copy": "Copiar",
"theme.CodeBlock.copyButtonAriaLabel": "Copiar código para a área de transferência",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Não foi possível encontrar o que você está procurando.",
"theme.NotFound.p2": "Entre em contato com o proprietário do site que lhe trouxe para cá e lhe informe que o link está quebrado.",
"theme.NotFound.title": "Página não encontrada",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/pt-PT.json b/packages/docusaurus-theme-classic/codeTranslations/pt-PT.json
index 9950e8db02de..3b5b905ae2e2 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/pt-PT.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/pt-PT.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Copiado",
"theme.CodeBlock.copy": "Copiar",
"theme.CodeBlock.copyButtonAriaLabel": "Copiar código para a área de transferência",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Não foi possível encontrar o que procura.",
"theme.NotFound.p2": "Por favor, contacte o proprietário do site que o trouxe aqui e informe-lhe que o link está partido.",
"theme.NotFound.title": "Página não encontrada",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/ru.json b/packages/docusaurus-theme-classic/codeTranslations/ru.json
index 7c6a32d604d9..b71a39a6bbf6 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/ru.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/ru.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Скопировано",
"theme.CodeBlock.copy": "Скопировать",
"theme.CodeBlock.copyButtonAriaLabel": "Скопировать в буфер обмена",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "К сожалению, мы не смогли найти запрашиваемую вами страницу.",
"theme.NotFound.p2": "Пожалуйста, обратитесь к владельцу сайта, с которого вы перешли на эту ссылку, чтобы сообщить ему, что ссылка не работает.",
"theme.NotFound.title": "Страница не найдена",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/sr.json b/packages/docusaurus-theme-classic/codeTranslations/sr.json
index 1b7befb76abf..87a5f712e055 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/sr.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/sr.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Копирано",
"theme.CodeBlock.copy": "Копирај",
"theme.CodeBlock.copyButtonAriaLabel": "Копирај код у меморију",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Тражени резултат не постоји.",
"theme.NotFound.p2": "Молимо вас да контактирате власника сајта који вас је упутио овде и обавестите га да је њихова веза нетачна.",
"theme.NotFound.title": "Страница није пронађена",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/tr.json b/packages/docusaurus-theme-classic/codeTranslations/tr.json
index e256de49ef15..f74a793b0d05 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/tr.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/tr.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Kopyalandı",
"theme.CodeBlock.copy": "Kopyala",
"theme.CodeBlock.copyButtonAriaLabel": "Kodu panoya kopyala",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Aradığınız şeyi bulamadık.",
"theme.NotFound.p2": "Lütfen sizi orijinal URL'ye yönlendiren sitenin sahibiyle iletişime geçin ve bağlantısının bozuk olduğunu bildirin.",
"theme.NotFound.title": "Sayfa Bulunamadı",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/vi.json b/packages/docusaurus-theme-classic/codeTranslations/vi.json
index ff52d99012c0..e0b756d14d9a 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/vi.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/vi.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "Đã sao chép",
"theme.CodeBlock.copy": "Sao chép",
"theme.CodeBlock.copyButtonAriaLabel": "Sao chép code vào bộ nhớ tạm",
+ "theme.ErrorPageContent.title": "This page crashed.",
+ "theme.ErrorPageContent.tryAgain": "Try again",
"theme.NotFound.p1": "Chúng tôi không thể tìm thấy những gì bạn đang tìm kiếm.",
"theme.NotFound.p2": "Vui lòng liên hệ với trang web đã dẫn bạn tới đây và thông báo cho họ biết rằng đường dẫn này bị hỏng.",
"theme.NotFound.title": "Không tìm thấy trang",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/zh-Hans.json b/packages/docusaurus-theme-classic/codeTranslations/zh-Hans.json
index 98d437177e75..cf0d97a23a40 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/zh-Hans.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/zh-Hans.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "复制成功",
"theme.CodeBlock.copy": "复制",
"theme.CodeBlock.copyButtonAriaLabel": "复制代码到剪贴板",
+ "theme.ErrorPageContent.title": "页面已崩溃。",
+ "theme.ErrorPageContent.tryAgain": "重试",
"theme.NotFound.p1": "我们找不到您要找的页面。",
"theme.NotFound.p2": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。",
"theme.NotFound.title": "找不到页面",
diff --git a/packages/docusaurus-theme-classic/codeTranslations/zh-Hant.json b/packages/docusaurus-theme-classic/codeTranslations/zh-Hant.json
index 80bcbf4f73ea..2edfbf796ba8 100644
--- a/packages/docusaurus-theme-classic/codeTranslations/zh-Hant.json
+++ b/packages/docusaurus-theme-classic/codeTranslations/zh-Hant.json
@@ -4,6 +4,8 @@
"theme.CodeBlock.copied": "複製成功",
"theme.CodeBlock.copy": "複製",
"theme.CodeBlock.copyButtonAriaLabel": "複製代碼至剪貼簿",
+ "theme.ErrorPageContent.title": "頁面已崩潰。",
+ "theme.ErrorPageContent.tryAgain": "重試",
"theme.NotFound.p1": "我們找不到您要找的頁面。",
"theme.NotFound.p2": "請聯絡原始連結來源網站的所有者,並通知他們連結已毀損。",
"theme.NotFound.title": "找不到頁面",
diff --git a/packages/docusaurus-theme-classic/src/theme/ErrorPageContent.tsx b/packages/docusaurus-theme-classic/src/theme/ErrorPageContent.tsx
new file mode 100644
index 000000000000..9a6478126045
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/ErrorPageContent.tsx
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React from 'react';
+import Translate from '@docusaurus/Translate';
+import type {Props} from '@theme/Error';
+
+export default function ErrorPageContent({
+ error,
+ tryAgain,
+}: Props): JSX.Element {
+ return (
+
+
+
+
+
+ This page crashed.
+
+
+
{error.message}
+
+
+
+
+
+
+ );
+}
diff --git a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx
index 64a8bd79b746..1f0e9e5e6388 100644
--- a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx
@@ -7,6 +7,7 @@
import React from 'react';
import clsx from 'clsx';
+import ErrorBoundary from '@docusaurus/ErrorBoundary';
import SkipToContent from '@theme/SkipToContent';
import AnnouncementBar from '@theme/AnnouncementBar';
import Navbar from '@theme/Navbar';
@@ -16,6 +17,7 @@ import LayoutHead from '@theme/LayoutHead';
import type {Props} from '@theme/Layout';
import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation';
import {ThemeClassNames} from '@docusaurus/theme-common';
+import ErrorPageContent from '@theme/ErrorPageContent';
import './styles.css';
function Layout(props: Props): JSX.Element {
@@ -39,7 +41,7 @@ function Layout(props: Props): JSX.Element {
wrapperClassName,
pageClassName,
)}>
- {children}
+ {children}
{!noFooter && }
diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts
index b1f9dba5d5f3..ccde4567c1e0 100644
--- a/packages/docusaurus-theme-classic/src/types.d.ts
+++ b/packages/docusaurus-theme-classic/src/types.d.ts
@@ -173,6 +173,13 @@ declare module '@theme/EditThisPage' {
export default EditThisPage;
}
+declare module '@theme/ErrorPageContent' {
+ import ErrorComponent from '@theme/Error';
+
+ const ErrorPageContent: typeof ErrorComponent;
+ export default ErrorPageContent;
+}
+
declare module '@theme/Footer' {
const Footer: () => JSX.Element | null;
export default Footer;
diff --git a/packages/docusaurus/src/client/App.tsx b/packages/docusaurus/src/client/App.tsx
index abbf3aa9e6f5..4082be154efc 100644
--- a/packages/docusaurus/src/client/App.tsx
+++ b/packages/docusaurus/src/client/App.tsx
@@ -11,24 +11,28 @@ import routes from '@generated/routes';
import renderRoutes from './exports/renderRoutes';
import {BrowserContextProvider} from './exports/browserContext';
import {DocusaurusContextProvider} from './exports/docusaurusContext';
+import ErrorBoundary from '@docusaurus/ErrorBoundary';
import PendingNavigation from './PendingNavigation';
import BaseUrlIssueBanner from './baseUrlIssueBanner/BaseUrlIssueBanner';
import Root from '@theme/Root';
+import Error from '@theme/Error';
import './client-lifecycles-dispatcher';
function App(): JSX.Element {
return (
-
-
-
-
-
- {renderRoutes(routes)}
-
-
-
-
+
+
+
+
+
+
+ {renderRoutes(routes)}
+
+
+
+
+
);
}
diff --git a/packages/docusaurus/src/client/exports/ErrorBoundary.tsx b/packages/docusaurus/src/client/exports/ErrorBoundary.tsx
new file mode 100644
index 000000000000..19981e03374d
--- /dev/null
+++ b/packages/docusaurus/src/client/exports/ErrorBoundary.tsx
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, {ReactNode} from 'react';
+
+import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
+import type {Props} from '@docusaurus/ErrorBoundary';
+import DefaultFallback from '@theme/Error';
+
+interface State {
+ error: Error | null;
+}
+
+class ErrorBoundary extends React.Component {
+ constructor(props: Props) {
+ super(props);
+ this.state = {error: null};
+ }
+
+ componentDidCatch(error: Error): void {
+ // Catch errors in any components below and re-render with error message
+ if (ExecutionEnvironment.canUseDOM) {
+ this.setState({error});
+ }
+ }
+
+ render(): ReactNode {
+ const {children} = this.props;
+ const {error} = this.state;
+
+ if (error) {
+ const fallback = this.props.fallback ?? DefaultFallback;
+ return fallback({
+ error,
+ tryAgain: () => this.setState({error: null}),
+ });
+ }
+
+ return children;
+ }
+}
+
+export default ErrorBoundary;
diff --git a/packages/docusaurus/src/client/theme-fallback/Error/index.js b/packages/docusaurus/src/client/theme-fallback/Error/index.js
new file mode 100644
index 000000000000..1c6dd9a7448e
--- /dev/null
+++ b/packages/docusaurus/src/client/theme-fallback/Error/index.js
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React from 'react';
+import Layout from '@theme/Layout';
+import ErrorBoundary from '@docusaurus/ErrorBoundary';
+
+function ErrorDisplay({error, tryAgain}) {
+ return (
+
+
This page crashed.
+
{error.message}
+
+
+ );
+}
+
+function Error({error, tryAgain}) {
+ // We wrap the error in its own error boundary because the layout can actually throw too...
+ // Only the ErrorDisplay component is simple enough to be considered safe to never throw
+ return (
+ }>
+
+
+
+
+ );
+}
+
+export default Error;
diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap
index 43d5b3c9083c..1a92081d4170 100644
--- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap
+++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap
@@ -4,6 +4,7 @@ exports[`base webpack config should create webpack aliases 1`] = `
Object {
"@docusaurus/BrowserOnly": "../../../../client/exports/BrowserOnly.tsx",
"@docusaurus/ComponentCreator": "../../../../client/exports/ComponentCreator.tsx",
+ "@docusaurus/ErrorBoundary": "../../../../client/exports/ErrorBoundary.tsx",
"@docusaurus/ExecutionEnvironment": "../../../../client/exports/ExecutionEnvironment.ts",
"@docusaurus/Head": "../../../../client/exports/Head.tsx",
"@docusaurus/Interpolate": "../../../../client/exports/Interpolate.tsx",
@@ -23,6 +24,7 @@ Object {
"@generated": "../../../../../../..",
"@site": "",
"@theme-init/PluginThemeComponentOverridden": "pluginThemeFolder/PluginThemeComponentOverridden.js",
+ "@theme-original/Error": "../../../../client/theme-fallback/Error/index.js",
"@theme-original/Layout": "../../../../client/theme-fallback/Layout/index.js",
"@theme-original/Loading": "../../../../client/theme-fallback/Loading/index.js",
"@theme-original/NotFound": "../../../../client/theme-fallback/NotFound/index.js",
@@ -30,6 +32,7 @@ Object {
"@theme-original/PluginThemeComponentOverridden": "pluginThemeFolder/PluginThemeComponentOverridden.js",
"@theme-original/Root": "../../../../client/theme-fallback/Root/index.js",
"@theme-original/subfolder/PluginThemeComponent2": "pluginThemeFolder/subfolder/PluginThemeComponent2.js",
+ "@theme/Error": "../../../../client/theme-fallback/Error/index.js",
"@theme/Layout": "../../../../client/theme-fallback/Layout/index.js",
"@theme/Loading": "../../../../client/theme-fallback/Loading/index.js",
"@theme/NotFound": "../../../../client/theme-fallback/NotFound/index.js",
@@ -46,6 +49,7 @@ exports[`getDocusaurusAliases() return appropriate webpack aliases 1`] = `
Object {
"@docusaurus/BrowserOnly": "../../client/exports/BrowserOnly.tsx",
"@docusaurus/ComponentCreator": "../../client/exports/ComponentCreator.tsx",
+ "@docusaurus/ErrorBoundary": "../../client/exports/ErrorBoundary.tsx",
"@docusaurus/ExecutionEnvironment": "../../client/exports/ExecutionEnvironment.ts",
"@docusaurus/Head": "../../client/exports/Head.tsx",
"@docusaurus/Interpolate": "../../client/exports/Interpolate.tsx",
diff --git a/website/_dogfooding/_pages tests/error-boundary-tests.js b/website/_dogfooding/_pages tests/error-boundary-tests.js
new file mode 100644
index 000000000000..b4c016c0a5dd
--- /dev/null
+++ b/website/_dogfooding/_pages tests/error-boundary-tests.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import Layout from '@theme/Layout';
+
+import ErrorBoundaryTestButton from '@site/src/components/ErrorBoundaryTestButton';
+
+export default function ErrorBoundaryTests() {
+ return (
+ <>
+ Crash outside layout
+
+
+
Error boundary tests
+
+
+ Crash inside layout
+
+
+
+
+ >
+ );
+}
diff --git a/website/docs/docusaurus-core.md b/website/docs/docusaurus-core.md
index eb456c6a07cf..46c1d5ac6f9c 100644
--- a/website/docs/docusaurus-core.md
+++ b/website/docs/docusaurus-core.md
@@ -8,6 +8,55 @@ Docusaurus provides some APIs on the clients that can be helpful to you when bui
## Components {#components}
+### `` {#errorboundary}
+
+This component creates a [React error boundary](https://reactjs.org/docs/error-boundaries.html).
+
+Use it to wrap components that might throw, and display a fallback when that happens instead of crashing the whole app.
+
+```jsx
+import React from 'react';
+import ErrorBoundary from '@docusaurus/ErrorBoundary';
+
+const SafeComponent = () => (
+ (
+
+
This component crashed because of error: {error.message}.
+
+
+ )}>
+
+
+);
+```
+
+```mdx-code-block
+import ErrorBoundaryTestButton from "@site/src/components/ErrorBoundaryTestButton"
+```
+
+:::tip
+
+To see it in action, click here:
+
+:::
+
+:::info
+
+Docusaurus uses this component to catch errors within the theme's layout, and also within the entire app.
+
+:::
+
+:::note
+
+This component doesn't catch build-time errors, and only protects against client-side render errors that can happen when using stateful React components.
+
+:::
+
+#### Props {#errorboundary-props}
+
+- `fallback`: an optional callback returning a JSX element. It will receive two props: `error`, the error that was caught, and `tryAgain`, a function (`() => void`) callback to reset the error in the component and try rendering it again.
+
### `` {#head}
This reusable React component will manage all of your changes to the document head. It takes plain HTML tags and outputs plain HTML tags and is beginner-friendly. It is a wrapper around [React Helmet](https://github.com/nfl/react-helmet).
diff --git a/website/src/components/ErrorBoundaryTestButton/index.tsx b/website/src/components/ErrorBoundaryTestButton/index.tsx
new file mode 100644
index 000000000000..5c7f0edfd2c9
--- /dev/null
+++ b/website/src/components/ErrorBoundaryTestButton/index.tsx
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, {useState} from 'react';
+
+export default function ErrorBoundaryTestButton({children = 'Boom!'}) {
+ const [state, setState] = useState(false);
+ if (state) {
+ throw new Error('Boom!');
+ }
+ return ;
+}