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
@@ -0,0 +1,9 @@
1
+ import { parseClientBitranLocation } from '@server/bitran/location';
2
+ import { getBitranToc } from '@server/bitran/toc';
3
+
4
+ export default defineEventHandler(async (event) => {
5
+ const location = await parseClientBitranLocation(
6
+ event.context.params!.location,
7
+ );
8
+ return await getBitranToc(location);
9
+ });
@@ -0,0 +1,42 @@
1
+ import { glob } from 'glob';
2
+ import { type Cameo } from '@erudit-js/cog/schema';
3
+
4
+ import { PROJECT_DIR } from '@erudit/globalPath';
5
+ import { IMPORT } from '@server/importer';
6
+
7
+ export default defineEventHandler<Promise<Cameo>>(async (event) => {
8
+ const cameoId = event.context.params?.cameoId;
9
+
10
+ if (typeof cameoId !== 'string' || !cameoId) {
11
+ throw createError({
12
+ statusCode: 400,
13
+ message: 'Cameo ID is required and must be a string!',
14
+ });
15
+ }
16
+
17
+ const avatarPaths = await glob(`cameos/${cameoId}/avatars/*`, {
18
+ cwd: PROJECT_DIR,
19
+ absolute: false,
20
+ posix: true,
21
+ });
22
+
23
+ const avatarRoutes = avatarPaths.map((path) => `/asset/${path}`);
24
+
25
+ let cameoConfig;
26
+ try {
27
+ cameoConfig = await IMPORT(`${PROJECT_DIR}/cameos/${cameoId}/cameo`, {
28
+ default: true,
29
+ });
30
+ } catch (error) {
31
+ throw createError({
32
+ statusCode: 500,
33
+ message: `Failed to import config for ID "${cameoId}"! Error: ${error}`,
34
+ });
35
+ }
36
+
37
+ return {
38
+ ...cameoConfig,
39
+ cameoId,
40
+ avatars: avatarRoutes,
41
+ } satisfies Cameo;
42
+ });
@@ -0,0 +1,5 @@
1
+ import { getCameoIds } from '@server/repository/cameo';
2
+
3
+ export default defineEventHandler(async () => {
4
+ return await getCameoIds();
5
+ });
@@ -1,72 +1,75 @@
1
- import { getTopicPartsLinks } from '@server/repository/topic';
2
- import { getContentBookFor } from '@server/repository/book';
3
- import { getContentGenericData } from '@server/repository/content';
4
-
5
- import type { ContentGenericData } from '@shared/content/data/base';
6
- import type { ContentTopicData } from '@shared/content/data/type/topic';
7
- import type { ContentGroupData } from '@shared/content/data/type/group';
8
- import type { ContentBookData } from '@shared/content/data/type/book';
9
-
10
- export default defineEventHandler(async (event) => {
11
- const contentId = getQuery(event)?.contentId as string;
12
-
13
- if (!contentId)
14
- throw createError({
15
- statusCode: 400,
16
- statusText: 'Missing content ID!',
17
- });
18
-
19
- const generic = await getContentGenericData(contentId);
20
-
21
- switch (generic.type) {
22
- case 'topic':
23
- return await getTopicData(generic);
24
- case 'group':
25
- return await getGroupData(generic);
26
- case 'book':
27
- return await getBookData(generic);
28
- }
29
-
30
- throw createError({
31
- statusCode: 400,
32
- statusText: `Unknown content data type "${generic.type}"!`,
33
- });
34
- });
35
-
36
- //
37
- //
38
- //
39
-
40
- async function getTopicData(
41
- generic: ContentGenericData,
42
- ): Promise<ContentTopicData> {
43
- const contentBook = await getContentBookFor(generic.contentId);
44
-
45
- return {
46
- type: 'topic',
47
- generic,
48
- bookTitle: contentBook?.title,
49
- topicPartLinks: await getTopicPartsLinks(generic.contentId),
50
- };
51
- }
52
-
53
- async function getGroupData(
54
- generic: ContentGenericData,
55
- ): Promise<ContentGroupData> {
56
- const contentBook = await getContentBookFor(generic.contentId);
57
-
58
- return {
59
- type: 'group',
60
- generic,
61
- bookTitle: contentBook?.title,
62
- };
63
- }
64
-
65
- async function getBookData(
66
- generic: ContentGenericData,
67
- ): Promise<ContentBookData> {
68
- return {
69
- type: 'book',
70
- generic,
71
- };
72
- }
1
+ import { getTopicPartsLinks } from '@server/repository/topic';
2
+ import { getContentBookFor } from '@server/repository/book';
3
+ import { getContentGenericData } from '@server/repository/content';
4
+ import { getFullContentId } from '@server/repository/contentId';
5
+
6
+ import type { ContentGenericData } from '@shared/content/data/base';
7
+ import type { ContentTopicData } from '@shared/content/data/type/topic';
8
+ import type { ContentGroupData } from '@shared/content/data/type/group';
9
+ import type { ContentBookData } from '@shared/content/data/type/book';
10
+
11
+ export default defineEventHandler(async (event) => {
12
+ let contentId = getQuery(event)?.contentId as string;
13
+ contentId = await getFullContentId(contentId);
14
+
15
+ if (!contentId) {
16
+ throw createError({
17
+ statusCode: 400,
18
+ statusText: 'Missing content ID!',
19
+ });
20
+ }
21
+
22
+ const generic = await getContentGenericData(contentId);
23
+
24
+ switch (generic.type) {
25
+ case 'topic':
26
+ return await getTopicData(generic);
27
+ case 'group':
28
+ return await getGroupData(generic);
29
+ case 'book':
30
+ return await getBookData(generic);
31
+ }
32
+
33
+ throw createError({
34
+ statusCode: 400,
35
+ statusText: `Unknown content data type "${generic.type}"!`,
36
+ });
37
+ });
38
+
39
+ //
40
+ //
41
+ //
42
+
43
+ async function getTopicData(
44
+ generic: ContentGenericData,
45
+ ): Promise<ContentTopicData> {
46
+ const contentBook = await getContentBookFor(generic.contentId);
47
+
48
+ return {
49
+ type: 'topic',
50
+ generic,
51
+ bookTitle: contentBook?.title,
52
+ topicPartLinks: await getTopicPartsLinks(generic.contentId),
53
+ };
54
+ }
55
+
56
+ async function getGroupData(
57
+ generic: ContentGenericData,
58
+ ): Promise<ContentGroupData> {
59
+ const contentBook = await getContentBookFor(generic.contentId);
60
+
61
+ return {
62
+ type: 'group',
63
+ generic,
64
+ bookTitle: contentBook?.title,
65
+ };
66
+ }
67
+
68
+ async function getBookData(
69
+ generic: ContentGenericData,
70
+ ): Promise<ContentBookData> {
71
+ return {
72
+ type: 'book',
73
+ generic,
74
+ };
75
+ }
@@ -1,6 +1,6 @@
1
- import { DbContributor } from '@server/db/entities/Contributor';
2
- import { ERUDIT_SERVER } from '@server/global';
3
-
4
- export default defineEventHandler(async () => {
5
- return await ERUDIT_SERVER.DB.manager.count(DbContributor);
6
- });
1
+ import { DbContributor } from '@server/db/entities/Contributor';
2
+ import { ERUDIT_SERVER } from '@server/global';
3
+
4
+ export default defineEventHandler(async () => {
5
+ return await ERUDIT_SERVER.DB.manager.count(DbContributor);
6
+ });
@@ -0,0 +1,44 @@
1
+ import { DbContribution } from '@server/db/entities/Contribution';
2
+ import { DbContributor } from '@server/db/entities/Contributor';
3
+ import { ERUDIT_SERVER } from '@server/global';
4
+
5
+ import { type ContributorListItem } from '@shared/contributor';
6
+
7
+ export default defineEventHandler<Promise<ContributorListItem[]>>(async () => {
8
+ const dbContributors = await ERUDIT_SERVER.DB.manager.find(DbContributor, {
9
+ select: ['contributorId', 'displayName', 'isEditor', 'avatar'],
10
+ });
11
+
12
+ if (dbContributors.length === 0) {
13
+ return [];
14
+ }
15
+
16
+ const contributors: ContributorListItem[] = await Promise.all(
17
+ dbContributors.map(async (dbContributor) => {
18
+ const contributions = await ERUDIT_SERVER.DB.manager.count(
19
+ DbContribution,
20
+ {
21
+ where: { contributorId: dbContributor.contributorId },
22
+ },
23
+ );
24
+
25
+ return {
26
+ contributorId: dbContributor.contributorId,
27
+ displayName: dbContributor.displayName,
28
+ isEditor: dbContributor.isEditor,
29
+ avatar: dbContributor.avatar,
30
+ contributions,
31
+ };
32
+ }),
33
+ );
34
+
35
+ contributors.sort((a, b) => {
36
+ if (a.isEditor !== b.isEditor) {
37
+ return a.isEditor ? -1 : 1;
38
+ }
39
+
40
+ return b.contributions - a.contributions;
41
+ });
42
+
43
+ return contributors;
44
+ });
@@ -0,0 +1,14 @@
1
+ import { getContributorPageData } from '@server/repository/contributor';
2
+
3
+ export default defineEventHandler(async (event) => {
4
+ const contributorId = event.context.params?.contributorId;
5
+
6
+ if (!contributorId) {
7
+ throw createError({
8
+ statusCode: 400,
9
+ message: 'Missing contributor ID!',
10
+ });
11
+ }
12
+
13
+ return await getContributorPageData(contributorId);
14
+ });
@@ -1,11 +1,11 @@
1
- export default defineEventHandler(() => {
2
- return {
3
- commit: {
4
- commit: {
5
- author: {
6
- date: '2019-08-30T14:57:06.000Z',
7
- },
8
- },
9
- },
10
- };
11
- });
1
+ export default defineEventHandler(() => {
2
+ return {
3
+ commit: {
4
+ commit: {
5
+ author: {
6
+ date: '2019-08-30T14:57:06.000Z',
7
+ },
8
+ },
9
+ },
10
+ };
11
+ });
@@ -1,12 +1,12 @@
1
- export default defineEventHandler(() => {
2
- return {
3
- en: {
4
- name: 'English',
5
- link: 'https://en.omath.net',
6
- },
7
- ru: {
8
- name: 'Русский',
9
- link: 'https://omath.ru',
10
- },
11
- };
12
- });
1
+ export default defineEventHandler(() => {
2
+ return {
3
+ en: {
4
+ name: 'English',
5
+ link: 'https://en.omath.net',
6
+ },
7
+ ru: {
8
+ name: 'Русский',
9
+ link: 'https://omath.ru',
10
+ },
11
+ };
12
+ });
@@ -1,12 +1,12 @@
1
- import { ERUDIT_SERVER } from '@server/global';
2
-
3
- export default defineEventHandler(() => {
4
- const strFunctions: Record<string, string> = {};
5
-
6
- for (const [key, func] of Object.entries(
7
- ERUDIT_SERVER.LANGUAGE?.functions || {},
8
- ))
9
- strFunctions[key] = 'return ' + func.toString();
10
-
11
- return strFunctions;
12
- });
1
+ import { ERUDIT_SERVER } from '@server/global';
2
+
3
+ export default defineEventHandler(() => {
4
+ const strFunctions: Record<string, string> = {};
5
+
6
+ for (const [key, func] of Object.entries(
7
+ ERUDIT_SERVER.LANGUAGE?.functions || {},
8
+ ))
9
+ strFunctions[key] = 'return ' + func.toString();
10
+
11
+ return strFunctions;
12
+ });
@@ -1,19 +1,19 @@
1
- import type { EruditPhraseId } from '@shared/types/language';
2
- import { ERUDIT_SERVER } from '@server/global';
3
-
4
- export default defineEventHandler((event) => {
5
- const phraseId = getRouterParam(event, 'phraseId');
6
- const phrase =
7
- ERUDIT_SERVER.LANGUAGE?.phrases?.[phraseId as EruditPhraseId];
8
-
9
- setResponseHeader(event, 'content-type', 'text/plain');
10
-
11
- if (typeof phrase === 'string') return phrase;
12
- else if (typeof phrase === 'function')
13
- return '~!~FUNC~!~' + 'return ' + phrase.toString();
14
-
15
- throw createError({
16
- statusCode: 400,
17
- statusText: `Unknown phrase id "${phraseId}"!`,
18
- });
19
- });
1
+ import type { EruditPhraseId } from '@shared/types/language';
2
+ import { ERUDIT_SERVER } from '@server/global';
3
+
4
+ export default defineEventHandler((event) => {
5
+ setResponseHeader(event, 'Content-Type', 'text/plain; charset=utf-8');
6
+
7
+ const phraseId = getRouterParam(event, 'phraseId');
8
+ const phrase =
9
+ ERUDIT_SERVER.LANGUAGE?.phrases?.[phraseId as EruditPhraseId];
10
+
11
+ if (typeof phrase === 'string') return phrase;
12
+ else if (typeof phrase === 'function')
13
+ return '~!~FUNC~!~' + 'return ' + phrase.toString();
14
+
15
+ throw createError({
16
+ statusCode: 400,
17
+ statusText: `Unknown phrase id "${phraseId}"!`,
18
+ });
19
+ });
@@ -1,8 +1,8 @@
1
- import { ERUDIT_SERVER } from '@server/global';
2
- import type { EruditPhraseId } from '@shared/types/language';
3
-
4
- export default defineEventHandler(() => {
5
- return Object.keys(
6
- ERUDIT_SERVER.LANGUAGE?.phrases || [],
7
- ) as EruditPhraseId[];
8
- });
1
+ import { ERUDIT_SERVER } from '@server/global';
2
+ import type { EruditPhraseId } from '@shared/types/language';
3
+
4
+ export default defineEventHandler(() => {
5
+ return Object.keys(
6
+ ERUDIT_SERVER.LANGUAGE?.phrases || [],
7
+ ) as EruditPhraseId[];
8
+ });
@@ -0,0 +1,14 @@
1
+ import { PROJECT_DIR } from '#erudit/globalPaths';
2
+ import { glob } from 'glob';
3
+
4
+ const includePatterns = [`cameos/*/avatars/*`];
5
+
6
+ export default defineEventHandler(async () => {
7
+ const files = await glob(includePatterns, {
8
+ cwd: PROJECT_DIR,
9
+ absolute: false,
10
+ posix: true,
11
+ });
12
+
13
+ return files.map((file) => '/asset/' + file);
14
+ });
@@ -0,0 +1,12 @@
1
+ import { glob } from 'glob';
2
+ import { PROJECT_DIR } from '#erudit/globalPaths';
3
+
4
+ export default defineEventHandler(async () => {
5
+ const avatars = await glob('contributors/*/avatar.*', {
6
+ cwd: PROJECT_DIR,
7
+ absolute: false,
8
+ posix: true,
9
+ });
10
+
11
+ return avatars.map((avatar) => '/asset/' + avatar);
12
+ });
@@ -0,0 +1,13 @@
1
+ import { ERUDIT_SERVER } from '@server/global';
2
+
3
+ export default defineEventHandler(async () => {
4
+ const serverSponsors = ERUDIT_SERVER.SPONSORS;
5
+
6
+ if (!serverSponsors) {
7
+ return [];
8
+ }
9
+
10
+ return Object.values(serverSponsors.avatars)
11
+ .filter(Boolean)
12
+ .map((avatar) => '/asset/' + avatar);
13
+ });
@@ -0,0 +1,12 @@
1
+ import { getCameoIds } from '@server/repository/cameo';
2
+ import { getTier2SponsorIds } from '@server/sponsor/repository';
3
+
4
+ export default defineEventHandler(async () => {
5
+ const cameoIds = await getCameoIds();
6
+ return [
7
+ '/api/cameo/ids',
8
+ '/api/sponsor/cameo/ids',
9
+ ...cameoIds.map((id) => `/api/cameo/data/${id}`),
10
+ ...getTier2SponsorIds().map((id) => `/api/sponsor/cameo/data/${id}`),
11
+ ];
12
+ });
@@ -0,0 +1,9 @@
1
+ import { ERUDIT_SERVER } from '@server/global';
2
+
3
+ export default defineEventHandler(() => {
4
+ const phraseRoutes = Object.keys(ERUDIT_SERVER.LANGUAGE?.phrases || []).map(
5
+ (phraseId) => `/api/language/phrase/${phraseId}`,
6
+ );
7
+
8
+ return ['/api/language/functions', ...phraseRoutes];
9
+ });
@@ -1,51 +1,78 @@
1
- import {
2
- getContentContext,
3
- getTopicPartContext,
4
- getContributorContext,
5
- } from '@erudit/server/plugin/content/context';
6
-
7
- import type { PreviewDataPageLink } from '@app/scripts/preview/data/pageLink';
8
- import type { LinkTargetPageType } from '@erudit/shared/bitran/link/target';
9
- import type { Context, ContextItem } from '@erudit/shared/content/context';
10
-
11
- export default defineEventHandler<Promise<PreviewDataPageLink>>(
12
- async (event) => {
13
- const urlParts = (event.context.params?.parts || '').split('/');
14
- const pageType: LinkTargetPageType = urlParts.shift() as any;
15
- const contentId: string = urlParts.join('/');
16
-
17
- const context: Context = await (async () => {
18
- switch (pageType) {
19
- case 'book':
20
- case 'group':
21
- return await getContentContext(contentId);
22
- case 'article':
23
- case 'summary':
24
- case 'practice':
25
- return await getTopicPartContext(pageType, contentId);
26
- case 'contributor':
27
- return await getContributorContext(contentId);
28
- }
29
-
30
- throw createError(`Can't handle "${pageType}" page type!`);
31
- })();
32
-
33
- const lastContextItem = context.pop() as ContextItem;
34
- const contextStr = context
35
- .filter((c) => !c.hidden)
36
- .map((c) => c.title)
37
- .join(' / ');
38
-
39
- return <PreviewDataPageLink>{
40
- type: 'page-link',
41
- footer: {
42
- secondary:
43
- (contextStr ? contextStr + ' • ' : '') +
44
- lastContextItem.type,
45
- primary: lastContextItem.title,
46
- href: lastContextItem.href,
47
- iconName: lastContextItem.icon,
48
- },
49
- };
50
- },
51
- );
1
+ import type { LinkTargetPageType } from '@erudit-js/bitran-elements/link/target';
2
+ import { isContentType } from '@erudit-js/cog/schema';
3
+
4
+ import {
5
+ getContentContext,
6
+ getTopicPartContext,
7
+ getContributorContext,
8
+ } from '@server/content/context';
9
+ import { getFullContentId } from '@server/repository/contentId';
10
+ import { ERUDIT_SERVER } from '@server/global';
11
+ import { DbContent } from '@server/db/entities/Content';
12
+
13
+ import type { Context, ContextItem } from '@erudit/shared/content/context';
14
+ import type { PreviewDataPageLink } from '@app/scripts/preview/data/pageLink';
15
+
16
+ export default defineEventHandler<Promise<PreviewDataPageLink>>(
17
+ async (event) => {
18
+ const urlParts = (event.context.params?.parts || '').split('/');
19
+ const pageType: LinkTargetPageType = urlParts.shift() as any;
20
+ const contentId: string = urlParts.join('/');
21
+
22
+ const context: Context = await (async () => {
23
+ switch (pageType) {
24
+ case 'book':
25
+ case 'group':
26
+ return await getContentContext(contentId);
27
+ case 'article':
28
+ case 'summary':
29
+ case 'practice':
30
+ return await getTopicPartContext(pageType, contentId);
31
+ case 'contributor':
32
+ return await getContributorContext(contentId);
33
+ }
34
+
35
+ throw createError(`Can't handle "${pageType as any}" page type!`);
36
+ })();
37
+
38
+ const lastContextItem = context.pop() as ContextItem;
39
+ const contextStr = context
40
+ .filter((c) => !c.hidden)
41
+ .map((c) => c.title)
42
+ .join(' / ');
43
+
44
+ const description = await (async () => {
45
+ if (!isContentType(pageType)) {
46
+ return;
47
+ }
48
+
49
+ const fullContentId = await getFullContentId(contentId);
50
+ const dbContent = await ERUDIT_SERVER.DB.manager.findOne(
51
+ DbContent,
52
+ {
53
+ select: ['description'],
54
+ where: { contentId: fullContentId },
55
+ },
56
+ );
57
+
58
+ if (!dbContent) {
59
+ return;
60
+ }
61
+
62
+ return dbContent.description?.trim();
63
+ })();
64
+
65
+ return <PreviewDataPageLink>{
66
+ type: 'page-link',
67
+ description,
68
+ footer: {
69
+ secondary:
70
+ (contextStr ? contextStr + ' • ' : '') +
71
+ lastContextItem.type,
72
+ primary: lastContextItem.title,
73
+ href: lastContextItem.href,
74
+ iconName: lastContextItem.icon,
75
+ },
76
+ };
77
+ },
78
+ );