erudit 3.0.0-dev.2 → 3.0.0-dev.21

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 (321) hide show
  1. package/app/app.vue +195 -172
  2. package/app/assets/icons/cameo-add.svg +3 -0
  3. package/app/assets/icons/diamond.svg +3 -0
  4. package/app/assets/icons/graduation.svg +3 -0
  5. package/app/components/Avatar.vue +118 -0
  6. package/app/components/EruditLink.vue +17 -0
  7. package/app/components/Loading.vue +23 -23
  8. package/app/components/SiteAside.vue +393 -382
  9. package/app/components/SiteMain.vue +32 -35
  10. package/app/components/ads/Ads.vue +33 -0
  11. package/app/components/ads/AdsBannerAside.vue +61 -0
  12. package/app/components/ads/AdsBannerBottom.vue +22 -0
  13. package/app/components/ads/AdsProviderCustom.vue +35 -0
  14. package/app/components/ads/AdsProviderYandex.vue +91 -0
  15. package/app/components/ads/AdsReplacer.vue +73 -0
  16. package/app/components/aside/AsideListItem.vue +91 -74
  17. package/app/components/aside/AsideMajor.vue +56 -56
  18. package/app/components/aside/AsideMinor.vue +97 -71
  19. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  20. package/app/components/aside/major/PaneSwitch.vue +54 -54
  21. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  22. package/app/components/aside/major/SiteInfo.vue +85 -85
  23. package/app/components/aside/major/panes/Language.vue +79 -79
  24. package/app/components/aside/major/panes/Pages.vue +50 -34
  25. package/app/components/aside/major/panes/Search.vue +11 -11
  26. package/app/components/aside/major/panes/nav/Nav.vue +92 -91
  27. package/app/components/aside/major/panes/nav/NavBook.vue +95 -86
  28. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  29. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  30. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  31. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  32. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  33. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  34. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  35. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  36. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  37. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  38. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -15
  39. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  40. package/app/components/aside/major/panes/other/Other.vue +16 -16
  41. package/app/components/aside/minor/{Contribute.vue → AsideMinorContribute.vue} +175 -145
  42. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  43. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  44. package/app/components/aside/minor/AsideMinorTopLink.vue +66 -67
  45. package/app/components/aside/minor/content/AsideMinorContent.vue +89 -92
  46. package/app/components/aside/minor/contributor/AsideMinorContributor.vue +78 -0
  47. package/app/components/aside/minor/contributor/BookContribution.vue +64 -0
  48. package/app/components/aside/minor/topic/AsideMinorTopic.vue +31 -32
  49. package/app/components/aside/minor/topic/TopicContributors.vue +183 -177
  50. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  51. package/app/components/aside/minor/topic/TopicToc.vue +212 -203
  52. package/app/components/aside/minor/topic/TopicTocItem.vue +19 -31
  53. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  54. package/app/components/bitran/BitranContent.vue +90 -63
  55. package/app/components/bitran/RenderWrapper.vue +10 -10
  56. package/app/components/contributor/ContributorListItem.vue +43 -35
  57. package/app/components/main/MainActionButton.vue +51 -0
  58. package/app/components/main/MainBitranContent.vue +55 -0
  59. package/app/components/main/{utils/Breadcrumb.vue → MainBreadcrumb.vue} +63 -75
  60. package/app/components/main/MainDescription.vue +24 -0
  61. package/app/components/main/MainSection.vue +58 -0
  62. package/app/components/main/MainTitle.vue +76 -0
  63. package/app/components/main/cameo/MainCameo.vue +135 -0
  64. package/app/components/main/cameo/MainCameoData.vue +232 -0
  65. package/app/components/main/content/ContentBreadcrumb.vue +28 -0
  66. package/app/components/main/{utils → content}/ContentDecoration.vue +29 -29
  67. package/app/components/main/{utils → content}/ContentPopover.vue +188 -176
  68. package/app/components/main/{utils → content}/ContentPopovers.vue +111 -105
  69. package/app/components/main/{utils → content}/ContentReferences.vue +70 -70
  70. package/app/components/main/{utils → content}/reference/ReferenceGroup.vue +38 -38
  71. package/app/components/main/{utils → content}/reference/ReferenceItem.vue +70 -68
  72. package/app/components/main/{utils → content}/reference/ReferenceSource.vue +120 -116
  73. package/app/components/main/topic/MainTopic.vue +76 -79
  74. package/app/components/main/topic/TopicPartSwitch.vue +119 -118
  75. package/app/components/preview/Preview.vue +186 -177
  76. package/app/components/preview/PreviewDisplay.vue +139 -139
  77. package/app/components/preview/PreviewFooterAction.vue +73 -73
  78. package/app/components/preview/PreviewLoading.vue +14 -14
  79. package/app/components/preview/PreviewScreen.vue +141 -99
  80. package/app/components/preview/display/Alert.vue +50 -50
  81. package/app/components/preview/display/Custom.vue +18 -18
  82. package/app/components/preview/display/GenericLink.vue +48 -48
  83. package/app/components/preview/display/PageLink.vue +22 -20
  84. package/app/components/preview/display/Unique.vue +46 -49
  85. package/app/components/sponsor/SponsorTier1.vue +89 -0
  86. package/app/components/sponsor/SponsorTier2.vue +109 -0
  87. package/app/components/transition/Fade.vue +19 -19
  88. package/app/components/tree/TreeContainer.vue +11 -11
  89. package/app/components/tree/TreeItem.vue +93 -89
  90. package/app/composables/adsAllowed.ts +11 -0
  91. package/app/composables/asset.ts +12 -0
  92. package/app/composables/bitran.ts +108 -127
  93. package/app/composables/bitranLocation.ts +7 -7
  94. package/app/composables/contentData.ts +38 -36
  95. package/app/composables/contentPage.ts +168 -156
  96. package/app/composables/contentRoute.ts +45 -45
  97. package/app/composables/darkMagic.ts +24 -24
  98. package/app/composables/externalApi.ts +69 -63
  99. package/app/composables/favicon.ts +8 -8
  100. package/app/composables/formatText.ts +99 -86
  101. package/app/composables/head.ts +24 -0
  102. package/app/composables/majorPane.ts +62 -60
  103. package/app/composables/phrases.ts +77 -80
  104. package/app/composables/theme.ts +29 -29
  105. package/app/composables/url.ts +43 -33
  106. package/app/pages/_test/preview.vue +110 -110
  107. package/app/pages/article/[...articleId].vue +3 -3
  108. package/app/pages/book/[...bookId].vue +42 -47
  109. package/app/pages/contributor/[contributorId].vue +227 -0
  110. package/app/pages/contributors.vue +184 -0
  111. package/app/pages/group/[...groupId].vue +53 -65
  112. package/app/pages/index.vue +32 -32
  113. package/app/pages/practice/[...practice].vue +3 -3
  114. package/app/pages/sponsors.vue +95 -0
  115. package/app/pages/summary/[...summaryId].vue +3 -3
  116. package/app/plugins/analytics.ts +95 -0
  117. package/app/plugins/prerender.server.ts +34 -0
  118. package/app/public/favicon/article.svg +5 -5
  119. package/app/public/favicon/default.svg +3 -3
  120. package/app/public/favicon/practice.svg +3 -3
  121. package/app/public/favicon/summary.svg +4 -4
  122. package/app/public/logotype.svg +2 -2
  123. package/app/scripts/_immediate.js +9 -9
  124. package/app/scripts/aside/index.ts +59 -59
  125. package/app/scripts/aside/major/nav.ts +26 -26
  126. package/app/scripts/aside/minor/state.ts +37 -37
  127. package/app/scripts/flag.ts +28 -28
  128. package/app/scripts/og.ts +28 -27
  129. package/app/scripts/preview/build.ts +76 -73
  130. package/app/scripts/preview/data/alert.ts +19 -19
  131. package/app/scripts/preview/data/custom.ts +8 -8
  132. package/app/scripts/preview/data/genericLink.ts +24 -24
  133. package/app/scripts/preview/data/pageLink.ts +23 -20
  134. package/app/scripts/preview/data/unique.ts +69 -70
  135. package/app/scripts/preview/data.ts +24 -24
  136. package/app/scripts/preview/display.ts +37 -37
  137. package/app/scripts/preview/footer.ts +9 -9
  138. package/app/scripts/preview/request.ts +51 -51
  139. package/app/scripts/preview/state.ts +63 -63
  140. package/app/styles/_immediate.css +7 -7
  141. package/app/styles/_util.scss +43 -43
  142. package/app/styles/_utils.scss +44 -44
  143. package/app/styles/app.scss +91 -91
  144. package/app/styles/def/_bp.scss +27 -27
  145. package/app/styles/def/_size.scss +7 -7
  146. package/app/styles/def/_z.scss +5 -5
  147. package/app/styles/normalize.scss +49 -63
  148. package/app/styles/partials/_darkMagic.scss +5 -5
  149. package/app/styles/partials/_fnav.scss +15 -15
  150. package/app/styles/partials/_preview.scss +5 -5
  151. package/bin/erudit.mjs +2 -0
  152. package/const.ts +3 -0
  153. package/globalPath.ts +21 -21
  154. package/globals/bitran.ts +1 -47
  155. package/globals/cameo.ts +5 -0
  156. package/globals/content.ts +27 -22
  157. package/globals/contributor.ts +5 -5
  158. package/globals/erudit.ts +5 -5
  159. package/globals/register.ts +23 -18
  160. package/globals/sponsor.ts +17 -0
  161. package/languages/en.ts +108 -95
  162. package/languages/ru.ts +112 -99
  163. package/module/bitran.ts +66 -34
  164. package/module/config.ts +35 -34
  165. package/module/imports.ts +74 -46
  166. package/module/index.ts +47 -47
  167. package/module/logger.ts +10 -10
  168. package/module/paths.ts +22 -22
  169. package/module/restart.ts +61 -61
  170. package/nuxt.config.ts +126 -112
  171. package/package.json +22 -15
  172. package/server/api/aside/major/nav/bookIds.ts +5 -5
  173. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  174. package/server/api/aside/major/nav/global.ts +7 -7
  175. package/server/api/aside/minor/book/[...bookId].ts +18 -0
  176. package/server/api/aside/minor/contributor/[contributorId].ts +18 -0
  177. package/server/api/aside/minor/group/[...groupId].ts +18 -0
  178. package/server/api/aside/minor/news.ts +7 -7
  179. package/server/api/aside/minor/topic.ts +36 -0
  180. package/server/api/bitran/content/[...location].ts +13 -0
  181. package/server/api/bitran/toc/[...location].ts +9 -0
  182. package/server/api/cameo/data/[cameoId].ts +42 -0
  183. package/server/api/cameo/ids.ts +5 -0
  184. package/server/api/content/data.ts +75 -72
  185. package/server/api/contributor/count.ts +6 -6
  186. package/server/api/contributor/list.ts +44 -0
  187. package/server/api/contributor/page/[contributorId].ts +14 -0
  188. package/server/api/fake/content.ts +11 -11
  189. package/server/api/fake/shared/languages.ts +12 -12
  190. package/server/api/language/functions.ts +12 -12
  191. package/server/api/language/phrase/[phraseId].ts +19 -19
  192. package/server/api/language/phraseIds.ts +8 -8
  193. package/server/api/prerender/assets/cameo.ts +14 -0
  194. package/server/api/prerender/assets/contributor.ts +12 -0
  195. package/server/api/prerender/assets/sponsor.ts +13 -0
  196. package/server/api/prerender/cameos.ts +12 -0
  197. package/server/api/prerender/language.ts +9 -0
  198. package/server/api/preview/page/[...parts].ts +78 -51
  199. package/server/api/preview/unique/{[location].ts → [...location].ts} +48 -55
  200. package/server/api/problem/generator/[...path].ts +26 -0
  201. package/server/api/sponsor/cameo/data/[sponsorId].ts +51 -0
  202. package/server/api/sponsor/cameo/ids.ts +5 -0
  203. package/server/api/sponsor/count.ts +5 -0
  204. package/server/api/sponsor/list.ts +36 -0
  205. package/server/plugin/bitran/content.ts +252 -187
  206. package/server/plugin/bitran/{products → elements}/include.ts +229 -230
  207. package/server/plugin/bitran/location.ts +43 -25
  208. package/server/plugin/bitran/toc.ts +94 -83
  209. package/server/plugin/bitran/transpiler.ts +18 -46
  210. package/server/plugin/build/close.ts +12 -10
  211. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  212. package/server/plugin/build/jobs/content/generic.ts +191 -176
  213. package/server/plugin/build/jobs/content/parse.ts +113 -100
  214. package/server/plugin/build/jobs/content/path.ts +6 -6
  215. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  216. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  217. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  218. package/server/plugin/build/jobs/contributors.ts +69 -66
  219. package/server/plugin/build/jobs/language.ts +36 -36
  220. package/server/plugin/build/jobs/nav.ts +345 -210
  221. package/server/plugin/build/process.ts +34 -25
  222. package/server/plugin/build/rebuild.ts +68 -55
  223. package/server/plugin/build/setup.ts +19 -21
  224. package/server/plugin/content/context.ts +119 -112
  225. package/server/plugin/db/entities/Book.ts +7 -7
  226. package/server/plugin/db/entities/Content.ts +45 -49
  227. package/server/plugin/db/entities/Contribution.ts +10 -10
  228. package/server/plugin/db/entities/Contributor.ts +25 -16
  229. package/server/plugin/db/entities/File.ts +10 -0
  230. package/server/plugin/db/entities/Group.ts +14 -14
  231. package/server/plugin/db/entities/Hash.ts +15 -15
  232. package/server/plugin/db/entities/Topic.ts +20 -20
  233. package/server/plugin/db/entities/Unique.ts +21 -21
  234. package/server/plugin/db/reset.ts +12 -0
  235. package/server/plugin/db/setup.ts +49 -34
  236. package/server/plugin/global.ts +18 -18
  237. package/server/plugin/importer.ts +16 -12
  238. package/server/plugin/index.ts +9 -9
  239. package/server/plugin/logger.ts +23 -23
  240. package/server/plugin/nav/node.ts +27 -26
  241. package/server/plugin/nav/utils.ts +179 -129
  242. package/server/plugin/repository/asideMinor.ts +51 -0
  243. package/server/plugin/repository/book.ts +39 -21
  244. package/server/plugin/repository/cameo.ts +16 -0
  245. package/server/plugin/repository/content.ts +240 -238
  246. package/server/plugin/repository/contentId.ts +40 -0
  247. package/server/plugin/repository/contributor.ts +129 -8
  248. package/server/plugin/repository/file.ts +10 -0
  249. package/server/plugin/repository/frontNav.ts +145 -148
  250. package/server/plugin/repository/topic.ts +35 -32
  251. package/server/plugin/sponsor/build.ts +82 -0
  252. package/server/plugin/sponsor/index.ts +5 -0
  253. package/server/plugin/sponsor/repository.ts +56 -0
  254. package/server/routes/asset/[...assetPath].ts +34 -0
  255. package/server/routes/robots.txt.ts +9 -0
  256. package/server/routes/sitemap.xml.ts +103 -0
  257. package/server/tsconfig.json +9 -9
  258. package/shared/aside/minor.ts +55 -50
  259. package/shared/asset.ts +17 -15
  260. package/shared/bitran/content.ts +9 -0
  261. package/shared/bitran/contentId.ts +56 -0
  262. package/shared/bitran/toc.ts +8 -8
  263. package/shared/breadcrumb.ts +7 -0
  264. package/shared/content/bookId.ts +12 -0
  265. package/shared/content/context.ts +9 -9
  266. package/shared/content/data/base.ts +32 -32
  267. package/shared/content/data/index.ts +5 -5
  268. package/shared/content/data/type/book.ts +5 -5
  269. package/shared/content/data/type/group.ts +6 -6
  270. package/shared/content/data/type/topic.ts +11 -11
  271. package/shared/content/previousNext.ts +9 -9
  272. package/shared/contributor.ts +34 -5
  273. package/shared/frontNav.ts +41 -41
  274. package/shared/icons.ts +38 -38
  275. package/shared/image.ts +5 -5
  276. package/shared/link.ts +28 -25
  277. package/shared/popover.ts +8 -0
  278. package/shared/types/language.ts +84 -75
  279. package/shared/utils/objectsEqual.ts +4 -4
  280. package/shared/utils/stringColor.ts +9 -9
  281. package/test/contentId.test.ts +91 -0
  282. package/test/utils/url.test.ts +99 -0
  283. package/tsconfig.json +8 -8
  284. package/utils/contentPath.ts +67 -0
  285. package/utils/ext.ts +41 -0
  286. package/utils/stress.ts +9 -9
  287. package/utils/url.ts +23 -0
  288. package/app/components/ads/BannerTemplate.vue +0 -51
  289. package/app/components/ads/BottomBanner.vue +0 -45
  290. package/app/components/ads/LeftBanner.vue +0 -50
  291. package/app/components/aside/minor/AsideMinorContributor.vue +0 -5
  292. package/app/components/contributor/ContributorAvatar.vue +0 -43
  293. package/app/components/main/utils/ContentDescription.vue +0 -19
  294. package/app/components/main/utils/ContentFlag.vue +0 -15
  295. package/app/components/main/utils/ContentSection.vue +0 -45
  296. package/app/components/main/utils/ContentTitle.vue +0 -39
  297. package/app/composables/bitranContent.ts +0 -37
  298. package/app/pages/members.vue +0 -6
  299. package/app/public/user.svg +0 -10
  300. package/app/scripts/aside/minor/topic.ts +0 -3
  301. package/app/styles/default.scss +0 -83
  302. package/server/api/aside/minor/path.ts +0 -78
  303. package/server/api/bitran/content/[location].ts +0 -7
  304. package/server/api/bitran/toc/[location].ts +0 -7
  305. package/server/plugin/bitran/products/link.ts +0 -116
  306. package/server/plugin/bitran/setup.ts +0 -9
  307. package/server/plugin/content/absoluteId.ts +0 -94
  308. package/shared/bitran/context.ts +0 -8
  309. package/shared/bitran/default.ts +0 -46
  310. package/shared/bitran/link/Link.vue +0 -167
  311. package/shared/bitran/link/factory.ts +0 -24
  312. package/shared/bitran/link/icon.svg +0 -3
  313. package/shared/bitran/link/languages/en.ts +0 -7
  314. package/shared/bitran/link/languages/ru.ts +0 -7
  315. package/shared/bitran/link/renderer.ts +0 -21
  316. package/shared/bitran/link/shared.ts +0 -17
  317. package/shared/bitran/link/target.ts +0 -134
  318. package/shared/bitran/link/transpiler.ts +0 -10
  319. package/shared/bitran/location.ts +0 -166
  320. package/test/bitran/link/target.test.ts +0 -141
  321. package/test/bitran/location.test.ts +0 -143
