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

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 (167) hide show
  1. package/app/app.vue +34 -11
  2. package/app/components/SiteAside.vue +17 -6
  3. package/app/components/SiteMain.vue +2 -3
  4. package/app/components/aside/AsideListItem.vue +3 -3
  5. package/app/components/aside/AsideMinor.vue +1 -1
  6. package/app/components/aside/major/SiteInfo.vue +2 -2
  7. package/app/components/aside/major/panes/Search.vue +10 -2
  8. package/app/components/aside/major/panes/nav/Nav.vue +25 -29
  9. package/app/components/aside/major/panes/nav/NavBook.vue +2 -1
  10. package/app/components/aside/major/panes/nav/NavGlobal.vue +1 -1
  11. package/app/components/aside/major/panes/nav/fnav/FNav.vue +1 -1
  12. package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +1 -1
  13. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +2 -2
  14. package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +1 -1
  15. package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +1 -1
  16. package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +1 -1
  17. package/app/components/aside/major/panes/other/ItemGenerator.vue +3 -5
  18. package/app/components/aside/minor/AsideMinorContributor.vue +1 -1
  19. package/app/components/aside/minor/AsideMinorNews.vue +1 -1
  20. package/app/components/aside/minor/AsideMinorPane.vue +2 -3
  21. package/app/components/aside/minor/content/AsideMinorContent.vue +1 -1
  22. package/app/components/aside/minor/topic/AsideMinorTopic.vue +1 -1
  23. package/app/components/aside/minor/topic/TopicContributors.vue +1 -1
  24. package/app/components/aside/minor/topic/TopicNav.vue +2 -2
  25. package/app/components/aside/minor/topic/TopicToc.vue +73 -57
  26. package/app/components/aside/minor/topic/TopicTocItem.vue +6 -7
  27. package/app/components/bitran/BitranContent.vue +31 -3
  28. package/app/components/contributor/ContributorAvatar.vue +10 -8
  29. package/app/components/main/topic/MainTopic.vue +2 -3
  30. package/app/components/main/topic/TopicPartSwitch.vue +1 -1
  31. package/app/components/main/utils/Breadcrumb.vue +1 -6
  32. package/app/components/main/utils/ContentDescription.vue +3 -4
  33. package/app/components/main/utils/ContentPopover.vue +19 -7
  34. package/app/components/main/utils/ContentPopovers.vue +13 -7
  35. package/app/components/main/utils/ContentReferences.vue +16 -22
  36. package/app/components/main/utils/ContentSection.vue +21 -18
  37. package/app/components/main/utils/ContentTitle.vue +36 -10
  38. package/app/components/main/utils/reference/ReferenceGroup.vue +5 -8
  39. package/app/components/main/utils/reference/ReferenceItem.vue +25 -21
  40. package/app/components/main/utils/reference/ReferenceSource.vue +42 -36
  41. package/app/components/preview/Preview.vue +11 -2
  42. package/app/components/preview/PreviewDisplay.vue +2 -2
  43. package/app/components/preview/PreviewLoading.vue +2 -3
  44. package/app/components/preview/PreviewScreen.vue +58 -16
  45. package/app/components/preview/display/Alert.vue +4 -4
  46. package/app/components/preview/display/Custom.vue +2 -2
  47. package/app/components/preview/display/GenericLink.vue +3 -3
  48. package/app/components/preview/display/PageLink.vue +2 -2
  49. package/app/components/preview/display/Unique.vue +9 -3
  50. package/app/components/transition/Fade.vue +4 -7
  51. package/app/components/tree/TreeContainer.vue +2 -3
  52. package/app/composables/bitran.ts +45 -64
  53. package/app/composables/bitranContent.ts +35 -3
  54. package/app/composables/bitranLocation.ts +1 -1
  55. package/app/composables/contentPage.ts +5 -4
  56. package/app/composables/contentRoute.ts +1 -1
  57. package/app/composables/externalApi.ts +1 -1
  58. package/app/composables/phrases.ts +1 -0
  59. package/app/pages/_test/preview.vue +4 -4
  60. package/app/pages/article/[...articleId].vue +1 -1
  61. package/app/pages/group/[...groupId].vue +3 -4
  62. package/app/pages/members.vue +2 -3
  63. package/app/pages/practice/[...practice].vue +1 -1
  64. package/app/pages/summary/[...summaryId].vue +1 -1
  65. package/app/public/favicon/article.svg +5 -5
  66. package/app/public/favicon/default.svg +3 -3
  67. package/app/public/favicon/practice.svg +3 -3
  68. package/app/public/favicon/summary.svg +4 -4
  69. package/app/public/logotype.svg +2 -2
  70. package/app/scripts/_immediate.js +7 -2
  71. package/app/scripts/flag.ts +1 -1
  72. package/app/scripts/preview/build.ts +17 -28
  73. package/app/scripts/preview/data/pageLink.ts +3 -1
  74. package/app/scripts/preview/data/unique.ts +7 -5
  75. package/app/scripts/preview/data.ts +12 -14
  76. package/app/scripts/preview/footer.ts +6 -6
  77. package/app/styles/_immediate.css +6 -2
  78. package/app/styles/_util.scss +13 -20
  79. package/app/styles/app.scss +1 -1
  80. package/app/styles/def/_bp.scss +13 -10
  81. package/app/styles/def/_size.scss +1 -1
  82. package/app/styles/def/_z.scss +1 -1
  83. package/app/styles/partials/_darkMagic.scss +3 -5
  84. package/app/styles/partials/_fnav.scss +4 -7
  85. package/app/styles/partials/_preview.scss +3 -5
  86. package/bin/erudit.mjs +2 -0
  87. package/const.ts +4 -0
  88. package/globalPath.ts +1 -1
  89. package/globals/bitran.ts +1 -47
  90. package/globals/content.ts +1 -1
  91. package/globals/contributor.ts +1 -1
  92. package/globals/erudit.ts +1 -1
  93. package/languages/en.ts +0 -1
  94. package/languages/ru.ts +0 -1
  95. package/module/bitran.ts +47 -15
  96. package/module/config.ts +4 -3
  97. package/module/imports.ts +19 -4
  98. package/module/index.ts +7 -7
  99. package/module/logger.ts +1 -1
  100. package/nuxt.config.ts +33 -17
  101. package/package.json +19 -13
  102. package/server/api/aside/major/nav/global.ts +1 -1
  103. package/server/api/aside/minor/path.ts +1 -2
  104. package/server/api/bitran/content/{[location].ts → [...location].ts} +2 -1
  105. package/server/api/bitran/toc/{[location].ts → [...location].ts} +1 -1
  106. package/server/api/fake/content.ts +6 -6
  107. package/server/api/language/phrase/[phraseId].ts +2 -2
  108. package/server/api/preview/page/[...parts].ts +4 -3
  109. package/server/api/preview/unique/[location].ts +9 -4
  110. package/server/plugin/bitran/content.ts +72 -45
  111. package/server/plugin/bitran/{products → elements}/include.ts +23 -37
  112. package/server/plugin/bitran/location.ts +1 -1
  113. package/server/plugin/bitran/toc.ts +23 -31
  114. package/server/plugin/bitran/transpiler.ts +4 -41
  115. package/server/plugin/build/jobs/content/files.ts +79 -0
  116. package/server/plugin/build/jobs/content/generic.ts +24 -8
  117. package/server/plugin/build/jobs/content/parse.ts +19 -10
  118. package/server/plugin/build/jobs/content/type/group.ts +1 -1
  119. package/server/plugin/build/jobs/content/type/topic.ts +1 -1
  120. package/server/plugin/build/jobs/contributors.ts +2 -2
  121. package/server/plugin/build/jobs/nav.ts +7 -2
  122. package/server/plugin/build/setup.ts +0 -2
  123. package/server/plugin/content/context.ts +6 -2
  124. package/server/plugin/db/entities/Content.ts +2 -2
  125. package/server/plugin/db/entities/File.ts +10 -0
  126. package/server/plugin/db/entities/Group.ts +1 -1
  127. package/server/plugin/db/entities/Topic.ts +1 -1
  128. package/server/plugin/db/setup.ts +2 -0
  129. package/server/plugin/global.ts +1 -3
  130. package/server/plugin/logger.ts +1 -1
  131. package/server/plugin/nav/node.ts +1 -1
  132. package/server/plugin/nav/utils.ts +4 -0
  133. package/server/plugin/repository/content.ts +8 -9
  134. package/server/plugin/repository/file.ts +10 -0
  135. package/server/plugin/repository/topic.ts +1 -1
  136. package/server/tsconfig.json +3 -1
  137. package/shared/aside/minor.ts +2 -1
  138. package/shared/asset.ts +11 -4
  139. package/shared/bitran/contentId.ts +88 -0
  140. package/shared/bitran/stringContent.ts +6 -0
  141. package/shared/content/data/base.ts +1 -1
  142. package/shared/content/data/type/topic.ts +1 -1
  143. package/shared/frontNav.ts +1 -1
  144. package/shared/icons.ts +2 -2
  145. package/shared/link.ts +5 -2
  146. package/shared/popover.ts +8 -0
  147. package/shared/types/language.ts +0 -1
  148. package/test/contentId.test.ts +91 -0
  149. package/app/components/main/utils/ContentFlag.vue +0 -16
  150. package/app/styles/default.scss +0 -85
  151. package/server/plugin/bitran/products/link.ts +0 -116
  152. package/server/plugin/bitran/setup.ts +0 -9
  153. package/server/plugin/content/absoluteId.ts +0 -94
  154. package/shared/bitran/context.ts +0 -8
  155. package/shared/bitran/default.ts +0 -46
  156. package/shared/bitran/link/Link.vue +0 -167
  157. package/shared/bitran/link/factory.ts +0 -24
  158. package/shared/bitran/link/icon.svg +0 -3
  159. package/shared/bitran/link/languages/en.ts +0 -7
  160. package/shared/bitran/link/languages/ru.ts +0 -7
  161. package/shared/bitran/link/renderer.ts +0 -21
  162. package/shared/bitran/link/shared.ts +0 -17
  163. package/shared/bitran/link/target.ts +0 -134
  164. package/shared/bitran/link/transpiler.ts +0 -10
  165. package/shared/bitran/location.ts +0 -166
  166. package/test/bitran/link/target.test.ts +0 -141
  167. package/test/bitran/location.test.ts +0 -143
