erudit 4.3.5-dev.1 → 4.3.6

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.
@@ -0,0 +1,42 @@
1
+ <script lang="ts" setup>
2
+ const { src } = defineProps<{
3
+ src: string;
4
+ }>();
5
+ </script>
6
+
7
+ <template>
8
+ <div :class="$style.imageTint">
9
+ <img :src />
10
+ <img :src />
11
+ </div>
12
+ </template>
13
+
14
+ <style module>
15
+ .imageTint {
16
+ position: relative;
17
+ overflow: hidden;
18
+ isolation: isolate;
19
+
20
+ img {
21
+ width: 100%;
22
+ }
23
+
24
+ img:first-child {
25
+ mix-blend-mode: multiply;
26
+ }
27
+
28
+ img:last-child {
29
+ position: absolute;
30
+ inset: 0;
31
+ z-index: -1;
32
+ filter: drop-shadow(
33
+ 0px 1000px 0
34
+ var(--tint, color-mix(in hsl, var(--color-brand), transparent 90%))
35
+ );
36
+ transform: translateY(-1000px);
37
+ opacity: var(--tint-opacity, 1);
38
+ transition: opacity var(--default-transition-timing-function)
39
+ var(--default-transition-duration);
40
+ }
41
+ }
42
+ </style>
@@ -132,19 +132,20 @@ async function searchResultClick() {
132
132
  />
133
133
  {{ formatText(secondaryTitle) }}
134
134
  </div>
135
- <div class="gap-small text-text flex items-center">
136
- <div class="relative size-[1.2em] shrink-0">
135
+ <div class="text-text">
136
+ <span class="mr-small relative">
137
+ <MyIcon name="__missing" class="invisible inline size-[1.2em]" />
137
138
  <TransitionFade>
138
139
  <MaybeMyIcon
139
140
  :name="icon"
140
141
  :key="iconKey"
141
- class="absolute top-px left-0 size-full"
142
+ class="absolute top-0 left-0 inline size-[1.2em]"
142
143
  />
143
144
  </TransitionFade>
144
- </div>
145
- <div>
145
+ </span>
146
+ <span>
146
147
  {{ formatText(primaryTitle) }}
147
- </div>
148
+ </span>
148
149
  </div>
149
150
  <div>
150
151
  <div
@@ -10,30 +10,40 @@ const hasExtra = child.stats || child.keyLinks;
10
10
  dark:bg-bg-aside rounded border bg-neutral-100 ring-2 ring-transparent
11
11
  transition-[border,box-shadow]"
12
12
  >
13
+ <EruditLink
14
+ v-if="child.decoration"
15
+ :to="child.link"
16
+ class="p-normal max-micro:pb-0 not-group-hocus:[--tint-opacity:0]
17
+ micro:float-right block"
18
+ >
19
+ <ImageTint
20
+ :src="fileUrl(child.decoration)"
21
+ class="m-auto block aspect-square max-h-[90px] max-w-[90px]"
22
+ />
23
+ </EruditLink>
24
+
13
25
  <EruditLink :to="child.link" class="p-normal gap-small flex flex-col">
14
- <div class="gap-small micro:gap-normal flex items-center">
26
+ <h2
27
+ class="group-hocus:text-brand micro:text-main-lg micro:text-start
28
+ text-center font-bold transition-[color]"
29
+ >
15
30
  <MyIcon
16
31
  :name="ICONS[child.type]"
17
- class="text-text-muted group-hocus:text-brand shrink-0 text-[1.2em]
18
- transition-[color]"
32
+ class="text-text-muted group-hocus:text-brand mr-small relative
33
+ -top-[1px] inline shrink-0 text-[1.2em] transition-[color]"
19
34
  />
20
- <h2
21
- class="group-hocus:text-brand gap-small micro:text-main-lg flex
22
- items-center font-bold transition-[color]"
23
- >
24
- {{ formatText(child.title) }}
25
- </h2>
26
- </div>
35
+ <span>{{ formatText(child.title) }}</span>
36
+ </h2>
27
37
 
28
- <div v-if="child.description" class="text-text-muted">
38
+ <div
39
+ v-if="child.description"
40
+ class="text-text-muted micro:text-start text-center"
41
+ >
29
42
  {{ formatText(child.description) }}
30
43
  </div>
31
44
  </EruditLink>
32
- <div
33
- v-if="hasExtra"
34
- class="border-t-border p-normal gap-normal flex flex-col border-t"
35
- >
36
- <div v-if="child.keyLinks" class="relative top-[1px]">
45
+ <div v-if="hasExtra" class="px-normal pb-normal gap-normal flex flex-col">
46
+ <div v-if="child.keyLinks">
37
47
  <MainKeyLinks :elementSnippets="child.keyLinks" mode="children" />
38
48
  </div>
39
49
  <div v-if="child.stats">
@@ -1,15 +1,29 @@
1
1
  <script lang="ts" setup>
2
- defineProps<{ decoration?: string }>();
2
+ defineProps<{
3
+ role: 'preamble-float' | 'preamble-static';
4
+ decoration?: string;
5
+ }>();
3
6
  </script>
4
7
 
5
8
  <template>
6
- <section
7
- v-if="decoration"
8
- class="pl-small pb-small pt-main pr-main float-right max-[700px]:hidden"
9
- >
10
- <img
11
- :src="fileUrl(decoration!)"
12
- class="block aspect-square max-h-[125px] w-full max-w-[125px]"
13
- />
14
- </section>
9
+ <template v-if="decoration">
10
+ <section
11
+ v-if="role === 'preamble-float'"
12
+ class="p-small pr-main float-right pt-3 max-[700px]:hidden"
13
+ >
14
+ <ImageTint
15
+ :src="fileUrl(decoration)"
16
+ class="block aspect-square max-h-[125px] max-w-[125px]"
17
+ />
18
+ </section>
19
+ <section
20
+ v-else-if="role === 'preamble-static'"
21
+ class="px-main py-main-half min-[700px]:hidden"
22
+ >
23
+ <ImageTint
24
+ :src="fileUrl(decoration)"
25
+ class="micro:m-0 m-auto block aspect-square max-h-[125px] max-w-[125px]"
26
+ />
27
+ </section>
28
+ </template>
15
29
  </template>
@@ -38,7 +38,8 @@ const phrase = await usePhrases('key_elements');
38
38
  <div
39
39
  v-else
40
40
  :style="{ '--keyBg': 'var(--color-bg-main)' }"
41
- class="gap-small text-main-sm flex flex-wrap"
41
+ class="gap-small text-main-sm micro:justify-start flex flex-wrap
42
+ justify-center"
42
43
  >
43
44
  <MainKeyLink v-for="keyLink of keyLinks" :keyLink />
44
45
  </div>
@@ -5,27 +5,35 @@ const { color = 'var(--color-brand)' } = defineProps<{
5
5
  icon: MaybeMyIconName;
6
6
  title: string;
7
7
  color?: string;
8
+ contentLabel?: string;
8
9
  }>();
9
10
  </script>
10
11
 
11
12
  <template>
12
13
  <section
13
- :style="{ '--titleColor': color }"
14
- class="gap-small micro:gap-normal micro:flex-row micro:justify-start px-main
15
- py-main-half not-first:micro:-my-3 not-first:micro:-top-1.5 relative flex
16
- flex-col items-center justify-center"
14
+ :style="{
15
+ '--titleColor': color,
16
+ '--iconColor':
17
+ 'color-mix(in srgb, var(--titleColor), var(--color-text) 70%)',
18
+ }"
19
+ class="gap-small micro:items-start px-main py-main-half relative flex
20
+ flex-col items-center justify-center leading-none"
17
21
  >
