@docusaurus/plugin-client-redirects 2.0.0-beta.ff31de0ff → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/collectRedirects.d.ts +2 -2
  2. package/lib/collectRedirects.js +45 -47
  3. package/lib/createRedirectPageContent.d.ts +2 -4
  4. package/lib/createRedirectPageContent.js +2 -4
  5. package/lib/extensionRedirects.d.ts +11 -3
  6. package/lib/extensionRedirects.js +22 -17
  7. package/lib/index.d.ts +5 -3
  8. package/lib/index.js +11 -8
  9. package/lib/options.d.ts +35 -0
  10. package/lib/options.js +36 -0
  11. package/lib/redirectValidation.d.ts +2 -2
  12. package/lib/types.d.ts +14 -16
  13. package/lib/writeRedirectFiles.d.ts +5 -5
  14. package/lib/writeRedirectFiles.js +41 -14
  15. package/package.json +16 -13
  16. package/src/collectRedirects.ts +76 -83
  17. package/src/createRedirectPageContent.ts +8 -10
  18. package/src/deps.d.ts +16 -0
  19. package/src/extensionRedirects.ts +32 -25
  20. package/src/index.ts +21 -14
  21. package/src/options.ts +75 -0
  22. package/src/redirectValidation.ts +3 -3
  23. package/src/types.ts +16 -30
  24. package/src/writeRedirectFiles.ts +53 -25
  25. package/lib/.tsbuildinfo +0 -1970
  26. package/lib/normalizePluginOptions.d.ts +0 -9
  27. package/lib/normalizePluginOptions.js +0 -44
  28. package/src/__tests__/__snapshots__/collectRedirects.test.ts.snap +0 -27
  29. package/src/__tests__/__snapshots__/createRedirectPageContent.test.ts.snap +0 -29
  30. package/src/__tests__/__snapshots__/normalizePluginOptions.test.ts.snap +0 -35
  31. package/src/__tests__/__snapshots__/redirectValidation.test.ts.snap +0 -11
  32. package/src/__tests__/__snapshots__/writeRedirectFiles.test.ts.snap +0 -71
  33. package/src/__tests__/collectRedirects.test.ts +0 -255
  34. package/src/__tests__/createRedirectPageContent.test.ts +0 -26
  35. package/src/__tests__/extensionRedirects.test.ts +0 -109
  36. package/src/__tests__/normalizePluginOptions.test.ts +0 -76
  37. package/src/__tests__/redirectValidation.test.ts +0 -66
  38. package/src/__tests__/writeRedirectFiles.test.ts +0 -146
  39. package/src/normalizePluginOptions.ts +0 -55
  40. package/tsconfig.json +0 -10
@@ -7,15 +7,17 @@
7
7
 
8
8
  import fs from 'fs-extra';
9
9
  import path from 'path';
10
- import {memoize} from 'lodash';
10
+ import _ from 'lodash';
11
+ import logger from '@docusaurus/logger';
12
+ import {normalizeUrl} from '@docusaurus/utils';
11
13
 
12
- import {PluginContext, RedirectMetadata} from './types';
13
14
  import createRedirectPageContent from './createRedirectPageContent';
14
- import {getFilePathForRoutePath, normalizeUrl} from '@docusaurus/utils';
15
+
16
+ import type {PluginContext, RedirectItem} from './types';
15
17
 
16
18
  export type WriteFilesPluginContext = Pick<PluginContext, 'baseUrl' | 'outDir'>;
17
19
 
