erudit 4.0.0-dev.3 → 4.0.0-dev.5

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 (336) hide show
  1. package/.nuxtrc +1 -1
  2. package/app/app.vue +34 -34
  3. package/app/components/EruditLink.ts +7 -7
  4. package/app/components/FancyBold.vue +16 -16
  5. package/app/components/FancyCard.vue +52 -58
  6. package/app/components/FancyCardTag.vue +16 -16
  7. package/app/components/Loading.vue +7 -0
  8. package/app/components/Prose.vue +55 -51
  9. package/app/components/ScrollHolder.vue +13 -13
  10. package/app/components/SmartMedia.vue +107 -112
  11. package/app/components/ads/Ads.vue +17 -17
  12. package/app/components/ads/AdsBannerAside.vue +29 -29
  13. package/app/components/ads/AdsBannerBottom.vue +6 -6
  14. package/app/components/ads/AdsReplacer.vue +19 -21
  15. package/app/components/ads/provider/Custom.vue +9 -9
  16. package/app/components/ads/provider/Yandex.vue +56 -56
  17. package/app/components/aside/AsideListItem.vue +47 -52
  18. package/app/components/aside/AsideMajor.vue +6 -6
  19. package/app/components/aside/AsideMinor.vue +47 -55
  20. package/app/components/aside/AsidePlainMessage.vue +9 -9
  21. package/app/components/aside/AsideSwitch.vue +53 -54
  22. package/app/components/aside/major/PaneHolder.vue +61 -61
  23. package/app/components/aside/major/PaneSwitcher.vue +50 -55
  24. package/app/components/aside/major/PaneSwitcherButton.vue +24 -24
  25. package/app/components/aside/major/PaneTemplate.vue +3 -3
  26. package/app/components/aside/major/SiteInfo.vue +40 -42
  27. package/app/components/aside/major/contentNav/PaneBookNav.vue +107 -116
  28. package/app/components/aside/major/contentNav/PaneGlobalNav.vue +19 -19
  29. package/app/components/aside/major/contentNav/items/ContentNavBook.vue +8 -8
  30. package/app/components/aside/major/contentNav/items/ContentNavFolder.vue +55 -56
  31. package/app/components/aside/major/contentNav/items/ContentNavItem.vue +16 -16
  32. package/app/components/aside/major/contentNav/items/ContentNavPage.vue +2 -6
  33. package/app/components/aside/major/contentNav/items/ContentNavSeparator.vue +34 -35
  34. package/app/components/aside/major/contentNav/items/ContentNavTopic.vue +6 -6
  35. package/app/components/aside/major/contentNav/items/Flags.vue +31 -33
  36. package/app/components/aside/major/contentNav/items/ItemTemplate.vue +13 -13
  37. package/app/components/aside/major/languages/PaneLanguages.vue +40 -40
  38. package/app/components/aside/major/pages/PanePages.vue +45 -45
  39. package/app/components/aside/major/search/PaneSearch.vue +111 -100
  40. package/app/components/aside/major/search/SearchInput.vue +52 -53
  41. package/app/components/aside/major/search/SearchResult.vue +125 -74
  42. package/app/components/aside/major/search/SearchStatus.vue +28 -28
  43. package/app/components/aside/major/search/search.worker.ts +129 -129
  44. package/app/components/aside/major/settings/BuildTime.vue +15 -15
  45. package/app/components/aside/major/settings/EngineVersion.vue +8 -7
  46. package/app/components/aside/major/settings/PaneSettings.vue +8 -8
  47. package/app/components/aside/major/settings/ThemeSwitcher.vue +38 -36
  48. package/app/components/aside/major/settings/repository/Repository.vue +18 -18
  49. package/app/components/aside/major/settings/repository/SecondaryGitHub.vue +47 -47
  50. package/app/components/aside/minor/AsideMinorPane.vue +5 -5
  51. package/app/components/aside/minor/AsideMinorPlainHeader.vue +20 -20
  52. package/app/components/aside/minor/content/AsideMinorContentContributions.vue +47 -51
  53. package/app/components/aside/minor/content/AsideMinorContentPage.vue +37 -37
  54. package/app/components/aside/minor/content/AsideMinorContentTopic.vue +61 -66
  55. package/app/components/aside/minor/content/ButtonPaneContributions.vue +101 -114
  56. package/app/components/aside/minor/content/ButtonPaneImprove.vue +112 -120
  57. package/app/components/aside/minor/content/Contribution.vue +36 -36
  58. package/app/components/aside/minor/content/Toc.vue +163 -163
  59. package/app/components/aside/minor/content/TocItem.vue +91 -91
  60. package/app/components/aside/minor/content/TopicPartButton.vue +35 -35
  61. package/app/components/aside/minor/contributor/AsideMinorContributor.vue +36 -39
  62. package/app/components/aside/minor/contributor/ItemBook.vue +33 -39
  63. package/app/components/aside/minor/contributor/ItemContent.vue +17 -17
  64. package/app/components/aside/minor/news/AsideMinorNews.vue +132 -132
  65. package/app/components/aside/minor/news/NewsItem.vue +69 -69
  66. package/app/components/aside/minor/news/RenderNewsElement.vue +42 -42
  67. package/app/components/aside/minor/news/elements/Mix.vue +11 -11
  68. package/app/components/aside/minor/news/elements/P.vue +14 -14
  69. package/app/components/aside/minor/news/elements/Ref.vue +59 -58
  70. package/app/components/aside/minor/news/elements/Text.vue +18 -18
  71. package/app/components/indexPage/IndexPagePersons.vue +116 -117
  72. package/app/components/main/MainAction.vue +26 -20
  73. package/app/components/main/MainBreadcrumbs.vue +28 -28
  74. package/app/components/main/MainContentChild.vue +44 -47
  75. package/app/components/main/MainContentChildren.vue +13 -14
  76. package/app/components/main/MainDecoration.vue +15 -15
  77. package/app/components/main/MainDescription.vue +13 -13
  78. package/app/components/main/MainFlag.vue +129 -133
  79. package/app/components/main/MainFlags.vue +17 -17
  80. package/app/components/main/MainGlow.vue +12 -12
  81. package/app/components/main/MainQuickLink.vue +90 -91
  82. package/app/components/main/MainQuickLinks.vue +40 -40
  83. package/app/components/main/MainQuote.vue +149 -159
  84. package/app/components/main/MainQuoteLoader.vue +86 -86
  85. package/app/components/main/MainSection.vue +44 -44
  86. package/app/components/main/MainSectionPreamble.vue +5 -5
  87. package/app/components/main/MainSubTitle.vue +11 -12
  88. package/app/components/main/MainTitle.vue +32 -32
  89. package/app/components/main/MainTopicPartPage.vue +88 -88
  90. package/app/components/main/MainTopicPartSwitch.vue +67 -71
  91. package/app/components/main/connections/Deps.vue +30 -34
  92. package/app/components/main/connections/Externals.vue +80 -104
  93. package/app/components/main/connections/MainConnections.vue +90 -94
  94. package/app/components/main/connections/MainConnectionsButton.vue +81 -81
  95. package/app/components/main/connections/ScrollPane.vue +10 -10
  96. package/app/components/main/contentStats/Item.vue +28 -34
  97. package/app/components/main/contentStats/ItemElement.vue +19 -19
  98. package/app/components/main/contentStats/ItemMaterials.vue +11 -11
  99. package/app/components/main/contentStats/MainContentStats.vue +50 -53
  100. package/app/components/preview/Preview.vue +110 -121
  101. package/app/components/preview/PreviewError.vue +4 -4
  102. package/app/components/preview/PreviewLoading.vue +3 -3
  103. package/app/components/preview/PreviewScreen.vue +48 -48
  104. package/app/components/preview/PreviewScreenButton.vue +27 -27
  105. package/app/components/preview/screen/ContentPage.vue +27 -30
  106. package/app/components/preview/screen/DirectLink.vue +13 -13
  107. package/app/components/preview/screen/Unique.vue +31 -32
  108. package/app/components/site/SiteAside.vue +50 -51
  109. package/app/components/site/SiteAsideOverlay.vue +8 -8
  110. package/app/components/site/SiteMain.vue +11 -11
  111. package/app/components/transition/Fade.vue +16 -16
  112. package/app/components/transition/Slide.vue +27 -27
  113. package/app/components/tree/TreeContainer.vue +3 -3
  114. package/app/components/tree/TreeItem.vue +27 -31
  115. package/app/composables/ads.ts +11 -11
  116. package/app/composables/analytics.ts +102 -102
  117. package/app/composables/appElements.ts +21 -21
  118. package/app/composables/aside.ts +15 -15
  119. package/app/composables/asideMajorPane.ts +82 -82
  120. package/app/composables/asideMinor.ts +109 -109
  121. package/app/composables/contentNav.ts +7 -7
  122. package/app/composables/favicon.ts +103 -108
  123. package/app/composables/file.ts +4 -3
  124. package/app/composables/formatText.ts +100 -100
  125. package/app/composables/loading.ts +26 -2
  126. package/app/composables/mainContent.ts +22 -22
  127. package/app/composables/og.ts +184 -182
  128. package/app/composables/phrases.ts +98 -98
  129. package/app/composables/preview.ts +44 -44
  130. package/app/composables/route.ts +4 -2
  131. package/app/composables/theme.ts +47 -51
  132. package/app/composables/url.ts +19 -11
  133. package/app/formatters/ru.ts +14 -14
  134. package/app/pages/article/[...articleId].vue +12 -12
  135. package/app/pages/book/[...bookId].vue +56 -56
  136. package/app/pages/contributor/[contributorId].vue +144 -150
  137. package/app/pages/contributors.vue +95 -99
  138. package/app/pages/group/[...groupId].vue +58 -58
  139. package/app/pages/index.vue +113 -117
  140. package/app/pages/page/[...pageId].vue +60 -60
  141. package/app/pages/practice/[...practiceId].vue +12 -12
  142. package/app/pages/sponsors.vue +88 -91
  143. package/app/pages/summary/[...summaryId].vue +12 -12
  144. package/app/plugins/appSetup/client/htmlBranding.ts +6 -6
  145. package/app/plugins/appSetup/client/welcome.ts +37 -35
  146. package/app/plugins/appSetup/config.ts +6 -6
  147. package/app/plugins/appSetup/global.ts +3 -3
  148. package/app/plugins/appSetup/index.ts +27 -28
  149. package/app/plugins/prerender.server.ts +40 -40
  150. package/app/router.options.ts +5 -5
  151. package/app/scripts/theme.js +21 -24
  152. package/app/styles/main.css +128 -124
  153. package/bin/erudit.js +12 -0
  154. package/modules/erudit/env.ts +8 -0
  155. package/modules/erudit/globals/content.ts +4 -4
  156. package/modules/erudit/globals/contributor.ts +1 -1
  157. package/modules/erudit/globals/eruditConfig.ts +5 -10
  158. package/modules/erudit/globals/problem.ts +1 -1
  159. package/modules/erudit/globals/prose.ts +1 -1
  160. package/modules/erudit/globals/public.ts +18 -18
  161. package/modules/erudit/index.ts +50 -60
  162. package/modules/erudit/logger.ts +10 -10
  163. package/modules/erudit/setup/elements/appTemplate.ts +44 -45
  164. package/modules/erudit/setup/elements/globalTemplate.ts +82 -82
  165. package/modules/erudit/setup/elements/globalTypes.ts +259 -273
  166. package/modules/erudit/setup/elements/setup.ts +163 -167
  167. package/modules/erudit/setup/elements/shared.ts +10 -10
  168. package/modules/erudit/setup/elements/tagsTable.ts +28 -28
  169. package/modules/erudit/setup/fullRestart.ts +61 -71
  170. package/modules/erudit/setup/globals.ts +206 -196
  171. package/modules/erudit/setup/publicAssets.ts +43 -52
  172. package/modules/erudit/setup/runtimeConfig.ts +106 -58
  173. package/modules/erudit/watcher.ts +20 -27
  174. package/nuxt.config.ts +102 -84
  175. package/package.json +51 -55
  176. package/server/api/aside/major/frontNav/book/[...shortId].ts +10 -10
  177. package/server/api/aside/major/frontNav/global.ts +5 -5
  178. package/server/api/aside/major/pages.ts +6 -6
  179. package/server/api/contributor/list.ts +60 -61
  180. package/server/api/contributor/page/[contributorId].ts +68 -68
  181. package/server/api/indexPage.ts +81 -81
  182. package/server/api/language/functions.ts +11 -11
  183. package/server/api/language/phrase/[phraseKey].ts +35 -35
  184. package/server/api/main/content/[...contentTypePath].ts +149 -153
  185. package/server/api/news/batch/[batchIndex].ts +5 -5
  186. package/server/api/pageSponsors.ts +56 -58
  187. package/server/api/prerender/content.ts +79 -82
  188. package/server/api/prerender/default.ts +35 -35
  189. package/server/api/prerender/files.ts +10 -10
  190. package/server/api/prerender/frontNav.ts +13 -13
  191. package/server/api/prerender/language.ts +7 -7
  192. package/server/api/prerender/news.ts +8 -8
  193. package/server/api/prerender/quotes.ts +15 -15
  194. package/server/api/preview/contentPage/[...contentTypePath].ts +63 -63
  195. package/server/api/preview/contentUnique/[...contentTypePathUnique].ts +73 -81
  196. package/server/api/problemScript/[...problemScriptPath].ts +88 -92
  197. package/server/api/quote/data/[quoteId].ts +84 -87
  198. package/server/api/quote/ids.ts +3 -3
  199. package/server/erudit/build.ts +132 -137
  200. package/server/erudit/cameos/build.ts +161 -161
  201. package/server/erudit/config.ts +13 -13
  202. package/server/erudit/content/global/build.ts +300 -297
  203. package/server/erudit/content/global/singleton.ts +5 -5
  204. package/server/erudit/content/nav/build.ts +459 -463
  205. package/server/erudit/content/nav/front.ts +125 -127
  206. package/server/erudit/content/nav/repository/books.ts +37 -40
  207. package/server/erudit/content/nav/repository/get.ts +33 -33
  208. package/server/erudit/content/nav/repository/hasChildren.ts +5 -5
  209. package/server/erudit/content/nav/repository/hasNav.ts +3 -3
  210. package/server/erudit/content/nav/repository/hasParent.ts +5 -5
  211. package/server/erudit/content/nav/repository/id.ts +9 -9
  212. package/server/erudit/content/nav/repository/index.ts +9 -9
  213. package/server/erudit/content/nav/repository/order.ts +14 -14
  214. package/server/erudit/content/nav/repository/previousNext.ts +35 -35
  215. package/server/erudit/content/nav/repository/walk.ts +127 -127
  216. package/server/erudit/content/nav/setup.ts +13 -13
  217. package/server/erudit/content/nav/types.ts +24 -24
  218. package/server/erudit/content/repository/breadcrumbs.ts +24 -24
  219. package/server/erudit/content/repository/children.ts +47 -47
  220. package/server/erudit/content/repository/connections.ts +35 -35
  221. package/server/erudit/content/repository/contentLink.ts +16 -16
  222. package/server/erudit/content/repository/decoration.ts +23 -23
  223. package/server/erudit/content/repository/deps.ts +121 -84
  224. package/server/erudit/content/repository/description.ts +11 -11
  225. package/server/erudit/content/repository/elementSnippets.ts +105 -105
  226. package/server/erudit/content/repository/externals.ts +50 -50
  227. package/server/erudit/content/repository/flags.ts +33 -33
  228. package/server/erudit/content/repository/seo.ts +12 -12
  229. package/server/erudit/content/repository/stats.ts +97 -97
  230. package/server/erudit/content/repository/title.ts +27 -27
  231. package/server/erudit/content/repository/topicParts.ts +39 -39
  232. package/server/erudit/content/repository/unique.ts +76 -76
  233. package/server/erudit/content/resolve/book.ts +29 -32
  234. package/server/erudit/content/resolve/group.ts +34 -39
  235. package/server/erudit/content/resolve/index.ts +272 -290
  236. package/server/erudit/content/resolve/page.ts +80 -87
  237. package/server/erudit/content/resolve/topic.ts +220 -246
  238. package/server/erudit/content/resolve/utils/contentError.ts +10 -10
  239. package/server/erudit/content/resolve/utils/insertContentItem.ts +113 -122
  240. package/server/erudit/content/resolve/utils/insertContentResolved.ts +126 -132
  241. package/server/erudit/content/search.ts +146 -163
  242. package/server/erudit/contributors/build.ts +158 -166
  243. package/server/erudit/contributors/global.ts +3 -3
  244. package/server/erudit/contributors/repository/avatarUrl.ts +10 -10
  245. package/server/erudit/contributors/repository/contributions.ts +171 -178
  246. package/server/erudit/contributors/repository/count.ts +3 -3
  247. package/server/erudit/contributors/search.ts +34 -34
  248. package/server/erudit/db/repository/pushFile.ts +23 -26
  249. package/server/erudit/db/repository/pushProblemScript.ts +19 -19
  250. package/server/erudit/db/repository/pushProseLink.ts +40 -40
  251. package/server/erudit/db/schema/cameos.ts +7 -7
  252. package/server/erudit/db/schema/content.ts +18 -18
  253. package/server/erudit/db/schema/contentContributions.ts +15 -15
  254. package/server/erudit/db/schema/contentDeps.ts +21 -21
  255. package/server/erudit/db/schema/contentElementStats.ts +20 -20
  256. package/server/erudit/db/schema/contentProseLinks.ts +23 -23
  257. package/server/erudit/db/schema/contentSnippets.ts +15 -15
  258. package/server/erudit/db/schema/contentToc.ts +16 -16
  259. package/server/erudit/db/schema/contentUniques.ts +19 -25
  260. package/server/erudit/db/schema/contributors.ts +12 -12
  261. package/server/erudit/db/schema/files.ts +11 -11
  262. package/server/erudit/db/schema/groups.ts +6 -6
  263. package/server/erudit/db/schema/index.ts +17 -17
  264. package/server/erudit/db/schema/news.ts +7 -7
  265. package/server/erudit/db/schema/pages.ts +7 -7
  266. package/server/erudit/db/schema/problemScripts.ts +14 -14
  267. package/server/erudit/db/schema/sponsors.ts +9 -9
  268. package/server/erudit/db/schema/topics.ts +9 -9
  269. package/server/erudit/db/setup.ts +62 -62
  270. package/server/erudit/db/types.ts +10 -10
  271. package/server/erudit/global.ts +38 -33
  272. package/server/erudit/importer.ts +94 -97
  273. package/server/erudit/index.ts +96 -90
  274. package/server/erudit/language/list/en.ts +116 -116
  275. package/server/erudit/language/list/ru.ts +120 -120
  276. package/server/erudit/language/list.ts +6 -6
  277. package/server/erudit/language/setup.ts +36 -36
  278. package/server/erudit/language/types.ts +16 -16
  279. package/server/erudit/logger.ts +73 -77
  280. package/server/erudit/news/build.ts +112 -114
  281. package/server/erudit/news/repository/batch.ts +61 -61
  282. package/server/erudit/path.ts +19 -0
  283. package/server/erudit/prose/repository/finalize.ts +68 -68
  284. package/server/erudit/prose/repository/get.ts +54 -54
  285. package/server/erudit/prose/repository/resolve.ts +17 -17
  286. package/server/erudit/prose/storage/callout.ts +16 -14
  287. package/server/erudit/prose/storage/image.ts +22 -20
  288. package/server/erudit/prose/storage/link.ts +222 -226
  289. package/server/erudit/prose/storage/problemScript.ts +23 -21
  290. package/server/erudit/prose/storage/video.ts +16 -14
  291. package/server/erudit/prose/transform/bundleProblemScript.ts +6 -6
  292. package/server/erudit/prose/transform/extensions.ts +15 -15
  293. package/server/erudit/quote/repository/ids.ts +31 -31
  294. package/server/erudit/repository.ts +96 -96
  295. package/server/erudit/sponsors/build.ts +161 -165
  296. package/server/erudit/sponsors/repository/avatarUrl.ts +10 -10
  297. package/server/erudit/sponsors/repository/count.ts +4 -4
  298. package/server/erudit/staticFile.ts +28 -28
  299. package/server/plugins/augmentCss.ts +17 -17
  300. package/server/plugins/lang.ts +5 -7
  301. package/server/plugins/metaViewport.ts +15 -15
  302. package/server/plugins/theme.ts +13 -13
  303. package/server/routes/file/[...path].ts +18 -18
  304. package/server/routes/robots.txt.ts +9 -9
  305. package/server/routes/search.json.gz.ts +76 -73
  306. package/server/routes/sitemap.xml.ts +83 -81
  307. package/shared/search/encoders.ts +10 -10
  308. package/shared/types/asideMajorPages.ts +2 -2
  309. package/shared/types/breadcrumbs.ts +3 -3
  310. package/shared/types/contentChildren.ts +10 -10
  311. package/shared/types/contentConnections.ts +27 -27
  312. package/shared/types/contentStats.ts +6 -6
  313. package/shared/types/elementSnippet.ts +14 -14
  314. package/shared/types/frontContentNav.ts +17 -17
  315. package/shared/types/indexPage.ts +20 -20
  316. package/shared/types/language.ts +174 -174
  317. package/shared/types/mainContent.ts +40 -40
  318. package/shared/types/news.ts +13 -13
  319. package/shared/types/preview.ts +28 -28
  320. package/shared/types/runtimeConfig.ts +29 -47
  321. package/shared/types/search.ts +32 -32
  322. package/shared/utils/contentTypePath.ts +44 -44
  323. package/shared/utils/icons.ts +7 -7
  324. package/shared/utils/pages.ts +19 -20
  325. package/shared/utils/stringColor.ts +8 -8
  326. package/shared/utils/toStringEqual.ts +13 -13
  327. package/shared/utils/zip.ts +64 -64
  328. package/test/shared/utils/zip.test.ts +8 -8
  329. package/tsconfig.json +15 -15
  330. package/bin/erudit.mjs +0 -2
  331. package/modules/erudit/setup/aliases.ts +0 -17
  332. package/modules/erudit/setup/baseUrl.ts +0 -19
  333. package/modules/erudit/setup/nuxtConfig.ts +0 -62
  334. package/modules/erudit/setup/projectConfig.ts +0 -114
  335. package/shared/utils/slasher.ts +0 -64
  336. package/test/shared/utils/slasher.test.ts +0 -75
