@docusaurus/utils 0.0.0-4759 → 0.0.0-4762

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 (81) hide show
  1. package/lib/constants.d.ts +49 -1
  2. package/lib/constants.d.ts.map +1 -1
  3. package/lib/constants.js +53 -8
  4. package/lib/constants.js.map +1 -1
  5. package/lib/dataFileUtils.d.ts +38 -2
  6. package/lib/dataFileUtils.d.ts.map +1 -1
  7. package/lib/dataFileUtils.js +34 -7
  8. package/lib/dataFileUtils.js.map +1 -1
  9. package/lib/emitUtils.d.ts +12 -0
  10. package/lib/emitUtils.d.ts.map +1 -1
  11. package/lib/emitUtils.js +22 -3
  12. package/lib/emitUtils.js.map +1 -1
  13. package/lib/gitUtils.d.ts +42 -2
  14. package/lib/gitUtils.d.ts.map +1 -1
  15. package/lib/gitUtils.js +2 -2
  16. package/lib/gitUtils.js.map +1 -1
  17. package/lib/globUtils.d.ts +27 -0
  18. package/lib/globUtils.d.ts.map +1 -1
  19. package/lib/globUtils.js +28 -10
  20. package/lib/globUtils.js.map +1 -1
  21. package/lib/hashUtils.d.ts +5 -4
  22. package/lib/hashUtils.d.ts.map +1 -1
  23. package/lib/hashUtils.js +6 -5
  24. package/lib/hashUtils.js.map +1 -1
  25. package/lib/i18nUtils.d.ts +11 -0
  26. package/lib/i18nUtils.d.ts.map +1 -1
  27. package/lib/i18nUtils.js +12 -3
  28. package/lib/i18nUtils.js.map +1 -1
  29. package/lib/index.d.ts +4 -4
  30. package/lib/index.d.ts.map +1 -1
  31. package/lib/index.js +4 -4
  32. package/lib/index.js.map +1 -1
  33. package/lib/jsUtils.d.ts +32 -4
  34. package/lib/jsUtils.d.ts.map +1 -1
  35. package/lib/jsUtils.js +35 -13
  36. package/lib/jsUtils.js.map +1 -1
  37. package/lib/markdownLinks.d.ts +45 -4
  38. package/lib/markdownLinks.d.ts.map +1 -1
  39. package/lib/markdownLinks.js +17 -8
  40. package/lib/markdownLinks.js.map +1 -1
  41. package/lib/markdownUtils.d.ts +80 -9
  42. package/lib/markdownUtils.d.ts.map +1 -1
  43. package/lib/markdownUtils.js +61 -10
  44. package/lib/markdownUtils.js.map +1 -1
  45. package/lib/pathUtils.d.ts +1 -1
  46. package/lib/pathUtils.d.ts.map +1 -1
  47. package/lib/pathUtils.js +2 -2
  48. package/lib/pathUtils.js.map +1 -1
  49. package/lib/slugger.d.ts +10 -0
  50. package/lib/slugger.d.ts.map +1 -1
  51. package/lib/slugger.js +4 -0
  52. package/lib/slugger.js.map +1 -1
  53. package/lib/tags.d.ts +31 -10
  54. package/lib/tags.d.ts.map +1 -1
  55. package/lib/tags.js +38 -24
  56. package/lib/tags.js.map +1 -1
  57. package/lib/urlUtils.d.ts +45 -2
  58. package/lib/urlUtils.d.ts.map +1 -1
  59. package/lib/urlUtils.js +48 -6
  60. package/lib/urlUtils.js.map +1 -1
  61. package/lib/webpackUtils.d.ts +5 -0
  62. package/lib/webpackUtils.d.ts.map +1 -1
  63. package/lib/webpackUtils.js +6 -2
  64. package/lib/webpackUtils.js.map +1 -1
  65. package/package.json +4 -4
  66. package/src/constants.ts +59 -7
  67. package/src/dataFileUtils.ts +43 -10
  68. package/src/emitUtils.ts +24 -5
  69. package/src/gitUtils.ts +46 -4
  70. package/src/globUtils.ts +29 -13
  71. package/src/hashUtils.ts +6 -5
  72. package/src/i18nUtils.ts +13 -4
  73. package/src/index.ts +3 -6
  74. package/src/jsUtils.ts +34 -20
  75. package/src/markdownLinks.ts +58 -22
  76. package/src/markdownUtils.ts +101 -23
  77. package/src/pathUtils.ts +2 -2
  78. package/src/slugger.ts +13 -1
  79. package/src/tags.ts +37 -25
  80. package/src/urlUtils.ts +49 -6
  81. package/src/webpackUtils.ts +10 -2
