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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/app/app.vue +195 -172
  2. package/app/assets/icons/cameo-add.svg +3 -0
  3. package/app/assets/icons/diamond.svg +3 -0
  4. package/app/assets/icons/graduation.svg +3 -0
  5. package/app/components/Avatar.vue +118 -0
  6. package/app/components/EruditLink.vue +17 -0
  7. package/app/components/Loading.vue +23 -23
  8. package/app/components/SiteAside.vue +393 -382
  9. package/app/components/SiteMain.vue +32 -35
  10. package/app/components/ads/Ads.vue +33 -0
  11. package/app/components/ads/AdsBannerAside.vue +61 -0
  12. package/app/components/ads/AdsBannerBottom.vue +22 -0
  13. package/app/components/ads/AdsProviderCustom.vue +35 -0
  14. package/app/components/ads/AdsProviderYandex.vue +91 -0
  15. package/app/components/ads/AdsReplacer.vue +73 -0
  16. package/app/components/aside/AsideListItem.vue +91 -74
  17. package/app/components/aside/AsideMajor.vue +56 -56
  18. package/app/components/aside/AsideMinor.vue +97 -71
  19. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  20. package/app/components/aside/major/PaneSwitch.vue +54 -54
  21. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  22. package/app/components/aside/major/SiteInfo.vue +85 -85
  23. package/app/components/aside/major/panes/Language.vue +79 -79
  24. package/app/components/aside/major/panes/Pages.vue +50 -34
  25. package/app/components/aside/major/panes/Search.vue +11 -11
  26. package/app/components/aside/major/panes/nav/Nav.vue +92 -91
  27. package/app/components/aside/major/panes/nav/NavBook.vue +95 -86
  28. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  29. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  30. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  31. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  32. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  33. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  34. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  35. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  36. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  37. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  38. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -15
  39. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  40. package/app/components/aside/major/panes/other/Other.vue +16 -16
  41. package/app/components/aside/minor/{Contribute.vue → AsideMinorContribute.vue} +175 -145
  42. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  43. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  44. package/app/components/aside/minor/AsideMinorTopLink.vue +66 -67
  45. package/app/components/aside/minor/content/AsideMinorContent.vue +89 -92
  46. package/app/components/aside/minor/contributor/AsideMinorContributor.vue +78 -0
  47. package/app/components/aside/minor/contributor/BookContribution.vue +64 -0
  48. package/app/components/aside/minor/topic/AsideMinorTopic.vue +31 -32
  49. package/app/components/aside/minor/topic/TopicContributors.vue +183 -177
  50. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  51. package/app/components/aside/minor/topic/TopicToc.vue +212 -203
  52. package/app/components/aside/minor/topic/TopicTocItem.vue +19 -31
  53. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  54. package/app/components/bitran/BitranContent.vue +90 -63
  55. package/app/components/bitran/RenderWrapper.vue +10 -10
  56. package/app/components/contributor/ContributorListItem.vue +43 -35
  57. package/app/components/main/MainActionButton.vue +51 -0
  58. package/app/components/main/MainBitranContent.vue +55 -0
  59. package/app/components/main/{utils/Breadcrumb.vue → MainBreadcrumb.vue} +63 -75
  60. package/app/components/main/MainDescription.vue +24 -0
  61. package/app/components/main/MainSection.vue +58 -0
  62. package/app/components/main/MainTitle.vue +76 -0
  63. package/app/components/main/cameo/MainCameo.vue +135 -0
  64. package/app/components/main/cameo/MainCameoData.vue +232 -0
  65. package/app/components/main/content/ContentBreadcrumb.vue +28 -0
  66. package/app/components/main/{utils → content}/ContentDecoration.vue +29 -29
  67. package/app/components/main/{utils → content}/ContentPopover.vue +188 -176
  68. package/app/components/main/{utils → content}/ContentPopovers.vue +111 -105
  69. package/app/components/main/{utils → content}/ContentReferences.vue +70 -70
  70. package/app/components/main/{utils → content}/reference/ReferenceGroup.vue +38 -38
  71. package/app/components/main/{utils → content}/reference/ReferenceItem.vue +70 -68
  72. package/app/components/main/{utils → content}/reference/ReferenceSource.vue +120 -116
  73. package/app/components/main/topic/MainTopic.vue +76 -79
  74. package/app/components/main/topic/TopicPartSwitch.vue +119 -118
  75. package/app/components/preview/Preview.vue +186 -177
  76. package/app/components/preview/PreviewDisplay.vue +139 -139
  77. package/app/components/preview/PreviewFooterAction.vue +73 -73
  78. package/app/components/preview/PreviewLoading.vue +14 -14
  79. package/app/components/preview/PreviewScreen.vue +141 -99
  80. package/app/components/preview/display/Alert.vue +50 -50
  81. package/app/components/preview/display/Custom.vue +18 -18
  82. package/app/components/preview/display/GenericLink.vue +48 -48
  83. package/app/components/preview/display/PageLink.vue +22 -20
  84. package/app/components/preview/display/Unique.vue +46 -49
  85. package/app/components/sponsor/SponsorTier1.vue +89 -0
  86. package/app/components/sponsor/SponsorTier2.vue +109 -0
  87. package/app/components/transition/Fade.vue +19 -19
  88. package/app/components/tree/TreeContainer.vue +11 -11
  89. package/app/components/tree/TreeItem.vue +93 -89
  90. package/app/composables/adsAllowed.ts +11 -0
  91. package/app/composables/asset.ts +12 -0
  92. package/app/composables/bitran.ts +108 -127
  93. package/app/composables/bitranLocation.ts +7 -7
  94. package/app/composables/contentData.ts +38 -36
  95. package/app/composables/contentPage.ts +168 -156
  96. package/app/composables/contentRoute.ts +45 -45
  97. package/app/composables/darkMagic.ts +24 -24
  98. package/app/composables/externalApi.ts +69 -63
  99. package/app/composables/favicon.ts +8 -8
  100. package/app/composables/formatText.ts +99 -86
  101. package/app/composables/head.ts +24 -0
  102. package/app/composables/majorPane.ts +62 -60
  103. package/app/composables/phrases.ts +77 -80
  104. package/app/composables/theme.ts +29 -29
  105. package/app/composables/url.ts +43 -33
  106. package/app/pages/_test/preview.vue +110 -110
  107. package/app/pages/article/[...articleId].vue +3 -3
  108. package/app/pages/book/[...bookId].vue +42 -47
  109. package/app/pages/contributor/[contributorId].vue +227 -0
  110. package/app/pages/contributors.vue +184 -0
  111. package/app/pages/group/[...groupId].vue +53 -65
  112. package/app/pages/index.vue +32 -32
  113. package/app/pages/practice/[...practice].vue +3 -3
  114. package/app/pages/sponsors.vue +95 -0
  115. package/app/pages/summary/[...summaryId].vue +3 -3
  116. package/app/plugins/analytics.ts +95 -0
  117. package/app/plugins/prerender.server.ts +34 -0
  118. package/app/public/favicon/article.svg +5 -5
  119. package/app/public/favicon/default.svg +3 -3
  120. package/app/public/favicon/practice.svg +3 -3
  121. package/app/public/favicon/summary.svg +4 -4
  122. package/app/public/logotype.svg +2 -2
  123. package/app/scripts/_immediate.js +9 -9
  124. package/app/scripts/aside/index.ts +59 -59
  125. package/app/scripts/aside/major/nav.ts +26 -26
  126. package/app/scripts/aside/minor/state.ts +37 -37
  127. package/app/scripts/flag.ts +28 -28
  128. package/app/scripts/og.ts +28 -27
  129. package/app/scripts/preview/build.ts +76 -73
  130. package/app/scripts/preview/data/alert.ts +19 -19
  131. package/app/scripts/preview/data/custom.ts +8 -8
  132. package/app/scripts/preview/data/genericLink.ts +24 -24
  133. package/app/scripts/preview/data/pageLink.ts +23 -20
  134. package/app/scripts/preview/data/unique.ts +69 -70
  135. package/app/scripts/preview/data.ts +24 -24
  136. package/app/scripts/preview/display.ts +37 -37
  137. package/app/scripts/preview/footer.ts +9 -9
  138. package/app/scripts/preview/request.ts +51 -51
  139. package/app/scripts/preview/state.ts +63 -63
  140. package/app/styles/_immediate.css +7 -7
  141. package/app/styles/_util.scss +43 -43
  142. package/app/styles/_utils.scss +44 -44
  143. package/app/styles/app.scss +91 -91
  144. package/app/styles/def/_bp.scss +27 -27
  145. package/app/styles/def/_size.scss +7 -7
  146. package/app/styles/def/_z.scss +5 -5
  147. package/app/styles/normalize.scss +49 -63
  148. package/app/styles/partials/_darkMagic.scss +5 -5
  149. package/app/styles/partials/_fnav.scss +15 -15
  150. package/app/styles/partials/_preview.scss +5 -5
  151. package/bin/erudit.mjs +2 -0
  152. package/const.ts +3 -0
  153. package/globalPath.ts +21 -21
  154. package/globals/bitran.ts +1 -47
  155. package/globals/cameo.ts +5 -0
  156. package/globals/content.ts +27 -22
  157. package/globals/contributor.ts +5 -5
  158. package/globals/erudit.ts +5 -5
  159. package/globals/register.ts +23 -18
  160. package/globals/sponsor.ts +17 -0
  161. package/languages/en.ts +108 -95
  162. package/languages/ru.ts +112 -99
  163. package/module/bitran.ts +66 -34
  164. package/module/config.ts +35 -34
  165. package/module/imports.ts +74 -46
  166. package/module/index.ts +47 -47
  167. package/module/logger.ts +10 -10
  168. package/module/paths.ts +22 -22
  169. package/module/restart.ts +61 -61
  170. package/nuxt.config.ts +126 -112
  171. package/package.json +22 -15
  172. package/server/api/aside/major/nav/bookIds.ts +5 -5
  173. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  174. package/server/api/aside/major/nav/global.ts +7 -7
  175. package/server/api/aside/minor/book/[...bookId].ts +18 -0
  176. package/server/api/aside/minor/contributor/[contributorId].ts +18 -0
  177. package/server/api/aside/minor/group/[...groupId].ts +18 -0
  178. package/server/api/aside/minor/news.ts +7 -7
  179. package/server/api/aside/minor/topic.ts +36 -0
  180. package/server/api/bitran/content/[...location].ts +13 -0
  181. package/server/api/bitran/toc/[...location].ts +9 -0
  182. package/server/api/cameo/data/[cameoId].ts +42 -0
  183. package/server/api/cameo/ids.ts +5 -0
  184. package/server/api/content/data.ts +75 -72
  185. package/server/api/contributor/count.ts +6 -6
  186. package/server/api/contributor/list.ts +44 -0
  187. package/server/api/contributor/page/[contributorId].ts +14 -0
  188. package/server/api/fake/content.ts +11 -11
  189. package/server/api/fake/shared/languages.ts +12 -12
  190. package/server/api/language/functions.ts +12 -12
  191. package/server/api/language/phrase/[phraseId].ts +19 -19
  192. package/server/api/language/phraseIds.ts +8 -8
  193. package/server/api/prerender/assets/cameo.ts +14 -0
  194. package/server/api/prerender/assets/contributor.ts +12 -0
  195. package/server/api/prerender/assets/sponsor.ts +13 -0
  196. package/server/api/prerender/cameos.ts +12 -0
  197. package/server/api/prerender/language.ts +9 -0
  198. package/server/api/preview/page/[...parts].ts +78 -51
  199. package/server/api/preview/unique/{[location].ts → [...location].ts} +48 -55
  200. package/server/api/problem/generator/[...path].ts +26 -0
  201. package/server/api/sponsor/cameo/data/[sponsorId].ts +51 -0
  202. package/server/api/sponsor/cameo/ids.ts +5 -0
  203. package/server/api/sponsor/count.ts +5 -0
  204. package/server/api/sponsor/list.ts +36 -0
  205. package/server/plugin/bitran/content.ts +252 -187
  206. package/server/plugin/bitran/{products → elements}/include.ts +229 -230
  207. package/server/plugin/bitran/location.ts +43 -25
  208. package/server/plugin/bitran/toc.ts +94 -83
  209. package/server/plugin/bitran/transpiler.ts +18 -46
  210. package/server/plugin/build/close.ts +12 -10
  211. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  212. package/server/plugin/build/jobs/content/generic.ts +191 -176
  213. package/server/plugin/build/jobs/content/parse.ts +113 -100
  214. package/server/plugin/build/jobs/content/path.ts +6 -6
  215. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  216. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  217. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  218. package/server/plugin/build/jobs/contributors.ts +69 -66
  219. package/server/plugin/build/jobs/language.ts +36 -36
  220. package/server/plugin/build/jobs/nav.ts +345 -210
  221. package/server/plugin/build/process.ts +34 -25
  222. package/server/plugin/build/rebuild.ts +68 -55
  223. package/server/plugin/build/setup.ts +19 -21
  224. package/server/plugin/content/context.ts +119 -112
  225. package/server/plugin/db/entities/Book.ts +7 -7
  226. package/server/plugin/db/entities/Content.ts +45 -49
  227. package/server/plugin/db/entities/Contribution.ts +10 -10
  228. package/server/plugin/db/entities/Contributor.ts +25 -16
  229. package/server/plugin/db/entities/File.ts +10 -0
  230. package/server/plugin/db/entities/Group.ts +14 -14
  231. package/server/plugin/db/entities/Hash.ts +15 -15
  232. package/server/plugin/db/entities/Topic.ts +20 -20
  233. package/server/plugin/db/entities/Unique.ts +21 -21
  234. package/server/plugin/db/reset.ts +12 -0
  235. package/server/plugin/db/setup.ts +49 -34
  236. package/server/plugin/global.ts +18 -18
  237. package/server/plugin/importer.ts +16 -12
  238. package/server/plugin/index.ts +9 -9
  239. package/server/plugin/logger.ts +23 -23
  240. package/server/plugin/nav/node.ts +27 -26
  241. package/server/plugin/nav/utils.ts +179 -129
  242. package/server/plugin/repository/asideMinor.ts +51 -0
  243. package/server/plugin/repository/book.ts +39 -21
  244. package/server/plugin/repository/cameo.ts +16 -0
  245. package/server/plugin/repository/content.ts +240 -238
  246. package/server/plugin/repository/contentId.ts +40 -0
  247. package/server/plugin/repository/contributor.ts +129 -8
  248. package/server/plugin/repository/file.ts +10 -0
  249. package/server/plugin/repository/frontNav.ts +145 -148
  250. package/server/plugin/repository/topic.ts +35 -32
  251. package/server/plugin/sponsor/build.ts +82 -0
  252. package/server/plugin/sponsor/index.ts +5 -0
  253. package/server/plugin/sponsor/repository.ts +56 -0
  254. package/server/routes/asset/[...assetPath].ts +34 -0
  255. package/server/routes/robots.txt.ts +9 -0
  256. package/server/routes/sitemap.xml.ts +103 -0
  257. package/server/tsconfig.json +9 -9
  258. package/shared/aside/minor.ts +55 -50
  259. package/shared/asset.ts +17 -15
  260. package/shared/bitran/content.ts +9 -0
  261. package/shared/bitran/contentId.ts +56 -0
  262. package/shared/bitran/toc.ts +8 -8
  263. package/shared/breadcrumb.ts +7 -0
  264. package/shared/content/bookId.ts +12 -0
  265. package/shared/content/context.ts +9 -9
  266. package/shared/content/data/base.ts +32 -32
  267. package/shared/content/data/index.ts +5 -5
  268. package/shared/content/data/type/book.ts +5 -5
  269. package/shared/content/data/type/group.ts +6 -6
  270. package/shared/content/data/type/topic.ts +11 -11
  271. package/shared/content/previousNext.ts +9 -9
  272. package/shared/contributor.ts +34 -5
  273. package/shared/frontNav.ts +41 -41
  274. package/shared/icons.ts +38 -38
  275. package/shared/image.ts +5 -5
  276. package/shared/link.ts +28 -25
  277. package/shared/popover.ts +8 -0
  278. package/shared/types/language.ts +84 -75
  279. package/shared/utils/objectsEqual.ts +4 -4
  280. package/shared/utils/stringColor.ts +9 -9
  281. package/test/contentId.test.ts +91 -0
  282. package/test/utils/url.test.ts +99 -0
  283. package/tsconfig.json +8 -8
  284. package/utils/contentPath.ts +67 -0
  285. package/utils/ext.ts +41 -0
  286. package/utils/stress.ts +9 -9
  287. package/utils/url.ts +23 -0
  288. package/app/components/ads/BannerTemplate.vue +0 -51
  289. package/app/components/ads/BottomBanner.vue +0 -45
  290. package/app/components/ads/LeftBanner.vue +0 -50
  291. package/app/components/aside/minor/AsideMinorContributor.vue +0 -5
  292. package/app/components/contributor/ContributorAvatar.vue +0 -43
  293. package/app/components/main/utils/ContentDescription.vue +0 -19
  294. package/app/components/main/utils/ContentFlag.vue +0 -15
  295. package/app/components/main/utils/ContentSection.vue +0 -45
  296. package/app/components/main/utils/ContentTitle.vue +0 -39
  297. package/app/composables/bitranContent.ts +0 -37
  298. package/app/pages/members.vue +0 -6
  299. package/app/public/user.svg +0 -10
  300. package/app/scripts/aside/minor/topic.ts +0 -3
  301. package/app/styles/default.scss +0 -83
  302. package/server/api/aside/minor/path.ts +0 -78
  303. package/server/api/bitran/content/[location].ts +0 -7
  304. package/server/api/bitran/toc/[location].ts +0 -7
  305. package/server/plugin/bitran/products/link.ts +0 -116
  306. package/server/plugin/bitran/setup.ts +0 -9
  307. package/server/plugin/content/absoluteId.ts +0 -94
  308. package/shared/bitran/context.ts +0 -8
  309. package/shared/bitran/default.ts +0 -46
  310. package/shared/bitran/link/Link.vue +0 -167
  311. package/shared/bitran/link/factory.ts +0 -24
  312. package/shared/bitran/link/icon.svg +0 -3
  313. package/shared/bitran/link/languages/en.ts +0 -7
  314. package/shared/bitran/link/languages/ru.ts +0 -7
  315. package/shared/bitran/link/renderer.ts +0 -21
  316. package/shared/bitran/link/shared.ts +0 -17
  317. package/shared/bitran/link/target.ts +0 -134
  318. package/shared/bitran/link/transpiler.ts +0 -10
  319. package/shared/bitran/location.ts +0 -166
  320. package/test/bitran/link/target.test.ts +0 -141
  321. package/test/bitran/location.test.ts +0 -143
