erudit 4.1.0 → 4.2.0-dev.1
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/assets/icons/update.svg +3 -0
- package/app/components/Prose.vue +7 -7
- package/app/components/SmartMedia.vue +4 -4
- package/app/components/aside/major/contentNav/PaneBookNav.vue +1 -4
- package/app/components/aside/minor/content/Toc.vue +24 -1
- package/app/components/aside/minor/content/TocItem.vue +2 -1
- package/app/components/aside/minor/news/AsideMinorNews.vue +1 -3
- package/app/components/aside/minor/news/NewsItem.vue +3 -4
- package/app/components/aside/minor/news/RenderNewsElement.vue +4 -11
- package/app/components/aside/minor/news/elements/Mix.vue +2 -3
- package/app/components/aside/minor/news/elements/P.vue +3 -3
- package/app/components/aside/minor/news/elements/Ref.vue +3 -3
- package/app/components/aside/minor/news/elements/Text.vue +2 -2
- package/app/components/main/MainContentChild.vue +3 -3
- package/app/components/main/{MainQuickLink.vue → MainKeyLink.vue} +11 -11
- package/app/components/main/{MainQuickLinks.vue → MainKeyLinks.vue} +7 -7
- package/app/components/main/MainQuoteLoader.vue +2 -4
- package/app/components/main/MainStickyHeader.vue +1 -1
- package/app/components/main/MainStickyHeaderPreamble.vue +6 -2
- package/app/components/main/MainTopicPartPage.vue +8 -3
- package/app/components/main/connections/DepUnique.vue +45 -0
- package/app/components/main/connections/Deps.vue +15 -5
- package/app/components/main/connections/Externals.vue +4 -4
- package/app/components/main/connections/MainConnections.vue +1 -0
- package/app/components/main/contentStats/ItemLastChanged.vue +68 -0
- package/app/components/main/contentStats/MainContentStats.vue +36 -28
- package/app/components/preview/PreviewScreen.vue +2 -2
- package/app/components/preview/screen/ContentPage.vue +1 -4
- package/app/components/preview/screen/Unique.vue +3 -5
- package/app/composables/appElements.ts +2 -4
- package/app/composables/asideMajorPane.ts +3 -3
- package/app/composables/fetchJson.ts +4 -0
- package/app/composables/lastChanged.ts +28 -0
- package/app/composables/mainContent.ts +1 -4
- package/app/composables/og.ts +43 -35
- package/app/composables/phrases.ts +0 -3
- package/app/composables/scrollUp.ts +1 -1
- package/app/pages/book/[...bookId].vue +5 -1
- package/app/pages/contributor/[contributorId].vue +3 -5
- package/app/pages/contributors.vue +1 -1
- package/app/pages/group/[...groupId].vue +5 -1
- package/app/pages/index.vue +1 -1
- package/app/pages/page/[...pageId].vue +8 -3
- package/app/pages/sponsors.vue +1 -1
- package/app/plugins/appSetup/index.ts +0 -5
- package/app/plugins/fetchJson.ts +11 -0
- package/app/plugins/prerender.server.ts +1 -1
- package/app/router.options.ts +1 -1
- package/modules/erudit/globals/prose.ts +3 -4
- package/modules/erudit/setup/elements/appTemplate.ts +6 -7
- package/modules/erudit/setup/elements/{globalTypes.ts → elementGlobalTypes.ts} +21 -21
- package/modules/erudit/setup/elements/globalTemplate.ts +29 -23
- package/modules/erudit/setup/elements/setup.ts +18 -16
- package/modules/erudit/setup/elements/shared.ts +2 -2
- package/modules/erudit/setup/elements/tagsTable.ts +1 -1
- package/modules/erudit/setup/runtimeConfig.ts +2 -0
- package/nuxt.config.ts +2 -2
- package/package.json +14 -13
- package/server/api/main/content/[...contentTypePath].ts +5 -4
- package/server/api/prerender/content.ts +1 -3
- package/server/api/preview/contentPage/[...contentTypePath].ts +1 -2
- package/server/api/preview/contentUnique/[...contentTypePathUnique].ts +16 -31
- package/server/api/problemScript/[...problemScriptPath].ts +73 -4
- package/server/erudit/content/global/build.ts +21 -7
- package/server/erudit/content/nav/build.ts +4 -4
- package/server/erudit/content/repository/children.ts +3 -3
- package/server/erudit/content/repository/deps.ts +127 -39
- package/server/erudit/content/repository/elementSnippets.ts +16 -16
- package/server/erudit/content/repository/stats.ts +30 -22
- package/server/erudit/content/repository/topicParts.ts +1 -1
- package/server/erudit/content/repository/unique.ts +14 -15
- package/server/erudit/content/resolve/index.ts +6 -1
- package/server/erudit/content/resolve/page.ts +15 -35
- package/server/erudit/content/resolve/topic.ts +33 -164
- package/server/erudit/content/resolve/utils/insertContentItem.ts +2 -2
- package/server/erudit/content/resolve/utils/insertContentResolved.ts +82 -31
- package/server/erudit/content/search.ts +5 -22
- package/server/erudit/contributors/build.ts +7 -8
- package/server/erudit/db/repository/pushFile.ts +10 -3
- package/server/erudit/db/repository/pushProblemScript.ts +14 -3
- package/server/erudit/db/schema/contentDeps.ts +3 -0
- package/server/erudit/db/schema/contentSnippets.ts +3 -3
- package/server/erudit/db/schema/contentUniques.ts +2 -2
- package/server/erudit/db/schema/contributors.ts +2 -2
- package/server/erudit/db/schema/news.ts +2 -2
- package/server/erudit/db/schema/pages.ts +2 -2
- package/server/erudit/db/schema/topics.ts +4 -4
- package/server/erudit/global.ts +4 -0
- package/server/erudit/importer.ts +16 -8
- package/server/erudit/index.ts +0 -3
- package/server/erudit/language/list/en.ts +1 -0
- package/server/erudit/language/list/ru.ts +1 -0
- package/server/erudit/news/build.ts +6 -6
- package/server/erudit/news/repository/batch.ts +2 -2
- package/server/erudit/prose/repository/finalize.ts +22 -25
- package/server/erudit/prose/repository/get.ts +3 -5
- package/server/erudit/prose/repository/rawToProse.ts +31 -0
- package/server/erudit/prose/storage/callout.ts +9 -7
- package/server/erudit/prose/storage/image.ts +8 -11
- package/server/erudit/prose/storage/link.ts +24 -32
- package/server/erudit/prose/storage/problemScript.ts +8 -14
- package/server/erudit/prose/storage/video.ts +9 -7
- package/server/erudit/repository.ts +4 -4
- package/server/routes/file/[...path].ts +1 -1
- package/shared/types/contentChildren.ts +5 -2
- package/shared/types/contentConnections.ts +9 -0
- package/shared/types/elementSnippet.ts +1 -1
- package/shared/types/indexPage.ts +3 -0
- package/shared/types/language.ts +1 -83
- package/shared/types/mainContent.ts +11 -5
- package/shared/types/news.ts +2 -2
- package/shared/types/preview.ts +3 -2
- package/shared/types/runtimeConfig.ts +1 -0
- package/shared/types/search.ts +2 -0
- package/shared/utils/pages.ts +4 -2
- package/shared/utils/stringColor.ts +16 -6
- package/server/erudit/prose/repository/resolve.ts +0 -17
- package/server/erudit/prose/transform/bundleProblemScript.ts +0 -6
|
@@ -4,11 +4,11 @@ export async function getContentDependencies(fullId: string) {
|
|
|
4
4
|
const hardDependencies: ContentHardDep[] = [];
|
|
5
5
|
|
|
6
6
|
const dbHardDependencies = await ERUDIT.db.query.contentDeps.findMany({
|
|
7
|
-
columns: {
|
|
7
|
+
columns: { toFullId: true, hard: true, reason: true },
|
|
8
8
|
where: and(
|
|
9
9
|
or(
|
|
10
|
-
eq(ERUDIT.db.schema.contentDeps.
|
|
11
|
-
like(ERUDIT.db.schema.contentDeps.
|
|
10
|
+
eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
|
|
11
|
+
like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
|
|
12
12
|
),
|
|
13
13
|
eq(ERUDIT.db.schema.contentDeps.hard, true),
|
|
14
14
|
),
|
|
@@ -16,18 +16,18 @@ export async function getContentDependencies(fullId: string) {
|
|
|
16
16
|
|
|
17
17
|
const fullId2Reason = dbHardDependencies.reduce((map, dbDependency) => {
|
|
18
18
|
if (dbDependency.reason) {
|
|
19
|
-
map.set(dbDependency.
|
|
19
|
+
map.set(dbDependency.toFullId, dbDependency.reason);
|
|
20
20
|
}
|
|
21
21
|
return map;
|
|
22
22
|
}, new Map<string, string>());
|
|
23
23
|
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const hardToFullIds = ERUDIT.contentNav.orderIds(
|
|
25
|
+
externalToFullIds(dbHardDependencies),
|
|
26
26
|
);
|
|
27
27
|
|
|
28
|
-
for (const
|
|
29
|
-
const reason = fullId2Reason.get(
|
|
30
|
-
const hardDep = await createContentDep('hard',
|
|
28
|
+
for (const toFullId of hardToFullIds) {
|
|
29
|
+
const reason = fullId2Reason.get(toFullId)!;
|
|
30
|
+
const hardDep = await createContentDep('hard', toFullId, undefined, reason);
|
|
31
31
|
if (hardDep) {
|
|
32
32
|
hardDependencies.push(hardDep);
|
|
33
33
|
}
|
|
@@ -40,23 +40,40 @@ export async function getContentDependencies(fullId: string) {
|
|
|
40
40
|
const autoDependencies: ContentAutoDep[] = [];
|
|
41
41
|
|
|
42
42
|
const dbAutoDependencies = await ERUDIT.db.query.contentDeps.findMany({
|
|
43
|
-
columns: {
|
|
43
|
+
columns: { toFullId: true, hard: true, uniqueNames: true },
|
|
44
44
|
where: and(
|
|
45
45
|
or(
|
|
46
|
-
eq(ERUDIT.db.schema.contentDeps.
|
|
47
|
-
like(ERUDIT.db.schema.contentDeps.
|
|
46
|
+
eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
|
|
47
|
+
like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
|
|
48
48
|
),
|
|
49
49
|
eq(ERUDIT.db.schema.contentDeps.hard, false),
|
|
50
50
|
),
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
+
// Merge unique names across rows that share the same toFullId
|
|
54
|
+
// (can happen when a topic and its children both dep on the same target).
|
|
55
|
+
const autoUniqueMap = new Map<string, Set<string>>();
|
|
56
|
+
for (const row of dbAutoDependencies) {
|
|
57
|
+
if (!autoUniqueMap.has(row.toFullId)) {
|
|
58
|
+
autoUniqueMap.set(row.toFullId, new Set());
|
|
59
|
+
}
|
|
60
|
+
if (row.uniqueNames) {
|
|
61
|
+
for (const name of row.uniqueNames.split(',')) {
|
|
62
|
+
autoUniqueMap.get(row.toFullId)!.add(name);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
// Skip auto-dependency if a hard dependency from the same source exists
|
|
54
|
-
const
|
|
55
|
-
.orderIds(
|
|
56
|
-
.filter((
|
|
68
|
+
const autoToFullIds = ERUDIT.contentNav
|
|
69
|
+
.orderIds(externalToFullIds(dbAutoDependencies))
|
|
70
|
+
.filter((toFullId) => !fullId2Reason.has(toFullId));
|
|
57
71
|
|
|
58
|
-
for (const
|
|
59
|
-
const
|
|
72
|
+
for (const toFullId of autoToFullIds) {
|
|
73
|
+
const uniquePairs = Array.from(autoUniqueMap.get(toFullId) ?? []).map(
|
|
74
|
+
(uniqueName) => ({ contentFullId: toFullId, uniqueName }),
|
|
75
|
+
);
|
|
76
|
+
const autoDep = await createContentDep('auto', toFullId, uniquePairs);
|
|
60
77
|
if (autoDep) {
|
|
61
78
|
autoDependencies.push(autoDep);
|
|
62
79
|
}
|
|
@@ -72,17 +89,17 @@ export async function getContentDependencies(fullId: string) {
|
|
|
72
89
|
//
|
|
73
90
|
|
|
74
91
|
// Skip dependency if it originates from current content item or its child
|
|
75
|
-
function
|
|
92
|
+
function externalToFullIds(dbDeps: { toFullId: string }[]) {
|
|
76
93
|
return dbDeps.reduce((ids, dbDep) => {
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
94
|
+
const toFullId = dbDep.toFullId;
|
|
95
|
+
const isToSelf = toFullId === fullId;
|
|
96
|
+
const isToChild = toFullId.startsWith(`${fullId}/`);
|
|
80
97
|
|
|
81
|
-
if (
|
|
98
|
+
if (isToSelf || isToChild) {
|
|
82
99
|
return ids;
|
|
83
100
|
}
|
|
84
101
|
|
|
85
|
-
ids.push(
|
|
102
|
+
ids.push(toFullId);
|
|
86
103
|
return ids;
|
|
87
104
|
}, [] as string[]);
|
|
88
105
|
}
|
|
@@ -92,32 +109,50 @@ export async function getContentDependents(
|
|
|
92
109
|
fullId: string,
|
|
93
110
|
): Promise<ContentAutoDep[]> {
|
|
94
111
|
const dbDependents = await ERUDIT.db.query.contentDeps.findMany({
|
|
95
|
-
columns: { fromFullId: true, toFullId: true },
|
|
112
|
+
columns: { fromFullId: true, toFullId: true, uniqueNames: true },
|
|
96
113
|
where: or(
|
|
97
|
-
eq(ERUDIT.db.schema.contentDeps.
|
|
98
|
-
like(ERUDIT.db.schema.contentDeps.
|
|
114
|
+
eq(ERUDIT.db.schema.contentDeps.toFullId, fullId),
|
|
115
|
+
like(ERUDIT.db.schema.contentDeps.toFullId, `${fullId}/%`),
|
|
99
116
|
),
|
|
100
117
|
});
|
|
101
118
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
// Group rows by fromFullId, collecting {contentFullId, uniqueName} pairs
|
|
120
|
+
// (toFullId can vary when a dependent references different child pages).
|
|
121
|
+
const fromUniquePairsMap = new Map<
|
|
122
|
+
string,
|
|
123
|
+
{ contentFullId: string; uniqueName: string }[]
|
|
124
|
+
>();
|
|
125
|
+
const externalFromFullIds: string[] = [];
|
|
107
126
|
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
for (const row of dbDependents) {
|
|
128
|
+
const fromFullId = row.fromFullId;
|
|
129
|
+
const isFromSelf = fromFullId === fullId;
|
|
130
|
+
const isFromChild = fromFullId.startsWith(`${fullId}/`);
|
|
131
|
+
|
|
132
|
+
if (isFromSelf || isFromChild) continue;
|
|
133
|
+
|
|
134
|
+
if (!fromUniquePairsMap.has(fromFullId)) {
|
|
135
|
+
fromUniquePairsMap.set(fromFullId, []);
|
|
136
|
+
externalFromFullIds.push(fromFullId);
|
|
110
137
|
}
|
|
111
138
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
139
|
+
if (row.uniqueNames) {
|
|
140
|
+
for (const name of row.uniqueNames.split(',')) {
|
|
141
|
+
fromUniquePairsMap
|
|
142
|
+
.get(fromFullId)!
|
|
143
|
+
.push({ contentFullId: row.toFullId, uniqueName: name });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
115
147
|
|
|
116
|
-
// Order
|
|
117
|
-
const
|
|
148
|
+
// Order sources according to nav structure
|
|
149
|
+
const fromFullIds = ERUDIT.contentNav.orderIds(externalFromFullIds);
|
|
118
150
|
|
|
119
151
|
const dependents = await Promise.all(
|
|
120
|
-
|
|
152
|
+
fromFullIds.map((fromFullId) => {
|
|
153
|
+
const uniquePairs = fromUniquePairsMap.get(fromFullId) ?? [];
|
|
154
|
+
return createContentDep('auto', fromFullId, uniquePairs);
|
|
155
|
+
}),
|
|
121
156
|
);
|
|
122
157
|
|
|
123
158
|
return dependents.filter((dep): dep is ContentAutoDep => dep !== undefined);
|
|
@@ -126,15 +161,18 @@ export async function getContentDependents(
|
|
|
126
161
|
async function createContentDep(
|
|
127
162
|
type: 'auto',
|
|
128
163
|
fullId: string,
|
|
164
|
+
uniquePairs: { contentFullId: string; uniqueName: string }[],
|
|
129
165
|
): Promise<ContentAutoDep | undefined>;
|
|
130
166
|
async function createContentDep(
|
|
131
167
|
type: 'hard',
|
|
132
168
|
fullId: string,
|
|
169
|
+
uniquePairs: undefined,
|
|
133
170
|
reason: string,
|
|
134
171
|
): Promise<ContentHardDep | undefined>;
|
|
135
172
|
async function createContentDep(
|
|
136
173
|
type: 'auto' | 'hard',
|
|
137
174
|
fullId: string,
|
|
175
|
+
uniquePairs?: { contentFullId: string; uniqueName: string }[],
|
|
138
176
|
reason?: string,
|
|
139
177
|
): Promise<ContentDep | undefined> {
|
|
140
178
|
const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
|
|
@@ -160,10 +198,60 @@ async function createContentDep(
|
|
|
160
198
|
};
|
|
161
199
|
}
|
|
162
200
|
|
|
201
|
+
const uniques =
|
|
202
|
+
uniquePairs && uniquePairs.length > 0
|
|
203
|
+
? await resolveUniqueEntries(uniquePairs)
|
|
204
|
+
: undefined;
|
|
205
|
+
|
|
163
206
|
return {
|
|
164
207
|
type: 'auto',
|
|
165
208
|
contentType,
|
|
166
209
|
title,
|
|
167
210
|
link,
|
|
211
|
+
...(uniques && uniques.length > 0 ? { uniques } : {}),
|
|
168
212
|
};
|
|
169
213
|
}
|
|
214
|
+
|
|
215
|
+
async function resolveUniqueEntries(
|
|
216
|
+
pairs: { contentFullId: string; uniqueName: string }[],
|
|
217
|
+
): Promise<ContentDepUnique[]> {
|
|
218
|
+
// Deduplicate by "contentFullId/uniqueName" to avoid showing the same
|
|
219
|
+
// element twice when multiple prose types reference it.
|
|
220
|
+
const seen = new Set<string>();
|
|
221
|
+
const unique: typeof pairs = [];
|
|
222
|
+
for (const pair of pairs) {
|
|
223
|
+
const key = `${pair.contentFullId}/${pair.uniqueName}`;
|
|
224
|
+
if (!seen.has(key)) {
|
|
225
|
+
seen.add(key);
|
|
226
|
+
unique.push(pair);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const results = await Promise.all(
|
|
231
|
+
unique.map(async ({ contentFullId, uniqueName }) => {
|
|
232
|
+
const dbUnique = await ERUDIT.db.query.contentUniques.findFirst({
|
|
233
|
+
columns: { title: true, prose: true },
|
|
234
|
+
where: and(
|
|
235
|
+
eq(ERUDIT.db.schema.contentUniques.contentFullId, contentFullId),
|
|
236
|
+
eq(ERUDIT.db.schema.contentUniques.uniqueName, uniqueName),
|
|
237
|
+
),
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
if (!dbUnique) return null;
|
|
241
|
+
|
|
242
|
+
const pageLink = await ERUDIT.repository.content.link(contentFullId);
|
|
243
|
+
const schemaName = dbUnique.prose.schema.name;
|
|
244
|
+
|
|
245
|
+
if (!schemaName) return null;
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
name: uniqueName,
|
|
249
|
+
title: dbUnique.title ?? undefined,
|
|
250
|
+
link: `${pageLink}?element=${dbUnique.prose.id}`,
|
|
251
|
+
schemaName,
|
|
252
|
+
} satisfies ContentDepUnique;
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
return results.filter((r): r is ContentDepUnique => r !== null);
|
|
257
|
+
}
|
|
@@ -15,7 +15,7 @@ export async function getContentElementSnippets(
|
|
|
15
15
|
where: and(
|
|
16
16
|
eq(ERUDIT.db.schema.contentSnippets.contentFullId, fullId),
|
|
17
17
|
or(
|
|
18
|
-
eq(ERUDIT.db.schema.contentSnippets.
|
|
18
|
+
eq(ERUDIT.db.schema.contentSnippets.key, true),
|
|
19
19
|
eq(ERUDIT.db.schema.contentSnippets.seo, true),
|
|
20
20
|
),
|
|
21
21
|
),
|
|
@@ -45,27 +45,27 @@ export async function getContentElementSnippets(
|
|
|
45
45
|
title: snippetData.title!,
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
if (snippetData.
|
|
49
|
-
snippet.
|
|
50
|
-
let
|
|
51
|
-
let
|
|
48
|
+
if (snippetData.key) {
|
|
49
|
+
snippet.key = {};
|
|
50
|
+
let keyTitle: string | undefined;
|
|
51
|
+
let keyDescription: string | undefined;
|
|
52
52
|
|
|
53
|
-
if (typeof snippetData.
|
|
54
|
-
|
|
55
|
-
} else if (typeof snippetData.
|
|
56
|
-
if (snippetData.
|
|
57
|
-
|
|
53
|
+
if (typeof snippetData.key === 'string') {
|
|
54
|
+
keyTitle = snippetData.key;
|
|
55
|
+
} else if (typeof snippetData.key === 'object') {
|
|
56
|
+
if (snippetData.key.title) {
|
|
57
|
+
keyTitle = snippetData.key.title;
|
|
58
58
|
}
|
|
59
|
-
if (snippetData.
|
|
60
|
-
|
|
59
|
+
if (snippetData.key.description) {
|
|
60
|
+
keyDescription = snippetData.key.description;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
if (
|
|
65
|
-
snippet.
|
|
64
|
+
if (keyTitle) {
|
|
65
|
+
snippet.key.title = keyTitle;
|
|
66
66
|
}
|
|
67
|
-
if (
|
|
68
|
-
snippet.
|
|
67
|
+
if (keyDescription) {
|
|
68
|
+
snippet.key.description = keyDescription;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
import { and, eq, sql } from 'drizzle-orm';
|
|
2
2
|
|
|
3
|
-
export async function
|
|
3
|
+
export async function updateContentSchemaCounts(
|
|
4
4
|
fullId: string,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
schemaCounts: Record<string, number>,
|
|
6
|
+
// schemaName: string,
|
|
7
|
+
// amount: number,
|
|
7
8
|
): Promise<void> {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
|
|
12
|
-
schemaName,
|
|
13
|
-
count: 0,
|
|
14
|
-
})
|
|
15
|
-
.onConflictDoNothing();
|
|
9
|
+
const schemasFilter = ERUDIT.config.countElements.flat();
|
|
10
|
+
const filteredSchemaCounts = Object.entries(schemaCounts).filter(
|
|
11
|
+
([schemaName]) => schemasFilter.includes(schemaName),
|
|
12
|
+
);
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
for (const [schemaName, amount] of filteredSchemaCounts) {
|
|
15
|
+
await ERUDIT.db
|
|
16
|
+
.insert(ERUDIT.db.schema.contentElementStats)
|
|
17
|
+
.values({
|
|
18
|
+
fullId,
|
|
19
|
+
schemaName,
|
|
20
|
+
count: 0,
|
|
21
|
+
})
|
|
22
|
+
.onConflictDoNothing();
|
|
23
|
+
|
|
24
|
+
await ERUDIT.db
|
|
25
|
+
.update(ERUDIT.db.schema.contentElementStats)
|
|
26
|
+
.set({
|
|
27
|
+
count: sql`${ERUDIT.db.schema.contentElementStats.count} + ${amount}`,
|
|
28
|
+
})
|
|
29
|
+
.where(
|
|
30
|
+
and(
|
|
31
|
+
eq(ERUDIT.db.schema.contentElementStats.fullId, fullId),
|
|
32
|
+
eq(ERUDIT.db.schema.contentElementStats.schemaName, schemaName),
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
export async function getContentStats(
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { and, eq } from 'drizzle-orm';
|
|
2
2
|
import {
|
|
3
|
+
isProseElement,
|
|
4
|
+
makeProseElement,
|
|
3
5
|
mixSchema,
|
|
4
|
-
walkElements,
|
|
5
6
|
WalkNoDeeper,
|
|
7
|
+
walkPreSync,
|
|
6
8
|
WalkStop,
|
|
7
|
-
type AnySchema,
|
|
8
9
|
type ProseElement,
|
|
9
|
-
} from '
|
|
10
|
+
} from 'tsprose';
|
|
10
11
|
import type { ContentProseType } from '@erudit-js/core/content/prose';
|
|
11
12
|
import { headingSchema } from '@erudit-js/prose/elements/heading/core';
|
|
12
13
|
|
|
@@ -36,21 +37,18 @@ export async function getContentUnique(
|
|
|
36
37
|
export async function getContentHeadingUnique(
|
|
37
38
|
fullId: string,
|
|
38
39
|
proseType: ContentProseType,
|
|
39
|
-
|
|
40
|
+
uniqueId: string,
|
|
40
41
|
) {
|
|
41
42
|
const contentProse = await ERUDIT.repository.prose.getContent(
|
|
42
43
|
proseType,
|
|
43
44
|
fullId,
|
|
44
45
|
);
|
|
45
46
|
|
|
46
|
-
const afterHeadingElements: ProseElement
|
|
47
|
+
const afterHeadingElements: ProseElement[] = [];
|
|
47
48
|
let adding = false;
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
element.schemaName === headingSchema.name &&
|
|
52
|
-
element.uniqueName === uniqueName
|
|
53
|
-
) {
|
|
50
|
+
walkPreSync(contentProse, (element) => {
|
|
51
|
+
if (isProseElement(element, headingSchema) && element.id === uniqueId) {
|
|
54
52
|
adding = true;
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -66,11 +64,12 @@ export async function getContentHeadingUnique(
|
|
|
66
64
|
}
|
|
67
65
|
});
|
|
68
66
|
|
|
69
|
-
const mix
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
const mix = makeProseElement({
|
|
68
|
+
schema: mixSchema,
|
|
69
|
+
elementHandler: (proseElement) => {
|
|
70
|
+
proseElement.children = afterHeadingElements;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
74
73
|
|
|
75
74
|
return mix;
|
|
76
75
|
}
|
|
@@ -232,7 +232,12 @@ export async function clearOldContentData(contentIds: string[]) {
|
|
|
232
232
|
|
|
233
233
|
await ERUDIT.db
|
|
234
234
|
.delete(ERUDIT.db.schema.contentDeps)
|
|
235
|
-
.where(
|
|
235
|
+
.where(
|
|
236
|
+
or(
|
|
237
|
+
inArray(ERUDIT.db.schema.contentDeps.toFullId, contentIds),
|
|
238
|
+
inArray(ERUDIT.db.schema.contentDeps.fromFullId, contentIds),
|
|
239
|
+
),
|
|
240
|
+
);
|
|
236
241
|
|
|
237
242
|
await ERUDIT.db
|
|
238
243
|
.delete(ERUDIT.db.schema.contentElementStats)
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { isDocument, type
|
|
1
|
+
import { isDocument, type Document } from 'tsprose';
|
|
2
2
|
import { isContentItem } from '@erudit-js/core/content/item';
|
|
3
3
|
import type { PageContentItem } from '@erudit-js/core/content/page';
|
|
4
|
-
import { isIncludedRawElement } from '@erudit-js/prose';
|
|
5
4
|
|
|
6
5
|
import type { ContentNavNode } from '../nav/types';
|
|
7
6
|
import { logContentError } from './utils/contentError';
|
|
8
7
|
import { insertContentItem } from './utils/insertContentItem';
|
|
9
|
-
import { resolveEruditProse } from '../../prose/repository/resolve';
|
|
10
8
|
import { insertContentResolved } from './utils/insertContentResolved';
|
|
11
9
|
|
|
12
10
|
export async function resolvePage(pageNode: ContentNavNode) {
|
|
@@ -16,7 +14,7 @@ export async function resolvePage(pageNode: ContentNavNode) {
|
|
|
16
14
|
|
|
17
15
|
try {
|
|
18
16
|
const pageModule = await ERUDIT.import<{
|
|
19
|
-
content:
|
|
17
|
+
content: Document;
|
|
20
18
|
page: PageContentItem;
|
|
21
19
|
}>(ERUDIT.paths.project(`content/${pageNode.contentRelPath}/page`));
|
|
22
20
|
|
|
@@ -30,49 +28,31 @@ export async function resolvePage(pageNode: ContentNavNode) {
|
|
|
30
28
|
|
|
31
29
|
await insertContentItem(pageNode, pageModule.page);
|
|
32
30
|
|
|
33
|
-
const elementsCount: Record<string, number> = {};
|
|
34
|
-
|
|
35
31
|
const proseDocument = pageModule.content;
|
|
36
|
-
const
|
|
37
|
-
proseDocument.
|
|
38
|
-
true,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (isIncludedRawElement(rawElement)) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
ERUDIT.config.countElements.flat().includes(rawElement.schemaName)
|
|
48
|
-
) {
|
|
49
|
-
elementsCount[rawElement.schemaName] =
|
|
50
|
-
(elementsCount[rawElement.schemaName] || 0) + 1;
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
);
|
|
32
|
+
const result = await ERUDIT.repository.prose.fromRaw({
|
|
33
|
+
rawProse: proseDocument.rawProse,
|
|
34
|
+
toc: { enabled: true },
|
|
35
|
+
snippets: { enabled: true },
|
|
36
|
+
});
|
|
54
37
|
|
|
55
|
-
if (
|
|
38
|
+
if (result.toc?.length) {
|
|
56
39
|
await ERUDIT.db.insert(ERUDIT.db.schema.contentToc).values({
|
|
57
40
|
fullId: pageNode.fullId,
|
|
58
|
-
toc:
|
|
41
|
+
toc: result.toc,
|
|
59
42
|
});
|
|
60
43
|
}
|
|
61
44
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
count,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
45
|
+
await ERUDIT.repository.content.updateSchemaCounts(
|
|
46
|
+
pageNode.fullId,
|
|
47
|
+
result.schemaCounts,
|
|
48
|
+
);
|
|
69
49
|
|
|
70
50
|
await ERUDIT.db.insert(ERUDIT.db.schema.pages).values({
|
|
71
51
|
fullId: pageNode.fullId,
|
|
72
|
-
prose:
|
|
52
|
+
prose: result.prose,
|
|
73
53
|
});
|
|
74
54
|
|
|
75
|
-
await insertContentResolved(pageNode.fullId, 'page',
|
|
55
|
+
await insertContentResolved(pageNode.fullId, 'page', result);
|
|
76
56
|
} catch (error) {
|
|
77
57
|
logContentError(pageNode);
|
|
78
58
|
throw error;
|