erudit 3.0.0-dev.11 → 3.0.0-dev.12
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/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/preview/PreviewScreen.vue +2 -2
- package/app/components/preview/display/PageLink.vue +1 -1
- package/app/composables/bitranContent.ts +3 -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 +1 -5
- package/package.json +8 -8
- 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 +13 -16
- 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 +10 -5
- 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 +8 -11
- package/server/plugin/content/context.ts +4 -1
- package/server/plugin/db/entities/Content.ts +0 -4
- package/server/plugin/db/entities/ContentId.ts +11 -0
- package/server/plugin/db/setup.ts +3 -1
- package/server/plugin/importer.ts +5 -1
- package/server/plugin/nav/utils.ts +4 -4
- package/server/plugin/repository/content.ts +4 -12
- package/server/plugin/repository/contentId.ts +26 -0
- package/server/plugin/repository/frontNav.ts +4 -4
- package/server/plugin/repository/topic.ts +4 -1
- package/shared/aside/minor.ts +2 -2
- package/shared/bitran/contentId.ts +4 -4
- package/shared/content/bookId.ts +11 -0
- package/shared/frontNav.ts +1 -1
|
@@ -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,
|
|
@@ -41,7 +40,7 @@ export async function traverseInclude(
|
|
|
41
40
|
step?: TraverseStepFn;
|
|
42
41
|
leave?: TraverseLeaveFn;
|
|
43
42
|
},
|
|
44
|
-
) {
|
|
43
|
+
): Promise<BlockNode[]> {
|
|
45
44
|
const entryLocation = stringifyBitranLocation(
|
|
46
45
|
parsePartialBitranLocation(includeNode.id, context.location),
|
|
47
46
|
);
|
|
@@ -58,7 +57,7 @@ export async function traverseInclude(
|
|
|
58
57
|
};
|
|
59
58
|
|
|
60
59
|
try {
|
|
61
|
-
await
|
|
60
|
+
return await _traverseInclude(
|
|
62
61
|
includeNode,
|
|
63
62
|
absEntryLocation,
|
|
64
63
|
context.aliases,
|
|
@@ -79,7 +78,7 @@ export async function traverseInclude(
|
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
async function
|
|
81
|
+
async function _traverseInclude(
|
|
83
82
|
includeNode: IncludeNode,
|
|
84
83
|
location: string,
|
|
85
84
|
aliases: BitranAliases,
|
|
@@ -89,7 +88,7 @@ async function _traverseStep(
|
|
|
89
88
|
leave?: TraverseLeaveFn;
|
|
90
89
|
},
|
|
91
90
|
travelMap: Record<string, string | null>,
|
|
92
|
-
) {
|
|
91
|
+
): Promise<BlockNode[]> {
|
|
93
92
|
let includeTargetLocation: string;
|
|
94
93
|
|
|
95
94
|
try {
|
|
@@ -144,15 +143,11 @@ async function _traverseStep(
|
|
|
144
143
|
aliases: dbUnique.context.aliases,
|
|
145
144
|
};
|
|
146
145
|
|
|
147
|
-
const bitranTranspiler = await createBitranTranspiler(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
context: structuredClone(context),
|
|
153
|
-
insideInclude: true,
|
|
154
|
-
}),
|
|
155
|
-
);
|
|
146
|
+
const bitranTranspiler = await createBitranTranspiler({
|
|
147
|
+
eruditConfig: ERUDIT_SERVER.CONFIG,
|
|
148
|
+
context: structuredClone(context),
|
|
149
|
+
insideInclude: true,
|
|
150
|
+
});
|
|
156
151
|
|
|
157
152
|
if (listeners.enter) {
|
|
158
153
|
await listeners.enter({
|
|
@@ -168,7 +163,7 @@ async function _traverseStep(
|
|
|
168
163
|
|
|
169
164
|
let stepErrorMessage: string | Error | undefined;
|
|
170
165
|
|
|
171
|
-
await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
166
|
+
const rootNode = await bitranTranspiler.parser.parse(dbUnique.content, {
|
|
172
167
|
step: async (node) => {
|
|
173
168
|
if (stepErrorMessage) return;
|
|
174
169
|
|
|
@@ -193,7 +188,7 @@ async function _traverseStep(
|
|
|
193
188
|
}
|
|
194
189
|
|
|
195
190
|
try {
|
|
196
|
-
await
|
|
191
|
+
await _traverseInclude(
|
|
197
192
|
node,
|
|
198
193
|
includeTargetLocation,
|
|
199
194
|
context.aliases,
|
|
@@ -218,6 +213,8 @@ async function _traverseStep(
|
|
|
218
213
|
_location: includeTargetLocation,
|
|
219
214
|
});
|
|
220
215
|
}
|
|
216
|
+
|
|
217
|
+
return (rootNode.children as BlockNode[]) ?? [];
|
|
221
218
|
}
|
|
222
219
|
|
|
223
220
|
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
|
}
|
|
@@ -23,6 +23,7 @@ import { IMPORT } from '@server/importer';
|
|
|
23
23
|
import { contributorExists } from '@server/repository/contributor';
|
|
24
24
|
import { DbContribution } from '@server/db/entities/Contribution';
|
|
25
25
|
import { DbFile } from '@server/db/entities/File';
|
|
26
|
+
import { DbContentId } from '@server/db/entities/ContentId';
|
|
26
27
|
|
|
27
28
|
import { contentAsset } from '@erudit/shared/asset';
|
|
28
29
|
import type { ImageData } from '@erudit/shared/image';
|
|
@@ -83,9 +84,13 @@ async function addContentItem(navNode: NavNode) {
|
|
|
83
84
|
`Adding ${stress(navNode.type)} content item ${stress(navNode.id)}...`,
|
|
84
85
|
);
|
|
85
86
|
|
|
87
|
+
const dbContentId = new DbContentId();
|
|
88
|
+
dbContentId.fullId = navNode.fullId;
|
|
89
|
+
dbContentId.shortId = navNode.id;
|
|
90
|
+
await ERUDIT_SERVER.DB.manager.save(dbContentId);
|
|
91
|
+
|
|
86
92
|
const dbContent = new DbContent();
|
|
87
|
-
dbContent.contentId = navNode.
|
|
88
|
-
dbContent.fullId = navNode.fullId;
|
|
93
|
+
dbContent.contentId = navNode.fullId;
|
|
89
94
|
dbContent.type = navNode.type;
|
|
90
95
|
dbContent.decoration = getDecoration(navNode);
|
|
91
96
|
dbContent.ogImage = await getOgImageData(navNode);
|
|
@@ -134,7 +139,7 @@ async function addContributions(navNode: NavNode, contributors?: string[]) {
|
|
|
134
139
|
if (!contributors || !contributors.length) {
|
|
135
140
|
if (navNode.type !== 'book' && navNode.type !== 'group')
|
|
136
141
|
logger.warn(
|
|
137
|
-
`${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.
|
|
142
|
+
`${navNode.type.at(0)!.toUpperCase() + navNode.type.slice(1)} ${stress(navNode.fullId)} has no contributors!`,
|
|
138
143
|
);
|
|
139
144
|
|
|
140
145
|
return;
|
|
@@ -143,13 +148,13 @@ async function addContributions(navNode: NavNode, contributors?: string[]) {
|
|
|
143
148
|
for (const contributorId of contributors) {
|
|
144
149
|
if (!(await contributorExists(contributorId))) {
|
|
145
150
|
logger.warn(
|
|
146
|
-
`Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.
|
|
151
|
+
`Skipping unknown contributor ${stress(contributorId)} when adding ${navNode.type} ${stress(navNode.fullId)}!`,
|
|
147
152
|
);
|
|
148
153
|
continue;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
const dbContribution = new DbContribution();
|
|
152
|
-
dbContribution.contentId = navNode.
|
|
157
|
+
dbContribution.contentId = navNode.fullId;
|
|
153
158
|
dbContribution.contributorId = contributorId;
|
|
154
159
|
await ERUDIT_SERVER.DB.manager.save(dbContribution);
|
|
155
160
|
}
|
|
@@ -12,7 +12,7 @@ export async function buildGroup({
|
|
|
12
12
|
config,
|
|
13
13
|
}: BuilderFunctionArgs<GroupConfig>) {
|
|
14
14
|
const dbGroup = new DbGroup();
|
|
15
|
-
dbGroup.contentId = navNode.
|
|
15
|
+
dbGroup.contentId = navNode.fullId;
|
|
16
16
|
dbGroup.type = config?.type || 'folder';
|
|
17
17
|
|
|
18
18
|
try {
|
|
@@ -26,7 +26,7 @@ export async function buildGroup({
|
|
|
26
26
|
await parseBitranContent(
|
|
27
27
|
{
|
|
28
28
|
type: 'group',
|
|
29
|
-
path:
|
|
29
|
+
path: dbGroup.contentId,
|
|
30
30
|
},
|
|
31
31
|
strContent,
|
|
32
32
|
);
|
|
@@ -9,7 +9,7 @@ import { parseBitranContent } from '../parse';
|
|
|
9
9
|
|
|
10
10
|
export async function buildTopic({ navNode }: BuilderFunctionArgs) {
|
|
11
11
|
const dbTopic = new DbTopic();
|
|
12
|
-
dbTopic.contentId = navNode.
|
|
12
|
+
dbTopic.contentId = navNode.fullId;
|
|
13
13
|
const existingTopicParts: TopicPart[] = [];
|
|
14
14
|
|
|
15
15
|
for (const topicPart of topicParts) {
|
|
@@ -25,7 +25,7 @@ export async function buildTopic({ navNode }: BuilderFunctionArgs) {
|
|
|
25
25
|
await parseBitranContent(
|
|
26
26
|
{
|
|
27
27
|
type: topicPart,
|
|
28
|
-
path:
|
|
28
|
+
path: dbTopic.contentId,
|
|
29
29
|
},
|
|
30
30
|
strContent,
|
|
31
31
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { globSync } from 'glob';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { resolvePaths } from '@erudit-js/cog/kit';
|
|
4
3
|
import {
|
|
5
4
|
contentTypes,
|
|
6
5
|
topicParts,
|
|
@@ -54,13 +53,15 @@ async function scanChildNodes(
|
|
|
54
53
|
parent: NavNode | RootNavNode,
|
|
55
54
|
insideBook: boolean,
|
|
56
55
|
): Promise<{ children: NavNode[] | undefined; newIds: Ids }> {
|
|
57
|
-
const currentFsPath = isRootNode(parent) ? '' : parent.path;
|
|
56
|
+
const currentFsPath = isRootNode(parent) ? '' : parent.path + '/';
|
|
58
57
|
|
|
59
58
|
const nodeFsPaths = globSync(
|
|
60
|
-
`${
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
`${currentFsPath}*/{${contentTypes.join(',')}}.{ts,js}`,
|
|
60
|
+
{
|
|
61
|
+
cwd: PROJECT_DIR + '/content',
|
|
62
|
+
posix: true,
|
|
63
|
+
},
|
|
64
|
+
).sort();
|
|
64
65
|
|
|
65
66
|
let newIds: Ids = {};
|
|
66
67
|
const children: NavNode[] = [];
|
|
@@ -77,11 +78,7 @@ async function scanChildNodes(
|
|
|
77
78
|
|
|
78
79
|
if (!pathParts) continue; // Wrong path pattern
|
|
79
80
|
|
|
80
|
-
const nodePath = nodeFsPath
|
|
81
|
-
.replace(PROJECT_DIR + '/content/', '')
|
|
82
|
-
.split('/')
|
|
83
|
-
.slice(0, -1)
|
|
84
|
-
.join('/');
|
|
81
|
+
const nodePath = nodeFsPath.split('/').slice(0, -1).join('/');
|
|
85
82
|
|
|
86
83
|
if (pathParts.type === 'book' && insideBook) {
|
|
87
84
|
logger.warn(
|
|
@@ -9,6 +9,7 @@ import { ERUDIT_SERVER } from '@server/global';
|
|
|
9
9
|
import { getIdsUp, isSkipId } from '@server/nav/utils';
|
|
10
10
|
import { DbContent } from '@server/db/entities/Content';
|
|
11
11
|
import { DbContributor } from '@server/db/entities/Contributor';
|
|
12
|
+
import { getFullContentId } from '@server/repository/contentId';
|
|
12
13
|
|
|
13
14
|
import type { Context } from '@shared/content/context';
|
|
14
15
|
import {
|
|
@@ -19,6 +20,8 @@ import {
|
|
|
19
20
|
import { CONTENT_TYPE_ICON, ICON, TOPIC_PART_ICON } from '@erudit/shared/icons';
|
|
20
21
|
|
|
21
22
|
export async function getContentContext(contentId: string): Promise<Context> {
|
|
23
|
+
contentId = await getFullContentId(contentId);
|
|
24
|
+
|
|
22
25
|
const context: Context = [];
|
|
23
26
|
|
|
24
27
|
for (const _contentId of (await getIdsUp(contentId)).reverse()) {
|
|
@@ -106,7 +109,7 @@ export async function getLocationContext(
|
|
|
106
109
|
|
|
107
110
|
async function getDbContent(contentId: string): Promise<DbContent> {
|
|
108
111
|
const dbContent = await ERUDIT_SERVER.DB.manager.findOne(DbContent, {
|
|
109
|
-
select: ['type', 'title', '
|
|
112
|
+
select: ['type', 'title', 'contentId'],
|
|
110
113
|
where: { contentId },
|
|
111
114
|
});
|
|
112
115
|
|
|
@@ -3,6 +3,7 @@ import { DataSource } from 'typeorm';
|
|
|
3
3
|
|
|
4
4
|
import { PROJECT_DIR } from '#erudit/globalPaths';
|
|
5
5
|
import { ERUDIT_SERVER } from '@server/global';
|
|
6
|
+
import { logger } from '../logger';
|
|
6
7
|
|
|
7
8
|
// Database Entities
|
|
8
9
|
import { DbContributor } from './entities/Contributor';
|
|
@@ -14,7 +15,7 @@ import { DbHash } from './entities/Hash';
|
|
|
14
15
|
import { DbTopic } from './entities/Topic';
|
|
15
16
|
import { DbUnique } from './entities/Unique';
|
|
16
17
|
import { DbFile } from './entities/File';
|
|
17
|
-
import {
|
|
18
|
+
import { DbContentId } from './entities/ContentId';
|
|
18
19
|
|
|
19
20
|
export async function setupDatabase() {
|
|
20
21
|
rmSync(PROJECT_DIR + '/.erudit/data.sqlite', { force: true });
|
|
@@ -27,6 +28,7 @@ export async function setupDatabase() {
|
|
|
27
28
|
dropSchema: true,
|
|
28
29
|
entities: [
|
|
29
30
|
DbBook,
|
|
31
|
+
DbContentId,
|
|
30
32
|
DbContent,
|
|
31
33
|
DbContribution,
|
|
32
34
|
DbContributor,
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { createJiti } from 'jiti';
|
|
2
|
-
import { ERUDIT_DIR } from '#erudit/globalPaths';
|
|
2
|
+
import { ERUDIT_DIR, PROJECT_DIR } from '#erudit/globalPaths';
|
|
3
3
|
|
|
4
4
|
const jiti = createJiti(ERUDIT_DIR, {
|
|
5
5
|
// Enable reimporting same files during process in development mode
|
|
6
6
|
fsCache: !import.meta.dev,
|
|
7
7
|
moduleCache: !import.meta.dev,
|
|
8
|
+
alias: {
|
|
9
|
+
'#project': PROJECT_DIR,
|
|
10
|
+
'#content': PROJECT_DIR + '/content',
|
|
11
|
+
},
|
|
8
12
|
});
|
|
9
13
|
|
|
10
14
|
export async function IMPORT(...args: Parameters<typeof jiti.import>) {
|