erudit 3.0.0-dev.11 → 3.0.0-dev.13
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/components/SiteMain.vue +1 -1
- package/app/components/aside/major/panes/nav/Nav.vue +11 -6
- package/app/components/aside/major/panes/nav/NavBook.vue +19 -11
- package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +1 -1
- package/app/components/aside/minor/Contribute.vue +2 -2
- 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 +2 -2
- package/app/components/aside/minor/topic/TopicToc.vue +1 -6
- package/app/components/aside/minor/topic/TopicTocItem.vue +3 -1
- package/app/components/main/utils/Breadcrumb.vue +1 -1
- package/app/components/main/utils/ContentReferences.vue +1 -1
- package/app/components/main/utils/reference/ReferenceGroup.vue +1 -1
- package/app/components/main/utils/reference/ReferenceItem.vue +5 -3
- package/app/components/main/utils/reference/ReferenceSource.vue +6 -4
- package/app/components/preview/PreviewScreen.vue +2 -2
- package/app/components/preview/display/PageLink.vue +1 -1
- package/app/composables/bitranContent.ts +2 -3
- package/app/composables/contentPage.ts +8 -7
- package/app/composables/formatText.ts +21 -8
- package/app/composables/phrases.ts +0 -16
- package/app/plugins/prerender.server.ts +22 -0
- package/app/scripts/preview/build.ts +1 -5
- package/app/scripts/preview/data/pageLink.ts +1 -0
- package/app/styles/normalize.scss +0 -14
- package/globals/content.ts +5 -0
- package/module/imports.ts +1 -0
- package/nuxt.config.ts +10 -5
- package/package.json +8 -8
- package/server/api/aside/major/nav/bookIds.ts +2 -2
- package/server/api/aside/minor/path.ts +19 -11
- package/server/api/bitran/content/[...location].ts +4 -2
- package/server/api/bitran/toc/[...location].ts +4 -2
- package/server/api/content/data.ts +5 -2
- package/server/api/prerender.ts +120 -0
- package/server/api/preview/page/[...parts].ts +30 -4
- package/server/api/preview/unique/{[location].ts → [...location].ts} +4 -3
- package/server/plugin/bitran/content.ts +3 -16
- package/server/plugin/bitran/elements/include.ts +40 -36
- package/server/plugin/bitran/location.ts +24 -10
- package/server/plugin/bitran/toc.ts +7 -2
- package/server/plugin/bitran/transpiler.ts +10 -1
- package/server/plugin/build/jobs/content/generic.ts +5 -6
- package/server/plugin/build/jobs/content/parse.ts +5 -1
- package/server/plugin/build/jobs/content/type/group.ts +2 -2
- package/server/plugin/build/jobs/content/type/topic.ts +2 -2
- package/server/plugin/build/jobs/nav.ts +28 -15
- package/server/plugin/content/context.ts +5 -2
- package/server/plugin/db/entities/Content.ts +0 -4
- package/server/plugin/db/setup.ts +1 -1
- package/server/plugin/importer.ts +5 -1
- package/server/plugin/nav/node.ts +2 -1
- package/server/plugin/nav/utils.ts +66 -24
- package/server/plugin/repository/content.ts +26 -23
- package/server/plugin/repository/contentId.ts +40 -0
- package/server/plugin/repository/frontNav.ts +6 -9
- package/server/plugin/repository/topic.ts +4 -1
- package/shared/aside/minor.ts +2 -2
- package/shared/bitran/contentId.ts +12 -44
- package/shared/content/bookId.ts +12 -0
- package/shared/frontNav.ts +1 -1
- package/test/contentId.test.ts +10 -10
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import { isTopicPart, locationFromPath } from '@erudit-js/cog/schema';
|
|
2
2
|
|
|
3
3
|
import type { AsideMinorContent, AsideMinorTopic } from '@shared/aside/minor';
|
|
4
|
-
import { getBitranToc } from '@
|
|
4
|
+
import { getBitranToc } from '@server/bitran/toc';
|
|
5
5
|
import {
|
|
6
6
|
getContentContributors,
|
|
7
|
-
getFullContentId,
|
|
8
7
|
getPreviousNext,
|
|
9
|
-
} from '@
|
|
10
|
-
import { getTopicPartsLinks } from '@
|
|
8
|
+
} from '@server/repository/content';
|
|
9
|
+
import { getTopicPartsLinks } from '@server/repository/topic';
|
|
10
|
+
import {
|
|
11
|
+
getFullContentId,
|
|
12
|
+
getShortContentId,
|
|
13
|
+
} from '@server/repository/contentId';
|
|
11
14
|
|
|
12
15
|
export default defineEventHandler(async (event) => {
|
|
13
16
|
const query = getQuery<{ path: string }>(event);
|
|
14
17
|
|
|
15
|
-
if (!query.path)
|
|
18
|
+
if (!query.path) {
|
|
16
19
|
throw createError({
|
|
17
20
|
statusCode: 400,
|
|
18
21
|
statusText: 'Missing "path" query parameter!',
|
|
19
22
|
});
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
const path = query.path.substring(1);
|
|
22
26
|
const pathStart = path.split('/')[0];
|
|
@@ -32,14 +36,18 @@ export default defineEventHandler(async (event) => {
|
|
|
32
36
|
async function createTopicData(path: string): Promise<AsideMinorTopic> {
|
|
33
37
|
const location = locationFromPath(path);
|
|
34
38
|
|
|
35
|
-
if (!location)
|
|
39
|
+
if (!location) {
|
|
36
40
|
throw createError({
|
|
37
41
|
statusCode: 400,
|
|
38
42
|
statusText: `Provided path "${path}" is not a valid topic location!`,
|
|
39
43
|
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (location.path) {
|
|
47
|
+
location.path = await getFullContentId(location.path);
|
|
48
|
+
}
|
|
40
49
|
|
|
41
50
|
const contentId = location.path;
|
|
42
|
-
const fullContentId = (await getFullContentId(contentId))!;
|
|
43
51
|
|
|
44
52
|
const toc = await getBitranToc(location);
|
|
45
53
|
const previousNext = await getPreviousNext(contentId);
|
|
@@ -48,7 +56,7 @@ async function createTopicData(path: string): Promise<AsideMinorTopic> {
|
|
|
48
56
|
|
|
49
57
|
return {
|
|
50
58
|
type: 'topic',
|
|
51
|
-
|
|
59
|
+
topicId: contentId,
|
|
52
60
|
location,
|
|
53
61
|
toc,
|
|
54
62
|
nav: {
|
|
@@ -63,14 +71,14 @@ async function createContentData(
|
|
|
63
71
|
type: string,
|
|
64
72
|
path: string,
|
|
65
73
|
): Promise<AsideMinorContent> {
|
|
66
|
-
const
|
|
67
|
-
const
|
|
74
|
+
const rawContentId = path.split('/').slice(1).join('/');
|
|
75
|
+
const contentId = (await getFullContentId(rawContentId))!;
|
|
68
76
|
const previousNext = await getPreviousNext(contentId);
|
|
69
77
|
const contributors = await getContentContributors(contentId);
|
|
70
78
|
|
|
71
79
|
return {
|
|
72
80
|
type: type as any,
|
|
73
|
-
|
|
81
|
+
contentId,
|
|
74
82
|
nav: previousNext,
|
|
75
83
|
contributors,
|
|
76
84
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseClientBitranLocation } from '@server/bitran/location';
|
|
2
2
|
import { getBitranContent } from '@server/bitran/content';
|
|
3
3
|
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
setResponseHeader(event, 'Content-Type', 'application/json; charset=utf-8');
|
|
6
|
-
const location =
|
|
6
|
+
const location = await parseClientBitranLocation(
|
|
7
|
+
event.context.params!.location,
|
|
8
|
+
);
|
|
7
9
|
return await getBitranContent(location);
|
|
8
10
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseClientBitranLocation } from '@server/bitran/location';
|
|
2
2
|
import { getBitranToc } from '@server/bitran/toc';
|
|
3
3
|
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
|
-
const location =
|
|
5
|
+
const location = await parseClientBitranLocation(
|
|
6
|
+
event.context.params!.location,
|
|
7
|
+
);
|
|
6
8
|
return await getBitranToc(location);
|
|
7
9
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getTopicPartsLinks } from '@server/repository/topic';
|
|
2
2
|
import { getContentBookFor } from '@server/repository/book';
|
|
3
3
|
import { getContentGenericData } from '@server/repository/content';
|
|
4
|
+
import { getFullContentId } from '@server/repository/contentId';
|
|
4
5
|
|
|
5
6
|
import type { ContentGenericData } from '@shared/content/data/base';
|
|
6
7
|
import type { ContentTopicData } from '@shared/content/data/type/topic';
|
|
@@ -8,13 +9,15 @@ import type { ContentGroupData } from '@shared/content/data/type/group';
|
|
|
8
9
|
import type { ContentBookData } from '@shared/content/data/type/book';
|
|
9
10
|
|
|
10
11
|
export default defineEventHandler(async (event) => {
|
|
11
|
-
|
|
12
|
+
let contentId = getQuery(event)?.contentId as string;
|
|
13
|
+
contentId = await getFullContentId(contentId);
|
|
12
14
|
|
|
13
|
-
if (!contentId)
|
|
15
|
+
if (!contentId) {
|
|
14
16
|
throw createError({
|
|
15
17
|
statusCode: 400,
|
|
16
18
|
statusText: 'Missing content ID!',
|
|
17
19
|
});
|
|
20
|
+
}
|
|
18
21
|
|
|
19
22
|
const generic = await getContentGenericData(contentId);
|
|
20
23
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
encodeBitranLocation,
|
|
3
|
+
parseBitranLocation,
|
|
4
|
+
stringifyBitranLocation,
|
|
5
|
+
} from '@erudit-js/cog/schema';
|
|
6
|
+
|
|
7
|
+
import { DbUnique } from '@server/db/entities/Unique';
|
|
8
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
9
|
+
import { DbBook } from '@server/db/entities/Book';
|
|
10
|
+
import { DbTopic } from '@server/db/entities/Topic';
|
|
11
|
+
import { DbGroup } from '@server/db/entities/Group';
|
|
12
|
+
import { DbContributor } from '@server/db/entities/Contributor';
|
|
13
|
+
import { getShortContentId } from '@server/repository/contentId';
|
|
14
|
+
|
|
15
|
+
export default defineEventHandler(async () => {
|
|
16
|
+
const routes: string[] = [];
|
|
17
|
+
routes.push(...language());
|
|
18
|
+
routes.push(...(await previewUniques()));
|
|
19
|
+
routes.push(...(await previewPages()));
|
|
20
|
+
|
|
21
|
+
return routes;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
//
|
|
25
|
+
//
|
|
26
|
+
//
|
|
27
|
+
|
|
28
|
+
function language() {
|
|
29
|
+
const phraseRoutes = Object.keys(ERUDIT_SERVER.LANGUAGE?.phrases || []).map(
|
|
30
|
+
(phraseId) => `/api/language/phrase/${phraseId}`,
|
|
31
|
+
);
|
|
32
|
+
return ['/api/language/functions', ...phraseRoutes];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function previewUniques() {
|
|
36
|
+
const dbUniques = await ERUDIT_SERVER.DB.manager.find(DbUnique, {
|
|
37
|
+
select: ['location'],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!dbUniques) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const routes: string[] = [];
|
|
45
|
+
for (const dbUnique of dbUniques) {
|
|
46
|
+
const location = parseBitranLocation(dbUnique.location);
|
|
47
|
+
|
|
48
|
+
if (location.path) {
|
|
49
|
+
location.path = await getShortContentId(location.path);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
routes.push(
|
|
53
|
+
`/api/preview/unique/${encodeBitranLocation(stringifyBitranLocation(location))}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return routes;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function previewPages() {
|
|
60
|
+
const pageRoutes: string[] = [];
|
|
61
|
+
|
|
62
|
+
// Books
|
|
63
|
+
|
|
64
|
+
const dbBooks = await ERUDIT_SERVER.DB.manager.find(DbBook, {
|
|
65
|
+
select: ['contentId'],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (dbBooks) {
|
|
69
|
+
for (const dbBook of dbBooks) {
|
|
70
|
+
const bookId = await getShortContentId(dbBook.contentId);
|
|
71
|
+
pageRoutes.push(`/api/preview/page/book/${bookId}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Topics
|
|
76
|
+
|
|
77
|
+
const dbTopics = await ERUDIT_SERVER.DB.manager.find(DbTopic, {
|
|
78
|
+
select: ['contentId', 'parts'],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (dbTopics) {
|
|
82
|
+
for (const dbTopic of dbTopics) {
|
|
83
|
+
const topicId = await getShortContentId(dbTopic.contentId);
|
|
84
|
+
for (const part of dbTopic.parts) {
|
|
85
|
+
pageRoutes.push(`/api/preview/page/${part}/${topicId}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Groups
|
|
91
|
+
|
|
92
|
+
const dbGroups = await ERUDIT_SERVER.DB.manager.find(DbGroup, {
|
|
93
|
+
select: ['contentId'],
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (dbGroups) {
|
|
97
|
+
for (const dbGroup of dbGroups) {
|
|
98
|
+
const groupId = await getShortContentId(dbGroup.contentId);
|
|
99
|
+
pageRoutes.push(`/api/preview/page/group/${groupId}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Contributors
|
|
104
|
+
|
|
105
|
+
const dbContributors = await ERUDIT_SERVER.DB.manager.find(DbContributor, {
|
|
106
|
+
select: ['contributorId'],
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (dbContributors) {
|
|
110
|
+
for (const dbContributor of dbContributors) {
|
|
111
|
+
pageRoutes.push(
|
|
112
|
+
`/api/preview/page/contributor/${dbContributor.contributorId}`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// // //
|
|
118
|
+
|
|
119
|
+
return pageRoutes;
|
|
120
|
+
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import type { LinkTargetPageType } from '@erudit-js/bitran-elements/link/target';
|
|
2
|
+
import { isContentType } from '@erudit-js/cog/schema';
|
|
3
|
+
|
|
1
4
|
import {
|
|
2
5
|
getContentContext,
|
|
3
6
|
getTopicPartContext,
|
|
4
7
|
getContributorContext,
|
|
5
|
-
} from '@
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
+
} from '@server/content/context';
|
|
9
|
+
import { getFullContentId } from '@server/repository/contentId';
|
|
10
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
11
|
+
import { DbContent } from '@server/db/entities/Content';
|
|
8
12
|
|
|
9
|
-
import type { PreviewDataPageLink } from '@app/scripts/preview/data/pageLink';
|
|
10
13
|
import type { Context, ContextItem } from '@erudit/shared/content/context';
|
|
14
|
+
import type { PreviewDataPageLink } from '@app/scripts/preview/data/pageLink';
|
|
11
15
|
|
|
12
16
|
export default defineEventHandler<Promise<PreviewDataPageLink>>(
|
|
13
17
|
async (event) => {
|
|
@@ -37,8 +41,30 @@ export default defineEventHandler<Promise<PreviewDataPageLink>>(
|
|
|
37
41
|
.map((c) => c.title)
|
|
38
42
|
.join(' / ');
|
|
39
43
|
|
|
44
|
+
const description = await (async () => {
|
|
45
|
+
if (!isContentType(pageType)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fullContentId = await getFullContentId(contentId);
|
|
50
|
+
const dbContent = await ERUDIT_SERVER.DB.manager.findOne(
|
|
51
|
+
DbContent,
|
|
52
|
+
{
|
|
53
|
+
select: ['description'],
|
|
54
|
+
where: { contentId: fullContentId },
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
if (!dbContent) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return dbContent.description?.trim();
|
|
63
|
+
})();
|
|
64
|
+
|
|
40
65
|
return <PreviewDataPageLink>{
|
|
41
66
|
type: 'page-link',
|
|
67
|
+
description,
|
|
42
68
|
footer: {
|
|
43
69
|
secondary:
|
|
44
70
|
(contextStr ? contextStr + ' • ' : '') +
|
|
@@ -2,13 +2,12 @@ import {
|
|
|
2
2
|
stringifyBitranLocation,
|
|
3
3
|
type BitranContext,
|
|
4
4
|
} from '@erudit-js/cog/schema';
|
|
5
|
-
import type { BitranContent } from '@bitran-js/renderer-vue';
|
|
6
5
|
|
|
7
|
-
import { parseUrlLocation } from '@server/bitran/location';
|
|
8
6
|
import { getLocationContext } from '@server/content/context';
|
|
9
7
|
import { ERUDIT_SERVER } from '@server/global';
|
|
10
8
|
import { DbUnique } from '@server/db/entities/Unique';
|
|
11
9
|
import { getBitranContent } from '@server/bitran/content';
|
|
10
|
+
import { parseClientBitranLocation } from '@server/bitran/location';
|
|
12
11
|
|
|
13
12
|
import type { Context } from '@shared/content/context';
|
|
14
13
|
import type { StringBitranContent } from '@erudit/shared/bitran/stringContent';
|
|
@@ -26,7 +25,9 @@ interface ReturnType {
|
|
|
26
25
|
export default defineEventHandler<Promise<ReturnType>>(async (event) => {
|
|
27
26
|
setResponseHeader(event, 'Content-Type', 'application/json; charset=utf-8');
|
|
28
27
|
|
|
29
|
-
const location =
|
|
28
|
+
const location = await parseClientBitranLocation(
|
|
29
|
+
event.context.params!.location,
|
|
30
|
+
);
|
|
30
31
|
|
|
31
32
|
const context = await getLocationContext(location);
|
|
32
33
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BlockErrorNode,
|
|
3
|
-
BlockNode,
|
|
4
3
|
BlocksNode,
|
|
5
4
|
createRenderData,
|
|
6
5
|
ElementNode,
|
|
@@ -12,7 +11,6 @@ import {
|
|
|
12
11
|
isTopicPart,
|
|
13
12
|
mergeAliases,
|
|
14
13
|
NO_ALIASES,
|
|
15
|
-
setEruditBitranRuntime,
|
|
16
14
|
stringifyBitranLocation,
|
|
17
15
|
type BitranContext,
|
|
18
16
|
type BitranLocation,
|
|
@@ -111,17 +109,13 @@ async function createBitranContent(
|
|
|
111
109
|
biCode: string,
|
|
112
110
|
generatePrerenderData: boolean = true,
|
|
113
111
|
): Promise<StringBitranContent> {
|
|
114
|
-
const bitranTranspiler = await createBitranTranspiler();
|
|
115
|
-
|
|
116
112
|
const runtime: EruditBitranRuntime = {
|
|
117
113
|
eruditConfig: ERUDIT_SERVER.CONFIG,
|
|
118
|
-
context,
|
|
119
114
|
insideInclude: false,
|
|
115
|
+
context,
|
|
120
116
|
};
|
|
121
117
|
|
|
122
|
-
|
|
123
|
-
setEruditBitranRuntime(item, runtime),
|
|
124
|
-
);
|
|
118
|
+
const bitranTranspiler = await createBitranTranspiler(runtime);
|
|
125
119
|
|
|
126
120
|
const renderDataStorage: RenderDataStorage = {};
|
|
127
121
|
|
|
@@ -183,14 +177,7 @@ async function resolveInclude(
|
|
|
183
177
|
let _blocks;
|
|
184
178
|
|
|
185
179
|
try {
|
|
186
|
-
const blocks
|
|
187
|
-
|
|
188
|
-
await traverseInclude(includeNode, context, {
|
|
189
|
-
step: async ({ _node }) => {
|
|
190
|
-
if (_node instanceof BlockNode) blocks.push(_node);
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
|
|
180
|
+
const blocks = await traverseInclude(includeNode, context, {});
|
|
194
181
|
const blocksNode = new BlocksNode(includeNode);
|
|
195
182
|
blocksNode.setNodes(blocks);
|
|
196
183
|
_blocks = blocksNode;
|
|
@@ -3,7 +3,6 @@ import type { BitranTranspiler } from '@bitran-js/transpiler';
|
|
|
3
3
|
import {
|
|
4
4
|
parseBitranLocation,
|
|
5
5
|
parsePartialBitranLocation,
|
|
6
|
-
setEruditBitranRuntime,
|
|
7
6
|
stringifyBitranLocation,
|
|
8
7
|
tryReplaceAlias,
|
|
9
8
|
type BitranAliases,
|
|
@@ -15,9 +14,10 @@ import { AliasesNode } from '@erudit-js/bitran-elements/aliases/shared';
|
|
|
15
14
|
import { createBitranTranspiler } from '@server/bitran/transpiler';
|
|
16
15
|
import { ERUDIT_SERVER } from '@server/global';
|
|
17
16
|
import { DbUnique } from '@server/db/entities/Unique';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
import {
|
|
18
|
+
resolveClientContentId,
|
|
19
|
+
serverAbsolutizeContentPath,
|
|
20
|
+
} from '@server/repository/contentId';
|
|
21
21
|
|
|
22
22
|
export type TraverseEnterFn = (payload: {
|
|
23
23
|
_location: string;
|
|
@@ -41,24 +41,27 @@ export async function traverseInclude(
|
|
|
41
41
|
step?: TraverseStepFn;
|
|
42
42
|
leave?: TraverseLeaveFn;
|
|
43
43
|
},
|
|
44
|
-
) {
|
|
45
|
-
const
|
|
46
|
-
|
|
44
|
+
): Promise<BlockNode[]> {
|
|
45
|
+
const rawLocation = parsePartialBitranLocation(
|
|
46
|
+
includeNode.id,
|
|
47
|
+
context.location,
|
|
47
48
|
);
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
if (rawLocation.path) {
|
|
51
|
+
rawLocation.path = serverAbsolutizeContentPath(
|
|
52
|
+
rawLocation.path,
|
|
53
|
+
context.location.path!,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const absEntryLocation = stringifyBitranLocation(rawLocation);
|
|
55
58
|
|
|
56
59
|
const travelMap: Record<string, string | null> = {
|
|
57
60
|
[absEntryLocation]: null,
|
|
58
61
|
};
|
|
59
62
|
|
|
60
63
|
try {
|
|
61
|
-
await
|
|
64
|
+
return await _traverseInclude(
|
|
62
65
|
includeNode,
|
|
63
66
|
absEntryLocation,
|
|
64
67
|
context.aliases,
|
|
@@ -79,7 +82,7 @@ export async function traverseInclude(
|
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
async function
|
|
85
|
+
async function _traverseInclude(
|
|
83
86
|
includeNode: IncludeNode,
|
|
84
87
|
location: string,
|
|
85
88
|
aliases: BitranAliases,
|
|
@@ -89,24 +92,27 @@ async function _traverseStep(
|
|
|
89
92
|
leave?: TraverseLeaveFn;
|
|
90
93
|
},
|
|
91
94
|
travelMap: Record<string, string | null>,
|
|
92
|
-
) {
|
|
95
|
+
): Promise<BlockNode[]> {
|
|
93
96
|
let includeTargetLocation: string;
|
|
94
97
|
|
|
95
98
|
try {
|
|
96
99
|
const parsedLocation = parseBitranLocation(location);
|
|
97
100
|
|
|
98
|
-
includeTargetLocation =
|
|
99
|
-
parsePartialBitranLocation(
|
|
101
|
+
includeTargetLocation = (() => {
|
|
102
|
+
const _location = parsePartialBitranLocation(
|
|
100
103
|
tryReplaceAlias(includeNode.parseData.location, aliases),
|
|
101
104
|
parsedLocation,
|
|
102
|
-
)
|
|
103
|
-
);
|
|
105
|
+
);
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
if (_location.path) {
|
|
108
|
+
_location.path = serverAbsolutizeContentPath(
|
|
109
|
+
_location.path,
|
|
110
|
+
parsedLocation.path!,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return stringifyBitranLocation(_location);
|
|
115
|
+
})();
|
|
110
116
|
} catch (error) {
|
|
111
117
|
travelMap[location] = includeNode.parseData.location;
|
|
112
118
|
throw new Error(
|
|
@@ -144,15 +150,11 @@ async function _traverseStep(
|
|
|
144
150
|
aliases: dbUnique.context.aliases,
|
|
145
151
|
};
|
|
146
152
|
|
|
147
|
-
const bitranTranspiler = await createBitranTranspiler(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
context: structuredClone(context),
|
|
153
|
-
insideInclude: true,
|
|
154
|
-
}),
|
|
155
|
-
);
|
|
153
|
+
const bitranTranspiler = await createBitranTranspiler({
|
|
154
|
+
eruditConfig: ERUDIT_SERVER.CONFIG,
|
|
155
|
+
context: structuredClone(context),
|
|
156
|
+
insideInclude: true,
|
|
157
|
+
});
|
|
156
158
|
|
|
157
159
|
if (listeners.enter) {
|
|
158
160
|
await listeners.enter({
|
|
@@ -168,7 +170,7 @@ async function _traverseStep(
|
|
|
168
170
|
|
|
169
171
|
let stepErrorMessage: string | Error | undefined;
|
|
170
172
|
|
|
171
|
-
await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
173
|
+
const rootNode = await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
172
174
|
step: async (node) => {
|
|
173
175
|
if (stepErrorMessage) return;
|
|
174
176
|
|
|
@@ -193,7 +195,7 @@ async function _traverseStep(
|
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
try {
|
|
196
|
-
await
|
|
198
|
+
await _traverseInclude(
|
|
197
199
|
node,
|
|
198
200
|
includeTargetLocation,
|
|
199
201
|
context.aliases,
|
|
@@ -218,6 +220,8 @@ async function _traverseStep(
|
|
|
218
220
|
_location: includeTargetLocation,
|
|
219
221
|
});
|
|
220
222
|
}
|
|
223
|
+
|
|
224
|
+
return (rootNode.children as BlockNode[]) ?? [];
|
|
221
225
|
}
|
|
222
226
|
|
|
223
227
|
function printIncludeTarget(target: string) {
|
|
@@ -3,23 +3,37 @@ import {
|
|
|
3
3
|
parseBitranLocation,
|
|
4
4
|
} from '@erudit-js/cog/schema';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
urlLocation = decodeURIComponent(urlLocation);
|
|
8
|
-
urlLocation = decodeBitranLocation(urlLocation);
|
|
6
|
+
import { getFullContentId } from '@server/repository/contentId';
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
export async function parseClientBitranLocation(clientLocation: string) {
|
|
9
|
+
clientLocation = decodeURIComponent(clientLocation);
|
|
10
|
+
clientLocation = decodeBitranLocation(clientLocation);
|
|
11
|
+
|
|
12
|
+
if (!clientLocation) {
|
|
11
13
|
throw createError({
|
|
12
|
-
statusCode:
|
|
14
|
+
statusCode: 400,
|
|
13
15
|
statusText: 'Empty content location router parameter!',
|
|
14
16
|
});
|
|
17
|
+
}
|
|
15
18
|
|
|
16
19
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const location = parseBitranLocation(clientLocation);
|
|
21
|
+
|
|
22
|
+
if (location.path) {
|
|
23
|
+
location.path = await getFullContentId(location.path);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return location;
|
|
27
|
+
} catch (_error) {
|
|
28
|
+
let error = `Failed to parse client location "${clientLocation}"!`;
|
|
29
|
+
|
|
30
|
+
if (_error) {
|
|
31
|
+
error += '\n\n' + _error;
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
throw createError({
|
|
20
|
-
statusCode:
|
|
21
|
-
statusText:
|
|
22
|
-
error?.message || `Can't parse location "${urlLocation}"!`,
|
|
35
|
+
statusCode: 400,
|
|
36
|
+
statusText: error,
|
|
23
37
|
});
|
|
24
38
|
}
|
|
25
39
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ElementNode } from '@bitran-js/core';
|
|
2
|
-
import type
|
|
2
|
+
import { NO_ALIASES, type BitranLocation } from '@erudit-js/cog/schema';
|
|
3
3
|
import {
|
|
4
4
|
headingName,
|
|
5
5
|
HeadingNode,
|
|
@@ -16,7 +16,12 @@ import { createBitranTranspiler } from './transpiler';
|
|
|
16
16
|
|
|
17
17
|
export async function getBitranToc(location: BitranLocation) {
|
|
18
18
|
const content = await getBitranContent(location, false);
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
const bitranCore = await createBitranTranspiler({
|
|
21
|
+
eruditConfig: ERUDIT_SERVER.CONFIG,
|
|
22
|
+
insideInclude: false,
|
|
23
|
+
context: { aliases: NO_ALIASES(), location },
|
|
24
|
+
});
|
|
20
25
|
|
|
21
26
|
const toc: Toc = [];
|
|
22
27
|
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { defineBitranTranspiler } from '@bitran-js/transpiler';
|
|
2
|
+
import {
|
|
3
|
+
setEruditBitranRuntime,
|
|
4
|
+
type EruditBitranRuntime,
|
|
5
|
+
} from '@erudit-js/cog/schema';
|
|
2
6
|
|
|
3
7
|
import getServerTranspilers from '#erudit/bitran/server';
|
|
4
8
|
|
|
5
|
-
export async function createBitranTranspiler() {
|
|
9
|
+
export async function createBitranTranspiler(runtime: EruditBitranRuntime) {
|
|
6
10
|
const serverTranspiler = await getServerTranspilers();
|
|
7
11
|
const bitranTranspiler = defineBitranTranspiler(serverTranspiler);
|
|
12
|
+
|
|
13
|
+
[bitranTranspiler.parser, bitranTranspiler.stringifier].forEach((item) => {
|
|
14
|
+
setEruditBitranRuntime(item, runtime);
|
|
15
|
+
});
|
|
16
|
+
|
|
8
17
|
return bitranTranspiler;
|
|
9
18
|
}
|
|
@@ -80,12 +80,11 @@ async function scanContentFiles() {
|
|
|
80
80
|
|
|
81
81
|
async function addContentItem(navNode: NavNode) {
|
|
82
82
|
debug.start(
|
|
83
|
-
`Adding ${stress(navNode.type)} content item ${stress(navNode.
|
|
83
|
+
`Adding ${stress(navNode.type)} content item ${stress(navNode.shortId)}...`,
|
|
84
84
|
);
|
|
85
85
|
|
|
86
86
|
const dbContent = new DbContent();
|
|
87
|
-
dbContent.contentId = navNode.
|
|
88
|
-
dbContent.fullId = navNode.fullId;
|
|
87
|
+
dbContent.contentId = navNode.fullId;
|
|
89
88
|
dbContent.type = navNode.type;
|
|
90
89
|
dbContent.decoration = getDecoration(navNode);
|
|
91
90
|
dbContent.ogImage = await getOgImageData(navNode);
|
|
@@ -134,7 +133,7 @@ async function addContributions(navNode: NavNode, contributors?: string[]) {
|
|
|
134
133
|
if (!contributors || !contributors.length) {
|
|
135
134
|
if (navNode.type !== 'book' && navNode.type !== 'group')
|
|
136
135
|
logger.warn(
|
|
137
|
-
`${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.
|
|
136
|
+
`${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.fullId)} has no contributors!`,
|
|
138
137
|
);
|
|
139
138
|
|
|
140
139
|
return;
|
|
@@ -143,13 +142,13 @@ async function addContributions(navNode: NavNode, contributors?: string[]) {
|
|
|
143
142
|
for (const contributorId of contributors) {
|
|
144
143
|
if (!(await contributorExists(contributorId))) {
|
|
145
144
|
logger.warn(
|
|
146
|
-
`Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.
|
|
145
|
+
`Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.fullId)}!`,
|
|
147
146
|
);
|
|
148
147
|
continue;
|
|
149
148
|
}
|
|
150
149
|
|
|
151
150
|
const dbContribution = new DbContribution();
|
|
152
|
-
dbContribution.contentId = navNode.
|
|
151
|
+
dbContribution.contentId = navNode.fullId;
|
|
153
152
|
dbContribution.contributorId = contributorId;
|
|
154
153
|
await ERUDIT_SERVER.DB.manager.save(dbContribution);
|
|
155
154
|
}
|
|
@@ -29,7 +29,11 @@ export async function parseBitranContent(
|
|
|
29
29
|
context.location = location;
|
|
30
30
|
context.aliases = NO_ALIASES();
|
|
31
31
|
|
|
32
|
-
bitranTranspiler ||= await createBitranTranspiler(
|
|
32
|
+
bitranTranspiler ||= await createBitranTranspiler({
|
|
33
|
+
context,
|
|
34
|
+
eruditConfig: ERUDIT_SERVER.CONFIG,
|
|
35
|
+
insideInclude: false,
|
|
36
|
+
});
|
|
33
37
|
|
|
34
38
|
// Tracking heading nodes to deal with them later
|
|
35
39
|
const headings: HeadingNode[] = [];
|