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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/app/app.vue +193 -191
  2. package/app/components/Loading.vue +23 -23
  3. package/app/components/SiteAside.vue +393 -393
  4. package/app/components/SiteMain.vue +32 -32
  5. package/app/components/ads/AdsProviderYandex.vue +2 -2
  6. package/app/components/aside/AsideListItem.vue +74 -74
  7. package/app/components/aside/AsideMajor.vue +56 -56
  8. package/app/components/aside/AsideMinor.vue +73 -73
  9. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  10. package/app/components/aside/major/PaneSwitch.vue +54 -54
  11. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  12. package/app/components/aside/major/SiteInfo.vue +85 -85
  13. package/app/components/aside/major/panes/Language.vue +79 -79
  14. package/app/components/aside/major/panes/Pages.vue +34 -34
  15. package/app/components/aside/major/panes/Search.vue +11 -11
  16. package/app/components/aside/major/panes/nav/Nav.vue +92 -92
  17. package/app/components/aside/major/panes/nav/NavBook.vue +95 -95
  18. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  19. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  20. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  21. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  22. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  23. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  24. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  25. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  26. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  27. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  28. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -13
  29. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  30. package/app/components/aside/major/panes/other/Other.vue +16 -16
  31. package/app/components/aside/minor/AsideMinorContributor.vue +5 -5
  32. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  33. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  34. package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
  35. package/app/components/aside/minor/Contribute.vue +145 -145
  36. package/app/components/aside/minor/content/AsideMinorContent.vue +92 -92
  37. package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -32
  38. package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
  39. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  40. package/app/components/aside/minor/topic/TopicToc.vue +214 -214
  41. package/app/components/aside/minor/topic/TopicTocItem.vue +32 -32
  42. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  43. package/app/components/bitran/BitranContent.vue +91 -91
  44. package/app/components/bitran/RenderWrapper.vue +10 -10
  45. package/app/components/contributor/ContributorAvatar.vue +45 -45
  46. package/app/components/contributor/ContributorListItem.vue +35 -35
  47. package/app/components/main/topic/MainTopic.vue +88 -88
  48. package/app/components/main/topic/TopicPartSwitch.vue +118 -118
  49. package/app/components/main/utils/Breadcrumb.vue +74 -74
  50. package/app/components/main/utils/ContentDecoration.vue +29 -29
  51. package/app/components/main/utils/ContentDescription.vue +19 -19
  52. package/app/components/main/utils/ContentPopover.vue +188 -188
  53. package/app/components/main/utils/ContentPopovers.vue +111 -111
  54. package/app/components/main/utils/ContentReferences.vue +70 -70
  55. package/app/components/main/utils/ContentSection.vue +45 -45
  56. package/app/components/main/utils/ContentTitle.vue +63 -63
  57. package/app/components/main/utils/reference/ReferenceGroup.vue +38 -38
  58. package/app/components/main/utils/reference/ReferenceItem.vue +70 -70
  59. package/app/components/main/utils/reference/ReferenceSource.vue +120 -120
  60. package/app/components/preview/Preview.vue +186 -186
  61. package/app/components/preview/PreviewDisplay.vue +139 -139
  62. package/app/components/preview/PreviewFooterAction.vue +73 -73
  63. package/app/components/preview/PreviewLoading.vue +14 -14
  64. package/app/components/preview/PreviewScreen.vue +141 -141
  65. package/app/components/preview/display/Alert.vue +50 -50
  66. package/app/components/preview/display/Custom.vue +18 -18
  67. package/app/components/preview/display/GenericLink.vue +48 -48
  68. package/app/components/preview/display/PageLink.vue +22 -22
  69. package/app/components/preview/display/Unique.vue +55 -55
  70. package/app/components/transition/Fade.vue +19 -19
  71. package/app/components/tree/TreeContainer.vue +11 -11
  72. package/app/components/tree/TreeItem.vue +89 -89
  73. package/app/composables/adsAllowed.ts +11 -0
  74. package/app/composables/bitran.ts +108 -108
  75. package/app/composables/bitranContent.ts +96 -92
  76. package/app/composables/bitranLocation.ts +7 -7
  77. package/app/composables/contentData.ts +38 -38
  78. package/app/composables/contentPage.ts +168 -158
  79. package/app/composables/contentRoute.ts +45 -45
  80. package/app/composables/darkMagic.ts +24 -24
  81. package/app/composables/externalApi.ts +69 -69
  82. package/app/composables/favicon.ts +8 -8
  83. package/app/composables/formatText.ts +99 -99
  84. package/app/composables/majorPane.ts +60 -60
  85. package/app/composables/phrases.ts +65 -65
  86. package/app/composables/theme.ts +29 -29
  87. package/app/composables/url.ts +33 -33
  88. package/app/pages/_test/preview.vue +110 -110
  89. package/app/pages/article/[...articleId].vue +3 -3
  90. package/app/pages/book/[...bookId].vue +47 -47
  91. package/app/pages/group/[...groupId].vue +66 -66
  92. package/app/pages/index.vue +32 -32
  93. package/app/pages/members.vue +5 -6
  94. package/app/pages/practice/[...practice].vue +3 -3
  95. package/app/pages/summary/[...summaryId].vue +3 -3
  96. package/app/plugins/analytics.ts +8 -0
  97. package/app/plugins/prerender.server.ts +22 -22
  98. package/app/scripts/_immediate.js +9 -9
  99. package/app/scripts/aside/index.ts +59 -59
  100. package/app/scripts/aside/major/nav.ts +26 -26
  101. package/app/scripts/aside/minor/state.ts +37 -37
  102. package/app/scripts/aside/minor/topic.ts +3 -3
  103. package/app/scripts/flag.ts +28 -28
  104. package/app/scripts/og.ts +27 -27
  105. package/app/scripts/preview/build.ts +76 -76
  106. package/app/scripts/preview/data/alert.ts +19 -19
  107. package/app/scripts/preview/data/custom.ts +8 -8
  108. package/app/scripts/preview/data/genericLink.ts +24 -24
  109. package/app/scripts/preview/data/pageLink.ts +23 -23
  110. package/app/scripts/preview/data/unique.ts +72 -72
  111. package/app/scripts/preview/data.ts +24 -24
  112. package/app/scripts/preview/display.ts +37 -37
  113. package/app/scripts/preview/footer.ts +9 -9
  114. package/app/scripts/preview/request.ts +51 -51
  115. package/app/scripts/preview/state.ts +63 -63
  116. package/app/styles/_immediate.css +7 -7
  117. package/app/styles/_util.scss +43 -43
  118. package/app/styles/_utils.scss +44 -44
  119. package/app/styles/app.scss +91 -91
  120. package/app/styles/def/_bp.scss +27 -27
  121. package/app/styles/def/_size.scss +7 -7
  122. package/app/styles/def/_z.scss +5 -5
  123. package/app/styles/normalize.scss +49 -49
  124. package/app/styles/partials/_darkMagic.scss +5 -5
  125. package/app/styles/partials/_fnav.scss +15 -15
  126. package/app/styles/partials/_preview.scss +5 -5
  127. package/bin/erudit.mjs +2 -2
  128. package/const.ts +4 -4
  129. package/globalPath.ts +21 -21
  130. package/globals/bitran.ts +1 -1
  131. package/globals/content.ts +27 -27
  132. package/globals/contributor.ts +5 -5
  133. package/globals/erudit.ts +5 -5
  134. package/globals/register.ts +18 -18
  135. package/languages/en.ts +94 -94
  136. package/languages/ru.ts +98 -98
  137. package/module/bitran.ts +66 -66
  138. package/module/config.ts +35 -35
  139. package/module/imports.ts +67 -67
  140. package/module/index.ts +47 -47
  141. package/module/logger.ts +10 -10
  142. package/module/paths.ts +22 -22
  143. package/module/restart.ts +61 -61
  144. package/nuxt.config.ts +131 -131
  145. package/package.json +4 -4
  146. package/server/api/aside/major/nav/bookIds.ts +5 -5
  147. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  148. package/server/api/aside/major/nav/global.ts +7 -7
  149. package/server/api/aside/minor/news.ts +7 -7
  150. package/server/api/aside/minor/path.ts +82 -82
  151. package/server/api/bitran/content/[...location].ts +10 -10
  152. package/server/api/bitran/toc/[...location].ts +9 -9
  153. package/server/api/content/data.ts +75 -75
  154. package/server/api/contributor/count.ts +6 -6
  155. package/server/api/fake/content.ts +11 -11
  156. package/server/api/fake/shared/languages.ts +12 -12
  157. package/server/api/language/functions.ts +12 -12
  158. package/server/api/language/phrase/[phraseId].ts +19 -19
  159. package/server/api/language/phraseIds.ts +8 -8
  160. package/server/api/prerender.ts +19 -120
  161. package/server/api/preview/page/[...parts].ts +78 -78
  162. package/server/api/preview/unique/[...location].ts +61 -61
  163. package/server/plugin/bitran/content.ts +237 -190
  164. package/server/plugin/bitran/elements/include.ts +229 -229
  165. package/server/plugin/bitran/location.ts +39 -39
  166. package/server/plugin/bitran/toc.ts +94 -94
  167. package/server/plugin/bitran/transpiler.ts +18 -18
  168. package/server/plugin/build/close.ts +12 -12
  169. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  170. package/server/plugin/build/jobs/content/generic.ts +191 -191
  171. package/server/plugin/build/jobs/content/parse.ts +113 -113
  172. package/server/plugin/build/jobs/content/path.ts +6 -6
  173. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  174. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  175. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  176. package/server/plugin/build/jobs/contributors.ts +66 -66
  177. package/server/plugin/build/jobs/language.ts +36 -36
  178. package/server/plugin/build/jobs/nav.ts +345 -345
  179. package/server/plugin/build/process.ts +32 -32
  180. package/server/plugin/build/rebuild.ts +66 -66
  181. package/server/plugin/build/setup.ts +19 -19
  182. package/server/plugin/content/context.ts +119 -119
  183. package/server/plugin/db/entities/Book.ts +7 -7
  184. package/server/plugin/db/entities/Content.ts +45 -45
  185. package/server/plugin/db/entities/Contribution.ts +10 -10
  186. package/server/plugin/db/entities/Contributor.ts +16 -16
  187. package/server/plugin/db/entities/File.ts +10 -10
  188. package/server/plugin/db/entities/Group.ts +14 -14
  189. package/server/plugin/db/entities/Hash.ts +15 -15
  190. package/server/plugin/db/entities/Topic.ts +20 -20
  191. package/server/plugin/db/entities/Unique.ts +21 -21
  192. package/server/plugin/db/reset.ts +12 -12
  193. package/server/plugin/db/setup.ts +49 -49
  194. package/server/plugin/global.ts +16 -16
  195. package/server/plugin/importer.ts +16 -16
  196. package/server/plugin/index.ts +9 -9
  197. package/server/plugin/logger.ts +23 -23
  198. package/server/plugin/nav/node.ts +27 -27
  199. package/server/plugin/nav/utils.ts +179 -175
  200. package/server/plugin/repository/book.ts +23 -21
  201. package/server/plugin/repository/content.ts +240 -240
  202. package/server/plugin/repository/contentId.ts +40 -40
  203. package/server/plugin/repository/contributor.ts +8 -8
  204. package/server/plugin/repository/file.ts +10 -10
  205. package/server/plugin/repository/frontNav.ts +145 -145
  206. package/server/plugin/repository/topic.ts +35 -35
  207. package/server/tsconfig.json +9 -9
  208. package/shared/aside/minor.ts +51 -51
  209. package/shared/asset.ts +22 -22
  210. package/shared/bitran/contentId.ts +56 -56
  211. package/shared/bitran/stringContent.ts +6 -6
  212. package/shared/bitran/toc.ts +8 -8
  213. package/shared/content/bookId.ts +12 -12
  214. package/shared/content/context.ts +9 -9
  215. package/shared/content/data/base.ts +32 -32
  216. package/shared/content/data/index.ts +5 -5
  217. package/shared/content/data/type/book.ts +5 -5
  218. package/shared/content/data/type/group.ts +6 -6
  219. package/shared/content/data/type/topic.ts +11 -11
  220. package/shared/content/previousNext.ts +9 -9
  221. package/shared/contributor.ts +5 -5
  222. package/shared/frontNav.ts +41 -41
  223. package/shared/icons.ts +38 -38
  224. package/shared/image.ts +5 -5
  225. package/shared/link.ts +28 -28
  226. package/shared/popover.ts +8 -8
  227. package/shared/types/language.ts +74 -74
  228. package/shared/utils/objectsEqual.ts +4 -4
  229. package/shared/utils/stringColor.ts +9 -9
  230. package/test/contentId.test.ts +91 -91
  231. package/tsconfig.json +8 -8
  232. package/utils/contentPath.ts +67 -67
  233. package/utils/slash.ts +11 -11
  234. package/utils/stress.ts +9 -9