@@ -1,297 +1,300 @@
1
- import { readFileSync, writeFileSync } from 'node:fs';
2
- import { topicParts, type TopicPart } from '@erudit-js/core/content/topic';
3
- import { $CONTENT } from './singleton';
4
-
5
- // Call singleton to trigger initialization
6
- $CONTENT;
7
-
8
- let initialBuild = true;
9
-
10
- const contentRoot = () => `${ERUDIT.config.paths.project}/content`;
11
-
12
- export async function buildGlobalContent() {
13
- ERUDIT.log.debug.start('Building global content...');
14
-
15
- const isInitial = initialBuild;
16
- initialBuild = false;
17
-
18
- if (!isInitial && !hasContentChanges()) {
19
- ERUDIT.log.info('Skipping global content — nothing changed.');
20
- return;
21
- }
22
-
23
- const linkObject = await buildLinkObject();
24
-
25
- const linkTypes = linkObjectToTypes(linkObject);
26
- writeFileSync(
27
- ERUDIT.config.paths.build + '/types/content.d.ts',
28
- linkTypes,
29
- 'utf-8',
30
- );
31
-
32
- ERUDIT.log.success(
33
- isInitial
34
- ? 'Global content build complete!'
35
- : 'Global content updated!',
36
- );
37
- }
38
-
39
- function hasContentChanges() {
40
- for (const file of (ERUDIT.changedFiles || new Set<string>()).values()) {
41
- if (file.startsWith(`${contentRoot()}/`)) {
42
- return true;
43
- }
44
- }
45
-
46
- return false;
47
- }
48
-
49
- function linkObjectToTypes(linkObject: any): string {
50
- const indent = (level: number) => ' '.repeat(level);
51
-
52
- function toCamelCase(str: string): string {
53
- return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase());
54
- }
55
-
56
- function processObject(obj: any, level: number): string {
57
- const lines: string[] = [];
58
-
59
- for (const [key, value] of Object.entries(obj) as [string, any][]) {
60
- if (key === '__jsdoc' || key === '__typeguard') continue;
61
-
62
- const camelKey = toCamelCase(key);
63
-
64
- // Add JSDoc comment if present
65
- if (value && typeof value === 'object' && value.__jsdoc) {
66
- const jsdocLines = value.__jsdoc.split('\n');
67
- jsdocLines.forEach((line: string) => {
68
- lines.push(indent(level) + line);
69
- });
70
- }
71
-
72
- // Determine if value has nested properties (excluding __jsdoc and __typeguard)
73
- const hasNestedProps =
74
- value &&
75
- typeof value === 'object' &&
76
- Object.keys(value).some(
77
- (k) => k !== '__jsdoc' && k !== '__typeguard',
78
- );
79
-
80
- // Get the typeguard from the object, default to GlobalContentItemTypeguard
81
- const typeguard =
82
- value?.__typeguard || 'GlobalContentItemTypeguard';
83
-
84
- if (hasNestedProps) {
85
- lines.push(indent(level) + `${camelKey}: ${typeguard} & {`);
86
- lines.push(processObject(value, level + 1));
87
- lines.push(indent(level) + `}`);
88
- } else {
89
- lines.push(indent(level) + `${camelKey}: ${typeguard} & {}`);
90
- }
91
- }
92
-
93
- return lines.join('\n');
94
- }
95
-
96
- const body = processObject(linkObject, 2);
97
-
98
- return `import type {
99
- GlobalContentItemTypeguard,
100
- GlobalContentTopicPartTypeguard,
101
- GlobalContentUniqueTypeguard,
102
- } from '@erudit-js/core/content/global';
103
-
104
- export {};
105
-
106
- declare global {
107
- const $CONTENT: {
108
- ${body}
109
- }
110
- }`;
111
- }
112
-
113
- /**
114
- * Loop through the content navigation tree and build a nested object representing the link structure:
115
- */
116
- async function buildLinkObject() {
117
- const linkTree: any = {};
118
-
119
- await ERUDIT.contentNav.walk((navItem) => {
120
- // Navigate to the correct position in the tree based on the full path
121
- let cursor = linkTree;
122
- const pathParts = navItem.fullId.split('/');
123
-
124
- // Navigate through parent parts
125
- for (let i = 0; i < pathParts.length - 1; i++) {
126
- cursor = cursor[pathParts[i]];
127
- }
128
-
129
- //
130
- //
131
- //
132
-
133
- if (navItem.type === 'page') {
134
- const pathToFile = `${ERUDIT.config.paths.project}/content/${navItem.contentRelPath}/${navItem.type}.tsx`;
135
- const moduleContent = readFileSync(pathToFile, 'utf-8');
136
- const title = tryGetTitle(moduleContent);
137
-
138
- const jsdoc = jsdocLines([
139
- title ? `Title: ${title}` : undefined,
140
- `Type: ${navItem.type}`,
141
- `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
142
- ]);
143
-
144
- cursor[navItem.idPart] = {
145
- __typeguard: 'GlobalContentItemTypeguard',
146
- __jsdoc: `
147
- /**
148
- ${jsdoc}
149
- */
150
- `.trim(),
151
- ...tryGetUniquesObject(
152
- moduleContent,
153
- pathToFile,
154
- navItem.contentRelPath,
155
- ),
156
- };
157
- } else if (navItem.type === 'topic') {
158
- const pathToTopicFile = `${ERUDIT.config.paths.project}/content/${navItem.contentRelPath}/topic.ts`;
159
- const topicModuleContent = readFileSync(pathToTopicFile, 'utf-8');
160
- const title = tryGetTitle(topicModuleContent);
161
-
162
- const jsdoc = jsdocLines([
163
- title ? `Title: ${title}` : undefined,
164
- `Type: topic`,
165
- `Location: [${navItem.contentRelPath}](file:///${pathToTopicFile})`,
166
- ]);
167
-
168
- cursor[navItem.idPart] = {
169
- __typeguard: 'GlobalContentItemTypeguard',
170
- __jsdoc: `
171
- /**
172
- ${jsdoc}
173
- */
174
- `.trim(),
175
- };
176
-
177
- for (const part of topicParts) {
178
- try {
179
- const pathToFile = `${ERUDIT.config.paths.project}/content/${navItem.contentRelPath}/${part}.tsx`;
180
- const partContent = readFileSync(pathToFile, 'utf-8');
181
-
182
- const jsdoc = jsdocLines([
183
- title ? `Title: ${title}` : undefined,
184
- `Type: topic`,
185
- `Part: ${part}`,
186
- `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
187
- ]);
188
-
189
- cursor[navItem.idPart][part as TopicPart] = {
190
- __typeguard: 'GlobalContentTopicPartTypeguard',
191
- __jsdoc: `
192
- /**
193
- ${jsdoc}
194
- */
195
- `.trim(),
196
- ...tryGetUniquesObject(
197
- partContent,
198
- pathToFile,
199
- navItem.contentRelPath,
200
- ),
201
- };
202
- } catch {}
203
- }
204
- } else {
205
- const pathToFile = `${ERUDIT.config.paths.project}/content/${navItem.contentRelPath}/${navItem.type}.ts`;
206
- const moduleContent = readFileSync(pathToFile, 'utf-8');
207
- const title = tryGetTitle(moduleContent);
208
-
209
- const jsdoc = jsdocLines([
210
- title ? `Title: ${title}` : undefined,
211
- `Type: ${navItem.type}`,
212
- `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
213
- ]);
214
-
215
- cursor[navItem.idPart] = {
216
- __typeguard: 'GlobalContentItemTypeguard',
217
- __jsdoc: `
218
- /**
219
- ${jsdoc}
220
- */
221
- `.trim(),
222
- };
223
- }
224
- });
225
-
226
- return linkTree;
227
- }
228
-
229
- function tryGetTitle(moduleContent: string) {
230
- const titleMatch = moduleContent.match(/title:\s*['"`](.*?)['"`]/);
231
-
232
- if (titleMatch) {
233
- return titleMatch[1].trim();
234
- }
235
- }
236
-
237
- function jsdocLines(lines: any[]) {
238
- return lines
239
- .filter(Boolean)
240
- .map((line) => ` * * ${line}`)
241
- .join('\n');
242
- }
243
-
244
- function tryGetUniquesObject(
245
- moduleContent: string,
246
- pathToFile: string,
247
- pathInContent: string,
248
- ) {
249
- // Match uniques: { ... } object (single or multiline)
250
- const uniquesMatch = moduleContent.match(/uniques:\s*\{([^}]*)\}/s);
251
-
252
- if (!uniquesMatch) {
253
- return {};
254
- }
255
-
256
- const uniquesContent = uniquesMatch[1];
257
-
258
- // Parse key-value pairs from uniques object
259
- const lines = uniquesContent.split('\n');
260
- const result: any = {};
261
-
262
- for (const line of lines) {
263
- // Skip commented out lines
264
- if (line.trim().startsWith('//')) {
265
- continue;
266
- }
267
-
268
- // Skip uniques starting with underscore
269
- if (line.trim().startsWith('_')) {
270
- continue;
271
- }
272
-
273
- const pairMatch = line.match(/(\w+):\s*(\w+)/);
274
- if (!pairMatch) {
275
- continue;
276
- }
277
-
278
- const [, uniqueName, tagName] = pairMatch;
279
-
280
- const jsdoc = jsdocLines([
281
- 'Unique',
282
- `Tag: \`<${tagName}>\``,
283
- `Location: [${pathInContent}](file:///${pathToFile})`,
284
- ]);
285
-
286
- result[`$${uniqueName}`] = {
287
- __typeguard: 'GlobalContentUniqueTypeguard',
288
- __jsdoc: `
289
- /**
290
- ${jsdoc}
291
- */
292
- `.trim(),
293
- };
294
- }
295
-
296
- return result;
297
- }
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { topicParts, type TopicPart } from '@erudit-js/core/content/topic';
3
+ import { $CONTENT } from './singleton';
4
+
5
+ // Call singleton to trigger initialization
6
+ $CONTENT;
7
+
8
+ let initialBuild = true;
9
+
10
+ const contentRoot = () => ERUDIT.paths.project('content');
11
+
12
+ export async function buildGlobalContent() {
13
+ ERUDIT.log.debug.start('Building global content...');
14
+
15
+ const isInitial = initialBuild;
16
+ initialBuild = false;
17
+
18
+ if (!isInitial && !hasContentChanges()) {
19
+ ERUDIT.log.info('Skipping global content — nothing changed.');
20
+ return;
21
+ }
22
+
23
+ const linkObject = await buildLinkObject();
24
+
25
+ const linkTypes = linkObjectToTypes(linkObject);
26
+ writeFileSync(
27
+ ERUDIT.paths.project('.erudit/types/content.d.ts'),
28
+ linkTypes,
29
+ 'utf-8',
30
+ );
31
+
32
+ ERUDIT.log.success(
33
+ isInitial ? 'Global content build complete!' : 'Global content updated!',
34
+ );
35
+ }
36
+
37
+ function hasContentChanges() {
38
+ for (const file of (ERUDIT.changedFiles || new Set<string>()).values()) {
39
+ if (file.startsWith(`${contentRoot()}/`)) {
40
+ return true;
41
+ }
42
+ }
43
+
44
+ return false;
45
+ }
46
+
47
+ function linkObjectToTypes(linkObject: any): string {
48
+ const indent = (level: number) => ' '.repeat(level);
49
+
50
+ function toCamelCase(str: string): string {
51
+ return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase());
52
+ }
53
+
54
+ function processObject(obj: any, level: number): string {
55
+ const lines: string[] = [];
56
+
57
+ for (const [key, value] of Object.entries(obj) as [string, any][]) {
58
+ if (key === '__jsdoc' || key === '__typeguard') continue;
59
+
60
+ const camelKey = toCamelCase(key);
61
+
62
+ // Add JSDoc comment if present
63
+ if (value && typeof value === 'object' && value.__jsdoc) {
64
+ const jsdocLines = value.__jsdoc.split('\n');
65
+ jsdocLines.forEach((line: string) => {
66
+ lines.push(indent(level) + line);
67
+ });
68
+ }
69
+
70
+ // Determine if value has nested properties (excluding __jsdoc and __typeguard)
71
+ const hasNestedProps =
72
+ value &&
73
+ typeof value === 'object' &&
74
+ Object.keys(value).some((k) => k !== '__jsdoc' && k !== '__typeguard');
75
+
76
+ // Get the typeguard from the object, default to GlobalContentItemTypeguard
77
+ const typeguard = value?.__typeguard || 'GlobalContentItemTypeguard';
78
+
79
+ if (hasNestedProps) {
80
+ lines.push(indent(level) + `${camelKey}: ${typeguard} & {`);
81
+ lines.push(processObject(value, level + 1));
82
+ lines.push(indent(level) + `}`);
83
+ } else {
84
+ lines.push(indent(level) + `${camelKey}: ${typeguard} & {}`);
85
+ }
86
+ }
87
+
88
+ return lines.join('\n');
89
+ }
90
+
91
+ const body = processObject(linkObject, 2);
92
+
93
+ return `import type {
94
+ GlobalContentItemTypeguard,
95
+ GlobalContentTopicPartTypeguard,
96
+ GlobalContentUniqueTypeguard,
97
+ } from '@erudit-js/core/content/global';
98
+
99
+ export {};
100
+
101
+ declare global {
102
+ const $CONTENT: {
103
+ ${body}
104
+ }
105
+ }`;
106
+ }
107
+
108
+ /**
109
+ * Loop through the content navigation tree and build a nested object representing the link structure:
110
+ */
111
+ async function buildLinkObject() {
112
+ const linkTree: any = {};
113
+
114
+ await ERUDIT.contentNav.walk((navItem) => {
115
+ // Navigate to the correct position in the tree based on the full path
116
+ let cursor = linkTree;
117
+ const pathParts = navItem.fullId.split('/');
118
+
119
+ // Navigate through parent parts
120
+ for (let i = 0; i < pathParts.length - 1; i++) {
121
+ cursor = cursor[pathParts[i]];
122
+ }
123
+
124
+ //
125
+ //
126
+ //
127
+
128
+ if (navItem.type === 'page') {
129
+ const pathToFile = ERUDIT.paths.project(
130
+ `content/${navItem.contentRelPath}/${navItem.type}.tsx`,
131
+ );
132
+ const moduleContent = readFileSync(pathToFile, 'utf-8');
133
+ const title = tryGetTitle(moduleContent);
134
+
135
+ const jsdoc = jsdocLines([
136
+ title ? `Title: ${title}` : undefined,
137
+ `Type: ${navItem.type}`,
138
+ `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
139
+ ]);
140
+
141
+ cursor[navItem.idPart] = {
142
+ __typeguard: 'GlobalContentItemTypeguard',
143
+ __jsdoc: `
144
+ /**
145
+ ${jsdoc}
146
+ */
147
+ `.trim(),
148
+ ...tryGetUniquesObject(
149
+ moduleContent,
150
+ pathToFile,
151
+ navItem.contentRelPath,
152
+ ),
153
+ };
154
+ } else if (navItem.type === 'topic') {
155
+ const pathToTopicFile = ERUDIT.paths.project(
156
+ `content/${navItem.contentRelPath}/topic.ts`,
157
+ );
158
+ const topicModuleContent = readFileSync(pathToTopicFile, 'utf-8');
159
+ const title = tryGetTitle(topicModuleContent);
160
+
161
+ const jsdoc = jsdocLines([
162
+ title ? `Title: ${title}` : undefined,
163
+ `Type: topic`,
164
+ `Location: [${navItem.contentRelPath}](file:///${pathToTopicFile})`,
165
+ ]);
166
+
167
+ cursor[navItem.idPart] = {
168
+ __typeguard: 'GlobalContentItemTypeguard',
169
+ __jsdoc: `
170
+ /**
171
+ ${jsdoc}
172
+ */
173
+ `.trim(),
174
+ };
175
+
176
+ for (const part of topicParts) {
177
+ try {
178
+ const pathToFile = ERUDIT.paths.project(
179
+ `content/${navItem.contentRelPath}/${part}.tsx`,
180
+ );
181
+ const partContent = readFileSync(pathToFile, 'utf-8');
182
+
183
+ const jsdoc = jsdocLines([
184
+ title ? `Title: ${title}` : undefined,
185
+ `Type: topic`,
186
+ `Part: ${part}`,
187
+ `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
188
+ ]);
189
+
190
+ cursor[navItem.idPart][part as TopicPart] = {
191
+ __typeguard: 'GlobalContentTopicPartTypeguard',
192
+ __jsdoc: `
193
+ /**
194
+ ${jsdoc}
195
+ */
196
+ `.trim(),
197
+ ...tryGetUniquesObject(
198
+ partContent,
199
+ pathToFile,
200
+ navItem.contentRelPath,
201
+ ),
202
+ };
203
+ } catch {}
204
+ }
205
+ } else {
206
+ const pathToFile = ERUDIT.paths.project(
207
+ `content/${navItem.contentRelPath}/${navItem.type}.ts`,
208
+ );
209
+ const moduleContent = readFileSync(pathToFile, 'utf-8');
210
+ const title = tryGetTitle(moduleContent);
211
+
212
+ const jsdoc = jsdocLines([
213
+ title ? `Title: ${title}` : undefined,
214
+ `Type: ${navItem.type}`,
215
+ `Location: [${navItem.contentRelPath}](file:///${pathToFile})`,
216
+ ]);
217
+
218
+ cursor[navItem.idPart] = {
219
+ __typeguard: 'GlobalContentItemTypeguard',
220
+ __jsdoc: `
221
+ /**
222
+ ${jsdoc}
223
+ */
224
+ `.trim(),
225
+ };
226
+ }
227
+ });
228
+
229
+ return linkTree;
230
+ }
231
+
232
+ function tryGetTitle(moduleContent: string) {
233
+ const titleMatch = moduleContent.match(/title:\s*['"`](.*?)['"`]/);
234
+
235
+ if (titleMatch) {
236
+ return titleMatch[1].trim();
237
+ }
238
+ }
239
+
240
+ function jsdocLines(lines: any[]) {
241
+ return lines
242
+ .filter(Boolean)
243
+ .map((line) => ` * * ${line}`)
244
+ .join('\n');
245
+ }
246
+
247
+ function tryGetUniquesObject(
248
+ moduleContent: string,
249
+ pathToFile: string,
250
+ pathInContent: string,
251
+ ) {
252
+ // Match uniques: { ... } object (single or multiline)
253
+ const uniquesMatch = moduleContent.match(/uniques:\s*\{([^}]*)\}/s);
254
+
255
+ if (!uniquesMatch) {
256
+ return {};
257
+ }
258
+
259
+ const uniquesContent = uniquesMatch[1];
260
+
261
+ // Parse key-value pairs from uniques object
262
+ const lines = uniquesContent.split('\n');
263
+ const result: any = {};
264
+
265
+ for (const line of lines) {
266
+ // Skip commented out lines
267
+ if (line.trim().startsWith('//')) {
268
+ continue;
269
+ }
270
+
271
+ // Skip uniques starting with underscore
272
+ if (line.trim().startsWith('_')) {
273
+ continue;
274
+ }
275
+
276
+ const pairMatch = line.match(/(\w+):\s*(\w+)/);
277
+ if (!pairMatch) {
278
+ continue;
279
+ }
280
+
281
+ const [, uniqueName, tagName] = pairMatch;
282
+
283
+ const jsdoc = jsdocLines([
284
+ 'Unique',
285
+ `Tag: \`<${tagName}>\``,
286
+ `Location: [${pathInContent}](file:///${pathToFile})`,
287
+ ]);
288
+
289
+ result[`$${uniqueName}`] = {
290
+ __typeguard: 'GlobalContentUniqueTypeguard',
291
+ __jsdoc: `
292
+ /**
293
+ ${jsdoc}
294
+ */
295
+ `.trim(),
296
+ };
297
+ }
298
+
299
+ return result;
300
+ }
@@ -1,5 +1,5 @@
1
- import { createGlobalContentProxy } from '@erudit-js/core/content/global';
2
-
3
- export const $CONTENT = createGlobalContentProxy();
4
-
5
- (globalThis as any).$CONTENT = $CONTENT;
1
+ import { createGlobalContentProxy } from '@erudit-js/core/content/global';
2
+
3
+ export const $CONTENT = createGlobalContentProxy();
4
+
5
+ (globalThis as any).$CONTENT = $CONTENT;