erudit 2.0.0-dev.9 → 3.0.0-dev.2

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 (237) hide show
  1. package/app/app.vue +172 -172
  2. package/app/components/Loading.vue +23 -23
  3. package/app/components/SiteAside.vue +382 -382
  4. package/app/components/SiteMain.vue +35 -35
  5. package/app/components/ads/BannerTemplate.vue +51 -51
  6. package/app/components/ads/BottomBanner.vue +45 -45
  7. package/app/components/ads/LeftBanner.vue +50 -50
  8. package/app/components/aside/AsideListItem.vue +74 -74
  9. package/app/components/aside/AsideMajor.vue +56 -56
  10. package/app/components/aside/AsideMinor.vue +71 -71
  11. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  12. package/app/components/aside/major/PaneSwitch.vue +54 -54
  13. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  14. package/app/components/aside/major/SiteInfo.vue +85 -85
  15. package/app/components/aside/major/panes/Language.vue +79 -79
  16. package/app/components/aside/major/panes/Pages.vue +34 -34
  17. package/app/components/aside/major/panes/Search.vue +11 -3
  18. package/app/components/aside/major/panes/nav/Nav.vue +91 -91
  19. package/app/components/aside/major/panes/nav/NavBook.vue +86 -86
  20. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  21. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  22. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  23. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  24. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  25. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  26. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  27. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  28. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  29. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  30. package/app/components/aside/major/panes/other/ItemGenerator.vue +15 -15
  31. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  32. package/app/components/aside/major/panes/other/Other.vue +16 -16
  33. package/app/components/aside/minor/AsideMinorContributor.vue +5 -5
  34. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  35. package/app/components/aside/minor/AsideMinorPane.vue +15 -16
  36. package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
  37. package/app/components/aside/minor/Contribute.vue +145 -145
  38. package/app/components/aside/minor/content/AsideMinorContent.vue +92 -92
  39. package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -32
  40. package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
  41. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  42. package/app/components/aside/minor/topic/TopicToc.vue +203 -203
  43. package/app/components/aside/minor/topic/TopicTocItem.vue +31 -31
  44. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  45. package/app/components/bitran/BitranContent.vue +63 -63
  46. package/app/components/bitran/RenderWrapper.vue +10 -10
  47. package/app/components/contributor/ContributorAvatar.vue +43 -43
  48. package/app/components/contributor/ContributorListItem.vue +35 -35
  49. package/app/components/main/topic/MainTopic.vue +79 -79
  50. package/app/components/main/topic/TopicPartSwitch.vue +118 -118
  51. package/app/components/main/utils/Breadcrumb.vue +75 -75
  52. package/app/components/main/utils/ContentDecoration.vue +29 -29
  53. package/app/components/main/utils/ContentDescription.vue +19 -20
  54. package/app/components/main/utils/ContentFlag.vue +15 -16
  55. package/app/components/main/utils/ContentPopover.vue +176 -176
  56. package/app/components/main/utils/ContentPopovers.vue +105 -105
  57. package/app/components/main/utils/ContentReferences.vue +70 -76
  58. package/app/components/main/utils/ContentSection.vue +45 -42
  59. package/app/components/main/utils/ContentTitle.vue +39 -37
  60. package/app/components/main/utils/reference/ReferenceGroup.vue +38 -41
  61. package/app/components/main/utils/reference/ReferenceItem.vue +68 -64
  62. package/app/components/main/utils/reference/ReferenceSource.vue +116 -110
  63. package/app/components/preview/Preview.vue +177 -177
  64. package/app/components/preview/PreviewDisplay.vue +139 -139
  65. package/app/components/preview/PreviewFooterAction.vue +73 -73
  66. package/app/components/preview/PreviewLoading.vue +14 -15
  67. package/app/components/preview/PreviewScreen.vue +99 -99
  68. package/app/components/preview/display/Alert.vue +50 -50
  69. package/app/components/preview/display/Custom.vue +18 -18
  70. package/app/components/preview/display/GenericLink.vue +48 -48
  71. package/app/components/preview/display/PageLink.vue +20 -20
  72. package/app/components/preview/display/Unique.vue +49 -49
  73. package/app/components/transition/Fade.vue +19 -22
  74. package/app/components/tree/TreeContainer.vue +11 -12
  75. package/app/components/tree/TreeItem.vue +89 -89
  76. package/app/composables/bitran.ts +127 -127
  77. package/app/composables/bitranContent.ts +37 -37
  78. package/app/composables/bitranLocation.ts +7 -7
  79. package/app/composables/contentData.ts +36 -36
  80. package/app/composables/contentPage.ts +156 -156
  81. package/app/composables/contentRoute.ts +45 -45
  82. package/app/composables/darkMagic.ts +24 -24
  83. package/app/composables/externalApi.ts +63 -63
  84. package/app/composables/favicon.ts +8 -8
  85. package/app/composables/formatText.ts +86 -86
  86. package/app/composables/majorPane.ts +60 -60
  87. package/app/composables/phrases.ts +80 -80
  88. package/app/composables/theme.ts +29 -29
  89. package/app/composables/url.ts +33 -33
  90. package/app/pages/_test/preview.vue +110 -110
  91. package/app/pages/article/[...articleId].vue +3 -3
  92. package/app/pages/book/[...bookId].vue +47 -47
  93. package/app/pages/group/[...groupId].vue +65 -65
  94. package/app/pages/index.vue +32 -32
  95. package/app/pages/members.vue +6 -7
  96. package/app/pages/practice/[...practice].vue +3 -3
  97. package/app/pages/summary/[...summaryId].vue +3 -3
  98. package/app/scripts/_immediate.js +9 -4
  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 +73 -84
  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 +20 -20
  110. package/app/scripts/preview/data/unique.ts +70 -70
  111. package/app/scripts/preview/data.ts +24 -26
  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 -3
  117. package/app/styles/_util.scss +43 -50
  118. package/app/styles/_utils.scss +44 -44
  119. package/app/styles/app.scss +91 -91
  120. package/app/styles/def/_bp.scss +27 -24
  121. package/app/styles/def/_size.scss +7 -7
  122. package/app/styles/def/_z.scss +5 -5
  123. package/app/styles/default.scss +83 -85
  124. package/app/styles/normalize.scss +63 -63
  125. package/app/styles/partials/_darkMagic.scss +5 -7
  126. package/app/styles/partials/_fnav.scss +15 -18
  127. package/app/styles/partials/_preview.scss +5 -7
  128. package/globalPath.ts +21 -21
  129. package/globals/bitran.ts +47 -47
  130. package/globals/content.ts +22 -22
  131. package/globals/contributor.ts +5 -5
  132. package/globals/erudit.ts +5 -5
  133. package/globals/register.ts +18 -18
  134. package/languages/en.ts +95 -95
  135. package/languages/ru.ts +99 -99
  136. package/module/bitran.ts +34 -34
  137. package/module/config.ts +34 -34
  138. package/module/imports.ts +46 -46
  139. package/module/index.ts +47 -47
  140. package/module/logger.ts +10 -10
  141. package/module/paths.ts +22 -22
  142. package/module/restart.ts +61 -61
  143. package/nuxt.config.ts +112 -107
  144. package/package.json +3 -3
  145. package/server/api/aside/major/nav/bookIds.ts +5 -5
  146. package/server/api/aside/major/nav/bookNav/[...bookId].ts +20 -20
  147. package/server/api/aside/major/nav/global.ts +7 -7
  148. package/server/api/aside/minor/news.ts +7 -7
  149. package/server/api/aside/minor/path.ts +78 -78
  150. package/server/api/bitran/content/[location].ts +7 -7
  151. package/server/api/bitran/toc/[location].ts +7 -7
  152. package/server/api/content/data.ts +72 -72
  153. package/server/api/contributor/count.ts +6 -6
  154. package/server/api/fake/content.ts +11 -11
  155. package/server/api/fake/shared/languages.ts +12 -12
  156. package/server/api/language/functions.ts +12 -12
  157. package/server/api/language/phrase/[phraseId].ts +19 -19
  158. package/server/api/language/phraseIds.ts +8 -8
  159. package/server/api/preview/page/[...parts].ts +51 -51
  160. package/server/api/preview/unique/[location].ts +55 -55
  161. package/server/plugin/bitran/content.ts +187 -187
  162. package/server/plugin/bitran/location.ts +25 -25
  163. package/server/plugin/bitran/products/include.ts +230 -230
  164. package/server/plugin/bitran/products/link.ts +116 -116
  165. package/server/plugin/bitran/setup.ts +9 -9
  166. package/server/plugin/bitran/toc.ts +83 -83
  167. package/server/plugin/bitran/transpiler.ts +46 -46
  168. package/server/plugin/build/close.ts +10 -10
  169. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  170. package/server/plugin/build/jobs/content/generic.ts +176 -176
  171. package/server/plugin/build/jobs/content/parse.ts +100 -100
  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 +210 -209
  179. package/server/plugin/build/process.ts +25 -25
  180. package/server/plugin/build/rebuild.ts +55 -55
  181. package/server/plugin/build/setup.ts +21 -21
  182. package/server/plugin/content/absoluteId.ts +94 -94
  183. package/server/plugin/content/context.ts +112 -112
  184. package/server/plugin/db/entities/Book.ts +7 -7
  185. package/server/plugin/db/entities/Content.ts +49 -49
  186. package/server/plugin/db/entities/Contribution.ts +10 -10
  187. package/server/plugin/db/entities/Contributor.ts +16 -16
  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/setup.ts +34 -34
  193. package/server/plugin/global.ts +18 -18
  194. package/server/plugin/importer.ts +12 -12
  195. package/server/plugin/index.ts +9 -9
  196. package/server/plugin/logger.ts +23 -23
  197. package/server/plugin/nav/node.ts +26 -26
  198. package/server/plugin/nav/utils.ts +129 -129
  199. package/server/plugin/repository/book.ts +21 -21
  200. package/server/plugin/repository/content.ts +238 -238
  201. package/server/plugin/repository/contributor.ts +8 -8
  202. package/server/plugin/repository/frontNav.ts +148 -148
  203. package/server/plugin/repository/topic.ts +32 -32
  204. package/server/tsconfig.json +9 -7
  205. package/shared/aside/minor.ts +50 -50
  206. package/shared/asset.ts +15 -15
  207. package/shared/bitran/context.ts +8 -8
  208. package/shared/bitran/default.ts +46 -46
  209. package/shared/bitran/link/Link.vue +167 -167
  210. package/shared/bitran/link/factory.ts +24 -24
  211. package/shared/bitran/link/languages/en.ts +7 -7
  212. package/shared/bitran/link/languages/ru.ts +7 -7
  213. package/shared/bitran/link/renderer.ts +21 -21
  214. package/shared/bitran/link/shared.ts +17 -17
  215. package/shared/bitran/link/target.ts +134 -134
  216. package/shared/bitran/link/transpiler.ts +10 -10
  217. package/shared/bitran/location.ts +166 -166
  218. package/shared/bitran/toc.ts +8 -8
  219. package/shared/content/context.ts +9 -9
  220. package/shared/content/data/base.ts +32 -32
  221. package/shared/content/data/index.ts +5 -5
  222. package/shared/content/data/type/book.ts +5 -5
  223. package/shared/content/data/type/group.ts +6 -6
  224. package/shared/content/data/type/topic.ts +11 -11
  225. package/shared/content/previousNext.ts +9 -9
  226. package/shared/contributor.ts +5 -5
  227. package/shared/frontNav.ts +41 -41
  228. package/shared/icons.ts +38 -38
  229. package/shared/image.ts +5 -5
  230. package/shared/link.ts +25 -25
  231. package/shared/types/language.ts +75 -75
  232. package/shared/utils/objectsEqual.ts +4 -4
  233. package/shared/utils/stringColor.ts +9 -9
  234. package/test/bitran/link/target.test.ts +141 -141
  235. package/test/bitran/location.test.ts +143 -143
  236. package/tsconfig.json +8 -8
  237. package/utils/stress.ts +9 -9
