erudit 4.3.4-dev.2 → 4.3.4
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/main/MainTopicPartPage.vue +3 -0
- package/app/composables/jsonLd.ts +71 -11
- package/app/composables/og.ts +8 -0
- package/app/pages/book/[...bookId].vue +4 -0
- package/app/pages/group/[...groupId].vue +4 -0
- package/app/pages/page/[...pageId].vue +3 -0
- package/package.json +5 -5
- package/server/erudit/prose/repository/finalize.ts +68 -0
|
@@ -49,6 +49,9 @@ await useContentSeo({
|
|
|
49
49
|
snippets: mainContent.snippets,
|
|
50
50
|
breadcrumbs: mainContent.breadcrumbs,
|
|
51
51
|
lastmod: mainContent.lastmod,
|
|
52
|
+
contributions: mainContent.contributions,
|
|
53
|
+
flags: mainContent.flags,
|
|
54
|
+
connections: mainContent.connections,
|
|
52
55
|
});
|
|
53
56
|
</script>
|
|
54
57
|
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import type { ContentContribution } from '@erudit-js/core/content/contributions';
|
|
2
|
+
import type { ContentFlags } from '@erudit-js/core/content/flags';
|
|
3
|
+
|
|
1
4
|
import type { Breadcrumbs } from '../../shared/types/breadcrumbs';
|
|
5
|
+
import type { ContentConnections } from '../../shared/types/contentConnections';
|
|
2
6
|
import type { ElementSnippet } from '../../shared/types/elementSnippet';
|
|
7
|
+
import type { MainContentChildrenItem } from '../../shared/types/mainContent';
|
|
8
|
+
|
|
9
|
+
function contentTypeToSchemaType(type: string): string {
|
|
10
|
+
return type === 'book' ? 'Book' : type === 'group' ? 'Course' : 'Article';
|
|
11
|
+
}
|
|
3
12
|
|
|
4
13
|
export function useJsonLd(key: string, data: Record<string, unknown>) {
|
|
5
14
|
useHead({
|
|
@@ -63,18 +72,17 @@ export function useContentArticleJsonLd(args: {
|
|
|
63
72
|
lastmod?: string;
|
|
64
73
|
keyElements?: ElementSnippet[];
|
|
65
74
|
breadcrumbs?: Breadcrumbs;
|
|
75
|
+
children?: MainContentChildrenItem[];
|
|
76
|
+
contributions?: ContentContribution[];
|
|
77
|
+
flags?: ContentFlags;
|
|
78
|
+
connections?: ContentConnections;
|
|
66
79
|
}) {
|
|
67
80
|
const withSiteUrl = useSiteUrl();
|
|
68
81
|
|
|
69
82
|
const siteTitle =
|
|
70
83
|
ERUDIT.config.seo?.siteTitle || ERUDIT.config.asideMajor?.siteInfo?.title;
|
|
71
84
|
|
|
72
|
-
const schemaType =
|
|
73
|
-
args.contentType === 'book'
|
|
74
|
-
? 'Book'
|
|
75
|
-
: args.contentType === 'group'
|
|
76
|
-
? 'Course'
|
|
77
|
-
: 'Article';
|
|
85
|
+
const schemaType = contentTypeToSchemaType(args.contentType);
|
|
78
86
|
|
|
79
87
|
const data: Record<string, unknown> = {
|
|
80
88
|
'@context': 'https://schema.org',
|
|
@@ -83,6 +91,7 @@ export function useContentArticleJsonLd(args: {
|
|
|
83
91
|
? { headline: formatText(args.title) }
|
|
84
92
|
: { name: formatText(args.title) }),
|
|
85
93
|
url: withSiteUrl(args.urlPath),
|
|
94
|
+
inLanguage: ERUDIT.config.language?.current || 'en',
|
|
86
95
|
};
|
|
87
96
|
|
|
88
97
|
if (args.description) {
|
|
@@ -111,11 +120,62 @@ export function useContentArticleJsonLd(args: {
|
|
|
111
120
|
};
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
const keyElementTerms = args.keyElements?.length
|
|
124
|
+
? args.keyElements.map((el) => ({
|
|
125
|
+
'@type': 'DefinedTerm',
|
|
126
|
+
name: formatText(el.seo?.title || el.key?.title || el.title),
|
|
127
|
+
url: withSiteUrl(el.link),
|
|
128
|
+
}))
|
|
129
|
+
: [];
|
|
130
|
+
|
|
131
|
+
if (keyElementTerms.length > 0) {
|
|
132
|
+
data.about = keyElementTerms;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hasPart: Record<string, unknown>[] = [];
|
|
136
|
+
|
|
137
|
+
if (args.children?.length) {
|
|
138
|
+
for (const child of args.children) {
|
|
139
|
+
const part: Record<string, unknown> = {
|
|
140
|
+
'@type': contentTypeToSchemaType(child.type),
|
|
141
|
+
name: formatText(child.title),
|
|
142
|
+
url: withSiteUrl(child.link),
|
|
143
|
+
};
|
|
144
|
+
if (child.description) {
|
|
145
|
+
part.description = formatText(child.description);
|
|
146
|
+
}
|
|
147
|
+
hasPart.push(part);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
hasPart.push(...keyElementTerms);
|
|
152
|
+
|
|
153
|
+
if (hasPart.length > 0) {
|
|
154
|
+
data.hasPart = hasPart;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (args.contributions?.length) {
|
|
158
|
+
data.author = args.contributions.map((c) => {
|
|
159
|
+
const person: Record<string, unknown> = {
|
|
160
|
+
'@type': 'Person',
|
|
161
|
+
name: c.name || c.contributorId,
|
|
162
|
+
};
|
|
163
|
+
if (c.avatarUrl) {
|
|
164
|
+
person.image = withSiteUrl(c.avatarUrl);
|
|
165
|
+
}
|
|
166
|
+
return person;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (args.flags?.advanced) {
|
|
171
|
+
data.educationalLevel = 'Advanced';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (args.connections?.hardDependencies?.length) {
|
|
175
|
+
data.isBasedOn = args.connections.hardDependencies.map((dep) => ({
|
|
176
|
+
'@type': contentTypeToSchemaType(dep.contentType),
|
|
177
|
+
name: formatText(dep.title),
|
|
178
|
+
url: withSiteUrl(dep.link),
|
|
119
179
|
}));
|
|
120
180
|
}
|
|
121
181
|
|
package/app/composables/og.ts
CHANGED
|
@@ -95,6 +95,10 @@ export async function useContentSeo(args: {
|
|
|
95
95
|
snippets?: ElementSnippet[];
|
|
96
96
|
breadcrumbs?: Breadcrumbs;
|
|
97
97
|
lastmod?: string;
|
|
98
|
+
children?: MainContentChildrenItem[];
|
|
99
|
+
contributions?: ContentContribution[];
|
|
100
|
+
flags?: ContentFlags;
|
|
101
|
+
connections?: ContentConnections;
|
|
98
102
|
}) {
|
|
99
103
|
const canUseBookTitle = ERUDIT.config.seo?.useBookSiteTitle;
|
|
100
104
|
|
|
@@ -163,6 +167,10 @@ export async function useContentSeo(args: {
|
|
|
163
167
|
lastmod: args.lastmod,
|
|
164
168
|
keyElements: args.snippets?.filter((snippet) => !!snippet.key),
|
|
165
169
|
breadcrumbs: args.breadcrumbs,
|
|
170
|
+
children: args.children,
|
|
171
|
+
contributions: args.contributions,
|
|
172
|
+
flags: args.flags,
|
|
173
|
+
connections: args.connections,
|
|
166
174
|
});
|
|
167
175
|
|
|
168
176
|
//
|
|
@@ -31,6 +31,10 @@ await useContentSeo({
|
|
|
31
31
|
seo: mainContent.seo,
|
|
32
32
|
breadcrumbs: mainContent.breadcrumbs,
|
|
33
33
|
lastmod: mainContent.lastmod,
|
|
34
|
+
children: mainContent.children,
|
|
35
|
+
contributions: mainContent.contributions,
|
|
36
|
+
flags: mainContent.flags,
|
|
37
|
+
connections: mainContent.connections,
|
|
34
38
|
});
|
|
35
39
|
</script>
|
|
36
40
|
|
|
@@ -33,6 +33,10 @@ await useContentSeo({
|
|
|
33
33
|
seo: mainContent.seo,
|
|
34
34
|
breadcrumbs: mainContent.breadcrumbs,
|
|
35
35
|
lastmod: mainContent.lastmod,
|
|
36
|
+
children: mainContent.children,
|
|
37
|
+
contributions: mainContent.contributions,
|
|
38
|
+
flags: mainContent.flags,
|
|
39
|
+
connections: mainContent.connections,
|
|
36
40
|
});
|
|
37
41
|
</script>
|
|
38
42
|
|
|
@@ -31,6 +31,9 @@ await useContentSeo({
|
|
|
31
31
|
snippets: mainContent.snippets,
|
|
32
32
|
breadcrumbs: mainContent.breadcrumbs,
|
|
33
33
|
lastmod: mainContent.lastmod,
|
|
34
|
+
contributions: mainContent.contributions,
|
|
35
|
+
flags: mainContent.flags,
|
|
36
|
+
connections: mainContent.connections,
|
|
34
37
|
});
|
|
35
38
|
</script>
|
|
36
39
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "erudit",
|
|
3
|
-
"version": "4.3.4
|
|
3
|
+
"version": "4.3.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "🤓 CMS for perfect educational sites.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@erudit-js/cli": "4.3.4
|
|
28
|
-
"@erudit-js/core": "4.3.4
|
|
29
|
-
"@erudit-js/prose": "4.3.4
|
|
27
|
+
"@erudit-js/cli": "4.3.4",
|
|
28
|
+
"@erudit-js/core": "4.3.4",
|
|
29
|
+
"@erudit-js/prose": "4.3.4",
|
|
30
30
|
"@floating-ui/vue": "^1.1.11",
|
|
31
31
|
"@resvg/resvg-js": "^2.6.2",
|
|
32
32
|
"@tailwindcss/vite": "^4.2.1",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"chokidar": "^5.0.0",
|
|
35
35
|
"consola": "^3.4.2",
|
|
36
36
|
"drizzle-kit": "^0.31.10",
|
|
37
|
-
"drizzle-orm": "^0.45.
|
|
37
|
+
"drizzle-orm": "^0.45.2",
|
|
38
38
|
"esbuild": "^0.27.4",
|
|
39
39
|
"flexsearch": "^0.8.212",
|
|
40
40
|
"glob": "^13.0.6",
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fillProseStorage,
|
|
3
3
|
isProseElement,
|
|
4
|
+
isRawElement,
|
|
4
5
|
type ProseElement,
|
|
6
|
+
type ProseStorage,
|
|
5
7
|
type ProseWithStorage,
|
|
8
|
+
type RawElement,
|
|
6
9
|
} from 'tsprose';
|
|
7
10
|
import { imageSchema } from '@erudit-js/prose/elements/image/core';
|
|
8
11
|
import { videoSchema } from '@erudit-js/prose/elements/video/core';
|
|
@@ -17,6 +20,7 @@ import {
|
|
|
17
20
|
} from '@erudit-js/prose/elements/link/dependency/core';
|
|
18
21
|
import { problemSchema } from '@erudit-js/prose/elements/problem/problem';
|
|
19
22
|
import { subProblemSchema } from '@erudit-js/prose/elements/problem/problems';
|
|
23
|
+
import { problemCheckSchema } from '@erudit-js/prose/elements/problem/problemCheck';
|
|
20
24
|
|
|
21
25
|
import { createImageStorage } from '../storage/image';
|
|
22
26
|
import { createVideoStorage } from '../storage/video';
|
|
@@ -26,6 +30,68 @@ import { createProblemScriptStorage } from '../storage/problemScript';
|
|
|
26
30
|
|
|
27
31
|
import { coreElements } from '#erudit/prose/global';
|
|
28
32
|
|
|
33
|
+
async function createStorageForRawElement(
|
|
34
|
+
rawElement: RawElement,
|
|
35
|
+
storageKey: string,
|
|
36
|
+
) {
|
|
37
|
+
switch (true) {
|
|
38
|
+
case isRawElement(rawElement, imageSchema):
|
|
39
|
+
return await createImageStorage(rawElement as any);
|
|
40
|
+
case isRawElement(rawElement, videoSchema):
|
|
41
|
+
return createVideoStorage(rawElement as any);
|
|
42
|
+
case isRawElement(rawElement, calloutSchema):
|
|
43
|
+
return createCalloutStorage(rawElement as any);
|
|
44
|
+
case isRawElement(rawElement, refSchema):
|
|
45
|
+
case isRawElement(rawElement, referenceSchema):
|
|
46
|
+
case isRawElement(rawElement, depSchema):
|
|
47
|
+
case isRawElement(rawElement, dependencySchema):
|
|
48
|
+
return await createLinkStorage(rawElement as any, storageKey);
|
|
49
|
+
case isRawElement(rawElement, problemSchema):
|
|
50
|
+
case isRawElement(rawElement, subProblemSchema):
|
|
51
|
+
return createProblemScriptStorage(rawElement as any, storageKey);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function collectEnsureStorage(
|
|
56
|
+
rawElements: RawElement[],
|
|
57
|
+
storage: ProseStorage,
|
|
58
|
+
) {
|
|
59
|
+
for (const rawElement of rawElements) {
|
|
60
|
+
if (rawElement.storageKey && !(rawElement.storageKey in storage)) {
|
|
61
|
+
const value = await createStorageForRawElement(
|
|
62
|
+
rawElement,
|
|
63
|
+
rawElement.storageKey,
|
|
64
|
+
);
|
|
65
|
+
if (value !== undefined) {
|
|
66
|
+
storage[rawElement.storageKey] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (rawElement.children) {
|
|
70
|
+
await collectEnsureStorage(rawElement.children as RawElement[], storage);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function processEnsureStorage(
|
|
76
|
+
element: ProseElement,
|
|
77
|
+
storage: ProseStorage,
|
|
78
|
+
) {
|
|
79
|
+
if (
|
|
80
|
+
(isProseElement(element, problemSchema) ||
|
|
81
|
+
isProseElement(element, subProblemSchema) ||
|
|
82
|
+
isProseElement(element, problemCheckSchema)) &&
|
|
83
|
+
element.data.ensureStorage
|
|
84
|
+
) {
|
|
85
|
+
await collectEnsureStorage(element.data.ensureStorage, storage);
|
|
86
|
+
delete element.data.ensureStorage;
|
|
87
|
+
}
|
|
88
|
+
if (element.children) {
|
|
89
|
+
for (const child of element.children as ProseElement[]) {
|
|
90
|
+
await processEnsureStorage(child, storage);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
29
95
|
export async function finalizeProse(
|
|
30
96
|
prose: ProseElement,
|
|
31
97
|
): Promise<ProseWithStorage> {
|
|
@@ -58,6 +124,8 @@ export async function finalizeProse(
|
|
|
58
124
|
},
|
|
59
125
|
});
|
|
60
126
|
|
|
127
|
+
await processEnsureStorage(prose, storage);
|
|
128
|
+
|
|
61
129
|
return {
|
|
62
130
|
prose,
|
|
63
131
|
storage,
|