erudit 3.0.0-dev.17 → 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 (233) 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/aside/AsideListItem.vue +74 -74
  6. package/app/components/aside/AsideMajor.vue +56 -56
  7. package/app/components/aside/AsideMinor.vue +73 -73
  8. package/app/components/aside/major/PaneContentScroll.vue +23 -23
  9. package/app/components/aside/major/PaneSwitch.vue +54 -54
  10. package/app/components/aside/major/PaneSwitchButton.vue +63 -63
  11. package/app/components/aside/major/SiteInfo.vue +85 -85
  12. package/app/components/aside/major/panes/Language.vue +79 -79
  13. package/app/components/aside/major/panes/Pages.vue +34 -34
  14. package/app/components/aside/major/panes/Search.vue +11 -11
  15. package/app/components/aside/major/panes/nav/Nav.vue +92 -92
  16. package/app/components/aside/major/panes/nav/NavBook.vue +95 -95
  17. package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
  18. package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
  19. package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
  20. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
  21. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
  22. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
  23. package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
  24. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
  25. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
  26. package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
  27. package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -13
  28. package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
  29. package/app/components/aside/major/panes/other/Other.vue +16 -16
  30. package/app/components/aside/minor/AsideMinorContributor.vue +5 -5
  31. package/app/components/aside/minor/AsideMinorNews.vue +11 -11
  32. package/app/components/aside/minor/AsideMinorPane.vue +15 -15
  33. package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
  34. package/app/components/aside/minor/Contribute.vue +145 -145
  35. package/app/components/aside/minor/content/AsideMinorContent.vue +92 -92
  36. package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -32
  37. package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
  38. package/app/components/aside/minor/topic/TopicNav.vue +49 -49
  39. package/app/components/aside/minor/topic/TopicToc.vue +214 -214
  40. package/app/components/aside/minor/topic/TopicTocItem.vue +32 -32
  41. package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
  42. package/app/components/bitran/BitranContent.vue +91 -91
  43. package/app/components/bitran/RenderWrapper.vue +10 -10
  44. package/app/components/contributor/ContributorAvatar.vue +45 -45
  45. package/app/components/contributor/ContributorListItem.vue +35 -35
  46. package/app/components/main/topic/MainTopic.vue +88 -88
  47. package/app/components/main/topic/TopicPartSwitch.vue +118 -118
  48. package/app/components/main/utils/Breadcrumb.vue +74 -74
  49. package/app/components/main/utils/ContentDecoration.vue +29 -29
  50. package/app/components/main/utils/ContentDescription.vue +19 -19
  51. package/app/components/main/utils/ContentPopover.vue +188 -188
  52. package/app/components/main/utils/ContentPopovers.vue +111 -111
  53. package/app/components/main/utils/ContentReferences.vue +70 -70
  54. package/app/components/main/utils/ContentSection.vue +45 -45
  55. package/app/components/main/utils/ContentTitle.vue +63 -63
  56. package/app/components/main/utils/reference/ReferenceGroup.vue +38 -38
  57. package/app/components/main/utils/reference/ReferenceItem.vue +70 -70
  58. package/app/components/main/utils/reference/ReferenceSource.vue +120 -120
  59. package/app/components/preview/Preview.vue +186 -186
  60. package/app/components/preview/PreviewDisplay.vue +139 -139
  61. package/app/components/preview/PreviewFooterAction.vue +73 -73
  62. package/app/components/preview/PreviewLoading.vue +14 -14
  63. package/app/components/preview/PreviewScreen.vue +141 -141
  64. package/app/components/preview/display/Alert.vue +50 -50
  65. package/app/components/preview/display/Custom.vue +18 -18
  66. package/app/components/preview/display/GenericLink.vue +48 -48
  67. package/app/components/preview/display/PageLink.vue +22 -22
  68. package/app/components/preview/display/Unique.vue +55 -55
  69. package/app/components/transition/Fade.vue +19 -19
  70. package/app/components/tree/TreeContainer.vue +11 -11
  71. package/app/components/tree/TreeItem.vue +89 -89
  72. package/app/composables/adsAllowed.ts +11 -0
  73. package/app/composables/bitran.ts +108 -108
  74. package/app/composables/bitranContent.ts +96 -92
  75. package/app/composables/bitranLocation.ts +7 -7
  76. package/app/composables/contentData.ts +38 -38
  77. package/app/composables/contentPage.ts +168 -158
  78. package/app/composables/contentRoute.ts +45 -45
  79. package/app/composables/darkMagic.ts +24 -24
  80. package/app/composables/externalApi.ts +69 -69
  81. package/app/composables/favicon.ts +8 -8
  82. package/app/composables/formatText.ts +99 -99
  83. package/app/composables/majorPane.ts +60 -60
  84. package/app/composables/phrases.ts +65 -65
  85. package/app/composables/theme.ts +29 -29
  86. package/app/composables/url.ts +33 -33
  87. package/app/pages/_test/preview.vue +110 -110
  88. package/app/pages/article/[...articleId].vue +3 -3
  89. package/app/pages/book/[...bookId].vue +47 -47
  90. package/app/pages/group/[...groupId].vue +66 -66
  91. package/app/pages/index.vue +32 -32
  92. package/app/pages/members.vue +5 -6
  93. package/app/pages/practice/[...practice].vue +3 -3
  94. package/app/pages/summary/[...summaryId].vue +3 -3
  95. package/app/plugins/analytics.ts +8 -0
  96. package/app/plugins/prerender.server.ts +22 -22
  97. package/app/scripts/_immediate.js +9 -9
  98. package/app/scripts/aside/index.ts +59 -59
  99. package/app/scripts/aside/major/nav.ts +26 -26
  100. package/app/scripts/aside/minor/state.ts +37 -37
  101. package/app/scripts/aside/minor/topic.ts +3 -3
  102. package/app/scripts/flag.ts +28 -28
  103. package/app/scripts/og.ts +27 -27
  104. package/app/scripts/preview/build.ts +76 -76
  105. package/app/scripts/preview/data/alert.ts +19 -19
  106. package/app/scripts/preview/data/custom.ts +8 -8
  107. package/app/scripts/preview/data/genericLink.ts +24 -24
  108. package/app/scripts/preview/data/pageLink.ts +23 -23
  109. package/app/scripts/preview/data/unique.ts +72 -72
  110. package/app/scripts/preview/data.ts +24 -24
  111. package/app/scripts/preview/display.ts +37 -37
  112. package/app/scripts/preview/footer.ts +9 -9
  113. package/app/scripts/preview/request.ts +51 -51
  114. package/app/scripts/preview/state.ts +63 -63
  115. package/app/styles/_immediate.css +7 -7
  116. package/app/styles/_util.scss +43 -43
  117. package/app/styles/_utils.scss +44 -44
  118. package/app/styles/app.scss +91 -91
  119. package/app/styles/def/_bp.scss +27 -27
  120. package/app/styles/def/_size.scss +7 -7
  121. package/app/styles/def/_z.scss +5 -5
  122. package/app/styles/normalize.scss +49 -49
  123. package/app/styles/partials/_darkMagic.scss +5 -5
  124. package/app/styles/partials/_fnav.scss +15 -15
  125. package/app/styles/partials/_preview.scss +5 -5
  126. package/bin/erudit.mjs +2 -2
  127. package/const.ts +4 -4
  128. package/globalPath.ts +21 -21
  129. package/globals/bitran.ts +1 -1
  130. package/globals/content.ts +27 -27
  131. package/globals/contributor.ts +5 -5
  132. package/globals/erudit.ts +5 -5
  133. package/globals/register.ts +18 -18
  134. package/languages/en.ts +94 -94
  135. package/languages/ru.ts +98 -98
  136. package/module/bitran.ts +66 -66
  137. package/module/config.ts +35 -35
  138. package/module/imports.ts +67 -67
  139. package/module/index.ts +47 -47
  140. package/module/logger.ts +10 -10
  141. package/module/paths.ts +22 -22
  142. package/module/restart.ts +61 -61
  143. package/nuxt.config.ts +131 -131
  144. package/package.json +4 -4
  145. package/server/api/aside/major/nav/bookIds.ts +5 -5
  146. package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
  147. package/server/api/aside/major/nav/global.ts +7 -7
  148. package/server/api/aside/minor/news.ts +7 -7
  149. package/server/api/aside/minor/path.ts +82 -82
  150. package/server/api/bitran/content/[...location].ts +10 -10
  151. package/server/api/bitran/toc/[...location].ts +9 -9
  152. package/server/api/content/data.ts +75 -75
  153. package/server/api/contributor/count.ts +6 -6
  154. package/server/api/fake/content.ts +11 -11
  155. package/server/api/fake/shared/languages.ts +12 -12
  156. package/server/api/language/functions.ts +12 -12
  157. package/server/api/language/phrase/[phraseId].ts +19 -19
  158. package/server/api/language/phraseIds.ts +8 -8
  159. package/server/api/prerender.ts +19 -120
  160. package/server/api/preview/page/[...parts].ts +78 -78
  161. package/server/api/preview/unique/[...location].ts +61 -61
  162. package/server/plugin/bitran/content.ts +237 -190
  163. package/server/plugin/bitran/elements/include.ts +229 -229
  164. package/server/plugin/bitran/location.ts +39 -39
  165. package/server/plugin/bitran/toc.ts +94 -94
  166. package/server/plugin/bitran/transpiler.ts +18 -18
  167. package/server/plugin/build/close.ts +12 -12
  168. package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
  169. package/server/plugin/build/jobs/content/generic.ts +191 -191
  170. package/server/plugin/build/jobs/content/parse.ts +113 -113
  171. package/server/plugin/build/jobs/content/path.ts +6 -6
  172. package/server/plugin/build/jobs/content/type/book.ts +9 -9
  173. package/server/plugin/build/jobs/content/type/group.ts +37 -37
  174. package/server/plugin/build/jobs/content/type/topic.ts +36 -36
  175. package/server/plugin/build/jobs/contributors.ts +66 -66
  176. package/server/plugin/build/jobs/language.ts +36 -36
  177. package/server/plugin/build/jobs/nav.ts +345 -345
  178. package/server/plugin/build/process.ts +32 -32
  179. package/server/plugin/build/rebuild.ts +66 -66
  180. package/server/plugin/build/setup.ts +19 -19
  181. package/server/plugin/content/context.ts +119 -119
  182. package/server/plugin/db/entities/Book.ts +7 -7
  183. package/server/plugin/db/entities/Content.ts +45 -45
  184. package/server/plugin/db/entities/Contribution.ts +10 -10
  185. package/server/plugin/db/entities/Contributor.ts +16 -16
  186. package/server/plugin/db/entities/File.ts +10 -10
  187. package/server/plugin/db/entities/Group.ts +14 -14
  188. package/server/plugin/db/entities/Hash.ts +15 -15
  189. package/server/plugin/db/entities/Topic.ts +20 -20
  190. package/server/plugin/db/entities/Unique.ts +21 -21
  191. package/server/plugin/db/reset.ts +12 -12
  192. package/server/plugin/db/setup.ts +49 -49
  193. package/server/plugin/global.ts +16 -16
  194. package/server/plugin/importer.ts +16 -16
  195. package/server/plugin/index.ts +9 -9
  196. package/server/plugin/logger.ts +23 -23
  197. package/server/plugin/nav/node.ts +27 -27
  198. package/server/plugin/nav/utils.ts +179 -175
  199. package/server/plugin/repository/book.ts +23 -21
  200. package/server/plugin/repository/content.ts +240 -240
  201. package/server/plugin/repository/contentId.ts +40 -40
  202. package/server/plugin/repository/contributor.ts +8 -8
  203. package/server/plugin/repository/file.ts +10 -10
  204. package/server/plugin/repository/frontNav.ts +145 -145
  205. package/server/plugin/repository/topic.ts +35 -35
  206. package/server/tsconfig.json +9 -9
  207. package/shared/aside/minor.ts +51 -51
  208. package/shared/asset.ts +22 -22
  209. package/shared/bitran/contentId.ts +56 -56
  210. package/shared/bitran/stringContent.ts +6 -6
  211. package/shared/bitran/toc.ts +8 -8
  212. package/shared/content/bookId.ts +12 -12
  213. package/shared/content/context.ts +9 -9
  214. package/shared/content/data/base.ts +32 -32
  215. package/shared/content/data/index.ts +5 -5
  216. package/shared/content/data/type/book.ts +5 -5
  217. package/shared/content/data/type/group.ts +6 -6
  218. package/shared/content/data/type/topic.ts +11 -11
  219. package/shared/content/previousNext.ts +9 -9
  220. package/shared/contributor.ts +5 -5
  221. package/shared/frontNav.ts +41 -41
  222. package/shared/icons.ts +38 -38
  223. package/shared/image.ts +5 -5
  224. package/shared/link.ts +28 -28
  225. package/shared/popover.ts +8 -8
  226. package/shared/types/language.ts +74 -74
  227. package/shared/utils/objectsEqual.ts +4 -4
  228. package/shared/utils/stringColor.ts +9 -9
  229. package/test/contentId.test.ts +91 -91
  230. package/tsconfig.json +8 -8
  231. package/utils/contentPath.ts +67 -67
  232. package/utils/slash.ts +11 -11
  233. 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>