@@ -1,10 +1,10 @@
1
1
  <script lang="ts" setup>
2
2
  import { headingName } from '@erudit-js/bitran-elements/heading/shared';
3
3
 
4
- import { stringifyBitranLocation } from '@shared/bitran/location';
4
+ import { stringifyBitranLocation } from '@erudit-js/cog/schema';
5
5
  import type { TocItem } from '@erudit/shared/bitran/toc';
6
- import { topicLocation } from '../../../../../app/scripts/aside/minor/topic';
7
- import { injectAsideData } from '../../../../../app/scripts/aside/minor/state';
6
+ import { topicLocation } from '@app/scripts/aside/minor/topic';
7
+ import { injectAsideData } from '@app/scripts/aside/minor/state';
8
8
  import type { AsideMinorTopic } from '@shared/aside/minor';
9
9
 
10
10
  import TopicTocItem from './TopicTocItem.vue';
@@ -23,13 +23,13 @@ type RuntimeToc = RuntimeTocItem[];
23
23
 
24
24
  const topicData = injectAsideData<AsideMinorTopic>();
25
25
  const phrase = await usePhrases('empty_toc');
26
- const runtimeToc = ref<RuntimeToc>();
26
+ const runtimeToc = ref<RuntimeToc>([]);
27
27
  const tocStateKey = ref(0);
