Compare commits

...

143 commits
v3.6.2 ... main

Author SHA1 Message Date
Shreedhar Bhat
fadb6d2607
test(reading-time): Unit tests for calculating reading time (#11116) 2025-04-30 12:47:51 +02:00
dependabot[bot]
16ebd55ef6
chore(deps): bump http-proxy-middleware from 2.0.7 to 2.0.9 (#11135)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-29 10:16:22 +02:00
dependabot[bot]
67924ca979
chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.1 to 2.9.2 (#11103)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 09:31:05 +02:00
dependabot[bot]
bf6f574383
chore(deps): bump actions/setup-node from 4.3.0 to 4.4.0 (#11102)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 09:30:51 +02:00
Sébastien Lorber
730ce485ba
feat(theme): make it possible to provide your own page title formatter (#11090) 2025-04-11 19:16:17 +02:00
Sébastien Lorber
5b944d6b64
feat(pages): Support frontMatter.slug like docs and blog plugins (#11088) 2025-04-11 14:44:19 +02:00
Sébastien Lorber
ac0a6f7d5b
chore: add pr: translations GitHub + lerna changelog label (#11087)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-11 12:51:42 +02:00
Sébastien Lorber
72b8621515
fix(theme): add missing rel="tag" attribute for docs/blog tags (#11085)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-11 11:44:12 +02:00
Sébastien Lorber
535c1c9835
docs: remove ref to Docusaurus v2 (#11084)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-11 11:05:44 +02:00
Sébastien Lorber
29d19a6884
refactor(live-codeblock): refactor live code block theme components (#11077) 2025-04-10 15:55:02 +02:00
Ben McCann
387157205a
chore(deps): upgrade cspell (#11078)
* chore(deps): upgrade cspell

* Add word

---------

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
2025-04-08 19:37:04 -04:00
Sébastien Lorber
e9dfecbce7
fix(c): fix yarn lint:spelling:fix script (#11075)
* fix lint:spelling:fix

* fix lint:spelling:fix
2025-04-08 16:11:41 +02:00
Sébastien Lorber
df5f465605
chore: upgrade Rspack 1.3.3 (#11073)
upgrade Rspack
2025-04-08 14:24:21 +02:00
Sébastien Lorber
67248f8e66
perf(core): remove bundler optimization.removeAvailableModules (#11072)
remove removeAvailableModules
2025-04-08 11:53:45 +02:00
dependabot[bot]
e8e67e9b9e
chore(deps): bump estree-util-value-to-estree from 3.1.2 to 3.3.3 (#11070)
Bumps [estree-util-value-to-estree](https://github.com/remcohaszing/estree-util-value-to-estree) from 3.1.2 to 3.3.3.
- [Release notes](https://github.com/remcohaszing/estree-util-value-to-estree/releases)
- [Commits](https://github.com/remcohaszing/estree-util-value-to-estree/compare/v3.1.2...v3.3.3)

---
updated-dependencies:
- dependency-name: estree-util-value-to-estree
  dependency-version: 3.3.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 11:29:46 +02:00
dependabot[bot]
08467e5f51
chore(deps): bump actions/dependency-review-action from 4.5.0 to 4.6.0 (#11069)
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](3b139cfc5f...ce3cf9537a)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 11:29:33 +02:00
Sébastien Lorber
abdd0c7995
fix(blog): fix blog Atom feed item url / XSL bug (#11068)
Fix blog Atom feed XSL
2025-04-07 19:10:01 +02:00
Sébastien Lorber
979ae084a7
feat(core): enable Rspack parallelCodeSplitting (#11067)
re-enable parallelCodeSplitting
2025-04-07 18:55:27 +02:00
Sébastien Lorber
6215983cdd
chore: upgrade mermaid, fix diagram labels bug (#11066)
* fix mermaid bug

* refactor: apply lint autofix

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-07 18:30:01 +02:00
Sébastien Lorber
b7ba0b54fb
chore: upgrade image-size deps to v2 (#11065)
* upgrade image-size to v2

* fix resizeImage script

* fix tests
2025-04-07 18:29:15 +02:00
Sébastien Lorber
31b279fea6
refactor(theme): introduce CodeBlockContextProvider + split into smaller components (#11062)
* introduce CodeBlockContextProvider

* refactor: apply lint autofix

* add comment

* move wordWrap to context

* Refactor button components

* remove console logs

* Extract more code block components

* Extract CodeBlockLineToken subcomponent

* add TODOs

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-04 20:11:40 +02:00
Sébastien Lorber
d28210d35b
refactor(theme): CodeBlock, centralize metadata parsing + refactor theme component (#11059)
* fix import duplicated

* centralize parsing of code block metadata

* split logic into many subcomponents

* extract getCodeBlockClassName

* fix duplicate useCodeWordWrap() call

* simplify JSX

* move ensureLanguageClassName logic to theme-common

* fix line highlighting bug

* rename tokens to lines

* Extract Pre/Code subcomponents

* Add tests for metadata language

* Add tests for metadata className

* Add tests for metadata title

* Add tests for metadata line highlighting

* Add tests for metadata lineNumbersStart
2025-04-04 18:15:34 +02:00
Sébastien Lorber
f6bdc3123b
refactor(theme): refactor CodeBlock parseLines logic + use inline snapshots to ease review (#11058)
* refactor codeblock parseLines logic + use inline snapshots

* refactor: apply lint autofix

* eslint

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-04-04 13:22:51 +02:00
Sébastien Lorber
16e3002911
fix(theme): navbar mobile sidebar should allow clicking dropdown parent link (#11053)
* try to repro + initial fix

* Use HTML button

* extract useItemCollapsible()

* Split DropdownNavbarItem into Mobile/Desktop subcomponents

* Add aria labels to button

* cleanup prop types

* aria label

* add translations

* cleanup types

* Split DefaultNavbarItem into Mobile/Desktop subcomponents

* revert change

* type fix
2025-04-03 18:40:45 +02:00
Sébastien Lorber
a05629eeb5
chore: use rspack 1.3.0 (#11039)
* upgrade rspack

* disable parallelCodeSplitting temporarily
2025-04-01 15:33:09 +02:00
程序员小墨
3176a2ccba
fix(theme): Fix code block magic comments with CRLF line breaks bug (#11046)
* fix: with CRLF line breaks, an extra empty line was rendered with // highlight-end at end of code blocks

See: #11036

* Add unit tests

---------

Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-04-01 15:14:02 +02:00
Daniel Kuschny
c0f3755d51
test(theme-common): Add tests for getLineNumbersStart (#11017) 2025-03-28 17:20:50 +01:00
Sébastien Lorber
dae29a2782
refactor(core): remove clean-webpack-plugin (#11037)
* remove clean-webpack-plugin

* refactor: apply lint autofix

* remove clean-webpack-plugin

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-03-27 18:44:48 +01:00
Sébastien Lorber
37d8844506
fix(cli): fix CLI write-translation bug (#11027)
* fix write-translation bug

* fix write-translation bug
2025-03-27 12:22:44 +01:00
Tatsunori Uchino
8881fd1a59
fix(theme-translation): add missing Japanese translation for System Mode (#11030) 2025-03-27 11:58:10 +01:00
Sébastien Lorber
e64e0e7c96
fix(ideal-image): fix waypoint initial scroll bug (#11026)
fiw waypoint initial scroll bug
2025-03-24 15:31:37 +01:00
Sébastien Lorber
43fdb825e8
fix(ideal-image): Internalize react-waypoint dependency, fix React 19 compatibility (#11014)
* copy waypoint, remove logs

* remove propTypes

* remove debug

* remove scrollableAncestor prop

* remove onPositionChange

* remove horizontal prop

* remove fireOnRapidScroll

* remove useless render code

* remove ensureRefIsUsedByChild

* remove children prop

* inline constants

* remove consolidated-events

* copy getCurrentPosition

* remove computeOffsetPixels

* extract findScrollableAncestor

* extract getBounds

* remove hasWindow

* remove onNextTick()

* fixes

* make it work, replace waypoint

* slim down

* slim down

* slim down

* use TypeScript

* slim down

* slim down

* revert
2025-03-20 12:33:27 +01:00
Sébastien Lorber
fcee060f40
refactor(ideal-image-plugin): internalize legacy component code (#11010)
* almost working

* refactor: apply lint autofix

* cspell ignore

* refactor: apply lint autofix

* type fixes

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-03-19 18:21:09 +01:00
Sébastien Lorber
502b9007be
perf(core): Optimize docusaurus start/serve, fix openBrowser() perf issue on macOS (#11007)
Optimize openBrowser() util
2025-03-19 13:18:32 +01:00
Sébastien Lorber
3782244ce7
feat(core): Add bundler tracing/profiling (#11006)
* Add rspack tracing/profiling

* Add CLI start PerfLogger

* cleanup BundlerCPUProfilerPlugin
2025-03-19 12:14:06 +01:00
Sébastien Lorber
e88f1aaf96
fix(mdx-loader): refactor and fix heading to toc html value serialization (#11004)
* refactor with iso behavior

* Add unit tests

* change behavior for <img> tags
2025-03-18 17:52:26 +01:00
dependabot[bot]
1d4d17da18
chore(deps): bump actions/setup-node from 4.2.0 to 4.3.0 (#11002)
* chore(deps): bump actions/setup-node from 4.2.0 to 4.3.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](1d0ff469b7...cdca7365b2)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* refactor: apply lint autofix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 10:01:00 +01:00
cylewaitforit
b0b95ccff9
fix(module-type-aliases): pin react-helmet-async to @slorber/react-helmet-async@1.3.0 (#10998) 2025-03-17 11:17:05 +01:00
Balthasar Hofer
579bb5ad37
fix(theme): CodeBlock should accept title of ReactNode type (#10999)
* allow ReactNode for CodeBlock title

* fix example
2025-03-17 11:03:10 +01:00
dependabot[bot]
7d36e2a8ff
chore(deps): bump @babel/runtime-corejs3 from 7.25.9 to 7.26.10 (#10990)
Bumps [@babel/runtime-corejs3](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs3) from 7.25.9 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime-corejs3)

---
updated-dependencies:
- dependency-name: "@babel/runtime-corejs3"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 18:51:00 +01:00
dependabot[bot]
39eded7b69
chore(deps): bump axios from 1.7.7 to 1.8.2 (#10970)
Bumps [axios](https://github.com/axios/axios) from 1.7.7 to 1.8.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.7...v1.8.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 18:32:20 +01:00
Sébastien Lorber
cb69b40c86
fix(theme): mobile drawer history blocker should be rendered conditionally (workaround) (#10989)
Add history blocker workaround
2025-03-14 18:22:00 +01:00
Sébastien Lorber
7cf94c03a4
feat(theme): Allow resetting colorMode to System/OS value (#10987)
* make it work

* fix

* Try to fix accessibility issues

* add translations

* rename 'auto' to 'system'

* refactor: apply lint autofix

* rename 'auto' to 'system'

* remove title prop

* typo

* use shorter title

* refactor: apply lint autofix

* document useColorMode tradeoffs + data-attribute variables

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
Co-authored-by: nasso
Co-authored-by: OzakIOne
2025-03-14 13:45:25 +01:00
pedenys
fd51384cab
docs: update external link to MDX reference (#10981)
Update markdown-features-code-blocks.mdx

Update external link to MDX reference
2025-03-13 10:53:45 +01:00
Jake Boone
549ab795c3
feat(plugin-npm2yarn): Add Bun to default tabs conversions (#10953)
* fix(plugin-npm2yarn): Add Bun as default to align with docs

* fix(plugin-npm2yarn): update test snapshot with bunx

* fix(plugin-npm2yarn): update test snapshot with bunx-create

* fix(plugin-npm2yarn): update screenshot to add pnpm and Bun

---------

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
2025-03-11 09:37:01 +01:00
dependabot[bot]
e2e85e6b50
chore(deps): bump prismjs from 1.29.0 to 1.30.0 (#10978)
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.29.0 to 1.30.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.29.0...v1.30.0)

---
updated-dependencies:
- dependency-name: prismjs
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 20:29:27 -04:00
Sébastien Lorber
15b0ef6d13
chore: add eslint-plugin-react-compiler (#10969)
* install ESLint plugin

* fix eslint CodeBlockLine error

* eslint

* eslint

* eslint

* refactor: apply lint autofix

* empty

---------

Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-03-07 18:04:40 +01:00
Sébastien Lorber
d33004da1e
chore: upgrade monorepo to TS 5.8 (#10966)
* Upgrade to TS 5.8

* increase build perf CI timeout values

* enable erasableSyntaxOnly

* enable erasableSyntaxOnly
2025-03-06 12:33:11 +01:00
Sébastien Lorber
dec3bcbbd7
fix(create-docusaurus): fix CLI and remove shelljs escapeShellArg util (#10958) 2025-02-28 20:09:59 +01:00
dependabot[bot]
2976dfea72
chore(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7 (#10957)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 19:07:23 +01:00
Sébastien Lorber
4d3930f944
refactor: remove react-dev-utils (CRA) dependency, internalize code (#10956)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-02-28 18:49:27 +01:00
ozaki
7f4a37949e
refactor: replace unmaintained shelljs dependency by execa (#10358)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-02-28 14:31:01 +01:00
Hidde de Vries
a6ef3897e0
fix(theme): only render secondaryMenu if it should be shown (#10705)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-02-27 16:39:03 +01:00
Sébastien Lorber
396deedba4
fix(theme): fix useColorMode().colorMode leading to React hydration mismatches (#10954) 2025-02-27 16:32:28 +01:00
マルコメ
9d7ceec189
docs: add missing code block language to README.md (#10952) 2025-02-26 10:15:03 +01:00
kilavvy
154c95c11c
docs: typo in documentation files (#10950) 2025-02-25 13:38:38 +01:00
Joshua Chen
f31bfec3c9
fix(theme-classic): fix ThemeClassName reference (#10948) 2025-02-24 02:07:16 -05:00
Sébastien Lorber
ca035d8562
feat(theme): add theme layout stable CSS classes (#10945) 2025-02-21 19:03:49 +01:00
Yangshun Tay
c10a18d51d
misc(blog): Update Yangshun bio (#10942) 2025-02-21 12:16:03 +01:00
Sébastien Lorber
e641568e7f
feat(core): Docusaurus Faster - Rspack Persistent Cache (#10931) 2025-02-21 11:39:48 +01:00
Massoud Maboudi
5b848cb2f0
docs(showcase): Update datagit.ir showcase image, description, and tags (#10939) 2025-02-20 13:04:16 +01:00
Sébastien Lorber
cdc3ba31d9
chore(algolia): bump docsearch dependency to v3.9 (#10941) 2025-02-20 11:25:52 +01:00
dependabot[bot]
1a71b3863a
chore(deps): bump dompurify from 3.1.6 to 3.2.4 (#10937)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 13:30:44 +01:00
dependabot[bot]
871af414a5
chore(deps): bump preactjs/compressed-size-action from 2.7.0 to 2.8.0 (#10936)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 12:56:25 +01:00
Taras
75e5a00a66
docs: disable plugin-debug in production by default (#10928) 2025-02-16 15:22:59 +01:00
Sébastien Lorber
af272bdefa
fix(docs): fix mdx loader cache invalidation bug on versions changes (#10934) 2025-02-14 17:46:41 +01:00
Sébastien Lorber
a72a06ecb1
fix(plugins): add missing validateOptions types (#10929)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-02-13 15:29:51 +01:00
Milica
04f7972f32
docs: updating showcase site link (#10925) 2025-02-13 12:21:15 +01:00
John Reilly
45065e8d2b
fix(seo): docs breadcrumb structured data should use JSON-LD and filter unliked categories (#10888)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-02-07 19:03:10 +01:00
Sébastien Lorber
cd7875bf84
docs: move docs of frontMatter.title_meta from docs to blog plugin (#10916) 2025-02-07 16:57:23 +01:00
Sébastien Lorber
5331de2962
fix(theme): collapse doc sidebar category on label click if active (#10886) 2025-02-07 16:18:36 +01:00
Sébastien Lorber
c5a793de9d
fix(core): use os.availableParallelism() for SSG worker threads count (#10915) 2025-02-07 16:05:02 +01:00
Sébastien Lorber
cd2792775e
fix(ideal-image): Add issuer to ideal-image Webpack loader (#10910) 2025-02-06 14:13:46 +01:00
Max Schmitt
3fde4a0d6a
fix(core): a11y fix on mobile DropdownNavbarItem (#10898) 2025-02-06 13:25:54 +01:00
Sébastien Lorber
b76f0feadc
fix(theme): apply docs sidebar_class_name in DocCard + better dogfooding (#10909) 2025-02-06 13:08:33 +01:00
reece-white
0162f6abc6
chore(plugin-debug): upgrade react-json-view-lite to v2.3.0 for react 19 (#10903) 2025-02-06 10:43:08 +01:00
Yoshiaki Yoshida
801bc7f74a
docs: update Cloudflare Pages deployment link (#10901) 2025-02-06 10:22:47 +01:00
Justin D Mathew
987eb1c6d2
docs(theme-live-codeblock): update versioned docs to include link to react-live (#10902) 2025-02-06 10:10:53 +01:00
Ramazan Sancar
f73d401d3a
fix(theme-translations): Turkish exist language translate completed. (#10893) 2025-02-04 17:43:37 +01:00
Tatsunori Uchino
a0248ed404
docs: Suggest remark-cjk-friendly in migration guide (#10892) 2025-02-03 13:02:20 +01:00
Waldir Pimenta
3198de8c45
docs: Clarify how to enable math equations (#10894)
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
2025-02-03 12:58:05 +01:00
Stephen Glass
dee39835a1
docs: fix grammar for installation docs (#10889) 2025-02-03 12:56:56 +01:00
Sébastien Lorber
7ca3aa5144
perf(theme): use SVG sprite for IconExternalLink (#10885) 2025-01-31 17:28:04 +01:00
Hichem Fantar
884f93eea8
fix(theme): fix <DocCard> height inconsistency (#10849)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-01-31 15:25:10 +01:00
jkboxomine
3b72bb43db
fix(docs): versioning CLI should copy localized translation file current.json to version-<v>.json (#10875)
Co-authored-by: Sungchang Ha <bryan98@naver.com>
2025-01-31 12:50:13 +01:00
Mariusz Krzaczkowski
bc3445c344
fix(theme-translations): Add missing Polish (pl) theme translations (#10884) 2025-01-31 11:30:00 +01:00
Kenneth Ormandy
78f44d0ae7
fix(theme): Hide code block buttons before React hydration (#10866) 2025-01-30 18:24:33 +01:00
Oleksiy Gapotchenko
4d7a28963a
feat(theme): add versions attribute to docsVersionDropdown navbar item (#10852)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2025-01-30 18:21:54 +01:00
Justin D Mathew
8bc3e8a092
docs(theme-live-codeblock): update theme-live-codeblock.mdx to include link to react-live (#10874) 2025-01-30 13:02:17 +01:00
dependabot[bot]
d025403f73
chore(deps): bump actions/setup-node from 4.1.0 to 4.2.0 (#10873)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 10:40:48 +01:00
Sébastien Lorber
5dc472759f
refactor(create-docusaurus): add future.v4 flag to init templates (#10871) 2025-01-27 16:05:12 +01:00
Tatsunori Uchino
b6d9fe2843
chore(deps): bump @rspack/core in Faster from 1.2.0-alpha.0 to 1.2.2 (#10870) 2025-01-27 15:32:10 +01:00
Sébastien Lorber
98aab81388
feat(core): Docusaurus Faster - SSG worker threads (#10826)
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
Co-authored-by: Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
Co-authored-by: João Victor Lopes <joaof.victor@hotmail.com>
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-01-27 14:24:30 +01:00
dependabot[bot]
042070cf9d
chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.0 to 2.9.1 (#10853)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-22 10:05:13 +01:00
dependabot[bot]
9700d47d69
chore(deps): bump katex from 0.16.11 to 0.16.21 (#10851)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 22:55:44 +01:00
Sébastien Lorber
9df5aae6de
feat(core): new postBuild({routesBuildMetadata}) API, deprecate head attribute + v4 future flag (#10850)
Co-authored-by: slorber <749374+slorber@users.noreply.github.com>
2025-01-17 17:26:48 +01:00
Sébastien Lorber
67207bc5e5
fix(theme): Fix <DocCardList> usage on docs at root of a sidebar (#10847)
Fix `<DocCardList>` usage on docs at root of a sidebar
2025-01-16 21:53:41 +01:00
Sébastien Lorber
e59355be76
feat(theme): code block showLineNumbers=start metastring (#10846) 2025-01-16 17:28:04 +01:00
João Victor Lopes
fcc9e5c56a
docs(website): Comparison with Rspress (#10822)
Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
2025-01-07 12:11:51 +01:00
Mariusz Krzaczkowski
5a50522905
fix(theme-translations): Add missing Polish (pl) theme translations (#10825) 2025-01-07 11:30:52 +01:00
Sébastien Lorber
97690abc94
fix(core): restore core svg file-loader (#10820) 2025-01-06 17:54:43 +01:00
Sébastien Lorber
35259521e0
chore(plugin-debug): upgrade react-json-view-lite to v2, prepare for React 19 (#10819) 2025-01-06 16:01:29 +01:00
Sébastien Lorber
431526ecbc
fix: perflogger mark detail bug (#10818) 2025-01-06 14:13:14 +01:00
FISH UP
0df69844b6
chore(theme-translations): add missing zh theme translations (#10816)
* fix(theme-translation): add missing zh-Hant theme translations

* fix(theme-translation): add missing zh-Hans theme translations
2025-01-05 19:38:25 -05:00
Sébastien Lorber
c17b55b58f
chore: update examples for v3.7.0 (#10814) 2025-01-03 19:32:21 +01:00
Sébastien Lorber
71d682c53b
chore: release Docusaurus 3.7.0 (#10812) 2025-01-03 18:11:21 +01:00
Sébastien Lorber
cacb973326
feat(core): Turn Rspack incremental on by default (again) (#10800) 2025-01-03 14:23:26 +01:00
Jake Boone
94a56fef08
refactor: reduce file size of docusaurus.svg (#10806) 2025-01-03 12:19:25 +01:00
Ivan Cheban
1b44d7ae3c
docs: simplify sidebar description (#10810) 2025-01-03 12:04:26 +01:00
Hichem Fantar
bdbdd5aff5
chore: specify package manager version in package.json (#10807) 2025-01-03 11:54:11 +01:00
Lehoczky Zoltán
9800180f57
fix(npm-to-yarn): add missing npm-to-yarn converter for Bun (#10803) 2024-12-30 17:22:26 +01:00
Zed Spencer-Milnes
56ccf19063
chore: Devcontainer upgrade to Ubuntu Noble & Node 22 (#10770) 2024-12-30 11:13:01 +01:00
Zed Spencer-Milnes
43795fcabb
feat(blog): Add author social icons for bluesky, mastodon, threads, twitch, youtube, instagram (#10768)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
Co-authored-by: Chas Emerick <chas@cemerick.com>
2024-12-27 12:32:25 +01:00
Sébastien Lorber
cc97d66dbb
refactor(algolia): simplify SearchBar component (#10801) 2024-12-26 18:59:00 +01:00
Sébastien Lorber
e8ad3923ea
fix(algolia): properly forward placeholder/translations to DocSearch components (#10799) 2024-12-26 16:30:23 +01:00
Sébastien Lorber
e7a8c9db82
refactor(core): Use Intl native API to get locale direction, remove rtl-detect depend… (#10798) 2024-12-26 15:44:07 +01:00
dependabot[bot]
092238d0fa
chore(deps): bump nanoid from 3.3.7 to 3.3.8 (#10771)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-26 13:47:48 +01:00
Pierre Millot
4a1ec52922
chore(algolia): upgrade algoliasearch to v5 (#10672)
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
2024-12-26 13:39:32 +01:00
Sébastien Lorber
37184e581d
fix(theme): Footer Column/Link should merge provided className (#10796) 2024-12-26 12:46:43 +01:00
Taylor Reece
e5ed9a3894
docs(showcase): Update Prismatic.io showcase image, description, and tags (#10795) 2024-12-24 16:38:24 +01:00
Sébastien Lorber
0f29a37b3a
feat: Add React 19 support to Docusaurus v3 (#10763) 2024-12-24 14:43:03 +01:00
Sébastien Lorber
f196a1eb29
fix(core): fix React hydration errors, change html minifier settings (#10786) 2024-12-23 18:45:31 +01:00
William Black
2565601af3
fix(theme-common): code block magic comments should support SQL block comments (#10782) 2024-12-20 17:16:59 +01:00
Jan Aukema
87a5ab9177
fix(theme-translations): Add missing Dutch (nl) theme translations (#10783)
Co-authored-by: Jan Aukema <j.aukema@atps.nl>
2024-12-20 17:03:03 +01:00
Sébastien Lorber
b5359db47e
refactor(website): remove pure-react-carousel (#10784) 2024-12-20 16:47:29 +01:00
Zen
c5a6c26d94
fix(theme-translation): add missing Korean (ko) theme translations (#10760) 2024-12-13 15:27:54 +01:00
Zen
9cefca42df
docs: add swizzle delete tip (#10759) 2024-12-13 15:27:03 +01:00
Sébastien Lorber
91c0b5bf35
fix(docs): fix sidebar item visibility bug for category index (#10754) 2024-12-10 13:06:21 +01:00
Sébastien Lorber
4966dce36e
refactor(core): swizzle wrap should use ReactNode instead of JSX.Element (#10747) 2024-12-06 18:24:18 +01:00
Sébastien Lorber
f9825af43e
refactor: prepare types for React 19 (#10746) 2024-12-06 18:03:04 +01:00
Alvin Bryan
e9f0641620
docs: Removed AgileTs from the Showcase (#10742) 2024-12-06 11:56:28 +01:00
Waldir Pimenta
01cad20b5a
docs: Link initialization docs together (#10740) 2024-12-05 13:55:59 +01:00
Sébastien Lorber
a995865314
feat(blog): Add frontMatter.sidebar_label (#10729) 2024-11-29 18:05:09 +01:00
Sébastien Lorber
df6f53a2f5
feat(svgr): create new Docusaurus SVGR plugin (#10677) 2024-11-29 17:26:34 +01:00
Sébastien Lorber
750edc78ff
refactor(theme-common): change storageUtils useSyncExternalCode getSnapshot workaround (#10728) 2024-11-29 16:50:10 +01:00
Sébastien Lorber
8098741245
fix(core): fix codegen routesChunkName possible hash collision (#10727) 2024-11-29 15:36:02 +01:00
Sébastien Lorber
1777b14566
chore: upgrade to TS 5.7 (#10725) 2024-11-28 16:51:42 +01:00
Sébastien Lorber
fb7ad2c1bb
fix(mdx-loader): fix md image paths with spaces bug related to transformImage encoding problem (#10723) 2024-11-28 16:39:43 +01:00
dependabot[bot]
ffdd415129
chore(deps): bump actions/dependency-review-action from 4.4.0 to 4.5.0 (#10721)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-26 09:21:27 +01:00
Lin Huang
60499e2cdc
docs: fix example typo for migration-versioned-sites.mdx (#10717) 2024-11-25 10:20:09 +01:00
Sébastien Lorber
fd43036ab8
chore: release Docusaurus 3.6.3 (#10713) 2024-11-22 17:13:56 +01:00
Sébastien Lorber
8561826026
fix(core): disable Rspack incremental in dev (#10712) 2024-11-22 16:05:13 +01:00
Sébastien Lorber
90e85e83a5
chore: release Docusaurus 3.6.2 (#10698) 2024-11-19 19:07:06 +01:00
937 changed files with 39112 additions and 8050 deletions

View file

@ -21,11 +21,14 @@
], ],
"ignorePaths": [ "ignorePaths": [
"CHANGELOG.md", "CHANGELOG.md",
"patches",
"packages/docusaurus-theme-translations/locales", "packages/docusaurus-theme-translations/locales",
"packages/docusaurus-plugin-ideal-image/src/theme/IdealImageLegacy",
"package.json", "package.json",
"yarn.lock", "yarn.lock",
"project-words.txt", "project-words.txt",
"__snapshots__", "__snapshots__",
"admin/scripts",
"website/src/data/users.tsx", "website/src/data/users.tsx",
"website/src/data/tweets.tsx", "website/src/data/tweets.tsx",
"website/docusaurus.config.localized.json", "website/docusaurus.config.localized.json",

View file

@ -1,5 +1,7 @@
{ {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-22.04", "image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
"customizations": {
"vscode": {
"settings": { "settings": {
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
@ -19,14 +21,16 @@
"orta.vscode-jest", "orta.vscode-jest",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"streetsidesoftware.code-spell-checker" "streetsidesoftware.code-spell-checker"
], ]
}
},
"forwardPorts": [3000], "forwardPorts": [3000],
"containerUser": "vscode", "containerUser": "vscode",
"postCreateCommand": "yarn install", "postCreateCommand": "yarn install",
"waitFor": "postCreateCommand", // otherwise automated jest tests fail "waitFor": "postCreateCommand", // otherwise automated jest tests fail
"features": { "features": {
"node": { "node": {
"version": "18" "version": "22"
}, },
"github-cli": "latest" "github-cli": "latest"
} }

View file

@ -22,3 +22,6 @@ packages/create-docusaurus/templates/facebook
website/_dogfooding/_swizzle_theme_tests website/_dogfooding/_swizzle_theme_tests
website/_dogfooding/_asset-tests/badSyntax.js website/_dogfooding/_asset-tests/badSyntax.js
packages/docusaurus-plugin-ideal-image/src/theme/IdealImageLegacy

13
.eslintrc.js vendored
View file

@ -60,6 +60,7 @@ module.exports = {
}, },
reportUnusedDisableDirectives: true, reportUnusedDisableDirectives: true,
plugins: [ plugins: [
'react-compiler',
'react-hooks', 'react-hooks',
'header', 'header',
'jest', 'jest',
@ -68,6 +69,7 @@ module.exports = {
'@docusaurus', '@docusaurus',
], ],
rules: { rules: {
'react-compiler/react-compiler': ERROR,
'react/jsx-uses-react': OFF, // JSX runtime: automatic 'react/jsx-uses-react': OFF, // JSX runtime: automatic
'react/react-in-jsx-scope': OFF, // JSX runtime: automatic 'react/react-in-jsx-scope': OFF, // JSX runtime: automatic
'array-callback-return': WARNING, 'array-callback-return': WARNING,
@ -296,7 +298,7 @@ module.exports = {
'jest/expect-expect': OFF, 'jest/expect-expect': OFF,
'jest/no-large-snapshots': [ 'jest/no-large-snapshots': [
WARNING, WARNING,
{maxSize: Infinity, inlineMaxSize: 10}, {maxSize: Infinity, inlineMaxSize: 50},
], ],
'jest/no-test-return-statement': ERROR, 'jest/no-test-return-statement': ERROR,
'jest/prefer-expect-resolves': WARNING, 'jest/prefer-expect-resolves': WARNING,
@ -380,7 +382,14 @@ module.exports = {
// We don't provide any escape hatches for this rule. Rest siblings and // We don't provide any escape hatches for this rule. Rest siblings and
// function placeholder params are always ignored, and any other unused // function placeholder params are always ignored, and any other unused
// locals must be justified with a disable comment. // locals must be justified with a disable comment.
'@typescript-eslint/no-unused-vars': [ERROR, {ignoreRestSiblings: true}], '@typescript-eslint/no-unused-vars': [
ERROR,
{
ignoreRestSiblings: true,
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/prefer-optional-chain': ERROR, '@typescript-eslint/prefer-optional-chain': ERROR,
'@docusaurus/no-html-links': ERROR, '@docusaurus/no-html-links': ERROR,
'@docusaurus/prefer-docusaurus-heading': ERROR, '@docusaurus/prefer-docusaurus-heading': ERROR,

View file

@ -30,7 +30,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*

View file

@ -24,7 +24,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -27,7 +27,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -43,12 +43,12 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.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@6fa0e7ca017120c754863b31123c5ee2860fd434 # v2 uses: preactjs/compressed-size-action@946a292cd35bd1088e0d7eb92b69d1a8d5b5d76a # v2
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
build-script: build:website:fast build-script: build:website:fast
@ -75,7 +75,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -85,14 +85,15 @@ jobs:
# Ensure build with a cold cache does not increase too much # Ensure build with a cold cache does not increase too much
- name: Build (cold cache) - name: Build (cold cache)
run: yarn build:website:fast run: yarn build:website:fast
timeout-minutes: ${{ matrix.DOCUSAURUS_INFRA == 'SLOWER' && 3 || 1 }} 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' }}
# 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)
run: yarn build:website:fast run: yarn build:website:fast
timeout-minutes: 1 # Temporary: upper value for Rspack until incremental cache works better
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' }}

View file

@ -24,7 +24,7 @@ jobs:
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@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -15,4 +15,4 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Dependency Review - name: Dependency Review
uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a # 4.4.0 uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 # 4.6.0

View file

@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
@ -64,7 +64,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@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # 2.9.0 uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # 2.9.2
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

@ -22,7 +22,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -33,7 +33,7 @@ jobs:
- name: Check for suspicious yarn.lock - name: Check for suspicious yarn.lock
# for allowed aliases, see https://github.com/yargs/cliui/pull/139/files#r1670711112 # for allowed aliases, see https://github.com/yargs/cliui/pull/139/files#r1670711112
run: yarn lockfile-lint --path yarn.lock --type yarn --allowed-hosts yarn --validate-https --validate-package-names --validate-integrity --empty-hostname=false --allowed-package-name-aliases react-loadable string-width-cjs strip-ansi-cjs wrap-ansi-cjs run: yarn lockfile-lint --path yarn.lock --type yarn --allowed-hosts yarn --validate-https --validate-package-names --validate-integrity --empty-hostname=false --allowed-package-name-aliases react-loadable react-helmet-async string-width-cjs strip-ansi-cjs wrap-ansi-cjs
- name: Lint - name: Lint
run: | run: |

View file

@ -24,7 +24,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -43,7 +43,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
cache: yarn cache: yarn
@ -68,7 +68,7 @@ jobs:
env: env:
# Our website should build even with limited memory # Our website should build even with limited memory
# See https://github.com/facebook/docusaurus/pull/10590 # See https://github.com/facebook/docusaurus/pull/10590
NODE_OPTIONS: '--max-old-space-size=250' NODE_OPTIONS: '--max-old-space-size=300'
DOCUSAURUS_PERF_LOGGER: 'true' DOCUSAURUS_PERF_LOGGER: 'true'
working-directory: ../test-website working-directory: ../test-website
@ -84,7 +84,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -153,7 +153,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -181,7 +181,7 @@ jobs:
env: env:
# Our website should build even with limited memory # Our website should build even with limited memory
# See https://github.com/facebook/docusaurus/pull/10590 # See https://github.com/facebook/docusaurus/pull/10590
NODE_OPTIONS: '--max-old-space-size=250' NODE_OPTIONS: '--max-old-space-size=300'
DOCUSAURUS_PERF_LOGGER: 'true' DOCUSAURUS_PERF_LOGGER: 'true'
working-directory: ../test-website working-directory: ../test-website
@ -193,7 +193,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js LTS - name: Use Node.js LTS
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn
@ -223,6 +223,6 @@ jobs:
env: env:
# Our website should build even with limited memory # Our website should build even with limited memory
# See https://github.com/facebook/docusaurus/pull/10590 # See https://github.com/facebook/docusaurus/pull/10590
NODE_OPTIONS: '--max-old-space-size=250' NODE_OPTIONS: '--max-old-space-size=300'
DOCUSAURUS_PERF_LOGGER: 'true' DOCUSAURUS_PERF_LOGGER: 'true'
working-directory: ../test-website working-directory: ../test-website

View file

@ -28,7 +28,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node LTS - name: Set up Node LTS
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: lts/* node-version: lts/*
cache: yarn cache: yarn

View file

@ -34,7 +34,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
- name: Installation - name: Installation

View file

@ -32,7 +32,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Use Node.js ${{ matrix.node }} - name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
cache: yarn cache: yarn
@ -49,7 +49,7 @@ jobs:
env: env:
# Our website should build even with limited memory # Our website should build even with limited memory
# See https://github.com/facebook/docusaurus/pull/10590 # See https://github.com/facebook/docusaurus/pull/10590
NODE_OPTIONS: '--max-old-space-size=400' NODE_OPTIONS: '--max-old-space-size=450'
DOCUSAURUS_PERF_LOGGER: 'true' DOCUSAURUS_PERF_LOGGER: 'true'
- name: Docusaurus site CSS order - name: Docusaurus site CSS order
run: yarn workspace website test:css-order run: yarn workspace website test:css-order

3
.gitignore vendored
View file

@ -45,3 +45,6 @@ website/i18n/**/*
#!website/i18n/fr/**/* #!website/i18n/fr/**/*
.netlify .netlify
website/rspack-tracing.json
website/bundler-cpu-profile.json

View file

@ -4,6 +4,7 @@ node_modules
build build
coverage coverage
.docusaurus .docusaurus
.idea
.svg .svg
*.svg *.svg

View file

@ -1,5 +1,121 @@
# Docusaurus Changelog # Docusaurus Changelog
## 3.7.0 (2025-01-03)
#### :rocket: New Feature
- `docusaurus-faster`, `docusaurus`
- [#10800](https://github.com/facebook/docusaurus/pull/10800) feat(core): Turn Rspack incremental on by default (again) ([@slorber](https://github.com/slorber))
- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`
- [#10768](https://github.com/facebook/docusaurus/pull/10768) feat(blog): Add author social icons for bluesky, mastodon, threads, twitch, youtube, instagram ([@GingerGeek](https://github.com/GingerGeek))
- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-google-tag-manager`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-rsdoctor`, `docusaurus-plugin-sitemap`, `docusaurus-plugin-svgr`, `docusaurus-plugin-vercel-analytics`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-mermaid`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus`
- [#10763](https://github.com/facebook/docusaurus/pull/10763) feat: Add React 19 support to Docusaurus v3 ([@slorber](https://github.com/slorber))
- `docusaurus-plugin-content-blog`
- [#10729](https://github.com/facebook/docusaurus/pull/10729) feat(blog): Add `frontMatter.sidebar_label` ([@slorber](https://github.com/slorber))
- `docusaurus-module-type-aliases`, `docusaurus-plugin-svgr`, `docusaurus-preset-classic`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`
- [#10677](https://github.com/facebook/docusaurus/pull/10677) feat(svgr): create new Docusaurus SVGR plugin ([@slorber](https://github.com/slorber))
#### :bug: Bug Fix
- `docusaurus-remark-plugin-npm2yarn`
- [#10803](https://github.com/facebook/docusaurus/pull/10803) fix(npm-to-yarn): add missing npm-to-yarn converter for Bun ([@Lehoczky](https://github.com/Lehoczky))
- `docusaurus-theme-classic`, `docusaurus-theme-common`
- [#10796](https://github.com/facebook/docusaurus/pull/10796) fix(theme): Footer Column/Link should merge provided className ([@slorber](https://github.com/slorber))
- `docusaurus-bundler`, `docusaurus-theme-common`
- [#10786](https://github.com/facebook/docusaurus/pull/10786) fix(core): fix React hydration errors, change html minifier settings ([@slorber](https://github.com/slorber))
- `docusaurus-theme-common`
- [#10782](https://github.com/facebook/docusaurus/pull/10782) fix(theme-common): code block magic comments should support SQL block comments ([@WillBlack403](https://github.com/WillBlack403))
- `docusaurus-theme-translations`
- [#10783](https://github.com/facebook/docusaurus/pull/10783) fix(theme-translations): Add missing Dutch (nl) theme translations ([@janaukema](https://github.com/janaukema))
- [#10760](https://github.com/facebook/docusaurus/pull/10760) fix(theme-translation): add missing Korean (ko) theme translations ([@effozen](https://github.com/effozen))
- `docusaurus-plugin-content-docs`
- [#10754](https://github.com/facebook/docusaurus/pull/10754) fix(docs): fix sidebar item visibility bug for category index ([@slorber](https://github.com/slorber))
- `docusaurus`
- [#10727](https://github.com/facebook/docusaurus/pull/10727) fix(core): fix codegen routesChunkName possible hash collision ([@slorber](https://github.com/slorber))
- `docusaurus-mdx-loader`
- [#10723](https://github.com/facebook/docusaurus/pull/10723) fix(mdx-loader): fix md image paths with spaces bug related to transformImage encoding problem ([@slorber](https://github.com/slorber))
#### :memo: Documentation
- [#10740](https://github.com/facebook/docusaurus/pull/10740) docs: Link initialization docs together ([@waldyrious](https://github.com/waldyrious))
#### :robot: Dependencies
- [#10771](https://github.com/facebook/docusaurus/pull/10771) chore(deps): bump nanoid from 3.3.7 to 3.3.8 ([@dependabot[bot]](https://github.com/apps/dependabot))
- [#10721](https://github.com/facebook/docusaurus/pull/10721) chore(deps): bump actions/dependency-review-action from 4.4.0 to 4.5.0 ([@dependabot[bot]](https://github.com/apps/dependabot))
#### :wrench: Maintenance
- Other
- [#10770](https://github.com/facebook/docusaurus/pull/10770) chore: Devcontainer upgrade to Ubuntu Noble & Node 22 ([@GingerGeek](https://github.com/GingerGeek))
- `docusaurus-theme-search-algolia`
- [#10801](https://github.com/facebook/docusaurus/pull/10801) refactor(algolia): simplify SearchBar component ([@slorber](https://github.com/slorber))
- [#10672](https://github.com/facebook/docusaurus/pull/10672) chore(algolia): upgrade algoliasearch to v5 ([@millotp](https://github.com/millotp))
- `docusaurus`
- [#10798](https://github.com/facebook/docusaurus/pull/10798) refactor(core): Use Intl native API to get locale direction, remove rtl-detect depend… ([@slorber](https://github.com/slorber))
- [#10747](https://github.com/facebook/docusaurus/pull/10747) refactor(core): swizzle wrap should use ReactNode instead of JSX.Element ([@slorber](https://github.com/slorber))
- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-mermaid`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus`
- [#10746](https://github.com/facebook/docusaurus/pull/10746) refactor: prepare types for React 19 ([@slorber](https://github.com/slorber))
- `docusaurus-theme-common`
- [#10728](https://github.com/facebook/docusaurus/pull/10728) refactor(theme-common): change storageUtils useSyncExternalCode getSnapshot workaround ([@slorber](https://github.com/slorber))
#### Committers: 14
- Alvin Bryan ([@alvinometric](https://github.com/alvinometric))
- Hichem Fantar ([@hichemfantar](https://github.com/hichemfantar))
- Ivan Cheban ([@ivancheban](https://github.com/ivancheban))
- Jake Boone ([@jakeboone02](https://github.com/jakeboone02))
- Jan Aukema ([@janaukema](https://github.com/janaukema))
- Lehoczky Zoltán ([@Lehoczky](https://github.com/Lehoczky))
- Lin Huang ([@codimiracle](https://github.com/codimiracle))
- Pierre Millot ([@millotp](https://github.com/millotp))
- Sébastien Lorber ([@slorber](https://github.com/slorber))
- Taylor Reece ([@taylorreece](https://github.com/taylorreece))
- Waldir Pimenta ([@waldyrious](https://github.com/waldyrious))
- William Black ([@WillBlack403](https://github.com/WillBlack403))
- Zed Spencer-Milnes ([@GingerGeek](https://github.com/GingerGeek))
- Zen ([@effozen](https://github.com/effozen))
## 3.6.3 (2024-11-22)
#### :bug: Bug Fix
- `docusaurus`
- [#10712](https://github.com/facebook/docusaurus/pull/10712) fix(core): disable Rspack incremental in dev ([@slorber](https://github.com/slorber))
#### Committers: 1
- Sébastien Lorber ([@slorber](https://github.com/slorber))
## 3.6.2 (2024-11-19)
#### :bug: Bug Fix
- `docusaurus-module-type-aliases`
- [#10693](https://github.com/facebook/docusaurus/pull/10693) fix(types): add missing ambiant TS declarations for .md / .mdx partials ([@slorber](https://github.com/slorber))
- `docusaurus-theme-translations`
- [#10688](https://github.com/facebook/docusaurus/pull/10688) fix(theme-translation): add and update Japanese translations ([@Ryoga-exe](https://github.com/Ryoga-exe))
- `docusaurus`
- [#10685](https://github.com/facebook/docusaurus/pull/10685) fix(cli): `docusaurus --help` should print plugin commands using `extendCli()` ([@slorber](https://github.com/slorber))
- `docusaurus-bundler`
- [#10680](https://github.com/facebook/docusaurus/pull/10680) fix(bundler): allow CSS nesting by default, restore postcss-preset-env ([@slorber](https://github.com/slorber))
- `create-docusaurus`
- [#10676](https://github.com/facebook/docusaurus/pull/10676) fix(create-docusaurus): add ts exclude to TS init template ([@slorber](https://github.com/slorber))
- `docusaurus-bundler`, `docusaurus-faster`, `docusaurus`
- [#10648](https://github.com/facebook/docusaurus/pull/10648) fix(faster): Upgrade to Rspack 1.1.1, fix build progress bar display ([@slorber](https://github.com/slorber))
#### :wrench: Maintenance
- [#10691](https://github.com/facebook/docusaurus/pull/10691) chore(ci): retry `yarn install` to ignore temporary network errors ([@slorber](https://github.com/slorber))
#### Committers: 5
- Junior_Gx ([@goffxnca](https://github.com/goffxnca))
- Kyle Tsang ([@kyletsang](https://github.com/kyletsang))
- Ryoga ([@Ryoga-exe](https://github.com/Ryoga-exe))
- Sébastien Lorber ([@slorber](https://github.com/slorber))
- Zwyx ([@Zwyx](https://github.com/Zwyx))
## 3.6.1 (2024-11-08) ## 3.6.1 (2024-11-08)
#### :bug: Bug Fix #### :bug: Bug Fix

View file

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

View file

@ -9,9 +9,9 @@ import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import {fileURLToPath} from 'url'; import {fileURLToPath} from 'url';
import {program} from 'commander'; import {program} from 'commander';
import logger from '@docusaurus/logger'; import {logger} from '@docusaurus/logger';
import sharp from 'sharp'; import sharp from 'sharp';
import imageSize from 'image-size'; import {imageSizeFromFile} from 'image-size/fromFile';
// You can use it as: // You can use it as:
// //
@ -64,7 +64,7 @@ program
await Promise.all( await Promise.all(
images.map(async (imgPath) => { images.map(async (imgPath) => {
const {width, height} = imageSize(imgPath); const {width, height} = await imageSizeFromFile(imgPath);
const targetWidth = const targetWidth =
options.width ?? (imgPath.includes(showcasePath) ? 640 : 1000); options.width ?? (imgPath.includes(showcasePath) ? 640 : 1000);
const targetHeight = const targetHeight =

View file

@ -5,7 +5,9 @@
# This source code is licensed under the MIT license found in the # This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree. # LICENSE file in the root directory of this source tree.
set -euo pipefail set -xeuo pipefail
rm -rf ../test-website
CUSTOM_REGISTRY_URL="http://localhost:4873" CUSTOM_REGISTRY_URL="http://localhost:4873"
NEW_VERSION="$(node -p "require('./packages/docusaurus/package.json').version")-NEW" NEW_VERSION="$(node -p "require('./packages/docusaurus/package.json').version")-NEW"
@ -52,7 +54,8 @@ git diff --name-only -- '*.json' | sed 's, ,\\&,g' | xargs git checkout --
cd .. cd ..
# Build skeleton website with new version # Build skeleton website with new version
npm_config_registry="$CUSTOM_REGISTRY_URL" npx 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
# Stop Docker container # Stop Docker container
if [[ -z "${KEEP_CONTAINER:-true}" ]] && ( $(docker container inspect "$CONTAINER_NAME" > /dev/null 2>&1) ); then if [[ -z "${KEEP_CONTAINER:-true}" ]] && ( $(docker container inspect "$CONTAINER_NAME" > /dev/null 2>&1) ); then

View file

@ -12,7 +12,7 @@ import {version as ReactVersion} from 'react';
import {version as ReactDOMVersion} from 'react-dom'; import {version as ReactDOMVersion} from 'react-dom';
export function TestComponent() { export function TestComponent() {
const expectedVersion = 18; const expectedVersion = 19;
if (!ReactVersion.startsWith(`${expectedVersion}`)) { if (!ReactVersion.startsWith(`${expectedVersion}`)) {
throw new Error( throw new Error(
`'test-bad-package/README.mdx' is rendered with bad React version: ${ReactVersion}`, `'test-bad-package/README.mdx' is rendered with bad React version: ${ReactVersion}`,

View file

@ -1,6 +1,6 @@
{ {
"name": "test-bad-package", "name": "test-bad-package",
"version": "3.6.1", "version": "3.7.0",
"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.6.1", "version": "3.7.0",
"description": "Argos visual diff tests", "description": "Argos visual diff tests",
"license": "MIT", "license": "MIT",
"private": true, "private": true,

View file

@ -55,7 +55,6 @@ function isBlacklisted(pathname: string) {
'/tests/pages/react-18', '/tests/pages/react-18',
// Flaky because of hydration error // Flaky because of hydration error
'/tests/blog/archive', '/tests/blog/archive',
'/tests/docs/tests/custom-props',
'/tests/pages/code-block-tests', '/tests/pages/code-block-tests',
'/tests/pages/embeds', '/tests/pages/embeds',
// Flaky because of hydration error with docusaurus serve + .html // Flaky because of hydration error with docusaurus serve + .html
@ -131,23 +130,18 @@ function throwOnConsole(page: Page) {
const typesToCheck = ['error', 'warning']; const typesToCheck = ['error', 'warning'];
const ignoreMessages = [ const ignoreMessages = [
// This mismatch warning looks like a React 18 bug to me
'Warning: Prop `%s` did not match. Server: %s Client: %s%s className "null" ""',
// TODO this fetch error message is unexpected and should be fixed // TODO this fetch error message is unexpected and should be fixed
// 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 looks like a legit hydration bug to fix // TODO legit hydration bugs to fix on embeds of /docs/styling-layout
// on /blog/releases/2.4 // useLocation() returns window.search/hash immediately :s
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-theme=light"', '/docs/configuration?docusaurus-theme=light',
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-theme=dark"', '/docs/configuration?docusaurus-theme=dark',
// on /blog/releases/3.0
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-data-navbar=false&docusaurus-data-red-border"', // Warning because react-live not supporting React automatic JSX runtime
// on /docs/styling-layout // See https://github.com/FormidableLabs/react-live/issues/405
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs" "/docs?docusaurus-data-navbar=false&docusaurus-data-red-border"', 'Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance',
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs/configuration" "/docs/configuration?docusaurus-theme=light"',
'Warning: Prop `%s` did not match. Server: %s Client: %s%s href "/docs/configuration" "/docs/configuration?docusaurus-theme=dark"',
// TODO weird problem related to KaTeX fonts refusing to decode? // TODO weird problem related to KaTeX fonts refusing to decode?
// on /docs/markdown-features/math-equations // on /docs/markdown-features/math-equations

2
examples/README.md generated
View file

@ -2,7 +2,7 @@
These example projects are generated with the init CLI: These example projects are generated with the init CLI:
``` ```bash
npx @docusaurus/init@latest init examples/<templateName> <templateName>` npx @docusaurus/init@latest init examples/<templateName> <templateName>`
``` ```

View file

@ -4,13 +4,13 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati
### Installation ### Installation
``` ```bash
$ yarn $ yarn
``` ```
### Local Development ### Local Development
``` ```bash
$ yarn start $ yarn start
``` ```
@ -18,7 +18,7 @@ This command starts a local development server and opens up a browser window. Mo
### Build ### Build
``` ```bash
$ yarn build $ yarn build
``` ```
@ -28,13 +28,13 @@ This command generates static content into the `build` directory and can be serv
Using SSH: Using SSH:
``` ```bash
$ USE_SSH=true yarn deploy $ USE_SSH=true yarn deploy
``` ```
Not using SSH: Not using SSH:
``` ```bash
$ GIT_USER=<Your GitHub username> yarn deploy $ GIT_USER=<Your GitHub username> yarn deploy
``` ```

View file

@ -16,18 +16,18 @@
"dev": "docusaurus start" "dev": "docusaurus start"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.0", "@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.6.0", "@docusaurus/preset-classic": "3.7.0",
"@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",
"react": "^18.0.0", "react": "^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.6.0", "@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.6.0", "@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.6.0", "@docusaurus/types": "3.7.0",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"browserslist": { "browserslist": {

View file

@ -1,3 +1,4 @@
import type {ReactNode} from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -5,7 +6,7 @@ import styles from './styles.module.css';
type FeatureItem = { type FeatureItem = {
title: string; title: string;
Svg: React.ComponentType<React.ComponentProps<'svg'>>; Svg: React.ComponentType<React.ComponentProps<'svg'>>;
description: JSX.Element; description: ReactNode;
}; };
const FeatureList: FeatureItem[] = [ const FeatureList: FeatureItem[] = [
@ -55,7 +56,7 @@ function Feature({title, Svg, description}: FeatureItem) {
); );
} }
export default function HomepageFeatures(): JSX.Element { export default function HomepageFeatures(): ReactNode {
return ( return (
<section className={styles.features}> <section className={styles.features}>
<div className="container"> <div className="container">

View file

@ -1,3 +1,4 @@
import type {ReactNode} from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
@ -28,7 +29,7 @@ function HomepageHeader() {
); );
} }
export default function Home(): JSX.Element { export default function Home(): ReactNode {
const {siteConfig} = useDocusaurusContext(); const {siteConfig} = useDocusaurusContext();
return ( return (
<Layout <Layout

View file

@ -3,5 +3,6 @@
"extends": "@docusaurus/tsconfig", "extends": "@docusaurus/tsconfig",
"compilerOptions": { "compilerOptions": {
"baseUrl": "." "baseUrl": "."
} },
"exclude": [".docusaurus", "build"]
} }

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,13 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati
### Installation ### Installation
``` ```bash
$ yarn $ yarn
``` ```
### Local Development ### Local Development
``` ```bash
$ yarn start $ yarn start
``` ```
@ -18,7 +18,7 @@ This command starts a local development server and opens up a browser window. Mo
### Build ### Build
``` ```bash
$ yarn build $ yarn build
``` ```
@ -28,13 +28,13 @@ This command generates static content into the `build` directory and can be serv
Using SSH: Using SSH:
``` ```bash
$ USE_SSH=true yarn deploy $ USE_SSH=true yarn deploy
``` ```
Not using SSH: Not using SSH:
``` ```bash
$ GIT_USER=<Your GitHub username> yarn deploy $ GIT_USER=<Your GitHub username> yarn deploy
``` ```

View file

@ -15,17 +15,17 @@
"dev": "docusaurus start" "dev": "docusaurus start"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.0", "@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.6.0", "@docusaurus/preset-classic": "3.7.0",
"@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",
"react": "^18.0.0", "react": "^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.6.0", "@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.6.0" "@docusaurus/types": "3.7.0"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{ {
"version": "3.6.1", "version": "3.7.0",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"useNx": false, "useNx": false,
@ -13,7 +13,8 @@
"pr: polish": ":nail_care: Polish", "pr: polish": ":nail_care: Polish",
"pr: documentation": ":memo: Documentation", "pr: documentation": ":memo: Documentation",
"pr: dependencies": ":robot: Dependencies", "pr: dependencies": ":robot: Dependencies",
"pr: maintenance": ":wrench: Maintenance" "pr: maintenance": ":wrench: Maintenance",
"pr: translations": ":globe_with_meridians: Translations"
}, },
"cacheDir": ".changelog" "cacheDir": ".changelog"
} }

View file

@ -15,6 +15,7 @@
"scripts": { "scripts": {
"start": "yarn build:packages && yarn start:website", "start": "yarn build:packages && yarn start:website",
"start:website": "yarn workspace website start", "start:website": "yarn workspace website start",
"start:website:profile": "DOCUSAURUS_BUNDLER_CPU_PROFILE=true DOCUSAURUS_RSPACK_TRACE=true yarn workspace website start",
"start:website:baseUrl": "yarn workspace website start:baseUrl", "start:website:baseUrl": "yarn workspace website start:baseUrl",
"start:website:blogOnly": "yarn workspace website start:blogOnly", "start:website:blogOnly": "yarn workspace website start:blogOnly",
"start:website:deployPreview": "cross-env NETLIFY=true CONTEXT='deploy-preview' yarn workspace website start", "start:website:deployPreview": "cross-env NETLIFY=true CONTEXT='deploy-preview' yarn workspace website start",
@ -22,6 +23,7 @@
"build": "yarn build:packages && yarn build:website", "build": "yarn build:packages && yarn build:website",
"build:packages": "lerna run build --no-private", "build:packages": "lerna run build --no-private",
"build:website": "yarn workspace website build", "build:website": "yarn workspace website build",
"build:website:profile": "DOCUSAURUS_BUNDLER_CPU_PROFILE=true DOCUSAURUS_RSPACK_TRACE=true yarn workspace website build",
"build:website:baseUrl": "yarn workspace website build:baseUrl", "build:website:baseUrl": "yarn workspace website build:baseUrl",
"build:website:blogOnly": "yarn workspace website build:blogOnly", "build:website:blogOnly": "yarn workspace website build:blogOnly",
"build:website:deployPreview:testWrap": "yarn workspace website test:swizzle:wrap:ts", "build:website:deployPreview:testWrap": "yarn workspace website test:swizzle:wrap:ts",
@ -50,7 +52,7 @@
"canary:bumpVersion": "yarn lerna version `yarn --silent canary:version` --exact --no-push --yes", "canary:bumpVersion": "yarn lerna version `yarn --silent canary:version` --exact --no-push --yes",
"canary:publish": "yarn lerna publish from-package --dist-tag canary --yes --no-verify-access", "canary:publish": "yarn lerna publish from-package --dist-tag canary --yes --no-verify-access",
"changelog": "lerna-changelog", "changelog": "lerna-changelog",
"postinstall": "yarn lock:update && yarn build:packages", "postinstall": "patch-package && yarn lock:update && yarn build:packages",
"prepare": "husky install", "prepare": "husky install",
"format": "prettier --write .", "format": "prettier --write .",
"format:diff": "prettier --list-different .", "format:diff": "prettier --list-different .",
@ -59,7 +61,7 @@
"lint:js": "eslint --cache --report-unused-disable-directives \"**/*.{js,jsx,ts,tsx,mjs}\"", "lint:js": "eslint --cache --report-unused-disable-directives \"**/*.{js,jsx,ts,tsx,mjs}\"",
"lint:js:fix": "yarn lint:js --fix", "lint:js:fix": "yarn lint:js --fix",
"lint:spelling": "cspell \"**\" --no-progress --show-context --show-suggestions", "lint:spelling": "cspell \"**\" --no-progress --show-context --show-suggestions",
"lint:spelling:fix": "yarn rimraf project-words.txt && echo \"# Project Words - DO NOT TOUCH - This is updated through CI\" >> project-words.txt && yarn -s lint:spelling --words-only --unique --no-exit-code --no-summary \"**\" | cross-env LC_ALL=en_US.UTF-8 sort --ignore-case >> project-words.txt", "lint:spelling:fix": "yarn rimraf project-words.txt && echo \"# Project Words - DO NOT TOUCH - This is updated through CI\" >> project-words.txt && yarn -s lint:spelling --words-only --unique --no-exit-code --no-summary \"**\" | cross-env LC_ALL=C sort --ignore-case >> project-words.txt",
"lint:style": "stylelint \"**/*.css\"", "lint:style": "stylelint \"**/*.css\"",
"lint:style:fix": "yarn lint:style --fix", "lint:style:fix": "yarn lint:style --fix",
"lerna": "lerna", "lerna": "lerna",
@ -83,14 +85,13 @@
"@types/node": "^18.16.19", "@types/node": "^18.16.19",
"@types/prompts": "^2.4.4", "@types/prompts": "^2.4.4",
"@types/react": "^18.2.15", "@types/react": "^18.2.15",
"@types/react-dev-utils": "^9.0.11",
"@types/react-test-renderer": "^18.0.0", "@types/react-test-renderer": "^18.0.0",
"@types/semver": "^7.5.0", "@types/semver": "^7.5.0",
"@types/shelljs": "^0.8.12", "@types/shelljs": "^0.8.12",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^5.62.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cspell": "^8.1.0", "cspell": "^8.18.1",
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
@ -99,10 +100,11 @@
"eslint-plugin-jest": "^27.2.3", "eslint-plugin-jest": "^27.2.3",
"eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.32.2", "eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-compiler": "^19.0.0-beta-40c6c23-20250301",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-regexp": "^1.15.0", "eslint-plugin-regexp": "^1.15.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"image-size": "^1.0.2", "image-size": "^2.0.2",
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"jest-serializer-ansi-escapes": "^3.0.0", "jest-serializer-ansi-escapes": "^3.0.0",
@ -112,10 +114,11 @@
"lint-staged": "~13.2.3", "lint-staged": "~13.2.3",
"lockfile-lint": "^4.14.0", "lockfile-lint": "^4.14.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"react": "^18.0.0", "react": "^18.0.0",
"react-dom": "^18.0.0", "react-dom": "^18.0.0",
"react-helmet-async": "^1.3.0",
"react-test-renderer": "^18.0.0", "react-test-renderer": "^18.0.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"sharp": "^0.32.3", "sharp": "^0.32.3",
@ -123,6 +126,7 @@
"stylelint": "^14.16.1", "stylelint": "^14.16.1",
"stylelint-config-prettier": "^9.0.5", "stylelint-config-prettier": "^9.0.5",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0",
"typescript": "~5.6.2" "typescript": "~5.8.2"
} },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "create-docusaurus", "name": "create-docusaurus",
"version": "3.6.1", "version": "3.7.0",
"description": "Create Docusaurus apps easily.", "description": "Create Docusaurus apps easily.",
"type": "module", "type": "module",
"repository": { "repository": {
@ -22,14 +22,14 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"commander": "^5.1.0", "commander": "^5.1.0",
"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",
"semver": "^7.5.4", "semver": "^7.5.4",
"shelljs": "^0.8.5",
"supports-color": "^9.4.0", "supports-color": "^9.4.0",
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },

View file

@ -10,10 +10,13 @@ import {fileURLToPath} from 'url';
import path from 'path'; import path from 'path';
import _ from 'lodash'; import _ from 'lodash';
import {logger} from '@docusaurus/logger'; import {logger} from '@docusaurus/logger';
import shell from 'shelljs'; import execa from 'execa';
import prompts, {type Choice} from 'prompts'; import prompts, {type Choice} from 'prompts';
import supportsColor from 'supports-color'; import supportsColor from 'supports-color';
import {escapeShellArg, askPreferredLanguage} from '@docusaurus/utils';
// TODO remove dependency on large @docusaurus/utils
// would be better to have a new smaller @docusaurus/utils-cli package
import {askPreferredLanguage} from '@docusaurus/utils';
type LanguagesOptions = { type LanguagesOptions = {
javascript?: boolean; javascript?: boolean;
@ -70,9 +73,9 @@ function findPackageManagerFromUserAgent(): PackageManager | undefined {
} }
async function askForPackageManagerChoice(): Promise<PackageManager> { async function askForPackageManagerChoice(): Promise<PackageManager> {
const hasYarn = shell.exec('yarn --version', {silent: true}).code === 0; const hasYarn = (await execa.command('yarn --version')).exitCode === 0;
const hasPnpm = shell.exec('pnpm --version', {silent: true}).code === 0; const hasPnpm = (await execa.command('pnpm --version')).exitCode === 0;
const hasBun = shell.exec('bun --version', {silent: true}).code === 0; const hasBun = (await execa.command('bun --version')).exitCode === 0;
if (!hasYarn && !hasPnpm && !hasBun) { if (!hasYarn && !hasPnpm && !hasBun) {
return 'npm'; return 'npm';
@ -530,10 +533,7 @@ export default async function init(
if (source.type === 'git') { if (source.type === 'git') {
const gitCommand = await getGitCommand(source.strategy); const gitCommand = await getGitCommand(source.strategy);
const gitCloneCommand = `${gitCommand} ${escapeShellArg( if ((await execa(gitCommand, [source.url, dest])).exitCode !== 0) {
source.url,
)} ${escapeShellArg(dest)}`;
if (shell.exec(gitCloneCommand).code !== 0) {
logger.error`Cloning Git template failed!`; logger.error`Cloning Git template failed!`;
process.exit(1); process.exit(1);
} }
@ -583,10 +583,13 @@ export default async function init(
const cdpath = path.relative('.', dest); const cdpath = path.relative('.', dest);
const pkgManager = await getPackageManager(dest, cliOptions); const pkgManager = await getPackageManager(dest, cliOptions);
if (!cliOptions.skipInstall) { if (!cliOptions.skipInstall) {
shell.cd(dest); process.chdir(dest);
logger.info`Installing dependencies with name=${pkgManager}...`; logger.info`Installing dependencies with name=${pkgManager}...`;
// ...
if ( if (
shell.exec( (
await execa.command(
pkgManager === 'yarn' pkgManager === 'yarn'
? 'yarn' ? 'yarn'
: pkgManager === 'bun' : pkgManager === 'bun'
@ -595,12 +598,12 @@ export default async function init(
{ {
env: { env: {
...process.env, ...process.env,
// Force coloring the output, since the command is invoked by // Force coloring the output
// shelljs, which is not an interactive shell
...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}),
}, },
}, },
).code !== 0 )
).exitCode !== 0
) { ) {
logger.error('Dependency installation failed.'); logger.error('Dependency installation failed.');
logger.info`The site directory has already been created, and you can retry by typing: logger.info`The site directory has already been created, and you can retry by typing:

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

View file

@ -1,6 +1,6 @@
{ {
"name": "docusaurus-2-classic-typescript-template", "name": "docusaurus-2-classic-typescript-template",
"version": "3.6.1", "version": "3.7.0",
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@ -15,18 +15,18 @@
"typecheck": "tsc" "typecheck": "tsc"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.1", "@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.6.1", "@docusaurus/preset-classic": "3.7.0",
"@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",
"react": "^18.0.0", "react": "^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.6.1", "@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.6.1", "@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"browserslist": { "browserslist": {

View file

@ -1,3 +1,4 @@
import type {ReactNode} from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -5,7 +6,7 @@ import styles from './styles.module.css';
type FeatureItem = { type FeatureItem = {
title: string; title: string;
Svg: React.ComponentType<React.ComponentProps<'svg'>>; Svg: React.ComponentType<React.ComponentProps<'svg'>>;
description: JSX.Element; description: ReactNode;
}; };
const FeatureList: FeatureItem[] = [ const FeatureList: FeatureItem[] = [
@ -55,7 +56,7 @@ function Feature({title, Svg, description}: FeatureItem) {
); );
} }
export default function HomepageFeatures(): JSX.Element { export default function HomepageFeatures(): ReactNode {
return ( return (
<section className={styles.features}> <section className={styles.features}>
<div className="container"> <div className="container">

View file

@ -1,3 +1,4 @@
import type {ReactNode} from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
@ -28,7 +29,7 @@ function HomepageHeader() {
); );
} }
export default function Home(): JSX.Element { export default function Home(): ReactNode {
const {siteConfig} = useDocusaurusContext(); const {siteConfig} = useDocusaurusContext();
return ( return (
<Layout <Layout

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

View file

@ -1,6 +1,6 @@
{ {
"name": "docusaurus-2-classic-template", "name": "docusaurus-2-classic-template",
"version": "3.6.1", "version": "3.7.0",
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@ -14,17 +14,17 @@
"write-heading-ids": "docusaurus write-heading-ids" "write-heading-ids": "docusaurus write-heading-ids"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.1", "@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.6.1", "@docusaurus/preset-classic": "3.7.0",
"@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",
"react": "^18.0.0", "react": "^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.6.1", "@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.6.1" "@docusaurus/types": "3.7.0"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

View file

@ -4,13 +4,13 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati
### Installation ### Installation
``` ```bash
$ yarn $ yarn
``` ```
### Local Development ### Local Development
``` ```bash
$ yarn start $ yarn start
``` ```
@ -18,7 +18,7 @@ This command starts a local development server and opens up a browser window. Mo
### Build ### Build
``` ```bash
$ yarn build $ yarn build
``` ```
@ -28,13 +28,13 @@ This command generates static content into the `build` directory and can be serv
Using SSH: Using SSH:
``` ```bash
$ USE_SSH=true yarn deploy $ USE_SSH=true yarn deploy
``` ```
Not using SSH: Not using SSH:
``` ```bash
$ GIT_USER=<Your GitHub username> yarn deploy $ GIT_USER=<Your GitHub username> yarn deploy
``` ```

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

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/babel", "name": "@docusaurus/babel",
"version": "3.6.1", "version": "3.7.0",
"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",
@ -38,8 +38,8 @@
"@babel/runtime": "^7.25.9", "@babel/runtime": "^7.25.9",
"@babel/runtime-corejs3": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9",
"@babel/traverse": "^7.25.9", "@babel/traverse": "^7.25.9",
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"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"

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/bundler", "name": "@docusaurus/bundler",
"version": "3.6.1", "version": "3.7.0",
"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,11 +19,11 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.25.9", "@babel/core": "^7.25.9",
"@docusaurus/babel": "3.6.1", "@docusaurus/babel": "3.7.0",
"@docusaurus/cssnano-preset": "3.6.1", "@docusaurus/cssnano-preset": "3.7.0",
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"babel-loader": "^9.2.1", "babel-loader": "^9.2.1",
"clean-css": "^5.3.2", "clean-css": "^5.3.2",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
@ -37,7 +37,6 @@
"postcss": "^8.4.26", "postcss": "^8.4.26",
"postcss-loader": "^7.3.3", "postcss-loader": "^7.3.3",
"postcss-preset-env": "^10.1.0", "postcss-preset-env": "^10.1.0",
"react-dev-utils": "^12.0.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",

View file

@ -7,7 +7,7 @@
import {type Configuration} from 'webpack'; import {type Configuration} from 'webpack';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages'; import formatWebpackMessages from './legacy/formatWebpackMessages';
import type webpack from 'webpack'; import type webpack from 'webpack';
import type {CurrentBundler} from '@docusaurus/types'; import type {CurrentBundler} from '@docusaurus/types';

View file

@ -0,0 +1,138 @@
/**
* 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.
*/
// TODO Legacy CRA react-dev-utils package code
// This code was in CRA/react-dev-utils (deprecated in 2025)
// We just copied the code as-is to remove a fat/useless dependency subtree
// See https://github.com/facebook/docusaurus/pull/10956
// See https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/formatWebpackMessages.js
/* eslint-disable */
const friendlySyntaxErrorLabel = 'Syntax error:';
function isLikelyASyntaxError(message) {
return message.indexOf(friendlySyntaxErrorLabel) !== -1;
}
// Cleans up webpack error messages.
function formatMessage(message) {
let lines = [];
if (typeof message === 'string') {
lines = message.split('\n');
} else if ('message' in message) {
lines = message['message'].split('\n');
} else if (Array.isArray(message)) {
message.forEach((message) => {
if ('message' in message) {
lines = message['message'].split('\n');
}
});
}
// Strip webpack-added headers off errors/warnings
// https://github.com/webpack/webpack/blob/master/lib/ModuleError.js
lines = lines.filter((line) => !/Module [A-z ]+\(from/.test(line));
// Transform parsing error into syntax error
// TODO: move this to our ESLint formatter?
lines = lines.map((line) => {
const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec(
line,
);
if (!parsingError) {
return line;
}
const [, errorLine, errorColumn, errorMessage] = parsingError;
return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})`;
});
message = lines.join('\n');
// Smoosh syntax errors (commonly found in CSS)
message = message.replace(
/SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g,
`${friendlySyntaxErrorLabel} $3 ($1:$2)\n`,
);
// Clean up export errors
message = message.replace(
/^.*export '(.+?)' was not found in '(.+?)'.*$/gm,
`Attempted import error: '$1' is not exported from '$2'.`,
);
message = message.replace(
/^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
`Attempted import error: '$2' does not contain a default export (imported as '$1').`,
);
message = message.replace(
/^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
`Attempted import error: '$1' is not exported from '$3' (imported as '$2').`,
);
lines = message.split('\n');
// Remove leading newline
if (lines.length > 2 && lines[1].trim() === '') {
lines.splice(1, 1);
}
// Clean up file name
lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
// Cleans up verbose "module not found" messages for files and packages.
if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
lines = [
lines[0],
lines[1]
.replace('Error: ', '')
.replace('Module not found: Cannot find file:', 'Cannot find file:'),
];
}
// Add helpful message for users trying to use Sass for the first time
if (lines[1] && lines[1].match(/Cannot find module.+sass/)) {
lines[1] = 'To import Sass files, you first need to install sass.\n';
lines[1] +=
'Run `npm install sass` or `yarn add sass` inside your workspace.';
}
message = lines.join('\n');
// Internal stacks are generally useless so we strip them... with the
// exception of stacks containing `webpack:` because they're normally
// from user code generated by webpack. For more information see
// https://github.com/facebook/create-react-app/pull/1050
message = message.replace(
/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm,
'',
); // at ... ...:x:y
message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, ''); // at <anonymous>
lines = message.split('\n');
// Remove duplicated newlines
lines = lines.filter(
(line, index, arr) =>
index === 0 ||
line.trim() !== '' ||
line.trim() !== arr[index - 1].trim(),
);
// Reassemble the message
message = lines.join('\n');
return message.trim();
}
/**
* @param {import("webpack").Stats.ToJsonOutput} json.
* @returns {{ errors: string[], warnings: string[] }}
*/
module.exports = function formatWebpackMessages(json) {
const formattedErrors = json.errors.map(formatMessage);
const formattedWarnings = json.warnings.map(formatMessage);
const result = {errors: formattedErrors, warnings: formattedWarnings};
if (result.errors.some(isLikelyASyntaxError)) {
// If there are any syntax errors, show just them.
result.errors = result.errors.filter(isLikelyASyntaxError);
}
return result;
};

View file

@ -47,9 +47,13 @@ async function getTerserMinifier(): Promise<HtmlMinifier> {
minify: async function minifyHtmlWithTerser(html) { minify: async function minifyHtmlWithTerser(html) {
try { try {
const code = await terserHtmlMinifier(html, { const code = await terserHtmlMinifier(html, {
// When enabled => React hydration errors
removeComments: false, removeComments: false,
removeRedundantAttributes: true, removeRedundantAttributes: false,
removeEmptyAttributes: true, removeEmptyAttributes: false,
sortAttributes: false,
sortClassName: false,
removeScriptTypeAttributes: true, removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true, removeStyleLinkTypeAttributes: true,
useShortDoctype: true, useShortDoctype: true,
@ -84,8 +88,13 @@ async function getSwcMinifier(): Promise<HtmlMinifier> {
sortSpaceSeparatedAttributeValues: false, sortSpaceSeparatedAttributeValues: false,
sortAttributes: false, sortAttributes: false,
removeRedundantAttributes: 'all', // When enabled => hydration error for className={"yt-lite "}
removeEmptyAttributes: true, normalizeAttributes: false,
// When enabled => hydration error for className=""
removeEmptyAttributes: false,
// When enabled => hydration error for <a target="_self">
removeRedundantAttributes: 'none',
minifyJs: true, minifyJs: true,
minifyJson: true, minifyJson: true,
minifyCss: true, minifyCss: true,

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/cssnano-preset", "name": "@docusaurus/cssnano-preset",
"version": "3.6.1", "version": "3.7.0",
"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",

View file

@ -26,4 +26,5 @@ const preset: typeof advancedBasePreset = function preset(opts) {
return advancedPreset; return advancedPreset;
}; };
// @ts-expect-error: TODO fix later
export = preset; export = preset;

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/faster", "name": "@docusaurus/faster",
"version": "3.6.1", "version": "3.7.0",
"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,8 +18,8 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"@rspack/core": "^1.1.1", "@rspack/core": "^1.3.3",
"@swc/core": "^1.7.39", "@swc/core": "^1.7.39",
"@swc/html": "^1.7.39", "@swc/html": "^1.7.39",
"browserslist": "^4.24.2", "browserslist": "^4.24.2",

View file

@ -11,6 +11,16 @@ import browserslist from 'browserslist';
import {minify as swcHtmlMinifier} from '@swc/html'; import {minify as swcHtmlMinifier} from '@swc/html';
import type {JsMinifyOptions, Options as SwcOptions} from '@swc/core'; import type {JsMinifyOptions, Options as SwcOptions} from '@swc/core';
// See https://rspack.dev/contribute/development/profiling
// File can be opened with https://ui.perfetto.dev/
if (process.env.DOCUSAURUS_RSPACK_TRACE) {
Rspack.experiments.globalTrace.register(
'trace',
'chrome',
'./rspack-tracing.json',
);
}
export const swcLoader = require.resolve('swc-loader'); export const swcLoader = require.resolve('swc-loader');
export const getSwcLoaderOptions = ({ export const getSwcLoaderOptions = ({

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/logger", "name": "@docusaurus/logger",
"version": "3.6.1", "version": "3.7.0",
"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": {

View file

@ -114,12 +114,24 @@ function createPerfLogger(): PerfLoggerAPI {
}, },
}); });
const end: PerfLoggerAPI['end'] = (label) => { const readMark = (label: string) => {
const { const startMark = performance.getEntriesByName(
duration, label,
detail: {memoryUsage}, 'mark',
} = performance.measure(label); )?.[0] as PerformanceMark;
if (!startMark) {
throw new Error(`No performance start mark for label=${label}`);
}
performance.clearMarks(label); performance.clearMarks(label);
return startMark;
};
const end: PerfLoggerAPI['end'] = (label) => {
const startMark = readMark(label);
const duration = performance.now() - startMark.startTime;
const {
detail: {memoryUsage},
} = startMark;
printPerfLog({ printPerfLog({
label: applyParentPrefix(label), label: applyParentPrefix(label),
duration, duration,

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/mdx-loader", "name": "@docusaurus/mdx-loader",
"version": "3.6.1", "version": "3.7.0",
"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,16 +18,16 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.6.1", "@docusaurus/utils-validation": "3.7.0",
"@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",
"estree-util-value-to-estree": "^3.0.1", "estree-util-value-to-estree": "^3.0.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
"image-size": "^1.0.2", "image-size": "^2.0.2",
"mdast-util-mdx": "^3.0.0", "mdast-util-mdx": "^3.0.0",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"rehype-raw": "^7.0.0", "rehype-raw": "^7.0.0",
@ -44,7 +44,7 @@
"webpack": "^5.88.1" "webpack": "^5.88.1"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"@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",
@ -58,8 +58,8 @@
"unist-util-remove-position": "^5.0.0" "unist-util-remove-position": "^5.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^18.0.0", "react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=18.0"

View file

@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import type {ReactNode} from 'react';
import {mdxLoader} from './loader'; import {mdxLoader} from './loader';
import type {TOCItem as TOCItemImported} from './remark/toc/types'; import type {TOCItem as TOCItemImported} from './remark/toc/types';
@ -34,7 +36,7 @@ export type LoadedMDXContent<FrontMatter, Metadata, Assets = undefined> = {
* in priority. * in priority.
*/ */
readonly assets: Assets; readonly assets: Assets;
(): JSX.Element; (): ReactNode;
}; };
export type {MDXPlugin} from './loader'; export type {MDXPlugin} from './loader';

View file

@ -218,6 +218,7 @@ export async function mdxLoader(
const compilerName = getWebpackLoaderCompilerName(this); const compilerName = getWebpackLoaderCompilerName(this);
const callback = this.async(); const callback = this.async();
const options: Options = this.getOptions(); const options: Options = this.getOptions();
options.dependencies?.forEach(this.addDependency);
try { try {
const result = await loadMDXWithCaching({ const result = await loadMDXWithCaching({
resource: this.resource, resource: this.resource,

View file

@ -11,6 +11,8 @@ import type {ResolveMarkdownLink} from './remark/resolveMarkdownLinks';
import type {PromiseWithResolvers} from './utils'; import type {PromiseWithResolvers} from './utils';
export type Options = Partial<MDXOptions> & { export type Options = Partial<MDXOptions> & {
dependencies?: string[];
markdownConfig: MarkdownConfig; markdownConfig: MarkdownConfig;
staticDirs: string[]; staticDirs: string[];
siteDir: string; siteDir: string;

View file

@ -22,8 +22,6 @@ 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';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
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 :/

View file

@ -4,10 +4,7 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer, Plugin} from 'unified'; import type {Transformer, Plugin} from 'unified';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {ContainerDirective} from 'mdast-util-directive'; import type {ContainerDirective} from 'mdast-util-directive';
import type {Parent, Root} from 'mdast'; import type {Parent, Root} from 'mdast';

View file

@ -4,11 +4,8 @@
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer, Plugin} from 'unified'; import type {Transformer, Plugin} from 'unified';
import type {Heading, Parent, Root} from 'mdast'; import type {Heading, Parent, Root} from 'mdast';
// @ts-expect-error: ES support...
import type {MdxJsxFlowElement} from 'mdast-util-mdx'; import type {MdxJsxFlowElement} from 'mdast-util-mdx';
interface PluginOptions { interface PluginOptions {

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer} from 'unified'; import type {Transformer} from 'unified';
import type {Root} from 'mdast'; import type {Root} from 'mdast';

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer} from 'unified'; import type {Transformer} from 'unified';
import type {Root} from 'mdast'; import type {Root} from 'mdast';

View file

@ -8,7 +8,6 @@
/* Based on remark-slug (https://github.com/remarkjs/remark-slug) and gatsby-remark-autolink-headers (https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-remark-autolink-headers) */ /* Based on remark-slug (https://github.com/remarkjs/remark-slug) and gatsby-remark-autolink-headers (https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-remark-autolink-headers) */
import {parseMarkdownHeadingId, createSlugger} from '@docusaurus/utils'; import {parseMarkdownHeadingId, createSlugger} from '@docusaurus/utils';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
import type {Root, Text} from 'mdast'; import type {Root, Text} from 'mdast';

View file

@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer, Plugin} from 'unified'; import type {Transformer, Plugin} from 'unified';
import type {Root} from 'mdast'; import type {Root} from 'mdast';
@ -26,6 +25,7 @@ const plugin: Plugin<unknown[], Root> = function plugin(): Transformer<Root> {
node.data.hProperties = node.data.hProperties || {}; node.data.hProperties = node.data.hProperties || {};
node.data.hProperties.metastring = node.meta; node.data.hProperties.metastring = node.meta;
// TODO Docusaurus v4: remove special case
// Retrocompatible support for live codeblock metastring // Retrocompatible support for live codeblock metastring
// Not really the appropriate place to handle that :s // Not really the appropriate place to handle that :s
node.data.hProperties.live = node.meta?.split(' ').includes('live'); node.data.hProperties.live = node.meta?.split(' ').includes('live');

View file

@ -7,7 +7,6 @@
import {transformNode} from '../utils'; import {transformNode} from '../utils';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Transformer} from 'unified'; import type {Transformer} from 'unified';
import type {Root} from 'mdast'; import type {Root} from 'mdast';

View file

@ -11,7 +11,6 @@ import {
type URLPath, type URLPath,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
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';

View file

@ -0,0 +1,126 @@
/**
* 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 {toHeadingHTMLValue} from '../utils';
import type {Heading} from 'mdast';
describe('toHeadingHTMLValue', () => {
async function convert(heading: Heading): Promise<string> {
const {toString} = await import('mdast-util-to-string');
return toHeadingHTMLValue(heading, toString);
}
it('converts a simple heading', async () => {
const heading: Heading = {
type: 'heading',
depth: 2,
children: [
{
type: 'text',
value: 'Some heading text',
},
],
};
await expect(convert(heading)).resolves.toMatchInlineSnapshot(
`"Some heading text"`,
);
});
it('converts a heading with b tag', async () => {
const heading: Heading = {
type: 'heading',
depth: 2,
children: [
{
type: 'mdxJsxTextElement',
name: 'b',
attributes: [],
children: [
{
type: 'text',
value: 'Some title',
},
],
},
],
};
await expect(convert(heading)).resolves.toMatchInlineSnapshot(
`"<b>Some title</b>"`,
);
});
it('converts a heading with span tag + className', async () => {
const heading: Heading = {
type: 'heading',
depth: 2,
children: [
{
type: 'mdxJsxTextElement',
name: 'span',
attributes: [
{
type: 'mdxJsxAttribute',
name: 'className',
value: 'my-class',
},
],
children: [
{
type: 'text',
value: 'Some title',
},
],
},
],
};
await expect(convert(heading)).resolves.toMatchInlineSnapshot(
`"<span class="my-class">Some title</span>"`,
);
});
it('converts a heading - remove img tag', async () => {
const heading: Heading = {
type: 'heading',
depth: 2,
children: [
{
type: 'mdxJsxTextElement',
name: 'img',
attributes: [
{
type: 'mdxJsxAttribute',
name: 'src',
value: '/img/slash-introducing.svg',
},
{
type: 'mdxJsxAttribute',
name: 'height',
value: '32',
},
{
type: 'mdxJsxAttribute',
name: 'alt',
value: 'test',
},
],
children: [],
},
{
type: 'text',
value: ' Some title',
},
],
};
await expect(convert(heading)).resolves.toMatchInlineSnapshot(
`"Some title"`,
);
});
});

View file

@ -14,13 +14,8 @@ import {
isNamedExport, isNamedExport,
} from './utils'; } from './utils';
import type {Heading, Root} from 'mdast'; import type {Heading, Root} from 'mdast';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
import type { import type {MdxjsEsm, MdxJsxFlowElement} from 'mdast-util-mdx';
MdxjsEsm,
MdxJsxFlowElement,
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
} from 'mdast-util-mdx';
import type {TOCItems} from './types'; import type {TOCItems} from './types';
import type {ImportDeclaration} from 'estree'; import type {ImportDeclaration} from 'estree';

View file

@ -5,11 +5,12 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {toValue} from '../utils'; import escapeHtml from 'escape-html';
import type {Node} from 'unist'; import type {Node, Parent} from 'unist';
import type { import type {
MdxjsEsm, MdxjsEsm,
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721 MdxJsxAttribute,
MdxJsxTextElement,
} from 'mdast-util-mdx'; } from 'mdast-util-mdx';
import type {TOCHeading, TOCItem, TOCItems, TOCSlice} from './types'; import type {TOCHeading, TOCItem, TOCItems, TOCSlice} from './types';
import type { import type {
@ -18,6 +19,7 @@ import type {
ImportDeclaration, ImportDeclaration,
ImportSpecifier, ImportSpecifier,
} from 'estree'; } from 'estree';
import type {Heading, PhrasingContent} from 'mdast';
export function getImportDeclarations(program: Program): ImportDeclaration[] { export function getImportDeclarations(program: Program): ImportDeclaration[] {
return program.body.filter( return program.body.filter(
@ -121,7 +123,7 @@ export async function createTOCExportNodeAST({
const {toString} = await import('mdast-util-to-string'); const {toString} = await import('mdast-util-to-string');
const {valueToEstree} = await import('estree-util-value-to-estree'); const {valueToEstree} = await import('estree-util-value-to-estree');
const value: TOCItem = { const value: TOCItem = {
value: toValue(heading, toString), value: toHeadingHTMLValue(heading, toString),
id: heading.data!.id!, id: heading.data!.id!,
level: heading.depth, level: heading.depth,
}; };
@ -175,3 +177,73 @@ export async function createTOCExportNodeAST({
}, },
}; };
} }
function stringifyChildren(
node: Parent,
toString: (param: unknown) => string, // TODO temporary, due to ESM
): string {
return (node.children as PhrasingContent[])
.map((item) => toHeadingHTMLValue(item, toString))
.join('')
.trim();
}
// TODO This is really a workaround, and not super reliable
// For now we only support serializing tagName, className and content
// Can we implement the TOC with real JSX nodes instead of html strings later?
function mdxJsxTextElementToHtml(
element: MdxJsxTextElement,
toString: (param: unknown) => string, // TODO temporary, due to ESM
): string {
const tag = element.name;
// See https://github.com/facebook/docusaurus/issues/11003#issuecomment-2733925363
if (tag === 'img') {
return '';
}
const attributes = element.attributes.filter(
(child): child is MdxJsxAttribute => child.type === 'mdxJsxAttribute',
);
const classAttribute =
attributes.find((attr) => attr.name === 'className') ??
attributes.find((attr) => attr.name === 'class');
const classAttributeString = classAttribute
? `class="${escapeHtml(String(classAttribute.value))}"`
: ``;
const allAttributes = classAttributeString ? ` ${classAttributeString}` : '';
const content = stringifyChildren(element, toString);
return `<${tag}${allAttributes}>${content}</${tag}>`;
}
export function toHeadingHTMLValue(
node: PhrasingContent | Heading | MdxJsxTextElement,
toString: (param: unknown) => string, // TODO temporary, due to ESM
): string {
switch (node.type) {
case 'mdxJsxTextElement': {
return mdxJsxTextElementToHtml(node as MdxJsxTextElement, toString);
}
case 'text':
return escapeHtml(node.value);
case 'heading':
return stringifyChildren(node, toString);
case 'inlineCode':
return `<code>${escapeHtml(node.value)}</code>`;
case 'emphasis':
return `<em>${stringifyChildren(node, toString)}</em>`;
case 'strong':
return `<strong>${stringifyChildren(node, toString)}</strong>`;
case 'delete':
return `<del>${stringifyChildren(node, toString)}</del>`;
case 'link':
return stringifyChildren(node, toString);
default:
return toString(node);
}
}

View file

@ -29,3 +29,13 @@ in paragraph ![img](static/img.png)
```md ```md
![img](./static/img.png) ![img](./static/img.png)
``` ```
## Images with spaces
![img](</img with spaces.png>)
![img](<@site/static/img with spaces.png>)
![img](</img with one encoded%2520space.png>)
![img](<@site/static/img with one encoded%2520space.png>)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

View file

@ -48,5 +48,15 @@ in paragraph <img alt="img" src={require("!<PROJECT_ROOT>/node_modules/url-loade
\`\`\`md \`\`\`md
![img](./static/img.png) ![img](./static/img.png)
\`\`\` \`\`\`
## Images with spaces
<img alt="img" 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/img with spaces.png").default} width="200" height="200" />
<img alt="img" 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/img with spaces.png").default} width="200" height="200" />
<img alt="img" 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/img with one encoded%20space.png").default} width="200" height="200" />
<img alt="img" 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/img with one encoded%20space.png").default} width="200" height="200" />
" "
`; `;

View file

@ -8,7 +8,6 @@
import path from 'path'; import path from 'path';
import url from 'url'; import url from 'url';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {promisify} from 'util';
import { import {
toMessageRelativeFilePath, toMessageRelativeFilePath,
posixPath, posixPath,
@ -17,12 +16,10 @@ import {
getFileLoaderUtils, getFileLoaderUtils,
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import sizeOf from 'image-size'; import {imageSizeFromFile} from 'image-size/fromFile';
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import {assetRequireAttributeValue, transformNode} from '../utils'; import {assetRequireAttributeValue, transformNode} from '../utils';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
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';
@ -82,7 +79,7 @@ async function toImageRequireNode(
} }
try { try {
const size = (await promisify(sizeOf)(imagePath))!; const size = (await imageSizeFromFile(imagePath))!;
if (size.width) { if (size.width) {
attributes.push({ attributes.push({
type: 'mdxJsxAttribute', type: 'mdxJsxAttribute',
@ -98,6 +95,7 @@ async function toImageRequireNode(
}); });
} }
} catch (err) { } catch (err) {
console.error(err);
// Workaround for https://github.com/yarnpkg/berry/pull/3889#issuecomment-1034469784 // Workaround for https://github.com/yarnpkg/berry/pull/3889#issuecomment-1034469784
// TODO remove this check once fixed in Yarn PnP // TODO remove this check once fixed in Yarn PnP
if (!process.versions.pnp) { if (!process.versions.pnp) {
@ -152,10 +150,7 @@ async function getImageAbsolutePath(
return imageFilePath; return imageFilePath;
} }
// relative paths are resolved against the source file's folder // relative paths are resolved against the source file's folder
const imageFilePath = path.join( const imageFilePath = path.join(path.dirname(filePath), imagePath);
path.dirname(filePath),
decodeURIComponent(imagePath),
);
await ensureImageFileExist(imageFilePath, filePath); await ensureImageFileExist(imageFilePath, filePath);
return imageFilePath; return imageFilePath;
} }
@ -180,9 +175,14 @@ async function processImageNode(target: Target, context: Context) {
return; return;
} }
// We decode it first because Node Url.pathname is always encoded
// while the image file-system path are not.
// See https://github.com/facebook/docusaurus/discussions/10720
const decodedPathname = decodeURIComponent(parsedUrl.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(parsedUrl.pathname, context); const imagePath = await getImageAbsolutePath(decodedPathname, context);
await toImageRequireNode(target, imagePath, context); await toImageRequireNode(target, imagePath, context);
} }

View file

@ -17,9 +17,7 @@ import {
} from '@docusaurus/utils'; } from '@docusaurus/utils';
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import {assetRequireAttributeValue, transformNode} from '../utils'; import {assetRequireAttributeValue, transformNode} from '../utils';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
import type {Plugin, Transformer} from 'unified'; import type {Plugin, Transformer} from 'unified';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
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, Literal, Root} from 'mdast';

View file

@ -10,14 +10,9 @@ import logger from '@docusaurus/logger';
import {posixPath} from '@docusaurus/utils'; import {posixPath} from '@docusaurus/utils';
import {transformNode} from '../utils'; import {transformNode} from '../utils';
import type {Root} from 'mdast'; import type {Root} from 'mdast';
import type {Parent} from 'unist';
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721 import type {Transformer, Processor, Plugin} from 'unified';
import type {Transformer, Processor, Parent, Plugin} from 'unified'; import type {Directives, TextDirective} from 'mdast-util-directive';
import type {
Directives,
TextDirective,
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
} from 'mdast-util-directive';
type DirectiveType = Directives['type']; type DirectiveType = Directives['type'];
@ -133,10 +128,8 @@ const plugin: Plugin<unknown[], Root> = function plugin(
const unusedDirectives: Directives[] = []; const unusedDirectives: Directives[] = [];
visit<Parent, DirectiveType[]>( // @ts-expect-error: TODO fix type
tree, visit<Parent, Directives>(tree, directiveTypes, (directive: Directives) => {
directiveTypes,
(directive: Directives) => {
// If directive data is set (hName/hProperties set by admonitions) // If directive data is set (hName/hProperties set by admonitions)
// this usually means the directive has been handled by another plugin // this usually means the directive has been handled by another plugin
if (isUnusedDirective(directive)) { if (isUnusedDirective(directive)) {
@ -146,8 +139,7 @@ const plugin: Plugin<unknown[], Root> = function plugin(
unusedDirectives.push(directive); unusedDirectives.push(directive);
} }
} }
}, });
);
// We only enable these warnings for the client compiler // We only enable these warnings for the client compiler
// This avoids emitting duplicate warnings in prod mode // This avoids emitting duplicate warnings in prod mode

View file

@ -5,15 +5,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import escapeHtml from 'escape-html'; import type {Node} from 'unist';
import type {Parent, Node} from 'unist'; import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx';
import type {PhrasingContent, Heading} from 'mdast';
import type {
MdxJsxAttribute,
MdxJsxAttributeValueExpression,
MdxJsxTextElement,
// @ts-expect-error: TODO see https://github.com/microsoft/TypeScript/issues/49721
} from 'mdast-util-mdx';
/** /**
* Util to transform one node type to another node type * Util to transform one node type to another node type
@ -36,70 +29,6 @@ export function transformNode<NewNode extends Node>(
return node as NewNode; return node as NewNode;
} }
export function stringifyContent(
node: Parent,
toString: (param: unknown) => string, // TODO weird but works
): string {
return (node.children as PhrasingContent[])
.map((item) => toValue(item, toString))
.join('');
}
// TODO This is really a workaround, and not super reliable
// For now we only support serializing tagName, className and content
// Can we implement the TOC with real JSX nodes instead of html strings later?
function mdxJsxTextElementToHtml(
element: MdxJsxTextElement,
toString: (param: unknown) => string, // TODO weird but works
): string {
const tag = element.name;
const attributes = element.attributes.filter(
(child): child is MdxJsxAttribute => child.type === 'mdxJsxAttribute',
);
const classAttribute =
attributes.find((attr) => attr.name === 'className') ??
attributes.find((attr) => attr.name === 'class');
const classAttributeString = classAttribute
? `class="${escapeHtml(String(classAttribute.value))}"`
: ``;
const allAttributes = classAttributeString ? ` ${classAttributeString}` : '';
const content = stringifyContent(element, toString);
return `<${tag}${allAttributes}>${content}</${tag}>`;
}
export function toValue(
node: PhrasingContent | Heading | MdxJsxTextElement,
toString: (param: unknown) => string, // TODO weird but works
): string {
switch (node.type) {
case 'mdxJsxTextElement': {
return mdxJsxTextElementToHtml(node as MdxJsxTextElement, toString);
}
case 'text':
return escapeHtml(node.value);
case 'heading':
return stringifyContent(node, toString);
case 'inlineCode':
return `<code>${escapeHtml(node.value)}</code>`;
case 'emphasis':
return `<em>${stringifyContent(node, toString)}</em>`;
case 'strong':
return `<strong>${stringifyContent(node, toString)}</strong>`;
case 'delete':
return `<del>${stringifyContent(node, toString)}</del>`;
case 'link':
return stringifyContent(node, toString);
default:
return toString(node);
}
}
export function assetRequireAttributeValue( export function assetRequireAttributeValue(
requireString: string, requireString: string,
hash: string, hash: string,

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/module-type-aliases", "name": "@docusaurus/module-type-aliases",
"version": "3.6.1", "version": "3.7.0",
"description": "Docusaurus module type aliases.", "description": "Docusaurus module type aliases.",
"types": "./src/index.d.ts", "types": "./src/index.d.ts",
"publishConfig": { "publishConfig": {
@ -12,12 +12,12 @@
"directory": "packages/docusaurus-module-type-aliases" "directory": "packages/docusaurus-module-type-aliases"
}, },
"dependencies": { "dependencies": {
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"@types/history": "^4.7.11", "@types/history": "^4.7.11",
"@types/react": "*", "@types/react": "*",
"@types/react-router-config": "*", "@types/react-router-config": "*",
"@types/react-router-dom": "*", "@types/react-router-dom": "*",
"react-helmet-async": "*", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0",
"react-loadable": "npm:@docusaurus/react-loadable@6.0.0" "react-loadable": "npm:@docusaurus/react-loadable@6.0.0"
}, },
"peerDependencies": { "peerDependencies": {

View file

@ -84,10 +84,11 @@ declare module '@theme-original/*';
declare module '@theme-init/*'; declare module '@theme-init/*';
declare module '@theme/Error' { declare module '@theme/Error' {
import type {ReactNode} from 'react';
import type {FallbackParams} from '@docusaurus/ErrorBoundary'; import type {FallbackParams} from '@docusaurus/ErrorBoundary';
export interface Props extends FallbackParams {} export interface Props extends FallbackParams {}
export default function Error(props: Props): JSX.Element; export default function Error(props: Props): ReactNode;
} }
declare module '@theme/Layout' { declare module '@theme/Layout' {
@ -96,17 +97,20 @@ declare module '@theme/Layout' {
export interface Props { export interface Props {
readonly children?: ReactNode; readonly children?: ReactNode;
} }
export default function Layout(props: Props): JSX.Element; export default function Layout(props: Props): ReactNode;
} }
declare module '@theme/Loading' { declare module '@theme/Loading' {
import type {ReactNode} from 'react';
import type {LoadingComponentProps} from 'react-loadable'; import type {LoadingComponentProps} from 'react-loadable';
export default function Loading(props: LoadingComponentProps): JSX.Element; export default function Loading(props: LoadingComponentProps): ReactNode;
} }
declare module '@theme/NotFound' { declare module '@theme/NotFound' {
export default function NotFound(): JSX.Element; import type {ReactNode} from 'react';
export default function NotFound(): ReactNode;
} }
declare module '@theme/Root' { declare module '@theme/Root' {
@ -115,11 +119,22 @@ declare module '@theme/Root' {
export interface Props { export interface Props {
readonly children: ReactNode; readonly children: ReactNode;
} }
export default function Root({children}: Props): JSX.Element; export default function Root({children}: Props): ReactNode;
}
declare module '@theme/ThemeProvider' {
import type {ReactNode} from 'react';
export interface Props {
readonly children: ReactNode;
}
export default function ThemeProvider({children}: Props): ReactNode;
} }
declare module '@theme/SiteMetadata' { declare module '@theme/SiteMetadata' {
export default function SiteMetadata(): JSX.Element; import type {ReactNode} from 'react';
export default function SiteMetadata(): ReactNode;
} }
declare module '@docusaurus/constants' { declare module '@docusaurus/constants' {
@ -134,13 +149,13 @@ declare module '@docusaurus/ErrorBoundary' {
readonly tryAgain: () => void; readonly tryAgain: () => void;
}; };
export type FallbackFunction = (params: FallbackParams) => JSX.Element; export type FallbackFunction = (params: FallbackParams) => ReactNode;
export interface Props { export interface Props {
readonly fallback?: FallbackFunction; readonly fallback?: FallbackFunction;
readonly children: ReactNode; readonly children: ReactNode;
} }
export default function ErrorBoundary(props: Props): JSX.Element; export default function ErrorBoundary(props: Props): ReactNode;
} }
declare module '@docusaurus/Head' { declare module '@docusaurus/Head' {
@ -149,11 +164,11 @@ declare module '@docusaurus/Head' {
export type Props = HelmetProps & {children: ReactNode}; export type Props = HelmetProps & {children: ReactNode};
export default function Head(props: Props): JSX.Element; export default function Head(props: Props): ReactNode;
} }
declare module '@docusaurus/Link' { declare module '@docusaurus/Link' {
import type {CSSProperties, ComponentProps} from 'react'; import type {CSSProperties, ComponentProps, ReactNode} from 'react';
import type {NavLinkProps as RRNavLinkProps} from 'react-router-dom'; import type {NavLinkProps as RRNavLinkProps} from 'react-router-dom';
type NavLinkProps = Partial<RRNavLinkProps>; type NavLinkProps = Partial<RRNavLinkProps>;
@ -169,7 +184,7 @@ declare module '@docusaurus/Link' {
/** Escape hatch in case broken links check doesn't make sense. */ /** Escape hatch in case broken links check doesn't make sense. */
readonly 'data-noBrokenLinkCheck'?: boolean; readonly 'data-noBrokenLinkCheck'?: boolean;
}; };
export default function Link(props: Props): JSX.Element; export default function Link(props: Props): ReactNode;
} }
declare module '@docusaurus/Interpolate' { declare module '@docusaurus/Interpolate' {
@ -203,7 +218,7 @@ declare module '@docusaurus/Interpolate' {
export default function Interpolate<Str extends string>( export default function Interpolate<Str extends string>(
props: InterpolateProps<Str>, props: InterpolateProps<Str>,
): JSX.Element; ): ReactNode;
} }
declare module '@docusaurus/Translate' { declare module '@docusaurus/Translate' {
@ -241,7 +256,7 @@ declare module '@docusaurus/Translate' {
export default function Translate<Str extends string>( export default function Translate<Str extends string>(
props: TranslateProps<Str>, props: TranslateProps<Str>,
): JSX.Element; ): ReactNode;
} }
declare module '@docusaurus/router' { declare module '@docusaurus/router' {
@ -318,11 +333,13 @@ declare module '@docusaurus/ComponentCreator' {
} }
declare module '@docusaurus/BrowserOnly' { declare module '@docusaurus/BrowserOnly' {
import type {ReactNode} from 'react';
export interface Props { export interface Props {
readonly children?: () => JSX.Element; readonly children?: () => ReactNode;
readonly fallback?: JSX.Element; readonly fallback?: ReactNode;
} }
export default function BrowserOnly(props: Props): JSX.Element | null; export default function BrowserOnly(props: Props): ReactNode | null;
} }
declare module '@docusaurus/isInternalUrl' { declare module '@docusaurus/isInternalUrl' {
@ -369,6 +386,9 @@ declare module '@docusaurus/useGlobalData' {
export default function useGlobalData(): GlobalData; export default function useGlobalData(): GlobalData;
} }
// TODO find a way to move this ambient type to the SVGR plugin?
// unfortunately looks complicated in practice
// see https://x.com/sebastienlorber/status/1859543512661832053
declare module '*.svg' { declare module '*.svg' {
import type {ComponentType, SVGProps} from 'react'; import type {ComponentType, SVGProps} from 'react';

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/plugin-client-redirects", "name": "@docusaurus/plugin-client-redirects",
"version": "3.6.1", "version": "3.7.0",
"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,22 +18,22 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.1", "@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.6.1", "@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.6.1", "@docusaurus/utils-validation": "3.7.0",
"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.6.1" "@docusaurus/types": "3.7.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^18.0.0", "react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=18.0"

View file

@ -71,7 +71,7 @@
<div class="blog-posts"> <div class="blog-posts">
<xsl:for-each select="atom:feed/atom:entry"> <xsl:for-each select="atom:feed/atom:entry">
<div class="blog-post"> <div class="blog-post">
<h3><a href="{atom:link[@rel='alternate']/@href}"><xsl:value-of <h3><a href="{atom:link/@href}"><xsl:value-of
select="atom:title" select="atom:title"
/></a></h3> /></a></h3>
<div class="blog-post-date"> <div class="blog-post-date">

View file

@ -1,6 +1,6 @@
{ {
"name": "@docusaurus/plugin-content-blog", "name": "@docusaurus/plugin-content-blog",
"version": "3.6.1", "version": "3.7.0",
"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,19 +31,20 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@docusaurus/core": "3.6.1", "@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.6.1", "@docusaurus/logger": "3.7.0",
"@docusaurus/mdx-loader": "3.6.1", "@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/theme-common": "3.6.1", "@docusaurus/theme-common": "3.7.0",
"@docusaurus/types": "3.6.1", "@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.6.1", "@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.6.1", "@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.6.1", "@docusaurus/utils-validation": "3.7.0",
"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",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"schema-dts": "^1.1.2",
"srcset": "^4.0.0", "srcset": "^4.0.0",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
@ -52,8 +53,8 @@
}, },
"peerDependencies": { "peerDependencies": {
"@docusaurus/plugin-content-docs": "*", "@docusaurus/plugin-content-docs": "*",
"react": "^18.0.0", "react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0" "react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=18.0" "node": ">=18.0"

View file

@ -71,7 +71,7 @@
<div class="blog-posts"> <div class="blog-posts">
<xsl:for-each select="atom:feed/atom:entry"> <xsl:for-each select="atom:feed/atom:entry">
<div class="blog-post"> <div class="blog-post">
<h3><a href="{atom:link[@rel='alternate']/@href}"><xsl:value-of <h3><a href="{atom:link/@href}"><xsl:value-of
select="atom:title" select="atom:title"
/></a></h3> /></a></h3>
<div class="blog-post-date"> <div class="blog-post-date">

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,23 @@
<!doctype html>
<html lang="en" dir="ltr" class="plugin-native plugin-id-default" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.7.0">
<title data-rh="true">Page Not Found | Docusaurus blog website fixture</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:image" content="https://docusaurus.io/img/docusaurus-social-card.jpg"><meta data-rh="true" name="twitter:image" content="https://docusaurus.io/img/docusaurus-social-card.jpg"><meta data-rh="true" property="og:url" content="https://docusaurus.io/blog/tags/global-tag-permalink (en)"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docusaurus_tag" content="default"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docsearch:docusaurus_tag" content="default"><meta data-rh="true" property="og:title" content="Page Not Found | Docusaurus blog website fixture"><link data-rh="true" rel="icon" href="/img/docusaurus.ico"><link data-rh="true" rel="canonical" href="https://docusaurus.io/blog/tags/global-tag-permalink (en)"><link data-rh="true" rel="alternate" href="https://docusaurus.io/blog/tags/global-tag-permalink (en)" hreflang="en"><link data-rh="true" rel="alternate" href="https://docusaurus.io/blog/tags/global-tag-permalink (en)" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://X1Z85QJPUV-dsn.algolia.net" crossorigin="anonymous"><link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="Docusaurus blog website fixture RSS Feed">
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="Docusaurus blog website fixture Atom Feed">
<link rel="alternate" type="application/json" href="/blog/feed.json" title="Docusaurus blog website fixture JSON Feed">
<link rel="search" type="application/opensearchdescription+xml" title="Docusaurus blog website fixture" href="/opensearch.xml"><link rel="stylesheet" href="/assets/css/styles.5eca0ed4.css">
<script src="/assets/js/runtime~main.972f9f8c.js" defer="defer"></script>
<script src="/assets/js/main.52184938.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>!function(){var t="light";var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",e||t),document.documentElement.setAttribute("data-theme-choice",e||t)}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_c5VT" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top navbarHideable_gzXY"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/img/docusaurus.svg" alt="Docusaurus Logo" class="themedComponent_NoEC themedComponent--light_xEpK"><img src="/img/docusaurus_keytar.svg" alt="Docusaurus Logo" class="themedComponent_NoEC themedComponent--dark__8yu"></div><b class="navbar__title text--truncate">Docusaurus</b></a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><div class="toggle_vYTj colorModeToggle_XGli"><button class="clean-btn toggleButton_dQHP toggleButtonDisabled_T3qH" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_dOhG lightToggleIcon_VoLy"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_dOhG darkToggleIcon_Y09b"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_dOhG systemToggleIcon_hBI2"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_J_Aa"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search (Command+K)"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_cF7l"><main class="container margin-vert--xl"><div class="row"><div class="col col--6 col--offset-3"><h1 class="hero__title">Page Not Found</h1><p>We could not find what you were looking for.</p><p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</p></div></div></main></div></div>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -237,6 +237,10 @@ exports[`atom has custom xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -273,6 +277,10 @@ exports[`atom has custom xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"
@ -683,6 +691,10 @@ exports[`atom has xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -719,6 +731,10 @@ exports[`atom has xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"
@ -900,6 +916,10 @@ exports[`json has custom xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -936,6 +956,10 @@ exports[`json has custom xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"
@ -1253,6 +1277,10 @@ exports[`json has xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -1289,6 +1317,10 @@ exports[`json has xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"
@ -1527,6 +1559,10 @@ exports[`rss has custom xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -1563,6 +1599,10 @@ exports[`rss has custom xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"
@ -1949,6 +1989,10 @@ exports[`rss has xslt files for feed: blog tree 1`] = `
├── atom.css ├── atom.css
├── atom.xml ├── atom.xml
├── atom.xsl ├── atom.xsl
├── authors
│ ├── index.html
│ └── slorber-custom-permalink-localized
│ └── index.html
├── blog-with-links ├── blog-with-links
│ └── index.html │ └── index.html
├── custom-atom.css ├── custom-atom.css
@ -1985,6 +2029,10 @@ exports[`rss has xslt files for feed: blog tree 1`] = `
│ │ └── index.html │ │ └── index.html
│ ├── date │ ├── date
│ │ └── index.html │ │ └── index.html
│ ├── global-tag-permalink (en)
│ │ └── index.html
│ ├── index.html
│ └── inline-tag
│ └── index.html │ └── index.html
└── unlisted └── unlisted
└── index.html" └── index.html"

View file

@ -15,14 +15,26 @@ describe('normalizeSocials', () => {
linkedin: 'ozakione', linkedin: 'ozakione',
github: 'ozakione', github: 'ozakione',
stackoverflow: 'ozakione', stackoverflow: 'ozakione',
threads: 'gingergeekuk',
bluesky: 'gingergeek.co.uk',
instagram: 'thisweekinreact',
twitch: 'gingergeek',
youtube: 'gingergeekuk',
mastodon: 'Mastodon',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"bluesky": "https://bsky.app/profile/gingergeek.co.uk",
"github": "https://github.com/ozakione", "github": "https://github.com/ozakione",
"instagram": "https://www.instagram.com/thisweekinreact",
"linkedin": "https://www.linkedin.com/in/ozakione/", "linkedin": "https://www.linkedin.com/in/ozakione/",
"mastodon": "https://mastodon.social/@Mastodon",
"stackoverflow": "https://stackoverflow.com/users/ozakione", "stackoverflow": "https://stackoverflow.com/users/ozakione",
"threads": "https://www.threads.net/@gingergeekuk",
"twitch": "https://twitch.tv/gingergeek",
"twitter": "https://twitter.com/ozakione", "twitter": "https://twitter.com/ozakione",
"youtube": "https://youtube.com/@gingergeekuk",
} }
`); `);
}); });
@ -33,13 +45,19 @@ describe('normalizeSocials', () => {
linkedIn: 'ozakione', linkedIn: 'ozakione',
gitHub: 'ozakione', gitHub: 'ozakione',
STACKoverflow: 'ozakione', STACKoverflow: 'ozakione',
instaGRam: 'thisweekinreact',
BLUESKY: 'gingergeek.co.uk',
tHrEaDs: 'gingergeekuk',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"bluesky": "https://bsky.app/profile/gingergeek.co.uk",
"github": "https://github.com/ozakione", "github": "https://github.com/ozakione",
"instagram": "https://www.instagram.com/thisweekinreact",
"linkedin": "https://www.linkedin.com/in/ozakione/", "linkedin": "https://www.linkedin.com/in/ozakione/",
"stackoverflow": "https://stackoverflow.com/users/ozakione", "stackoverflow": "https://stackoverflow.com/users/ozakione",
"threads": "https://www.threads.net/@gingergeekuk",
"twitter": "https://twitter.com/ozakione", "twitter": "https://twitter.com/ozakione",
} }
`); `);
@ -62,12 +80,14 @@ describe('normalizeSocials', () => {
linkedin: 'ozakione', linkedin: 'ozakione',
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',
}; };
expect(normalizeSocials(socials)).toMatchInlineSnapshot(` expect(normalizeSocials(socials)).toMatchInlineSnapshot(`
{ {
"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",
"stackoverflow": "https://stackoverflow.com/ozakione", "stackoverflow": "https://stackoverflow.com/ozakione",
"twitter": "https://twitter.com/ozakione", "twitter": "https://twitter.com/ozakione",
} }

View file

@ -79,6 +79,7 @@ describe('validateBlogPostFrontMatter description', () => {
prefix: 'description', prefix: 'description',
validFrontMatters: [ validFrontMatters: [
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398 // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
{description: undefined},
{description: ''}, {description: ''},
{description: 'description'}, {description: 'description'},
], ],
@ -90,6 +91,7 @@ describe('validateBlogPostFrontMatter title', () => {
prefix: 'title', prefix: 'title',
validFrontMatters: [ validFrontMatters: [
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398 // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
{title: undefined},
{title: ''}, {title: ''},
{title: 'title'}, {title: 'title'},
], ],
@ -103,7 +105,11 @@ describe('validateBlogPostFrontMatter title', () => {
describe('validateBlogPostFrontMatter title_meta', () => { describe('validateBlogPostFrontMatter title_meta', () => {
testField({ testField({
prefix: 'title_meta', prefix: 'title_meta',
validFrontMatters: [{title: ''}, {title_meta: 'title'}], validFrontMatters: [
{title_meta: undefined},
{title_meta: ''},
{title_meta: 'title'},
],
invalidFrontMatters: [ invalidFrontMatters: [
[{title_meta: null}, 'must be a string'], [{title_meta: null}, 'must be a string'],
[{title_meta: false}, 'must be a string'], [{title_meta: false}, 'must be a string'],
@ -111,6 +117,21 @@ describe('validateBlogPostFrontMatter title_meta', () => {
}); });
}); });
describe('validateBlogPostFrontMatter sidebar_label', () => {
testField({
prefix: 'title_meta',
validFrontMatters: [
{sidebar_label: undefined},
{sidebar_label: ''},
{sidebar_label: 'title'},
],
invalidFrontMatters: [
[{sidebar_label: null}, 'must be a string'],
[{sidebar_label: false}, 'must be a string'],
],
});
});
describe('validateBlogPostFrontMatter id', () => { describe('validateBlogPostFrontMatter id', () => {
testField({ testField({
prefix: 'id', prefix: 'id',

View file

@ -94,7 +94,7 @@ describe('toBlogSidebarProp', () => {
permalink: '/blog/blog-2', permalink: '/blog/blog-2',
unlisted: true, unlisted: true,
date: '2024-01-01', date: '2024-01-01',
frontMatter: {hello: 'world'}, frontMatter: {hello: 'world', sidebar_label: 'title 2 (custom)'},
tags: [{label: 'tag1', permalink: '/tag1', inline: false}], tags: [{label: 'tag1', permalink: '/tag1', inline: false}],
}, },
}), }),
@ -117,7 +117,7 @@ describe('toBlogSidebarProp', () => {
{ {
"date": "2024-01-01", "date": "2024-01-01",
"permalink": "/blog/blog-2", "permalink": "/blog/blog-2",
"title": "title 2", "title": "title 2 (custom)",
"unlisted": true, "unlisted": true,
}, },
], ],

View file

@ -0,0 +1,56 @@
/**
* 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 {calculateReadingTime} from '../readingTime';
describe('calculateReadingTime', () => {
it('calculates reading time for empty content', () => {
expect(calculateReadingTime('')).toBe(0);
});
it('calculates reading time for short content', () => {
const content = 'This is a short test content.';
expect(calculateReadingTime(content)).toBe(0.03);
});
it('calculates reading time for long content', () => {
const content = 'This is a test content. '.repeat(100);
expect(calculateReadingTime(content)).toBe(2.5);
});
it('respects custom words per minute', () => {
const content = 'This is a test content. '.repeat(100);
expect(calculateReadingTime(content, {wordsPerMinute: 100})).toBe(5);
});
it('handles content with special characters', () => {
const content = 'Hello! How are you? This is a test...';
expect(calculateReadingTime(content)).toBe(0.04);
});
it('handles content with multiple lines', () => {
const content = `This is line 1.
This is line 2.
This is line 3.`;
expect(calculateReadingTime(content)).toBe(0.06);
});
it('handles content with HTML tags', () => {
const content = '<p>This is a <strong>test</strong> content.</p>';
expect(calculateReadingTime(content)).toBe(0.025);
});
it('handles content with markdown', () => {
const content = '# Title\n\nThis is **bold** and *italic* text.';
expect(calculateReadingTime(content)).toBe(0.04);
});
it('handles CJK content', () => {
const content = '你好,世界!这是一段测试内容。';
expect(calculateReadingTime(content)).toBe(0.06);
});
});

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