Compare commits

...

154 Commits
v3.8.0 ... main

Author SHA1 Message Date
Sébastien Lorber 5bc5c90dc7
chore(website): upgrade to DocSearch 4.4.0 + fix little website theming issues (#11626)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-12-23 16:29:00 +01:00
dependabot[bot] ee9dfd5d0b
chore(deps): bump preactjs/compressed-size-action from 2.8.0 to 2.9.0 - pin all remaining GitHub actions (#11625)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-12-23 11:10:37 +01:00
Cesar Garcia 7f5d6122d2
fix(docs): breadcrumb APIs only return category/docs items, ignoring links (#11616)
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Canary Release / Publish Canary (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-12-22 17:04:14 +01:00
Matthew Cheung 47a98a1d6e
feat(create-docusaurus): enable creation in current directory (#11611) 2025-12-22 16:54:03 +01:00
Nader Jaber 75a529bb8f
docs: Add expose-markdown-docusaurus-plugin resource (#11623)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-12-22 10:24:50 +01:00
Salman Chishti acd96cb3f0
chore: Upgrade GitHub Actions for Node 24 compatibility (#11621) 2025-12-22 10:18:14 +01:00
Salman Chishti 0799e20b67
chore: Upgrade GitHub Actions to latest versions (#11622)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-12-17 16:45:43 +01:00
dependabot[bot] d4a66aa2ed
chore(deps): bump actions/setup-node from 6.0.0 to 6.1.0 (#11608)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-09 15:18:18 +01:00
dependabot[bot] 0f8cda2f65
chore(deps): bump actions/checkout from 6.0.0 to 6.0.1 (#11609)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-09 15:18:02 +01:00
TheCyperpunk 59bce2b21c
fix(a11y): add Space key support for navbar dropdowns (#11513)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-12-05 19:33:44 +01:00
Andrew Kazakov 21b7b7fd02
fix(eslint-plugin): specify exact type of `no-untranslated-text` rule options (#11587) 2025-12-05 19:26:58 +01:00
Sébastien Lorber 5e77169b35
fix(core): webpack aliases shouldn't be created for test files and typedefs (#11604) 2025-12-05 19:15:41 +01:00
Hugo Häggmark 616dec13b3
feat(theme-search-algolia): allow overriding transformSearchClient (#11581)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-12-05 18:44:15 +01:00
Sébastien Lorber 455358880d
fix(core): Fix openBrowser AppleScript support for Arc (#11603)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-12-05 16:41:58 +01:00
dependabot[bot] 6efe49abaf
chore(deps): bump node-forge from 1.3.1 to 1.3.3 in /examples/classic-typescript (#11601)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-04 15:16:59 +01:00
Justin Beckwith ebb0d0e3bb
chore(deps): remove unused @babel/runtime-corejs3 dependency (#11586)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-12-04 15:09:29 +01:00
dependabot[bot] eccc778249
chore(deps): bump mdast-util-to-hast from 13.2.0 to 13.2.1 (#11589)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-02 13:09:12 +01:00
Sébastien Lorber c6c0f636a8
fix(core): in `isInternalUrl()`, URI protocol scheme detection should implement the spec more strictly (#11579)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-11-27 17:33:12 +01:00
Sébastien Lorber c32ed21431
fix(blog): Fix author paginated page url: `/blog/authors/<author>/page/2` (#11577) 2025-11-27 16:39:08 +01:00
Balthasar Hofer c6a86ff717
feat(core): support custom html elements in head tags (#11571)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-11-27 11:19:53 +01:00
dependabot[bot] d379344e6a
chore(deps): bump node-forge from 1.3.1 to 1.3.2 (#11574)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-27 10:46:49 +01:00
dependabot[bot] 5c7ba4e9d6
chore(deps): bump actions/dependency-review-action from 4.8.1 to 4.8.2 (#11557)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-25 14:23:03 +01:00
dependabot[bot] a72be12acc
chore(deps): bump actions/checkout from 5.0.0 to 6.0.0 (#11569)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-25 13:46:46 +01:00
Sébastien Lorber d6cbf6f9e8
fix(theme): Fix code block text selection copy on Firefox? (#11565)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-11-21 19:19:55 +01:00
Pyry Takala f13adecec0
fix(theme-search-algolia): preserve query strings in useSearchResultUrlProcessor (#11560)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-11-21 11:43:38 +01:00
Natan Yagudayev 89633b4d33
feat(theme-search-algolia): add support for DocSearch v4.3.2 and new Suggested Questions (#11541)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-11-21 11:31:51 +01:00
Kohei Watanabe bbec801e3f
fix(mdx-loader): fix url.parse deprecation warning on Node 24+ (#11530)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-11-20 21:38:15 +01:00
Sébastien Lorber 366b4a1b26
test(blog): Add basic tests for blog routes. (#11564) 2025-11-20 16:04:06 +01:00
Sébastien Lorber 66dbc7da39 chore(docs, blog, pages): refactor/normalize plugin option id types for all content plugins (#11563)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-11-20 13:27:29 +01:00
Sébastien Lorber 37530aaafb
chore(blog): refactor blog Content, remove useless `blogListPaginated` attribute (#11562) 2025-11-20 12:52:29 +01:00
Pyry Takala 7880f26a07
fix(content-blog): filter unlisted posts from author pages (#11559) 2025-11-20 11:20:02 +01:00
Max Clayton Clowes b61745a9e2
docs: resource add plugins glossary & cookie-consentl; fix formatting… (#11555) 2025-11-20 11:18:37 +01:00
Sébastien Lorber 05acc90c01
chore(ci): Improve Netlify cache + Run `git backfill` in parallel (#11554)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-11-17 11:46:23 +01:00
Sébastien Lorber 963159b3c1
chore(ci): upgrade Netlify to Node 24 (LTS) + add `git backfill` command (#11553) 2025-11-17 09:50:11 +01:00
Sébastien Lorber acc66c14b0
feat(core): New siteConfig `future.experimental_vcs` API + `future.experimental_faster.gitEagerVcs` flag (#11512)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25.1) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-11-14 18:15:45 +01:00
dependabot[bot] a24b8ad5ed
chore(deps): bump js-yaml from 4.1.0 to 4.1.1 (#11551)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-14 17:23:54 +01:00
Sébastien Lorber 9c85f8689a
fix(core): optimize i18n integration for site builds + improve inference of locale config (#11550) 2025-11-14 13:13:05 +01:00
Luiz Carlos 6a38ccdfb0
fix(translations): complete theme translations for Algolia pt-br (#11533)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-11-06 14:37:29 +01:00
Bhoomi Sharma c81409b5a3
docs: Remove redundant "as well" in README introduction (#11525)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-10-31 18:11:11 +01:00
dependabot[bot] f8bedbd0a0
chore(deps): bump actions/upload-artifact from 4 to 5 (#11514)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-28 16:59:28 +01:00
dependabot[bot] 7651d42e11
chore(deps): bump github/codeql-action from 4.30.9 to 4.31.0 (#11515)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-28 16:58:48 +01:00
dependabot[bot] a4742594a9
chore(deps): bump github/codeql-action from 4.30.8 to 4.30.9 (#11504)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 17:41:10 +02:00
dependabot[bot] 74542245b3
chore(deps): bump actions/setup-node from 5.0.0 to 6.0.0 (#11503)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 17:41:00 +02:00
Anukool Pandey 6b3ed1ee65
fix(website): Correct the site homepage overflows (CTA buttons + new version heading) (#11500)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-10-20 13:15:59 +02:00
Sébastien Lorber 0372ecd1e9
fix(faster): fix server build SWC / browserslist node target (#11496)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (25) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-10-17 21:02:45 +02:00
Sébastien Lorber e133e8d6d2
chore(ci): add nodejs 25 to CI jobs matrix (#11495) 2025-10-17 18:08:45 +02:00
Sébastien Lorber 5e846f6496
chore: update examples for v3.9.2 (#11494) 2025-10-17 17:38:38 +02:00
Sébastien Lorber bca9ce746f
chore: release v3.9.2 (#11491) 2025-10-17 17:15:09 +02:00
Sébastien Lorber c8fc3311f1
fix(docs): add support for missing `sidebar_key` front matter attribute (#11490)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-10-17 12:34:08 +02:00
Maysara d9d29046ec
fix(translations): improve Arabic theme translations (#11484) 2025-10-17 10:11:47 +02:00
YDKK 5423a779c1
fix(cssnano-preset): disable CSS counter minification (#11487)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
2025-10-16 18:21:54 +02:00
Eleni Grosdouli 2a10b5453f
fix(docs): Fix deployment docs for v3.9.1 - Node.js version should be v20 (#11474)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-10-14 09:54:20 +02:00
dependabot[bot] ccf03d6e38
chore(deps): bump stefanzweifel/git-auto-commit-action from 6 to 7 (#11479)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-14 09:44:07 +02:00
dependabot[bot] 8b44659c50
chore(deps): bump github/codeql-action from 3.26.5 to 4.30.8 (#11480)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-14 09:32:18 +02:00
dependabot[bot] 258769d1c8
chore(deps): bump actions/dependency-review-action from 4.8.0 to 4.8.1 (#11481)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-14 09:32:02 +02:00
Sébastien Lorber 19ea360fd5
fix(theme-search-algolia): Fix Algolia AskAI validation logic (#11468)
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
Canary Release / Publish Canary (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-10-13 18:57:09 +02:00
Sébastien Lorber 43665c5f08
docs: remove Astro link in v3.9 blog post (nodejs upgrade) (#11469)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-10-10 18:42:30 +02:00
Richa Kiran 7b33dc109b
fix(theme): remove "Edit this page" button from print view (#11463) 2025-10-10 16:42:37 +02:00
Mariusz Krzaczkowski 505ff8d228
fix(theme-translation): add missing Polish (pl) theme translations (#11431)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-10-09 17:45:42 +02:00
Ethan 13ec1eaa3e
docs(website): fix typo for onBrokenMarkdownImages (#11444) 2025-10-09 17:44:15 +02:00
dependabot[bot] a7c0aab8be
chore(deps): bump actions/dependency-review-action from 4.7.3 to 4.8.0 (#11446)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-09 12:50:37 +02:00
Sébastien Lorber ac630f8279
fix(theme): Fix CSS `scroll-margin-top` when clicking footnote items, factorize code (#11466) 2025-10-09 12:34:54 +02:00
Alexander Trofimov 598af3b8e8
fix(core): allow `i18n.localeConfigs.translate` in validation (#11452)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-10-09 10:47:53 +02:00
Dan Roscigno 8f32716def
docs(website): upgrade Node.js version from 18 to 20 in GitHub/Travis workflow examples (#11443)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-09-29 17:33:43 +02:00
Sébastien Lorber f89fbae282
perf(theme-mermaid): lazy load the Mermaid library (#11438)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-09-26 23:29:22 +02:00
Sébastien Lorber b4cc50a423
fix(theme-mermaid): Fix Mermaid ELK layout dependency required bug on v3.9 (#11437)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-09-26 16:36:27 +02:00
Sébastien Lorber c3e5db1dc3
chore: release v3.9.1 (#11436) 2025-09-26 15:31:09 +02:00
Sébastien Lorber e41fa2e191
fix(core): fix Docusaurus outDir for sites using baseUrl (#11434) 2025-09-26 12:58:41 +02:00
Sébastien Lorber 016b80b55d
fix(website): Crowdin: downgrade mdx parser to v1.2 (#11432) 2025-09-26 11:38:55 +02:00
Sébastien Lorber aff609a848
chore: update examples for v3.9 (#11429)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-09-25 18:22:29 +02:00
Sébastien Lorber c24d7dc86a
chore: release v3.9 (#11419)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-09-25 17:56:37 +02:00
Sébastien Lorber 422f5d91ef
feat(theme-search-algolia): use DocSearch v4.1, optimize integration (#11421)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-09-25 16:11:12 +02:00
Sébastien Lorber 70f6312c0d
feat(blog): Add support for email social icon + resize default social icon a bit (#11425)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-09-23 15:08:02 +02:00
Sébastien Lorber 50ca86aa04
feat(theme): Add theme-tabs-container stable className (#11426) 2025-09-23 14:58:23 +02:00
Sébastien Lorber 4dc05762ee
fix(theme): fix copy of indented code blocks, replace copy-text-to-clipboard by clipboard API (#11422)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-09-23 12:52:14 +02:00
Akshat Sinha 0bc6b6e394
fix(website): showcase spelling mistake of the word docusaurus in user desc (#11417)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-09-22 11:40:44 +02:00
Dylan Tientcheu 9c689880ed
feat(search): add runtime support for DocSearch v4 (#11327)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-09-19 14:15:57 +02:00
Sébastien Lorber a9bab411ad
feat(faster): upgrade Rspack to 1.5, use lazyBarrel experiment, remove deprecated option (#11415)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-09-19 12:11:39 +02:00
Bartosz Kaszubowski 80a4518ffb
fix(theme): remove hardcoded fill from Bluesky and LinkedIn icons (#11407)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-09-12 22:19:51 +02:00
Sébastien Lorber af3d5caf86
fix(deps): upgrade webpack-dev-server to v5, fix security warning (#11410) 2025-09-12 19:51:22 +02:00
Sébastien Lorber 24d01bb839
fix(theme): fix `useColorMode()` visual glitches due to provider unmounts/remounts (#11405) 2025-09-12 19:37:30 +02:00
Sébastien Lorber 1c484e1d59
chore: drop support for Node 18, that reached End-of-Life (#11408) 2025-09-12 18:48:12 +02:00
dependabot[bot] e8f72697a5
chore(deps): bump actions/github-script from 7.0.1 to 8.0.0 (#11402)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 14:34:20 +02:00
dependabot[bot] 3b7778a57a
chore(deps): bump actions/dependency-review-action from 4.7.2 to 4.7.3 (#11401)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 14:34:12 +02:00
dependabot[bot] 7d4e430cf9
chore(deps): bump actions/setup-node from 4.4.0 to 5.0.0 (#11403)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 14:34:04 +02:00
Sébastien Lorber 3dacdf33c9
feat(mdx): resolve `@site/*` markdown links, fix resolution priority bugs (#11397)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-09-04 15:29:26 +02:00
Sébastien Lorber 72c48b5806
chore(ci): Change Lighthouse trigger from pull_request_target to pull_request (#11393)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
2025-09-01 15:21:14 +02:00
Sébastien Lorber 6021faf97f
fix(theme): render sidebar category index with unlisted children as a simple doc/link item (#11389)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-08-29 19:00:11 +02:00
Joshua Chen bfdcc73e17
meta: add a section on AI-assisted PRs in CONTRIBUTING guide (#11388)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-08-28 14:32:17 +02:00
Sébastien Lorber ece9432b3a
fix(ssg): HTML minifier should preserve `<head>` for `og:image` crawlers (#11383)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-08-25 14:22:10 +02:00
Feez2403 305910758b
feat(mermaid): support elk layout (#11357)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-08-24 20:11:21 +02:00
ya-dvorovenko c131034bc2
docs: remove stray character in plugin overview page (#11368)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-08-24 12:11:22 +02:00
dependabot[bot] 34b355b550
chore(deps): bump actions/dependency-review-action from 4.7.1 to 4.7.2 (#11373)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-24 12:06:16 +02:00
Jaime Iniesta 87d878471e
docs: adds link to latest accessibility stats and reports in Rocket Validator (#11376) 2025-08-24 12:05:52 +02:00
dependabot[bot] a4c33bfea5
chore(deps): bump actions/checkout from 4 to 5 (#11365)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-15 12:40:41 +01:00
Sébastien Lorber 27945b3b34
fix(theme): Add translate no to heading anchors and blog authors (#11360)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-08-04 13:30:35 +02:00
Maria Stellini b1391349f5
docs: clarify impact of document ID on the URL (#11339)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-07-31 13:58:37 +02:00
Sébastien Lorber 942094af3c
fix(theme): Doc sidebar links/categories with long labels should display properly (#11356)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-07-31 13:48:00 +02:00
Weston Thayer 749b45e629
fix(theme): Add `aria-label` to `IconExternalLink` with value `'(opens in new tab)'` (#11331)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-07-28 18:36:53 +02:00
Sébastien Lorber 2febb76fae
feat(core): Add `i18n.localeConfigs[locale].{url,baseUrl}` config options (#11316)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-07-28 17:04:34 +02:00
hjcho 12bcad9837
fix(theme-classic): fix collapsed sidebar category expansion when navigating to another link within that category (#11338)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: qqq614 <heeje.cho@navercorp.com>
2025-07-24 11:03:25 +02:00
Sébastien Lorber c81808459d
fix(core): Fix docusaurus start on macOS when exec throws a synchronous error (#11347)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-07-24 11:01:03 +02:00
Guo Ci e83747f323
Fix npm command typos in deployment.mdx (#11337) 2025-07-24 10:03:46 +02:00
dependabot[bot] 2655db686e
chore(deps): bump form-data from 4.0.1 to 4.0.4 (#11342)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:01:10 +02:00
dependabot[bot] 0239c18b78
chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.3 to 2.9.4 (#11341)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:01:03 +02:00
Sébastien Lorber a3324ff65e
docs: fix release notes link (#11329)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-07-15 15:11:20 +02:00
Seth Falco 2adbc0d6a0
chore: minor reduction to inline svg/js code (#11317) 2025-07-15 14:58:05 +02:00
Marcelo Junior 0306d18240
fix(theme-translations): Add missing Portuguese (pt-BR) theme translations and improve some of it. (#11315)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-07-10 09:42:11 +02:00
Sébastien Lorber 3733dfee52
test: fix site test infinite loop in Jest --watch mode + simplify test (#11312)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-07-07 16:50:01 +02:00
Sébastien Lorber 1808945c1f
feat(core): add `i18n.localeConfigs.translate` + skip translation process if `i18n/<locale>` dir doesn't exist (#11304) 2025-07-07 14:55:46 +02:00
Sébastien Lorber e0524a5c84
docs(website): fix duplicate anchor id typo (#11311)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-07-07 12:04:30 +02:00
Sergey Schetinin 4c3daab18b
fix(translations): Add missing Ukrainian translations (#11305)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-07-04 15:20:16 +02:00
Sébastien Lorber fad80c4421
test(docs): fix docs tests issues (#11307) 2025-07-04 15:14:17 +02:00
Sébastien Lorber da08536816
feat(docs): sidebar item `key` attribute - fix docs translations key conflicts (#11228)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-07-03 13:40:00 +02:00
Sébastien Lorber d9d7e855c2
feat(faster): Upgrade to Rspack 1.4 (#11294)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-06-26 17:10:41 +02:00
Sébastien Lorber b0df38d317
feat(create-docusaurus): use respectPrefersColorScheme in init template (#11293) 2025-06-26 15:36:46 +02:00
Sébastien Lorber 0f7cf285a3
chore(website): use local SVGs for footer badges (argos + netlify) (#11291)
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
CodeQL / Analyze (javascript) (push) Has been cancelled
2025-06-25 16:17:01 +02:00
Sébastien Lorber 385102df9f
chore: upgrade website to Rspack 1.4 + fix Rspack internal performance tracing (#11290) 2025-06-25 15:34:44 +02:00
Sébastien Lorber 1592094206
fix(theme): Fix footnote ref scrolling behind the navbar when footnote back reference clicked (#11289)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-06-25 11:11:38 +02:00
Sébastien Lorber e82cd48842
chore(website): split changelog per version + adjust changelog plugin implementation (#11287)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-06-24 17:05:58 +02:00
Sébastien Lorber e14caf1f78
feat(core): add `siteConfig.markdown.emoji` config option to disable `remark-emoji` (#11282) 2025-06-24 16:38:08 +02:00
Sébastien Lorber 96c38d5fdd
feat(core): Add `siteConfig.markdown.hooks`, deprecate `siteConfig.onBrokenMarkdownLinks` (#11283) 2025-06-24 15:51:33 +02:00
dependabot[bot] ef71ddf937
chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.2 to 2.9.3 (#11285)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-24 11:09:33 +02:00
Sébastien Lorber 1cbc0118b0
fix(docs): Fix empty sidebar item category `className` lost when post-processed to a doc (#11281)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-06-19 19:04:28 +02:00
stubinubin 068d4c63a9
fix(theme-common): Export FooterColumnItem type (#11280) 2025-06-19 18:31:03 +02:00
enumura a94fdbe21c
fix(dev-server): use correct dev server HTML lang attribute (#11271)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-06-17 16:11:14 +02:00
dependabot[bot] ee332e951d
chore(deps): bump stefanzweifel/git-auto-commit-action from 5 to 6 (#11272)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 09:51:18 +02:00
dependabot[bot] 3ed2ea2ecf
chore(deps): bump treosh/lighthouse-ci-action from 12.1.0 to 12.6.1 (#11273)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 09:50:37 +02:00
Sébastien Lorber 6cb955987e
fix(theme): make `useHistorySelector()` hydration-safe + use it read search/hash in theme (#11263)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-06-13 18:49:28 +02:00
Riccardo a392c33b8e
docs: fix announcement bar css selector (#11262)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-06-13 11:38:48 +02:00
Sébastien Lorber b54103be5d
fix(docs): prevent docs ids conflicts within a version (#11251)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 Windows (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-06-06 20:12:44 +02:00
Sébastien Lorber f811e2dbf4
chore: release 3.8.1 (#11249)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-06-06 17:45:58 +02:00
Sébastien Lorber 315e3f617e
chore(faster): upgrade Rspack (#11248) 2025-06-06 11:44:59 +02:00
Sébastien Lorber a36ac15947
fix(bundler): upgrade bundler CSS deps to fix potential bugs (#11243)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-06-05 18:56:09 +02:00
Sébastien Lorber 60df4936aa
fix(theme): fix unability to navigate to category's page when browsing its children items (#11242) 2025-06-05 18:13:46 +02:00
Sébastien Lorber d3ab0e63a0
fix(css-cascade-layers): fix windows css cascade layers bug (#11241) 2025-06-05 17:03:41 +02:00
Sébastien Lorber ef23f546fd
chore(ci): add yarn-v1-windows e2e job (#11231)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
2025-06-05 12:50:07 +02:00
Léo Vincent e17a26ab45
docs: deployment, fix build website commands (#11238)
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
CodeQL / Analyze (javascript) (push) Has been cancelled
2025-06-04 23:32:24 +02:00
Sébastien Lorber 18b47fdfc1
refactor(docs): extract `loadVersion()` without changing the behavior (#11230)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
* refactor, extract loadVersion() without changing behavior

* Add minimal test case for loadVersion()

* Add minimal test case for loadVersion()

* more refactor, rename index.ts to version.ts

* fix tests

* empty
2025-06-02 18:44:07 +02:00
Phil Parsons dacfc17fb4
fix(website): ensure feedback widget renders with correct theme (#11224)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
Co-authored-by: Phil Parsons <p-m-p@users.noreply.github.com>
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-06-02 12:40:25 +02:00
Sébastien Lorber ffa7525ff9
fix(bundler): fix `docusaurus start` using `concatenateModules: true` (#11222)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-05-30 21:07:11 +02:00
Sébastien Lorber 1c454a9430
fix(types): fix future flags public types (#11221) 2025-05-30 19:22:56 +02:00
Weslley Araújo dd6396dd39
fix: include Arc to supported Chromium Browsers (#11217)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-05-30 09:52:22 +02:00
Sébastien Lorber ad56077c70
perf(website): optimize website i18n build time by removing useless git log calls (#11214)
Some checks failed
Argos CI / take-screenshots (push) Has been cancelled
Build Hash Router / Build Hash Router (push) Has been cancelled
Canary Release / Publish Canary (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Continuous Releases / Continuous Releases (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (18.0) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (20) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (22) (push) Has been cancelled
E2E Tests / E2E — Yarn v1 (24) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Has been cancelled
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Has been cancelled
E2E Tests / E2E — npm (push) Has been cancelled
E2E Tests / E2E — pnpm (push) Has been cancelled
2025-05-28 16:34:23 +02:00
Sébastien Lorber 2b15b85645
chore: upgrade to Node 22 by default (#11212) 2025-05-28 15:04:14 +02:00
Sébastien Lorber 264774a550
perf: avoid duplicated `git log` calls in `loadContent()` and `postBuild()` for untracked Git files (#11211)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-05-28 14:03:10 +02:00
Sébastien Lorber 68aa3c876b
fix(core): fix `docusaurus start` error for macOS users with no Chromium-based browser (#11205)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-05-27 17:13:32 +02:00
Sébastien Lorber 76518fd206
chore: Add missing v3.8 blog post mdx-code-block (#11203) 2025-05-27 13:06:04 +02:00
Sébastien Lorber 7e87ea320c
chore: update examples for Docusaurus 3.8 (#11202) 2025-05-27 12:42:26 +02:00
Sébastien Lorber b126e643d1
chore: release Docusaurus 3.8 (#11200)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-05-27 12:21:15 +02:00
Dave Meyer 8a5a0c110e
docs: fix highlighted lines in github link to commonly used languages (#11188)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-05-27 10:41:05 +02:00
Noritaka Kobayashi 8958c11c58
chore: fix typos in comment-out (#11197) 2025-05-27 10:38:35 +02:00
Ben McCann ba18a8b8b9
chore: simplify construction of test paths (#11196)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
2025-05-26 13:29:23 +02:00
Noritaka Kobayashi 5d858f5e66
refactor: remove unnecessary undefined & use optional chain (#11192) 2025-05-26 13:07:56 +02:00
696 changed files with 72771 additions and 15705 deletions

View File

@ -21,6 +21,7 @@
], ],
"ignorePaths": [ "ignorePaths": [
"CHANGELOG.md", "CHANGELOG.md",
"CHANGELOG-v*.md",
"patches", "patches",
"packages/docusaurus-theme-translations/locales", "packages/docusaurus-theme-translations/locales",
"packages/docusaurus-plugin-ideal-image/src/theme/IdealImageLegacy", "packages/docusaurus-plugin-ideal-image/src/theme/IdealImageLegacy",

4
.eslintrc.js vendored
View File

@ -214,7 +214,7 @@ module.exports = {
], ],
'no-useless-escape': WARNING, 'no-useless-escape': WARNING,
'no-void': [ERROR, {allowAsStatement: true}], 'no-void': [ERROR, {allowAsStatement: true}],
'prefer-destructuring': WARNING, 'prefer-destructuring': OFF,
'prefer-named-capture-group': WARNING, 'prefer-named-capture-group': WARNING,
'prefer-template': WARNING, 'prefer-template': WARNING,
yoda: WARNING, yoda: WARNING,
@ -304,7 +304,7 @@ module.exports = {
'jest/prefer-expect-resolves': WARNING, 'jest/prefer-expect-resolves': WARNING,
'jest/prefer-lowercase-title': [WARNING, {ignore: ['describe']}], 'jest/prefer-lowercase-title': [WARNING, {ignore: ['describe']}],
'jest/prefer-spy-on': WARNING, 'jest/prefer-spy-on': WARNING,
'jest/prefer-to-be': WARNING, 'jest/prefer-to-be': OFF,
'jest/prefer-to-have-length': WARNING, 'jest/prefer-to-have-length': WARNING,
'jest/require-top-level-describe': ERROR, 'jest/require-top-level-describe': ERROR,
'jest/valid-title': [ 'jest/valid-title': [

View File

@ -27,10 +27,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -22,9 +22,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -32,3 +32,5 @@ jobs:
run: yarn || yarn || yarn run: yarn || yarn || yarn
- name: Build blog-only - name: Build blog-only
run: yarn workspace website build:blogOnly run: yarn workspace website build:blogOnly
env:
DOCUSAURUS_PERF_LOGGER: 'true'

View File

@ -25,9 +25,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -37,26 +37,27 @@ jobs:
- name: Build Hash Router - name: Build Hash Router
run: yarn build:website:fast run: yarn build:website:fast
env: env:
DOCUSAURUS_PERF_LOGGER: 'true'
DOCUSAURUS_ROUTER: 'hash' DOCUSAURUS_ROUTER: 'hash'
# Note: hash router + baseUrl do not play well together # Note: hash router + baseUrl do not play well together
# This would host at https://facebook.github.io/docusaurus/#/docusaurus/ # This would host at https://facebook.github.io/docusaurus/#/docusaurus/
# BASE_URL: '/docusaurus/' # hash router + # BASE_URL: '/docusaurus/' # hash router +
- name: Upload Website artifact - name: Upload Website artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: website-hash-router-archive name: website-hash-router-archive
path: website/build path: website/build
#- name: Upload Website Pages artifact #- name: Upload Website Pages artifact
# uses: actions/upload-pages-artifact@v3 # uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
# with: # with:
# path: website/build # path: website/build
# Deploy to https://facebook.github.io/docusaurus/ # Deploy to https://facebook.github.io/docusaurus/
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
if: ${{ github.event_name != 'pull_request' && github.ref_name == 'main' }} if: ${{ github.event_name != 'pull_request' && github.ref_name == 'main' }}
uses: peaceiris/actions-gh-pages@v4 uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: website/build publish_dir: website/build
@ -80,4 +81,4 @@ jobs:
# steps: # steps:
# - name: Deploy to GitHub Pages # - name: Deploy to GitHub Pages
# id: deployment # id: deployment
# uses: actions/deploy-pages@v4 # uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

View File

@ -41,14 +41,14 @@ jobs:
DOCUSAURUS_INFRA: ['SLOWER', 'FASTER'] DOCUSAURUS_INFRA: ['SLOWER', 'FASTER']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
- name: Track build size changes - name: Track build size changes
uses: preactjs/compressed-size-action@946a292cd35bd1088e0d7eb92b69d1a8d5b5d76a # v2 uses: preactjs/compressed-size-action@8518045ed95e94e971b83333085e1cb99aa18aa8 # v2.9.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
build-script: build:website:fast build-script: build:website:fast
@ -62,6 +62,7 @@ jobs:
comment-key: DOCUSAURUS_INFRA_${{ matrix.DOCUSAURUS_INFRA }} comment-key: DOCUSAURUS_INFRA_${{ matrix.DOCUSAURUS_INFRA }}
env: env:
DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }} DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }}
DOCUSAURUS_PERF_LOGGER: 'true'
# Ensures build times stay under reasonable thresholds # Ensures build times stay under reasonable thresholds
build-time: build-time:
@ -73,9 +74,9 @@ jobs:
DOCUSAURUS_INFRA: ['SLOWER', 'FASTER'] DOCUSAURUS_INFRA: ['SLOWER', 'FASTER']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -88,6 +89,7 @@ jobs:
timeout-minutes: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 3 || 2 }} timeout-minutes: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 3 || 2 }}
env: env:
DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }} DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }}
DOCUSAURUS_PERF_LOGGER: 'true'
# Ensure build with a warm cache does not increase too much # Ensure build with a warm cache does not increase too much
- name: Build (warm cache) - name: Build (warm cache)
@ -96,5 +98,6 @@ jobs:
timeout-minutes: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 1 || 2 }} timeout-minutes: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 1 || 2 }}
env: env:
DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }} DOCUSAURUS_SLOWER: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 'true' || 'false' }}
DOCUSAURUS_PERF_LOGGER: 'true'
# TODO post a GitHub comment with build with perf warnings? # TODO post a GitHub comment with build with perf warnings?

View File

@ -20,11 +20,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with: with:
fetch-depth: 0 # Needed to get the commit number with "git rev-list --count HEAD" fetch-depth: 0 # Needed to get the commit number with "git rev-list --count HEAD"
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -33,12 +33,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # 3.26.5 uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 4.31.0
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # 3.26.5 uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb # 4.31.0

View File

@ -18,10 +18,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -13,6 +13,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Dependency Review - name: Dependency Review
uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # 4.7.1 uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # 4.8.2

View File

@ -1,7 +1,7 @@
name: Lighthouse Report name: Lighthouse Report
on: on:
pull_request_target: pull_request:
branches: branches:
- main - main
- docusaurus-v** - docusaurus-v**
@ -21,10 +21,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -37,7 +37,7 @@ jobs:
- name: Audit URLs using Lighthouse - name: Audit URLs using Lighthouse
id: lighthouse_audit id: lighthouse_audit
uses: treosh/lighthouse-ci-action@2f8dda6cf4de7d73b29853c3f29e73a01e297bd8 # 12.1.0 uses: treosh/lighthouse-ci-action@fcd65974f7c4c2bf0ee9d09b84d2489183c29726 # 12.6.1
with: with:
urls: | urls: |
http://localhost:3000 http://localhost:3000
@ -53,7 +53,7 @@ jobs:
- name: Format lighthouse score - name: Format lighthouse score
id: format_lighthouse_score id: format_lighthouse_score
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # 7.0.1 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # 8.0.0
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
script: | script: |
@ -65,7 +65,7 @@ jobs:
- name: Add Lighthouse stats as comment - name: Add Lighthouse stats as comment
id: comment_to_pr id: comment_to_pr
uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # 2.9.2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # 2.9.4
with: with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
number: ${{ github.event.pull_request.number }} number: ${{ github.event.pull_request.number }}

View File

@ -19,7 +19,7 @@ jobs:
contents: write contents: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with: with:
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
@ -42,6 +42,6 @@ jobs:
- name: Print Diff - name: Print Diff
run: git diff run: git diff
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
with: with:
commit_message: 'refactor: apply lint autofix' commit_message: 'refactor: apply lint autofix'

View File

@ -20,9 +20,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -22,9 +22,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -38,12 +38,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node: ['18.0', '20', '22', '24'] node: ['20.0', '20', '22', '24', '25.1']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
cache: yarn cache: yarn
@ -72,6 +72,48 @@ jobs:
DOCUSAURUS_PERF_LOGGER: 'true' DOCUSAURUS_PERF_LOGGER: 'true'
working-directory: ../test-website working-directory: ../test-website
yarn-v1-windows:
name: E2E — Yarn v1 Windows
timeout-minutes: 30
runs-on: windows-8-core
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js LTS
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: lts/*
cache: yarn
- name: Installation
run: yarn || yarn || yarn
- name: Generate test-website project against main branch
# Not using test-release.sh => no verdaccio docker image on Windows
# run: bash ./admin/scripts/test-release.sh -s
run: yarn create-docusaurus test-website-in-workspace classic --typescript
- name: Install test-website project with Yarn v1
run: yarn || yarn || yarn
working-directory: test-website-in-workspace
- name: Start test-website project
run: yarn start --no-open
working-directory: test-website-in-workspace
env:
E2E_TEST: true
- name: Build test-website project
# We build 2 locales to ensure a localized site doesn't leak memory
# See https://github.com/facebook/docusaurus/pull/10599
run: yarn build --locale en --locale fr
env:
# Our website should build even with limited memory
# See https://github.com/facebook/docusaurus/pull/10590
NODE_OPTIONS: '--max-old-space-size=300'
DOCUSAURUS_PERF_LOGGER: 'true'
working-directory: test-website-in-workspace
- name: Upload Website artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: website-e2e-windows
path: test-website-in-workspace/build
yarn-berry: yarn-berry:
name: E2E — Yarn Berry name: E2E — Yarn Berry
timeout-minutes: 30 timeout-minutes: 30
@ -82,9 +124,9 @@ jobs:
variant: [-s, -st] variant: [-s, -st]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -151,9 +193,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -191,9 +233,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -26,9 +26,9 @@ jobs:
variant: ['js', 'ts'] variant: ['js', 'ts']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Node LTS - name: Set up Node LTS
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View File

@ -27,14 +27,14 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
matrix: matrix:
node: ['18.0', '20', '22', '24'] node: ['20.0', '20', '22', '24', '25.1']
steps: steps:
- name: Support longpaths - name: Support longpaths
run: git config --system core.longpaths true run: git config --system core.longpaths true
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
cache: yarn cache: yarn
@ -54,14 +54,20 @@ jobs:
run: yarn workspace website test:swizzle:wrap:ts run: yarn workspace website test:swizzle:wrap:ts
- name: Docusaurus Build - name: Docusaurus Build
run: yarn build:website:fast run: yarn build:website:fast
env:
DOCUSAURUS_PERF_LOGGER: 'true'
- name: TypeCheck website - name: TypeCheck website
# TODO temporary, remove TS skipLibCheck
# see https://github.com/facebook/docusaurus/pull/10486 # see https://github.com/facebook/docusaurus/pull/10486
run: yarn workspace website typecheck --project tsconfig.skipLibCheck.json run: yarn workspace website typecheck
- name: TypeCheck website - min version - v5.1 - name: TypeCheck website - min version - v5.1
run: | run: |
yarn add typescript@5.1.6 --exact -D -W --ignore-scripts yarn add typescript@5.1.6 --exact -D -W --ignore-scripts
# DocSearch@4/ai@5 doesn't support TS 5.1 (with skipLibCheck=false)
jq '.resolutions."@docsearch/react" = "^3.9.0"' package.json > package.json.tmp && mv -Force package.json.tmp package.json
yarn add @docsearch/react@^3.9.0 --exact -D -W --ignore-scripts
yarn workspace website typecheck yarn workspace website typecheck
- name: TypeCheck website - max version - Latest - name: TypeCheck website - max version - Latest
# For latest TS there are often lib check errors, so we disable it # For latest TS there are often lib check errors, so we disable it

View File

@ -27,12 +27,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node: ['18.0', '20', '22', '24'] node: ['20.0', '20', '22', '24', '25.1']
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
cache: yarn cache: yarn
@ -55,12 +55,16 @@ jobs:
run: yarn workspace website test:css-order run: yarn workspace website test:css-order
- name: TypeCheck website - name: TypeCheck website
# TODO temporary, remove TS skipLibCheck
# see https://github.com/facebook/docusaurus/pull/10486 # see https://github.com/facebook/docusaurus/pull/10486
run: yarn workspace website typecheck --project tsconfig.skipLibCheck.json run: yarn workspace website typecheck
- name: TypeCheck website - min version - v5.1 - name: TypeCheck website - min version - v5.1
run: | run: |
yarn add typescript@5.1.6 --exact -D -W --ignore-scripts yarn add typescript@5.1.6 --exact -D -W --ignore-scripts
# DocSearch@4/ai@5 doesn't support TS 5.1 (with skipLibCheck=false)
jq '.resolutions."@docsearch/react" = "^3.9.0"' package.json > package.json.tmp && mv -f package.json.tmp package.json
yarn add @docsearch/react@^3.9.0 --exact -D -W --ignore-scripts
yarn workspace website typecheck yarn workspace website typecheck
- name: TypeCheck website - max version - Latest - name: TypeCheck website - max version - Latest
# For latest TS there are often lib check errors, so we disable it # For latest TS there are often lib check errors, so we disable it

1
.gitignore vendored
View File

@ -47,6 +47,7 @@ website/i18n/**/*
.netlify .netlify
website/rspack-tracing.json website/rspack-tracing.json
website/rspack-tracing.pftrace
website/bundler-cpu-profile.json website/bundler-cpu-profile.json
website/profile.json.gz website/profile.json.gz

2
.nvmrc
View File

@ -1 +1 @@
18 22

View File

@ -1,7 +1,7 @@
dist dist
node_modules node_modules
.yarn .yarn
build **/build/**
coverage coverage
.docusaurus .docusaurus
.idea .idea
@ -11,6 +11,8 @@ coverage
jest/vendor jest/vendor
argos/test-results
packages/lqip-loader/lib/ packages/lqip-loader/lib/
packages/docusaurus/lib/ packages/docusaurus/lib/
packages/docusaurus-*/lib/* packages/docusaurus-*/lib/*

6757
CHANGELOG-v2.md Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@ Apart from the `good first issue`, the following labels are also worth looking a
- [`help wanted`](https://github.com/facebook/docusaurus/labels/help%20wanted): if you have specific knowledge in one domain, working on these issues can make your expertise shine. - [`help wanted`](https://github.com/facebook/docusaurus/labels/help%20wanted): if you have specific knowledge in one domain, working on these issues can make your expertise shine.
- [`status: accepting pr`](https://github.com/facebook/docusaurus/labels/status%3A%20accepting%20pr): community contributors can feel free to claim any of these. - [`status: accepting pr`](https://github.com/facebook/docusaurus/labels/status%3A%20accepting%20pr): community contributors can feel free to claim any of these.
If you want to work on any of these issues, just drop a message saying "I'd like to work on this", and we will assign the issue to you and update the issue's status as "claimed". **You are expected to send a pull request within seven days** after that, so we can still delegate the issue to someone else if you are unavailable. If you want to work on any of these issues, just drop a message saying "I am working on this". **You do not need to ask for assignment to work on any issue explicitly marked as welcoming external contributions.** However, don't "cookie lick", or squat on an issue without actually sending a PR. You are automatically considered as giving up if you don't **send a PR within seven days after your comment**, and the issue automatically becomes up for grabs again.
Alternatively, when opening an issue, you can also click the "self service" checkbox to indicate that you'd like to work on the issue yourself, which will also make us see the issue as "claimed". Alternatively, when opening an issue, you can also click the "self service" checkbox to indicate that you'd like to work on the issue yourself, which will also make us see the issue as "claimed".
@ -214,6 +214,16 @@ After you have signed the CLA, the CLA bot would automatically update the PR sta
If it happens that you were unavailable and your PR gets closed, feel free to reopen once it's ready! We are still happy to review it, help you complete it, and eventually merge it. If it happens that you were unavailable and your PR gets closed, feel free to reopen once it's ready! We are still happy to review it, help you complete it, and eventually merge it.
### AI-assisted PRs
We welcome the use of AI tools for authoring PRs, and we love to see people pushing the boundaries of AI capabilities. The core team actively uses different AI tools in our development process. However, we are aware that **many people are sending entirely AI-generated PRs as a low-effort way to farm OSS contributions**, so please be mindful of the following etiquette to show your respect for our time and our codebase:
- **Be transparent**: If a significant portion of your code is AI generated, please indicate that in your PR description.
- **Be accountable**: You are responsible for the code you submit, regardless of whether it was generated by AI or written by you. You should be able to explain every line of the code, ensure all tests pass, and address our reviews.
- **Be reasonable**: Sometimes we receive 1k LOC PRs that are obviously AI-generated and implement unsolicited features. Please note that significant changes require prior communication and approval from the team in the form of an issue.
We retain the right to close any PR that we deem as unproductive or low-effort, even when we agree with the spirit of the change.
### Breaking Changes ### Breaking Changes
When adding a new breaking change, follow this template in your pull request: When adding a new breaking change, follow this template in your pull request:
@ -227,6 +237,10 @@ When adding a new breaking change, follow this template in your pull request:
- **Severity (number of people affected x effort)**: - **Severity (number of people affected x effort)**:
``` ```
> [!NOTE]
>
> Breaking changes should be discussed in the issue tracker before being implemented.
### What Happens Next? ### What Happens Next?
The core Docusaurus team will be monitoring pull requests. Do help us by keeping pull requests consistent by following the guidelines above. The core Docusaurus team will be monitoring pull requests. Do help us by keeping pull requests consistent by following the guidelines above.

View File

@ -45,7 +45,7 @@ Short on time? Check out our [5-minute tutorial ⏱️](https://tutorial.docusau
- **Customizable** - **Customizable**
> While Docusaurus ships with the key pages and sections you need to get started, including a home page, a docs section, a [blog](https://docusaurus.io/docs/blog), and additional support pages, it is also [customizable](https://docusaurus.io/docs/creating-pages) as well to ensure you have a site that is [uniquely yours](https://docusaurus.io/docs/styling-layout). > While Docusaurus ships with the key pages and sections you need to get started, including a home page, a docs section, a [blog](https://docusaurus.io/docs/blog), and additional support pages, it is also [customizable](https://docusaurus.io/docs/creating-pages) to ensure you have a site that is [uniquely yours](https://docusaurus.io/docs/styling-layout).
## Installation ## Installation
@ -120,4 +120,4 @@ The Docusaurus documentation (e.g., `.md` files in the `/docs` folder) is [Creat
[![Rocket Validator logo](./admin/img/rocketvalidator-logo.png)](https://rocketvalidator.com/) [![Rocket Validator logo](./admin/img/rocketvalidator-logo.png)](https://rocketvalidator.com/)
[Rocket Validator](https://rocketvalidator.com/) helps us find HTML markup or accessibility issues. [Rocket Validator](https://rocketvalidator.com/) helps us find [HTML markup and accessibility issues](https://rocketvalidator.com/stats/docusaurus.io).

View File

@ -1,6 +1,6 @@
{ {
"name": "new.docusaurus.io", "name": "new.docusaurus.io",
"version": "3.7.0", "version": "3.9.2",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "npx --package netlify-cli netlify dev" "start": "npx --package netlify-cli netlify dev"

View File

@ -78,7 +78,7 @@ Not all labels will appear in the changelog—some are designed not to. However,
is:pr is:merged sort:updated-desc -label:"pr: breaking change","pr: new feature","pr: bug fix","pr: performance","pr: polish","pr: documentation","pr: maintenance","pr: internal","pr: dependencies","pr: showcase" is:pr is:merged sort:updated-desc -label:"pr: breaking change","pr: new feature","pr: bug fix","pr: performance","pr: polish","pr: documentation","pr: maintenance","pr: internal","pr: dependencies","pr: showcase"
``` ```
[Check tags of all recently merged Pull-Requests](https://github.com/facebook/docusaurus/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+-label%3A%22pr%3A+breaking+change%22%2C%22pr%3A+new+feature%22%2C%22pr%3A+bug+fix%22%2C%22pr%3A+performance%22%2C%22pr%3A+polish%22%2C%22pr%3A+documentation%22%2C%22pr%3A+maintenance%22%2C%22pr%3A+internal%22%2C%22pr%3A+dependencies%22%2C%22pr%3A+showcase%22) [Check tags of all recently merged Pull-Requests](https://github.com/facebook/docusaurus/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+-label%3A%22pr%3A+breaking+change%22%2C%22pr%3A+new+feature%22%2C%22pr%3A+bug+fix%22%2C%22pr%3A+performance%22%2C%22pr%3A+polish%22%2C%22pr%3A+documentation%22%2C%22pr%3A+maintenance%22%2C%22pr%3A+internal%22%2C%22pr%3A+dependencies%22%2C%22pr%3A+showcase%22%2C%22pr%3A+ignore%22%2C%22pr%3A+translations%22+)
Some general principles about the labeling process: Some general principles about the labeling process:

View File

@ -53,6 +53,8 @@ git diff --name-only -- '*.json' | sed 's, ,\\&,g' | xargs git checkout --
# The website is generated outside the repo to minimize chances of yarn resolving the wrong version # The website is generated outside the repo to minimize chances of yarn resolving the wrong version
cd .. cd ..
echo Generating test-website in `pwd`
# Build skeleton website with new version # Build skeleton website with new version
npm_config_registry="$CUSTOM_REGISTRY_URL" npx --yes --loglevel silly create-docusaurus@"$NEW_VERSION" test-website classic --javascript $EXTRA_OPTS npm_config_registry="$CUSTOM_REGISTRY_URL" npx --yes --loglevel silly create-docusaurus@"$NEW_VERSION" test-website classic --javascript $EXTRA_OPTS

View File

@ -1,6 +1,6 @@
{ {
"name": "test-bad-package", "name": "test-bad-package",
"version": "3.7.0", "version": "3.9.2",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@mdx-js/react": "1.0.1", "@mdx-js/react": "1.0.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "argos", "name": "argos",
"version": "3.7.0", "version": "3.9.2",
"description": "Argos visual diff tests", "description": "Argos visual diff tests",
"license": "MIT", "license": "MIT",
"private": true, "private": true,

View File

@ -134,11 +134,6 @@ function throwOnConsole(page: Page) {
// it's already happening in main branch // it's already happening in main branch
'Failed to load resource: the server responded with a status of 404 (Not Found)', 'Failed to load resource: the server responded with a status of 404 (Not Found)',
// TODO legit hydration bugs to fix on embeds of /docs/styling-layout
// useLocation() returns window.search/hash immediately :s
'/docs/configuration?docusaurus-theme=light',
'/docs/configuration?docusaurus-theme=dark',
// Warning because react-live not supporting React automatic JSX runtime // Warning because react-live not supporting React automatic JSX runtime
// See https://github.com/FormidableLabs/react-live/issues/405 // See https://github.com/FormidableLabs/react-live/issues/405
'Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance', 'Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance',

View File

@ -20,6 +20,19 @@ languages_mapping: &languages_mapping
two_letters_code: two_letters_code:
pt-BR: pt-BR pt-BR: pt-BR
# Crowdin regularly update their MDX parser
# Unfortunately, their v2 parser is more "MDX compliant" and thus can't parse
# Docusaurus MDX files correctly due to our custom {#headingId} syntax.
# Adding this type param permits using their older v1.2 parser.
# Note: you can find the version of a file using browser DevTools
# The source file icons will have a class such as "file_type_mdx_v1_2"
#
# TODO fix our headingId syntax
# providing an explicit type is annoying and not future-proof
# there's a risk that when adding an image in /docs, it will be parsed as mdx
# and duplicating source file configs for various extensions is not great either
mdx_file_type: &mdx_file_type mdx_v1_2
# #
# Files configuration # Files configuration
# #
@ -27,18 +40,33 @@ files:
- source: /website/i18n/en/**/* - source: /website/i18n/en/**/*
translation: /website/i18n/%two_letters_code%/**/%original_file_name% translation: /website/i18n/%two_letters_code%/**/%original_file_name%
languages_mapping: *languages_mapping languages_mapping: *languages_mapping
- source: /website/docs/**/*.mdx
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
languages_mapping: *languages_mapping
type: *mdx_file_type
- source: /website/docs/**/* - source: /website/docs/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name% translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%
languages_mapping: *languages_mapping languages_mapping: *languages_mapping
- source: /website/community/**/* ignore: [/**/*.mdx]
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs-community/current/**/%original_file_name%
- source: /website/versioned_docs/**/*.mdx
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/**/%original_file_name%
languages_mapping: *languages_mapping languages_mapping: *languages_mapping
type: *mdx_file_type
- source: /website/versioned_docs/**/* - source: /website/versioned_docs/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/**/%original_file_name% translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/**/%original_file_name%
languages_mapping: *languages_mapping languages_mapping: *languages_mapping
ignore: [/**/*.mdx]
- source: /website/community/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-docs-community/current/**/%original_file_name%
languages_mapping: *languages_mapping
- source: /website/blog/**/* - source: /website/blog/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name% translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%
languages_mapping: *languages_mapping languages_mapping: *languages_mapping
- source: /website/src/pages/**/* - source: /website/src/pages/**/*
translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-pages/**/%original_file_name% translation: /website/i18n/%two_letters_code%/docusaurus-plugin-content-pages/**/%original_file_name%
ignore: [/**/*.js, /**/*.jsx, /**/*.ts, /**/*.tsx, /**/*.css] ignore: [/**/*.js, /**/*.jsx, /**/*.ts, /**/*.tsx, /**/*.css]

View File

@ -2,40 +2,40 @@
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
### Installation ## Installation
```bash ```bash
$ yarn yarn
``` ```
### Local Development ## Local Development
```bash ```bash
$ yarn start yarn start
``` ```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build ## Build
```bash ```bash
$ yarn build yarn build
``` ```
This command generates static content into the `build` directory and can be served using any static contents hosting service. This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment ## Deployment
Using SSH: Using SSH:
```bash ```bash
$ USE_SSH=true yarn deploy USE_SSH=true yarn deploy
``` ```
Not using SSH: Not using SSH:
```bash ```bash
$ GIT_USER=<Your GitHub username> yarn deploy GIT_USER=<Your GitHub username> yarn deploy
``` ```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

View File

@ -1,12 +1,14 @@
yangshun: yangshun:
name: Yangshun Tay name: Yangshun Tay
title: Front End Engineer @ Facebook title: Ex-Meta Staff Engineer, Co-founder GreatFrontEnd
url: https://github.com/yangshun url: https://linkedin.com/in/yangshun
image_url: https://github.com/yangshun.png image_url: https://github.com/yangshun.png
page: true page: true
socials: socials:
x: yangshunz x: yangshunz
linkedin: yangshun
github: yangshun github: yangshun
newsletter: https://www.greatfrontend.com
slorber: slorber:
name: Sébastien Lorber name: Sébastien Lorber

View File

@ -14,7 +14,7 @@ Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new
### What you'll need ### What you'll need
- [Node.js](https://nodejs.org/en/download/) version 18.0 or above: - [Node.js](https://nodejs.org/en/download/) version 20.0 or above:
- When installing Node.js, you are recommended to check all checkboxes related to dependencies. - When installing Node.js, you are recommended to check all checkboxes related to dependencies.
## Generate a new site ## Generate a new site

View File

@ -9,6 +9,11 @@ const config: Config = {
tagline: 'Dinosaurs are cool', tagline: 'Dinosaurs are cool',
favicon: 'img/favicon.ico', favicon: 'img/favicon.ico',
// Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future
future: {
v4: true, // Improve compatibility with the upcoming Docusaurus v4
},
// Set the production url of your site here // Set the production url of your site here
url: 'https://your-docusaurus-site.example.com', url: 'https://your-docusaurus-site.example.com',
// Set the /<baseUrl>/ pathname under which your site is served // Set the /<baseUrl>/ pathname under which your site is served
@ -21,7 +26,6 @@ const config: Config = {
projectName: 'docusaurus', // Usually your repo name. projectName: 'docusaurus', // Usually your repo name.
onBrokenLinks: 'throw', onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set // Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you // useful metadata like html lang. For example, if your site is Chinese, you
@ -67,6 +71,9 @@ const config: Config = {
themeConfig: { themeConfig: {
// Replace with your project's social card // Replace with your project's social card
image: 'img/docusaurus-social-card.jpg', image: 'img/docusaurus-social-card.jpg',
colorMode: {
respectPrefersColorScheme: true,
},
navbar: { navbar: {
title: 'My Site', title: 'My Site',
logo: { logo: {

View File

@ -16,8 +16,8 @@
"dev": "docusaurus start" "dev": "docusaurus start"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/preset-classic": "3.7.0", "@docusaurus/preset-classic": "3.9.2",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0", "prism-react-renderer": "^2.3.0",
@ -25,9 +25,9 @@
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0", "@docusaurus/module-type-aliases": "3.9.2",
"@docusaurus/tsconfig": "3.7.0", "@docusaurus/tsconfig": "3.9.2",
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"browserslist": { "browserslist": {
@ -43,7 +43,7 @@
] ]
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
}, },
"description": "Docusaurus example project (classic-typescript template)" "description": "Docusaurus example project (classic-typescript template)"
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,40 +2,40 @@
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
### Installation ## Installation
```bash ```bash
$ yarn yarn
``` ```
### Local Development ## Local Development
```bash ```bash
$ yarn start yarn start
``` ```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build ## Build
```bash ```bash
$ yarn build yarn build
``` ```
This command generates static content into the `build` directory and can be served using any static contents hosting service. This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment ## Deployment
Using SSH: Using SSH:
```bash ```bash
$ USE_SSH=true yarn deploy USE_SSH=true yarn deploy
``` ```
Not using SSH: Not using SSH:
```bash ```bash
$ GIT_USER=<Your GitHub username> yarn deploy GIT_USER=<Your GitHub username> yarn deploy
``` ```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

View File

@ -1,12 +1,14 @@
yangshun: yangshun:
name: Yangshun Tay name: Yangshun Tay
title: Front End Engineer @ Facebook title: Ex-Meta Staff Engineer, Co-founder GreatFrontEnd
url: https://github.com/yangshun url: https://linkedin.com/in/yangshun
image_url: https://github.com/yangshun.png image_url: https://github.com/yangshun.png
page: true page: true
socials: socials:
x: yangshunz x: yangshunz
linkedin: yangshun
github: yangshun github: yangshun
newsletter: https://www.greatfrontend.com
slorber: slorber:
name: Sébastien Lorber name: Sébastien Lorber

View File

@ -14,7 +14,7 @@ Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new
### What you'll need ### What you'll need
- [Node.js](https://nodejs.org/en/download/) version 18.0 or above: - [Node.js](https://nodejs.org/en/download/) version 20.0 or above:
- When installing Node.js, you are recommended to check all checkboxes related to dependencies. - When installing Node.js, you are recommended to check all checkboxes related to dependencies.
## Generate a new site ## Generate a new site

View File

@ -14,6 +14,11 @@ const config = {
tagline: 'Dinosaurs are cool', tagline: 'Dinosaurs are cool',
favicon: 'img/favicon.ico', favicon: 'img/favicon.ico',
// Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future
future: {
v4: true, // Improve compatibility with the upcoming Docusaurus v4
},
// Set the production url of your site here // Set the production url of your site here
url: 'https://your-docusaurus-site.example.com', url: 'https://your-docusaurus-site.example.com',
// Set the /<baseUrl>/ pathname under which your site is served // Set the /<baseUrl>/ pathname under which your site is served
@ -26,7 +31,6 @@ const config = {
projectName: 'docusaurus', // Usually your repo name. projectName: 'docusaurus', // Usually your repo name.
onBrokenLinks: 'throw', onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set // Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you // useful metadata like html lang. For example, if your site is Chinese, you
@ -75,6 +79,9 @@ const config = {
({ ({
// Replace with your project's social card // Replace with your project's social card
image: 'img/docusaurus-social-card.jpg', image: 'img/docusaurus-social-card.jpg',
colorMode: {
respectPrefersColorScheme: true,
},
navbar: { navbar: {
title: 'My Site', title: 'My Site',
logo: { logo: {

View File

@ -15,8 +15,8 @@
"dev": "docusaurus start" "dev": "docusaurus start"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/preset-classic": "3.7.0", "@docusaurus/preset-classic": "3.9.2",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0", "prism-react-renderer": "^2.3.0",
@ -24,8 +24,8 @@
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0", "@docusaurus/module-type-aliases": "3.9.2",
"@docusaurus/types": "3.7.0" "@docusaurus/types": "3.9.2"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -40,7 +40,7 @@
] ]
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
}, },
"description": "Docusaurus example project" "description": "Docusaurus example project"
} }

File diff suppressed because it is too large Load Diff

7
jest.config.mjs vendored
View File

@ -32,15 +32,16 @@ const ignorePatterns = [
export default { export default {
rootDir: fileURLToPath(new URL('.', import.meta.url)), rootDir: fileURLToPath(new URL('.', import.meta.url)),
verbose: true, verbose: true,
// Default 5s timeout often fails on Windows :s,
// see https://github.com/facebook/docusaurus/pull/8259
testTimeout: 15000,
setupFiles: ['./jest/setup.js'], setupFiles: ['./jest/setup.js'],
testEnvironmentOptions: { testEnvironmentOptions: {
url: 'https://docusaurus.io/', url: 'https://docusaurus.io/',
}, },
testEnvironment: 'node', testEnvironment: 'node',
testPathIgnorePatterns: ignorePatterns, testPathIgnorePatterns: ignorePatterns,
// Default 5s timeout often fails on Windows :s, watchPathIgnorePatterns: ['/\\.docusaurus'],
// see https://github.com/facebook/docusaurus/pull/8259
testTimeout: 15000,
coveragePathIgnorePatterns: [ coveragePathIgnorePatterns: [
...ignorePatterns, ...ignorePatterns,
// We also ignore all package entry points // We also ignore all package entry points

5
jest/deps.d.ts vendored
View File

@ -12,8 +12,3 @@ declare module 'to-vfile' {
export function read(path: string, encoding?: string): Promise<VFile>; export function read(path: string, encoding?: string): Promise<VFile>;
} }
declare module '@testing-utils/git' {
const createTempRepo: typeof import('./utils/git').createTempRepo;
export {createTempRepo};
}

View File

@ -82,7 +82,7 @@ function normalizePaths<T>(value: T): T {
(val) => val.split(cwdReal).join('<PROJECT_ROOT>'), (val) => val.split(cwdReal).join('<PROJECT_ROOT>'),
(val) => val.split(cwd).join('<PROJECT_ROOT>'), (val) => val.split(cwd).join('<PROJECT_ROOT>'),
// Replace home directory with <TEMP_DIR> // Replace temp directory with <TEMP_DIR>
(val) => val.split(tempDirReal).join('<TEMP_DIR>'), (val) => val.split(tempDirReal).join('<TEMP_DIR>'),
(val) => val.split(tempDir).join('<TEMP_DIR>'), (val) => val.split(tempDir).join('<TEMP_DIR>'),

63
jest/utils/git.ts vendored
View File

@ -1,63 +0,0 @@
/**
* 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 fs from 'fs-extra';
import os from 'os';
import path from 'path';
import shell from 'shelljs';
class Git {
constructor(private dir: string) {
const res = shell.exec('git init', {cwd: dir, silent: true});
if (res.code !== 0) {
throw new Error(`git init exited with code ${res.code}.
stderr: ${res.stderr}
stdout: ${res.stdout}`);
}
// Doesn't matter currently
shell.exec('git config user.email "test@jc-verse.com"', {
cwd: dir,
silent: true,
});
shell.exec('git config user.name "Test"', {cwd: dir, silent: true});
shell.exec('git commit --allow-empty -m "First commit"', {
cwd: dir,
silent: true,
});
}
commit(msg: string, date: string, author: string): void {
const addRes = shell.exec('git add .', {cwd: this.dir, silent: true});
const commitRes = shell.exec(
`git commit -m "${msg}" --date "${date}T00:00:00Z" --author "${author}"`,
{
cwd: this.dir,
env: {GIT_COMMITTER_DATE: `${date}T00:00:00Z`},
silent: true,
},
);
if (addRes.code !== 0) {
throw new Error(`git add exited with code ${addRes.code}.
stderr: ${addRes.stderr}
stdout: ${addRes.stdout}`);
}
if (commitRes.code !== 0) {
throw new Error(`git commit exited with code ${commitRes.code}.
stderr: ${commitRes.stderr}
stdout: ${commitRes.stdout}`);
}
}
}
// This function is sync so the same mock repo can be shared across tests
export function createTempRepo(): {repoDir: string; git: Git} {
const repoDir = fs.mkdtempSync(path.join(os.tmpdir(), 'git-test-repo'));
const git = new Git(repoDir);
return {repoDir, git};
}

View File

@ -1,5 +1,5 @@
{ {
"version": "3.7.0", "version": "3.9.2",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"useNx": false, "useNx": false,

View File

@ -1,6 +1,6 @@
{ {
"name": "create-docusaurus", "name": "create-docusaurus",
"version": "3.7.0", "version": "3.9.2",
"description": "Create Docusaurus apps easily.", "description": "Create Docusaurus apps easily.",
"type": "module", "type": "module",
"repository": { "repository": {
@ -22,10 +22,10 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"commander": "^5.1.0", "commander": "^5.1.0",
"execa": "5.1.1", "execa": "^5.1.1",
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"prompts": "^2.4.2", "prompts": "^2.4.2",
@ -37,6 +37,6 @@
"@types/supports-color": "^8.1.1" "@types/supports-color": "^8.1.1"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -273,7 +273,10 @@ async function getSiteName(
return 'A website name is required.'; return 'A website name is required.';
} }
const dest = path.resolve(rootDir, siteName); const dest = path.resolve(rootDir, siteName);
if (await fs.pathExists(dest)) { if (siteName === '.' && (await fs.readdir(dest)).length > 0) {
return logger.interpolate`Directory not empty at path=${dest}!`;
}
if (siteName !== '.' && (await fs.pathExists(dest))) {
return logger.interpolate`Directory already exists at path=${dest}!`; return logger.interpolate`Directory already exists at path=${dest}!`;
} }
return true; return true;

View File

@ -26,7 +26,6 @@ const config: Config = {
projectName: 'docusaurus', // Usually your repo name. projectName: 'docusaurus', // Usually your repo name.
onBrokenLinks: 'throw', onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set // Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you // useful metadata like html lang. For example, if your site is Chinese, you
@ -72,6 +71,9 @@ const config: Config = {
themeConfig: { themeConfig: {
// Replace with your project's social card // Replace with your project's social card
image: 'img/docusaurus-social-card.jpg', image: 'img/docusaurus-social-card.jpg',
colorMode: {
respectPrefersColorScheme: true,
},
navbar: { navbar: {
title: 'My Site', title: 'My Site',
logo: { logo: {

View File

@ -1,6 +1,6 @@
{ {
"name": "docusaurus-2-classic-typescript-template", "name": "docusaurus-2-classic-typescript-template",
"version": "3.7.0", "version": "3.9.2",
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@ -15,8 +15,8 @@
"typecheck": "tsc" "typecheck": "tsc"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/preset-classic": "3.7.0", "@docusaurus/preset-classic": "3.9.2",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0", "prism-react-renderer": "^2.3.0",
@ -24,9 +24,9 @@
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0", "@docusaurus/module-type-aliases": "3.9.2",
"@docusaurus/tsconfig": "3.7.0", "@docusaurus/tsconfig": "3.9.2",
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"browserslist": { "browserslist": {
@ -42,6 +42,6 @@
] ]
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -31,7 +31,6 @@ const config = {
projectName: 'docusaurus', // Usually your repo name. projectName: 'docusaurus', // Usually your repo name.
onBrokenLinks: 'throw', onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set // Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you // useful metadata like html lang. For example, if your site is Chinese, you
@ -80,6 +79,9 @@ const config = {
({ ({
// Replace with your project's social card // Replace with your project's social card
image: 'img/docusaurus-social-card.jpg', image: 'img/docusaurus-social-card.jpg',
colorMode: {
respectPrefersColorScheme: true,
},
navbar: { navbar: {
title: 'My Site', title: 'My Site',
logo: { logo: {

View File

@ -1,6 +1,6 @@
{ {
"name": "docusaurus-2-classic-template", "name": "docusaurus-2-classic-template",
"version": "3.7.0", "version": "3.9.2",
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@ -14,8 +14,8 @@
"write-heading-ids": "docusaurus write-heading-ids" "write-heading-ids": "docusaurus write-heading-ids"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/preset-classic": "3.7.0", "@docusaurus/preset-classic": "3.9.2",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0", "prism-react-renderer": "^2.3.0",
@ -23,8 +23,8 @@
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0", "@docusaurus/module-type-aliases": "3.9.2",
"@docusaurus/types": "3.7.0" "@docusaurus/types": "3.9.2"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -39,6 +39,6 @@
] ]
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -14,7 +14,7 @@ Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new
### What you'll need ### What you'll need
- [Node.js](https://nodejs.org/en/download/) version 18.0 or above: - [Node.js](https://nodejs.org/en/download/) version 20.0 or above:
- When installing Node.js, you are recommended to check all checkboxes related to dependencies. - When installing Node.js, you are recommended to check all checkboxes related to dependencies.
## Generate a new site ## Generate a new site

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/babel", "name": "@docusaurus/babel",
"version": "3.7.0", "version": "3.9.2",
"description": "Docusaurus package for Babel-related utils.", "description": "Docusaurus package for Babel-related utils.",
"main": "./lib/index.js", "main": "./lib/index.js",
"types": "./lib/index.d.ts", "types": "./lib/index.d.ts",
@ -36,15 +36,14 @@
"@babel/preset-react": "^7.25.9", "@babel/preset-react": "^7.25.9",
"@babel/preset-typescript": "^7.25.9", "@babel/preset-typescript": "^7.25.9",
"@babel/runtime": "^7.25.9", "@babel/runtime": "^7.25.9",
"@babel/runtime-corejs3": "^7.25.9",
"@babel/traverse": "^7.25.9", "@babel/traverse": "^7.25.9",
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-dynamic-import-node": "^2.3.3",
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/bundler", "name": "@docusaurus/bundler",
"version": "3.7.0", "version": "3.9.2",
"description": "Docusaurus util package to abstract the current bundler.", "description": "Docusaurus util package to abstract the current bundler.",
"main": "./lib/index.js", "main": "./lib/index.js",
"types": "./lib/index.d.ts", "types": "./lib/index.d.ts",
@ -19,24 +19,24 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.25.9", "@babel/core": "^7.25.9",
"@docusaurus/babel": "3.7.0", "@docusaurus/babel": "3.9.2",
"@docusaurus/cssnano-preset": "3.7.0", "@docusaurus/cssnano-preset": "3.9.2",
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"babel-loader": "^9.2.1", "babel-loader": "^9.2.1",
"clean-css": "^5.3.2", "clean-css": "^5.3.3",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1", "css-loader": "^6.11.0",
"css-minimizer-webpack-plugin": "^5.0.1", "css-minimizer-webpack-plugin": "^5.0.1",
"cssnano": "^6.1.2", "cssnano": "^6.1.2",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"html-minifier-terser": "^7.2.0", "html-minifier-terser": "^7.2.0",
"mini-css-extract-plugin": "^2.9.1", "mini-css-extract-plugin": "^2.9.2",
"null-loader": "^4.0.1", "null-loader": "^4.0.1",
"postcss": "^8.4.26", "postcss": "^8.5.4",
"postcss-loader": "^7.3.3", "postcss-loader": "^7.3.4",
"postcss-preset-env": "^10.1.0", "postcss-preset-env": "^10.2.1",
"terser-webpack-plugin": "^5.3.9", "terser-webpack-plugin": "^5.3.9",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
@ -55,6 +55,6 @@
"@total-typescript/shoehorn": "^0.1.2" "@total-typescript/shoehorn": "^0.1.2"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -129,8 +129,8 @@ export async function registerBundlerTracing({
await Rspack.experiments.globalTrace.register( await Rspack.experiments.globalTrace.register(
filter, filter,
'chrome', 'perfetto',
'./rspack-tracing.json', './rspack-tracing.pftrace',
); );
console.info(`Rspack tracing registered, filter=${filter}`); console.info(`Rspack tracing registered, filter=${filter}`);

View File

@ -28,7 +28,7 @@ async function createSwcJsLoaderFactory(): Promise<
return ({isServer}) => { return ({isServer}) => {
return { return {
loader, loader,
options: getOptions({isServer}), options: getOptions({isServer, bundlerName: 'webpack'}),
}; };
}; };
} }
@ -42,7 +42,7 @@ async function createRspackSwcJsLoaderFactory(): Promise<
return ({isServer}) => { return ({isServer}) => {
return { return {
loader, loader,
options: getOptions({isServer}), options: getOptions({isServer, bundlerName: 'rspack'}),
}; };
}; };
} }

View File

@ -142,7 +142,10 @@ async function getRspackMinimizers({
}: MinimizersConfig): Promise<WebpackPluginInstance[]> { }: MinimizersConfig): Promise<WebpackPluginInstance[]> {
const rspack = getCurrentBundlerAsRspack({currentBundler}); const rspack = getCurrentBundlerAsRspack({currentBundler});
const getBrowserslistQueries = await importGetBrowserslistQueries(); const getBrowserslistQueries = await importGetBrowserslistQueries();
const browserslistQueries = getBrowserslistQueries({isServer: false}); const browserslistQueries = getBrowserslistQueries({
isServer: false,
bundlerName: 'rspack',
});
const swcJsMinimizerOptions = await importSwcJsMinimizerOptions(); const swcJsMinimizerOptions = await importSwcJsMinimizerOptions();
return [ return [
// See https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin // See https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin

View File

@ -84,6 +84,10 @@ async function getSwcMinifier(): Promise<HtmlMinifier> {
// TODO maybe it's fine to only keep <!-- --> React comments? // TODO maybe it's fine to only keep <!-- --> React comments?
preserveComments: [], preserveComments: [],
// Keep <head> tag: important for social image crawlers like LinkedIn
// See https://github.com/swc-project/swc/issues/10994
tagOmission: 'keep-head-and-body',
// Sorting these attributes (class) can lead to React hydration errors // Sorting these attributes (class) can lead to React hydration errors
sortSpaceSeparatedAttributeValues: false, sortSpaceSeparatedAttributeValues: false,
sortAttributes: false, sortAttributes: false,

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/cssnano-preset", "name": "@docusaurus/cssnano-preset",
"version": "3.7.0", "version": "3.9.2",
"description": "Advanced cssnano preset for maximum optimization.", "description": "Advanced cssnano preset for maximum optimization.",
"main": "lib/index.js", "main": "lib/index.js",
"license": "MIT", "license": "MIT",
@ -18,7 +18,7 @@
}, },
"dependencies": { "dependencies": {
"cssnano-preset-advanced": "^6.1.2", "cssnano-preset-advanced": "^6.1.2",
"postcss": "^8.4.38", "postcss": "^8.5.4",
"postcss-sort-media-queries": "^5.2.0", "postcss-sort-media-queries": "^5.2.0",
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },
@ -26,6 +26,6 @@
"to-vfile": "^6.1.0" "to-vfile": "^6.1.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -13,6 +13,9 @@ const preset: typeof advancedBasePreset = function preset(opts) {
const advancedPreset = advancedBasePreset({ const advancedPreset = advancedBasePreset({
autoprefixer: {add: false}, autoprefixer: {add: false},
discardComments: {removeAll: true}, discardComments: {removeAll: true},
// See CodeBlock custom line number bug: https://github.com/facebook/docusaurus/pull/11487
/* cSpell:ignore Idents */
reduceIdents: {counter: false},
/* cSpell:ignore zindex */ /* cSpell:ignore zindex */
zindex: false, zindex: false,
...opts, ...opts,

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/faster", "name": "@docusaurus/faster",
"version": "3.7.0", "version": "3.9.2",
"description": "Docusaurus experimental package exposing new modern dependencies to make the build faster.", "description": "Docusaurus experimental package exposing new modern dependencies to make the build faster.",
"main": "./lib/index.js", "main": "./lib/index.js",
"types": "./lib/index.d.ts", "types": "./lib/index.d.ts",
@ -18,18 +18,19 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"@rspack/core": "^1.3.10", "@rspack/core": "^1.5.0",
"@swc/core": "^1.7.39", "@swc/core": "^1.7.39",
"@swc/html": "^1.7.39", "@swc/html": "^1.13.5",
"browserslist": "^4.24.2", "browserslist": "^4.24.2",
"lightningcss": "^1.27.0", "lightningcss": "^1.27.0",
"semver": "^7.5.4",
"swc-loader": "^0.2.6", "swc-loader": "^0.2.6",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"webpack": "^5.95.0" "webpack": "^5.95.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
}, },
"peerDependencies": { "peerDependencies": {
"@docusaurus/types": "*" "@docusaurus/types": "*"

View File

@ -9,18 +9,22 @@ import Rspack from '@rspack/core';
import * as lightningcss from 'lightningcss'; import * as lightningcss from 'lightningcss';
import browserslist from 'browserslist'; import browserslist from 'browserslist';
import {minify as swcHtmlMinifier} from '@swc/html'; import {minify as swcHtmlMinifier} from '@swc/html';
import semver from 'semver';
import type {JsMinifyOptions, Options as SwcOptions} from '@swc/core'; import type {JsMinifyOptions, Options as SwcOptions} from '@swc/core';
import type {CurrentBundler} from '@docusaurus/types';
export const swcLoader = require.resolve('swc-loader'); export const swcLoader = require.resolve('swc-loader');
export const getSwcLoaderOptions = ({ export const getSwcLoaderOptions = ({
isServer, isServer,
bundlerName,
}: { }: {
isServer: boolean; isServer: boolean;
bundlerName: CurrentBundler['name'];
}): SwcOptions => { }): SwcOptions => {
return { return {
env: { env: {
targets: getBrowserslistQueries({isServer}), targets: getBrowserslistQueries({isServer, bundlerName}),
}, },
jsc: { jsc: {
parser: { parser: {
@ -63,20 +67,53 @@ export function getSwcJsMinimizerOptions(): JsMinifyOptions {
}; };
} }
// TODO this is not accurate
// for Rspack we should read from the built-in browserslist data
// see https://github.com/facebook/docusaurus/pull/11496
function getLastBrowserslistKnownNodeVersion(
bundlerName: CurrentBundler['name'],
): string {
if (bundlerName === 'rspack') {
// TODO hardcoded value until Rspack exposes its Browserslist data
// see https://github.com/facebook/docusaurus/pull/11496
return '22.0.0';
}
// browserslist('last 1 node versions')[0]!.replace('node ', '')
return browserslist.nodeVersions.at(-1)!;
}
function getMinVersion(v1: string, v2: string): string {
return semver.lt(v1, v2) ? v1 : v2;
}
// We need this because of Rspack built-in LightningCSS integration // We need this because of Rspack built-in LightningCSS integration
// See https://github.com/orgs/browserslist/discussions/846 // See https://github.com/orgs/browserslist/discussions/846
export function getBrowserslistQueries({ export function getBrowserslistQueries({
isServer, isServer,
bundlerName,
}: { }: {
isServer: boolean; isServer: boolean;
bundlerName: CurrentBundler['name'];
}): string[] { }): string[] {
if (isServer) { if (isServer) {
return [`node ${process.versions.node}`]; // Escape hatch env variable
if (process.env.DOCUSAURUS_SERVER_NODE_TARGET) {
return [`node ${process.env.DOCUSAURUS_SERVER_NODE_TARGET}`];
}
// For server builds, we want to use the current Node version as target
// But we can't pass a target that Browserslist doesn't know about yet
const nodeTarget = getMinVersion(
process.versions.node,
getLastBrowserslistKnownNodeVersion(bundlerName),
);
return [`node ${nodeTarget}`];
} }
const queries = browserslist.loadConfig({path: process.cwd()}) ?? [ const queries = browserslist.loadConfig({path: process.cwd()}) ?? [
...browserslist.defaults, ...browserslist.defaults,
]; ];
return queries; return queries;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/logger", "name": "@docusaurus/logger",
"version": "3.7.0", "version": "3.9.2",
"description": "An encapsulated logger for semantically formatting console messages.", "description": "An encapsulated logger for semantically formatting console messages.",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@ -24,7 +24,7 @@
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
}, },
"devDependencies": { "devDependencies": {
"@types/supports-color": "^8.1.1" "@types/supports-color": "^8.1.1"

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/mdx-loader", "name": "@docusaurus/mdx-loader",
"version": "3.7.0", "version": "3.9.2",
"description": "Docusaurus Loader for MDX", "description": "Docusaurus Loader for MDX",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@ -18,9 +18,9 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"@docusaurus/utils-validation": "3.7.0", "@docusaurus/utils-validation": "3.9.2",
"@mdx-js/mdx": "^3.0.0", "@mdx-js/mdx": "^3.0.0",
"@slorber/remark-comment": "^1.0.0", "@slorber/remark-comment": "^1.0.0",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
@ -44,7 +44,7 @@
"webpack": "^5.88.1" "webpack": "^5.88.1"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"@types/escape-html": "^1.0.2", "@types/escape-html": "^1.0.2",
"@types/mdast": "^4.0.2", "@types/mdast": "^4.0.2",
"@types/stringify-object": "^3.3.1", "@types/stringify-object": "^3.3.1",
@ -62,6 +62,6 @@
"react-dom": "^18.0.0 || ^19.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -22,6 +22,9 @@ import type {WebpackCompilerName} from '@docusaurus/utils';
import type {MDXFrontMatter} from './frontMatter'; import type {MDXFrontMatter} from './frontMatter';
import type {Options} from './options'; import type {Options} from './options';
import type {AdmonitionOptions} from './remark/admonitions'; import type {AdmonitionOptions} from './remark/admonitions';
import type {PluginOptions as ResolveMarkdownLinksOptions} from './remark/resolveMarkdownLinks';
import type {PluginOptions as TransformLinksOptions} from './remark/transformLinks';
import type {PluginOptions as TransformImageOptions} from './remark/transformImage';
import type {ProcessorOptions} from '@mdx-js/mdx'; import type {ProcessorOptions} from '@mdx-js/mdx';
// TODO as of April 2023, no way to import/re-export this ESM type easily :/ // TODO as of April 2023, no way to import/re-export this ESM type easily :/
@ -92,7 +95,7 @@ async function createProcessorFactory() {
headings, headings,
{anchorsMaintainCase: options.markdownConfig.anchors.maintainCase}, {anchorsMaintainCase: options.markdownConfig.anchors.maintainCase},
], ],
emoji, ...(options.markdownConfig.emoji ? [emoji] : []),
toc, toc,
]; ];
} }
@ -121,13 +124,19 @@ async function createProcessorFactory() {
{ {
staticDirs: options.staticDirs, staticDirs: options.staticDirs,
siteDir: options.siteDir, siteDir: options.siteDir,
}, onBrokenMarkdownImages:
options.markdownConfig.hooks.onBrokenMarkdownImages,
} satisfies TransformImageOptions,
], ],
// TODO merge this with transformLinks? // TODO merge this with transformLinks?
options.resolveMarkdownLink options.resolveMarkdownLink
? [ ? [
resolveMarkdownLinks, resolveMarkdownLinks,
{resolveMarkdownLink: options.resolveMarkdownLink}, {
resolveMarkdownLink: options.resolveMarkdownLink,
onBrokenMarkdownLinks:
options.markdownConfig.hooks.onBrokenMarkdownLinks,
} satisfies ResolveMarkdownLinksOptions,
] ]
: undefined, : undefined,
[ [
@ -135,7 +144,9 @@ async function createProcessorFactory() {
{ {
staticDirs: options.staticDirs, staticDirs: options.staticDirs,
siteDir: options.siteDir, siteDir: options.siteDir,
}, onBrokenMarkdownLinks:
options.markdownConfig.hooks.onBrokenMarkdownLinks,
} satisfies TransformLinksOptions,
], ],
gfm, gfm,
options.markdownConfig.mdx1Compat.comments ? comment : null, options.markdownConfig.mdx1Compat.comments ? comment : null,

View File

@ -5,22 +5,47 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {jest} from '@jest/globals';
import * as path from 'path';
import plugin from '..'; import plugin from '..';
import type {PluginOptions} from '../index'; import type {PluginOptions} from '../index';
async function process(content: string) { const siteDir = __dirname;
const {remark} = await import('remark');
const options: PluginOptions = { const DefaultTestOptions: PluginOptions = {
resolveMarkdownLink: ({linkPathname}) => `/RESOLVED---${linkPathname}`, resolveMarkdownLink: ({linkPathname}) => `/RESOLVED---${linkPathname}`,
onBrokenMarkdownLinks: 'throw',
};
async function process(content: string, optionsInput?: Partial<PluginOptions>) {
const options = {
...DefaultTestOptions,
...optionsInput,
}; };
const result = await remark().use(plugin, options).process(content); const {remark} = await import('remark');
const result = await remark()
.use(plugin, options)
.process({
value: content,
path: path.posix.join(siteDir, 'docs', 'myFile.mdx'),
});
return result.value; return result.value;
} }
describe('resolveMarkdownLinks remark plugin', () => { describe('resolveMarkdownLinks remark plugin', () => {
it('accepts non-md link', async () => {
/* language=markdown */
const content = `[link1](link1)`;
const result = await process(content);
expect(result).toMatchInlineSnapshot(`
"[link1](link1)
"
`);
});
it('resolves Markdown and MDX links', async () => { it('resolves Markdown and MDX links', async () => {
/* language=markdown */ /* language=markdown */
const content = `[link1](link1.mdx) const content = `[link1](link1.mdx)
@ -157,4 +182,212 @@ this is a code block
" "
`); `);
}); });
describe('onBrokenMarkdownLinks', () => {
const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {});
beforeEach(() => {
warnMock.mockClear();
});
async function processResolutionErrors(
content: string,
onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'] = 'throw',
) {
return process(content, {
resolveMarkdownLink: () => null,
onBrokenMarkdownLinks,
});
}
describe('throws', () => {
it('for unresolvable mdx link', async () => {
/* language=markdown */
const content = `[link1](link1.mdx)`;
await expect(() => processResolutionErrors(content)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown link with URL \`link1.mdx\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (1:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs."
`);
});
it('for unresolvable md link', async () => {
/* language=markdown */
const content = `[link1](link1.md)`;
await expect(() => processResolutionErrors(content)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown link with URL \`link1.md\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (1:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs."
`);
});
});
describe('warns', () => {
it('for unresolvable md and mdx link', async () => {
/* language=markdown */
const content = `
[link1](link1.mdx)
[link2](link2)
[link3](dir/link3.md)
[link 4](/link/4)
`;
const result = await processResolutionErrors(content, 'warn');
expect(result).toMatchInlineSnapshot(`
"[link1](link1.mdx)
[link2](link2)
[link3](dir/link3.md)
[link 4](/link/4)
"
`);
expect(warnMock).toHaveBeenCalledTimes(2);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown link with URL \`link1.mdx\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (2:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.",
],
[
"[WARNING] Markdown link with URL \`dir/link3.md\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (6:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.",
],
]
`);
});
it('for unresolvable md and mdx link - with recovery', async () => {
/* language=markdown */
const content = `
[link1](link1.mdx)
[link2](link2)
[link3](dir/link3.md?query#hash)
[link 4](/link/4)
`;
const result = await processResolutionErrors(content, (params) => {
console.warn(`onBrokenMarkdownLinks called with`, params);
// We can alter the AST Node
params.node.title = 'fixed link title';
params.node.url = 'ignored, less important than returned value';
// Or return a new URL
return `/recovered-link`;
});
expect(result).toMatchInlineSnapshot(`
"[link1](/recovered-link "fixed link title")
[link2](link2)
[link3](/recovered-link "fixed link title")
[link 4](/link/4)
"
`);
expect(warnMock).toHaveBeenCalledTimes(2);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownLinks called with",
{
"node": {
"children": [
{
"position": {
"end": {
"column": 7,
"line": 2,
"offset": 7,
},
"start": {
"column": 2,
"line": 2,
"offset": 2,
},
},
"type": "text",
"value": "link1",
},
],
"position": {
"end": {
"column": 19,
"line": 2,
"offset": 19,
},
"start": {
"column": 1,
"line": 2,
"offset": 1,
},
},
"title": "fixed link title",
"type": "link",
"url": "/recovered-link",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx",
"url": "link1.mdx",
},
],
[
"onBrokenMarkdownLinks called with",
{
"node": {
"children": [
{
"position": {
"end": {
"column": 7,
"line": 6,
"offset": 43,
},
"start": {
"column": 2,
"line": 6,
"offset": 38,
},
},
"type": "text",
"value": "link3",
},
],
"position": {
"end": {
"column": 33,
"line": 6,
"offset": 69,
},
"start": {
"column": 1,
"line": 6,
"offset": 37,
},
},
"title": "fixed link title",
"type": "link",
"url": "/recovered-link",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx",
"url": "dir/link3.md?query#hash",
},
],
]
`);
});
});
});
}); });

View File

@ -8,11 +8,18 @@
import { import {
parseLocalURLPath, parseLocalURLPath,
serializeURLPath, serializeURLPath,
toMessageRelativeFilePath,
type URLPath, type URLPath,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import logger from '@docusaurus/logger';
import {formatNodePositionExtraMessage} from '../utils';
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
import type {Definition, Link, Root} from 'mdast'; import type {Definition, Link, Root} from 'mdast';
import type {
MarkdownConfig,
OnBrokenMarkdownLinksFunction,
} from '@docusaurus/types';
type ResolveMarkdownLinkParams = { type ResolveMarkdownLinkParams = {
/** /**
@ -32,6 +39,33 @@ export type ResolveMarkdownLink = (
export interface PluginOptions { export interface PluginOptions {
resolveMarkdownLink: ResolveMarkdownLink; resolveMarkdownLink: ResolveMarkdownLink;
onBrokenMarkdownLinks: MarkdownConfig['hooks']['onBrokenMarkdownLinks'];
}
function asFunction(
onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'],
): OnBrokenMarkdownLinksFunction {
if (typeof onBrokenMarkdownLinks === 'string') {
const extraHelp =
onBrokenMarkdownLinks === 'throw'
? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} option, or apply the code=${'pathname://'} protocol to the broken link URLs.`
: '';
return ({sourceFilePath, url: linkUrl, node}) => {
const relativePath = toMessageRelativeFilePath(sourceFilePath);
logger.report(
onBrokenMarkdownLinks,
)`Markdown link with URL code=${linkUrl} in source file path=${relativePath}${formatNodePositionExtraMessage(
node,
)} couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.${extraHelp}`;
};
} else {
return (params) =>
onBrokenMarkdownLinks({
...params,
sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath),
});
}
} }
const HAS_MARKDOWN_EXTENSION = /\.mdx?$/i; const HAS_MARKDOWN_EXTENSION = /\.mdx?$/i;
@ -57,10 +91,15 @@ function parseMarkdownLinkURLPath(link: string): URLPath | null {
* This is exposed as "data.contentTitle" to the processed vfile * This is exposed as "data.contentTitle" to the processed vfile
* Also gives the ability to strip that content title (used for the blog plugin) * Also gives the ability to strip that content title (used for the blog plugin)
*/ */
// TODO merge this plugin with "transformLinks"
// in general we'd want to avoid traversing multiple times the same AST
const plugin: Plugin<PluginOptions[], Root> = function plugin( const plugin: Plugin<PluginOptions[], Root> = function plugin(
options, options,
): Transformer<Root> { ): Transformer<Root> {
const {resolveMarkdownLink} = options; const {resolveMarkdownLink} = options;
const onBrokenMarkdownLinks = asFunction(options.onBrokenMarkdownLinks);
return async (root, file) => { return async (root, file) => {
const {visit} = await import('unist-util-visit'); const {visit} = await import('unist-util-visit');
@ -71,18 +110,26 @@ const plugin: Plugin<PluginOptions[], Root> = function plugin(
return; return;
} }
const sourceFilePath = file.path;
const permalink = resolveMarkdownLink({ const permalink = resolveMarkdownLink({
sourceFilePath: file.path, sourceFilePath,
linkPathname: linkURLPath.pathname, linkPathname: linkURLPath.pathname,
}); });
if (permalink) { if (permalink) {
// This reapplies the link ?qs#hash part to the resolved pathname // This reapplies the link ?qs#hash part to the resolved pathname
const resolvedUrl = serializeURLPath({ link.url = serializeURLPath({
...linkURLPath, ...linkURLPath,
pathname: permalink, pathname: permalink,
}); });
link.url = resolvedUrl; } else {
link.url =
onBrokenMarkdownLinks({
url: link.url,
sourceFilePath,
node: link,
}) ?? link.url;
} }
}); });
}; };

View File

@ -1 +0,0 @@
![img](/img/doesNotExist.png)

View File

@ -1 +0,0 @@
![img](./notFound.png)

View File

@ -1 +0,0 @@
![invalid image](/invalid.png)

View File

@ -1 +0,0 @@
![img](pathname:///img/unchecked.png)

View File

@ -1,16 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transformImage plugin does not choke on invalid image 1`] = ` exports[`transformImage plugin does not choke on invalid image 1`] = `
"<img alt="invalid image" src={require("!<PROJECT_ROOT>/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js!./static/invalid.png").default} /> "<img alt="invalid image" src={require("!<PROJECT_ROOT>/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js!./../static/invalid.png").default} />
" "
`; `;
exports[`transformImage plugin fail if image does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static/img/doesNotExist.png or packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static2/img/doesNotExist.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md not found."`;
exports[`transformImage plugin fail if image relative path does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/notFound.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md not found."`;
exports[`transformImage plugin fail if image url is absent 1`] = `"Markdown image URL is mandatory in "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md" file"`;
exports[`transformImage plugin pathname protocol 1`] = ` exports[`transformImage plugin pathname protocol 1`] = `
"![img](/img/unchecked.png) "![img](/img/unchecked.png)
" "

View File

@ -6,65 +6,361 @@
*/ */
import {jest} from '@jest/globals'; import {jest} from '@jest/globals';
import path from 'path'; import * as path from 'path';
import vfile from 'to-vfile'; import vfile from 'to-vfile';
import plugin, {type PluginOptions} from '../index'; import plugin, {type PluginOptions} from '../index';
const processFixture = async ( const siteDir = path.join(__dirname, '__fixtures__');
name: string,
options: Partial<PluginOptions>,
) => {
const {remark} = await import('remark');
const {default: mdx} = await import('remark-mdx');
const filePath = path.join(__dirname, `__fixtures__/${name}.md`);
const file = await vfile.read(filePath);
const result = await remark()
.use(mdx)
.use(plugin, {siteDir: __dirname, staticDirs: [], ...options})
.process(file);
return result.value;
};
const staticDirs = [ const staticDirs = [
path.join(__dirname, '__fixtures__/static'), path.join(__dirname, '__fixtures__/static'),
path.join(__dirname, '__fixtures__/static2'), path.join(__dirname, '__fixtures__/static2'),
]; ];
const siteDir = path.join(__dirname, '__fixtures__'); const getProcessor = async (options?: Partial<PluginOptions>) => {
const {remark} = await import('remark');
const {default: mdx} = await import('remark-mdx');
return remark()
.use(mdx)
.use(plugin, {
siteDir,
staticDirs,
onBrokenMarkdownImages: 'throw',
...options,
});
};
const processFixture = async (
name: string,
options?: Partial<PluginOptions>,
) => {
const filePath = path.join(__dirname, `__fixtures__/${name}.md`);
const file = await vfile.read(filePath);
const processor = await getProcessor(options);
const result = await processor.process(file);
return result.value;
};
const processContent = async (
content: string,
options?: Partial<PluginOptions>,
) => {
const processor = await getProcessor(options);
const result = await processor.process({
value: content,
path: path.posix.join(siteDir, 'docs', 'myFile.mdx'),
});
return result.value.toString();
};
describe('transformImage plugin', () => { describe('transformImage plugin', () => {
it('fail if image does not exist', async () => {
await expect(
processFixture('fail', {staticDirs}),
).rejects.toThrowErrorMatchingSnapshot();
});
it('fail if image relative path does not exist', async () => {
await expect(
processFixture('fail2', {staticDirs}),
).rejects.toThrowErrorMatchingSnapshot();
});
it('fail if image url is absent', async () => {
await expect(
processFixture('noUrl', {staticDirs}),
).rejects.toThrowErrorMatchingSnapshot();
});
it('transform md images to <img />', async () => { it('transform md images to <img />', async () => {
const result = await processFixture('img', {staticDirs, siteDir}); // TODO split that large fixture into many smaller test cases?
const result = await processFixture('img');
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
it('pathname protocol', async () => { it('pathname protocol', async () => {
const result = await processFixture('pathname', {staticDirs}); const result = await processContent(
`![img](pathname:///img/unchecked.png)`,
);
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
it('does not choke on invalid image', async () => { it('does not choke on invalid image', async () => {
const errorMock = jest.spyOn(console, 'warn').mockImplementation(() => {}); const errorMock = jest.spyOn(console, 'warn').mockImplementation(() => {});
const result = await processFixture('invalid-img', {staticDirs}); const result = await processContent(`![invalid image](/invalid.png)`);
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
expect(errorMock).toHaveBeenCalledTimes(1); expect(errorMock).toHaveBeenCalledTimes(1);
}); });
describe('onBrokenMarkdownImages', () => {
const fixtures = {
doesNotExistAbsolute: `![img](/img/doesNotExist.png)`,
doesNotExistRelative: `![img](./doesNotExist.png)`,
doesNotExistSiteAlias: `![img](@site/doesNotExist.png)`,
urlEmpty: `![img]()`,
};
describe('throws', () => {
it('if image absolute path does not exist', async () => {
await expect(processContent(fixtures.doesNotExistAbsolute)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown image with URL \`/img/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs."
`);
});
it('if image relative path does not exist', async () => {
await expect(processContent(fixtures.doesNotExistRelative)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown image with URL \`./doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs."
`);
});
it('if image @site path does not exist', async () => {
await expect(processContent(fixtures.doesNotExistSiteAlias)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown image with URL \`@site/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs."
`);
});
it('if image url empty', async () => {
await expect(processContent(fixtures.urlEmpty)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown image with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1).
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs."
`);
});
});
describe('warns', () => {
function processWarn(content: string) {
return processContent(content, {onBrokenMarkdownImages: 'warn'});
}
const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {});
beforeEach(() => {
warnMock.mockClear();
});
it('if image absolute path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistAbsolute);
expect(result).toMatchInlineSnapshot(`
"![img](/img/doesNotExist.png)
"
`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown image with URL \`/img/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.",
],
]
`);
});
it('if image relative path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistRelative);
expect(result).toMatchInlineSnapshot(`
"![img](./doesNotExist.png)
"
`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown image with URL \`./doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.",
],
]
`);
});
it('if image @site path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistSiteAlias);
expect(result).toMatchInlineSnapshot(`
"![img](@site/doesNotExist.png)
"
`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown image with URL \`@site/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.",
],
]
`);
});
it('if image url empty', async () => {
const result = await processWarn(fixtures.urlEmpty);
expect(result).toMatchInlineSnapshot(`
"![img]()
"
`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown image with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1).",
],
]
`);
});
});
describe('function form', () => {
function processWarn(content: string) {
return processContent(content, {
onBrokenMarkdownImages: (params) => {
console.log('onBrokenMarkdownImages called for ', params);
// We can alter the AST Node
params.node.alt = 'new 404 alt';
params.node.url = 'ignored, less important than returned value';
// Or return a new URL
return '/404.png';
},
});
}
const logMock = jest.spyOn(console, 'log').mockImplementation(() => {});
beforeEach(() => {
logMock.mockClear();
});
it('if image absolute path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistAbsolute);
expect(result).toMatchInlineSnapshot(`
"![new 404 alt](/404.png)
"
`);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownImages called for ",
{
"node": {
"alt": "new 404 alt",
"position": {
"end": {
"column": 30,
"line": 1,
"offset": 29,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": null,
"type": "image",
"url": "/404.png",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx",
"url": "/img/doesNotExist.png",
},
],
]
`);
});
it('if image relative path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistRelative);
expect(result).toMatchInlineSnapshot(`
"![new 404 alt](/404.png)
"
`);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownImages called for ",
{
"node": {
"alt": "new 404 alt",
"position": {
"end": {
"column": 27,
"line": 1,
"offset": 26,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": null,
"type": "image",
"url": "/404.png",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx",
"url": "./doesNotExist.png",
},
],
]
`);
});
it('if image @site path does not exist', async () => {
const result = await processWarn(fixtures.doesNotExistSiteAlias);
expect(result).toMatchInlineSnapshot(`
"![new 404 alt](/404.png)
"
`);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownImages called for ",
{
"node": {
"alt": "new 404 alt",
"position": {
"end": {
"column": 31,
"line": 1,
"offset": 30,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": null,
"type": "image",
"url": "/404.png",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx",
"url": "@site/doesNotExist.png",
},
],
]
`);
});
it('if image url empty', async () => {
const result = await processWarn(fixtures.urlEmpty);
expect(result).toMatchInlineSnapshot(`
"![new 404 alt](/404.png)
"
`);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownImages called for ",
{
"node": {
"alt": "new 404 alt",
"position": {
"end": {
"column": 9,
"line": 1,
"offset": 8,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": null,
"type": "image",
"url": "/404.png",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx",
"url": "",
},
],
]
`);
});
});
});
}); });

View File

@ -6,7 +6,6 @@
*/ */
import path from 'path'; import path from 'path';
import url from 'url';
import fs from 'fs-extra'; import fs from 'fs-extra';
import { import {
toMessageRelativeFilePath, toMessageRelativeFilePath,
@ -15,26 +14,72 @@ import {
findAsyncSequential, findAsyncSequential,
getFileLoaderUtils, getFileLoaderUtils,
parseURLOrPath, parseURLOrPath,
parseLocalURLPath,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import {imageSizeFromFile} from 'image-size/fromFile'; import {imageSizeFromFile} from 'image-size/fromFile';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {assetRequireAttributeValue, transformNode} from '../utils'; import {
assetRequireAttributeValue,
formatNodePositionExtraMessage,
transformNode,
} from '../utils';
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
import type {MdxJsxTextElement} from 'mdast-util-mdx'; import type {MdxJsxTextElement} from 'mdast-util-mdx';
import type {Image, Root} from 'mdast'; import type {Image, Root} from 'mdast';
import type {Parent} from 'unist'; import type {Parent} from 'unist';
import type {
MarkdownConfig,
OnBrokenMarkdownImagesFunction,
} from '@docusaurus/types';
type PluginOptions = { export type PluginOptions = {
staticDirs: string[]; staticDirs: string[];
siteDir: string; siteDir: string;
onBrokenMarkdownImages: MarkdownConfig['hooks']['onBrokenMarkdownImages'];
}; };
type Context = PluginOptions & { type Context = {
staticDirs: PluginOptions['staticDirs'];
siteDir: PluginOptions['siteDir'];
onBrokenMarkdownImages: OnBrokenMarkdownImagesFunction;
filePath: string; filePath: string;
inlineMarkdownImageFileLoader: string; inlineMarkdownImageFileLoader: string;
}; };
function asFunction(
onBrokenMarkdownImages: PluginOptions['onBrokenMarkdownImages'],
): OnBrokenMarkdownImagesFunction {
if (typeof onBrokenMarkdownImages === 'string') {
const extraHelp =
onBrokenMarkdownImages === 'throw'
? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownImages'} option, or apply the code=${'pathname://'} protocol to the broken image URLs.`
: '';
return ({sourceFilePath, url: imageUrl, node}) => {
const relativePath = toMessageRelativeFilePath(sourceFilePath);
if (imageUrl) {
logger.report(
onBrokenMarkdownImages,
)`Markdown image with URL code=${imageUrl} in source file path=${relativePath}${formatNodePositionExtraMessage(
node,
)} couldn't be resolved to an existing local image file.${extraHelp}`;
} else {
logger.report(
onBrokenMarkdownImages,
)`Markdown image with empty URL found in source file path=${relativePath}${formatNodePositionExtraMessage(
node,
)}.${extraHelp}`;
}
};
} else {
return (params) =>
onBrokenMarkdownImages({
...params,
sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath),
});
}
}
type Target = [node: Image, index: number, parent: Parent]; type Target = [node: Image, index: number, parent: Parent];
async function toImageRequireNode( async function toImageRequireNode(
@ -51,7 +96,7 @@ async function toImageRequireNode(
); );
relativeImagePath = `./${relativeImagePath}`; relativeImagePath = `./${relativeImagePath}`;
const parsedUrl = parseURLOrPath(node.url, 'https://example.com'); const parsedUrl = parseURLOrPath(node.url);
const hash = parsedUrl.hash ?? ''; const hash = parsedUrl.hash ?? '';
const search = parsedUrl.search ?? ''; const search = parsedUrl.search ?? '';
const requireString = `${context.inlineMarkdownImageFileLoader}${ const requireString = `${context.inlineMarkdownImageFileLoader}${
@ -113,64 +158,60 @@ ${(err as Error).message}`;
}); });
} }
async function ensureImageFileExist(imagePath: string, sourceFilePath: string) { async function getLocalImageAbsolutePath(
const imageExists = await fs.pathExists(imagePath); originalImagePath: string,
if (!imageExists) {
throw new Error(
`Image ${toMessageRelativeFilePath(
imagePath,
)} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
);
}
}
async function getImageAbsolutePath(
imagePath: string,
{siteDir, filePath, staticDirs}: Context, {siteDir, filePath, staticDirs}: Context,
) { ) {
if (imagePath.startsWith('@site/')) { if (originalImagePath.startsWith('@site/')) {
const imageFilePath = path.join(siteDir, imagePath.replace('@site/', '')); const imageFilePath = path.join(
await ensureImageFileExist(imageFilePath, filePath); siteDir,
originalImagePath.replace('@site/', ''),
);
if (!(await fs.pathExists(imageFilePath))) {
return null;
}
return imageFilePath; return imageFilePath;
} else if (path.isAbsolute(imagePath)) { } else if (path.isAbsolute(originalImagePath)) {
// Absolute paths are expected to exist in the static folder. // Absolute paths are expected to exist in the static folder.
const possiblePaths = staticDirs.map((dir) => path.join(dir, imagePath)); const possiblePaths = staticDirs.map((dir) =>
path.join(dir, originalImagePath),
);
const imageFilePath = await findAsyncSequential( const imageFilePath = await findAsyncSequential(
possiblePaths, possiblePaths,
fs.pathExists, fs.pathExists,
); );
if (!imageFilePath) { if (!imageFilePath) {
throw new Error( return null;
`Image ${possiblePaths }
.map((p) => toMessageRelativeFilePath(p)) return imageFilePath;
.join(' or ')} used in ${toMessageRelativeFilePath( } else {
filePath, // relative paths are resolved against the source file's folder
)} not found.`, const imageFilePath = path.join(path.dirname(filePath), originalImagePath);
); if (!(await fs.pathExists(imageFilePath))) {
return null;
} }
return imageFilePath; return imageFilePath;
} }
// relative paths are resolved against the source file's folder
const imageFilePath = path.join(path.dirname(filePath), imagePath);
await ensureImageFileExist(imageFilePath, filePath);
return imageFilePath;
} }
async function processImageNode(target: Target, context: Context) { async function processImageNode(target: Target, context: Context) {
const [node] = target; const [node] = target;
if (!node.url) { if (!node.url) {
throw new Error( node.url =
`Markdown image URL is mandatory in "${toMessageRelativeFilePath( context.onBrokenMarkdownImages({
context.filePath, url: node.url,
)}" file`, sourceFilePath: context.filePath,
); node,
}) ?? node.url;
return;
} }
const parsedUrl = url.parse(node.url); const localUrlPath = parseLocalURLPath(node.url);
if (parsedUrl.protocol || !parsedUrl.pathname) { if (!localUrlPath) {
// pathname:// is an escape hatch, in case user does not want her images to // pathname:// is an escape hatch, in case the user does not want images to
// be converted to require calls going through webpack loader // be converted to require calls going through webpack loader
if (parsedUrl.protocol === 'pathname:') { if (parseURLOrPath(node.url).protocol === 'pathname:') {
node.url = node.url.replace('pathname://', ''); node.url = node.url.replace('pathname://', '');
} }
return; return;
@ -179,17 +220,31 @@ async function processImageNode(target: Target, context: Context) {
// We decode it first because Node Url.pathname is always encoded // We decode it first because Node Url.pathname is always encoded
// while the image file-system path are not. // while the image file-system path are not.
// See https://github.com/facebook/docusaurus/discussions/10720 // See https://github.com/facebook/docusaurus/discussions/10720
const decodedPathname = decodeURIComponent(parsedUrl.pathname); const decodedPathname = decodeURIComponent(localUrlPath.pathname);
// We try to convert image urls without protocol to images with require calls // We try to convert image urls without protocol to images with require calls
// going through webpack ensures that image assets exist at build time // going through webpack ensures that image assets exist at build time
const imagePath = await getImageAbsolutePath(decodedPathname, context); const localImagePath = await getLocalImageAbsolutePath(
await toImageRequireNode(target, imagePath, context); decodedPathname,
context,
);
if (localImagePath === null) {
node.url =
context.onBrokenMarkdownImages({
url: node.url,
sourceFilePath: context.filePath,
node,
}) ?? node.url;
} else {
await toImageRequireNode(target, localImagePath, context);
}
} }
const plugin: Plugin<PluginOptions[], Root> = function plugin( const plugin: Plugin<PluginOptions[], Root> = function plugin(
options, options,
): Transformer<Root> { ): Transformer<Root> {
const onBrokenMarkdownImages = asFunction(options.onBrokenMarkdownImages);
return async (root, vfile) => { return async (root, vfile) => {
const {visit} = await import('unist-util-visit'); const {visit} = await import('unist-util-visit');
@ -201,6 +256,7 @@ const plugin: Plugin<PluginOptions[], Root> = function plugin(
filePath: vfile.path!, filePath: vfile.path!,
inlineMarkdownImageFileLoader: inlineMarkdownImageFileLoader:
fileLoaderUtils.loaders.inlineMarkdownImageFileLoader, fileLoaderUtils.loaders.inlineMarkdownImageFileLoader,
onBrokenMarkdownImages,
}; };
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];

View File

@ -1 +0,0 @@
[asset](pathname:///asset/unchecked.pdf)

View File

@ -1,15 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transformAsset plugin fail if asset url is absent 1`] = `"Markdown link URL is mandatory in "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md" file (title: asset, line: 1)."`; exports[`transformLinks plugin transform md links to <a /> 1`] = `
exports[`transformAsset plugin fail if asset with site alias does not exist 1`] = `"Asset packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/foo.pdf used in packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md not found."`;
exports[`transformAsset plugin pathname protocol 1`] = `
"[asset](pathname:///asset/unchecked.pdf)
"
`;
exports[`transformAsset plugin transform md links to <a /> 1`] = `
"[asset](https://example.com/asset.pdf) "[asset](https://example.com/asset.pdf)
<a target="_blank" data-noBrokenLinkCheck={true} href={require("!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} /> <a target="_blank" data-noBrokenLinkCheck={true} href={require("!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} />
@ -54,6 +45,5 @@ in paragraph <a target="_blank" data-noBrokenLinkCheck={true} href={require("!<P
<a target="_blank" data-noBrokenLinkCheck={true} href={require("./data.raw!=!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./data.json").default}>JSON</a> <a target="_blank" data-noBrokenLinkCheck={true} href={require("./data.raw!=!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./data.json").default}>JSON</a>
<a target="_blank" data-noBrokenLinkCheck={true} href={require("./static/static-json.raw!=!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON</a> <a target="_blank" data-noBrokenLinkCheck={true} href={require("./static/static-json.raw!=!<PROJECT_ROOT>/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON</a>"
"
`; `;

View File

@ -5,53 +5,270 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import path from 'path'; import {jest} from '@jest/globals';
import * as path from 'path';
import vfile from 'to-vfile'; import vfile from 'to-vfile';
import plugin from '..'; import plugin, {type PluginOptions} from '..';
import transformImage, {type PluginOptions} from '../../transformImage'; import transformImage from '../../transformImage';
const processFixture = async (name: string, options?: PluginOptions) => { const siteDir = path.join(__dirname, `__fixtures__`);
const staticDirs = [
path.join(siteDir, 'static'),
path.join(siteDir, 'static2'),
];
const getProcessor = async (options?: Partial<PluginOptions>) => {
const {remark} = await import('remark'); const {remark} = await import('remark');
const {default: mdx} = await import('remark-mdx'); const {default: mdx} = await import('remark-mdx');
const siteDir = path.join(__dirname, `__fixtures__`); return remark()
const staticDirs = [
path.join(siteDir, 'static'),
path.join(siteDir, 'static2'),
];
const file = await vfile.read(path.join(siteDir, `${name}.md`));
const result = await remark()
.use(mdx) .use(mdx)
.use(transformImage, {...options, siteDir, staticDirs}) .use(transformImage, {
.use(plugin, { siteDir,
...options,
staticDirs, staticDirs,
siteDir: path.join(__dirname, '__fixtures__'), onBrokenMarkdownImages: 'throw',
}) })
.process(file); .use(plugin, {
staticDirs,
return result.value; siteDir,
onBrokenMarkdownLinks: 'throw',
...options,
});
}; };
describe('transformAsset plugin', () => { const processFixture = async (
it('fail if asset url is absent', async () => { name: string,
await expect( options?: Partial<PluginOptions>,
processFixture('noUrl'), ) => {
).rejects.toThrowErrorMatchingSnapshot(); const processor = await getProcessor(options);
}); const file = await vfile.read(path.join(siteDir, `${name}.md`));
const result = await processor.process(file);
return result.value.toString().trim();
};
it('fail if asset with site alias does not exist', async () => { const processContent = async (
await expect( content: string,
processFixture('nonexistentSiteAlias'), options?: Partial<PluginOptions>,
).rejects.toThrowErrorMatchingSnapshot(); ) => {
const processor = await getProcessor(options);
const result = await processor.process({
value: content,
path: path.posix.join(siteDir, 'docs', 'myFile.mdx'),
}); });
return result.value.toString().trim();
};
describe('transformLinks plugin', () => {
it('transform md links to <a />', async () => { it('transform md links to <a />', async () => {
// TODO split fixture in many smaller test cases
const result = await processFixture('asset'); const result = await processFixture('asset');
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
it('pathname protocol', async () => { it('pathname protocol', async () => {
const result = await processFixture('pathname'); const result = await processContent(`pathname:///unchecked.pdf)`);
expect(result).toMatchSnapshot(); expect(result).toMatchInlineSnapshot(`"pathname:///unchecked.pdf)"`);
});
it('accepts absolute file that does not exist', async () => {
const result = await processContent(`[file](/dir/file.zip)`);
expect(result).toMatchInlineSnapshot(`"[file](/dir/file.zip)"`);
});
it('accepts relative file that does not exist', async () => {
const result = await processContent(`[file](dir/file.zip)`);
expect(result).toMatchInlineSnapshot(`"[file](dir/file.zip)"`);
});
describe('onBrokenMarkdownLinks', () => {
const fixtures = {
urlEmpty: `[empty]()`,
fileDoesNotExistSiteAlias: `[file](@site/file.zip)`,
};
describe('throws', () => {
it('if url is empty', async () => {
await expect(processContent(fixtures.urlEmpty)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown link with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1).
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs."
`);
});
it('if file with site alias does not exist', async () => {
await expect(processContent(fixtures.fileDoesNotExistSiteAlias)).rejects
.toThrowErrorMatchingInlineSnapshot(`
"Markdown link with URL \`@site/file.zip\` in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.
To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs."
`);
});
});
describe('warns', () => {
function processWarn(content: string) {
return processContent(content, {onBrokenMarkdownLinks: 'warn'});
}
const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {});
beforeEach(() => {
warnMock.mockClear();
});
it('if url is empty', async () => {
const result = await processWarn(fixtures.urlEmpty);
expect(result).toMatchInlineSnapshot(`"[empty]()"`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown link with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1).",
],
]
`);
});
it('if file with site alias does not exist', async () => {
const result = await processWarn(fixtures.fileDoesNotExistSiteAlias);
expect(result).toMatchInlineSnapshot(`"[file](@site/file.zip)"`);
expect(warnMock).toHaveBeenCalledTimes(1);
expect(warnMock.mock.calls).toMatchInlineSnapshot(`
[
[
"[WARNING] Markdown link with URL \`@site/file.zip\` in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.",
],
]
`);
});
});
describe('function form', () => {
function processWarn(content: string) {
return processContent(content, {
onBrokenMarkdownLinks: (params) => {
console.log('onBrokenMarkdownLinks called with', params);
// We can alter the AST Node
params.node.title = 'fixed link title';
params.node.url = 'ignored, less important than returned value';
// Or return a new URL
return '/404';
},
});
}
const logMock = jest.spyOn(console, 'log').mockImplementation(() => {});
beforeEach(() => {
logMock.mockClear();
});
it('if url is empty', async () => {
const result = await processWarn(fixtures.urlEmpty);
expect(result).toMatchInlineSnapshot(
`"[empty](/404 "fixed link title")"`,
);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownLinks called with",
{
"node": {
"children": [
{
"position": {
"end": {
"column": 7,
"line": 1,
"offset": 6,
},
"start": {
"column": 2,
"line": 1,
"offset": 1,
},
},
"type": "text",
"value": "empty",
},
],
"position": {
"end": {
"column": 10,
"line": 1,
"offset": 9,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": "fixed link title",
"type": "link",
"url": "/404",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx",
"url": "",
},
],
]
`);
});
it('if file with site alias does not exist', async () => {
const result = await processWarn(fixtures.fileDoesNotExistSiteAlias);
expect(result).toMatchInlineSnapshot(
`"[file](/404 "fixed link title")"`,
);
expect(logMock).toHaveBeenCalledTimes(1);
expect(logMock.mock.calls).toMatchInlineSnapshot(`
[
[
"onBrokenMarkdownLinks called with",
{
"node": {
"children": [
{
"position": {
"end": {
"column": 6,
"line": 1,
"offset": 5,
},
"start": {
"column": 2,
"line": 1,
"offset": 1,
},
},
"type": "text",
"value": "file",
},
],
"position": {
"end": {
"column": 23,
"line": 1,
"offset": 22,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"title": "fixed link title",
"type": "link",
"url": "/404",
},
"sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx",
"url": "@site/file.zip",
},
],
]
`);
});
});
}); });
}); });

View File

@ -6,7 +6,6 @@
*/ */
import path from 'path'; import path from 'path';
import url from 'url';
import fs from 'fs-extra'; import fs from 'fs-extra';
import { import {
toMessageRelativeFilePath, toMessageRelativeFilePath,
@ -15,26 +14,75 @@ import {
findAsyncSequential, findAsyncSequential,
getFileLoaderUtils, getFileLoaderUtils,
parseURLOrPath, parseURLOrPath,
parseLocalURLPath,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import {assetRequireAttributeValue, transformNode} from '../utils'; import logger from '@docusaurus/logger';
import {
assetRequireAttributeValue,
formatNodePositionExtraMessage,
transformNode,
} from '../utils';
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
import type {MdxJsxTextElement} from 'mdast-util-mdx'; import type {MdxJsxTextElement} from 'mdast-util-mdx';
import type {Parent} from 'unist'; import type {Parent} from 'unist';
import type {Link, Literal, Root} from 'mdast'; import type {Link, Root} from 'mdast';
import type {
MarkdownConfig,
OnBrokenMarkdownLinksFunction,
} from '@docusaurus/types';
type PluginOptions = { export type PluginOptions = {
staticDirs: string[]; staticDirs: string[];
siteDir: string; siteDir: string;
onBrokenMarkdownLinks: MarkdownConfig['hooks']['onBrokenMarkdownLinks'];
}; };
type Context = PluginOptions & { type Context = PluginOptions & {
staticDirs: string[];
siteDir: string;
onBrokenMarkdownLinks: OnBrokenMarkdownLinksFunction;
filePath: string; filePath: string;
inlineMarkdownLinkFileLoader: string; inlineMarkdownLinkFileLoader: string;
}; };
type Target = [node: Link, index: number, parent: Parent]; type Target = [node: Link, index: number, parent: Parent];
function asFunction(
onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'],
): OnBrokenMarkdownLinksFunction {
if (typeof onBrokenMarkdownLinks === 'string') {
const extraHelp =
onBrokenMarkdownLinks === 'throw'
? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} option, or apply the code=${'pathname://'} protocol to the broken link URLs.`
: '';
return ({sourceFilePath, url: linkUrl, node}) => {
const relativePath = toMessageRelativeFilePath(sourceFilePath);
if (linkUrl) {
logger.report(
onBrokenMarkdownLinks,
)`Markdown link with URL code=${linkUrl} in source file path=${relativePath}${formatNodePositionExtraMessage(
node,
)} couldn't be resolved.
Make sure it references a local Markdown file that exists within the current plugin.${extraHelp}`;
} else {
logger.report(
onBrokenMarkdownLinks,
)`Markdown link with empty URL found in source file path=${relativePath}${formatNodePositionExtraMessage(
node,
)}.${extraHelp}`;
}
};
} else {
return (params) =>
onBrokenMarkdownLinks({
...params,
sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath),
});
}
}
/** /**
* Transforms the link node to a JSX `<a>` element with a `require()` call. * Transforms the link node to a JSX `<a>` element with a `require()` call.
*/ */
@ -123,27 +171,15 @@ async function toAssetRequireNode(
}); });
} }
async function ensureAssetFileExist(assetPath: string, sourceFilePath: string) { async function getLocalFileAbsolutePath(
const assetExists = await fs.pathExists(assetPath);
if (!assetExists) {
throw new Error(
`Asset ${toMessageRelativeFilePath(
assetPath,
)} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
);
}
}
async function getAssetAbsolutePath(
assetPath: string, assetPath: string,
{siteDir, filePath, staticDirs}: Context, {siteDir, filePath, staticDirs}: Context,
) { ) {
if (assetPath.startsWith('@site/')) { if (assetPath.startsWith('@site/')) {
const assetFilePath = path.join(siteDir, assetPath.replace('@site/', '')); const assetFilePath = path.join(siteDir, assetPath.replace('@site/', ''));
// The @site alias is the only way to believe that the user wants an asset. if (await fs.pathExists(assetFilePath)) {
// Everything else can just be a link URL return assetFilePath;
await ensureAssetFileExist(assetFilePath, filePath); }
return assetFilePath;
} else if (path.isAbsolute(assetPath)) { } else if (path.isAbsolute(assetPath)) {
const assetFilePath = await findAsyncSequential( const assetFilePath = await findAsyncSequential(
staticDirs.map((dir) => path.join(dir, assetPath)), staticDirs.map((dir) => path.join(dir, assetPath)),
@ -164,54 +200,71 @@ async function getAssetAbsolutePath(
async function processLinkNode(target: Target, context: Context) { async function processLinkNode(target: Target, context: Context) {
const [node] = target; const [node] = target;
if (!node.url) { if (!node.url) {
// Try to improve error feedback node.url =
// see https://github.com/facebook/docusaurus/issues/3309#issuecomment-690371675 context.onBrokenMarkdownLinks({
const title = url: node.url,
node.title ?? (node.children[0] as Literal | undefined)?.value ?? '?'; sourceFilePath: context.filePath,
const line = node.position?.start.line ?? '?'; node,
throw new Error( }) ?? node.url;
`Markdown link URL is mandatory in "${toMessageRelativeFilePath( return;
context.filePath,
)}" file (title: ${title}, line: ${line}).`,
);
} }
const parsedUrl = url.parse(node.url); const localUrlPath = parseLocalURLPath(node.url);
if (parsedUrl.protocol || !parsedUrl.pathname) { if (!localUrlPath) {
// Don't process pathname:// here, it's used by the <Link> component // Don't process pathname:// here, it's used by the <Link> component
return; return;
} }
const hasSiteAlias = parsedUrl.pathname.startsWith('@site/');
const hasSiteAlias = localUrlPath.pathname.startsWith('@site/');
const hasAssetLikeExtension = const hasAssetLikeExtension =
path.extname(parsedUrl.pathname) && path.extname(localUrlPath.pathname) &&
!parsedUrl.pathname.match(/\.(?:mdx?|html)(?:#|$)/); !localUrlPath.pathname.match(/\.(?:mdx?|html)(?:#|$)/);
if (!hasSiteAlias && !hasAssetLikeExtension) { if (!hasSiteAlias && !hasAssetLikeExtension) {
return; return;
} }
const assetPath = await getAssetAbsolutePath( const localFilePath = await getLocalFileAbsolutePath(
decodeURIComponent(parsedUrl.pathname), decodeURIComponent(localUrlPath.pathname),
context, context,
); );
if (assetPath) {
await toAssetRequireNode(target, assetPath, context); if (localFilePath) {
await toAssetRequireNode(target, localFilePath, context);
} else {
// The @site alias is the only way to believe that the user wants an asset.
if (hasSiteAlias) {
node.url =
context.onBrokenMarkdownLinks({
url: node.url,
sourceFilePath: context.filePath,
node,
}) ?? node.url;
} else {
// Even if the url has a dot, and it looks like a file extension
// it can be risky to throw and fail fast by default
// It's perfectly valid for a route path segment to look like a filename
}
} }
} }
const plugin: Plugin<PluginOptions[], Root> = function plugin( const plugin: Plugin<PluginOptions[], Root> = function plugin(
options, options,
): Transformer<Root> { ): Transformer<Root> {
const onBrokenMarkdownLinks = asFunction(options.onBrokenMarkdownLinks);
return async (root, vfile) => { return async (root, vfile) => {
const {visit} = await import('unist-util-visit'); const {visit} = await import('unist-util-visit');
const fileLoaderUtils = getFileLoaderUtils( const fileLoaderUtils = getFileLoaderUtils(
vfile.data.compilerName === 'server', vfile.data.compilerName === 'server',
); );
const context: Context = { const context: Context = {
...options, ...options,
filePath: vfile.path!, filePath: vfile.path!,
inlineMarkdownLinkFileLoader: inlineMarkdownLinkFileLoader:
fileLoaderUtils.loaders.inlineMarkdownLinkFileLoader, fileLoaderUtils.loaders.inlineMarkdownLinkFileLoader,
onBrokenMarkdownLinks,
}; };
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];

View File

@ -8,7 +8,7 @@ import path from 'path';
import process from 'process'; import process from 'process';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {posixPath} from '@docusaurus/utils'; import {posixPath} from '@docusaurus/utils';
import {transformNode} from '../utils'; import {formatNodePositionExtraMessage, transformNode} from '../utils';
import type {Root} from 'mdast'; import type {Root} from 'mdast';
import type {Parent} from 'unist'; import type {Parent} from 'unist';
import type {Transformer, Processor, Plugin} from 'unified'; import type {Transformer, Processor, Plugin} from 'unified';
@ -39,17 +39,9 @@ function formatDirectiveName(directive: Directives) {
return `${prefix}${directive.name}`; return `${prefix}${directive.name}`;
} }
function formatDirectivePosition(directive: Directives): string | undefined {
return directive.position?.start
? logger.interpolate`number=${directive.position.start.line}:number=${directive.position.start.column}`
: undefined;
}
function formatUnusedDirectiveMessage(directive: Directives) { function formatUnusedDirectiveMessage(directive: Directives) {
const name = formatDirectiveName(directive); const name = formatDirectiveName(directive);
const position = formatDirectivePosition(directive); return `- ${name}${formatNodePositionExtraMessage(directive)}`;
return `- ${name} ${position ? `(${position})` : ''}`;
} }
function formatUnusedDirectivesMessage({ function formatUnusedDirectivesMessage({

View File

@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import logger from '@docusaurus/logger';
import type {Node} from 'unist'; import type {Node} from 'unist';
import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx'; import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx';
@ -83,3 +84,16 @@ export function assetRequireAttributeValue(
}, },
}; };
} }
function formatNodePosition(node: Node): string | undefined {
return node.position?.start
? logger.interpolate`number=${node.position.start.line}:number=${node.position.start.column}`
: undefined;
}
// Returns " (line:column)" when position info is available
// The initial space is useful to append easily to any existing message
export function formatNodePositionExtraMessage(node: Node): string {
const position = formatNodePosition(node);
return `${position ? ` (${position})` : ''}`;
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/module-type-aliases", "name": "@docusaurus/module-type-aliases",
"version": "3.7.0", "version": "3.9.2",
"description": "Docusaurus module type aliases.", "description": "Docusaurus module type aliases.",
"types": "./src/index.d.ts", "types": "./src/index.d.ts",
"publishConfig": { "publishConfig": {
@ -12,7 +12,7 @@
"directory": "packages/docusaurus-module-type-aliases" "directory": "packages/docusaurus-module-type-aliases"
}, },
"dependencies": { "dependencies": {
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"@types/history": "^4.7.11", "@types/history": "^4.7.11",
"@types/react": "*", "@types/react": "*",
"@types/react-router-config": "*", "@types/react-router-config": "*",

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/plugin-client-redirects", "name": "@docusaurus/plugin-client-redirects",
"version": "3.7.0", "version": "3.9.2",
"description": "Client redirects plugin for Docusaurus.", "description": "Client redirects plugin for Docusaurus.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@ -18,24 +18,24 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"@docusaurus/utils-common": "3.7.0", "@docusaurus/utils-common": "3.9.2",
"@docusaurus/utils-validation": "3.7.0", "@docusaurus/utils-validation": "3.9.2",
"eta": "^2.2.0", "eta": "^2.2.0",
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/types": "3.7.0" "@docusaurus/types": "3.9.2"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/plugin-content-blog", "name": "@docusaurus/plugin-content-blog",
"version": "3.7.0", "version": "3.9.2",
"description": "Blog plugin for Docusaurus.", "description": "Blog plugin for Docusaurus.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "src/plugin-content-blog.d.ts", "types": "src/plugin-content-blog.d.ts",
@ -31,14 +31,14 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.9.2",
"@docusaurus/logger": "3.7.0", "@docusaurus/logger": "3.9.2",
"@docusaurus/mdx-loader": "3.7.0", "@docusaurus/mdx-loader": "3.9.2",
"@docusaurus/theme-common": "3.7.0", "@docusaurus/theme-common": "3.9.2",
"@docusaurus/types": "3.7.0", "@docusaurus/types": "3.9.2",
"@docusaurus/utils": "3.7.0", "@docusaurus/utils": "3.9.2",
"@docusaurus/utils-common": "3.7.0", "@docusaurus/utils-common": "3.9.2",
"@docusaurus/utils-validation": "3.7.0", "@docusaurus/utils-validation": "3.9.2",
"cheerio": "1.0.0-rc.12", "cheerio": "1.0.0-rc.12",
"feed": "^4.2.2", "feed": "^4.2.2",
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
@ -56,7 +56,7 @@
"react-dom": "^18.0.0 || ^19.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=20.0"
}, },
"devDependencies": { "devDependencies": {
"@total-typescript/shoehorn": "^0.1.2", "@total-typescript/shoehorn": "^0.1.2",

View File

@ -0,0 +1,637 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`buildAllRoutes works for realistic blog post 2`] = `
[
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post1.md",
},
"modules": {
"content": "@site/blog/post1.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post1",
},
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post2.md",
},
"modules": {
"content": "@site/blog/post2.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post2",
},
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post3.md",
},
"modules": {
"content": "@site/blog/post3.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post3",
},
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post4.md",
},
"modules": {
"content": "@site/blog/post4.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post4",
},
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post5.md",
},
"modules": {
"content": "@site/blog/post5.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post5",
},
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/post6.md",
},
"modules": {
"content": "@site/blog/post6.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/post6",
},
{
"component": "@theme/BlogListPage",
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post1.md",
"query": {
"truncated": true,
},
},
},
{
"content": {
"__import": true,
"path": "@site/blog/post2.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog",
"props": {
"metadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": "/blog/page/2",
"page": 1,
"permalink": "/blog",
"postsPerPage": 2,
"previousPage": undefined,
"totalCount": 5,
"totalPages": 3,
},
},
},
{
"component": "@theme/BlogListPage",
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post4.md",
"query": {
"truncated": true,
},
},
},
{
"content": {
"__import": true,
"path": "@site/blog/post5.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/page/2",
"props": {
"metadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": "/blog/page/3",
"page": 2,
"permalink": "/blog/page/2",
"postsPerPage": 2,
"previousPage": "/blog",
"totalCount": 5,
"totalPages": 3,
},
},
},
{
"component": "@theme/BlogListPage",
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post6.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/page/3",
"props": {
"metadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": undefined,
"page": 3,
"permalink": "/blog/page/3",
"postsPerPage": 2,
"previousPage": "/blog/page/2",
"totalCount": 5,
"totalPages": 3,
},
},
},
{
"component": "@theme/BlogArchivePage",
"exact": true,
"path": "/blog/archive",
"props": {
"archive": {
"blogPosts": [
{
"content": "Content for post1",
"id": "post1",
"metadata": {
"authors": [
{
"key": "author1",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post1",
"frontMatter": {},
"permalink": "/blog/post1",
"readingTime": 2,
"source": "@site/blog/post1.md",
"tags": [],
"title": "Title for post1",
},
},
{
"content": "Content for post2",
"id": "post2",
"metadata": {
"authors": [
{
"key": "author1",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post2",
"frontMatter": {},
"permalink": "/blog/post2",
"readingTime": 2,
"source": "@site/blog/post2.md",
"tags": [],
"title": "Title for post2",
},
},
{
"content": "Content for post4",
"id": "post4",
"metadata": {
"authors": [
{
"key": "author1",
},
{
"key": "author2",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post4",
"frontMatter": {},
"permalink": "/blog/post4",
"readingTime": 2,
"source": "@site/blog/post4.md",
"tags": [],
"title": "Title for post4",
},
},
{
"content": "Content for post5",
"id": "post5",
"metadata": {
"authors": [
{
"key": "author2",
},
{
"key": "author3",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post5",
"frontMatter": {},
"permalink": "/blog/post5",
"readingTime": 2,
"source": "@site/blog/post5.md",
"tags": [],
"title": "Title for post5",
},
},
{
"content": "Content for post6",
"id": "post6",
"metadata": {
"authors": [],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post6",
"frontMatter": {},
"permalink": "/blog/post6",
"readingTime": 2,
"source": "@site/blog/post6.md",
"tags": [],
"title": "Title for post6",
},
},
],
},
},
},
{
"component": "@theme/Blog/Pages/BlogAuthorsListPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"modules": {
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/authors",
"props": {
"authors": [
{
"count": 3,
"key": "author1",
"name": "Author 1",
"page": {
"permalink": "/blog/authors/author1",
},
},
{
"count": 2,
"key": "author2",
"name": "Author 2",
"page": null,
},
{
"count": 1,
"key": "author3",
"name": "Author 3",
"page": {
"permalink": "/blog/authors/author3",
},
},
],
},
},
{
"component": "@theme/Blog/Pages/BlogAuthorsPostsPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post1.md",
"query": {
"truncated": true,
},
},
},
{
"content": {
"__import": true,
"path": "@site/blog/post2.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/authors/author1",
"props": {
"author": {
"count": 3,
"key": "author1",
"name": "Author 1",
"page": {
"permalink": "/blog/authors/author1",
},
},
"listMetadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": "/blog/authors/author1/page/2",
"page": 1,
"permalink": "/blog/authors/author1",
"postsPerPage": 2,
"previousPage": undefined,
"totalCount": 3,
"totalPages": 2,
},
},
},
{
"component": "@theme/Blog/Pages/BlogAuthorsPostsPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post4.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/authors/author1/page/2",
"props": {
"author": {
"count": 3,
"key": "author1",
"name": "Author 1",
"page": {
"permalink": "/blog/authors/author1",
},
},
"listMetadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": undefined,
"page": 2,
"permalink": "/blog/authors/author1/page/2",
"postsPerPage": 2,
"previousPage": "/blog/authors/author1",
"totalCount": 3,
"totalPages": 2,
},
},
},
{
"component": "@theme/Blog/Pages/BlogAuthorsPostsPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/post5.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/authors/author3",
"props": {
"author": {
"count": 1,
"key": "author3",
"name": "Author 3",
"page": {
"permalink": "/blog/authors/author3",
},
},
"listMetadata": {
"blogDescription": "Custom blog description",
"blogTitle": "Custom blog title",
"nextPage": undefined,
"page": 1,
"permalink": "/blog/authors/author3",
"postsPerPage": 2,
"previousPage": undefined,
"totalCount": 1,
"totalPages": 1,
},
},
},
]
`;
exports[`buildAllRoutes works for realistic blog post 3`] = `
{
"blog-post-list-prop-default.json": {
"items": [
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/post1",
"title": "Title for post1",
"unlisted": undefined,
},
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/post2",
"title": "Title for post2",
"unlisted": undefined,
},
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/post3",
"title": "Title for post3",
"unlisted": true,
},
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/post4",
"title": "Title for post4",
"unlisted": undefined,
},
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/post5",
"title": "Title for post5",
"unlisted": undefined,
},
],
"title": "Custom blog sidebar title",
},
"blogMetadata-default.json": {
"authorsListPath": "/blog/authors",
"blogBasePath": "/blog",
"blogTitle": "Custom blog title",
},
"site-blog-post-1-md-235.json": {
"authors": [
{
"key": "author1",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post1",
"frontMatter": {},
"permalink": "/blog/post1",
"readingTime": 2,
"source": "@site/blog/post1.md",
"tags": [],
"title": "Title for post1",
},
"site-blog-post-2-md-b42.json": {
"authors": [
{
"key": "author1",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post2",
"frontMatter": {},
"permalink": "/blog/post2",
"readingTime": 2,
"source": "@site/blog/post2.md",
"tags": [],
"title": "Title for post2",
},
"site-blog-post-3-md-3b7.json": {
"authors": [
{
"key": "author3",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post3",
"frontMatter": {},
"permalink": "/blog/post3",
"readingTime": 2,
"source": "@site/blog/post3.md",
"tags": [],
"title": "Title for post3",
"unlisted": true,
},
"site-blog-post-4-md-15a.json": {
"authors": [
{
"key": "author1",
},
{
"key": "author2",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post4",
"frontMatter": {},
"permalink": "/blog/post4",
"readingTime": 2,
"source": "@site/blog/post4.md",
"tags": [],
"title": "Title for post4",
},
"site-blog-post-5-md-274.json": {
"authors": [
{
"key": "author2",
},
{
"key": "author3",
},
],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post5",
"frontMatter": {},
"permalink": "/blog/post5",
"readingTime": 2,
"source": "@site/blog/post5.md",
"tags": [],
"title": "Title for post5",
},
"site-blog-post-6-md-3ca.json": {
"authors": [],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for post6",
"frontMatter": {},
"permalink": "/blog/post6",
"readingTime": 2,
"source": "@site/blog/post6.md",
"tags": [],
"title": "Title for post6",
},
}
`;

View File

@ -24,24 +24,7 @@ exports[`getContentTranslationFiles returns translation files matching snapshot
exports[`translateContent falls back when translation is incomplete 1`] = ` exports[`translateContent falls back when translation is incomplete 1`] = `
{ {
"blogListPaginated": [ "blogDescription": "Someone's random blog",
{
"items": [
"hello",
],
"metadata": {
"blogDescription": "Someone's random blog",
"blogTitle": "My blog",
"nextPage": undefined,
"page": 1,
"permalink": "/",
"postsPerPage": 10,
"previousPage": undefined,
"totalCount": 1,
"totalPages": 1,
},
},
],
"blogPosts": [ "blogPosts": [
{ {
"content": "", "content": "",
@ -63,29 +46,13 @@ exports[`translateContent falls back when translation is incomplete 1`] = `
"blogSidebarTitle": "All my posts", "blogSidebarTitle": "All my posts",
"blogTags": {}, "blogTags": {},
"blogTagsListPath": "/tags", "blogTagsListPath": "/tags",
"blogTitle": "My blog",
} }
`; `;
exports[`translateContent returns translated loaded 1`] = ` exports[`translateContent returns translated loaded 1`] = `
{ {
"blogListPaginated": [ "blogDescription": "Someone's random blog (translated)",
{
"items": [
"hello",
],
"metadata": {
"blogDescription": "Someone's random blog (translated)",
"blogTitle": "My blog (translated)",
"nextPage": undefined,
"page": 1,
"permalink": "/",
"postsPerPage": 10,
"previousPage": undefined,
"totalCount": 1,
"totalPages": 1,
},
},
],
"blogPosts": [ "blogPosts": [
{ {
"content": "", "content": "",
@ -107,5 +74,6 @@ exports[`translateContent returns translated loaded 1`] = `
"blogSidebarTitle": "All my posts (translated)", "blogSidebarTitle": "All my posts (translated)",
"blogTags": {}, "blogTags": {},
"blogTagsListPath": "/tags", "blogTagsListPath": "/tags",
"blogTitle": "My blog (translated)",
} }
`; `;

View File

@ -21,11 +21,13 @@ describe('normalizeSocials', () => {
twitch: 'gingergeek', twitch: 'gingergeek',
youtube: 'gingergeekuk', youtube: 'gingergeekuk',
mastodon: 'Mastodon', mastodon: 'Mastodon',
email: 'seb@example.com',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"bluesky": "https://bsky.app/profile/gingergeek.co.uk", "bluesky": "https://bsky.app/profile/gingergeek.co.uk",
"email": "mailto:seb@example.com",
"github": "https://github.com/ozakione", "github": "https://github.com/ozakione",
"instagram": "https://www.instagram.com/thisweekinreact", "instagram": "https://www.instagram.com/thisweekinreact",
"linkedin": "https://www.linkedin.com/in/ozakione/", "linkedin": "https://www.linkedin.com/in/ozakione/",
@ -48,11 +50,13 @@ describe('normalizeSocials', () => {
instaGRam: 'thisweekinreact', instaGRam: 'thisweekinreact',
BLUESKY: 'gingergeek.co.uk', BLUESKY: 'gingergeek.co.uk',
tHrEaDs: 'gingergeekuk', tHrEaDs: 'gingergeekuk',
eMAil: 'seb@example.com',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"bluesky": "https://bsky.app/profile/gingergeek.co.uk", "bluesky": "https://bsky.app/profile/gingergeek.co.uk",
"email": "mailto:seb@example.com",
"github": "https://github.com/ozakione", "github": "https://github.com/ozakione",
"instagram": "https://www.instagram.com/thisweekinreact", "instagram": "https://www.instagram.com/thisweekinreact",
"linkedin": "https://www.linkedin.com/in/ozakione/", "linkedin": "https://www.linkedin.com/in/ozakione/",
@ -69,6 +73,7 @@ describe('normalizeSocials', () => {
linkedin: 'https://linkedin.com/ozakione', linkedin: 'https://linkedin.com/ozakione',
github: 'https://github.com/ozakione', github: 'https://github.com/ozakione',
stackoverflow: 'https://stackoverflow.com/ozakione', stackoverflow: 'https://stackoverflow.com/ozakione',
email: 'mailto:seb@example.com',
}; };
expect(normalizeSocials(socials)).toEqual(socials); expect(normalizeSocials(socials)).toEqual(socials);
@ -81,10 +86,12 @@ describe('normalizeSocials', () => {
github: 'https://github.com/ozakione', github: 'https://github.com/ozakione',
stackoverflow: 'https://stackoverflow.com/ozakione', stackoverflow: 'https://stackoverflow.com/ozakione',
mastodon: 'https://hachyderm.io/@hachyderm', mastodon: 'https://hachyderm.io/@hachyderm',
email: 'mailto:seb@example.com',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"email": "mailto:seb@example.com",
"github": "https://github.com/ozakione", "github": "https://github.com/ozakione",
"linkedin": "https://www.linkedin.com/in/ozakione/", "linkedin": "https://www.linkedin.com/in/ozakione/",
"mastodon": "https://hachyderm.io/@hachyderm", "mastodon": "https://hachyderm.io/@hachyderm",

View File

@ -8,7 +8,10 @@
import {jest} from '@jest/globals'; import {jest} from '@jest/globals';
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils'; import {
DEFAULT_PARSE_FRONT_MATTER,
DEFAULT_VCS_CONFIG,
} from '@docusaurus/utils';
import {fromPartial} from '@total-typescript/shoehorn'; import {fromPartial} from '@total-typescript/shoehorn';
import {normalizePluginOptions} from '@docusaurus/utils-validation'; import {normalizePluginOptions} from '@docusaurus/utils-validation';
import tree from 'tree-node-cli'; import tree from 'tree-node-cli';
@ -51,7 +54,7 @@ function getBlogContentPaths(siteDir: string): BlogContentPaths {
} }
async function testGenerateFeeds( async function testGenerateFeeds(
context: LoadContext, contextInput: LoadContext,
optionsInput: Options, optionsInput: Options,
): Promise<void> { ): Promise<void> {
const options = validateOptions({ const options = validateOptions({
@ -62,6 +65,17 @@ async function testGenerateFeeds(
options: optionsInput, options: optionsInput,
}); });
const context: LoadContext = {
...contextInput,
siteConfig: {
...contextInput.siteConfig,
future: {
...contextInput.siteConfig?.future,
experimental_vcs: DEFAULT_VCS_CONFIG,
},
},
};
const contentPaths = getBlogContentPaths(context.siteDir); const contentPaths = getBlogContentPaths(context.siteDir);
const authorsMap = await getAuthorsMap({ const authorsMap = await getAuthorsMap({
contentPaths, contentPaths,

View File

@ -6,13 +6,9 @@
*/ */
import {jest} from '@jest/globals'; import {jest} from '@jest/globals';
import path from 'path'; import * as path from 'path';
import {normalizePluginOptions} from '@docusaurus/utils-validation'; import {normalizePluginOptions} from '@docusaurus/utils-validation';
import { import {posixPath, getLocaleConfig, TEST_VCS} from '@docusaurus/utils';
posixPath,
getFileCommitDate,
LAST_UPDATE_FALLBACK,
} from '@docusaurus/utils';
import {DEFAULT_FUTURE_CONFIG} from '@docusaurus/core/src/server/configValidation'; import {DEFAULT_FUTURE_CONFIG} from '@docusaurus/core/src/server/configValidation';
import pluginContentBlog from '../index'; import pluginContentBlog from '../index';
import {validateOptions} from '../options'; import {validateOptions} from '../options';
@ -22,6 +18,7 @@ import type {
I18n, I18n,
Validate, Validate,
MarkdownConfig, MarkdownConfig,
I18nLocaleConfig,
} from '@docusaurus/types'; } from '@docusaurus/types';
import type { import type {
BlogPost, BlogPost,
@ -30,6 +27,10 @@ import type {
EditUrlFunction, EditUrlFunction,
} from '@docusaurus/plugin-content-blog'; } from '@docusaurus/plugin-content-blog';
async function getFileCreationDate(filePath: string): Promise<Date> {
return new Date((await TEST_VCS.getFileCreationInfo(filePath)).timestamp);
}
const markdown: MarkdownConfig = { const markdown: MarkdownConfig = {
format: 'mdx', format: 'mdx',
mermaid: true, mermaid: true,
@ -67,7 +68,10 @@ Available blog post titles are:\n- ${blogPosts
return post; return post;
} }
function getI18n(locale: string): I18n { function getI18n(
locale: string,
localeConfigOptions?: Partial<I18nLocaleConfig>,
): I18n {
return { return {
currentLocale: locale, currentLocale: locale,
locales: [locale], locales: [locale],
@ -80,6 +84,8 @@ function getI18n(locale: string): I18n {
htmlLang: locale, htmlLang: locale,
direction: 'ltr', direction: 'ltr',
path: locale, path: locale,
translate: true,
...localeConfigOptions,
}, },
}, },
}; };
@ -94,13 +100,14 @@ const BaseEditUrl = 'https://baseEditUrl.com/edit';
const getPlugin = async ( const getPlugin = async (
siteDir: string, siteDir: string,
pluginOptions: Partial<PluginOptions> = {}, pluginOptions: Partial<PluginOptions> = {},
i18n: I18n = DefaultI18N, i18nOptions: Partial<I18n> = {},
) => { ) => {
const i18n = {...DefaultI18N, ...i18nOptions};
const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus');
const localizationDir = path.join( const localizationDir = path.join(
siteDir, siteDir,
i18n.path, i18n.path,
i18n.localeConfigs[i18n.currentLocale]!.path, getLocaleConfig(i18n).path,
); );
const siteConfig = { const siteConfig = {
title: 'Hello', title: 'Hello',
@ -153,20 +160,34 @@ const getBlogTags = async (
}; };
describe('blog plugin', () => { describe('blog plugin', () => {
it('getPathsToWatch returns right files', async () => { describe('getPathsToWatch', () => {
const siteDir = path.join(__dirname, '__fixtures__', 'website'); async function runTest({translate}: {translate: boolean}) {
const plugin = await getPlugin(siteDir); const siteDir = path.join(__dirname, '__fixtures__', 'website');
const pathsToWatch = plugin.getPathsToWatch!(); const plugin = await getPlugin(siteDir, {}, getI18n('en', {translate}));
const relativePathsToWatch = pathsToWatch.map((p) => const pathsToWatch = plugin.getPathsToWatch!();
posixPath(path.relative(siteDir, p)), return pathsToWatch.map((p) => posixPath(path.relative(siteDir, p)));
); }
expect(relativePathsToWatch).toEqual([
'i18n/en/docusaurus-plugin-content-blog/authors.yml', it('getPathsToWatch returns right files', async () => {
'i18n/en/docusaurus-plugin-content-blog/tags.yml', const relativePathsToWatch = await runTest({translate: true});
'blog/tags.yml', expect(relativePathsToWatch).toEqual([
'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}', 'i18n/en/docusaurus-plugin-content-blog/authors.yml',
'blog/**/*.{md,mdx}', 'i18n/en/docusaurus-plugin-content-blog/tags.yml',
]); // 'blog/authors.yml', // TODO weird that it's not here but tags is?
'blog/tags.yml',
'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}',
'blog/**/*.{md,mdx}',
]);
});
it('getPathsToWatch returns right files (translate: false)', async () => {
const relativePathsToWatch = await runTest({translate: false});
expect(relativePathsToWatch).toEqual([
'blog/authors.yml',
'blog/tags.yml',
'blog/**/*.{md,mdx}',
]);
});
}); });
it('builds a simple website', async () => { it('builds a simple website', async () => {
@ -377,6 +398,54 @@ describe('blog plugin', () => {
}); });
}); });
describe('i18n config translate is wired properly', () => {
async function runTest({translate}: {translate: boolean}) {
const siteDir = path.join(__dirname, '__fixtures__', 'website');
const blogPosts = await getBlogPosts(
siteDir,
{},
getI18n('en', {translate}),
);
// Simpler to snapshot
return blogPosts.map((post) => post.metadata.title);
}
it('works with translate: false', async () => {
await expect(runTest({translate: false})).resolves.toMatchInlineSnapshot(`
[
"test links",
"MDX Blog Sample with require calls",
"Full Blog Sample",
"Complex Slug",
"Simple Slug",
"draft",
"unlisted",
"some heading",
"date-matter",
"Happy 1st Birthday Slash!",
]
`);
});
it('works with translate: true', async () => {
await expect(runTest({translate: true})).resolves.toMatchInlineSnapshot(`
[
"test links",
"MDX Blog Sample with require calls",
"Full Blog Sample",
"Complex Slug",
"Simple Slug",
"draft",
"unlisted",
"some heading",
"date-matter",
"Happy 1st Birthday Slash! (translated)",
]
`);
});
});
it('handles edit URL with editLocalizedBlogs: true', async () => { it('handles edit URL with editLocalizedBlogs: true', async () => {
const siteDir = path.join(__dirname, '__fixtures__', 'website'); const siteDir = path.join(__dirname, '__fixtures__', 'website');
const blogPosts = await getBlogPosts(siteDir, {editLocalizedFiles: true}); const blogPosts = await getBlogPosts(siteDir, {editLocalizedFiles: true});
@ -390,6 +459,23 @@ describe('blog plugin', () => {
); );
}); });
it('handles edit URL with editLocalizedBlogs: true and translate: false', async () => {
const siteDir = path.join(__dirname, '__fixtures__', 'website');
const blogPosts = await getBlogPosts(
siteDir,
{editLocalizedFiles: true},
getI18n('en', {translate: false}),
);
const localizedBlogPost = blogPosts.find(
(v) => v.metadata.title === 'Happy 1st Birthday Slash!',
)!;
expect(localizedBlogPost.metadata.editUrl).toBe(
`${BaseEditUrl}/blog/2018-12-14-Happy-First-Birthday-Slash.md`,
);
});
it('handles edit URL with editUrl function', async () => { it('handles edit URL with editUrl function', async () => {
const siteDir = path.join(__dirname, '__fixtures__', 'website'); const siteDir = path.join(__dirname, '__fixtures__', 'website');
@ -474,9 +560,7 @@ describe('blog plugin', () => {
const blogPosts = await getBlogPosts(siteDir); const blogPosts = await getBlogPosts(siteDir);
const noDateSource = path.posix.join('@site', PluginPath, 'no date.md'); const noDateSource = path.posix.join('@site', PluginPath, 'no date.md');
const noDateSourceFile = path.posix.join(siteDir, PluginPath, 'no date.md'); const noDateSourceFile = path.posix.join(siteDir, PluginPath, 'no date.md');
// We know the file exists and we know we have git const noDateSourceTime = await getFileCreationDate(noDateSourceFile);
const result = await getFileCommitDate(noDateSourceFile, {age: 'oldest'});
const noDateSourceTime = result.date;
expect({ expect({
...getByTitle(blogPosts, 'no date').metadata, ...getByTitle(blogPosts, 'no date').metadata,
@ -554,10 +638,7 @@ describe('blog plugin', () => {
}, },
DefaultI18N, DefaultI18N,
); );
const {blogPosts, blogTags, blogListPaginated} = const {blogPosts, blogTags} = (await plugin.loadContent!())!;
(await plugin.loadContent!())!;
expect(blogListPaginated).toHaveLength(3);
expect(Object.keys(blogTags)).toHaveLength(2); expect(Object.keys(blogTags)).toHaveLength(2);
expect(blogTags).toMatchSnapshot(); expect(blogTags).toMatchSnapshot();
@ -587,29 +668,23 @@ describe('last update', () => {
); );
const {blogPosts} = (await plugin.loadContent!())!; const {blogPosts} = (await plugin.loadContent!())!;
const TestLastUpdate = await TEST_VCS.getFileLastUpdateInfo('any path');
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb'); expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt, lastUpdateFor('2021-01-01'),
); );
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe( expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt, lastUpdateFor('2021-01-01'),
); );
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb'); expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe( expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
LAST_UPDATE_FALLBACK.lastUpdatedBy, expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
}); });
it('time only', async () => { it('time only', async () => {
@ -623,29 +698,27 @@ describe('last update', () => {
); );
const {blogPosts} = (await plugin.loadContent!())!; const {blogPosts} = (await plugin.loadContent!())!;
expect(blogPosts[0]?.metadata.title).toBe('Author'); const TestLastUpdate = await TEST_VCS.getFileLastUpdateInfo('any path');
expect(blogPosts[0]?.metadata.title).toBe('Both');
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBeUndefined(); expect(blogPosts[0]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt, lastUpdateFor('2021-01-01'),
); );
expect(blogPosts[1]?.metadata.title).toBe('Nothing'); expect(blogPosts[1]?.metadata.title).toBe('Last update date');
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBeUndefined(); expect(blogPosts[1]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt, lastUpdateFor('2021-01-01'),
); );
expect(blogPosts[2]?.metadata.title).toBe('Both'); expect(blogPosts[2]?.metadata.title).toBe('Author');
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBeUndefined(); expect(blogPosts[2]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[3]?.metadata.title).toBe('Last update date'); expect(blogPosts[3]?.metadata.title).toBe('Nothing');
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBeUndefined(); expect(blogPosts[3]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe( expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
lastUpdateFor('2021-01-01'),
);
}); });
it('author only', async () => { it('author only', async () => {
@ -659,20 +732,18 @@ describe('last update', () => {
); );
const {blogPosts} = (await plugin.loadContent!())!; const {blogPosts} = (await plugin.loadContent!())!;
const TestLastUpdate = await TEST_VCS.getFileLastUpdateInfo('any path');
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb'); expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBeUndefined(); expect(blogPosts[0]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe( expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBeUndefined(); expect(blogPosts[1]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb'); expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBeUndefined(); expect(blogPosts[2]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe( expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBeUndefined(); expect(blogPosts[3]?.metadata.lastUpdatedAt).toBeUndefined();
}); });

View File

@ -0,0 +1,324 @@
/**
* 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 * as _ from 'lodash';
import {fromPartial} from '@total-typescript/shoehorn';
import {buildAllRoutes} from '../routes';
import {DEFAULT_OPTIONS} from '../options';
import type {PartialDeep} from '@total-typescript/shoehorn';
import type {BlogPost, BlogPostMetadata} from '@docusaurus/plugin-content-blog';
type Params = Parameters<typeof buildAllRoutes>[0];
async function testBuildAllRoutes(overrides: PartialDeep<Params> = {}) {
const createData = jest.fn(
async (name: string, _data: unknown) => `/data/${name}`,
);
const params: Params = fromPartial<Params>({
baseUrl: '/',
aliasedSource: (str: string) => `@aliased${str}`,
...overrides,
content: {
blogTitle: 'Blog Title',
blogDescription: 'Blog Description',
blogSidebarTitle: 'Blog Sidebar Title',
authorsMap: {},
blogTagsListPath: '',
blogTags: {},
blogPosts: [],
...overrides?.content,
},
options: {
...DEFAULT_OPTIONS,
...overrides?.options,
},
actions: {
createData,
...overrides?.actions,
},
});
const routes = await buildAllRoutes(params);
const data = Object.fromEntries(
createData.mock.calls.map((call) => [call[0], call[1]]),
);
function getRouteByPath(path: string) {
const route = routes.find((r) => r.path === path);
if (!route) {
throw new Error(`Route not found for path: ${path}`);
}
return route;
}
function getRoutesByComponent(component: string) {
return routes.filter((r) => r.component === component);
}
return {routes, data, utils: {getRouteByPath, getRoutesByComponent}};
}
function blogPost(overrides: PartialDeep<BlogPost> = {}): BlogPost {
const id = overrides.id ?? 'blog-post';
return fromPartial<BlogPost>({
id,
content: `Content for ${id}`,
...overrides,
metadata: fromPartial<BlogPostMetadata>({
title: `Title for ${id}`,
description: `Description for ${id}`,
permalink: `/blog/${id}`,
source: `@site/blog/${id}.md`,
date: new Date('2020-01-01'),
tags: [],
readingTime: 2,
authors: [],
frontMatter: {
...overrides?.metadata?.frontMatter,
},
...overrides?.metadata,
}),
});
}
describe('buildAllRoutes', () => {
it('works for empty blog', async () => {
const {routes, data} = await testBuildAllRoutes({
content: {
blogPosts: [],
},
});
expect(routes).toMatchInlineSnapshot(`
[
{
"component": "@theme/BlogListPage",
"exact": true,
"modules": {
"items": [],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog",
"props": {
"metadata": {
"blogDescription": "Blog Description",
"blogTitle": "Blog Title",
"nextPage": undefined,
"page": 1,
"permalink": "/blog",
"postsPerPage": 10,
"previousPage": undefined,
"totalCount": 0,
"totalPages": 1,
},
},
},
]
`);
expect(data).toMatchInlineSnapshot(`
{
"blog-post-list-prop-default.json": {
"items": [],
"title": "Blog Sidebar Title",
},
"blogMetadata-default.json": {
"authorsListPath": "/blog/authors",
"blogBasePath": "/blog",
"blogTitle": "Blog Title",
},
}
`);
});
it('works for single blog post', async () => {
const {routes, data} = await testBuildAllRoutes({
content: {
blogPosts: [blogPost()],
},
});
expect(routes).toMatchInlineSnapshot(`
[
{
"component": "@theme/BlogPostPage",
"context": {
"blogMetadata": "@aliased/data/blogMetadata-default.json",
},
"exact": true,
"metadata": {
"lastUpdatedAt": undefined,
"sourceFilePath": "blog/blog-post.md",
},
"modules": {
"content": "@site/blog/blog-post.md",
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog/blog-post",
},
{
"component": "@theme/BlogListPage",
"exact": true,
"modules": {
"items": [
{
"content": {
"__import": true,
"path": "@site/blog/blog-post.md",
"query": {
"truncated": true,
},
},
},
],
"sidebar": "@aliased/data/blog-post-list-prop-default.json",
},
"path": "/blog",
"props": {
"metadata": {
"blogDescription": "Blog Description",
"blogTitle": "Blog Title",
"nextPage": undefined,
"page": 1,
"permalink": "/blog",
"postsPerPage": 10,
"previousPage": undefined,
"totalCount": 1,
"totalPages": 1,
},
},
},
{
"component": "@theme/BlogArchivePage",
"exact": true,
"path": "/blog/archive",
"props": {
"archive": {
"blogPosts": [
{
"content": "Content for blog-post",
"id": "blog-post",
"metadata": {
"authors": [],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for blog-post",
"frontMatter": {},
"permalink": "/blog/blog-post",
"readingTime": 2,
"source": "@site/blog/blog-post.md",
"tags": [],
"title": "Title for blog-post",
},
},
],
},
},
},
]
`);
expect(data).toMatchInlineSnapshot(`
{
"blog-post-list-prop-default.json": {
"items": [
{
"date": 2020-01-01T00:00:00.000Z,
"permalink": "/blog/blog-post",
"title": "Title for blog-post",
"unlisted": undefined,
},
],
"title": "Blog Sidebar Title",
},
"blogMetadata-default.json": {
"authorsListPath": "/blog/authors",
"blogBasePath": "/blog",
"blogTitle": "Blog Title",
},
"site-blog-blog-post-md-0d7.json": {
"authors": [],
"date": 2020-01-01T00:00:00.000Z,
"description": "Description for blog-post",
"frontMatter": {},
"permalink": "/blog/blog-post",
"readingTime": 2,
"source": "@site/blog/blog-post.md",
"tags": [],
"title": "Title for blog-post",
},
}
`);
});
it('works for realistic blog post', async () => {
const {routes, data} = await testBuildAllRoutes({
options: {
postsPerPage: 2,
},
content: {
blogTitle: 'Custom blog title',
blogDescription: 'Custom blog description',
blogSidebarTitle: 'Custom blog sidebar title',
blogPosts: [
blogPost({id: 'post1', metadata: {authors: [{key: 'author1'}]}}),
blogPost({id: 'post2', metadata: {authors: [{key: 'author1'}]}}),
blogPost({
id: 'post3',
metadata: {
authors: [{key: 'author3'}],
unlisted: true,
},
}),
blogPost({
id: 'post4',
metadata: {
authors: [{key: 'author1'}, {key: 'author2'}],
},
}),
blogPost({
id: 'post5',
metadata: {authors: [{key: 'author2'}, {key: 'author3'}]},
}),
blogPost({id: 'post6'}),
],
authorsMap: {
author1: {
key: 'author1',
name: 'Author 1',
page: {permalink: '/blog/authors/author1'},
},
author2: {
key: 'author2',
name: 'Author 2',
page: null,
},
author3: {
key: 'author3',
name: 'Author 3',
page: {permalink: '/blog/authors/author3'},
},
},
},
});
expect(_.countBy(routes, 'component')).toMatchInlineSnapshot(`
{
"@theme/Blog/Pages/BlogAuthorsListPage": 1,
"@theme/Blog/Pages/BlogAuthorsPostsPage": 3,
"@theme/BlogArchivePage": 1,
"@theme/BlogListPage": 3,
"@theme/BlogPostPage": 6,
}
`);
expect(routes).toMatchSnapshot();
expect(data).toMatchSnapshot();
});
});

View File

@ -6,6 +6,7 @@
*/ */
import {updateTranslationFileMessages} from '@docusaurus/utils'; import {updateTranslationFileMessages} from '@docusaurus/utils';
import {fromPartial} from '@total-typescript/shoehorn';
import {getTranslationFiles, translateContent} from '../translations'; import {getTranslationFiles, translateContent} from '../translations';
import {DEFAULT_OPTIONS} from '../options'; import {DEFAULT_OPTIONS} from '../options';
import type { import type {
@ -16,13 +17,13 @@ import type {
const sampleBlogOptions: PluginOptions = { const sampleBlogOptions: PluginOptions = {
...DEFAULT_OPTIONS, ...DEFAULT_OPTIONS,
blogSidebarTitle: 'All my posts',
blogTitle: 'My blog', blogTitle: 'My blog',
blogDescription: "Someone's random blog", blogDescription: "Someone's random blog",
blogSidebarTitle: 'All my posts',
}; };
const sampleBlogPosts: BlogPost[] = [ const sampleBlogPosts: BlogPost[] = [
{ fromPartial({
id: 'hello', id: 'hello',
metadata: { metadata: {
permalink: '/blog/2021/06/19/hello', permalink: '/blog/2021/06/19/hello',
@ -37,27 +38,13 @@ const sampleBlogPosts: BlogPost[] = [
unlisted: false, unlisted: false,
}, },
content: '', content: '',
}, }),
]; ];
const sampleBlogContent: BlogContent = { const sampleBlogContent: BlogContent = {
blogTitle: sampleBlogOptions.blogTitle,
blogDescription: sampleBlogOptions.blogDescription,
blogSidebarTitle: sampleBlogOptions.blogSidebarTitle, blogSidebarTitle: sampleBlogOptions.blogSidebarTitle,
blogListPaginated: [
{
items: ['hello'],
metadata: {
permalink: '/',
page: 1,
postsPerPage: 10,
totalPages: 1,
totalCount: 1,
previousPage: undefined,
nextPage: undefined,
blogTitle: sampleBlogOptions.blogTitle,
blogDescription: sampleBlogOptions.blogDescription,
},
},
],
blogPosts: sampleBlogPosts, blogPosts: sampleBlogPosts,
blogTags: {}, blogTags: {},
blogTagsListPath: '/tags', blogTagsListPath: '/tags',

View File

@ -27,6 +27,7 @@ export const AuthorSocialsSchema = Joi.object<AuthorSocials>({
mastodon: Joi.string(), mastodon: Joi.string(),
twitch: Joi.string(), twitch: Joi.string(),
youtube: Joi.string(), youtube: Joi.string(),
email: Joi.string(),
}).unknown(); }).unknown();
type PredefinedPlatformNormalizer = (value: string) => string; type PredefinedPlatformNormalizer = (value: string) => string;
@ -47,12 +48,12 @@ const PredefinedPlatformNormalizers: Record<
mastodon: (handle: string) => `https://mastodon.social/@${handle}`, // can be in format user@other.server and it will redirect if needed mastodon: (handle: string) => `https://mastodon.social/@${handle}`, // can be in format user@other.server and it will redirect if needed
twitch: (handle: string) => `https://twitch.tv/${handle}`, twitch: (handle: string) => `https://twitch.tv/${handle}`,
youtube: (handle: string) => `https://youtube.com/@${handle}`, // https://support.google.com/youtube/answer/6180214?hl=en youtube: (handle: string) => `https://youtube.com/@${handle}`, // https://support.google.com/youtube/answer/6180214?hl=en
email: (email: string) => `mailto:${email}`,
}; };
type SocialEntry = [string, string]; type SocialEntry = [string, string];
function normalizeSocialEntry([platform, value]: SocialEntry): SocialEntry { function normalizeSocialEntry([platform, value]: SocialEntry): SocialEntry {
const normalizer = PredefinedPlatformNormalizers[platform.toLowerCase()];
if (typeof value !== 'string') { if (typeof value !== 'string') {
throw new Error( throw new Error(
`Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs. `Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs.
@ -60,7 +61,9 @@ Social platform '${platform}' has illegal value '${value}'`,
); );
} }
const isAbsoluteUrl = const isAbsoluteUrl =
value.startsWith('http://') || value.startsWith('https://'); value.startsWith('http://') ||
value.startsWith('https://') ||
value.startsWith('mailto:');
if (isAbsoluteUrl) { if (isAbsoluteUrl) {
return [platform, value]; return [platform, value];
} else if (value.includes('/')) { } else if (value.includes('/')) {
@ -69,6 +72,7 @@ Social platform '${platform}' has illegal value '${value}'`,
Social platform '${platform}' has illegal value '${value}'`, Social platform '${platform}' has illegal value '${value}'`,
); );
} }
const normalizer = PredefinedPlatformNormalizers[platform.toLowerCase()];
if (normalizer && !isAbsoluteUrl) { if (normalizer && !isAbsoluteUrl) {
const normalizedPlatform = platform.toLowerCase(); const normalizedPlatform = platform.toLowerCase();
const normalizedValue = normalizer(value); const normalizedValue = normalizer(value);

View File

@ -19,7 +19,6 @@ import {
Globby, Globby,
groupTaggedItems, groupTaggedItems,
getTagVisibility, getTagVisibility,
getFileCommitDate,
getContentPathList, getContentPathList,
isUnlisted, isUnlisted,
isDraft, isDraft,
@ -225,6 +224,7 @@ async function processBlogSourceFile(
siteConfig: { siteConfig: {
baseUrl, baseUrl,
markdown: {parseFrontMatter}, markdown: {parseFrontMatter},
future: {experimental_vcs: vcs},
}, },
siteDir, siteDir,
i18n, i18n,
@ -257,6 +257,7 @@ async function processBlogSourceFile(
blogSourceAbsolute, blogSourceAbsolute,
options, options,
frontMatter.last_update, frontMatter.last_update,
vcs,
); );
const draft = isDraft({frontMatter}); const draft = isDraft({frontMatter});
@ -285,17 +286,11 @@ async function processBlogSourceFile(
return parsedBlogFileName.date; return parsedBlogFileName.date;
} }
try { const result = await vcs.getFileCreationInfo(blogSourceAbsolute);
const result = await getFileCommitDate(blogSourceAbsolute, { if (result == null) {
age: 'oldest',
includeAuthor: false,
});
return result.date;
} catch (err) {
logger.warn(err);
return (await fs.stat(blogSourceAbsolute)).birthtime; return (await fs.stat(blogSourceAbsolute)).birthtime;
} }
return new Date(result.timestamp);
} }
const date = await getDate(); const date = await getDate();
@ -323,7 +318,9 @@ async function processBlogSourceFile(
} else if (typeof editUrl === 'string') { } else if (typeof editUrl === 'string') {
const isLocalized = blogDirPath === contentPaths.contentPathLocalized; const isLocalized = blogDirPath === contentPaths.contentPathLocalized;
const fileContentPath = const fileContentPath =
isLocalized && options.editLocalizedFiles isLocalized &&
options.editLocalizedFiles &&
contentPaths.contentPathLocalized
? contentPaths.contentPathLocalized ? contentPaths.contentPathLocalized
: contentPaths.contentPath; : contentPaths.contentPath;
@ -404,6 +401,8 @@ export async function generateBlogPosts(
ignore: exclude, ignore: exclude,
}); });
// TODO this should be done outside of this function
// directly in plugin loadContent()
const tagsFile = await getTagsFile({contentPaths, tags: options.tags}); const tagsFile = await getTagsFile({contentPaths, tags: options.tags});
async function doProcessBlogSourceFile(blogSourceFile: string) { async function doProcessBlogSourceFile(blogSourceFile: string) {

View File

@ -17,14 +17,13 @@ import {
createAbsoluteFilePathMatcher, createAbsoluteFilePathMatcher,
getContentPathList, getContentPathList,
getDataFilePath, getDataFilePath,
DEFAULT_PLUGIN_ID,
resolveMarkdownLinkPathname, resolveMarkdownLinkPathname,
getLocaleConfig,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation'; import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation';
import {createMDXLoaderItem} from '@docusaurus/mdx-loader'; import {createMDXLoaderItem} from '@docusaurus/mdx-loader';
import { import {
getBlogTags, getBlogTags,
paginateBlogPosts,
shouldBeListed, shouldBeListed,
applyProcessBlogPosts, applyProcessBlogPosts,
generateBlogPosts, generateBlogPosts,
@ -44,7 +43,6 @@ import type {
Assets, Assets,
BlogTags, BlogTags,
BlogContent, BlogContent,
BlogPaginated,
} from '@docusaurus/plugin-content-blog'; } from '@docusaurus/plugin-content-blog';
import type {RuleSetRule, RuleSetUseItem} from 'webpack'; import type {RuleSetRule, RuleSetUseItem} from 'webpack';
@ -71,17 +69,20 @@ export default async function pluginContentBlog(
); );
} }
const {onBrokenMarkdownLinks, baseUrl} = siteConfig; const {baseUrl} = siteConfig;
const shouldTranslate = getLocaleConfig(context.i18n).translate;
const contentPaths: BlogContentPaths = { const contentPaths: BlogContentPaths = {
contentPath: path.resolve(siteDir, options.path), contentPath: path.resolve(siteDir, options.path),
contentPathLocalized: getPluginI18nPath({ contentPathLocalized: shouldTranslate
localizationDir, ? getPluginI18nPath({
pluginName: PluginName, localizationDir,
pluginId: options.id, pluginName: PluginName,
}), pluginId: options.id,
})
: undefined,
}; };
const pluginId = options.id ?? DEFAULT_PLUGIN_ID; const pluginId = options.id;
const pluginDataDirRoot = path.join(generatedFilesDir, PluginName); const pluginDataDirRoot = path.join(generatedFilesDir, PluginName);
const dataDir = path.join(pluginDataDirRoot, pluginId); const dataDir = path.join(pluginDataDirRoot, pluginId);
@ -154,18 +155,12 @@ export default async function pluginContentBlog(
}, },
markdownConfig: siteConfig.markdown, markdownConfig: siteConfig.markdown,
resolveMarkdownLink: ({linkPathname, sourceFilePath}) => { resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
const permalink = resolveMarkdownLinkPathname(linkPathname, { return resolveMarkdownLinkPathname(linkPathname, {
sourceFilePath, sourceFilePath,
sourceToPermalink: contentHelpers.sourceToPermalink, sourceToPermalink: contentHelpers.sourceToPermalink,
siteDir, siteDir,
contentPaths, contentPaths,
}); });
if (permalink === null) {
logger.report(
onBrokenMarkdownLinks,
)`Blog markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath}`;
}
return permalink;
}, },
}); });
@ -262,9 +257,10 @@ export default async function pluginContentBlog(
if (!blogPosts.length) { if (!blogPosts.length) {
return { return {
blogTitle,
blogDescription,
blogSidebarTitle, blogSidebarTitle,
blogPosts: [], blogPosts: [],
blogListPaginated: [],
blogTags: {}, blogTags: {},
blogTagsListPath, blogTagsListPath,
authorsMap, authorsMap,
@ -293,15 +289,9 @@ export default async function pluginContentBlog(
} }
}); });
const blogListPaginated: BlogPaginated[] = paginateBlogPosts({ // TODO this is not the correct place to aggregate and paginate tags
blogPosts: listedBlogPosts, // for reasons similar to https://github.com/facebook/docusaurus/pull/11562
blogTitle, // What we should do here is only read the tags file (similar to authors)
blogDescription,
postsPerPageOption,
basePageUrl: baseBlogUrl,
pageBasePath,
});
const blogTags: BlogTags = getBlogTags({ const blogTags: BlogTags = getBlogTags({
blogPosts, blogPosts,
postsPerPageOption, postsPerPageOption,
@ -311,9 +301,10 @@ export default async function pluginContentBlog(
}); });
return { return {
blogTitle,
blogDescription,
blogSidebarTitle, blogSidebarTitle,
blogPosts, blogPosts,
blogListPaginated,
blogTags, blogTags,
blogTagsListPath, blogTagsListPath,
authorsMap, authorsMap,

Some files were not shown because too many files have changed in this diff Show More