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.
- package/app/app.vue +34 -11
- package/app/components/SiteAside.vue +17 -6
- package/app/components/SiteMain.vue +2 -3
- package/app/components/aside/AsideListItem.vue +3 -3
- package/app/components/aside/AsideMinor.vue +1 -1
- package/app/components/aside/major/SiteInfo.vue +2 -2
- package/app/components/aside/major/panes/Search.vue +10 -2
- package/app/components/aside/major/panes/nav/Nav.vue +25 -29
- package/app/components/aside/major/panes/nav/NavBook.vue +2 -1
- package/app/components/aside/major/panes/nav/NavGlobal.vue +1 -1
- package/app/components/aside/major/panes/nav/fnav/FNav.vue +1 -1
- package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +1 -1
- package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +2 -2
- package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +1 -1
- package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +1 -1
- package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +1 -1
- package/app/components/aside/major/panes/other/ItemGenerator.vue +3 -5
- package/app/components/aside/minor/AsideMinorContributor.vue +1 -1
- package/app/components/aside/minor/AsideMinorNews.vue +1 -1
- package/app/components/aside/minor/AsideMinorPane.vue +2 -3
- package/app/components/aside/minor/content/AsideMinorContent.vue +1 -1
- package/app/components/aside/minor/topic/AsideMinorTopic.vue +1 -1
- package/app/components/aside/minor/topic/TopicContributors.vue +1 -1
- package/app/components/aside/minor/topic/TopicNav.vue +2 -2
- package/app/components/aside/minor/topic/TopicToc.vue +73 -57
- package/app/components/aside/minor/topic/TopicTocItem.vue +6 -7
- package/app/components/bitran/BitranContent.vue +31 -3
- package/app/components/contributor/ContributorAvatar.vue +10 -8
- package/app/components/main/topic/MainTopic.vue +2 -3
- package/app/components/main/topic/TopicPartSwitch.vue +1 -1
- package/app/components/main/utils/Breadcrumb.vue +1 -6
- package/app/components/main/utils/ContentDescription.vue +3 -4
- package/app/components/main/utils/ContentPopover.vue +19 -7
- package/app/components/main/utils/ContentPopovers.vue +13 -7
- package/app/components/main/utils/ContentReferences.vue +16 -22
- package/app/components/main/utils/ContentSection.vue +21 -18
- package/app/components/main/utils/ContentTitle.vue +36 -10
- package/app/components/main/utils/reference/ReferenceGroup.vue +5 -8
- package/app/components/main/utils/reference/ReferenceItem.vue +25 -21
- package/app/components/main/utils/reference/ReferenceSource.vue +42 -36
- package/app/components/preview/Preview.vue +11 -2
- package/app/components/preview/PreviewDisplay.vue +2 -2
- package/app/components/preview/PreviewLoading.vue +2 -3
- package/app/components/preview/PreviewScreen.vue +58 -16
- package/app/components/preview/display/Alert.vue +4 -4
- package/app/components/preview/display/Custom.vue +2 -2
- package/app/components/preview/display/GenericLink.vue +3 -3
- package/app/components/preview/display/PageLink.vue +2 -2
- package/app/components/preview/display/Unique.vue +9 -3
- package/app/components/transition/Fade.vue +4 -7
- package/app/components/tree/TreeContainer.vue +2 -3
- package/app/composables/bitran.ts +45 -64
- package/app/composables/bitranContent.ts +35 -3
- package/app/composables/bitranLocation.ts +1 -1
- package/app/composables/contentPage.ts +5 -4
- package/app/composables/contentRoute.ts +1 -1
- package/app/composables/externalApi.ts +1 -1
- package/app/composables/phrases.ts +1 -0
- package/app/pages/_test/preview.vue +4 -4
- package/app/pages/article/[...articleId].vue +1 -1
- package/app/pages/group/[...groupId].vue +3 -4
- package/app/pages/members.vue +2 -3
- package/app/pages/practice/[...practice].vue +1 -1
- package/app/pages/summary/[...summaryId].vue +1 -1
- package/app/public/favicon/article.svg +5 -5
- package/app/public/favicon/default.svg +3 -3
- package/app/public/favicon/practice.svg +3 -3
- package/app/public/favicon/summary.svg +4 -4
- package/app/public/logotype.svg +2 -2
- package/app/scripts/_immediate.js +7 -2
- package/app/scripts/flag.ts +1 -1
- package/app/scripts/preview/build.ts +17 -28
- package/app/scripts/preview/data/pageLink.ts +3 -1
- package/app/scripts/preview/data/unique.ts +7 -5
- package/app/scripts/preview/data.ts +12 -14
- package/app/scripts/preview/footer.ts +6 -6
- package/app/styles/_immediate.css +6 -2
- package/app/styles/_util.scss +13 -20
- package/app/styles/app.scss +1 -1
- package/app/styles/def/_bp.scss +13 -10
- package/app/styles/def/_size.scss +1 -1
- package/app/styles/def/_z.scss +1 -1
- package/app/styles/partials/_darkMagic.scss +3 -5
- package/app/styles/partials/_fnav.scss +4 -7
- package/app/styles/partials/_preview.scss +3 -5
- package/bin/erudit.mjs +2 -0
- package/const.ts +4 -0
- package/globalPath.ts +1 -1
- package/globals/bitran.ts +1 -47
- package/globals/content.ts +1 -1
- package/globals/contributor.ts +1 -1
- package/globals/erudit.ts +1 -1
- package/languages/en.ts +0 -1
- package/languages/ru.ts +0 -1
- package/module/bitran.ts +47 -15
- package/module/config.ts +4 -3
- package/module/imports.ts +19 -4
- package/module/index.ts +7 -7
- package/module/logger.ts +1 -1
- package/nuxt.config.ts +33 -17
- package/package.json +19 -13
- package/server/api/aside/major/nav/global.ts +1 -1
- package/server/api/aside/minor/path.ts +1 -2
- package/server/api/bitran/content/{[location].ts → [...location].ts} +2 -1
- package/server/api/bitran/toc/{[location].ts → [...location].ts} +1 -1
- package/server/api/fake/content.ts +6 -6
- package/server/api/language/phrase/[phraseId].ts +2 -2
- package/server/api/preview/page/[...parts].ts +4 -3
- package/server/api/preview/unique/[location].ts +9 -4
- package/server/plugin/bitran/content.ts +72 -45
- package/server/plugin/bitran/{products → elements}/include.ts +23 -37
- package/server/plugin/bitran/location.ts +1 -1
- package/server/plugin/bitran/toc.ts +23 -31
- package/server/plugin/bitran/transpiler.ts +4 -41
- package/server/plugin/build/jobs/content/files.ts +79 -0
- package/server/plugin/build/jobs/content/generic.ts +24 -8
- package/server/plugin/build/jobs/content/parse.ts +19 -10
- package/server/plugin/build/jobs/content/type/group.ts +1 -1
- package/server/plugin/build/jobs/content/type/topic.ts +1 -1
- package/server/plugin/build/jobs/contributors.ts +2 -2
- package/server/plugin/build/jobs/nav.ts +7 -2
- package/server/plugin/build/setup.ts +0 -2
- package/server/plugin/content/context.ts +6 -2
- package/server/plugin/db/entities/Content.ts +2 -2
- package/server/plugin/db/entities/File.ts +10 -0
- package/server/plugin/db/entities/Group.ts +1 -1
- package/server/plugin/db/entities/Topic.ts +1 -1
- package/server/plugin/db/setup.ts +2 -0
- package/server/plugin/global.ts +1 -3
- package/server/plugin/logger.ts +1 -1
- package/server/plugin/nav/node.ts +1 -1
- package/server/plugin/nav/utils.ts +4 -0
- package/server/plugin/repository/content.ts +8 -9
- package/server/plugin/repository/file.ts +10 -0
- package/server/plugin/repository/topic.ts +1 -1
- package/server/tsconfig.json +3 -1
- package/shared/aside/minor.ts +2 -1
- package/shared/asset.ts +11 -4
- package/shared/bitran/contentId.ts +88 -0
- package/shared/bitran/stringContent.ts +6 -0
- package/shared/content/data/base.ts +1 -1
- package/shared/content/data/type/topic.ts +1 -1
- package/shared/frontNav.ts +1 -1
- package/shared/icons.ts +2 -2
- package/shared/link.ts +5 -2
- package/shared/popover.ts +8 -0
- package/shared/types/language.ts +0 -1
- package/test/contentId.test.ts +91 -0
- package/app/components/main/utils/ContentFlag.vue +0 -16
- package/app/styles/default.scss +0 -85
- package/server/plugin/bitran/products/link.ts +0 -116
- package/server/plugin/bitran/setup.ts +0 -9
- package/server/plugin/content/absoluteId.ts +0 -94
- package/shared/bitran/context.ts +0 -8
- package/shared/bitran/default.ts +0 -46
- package/shared/bitran/link/Link.vue +0 -167
- package/shared/bitran/link/factory.ts +0 -24
- package/shared/bitran/link/icon.svg +0 -3
- package/shared/bitran/link/languages/en.ts +0 -7
- package/shared/bitran/link/languages/ru.ts +0 -7
- package/shared/bitran/link/renderer.ts +0 -21
- package/shared/bitran/link/shared.ts +0 -17
- package/shared/bitran/link/target.ts +0 -134
- package/shared/bitran/link/transpiler.ts +0 -10
- package/shared/bitran/location.ts +0 -166
- package/test/bitran/link/target.test.ts +0 -141
- 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 '@
|
|
4
|
+
import { stringifyBitranLocation } from '@erudit-js/cog/schema';
|
|
5
5
|
import type { TocItem } from '@erudit/shared/bitran/toc';
|
|
6
|
-
import { topicLocation } from '
|
|
7
|
-
import { injectAsideData } from '
|
|
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
|
-
//
|
|
58
|
+
function disableLiveToc(): void {
|
|
59
|
+
// Skip if not in client-side
|
|
60
|
+
if (import.meta.server) return;
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
// Live TOC heading with `window` events
|
|
63
|
+
for (const event of windowEvents) {
|
|
62
64
|
window.removeEventListener(event, updateActiveTopHeading);
|
|
65
|
+
}
|
|
63
66
|
|
|
64
|
-
headings =
|
|
67
|
+
headings = [];
|
|
68
|
+
closestAboveHeading = null;
|
|
65
69
|
|
|
66
70
|
// Live TOC with Intersection Observer
|
|
71
|
+
id2TocItemIndex = {};
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
146
|
-
tocItem
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
|
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
|
|
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:
|
|
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}`
|
|
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
|
|
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 '
|
|
57
|
+
@use '$/def/bp';
|
|
39
58
|
|
|
40
59
|
.eruditBitranContainer {
|
|
41
60
|
padding: var(--_pMainY) var(--_pMainX);
|
|
42
|
-
padding-left: calc(var(--_pMainX) -
|
|
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="
|
|
11
|
-
:style="{
|
|
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
|
|
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 '
|
|
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
|
|
31
|
+
let showTimeout: any;
|
|
32
|
+
let hideTimeout: any;
|
|
32
33
|
|
|
33
|
-
function showPopover() {
|
|
34
|
+
function showPopover(immediate?: boolean) {
|
|
34
35
|
clearTimeout(hideTimeout);
|
|
35
|
-
|
|
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 '@
|
|
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>'
|
|
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:
|
|
91
|
+
list-style-type: none;
|
|
91
92
|
list-style-position: inside;
|
|
92
93
|
padding-inline-start: 0;
|
|
93
94
|
|
|
94
95
|
li {
|
|
95
|
-
|
|
96
|
-
|
|
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(
|
|
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>
|