package/src/tags.ts CHANGED
@@ -10,12 +10,13 @@ import {normalizeUrl} from './urlUtils';
10
10
 
11
11
  export type Tag = {
12
12
  label: string;
13
+ /** Permalink to this tag's page, without the `/tags/` base path. */
13
14
  permalink: string;
14
15
  };
15
16
 
16
17
  export type FrontMatterTag = string | Tag;
17
18
 
18
- export function normalizeFrontMatterTag(
19
+ function normalizeFrontMatterTag(
19
20
  tagsPath: string,
20
21
  frontMatterTag: FrontMatterTag,
21
22
  ): Tag {
@@ -45,8 +46,19 @@ export function normalizeFrontMatterTag(
45
46
  };
46
47
  }
47
48
 
49
+ /**
50
+ * Takes tag objects as they are defined in front matter, and normalizes each
51
+ * into a standard tag object. The permalink is created by appending the
52
+ * sluggified label to `tagsPath`. Front matter tags already containing
53
+ * permalinks would still have `tagsPath` prepended.
54
+ *
55
+ * The result will always be unique by permalinks. The behavior with colliding
56
+ * permalinks is undetermined.
57
+ */
48
58
  export function normalizeFrontMatterTags(
59
+ /** Base path to append the tag permalinks to. */
49
60
  tagsPath: string,
61
+ /** Can be `undefined`, so that we can directly pipe in `frontMatter.tags`. */
50
62
  frontMatterTags: FrontMatterTag[] | undefined = [],
51
63
  ): Tag[] {
52
64
  const tags = frontMatterTags.map((tag) =>
@@ -56,42 +68,42 @@ export function normalizeFrontMatterTags(
56
68
  return _.uniqBy(tags, (tag) => tag.permalink);
57
69
  }
58
70
 
59
- export type TaggedItemGroup<Item> = {
71
+ type TaggedItemGroup<Item> = {
60
72
  tag: Tag;
61
73
  items: Item[];
62
74
  };
63
75
 
64
76
  /**
65
- * Permits to group docs/blogPosts by tag (provided by front matter)
66
- * Note: groups are indexed by permalink, because routes must be unique in the
67
- * end. Labels may vary on 2 md files but they are normalized. Docs with
68
- * label='some label' and label='some-label' should end-up in the same
69
- * group/page in the end. We can't create 2 routes /some-label because one would
70
- * override the other
77
+ * Permits to group docs/blog posts by tag (provided by front matter).
78
+ *
79
+ * @returns a map from tag permalink to the items and other relevant tag data.
80
+ * The record is indexed by permalink, because routes must be unique in the end.
81
+ * Labels may vary on 2 MD files but they are normalized. Docs with
82
+ * label='some label' and label='some-label' should end up in the same page.
71
83
  */
72
84
  export function groupTaggedItems<Item>(
73
85
  items: readonly Item[],
86
+ /**
87
+ * A callback telling me how to get the tags list of the current item. Usually
88
+ * simply getting it from some metadata of the current item.
89
+ */
74
90
  getItemTags: (item: Item) => readonly Tag[],
75
- ): Record<string, TaggedItemGroup<Item>> {
76
- const result: Record<string, TaggedItemGroup<Item>> = {};
77
-
78
- function handleItemTag(item: Item, tag: Tag) {
79
- // Init missing tag groups
80
- // TODO: it's not really clear what should be the behavior if 2 items have
81
- // the same tag but the permalink is different for each
82
- // For now, the first tag found wins
83
- result[tag.permalink] ??= {
84
- tag,
85
- items: [],
86
- };
87
-
88
- // Add item to group
89
- result[tag.permalink]!.items.push(item);
90
- }
91
+ ): {[permalink: string]: TaggedItemGroup<Item>} {
92
+ const result: {[permalink: string]: TaggedItemGroup<Item>} = {};
91
93
 
92
94
  items.forEach((item) => {
93
95
  getItemTags(item).forEach((tag) => {
94
- handleItemTag(item, tag);
96
+ // Init missing tag groups
97
+ // TODO: it's not really clear what should be the behavior if 2 tags have
98
+ // the same permalink but the label is different for each
99
+ // For now, the first tag found wins
100
+ result[tag.permalink] ??= {
101
+ tag,
102
+ items: [],
103
+ };
104
+
105
+ // Add item to group
106
+ result[tag.permalink]!.items.push(item);
95
107
  });
96
108
  });
97
109
 
package/src/urlUtils.ts CHANGED
@@ -8,6 +8,18 @@
8
8
  import {removeSuffix} from './jsUtils';
9
9
  import resolvePathnameUnsafe from 'resolve-pathname';
10
10
 
11
+ /**
12
+ * Much like `path.join`, but much better. Takes an array of URL segments, and
13
+ * joins them into a reasonable URL.
14
+ *
15
+ * - `["file:", "/home", "/user/", "website"]` => `file:///home/user/website`
16
+ * - `["file://", "home", "/user/", "website"]` => `file://home/user/website` (relative!)
17
+ * - Remove trailing slash before parameters or hash.
18
+ * - Replace `?` in query parameters with `&`.
19
+ * - Dedupe forward slashes in the entire path, avoiding protocol slashes.
20
+ *
21
+ * @throws {TypeError} If any of the URL segment is not a string, this throws.
22
+ */
11
23
  export function normalizeUrl(rawUrls: string[]): string {
12
24
  const urls = [...rawUrls];
13
25
  const resultArray = [];
@@ -75,8 +87,8 @@ export function normalizeUrl(rawUrls: string[]): string {
75
87
  }
76
88
 
77
89
  let str = resultArray.join('/');
78
- // Each input component is now separated by a single slash
79
- // except the possible first plain protocol part.
90
+ // Each input component is now separated by a single slash except the possible
91
+ // first plain protocol part.
80
92
 
81
93
  // Remove trailing slash before parameters or hash.
82
94
  str = str.replace(/\/(?<search>\?|&|#[^!])/g, '$1');
@@ -94,6 +106,11 @@ export function normalizeUrl(rawUrls: string[]): string {
94
106
  return str;
95
107
  }
96
108
 
109
+ /**
110
+ * Takes a file's path, relative to its content folder, and computes its edit
111
+ * URL. If `editUrl` is `undefined`, this returns `undefined`, as is the case
112
+ * when the user doesn't want an edit URL in her config.
113
+ */
97
114
  export function getEditUrl(
98
115
  fileRelativePath: string,
99
116
  editUrl?: string,
@@ -105,8 +122,8 @@ export function getEditUrl(
105
122
  }
106
123
 
107
124
  /**
108
- * Convert filepath to url path.
109
- * Example: 'index.md' -> '/', 'foo/bar.js' -> '/foo/bar',
125
+ * Converts file path to a reasonable URL path, e.g. `'index.md'` -> `'/'`,
126
+ * `'foo/bar.js'` -> `'/foo/bar'`
110
127
  */
111
128
  export function fileToPath(file: string): string {
112
129
  const indexRE = /(?<dirname>^|.*\/)index\.(?:mdx?|jsx?|tsx?)$/i;
@@ -118,6 +135,13 @@ export function fileToPath(file: string): string {
118
135
  return `/${file.replace(extRE, '').replace(/\\/g, '/')}`;
119
136
  }
120
137
 
138
+ /**
139
+ * Similar to `encodeURI`, but uses `encodeURIComponent` and assumes there's no
140
+ * query.
141
+ *
142
+ * `encodeURI("/question?/answer")` => `"/question?/answer#section"`;
143
+ * `encodePath("/question?/answer#section")` => `"/question%3F/answer%23foo"`
144
+ */
121
145
  export function encodePath(userPath: string): string {
122
146
  return userPath
123
147
  .split('/')
@@ -125,6 +149,10 @@ export function encodePath(userPath: string): string {
125
149
  .join('/');
126
150
  }
127
151
 
152
+ /**
153
+ * Whether `str` is a valid pathname. It must be absolute, and not contain
154
+ * special characters.
155
+ */
128
156
  export function isValidPathname(str: string): boolean {
129
157
  if (!str.startsWith('/')) {
130
158
  return false;
@@ -138,22 +166,31 @@ export function isValidPathname(str: string): boolean {
138
166
  }
139
167
  }
140
168
 
141
- // resolve pathname and fail fast if resolution fails
169
+ /**
170
+ * Resolve pathnames and fail-fast if resolution fails. Uses standard URL
171
+ * semantics (provided by `resolve-pathname` which is used internally by React
172
+ * router)
173
+ */
142
174
  export function resolvePathname(to: string, from?: string): string {
143
175
  return resolvePathnameUnsafe(to, from);
144
176
  }
177
+ /** Appends a leading slash to `str`, if one doesn't exist. */
145
178
  export function addLeadingSlash(str: string): string {
146
179
  return str.startsWith('/') ? str : `/${str}`;
147
180
  }
148
181
 
149
182
  // TODO deduplicate: also present in @docusaurus/utils-common
183
+ /** Appends a trailing slash to `str`, if one doesn't exist. */
150
184
  export function addTrailingSlash(str: string): string {
151
185
  return str.endsWith('/') ? str : `${str}/`;
152
186
  }
187
+
188
+ /** Removes the trailing slash from `str`. */
153
189
  export function removeTrailingSlash(str: string): string {
154
190
  return removeSuffix(str, '/');
155
191
  }
156
192
 
193
+ /** Constructs an SSH URL that can be used to push to GitHub. */
157
194
  export function buildSshUrl(
158
195
  githubHost: string,
159
196
  organizationName: string,
@@ -166,6 +203,7 @@ export function buildSshUrl(
166
203
  return `git@${githubHost}:${organizationName}/${projectName}.git`;
167
204
  }
168
205
 
206
+ /** Constructs an HTTP URL that can be used to push to GitHub. */
169
207
  export function buildHttpsUrl(
170
208
  gitCredentials: string,
171
209
  githubHost: string,
@@ -179,6 +217,11 @@ export function buildHttpsUrl(
179
217
  return `https://${gitCredentials}@${githubHost}/${organizationName}/${projectName}.git`;
180
218
  }
181
219
 
220
+ /**
221
+ * Whether the current URL is an SSH protocol. In addition to looking for
222
+ * `ssh:`, it will also allow protocol-less URLs like
223
+ * `git@github.com:facebook/docusaurus.git`.
224
+ */
182
225
  export function hasSSHProtocol(sourceRepoUrl: string): boolean {
183
226
  try {
184
227
  if (new URL(sourceRepoUrl).protocol === 'ssh:') {
@@ -187,6 +230,6 @@ export function hasSSHProtocol(sourceRepoUrl: string): boolean {
187
230
  return false;
188
231
  } catch {
189
232
  // Fails when there isn't a protocol
190
- return /^(?:[\w-]+@)?[\w.-]+:[\w./-]+/.test(sourceRepoUrl); // git@github.com:facebook/docusaurus.git
233
+ return /^(?:[\w-]+@)?[\w.-]+:[\w./-]+/.test(sourceRepoUrl);
191
234
  }
192
235
  }
@@ -31,7 +31,11 @@ type FileLoaderUtils = {
31
31
  };
32
32
  };
33
33
 
34
- // Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
34
+ /**
35
+ * Returns unified loader configurations to be used for various file types.
36
+ *
37
+ * Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
38
+ */
35
39
  export function getFileLoaderUtils(): FileLoaderUtils {
36
40
  // files/images < urlLoaderLimit will be inlined as base64 strings directly in
37
41
  // the html
@@ -39,7 +43,11 @@ export function getFileLoaderUtils(): FileLoaderUtils {
39
43
 
40
44
  // defines the path/pattern of the assets handled by webpack
41
45
  const fileLoaderFileName = (folder: AssetFolder) =>
42
- `${OUTPUT_STATIC_ASSETS_DIR_NAME}/${folder}/[name]-[contenthash].[ext]`;
46
+ path.posix.join(
47
+ OUTPUT_STATIC_ASSETS_DIR_NAME,
48
+ folder,
49
+ '[name]-[contenthash].[ext]',
50
+ );
43
51
 
44
52
  const loaders: FileLoaderUtils['loaders'] = {
45
53
  file: (options: {folder: AssetFolder}) => ({