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,84 +1,121 @@
1
- import { eq, like, or } from 'drizzle-orm';
2
-
3
- export async function getContentDependencies(fullId: string): Promise<{
4
- hardDependencies: ContentHardDep[];
5
- autoDependencies: ContentAutoDep[];
6
- }> {
7
- const hardDependencies: ContentHardDep[] = [];
8
- const autoDependencies: ContentAutoDep[] = [];
9
-
10
- const dbContents = await ERUDIT.db.query.contentDeps.findMany({
11
- columns: { fromFullId: true, toFullId: true, hard: true, reason: true },
12
- where: or(
13
- eq(ERUDIT.db.schema.contentDeps.toFullId, fullId),
14
- like(ERUDIT.db.schema.contentDeps.toFullId, `${fullId}/%`),
15
- ),
16
- });
17
-
18
- for (const dbContent of dbContents) {
19
- // Skip child-only self-references
20
- const isToChild = dbContent.toFullId.startsWith(`${fullId}/`);
21
- const isFromChild = dbContent.fromFullId.startsWith(`${fullId}/`);
22
- if (isToChild && isFromChild) {
23
- continue;
24
- }
25
-
26
- const dep = await getContentAutoDep(dbContent.fromFullId);
27
-
28
- if (dbContent.hard && fullId === dbContent.toFullId) {
29
- hardDependencies.push({
30
- ...dep,
31
- type: 'hard',
32
- reason: dbContent.reason!,
33
- });
34
- } else {
35
- autoDependencies.push(dep);
36
- }
37
- }
38
-
39
- return { hardDependencies, autoDependencies };
40
- }
41
-
42
- export async function getContentDependents(
43
- fullId: string,
44
- ): Promise<ContentAutoDep[]> {
45
- const dependents: ContentAutoDep[] = [];
46
-
47
- const dbContents = await ERUDIT.db.query.contentDeps.findMany({
48
- columns: { fromFullId: true, toFullId: true },
49
- where: or(
50
- eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
51
- like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
52
- ),
53
- });
54
-
55
- for (const dbContent of dbContents) {
56
- // Skip child-only self-references
57
- const isFromChild = dbContent.fromFullId.startsWith(`${fullId}/`);
58
- const isToChild = dbContent.toFullId.startsWith(`${fullId}/`);
59
- if (isFromChild && isToChild) {
60
- continue;
61
- }
62
-
63
- const dep = await getContentAutoDep(dbContent.toFullId);
64
- dependents.push(dep);
65
- }
66
-
67
- return dependents;
68
- }
69
-
70
- export async function getContentAutoDep(
71
- fullId: string,
72
- ): Promise<ContentAutoDep> {
73
- const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
74
- const contentType = navNode.type;
75
- const title = await ERUDIT.repository.content.title(fullId);
76
- const link = await ERUDIT.repository.content.link(fullId);
77
-
78
- return {
79
- type: 'auto',
80
- contentType,
81
- title,
82
- link,
83
- };
84
- }
1
+ import { eq, like, or } from 'drizzle-orm';
2
+
3
+ type ContentAutoDepCache = Map<string, Promise<ContentAutoDep>>;
4
+
5
+ async function buildContentAutoDep(fullId: string): Promise<ContentAutoDep> {
6
+ const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
7
+ const contentType = navNode.type;
8
+ const [title, link] = await Promise.all([
9
+ ERUDIT.repository.content.title(fullId),
10
+ ERUDIT.repository.content.link(fullId),
11
+ ]);
12
+
13
+ return {
14
+ type: 'auto',
15
+ contentType,
16
+ title,
17
+ link,
18
+ };
19
+ }
20
+
21
+ function getContentAutoDepCached(
22
+ fullId: string,
23
+ cache: ContentAutoDepCache,
24
+ ): Promise<ContentAutoDep> {
25
+ const existing = cache.get(fullId);
26
+ if (existing) {
27
+ return existing;
28
+ }
29
+
30
+ const created = buildContentAutoDep(fullId);
31
+ cache.set(fullId, created);
32
+ return created;
33
+ }
34
+
35
+ export async function getContentDependencies(fullId: string): Promise<{
36
+ hardDependencies: ContentHardDep[];
37
+ autoDependencies: ContentAutoDep[];
38
+ }> {
39
+ const hardDependencies: ContentHardDep[] = [];
40
+ const autoDependencies: ContentAutoDep[] = [];
41
+ const cache: ContentAutoDepCache = new Map();
42
+
43
+ const dbContents = await ERUDIT.db.query.contentDeps.findMany({
44
+ columns: { fromFullId: true, toFullId: true, hard: true, reason: true },
45
+ where: or(
46
+ eq(ERUDIT.db.schema.contentDeps.toFullId, fullId),
47
+ like(ERUDIT.db.schema.contentDeps.toFullId, `${fullId}/%`),
48
+ ),
49
+ });
50
+
51
+ const filtered = dbContents.filter((dbContent) => {
52
+ // Skip child-only self-references
53
+ const isToChild = dbContent.toFullId.startsWith(`${fullId}/`);
54
+ const isFromChild = dbContent.fromFullId.startsWith(`${fullId}/`);
55
+ return !(isToChild && isFromChild);
56
+ });
57
+
58
+ // Precompute to ensure hard deps always take precedence, regardless of DB row ordering.
59
+ const hardDepFromIds = new Set(
60
+ filtered
61
+ .filter((dbContent) => dbContent.hard && fullId === dbContent.toFullId)
62
+ .map((dbContent) => dbContent.fromFullId),
63
+ );
64
+
65
+ const deps = await Promise.all(
66
+ filtered.map((dbContent) =>
67
+ getContentAutoDepCached(dbContent.fromFullId, cache),
68
+ ),
69
+ );
70
+
71
+ for (const [i, dbContent] of filtered.entries()) {
72
+ const dep = deps[i]!;
73
+
74
+ if (dbContent.hard && fullId === dbContent.toFullId) {
75
+ hardDependencies.push({
76
+ ...dep,
77
+ type: 'hard',
78
+ reason: dbContent.reason!,
79
+ });
80
+ } else if (!hardDepFromIds.has(dbContent.fromFullId)) {
81
+ autoDependencies.push(dep);
82
+ }
83
+ }
84
+
85
+ return { hardDependencies, autoDependencies };
86
+ }
87
+
88
+ export async function getContentDependents(
89
+ fullId: string,
90
+ ): Promise<ContentAutoDep[]> {
91
+ const cache: ContentAutoDepCache = new Map();
92
+
93
+ const dbContents = await ERUDIT.db.query.contentDeps.findMany({
94
+ columns: { fromFullId: true, toFullId: true },
95
+ where: or(
96
+ eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
97
+ like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
98
+ ),
99
+ });
100
+
101
+ const filtered = dbContents.filter((dbContent) => {
102
+ // Skip child-only self-references
103
+ const isFromChild = dbContent.fromFullId.startsWith(`${fullId}/`);
104
+ const isToChild = dbContent.toFullId.startsWith(`${fullId}/`);
105
+ return !(isFromChild && isToChild);
106
+ });
107
+
108
+ const deps = await Promise.all(
109
+ filtered.map((dbContent) =>
110
+ getContentAutoDepCached(dbContent.toFullId, cache),
111
+ ),
112
+ );
113
+
114
+ return deps;
115
+ }
116
+
117
+ export async function getContentAutoDep(
118
+ fullId: string,
119
+ ): Promise<ContentAutoDep> {
120
+ return buildContentAutoDep(fullId);
121
+ }
@@ -1,11 +1,11 @@
1
- import { eq } from 'drizzle-orm';
2
-
3
- export async function getContentDescription(
4
- fullContentId: string,
5
- ): Promise<string | undefined> {
6
- const dbContentItem = (await ERUDIT.db.query.content.findFirst({
7
- where: eq(ERUDIT.db.schema.content.fullId, fullContentId),
8
- }))!;
9
-
10
- return dbContentItem.description || undefined;
11
- }
1
+ import { eq } from 'drizzle-orm';
2
+
3
+ export async function getContentDescription(
4
+ fullContentId: string,
5
+ ): Promise<string | undefined> {
6
+ const dbContentItem = (await ERUDIT.db.query.content.findFirst({
7
+ where: eq(ERUDIT.db.schema.content.fullId, fullContentId),
8
+ }))!;
9
+
10
+ return dbContentItem.description || undefined;
11
+ }
@@ -1,105 +1,105 @@
1
- import { and, asc, eq, or } from 'drizzle-orm';
2
-
3
- export async function getContentElementSnippets(
4
- fullId: string,
5
- ): Promise<ElementSnippet[] | undefined> {
6
- const snippets: ElementSnippet[] = [];
7
-
8
- const dbSnippets = await ERUDIT.db.query.contentSnippets.findMany({
9
- columns: {
10
- contentProseType: true,
11
- schemaName: true,
12
- elementId: true,
13
- snippetData: true,
14
- },
15
- where: and(
16
- eq(ERUDIT.db.schema.contentSnippets.contentFullId, fullId),
17
- or(
18
- eq(ERUDIT.db.schema.contentSnippets.quick, true),
19
- eq(ERUDIT.db.schema.contentSnippets.seo, true),
20
- ),
21
- ),
22
- orderBy: (snippets) => asc(snippets.snippetId),
23
- });
24
-
25
- const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
26
-
27
- for (const dbSnippet of dbSnippets) {
28
- const link = (() => {
29
- if (dbSnippet.contentProseType === 'page') {
30
- return PAGES.page(navNode.shortId, dbSnippet.elementId);
31
- }
32
-
33
- return PAGES.topic(
34
- dbSnippet.contentProseType,
35
- navNode.shortId,
36
- dbSnippet.elementId,
37
- );
38
- })();
39
-
40
- const snippetData = dbSnippet.snippetData;
41
-
42
- const snippet: ElementSnippet = {
43
- link,
44
- schemaName: dbSnippet.schemaName,
45
- title: snippetData.title!,
46
- };
47
-
48
- if (snippetData.quick) {
49
- snippet.quick = {};
50
- let quickTitle: string | undefined;
51
- let quickDescription: string | undefined;
52
-
53
- if (typeof snippetData.quick === 'string') {
54
- quickTitle = snippetData.quick;
55
- } else if (typeof snippetData.quick === 'object') {
56
- if (snippetData.quick.title) {
57
- quickTitle = snippetData.quick.title;
58
- }
59
- if (snippetData.quick.description) {
60
- quickDescription = snippetData.quick.description;
61
- }
62
- }
63
-
64
- if (quickTitle) {
65
- snippet.quick.title = quickTitle;
66
- }
67
- if (quickDescription) {
68
- snippet.quick.description = quickDescription;
69
- }
70
- }
71
-
72
- if (snippetData.seo) {
73
- snippet.seo = {};
74
-
75
- let seoTitle: string | undefined;
76
- let seoDescription: string | undefined;
77
-
78
- if (typeof snippetData.seo === 'string') {
79
- seoTitle = snippetData.seo;
80
- } else if (typeof snippetData.seo === 'object') {
81
- if (snippetData.seo.title) {
82
- seoTitle = snippetData.seo.title;
83
- }
84
- if (snippetData.seo.description) {
85
- seoDescription = snippetData.seo.description;
86
- }
87
- }
88
-
89
- if (seoTitle) {
90
- snippet.seo.title = seoTitle;
91
- }
92
- if (seoDescription) {
93
- snippet.seo.description = seoDescription;
94
- }
95
- }
96
-
97
- if (snippetData.description) {
98
- snippet.description = snippetData.description;
99
- }
100
-
101
- snippets.push(snippet);
102
- }
103
-
104
- return snippets.length > 0 ? snippets : undefined;
105
- }
1
+ import { and, asc, eq, or } from 'drizzle-orm';
2
+
3
+ export async function getContentElementSnippets(
4
+ fullId: string,
5
+ ): Promise<ElementSnippet[] | undefined> {
6
+ const snippets: ElementSnippet[] = [];
7
+
8
+ const dbSnippets = await ERUDIT.db.query.contentSnippets.findMany({
9
+ columns: {
10
+ contentProseType: true,
11
+ schemaName: true,
12
+ elementId: true,
13
+ snippetData: true,
14
+ },
15
+ where: and(
16
+ eq(ERUDIT.db.schema.contentSnippets.contentFullId, fullId),
17
+ or(
18
+ eq(ERUDIT.db.schema.contentSnippets.quick, true),
19
+ eq(ERUDIT.db.schema.contentSnippets.seo, true),
20
+ ),
21
+ ),
22
+ orderBy: (snippets) => asc(snippets.snippetId),
23
+ });
24
+
25
+ const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
26
+
27
+ for (const dbSnippet of dbSnippets) {
28
+ const link = (() => {
29
+ if (dbSnippet.contentProseType === 'page') {
30
+ return PAGES.page(navNode.shortId, dbSnippet.elementId);
31
+ }
32
+
33
+ return PAGES.topic(
34
+ dbSnippet.contentProseType,
35
+ navNode.shortId,
36
+ dbSnippet.elementId,
37
+ );
38
+ })();
39
+
40
+ const snippetData = dbSnippet.snippetData;
41
+
42
+ const snippet: ElementSnippet = {
43
+ link,
44
+ schemaName: dbSnippet.schemaName,
45
+ title: snippetData.title!,
46
+ };
47
+
48
+ if (snippetData.quick) {
49
+ snippet.quick = {};
50
+ let quickTitle: string | undefined;
51
+ let quickDescription: string | undefined;
52
+
53
+ if (typeof snippetData.quick === 'string') {
54
+ quickTitle = snippetData.quick;
55
+ } else if (typeof snippetData.quick === 'object') {
56
+ if (snippetData.quick.title) {
57
+ quickTitle = snippetData.quick.title;
58
+ }
59
+ if (snippetData.quick.description) {
60
+ quickDescription = snippetData.quick.description;
61
+ }
62
+ }
63
+
64
+ if (quickTitle) {
65
+ snippet.quick.title = quickTitle;
66
+ }
67
+ if (quickDescription) {
68
+ snippet.quick.description = quickDescription;
69
+ }
70
+ }
71
+
72
+ if (snippetData.seo) {
73
+ snippet.seo = {};
74
+
75
+ let seoTitle: string | undefined;
76
+ let seoDescription: string | undefined;
77
+
78
+ if (typeof snippetData.seo === 'string') {
79
+ seoTitle = snippetData.seo;
80
+ } else if (typeof snippetData.seo === 'object') {
81
+ if (snippetData.seo.title) {
82
+ seoTitle = snippetData.seo.title;
83
+ }
84
+ if (snippetData.seo.description) {
85
+ seoDescription = snippetData.seo.description;
86
+ }
87
+ }
88
+
89
+ if (seoTitle) {
90
+ snippet.seo.title = seoTitle;
91
+ }
92
+ if (seoDescription) {
93
+ snippet.seo.description = seoDescription;
94
+ }
95
+ }
96
+
97
+ if (snippetData.description) {
98
+ snippet.description = snippetData.description;
99
+ }
100
+
101
+ snippets.push(snippet);
102
+ }
103
+
104
+ return snippets.length > 0 ? snippets : undefined;
105
+ }
@@ -1,50 +1,50 @@
1
- import { eq, like } from 'drizzle-orm';
2
- import type { ContentExternals } from '@erudit-js/core/content/externals';
3
-
4
- export async function getContentExternals(
5
- fullId: string,
6
- ): Promise<ContentExternals> {
7
- const externals: ContentExternals = [];
8
-
9
- const dbOwnContentItem = await ERUDIT.db.query.content.findFirst({
10
- columns: { externals: true },
11
- where: eq(ERUDIT.db.schema.content.fullId, fullId),
12
- });
13
-
14
- if (dbOwnContentItem?.externals) {
15
- externals.push({
16
- type: 'own',
17
- items: dbOwnContentItem.externals,
18
- });
19
- }
20
- const parts = fullId.split('/');
21
- const dbParentContentItems = [];
22
-
23
- for (let i = parts.length - 1; i > 0; i--) {
24
- const parentId = parts.slice(0, i).join('/');
25
- const dbParentContentItem = await ERUDIT.db.query.content.findFirst({
26
- columns: {
27
- fullId: true,
28
- externals: true,
29
- title: true,
30
- },
31
- where: eq(ERUDIT.db.schema.content.fullId, parentId),
32
- });
33
-
34
- if (dbParentContentItem) {
35
- dbParentContentItems.push(dbParentContentItem);
36
- }
37
- }
38
-
39
- for (const dbParentContentItem of dbParentContentItems) {
40
- if (dbParentContentItem?.externals) {
41
- externals.push({
42
- type: 'parent',
43
- title: dbParentContentItem.title,
44
- items: dbParentContentItem.externals,
45
- });
46
- }
47
- }
48
-
49
- return externals;
50
- }
1
+ import { eq, like } from 'drizzle-orm';
2
+ import type { ContentExternals } from '@erudit-js/core/content/externals';
3
+
4
+ export async function getContentExternals(
5
+ fullId: string,
6
+ ): Promise<ContentExternals> {
7
+ const externals: ContentExternals = [];
8
+
9
+ const dbOwnContentItem = await ERUDIT.db.query.content.findFirst({
10
+ columns: { externals: true },
11
+ where: eq(ERUDIT.db.schema.content.fullId, fullId),
12
+ });
13
+
14
+ if (dbOwnContentItem?.externals) {
15
+ externals.push({
16
+ type: 'own',
17
+ items: dbOwnContentItem.externals,
18
+ });
19
+ }
20
+ const parts = fullId.split('/');
21
+ const dbParentContentItems = [];
22
+
23
+ for (let i = parts.length - 1; i > 0; i--) {
24
+ const parentId = parts.slice(0, i).join('/');
25
+ const dbParentContentItem = await ERUDIT.db.query.content.findFirst({
26
+ columns: {
27
+ fullId: true,
28
+ externals: true,
29
+ title: true,
30
+ },
31
+ where: eq(ERUDIT.db.schema.content.fullId, parentId),
32
+ });
33
+
34
+ if (dbParentContentItem) {
35
+ dbParentContentItems.push(dbParentContentItem);
36
+ }
37
+ }
38
+
39
+ for (const dbParentContentItem of dbParentContentItems) {
40
+ if (dbParentContentItem?.externals) {
41
+ externals.push({
42
+ type: 'parent',
43
+ title: dbParentContentItem.title,
44
+ items: dbParentContentItem.externals,
45
+ });
46
+ }
47
+ }
48
+
49
+ return externals;
50
+ }
@@ -1,33 +1,33 @@
1
- import { eq } from 'drizzle-orm';
2
- import type { ContentFlags } from '@erudit-js/core/content/flags';
3
-
4
- export async function getContentFlags(
5
- fullId: string,
6
- ): Promise<ContentFlags | undefined> {
7
- const flags: ContentFlags = {};
8
-
9
- const parts = fullId.split('/');
10
- for (let i = 1; i <= parts.length; i++) {
11
- const trimmedId = parts.slice(0, i).join('/');
12
-
13
- const dbContent = await ERUDIT.db.query.content.findFirst({
14
- columns: { flags: true },
15
- where: eq(ERUDIT.db.schema.content.fullId, trimmedId),
16
- });
17
-
18
- const dbFlags = dbContent?.flags || {};
19
-
20
- for (const [key, value] of Object.entries(dbFlags) as [
21
- keyof ContentFlags,
22
- boolean,
23
- ][]) {
24
- if (value === false) {
25
- delete flags[key];
26
- } else {
27
- flags[key] = value;
28
- }
29
- }
30
- }
31
-
32
- return Object.keys(flags).length > 0 ? flags : undefined;
33
- }
1
+ import { eq } from 'drizzle-orm';
2
+ import type { ContentFlags } from '@erudit-js/core/content/flags';
3
+
4
+ export async function getContentFlags(
5
+ fullId: string,
6
+ ): Promise<ContentFlags | undefined> {
7
+ const flags: ContentFlags = {};
8
+
9
+ const parts = fullId.split('/');
10
+ for (let i = 1; i <= parts.length; i++) {
11
+ const trimmedId = parts.slice(0, i).join('/');
12
+
13
+ const dbContent = await ERUDIT.db.query.content.findFirst({
14
+ columns: { flags: true },
15
+ where: eq(ERUDIT.db.schema.content.fullId, trimmedId),
16
+ });
17
+
18
+ const dbFlags = dbContent?.flags || {};
19
+
20
+ for (const [key, value] of Object.entries(dbFlags) as [
21
+ keyof ContentFlags,
22
+ boolean,
23
+ ][]) {
24
+ if (value === false) {
25
+ delete flags[key];
26
+ } else {
27
+ flags[key] = value;
28
+ }
29
+ }
30
+ }
31
+
32
+ return Object.keys(flags).length > 0 ? flags : undefined;
33
+ }
@@ -1,12 +1,12 @@
1
- import { eq } from 'drizzle-orm';
2
-
3
- export async function getContentSeo(fullContentId: string) {
4
- const dbContentItem = await ERUDIT.db.query.content.findFirst({
5
- columns: {
6
- seo: true,
7
- },
8
- where: eq(ERUDIT.db.schema.content.fullId, fullContentId),
9
- });
10
-
11
- return dbContentItem?.seo || undefined;
12
- }
1
+ import { eq } from 'drizzle-orm';
2
+
3
+ export async function getContentSeo(fullContentId: string) {
4
+ const dbContentItem = await ERUDIT.db.query.content.findFirst({
5
+ columns: {
6
+ seo: true,
7
+ },
8
+ where: eq(ERUDIT.db.schema.content.fullId, fullContentId),
9
+ });
10
+
11
+ return dbContentItem?.seo || undefined;
12
+ }