@docusaurus/plugin-content-docs 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 (231) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +12 -0
  2. package/lib/categoryGeneratedIndex.js +37 -0
  3. package/lib/cli.d.ts +3 -2
  4. package/lib/cli.js +62 -72
  5. package/lib/client/docsClientUtils.d.ts +9 -28
  6. package/lib/client/docsClientUtils.js +35 -51
  7. package/lib/client/index.d.ts +81 -0
  8. package/lib/client/index.js +67 -0
  9. package/lib/constants.d.ts +4 -0
  10. package/lib/constants.js +4 -1
  11. package/lib/docs.d.ts +35 -8
  12. package/lib/docs.js +211 -78
  13. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → lib/frontMatter.d.ts} +4 -10
  14. package/lib/frontMatter.js +53 -0
  15. package/lib/globalData.d.ts +3 -3
  16. package/lib/globalData.js +35 -6
  17. package/lib/index.d.ts +3 -3
  18. package/lib/index.js +137 -146
  19. package/lib/lastUpdate.d.ts +4 -6
  20. package/lib/lastUpdate.js +22 -26
  21. package/lib/markdown/index.d.ts +3 -6
  22. package/lib/markdown/index.js +3 -3
  23. package/lib/markdown/linkify.d.ts +1 -1
  24. package/lib/markdown/linkify.js +7 -4
  25. package/lib/numberPrefix.d.ts +1 -1
  26. package/lib/numberPrefix.js +16 -21
  27. package/lib/options.d.ts +3 -5
  28. package/lib/options.js +57 -29
  29. package/lib/props.d.ts +7 -2
  30. package/lib/props.js +87 -16
  31. package/lib/routes.d.ts +29 -0
  32. package/lib/routes.js +96 -0
  33. package/lib/server-export.d.ts +9 -0
  34. package/lib/server-export.js +25 -0
  35. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +1 -6
  36. package/lib/sidebars/generator.js +209 -0
  37. package/lib/sidebars/index.d.ts +13 -0
  38. package/lib/sidebars/index.js +92 -0
  39. package/lib/sidebars/normalization.d.ts +13 -0
  40. package/lib/sidebars/normalization.js +59 -0
  41. package/lib/sidebars/postProcessor.d.ts +11 -0
  42. package/lib/sidebars/postProcessor.js +81 -0
  43. package/lib/sidebars/processor.d.ts +10 -0
  44. package/lib/sidebars/processor.js +79 -0
  45. package/lib/sidebars/types.d.ts +183 -0
  46. package/{types.d.ts → lib/sidebars/types.js} +2 -7
  47. package/lib/sidebars/utils.d.ts +55 -0
  48. package/lib/sidebars/utils.js +259 -0
  49. package/lib/sidebars/validation.d.ts +11 -0
  50. package/lib/sidebars/validation.js +143 -0
  51. package/lib/slug.d.ts +5 -4
  52. package/lib/slug.js +29 -19
  53. package/{src/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js → lib/tags.d.ts} +3 -14
  54. package/lib/tags.js +21 -0
  55. package/lib/translations.d.ts +3 -3
  56. package/lib/translations.js +100 -93
  57. package/lib/types.d.ts +13 -172
  58. package/lib/versions/files.d.ts +50 -0
  59. package/lib/versions/files.js +141 -0
  60. package/lib/versions/index.d.ts +36 -0
  61. package/lib/versions/index.js +154 -0
  62. package/lib/versions/validation.d.ts +17 -0
  63. package/lib/versions/validation.js +71 -0
  64. package/package.json +44 -29
  65. package/src/categoryGeneratedIndex.ts +60 -0
  66. package/src/cli.ts +94 -114
  67. package/src/client/docsClientUtils.ts +47 -84
  68. package/src/client/index.ts +158 -0
  69. package/src/constants.ts +4 -2
  70. package/src/docs.ts +294 -78
  71. package/src/frontMatter.ts +63 -0
  72. package/src/globalData.ts +57 -7
  73. package/src/index.ts +200 -204
  74. package/src/lastUpdate.ts +27 -34
  75. package/src/markdown/index.ts +10 -16
  76. package/src/markdown/linkify.ts +8 -5
  77. package/src/numberPrefix.ts +19 -26
  78. package/src/options.ts +61 -43
  79. package/src/plugin-content-docs.d.ts +575 -78
  80. package/src/props.ts +128 -23
  81. package/src/routes.ts +159 -0
  82. package/src/server-export.ts +26 -0
  83. package/src/sidebars/README.md +10 -0
  84. package/src/sidebars/generator.ts +292 -0
  85. package/src/sidebars/index.ts +118 -0
  86. package/src/sidebars/normalization.ts +91 -0
  87. package/src/sidebars/postProcessor.ts +112 -0
  88. package/src/sidebars/processor.ts +123 -0
  89. package/src/sidebars/types.ts +280 -0
  90. package/src/sidebars/utils.ts +393 -0
  91. package/src/sidebars/validation.ts +179 -0
  92. package/src/slug.ts +42 -23
  93. package/src/tags.ts +20 -0
  94. package/src/translations.ts +155 -124
  95. package/src/types.ts +17 -234
  96. package/src/versions/files.ts +216 -0
  97. package/src/versions/index.ts +246 -0
  98. package/src/versions/validation.ts +115 -0
  99. package/lib/.tsbuildinfo +0 -4673
  100. package/lib/docFrontMatter.d.ts +0 -21
  101. package/lib/docFrontMatter.js +0 -33
  102. package/lib/sidebarItemsGenerator.js +0 -211
  103. package/lib/sidebars.d.ts +0 -42
  104. package/lib/sidebars.js +0 -309
  105. package/lib/theme/hooks/useDocs.d.ts +0 -20
  106. package/lib/theme/hooks/useDocs.js +0 -72
  107. package/lib/versions.d.ts +0 -16
  108. package/lib/versions.js +0 -287
  109. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  110. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  111. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  112. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  113. package/src/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  114. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  115. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  116. package/src/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  117. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  118. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  119. package/src/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  120. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  121. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  122. package/src/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  123. package/src/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  124. package/src/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  125. package/src/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  126. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  127. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -67
  128. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  129. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -52
  130. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  131. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  132. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -5
  133. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -5
  134. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -5
  135. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -5
  136. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  137. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  138. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  139. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  140. package/src/__tests__/__fixtures__/simple-site/docusaurus.config.js +0 -14
  141. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -23
  142. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  143. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  144. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  145. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  146. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  147. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  148. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  149. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  150. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  151. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  152. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  153. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  154. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  155. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  156. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  157. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  158. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  159. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  160. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js +0 -14
  161. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars.js +0 -23
  162. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +0 -7
  163. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +0 -8
  164. package/src/__tests__/__fixtures__/site-with-doc-label/docusaurus.config.js +0 -14
  165. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  166. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  167. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  168. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  169. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  170. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  171. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -4
  172. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -1
  173. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  174. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  175. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  176. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  177. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  178. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  179. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  180. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  181. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  182. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  183. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  184. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -1
  185. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  186. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -1
  187. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  188. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  189. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  190. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  191. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  192. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  193. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  194. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  195. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  196. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  197. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  198. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  199. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -90
  200. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -1907
  201. package/src/__tests__/__snapshots__/sidebars.test.ts.snap +0 -218
  202. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -487
  203. package/src/__tests__/cli.test.ts +0 -333
  204. package/src/__tests__/docFrontMatter.test.ts +0 -204
  205. package/src/__tests__/docs.test.ts +0 -875
  206. package/src/__tests__/index.test.ts +0 -1831
  207. package/src/__tests__/lastUpdate.test.ts +0 -68
  208. package/src/__tests__/numberPrefix.test.ts +0 -199
  209. package/src/__tests__/options.test.ts +0 -232
  210. package/src/__tests__/sidebarItemsGenerator.test.ts +0 -336
  211. package/src/__tests__/sidebars.test.ts +0 -638
  212. package/src/__tests__/slug.test.ts +0 -109
  213. package/src/__tests__/translations.test.ts +0 -159
  214. package/src/__tests__/versions.test.ts +0 -718
  215. package/src/client/__tests__/docsClientUtils.test.ts +0 -372
  216. package/src/docFrontMatter.ts +0 -53
  217. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  218. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  219. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  220. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  221. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  222. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  223. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  224. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  225. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  226. package/src/markdown/__tests__/linkify.test.ts +0 -190
  227. package/src/sidebarItemsGenerator.ts +0 -307
  228. package/src/sidebars.ts +0 -489
  229. package/src/theme/hooks/useDocs.ts +0 -99
  230. package/src/versions.ts +0 -511
  231. package/tsconfig.json +0 -9
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import {Joi, URISchema} from '@docusaurus/utils-validation';
9
+ import type {
10
+ SidebarItemConfig,
11
+ SidebarItemBase,
12
+ SidebarItemAutogenerated,
13
+ SidebarItemDoc,
14
+ SidebarItemHtml,
15
+ SidebarItemLink,
16
+ SidebarItemCategoryConfig,
17
+ SidebarItemCategoryLink,
18
+ SidebarItemCategoryLinkDoc,
19
+ SidebarItemCategoryLinkGeneratedIndex,
20
+ NormalizedSidebars,
21
+ NormalizedSidebarItem,
22
+ NormalizedSidebarItemCategory,
23
+ CategoryMetadataFile,
24
+ } from './types';
25
+
26
+ // NOTE: we don't add any default values during validation on purpose!
27
+ // Config types are exposed to users for typechecking and we use the same type
28
+ // in normalization
29
+
30
+ const sidebarItemBaseSchema = Joi.object<SidebarItemBase>({
31
+ className: Joi.string(),
32
+ customProps: Joi.object().unknown(),
33
+ });
34
+
35
+ const sidebarItemAutogeneratedSchema =
36
+ sidebarItemBaseSchema.append<SidebarItemAutogenerated>({
37
+ type: 'autogenerated',
38
+ dirName: Joi.string()
39
+ .required()
40
+ .pattern(/^[^/](?:.*[^/])?$/)
41
+ .message(
42
+ '"dirName" must be a dir path relative to the docs folder root, and should not start or end with slash',
43
+ ),
44
+ });
45
+
46
+ const sidebarItemDocSchema = sidebarItemBaseSchema.append<SidebarItemDoc>({
47
+ type: Joi.string().valid('doc', 'ref').required(),
48
+ id: Joi.string().required(),
49
+ label: Joi.string(),
50
+ translatable: Joi.boolean(),
51
+ });
52
+
53
+ const sidebarItemHtmlSchema = sidebarItemBaseSchema.append<SidebarItemHtml>({
54
+ type: 'html',
55
+ value: Joi.string().required(),
56
+ defaultStyle: Joi.boolean(),
57
+ });
58
+
59
+ const sidebarItemLinkSchema = sidebarItemBaseSchema.append<SidebarItemLink>({
60
+ type: 'link',
61
+ href: URISchema.required(),
62
+ label: Joi.string()
63
+ .required()
64
+ .messages({'any.unknown': '"label" must be a string'}),
65
+ });
66
+
67
+ const sidebarItemCategoryLinkSchema = Joi.object<SidebarItemCategoryLink>()
68
+ .allow(null)
69
+ .when('.type', {
70
+ switch: [
71
+ {
72
+ is: 'doc',
73
+ then: Joi.object<SidebarItemCategoryLinkDoc>({
74
+ type: 'doc',
75
+ id: Joi.string().required(),
76
+ }),
77
+ },
78
+ {
79
+ is: 'generated-index',
80
+ then: Joi.object<SidebarItemCategoryLinkGeneratedIndex>({
81
+ type: 'generated-index',
82
+ slug: Joi.string().optional(),
83
+ // This one is not in the user config, only in the normalized version
84
+ // permalink: Joi.string().optional(),
85
+ title: Joi.string().optional(),
86
+ description: Joi.string().optional(),
87
+ image: Joi.string().optional(),
88
+ keywords: [Joi.string(), Joi.array().items(Joi.string())],
89
+ }),
90
+ },
91
+ {
92
+ is: Joi.required(),
93
+ then: Joi.forbidden().messages({
94
+ 'any.unknown': 'Unknown sidebar category link type "{.type}".',
95
+ }),
96
+ },
97
+ ],
98
+ });
99
+
100
+ const sidebarItemCategorySchema =
101
+ sidebarItemBaseSchema.append<SidebarItemCategoryConfig>({
102
+ type: 'category',
103
+ label: Joi.string()
104
+ .required()
105
+ .messages({'any.unknown': '"label" must be a string'}),
106
+ items: Joi.array()
107
+ .required()
108
+ .messages({'any.unknown': '"items" must be an array'}),
109
+ // TODO: Joi doesn't allow mutual recursion. See https://github.com/sideway/joi/issues/2611
110
+ // .items(Joi.link('#sidebarItemSchema')),
111
+ link: sidebarItemCategoryLinkSchema,
112
+ collapsed: Joi.boolean().messages({
113
+ 'any.unknown': '"collapsed" must be a boolean',
114
+ }),
115
+ collapsible: Joi.boolean().messages({
116
+ 'any.unknown': '"collapsible" must be a boolean',
117
+ }),
118
+ });
119
+
120
+ const sidebarItemSchema = Joi.object<SidebarItemConfig>().when('.type', {
121
+ switch: [
122
+ {is: 'link', then: sidebarItemLinkSchema},
123
+ {
124
+ is: Joi.string().valid('doc', 'ref').required(),
125
+ then: sidebarItemDocSchema,
126
+ },
127
+ {is: 'html', then: sidebarItemHtmlSchema},
128
+ {is: 'autogenerated', then: sidebarItemAutogeneratedSchema},
129
+ {is: 'category', then: sidebarItemCategorySchema},
130
+ {
131
+ is: Joi.any().required(),
132
+ then: Joi.forbidden().messages({
133
+ 'any.unknown': 'Unknown sidebar item type "{.type}".',
134
+ }),
135
+ },
136
+ ],
137
+ });
138
+ // .id('sidebarItemSchema');
139
+
140
+ function validateSidebarItem(
141
+ item: unknown,
142
+ ): asserts item is NormalizedSidebarItem {
143
+ // TODO: remove once with proper Joi support
144
+ // Because we can't use Joi to validate nested items (see above), we do it
145
+ // manually
146
+ Joi.assert(item, sidebarItemSchema);
147
+
148
+ if ((item as NormalizedSidebarItem).type === 'category') {
149
+ (item as NormalizedSidebarItemCategory).items.forEach(validateSidebarItem);
150
+ }
151
+ }
152
+
153
+ export function validateSidebars(sidebars: {
154
+ [sidebarId: string]: unknown;
155
+ }): asserts sidebars is NormalizedSidebars {
156
+ Object.values(sidebars as NormalizedSidebars).forEach((sidebar) => {
157
+ sidebar.forEach(validateSidebarItem);
158
+ });
159
+ }
160
+
161
+ const categoryMetadataFileSchema = Joi.object<CategoryMetadataFile>({
162
+ label: Joi.string(),
163
+ position: Joi.number(),
164
+ collapsed: Joi.boolean(),
165
+ collapsible: Joi.boolean(),
166
+ className: Joi.string(),
167
+ link: sidebarItemCategoryLinkSchema,
168
+ customProps: Joi.object().unknown(),
169
+ });
170
+
171
+ export function validateCategoryMetadataFile(
172
+ unsafeContent: unknown,
173
+ ): CategoryMetadataFile {
174
+ const {error, value} = categoryMetadataFileSchema.validate(unsafeContent);
175
+ if (error) {
176
+ throw error;
177
+ }
178
+ return value;
179
+ }
package/src/slug.ts CHANGED
@@ -15,50 +15,69 @@ import {
15
15
  DefaultNumberPrefixParser,
16
16
  stripPathNumberPrefixes,
17
17
  } from './numberPrefix';
