erudit 3.0.0-dev.4 → 3.0.0-dev.5
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 +195 -172
- package/app/components/Loading.vue +23 -23
- package/app/components/SiteAside.vue +393 -382
- package/app/components/SiteMain.vue +35 -35
- package/app/components/ads/BannerTemplate.vue +51 -51
- package/app/components/ads/BottomBanner.vue +45 -45
- package/app/components/ads/LeftBanner.vue +50 -50
- package/app/components/aside/AsideListItem.vue +74 -74
- package/app/components/aside/AsideMajor.vue +56 -56
- package/app/components/aside/AsideMinor.vue +71 -71
- package/app/components/aside/major/PaneContentScroll.vue +23 -23
- package/app/components/aside/major/PaneSwitch.vue +54 -54
- package/app/components/aside/major/PaneSwitchButton.vue +63 -63
- package/app/components/aside/major/SiteInfo.vue +85 -85
- package/app/components/aside/major/panes/Language.vue +79 -79
- package/app/components/aside/major/panes/Pages.vue +34 -34
- package/app/components/aside/major/panes/Search.vue +11 -11
- package/app/components/aside/major/panes/nav/Nav.vue +87 -91
- package/app/components/aside/major/panes/nav/NavBook.vue +87 -87
- package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
- package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
- package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
- package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
- package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
- package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
- package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
- package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
- package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
- package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
- package/app/components/aside/major/panes/other/ItemGenerator.vue +15 -15
- package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
- package/app/components/aside/major/panes/other/Other.vue +16 -16
- package/app/components/aside/minor/AsideMinorContributor.vue +5 -5
- package/app/components/aside/minor/AsideMinorNews.vue +11 -11
- package/app/components/aside/minor/AsideMinorPane.vue +15 -15
- package/app/components/aside/minor/AsideMinorTopLink.vue +67 -67
- package/app/components/aside/minor/Contribute.vue +145 -145
- package/app/components/aside/minor/content/AsideMinorContent.vue +92 -92
- package/app/components/aside/minor/topic/AsideMinorTopic.vue +32 -32
- package/app/components/aside/minor/topic/TopicContributors.vue +177 -177
- package/app/components/aside/minor/topic/TopicNav.vue +49 -49
- package/app/components/aside/minor/topic/TopicToc.vue +219 -203
- package/app/components/aside/minor/topic/TopicTocItem.vue +30 -31
- package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
- package/app/components/bitran/BitranContent.vue +70 -63
- package/app/components/bitran/RenderWrapper.vue +10 -10
- package/app/components/contributor/ContributorAvatar.vue +43 -43
- package/app/components/contributor/ContributorListItem.vue +35 -35
- package/app/components/main/topic/MainTopic.vue +79 -79
- package/app/components/main/topic/TopicPartSwitch.vue +118 -118
- package/app/components/main/utils/Breadcrumb.vue +75 -75
- package/app/components/main/utils/ContentDecoration.vue +29 -29
- package/app/components/main/utils/ContentDescription.vue +19 -19
- package/app/components/main/utils/ContentPopover.vue +188 -176
- package/app/components/main/utils/ContentPopovers.vue +105 -105
- package/app/components/main/utils/ContentReferences.vue +70 -70
- package/app/components/main/utils/ContentSection.vue +45 -45
- package/app/components/main/utils/ContentTitle.vue +63 -39
- package/app/components/main/utils/reference/ReferenceGroup.vue +38 -38
- package/app/components/main/utils/reference/ReferenceItem.vue +68 -68
- package/app/components/main/utils/reference/ReferenceSource.vue +116 -116
- package/app/components/preview/Preview.vue +186 -177
- package/app/components/preview/PreviewDisplay.vue +139 -139
- package/app/components/preview/PreviewFooterAction.vue +73 -73
- package/app/components/preview/PreviewLoading.vue +14 -14
- package/app/components/preview/PreviewScreen.vue +141 -99
- package/app/components/preview/display/Alert.vue +50 -50
- package/app/components/preview/display/Custom.vue +18 -18
- package/app/components/preview/display/GenericLink.vue +48 -48
- package/app/components/preview/display/PageLink.vue +20 -20
- package/app/components/preview/display/Unique.vue +49 -49
- package/app/components/transition/Fade.vue +19 -19
- package/app/components/tree/TreeContainer.vue +11 -11
- package/app/components/tree/TreeItem.vue +89 -89
- package/app/composables/bitran.ts +129 -127
- package/app/composables/bitranContent.ts +39 -39
- package/app/composables/bitranLocation.ts +7 -7
- package/app/composables/contentData.ts +36 -36
- package/app/composables/contentPage.ts +157 -156
- package/app/composables/contentRoute.ts +45 -45
- package/app/composables/darkMagic.ts +24 -24
- package/app/composables/externalApi.ts +63 -63
- package/app/composables/favicon.ts +8 -8
- package/app/composables/formatText.ts +86 -86
- package/app/composables/majorPane.ts +60 -60
- package/app/composables/phrases.ts +81 -81
- package/app/composables/theme.ts +29 -29
- package/app/composables/url.ts +33 -33
- package/app/pages/_test/preview.vue +110 -110
- package/app/pages/article/[...articleId].vue +3 -3
- package/app/pages/book/[...bookId].vue +47 -47
- package/app/pages/group/[...groupId].vue +65 -65
- package/app/pages/index.vue +32 -32
- package/app/pages/members.vue +6 -6
- package/app/pages/practice/[...practice].vue +3 -3
- package/app/pages/summary/[...summaryId].vue +3 -3
- package/app/public/favicon/article.svg +9 -9
- 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 +9 -9
- package/app/scripts/aside/index.ts +59 -59
- package/app/scripts/aside/major/nav.ts +26 -26
- package/app/scripts/aside/minor/state.ts +37 -37
- package/app/scripts/aside/minor/topic.ts +3 -3
- package/app/scripts/flag.ts +28 -28
- package/app/scripts/og.ts +27 -27
- package/app/scripts/preview/build.ts +73 -73
- package/app/scripts/preview/data/alert.ts +19 -19
- package/app/scripts/preview/data/custom.ts +8 -8
- package/app/scripts/preview/data/genericLink.ts +24 -24
- package/app/scripts/preview/data/pageLink.ts +22 -22
- package/app/scripts/preview/data/unique.ts +71 -71
- package/app/scripts/preview/data.ts +24 -24
- package/app/scripts/preview/display.ts +37 -37
- package/app/scripts/preview/footer.ts +9 -9
- package/app/scripts/preview/request.ts +51 -51
- package/app/scripts/preview/state.ts +63 -63
- package/app/styles/_immediate.css +7 -7
- package/app/styles/_util.scss +43 -43
- package/app/styles/_utils.scss +44 -44
- package/app/styles/app.scss +91 -91
- package/app/styles/def/_bp.scss +27 -27
- package/app/styles/def/_size.scss +7 -7
- package/app/styles/def/_z.scss +5 -5
- package/app/styles/normalize.scss +63 -63
- package/app/styles/partials/_darkMagic.scss +5 -5
- package/app/styles/partials/_fnav.scss +15 -15
- package/app/styles/partials/_preview.scss +5 -5
- package/globalPath.ts +21 -21
- package/globals/bitran.ts +2 -47
- package/globals/content.ts +22 -22
- package/globals/contributor.ts +5 -5
- package/globals/erudit.ts +5 -5
- package/globals/register.ts +18 -18
- package/languages/en.ts +95 -95
- package/languages/ru.ts +99 -99
- package/module/bitran.ts +35 -34
- package/module/config.ts +34 -34
- package/module/imports.ts +50 -46
- package/module/index.ts +47 -47
- package/module/logger.ts +10 -10
- package/module/paths.ts +22 -22
- package/module/restart.ts +61 -61
- package/nuxt.config.ts +138 -112
- package/package.json +7 -8
- package/server/api/aside/major/nav/bookIds.ts +5 -5
- package/server/api/aside/major/nav/bookNav/[...bookId].ts +20 -20
- package/server/api/aside/major/nav/global.ts +7 -7
- package/server/api/aside/minor/news.ts +7 -7
- package/server/api/aside/minor/path.ts +78 -78
- package/server/api/bitran/content/[location].ts +8 -8
- package/server/api/bitran/toc/[location].ts +7 -7
- package/server/api/content/data.ts +72 -72
- package/server/api/contributor/count.ts +6 -6
- package/server/api/fake/content.ts +11 -11
- package/server/api/fake/shared/languages.ts +12 -12
- package/server/api/language/functions.ts +12 -12
- package/server/api/language/phrase/[phraseId].ts +19 -19
- package/server/api/language/phraseIds.ts +8 -8
- package/server/api/preview/page/[...parts].ts +51 -51
- package/server/api/preview/unique/[location].ts +57 -57
- package/server/plugin/bitran/content.ts +187 -187
- package/server/plugin/bitran/location.ts +25 -25
- package/server/plugin/bitran/products/include.ts +230 -230
- package/server/plugin/bitran/products/link.ts +116 -116
- package/server/plugin/bitran/setup.ts +11 -9
- package/server/plugin/bitran/toc.ts +83 -83
- package/server/plugin/bitran/transpiler.ts +48 -46
- package/server/plugin/build/close.ts +10 -10
- package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
- package/server/plugin/build/jobs/content/generic.ts +176 -176
- package/server/plugin/build/jobs/content/parse.ts +100 -100
- package/server/plugin/build/jobs/content/path.ts +6 -6
- package/server/plugin/build/jobs/content/type/book.ts +9 -9
- package/server/plugin/build/jobs/content/type/group.ts +37 -37
- package/server/plugin/build/jobs/content/type/topic.ts +36 -36
- package/server/plugin/build/jobs/contributors.ts +66 -66
- package/server/plugin/build/jobs/language.ts +36 -36
- package/server/plugin/build/jobs/nav.ts +210 -210
- package/server/plugin/build/process.ts +25 -25
- package/server/plugin/build/rebuild.ts +55 -55
- package/server/plugin/build/setup.ts +21 -21
- package/server/plugin/content/absoluteId.ts +94 -94
- package/server/plugin/content/context.ts +112 -112
- package/server/plugin/db/entities/Book.ts +7 -7
- package/server/plugin/db/entities/Content.ts +49 -49
- package/server/plugin/db/entities/Contribution.ts +10 -10
- package/server/plugin/db/entities/Contributor.ts +16 -16
- package/server/plugin/db/entities/Group.ts +14 -14
- package/server/plugin/db/entities/Hash.ts +15 -15
- package/server/plugin/db/entities/Topic.ts +20 -20
- package/server/plugin/db/entities/Unique.ts +21 -21
- package/server/plugin/db/setup.ts +34 -34
- package/server/plugin/global.ts +17 -18
- package/server/plugin/importer.ts +12 -12
- package/server/plugin/index.ts +9 -9
- package/server/plugin/logger.ts +23 -23
- package/server/plugin/nav/node.ts +26 -26
- package/server/plugin/nav/utils.ts +129 -129
- package/server/plugin/repository/book.ts +21 -21
- package/server/plugin/repository/content.ts +238 -238
- package/server/plugin/repository/contributor.ts +8 -8
- package/server/plugin/repository/frontNav.ts +148 -148
- package/server/plugin/repository/topic.ts +32 -32
- package/server/tsconfig.json +9 -9
- package/shared/aside/minor.ts +50 -50
- package/shared/asset.ts +15 -15
- package/shared/bitran/context.ts +8 -8
- package/shared/bitran/default.ts +46 -46
- package/shared/bitran/link/Link.vue +166 -167
- package/shared/bitran/link/factory.ts +24 -24
- package/shared/bitran/link/languages/en.ts +7 -7
- package/shared/bitran/link/languages/ru.ts +7 -7
- package/shared/bitran/link/renderer.ts +21 -21
- package/shared/bitran/link/shared.ts +17 -17
- package/shared/bitran/link/target.ts +134 -134
- package/shared/bitran/link/transpiler.ts +10 -10
- package/shared/bitran/location.ts +166 -166
- package/shared/bitran/toc.ts +8 -8
- package/shared/content/context.ts +9 -9
- package/shared/content/data/base.ts +32 -32
- package/shared/content/data/index.ts +5 -5
- package/shared/content/data/type/book.ts +5 -5
- package/shared/content/data/type/group.ts +6 -6
- package/shared/content/data/type/topic.ts +11 -11
- package/shared/content/previousNext.ts +9 -9
- package/shared/contributor.ts +5 -5
- package/shared/frontNav.ts +41 -41
- package/shared/icons.ts +38 -38
- package/shared/image.ts +5 -5
- package/shared/link.ts +25 -25
- package/shared/popover.ts +8 -0
- package/shared/types/language.ts +75 -75
- package/shared/utils/objectsEqual.ts +4 -4
- package/shared/utils/stringColor.ts +9 -9
- package/test/bitran/link/target.test.ts +141 -141
- package/test/bitran/location.test.ts +143 -143
- package/tsconfig.json +8 -8
- package/utils/stress.ts +9 -9
- package/app/components/main/utils/ContentFlag.vue +0 -15
- package/app/styles/default.scss +0 -83
|
@@ -1,230 +1,230 @@
|
|
|
1
|
-
import { BlockNode, type ElementNode } from '@bitran-js/core';
|
|
2
|
-
import type { BitranTranspiler } from '@bitran-js/transpiler';
|
|
3
|
-
import { IncludeNode } from '@erudit-js/bitran-elements/include/shared';
|
|
4
|
-
import {
|
|
5
|
-
AliasesNode,
|
|
6
|
-
tryReplaceAlias,
|
|
7
|
-
type Aliases,
|
|
8
|
-
} from '@erudit-js/bitran-elements/aliases/shared';
|
|
9
|
-
|
|
10
|
-
import { createBitranTranspiler } from '@server/bitran/transpiler';
|
|
11
|
-
import { ERUDIT_SERVER } from '@server/global';
|
|
12
|
-
import { DbUnique } from '@server/db/entities/Unique';
|
|
13
|
-
import {
|
|
14
|
-
toAbsoluteContentId,
|
|
15
|
-
toAbsoluteContentLocation,
|
|
16
|
-
} from '@server/content/absoluteId';
|
|
17
|
-
|
|
18
|
-
import type { BitranContext } from '@erudit/shared/bitran/context';
|
|
19
|
-
import {
|
|
20
|
-
parseBitranLocation,
|
|
21
|
-
parsePartialBitranLocation,
|
|
22
|
-
stringifyBitranLocation,
|
|
23
|
-
} from '@erudit/shared/bitran/location';
|
|
24
|
-
import { createLinkTarget } from '@erudit/shared/bitran/link/target';
|
|
25
|
-
import { LinkNode } from '@erudit/shared/bitran/link/shared';
|
|
26
|
-
|
|
27
|
-
export type TraverseEnterFn = (payload: {
|
|
28
|
-
_location: string;
|
|
29
|
-
_bitranTranspiler: BitranTranspiler;
|
|
30
|
-
_biCode: string;
|
|
31
|
-
}) => Promise<any>;
|
|
32
|
-
|
|
33
|
-
export type TraverseStepFn = (payload: {
|
|
34
|
-
_location: string;
|
|
35
|
-
_bitranTranspiler: BitranTranspiler;
|
|
36
|
-
_node: ElementNode;
|
|
37
|
-
}) => Promise<any>;
|
|
38
|
-
|
|
39
|
-
export type TraverseLeaveFn = (payload: { _location: string }) => Promise<any>;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* This operation is heavy as fuck.
|
|
43
|
-
* It consumes a lot of memory and is slow.
|
|
44
|
-
* Use as rarely as possible!
|
|
45
|
-
*/
|
|
46
|
-
export async function traverseInclude(
|
|
47
|
-
includeNode: IncludeNode,
|
|
48
|
-
context: BitranContext,
|
|
49
|
-
listeners: {
|
|
50
|
-
enter?: TraverseEnterFn;
|
|
51
|
-
step?: TraverseStepFn;
|
|
52
|
-
leave?: TraverseLeaveFn;
|
|
53
|
-
},
|
|
54
|
-
) {
|
|
55
|
-
const entryLocation = stringifyBitranLocation(
|
|
56
|
-
parsePartialBitranLocation(includeNode.id, context.location),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
const travelMap: Record<string, string | null> = {
|
|
60
|
-
// Not displayed when error, but needed for checking infinite loops
|
|
61
|
-
[entryLocation]: null,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
await _traverseStep(
|
|
66
|
-
includeNode,
|
|
67
|
-
entryLocation,
|
|
68
|
-
context.aliases,
|
|
69
|
-
listeners,
|
|
70
|
-
travelMap,
|
|
71
|
-
);
|
|
72
|
-
} catch (message) {
|
|
73
|
-
let finalMessage = `Include Traversal Error!\n\n${message}\n\n`;
|
|
74
|
-
|
|
75
|
-
for (const [location, includeTarget] of Object.entries(
|
|
76
|
-
travelMap,
|
|
77
|
-
).reverse()) {
|
|
78
|
-
if (includeTarget === null) continue;
|
|
79
|
-
|
|
80
|
-
finalMessage += `at "${printIncludeTarget(includeTarget)}" in "${location}"\n`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
throw new Error(finalMessage);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function _traverseStep(
|
|
88
|
-
includeNode: IncludeNode,
|
|
89
|
-
location: string,
|
|
90
|
-
aliases: Aliases,
|
|
91
|
-
listeners: {
|
|
92
|
-
enter?: TraverseEnterFn;
|
|
93
|
-
step?: TraverseStepFn;
|
|
94
|
-
leave?: TraverseLeaveFn;
|
|
95
|
-
},
|
|
96
|
-
travelMap: Record<string, string | null>,
|
|
97
|
-
) {
|
|
98
|
-
let includeTargetLocation: string;
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const parsedLocation = parseBitranLocation(location);
|
|
102
|
-
|
|
103
|
-
includeTargetLocation = stringifyBitranLocation(
|
|
104
|
-
parsePartialBitranLocation(
|
|
105
|
-
tryReplaceAlias(includeNode.parseData.location, aliases),
|
|
106
|
-
parsedLocation,
|
|
107
|
-
),
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
includeTargetLocation = toAbsoluteContentLocation(
|
|
111
|
-
includeTargetLocation,
|
|
112
|
-
parsedLocation.path!,
|
|
113
|
-
);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
travelMap[location] = includeNode.parseData.location;
|
|
116
|
-
throw error;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (includeTargetLocation in travelMap)
|
|
120
|
-
throw `Include "${printIncludeTarget(includeNode.parseData.location)}" targets "${includeTargetLocation}" which creates infinite loop!`;
|
|
121
|
-
|
|
122
|
-
travelMap[location] = includeNode.parseData.location;
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
// Loading Unique this Include is referencing to.
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
|
|
129
|
-
where: { location: includeTargetLocation },
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
if (!dbUnique)
|
|
133
|
-
throw `Include "${printIncludeTarget(includeNode.parseData.location)}" is targeting to non-existing unique "${includeTargetLocation}"!`;
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
// Creating Bitran core within loaded unique's location context.
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
const context: BitranContext = {
|
|
140
|
-
location: parseBitranLocation(includeTargetLocation),
|
|
141
|
-
aliases: dbUnique.context.aliases,
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const bitranTranspiler = await createBitranTranspiler();
|
|
145
|
-
|
|
146
|
-
listeners.enter &&
|
|
147
|
-
(await listeners.enter({
|
|
148
|
-
_biCode: dbUnique.content,
|
|
149
|
-
_location: includeTargetLocation,
|
|
150
|
-
_bitranTranspiler: bitranTranspiler,
|
|
151
|
-
}));
|
|
152
|
-
|
|
153
|
-
//
|
|
154
|
-
// Parsing unique content and sub-traversing all includes if any.
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
let stepErrorMessage: string | undefined;
|
|
158
|
-
|
|
159
|
-
await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
160
|
-
step: async (node) => {
|
|
161
|
-
if (stepErrorMessage) return;
|
|
162
|
-
|
|
163
|
-
// Skip Alias nodes to prevent them being injected into calling document context and possibly conflicting with other aliases, includes and links...
|
|
164
|
-
if (node instanceof AliasesNode) return;
|
|
165
|
-
|
|
166
|
-
// Replacing block ids with absolute ones to make possible to link to them
|
|
167
|
-
if (node instanceof BlockNode)
|
|
168
|
-
node.meta.id = Object.keys(travelMap)
|
|
169
|
-
.concat([location])
|
|
170
|
-
.join('__');
|
|
171
|
-
|
|
172
|
-
if (node instanceof LinkNode) {
|
|
173
|
-
const linkTarget = createLinkTarget(node.parseData.target, {
|
|
174
|
-
location: context.location,
|
|
175
|
-
aliases: context.aliases ?? {},
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
switch (linkTarget.type) {
|
|
179
|
-
case 'unique':
|
|
180
|
-
node.parseData.target = toAbsoluteContentLocation(
|
|
181
|
-
linkTarget.strlocation,
|
|
182
|
-
context.location?.path!,
|
|
183
|
-
);
|
|
184
|
-
break;
|
|
185
|
-
case 'page':
|
|
186
|
-
node.parseData.target = `page|${linkTarget.pageType}|${toAbsoluteContentId(linkTarget.path!, context.location?.path!)}`;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (!(node instanceof IncludeNode)) {
|
|
192
|
-
listeners.step &&
|
|
193
|
-
(await listeners.step({
|
|
194
|
-
_location: includeTargetLocation,
|
|
195
|
-
_node: node,
|
|
196
|
-
_bitranTranspiler: bitranTranspiler,
|
|
197
|
-
}));
|
|
198
|
-
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
try {
|
|
203
|
-
await _traverseStep(
|
|
204
|
-
node,
|
|
205
|
-
includeTargetLocation,
|
|
206
|
-
context.aliases,
|
|
207
|
-
listeners,
|
|
208
|
-
travelMap,
|
|
209
|
-
);
|
|
210
|
-
} catch (message: any) {
|
|
211
|
-
stepErrorMessage = message;
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
if (stepErrorMessage) throw stepErrorMessage;
|
|
217
|
-
|
|
218
|
-
//
|
|
219
|
-
// Leaving from current Include
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
listeners.leave &&
|
|
223
|
-
(await listeners.leave({
|
|
224
|
-
_location: includeTargetLocation,
|
|
225
|
-
}));
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function printIncludeTarget(target: string) {
|
|
229
|
-
return `<~ ${target}`;
|
|
230
|
-
}
|
|
1
|
+
import { BlockNode, type ElementNode } from '@bitran-js/core';
|
|
2
|
+
import type { BitranTranspiler } from '@bitran-js/transpiler';
|
|
3
|
+
import { IncludeNode } from '@erudit-js/bitran-elements/include/shared';
|
|
4
|
+
import {
|
|
5
|
+
AliasesNode,
|
|
6
|
+
tryReplaceAlias,
|
|
7
|
+
type Aliases,
|
|
8
|
+
} from '@erudit-js/bitran-elements/aliases/shared';
|
|
9
|
+
|
|
10
|
+
import { createBitranTranspiler } from '@server/bitran/transpiler';
|
|
11
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
12
|
+
import { DbUnique } from '@server/db/entities/Unique';
|
|
13
|
+
import {
|
|
14
|
+
toAbsoluteContentId,
|
|
15
|
+
toAbsoluteContentLocation,
|
|
16
|
+
} from '@server/content/absoluteId';
|
|
17
|
+
|
|
18
|
+
import type { BitranContext } from '@erudit/shared/bitran/context';
|
|
19
|
+
import {
|
|
20
|
+
parseBitranLocation,
|
|
21
|
+
parsePartialBitranLocation,
|
|
22
|
+
stringifyBitranLocation,
|
|
23
|
+
} from '@erudit/shared/bitran/location';
|
|
24
|
+
import { createLinkTarget } from '@erudit/shared/bitran/link/target';
|
|
25
|
+
import { LinkNode } from '@erudit/shared/bitran/link/shared';
|
|
26
|
+
|
|
27
|
+
export type TraverseEnterFn = (payload: {
|
|
28
|
+
_location: string;
|
|
29
|
+
_bitranTranspiler: BitranTranspiler;
|
|
30
|
+
_biCode: string;
|
|
31
|
+
}) => Promise<any>;
|
|
32
|
+
|
|
33
|
+
export type TraverseStepFn = (payload: {
|
|
34
|
+
_location: string;
|
|
35
|
+
_bitranTranspiler: BitranTranspiler;
|
|
36
|
+
_node: ElementNode;
|
|
37
|
+
}) => Promise<any>;
|
|
38
|
+
|
|
39
|
+
export type TraverseLeaveFn = (payload: { _location: string }) => Promise<any>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* This operation is heavy as fuck.
|
|
43
|
+
* It consumes a lot of memory and is slow.
|
|
44
|
+
* Use as rarely as possible!
|
|
45
|
+
*/
|
|
46
|
+
export async function traverseInclude(
|
|
47
|
+
includeNode: IncludeNode,
|
|
48
|
+
context: BitranContext,
|
|
49
|
+
listeners: {
|
|
50
|
+
enter?: TraverseEnterFn;
|
|
51
|
+
step?: TraverseStepFn;
|
|
52
|
+
leave?: TraverseLeaveFn;
|
|
53
|
+
},
|
|
54
|
+
) {
|
|
55
|
+
const entryLocation = stringifyBitranLocation(
|
|
56
|
+
parsePartialBitranLocation(includeNode.id, context.location),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const travelMap: Record<string, string | null> = {
|
|
60
|
+
// Not displayed when error, but needed for checking infinite loops
|
|
61
|
+
[entryLocation]: null,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
await _traverseStep(
|
|
66
|
+
includeNode,
|
|
67
|
+
entryLocation,
|
|
68
|
+
context.aliases,
|
|
69
|
+
listeners,
|
|
70
|
+
travelMap,
|
|
71
|
+
);
|
|
72
|
+
} catch (message) {
|
|
73
|
+
let finalMessage = `Include Traversal Error!\n\n${message}\n\n`;
|
|
74
|
+
|
|
75
|
+
for (const [location, includeTarget] of Object.entries(
|
|
76
|
+
travelMap,
|
|
77
|
+
).reverse()) {
|
|
78
|
+
if (includeTarget === null) continue;
|
|
79
|
+
|
|
80
|
+
finalMessage += `at "${printIncludeTarget(includeTarget)}" in "${location}"\n`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new Error(finalMessage);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function _traverseStep(
|
|
88
|
+
includeNode: IncludeNode,
|
|
89
|
+
location: string,
|
|
90
|
+
aliases: Aliases,
|
|
91
|
+
listeners: {
|
|
92
|
+
enter?: TraverseEnterFn;
|
|
93
|
+
step?: TraverseStepFn;
|
|
94
|
+
leave?: TraverseLeaveFn;
|
|
95
|
+
},
|
|
96
|
+
travelMap: Record<string, string | null>,
|
|
97
|
+
) {
|
|
98
|
+
let includeTargetLocation: string;
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const parsedLocation = parseBitranLocation(location);
|
|
102
|
+
|
|
103
|
+
includeTargetLocation = stringifyBitranLocation(
|
|
104
|
+
parsePartialBitranLocation(
|
|
105
|
+
tryReplaceAlias(includeNode.parseData.location, aliases),
|
|
106
|
+
parsedLocation,
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
includeTargetLocation = toAbsoluteContentLocation(
|
|
111
|
+
includeTargetLocation,
|
|
112
|
+
parsedLocation.path!,
|
|
113
|
+
);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
travelMap[location] = includeNode.parseData.location;
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (includeTargetLocation in travelMap)
|
|
120
|
+
throw `Include "${printIncludeTarget(includeNode.parseData.location)}" targets "${includeTargetLocation}" which creates infinite loop!`;
|
|
121
|
+
|
|
122
|
+
travelMap[location] = includeNode.parseData.location;
|
|
123
|
+
|
|
124
|
+
//
|
|
125
|
+
// Loading Unique this Include is referencing to.
|
|
126
|
+
//
|
|
127
|
+
|
|
128
|
+
const dbUnique = await ERUDIT_SERVER.DB.manager.findOne(DbUnique, {
|
|
129
|
+
where: { location: includeTargetLocation },
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (!dbUnique)
|
|
133
|
+
throw `Include "${printIncludeTarget(includeNode.parseData.location)}" is targeting to non-existing unique "${includeTargetLocation}"!`;
|
|
134
|
+
|
|
135
|
+
//
|
|
136
|
+
// Creating Bitran core within loaded unique's location context.
|
|
137
|
+
//
|
|
138
|
+
|
|
139
|
+
const context: BitranContext = {
|
|
140
|
+
location: parseBitranLocation(includeTargetLocation),
|
|
141
|
+
aliases: dbUnique.context.aliases,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const bitranTranspiler = await createBitranTranspiler();
|
|
145
|
+
|
|
146
|
+
listeners.enter &&
|
|
147
|
+
(await listeners.enter({
|
|
148
|
+
_biCode: dbUnique.content,
|
|
149
|
+
_location: includeTargetLocation,
|
|
150
|
+
_bitranTranspiler: bitranTranspiler,
|
|
151
|
+
}));
|
|
152
|
+
|
|
153
|
+
//
|
|
154
|
+
// Parsing unique content and sub-traversing all includes if any.
|
|
155
|
+
//
|
|
156
|
+
|
|
157
|
+
let stepErrorMessage: string | undefined;
|
|
158
|
+
|
|
159
|
+
await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
160
|
+
step: async (node) => {
|
|
161
|
+
if (stepErrorMessage) return;
|
|
162
|
+
|
|
163
|
+
// Skip Alias nodes to prevent them being injected into calling document context and possibly conflicting with other aliases, includes and links...
|
|
164
|
+
if (node instanceof AliasesNode) return;
|
|
165
|
+
|
|
166
|
+
// Replacing block ids with absolute ones to make possible to link to them
|
|
167
|
+
if (node instanceof BlockNode)
|
|
168
|
+
node.meta.id = Object.keys(travelMap)
|
|
169
|
+
.concat([location])
|
|
170
|
+
.join('__');
|
|
171
|
+
|
|
172
|
+
if (node instanceof LinkNode) {
|
|
173
|
+
const linkTarget = createLinkTarget(node.parseData.target, {
|
|
174
|
+
location: context.location,
|
|
175
|
+
aliases: context.aliases ?? {},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
switch (linkTarget.type) {
|
|
179
|
+
case 'unique':
|
|
180
|
+
node.parseData.target = toAbsoluteContentLocation(
|
|
181
|
+
linkTarget.strlocation,
|
|
182
|
+
context.location?.path!,
|
|
183
|
+
);
|
|
184
|
+
break;
|
|
185
|
+
case 'page':
|
|
186
|
+
node.parseData.target = `page|${linkTarget.pageType}|${toAbsoluteContentId(linkTarget.path!, context.location?.path!)}`;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!(node instanceof IncludeNode)) {
|
|
192
|
+
listeners.step &&
|
|
193
|
+
(await listeners.step({
|
|
194
|
+
_location: includeTargetLocation,
|
|
195
|
+
_node: node,
|
|
196
|
+
_bitranTranspiler: bitranTranspiler,
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
await _traverseStep(
|
|
204
|
+
node,
|
|
205
|
+
includeTargetLocation,
|
|
206
|
+
context.aliases,
|
|
207
|
+
listeners,
|
|
208
|
+
travelMap,
|
|
209
|
+
);
|
|
210
|
+
} catch (message: any) {
|
|
211
|
+
stepErrorMessage = message;
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (stepErrorMessage) throw stepErrorMessage;
|
|
217
|
+
|
|
218
|
+
//
|
|
219
|
+
// Leaving from current Include
|
|
220
|
+
//
|
|
221
|
+
|
|
222
|
+
listeners.leave &&
|
|
223
|
+
(await listeners.leave({
|
|
224
|
+
_location: includeTargetLocation,
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function printIncludeTarget(target: string) {
|
|
229
|
+
return `<~ ${target}`;
|
|
230
|
+
}
|