erudit 3.0.0-dev.16 → 3.0.0-dev.18

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 (234) hide show
  1. package/app/app.vue +193 -191
  2. package/app/components/Loading.vue +23 -23
  3. package/app/components/SiteAside.vue +393 -393
  4. package/app/components/SiteMain.vue +32 -32
  5. package/app/components/ads/AdsProviderYandex.vue +2 -2
  6. package/app/components/aside/AsideListItem.vue +74 -74
  7. package/app/components/aside/AsideMajor.vue +56 -56
  8. package/app/components/aside/AsideMinor.vue +73 -73
  9. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  10. package/app/components/aside/major/PaneSwitch.vue +54 -54
  11. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  12. package/app/components/aside/major/SiteInfo.vue +85 -85
  13. package/app/components/aside/major/panes/Language.vue +79 -79
  14. package/app/components/aside/major/panes/Pages.vue +34 -34
  15. package/app/components/aside/major/panes/Search.vue +11 -11
  16. package/app/components/aside/major/panes/nav/Nav.vue +92 -92
  17. package/app/components/aside/major/panes/nav/NavBook.vue +95 -95
  18. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  19. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  20. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  21. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  22. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  23. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  24. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  25. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  26. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  27. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  28. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -13
  29. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  30. package/app/components/aside/major/panes/other/Other.vue +16 -16
  31. package/app/components/aside/minor/AsideMinorContributor.vue +5 -5
  32. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  33. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  34. package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
  35. package/app/components/aside/minor/Contribute.vue +145 -145
  36. package/app/components/aside/minor/content/AsideMinorContent.vue +92 -92
  37. package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -32
  38. package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
  39. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  40. package/app/components/aside/minor/topic/TopicToc.vue +214 -214
  41. package/app/components/aside/minor/topic/TopicTocItem.vue +32 -32
  42. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  43. package/app/components/bitran/BitranContent.vue +91 -91
  44. package/app/components/bitran/RenderWrapper.vue +10 -10
  45. package/app/components/contributor/ContributorAvatar.vue +45 -45
  46. package/app/components/contributor/ContributorListItem.vue +35 -35
  47. package/app/components/main/topic/MainTopic.vue +88 -88
  48. package/app/components/main/topic/TopicPartSwitch.vue +118 -118
  49. package/app/components/main/utils/Breadcrumb.vue +74 -74
  50. package/app/components/main/utils/ContentDecoration.vue +29 -29
  51. package/app/components/main/utils/ContentDescription.vue +19 -19
  52. package/app/components/main/utils/ContentPopover.vue +188 -188
  53. package/app/components/main/utils/ContentPopovers.vue +111 -111
  54. package/app/components/main/utils/ContentReferences.vue +70 -70
  55. package/app/components/main/utils/ContentSection.vue +45 -45
  56. package/app/components/main/utils/ContentTitle.vue +63 -63
  57. package/app/components/main/utils/reference/ReferenceGroup.vue +38 -38
  58. package/app/components/main/utils/reference/ReferenceItem.vue +70 -70
  59. package/app/components/main/utils/reference/ReferenceSource.vue +120 -120
  60. package/app/components/preview/Preview.vue +186 -186
  61. package/app/components/preview/PreviewDisplay.vue +139 -139
  62. package/app/components/preview/PreviewFooterAction.vue +73 -73
  63. package/app/components/preview/PreviewLoading.vue +14 -14
  64. package/app/components/preview/PreviewScreen.vue +141 -141
  65. package/app/components/preview/display/Alert.vue +50 -50
  66. package/app/components/preview/display/Custom.vue +18 -18
  67. package/app/components/preview/display/GenericLink.vue +48 -48
  68. package/app/components/preview/display/PageLink.vue +22 -22
  69. package/app/components/preview/display/Unique.vue +55 -55
  70. package/app/components/transition/Fade.vue +19 -19
  71. package/app/components/tree/TreeContainer.vue +11 -11
  72. package/app/components/tree/TreeItem.vue +89 -89
  73. package/app/composables/adsAllowed.ts +11 -0
  74. package/app/composables/bitran.ts +108 -108
  75. package/app/composables/bitranContent.ts +96 -92
  76. package/app/composables/bitranLocation.ts +7 -7
  77. package/app/composables/contentData.ts +38 -38
  78. package/app/composables/contentPage.ts +168 -158
  79. package/app/composables/contentRoute.ts +45 -45
  80. package/app/composables/darkMagic.ts +24 -24
  81. package/app/composables/externalApi.ts +69 -69
  82. package/app/composables/favicon.ts +8 -8
  83. package/app/composables/formatText.ts +99 -99
  84. package/app/composables/majorPane.ts +60 -60
  85. package/app/composables/phrases.ts +65 -65
  86. package/app/composables/theme.ts +29 -29
  87. package/app/composables/url.ts +33 -33
  88. package/app/pages/_test/preview.vue +110 -110
  89. package/app/pages/article/[...articleId].vue +3 -3
  90. package/app/pages/book/[...bookId].vue +47 -47
  91. package/app/pages/group/[...groupId].vue +66 -66
  92. package/app/pages/index.vue +32 -32
  93. package/app/pages/members.vue +5 -6
  94. package/app/pages/practice/[...practice].vue +3 -3
  95. package/app/pages/summary/[...summaryId].vue +3 -3
  96. package/app/plugins/analytics.ts +8 -0
  97. package/app/plugins/prerender.server.ts +22 -22
  98. package/app/scripts/_immediate.js +9 -9
  99. package/app/scripts/aside/index.ts +59 -59
  100. package/app/scripts/aside/major/nav.ts +26 -26
  101. package/app/scripts/aside/minor/state.ts +37 -37
  102. package/app/scripts/aside/minor/topic.ts +3 -3
  103. package/app/scripts/flag.ts +28 -28
  104. package/app/scripts/og.ts +27 -27
  105. package/app/scripts/preview/build.ts +76 -76
  106. package/app/scripts/preview/data/alert.ts +19 -19
  107. package/app/scripts/preview/data/custom.ts +8 -8
  108. package/app/scripts/preview/data/genericLink.ts +24 -24
  109. package/app/scripts/preview/data/pageLink.ts +23 -23
  110. package/app/scripts/preview/data/unique.ts +72 -72
  111. package/app/scripts/preview/data.ts +24 -24
  112. package/app/scripts/preview/display.ts +37 -37
  113. package/app/scripts/preview/footer.ts +9 -9
  114. package/app/scripts/preview/request.ts +51 -51
  115. package/app/scripts/preview/state.ts +63 -63
  116. package/app/styles/_immediate.css +7 -7
  117. package/app/styles/_util.scss +43 -43
  118. package/app/styles/_utils.scss +44 -44
  119. package/app/styles/app.scss +91 -91
  120. package/app/styles/def/_bp.scss +27 -27
  121. package/app/styles/def/_size.scss +7 -7
  122. package/app/styles/def/_z.scss +5 -5
  123. package/app/styles/normalize.scss +49 -49
  124. package/app/styles/partials/_darkMagic.scss +5 -5
  125. package/app/styles/partials/_fnav.scss +15 -15
  126. package/app/styles/partials/_preview.scss +5 -5
  127. package/bin/erudit.mjs +2 -2
  128. package/const.ts +4 -4
  129. package/globalPath.ts +21 -21
  130. package/globals/bitran.ts +1 -1
  131. package/globals/content.ts +27 -27
  132. package/globals/contributor.ts +5 -5
  133. package/globals/erudit.ts +5 -5
  134. package/globals/register.ts +18 -18
  135. package/languages/en.ts +94 -94
  136. package/languages/ru.ts +98 -98
  137. package/module/bitran.ts +66 -66
  138. package/module/config.ts +35 -35
  139. package/module/imports.ts +67 -67
  140. package/module/index.ts +47 -47
  141. package/module/logger.ts +10 -10
  142. package/module/paths.ts +22 -22
  143. package/module/restart.ts +61 -61
  144. package/nuxt.config.ts +131 -131
  145. package/package.json +4 -4
  146. package/server/api/aside/major/nav/bookIds.ts +5 -5
  147. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  148. package/server/api/aside/major/nav/global.ts +7 -7
  149. package/server/api/aside/minor/news.ts +7 -7
  150. package/server/api/aside/minor/path.ts +82 -82
  151. package/server/api/bitran/content/[...location].ts +10 -10
  152. package/server/api/bitran/toc/[...location].ts +9 -9
  153. package/server/api/content/data.ts +75 -75
  154. package/server/api/contributor/count.ts +6 -6
  155. package/server/api/fake/content.ts +11 -11
  156. package/server/api/fake/shared/languages.ts +12 -12
  157. package/server/api/language/functions.ts +12 -12
  158. package/server/api/language/phrase/[phraseId].ts +19 -19
  159. package/server/api/language/phraseIds.ts +8 -8
  160. package/server/api/prerender.ts +19 -120
  161. package/server/api/preview/page/[...parts].ts +78 -78
  162. package/server/api/preview/unique/[...location].ts +61 -61
  163. package/server/plugin/bitran/content.ts +237 -190
  164. package/server/plugin/bitran/elements/include.ts +229 -229
  165. package/server/plugin/bitran/location.ts +39 -39
  166. package/server/plugin/bitran/toc.ts +94 -94
  167. package/server/plugin/bitran/transpiler.ts +18 -18
  168. package/server/plugin/build/close.ts +12 -12
  169. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  170. package/server/plugin/build/jobs/content/generic.ts +191 -191
  171. package/server/plugin/build/jobs/content/parse.ts +113 -113
  172. package/server/plugin/build/jobs/content/path.ts +6 -6
  173. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  174. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  175. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  176. package/server/plugin/build/jobs/contributors.ts +66 -66
  177. package/server/plugin/build/jobs/language.ts +36 -36
  178. package/server/plugin/build/jobs/nav.ts +345 -345
  179. package/server/plugin/build/process.ts +32 -32
  180. package/server/plugin/build/rebuild.ts +66 -66
  181. package/server/plugin/build/setup.ts +19 -19
  182. package/server/plugin/content/context.ts +119 -119
  183. package/server/plugin/db/entities/Book.ts +7 -7
  184. package/server/plugin/db/entities/Content.ts +45 -45
  185. package/server/plugin/db/entities/Contribution.ts +10 -10
  186. package/server/plugin/db/entities/Contributor.ts +16 -16
  187. package/server/plugin/db/entities/File.ts +10 -10
  188. package/server/plugin/db/entities/Group.ts +14 -14
  189. package/server/plugin/db/entities/Hash.ts +15 -15
  190. package/server/plugin/db/entities/Topic.ts +20 -20
  191. package/server/plugin/db/entities/Unique.ts +21 -21
  192. package/server/plugin/db/reset.ts +12 -12
  193. package/server/plugin/db/setup.ts +49 -49
  194. package/server/plugin/global.ts +16 -16
  195. package/server/plugin/importer.ts +16 -16
  196. package/server/plugin/index.ts +9 -9
  197. package/server/plugin/logger.ts +23 -23
  198. package/server/plugin/nav/node.ts +27 -27
  199. package/server/plugin/nav/utils.ts +179 -175
  200. package/server/plugin/repository/book.ts +23 -21
  201. package/server/plugin/repository/content.ts +240 -240
  202. package/server/plugin/repository/contentId.ts +40 -40
  203. package/server/plugin/repository/contributor.ts +8 -8
  204. package/server/plugin/repository/file.ts +10 -10
  205. package/server/plugin/repository/frontNav.ts +145 -145
  206. package/server/plugin/repository/topic.ts +35 -35
  207. package/server/tsconfig.json +9 -9
  208. package/shared/aside/minor.ts +51 -51
  209. package/shared/asset.ts +22 -22
  210. package/shared/bitran/contentId.ts +56 -56
  211. package/shared/bitran/stringContent.ts +6 -6
  212. package/shared/bitran/toc.ts +8 -8
  213. package/shared/content/bookId.ts +12 -12
  214. package/shared/content/context.ts +9 -9
  215. package/shared/content/data/base.ts +32 -32
  216. package/shared/content/data/index.ts +5 -5
  217. package/shared/content/data/type/book.ts +5 -5
  218. package/shared/content/data/type/group.ts +6 -6
  219. package/shared/content/data/type/topic.ts +11 -11
  220. package/shared/content/previousNext.ts +9 -9
  221. package/shared/contributor.ts +5 -5
  222. package/shared/frontNav.ts +41 -41
  223. package/shared/icons.ts +38 -38
  224. package/shared/image.ts +5 -5
  225. package/shared/link.ts +28 -28
  226. package/shared/popover.ts +8 -8
  227. package/shared/types/language.ts +74 -74
  228. package/shared/utils/objectsEqual.ts +4 -4
  229. package/shared/utils/stringColor.ts +9 -9
  230. package/test/contentId.test.ts +91 -91
  231. package/tsconfig.json +8 -8
  232. package/utils/contentPath.ts +67 -67
  233. package/utils/slash.ts +11 -11
  234. package/utils/stress.ts +9 -9