18
- import {NumberPrefixParser} from './types';
18
+ import {isCategoryIndex, toCategoryIndexMatcherParam} from './docs';
19
+ import type {
20
+ NumberPrefixParser,
21
+ DocMetadataBase,
22
+ } from '@docusaurus/plugin-content-docs';
19
23
 
20
24
  export default function getSlug({
21
25
  baseID,
22
- frontmatterSlug,
23
- dirName,
26
+ frontMatterSlug,
27
+ source,
28
+ sourceDirName,
24
29
  stripDirNumberPrefixes = true,
25
30
  numberPrefixParser = DefaultNumberPrefixParser,
26
31
  }: {
27
32
  baseID: string;
28
- frontmatterSlug?: string;
29
- dirName: string;
33
+ frontMatterSlug?: string;
34
+ source: DocMetadataBase['source'];
35
+ sourceDirName: DocMetadataBase['sourceDirName'];
30
36
  stripDirNumberPrefixes?: boolean;
31
37
  numberPrefixParser?: NumberPrefixParser;
32
38
  }): string {
33
- const baseSlug = frontmatterSlug || baseID;
34
- let slug: string;
35
- if (baseSlug.startsWith('/')) {
36
- slug = baseSlug;
37
- } else {
39
+ function getDirNameSlug(): string {
38
40
  const dirNameStripped = stripDirNumberPrefixes
39
- ? stripPathNumberPrefixes(dirName, numberPrefixParser)
40
- : dirName;
41
+ ? stripPathNumberPrefixes(sourceDirName, numberPrefixParser)
42
+ : sourceDirName;
41
43
  const resolveDirname =
42
- dirName === '.'
44
+ sourceDirName === '.'
43
45
  ? '/'
44
46
  : addLeadingSlash(addTrailingSlash(dirNameStripped));
45
- slug = resolvePathname(baseSlug, resolveDirname);
47
+ return resolveDirname;
46
48
  }
47
49
 
48
- if (!isValidPathname(slug)) {
49
- throw new Error(
50
- `We couldn't compute a valid slug for document with id=${baseID} in folder=${dirName}
51
- The slug we computed looks invalid: ${slug}
52
- Maybe your slug frontmatter is incorrect or you use weird chars in the file path?
53
- By using the slug frontmatter, you should be able to fix this error, by using the slug of your choice:
50
+ function computeSlug(): string {
51
+ if (frontMatterSlug?.startsWith('/')) {
52
+ return frontMatterSlug;
53
+ }
54
+ const dirNameSlug = getDirNameSlug();
55
+ if (
56
+ !frontMatterSlug &&
57
+ isCategoryIndex(toCategoryIndexMatcherParam({source, sourceDirName}))
58
+ ) {
59
+ return dirNameSlug;
60
+ }
61
+ const baseSlug = frontMatterSlug ?? baseID;
62
+ return resolvePathname(baseSlug, getDirNameSlug());
63
+ }
64
+
65
+ function ensureValidSlug(slug: string): string {
66
+ if (!isValidPathname(slug)) {
67
+ throw new Error(
68
+ `We couldn't compute a valid slug for document with ID "${baseID}" in "${sourceDirName}" directory.
69
+ The slug we computed looks invalid: ${slug}.
70
+ Maybe your slug front matter is incorrect or there are special characters in the file path?
71
+ By using front matter to set a custom slug, you should be able to fix this error:
54
72
 
55
- Example =>
56
73
  ---
57
74
  slug: /my/customDocPath
58
75
  ---
59
76
  `,
60
- );
77
+ );
78
+ }
79
+ return slug;
61
80
  }
62
81
 
63
- return slug;
82
+ return ensureValidSlug(computeSlug());
64
83
  }
package/src/tags.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import _ from 'lodash';
9
+ import {groupTaggedItems} from '@docusaurus/utils';
10
+ import type {VersionTags} from './types';
11
+ import type {DocMetadata} from '@docusaurus/plugin-content-docs';
12
+
13
+ export function getVersionTags(docs: DocMetadata[]): VersionTags {
14
+ const groups = groupTaggedItems(docs, (doc) => doc.tags);
15
+ return _.mapValues(groups, (group) => ({
16
+ label: group.tag.label,
17
+ docIds: group.items.map((item) => item.id),
18
+ permalink: group.tag.permalink,
19
+ }));
20
+ }
@@ -5,36 +5,39 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {
9
- LoadedVersion,
10
- Sidebar,
11
- LoadedContent,
12
- Sidebars,
13
- SidebarItem,
14
- } from './types';
15
-
16
- import {chain, mapValues, flatten, keyBy} from 'lodash';
8
+ import _ from 'lodash';
9
+ import {mergeTranslations} from '@docusaurus/utils';
10
+ import {CURRENT_VERSION_NAME} from './constants';
17
11
  import {
18
12
  collectSidebarCategories,
19
13
  transformSidebarItems,
20
14
  collectSidebarLinks,
21
- } from './sidebars';
22
- import {
15
+ collectSidebarDocItems,
16
+ collectSidebarRefs,
17
+ } from './sidebars/utils';
18
+ import type {
19
+ LoadedVersion,
20
+ LoadedContent,
21
+ } from '@docusaurus/plugin-content-docs';
22
+ import type {
23
+ Sidebar,
24
+ SidebarItemCategory,
25
+ SidebarItemCategoryLink,
26
+ Sidebars,
27
+ } from './sidebars/types';
28
+ import type {
23
29
  TranslationFileContent,
24
30
  TranslationFile,
25
- TranslationFiles,
31
+ TranslationMessage,
26
32
  } from '@docusaurus/types';
27
- import {mergeTranslations} from '@docusaurus/utils';
28
- import {CURRENT_VERSION_NAME} from './constants';
29
33
 
30
34
  function getVersionFileName(versionName: string): string {
31
35
  if (versionName === CURRENT_VERSION_NAME) {
32
36
  return versionName;
33
- } else {
34
- // I don't like this "version-" prefix,
35
- // but it's for consistency with site/versioned_docs
36
- return `version-${versionName}`;
37
37
  }
38
+ // I don't like this "version-" prefix,
39
+ // but it's for consistency with site/versioned_docs
40
+ return `version-${versionName}`;
38
41
  }
39
42
 
40
43
  // TODO legacy, the sidebar name is like "version-2.0.0-alpha.66/docs"
@@ -54,72 +57,78 @@ function getNormalizedSidebarName({
54
57
  return rest.join('/');
55
58
  }
56
59
 
57
- /*
58
- // Do we need to translate doc metadatas?
59
- // It seems translating frontmatter labels is good enough
60
- function getDocTranslations(doc: DocMetadata): TranslationFileContent {
61
- return {
62
- [`${doc.unversionedId}.title`]: {
63
- message: doc.title,
64
- description: `The title for doc with id=${doc.unversionedId}`,
65
- },
66
- ...(doc.sidebar_label
67
- ? {
68
- [`${doc.unversionedId}.sidebar_label`]: {
69
- message: doc.sidebar_label,
70
- description: `The sidebar label for doc with id=${doc.unversionedId}`,
71
- },
72
- }
73
- : undefined),
74
- };
75
- }
76
- function translateDoc(
77
- doc: DocMetadata,
78
- docsTranslations: TranslationFileContent,
79
- ): DocMetadata {
80
- return {
81
- ...doc,
82
- title: docsTranslations[`${doc.unversionedId}.title`]?.message ?? doc.title,
83
- sidebar_label:
84
- docsTranslations[`${doc.unversionedId}.sidebar_label`]?.message ??
85
- doc.sidebar_label,
86
- };
87
- }
88
-
89
- function getDocsTranslations(version: LoadedVersion): TranslationFileContent {
90
- return mergeTranslations(version.docs.map(getDocTranslations));
91
- }
92
- function translateDocs(
93
- docs: DocMetadata[],
94
- docsTranslations: TranslationFileContent,
95
- ): DocMetadata[] {
96
- return docs.map((doc) => translateDoc(doc, docsTranslations));
97
- }
98
- */
99
-
100
60
  function getSidebarTranslationFileContent(
101
61
  sidebar: Sidebar,
102
62
  sidebarName: string,
103
63
  ): TranslationFileContent {
64
+ type TranslationMessageEntry = [string, TranslationMessage];
65
+
104
66
  const categories = collectSidebarCategories(sidebar);
105
- const categoryContent: TranslationFileContent = chain(categories)
106
- .keyBy((category) => `sidebar.${sidebarName}.category.${category.label}`)
107
- .mapValues((category) => ({
108
- message: category.label,
109
- description: `The label for category ${category.label} in sidebar ${sidebarName}`,
110
- }))
111
- .value();
67
+
68
+ const categoryContent: TranslationFileContent = Object.fromEntries(
69
+ categories.flatMap((category) => {
70
+ const entries: TranslationMessageEntry[] = [];
71
+
72
+ entries.push([
73
+ `sidebar.${sidebarName}.category.${category.label}`,
74
+ {
75
+ message: category.label,
76
+ description: `The label for category ${category.label} in sidebar ${sidebarName}`,
77
+ },
78
+ ]);
79
+
80
+ if (category.link?.type === 'generated-index') {
81
+ if (category.link.title) {
82
+ entries.push([
83
+ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.title`,
84
+ {
85
+ message: category.link.title,
86
+ description: `The generated-index page title for category ${category.label} in sidebar ${sidebarName}`,
87
+ },
88
+ ]);
89
+ }
90
+ if (category.link.description) {
91
+ entries.push([
92
+ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.description`,
93
+ {
94
+ message: category.link.description,
95
+ description: `The generated-index page description for category ${category.label} in sidebar ${sidebarName}`,
96
+ },
97
+ ]);
98
+ }
99
+ }
100
+
101
+ return entries;
102
+ }),
103
+ );
112
104
 
113
105
  const links = collectSidebarLinks(sidebar);
114
- const linksContent: TranslationFileContent = chain(links)
115
- .keyBy((link) => `sidebar.${sidebarName}.link.${link.label}`)
116
- .mapValues((link) => ({
117
- message: link.label,
118
- description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`,
119
- }))
120
- .value();
106
+ const linksContent: TranslationFileContent = Object.fromEntries(
107
+ links.map((link) => [
108
+ `sidebar.${sidebarName}.link.${link.label}`,
109
+ {
110
+ message: link.label,
111
+ description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`,
112
+ },
113
+ ]),
114
+ );
115
+
116
+ const docs = collectSidebarDocItems(sidebar)
117
+ .concat(collectSidebarRefs(sidebar))
118
+ .filter((item) => item.translatable);
119
+ const docLinksContent: TranslationFileContent = Object.fromEntries(
120
+ docs.map((doc) => [
121
+ `sidebar.${sidebarName}.doc.${doc.label!}`,
122
+ {
123
+ message: doc.label!,
124
+ description: `The label for the doc item ${doc.label!} in sidebar ${sidebarName}, linking to the doc ${
125
+ doc.id
126
+ }`,
127
+ },
128
+ ]),
129
+ );
121
130
 
122
- return mergeTranslations([categoryContent, linksContent]);
131
+ return mergeTranslations([categoryContent, linksContent, docLinksContent]);
123
132
  }
124
133
 
125
134
  function translateSidebar({
@@ -131,29 +140,59 @@ function translateSidebar({
131
140
  sidebarName: string;
132
141
  sidebarsTranslations: TranslationFileContent;
133
142
  }): Sidebar {
134
- return transformSidebarItems(
135
- sidebar,
136
- (item: SidebarItem): SidebarItem => {
137
- if (item.type === 'category') {
138
- return {
139
- ...item,
140
- label:
141
- sidebarsTranslations[
142
- `sidebar.${sidebarName}.category.${item.label}`
143
- ]?.message ?? item.label,
144
- };
145
- }
146
- if (item.type === 'link') {
147
- return {
148
- ...item,
149
- label:
150
- sidebarsTranslations[`sidebar.${sidebarName}.link.${item.label}`]
151
- ?.message ?? item.label,
152
- };
153
- }
154
- return item;
155
- },
156
- );
143
+ function transformSidebarCategoryLink(
144
+ category: SidebarItemCategory,
145
+ ): SidebarItemCategoryLink | undefined {
146
+ if (!category.link) {
147
+ return undefined;
148
+ }
149
+ if (category.link.type === 'generated-index') {
150
+ const title =
151
+ sidebarsTranslations[
152
+ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.title`
153
+ ]?.message ?? category.link.title;
154
+ const description =
155
+ sidebarsTranslations[
156
+ `sidebar.${sidebarName}.category.${category.label}.link.generated-index.description`
157
+ ]?.message ?? category.link.description;
158
+ return {
159
+ ...category.link,
160
+ title,
161
+ description,
162
+ };
163
+ }
164
+ return category.link;
165
+ }
166
+
167
+ return transformSidebarItems(sidebar, (item) => {
168
+ if (item.type === 'category') {
169
+ const link = transformSidebarCategoryLink(item);
170
+ return {
171
+ ...item,
172
+ label:
173
+ sidebarsTranslations[`sidebar.${sidebarName}.category.${item.label}`]
174
+ ?.message ?? item.label,
175
+ ...(link && {link}),
176
+ };
177
+ }
178
+ if (item.type === 'link') {
179
+ return {
180
+ ...item,
181
+ label:
182
+ sidebarsTranslations[`sidebar.${sidebarName}.link.${item.label}`]
183
+ ?.message ?? item.label,
184
+ };
185
+ }
186
+ if ((item.type === 'doc' || item.type === 'ref') && item.translatable) {
187
+ return {
188
+ ...item,
189
+ label:
190
+ sidebarsTranslations[`sidebar.${sidebarName}.doc.${item.label!}`]
191
+ ?.message ?? item.label,
192
+ };
193
+ }
194
+ return item;
195
+ });
157
196
  }
158
197
 
159
198
  function getSidebarsTranslations(
@@ -173,79 +212,71 @@ function translateSidebars(
173
212
  version: LoadedVersion,
174
213
  sidebarsTranslations: TranslationFileContent,
175
214
  ): Sidebars {
176
- return mapValues(version.sidebars, (sidebar, sidebarName) => {
177
- return translateSidebar({
215
+ return _.mapValues(version.sidebars, (sidebar, sidebarName) =>
216
+ translateSidebar({
178
217
  sidebar,
179
218
  sidebarName: getNormalizedSidebarName({
180
219
  sidebarName,
181
220
  versionName: version.versionName,
182
221
  }),
183
222
  sidebarsTranslations,
184
- });
185
- });
223
+ }),
224
+ );
186
225
  }
187
226
 
188
- function getVersionTranslationFiles(version: LoadedVersion): TranslationFiles {
227
+ function getVersionTranslationFiles(version: LoadedVersion): TranslationFile[] {
189
228
  const versionTranslations: TranslationFileContent = {
190
229
  'version.label': {
191
- message: version.versionLabel,
230
+ message: version.label,
192
231
  description: `The label for version ${version.versionName}`,
193
232
  },
194
233
  };
195
234
 
196
- const sidebarsTranslations: TranslationFileContent = getSidebarsTranslations(
197
- version,
198
- );
199
-
200
- // const docsTranslations: TranslationFileContent = getDocsTranslations(version);
235
+ const sidebarsTranslations: TranslationFileContent =
236
+ getSidebarsTranslations(version);
201
237
 
202
238
  return [
203
239
  {
204
240
  path: getVersionFileName(version.versionName),
205
- content: mergeTranslations([
206
- versionTranslations,
207
- sidebarsTranslations,
208
- // docsTranslations,
209
- ]),
241
+ content: mergeTranslations([versionTranslations, sidebarsTranslations]),
210
242
  },
211
243
  ];
212
244
  }
213
245
  function translateVersion(
214
246
  version: LoadedVersion,
215
- translationFiles: Record<string, TranslationFile>,
247
+ translationFiles: {[fileName: string]: TranslationFile},
216
248
  ): LoadedVersion {
217
249
  const versionTranslations =
218
- translationFiles[getVersionFileName(version.versionName)].content;
250
+ translationFiles[getVersionFileName(version.versionName)]!.content;
219
251
  return {
220
252
  ...version,
221
- versionLabel: versionTranslations['version.label']?.message,
253
+ label: versionTranslations['version.label']?.message ?? version.label,
222
254
  sidebars: translateSidebars(version, versionTranslations),
223
- // docs: translateDocs(version.docs, versionTranslations),
224
255
  };
225
256
  }
226
257
 
227
258
  function getVersionsTranslationFiles(
228
259
  versions: LoadedVersion[],
229
- ): TranslationFiles {
230
- return flatten(versions.map(getVersionTranslationFiles));
260
+ ): TranslationFile[] {
261
+ return versions.flatMap(getVersionTranslationFiles);
231
262
  }
232
263
  function translateVersions(
233
264
  versions: LoadedVersion[],
234
- translationFiles: Record<string, TranslationFile>,
265
+ translationFiles: {[fileName: string]: TranslationFile},
235
266
  ): LoadedVersion[] {
236
267
  return versions.map((version) => translateVersion(version, translationFiles));
237
268
  }
238
269
 
239
270
  export function getLoadedContentTranslationFiles(
240
271
  loadedContent: LoadedContent,
241
- ): TranslationFiles {
272
+ ): TranslationFile[] {
242
273
  return getVersionsTranslationFiles(loadedContent.loadedVersions);
243
274
  }
244
275
  export function translateLoadedContent(
245
276
  loadedContent: LoadedContent,
246
277
  translationFiles: TranslationFile[],
247
278
  ): LoadedContent {
248
- const translationFilesMap: Record<string, TranslationFile> = keyBy(
279
+ const translationFilesMap: {[fileName: string]: TranslationFile} = _.keyBy(
249
280
  translationFiles,
250
281
  (f) => f.path,
251
282
  );