@@ -1,24 +1,24 @@
1
- <template>
2
- <div :class="$style.navBookLoading">
3
- <Loading />
4
- </div>
5
- </template>
6
-
7
- <style lang="scss" module>
8
- .navBookLoading {
9
- position: absolute;
10
- z-index: 100;
11
- top: 0;
12
- left: 0;
13
- width: 100%;
14
- height: 100%;
15
- background: var(--bgAside);
16
-
17
- display: flex;
18
- align-items: center;
19
- justify-content: center;
20
- font-size: 60px;
21
-
22
- @include transition(opacity, box-shadow);
23
- }
24
- </style>
1
+ <template>
2
+ <div :class="$style.navBookLoading">
3
+ <Loading />
4
+ </div>
5
+ </template>
6
+
7
+ <style lang="scss" module>
8
+ .navBookLoading {
9
+ position: absolute;
10
+ z-index: 100;
11
+ top: 0;
12
+ left: 0;
13
+ width: 100%;
14
+ height: 100%;
15
+ background: var(--bgAside);
16
+
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ font-size: 60px;
21
+
22
+ @include transition(opacity, box-shadow);
23
+ }
24
+ </style>
@@ -1,16 +1,16 @@
1
- <script lang="ts" setup>
2
- import { getAsideMajorNavPayload } from '@app/scripts/aside/major/nav';
3
-
4
- import FNav from './fnav/FNav.vue';
5
- import PaneContentScroll from '../../PaneContentScroll.vue';
6
-
7
- const contentRoute = useContentRoute();
8
- const asideMajorNav = getAsideMajorNavPayload();
9
- const globalNav = asideMajorNav.globalNav;
10
- </script>
11
-
12
- <template>
13
- <PaneContentScroll>
14
- <FNav :nav="globalNav" :contentId="contentRoute?.contentId" />
15
- </PaneContentScroll>
16
- </template>
1
+ <script lang="ts" setup>
2
+ import { getAsideMajorNavPayload } from '@app/scripts/aside/major/nav';
3
+
4
+ import FNav from './fnav/FNav.vue';
5
+ import PaneContentScroll from '../../PaneContentScroll.vue';
6
+
7
+ const contentRoute = useContentRoute();
8
+ const asideMajorNav = getAsideMajorNavPayload();
9
+ const globalNav = asideMajorNav.globalNav;
10
+ </script>
11
+
12
+ <template>
13
+ <PaneContentScroll>
14
+ <FNav :nav="globalNav" :contentId="contentRoute?.contentId" />
15
+ </PaneContentScroll>
16
+ </template>
@@ -1,105 +1,105 @@
1
- <script lang="ts" setup>
2
- import type {
3
- FrontNav,
4
- FrontNavContainer,
5
- FrontNavItem,
6
- } from '@shared/frontNav';
7
- import { navStateKey, type NavState } from '@app/scripts/aside/major/nav';
8
-
9
- import FNavItem from './FNavItem.vue';
10
-
11
- const props = defineProps<{ nav: FrontNav; contentId?: string }>();
12
- const hashNav = shallowRef<Record<string, FrontNavItem>>();
13
- const navState = shallowRef<NavState>();
14
-
15
- function setupHashNav() {
16
- hashNav.value = {};
17
-
18
- if (!props.nav) return;
19
-
20
- function addNavItem(navItem: FrontNavItem) {
21
- hashNav.value![navItem.fullId] = navItem;
22
- for (const child of (navItem as FrontNavContainer).children || [])
23
- addNavItem(child);
24
- }
25
-
26
- for (const topNavItem of props.nav) addNavItem(topNavItem);
27
- }
28
-
29
- function setupNavState() {
30
- // We create a ref for every nav item to check wheter it is active or not.
31
- // Yes, it uses a lot of memory, but it is still better than messing with recursive tree recreations.
32
-
33
- navState.value = {};
34
-
35
- for (const navItem of Object.values(hashNav.value!))
36
- navState.value[navItem.id] = shallowRef(null);
37
- }
38
-
39
- function updateNavState() {
40
- // We watch current content route and update navigation state for each item.
41
- // United watcher here instead of watcher on each navigation item instance.
42
-
43
- if (!hashNav.value || !navState.value) return;
44
-
45
- let currentFullId: string | undefined;
46
-
47
- for (const navItem of Object.values(hashNav.value)) {
48
- navState.value[navItem.id]!.value = null;
49
- if (props.contentId?.startsWith(navItem.id))
50
- currentFullId = navItem.fullId;
51
- }
52
-
53
- if (!currentFullId) return;
54
-
55
- const idParts = currentFullId.split('/');
56
- while (idParts.length) {
57
- const _fullId = idParts.join('/');
58
- const navItem = hashNav.value[_fullId];
59
-
60
- if (navItem)
61
- navState.value[navItem.id]!.value =
62
- _fullId === currentFullId ? 'active' : 'activePart';
63
-
64
- idParts.pop();
65
- }
66
- }
67
-
68
- setupHashNav();
69
- setupNavState();
70
- updateNavState();
71
-
72
- watch(
73
- () => props.nav,
74
- () => {
75
- setupHashNav();
76
- setupNavState();
77
- updateNavState();
78
- },
79
- );
80
-
81
- watch(() => props.contentId, updateNavState);
82
-
83
- // @ts-ignore
84
- provide(navStateKey, navState);
85
-
86
- const phrase = await usePhrases('empty_nav');
87
- </script>
88
-
89
- <template>
90
- <TreeContainer v-if="nav && nav.length > 0">
91
- <slot name="before"></slot>
92
- <FNavItem v-for="navItem of nav" :navItem />
93
- </TreeContainer>
94
- <div v-else :class="$style.emptyNav">
95
- {{ phrase.empty_nav }}
96
- </div>
97
- </template>
98
-
99
- <style lang="scss" module>
100
- .emptyNav {
101
- padding: var(--gap);
102
- color: var(--textMuted);
103
- text-align: center;
104
- }
105
- </style>
1
+ <script lang="ts" setup>
2
+ import type {
3
+ FrontNav,
4
+ FrontNavContainer,
5
+ FrontNavItem,
6
+ } from '@shared/frontNav';
7
+ import { navStateKey, type NavState } from '@app/scripts/aside/major/nav';
8
+
9
+ import FNavItem from './FNavItem.vue';
10
+
11
+ const props = defineProps<{ nav: FrontNav; contentId?: string }>();
12
+ const hashNav = shallowRef<Record<string, FrontNavItem>>();
13
+ const navState = shallowRef<NavState>();
14
+
15
+ function setupHashNav() {
16
+ hashNav.value = {};
17
+
18
+ if (!props.nav) return;
19
+
20
+ function addNavItem(navItem: FrontNavItem) {
21
+ hashNav.value![navItem.fullId] = navItem;
22
+ for (const child of (navItem as FrontNavContainer).children || [])
23
+ addNavItem(child);
24
+ }
25
+
26
+ for (const topNavItem of props.nav) addNavItem(topNavItem);
27
+ }
28
+
29
+ function setupNavState() {
30
+ // We create a ref for every nav item to check wheter it is active or not.
31
+ // Yes, it uses a lot of memory, but it is still better than messing with recursive tree recreations.
32
+
33
+ navState.value = {};
34
+
35
+ for (const navItem of Object.values(hashNav.value!))
36
+ navState.value[navItem.id] = shallowRef(null);
37
+ }
38
+
39
+ function updateNavState() {
40
+ // We watch current content route and update navigation state for each item.
41
+ // United watcher here instead of watcher on each navigation item instance.
42
+
43
+ if (!hashNav.value || !navState.value) return;
44
+
45
+ let currentFullId: string | undefined;
46
+
47
+ for (const navItem of Object.values(hashNav.value)) {
48
+ navState.value[navItem.id]!.value = null;
49
+ if (props.contentId?.startsWith(navItem.id))
50
+ currentFullId = navItem.fullId;
51
+ }
52
+
53
+ if (!currentFullId) return;
54
+
55
+ const idParts = currentFullId.split('/');
56
+ while (idParts.length) {
57
+ const _fullId = idParts.join('/');
58
+ const navItem = hashNav.value[_fullId];
59
+
60
+ if (navItem)
61
+ navState.value[navItem.id]!.value =
62
+ _fullId === currentFullId ? 'active' : 'activePart';
63
+
64
+ idParts.pop();
65
+ }
66
+ }
67
+
68
+ setupHashNav();
69
+ setupNavState();
70
+ updateNavState();
71
+
72
+ watch(
73
+ () => props.nav,
74
+ () => {
75
+ setupHashNav();
76
+ setupNavState();
77
+ updateNavState();
78
+ },
79
+ );
80
+
81
+ watch(() => props.contentId, updateNavState);
82
+
83
+ // @ts-ignore
84
+ provide(navStateKey, navState);
85
+
86
+ const phrase = await usePhrases('empty_nav');
87
+ </script>
88
+
89
+ <template>
90
+ <TreeContainer v-if="nav && nav.length > 0">
91
+ <slot name="before"></slot>
92
+ <FNavItem v-for="navItem of nav" :navItem />
93
+ </TreeContainer>
94
+ <div v-else :class="$style.emptyNav">
95
+ {{ phrase.empty_nav }}
96
+ </div>
97
+ </template>
98
+
99
+ <style lang="scss" module>
100
+ .emptyNav {
101
+ padding: var(--gap);
102
+ color: var(--textMuted);
103
+ text-align: center;
104
+ }
105
+ </style>
@@ -1,32 +1,32 @@
1
- <script lang="ts" setup>
2
- import type { FrontNavBook } from '@shared/frontNav';
3
- import {
4
- insideNavBook,
5
- navBookId,
6
- navStateKey,
7
- } from '@app/scripts/aside/major/nav';
8
-
9
- import FNavFlags from './FNavFlags.vue';
10
-
11
- const props = defineProps<{ navItem: FrontNavBook }>();
12
- const navState = inject(navStateKey);
13
- const active = computed(() => !!navState!.value[props.navItem.id]!.value);
14
-
15
- function bookClick() {
16
- navBookId.value = props.navItem.id;
17
- insideNavBook.value = true;
18
- }
19
- </script>
20
-
21
- <template>
22
- <TreeItem
23
- icon="outline/book"
24
- :label="navItem.label"
25
- :level="navItem.level"
26
- :link="active ? undefined : `/book/${navItem.id}`"
27
- @click="bookClick"
28
- :active
29
- >
30
- <FNavFlags v-if="navItem.flags" :flags="navItem.flags" />
31
- </TreeItem>
32
- </template>
1
+ <script lang="ts" setup>
2
+ import type { FrontNavBook } from '@shared/frontNav';
3
+ import {
4
+ insideNavBook,
5
+ navBookId,
6
+ navStateKey,
7
+ } from '@app/scripts/aside/major/nav';
8
+
9
+ import FNavFlags from './FNavFlags.vue';
10
+
11
+ const props = defineProps<{ navItem: FrontNavBook }>();
12
+ const navState = inject(navStateKey);
13
+ const active = computed(() => !!navState!.value[props.navItem.id]!.value);
14
+
15
+ function bookClick() {
16
+ navBookId.value = props.navItem.id;
17
+ insideNavBook.value = true;
18
+ }
19
+ </script>
20
+
21
+ <template>
22
+ <TreeItem
23
+ icon="outline/book"
24
+ :label="navItem.label"
25
+ :level="navItem.level"
26
+ :link="active ? undefined : `/book/${navItem.id}`"
27
+ @click="bookClick"
28
+ :active
29
+ >
30
+ <FNavFlags v-if="navItem.flags" :flags="navItem.flags" />
31
+ </TreeItem>
32
+ </template>
@@ -1,40 +1,40 @@
1
- <script lang="ts" setup>
2
- import type { ContentFlag } from 'erudit-cog/schema';
3
- import { flagsData } from '@app/scripts/flag';
4
-
5
- defineProps<{ flags: Record<ContentFlag, boolean> }>();
6
-
7
- const phrases = Object.values(flagsData).map((data) => data.title);
8
- const phrase = await usePhrases(...phrases);
9
- </script>
10
-
11
- <template>
12
- <div :class="$style.flags">
13
- <MyIcon
14
- v-for="(value, flag) in flags"
15
- :name="flagsData[flag].icon"
16
- :title="phrase[flagsData[flag].title]"
17
- :class="$style.flag"
18
- />
19
- </div>
20
- </template>
21
-
22
- <style lang="scss" module>
23
- .flags {
24
- display: flex;
25
- align-items: center;
26
- gap: var(--gapSmall);
27
- }
28
-
29
- .flag {
30
- cursor: help;
31
- font-size: 16px;
32
- color: var(--textDimmed);
33
- opacity: 0.65;
34
- @include transition(opacity);
35
-
36
- &:hover {
37
- opacity: 1;
38
- }
39
- }
40
- </style>
1
+ <script lang="ts" setup>
2
+ import type { ContentFlag } from '@erudit-js/cog/schema';
3
+ import { flagsData } from '@app/scripts/flag';
4
+
5
+ defineProps<{ flags: Partial<Record<ContentFlag, boolean>> }>();
6
+
7
+ const phrases = Object.values(flagsData).map((data) => data.title);
8
+ const phrase = await usePhrases(...phrases);
9
+ </script>
10
+
11
+ <template>
12
+ <div :class="$style.flags">
13
+ <MyIcon
14
+ v-for="(value, flag) in flags"
15
+ :name="flagsData[flag].icon"
16
+ :title="phrase[flagsData[flag].title]"
17
+ :class="$style.flag"
18
+ />
19
+ </div>
20
+ </template>
21
+
22
+ <style lang="scss" module>
23
+ .flags {
24
+ display: flex;
25
+ align-items: center;
26
+ gap: var(--gapSmall);
27
+ }
28
+
29
+ .flag {
30
+ cursor: help;
31
+ font-size: 16px;
32
+ color: var(--textDimmed);
33
+ opacity: 0.65;
34
+ @include transition(opacity);
35
+
36
+ &:hover {
37
+ opacity: 1;
38
+ }
39
+ }
40
+ </style>
@@ -1,60 +1,60 @@
1
- <script lang="ts" setup>
2
- import type { FrontNavFolder } from '@shared/frontNav';
3
- import { navStateKey } from '@app/scripts/aside/major/nav';
4
-
5
- import FNavItem from './FNavItem.vue';
6
- import FNavFlags from './FNavFlags.vue';
7
-
8
- const props = defineProps<{ navItem: FrontNavFolder }>();
9
- const navState = inject(navStateKey);
10
-
11
- const active = ref(false);
12
- const accent = ref(false);
13
-
14
- function onStateUpdate() {
15
- const newState = navState!.value[props.navItem.id]!.value;
16
- active.value = newState === 'active';
17
- accent.value = newState === 'activePart';
18
- }
19
-
20
- onStateUpdate();
21
- watch(navState!.value[props.navItem.id]!, onStateUpdate);
22
-
23
- const visible = computed(() => active.value || accent.value);
24
- </script>
25
-
26
- <template>
27
- <div>
28
- <TreeItem
29
- :icon="`folder${visible ? '-open' : ''}`"
30
- :link="`/group/${navItem.id}`"
31
- :label="navItem.label"
32
- :active
33
- :accent
34
- :level="navItem.level"
35
- >
36
- <FNavFlags v-if="navItem.flags" :flags="navItem.flags" />
37
- </TreeItem>
38
-
39
- <div :class="[$style.groupBody, visible && $style.visible]">
40
- <FNavItem
41
- v-for="childItem of navItem.children"
42
- :navItem="childItem"
43
- />
44
- </div>
45
- </div>
46
- </template>
47
-
48
- <style lang="scss" module>
49
- @use '$/partials/fnav';
50
-
51
- .groupBody {
52
- overflow: hidden;
53
- height: 0;
54
- @include transition(height);
55
-
56
- &.visible {
57
- height: auto;
58
- }
59
- }
60
- </style>
1
+ <script lang="ts" setup>
2
+ import type { FrontNavFolder } from '@shared/frontNav';
3
+ import { navStateKey } from '@app/scripts/aside/major/nav';
4
+
5
+ import FNavItem from './FNavItem.vue';
6
+ import FNavFlags from './FNavFlags.vue';
7
+
8
+ const props = defineProps<{ navItem: FrontNavFolder }>();
9
+ const navState = inject(navStateKey);
10
+
11
+ const active = ref(false);
12
+ const accent = ref(false);
13
+
14
+ function onStateUpdate() {
15
+ const newState = navState!.value[props.navItem.id]!.value;
16
+ active.value = newState === 'active';
17
+ accent.value = newState === 'activePart';
18
+ }
19
+
20
+ onStateUpdate();
21
+ watch(navState!.value[props.navItem.id]!, onStateUpdate);
22
+
23
+ const visible = computed(() => active.value || accent.value);
24
+ </script>
25
+
26
+ <template>
27
+ <div>
28
+ <TreeItem
29
+ :icon="`folder${visible ? '-open' : ''}`"
30
+ :link="`/group/${navItem.id}`"
31
+ :label="navItem.label"
32
+ :active
33
+ :accent
34
+ :level="navItem.level"
35
+ >
36
+ <FNavFlags v-if="navItem.flags" :flags="navItem.flags" />
37
+ </TreeItem>
38
+
39
+ <div :class="[$style.groupBody, visible && $style.visible]">
40
+ <FNavItem
41
+ v-for="childItem of navItem.children"
42
+ :navItem="childItem"
43
+ />
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <style lang="scss" module>
49
+ @use '$/partials/fnav';
50
+
51
+ .groupBody {
52
+ overflow: hidden;
53
+ height: 0;
54
+ @include transition(height);
55
+
56
+ &.visible {
57
+ height: auto;
58
+ }
59
+ }
60
+ </style>
@@ -1,34 +1,34 @@
1
- <script lang="ts" setup>
2
- import type { FrontNavItem, FrontNavType } from '@shared/frontNav';
3
-
4
- import FNavBook from './FNavBook.vue';
5
- import FNavSeparator from './FNavSeparator.vue';
6
- import FNavFolder from './FNavFolder.vue';
7
- import FNavTopic from './FNavTopic.vue';
8
-
9
- defineProps<{ navItem: FrontNavItem }>();
10
-
11
- const navComponent: Record<FrontNavType, Component> = {
12
- book: FNavBook,
13
- separator: FNavSeparator,
14
- folder: FNavFolder,
15
- topic: FNavTopic,
16
- };
17
- </script>
18
-
19
- <template>
20
- <component
21
- :is="navComponent[navItem.type]"
22
- :navItem
23
- :class="[
24
- $style.frontNavItem,
25
- $style[
26
- `frontNav${navItem.type[0]!.toUpperCase() + navItem.type.substring(1)}`
27
- ],
28
- ]"
29
- />
30
- </template>
31
-
32
- <style lang="scss" module>
33
- @use '$/partials/fnav';
34
- </style>
1
+ <script lang="ts" setup>
2
+ import type { FrontNavItem, FrontNavType } from '@shared/frontNav';
3
+
4
+ import FNavBook from './FNavBook.vue';
5
+ import FNavSeparator from './FNavSeparator.vue';
6
+ import FNavFolder from './FNavFolder.vue';
7
+ import FNavTopic from './FNavTopic.vue';
8
+
9
+ defineProps<{ navItem: FrontNavItem }>();
10
+
11
+ const navComponent: Record<FrontNavType, Component> = {
12
+ book: FNavBook,
13
+ separator: FNavSeparator,
14
+ folder: FNavFolder,
15
+ topic: FNavTopic,
16
+ };
17
+ </script>
18
+
19
+ <template>
20
+ <component
21
+ :is="navComponent[navItem.type]"
22
+ :navItem
23
+ :class="[
24
+ $style.frontNavItem,
25
+ $style[
26
+ `frontNav${navItem.type[0]!.toUpperCase() + navItem.type.substring(1)}`
27
+ ],
28
+ ]"
29
+ />
30
+ </template>
31
+
32
+ <style lang="scss" module>
33
+ @use '$/partials/fnav';
34
+ </style>