@@ -1,61 +1,61 @@
1
- import {
2
- stringifyBitranLocation,
3
- type BitranContext,
4
- } from '@erudit-js/cog/schema';
5
-
6
- import { getLocationContext } from '@server/content/context';
7
- import { ERUDIT_SERVER } from '@server/global';
8
- import { DbUnique } from '@server/db/entities/Unique';
9
- import { getBitranContent } from '@server/bitran/content';
10
- import { parseClientBitranLocation } from '@server/bitran/location';
11
-
12
- import type { Context } from '@shared/content/context';
13
- import type { StringBitranContent } from '@erudit/shared/bitran/stringContent';
14
-
15
- interface ReturnType {
16
- context: Context;
17
- productTitle?: string;
18
- bitran: {
19
- productName: string;
20
- context: BitranContext;
21
- content: StringBitranContent;
22
- };
23
- }
24
-
25
- export default defineEventHandler<Promise<ReturnType>>(async (event) => {
26
- setResponseHeader(event, 'Content-Type', 'application/json; charset=utf-8');
27
-
28
- const location = await parseClientBitranLocation(
29
- event.context.params!.location,
30
- );
31
-
32
- const context = await getLocationContext(location);
33
-
34
- const dbUnique = await (async () => {
35
- const dbUnique = ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
36
- select: ['productName', 'title', 'context'],
37
- where: { location: stringifyBitranLocation(location) },
38
- });
39
-
40
- if (!dbUnique)
41
- throw createError(
42
- `Missing unique "${stringifyBitranLocation(location)}"!`,
43
- );
44
-
45
- return dbUnique as any as DbUnique;
46
- })();
47
-
48
- const bitran = await (async () => {
49
- return {
50
- content: await getBitranContent(location),
51
- context: dbUnique.context,
52
- productName: dbUnique.productName,
53
- };
54
- })();
55
-
56
- return <ReturnType>{
57
- context,
58
- productTitle: dbUnique.title,
59
- bitran,
60
- };
61
- });
1
+ import {
2
+ stringifyBitranLocation,
3
+ type BitranContext,
4
+ } from '@erudit-js/cog/schema';
5
+
6
+ import { getLocationContext } from '@server/content/context';
7
+ import { ERUDIT_SERVER } from '@server/global';
8
+ import { DbUnique } from '@server/db/entities/Unique';
9
+ import { getBitranContent } from '@server/bitran/content';
10
+ import { parseClientBitranLocation } from '@server/bitran/location';
11
+
12
+ import type { Context } from '@shared/content/context';
13
+ import type { StringBitranContent } from '@erudit/shared/bitran/stringContent';
14
+
15
+ interface ReturnType {
16
+ context: Context;
17
+ productTitle?: string;
18
+ bitran: {
19
+ productName: string;
20
+ context: BitranContext;
21
+ content: StringBitranContent;
22
+ };
23
+ }
24
+
25
+ export default defineEventHandler<Promise<ReturnType>>(async (event) => {
26
+ setResponseHeader(event, 'Content-Type', 'application/json; charset=utf-8');
27
+
28
+ const location = await parseClientBitranLocation(
29
+ event.context.params!.location,
30
+ );
31
+
32
+ const context = await getLocationContext(location);
33
+
34
+ const dbUnique = await (async () => {
35
+ const dbUnique = ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
36
+ select: ['productName', 'title', 'context'],
37
+ where: { location: stringifyBitranLocation(location) },
38
+ });
39
+
40
+ if (!dbUnique)
41
+ throw createError(
42
+ `Missing unique "${stringifyBitranLocation(location)}"!`,
43
+ );
44
+
45
+ return dbUnique as any as DbUnique;
46
+ })();
47
+
48
+ const bitran = await (async () => {
49
+ return {
50
+ content: await getBitranContent(location),
51
+ context: dbUnique.context,
52
+ productName: dbUnique.productName,
53
+ };
54
+ })();
55
+
56
+ return <ReturnType>{
57
+ context,
58
+ productTitle: dbUnique.title,
59
+ bitran,
60
+ };
61
+ });
@@ -1,190 +1,237 @@
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
-
23
- import { ERUDIT_SERVER } from '@server/global';
24
- import { DbUnique } from '@server/db/entities/Unique';
25
- import { DbTopic } from '@server/db/entities/Topic';
26
- import { DbGroup } from '@server/db/entities/Group';
27
- import { traverseInclude } from '@server/bitran/elements/include';
28
- import { createBitranTranspiler } from '@server/bitran/transpiler';
29
- import { logger } from '@server/logger';
30
-
31
- import type { StringBitranContent } from '@shared/bitran/stringContent';
32
-
33
- interface RawBitranContent {
34
- context: BitranContext;
35
- biCode: string;
36
- }
37
-
38
- export async function getBitranContent(
39
- location: BitranLocation,
40
- generatePrerenderData: boolean = true,
41
- ): Promise<StringBitranContent> {
42
- const rawContent = await getRawBitranContent(location);
43
- const bitranContent = await createBitranContent(
44
- rawContent.context,
45
- rawContent.biCode,
46
- generatePrerenderData,
47
- );
48
- return bitranContent;
49
- }
50
-
51
- export async function getRawBitranContent(
52
- location: BitranLocation,
53
- ): Promise<RawBitranContent> {
54
- const throwNotFound = () => {
55
- throw createError({
56
- statusCode: 404,
57
- statusText: `Can't find content for location "${stringifyBitranLocation(location)}"!`,
58
- });
59
- };
60
-
61
- if (location.unique) {
62
- const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
63
- where: { location: stringifyBitranLocation(location) },
64
- });
65
-
66
- if (!dbUnique) throwNotFound();
67
-
68
- return {
69
- biCode: dbUnique!.content,
70
- context: dbUnique!.context,
71
- };
72
- }
73
-
74
- if (isTopicPart(location.type)) {
75
- const topicPart = location.type as TopicPart;
76
-
77
- const dbTopic = await ERUDIT_SERVER.DB.manager.findOne(DbTopic, {
78
- select: ['contentId', topicPart],
79
- where: { contentId: location.path },
80
- });
81
-
82
- if (!dbTopic) throwNotFound();
83
-
84
- return {
85
- biCode: dbTopic![topicPart]!,
86
- context: { location, aliases: NO_ALIASES() },
87
- };
88
- }
89
-
90
- if (location.type === 'group') {
91
- const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
92
- select: ['contentId', 'content'],
93
- where: { contentId: location.path },
94
- });
95
-
96
- if (!dbGroup) throwNotFound();
97
-
98
- return {
99
- biCode: dbGroup!.content!,
100
- context: { location, aliases: NO_ALIASES() },
101
- };
102
- }
103
-
104
- return throwNotFound();
105
- }
106
-
107
- async function createBitranContent(
108
- context: BitranContext,
109
- biCode: string,
110
- generatePrerenderData: boolean = true,
111
- ): Promise<StringBitranContent> {
112
- const runtime: EruditBitranRuntime = {
113
- eruditConfig: ERUDIT_SERVER.CONFIG,
114
- insideInclude: false,
115
- context,
116
- };
117
-
118
- const bitranTranspiler = await createBitranTranspiler(runtime);
119
-
120
- const renderDataStorage: RenderDataStorage = {};
121
-
122
- async function makePreRender(node: ElementNode) {
123
- if (generatePrerenderData === false) {
124
- return;
125
- }
126
-
127
- const transpiler = bitranTranspiler.transpilers[node.name];
128
- await createRenderData({
129
- storage: renderDataStorage,
130
- node,
131
- extra: runtime,
132
- generator: transpiler?.renderDataGenerator,
133
- });
134
- }
135
-
136
- const root = await bitranTranspiler.parser.parse(biCode, {
137
- async step(node) {
138
- switch (true) {
139
- case node instanceof AliasesNode:
140
- mergeAliases(context.aliases, node.parseData);
141
- break;
142
- case node instanceof IncludeNode:
143
- const includeNode = await resolveInclude(node, context);
144
- await walkDown(includeNode, async (child) => {
145
- if (child instanceof ElementNode) {
146
- await makePreRender(child);
147
- }
148
- });
149
- break;
150
- case node instanceof BlockErrorNode:
151
- case node instanceof InlinerErrorNode:
152
- logParseError(node.name, node.error);
153
- return;
154
- }
155
-
156
- await makePreRender(node);
157
- },
158
- });
159
-
160
- const finalContent = await bitranTranspiler.stringifier.stringify(root);
161
-
162
- return {
163
- biCode: finalContent,
164
- renderDataStorage,
165
- };
166
- }
167
-
168
- async function resolveInclude(
169
- includeNode: IncludeNode,
170
- context: BitranContext,
171
- ): Promise<IncludeNode> {
172
- let _blocks;
173
-
174
- try {
175
- const blocks = await traverseInclude(includeNode, context, {});
176
- const blocksNode = new BlocksNode(includeNode);
177
- blocksNode.setNodes(blocks);
178
- _blocks = blocksNode;
179
- includeNode.parseData.blocks = _blocks;
180
- } catch (error: any) {
181
- includeNode.parseData.error = error?.message || error;
182
- }
183
-
184
- includeNode.parseData.resolved = true;
185
- return includeNode;
186
- }
187
-
188
- function logParseError(nodeName: string, error: string) {
189
- logger.warn(`Error parsing "${nodeName}" element!\n\n${error}`);
190
- }
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 { traverseInclude } from '@server/bitran/elements/include';
38
+ import { createBitranTranspiler } from '@server/bitran/transpiler';
39
+ import { logger } from '@server/logger';
40
+
41
+ import type { StringBitranContent } from '@shared/bitran/stringContent';
42
+
43
+ interface RawBitranContent {
44
+ context: BitranContext;
45
+ biCode: string;
46
+ }
47
+
48
+ export type EruditBitranContent = StringBitranContent & {
49
+ routes: string[];
50
+ };
51
+
52
+ export async function getBitranContent(
53
+ location: BitranLocation,
54
+ generatePrerenderData: boolean = true,
55
+ ): Promise<StringBitranContent> {
56
+ const rawContent = await getRawBitranContent(location);
57
+ const bitranContent = await createBitranContent(
58
+ rawContent.context,
59
+ rawContent.biCode,
60
+ generatePrerenderData,
61
+ );
62
+ return bitranContent;
63
+ }
64
+
65
+ export async function getRawBitranContent(
66
+ location: BitranLocation,
67
+ ): Promise<RawBitranContent> {
68
+ const throwNotFound = () => {
69
+ throw createError({
70
+ statusCode: 404,
71
+ statusText: `Can't find content for location "${stringifyBitranLocation(location)}"!`,
72
+ });
73
+ };
74
+
75
+ if (location.unique) {
76
+ const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
77
+ where: { location: stringifyBitranLocation(location) },
78
+ });
79
+
80
+ if (!dbUnique) throwNotFound();
81
+
82
+ return {
83
+ biCode: dbUnique!.content,
84
+ context: dbUnique!.context,
85
+ };
86
+ }
87
+
88
+ if (isTopicPart(location.type)) {
89
+ const topicPart = location.type as TopicPart;
90
+
91
+ const dbTopic = await ERUDIT_SERVER.DB.manager.findOne(DbTopic, {
92
+ select: ['contentId', topicPart],
93
+ where: { contentId: location.path },
94
+ });
95
+
96
+ if (!dbTopic) throwNotFound();
97
+
98
+ return {
99
+ biCode: dbTopic![topicPart]!,
100
+ context: { location, aliases: NO_ALIASES() },
101
+ };
102
+ }
103
+
104
+ if (location.type === 'group') {
105
+ const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
106
+ select: ['contentId', 'content'],
107
+ where: { contentId: location.path },
108
+ });
109
+
110
+ if (!dbGroup) throwNotFound();
111
+
112
+ return {
113
+ biCode: dbGroup!.content!,
114
+ context: { location, aliases: NO_ALIASES() },
115
+ };
116
+ }
117
+
118
+ return throwNotFound();
119
+ }
120
+
121
+ async function createBitranContent(
122
+ context: BitranContext,
123
+ biCode: string,
124
+ generatePrerenderData: boolean = true,
125
+ ): Promise<EruditBitranContent> {
126
+ const runtime: EruditBitranRuntime = {
127
+ eruditConfig: ERUDIT_SERVER.CONFIG,
128
+ insideInclude: false,
129
+ context,
130
+ };
131
+
132
+ const bitranTranspiler = await createBitranTranspiler(runtime);
133
+
134
+ const renderDataStorage: RenderDataStorage = {};
135
+
136
+ const routes: string[] = [];
137
+ const addRoute = (
138
+ newRoutes: string | undefined | (string | undefined)[],
139
+ ) => {
140
+ if (Array.isArray(newRoutes)) {
141
+ routes.push(...(newRoutes.filter(Boolean) as string[]));
142
+ } else if (newRoutes) {
143
+ routes.push(newRoutes);
144
+ }
145
+ };
146
+
147
+ async function setNodeRenderData(node: ElementNode) {
148
+ if (generatePrerenderData === false) {
149
+ return;
150
+ }
151
+
152
+ const transpiler = bitranTranspiler.transpilers[node.name];
153
+
154
+ const renderDataResult = await createRenderData({
155
+ storage: renderDataStorage,
156
+ node,
157
+ extra: runtime,
158
+ generator: transpiler?.renderDataGenerator,
159
+ });
160
+
161
+ if (renderDataResult?.type === 'success') {
162
+ node.renderData = renderDataResult.data;
163
+ }
164
+ }
165
+
166
+ async function addNodePrerenderRoute(node: ElementNode) {
167
+ switch (true) {
168
+ case node instanceof ProblemNode:
169
+ addRoute(prerenderProblem(node));
170
+ break;
171
+ case node instanceof ProblemsNode:
172
+ addRoute(await prerenderProblems(node, runtime));
173
+ break;
174
+ case node instanceof LinkNode:
175
+ addRoute(prerenderLink(node, runtime));
176
+ break;
177
+ }
178
+ }
179
+
180
+ const root = await bitranTranspiler.parser.parse(biCode, {
181
+ async step(node) {
182
+ switch (true) {
183
+ case node instanceof BlockErrorNode:
184
+ case node instanceof InlinerErrorNode:
185
+ logParseError(node.name, node.error);
186
+ return;
187
+ case node instanceof AliasesNode:
188
+ mergeAliases(context.aliases, node.parseData);
189
+ break;
190
+ case node instanceof IncludeNode:
191
+ const includeNode = await resolveInclude(node, context);
192
+ await walkDown(includeNode, async (child) => {
193
+ if (child instanceof ElementNode) {
194
+ await setNodeRenderData(child);
195
+ await addNodePrerenderRoute(child);
196
+ }
197
+ });
198
+ break;
199
+ }
200
+
201
+ await setNodeRenderData(node);
202
+ await addNodePrerenderRoute(node);
203
+ },
204
+ });
205
+
206
+ const finalContent = await bitranTranspiler.stringifier.stringify(root);
207
+
208
+ return {
209
+ biCode: finalContent,
210
+ renderDataStorage,
211
+ routes,
212
+ };
213
+ }
214
+
215
+ async function resolveInclude(
216
+ includeNode: IncludeNode,
217
+ context: BitranContext,
218
+ ): Promise<IncludeNode> {
219
+ let _blocks;
220
+
221
+ try {
222
+ const blocks = await traverseInclude(includeNode, context, {});
223
+ const blocksNode = new BlocksNode(includeNode);
224
+ blocksNode.setNodes(blocks);
225
+ _blocks = blocksNode;
226
+ includeNode.parseData.blocks = _blocks;
227
+ } catch (error: any) {
228
+ includeNode.parseData.error = error?.message || error;
229
+ }
230
+
231
+ includeNode.parseData.resolved = true;
232
+ return includeNode;
233
+ }
234
+
235
+ function logParseError(nodeName: string, error: string) {
236
+ logger.warn(`Error parsing "${nodeName}" element!\n\n${error}`);
237
+ }