@@ -1,92 +1,92 @@
1
- <script lang="ts" setup>
2
- import type { FrontNav } from '@shared/frontNav';
3
- import { detectContentBookId } from '@shared/content/bookId';
4
-
5
- import {
6
- getAsideMajorNavPayload,
7
- insideNavBook,
8
- navBookId,
9
- navBookVisible,
10
- } from '@app/scripts/aside/major/nav';
11
-
12
- import NavGlobal from './NavGlobal.vue';
13
- import NavBook from './NavBook.vue';
14
-
15
- const contentRoute = useContentRoute();
16
- const asideMajorNav = getAsideMajorNavPayload();
17
-
18
- asideMajorNav.booksIds ||= (await $fetch('/api/aside/major/nav/bookIds', {
19
- responseType: 'json',
20
- })) as string[];
21
-
22
- asideMajorNav.globalNav ||= (await $fetch('/api/aside/major/nav/global', {
23
- responseType: 'json',
24
- })) as FrontNav;
25
-
26
- const checkIfInsideBook = () => {
27
- if (contentRoute.value) {
28
- const bookId = detectContentBookId(
29
- contentRoute.value.contentId,
30
- asideMajorNav.booksIds,
31
- );
32
-
33
- if (bookId) {
34
- navBookId.value = bookId;
35
- insideNavBook.value = true;
36
- return;
37
- }
38
- }
39
-
40
- // If we get here, we're not in any book
41
- navBookId.value = undefined;
42
- insideNavBook.value = false;
43
- };
44
-
45
- checkIfInsideBook();
46
-
47
- onMounted(() => {
48
- watch(contentRoute, () => {
49
- checkIfInsideBook();
50
- });
51
- });
52
- </script>
53
-
54
- <template>
55
- <div :class="[$style.navHolder, navBookVisible && $style.navBookVisible]">
56
- <NavGlobal :class="$style.navGlobal" />
57
- <NavBook :class="$style.navBook" />
58
- </div>
59
- </template>
60
-
61
- <style lang="scss" module>
62
- .navHolder {
63
- position: relative;
64
- width: 100%;
65
- height: 100%;
66
-
67
- .navGlobal,
68
- .navBook {
69
- position: absolute;
70
- top: 0;
71
- left: 0;
72
- width: 100%;
73
- height: 100%;
74
- opacity: 1;
75
- @include transition(left, opacity);
76
- }
77
-
78
- &.navBookVisible {
79
- .navGlobal {
80
- left: calc(-1 * var(--wAside));
81
- opacity: 0;
82
- }
83
- }
84
-
85
- &:not(.navBookVisible) {
86
- .navBook {
87
- left: calc(1 * var(--wAside));
88
- opacity: 0;
89
- }
90
- }
91
- }
92
- </style>
1
+ <script lang="ts" setup>
2
+ import type { FrontNav } from '@shared/frontNav';
3
+ import { detectContentBookId } from '@shared/content/bookId';
4
+
5
+ import {
6
+ getAsideMajorNavPayload,
7
+ insideNavBook,
8
+ navBookId,
9
+ navBookVisible,
10
+ } from '@app/scripts/aside/major/nav';
11
+
12
+ import NavGlobal from './NavGlobal.vue';
13
+ import NavBook from './NavBook.vue';
14
+
15
+ const contentRoute = useContentRoute();
16
+ const asideMajorNav = getAsideMajorNavPayload();
17
+
18
+ asideMajorNav.booksIds ||= (await $fetch('/api/aside/major/nav/bookIds', {
19
+ responseType: 'json',
20
+ })) as string[];
21
+
22
+ asideMajorNav.globalNav ||= (await $fetch('/api/aside/major/nav/global', {
23
+ responseType: 'json',
24
+ })) as FrontNav;
25
+
26
+ const checkIfInsideBook = () => {
27
+ if (contentRoute.value) {
28
+ const bookId = detectContentBookId(
29
+ contentRoute.value.contentId,
30
+ asideMajorNav.booksIds,
31
+ );
32
+
33
+ if (bookId) {
34
+ navBookId.value = bookId;
35
+ insideNavBook.value = true;
36
+ return;
37
+ }
38
+ }
39
+
40
+ // If we get here, we're not in any book
41
+ navBookId.value = undefined;
42
+ insideNavBook.value = false;
43
+ };
44
+
45
+ checkIfInsideBook();
46
+
47
+ onMounted(() => {
48
+ watch(contentRoute, () => {
49
+ checkIfInsideBook();
50
+ });
51
+ });
52
+ </script>
53
+
54
+ <template>
55
+ <div :class="[$style.navHolder, navBookVisible && $style.navBookVisible]">
56
+ <NavGlobal :class="$style.navGlobal" />
57
+ <NavBook :class="$style.navBook" />
58
+ </div>
59
+ </template>
60
+
61
+ <style lang="scss" module>
62
+ .navHolder {
63
+ position: relative;
64
+ width: 100%;
65
+ height: 100%;
66
+
67
+ .navGlobal,
68
+ .navBook {
69
+ position: absolute;
70
+ top: 0;
71
+ left: 0;
72
+ width: 100%;
73
+ height: 100%;
74
+ opacity: 1;
75
+ @include transition(left, opacity);
76
+ }
77
+
78
+ &.navBookVisible {
79
+ .navGlobal {
80
+ left: calc(-1 * var(--wAside));
81
+ opacity: 0;
82
+ }
83
+ }
84
+
85
+ &:not(.navBookVisible) {
86
+ .navBook {
87
+ left: calc(1 * var(--wAside));
88
+ opacity: 0;
89
+ }
90
+ }
91
+ }
92
+ </style>
@@ -1,95 +1,95 @@
1
- <script lang="ts" setup>
2
- import type { FrontNavBook } from '@shared/frontNav';
3
- import { insideNavBook, navBookId } from '@app/scripts/aside/major/nav';
4
-
5
- import PaneContentScroll from '../../PaneContentScroll.vue';
6
- import FNav from './fnav/FNav.vue';
7
- import FNavFlags from './fnav/FNavFlags.vue';
8
- import NavBookLoading from './NavBookLoading.vue';
9
-
10
- const loading = ref(true);
11
-
12
- const nuxtApp = useNuxtApp();
13
- const contentRoute = useContentRoute();
14
- const book = shallowRef<FrontNavBook>();
15
-
16
- async function setupNavBook() {
17
- loading.value = true;
18
-
19
- if (!navBookId.value) return;
20
-
21
- nuxtApp.runWithContext(() =>
22
- prerenderRoutes(`/api/aside/major/nav/bookNav/${navBookId.value}`),
23
- );
24
- book.value = await $fetch(
25
- `/api/aside/major/nav/bookNav/${navBookId.value}`,
26
- { responseType: 'json' },
27
- );
28
-
29
- loading.value = false;
30
- }
31
-
32
- watch(navBookId, setupNavBook);
33
- await setupNavBook();
34
- const pharse = await usePhrases('to_index', 'about_book');
35
- </script>
36
-
37
- <template>
38
- <div>
39
- <PaneContentScroll v-if="book">
40
- <section :class="$style.bookHeader">
41
- <div :class="$style.title">{{ book.label }}</div>
42
- <FNavFlags
43
- v-if="book.flags"
44
- :flags="book.flags"
45
- :class="$style.flags"
46
- />
47
- </section>
48
- <FNav :nav="book.children!" :contentId="contentRoute?.contentId">
49
- <template v-slot:before>
50
- <section :class="$style.bookActions">
51
- <TreeItem
52
- icon="arrow-left"
53
- :label="pharse.to_index"
54
- @click="insideNavBook = false"
55
- />
56
- <TreeItem
57
- icon="book-question"
58
- :label="pharse.about_book"
59
- :active="contentRoute?.contentId === book.id"
60
- :link="`/book/${book.id}`"
61
- />
62
- </section>
63
- </template>
64
- </FNav>
65
- </PaneContentScroll>
66
- <TransitionFade>
67
- <NavBookLoading v-if="loading" />
68
- </TransitionFade>
69
- </div>
70
- </template>
71
-
72
- <style lang="scss" module>
73
- .bookHeader {
74
- display: flex;
75
- align-items: center;
76
- padding: var(--gap);
77
- border-bottom: 1px solid var(--border);
78
-
79
- .title {
80
- flex: 1;
81
- font-weight: 600;
82
- color: var(--text);
83
- }
84
-
85
- .flags {
86
- flex-shrink: 0;
87
- }
88
- }
89
-
90
- .bookActions {
91
- border-bottom: 1px solid var(--border);
92
- padding-bottom: calc(var(--gap) / 2);
93
- margin-bottom: calc(var(--gap) / 2);
94
- }
95
- </style>
1
+ <script lang="ts" setup>
2
+ import type { FrontNavBook } from '@shared/frontNav';
3
+ import { insideNavBook, navBookId } from '@app/scripts/aside/major/nav';
4
+
5
+ import PaneContentScroll from '../../PaneContentScroll.vue';
6
+ import FNav from './fnav/FNav.vue';
7
+ import FNavFlags from './fnav/FNavFlags.vue';
8
+ import NavBookLoading from './NavBookLoading.vue';
9
+
10
+ const loading = ref(true);
11
+
12
+ const nuxtApp = useNuxtApp();
13
+ const contentRoute = useContentRoute();
14
+ const book = shallowRef<FrontNavBook>();
15
+
16
+ async function setupNavBook() {
17
+ loading.value = true;
18
+
19
+ if (!navBookId.value) return;
20
+
21
+ nuxtApp.runWithContext(() =>
22
+ prerenderRoutes(`/api/aside/major/nav/bookNav/${navBookId.value}`),
23
+ );
24
+ book.value = await $fetch(
25
+ `/api/aside/major/nav/bookNav/${navBookId.value}`,
26
+ { responseType: 'json' },
27
+ );
28
+
29
+ loading.value = false;
30
+ }
31
+
32
+ watch(navBookId, setupNavBook);
33
+ await setupNavBook();
34
+ const pharse = await usePhrases('to_index', 'about_book');
35
+ </script>
36
+
37
+ <template>
38
+ <div>
39
+ <PaneContentScroll v-if="book">
40
+ <section :class="$style.bookHeader">
41
+ <div :class="$style.title">{{ book.label }}</div>
42
+ <FNavFlags
43
+ v-if="book.flags"
44
+ :flags="book.flags"
45
+ :class="$style.flags"
46
+ />
47
+ </section>
48
+ <FNav :nav="book.children!" :contentId="contentRoute?.contentId">
49
+ <template v-slot:before>
50
+ <section :class="$style.bookActions">
51
+ <TreeItem
52
+ icon="arrow-left"
53
+ :label="pharse.to_index"
54
+ @click="insideNavBook = false"
55
+ />
56
+ <TreeItem
57
+ icon="book-question"
58
+ :label="pharse.about_book"
59
+ :active="contentRoute?.contentId === book.id"
60
+ :link="`/book/${book.id}`"
61
+ />
62
+ </section>
63
+ </template>
64
+ </FNav>
65
+ </PaneContentScroll>
66
+ <TransitionFade>
67
+ <NavBookLoading v-if="loading" />
68
+ </TransitionFade>
69
+ </div>
70
+ </template>
71
+
72
+ <style lang="scss" module>
73
+ .bookHeader {
74
+ display: flex;
75
+ align-items: center;
76
+ padding: var(--gap);
77
+ border-bottom: 1px solid var(--border);
78
+
79
+ .title {
80
+ flex: 1;
81
+ font-weight: 600;
82
+ color: var(--text);
83
+ }
84
+
85
+ .flags {
86
+ flex-shrink: 0;
87
+ }
88
+ }
89
+
90
+ .bookActions {
91
+ border-bottom: 1px solid var(--border);
92
+ padding-bottom: calc(var(--gap) / 2);
93
+ margin-bottom: calc(var(--gap) / 2);
94
+ }
95
+ </style>
@@ -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>