18
- export type RedirectFileMetadata = {
20
+ export type RedirectFile = {
19
21
  fileAbsolutePath: string;
20
22
  fileContent: string;
21
23
  };
@@ -24,22 +26,52 @@ export function createToUrl(baseUrl: string, to: string): string {
24
26
  return normalizeUrl([baseUrl, to]);
25
27
  }
26
28
 
27
- export function toRedirectFilesMetadata(
28
- redirects: RedirectMetadata[],
29
+ // Create redirect file path
30
+ // Make sure this path has lower precedence over the original file path when
31
+ // served by host providers!
32
+ // Otherwise it can produce infinite redirect loops!
33
+ //
34
+ // See https://github.com/facebook/docusaurus/issues/5055
35
+ // See https://github.com/facebook/docusaurus/pull/5085
36
+ // See https://github.com/facebook/docusaurus/pull/5102
37
+ function getRedirectFilePath(
38
+ fromPath: string,
39
+ trailingSlash: boolean | undefined, // Now unused, on purpose
40
+ ): string {
41
+ const fileName = path.basename(fromPath);
42
+ const filePath = path.dirname(fromPath);
43
+ // Edge case for https://github.com/facebook/docusaurus/pull/5102
44
+ // If the redirect source path is /xyz, with file /xyz.html
45
+ // We can't write the redirect file at /xyz.html/index.html because for Unix
46
+ // FS, a file/folder can't have the same name "xyz.html"
47
+ // The only possible solution for a redirect file is thus /xyz.html.html (I
48
+ // know, looks suspicious)
49
+ if (trailingSlash === false && fileName.endsWith('.html')) {
50
+ return path.join(filePath, `${fileName}.html`);
51
+ }
52
+ // If the target path is /xyz, with file /xyz/index.html, we don't want the
53
+ // redirect file to be /xyz.html, otherwise it would be picked in priority and
54
+ // the redirect file would redirect to itself. We prefer the redirect file to
55
+ // be /xyz.html/index.html, served with lower priority for most static hosting
56
+ // tools
57
+ return path.join(filePath, `${fileName}/index.html`);
58
+ }
59
+
60
+ export function toRedirectFiles(
61
+ redirects: RedirectItem[],
29
62
  pluginContext: WriteFilesPluginContext,
30
- ): RedirectFileMetadata[] {
63
+ trailingSlash: boolean | undefined,
64
+ ): RedirectFile[] {
31
65
  // Perf: avoid rendering the template twice with the exact same "props"
32
66
  // We might create multiple redirect pages for the same destination url
33
67
  // note: the first fn arg is the cache key!
34
- const createPageContentMemoized = memoize((toUrl: string) => {
35
- return createRedirectPageContent({toUrl});
36
- });
68
+ const createPageContentMemoized = _.memoize((toUrl: string) =>
69
+ createRedirectPageContent({toUrl}),
70
+ );
37
71
 
38
- const createFileMetadata = (redirect: RedirectMetadata) => {
39
- const fileAbsolutePath = path.join(
40
- pluginContext.outDir,
41
- getFilePathForRoutePath(redirect.from),
42
- );
72
+ const createFileMetadata = (redirect: RedirectItem) => {
73
+ const fileRelativePath = getRedirectFilePath(redirect.from, trailingSlash);
74
+ const fileAbsolutePath = path.join(pluginContext.outDir, fileRelativePath);
43
75
  const toUrl = createToUrl(pluginContext.baseUrl, redirect.to);
44
76
  const fileContent = createPageContentMemoized(toUrl);
45
77
  return {
@@ -52,18 +84,15 @@ export function toRedirectFilesMetadata(
52
84
  return redirects.map(createFileMetadata);
53
85
  }
54
86
 
55
- export async function writeRedirectFile(
56
- file: RedirectFileMetadata,
57
- ): Promise<void> {
87
+ export async function writeRedirectFile(file: RedirectFile): Promise<void> {
58
88
  try {
59
89
  // User-friendly security to prevent file overrides
60
90
  if (await fs.pathExists(file.fileAbsolutePath)) {
61
91
  throw new Error(
62
- 'The redirect plugin is not supposed to override existing files',
92
+ 'The redirect plugin is not supposed to override existing files.',
63
93
  );
64
94
  }
65
- await fs.ensureDir(path.dirname(file.fileAbsolutePath));
66
- await fs.writeFile(
95
+ await fs.outputFile(
67
96
  file.fileAbsolutePath,
68
97
  file.fileContent,
69
98
  // Hard security to prevent file overrides
@@ -71,14 +100,13 @@ export async function writeRedirectFile(
71
100
  {flag: 'wx'},
72
101
  );
73
102
  } catch (err) {
74
- throw new Error(
75
- `Redirect file creation error for path=${file.fileAbsolutePath}: ${err}`,
76
- );
103
+ logger.error`Redirect file creation error for path=${file.fileAbsolutePath}.`;
104
+ throw err;
77
105
  }
78
106
  }
79
107
 
80
108
  export default async function writeRedirectFiles(
81
- redirectFiles: RedirectFileMetadata[],
109
+ redirectFiles: RedirectFile[],
82
110
  ): Promise<void> {
83
111
  await Promise.all(redirectFiles.map(writeRedirectFile));
84
112
  }