18
22
  <div
19
- class="max-micro:rounded-full max-micro:p-4
20
- max-micro:bg-(--titleColor)/80"
23
+ class="gap-small micro:hidden flex items-center text-[1.1em] font-semibold
24
+ text-(--iconColor)"
21
25
  >
22
- <MaybeMyIcon
23
- :name="icon"
24
- class="max-micro:text-white micro:text-[38px] text-[30px]
25
- text-[color-mix(in_srgb,var(--titleColor),var(--color-text)_70%)]"
26
- />
26
+ <MaybeMyIcon :name="icon" class="text-[1.2em]" />
27
+ <span class="micro:hidden">{{ contentLabel }}</span>
27
28
  </div>
28
29
  <h1 class="text-size-h1 max-micro:text-center">
30
+ <span :title="contentLabel" class="mr-normal cursor-help">
31
+ <MaybeMyIcon
32
+ :name="icon"
33
+ class="max-micro:hidden relative -top-[1px] inline cursor-help
34
+ text-[1.1em] text-(--iconColor)"
35
+ />
36
+ </span>
29
37
  <FancyBold :text="title" :color="color" />
30
38
  </h1>
31
39
  </section>
@@ -18,6 +18,7 @@ async function proseMounted() {
18
18
  }
19
19
 
20
20
  const phrase = await usePhrases(
21
+ 'article',
21
22
  'summary',
22
23
  'practice',
23
24
  'article_seo_description',
@@ -30,21 +31,17 @@ await useContentSeo({
30
31
  title: mainContent.title,
31
32
  bookTitle: mainContent.bookTitle,
32
33
  contentTypeSuffix:
33
- mainContent.part !== 'article' ? phrase[mainContent.part] : undefined,
34
+ mainContent.part !== mainContent.parts[0]
35
+ ? phrase[mainContent.part]
36
+ : undefined,
34
37
  contentTypePath: {
35
38
  type: 'topic',
36
39
  topicPart: mainContent.part,
37
40
  contentId: mainContent.shortId,
38
41
  },
39
42
  description:
40
- mainContent.part === 'article'
41
- ? mainContent.description ||
42
- phrase.article_seo_description(mainContent.title)
43
- : mainContent.part === 'summary'
44
- ? phrase.summary_seo_description(mainContent.title)
45
- : mainContent.part === 'practice'
46
- ? phrase.practice_seo_description(mainContent.title)
47
- : undefined,
43
+ (mainContent.part === mainContent.parts[0] && mainContent.description) ||
44
+ phrase[`${mainContent.part}_seo_description`](mainContent.title),
48
45
  seo: mainContent.seo,
49
46
  snippets: mainContent.snippets,
50
47
  breadcrumbs: mainContent.breadcrumbs,
@@ -57,10 +54,21 @@ await useContentSeo({
57
54
 
58
55
  <template>
59
56
  <MainGlow />
60
- <MainDecoration :decoration="mainContent.decoration" />
61
57
  <MainSectionPreamble>
58
+ <MainDecoration
59
+ role="preamble-float"
60
+ :decoration="mainContent.decoration"
61
+ />
62
62
  <MainBreadcrumbs :breadcrumbs="mainContent.breadcrumbs" />
63
- <MainTitle :icon="ICONS[mainContent.part]" :title="mainContent.title" />
63
+ <MainDecoration
64
+ role="preamble-static"
65
+ :decoration="mainContent.decoration"
66
+ />
67
+ <MainTitle
68
+ :icon="ICONS[mainContent.part]"
69
+ :title="mainContent.title"
70
+ :contentLabel="phrase[mainContent.part]"
71
+ />
64
72
  <MainFlags :flags="mainContent.flags" />
65
73
  <MainDescription :description="mainContent.description" />
66
74
  <MainKeyLinks mode="single" :elementSnippets="mainContent.snippets" />
@@ -38,7 +38,8 @@ const phrase = await usePhrases('stats');
38
38
  </section>
39
39
  <div
40
40
  v-else-if="mode === 'children' && stats"
41
- class="gap-small micro:gap-normal text-main-sm flex flex-wrap"
41
+ class="gap-small micro:gap-normal text-main-sm micro:justify-start flex
42
+ flex-wrap justify-center"
42
43
  >
43
44
  <ItemMaterials
44
45
  v-if="stats.materials"
@@ -26,8 +26,14 @@ defineProps<{
26
26
  },
27
27
  ]"
28
28
  >
29
- <MaybeMyIcon v-if="icon" :name="icon" class="shrink-0 text-[1.2em]" />
30
- <div class="flex-1">{{ main }}</div>
29
+ <div class="flex-1">
30
+ <MaybeMyIcon
31
+ v-if="icon"
32
+ :name="icon"
33
+ class="mr-small inline text-[1.2em]"
34
+ />
35
+ <span>{{ main }}</span>
36
+ </div>
31
37
  <div class="shrink-0" v-if="$slots.secondary">
32
38
  <slot name="secondary"></slot>
33
39
  </div>
@@ -111,7 +111,7 @@ export async function useContentSeo(args: {
111
111
 
112
112
  const fullTitle =
113
113
  (args.seo?.title || args.title) +
114
- (args.contentTypeSuffix ? ' [' + args.contentTypeSuffix + ']' : '') +
114
+ (args.contentTypeSuffix ? ' - ' + args.contentTypeSuffix : '') +
115
115
  ' - ' +
116
116
  seoSiteTitle;
117
117
 
@@ -18,7 +18,7 @@ if (ERUDIT.config.contributors?.enabled) {
18
18
  showNewsAside();
19
19
  }
20
20
 
21
- const phrase = await usePhrases('begin_learning');
21
+ const phrase = await usePhrases('book', 'begin_learning');
22
22
  const lastChangedDate = useLastChanged(() => mainContent.lastmod);
23
23
 
24
24
  await useContentSeo({
@@ -40,10 +40,21 @@ await useContentSeo({
40
40
 
41
41
  <template>
42
42
  <MainGlow />
43
- <MainDecoration :decoration="mainContent.decoration" />
44
43
  <MainSectionPreamble>
44
+ <MainDecoration
45
+ role="preamble-float"
46
+ :decoration="mainContent.decoration"
47
+ />
45
48
  <MainBreadcrumbs :breadcrumbs="mainContent.breadcrumbs" />
46
- <MainTitle icon="book" :title="mainContent.title" />
49
+ <MainDecoration
50
+ role="preamble-static"
51
+ :decoration="mainContent.decoration"
52
+ />
53
+ <MainTitle
54
+ icon="book"
55
+ :title="mainContent.title"
56
+ :contentLabel="phrase.book"
57
+ />
47
58
  <MainFlags :flags="mainContent.flags" />
48
59
  <MainDescription :description="mainContent.description" />
49
60
  <MainConnections :connections="mainContent.connections" />
@@ -42,10 +42,21 @@ await useContentSeo({
42
42
 
43
43
  <template>
44
44
  <MainGlow />
45
- <MainDecoration :decoration="mainContent.decoration" />
46
45
  <MainSectionPreamble>
46
+ <MainDecoration
47
+ role="preamble-float"
48
+ :decoration="mainContent.decoration"
49
+ />
47
50
  <MainBreadcrumbs :breadcrumbs="mainContent.breadcrumbs" />
48
- <MainTitle icon="folder-open" :title="mainContent.title" />
51
+ <MainDecoration
52
+ role="preamble-static"
53
+ :decoration="mainContent.decoration"
54
+ />
55
+ <MainTitle
56
+ icon="folder-open"
57
+ :title="mainContent.title"
58
+ :contentLabel="phrase.group"
59
+ />
49
60
  <MainFlags :flags="mainContent.flags" />
50
61
  <MainDescription :description="mainContent.description" />
51
62
  <MainConnections :connections="mainContent.connections" />
@@ -35,14 +35,27 @@ await useContentSeo({
35
35
  flags: mainContent.flags,
36
36
  connections: mainContent.connections,
37
37
  });
38
+
39
+ const phrase = await usePhrases('page');
38
40
  </script>
39
41
 
40
42
  <template>
41
43
  <MainGlow />
42
- <MainDecoration :decoration="mainContent.decoration" />
43
44
  <MainSectionPreamble>
45
+ <MainDecoration
46
+ role="preamble-float"
47
+ :decoration="mainContent.decoration"
48
+ />
44
49
  <MainBreadcrumbs :breadcrumbs="mainContent.breadcrumbs" />
45
- <MainTitle icon="lines" :title="mainContent.title" />
50
+ <MainDecoration
51
+ role="preamble-static"
52
+ :decoration="mainContent.decoration"
53
+ />
54
+ <MainTitle
55
+ icon="lines"
56
+ :title="mainContent.title"
57
+ :contentLabel="phrase.page"
58
+ />
46
59
  <MainFlags :flags="mainContent.flags" />
47
60
  <MainDescription :description="mainContent.description" />
48
61
  <MainKeyLinks mode="single" :elementSnippets="mainContent.snippets" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "erudit",
3
- "version": "4.3.5-dev.1",
3
+ "version": "4.3.6",
4
4
  "type": "module",
5
5
  "description": "🤓 CMS for perfect educational sites.",
6
6
  "license": "MIT",
@@ -24,23 +24,23 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@erudit-js/cli": "4.3.5-dev.1",
28
- "@erudit-js/core": "4.3.5-dev.1",
29
- "@erudit-js/prose": "4.3.5-dev.1",
27
+ "@erudit-js/cli": "4.3.6",
28
+ "@erudit-js/core": "4.3.6",
29
+ "@erudit-js/prose": "4.3.6",
30
30
  "@floating-ui/vue": "^1.1.11",
31
31
  "@resvg/resvg-js": "^2.6.2",
32
32
  "@tailwindcss/vite": "^4.2.1",
33
- "better-sqlite3": "^12.8.0",
33
+ "better-sqlite3": "^12.9.0",
34
34
  "chokidar": "^5.0.0",
35
35
  "consola": "^3.4.2",
36
36
  "drizzle-kit": "^0.31.10",
37
37
  "drizzle-orm": "^0.45.2",
38
- "esbuild": "^0.27.4",
38
+ "esbuild": "^0.28.0",
39
39
  "flexsearch": "^0.8.212",
40
40
  "glob": "^13.0.6",
41
41
  "image-size": "^2.0.2",
42
42
  "jiti": "^2.6.1",
43
- "nuxt": "4.4.2",
43
+ "nuxt": "4.4.4",
44
44
  "nuxt-my-icons": "1.2.2",
45
45
  "perfect-debounce": "^2.1.0",
46
46
  "satori": "^0.26.0",
@@ -21,6 +21,9 @@ export async function getContentChildren(
21
21
  'nav',
22
22
  );
23
23
  const description = await getContentDescription(childNode.fullId);
24
+ const decoration = await ERUDIT.repository.content.ownDecoration(
25
+ childNode.fullId,
26
+ );
24
27
  const elementSnippets = await ERUDIT.repository.content.elementSnippets(
25
28
  childNode.fullId,
26
29
  );
@@ -37,6 +40,10 @@ export async function getContentChildren(
37
40
  child.description = description;
38
41
  }
39
42
 
43
+ if (decoration) {
44
+ child.decoration = decoration;
45
+ }
46
+
40
47
  if (keyLinks && keyLinks.length > 0) {
41
48
  child.keyLinks = keyLinks;
42
49
  }
@@ -1,5 +1,10 @@
1
1
  import { eq } from 'drizzle-orm';
2
2
 
3
+ function buildDecorationPath(fullId: string, extension: string) {
4
+ const navNode = ERUDIT.contentNav.getNodeOrThrow(fullId);
5
+ return 'content/' + navNode.contentRelPath + '/decoration.' + extension;
6
+ }
7
+
3
8
  export async function getContentDecoration(fullId: string) {
4
9
  const parts = fullId.split('/');
5
10
  for (let i = parts.length; i > 0; i--) {
@@ -11,13 +16,18 @@ export async function getContentDecoration(fullId: string) {
11
16
  });
12
17
 
13
18
  if (dbContent?.decorationExtension) {
14
- const navNode = ERUDIT.contentNav.getNodeOrThrow(trimmedId);
15
- return (
16
- 'content/' +
17
- navNode.contentRelPath +
18
- '/decoration.' +
19
- dbContent.decorationExtension
20
- );
19
+ return buildDecorationPath(trimmedId, dbContent.decorationExtension);
21
20
  }
22
21
  }
23
22
  }
23
+
24
+ export async function getContentOwnDecoration(fullId: string) {
25
+ const dbContent = await ERUDIT.db.query.content.findFirst({
26
+ columns: { decorationExtension: true },
27
+ where: eq(ERUDIT.db.schema.content.fullId, fullId),
28
+ });
29
+
30
+ if (dbContent?.decorationExtension) {
31
+ return buildDecorationPath(fullId, dbContent.decorationExtension);
32
+ }
33
+ }
@@ -35,6 +35,47 @@ export async function getContentDependencies(fullId: string) {
35
35
  }
36
36
  }
37
37
 
38
+ // Fetch auto deps early so we can merge their unique names into overlapping
39
+ // hard deps. On books/groups the hard dep row itself has no uniqueNames
40
+ // (declared at the container level) while children's auto deps carry the
41
+ // exact element references from prose <Dep> tags.
42
+ const dbAutoDependencies = await ERUDIT.db.query.contentDeps.findMany({
43
+ columns: { toFullId: true, hard: true, uniqueNames: true },
44
+ where: and(
45
+ or(
46
+ eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
47
+ like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
48
+ ),
49
+ eq(ERUDIT.db.schema.contentDeps.hard, false),
50
+ ),
51
+ });
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
+
67
+ // When an auto dep targets the same content item as a hard dep, the auto
68
+ // dep will be filtered out later. Merge its unique names into the hard dep
69
+ // so the exact element sublisting is not lost.
70
+ for (const [toFullId, autoUniques] of autoUniqueMap) {
71
+ if (hardUniqueMap.has(toFullId)) {
72
+ const hardSet = hardUniqueMap.get(toFullId)!;
73
+ for (const name of autoUniques) {
74
+ hardSet.add(name);
75
+ }
76
+ }
77
+ }
78
+
38
79
  const hardToFullIds = ERUDIT.contentNav.orderIds(
39
80
  externalToFullIds(dbHardDependencies),
40
81
  );
@@ -61,31 +102,6 @@ export async function getContentDependencies(fullId: string) {
61
102
 
62
103
  const autoDependencies: ContentAutoDep[] = [];
63
104
 
64
- const dbAutoDependencies = await ERUDIT.db.query.contentDeps.findMany({
65
- columns: { toFullId: true, hard: true, uniqueNames: true },
66
- where: and(
67
- or(
68
- eq(ERUDIT.db.schema.contentDeps.fromFullId, fullId),
69
- like(ERUDIT.db.schema.contentDeps.fromFullId, `${fullId}/%`),
70
- ),
71
- eq(ERUDIT.db.schema.contentDeps.hard, false),
72
- ),
73
- });
74
-
75
- // Merge unique names across rows that share the same toFullId
76
- // (can happen when a topic and its children both dep on the same target).
77
- const autoUniqueMap = new Map<string, Set<string>>();
78
- for (const row of dbAutoDependencies) {
79
- if (!autoUniqueMap.has(row.toFullId)) {
80
- autoUniqueMap.set(row.toFullId, new Set());
81
- }
82
- if (row.uniqueNames) {
83
- for (const name of row.uniqueNames.split(',')) {
84
- autoUniqueMap.get(row.toFullId)!.add(name);
85
- }
86
- }
87
- }
88
-
89
105
  // Skip auto-dependency if a hard dependency from the same source exists
90
106
  const autoToFullIds = ERUDIT.contentNav
91
107
  .orderIds(externalToFullIds(dbAutoDependencies))
@@ -33,7 +33,7 @@ export const phrases: LanguagePhrases = {
33
33
  topic: 'Тема',
34
34
  article: 'Статья',
35
35
  summary: 'Конспект',
36
- practice: 'Практика',
36
+ practice: 'Задачи',
37
37
  page: 'Страница',
38
38
  preview_content_page_description:
39
39
  'Вы собираетесь перейти на страницу контента:',
@@ -16,7 +16,10 @@ import {
16
16
  getContentHeadingUnique,
17
17
  getContentUnique,
18
18
  } from './content/repository/unique';
19
- import { getContentDecoration } from './content/repository/decoration';
19
+ import {
20
+ getContentDecoration,
21
+ getContentOwnDecoration,
22
+ } from './content/repository/decoration';
20
23
  import { getContentFlags } from './content/repository/flags';
21
24
  import { getContentConnections } from './content/repository/connections';
22
25
  import { getQuoteIds } from './quote/repository/ids';
@@ -70,6 +73,7 @@ export const repository = {
70
73
  title: getContentTitle,
71
74
  description: getContentDescription,
72
75
  decoration: getContentDecoration,
76
+ ownDecoration: getContentOwnDecoration,
73
77
  elementSnippets: getContentElementSnippets,
74
78
  flags: getContentFlags,
75
79
  connections: getContentConnections,
@@ -35,6 +35,7 @@ export interface MainContentChildrenItem {
35
35
  link: string;
36
36
  title: string;
37
37
  description?: string;
38
+ decoration?: string;
38
39
  keyLinks?: ElementSnippet[];
39
40
  stats?: ContentStats;
40
41
  }