Compare commits

..

107 Commits

Author SHA1 Message Date
taranvohra d6b9fe6643 Bump api package 2024-10-11 12:58:44 +05:30
taranvohra 766c97a100 Merge remote-tracking branch 'origin/main' into cleanup-legacy-code 2024-10-11 12:58:05 +05:30
Greg Bergé 32e4193557 Implement header link style (#2513) 2024-10-09 15:25:47 +02:00
Zeno Kapitein 133c3e7c0a Update Checkbox component (#2511) 2024-10-08 11:02:51 +02:00
taranvohra 29fca1e835 bun.lockb 2024-10-07 02:01:02 +05:30
taranvohra 48b5c0707b Merge main 2024-10-07 01:52:50 +05:30
Samy Pessé 6ce3cea682 Stop using KV cache backend for now, but also improves it for higher performances (#2510) 2024-10-03 15:46:58 +02:00
Greg Bergé 250e77d18b Fix synced blocks display (#2508) 2024-10-03 10:30:21 +02:00
Addison e3bfe006e9 Add badges section to readme (#2507) 2024-10-02 18:15:37 +09:00
Taran Vohra 76aeecdc68 Remove /v/ from e2e tests (#2505) 2024-10-01 12:04:08 +05:30
Samy Pessé 15d2ee3e76 Show captions for file blocks (#2506) 2024-09-30 17:54:25 +02:00
Taran Vohra b066db479f Bump the cache key for api.getPublishedContentByUrl (#2502) 2024-09-30 15:04:30 +02:00
Samy Pessé a69ff2789a Fix locationHint not being passed when purging the cache (#2504) 2024-09-30 14:45:17 +02:00
Taran Vohra 4df235d64a Add more visitor auth cookie combinations with /v/ for backwards compatibility (#2503) 2024-09-30 17:33:33 +05:30
Taran Vohra 11524457e3 URL alternative resolution criteria (#2497) 2024-09-30 14:18:44 +05:30
Addison 8f7364293e Update Documented on GB badge from encoded to uploaded icon (#2501) 2024-09-30 15:44:45 +08:00
Samy Pessé 56f5fa1fbe Lower usage of KV cache to 30% of tags (#2500) 2024-09-29 10:31:27 +02:00
Samy Pessé b075f0f7e9 Switch to aria-current="page" for the TOC items (#2499) 2024-09-27 12:54:11 +02:00
Samy Pessé 0ca32afe8d Lower usage of KV cache to 60% of tags (#2498) 2024-09-27 11:46:15 +02:00
Samy Pessé 32c2f257a9 Lower usage of KV cache to 80% of tags (#2496) 2024-09-26 19:28:25 +02:00
Brett Jephson a7066ccbe1 Fix: mobile navigation scroll (#2486)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-09-26 14:42:09 +01:00
Taran Vohra 09248e0efe Revert "generate upto URL with 3 segments to support the new site url format" (#2494) 2024-09-26 18:29:01 +05:30
Taran Vohra e2ef22fc5f generate upto URL with 3 segments to support the new site url format (#2493)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-09-26 17:16:22 +05:30
Samy Pessé 75f825e4f8 Disable KV cache for 5% of the cache tags (#2490) 2024-09-26 10:23:25 +02:00
Samy Pessé 9b8d5198e4 Experiment with lower DO billable duration by using direct RPC methods (#2492) 2024-09-25 23:57:43 +02:00
Samy Pessé e09f747727 Refresh change request cache when click refresh button (#2489) 2024-09-25 16:15:42 +02:00
Samy Pessé 16e6171750 Cache embeds for faster rendering (#2488) 2024-09-25 13:33:40 +02:00
Samy Pessé f885e887ea Improve change request previews: consistency and toolbar (#2487) 2024-09-25 12:54:15 +02:00
Samy Pessé 5096f7fbc5 Disable KV cache for docs.gitbook.com and change requests (#2485) 2024-09-25 11:53:53 +02:00
Brett Jephson f16560c1ee Scroll offset (#2484) 2024-09-25 08:52:44 +01:00
Samy Pessé d0f4860759 Refresh icons urls to purge cache of 500 (#2483) 2024-09-24 18:16:35 +02:00
Samy Pessé 34d36c6de1 Fix next-on-pages configuration for ~gitbook/static (#2482) 2024-09-24 17:25:58 +02:00
Brett Jephson 042b850b5d RND-2147: automatically scroll TOC (#2478) 2024-09-24 16:24:55 +01:00
Samy Pessé 73892f4fc2 Fix release preview CI workflow (#2481) 2024-09-24 13:13:45 +02:00
Samy Pessé 636b868bf1 Experimental new cache backend powered by DO (#2479)
Co-authored-by: Johan Preynat <johan.preynat@gmail.com>
2024-09-24 12:55:49 +02:00
Addison b144368e3f Update Dutch "Ask or Search" terminology to fit on one line (#2480) 2024-09-24 16:30:30 +09:00
Scott Cazan 683b4193d1 Don't use customized site title for space in search selector (#2367) 2024-09-23 12:43:03 +02:00
Samy Pessé f4c953665a Optimize layout shift while transitioning between pages with full width blocks (#2477) 2024-09-23 06:19:49 +02:00
Samy Pessé 0f990c772a Show definition title when visible in cards (#2476) 2024-09-22 19:04:23 +02:00
Samy Pessé 0bf985af61 Don't show hidden pages in the empty state of a page (#2475) 2024-09-19 15:17:13 +02:00
Samy Pessé 42473611d3 Add required query parameters to the code sample (#2474) 2024-09-19 14:31:22 +02:00
Samy Pessé 2c437f7d94 Fix linking to tabs itself (#2473) 2024-09-19 10:52:34 +02:00
vibhanshub aa8c49eb0c Display pattern if available in OpenAPI params (#2461)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-09-19 09:59:10 +02:00
Samy Pessé b32e40c72a Persist state of tabs and dynamically sync them based on title (#2472) 2024-09-19 09:40:54 +02:00
Samy Pessé 2ff7ed1b52 Hide button on mobile to open toc if disabled at the page level (#2471) 2024-09-18 19:49:02 +02:00
Samy Pessé bfbed1a69b Use translation for "Sponsored via GitBook" (#2469) 2024-09-17 13:41:53 +02:00
Samy Pessé ef9d012be9 Fix generation of icons package and add task "clean" (#2470) 2024-09-17 13:41:18 +02:00
Nichlas f12a2155c0 Added the Norwegian language (#2467)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-09-17 12:15:21 +02:00
Taran Vohra 43f696c4a8 use samesite none for tracking cookie (#2299) 2024-09-17 11:57:28 +05:30
Samy Pessé 4c19014dcd Prevent robots indexation for pages where it's disabled (#2464) 2024-09-13 13:52:15 +02:00
Samy Pessé 0e7f9d6778 Fix TS error when adding support for a locale not yet supported by API (#2465) 2024-09-13 10:30:20 +02:00
Rens Reinders 00a0bf3c1b Add Dutch Locale support (#2450) 2024-09-13 10:12:44 +02:00
taranvohra 434cfd7a08 WIP 2024-09-12 18:02:33 +02:00
taranvohra e3587d59aa use gitbook/api version 0.61 2024-09-12 17:40:55 +02:00
Brett Jephson e9149036f6 RND-3387: synchronize response tabs (#2457)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-09-12 11:01:29 +01:00
Addison b6a9967959 Update search/ask wording for Japanese localization to fit UI better (#2462) 2024-09-12 09:58:58 +02:00
Addison 8bbc3caf3e Update Readme & Contributing Guide (#2459) 2024-09-09 15:28:19 +02:00
Samy Pessé 237b703a6c Fix crash in OpenAPI block because of undefined examples (#2458) 2024-09-06 16:55:04 +02:00
vibhanshub cf3045a718 Add Python support in code samples (#2453) 2024-09-06 14:29:50 +01:00
vibhanshub a679e7283f Render mandatory headers in the code sample (#2445) 2024-09-06 13:24:52 +01:00
Samy Pessé 13c75341e2 Use ellipsis and fix icon color for more links in the header on small screen (#2455) 2024-09-06 11:57:42 +02:00
Marc Laventure 4cbcc5bb20 fix: rollback scalar (#2454)
Co-authored-by: Brett Jephson <brett@gitbook.io>
2024-09-06 10:32:33 +01:00
Brett Jephson 51955dae3b Response examples with status code tabs (#2448) 2024-09-06 09:35:43 +01:00
Brett Jephson 51fa3ab2c8 Use content-visibility on open api operations (#2451) 2024-09-05 17:21:42 +01:00
Samy Pessé af9e66e87e Only display spaces dropdown in compact header when site is multi-variants (#2447) 2024-09-03 19:49:05 +02:00
Samy Pessé 8878dc7f80 Accept special ip headers from gitbook backend (#2446) 2024-09-03 16:47:51 +02:00
Scott Cazan 4336bc20e0 Filter out short searches less then 2 chars, bigger debounce (#2440) 2024-09-03 14:49:35 +02:00
Samy Pessé 4a7613a521 Fix community ads fetching (#2444) 2024-09-03 13:54:31 +02:00
Samy Pessé 689f55340f Fix inconsistent click area in table because of scroll indicator (#2443) 2024-09-02 14:58:56 +02:00
Taran Vohra 160ae3d49d Add spaces dropdown to CompactHeader component (#2439) 2024-08-28 10:08:25 +05:30
Marc Laventure c079c3c6d9 chore: bump scalar package (#2421)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-08-21 08:27:22 +02:00
Samy Pessé cb782a7557 Fix running GitBook locally and fix community ad rendering (#2437) 2024-08-20 19:37:33 +02:00
Abhishek 502d8fc087 Fix typo in README.md (#2430) 2024-08-20 14:55:46 +02:00
Brett Jephson 6295881138 RND-3373: update the shadow for dark mode in multi-space search (#2436) 2024-08-20 13:54:28 +01:00
Brett Jephson 17f71ba680 RND-3113: expand when expandable anchor (#2435) 2024-08-20 11:04:00 +01:00
Brett Jephson 5fe7adb87b RND-3532: drop down menu for hidden links at small screen size (#2434) 2024-08-19 11:51:48 +01:00
spastorelli 41684d091b Revert "Automatically scroll to the active page in table of contents (#2425) (#2429) 2024-08-15 16:52:27 +02:00
spastorelli 9f6c3347cb Automatically scroll to the active page in table of contents (#2425) 2024-08-15 11:42:48 +02:00
Samy Pessé aa321989c4 Use a <div> instead of <h1> in the top header (#2428) 2024-08-14 10:02:42 +02:00
Samy Pessé 0f1565cb4b Fix mermaid / contentkit webframe not updating properly (#2427) 2024-08-13 15:26:11 +02:00
Samy Pessé 3996110ebd Optimize and resize images in community ads (#2426) 2024-08-09 15:41:35 +02:00
Samy Pessé 3422ad4c84 Iteration on community ads (#2422) 2024-08-09 12:31:36 +02:00
spastorelli 3c07e65b9a Fix paragraph top margin in quote blocks (#2423) 2024-08-09 10:58:20 +02:00
Steven H 287df91661 Add an nvmrc file (#2405) 2024-08-07 15:32:08 +01:00
Samy Pessé 776bc3135a Fix running repository without access to Pro token for @gitbook/icons (#2417)
Co-authored-by: Valentino Hudhra <2587839+valentin0h@users.noreply.github.com>
2024-08-02 18:40:44 +02:00
Samy Pessé 4638958c9f Fix preview of customization (#2418) 2024-08-02 18:24:41 +02:00
Samy Pessé 1f24fe46c4 Add support for page icons and icons style customization (#2416) 2024-08-02 17:28:32 +02:00
Valentino Hudhra ccbcab8822 Control tracking of page views with env/header variables (#2380) 2024-08-02 16:10:28 +02:00
Marc Laventure 094e9cdac2 chore: bump scalar (#2410)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-08-02 10:24:39 +02:00
Samy Pessé 5c35f36b3a Prepare @gitbook/icons package and use it as a replacement of geist/icons (#2404) 2024-08-02 09:59:44 +02:00
Steven H d7ec2b57a4 Bump getPublishedContentByUrl cache to fix a recent issue with the GitBook API (#2414) 2024-08-01 06:54:09 +01:00
Steven H 373a1e0312 Bump URL resolution caches after a recent hotfix. (#2412) 2024-07-29 14:22:20 +01:00
Taran Vohra e9fe3975bb Pass shareKey as context while fetching space (#2409) 2024-07-26 16:14:20 +05:30
Samy Pessé 32a73b55d4 Version Packages (#2403)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-25 15:12:18 +02:00
Samy Pessé 0426312d6c Reset to first tab when tabs change in an InteractiveSection (#2407) 2024-07-25 15:09:21 +02:00
Samy Pessé ede2335fb3 Fix x-codeSamples: false not working at the single operation level (#2408) 2024-07-25 14:59:30 +02:00
Amrit Kahlon 709f1a1ccb Update Scalar Api Client to new version (#2406)
Co-authored-by: marclave <marc@scalar.com>
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-07-25 10:25:50 +02:00
Samy Pessé 24b785cbfb Update shiki to fix diff code highlighting (#2338) 2024-07-25 09:33:42 +02:00
Samy Pessé acc3f2f418 Fix Scalar proxy failing on Cloudflare (#2402) 2024-07-24 11:41:35 +02:00
Scott Cazan d4a653d6a9 Use SpaceURL in getURL function to for cross-space searches (#2399) 2024-07-23 12:07:32 +02:00
Samy Pessé 7e74d25447 Version Packages (#2397)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-22 16:26:53 +02:00
Samy Pessé 3445db41ce Fix packages not including all files (#2396) 2024-07-22 16:20:06 +02:00
Samy Pessé d1bd02a6f5 Version Packages (#2395)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-22 15:43:27 +02:00
Samy Pessé 24cd72e088 Use a personal token for the changeset GitHub workflow (#2394) 2024-07-22 15:30:11 +02:00
github-actions[bot] 47f7558c38 Version Packages (#2393)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-22 15:05:57 +02:00
Samy Pessé de747b7b33 Better structure monorepo and publish JS files for react-openapi and react-math (#2392) 2024-07-22 15:02:04 +02:00
Samy Pessé 8e8b73fbd9 Publish packages as public with changeset (#2391) 2024-07-21 21:25:43 +02:00
489 changed files with 5901 additions and 2881 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Avoid multiple <h1> in the page by using a <div> for the title in the header
+6
View File
@@ -0,0 +1,6 @@
---
'@gitbook/react-openapi': patch
'gitbook': patch
---
Adds content-visibility css property to OpenAPI Operation for better render performance
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/cache-do': minor
---
Experiment with optimizing billable duration in Cloudflare by using multiple RPC sessions instead of one
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix scroll position when navigating pages on mobile
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': minor
---
Add Python support in Code Samples
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
RND-3532: drop down menu for hidden links at small screen size
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Change dark mode shadow for multi-space search toolbar
+1 -1
View File
@@ -4,7 +4,7 @@
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Use ellipsis and fix icon color for more links in the header on small screen
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Improve consistency of change request preview by removing cache-control on response
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/icons': patch
---
Update version for static assets to fix invalid caching
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Revalidate change request cached content when pressing refresh button
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/icons': patch
---
Fix first run of the package in development mode
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Improve performances of loading pages with embeds by caching them
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
bump: scalar from 1.0.5 to 1.0.7
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Replace all icons, previously imported from Geist, by new package `@gitbook/icons`
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/cache-do': minor
---
First version of a new cache backend powered by Cloudflare Durable Objects
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Add support for Norwegian language
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Optimize layout shift while transitioning between pages with full width blocks (ex: OpenAPI blocks)
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Add support for page icons
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix GitBook specific static assets not being served correctly when deployed on Cloudflare
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Only display spaces dropdown in compact header when site is multi-variants
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/cache-do': patch
---
Enable Workers observability with a sampling of 0.1
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/icons': minor
---
Initial release for `@gitbook/icons`, a package of content icons to be used for pages, documents, etc.
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Automatically scroll to active item in TOC
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Persist state of tabs and dynamically sync them based on title
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Ensure "Sponsored via GitBook" can be translated in all languages
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Show the caption for file blocks
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Use url hash to open Expandable and scroll to anchor
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix margin for paragraphs in quote blocks
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Use new cache backend, powered by Durable Objects, alongside the existing ones (KV, etc).
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Include offset in calculations of whether scrollable element is in view
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': minor
---
Add required query parameters to the code sample
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': minor
---
Display pattern if available in parmas in OpenAPI block
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix inconsistent click area in table because of scroll indicator
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Stop using KV cache backend for now, but also improves it for higher performances
+6
View File
@@ -0,0 +1,6 @@
---
'@gitbook/react-openapi': minor
'gitbook': patch
---
Synchronize response and response example tabs
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Show definition title when visible in cards
+6
View File
@@ -0,0 +1,6 @@
---
'@gitbook/react-openapi': minor
'gitbook': patch
---
Rollback of scalar modal while fixing perf issue
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Optimize images rendered in community ads
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Update design of Checkbox to be more consistent and readable
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-contentkit': patch
---
Fix rendering of webframe with SSR causing wrong communication between frame and renderer
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Disable KV cache for docs.gitbook.com as a test, also disable it for change-request to improve consistency
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Add optional env `GITBOOK_INTEGRATIONS_HOST` to configure the host serving the integrations
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
Fix crash when `example` is undefined for a response
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Improve the toolbar for change-requests and revisions to show more actions
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Add support for icons style customization for sites
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
Adds tabs to Response Example section e.g. for status code examples
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
Render mandatory headers in code sample
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
Update Scalar client to latest version
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Prevent search indexation for pages where it's configured as disabled
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix table of contents being visible on mobile when disabled at the page level
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix accessibility of the table of contents by using `aria-current` instead of `aria-selected`
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Update rendering of community ads to match new API response, and make it possible to preview ads.
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-math': minor
---
Export binary `gitbook-math` to copy assets to a directory
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix "ip" being passed to BSA for community ads
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Changed the alternative URL resolution criteria in order to support site URLs without /v/ prefix
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/icons': minor
---
Fix bin gitbook-icons when installed without the Pro token
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Don't show hidden pages in the empty state of a page
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Fix linking to a tab itself
+21 -7
View File
@@ -1,6 +1,8 @@
# Welcome to GitBook's contributing guide!
Thank you for investing your time in contributing to GitBook. Any contribution you make will be reviewed by our team.In this guide, you'll learn the different ways you can contribute.
> _For help, support, feature requests, and product questions - head to our [GitHub Community](https://github.com/orgs/GitbookIO/discussions) 🤖_
Thank you for investing your time in contributing to GitBook. Any contribution you make will be reviewed by our team. In this guide, you'll learn the different ways you can contribute.
## Types of Contributions
@@ -45,13 +47,25 @@ Any contribution you make can be made to the code located in this repository. In
- [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.
##### GitHub Codespaces:
- [Fork, edit, and preview](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace) using [GitHub Codespaces](https://github.com/features/codespaces) without having to install and run the project locally.
#### 2. Create a working branch and start with your changes
After forking this repository, you'll want to [create a branch](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-a-branch-for-an-issue) to work off of. After creating the branch, you can start making changes!
After forking this repository, you'll want to [create a branch](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-a-branch-for-an-issue) to work off of.
#### 3. Install dependencies and run the project locally
GitBook uses [Bun](https://bun.sh/) to run the project. Make sure you're using the specified version of `node` before running any of the development commands to ensure a smooth development experience.
You can easily do this by running the command `nvm use`.
To start your local version of GitBook, run the command `bun dev`.
#### 4. Preview your changes
When running the development server, published GitBook sites can be rendered through your local version at `http://localhost:3000/`.
For example, our published docs can be viewed using the local version by visiting `http://localhost:3000/docs.gitbook.com` after running the development server.
You can visit any published GitBook site behind your development server. Please make sure your site is [published publicly](https://docs.gitbook.com/published-documentation/publish-your-content-as-a-docs-site) to ensure you can view the site correctly in your development version.
### Commit your update
@@ -71,4 +85,4 @@ When you're finished with the changes, [create a pull request](https://docs.gith
### Your PR is merged
Congratulations 🎉Thank you for your contribution! Once your PR is merged, your contributions will be publicly visible on the relevant repository.
Congratulations 🎉 Thank you for your contribution! Once your PR is merged, your contributions will be publicly visible on the relevant repository.
+3 -1
View File
@@ -7,7 +7,7 @@ runs:
- name: 🏗 Prepare Playwright env
shell: bash
run: |
PLAYWRIGHT_VERSION=$(npm ls --json @playwright/test | jq --raw-output '.dependencies["@playwright/test"].version')
PLAYWRIGHT_VERSION=$(npm ls --json @playwright/test | jq --raw-output '.dependencies["gitbook"].dependencies["@playwright/test"].version')
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
# Cache browser binaries, cache key is based on Playwright version and OS
@@ -24,6 +24,7 @@ runs:
- name: 🏗 Install Playwright browser binaries & OS dependencies
if: steps.playwright-cache.outputs.cache-hit != 'true'
shell: bash
working-directory: packages/gitbook
run: |
bun x playwright install --with-deps chromium
@@ -31,5 +32,6 @@ runs:
- name: 🏗 Install Playwright OS dependencies
if: steps.playwright-cache.outputs.cache-hit == 'true'
shell: bash
working-directory: packages/gitbook
run: |
bun x playwright install-deps
+28 -3
View File
@@ -4,7 +4,8 @@ on:
push:
branches:
- main
env:
NPMRC_FONT_AWESOME_TOKEN: ${{ secrets.NPMRC_FONT_AWESOME_TOKEN }}
jobs:
deploy:
name: Deploy to Cloudflare Pages
@@ -58,7 +59,7 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ vars.CLOUDFLARE_PROJECT_NAME }}
directory: ./.vercel/output/static
directory: ./packages/gitbook/.vercel/output/static
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
workingDirectory: ./
- name: Outputs
@@ -92,6 +93,12 @@ jobs:
env:
BASE_URL: ${{needs.deploy.outputs.deployment_url}}
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-test-results
path: packages/gitbook/test-results/
retention-days: 3
pagespeed-testing:
runs-on: ubuntu-latest
name: PageSpeed Testing
@@ -108,7 +115,7 @@ jobs:
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- name: Run pagespeed tests
run: bun ./tests/pagespeed-testing.ts $DEPLOYMENT_URL
run: bun ./packages/gitbook/tests/pagespeed-testing.ts $DEPLOYMENT_URL
env:
DEPLOYMENT_URL: ${{needs.deploy.outputs.deployment_url}}
PAGESPEED_API_KEY: ${{ secrets.PAGESPEED_API_KEY }}
@@ -157,6 +164,24 @@ jobs:
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- run: bun unit
build-oss:
# CI to check that the repository builds correctly on a machine without the credentials
runs-on: ubuntu-latest
name: Build (Open Source)
env:
NPMRC_FONT_AWESOME_TOKEN: ''
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.1.18
- name: Install dependencies
run: bun install --frozen-lockfile
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- run: bun run build
typecheck:
runs-on: ubuntu-latest
name: Typecheck
+26 -1
View File
@@ -31,5 +31,30 @@ jobs:
with:
publish: npm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Using a PAT instead of GITHUB_TOKEN because we need to run workflows when releases are created
# https://github.com/orgs/community/discussions/26875#discussioncomment-3253761
GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
release-preview:
# For now it releases the cache-do to both preview and production
# Once we changed to deploy the app only on release, we should change `release:preview` in `cache-do`
name: Release Preview
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.1.18
- name: Install dependencies
run: bun install --frozen-lockfile
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- name: Release preview packages
run: bun run release:preview
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+5 -29
View File
@@ -5,16 +5,6 @@ node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
@@ -24,25 +14,11 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# Turbo
.turbo
# vercel
# Vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# visual tests
screenshots/
# Sentry Config File
.sentryclirc
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
# Generated public files
/public/~gitbook/static/
# Env files
.env.local
+1
View File
@@ -0,0 +1 @@
v20.6
+6
View File
@@ -1,4 +1,10 @@
.next
.vercel
# Generated
packages/emoji-codepoints/index.ts
packages/gitbook/public/~gitbook/static/
packages/icons/src/data/*.json
# Build files
dist/
+38 -9
View File
@@ -5,7 +5,7 @@
</p>
<p align="center">
<a href="https://gitbook.com"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=data:image/svg%2bxml;base64,PHN2ZyB3aWR0aD0iNjUiIGhlaWdodD0iNjUiIHZpZXdCb3g9IjAgMCA2NSA2NSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI3LjM5NjQgMzMuNjc2NEMzMC41MjU1IDM1LjQ4MjQgMzIuMDkgMzYuMzg1NCAzMy44MDgzIDM2LjM4NjlDMzUuNTI2NSAzNi4zODg0IDM3LjA5MjYgMzUuNDg4MiA0MC4yMjQ5IDMzLjY4NzdMNjAuMTkxNCAyMi4yMTA0QzYxLjA5MjcgMjEuNjkyMiA2MS42NDg0IDIwLjczMTggNjEuNjQ4NCAxOS42OTIxQzYxLjY0ODQgMTguNjUyNCA2MS4wOTI3IDE3LjY5MiA2MC4xOTE0IDE3LjE3MzlMNDAuMjE3NyA1LjY5MjQ1QzM3LjA4ODggMy44OTM4NiAzNS41MjQzIDIuOTk0NTcgMzMuODA3OCAyLjk5NTI0QzMyLjA5MTIgMi45OTU5MSAzMC41Mjc1IDMuODk2NDIgMjcuNCA1LjY5NzQ0TDEwLjIyOTMgMTUuNTg1NUMxMC4xMDIgMTUuNjU4OCAxMC4wMzg0IDE1LjY5NTQgOS45NzkwOCAxNS43MzAxQzQuMTEzNzEgMTkuMTYzNyAwLjQ4OTg5MiAyNS40MzIzIDAuNDQxNDM4IDMyLjIyODZDMC40NDA5NDggMzIuMjk3MyAwLjQ0MDk0OCAzMi4zNzA4IDAuNDQwOTQ4IDMyLjUxNzZDMC40NDA5NDggMzIuNjY0MyAwLjQ0MDk0OCAzMi43Mzc2IDAuNDQxNDM3IDMyLjgwNjNDMC40ODk3ODUgMzkuNTk0OSA0LjEwNTUyIDQ1Ljg1NzcgOS45NjA0NCA0OS4yOTRDMTAuMDE5NiA0OS4zMjg3IDEwLjA4MzIgNDkuMzY1NCAxMC4yMTAyIDQ5LjQzODdMMjAuOTY1OSA1NS42NDg3QzI3LjIzMzIgNTkuMjY3MyAzMC4zNjY4IDYxLjA3NjYgMzMuODA4MSA2MS4wNzc3QzM3LjI0OTMgNjEuMDc4OSA0MC4zODQyIDU5LjI3MTcgNDYuNjUzOSA1NS42NTc0TDU4LjAwOCA0OS4xMTIxQzYxLjE0NzQgNDcuMzAyMyA2Mi43MTcxIDQ2LjM5NzQgNjMuNTc5IDQ0LjkwNTZDNjQuNDQwOSA0My40MTM5IDY0LjQ0MDkgNDEuNjAyIDY0LjQ0MDkgMzcuOTc4NFYzMC45NzgxQzY0LjQ0MDkgMjkuOTcyOCA2My44OTY1IDI5LjA0NjQgNjMuMDE4MiAyOC41NTczQzYyLjE2ODQgMjguMDgzOSA2MS4xMzI1IDI4LjA5MSA2MC4yODkxIDI4LjU3NThMMzcuMDA3NCA0MS45NTg4QzM1LjQ0NTQgNDIuODU2NyAzNC42NjQzIDQzLjMwNTYgMzMuODA3MyA0My4zMDU5QzMyLjk1MDIgNDMuMzA2MiAzMi4xNjg5IDQyLjg1NzcgMzAuNjA2MyA0MS45NjA3TDE0Ljg0ODcgMzIuOTE1NUMxNC4wNTk0IDMyLjQ2MjQgMTMuNjY0NyAzMi4yMzU5IDEzLjM0NzcgMzIuMTk1QzEyLjYyNSAzMi4xMDE3IDExLjkzMDEgMzIuNTA2NiAxMS42NTQ4IDMzLjE4MTNDMTEuNTM0MSAzMy40NzcyIDExLjUzNjUgMzMuOTMyMiAxMS41NDE0IDM0Ljg0MjRDMTEuNTQ1IDM1LjUxMjQgMTEuNTQ2OCAzNS44NDc0IDExLjYwOTQgMzYuMTU1NkMxMS43NDk3IDM2Ljg0NTYgMTIuMTEyNyAzNy40NzA1IDEyLjY0MjggMzcuOTM0MUMxMi44Nzk1IDM4LjE0MTEgMTMuMTY5NiAzOC4zMDg1IDEzLjc1IDM4LjY0MzVMMzAuNTk3NCA0OC4zNjcyQzMyLjE2NDEgNDkuMjcxNCAzMi45NDc0IDQ5LjcyMzUgMzMuODA3NSA0OS43MjM3QzM0LjY2NzcgNDkuNzIzOSAzNS40NTEzIDQ5LjI3MjMgMzcuMDE4NCA0OC4zNjg5TDU3LjY2ODQgMzYuNDY1NEM1OC4yMDM3IDM2LjE1NjkgNTguNDcxNCAzNi4wMDI2IDU4LjY3MjEgMzYuMTE4NUM1OC44NzI3IDM2LjIzNDUgNTguODcyNyAzNi41NDM0IDU4Ljg3MjcgMzcuMTYxM1Y0MC4zMzY1QzU4Ljg3MjcgNDEuMjQyNCA1OC44NzI3IDQxLjY5NTQgNTguNjU3MiA0Mi4wNjgzQzU4LjQ0MTggNDIuNDQxMyA1OC4wNDkzIDQyLjY2NzUgNTcuMjY0NCA0My4xMTk5TDQwLjIzMjIgNTIuOTM4QzM3LjA5NjYgNTQuNzQ1NCAzNS41Mjg4IDU1LjY0OTIgMzMuODA3OSA1NS42NDg0QzMyLjA4NjkgNTUuNjQ3NiAzMC41MTk5IDU0Ljc0MjQgMjcuMzg2IDUyLjkzMjFMMTEuNDUwOSA0My43MjdDMTEuNDAwMyA0My42OTc4IDExLjM3NSA0My42ODMyIDExLjM1MTQgNDMuNjY5NEM4LjAxMDIzIDQxLjcxNyA1Ljk0ODU5IDM4LjE0NTEgNS45MjkyNSAzNC4yNzU0QzUuOTI5MTIgMzQuMjQ4IDUuOTI5MTIgMzQuMjE4OCA1LjkyOTEyIDM0LjE2MDRWMzEuMjQ1OEM1LjkyOTEyIDI5LjEwOTUgNy4wNjY4OSAyNy4xMzQ5IDguOTE1MTMgMjYuMDYzNkMxMC41NDgzIDI1LjExNjkgMTIuNTYyOCAyNS4xMTUxIDE0LjE5NzcgMjYuMDU4N0wyNy4zOTY0IDMzLjY3NjRaIiBmaWxsPSIjRjJGN0Y3Ii8+Cjwvc3ZnPgo=&labelColor=5c5c5c&color=3F89A1&label=%20" alt="Documented on GitBook"></a>
<a href="https://gitbook.com"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=3F89A1"></a>
<a href="#"><img src="https://img.shields.io/badge/Open_Source-❤️-FDA599?"/></a>
<a href="/LICENSE"><img src="https://img.shields.io/badge/License-GNU_GPLv3-F4E28D"/></a>
<a href="/.github/CONTRIBUTING.md"><img src="https://img.shields.io/github/contributors/gitbookIO/gitbook"/></a>
@@ -14,7 +14,7 @@
<p align="center">Welcome to GitBook, the platform for managing technical knowledge for teams.</p>
<p align="center">This repository contains the open-source code used to render GitBook's published content.</p>
<p align="center">This repository contains the open source code used to render GitBook's published content.</p>
<p align="center">
<img alt="GitBook Open Published Site" src="./assets/published-site.png">
@@ -46,19 +46,28 @@ To run a local version of this project, please follow these simple steps.
git clone https://github.com/gitbookIO/gitbook.git
```
2. Install the project's dependencies through Bun.
2. Ensure you are using the project's version of `node`. Running `nvm use` will change your local version to the correct one.
3. Install the project's dependencies through Bun.
```
bun install
```
3. Start your local development server.
4. Start your local development server.
```
bun dev
```
Then open the space in your web browser, using http://localhost:3000/<host>/<path> (example: http://localhost:3000/docs.gitbook.com).
5. Open a published GitBook space in your web browser, prefixing it with `http://localhost:3000/`.
examples:
- http://localhost:3000/docs.gitbook.com
- http://localhost:3000/open-source.gitbook.io/midjourney
Any published GitBook site can be accessed through your local development instance, and any updates you make to the codebase will be reflected in your browser.
### Other development commands
@@ -71,7 +80,7 @@ All pull-requests will be tested against both visual and performances testing to
## Contributing
GitBook's rendering engine is fully open-source and built on top of [Next.js](https://nextjs.org/). Head to our [contributing guide](https://github.com/GitbookIO/gitbook/.github/CONTRIBUTING.md) to learn more about the workflow on adding your first Pull Request.
GitBook's rendering engine is fully open source and built on top of [Next.js](https://nextjs.org/). Head to our [contributing guide](https://github.com/GitbookIO/gitbook/blob/main/.github/CONTRIBUTING.md) to learn more about the workflow on adding your first Pull Request.
### Types of contributions
@@ -79,7 +88,7 @@ We encourage you to contribute to GitBook to help us build the best tool for doc
#### Translations
The GitBook UI is rendered using a set of translation files found in [`src/intl/translations`](/src/intl/translations/). We welcome all additional translations for the UI.
The GitBook UI is rendered using a set of translation files found in [`packages/gitbook/src/intl/translations`](/packages/gitbook/src/intl/translations/). We welcome all additional translations for the UI.
#### Bugs
@@ -90,7 +99,7 @@ Encounter a bug or find an issue you'd like to fix? Helping us fix issues relate
> [!WARNING]
> While it is possible to self-host this project, we do not recommend this unless you are certain this option fits your need.
>
> _Looking to add a specific feature in GitBook? Head to our [contributing guide](/.github/CONTRIBUTING.md) to get started._
> _Looking to add a specific feature in GitBook? Head to our [contributing guide](https://github.com/GitbookIO/gitbook/blob/main/.github/CONTRIBUTING.md) to get started._
>
> Self-hosting this project puts the responsibility of maintaining and merging future updates on **you**. We cannot guarantee support, maintenance, or updates to forked and self-hosted instances of this project.
>
@@ -106,10 +115,30 @@ On the con side, you become responsible for the reliability of your published si
Distributed under the [GNU GPLv3 License](https://github.com/GitBookIO/gitbook/blob/main/LICENSE).
If you plan to distribute the code, you must the source code public to comply with GNU GPLv3. To clone in a private repository, acquire a [commercial license](https://www.gitbook.com/pricing).
If you plan to distribute the code, you must make the source code public to comply with the GNU GPLv3. To clone in a private repository, acquire a [commercial license](https://www.gitbook.com/pricing).
See `LICENSE` for more information.
## Badges
<p align="left">
<a href="https://gitbook.com"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=3F89A1"></a>
<a href="https://gitbook.com"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=F4E28D"></a>
<a href="https://gitbook.com"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=FDA599"></a>
</p>
```md
[![GitBook](https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=3F89A1)](https://gitbook.com/)
```
```html
<a href="https://gitbook.com">
<img
src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=3F89A1"
/>
</a>
```
## Acknowledgements
GitBook wouldn't be possible without these projects:
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
[install.scopes]
"awesome.me" = { token = "$NPMRC_FONT_AWESOME_TOKEN", url = "https://npm.fontawesome.com/" }
+22 -84
View File
@@ -1,96 +1,34 @@
{
"name": "gitbook",
"version": "0.1.0",
"devDependencies": {
"@changesets/cli": "^2.27.7",
"prettier": "^3.0.3",
"turbo": "^2.1.2"
},
"packageManager": "bun@1.1.18",
"patchedDependencies": {
"@vercel/next@4.3.6": "patches/@vercel%2Fnext@4.3.6.patch"
},
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build:cloudflare": "next-on-pages",
"start": "next start",
"lint": "next lint",
"dev": "turbo run dev",
"build": "turbo run build",
"build:cloudflare": "turbo run build:cloudflare",
"lint": "turbo run lint",
"lint:fix": "turbo run lint -- --fix",
"typecheck": "turbo run typecheck",
"format": "prettier ./ --ignore-unknown --write",
"format:check": "prettier ./ --ignore-unknown --list-different",
"typecheck": "tsc --noEmit",
"unit": "bun test {src,packages}",
"e2e": "playwright test",
"unit": "turbo run unit",
"e2e": "turbo run e2e",
"changeset": "changeset",
"release": "changeset publish",
"postinstall": "rm -rf ./public/~gitbook/static/mathjax@3.2.2 && mkdir -p ./public/~gitbook/static/ && cp -R node_modules/mathjax/es5 ./public/~gitbook/static/mathjax@3.2.2"
"release": "turbo run release && changeset publish",
"release:preview": "turbo run release:preview",
"download:env": "op read op://gitbook-x-dev/gitbook-open/.env.local >> .env.local",
"clean": "turbo run clean"
},
"workspaces": [
"packages/*"
],
"dependencies": {
"@geist-ui/icons": "^1.0.2",
"@gitbook/api": "^0.56.0",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-popover": "^1.0.7",
"@sentry/nextjs": "^7.94.1",
"@sindresorhus/fnv1a": "^3.1.0",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/typography": "^0.5.10",
"@upstash/redis": "^1.27.1",
"ajv": "^8.12.0",
"assert-never": "^1.2.1",
"bun-types": "^1.0.7",
"classnames": "^2.5.1",
"content-security-policy-merger": "^1.0.0",
"framer-motion": "^10.16.14",
"js-cookie": "^3.0.5",
"jsontoxml": "^1.0.1",
"katex": "^0.16.9",
"mathjax": "^3.2.2",
"memoizee": "^0.4.15",
"next": "^14.1.3",
"next-themes": "^0.2.1",
"nuqs": "^1.17.4",
"object-hash": "^3.0.0",
"openapi-types": "^12.1.3",
"p-map": "^7.0.0",
"parse-cache-control": "^1.0.1",
"react": "^18",
"react-dom": "^18",
"react-hotkeys-hook": "^4.4.1",
"recoil": "^0.7.7",
"rehype-sanitize": "^6.0.0",
"rehype-stringify": "^10.0.0",
"remark-gfm": "^4.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"rison": "^0.1.1",
"server-only": "^0.0.1",
"shiki": "^1.2.0",
"tailwind-merge": "^2.2.0",
"tailwind-shades": "^1.1.2",
"unified": "^11.0.4",
"url-join": "^5.0.0"
},
"devDependencies": {
"@argos-ci/playwright": "^2.0.0",
"@changesets/cli": "^2.27.7",
"@cloudflare/next-on-pages": "^1.11.3",
"@cloudflare/workers-types": "^4.20231218.0",
"@playwright/test": "^1.42.1",
"@types/js-cookie": "^3.0.6",
"@types/jsontoxml": "^1.0.5",
"@types/jsonwebtoken": "^9.0.6",
"@types/katex": "^0.16.5",
"@types/node": "^20",
"@types/object-hash": "^3.0.6",
"@types/parse-cache-control": "^1.0.4",
"@types/psi": "^4.1.6",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/rison": "^0.0.9",
"autoprefixer": "^10",
"eslint": "^8",
"eslint-config-next": "13.5.6",
"eslint-plugin-import": "^2.29.0",
"jsonwebtoken": "^9.0.2",
"postcss": "^8",
"prettier": "^3.0.3",
"psi": "^4.1.0",
"tailwindcss": "^3.4.0",
"typescript": "^5"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
.wrangler
worker-configuration.d.ts
dist/
+22
View File
@@ -0,0 +1,22 @@
# `@gitbook/cache-do`
Cache backend, powered by Cloudflare Durable Objects. The cache is optimized for GitBook use-cases.
### Performances
The cache backend is optimized for performances by being distributed and accessible close to the worker locations that are reading it.
### Geo-distribution
To achieve a good balance between **performances** and **consistency**, cache objects are distributed over 7 locations, representing continents.
It makes it possible to purge all 7 locations in one go and achieve fast consistency.
### Concepts
**Cache tag**: unique tag in the cache environment. A cache tag groups multiple keys that should be purged together in one operation.
Cache tags should not contain a large set of unique keys. Exceeding thousands could lead to performances or reliability issues.
**Cache key**: unique key in the cache environment. Each key should be assigned to a `tag`.
**Location**: cache is distributed over 7 unique locations, one for each continent.
+42
View File
@@ -0,0 +1,42 @@
{
"name": "@gitbook/cache-do",
"type": "module",
"private": true,
"exports": {
".": {
"types": "./dist/index.d.ts",
"development": "./src/index.ts",
"default": "./dist/index.js"
},
"./api": {
"types": "./dist/api.d.ts",
"development": "./src/api.ts",
"default": "./dist/api.js"
}
},
"version": "0.0.0",
"dependencies": {
"@msgpack/msgpack": "^3.0.0-beta2",
"lru_map": "^0.4.1"
},
"devDependencies": {
"typescript": "^5.5.3",
"wrangler": "^3.78.7"
},
"scripts": {
"generate": "wrangler types --experimental-include-runtime",
"build": "tsc",
"typecheck": "tsc --noEmit",
"dev": "tsc -w",
"release": "wrangler deploy",
"release:preview": "wrangler deploy && wrangler deploy --env preview"
},
"files": [
"dist",
"src",
"bin",
"data",
"README.md",
"CHANGELOG.md"
]
}
+299
View File
@@ -0,0 +1,299 @@
import { encode, decode } from '@msgpack/msgpack';
import { DurableObject } from 'cloudflare:workers';
import { LRUMap } from 'lru_map';
export interface CacheObjectDescriptor {
get: <Value = unknown>(key: string) => Promise<Value | undefined>;
set: <Value = unknown>(key: string, value: Value, expiresAt: number) => Promise<void>;
}
/**
* Value stored in a chunked binary msgpack format.
* Stored under the key `prop.${key}.${index}`.
*/
interface CacheObjectProp<Value = unknown> {
value: Value;
expiresAt: number;
}
/**
* Expiration clock stored under the key `exp.${expiresAt}.${key}`.
*/
interface CacheObjectExp {
/** Key of the property */
k: string;
/** Number of chunks */
c: number;
}
/**
* Durable Object class being deployed as a distributed cache.
*/
export class CacheObject extends DurableObject {
private lru = new LRUMap<string, { match: CacheObjectProp | undefined }>(500);
/**
* Open a descriptor to access the cache object.
* The goal is to minimize the amount of RPC sessions between the client and the cache object.
* One session is opened per request on the client side and used to perform multiple operations.
* https://developers.cloudflare.com/workers/runtime-apis/rpc/#return-functions-from-rpc-methods
*/
public open(): CacheObjectDescriptor {
return {
get: async <Value = unknown>(key: string) => {
return this.get<Value>(key);
},
set: async <Value = unknown>(key: string, value: Value, expiresAt: number) => {
await this.set(key, value, expiresAt);
},
};
}
/**
* Get the value of a property.
*/
public async get<Value = unknown>(key: string) {
return this.logOperation({ operation: 'get', key }, async (setLog) => {
// Try the memory state first.
const memoryEntry = this.lru.get(key);
if (memoryEntry) {
setLog({ memory: true });
setLog({ memoryMatch: !!memoryEntry.match });
if (!memoryEntry.match) {
return;
}
const isExpired = memoryEntry.match.expiresAt < Date.now();
setLog({ memoryExpired: isExpired });
if (!isExpired) {
return memoryEntry.match.value as Value;
}
}
return await this.getFromStorage<Value>(key);
});
}
/**
* Get the value of a property from the DO storage.
*/
public async getFromStorage<Value = unknown>(key: string) {
return this.logOperation({ operation: 'getFromStorage', key }, async (setLog) => {
const entries = await this.ctx.storage.list<Uint8Array>({
prefix: getStoragePropKey(key),
noCache: true,
});
if (entries.size) {
const entry = decodeChunks<CacheObjectProp<Value>>(entries);
setLog({ chunks: entries.size, chunksSize: entry?.size ?? 0 });
if (entry && entry.value.expiresAt > Date.now()) {
// Found
this.lru.set(key, { match: entry.value });
return entry.value.value;
}
}
// Not found
this.lru.set(key, { match: undefined });
});
}
/**
* Set a value in the cache object.
*/
public async set<Value = unknown>(key: string, value: Value, expiresAt: number) {
return this.logOperation({ operation: 'set', key }, async (setLog) => {
const prop: CacheObjectProp<Value> = {
value,
expiresAt,
};
this.lru.set(key, { match: prop });
await this.ctx.storage.transaction(async (tx) => {
const entries = encodeChunks(key, prop);
const chunks = Object.keys(entries).length;
setLog({ chunks });
const clockValue: CacheObjectExp = {
k: key,
c: chunks,
};
await tx.put(getGCClockKey(key, expiresAt), clockValue);
await tx.put(entries);
const currentAlarm = await tx.getAlarm();
if (!currentAlarm) {
// Set an alarm to garbage collect all entries that have expired in 12h.
await tx.setAlarm(Date.now() + 12 * 60 * 60 * 1000);
}
});
});
}
/**
* Purge all keys in the cache object.
*/
public async purge() {
return this.logOperation({ operation: 'purge' }, async (setLog) => {
let result = new Set<string>();
try {
// List all the keys in the cache object.
const entries = await this.ctx.storage.list<CacheObjectExp>({
prefix: 'exp.',
noCache: true,
});
setLog({ entries: entries.size });
entries.forEach((exp) => {
result.add(exp.k);
});
} catch (error) {
// If an error occurs, reset the cache object.
// This is a safety mechanism to prevent the cache object from being stuck in a bad state.
console.error('Error during purge, resetting the cache object', error);
}
await this.reset();
return Array.from(result);
});
}
/**
* Alarm to garbage collect all entries that have expired.
*/
async alarm() {
return this.logOperation({ operation: 'alarm' }, async (setLog) => {
try {
const entries = await this.ctx.storage.list<CacheObjectExp>({
prefix: 'exp.',
noCache: true,
});
setLog({ entries: entries.size });
const toDeleteSet = new Set<string>();
for (const [key, exp] of entries) {
const timestamp = parseInt(key.split('.')[1]);
if (timestamp < Date.now()) {
toDeleteSet.add(key);
for (let i = 0; i < exp.c; i++) {
toDeleteSet.add(getStoragePropChunkKey(exp.k, i));
}
}
}
// Delete the keys by batch of 128.
const toDelete = Array.from(toDeleteSet);
setLog({ toDelete: toDelete.length });
for (let i = 0; i < toDelete.length; i += 128) {
await this.ctx.storage.delete(toDelete.slice(i, i + 128));
}
// If there are still keys to delete, set an alarm to continue the deletion in 12h.
if (toDelete.length) {
await this.ctx.storage.setAlarm(Date.now() + 12 * 60 * 60 * 1000);
}
} catch (error) {
// If an error occurs, reset the cache object.
// This is a safety mechanism to prevent the cache object from being stuck in a bad state.
console.error('Error during alarm, reset the cache object', error);
await this.reset();
}
});
}
/**
* Reset the cache object.
*/
async reset() {
return this.logOperation({ operation: 'reset' }, async () => {
this.lru.clear();
await this.ctx.storage.deleteAll();
});
}
/**
* Time and log an operation.
*/
async logOperation<T>(
log: Record<string, unknown>,
fn: (update: (log: Record<string, unknown>) => void) => Promise<T>,
): Promise<T> {
const objectId = this.ctx.id.name ?? this.ctx.id.toString();
let update: Record<string, unknown> = {};
const start = performance.now();
try {
return await fn((arg) => {
Object.assign(update, arg);
});
} finally {
const duration = performance.now() - start;
console.log({ ...log, ...update, objectId, duration });
}
}
}
function getStoragePropKey(key: string): string {
return `prop.${key}.`;
}
function getStoragePropChunkKey(key: string, index: number): string {
return `${getStoragePropKey(key)}${index}`;
}
function getGCClockRootKey(timestamp: number): string {
return `exp.${timestamp}.`;
}
function getGCClockKey(key: string, expiresAt: number): string {
return `${getGCClockRootKey(expiresAt)}${key}`;
}
function encodeChunks<T>(key: string, value: T): Record<string, Uint8Array> {
const buf = encode(value);
const entries: Record<string, Uint8Array> = {};
const chunks = chunkUint8Array(buf, 128 * 1024);
for (let index = 0; index < chunks.length; index++) {
entries[getStoragePropChunkKey(key, index)] = chunks[index];
}
return entries;
}
function decodeChunks<T>(entries: Map<string, Uint8Array>): { value: T; size: number } | undefined {
const chunks = Array.from(entries.entries())
.map(([key, value]) => {
const index = parseInt(key.split('.').pop()!);
return [index, value] as const;
})
.sort(([a], [b]) => a - b)
.map(([, value]) => value);
if (chunks.length === 0) {
return;
}
const buf = mergeUint8Array(chunks);
return { value: decode(buf) as T, size: buf.length };
}
function chunkUint8Array(input: Uint8Array, chunkSize: number): Uint8Array[] {
const chunks: Uint8Array[] = [];
for (let i = 0; i < input.length; i += chunkSize) {
chunks.push(input.slice(i, i + chunkSize));
}
return chunks;
}
function mergeUint8Array(chunks: Uint8Array[]): Uint8Array {
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.length;
}
return result;
}
+97
View File
@@ -0,0 +1,97 @@
import type { CacheObject, CacheObjectDescriptor } from './CacheObject';
export type CacheLocationId = ContinentCode;
const allLocations: CacheLocationId[] = ['AF', 'AS', 'NA', 'SA', 'AN', 'EU', 'OC'];
/**
* Location hint for the CacheObject durable object.
*/
const doLocationHints: {
[key in CacheLocationId]: DurableObjectLocationHint;
} = {
AF: 'afr',
AS: 'apac',
NA: 'wnam',
SA: 'sam',
AN: 'oc',
EU: 'weur',
OC: 'oc',
};
/**
* Client to access a cache tag.
*/
export class CacheObjectStub {
private stub: DurableObjectStub<CacheObject>;
constructor(
/** Binding to the CacheObject durable object */
private doNamespace: DurableObjectNamespace<CacheObject>,
/** ID of the location to target */
private locationId: CacheLocationId,
/** Name of the tag */
private tag: string,
) {
const groupId = getCacheObjectIdName(this.locationId, this.tag);
this.stub = this.doNamespace.get(this.doNamespace.idFromName(groupId), {
// Initialize the object with a locaiton hint,
// as we might want to purge all locations before the object is created.
// https://developers.cloudflare.com/durable-objects/reference/data-location/
locationHint: doLocationHints[this.locationId],
});
}
/**
* Open a descriptor to the cache object.
* It can be used to perform multiple operations in a single RPC session.
* Ex:
* ```ts
* using desc = cache.open();
* await desc.set('key', 'value', Date.now() + 1000);
* await desc.get('key');
* ```
*/
async open() {
return await this.stub.open();
}
/**
* Get a value from the cache.
*/
async get<Value = unknown>(key: string) {
return (await this.stub.get(key)) as Value | undefined;
}
/**
* Set a value in the cache.
*/
async set<Value = unknown>(key: string, value: Value, expiresAt: number) {
return await this.stub.set(key, value, expiresAt);
}
/**
* Purge all keys in the cache tag.
*/
async purge() {
const keys = new Set<string>();
await Promise.all(
allLocations.map(async (locationId) => {
const groupId = getCacheObjectIdName(locationId, this.tag);
const cacheGroup = this.doNamespace.get(this.doNamespace.idFromName(groupId), {
// Initialize the object with a locaiton hint,
// as we might want to purge all locations before the object is created.
// https://developers.cloudflare.com/durable-objects/reference/data-location/
locationHint: doLocationHints[this.locationId],
});
const locationkeys = await cacheGroup.purge();
locationkeys.forEach((key) => keys.add(key));
}),
);
return keys;
}
}
function getCacheObjectIdName(locationId: CacheLocationId, tag: string): string {
return `${locationId}:${tag}`;
}
+1
View File
@@ -0,0 +1 @@
export * from './CacheObjectStub';
+9
View File
@@ -0,0 +1,9 @@
import { WorkerEntrypoint } from 'cloudflare:workers';
export * from './CacheObject';
export default class Worker extends WorkerEntrypoint {
fetch() {
return new Response('Hello, world!');
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": false,
"declaration": true,
"outDir": "dist",
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true,
"types": ["./.wrangler/types/runtime.d.ts"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
+28
View File
@@ -0,0 +1,28 @@
main = "./src/index.ts"
name = "gitbook-open-cache"
compatibility_date = "2024-09-02"
durable_objects.bindings = [
{name = "CACHE", class_name = "CacheObject"}
]
migrations = [
{tag = "v1", new_classes = ["CacheObject"]}
]
[observability]
enabled = true
head_sampling_rate = 0.01
[env.preview]
name = "gitbook-open-cache-preview"
durable_objects.bindings = [
{name = "CACHE", class_name = "CacheObject"}
]
migrations = [
{tag = "v1", new_classes = ["CacheObject"]}
]
[env.preview.observability]
enabled = true
head_sampling_rate = 1
+1 -1
View File
@@ -1 +1 @@
index.ts
dist/
+4 -2
View File
@@ -1,4 +1,5 @@
import fs from 'fs';
import fs from 'node:fs';
import path from 'node:path';
import emojisRaws from 'emoji-assets/emoji.json';
interface EmojiData {
@@ -20,7 +21,8 @@ Object.entries(emojis).forEach(([key, value]) => {
}
});
fs.mkdirSync(path.resolve(__dirname, 'dist'), { recursive: true });
fs.writeFileSync(
'index.ts',
path.resolve(__dirname, 'dist/index.ts'),
`export const emojiCodepoints: Record<string, string> = ${JSON.stringify(output, null, 4)};`,
);
+3 -2
View File
@@ -3,12 +3,13 @@
"description": "Optimized mapping of codepoints to the fully qualified emoji codepoints",
"version": "0.2.0",
"private": true,
"exports": "./index.ts",
"exports": "./dist/index.ts",
"dependencies": {},
"devDependencies": {
"emoji-assets": "^8.0.0"
},
"scripts": {
"postinstall": "bun ./build.ts"
"generate": "bun ./build.ts",
"clean": "rm -rf ./dist"
}
}
@@ -25,3 +25,6 @@
### Sentry ###
# SENTRY_DSN=xxx
### Silent logs
# SILENT=true
+35
View File
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# visual tests
screenshots/
# Sentry Config File
.sentryclirc
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
# Generated public files
/public/~gitbook/static/
+47
View File
@@ -0,0 +1,47 @@
# gitbook
## 0.3.0
### Minor Changes
- 24b785c: Update shiki for code block syntax highlighting, with support for more languages and fixes for diffs. It also patches the deployment on Cloudflare to support edge functions larger than 4MB.
### Patch Changes
- acc3f2f: Fix error with the "Try it" of OpenAPI block because of the Scalar proxy failing on Cloudflare with the `cache` option
- Updated dependencies [709f1a1]
- Updated dependencies [ede2335]
- Updated dependencies [0426312]
- @gitbook/react-openapi@0.6.0
## 0.2.2
### Patch Changes
- Updated dependencies [3445db4]
- @gitbook/react-contentkit@0.5.0
- @gitbook/react-openapi@0.5.0
- @gitbook/react-math@0.5.0
## 0.2.1
### Patch Changes
- Updated dependencies [24cd72e]
- @gitbook/react-contentkit@0.4.0
- @gitbook/react-math@0.4.0
- @gitbook/react-openapi@0.4.0
## 0.2.0
### Minor Changes
- de747b7: Refactor the repository to be a proper monorepo and publish JS files on NPM instead of TypeScript files.
### Patch Changes
- Updated dependencies [de747b7]
- Updated dependencies [de747b7]
- @gitbook/react-contentkit@0.3.0
- @gitbook/react-openapi@0.3.0
- @gitbook/react-math@0.3.0
+4
View File
@@ -0,0 +1,4 @@
{
"version": 1,
"exclude": ["/~gitbook/static/*"]
}
+7
View File
@@ -0,0 +1,7 @@
import type { CacheObject } from '@gitbook/cache-do';
declare global {
interface CloudflareEnv {
CACHE?: DurableObjectNamespace<CacheObject>;
}
}
@@ -1,21 +1,24 @@
import { argosScreenshot } from '@argos-ci/playwright';
import {
CustomizationHeaderPreset,
CustomizationIconsStyle,
CustomizationLocale,
CustomizationSettings,
SiteCustomizationSettings,
} from '@gitbook/api';
import { test, expect, Page } from '@playwright/test';
import jwt from 'jsonwebtoken';
import rison from 'rison';
import { DeepPartial } from 'ts-essentials';
import { getContentTestURL } from '../tests/utils';
interface Test {
name: string;
url: string;
run?: (page: Page) => Promise<unknown>;
fullPage?: boolean;
screenshot?: false;
url: string; // URL to visit for testing
run?: (page: Page) => Promise<unknown>; // The test to run
fullPage?: boolean; // Whether the test should be fullscreened during testing
screenshot?: false; // Should a screenshot be stored
only?: boolean; // Only run this test
}
interface TestsCase {
@@ -102,7 +105,32 @@ const testCases: TestsCase[] = [
},
{
name: 'RFC variant',
url: 'v/rfcs',
url: 'rfcs',
},
{
name: 'Customized variant titles are displayed',
url: '',
run: async (page) => {
const spaceDrowpdown = page.locator('[data-testid="space-dropdown-button"]');
await spaceDrowpdown.click();
const variantSelectionDropdown = page.locator(
'css=[data-testid="space-dropdown-button"] + div',
);
// the customized space title
await expect(
variantSelectionDropdown.getByRole('link', {
name: 'Multi-Variants',
}),
).toBeVisible();
// the NON-customized space title
await expect(
variantSelectionDropdown.getByRole('link', {
name: 'RFCs',
}),
).toBeVisible();
},
},
],
},
@@ -129,13 +157,13 @@ const testCases: TestsCase[] = [
// It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
await page.waitForURL(
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions/v/2.0/reference/api-reference/pets?fallback=true',
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions/2.0/reference/api-reference/pets?fallback=true',
);
},
},
{
name: 'Keep navigation path/route when switching variant (Share link)',
url: 'api-multi-versions-share-links/bRfQbzwsK8rbN1GRxx7K/reference/api-reference/pets',
url: 'api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/reference/api-reference/pets',
screenshot: false,
run: async (page) => {
const spaceDrowpdown = await page.waitForSelector(
@@ -152,7 +180,7 @@ const testCases: TestsCase[] = [
// It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
await page.waitForURL(
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-share-links/bRfQbzwsK8rbN1GRxx7K/v/2.0/reference/api-reference/pets?fallback=true',
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/2.0/reference/api-reference/pets?fallback=true',
);
},
},
@@ -187,7 +215,7 @@ const testCases: TestsCase[] = [
// It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
await page.waitForURL(
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-va/v/2.0/reference/api-reference/pets?fallback=true',
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-va/2.0/reference/api-reference/pets?fallback=true',
);
},
},
@@ -230,7 +258,7 @@ const testCases: TestsCase[] = [
},
{
name: 'Versioning',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'Revision',
@@ -241,7 +269,7 @@ const testCases: TestsCase[] = [
},
{
name: 'PDF',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'PDF',
@@ -251,7 +279,7 @@ const testCases: TestsCase[] = [
},
{
name: 'Content tests',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'Text',
@@ -344,11 +372,21 @@ const testCases: TestsCase[] = [
name: 'Math',
url: 'blocks/math',
},
{
name: 'Files',
url: 'blocks/files',
fullPage: true,
},
{
name: 'Embeds',
url: 'blocks/embeds',
fullPage: true,
},
{
name: 'Page links',
url: 'blocks/page-links',
fullPage: true,
},
{
name: 'Annotations',
url: 'blocks/annotations',
@@ -361,7 +399,7 @@ const testCases: TestsCase[] = [
},
{
name: 'Page options',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'Hidden',
@@ -383,11 +421,16 @@ const testCases: TestsCase[] = [
url: 'page-options/page-with-cover-and-no-toc',
run: waitForCookiesDialog,
},
{
name: 'With icon',
url: 'page-options/page-with-icon',
run: waitForCookiesDialog,
},
],
},
{
name: 'Customization',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'Without header',
@@ -399,16 +442,60 @@ const testCases: TestsCase[] = [
}),
run: waitForCookiesDialog,
},
{
name: 'With duotone icons',
url:
'page-options/page-with-icon' +
getCustomizationURL({
styling: {
icons: CustomizationIconsStyle.Duotone,
},
}),
run: waitForCookiesDialog,
},
{
name: 'With header buttons',
url: getCustomizationURL({
header: {
preset: CustomizationHeaderPreset.Default,
links: [
{
title: 'Secondary button',
to: { kind: 'url', url: 'https://www.gitbook.com' },
// @ts-ignore Remove once we upgrade to the latest version of the API
style: 'button-secondary',
},
{
title: 'Primary button',
to: { kind: 'url', url: 'https://www.gitbook.com' },
// @ts-ignore Remove once we upgrade to the latest version of the API
style: 'button-primary',
},
],
},
}),
run: waitForCookiesDialog,
},
],
},
{
name: 'Ads',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: 'Without previewed ads',
url: 'text-page?ads_preview=1',
run: waitForCookiesDialog,
},
],
},
{
name: 'Share links',
baseUrl: 'https://gitbook.gitbook.io/test-share-links/',
baseUrl: 'https://gitbook.gitbook.io/gbo-tests-share-links/',
tests: [
{
name: 'Valid link',
url: 'Fc6mMII9FKgnwm7qqynx/',
run: waitForCookiesDialog,
url: 'TGs8PkF4GWVtbmPnWhYL/',
},
{
name: 'Invalid link',
@@ -495,7 +582,7 @@ const testCases: TestsCase[] = [
expiresIn: '24h',
},
);
return `v/spacea?jwt_token=${token}`;
return `spacea?jwt_token=${token}`;
})(),
run: waitForCookiesDialog,
},
@@ -512,7 +599,7 @@ const testCases: TestsCase[] = [
expiresIn: '24h',
},
);
return `v/spaceb?jwt_token=${token}`;
return `spaceb?jwt_token=${token}`;
})(),
run: waitForCookiesDialog,
},
@@ -529,7 +616,7 @@ const testCases: TestsCase[] = [
expiresIn: '24h',
},
);
return `v/spacec?jwt_token=${token}`;
return `spacec?jwt_token=${token}`;
})(),
run: waitForCookiesDialog,
},
@@ -611,13 +698,12 @@ const testCases: TestsCase[] = [
},
{
name: 'Languages',
baseUrl: 'https://gitbook.gitbook.io/test-1-1/',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: allLocales.map((locale) => ({
name: locale,
url: getCustomizationURL({
internationalization: {
locale,
inherit: false,
},
}),
run: async (page) => {
@@ -626,12 +712,64 @@ const testCases: TestsCase[] = [
},
})),
},
{
name: 'SEO',
baseUrl: 'https://gitbook.gitbook.io/test-gitbook-open/',
tests: [
{
name: `Index by default`,
url: '?x-gitbook-search-indexation=true',
screenshot: false,
run: async (page) => {
const metaRobots = page.locator('meta[name="robots"]');
await expect(metaRobots).toHaveAttribute('content', 'index, follow');
},
},
{
name: `Don't index noIndex`,
url: 'page-options/page-no-index?x-gitbook-search-indexation=true',
screenshot: false,
run: async (page) => {
const metaRobots = page.locator('meta[name="robots"]');
await expect(metaRobots).toHaveAttribute('content', 'noindex, nofollow');
},
},
{
name: `Don't index descendant of noIndex`,
url: 'page-options/page-no-index/descendant-of-page-no-index?x-gitbook-search-indexation=true',
screenshot: false,
run: async (page) => {
const metaRobots = page.locator('meta[name="robots"]');
await expect(metaRobots).toHaveAttribute('content', 'noindex, nofollow');
},
},
{
name: `Don't index noRobotsIndex`,
url: 'page-options/page-no-robots-index?x-gitbook-search-indexation=true',
screenshot: false,
run: async (page) => {
const metaRobots = page.locator('meta[name="robots"]');
await expect(metaRobots).toHaveAttribute('content', 'noindex, nofollow');
},
},
{
name: `Don't index descendant of noRobotsIndex`,
url: 'page-options/page-no-robots-index/descendant-of-page-no-robots-index?x-gitbook-search-indexation=true',
screenshot: false,
run: async (page) => {
const metaRobots = page.locator('meta[name="robots"]');
await expect(metaRobots).toHaveAttribute('content', 'noindex, nofollow');
},
},
],
},
];
for (const testCase of testCases) {
test.describe(testCase.name, () => {
for (const testEntry of testCase.tests) {
test(testEntry.name, async ({ page, baseURL }) => {
const testFn = testEntry.only ? test.only : test;
testFn(testEntry.name, async ({ page, baseURL }) => {
const contentUrl = new URL(testEntry.url, testCase.baseUrl);
const url = getContentTestURL(contentUrl.toString(), baseURL);
await page.goto(url);
@@ -658,7 +796,7 @@ for (const testCase of testCases) {
/**
* Create a URL with customization settings.
*/
function getCustomizationURL(partial: Partial<CustomizationSettings>): string {
function getCustomizationURL(partial: DeepPartial<SiteCustomizationSettings>): string {
const encoded = rison.encode_object(partial);
const searchParams = new URLSearchParams();
@@ -7,6 +7,8 @@ module.exports = withSentryConfig(
SENTRY_DSN: process.env.SENTRY_DSN ?? '',
SENTRY_ENVIRONMENT: process.env.SENTRY_ENVIRONMENT ?? 'development',
GITBOOK_ASSETS_PREFIX: process.env.GITBOOK_ASSETS_PREFIX,
GITBOOK_ICONS_URL: process.env.GITBOOK_ICONS_URL,
GITBOOK_ICONS_TOKEN: process.env.GITBOOK_ICONS_TOKEN,
},
webpack(config, { dev, webpack }) {
+96
View File
@@ -0,0 +1,96 @@
{
"name": "gitbook",
"version": "0.3.0",
"private": true,
"scripts": {
"dev": "env-cmd --silent -f ../../.env.local next dev",
"build": "next build",
"build:cloudflare": "next-on-pages",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit",
"e2e": "playwright test",
"unit": "bun test {src,packages}",
"generate": "gitbook-icons ./public/~gitbook/static/icons custom-icons && gitbook-math ./public/~gitbook/static/math",
"copy:icons": "gitbook-icons ./public/~gitbook/static/icons",
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static"
},
"dependencies": {
"@gitbook/api": "0.64.1",
"@gitbook/cache-do": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/icons": "workspace:*",
"@gitbook/react-contentkit": "workspace:*",
"@gitbook/react-math": "workspace:*",
"@gitbook/react-openapi": "workspace:*",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-popover": "^1.0.7",
"@sentry/nextjs": "^7.94.1",
"@sindresorhus/fnv1a": "^3.1.0",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/typography": "^0.5.10",
"@upstash/redis": "^1.27.1",
"ajv": "^8.12.0",
"assert-never": "^1.2.1",
"bun-types": "^1.1.20",
"classnames": "^2.5.1",
"content-security-policy-merger": "^1.0.0",
"framer-motion": "^10.16.14",
"js-cookie": "^3.0.5",
"jsontoxml": "^1.0.1",
"katex": "^0.16.9",
"mathjax": "^3.2.2",
"memoizee": "^0.4.15",
"next": "^14.2.5",
"next-themes": "^0.2.1",
"nuqs": "^1.17.4",
"object-hash": "^3.0.0",
"openapi-types": "^12.1.3",
"p-map": "^7.0.0",
"parse-cache-control": "^1.0.1",
"postcss-color-contrast": "^1.1.0",
"react": "^18",
"react-dom": "^18",
"react-hotkeys-hook": "^4.4.1",
"recoil": "^0.7.7",
"rehype-sanitize": "^6.0.0",
"rehype-stringify": "^10.0.0",
"remark-gfm": "^4.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"rison": "^0.1.1",
"server-only": "^0.0.1",
"shiki": "^1.11.1",
"tailwind-merge": "^2.2.0",
"tailwind-shades": "^1.1.2",
"unified": "^11.0.4",
"url-join": "^5.0.0"
},
"devDependencies": {
"@argos-ci/playwright": "^2.0.0",
"@playwright/test": "^1.42.1",
"@cloudflare/next-on-pages": "^1.13.3",
"@cloudflare/workers-types": "^4.20240725.0",
"@types/js-cookie": "^3.0.6",
"@types/jsontoxml": "^1.0.5",
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^20",
"@types/object-hash": "^3.0.6",
"@types/parse-cache-control": "^1.0.4",
"@types/psi": "^4.1.6",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/rison": "^0.0.9",
"autoprefixer": "^10",
"eslint": "^8",
"eslint-config-next": "^14.2.5",
"eslint-plugin-import": "^2.29.1",
"jsonwebtoken": "^9.0.2",
"postcss": "^8",
"psi": "^4.1.0",
"tailwindcss": "^3.4.0",
"typescript": "^5.5.3",
"env-cmd": "^10.1.0",
"ts-essentials": "^10.0.1"
}
}
+3
View File
@@ -0,0 +1,3 @@
# GitBook immutable static assets
/~gitbook/static/*
cache-control: public,max-age=31536000,immutable
@@ -29,7 +29,6 @@ export async function POST(req: NextRequest) {
return NextResponse.json({
success: true,
keys: result.keys,
stats: result.stats,
});
}

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