28
28
 
29
29
  watch(topicData, setupRuntimeToc);
30
30
  setupRuntimeToc();
31
31
 
32
- function setupRuntimeToc() {
32
+ function setupRuntimeToc(): void {
33
33
  const _newToc: RuntimeToc = [];
34
34
 
35
35
  for (let i = 0; i < topicData.value.toc.length; i++) {
@@ -40,71 +40,81 @@ function setupRuntimeToc() {
40
40
  });
41
41
  }
42
42
 
43
- tocStateKey.value++;
44
43
  runtimeToc.value = _newToc;
44
+ tocStateKey.value++;
45
45
  }
46
46
 
47
47
  //
48
48
  // Live TOC
49
49
  //
50
50
 
51
- let observer: IntersectionObserver;
51
+ let observer: IntersectionObserver | null = null;
52
52
  let id2TocItemIndex: Record<string, number> = {};
53
53
 
54
- const windowEvents = ['DOMContentLoaded', 'load', 'resize', 'scroll'];
55
- let headings: RuntimeTocItem[];
56
- let closestAboveHeading: RuntimeTocItem;
54
+ const windowEvents = ['DOMContentLoaded', 'load', 'resize', 'scroll'] as const;
55
+ let headings: RuntimeTocItem[] = [];
56
+ let closestAboveHeading: RuntimeTocItem | null = null;
57
57
 