@@ -1,187 +1,252 @@
1
- import { isTopicPart, type TopicPart } from 'erudit-cog/schema';
2
- import { createPreRenderData, type PreRenderData } from '@bitran-js/transpiler';
3
- import { BlockNode, BlocksNode } from '@bitran-js/core';
4
- import { type BitranContent } from '@bitran-js/renderer-vue';
5
- import {
6
- AliasesNode,
7
- mergeAliases,
8
- NO_ALIASES,
9
- } from '@erudit-js/bitran-elements/aliases/shared';
10
- import { IncludeNode } from '@erudit-js/bitran-elements/include/shared';
11
-
12
- import { ERUDIT_SERVER } from '@server/global';
13
- import { DbUnique } from '@server/db/entities/Unique';
14
- import { DbTopic } from '@server/db/entities/Topic';
15
- import { DbGroup } from '@server/db/entities/Group';
16
- import { resolveLinkTarget } from '@server/bitran/products/link';
17
- import { traverseInclude } from '@server/bitran/products/include';
18
- import { createBitranTranspiler } from '@server/bitran/transpiler';
19
-
20
- import type { BitranContext } from '@erudit/shared/bitran/context';
21
- import {
22
- stringifyBitranLocation,
23
- type BitranLocation,
24
- } from '@erudit/shared/bitran/location';
25
- import { LinkNode } from '@erudit/shared/bitran/link/shared';
26
-
27
- interface RawBitranContent {
28
- context: BitranContext;
29
- biCode: string;
30
- }
31
-
32
- export async function getBitranContent(
33
- location: BitranLocation,
34
- ): Promise<BitranContent> {
35
- const rawContent = await getRawBitranContent(location);
36
- const bitranContent = await createBitranContent(
37
- rawContent.context,
38
- rawContent.biCode,
39
- );
40
- return bitranContent;
41
- }
42
-
43
- export async function getRawBitranContent(
44
- location: BitranLocation,
45
- ): Promise<RawBitranContent> {
46
- const throwNotFound = () => {
47
- throw createError({
48
- statusCode: 404,
49
- statusText: `Can't find content for location "${stringifyBitranLocation(location)}"!`,
50
- });
51
- };
52
-
53
- if (location.unique) {
54
- const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
55
- where: { location: stringifyBitranLocation(location) },
56
- });
57
-
58
- if (!dbUnique) throwNotFound();
59
-
60
- return {
61
- biCode: dbUnique!.content,
62
- context: dbUnique!.context,
63
- };
64
- }
65
-
66
- if (isTopicPart(location.type)) {
67
- const topicPart = location.type as TopicPart;
68
-
69
- const dbTopic = await ERUDIT_SERVER.DB.manager.findOne(DbTopic, {
70
- select: ['contentId', topicPart],
71
- where: { contentId: location.path },
72
- });
73
-
74
- if (!dbTopic) throwNotFound();
75
-
76
- return {
77
- biCode: dbTopic![topicPart]!,
78
- context: { location, aliases: NO_ALIASES() },
79
- };
80
- }
81
-
82
- if (location.type === 'group') {
83
- const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
84
- select: ['contentId', 'content'],
85
- where: { contentId: location.path },
86
- });
87
-
88
- if (!dbGroup) throwNotFound();
89
-
90
- return {
91
- biCode: dbGroup!.content!,
92
- context: { location, aliases: NO_ALIASES() },
93
- };
94
- }
95
-
96
- return throwNotFound();
97
- }
98
-
99
- async function createBitranContent(
100
- context: BitranContext,
101
- biCode: string,
102
- ): Promise<BitranContent> {
103
- const bitranTranspiler = await createBitranTranspiler();
104
-
105
- const root = await bitranTranspiler.parser.parse(biCode, {
106
- async step(node) {
107
- if (node instanceof AliasesNode) {
108
- mergeAliases(context.aliases, node.parseData);
109
- return;
110
- }
111
-
112
- if (node instanceof IncludeNode) {
113
- await resolveInclude(node, context);
114
- return;
115
- }
116
- },
117
- });
118
-
119
- const finalContent = await bitranTranspiler.stringifier.stringify(root);
120
-
121
- // Building render data
122
- const preRenderDataMap: Record<string, PreRenderData> = {};
123
- await bitranTranspiler.parser.parse(finalContent, {
124
- step: async (node) => {
125
- const id = node.id;
126
- const elementTranspiler = bitranTranspiler.transpilers[node.name]!;
127
-
128
- if (node instanceof LinkNode) {
129
- try {
130
- preRenderDataMap[id] = {
131
- type: 'success',
132
- data: await resolveLinkTarget(node.parseData, {
133
- location: context.location,
134
- aliases: context.aliases ?? {},
135
- }),
136
- };
137
- } catch (error: any) {
138
- preRenderDataMap[id] = {
139
- type: 'error',
140
- message: error?.message || String(error),
141
- };
142
- }
143
- return;
144
- }
145
-
146
- if (id) {
147
- const preRenderData = await createPreRenderData(
148
- node,
149
- elementTranspiler,
150
- );
151
- if (preRenderData) preRenderDataMap[id] = preRenderData;
152
- }
153
- },
154
- });
155
-
156
- return {
157
- biCode: finalContent,
158
- preRenderData: preRenderDataMap,
159
- };
160
- }
161
-
162
- async function resolveInclude(
163
- includeNode: IncludeNode,
164
- context: BitranContext,
165
- ): Promise<IncludeNode> {
166
- let _blocks;
167
-
168
- try {
169
- const blocks: BlockNode[] = [];
170
-
171
- await traverseInclude(includeNode, context, {
172
- step: async ({ _node }) => {
173
- if (_node instanceof BlockNode) blocks.push(_node);
174
- },
175
- });
176
-
177
- const blocksNode = new BlocksNode(includeNode);
178
- blocksNode.setNodes(blocks);
179
- _blocks = blocksNode;
180
- includeNode.parseData.blocks = _blocks;
181
- } catch (error: any) {
182
- includeNode.parseData.error = error?.message || error;
183
- }
184
-
185
- includeNode.parseData.resolved = true;
186
- return includeNode;
187
- }
1
+ import {
2
+ BlockErrorNode,
3
+ BlocksNode,
4
+ createRenderData,
5
+ ElementNode,
6
+ InlinerErrorNode,
7
+ walkDown,
8
+ type RenderDataStorage,
9
+ } from '@bitran-js/core';
10
+ import {
11
+ isTopicPart,
12
+ mergeAliases,
13
+ NO_ALIASES,
14
+ stringifyBitranLocation,
15
+ type BitranContext,
16
+ type BitranLocation,
17
+ type EruditBitranRuntime,
18
+ type TopicPart,
19
+ } from '@erudit-js/cog/schema';
20
+ import { AliasesNode } from '@erudit-js/bitran-elements/aliases/shared';
21
+ import { IncludeNode } from '@erudit-js/bitran-elements/include/shared';
22
+ import {
23
+ ProblemNode,
24
+ ProblemsNode,
25
+ } from '@erudit-js/bitran-elements/problem/shared';
26
+ import {
27
+ prerenderProblem,
28
+ prerenderProblems,
29
+ } from '@erudit-js/bitran-elements/problem/prerender';
30
+ import { LinkNode } from '@erudit-js/bitran-elements/link/shared';
31
+ import { prerenderLink } from '@erudit-js/bitran-elements/link/prerender';
32
+
33
+ import { ERUDIT_SERVER } from '@server/global';
34
+ import { DbUnique } from '@server/db/entities/Unique';
35
+ import { DbTopic } from '@server/db/entities/Topic';
36
+ import { DbGroup } from '@server/db/entities/Group';
37
+ import { DbContributor } from '@server/db/entities/Contributor';
38
+ import { traverseInclude } from '@server/bitran/elements/include';
39
+ import { createBitranTranspiler } from '@server/bitran/transpiler';
40
+ import { logger } from '@server/logger';
41
+
42
+ import { type RawBitranContent } from '@erudit/shared/bitran/content';
43
+
44
+ export async function getBitranContent(
45
+ location: BitranLocation,
46
+ generatePrerenderData: boolean = true,
47
+ ): Promise<RawBitranContent> {
48
+ const { biCode, context } = await retrieveContentFrom(location);
49
+ const bitranContent = await createBitranContent(
50
+ context,
51
+ biCode,
52
+ generatePrerenderData,
53
+ );
54
+ return bitranContent;
55
+ }
56
+
57
+ //
58
+ // Local
59
+ //
60
+
61
+ async function retrieveContentFrom(location: BitranLocation) {
62
+ const throwNotFound = () => {
63
+ throw createError({
64
+ statusCode: 404,
65
+ statusText: `Can't find content for location "${stringifyBitranLocation(location)}"!`,
66
+ });
67
+ };
68
+
69
+ if (location.unique) {
70
+ const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
71
+ where: { location: stringifyBitranLocation(location) },
72
+ });
73
+
74
+ if (!dbUnique) throwNotFound();
75
+
76
+ return {
77
+ biCode: dbUnique!.content,
78
+ context: dbUnique!.context,
79
+ };
80
+ }
81
+
82
+ if (isTopicPart(location.type)) {
83
+ const topicPart = location.type as TopicPart;
84
+
85
+ const dbTopic = await ERUDIT_SERVER.DB.manager.findOne(DbTopic, {
86
+ select: ['contentId', topicPart],
87
+ where: { contentId: location.path },
88
+ });
89
+
90
+ if (!dbTopic) throwNotFound();
91
+
92
+ return {
93
+ biCode: dbTopic![topicPart]!,
94
+ context: { location, aliases: NO_ALIASES() },
95
+ };
96
+ }
97
+
98
+ if (location.type === 'group') {
99
+ const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
100
+ select: ['contentId', 'content'],
101
+ where: { contentId: location.path },
102
+ });
103
+
104
+ if (!dbGroup) throwNotFound();
105
+
106
+ return {
107
+ biCode: dbGroup!.content!,
108
+ context: { location, aliases: NO_ALIASES() },
109
+ };
110
+ }
111
+
112
+ if (location.type === 'contributor') {
113
+ const dbContributor = await ERUDIT_SERVER.DB.manager.findOne(
114
+ DbContributor,
115
+ {
116
+ select: ['description'],
117
+ where: { contributorId: location.path },
118
+ },
119
+ );
120
+
121
+ if (!dbContributor) throwNotFound();
122
+
123
+ return {
124
+ biCode: dbContributor!.description!,
125
+ context: { location, aliases: NO_ALIASES() },
126
+ };
127
+ }
128
+
129
+ return throwNotFound();
130
+ }
131
+
132
+ async function createBitranContent(
133
+ context: BitranContext,
134
+ biCode: string,
135
+ generatePrerenderData: boolean = true,
136
+ ): Promise<RawBitranContent> {
137
+ const runtime: EruditBitranRuntime = {
138
+ eruditConfig: ERUDIT_SERVER.CONFIG,
139
+ insideInclude: false,
140
+ context,
141
+ };
142
+
143
+ const bitranTranspiler = await createBitranTranspiler(runtime);
144
+
145
+ const renderDataStorage: RenderDataStorage = {};
146
+
147
+ const routes: string[] = [];
148
+ const addRoute = (
149
+ newRoutes: string | undefined | (string | undefined)[],
150
+ ) => {
151
+ if (Array.isArray(newRoutes)) {
152
+ routes.push(...(newRoutes.filter(Boolean) as string[]));
153
+ } else if (newRoutes) {
154
+ routes.push(newRoutes);
155
+ }
156
+ };
157
+
158
+ async function setNodeRenderData(node: ElementNode) {
159
+ if (generatePrerenderData === false) {
160
+ return;
161
+ }
162
+
163
+ const transpiler = bitranTranspiler.transpilers[node.name];
164
+
165
+ const renderDataResult = await createRenderData({
166
+ storage: renderDataStorage,
167
+ node,
168
+ extra: runtime,
169
+ generator: transpiler?.renderDataGenerator,
170
+ });
171
+
172
+ if (renderDataResult?.type === 'success') {
173
+ node.renderData = renderDataResult.data;
174
+ }
175
+ }
176
+
177
+ async function addNodePrerenderRoute(node: ElementNode) {
178
+ switch (true) {
179
+ case node instanceof ProblemNode:
180
+ addRoute(prerenderProblem(node));
181
+ break;
182
+ case node instanceof ProblemsNode:
183
+ addRoute(await prerenderProblems(node, runtime));
184
+ break;
185
+ case node instanceof LinkNode:
186
+ addRoute(prerenderLink(node, runtime));
187
+ break;
188
+ }
189
+ }
190
+
191
+ const root = await bitranTranspiler.parser.parse(biCode, {
192
+ async step(node) {
193
+ switch (true) {
194
+ case node instanceof BlockErrorNode:
195
+ case node instanceof InlinerErrorNode:
196
+ logParseError(node.name, node.error);
197
+ return;
198
+ case node instanceof AliasesNode:
199
+ mergeAliases(context.aliases, node.parseData);
200
+ break;
201
+ case node instanceof IncludeNode:
202
+ const includeNode = await resolveInclude(node, context);
203
+ await walkDown(includeNode, async (child) => {
204
+ if (child instanceof ElementNode) {
205
+ await setNodeRenderData(child);
206
+ await addNodePrerenderRoute(child);
207
+ }
208
+ });
209
+ break;
210
+ }
211
+
212
+ await setNodeRenderData(node);
213
+ await addNodePrerenderRoute(node);
214
+ },
215
+ });
216
+
217
+ const finalContent = await bitranTranspiler.stringifier.stringify(root);
218
+
219
+ return {
220
+ biCode: finalContent,
221
+ storage: renderDataStorage,
222
+ routes,
223
+ context: {
224
+ location: context.location,
225
+ aliases: context.aliases,
226
+ },
227
+ };
228
+ }
229
+
230
+ async function resolveInclude(
231
+ includeNode: IncludeNode,
232
+ context: BitranContext,
233
+ ): Promise<IncludeNode> {
234
+ let _blocks;
235
+
236
+ try {
237
+ const blocks = await traverseInclude(includeNode, context, {});
238
+ const blocksNode = new BlocksNode(includeNode);
239
+ blocksNode.setNodes(blocks);
240
+ _blocks = blocksNode;
241
+ includeNode.parseData.blocks = _blocks;
242
+ } catch (error: any) {
243
+ includeNode.parseData.error = error?.message || error;
244
+ }
245
+
246
+ includeNode.parseData.resolved = true;
247
+ return includeNode;
248
+ }
249
+
250
+ function logParseError(nodeName: string, error: string) {
251
+ logger.warn(`Error parsing "${nodeName}" element!\n\n${error}`);
252
+ }