Skip to content

Commit 17f3e02

Browse files
authored
feat(core): hash router option - browse site offline (experimental) (#9859)
1 parent b73ad1e commit 17f3e02

File tree

38 files changed

+1018
-266
lines changed

38 files changed

+1018
-266
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Build Hash Router
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
- docusaurus-v**
8+
paths:
9+
- packages/**
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
build:
17+
name: Build Hash Router
18+
timeout-minutes: 30
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
23+
- name: Set up Node
24+
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
25+
with:
26+
node-version: '18'
27+
cache: yarn
28+
- name: Installation
29+
run: yarn
30+
- name: Build Hash Router
31+
run: yarn build:website:fast
32+
env:
33+
DOCUSAURUS_ROUTER: 'hash'
34+
BASE_URL: '/docusaurus/' # GH pages deploys under https://facebook.github.io/docusaurus/
35+
- name: Upload Website artifact
36+
uses: actions/upload-artifact@v4
37+
with:
38+
name: website-hash-router-archive
39+
path: website/build
40+
- name: Upload Website Pages artifact
41+
uses: actions/upload-pages-artifact@v3
42+
with:
43+
path: website/build
44+
45+
# See https://docusaurus.io/docs/deployment#triggering-deployment-with-github-actions
46+
deploy:
47+
name: Deploy to GitHub Pages
48+
if: ${{ github.event_name != 'pull_request' && github.ref_name == 'main')}}
49+
needs: build
50+
permissions:
51+
pages: write
52+
id-token: write
53+
environment:
54+
name: github-pages
55+
url: ${{ steps.deployment.outputs.page_url }}
56+
runs-on: ubuntu-latest
57+
steps:
58+
- name: Deploy to GitHub Pages
59+
id: deployment
60+
uses: actions/deploy-pages@v4

packages/docusaurus-plugin-client-redirects/src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import {addLeadingSlash, removePrefix} from '@docusaurus/utils-common';
9+
import logger from '@docusaurus/logger';
910
import collectRedirects from './collectRedirects';
1011
import writeRedirectFiles, {
1112
toRedirectFiles,
@@ -15,14 +16,24 @@ import type {LoadContext, Plugin} from '@docusaurus/types';
1516
import type {PluginContext, RedirectItem} from './types';
1617
import type {PluginOptions, Options} from './options';
1718

19+
const PluginName = 'docusaurus-plugin-client-redirects';
20+
1821
export default function pluginClientRedirectsPages(
1922
context: LoadContext,
2023
options: PluginOptions,
2124
): Plugin<void> {
2225
const {trailingSlash} = context.siteConfig;
26+
const router = context.siteConfig.future.experimental_router;
27+
28+
if (router === 'hash') {
29+
logger.warn(
30+
`${PluginName} does not support the Hash Router and will be disabled.`,
31+
);
32+
return {name: PluginName};
33+
}
2334

2435
return {
25-
name: 'docusaurus-plugin-client-redirects',
36+
name: PluginName,
2637
async postBuild(props) {
2738
const pluginContext: PluginContext = {
2839
relativeRoutesPaths: props.routesPaths.map(

packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ const getPlugin = async (
106106
baseUrl: '/',
107107
url: 'https://docusaurus.io',
108108
markdown,
109+
future: {},
109110
} as DocusaurusConfig;
110111
return pluginContentBlog(
111112
{

packages/docusaurus-plugin-content-blog/src/feed.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
applyTrailingSlash,
1717
} from '@docusaurus/utils-common';
1818
import {load as cheerioLoad} from 'cheerio';
19-
import type {DocusaurusConfig} from '@docusaurus/types';
19+
import type {DocusaurusConfig, HtmlTags, LoadContext} from '@docusaurus/types';
2020
import type {
2121
FeedType,
2222
PluginOptions,
@@ -254,3 +254,59 @@ export async function createBlogFeedFiles({
254254
),
255255
);
256256
}
257+
258+
export function createFeedHtmlHeadTags({
259+
context,
260+
options,
261+
}: {
262+
context: LoadContext;
263+
options: PluginOptions;
264+
}): HtmlTags {
265+
const feedTypes = options.feedOptions.type;
266+
if (!feedTypes) {
267+
return [];
268+
}
269+
const feedTitle = options.feedOptions.title ?? context.siteConfig.title;
270+
const feedsConfig = {
271+
rss: {
272+
type: 'application/rss+xml',
273+
path: 'rss.xml',
274+
title: `${feedTitle} RSS Feed`,
275+
},
276+
atom: {
277+
type: 'application/atom+xml',
278+
path: 'atom.xml',
279+
title: `${feedTitle} Atom Feed`,
280+
},
281+
json: {
282+
type: 'application/json',
283+
path: 'feed.json',
284+
title: `${feedTitle} JSON Feed`,
285+
},
286+
};
287+
const headTags: HtmlTags = [];
288+
289+
feedTypes.forEach((feedType) => {
290+
const {
291+
type,
292+
path: feedConfigPath,
293+
title: feedConfigTitle,
294+
} = feedsConfig[feedType];
295+
296+
headTags.push({
297+
tagName: 'link',
298+
attributes: {
299+
rel: 'alternate',
300+
type,
301+
href: normalizeUrl([
302+
context.siteConfig.baseUrl,
303+
options.routeBasePath,
304+
feedConfigPath,
305+
]),
306+
title: feedConfigTitle,
307+
},
308+
});
309+
});
310+
311+
return headTags;
312+
}

packages/docusaurus-plugin-content-blog/src/index.ts

Lines changed: 30 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ import {
2929
} from './blogUtils';
3030
import footnoteIDFixer from './remark/footnoteIDFixer';
3131
import {translateContent, getTranslationFiles} from './translations';
32-
import {createBlogFeedFiles} from './feed';
32+
import {createBlogFeedFiles, createFeedHtmlHeadTags} from './feed';
3333

3434
import {createAllRoutes} from './routes';
3535
import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types';
36-
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
36+
import type {LoadContext, Plugin} from '@docusaurus/types';
3737
import type {
3838
PluginOptions,
3939
BlogPostFrontMatter,
@@ -44,6 +44,8 @@ import type {
4444
BlogPaginated,
4545
} from '@docusaurus/plugin-content-blog';
4646

47+
const PluginName = 'docusaurus-plugin-content-blog';
48+
4749
export default async function pluginContentBlog(
4850
context: LoadContext,
4951
options: PluginOptions,
@@ -55,22 +57,29 @@ export default async function pluginContentBlog(
5557
localizationDir,
5658
i18n: {currentLocale},
5759
} = context;
60+
61+
const router = siteConfig.future.experimental_router;
62+
const isBlogFeedDisabledBecauseOfHashRouter =
63+
router === 'hash' && !!options.feedOptions.type;
64+
if (isBlogFeedDisabledBecauseOfHashRouter) {
65+
logger.warn(
66+
`${PluginName} feed feature does not support the Hash Router. Feeds won't be generated.`,
67+
);
68+
}
69+
5870
const {onBrokenMarkdownLinks, baseUrl} = siteConfig;
5971

6072
const contentPaths: BlogContentPaths = {
6173
contentPath: path.resolve(siteDir, options.path),
6274
contentPathLocalized: getPluginI18nPath({
6375
localizationDir,
64-
pluginName: 'docusaurus-plugin-content-blog',
76+
pluginName: PluginName,
6577
pluginId: options.id,
6678
}),
6779
};
6880
const pluginId = options.id ?? DEFAULT_PLUGIN_ID;
6981

70-
const pluginDataDirRoot = path.join(
71-
generatedFilesDir,
72-
'docusaurus-plugin-content-blog',
73-
);
82+
const pluginDataDirRoot = path.join(generatedFilesDir, PluginName);
7483
const dataDir = path.join(pluginDataDirRoot, pluginId);
7584
// TODO Docusaurus v4 breaking change
7685
// module aliasing should be automatic
@@ -84,7 +93,7 @@ export default async function pluginContentBlog(
8493
});
8594

8695
return {
87-
name: 'docusaurus-plugin-content-blog',
96+
name: PluginName,
8897

8998
getPathsToWatch() {
9099
const {include} = options;
@@ -295,15 +304,16 @@ export default async function pluginContentBlog(
295304
},
296305

297306
async postBuild({outDir, content}) {
298-
if (!options.feedOptions.type) {
299-
return;
300-
}
301-
const {blogPosts} = content;
302-
if (!blogPosts.length) {
307+
if (
308+
!content.blogPosts.length ||
309+
!options.feedOptions.type ||
310+
isBlogFeedDisabledBecauseOfHashRouter
311+
) {
303312
return;
304313
}
314+
305315
await createBlogFeedFiles({
306-
blogPosts,
316+
blogPosts: content.blogPosts,
307317
options,
308318
outDir,
309319
siteConfig,
@@ -312,56 +322,15 @@ export default async function pluginContentBlog(
312322
},
313323

314324
injectHtmlTags({content}) {
315-
if (!content.blogPosts.length || !options.feedOptions.type) {
325+
if (
326+
!content.blogPosts.length ||
327+
!options.feedOptions.type ||
328+
isBlogFeedDisabledBecauseOfHashRouter
329+
) {
316330
return {};
317331
}
318332

319-
const feedTypes = options.feedOptions.type;
320-
const feedTitle = options.feedOptions.title ?? context.siteConfig.title;
321-
const feedsConfig = {
322-
rss: {
323-
type: 'application/rss+xml',
324-
path: 'rss.xml',
325-
title: `${feedTitle} RSS Feed`,
326-
},
327-
atom: {
328-
type: 'application/atom+xml',
329-
path: 'atom.xml',
330-
title: `${feedTitle} Atom Feed`,
331-
},
332-
json: {
333-
type: 'application/json',
334-
path: 'feed.json',
335-
title: `${feedTitle} JSON Feed`,
336-
},
337-
};
338-
const headTags: HtmlTags = [];
339-
340-
feedTypes.forEach((feedType) => {
341-
const {
342-
type,
343-
path: feedConfigPath,
344-
title: feedConfigTitle,
345-
} = feedsConfig[feedType];
346-
347-
headTags.push({
348-
tagName: 'link',
349-
attributes: {
350-
rel: 'alternate',
351-
type,
352-
href: normalizeUrl([
353-
baseUrl,
354-
options.routeBasePath,
355-
feedConfigPath,
356-
]),
357-
title: feedConfigTitle,
358-
},
359-
});
360-
});
361-
362-
return {
363-
headTags,
364-
};
333+
return {headTags: createFeedHtmlHeadTags({context, options})};
365334
},
366335
};
367336
}

packages/docusaurus-plugin-pwa/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@babel/core": "^7.23.3",
2424
"@babel/preset-env": "^7.23.3",
2525
"@docusaurus/core": "3.3.2",
26+
"@docusaurus/logger": "3.3.2",
2627
"@docusaurus/theme-common": "3.3.2",
2728
"@docusaurus/theme-translations": "3.3.2",
2829
"@docusaurus/types": "3.3.2",

packages/docusaurus-plugin-pwa/src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import WebpackBar from 'webpackbar';
1111
import Terser from 'terser-webpack-plugin';
1212
import {injectManifest} from 'workbox-build';
1313
import {normalizeUrl} from '@docusaurus/utils';
14+
import logger from '@docusaurus/logger';
1415
import {compile} from '@docusaurus/core/lib/webpack/utils';
1516
import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
1617
import type {HtmlTags, LoadContext, Plugin} from '@docusaurus/types';
1718
import type {PluginOptions} from '@docusaurus/plugin-pwa';
1819

20+
const PluginName = 'docusaurus-plugin-pwa';
21+
1922
const isProd = process.env.NODE_ENV === 'production';
2023

2124
function getSWBabelLoader() {
@@ -47,6 +50,7 @@ export default function pluginPWA(
4750
outDir,
4851
baseUrl,
4952
i18n: {currentLocale},
53+
siteConfig,
5054
} = context;
5155
const {
5256
debug,
@@ -57,8 +61,15 @@ export default function pluginPWA(
5761
swRegister,
5862
} = options;
5963

64+
if (siteConfig.future.experimental_router === 'hash') {
65+
logger.warn(
66+
`${PluginName} does not support the Hash Router and will be disabled.`,
67+
);
68+
return {name: PluginName};
69+
}
70+
6071
return {
61-
name: 'docusaurus-plugin-pwa',
72+
name: PluginName,
6273

6374
getThemePath() {
6475
return '../lib/theme';

packages/docusaurus-plugin-sitemap/src/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ import createSitemap from './createSitemap';
1212
import type {PluginOptions, Options} from './options';
1313
import type {LoadContext, Plugin} from '@docusaurus/types';
1414

15+
const PluginName = 'docusaurus-plugin-sitemap';
16+
1517
export default function pluginSitemap(
1618
context: LoadContext,
1719
options: PluginOptions,
1820
): Plugin<void> {
21+
if (context.siteConfig.future.experimental_router === 'hash') {
22+
logger.warn(
23+
`${PluginName} does not support the Hash Router and will be disabled.`,
24+
);
25+
return {name: PluginName};
26+
}
27+
1928
return {
20-
name: 'docusaurus-plugin-sitemap',
29+
name: PluginName,
2130

2231
async postBuild({siteConfig, routes, outDir, head}) {
2332
if (siteConfig.noIndex) {

0 commit comments

Comments
 (0)