58
- function disableLiveToc() {
59
- // Live TOC heading with `window` events
58
+ function disableLiveToc(): void {
59
+ // Skip if not in client-side
60
+ if (import.meta.server) return;
60
61
 
61
- for (const event of windowEvents)
62
+ // Live TOC heading with `window` events
63
+ for (const event of windowEvents) {
62
64
  window.removeEventListener(event, updateActiveTopHeading);
65
+ }
63
66
 
64
- headings = closestAboveHeading = null;
67
+ headings = [];
68
+ closestAboveHeading = null;
65
69
 
66
70
  // Live TOC with Intersection Observer
71
+ id2TocItemIndex = {};
67
72
 
68
- id2TocItemIndex = null;
69
-
70
- observer?.disconnect();
71
- observer = null;
72
-
73
- //
73
+ if (observer) {
74
+ observer.disconnect();
75
+ observer = null;
76
+ }
74
77
 
78
+ // Reset active state
75
79
  if (runtimeToc.value?.length) {
76
- for (const tocItem of runtimeToc.value) tocItem._active = 0;
80
+ for (const tocItem of runtimeToc.value) {
81
+ tocItem._active = 0;
82
+ }
77
83
  }
78
84
  }
79
85
 
80
- function enableLiveToc() {
86
+ function enableLiveToc(): void {
87
+ // Skip if not in client-side
88
+ if (import.meta.server) return;
81
89
  if (!runtimeToc.value?.length) return;
82
90
 
83
91
  // Live TOC heading with `window` events
84
-
85
92
  headings = runtimeToc.value.filter(
86
93
  (item) => item.productName === headingName,
87
94
  );
88
95
 
89
- for (const event of windowEvents)
96
+ for (const event of windowEvents) {
90
97
  window.addEventListener(event, updateActiveTopHeading);
98
+ }
91
99
 
92
100
  updateActiveTopHeading();
93
101
 
94
102
  // Live TOC with Intersection Observer
95
-
96
103
  observer = new IntersectionObserver(intersectionTrigger);
97
104
  id2TocItemIndex = {};
98
105
 
99
106
  for (const tocItem of runtimeToc.value) {
100
107
  const id = tocItem.id;
101
108
  id2TocItemIndex[id] = tocItem._position;
102
- observer.observe(document.getElementById(id));
109
+ const element = document.getElementById(id);
110
+ if (element) {
111
+ observer.observe(element);
112
+ }
103
113
  }
104
114
  }
105
115
 
106
- function updateActiveTopHeading() {
107
- function getBottom(id: string) {
116
+ function updateActiveTopHeading(): void {
117
+ function getBottom(id: string): number {
108
118
  const defaultBottom = 1;
109
119
  const element = document.getElementById(id);
110
120
  return element ? element.getBoundingClientRect().bottom : defaultBottom;
@@ -115,39 +125,44 @@ function updateActiveTopHeading() {
115
125
  closestAboveHeading = null;
116
126
  }
117
127
 
118
- if (runtimeToc.value?.length) {
119
- let topIndex = 0;
120
- let bottomIndex = headings.length;
121
- let targetIndex = 0;
122
-
123
- while (topIndex < bottomIndex) {
124
- const middleIndex = ((topIndex + bottomIndex) / 2) | 0;
125
- const middleHeading = headings[middleIndex];
126
- const middleHeadingTop = getBottom(middleHeading.id);
127
-
128
- if (middleHeadingTop <= 0) {
129
- targetIndex = middleIndex;
130
- topIndex = middleIndex + 1;
131
- } else {
132
- bottomIndex = middleIndex;
133
- }
128
+ if (!runtimeToc.value?.length || !headings.length) return;
129
+
130
+ let topIndex = 0;
131
+ let bottomIndex = headings.length;
132
+ let targetIndex = 0;
133
+
134
+ while (topIndex < bottomIndex) {
135
+ const middleIndex = ((topIndex + bottomIndex) / 2) | 0;
136
+ const middleHeading = headings[middleIndex]!;
137
+ const middleHeadingTop = getBottom(middleHeading.id);
138
+
139
+ if (middleHeadingTop <= 0) {
140
+ targetIndex = middleIndex;
141
+ topIndex = middleIndex + 1;
142
+ } else {
143
+ bottomIndex = middleIndex;
134
144
  }
145
+ }
135
146
 
136
- closestAboveHeading = headings[targetIndex];
137
- if (closestAboveHeading && closestAboveHeading._active < 2)
138
- closestAboveHeading._active =
139
- getBottom(closestAboveHeading.id) <= 0 ? 1 : 0;
147
+ closestAboveHeading = headings[targetIndex]!;
148
+ if (closestAboveHeading && closestAboveHeading._active < 2) {
149
+ closestAboveHeading._active =
150
+ getBottom(closestAboveHeading.id) <= 0 ? 1 : 0;
140
151
  }
141
152
  }
142
153
 
143
- function intersectionTrigger(entries: IntersectionObserverEntry[]) {
154
+ function intersectionTrigger(entries: IntersectionObserverEntry[]): void {
144
155
  for (const entry of entries) {
145
- const tocItem = runtimeToc.value[id2TocItemIndex[entry.target.id]];
146
- tocItem._active = entry.isIntersecting
147
- ? 2
148
- : tocItem._active === 1
149
- ? 1
150
- : 0;
156
+ const itemIndex = id2TocItemIndex[entry.target.id]!;
157
+ const tocItem = runtimeToc.value?.[itemIndex];
158
+
159
+ if (tocItem) {
160
+ tocItem._active = entry.isIntersecting
161
+ ? 2
162
+ : tocItem._active === 1
163
+ ? 1
164
+ : 0;
165
+ }
151
166
  }
152
167
  }
153
168
 
@@ -162,8 +177,9 @@ onMounted(() => {
162
177
  if (
163
178
  stringifyBitranLocation(topicData.value.location) ===
164
179
  stringifyBitranLocation(topicLocation.value)
165
- )
180
+ ) {
166
181
  enableLiveToc();
182
+ }
167
183
  },
168
184
  { immediate: true },
169
185
  );
@@ -176,7 +192,7 @@ onUnmounted(() => {
176
192
 
177
193
  <template>
178
194
  <section :class="$style.topicToc">
179
- <TreeContainer v-if="runtimeToc.length > 0">
195
+ <TreeContainer v-if="runtimeToc?.length > 0" :key="tocStateKey">
180
196
  <TopicTocItem
181
197
  v-for="tocItem of runtimeToc"
182
198
  v-memo="[tocStateKey, tocItem.id, tocItem._active]"
@@ -1,21 +1,20 @@
1
1
  <script lang="ts" setup>
2
2
  import type { TocItem } from '@erudit/shared/bitran/toc';
3
3
 
4
- const { tocItem } = defineProps<{ tocItem: TocItem; active: boolean }>();
5
-
6
- const productName = tocItem.productName;
4
+ const props = defineProps<{ tocItem: TocItem; active: boolean }>();
5
+ const productName = props.tocItem.productName;
7
6
  const productIcon = await useBitranElementIcon(productName);
8
7
  const productPhrase = await useBitranElementLanguage(productName);
9
8
 
10
- function tocItemClick(event: Event) {
9
+ function tocItemClick(event: MouseEvent): void {
11
10
  navigateTo({
12
11
  query: {
13
- element: tocItem.id,
12
+ element: props.tocItem.id,
14
13
  },
14
+ //hash: props.tocItem.id, // Apply page hash as requested in the comment
15
15
  });
16
16
  event.preventDefault();
17
17
  event.stopPropagation();
18
- return false;
19
18
  }
20
19
  </script>
21
20
 
@@ -23,7 +22,7 @@ function tocItemClick(event: Event) {
23
22
  <TreeItem
24
23
  :label="tocItem.title || productPhrase('_element_title')"
25
24
  :level="tocItem.level"
26
- :link="`?element=${tocItem.id}` /* Apply page hash! */"
25
+ :link="`?element=${tocItem.id}`"
27
26
  :svg="productIcon"
28
27
  :active
29
28
  @click="tocItemClick"
@@ -1,7 +1,11 @@
1
1
  <script lang="ts" setup>
2
2
  import { Bitran, type BitranContent } from '@bitran-js/renderer-vue';
3
+ import {
4
+ setEruditBitranRuntime,
5
+ type BitranContext,
6
+ } from '@erudit-js/cog/schema';
3
7
 
4
- import type { BitranContext } from '@shared/bitran/context';
8
+ import eruditConfig from '#erudit/config';
5
9
 
6
10
  import RenderWrapper from './RenderWrapper.vue';
7
11
 
@@ -10,9 +14,18 @@ const props = defineProps<{
10
14
  context: BitranContext;
11
15
  }>();
12
16
 
17
+ /* Remove transpiler from Bitran Vue Component at all? It takes RootNode already... */
13
18
  const bitranTranspiler = await useBitranTranspiler();
14
19
  const bitranRenderers = await useBitranRenderers();
15
20
 
21
+ [(bitranTranspiler.parser, bitranTranspiler.stringifier)].forEach((item) => {
22
+ setEruditBitranRuntime(item, {
23
+ eruditConfig,
24
+ insideInclude: false,
25
+ context: props.context,
26
+ });
27
+ });
28
+
16
29
  const formatText = useFormatText();
17
30
 
18
31
  // onMounted(() => {
@@ -20,6 +33,9 @@ const formatText = useFormatText();
20
33
  // //console.log('Highlighting product:', urlElement.value);
21
34
  // }, { immediate: true });
22
35
  // });
36
+
37
+ const isDev = import.meta.dev;
38
+ const isServer = import.meta.server;
23
39
  </script>
24
40
 
25
41
  <template>
@@ -31,15 +47,18 @@ const formatText = useFormatText();
31
47
  :editMode="false"
32
48
  :formatText
33
49
  :RenderWrapper
50
+ :isDev
51
+ :isServer
52
+ :language="eruditConfig.language"
34
53
  />
35
54
  </template>
36
55
 
37
56
  <style lang="scss" module>
38
- @use '@bitran-js/renderer-vue/scss/def' as bitranDef;
57
+ @use '$/def/bp';
39
58
 
40
59
  .eruditBitranContainer {
41
60
  padding: var(--_pMainY) var(--_pMainX);
42
- padding-left: calc(var(--_pMainX) - #{bitranDef.$asideWidth});
61
+ padding-left: calc(var(--_pMainX) - var(--_bitran_asideWidth));
43
62
 
44
63
  // Setting up Bitran
45
64
 
@@ -59,5 +78,14 @@ const formatText = useFormatText();
59
78
  --bitran_textMuted: var(--textMuted);
60
79
  --bitran_textDimmed: var(--textDimmed);
61
80
  --bitran_textDisabled: var(--textDisabled);
81
+ --bitran_textDeep: var(--textDeep);
82
+
83
+ --bitran_colorBrand: var(--brand);
84
+
85
+ --bitran_colorBorder: var(--border);
86
+
87
+ @include bp.below('mobile') {
88
+ --bitran_gapBlocks: calc(22px);
89
+ }
62
90
  }
63
91
  </style>
@@ -7,8 +7,16 @@ const hasAvatar = computed(() => !!props.avatar);
7
7
 
8
8
  <template>
9
9
  <div
10
- :class="[$style.contributorAvatar, !hasAvatar && $style.noAvatar]"
11
- :style="{ '--_avatarBlendColor': stringColor(props.contributorId) }"
10
+ :class="$style.contributorAvatar"
11
+ :style="{
12
+ ...(!hasAvatar
13
+ ? {
14
+ backgroundImage: `url(${eruditAsset('user.svg')})`,
15
+ backgroundColor: stringColor(props.contributorId),
16
+ backgroundBlendMode: 'hard-light',
17
+ }
18
+ : {}),
19
+ }"
12
20
  >
13
21
  <img
14
22
  v-if="hasAvatar"
@@ -30,12 +38,6 @@ const hasAvatar = computed(() => !!props.avatar);
30
38
  overflow: hidden;
31
39
  background: var(--border);
32
40
 
33
- &.noAvatar {
34
- background-image: url('/_erudit-asset/user.svg');
35
- background-color: var(--_avatarBlendColor);
36
- background-blend-mode: hard-light;
37
- }
38
-
39
41
  > img {
40
42
  display: block;
41
43
  }
@@ -1,11 +1,10 @@
1
1
  <script lang="ts" setup>
2
- import type { TopicPart } from 'erudit-cog/schema';
3
- import { NO_ALIASES } from '@erudit-js/bitran-elements/aliases/shared';
2
+ import { NO_ALIASES, type TopicPart } from '@erudit-js/cog/schema';
4
3
 
5
4
  import eruditConfig from '#erudit/config';
6
5
 
7
6
  import { type ContentTopicData } from '@erudit/shared/content/data/type/topic';
8
- import { topicLocation } from '../../../../app/scripts/aside/minor/topic';
7
+ import { topicLocation } from '@app/scripts/aside/minor/topic';
9
8
 
10
9
  import ContentDecoration from '../utils/ContentDecoration.vue';
11
10
  import ContentTitle from '../utils/ContentTitle.vue';
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { topicParts, type TopicPart } from 'erudit-cog/schema';
2
+ import { topicParts, type TopicPart } from '@erudit-js/cog/schema';
3
3
 
4
4
  import type { TopicPartLinks } from '@erudit/shared/content/data/type/topic';
5
5
  import { TOPIC_PART_ICON } from '@erudit/shared/icons';
@@ -56,18 +56,13 @@ function getIcon(contextIcon: string) {
56
56
 
57
57
  @include transition(color);
58
58
 
59
- // [my-icon]
60
- // {
61
- // position: relative;
62
- // top: .6px;
63
- // }
64
-
65
59
  &:hover {
66
60
  color: var(--textMuted);
67
61
  }
68
62
  }
69
63
 
70
64
  .sep {
65
+ flex-shrink: 0;
71
66
  position: relative;
72
67
  top: 0.5px;
73
68
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- defineProps<{ description: string; }>();
2
+ defineProps<{ description: string }>();
3
3
  const pretty = await useFormatText();
4
4
  </script>
5
5
 
@@ -10,11 +10,10 @@ const pretty = await useFormatText();
10
10
  </template>
11
11
 
12
12
  <style lang="scss" module>
13
- .contentDescription
14
- {
13
+ .contentDescription {
15
14
  padding: var(--_pMainY) var(--_pMainX);
16
15
  font-weight: 500;
17
16
  font-size: 1.1em;
18
17
  color: var(--text);
19
18
  }
20
- </style>
19
+ </style>
@@ -17,8 +17,7 @@ const { floatingStyles, middlewareData } = useFloating(
17
17
  whileElementsMounted: autoUpdate,
18
18
  middleware: [
19
19
  shift({
20
- boundary: document?.querySelector('[erudit-main]'),
21
- padding: 15,
20
+ boundary: document?.querySelector('[erudit-main]') || undefined,
22
21
  }),
23
22
  arrow({ element: arrowElement }),
24
23
  ],
@@ -27,15 +26,26 @@ const { floatingStyles, middlewareData } = useFloating(
27
26
 
28
27
  const popoverVisible = ref(false);
29
28
 
29
+ const showDelay = 400;
30
30
  const hideDelay = 100;
31
- let hideTimeout;
31
+ let showTimeout: any;
32
+ let hideTimeout: any;
32
33
 
33
- function showPopover() {
34
+ function showPopover(immediate?: boolean) {
34
35
  clearTimeout(hideTimeout);
35
- popoverVisible.value = true;
36
+ clearTimeout(showTimeout);
37
+
38
+ if (immediate) {
39
+ popoverVisible.value = true;
40
+ } else {
41
+ showTimeout = setTimeout(() => {
42
+ popoverVisible.value = true;
43
+ }, showDelay);
44
+ }
36
45
  }
37
46
 
38
47
  function hidePopover() {
48
+ clearTimeout(showTimeout);
39
49
  hideTimeout = setTimeout(() => {
40
50
  popoverVisible.value = false;
41
51
  }, hideDelay);
@@ -47,8 +57,9 @@ function hidePopover() {
47
57
  ref="reference"
48
58
  :class="$style.reference"
49
59
  :style="`--popoverColor: ${data.color}`"
50
- @mouseenter="showPopover"
60
+ @mouseenter="() => showPopover()"
51
61
  @mouseleave="hidePopover"
62
+ @click="() => showPopover(true)"
52
63
  >
53
64
  <MyIcon v-if="isMyIcon(data.icon)" :name="data.icon as any" />
54
65
  <MyRuntimeIcon v-else name="popover-icon" :svg="data.icon" />
@@ -129,9 +140,10 @@ function hidePopover() {
129
140
 
130
141
  position: absolute;
131
142
  z-index: 999;
132
- min-width: 300px;
133
143
  max-width: 320px;
134
144
  padding-top: var(--gap);
145
+ padding-left: var(--gap);
146
+ padding-right: var(--gap);
135
147
  line-height: normal;
136
148
 
137
149
  .arrow {
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { ContentFlag } from '@package';
2
+ import type { ContentFlag } from '@erudit-js/cog/schema';
3
3
 
4
4
  import type { ContentGenericData } from '@shared/content/data/base';
5
5
 
@@ -24,7 +24,7 @@ const phrase = await usePhrases(
24
24
 
25
25
  const flagData: Record<ContentFlag, PopoverData> = {
26
26
  dev: {
27
- icon: <MyIconName>'alert',
27
+ icon: <MyIconName>'construction',
28
28
  color: 'var(--warn)',
29
29
  title: phrase.flag_dev,
30
30
  description: phrase.flag_dev_description,
@@ -63,13 +63,14 @@ const hasPopovers = computed(() => {
63
63
  <template>
64
64
  <section v-if="hasPopovers" :class="$style.popovers">
65
65
  <ContentPopover
66
- v-for="flagName of Object.keys(generic.flags)"
66
+ v-for="flagName of Object.keys(generic.flags) as ContentFlag[]"
67
67
  :data="flagData[flagName]"
68
68
  />
69
69
 
70
70
  <ContentPopover v-if="generic?.dependencies" :data="dependenciesData">
71
71
  <ul :class="$style.dependenciesList">
72
72
  <li v-for="(value, key) in generic.dependencies">
73
+ <MyIcon :name="'arrow-left'" wrapper="span" />
73
74
  <NuxtLink :prefetch="false" :to="key">{{ value }}</NuxtLink>
74
75
  </li>
75
76
  </ul>
@@ -87,18 +88,23 @@ const hasPopovers = computed(() => {
87
88
 
88
89
  .dependenciesList {
89
90
  margin-top: var(--gapSmall);
90
- list-style-type: square;
91
+ list-style-type: none;
91
92
  list-style-position: inside;
92
93
  padding-inline-start: 0;
93
94
 
94
95
  li {
95
- &::marker {
96
- content: '↪';
96
+ display: flex;
97
+ gap: var(--gapSmall);
98
+ align-items: center;
99
+
100
+ [my-icon] {
101
+ flex-shrink: 0;
102
+ font-size: 0.95em;
103
+ transform: scaleX(-1);
97
104
  }
98
105
 
99
106
  a {
100
107
  color: inherit;
101
- padding-left: var(--gapSmall);
102
108
  }
103
109
  }
104
110
  }
@@ -3,16 +3,16 @@ import type { ContentReferences } from '@package';
3
3
 
4
4
  import ReferenceGroup from './reference/ReferenceGroup.vue';
5
5
 
6
- const props = defineProps<{ references: ContentReferences; }>();
6
+ const props = defineProps<{ references: ContentReferences }>();
7
7
 
8
8
  const count = computed(() => {
9
- return props.references.reduce((sum, referenceGroup) => sum + (referenceGroup.references.length || 0), 0);
9
+ return props.references.reduce(
10
+ (sum, referenceGroup) => sum + (referenceGroup.references.length || 0),
11
+ 0,
12
+ );
10
13
  });
11
14
 
12
- const phrase = await usePhrases(
13
- 'references',
14
- 'references_description',
15
- );
15
+ const phrase = await usePhrases('references', 'references_description');
16
16
  </script>
17
17
 
18
18
  <template>
@@ -30,47 +30,41 @@ const phrase = await usePhrases(
30
30
  </template>
31
31
 
32
32
  <style lang="scss" module>
33
- .heading
34
- {
33
+ .heading {
35
34
  display: flex;
36
35
  align-items: center;
37
36
  gap: var(--gap);
38
37
  padding: var(--_pMainY) var(--_pMainX);
39
38
 
40
- .icon
41
- {
42
- font-size: .9em;
39
+ .icon {
40
+ font-size: 0.9em;
43
41
  color: var(--textMuted);
44
42
  }
45
43
 
46
- .count
47
- {
44
+ .count {
48
45
  position: relative;
49
46
  top: 1px;
50
47
  font-weight: 550;
51
- font-size: .6em;
52
- background: color-mix(in srgb, var(--textDimmed), transparent 65%) ;
48
+ font-size: 0.6em;
49
+ background: color-mix(in srgb, var(--textDimmed), transparent 65%);
53
50
  border-radius: 20px;
54
51
  padding: 2px 10px;
55
52
  }
56
53
  }
57
54
 
58
- .description
59
- {
55
+ .description {
60
56
  padding: var(--_pMainY) var(--_pMainX);
61
57
  }
62
58
 
63
- .referenceGroups
64
- {
59
+ .referenceGroups {
65
60
  display: flex;
66
61
  flex-direction: column;
67
62
  padding: var(--_pMainY) var(--_pMainX);
68
63
 
69
- > *:not(:last-of-type)
70
- {
64
+ > *:not(:last-of-type) {
71
65
  padding-bottom: var(--gap);
72
66
  margin-bottom: var(--gap);
73
67
  border-bottom: 1px solid var(--border);
74
68
  }
75
69
  }
76
- </style>
70
+ </style>