@@ -1,176 +1,176 @@
1
- import { existsSync } from 'node:fs';
2
- import { globSync } from 'glob';
3
- import chalk from 'chalk';
4
- import sizeOf from 'image-size';
5
- import {
6
- contentTypes,
7
- type ContentConfig,
8
- type ContentReferences,
9
- type ContentType,
10
- } from 'erudit-cog/schema';
11
- import { resolvePaths } from 'erudit-cog/kit';
12
-
13
- import { PROJECT_DIR } from '#erudit/globalPaths';
14
- import { stress } from '@erudit/utils/stress';
15
-
16
- import { debug, logger } from '@server/logger';
17
- import { ERUDIT_SERVER } from '@server/global';
18
- import { walkNav } from '@server/nav/utils';
19
- import { isRootNode, type NavNode } from '@server/nav/node';
20
- import { DbContent } from '@server/db/entities/Content';
21
- import { IMPORT } from '@server/importer';
22
- import { contributorExists } from '@server/repository/contributor';
23
- import { DbContribution } from '@server/db/entities/Contribution';
24
-
25
- import { contentAsset } from '@erudit/shared/asset';
26
- import type { ImageData } from '@erudit/shared/image';
27
-
28
- import type { BuilderFunctionArgs } from './builderArgs';
29
- import { contentItemPath } from './path';
30
- import { buildBook } from './type/book';
31
- import { buildGroup } from './type/group';
32
- import { buildTopic } from './type/topic';
33
-
34
- const typeBuilders: Record<ContentType, Function> = {
35
- book: buildBook,
36
- group: buildGroup,
37
- topic: buildTopic,
38
- };
39
-
40
- export async function buildContent() {
41
- if (!ERUDIT_SERVER.NAV) return;
42
-
43
- debug.start('Building content...');
44
-
45
- const counters: Record<ContentType, number> = Object.fromEntries(
46
- contentTypes.map((contentType) => [contentType, 0]),
47
- ) as any;
48
-
49
- await walkNav(async (node) => {
50
- if (isRootNode(node)) return;
51
- counters[node.type]++;
52
- await addContentItem(node);
53
- });
54
-
55
- logger.success(
56
- 'Content built successfully!',
57
- chalk.dim(
58
- '(' +
59
- Object.entries(counters)
60
- .map(([k, v]) => `${k.at(0)!.toUpperCase()}: ${v}`)
61
- .join(', ') +
62
- ')',
63
- ),
64
- );
65
- }
66
-
67
- async function addContentItem(navNode: NavNode) {
68
- debug.start(
69
- `Adding ${stress(navNode.type)} content item ${stress(navNode.id)}...`,
70
- );
71
-
72
- const dbContent = new DbContent();
73
- dbContent.contentId = navNode.id;
74
- dbContent.fullId = navNode.fullId;
75
- dbContent.type = navNode.type;
76
- dbContent.decoration = getDecoration(navNode);
77
- dbContent.ogImage = getOgImageData(navNode);
78
- dbContent.references = await getContentReferences(navNode);
79
-
80
- let config: Partial<ContentConfig> | undefined;
81
-
82
- try {
83
- config = (await IMPORT(contentItemPath(navNode, navNode.type), {
84
- default: true,
85
- })) as Partial<ContentConfig>;
86
-
87
- dbContent.title = config.title;
88
- dbContent.navTitle = config.navTitle;
89
- dbContent.description = config.description;
90
- dbContent.flags = config.flags;
91
- dbContent.dependencies = config.dependencies;
92
-
93
- if (config.seo) {
94
- dbContent.seo = {
95
- title: config.seo?.title,
96
- description: config.seo?.description,
97
- };
98
- }
99
-
100
- await addContributions(navNode, config.contributors);
101
- } catch {}
102
-
103
- await ERUDIT_SERVER.DB.manager.save(dbContent);
104
-
105
- await typeBuilders[navNode.type](<BuilderFunctionArgs>{
106
- navNode,
107
- dbContent,
108
- config,
109
- });
110
- }
111
-
112
- function getDecoration(navNode: NavNode) {
113
- if (existsSync(contentItemPath(navNode, 'decoration.svg')))
114
- return `/${navNode.path}/decoration.svg`;
115
-
116
- return undefined;
117
- }
118
-
119
- async function addContributions(navNode: NavNode, contributors?: string[]) {
120
- if (!contributors || !contributors.length) {
121
- if (navNode.type !== 'book' && navNode.type !== 'group')
122
- logger.warn(
123
- `${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.id)} has no contributors!`,
124
- );
125
-
126
- return;
127
- }
128
-
129
- for (const contributorId of contributors) {
130
- if (!(await contributorExists(contributorId))) {
131
- logger.warn(
132
- `Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.id)}!`,
133
- );
134
- continue;
135
- }
136
-
137
- const dbContribution = new DbContribution();
138
- dbContribution.contentId = navNode.id;
139
- dbContribution.contributorId = contributorId;
140
- await ERUDIT_SERVER.DB.manager.save(dbContribution);
141
- }
142
- }
143
-
144
- function getOgImageData(navNode: NavNode): ImageData | undefined {
145
- const ogImagePath = globSync(
146
- contentItemPath(navNode, 'og-image.{svg,webp,jpg,png}'),
147
- ).pop();
148
-
149
- if (ogImagePath) {
150
- const size = sizeOf(ogImagePath);
151
- return {
152
- src: contentAsset(
153
- resolvePaths(ogImagePath).replace(
154
- PROJECT_DIR + '/content/',
155
- '',
156
- ),
157
- ),
158
- width: size.width!,
159
- height: size.height!,
160
- };
161
- }
162
-
163
- return undefined;
164
- }
165
-
166
- async function getContentReferences(navNode: NavNode) {
167
- try {
168
- const references = await IMPORT(
169
- contentItemPath(navNode, `references`),
170
- { default: true },
171
- );
172
- return references as ContentReferences;
173
- } catch (error) {}
174
-
175
- return undefined;
176
- }
1
+ import { existsSync } from 'node:fs';
2
+ import { globSync } from 'glob';
3
+ import chalk from 'chalk';
4
+ import sizeOf from 'image-size';
5
+ import {
6
+ contentTypes,
7
+ type ContentConfig,
8
+ type ContentReferences,
9
+ type ContentType,
10
+ } from 'erudit-cog/schema';
11
+ import { resolvePaths } from 'erudit-cog/kit';
12
+
13
+ import { PROJECT_DIR } from '#erudit/globalPaths';
14
+ import { stress } from '@erudit/utils/stress';
15
+
16
+ import { debug, logger } from '@server/logger';
17
+ import { ERUDIT_SERVER } from '@server/global';
18
+ import { walkNav } from '@server/nav/utils';
19
+ import { isRootNode, type NavNode } from '@server/nav/node';
20
+ import { DbContent } from '@server/db/entities/Content';
21
+ import { IMPORT } from '@server/importer';
22
+ import { contributorExists } from '@server/repository/contributor';
23
+ import { DbContribution } from '@server/db/entities/Contribution';
24
+
25
+ import { contentAsset } from '@erudit/shared/asset';
26
+ import type { ImageData } from '@erudit/shared/image';
27
+
28
+ import type { BuilderFunctionArgs } from './builderArgs';
29
+ import { contentItemPath } from './path';
30
+ import { buildBook } from './type/book';
31
+ import { buildGroup } from './type/group';
32
+ import { buildTopic } from './type/topic';
33
+
34
+ const typeBuilders: Record<ContentType, Function> = {
35
+ book: buildBook,
36
+ group: buildGroup,
37
+ topic: buildTopic,
38
+ };
39
+
40
+ export async function buildContent() {
41
+ if (!ERUDIT_SERVER.NAV) return;
42
+
43
+ debug.start('Building content...');
44
+
45
+ const counters: Record<ContentType, number> = Object.fromEntries(
46
+ contentTypes.map((contentType) => [contentType, 0]),
47
+ ) as any;
48
+
49
+ await walkNav(async (node) => {
50
+ if (isRootNode(node)) return;
51
+ counters[node.type]++;
52
+ await addContentItem(node);
53
+ });
54
+
55
+ logger.success(
56
+ 'Content built successfully!',
57
+ chalk.dim(
58
+ '(' +
59
+ Object.entries(counters)
60
+ .map(([k, v]) => `${k.at(0)!.toUpperCase()}: ${v}`)
61
+ .join(', ') +
62
+ ')',
63
+ ),
64
+ );
65
+ }
66
+
67
+ async function addContentItem(navNode: NavNode) {
68
+ debug.start(
69
+ `Adding ${stress(navNode.type)} content item ${stress(navNode.id)}...`,
70
+ );
71
+
72
+ const dbContent = new DbContent();
73
+ dbContent.contentId = navNode.id;
74
+ dbContent.fullId = navNode.fullId;
75
+ dbContent.type = navNode.type;
76
+ dbContent.decoration = getDecoration(navNode);
77
+ dbContent.ogImage = getOgImageData(navNode);
78
+ dbContent.references = await getContentReferences(navNode);
79
+
80
+ let config: Partial<ContentConfig> | undefined;
81
+
82
+ try {
83
+ config = (await IMPORT(contentItemPath(navNode, navNode.type), {
84
+ default: true,
85
+ })) as Partial<ContentConfig>;
86
+
87
+ dbContent.title = config.title;
88
+ dbContent.navTitle = config.navTitle;
89
+ dbContent.description = config.description;
90
+ dbContent.flags = config.flags;
91
+ dbContent.dependencies = config.dependencies;
92
+
93
+ if (config.seo) {
94
+ dbContent.seo = {
95
+ title: config.seo?.title,
96
+ description: config.seo?.description,
97
+ };
98
+ }
99
+
100
+ await addContributions(navNode, config.contributors);
101
+ } catch {}
102
+
103
+ await ERUDIT_SERVER.DB.manager.save(dbContent);
104
+
105
+ await typeBuilders[navNode.type](<BuilderFunctionArgs>{
106
+ navNode,
107
+ dbContent,
108
+ config,
109
+ });
110
+ }
111
+
112
+ function getDecoration(navNode: NavNode) {
113
+ if (existsSync(contentItemPath(navNode, 'decoration.svg')))
114
+ return `/${navNode.path}/decoration.svg`;
115
+
116
+ return undefined;
117
+ }
118
+
119
+ async function addContributions(navNode: NavNode, contributors?: string[]) {
120
+ if (!contributors || !contributors.length) {
121
+ if (navNode.type !== 'book' && navNode.type !== 'group')
122
+ logger.warn(
123
+ `${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.id)} has no contributors!`,
124
+ );
125
+
126
+ return;
127
+ }
128
+
129
+ for (const contributorId of contributors) {
130
+ if (!(await contributorExists(contributorId))) {
131
+ logger.warn(
132
+ `Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.id)}!`,
133
+ );
134
+ continue;
135
+ }
136
+
137
+ const dbContribution = new DbContribution();
138
+ dbContribution.contentId = navNode.id;
139
+ dbContribution.contributorId = contributorId;
140
+ await ERUDIT_SERVER.DB.manager.save(dbContribution);
141
+ }
142
+ }
143
+
144
+ function getOgImageData(navNode: NavNode): ImageData | undefined {
145
+ const ogImagePath = globSync(
146
+ contentItemPath(navNode, 'og-image.{svg,webp,jpg,png}'),
147
+ ).pop();
148
+
149
+ if (ogImagePath) {
150
+ const size = sizeOf(ogImagePath);
151
+ return {
152
+ src: contentAsset(
153
+ resolvePaths(ogImagePath).replace(
154
+ PROJECT_DIR + '/content/',
155
+ '',
156
+ ),
157
+ ),
158
+ width: size.width!,
159
+ height: size.height!,
160
+ };
161
+ }
162
+
163
+ return undefined;
164
+ }
165
+
166
+ async function getContentReferences(navNode: NavNode) {
167
+ try {
168
+ const references = await IMPORT(
169
+ contentItemPath(navNode, `references`),
170
+ { default: true },
171
+ );
172
+ return references as ContentReferences;
173
+ } catch (error) {}
174
+
175
+ return undefined;
176
+ }
@@ -1,100 +1,100 @@
1
- import { ElementNode, walkForward } from '@bitran-js/core';
2
- import { type BitranTranspiler } from '@bitran-js/transpiler';
3
- import {
4
- AliasesNode,
5
- mergeAliases,
6
- NO_ALIASES,
7
- } from '@erudit-js/bitran-elements/aliases/shared';
8
- import { HeadingNode } from '@erudit-js/bitran-elements/heading/shared';
9
-
10
- import { createBitranTranspiler } from '@server/bitran/transpiler';
11
- import { ERUDIT_SERVER } from '@server/global';
12
- import { DbUnique } from '@server/db/entities/Unique';
13
-
14
- import type { BitranContext } from '@shared/bitran/context';
15
- import {
16
- stringifyBitranLocation,
17
- type BitranLocation,
18
- } from '@shared/bitran/location';
19
-
20
- let context: BitranContext = {} as any;
21
- let bitranTranspiler: BitranTranspiler;
22
-
23
- const blocksAfterHeading = 2;
24
-
25
- export async function parseBitranContent(
26
- location: BitranLocation,
27
- biCode: string,
28
- ) {
29
- // Reset Bitran context in order not to create core each time
30
- context.location = location;
31
- context.aliases = NO_ALIASES();
32
-
33
- bitranTranspiler ||= await createBitranTranspiler();
34
-
35
- // Tracking heading nodes to deal with them later
36
- const headings: HeadingNode[] = [];
37
-
38
- await bitranTranspiler.parser.parse(biCode, {
39
- async step(node) {
40
- const meta = node.meta;
41
- const uniqueId = meta?.id;
42
-
43
- if (node instanceof AliasesNode) {
44
- mergeAliases(context.aliases, node.parseData);
45
- }
46
-
47
- if (uniqueId) {
48
- if (node instanceof HeadingNode) {
49
- headings.push(node);
50
- return;
51
- }
52
-
53
- await addUnique(node);
54
- }
55
- },
56
- });
57
-
58
- for (const heading of headings) {
59
- let blocksAfter = 0;
60
- let content = await bitranTranspiler.stringifier.stringify(heading);
61
-
62
- await walkForward(heading, async (node) => {
63
- if (blocksAfter >= blocksAfterHeading) return false;
64
-
65
- if (node instanceof AliasesNode) return;
66
- // Spoiler
67
- // Todo
68
-
69
- content +=
70
- '\n\n' + (await bitranTranspiler.stringifier.stringify(node));
71
-
72
- blocksAfter++;
73
- });
74
-
75
- await addUnique(heading, content);
76
- }
77
-
78
- //
79
- //
80
- //
81
-
82
- function createUniqueLocation(node: ElementNode) {
83
- return stringifyBitranLocation({
84
- ...location,
85
- ...{ unique: node.meta.id! },
86
- });
87
- }
88
-
89
- async function addUnique(node: ElementNode, content?: string) {
90
- const dbUnique = new DbUnique();
91
- dbUnique.location = createUniqueLocation(node);
92
- dbUnique.content =
93
- content || (await bitranTranspiler.stringifier.stringify(node));
94
- dbUnique.title = node.parseData?.title || node.meta?.title;
95
- dbUnique.productName = node.name;
96
- dbUnique.context = context;
97
-
98
- await ERUDIT_SERVER.DB.manager.save(dbUnique);
99
- }
100
- }
1
+ import { ElementNode, walkForward } from '@bitran-js/core';
2
+ import { type BitranTranspiler } from '@bitran-js/transpiler';
3
+ import {
4
+ AliasesNode,
5
+ mergeAliases,
6
+ NO_ALIASES,
7
+ } from '@erudit-js/bitran-elements/aliases/shared';
8
+ import { HeadingNode } from '@erudit-js/bitran-elements/heading/shared';
9
+
10
+ import { createBitranTranspiler } from '@server/bitran/transpiler';
11
+ import { ERUDIT_SERVER } from '@server/global';
12
+ import { DbUnique } from '@server/db/entities/Unique';
13
+
14
+ import type { BitranContext } from '@shared/bitran/context';
15
+ import {
16
+ stringifyBitranLocation,
17
+ type BitranLocation,
18
+ } from '@shared/bitran/location';
19
+
20
+ let context: BitranContext = {} as any;
21
+ let bitranTranspiler: BitranTranspiler;
22
+
23
+ const blocksAfterHeading = 2;
24
+
25
+ export async function parseBitranContent(
26
+ location: BitranLocation,
27
+ biCode: string,
28
+ ) {
29
+ // Reset Bitran context in order not to create core each time
30
+ context.location = location;
31
+ context.aliases = NO_ALIASES();
32
+
33
+ bitranTranspiler ||= await createBitranTranspiler();
34
+
35
+ // Tracking heading nodes to deal with them later
36
+ const headings: HeadingNode[] = [];
37
+
38
+ await bitranTranspiler.parser.parse(biCode, {
39
+ async step(node) {
40
+ const meta = node.meta;
41
+ const uniqueId = meta?.id;
42
+
43
+ if (node instanceof AliasesNode) {
44
+ mergeAliases(context.aliases, node.parseData);
45
+ }
46
+
47
+ if (uniqueId) {
48
+ if (node instanceof HeadingNode) {
49
+ headings.push(node);
50
+ return;
51
+ }
52
+
53
+ await addUnique(node);
54
+ }
55
+ },
56
+ });
57
+
58
+ for (const heading of headings) {
59
+ let blocksAfter = 0;
60
+ let content = await bitranTranspiler.stringifier.stringify(heading);
61
+
62
+ await walkForward(heading, async (node) => {
63
+ if (blocksAfter >= blocksAfterHeading) return false;
64
+
65
+ if (node instanceof AliasesNode) return;
66
+ // Spoiler
67
+ // Todo
68
+
69
+ content +=
70
+ '\n\n' + (await bitranTranspiler.stringifier.stringify(node));
71
+
72
+ blocksAfter++;
73
+ });
74
+
75
+ await addUnique(heading, content);
76
+ }
77
+
78
+ //
79
+ //
80
+ //
81
+
82
+ function createUniqueLocation(node: ElementNode) {
83
+ return stringifyBitranLocation({
84
+ ...location,
85
+ ...{ unique: node.meta.id! },
86
+ });
87
+ }
88
+
89
+ async function addUnique(node: ElementNode, content?: string) {
90
+ const dbUnique = new DbUnique();
91
+ dbUnique.location = createUniqueLocation(node);
92
+ dbUnique.content =
93
+ content || (await bitranTranspiler.stringifier.stringify(node));
94
+ dbUnique.title = node.parseData?.title || node.meta?.title;
95
+ dbUnique.productName = node.name;
96
+ dbUnique.context = context;
97
+
98
+ await ERUDIT_SERVER.DB.manager.save(dbUnique);
99
+ }
100
+ }
@@ -1,6 +1,6 @@
1
- import { PROJECT_DIR } from '#erudit/globalPaths';
2
- import type { NavNode } from '@server/nav/node';
3
-
4
- export function contentItemPath(navNode: NavNode, path?: string) {
5
- return PROJECT_DIR + `/content/${navNode.path}${path ? '/' + path : ''}`;
6
- }
1
+ import { PROJECT_DIR } from '#erudit/globalPaths';
2
+ import type { NavNode } from '@server/nav/node';
3
+
4
+ export function contentItemPath(navNode: NavNode, path?: string) {
5
+ return PROJECT_DIR + `/content/${navNode.path}${path ? '/' + path : ''}`;
6
+ }
@@ -1,9 +1,9 @@
1
- import { DbBook } from '@server/db/entities/Book';
2
- import { ERUDIT_SERVER } from '@server/global';
3
- import type { BuilderFunctionArgs } from '../builderArgs';
4
-
5
- export async function buildBook({ dbContent }: BuilderFunctionArgs) {
6
- const dbBook = new DbBook();
7
- dbBook.contentId = dbContent.contentId;
8
- await ERUDIT_SERVER.DB.manager.save(dbBook);
9
- }
1
+ import { DbBook } from '@server/db/entities/Book';
2
+ import { ERUDIT_SERVER } from '@server/global';
3
+ import type { BuilderFunctionArgs } from '../builderArgs';
4
+
5
+ export async function buildBook({ dbContent }: BuilderFunctionArgs) {
6
+ const dbBook = new DbBook();
7
+ dbBook.contentId = dbContent.contentId;
8
+ await ERUDIT_SERVER.DB.manager.save(dbBook);
9
+ }
@@ -1,37 +1,37 @@
1
- import { readFileSync } from 'node:fs';
2
- import type { GroupConfig } from 'erudit-cog/schema';
3
-
4
- import { DbGroup } from '@server/db/entities/Group';
5
- import { ERUDIT_SERVER } from '@erudit/server/plugin/global';
6
- import type { BuilderFunctionArgs } from '../builderArgs';
7
- import { contentItemPath } from '../path';
8
- import { parseBitranContent } from '../parse';
9
-
10
- export async function buildGroup({
11
- navNode,
12
- config,
13
- }: BuilderFunctionArgs<GroupConfig>) {
14
- const dbGroup = new DbGroup();
15
- dbGroup.contentId = navNode.id;
16
- dbGroup.type = config?.type || 'folder';
17
-
18
- try {
19
- const strContent = readFileSync(
20
- contentItemPath(navNode, 'content.bi'),
21
- 'utf-8',
22
- );
23
-
24
- if (strContent) {
25
- dbGroup.content = strContent;
26
- await parseBitranContent(
27
- {
28
- type: 'group',
29
- path: navNode.id,
30
- },
31
- strContent,
32
- );
33
- }
34
- } catch {}
35
-
36
- await ERUDIT_SERVER.DB.manager.save(dbGroup);
37
- }
1
+ import { readFileSync } from 'node:fs';
2
+ import type { GroupConfig } from 'erudit-cog/schema';
3
+
4
+ import { DbGroup } from '@server/db/entities/Group';
5
+ import { ERUDIT_SERVER } from '@erudit/server/plugin/global';
6
+ import type { BuilderFunctionArgs } from '../builderArgs';
7
+ import { contentItemPath } from '../path';
8
+ import { parseBitranContent } from '../parse';
9
+
10
+ export async function buildGroup({
11
+ navNode,
12
+ config,
13
+ }: BuilderFunctionArgs<GroupConfig>) {
14
+ const dbGroup = new DbGroup();
15
+ dbGroup.contentId = navNode.id;
16
+ dbGroup.type = config?.type || 'folder';
17
+
18
+ try {
19
+ const strContent = readFileSync(
20
+ contentItemPath(navNode, 'content.bi'),
21
+ 'utf-8',
22
+ );
23
+
24
+ if (strContent) {
25
+ dbGroup.content = strContent;
26
+ await parseBitranContent(
27
+ {
28
+ type: 'group',
29
+ path: navNode.id,
30
+ },
31
+ strContent,
32
+ );
33
+ }
34
+ } catch {}
35
+
36
+ await ERUDIT_SERVER.DB.manager.save(dbGroup);
37
+ }