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.
Files changed (62) hide show
  1. package/app/components/SiteMain.vue +1 -1
  2. package/app/components/aside/major/panes/nav/Nav.vue +11 -6
  3. package/app/components/aside/major/panes/nav/NavBook.vue +19 -11
  4. package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +1 -1
  5. package/app/components/aside/minor/Contribute.vue +2 -2
  6. package/app/components/aside/minor/content/AsideMinorContent.vue +1 -1
  7. package/app/components/aside/minor/topic/AsideMinorTopic.vue +1 -1
  8. package/app/components/aside/minor/topic/TopicContributors.vue +2 -2
  9. package/app/components/aside/minor/topic/TopicToc.vue +1 -6
  10. package/app/components/aside/minor/topic/TopicTocItem.vue +3 -1
  11. package/app/components/main/utils/Breadcrumb.vue +1 -1
  12. package/app/components/main/utils/ContentReferences.vue +1 -1
  13. package/app/components/main/utils/reference/ReferenceGroup.vue +1 -1
  14. package/app/components/main/utils/reference/ReferenceItem.vue +5 -3
  15. package/app/components/main/utils/reference/ReferenceSource.vue +6 -4
  16. package/app/components/preview/PreviewScreen.vue +2 -2
  17. package/app/components/preview/display/PageLink.vue +1 -1
  18. package/app/composables/bitranContent.ts +2 -3
  19. package/app/composables/contentPage.ts +8 -7
  20. package/app/composables/formatText.ts +21 -8
  21. package/app/composables/phrases.ts +0 -16
  22. package/app/plugins/prerender.server.ts +22 -0
  23. package/app/scripts/preview/build.ts +1 -5
  24. package/app/scripts/preview/data/pageLink.ts +1 -0
  25. package/app/styles/normalize.scss +0 -14
  26. package/globals/content.ts +5 -0
  27. package/module/imports.ts +1 -0
  28. package/nuxt.config.ts +10 -5
  29. package/package.json +8 -8
  30. package/server/api/aside/major/nav/bookIds.ts +2 -2
  31. package/server/api/aside/minor/path.ts +19 -11
  32. package/server/api/bitran/content/[...location].ts +4 -2
  33. package/server/api/bitran/toc/[...location].ts +4 -2
  34. package/server/api/content/data.ts +5 -2
  35. package/server/api/prerender.ts +120 -0
  36. package/server/api/preview/page/[...parts].ts +30 -4
  37. package/server/api/preview/unique/{[location].ts → [...location].ts} +4 -3
  38. package/server/plugin/bitran/content.ts +3 -16
  39. package/server/plugin/bitran/elements/include.ts +40 -36
  40. package/server/plugin/bitran/location.ts +24 -10
  41. package/server/plugin/bitran/toc.ts +7 -2
  42. package/server/plugin/bitran/transpiler.ts +10 -1
  43. package/server/plugin/build/jobs/content/generic.ts +5 -6
  44. package/server/plugin/build/jobs/content/parse.ts +5 -1
  45. package/server/plugin/build/jobs/content/type/group.ts +2 -2
  46. package/server/plugin/build/jobs/content/type/topic.ts +2 -2
  47. package/server/plugin/build/jobs/nav.ts +28 -15
  48. package/server/plugin/content/context.ts +5 -2
  49. package/server/plugin/db/entities/Content.ts +0 -4
  50. package/server/plugin/db/setup.ts +1 -1
  51. package/server/plugin/importer.ts +5 -1
  52. package/server/plugin/nav/node.ts +2 -1
  53. package/server/plugin/nav/utils.ts +66 -24
  54. package/server/plugin/repository/content.ts +26 -23
  55. package/server/plugin/repository/contentId.ts +40 -0
  56. package/server/plugin/repository/frontNav.ts +6 -9
  57. package/server/plugin/repository/topic.ts +4 -1
  58. package/shared/aside/minor.ts +2 -2
  59. package/shared/bitran/contentId.ts +12 -44
  60. package/shared/content/bookId.ts +12 -0
  61. package/shared/frontNav.ts +1 -1
  62. package/test/contentId.test.ts +10 -10
@@ -22,7 +22,7 @@
22
22
 
23
23
  @include bp.below('mobile') {
24
24
  --_pMainBase: var(--_bitran_asideWidth);
25
- font-size: 14px;
25
+ font-size: 15px;
26
26
  }
27
27
 
28
28
  .mainInner {
@@ -1,5 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
  import type { FrontNav } from '@shared/frontNav';
3
+ import { detectContentBookId } from '@shared/content/bookId';
4
+
3
5
  import {
4
6
  getAsideMajorNavPayload,
5
7
  insideNavBook,
@@ -23,12 +25,15 @@ asideMajorNav.globalNav ||= (await $fetch('/api/aside/major/nav/global', {
23
25
 
24
26
  const checkIfInsideBook = () => {
25
27
  if (contentRoute.value) {
26
- for (const bookId of asideMajorNav.booksIds) {
27
- if (contentRoute.value.contentId.startsWith(bookId)) {
28
- navBookId.value = bookId;
29
- insideNavBook.value = true;
30
- return;
31
- }
28
+ const bookId = detectContentBookId(
29
+ contentRoute.value.contentId,
30
+ asideMajorNav.booksIds
31
+ );
32
+
33
+ if (bookId) {
34
+ navBookId.value = bookId;
35
+ insideNavBook.value = true;
36
+ return;
32
37
  }
33
38
  }
34
39
 
@@ -47,17 +47,19 @@ const pharse = await usePhrases('to_index', 'about_book');
47
47
  </section>
48
48
  <FNav :nav="book.children!" :contentId="contentRoute?.contentId">
49
49
  <template v-slot:before>
50
- <TreeItem
51
- icon="arrow-left"
52
- :label="pharse.to_index"
53
- @click="insideNavBook = false"
54
- />
55
- <TreeItem
56
- icon="book-question"
57
- :label="pharse.about_book"
58
- :active="contentRoute?.contentId === book.id"
59
- :link="`/book/${book.id}`"
60
- />
50
+ <section :class="$style.bookActions">
51
+ <TreeItem
52
+ icon="arrow-left"
53
+ :label="pharse.to_index"
54
+ @click="insideNavBook = false"
55
+ />
56
+ <TreeItem
57
+ icon="book-question"
58
+ :label="pharse.about_book"
59
+ :active="contentRoute?.contentId === book.id"
60
+ :link="`/book/${book.id}`"
61
+ />
62
+ </section>
61
63
  </template>
62
64
  </FNav>
63
65
  </PaneContentScroll>
@@ -84,4 +86,10 @@ const pharse = await usePhrases('to_index', 'about_book');
84
86
  flex-shrink: 0;
85
87
  }
86
88
  }
89
+
90
+ .bookActions {
91
+ border-bottom: 1px solid var(--border);
92
+ padding-bottom: calc(var(--gap)/2);
93
+ margin-bottom: calc(var(--gap)/2);
94
+ }
87
95
  </style>
@@ -2,7 +2,7 @@
2
2
  import type { ContentFlag } from '@erudit-js/cog/schema';
3
3
  import { flagsData } from '@app/scripts/flag';
4
4
 
5
- defineProps<{ flags: Record<ContentFlag, boolean> }>();
5
+ defineProps<{ flags: Partial<Record<ContentFlag, boolean>> }>();
6
6
 
7
7
  const phrases = Object.values(flagsData).map((data) => data.title);
8
8
  const phrase = await usePhrases(...phrases);
@@ -3,7 +3,7 @@ import eruditConfig from '#erudit/config';
3
3
 
4
4
  import AsideOverlayPane from '../utils/AsideOverlayPane.vue';
5
5
 
6
- const props = defineProps<{ fullContentId: string }>();
6
+ const props = defineProps<{ contentId: string }>();
7
7
  const phrase = await usePhrases(
8
8
  'make_contribution',
9
9
  'material_improvement',
@@ -23,7 +23,7 @@ const issueLink = computed(() => {
23
23
  const editPageLink = computed(() => {
24
24
  const ghRepository = eruditConfig.repository;
25
25
  return ghRepository
26
- ? `https://github.com/${ghRepository.name}/tree/${ghRepository.branch}/content/${props.fullContentId}`
26
+ ? `https://github.com/${ghRepository.name}/tree/${ghRepository.branch}/content/${props.contentId}`
27
27
  : null;
28
28
  });
29
29
  </script>
@@ -40,7 +40,7 @@ watch(contentData, () => (contributePaneVisible.value = false));
40
40
  {{ phrase.no_contributors }}
41
41
  </section>
42
42
  <AsideMinorContribute
43
- :fullContentId="contentData.fullContentId"
43
+ :contentId="contentData.contentId"
44
44
  v-model:pane="contributePaneVisible"
45
45
  />
46
46
  </AsideMinorPane>
@@ -18,7 +18,7 @@ watch(topicData, () => (contributePaneVisible.value = false));
18
18
  <TopicToc />
19
19
  <TopicContributors v-if="topicData.contributors" />
20
20
  <AsideMinorContribute
21
- :fullContentId="topicData.fullContentId"
21
+ :contentId="topicData.topicId"
22
22
  v-model:pane="contributePaneVisible"
23
23
  />
24
24
  </AsideMinorPane>
@@ -27,9 +27,9 @@ onMounted(() => {
27
27
  watch(
28
28
  topicData,
29
29
  () => {
30
- if (previousFullId === topicData.value.fullContentId) return;
30
+ if (previousFullId === topicData.value.topicId) return;
31
31
 
32
- previousFullId = topicData.value.fullContentId;
32
+ previousFullId = topicData.value.topicId;
33
33
  showcase.value = [...topicData.value.contributors!]
34
34
  .sort(() => 0.5 - Math.random())
35
35
  .slice(0, counter.value.showcase);
@@ -174,12 +174,7 @@ onMounted(() => {
174
174
 
175
175
  if (!topicData.value.location || !topicLocation.value) return;
176
176
 
177
- if (
178
- stringifyBitranLocation(topicData.value.location) ===
179
- stringifyBitranLocation(topicLocation.value)
180
- ) {
181
- enableLiveToc();
182
- }
177
+ enableLiveToc();
183
178
  },
184
179
  { immediate: true },
185
180
  );
@@ -6,6 +6,8 @@ const productName = props.tocItem.productName;
6
6
  const productIcon = await useBitranElementIcon(productName);
7
7
  const productPhrase = await useBitranElementLanguage(productName);
8
8
 
9
+ const pretty = useFormatText();
10
+
9
11
  function tocItemClick(event: MouseEvent): void {
10
12
  navigateTo({
11
13
  query: {
@@ -20,7 +22,7 @@ function tocItemClick(event: MouseEvent): void {
20
22
 
21
23
  <template>
22
24
  <TreeItem
23
- :label="tocItem.title || productPhrase('_element_title')"
25
+ :label="pretty(tocItem.title || productPhrase('_element_title'))"
24
26
  :level="tocItem.level"
25
27
  :link="`?element=${tocItem.id}`"
26
28
  :svg="productIcon"
@@ -13,7 +13,7 @@ function getIcon(contextIcon: string) {
13
13
 
14
14
  <template>
15
15
  <section :class="$style.breadcrumb">
16
- <template v-for="contextItem of context.slice(0, -1)">
16
+ <template v-for="contextItem of context.slice(0, -1).filter(item => !item.hidden)">
17
17
  <Link :to="contextItem.href" :class="$style.breadcrumbItem">
18
18
  <MyIcon :name="getIcon(contextItem.icon)" wrapper="span" />
19
19
  {{ contextItem.title }}
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { ContentReferences } from '@package';
2
+ import type { ContentReferences } from '@erudit-js/cog/schema';
3
3
 
4
4
  import ReferenceGroup from './reference/ReferenceGroup.vue';
5
5
 
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { ContentReferenceGroup } from '@package';
2
+ import type { ContentReferenceGroup } from '@erudit-js/cog/schema';
3
3
 
4
4
  import ReferenceSource from './ReferenceSource.vue';
5
5
  import ReferenceItem from './ReferenceItem.vue';
@@ -1,7 +1,9 @@
1
1
  <script lang="ts" setup>
2
- import type { ContentReferenceItem } from '@package';
2
+ import type { ContentReferenceItem } from '@erudit-js/cog/schema';
3
3
 
4
4
  defineProps<{ reference: ContentReferenceItem }>();
5
+
6
+ const pretty = useFormatText();
5
7
  </script>
6
8
 
7
9
  <template>
@@ -10,7 +12,7 @@ defineProps<{ reference: ContentReferenceItem }>();
10
12
  <div :class="$style.body">
11
13
  <div :class="$style.header">
12
14
  <a :href="reference.link" target="_blank">{{
13
- reference.title
15
+ pretty(reference.title)
14
16
  }}</a>
15
17
  <MyIcon
16
18
  v-if="reference.link"
@@ -19,7 +21,7 @@ defineProps<{ reference: ContentReferenceItem }>();
19
21
  />
20
22
  </div>
21
23
  <div v-if="reference.description" :class="$style.description">
22
- {{ reference.description }}
24
+ {{ pretty(reference.description) }}
23
25
  </div>
24
26
  </div>
25
27
  </div>
@@ -1,6 +1,7 @@
1
1
  <script lang="ts" setup>
2
+ import type { ContentReferenceSource } from '@erudit-js/cog/schema';
3
+
2
4
  import { type MyIconName } from '#my-icons';
3
- import type { ContentReferenceSource } from '@package';
4
5
 
5
6
  const props = defineProps<{ source: ContentReferenceSource }>();
6
7
 
@@ -15,6 +16,7 @@ const typeIcon = computed<MyIconName>(() => {
15
16
  }
16
17
  });
17
18
 
19
+ const pretty = useFormatText();
18
20
  const phrase = await usePhrases('reference_source_featured');
19
21
  </script>
20
22
 
@@ -26,7 +28,7 @@ const phrase = await usePhrases('reference_source_featured');
26
28
  <div :class="$style.body">
27
29
  <div :class="$style.header">
28
30
  <MyIcon :name="typeIcon" :class="$style.headerTypeIcon" />
29
- <a :href="source.link" target="_blank">{{ source.title }}</a>
31
+ <a :href="source.link" target="_blank">{{ pretty(source.title) }}</a>
30
32
  <MyIcon
31
33
  v-if="source.featured"
32
34
  name="star"
@@ -40,10 +42,10 @@ const phrase = await usePhrases('reference_source_featured');
40
42
  />
41
43
  </div>
42
44
  <div v-if="source.description" :class="$style.description">
43
- {{ source.description }}
45
+ {{ pretty(source.description) }}
44
46
  </div>
45
47
  <div v-if="source.comment" :class="$style.comment">
46
- {{ source.comment }}
48
+ {{ pretty(source.comment) }}
47
49
  </div>
48
50
  </div>
49
51
  </div>
@@ -5,7 +5,7 @@ import { buildPreviewData } from '@app/scripts/preview/build';
5
5
  import { getPreviewDisplayComponent } from '@app/scripts/preview/display';
6
6
  import { createPreviewError } from '@app/scripts/preview/data/alert';
7
7
 
8
- import { PreviewDisplayAlert } from '#components';
8
+ import { LazyPreviewDisplayAlert } from '#components';
9
9
 
10
10
  const { request } = defineProps<{ request: PreviewRequest }>();
11
11
  const height = defineModel<number>('height');
@@ -35,7 +35,7 @@ const setupDisplay = setTimeout(async () => {
35
35
  message: error?.message || error,
36
36
  });
37
37
 
38
- DisplayComponent.value = PreviewDisplayAlert;
38
+ DisplayComponent.value = LazyPreviewDisplayAlert;
39
39
  }
40
40
 
41
41
  await nextTick();
@@ -9,7 +9,7 @@ const phrase = await usePhrases('internal_link_warn');
9
9
 
10
10
  <template>
11
11
  <PreviewDisplay :footer="data.footer">
12
- <div :class="$style.wrapper">{{ phrase.internal_link_warn }}</div>
12
+ <div :class="$style.wrapper">{{ data.description || phrase.internal_link_warn }}</div>
13
13
  </PreviewDisplay>
14
14
  </template>
15
15
 
@@ -29,8 +29,7 @@ export async function useBitranContent(
29
29
  })();
30
30
  }
31
31
 
32
- const apiRoute = `/api/bitran/content/${encodeBitranLocation(stringifyBitranLocation(location.value!))}`;
33
- nuxtApp.runWithContext(() => prerenderRoutes(apiRoute));
32
+ const contentApiRoute = `/api/bitran/content/${encodeBitranLocation(stringifyBitranLocation(location.value!))}`;
34
33
 
35
34
  // @ts-ignore
36
35
  contentPromise = (async () => {
@@ -49,7 +48,7 @@ export async function useBitranContent(
49
48
  if (payload.location === locationString) {
50
49
  stringContent = payload;
51
50
  } else {
52
- stringContent = await $fetch(apiRoute, {
51
+ stringContent = await $fetch(contentApiRoute, {
53
52
  responseType: 'json',
54
53
  });
55
54
 
@@ -62,17 +62,16 @@ export function useContentPage(contentData: Ref<ContentData>) {
62
62
  contentData.value.generic.title ||
63
63
  contentData.value.generic.contentId.split('/').pop();
64
64
 
65
- if (contentData.value.type !== 'book') {
66
- const bookTitle = contentData.value?.bookTitle;
67
- title += bookTitle ? ` | ${bookTitle}` : '';
68
- }
69
-
70
65
  if (contentRoute.value!.type === 'topic') {
71
66
  const topicPart = contentRoute.value!.topicPart;
72
-
73
67
  if (topicPart !== 'article') title += ` | ${phrase[topicPart]}`;
74
68
  }
75
69
 
70
+ if (contentData.value.type !== 'book') {
71
+ const bookTitle = contentData.value?.bookTitle;
72
+ title += bookTitle ? ` | ${bookTitle}` : '';
73
+ }
74
+
76
75
  title +=
77
76
  ' - ' +
78
77
  (eruditConfig.seo?.title ||
@@ -91,7 +90,9 @@ export function useContentPage(contentData: Ref<ContentData>) {
91
90
  contentData.value.generic?.description;
92
91
 
93
92
  if (customDescription) {
94
- seo.description.value = customDescription;
93
+ seo.description.value = customDescription
94
+ .trim()
95
+ .replace(/\n/g, ' ');
95
96
  return;
96
97
  }
97
98
 
@@ -1,5 +1,16 @@
1
1
  import eruditConfig from '#erudit/config';
2
2
 
3
+ export interface FormatState {
4
+ quoteOpen: boolean;
5
+ }
6
+
7
+ const defaultFormatState: FormatState = {
8
+ quoteOpen: false,
9
+ };
10
+
11
+ export type FormatFunction = (text: string, state?: FormatState) => string;
12
+ export type FormatterFunction = (text: string, state: FormatState) => string;
13
+
3
14
  let formatFunction: FormatFunction;
4
15
 
5
16
  export function useFormatText() {
@@ -11,10 +22,8 @@ export function useFormatText() {
11
22
  return formatFunction;
12
23
  }
13
24
 
14
- type FormatFunction = (text: string) => string;
15
-
16
25
  function createFormatFunction(language?: string): FormatFunction {
17
- const formatters: FormatFunction[] = [];
26
+ const formatters: FormatterFunction[] = [];
18
27
 
19
28
  //
20
29
  // Em Dashes
@@ -36,10 +45,11 @@ function createFormatFunction(language?: string): FormatFunction {
36
45
  }
37
46
  })();
38
47
 
39
- formatters.push((text) => {
40
- let open = false;
48
+ formatters.push((text, state) => {
41
49
  return text.replaceAll(/"/gm, () => {
42
- return (open = !open) ? quoteSymbols[0] : quoteSymbols[1];
50
+ return (state.quoteOpen = !state.quoteOpen)
51
+ ? quoteSymbols[0]
52
+ : quoteSymbols[1];
43
53
  });
44
54
  });
45
55
  }
@@ -60,10 +70,13 @@ function createFormatFunction(language?: string): FormatFunction {
60
70
  //
61
71
  //
62
72
 
63
- function formatText(text: string): string {
73
+ function formatText(
74
+ text: string,
75
+ state: FormatState = defaultFormatState,
76
+ ): string {
64
77
  if (!text) return text;
65
78
 
66
- for (const formatter of formatters) text = formatter(text);
79
+ for (const formatter of formatters) text = formatter(text, state);
67
80
 
68
81
  return text;
69
82
  }
@@ -15,7 +15,6 @@ const functionPhrases: Record<string, Function> = {};
15
15
  const phraseApiRoute = (phraseId: EruditPhraseId) =>
16
16
  `/api/language/phrase/${phraseId}`;
17
17
  const functionsApiRoute = '/api/language/functions';
18
- const phraseIdsApiRoute = '/api/language/phraseIds';
19
18
 
20
19
  export function usePhrases<T extends EruditPhraseId[]>(
21
20
  ...phraseIds: T
@@ -26,11 +25,9 @@ export function usePhrases<T extends EruditPhraseId[]>(
26
25
  nuxt.payload.data[payloadKey] ||=
27
26
  {});
28
27
 
29
- const prerenderAllPromise = prerenderAllPhrases();
30
28
  const prepareFunctionsPromise = prepareFunctions(payload);
31
29
 
32
30
  return (async () => {
33
- await prerenderAllPromise;
34
31
  await prepareFunctionsPromise;
35
32
 
36
33
  payload.strPhrases ||= {};
@@ -58,19 +55,6 @@ export function usePhrases<T extends EruditPhraseId[]>(
58
55
  })();
59
56
  }
60
57
 
61
- async function prerenderAllPhrases() {
62
- if (import.meta.dev) return;
63
-
64
- if (import.meta.client) return;
65
-
66
- const nuxt = useNuxtApp();
67
-
68
- const phraseIds = await $fetch(phraseIdsApiRoute);
69
- nuxt.runWithContext(() =>
70
- prerenderRoutes(phraseIds.map((phraseId) => phraseApiRoute(phraseId))),
71
- );
72
- }
73
-
74
58
  async function prepareFunctions(payload: LanguagePayload) {
75
59
  if (payload?.strFunctions) return;
76
60
 
@@ -0,0 +1,22 @@
1
+ let alreadyPrerendered = false;
2
+ let isPrerendering = false;
3
+
4
+ export default defineNuxtPlugin({
5
+ name: 'erudit-prerender',
6
+ async setup(_nuxt) {
7
+ if (import.meta.dev) {
8
+ return; // Server is available so no need to prerender in dev mode
9
+ }
10
+
11
+ if (alreadyPrerendered || isPrerendering) {
12
+ return;
13
+ }
14
+
15
+ isPrerendering = true;
16
+
17
+ const routesToPrerender = await $fetch<string[]>('/api/prerender');
18
+ _nuxt.runWithContext(() => prerenderRoutes(routesToPrerender));
19
+
20
+ alreadyPrerendered = true;
21
+ },
22
+ });
@@ -1,4 +1,5 @@
1
1
  import { PreviewDataType, type PreviewData } from './data';
2
+ import { createPreviewError } from './data/alert';
2
3
  import { PreviewRequestType, type PreviewRequest } from './request';
3
4
  import { PreviewThemeName } from './state';
4
5
 
@@ -26,8 +27,6 @@ export async function buildPreviewData(
26
27
  'expected_page_hash',
27
28
  );
28
29
 
29
- const { createPreviewError } = await import('./data/alert');
30
-
31
30
  return createPreviewError({
32
31
  title: phrase.preview_missing_title,
33
32
  message: phrase.preview_missing_explain_mismatch,
@@ -40,8 +39,6 @@ export async function buildPreviewData(
40
39
  'element_id',
41
40
  );
42
41
 
43
- const { createPreviewError } = await import('./data/alert');
44
-
45
42
  return createPreviewError({
46
43
  title: phrase.preview_missing_title,
47
44
  message: phrase.preview_missing_explain,
@@ -72,7 +69,6 @@ export async function buildPreviewData(
72
69
  if (result) return result;
73
70
  }
74
71
 
75
- const { createPreviewError } = await import('./data/alert');
76
72
  throw createPreviewError({
77
73
  message: `Unable to build preview data for request!`,
78
74
  pre: JSON.stringify(request, null, 4),
@@ -5,6 +5,7 @@ import type { PreviewFooter } from '../footer';
5
5
  export interface PreviewDataPageLink extends PreviewDataBase {
6
6
  type: PreviewDataType.PageLink;
7
7
  footer: PreviewFooter;
8
+ description?: string;
8
9
  }
9
10
 
10
11
  export async function buildPageLink(
@@ -47,17 +47,3 @@ h5,
47
47
  h6 {
48
48
  overflow-wrap: break-word;
49
49
  }
50
-
51
- /* 8. Improve line wrapping */
52
- p {
53
- text-wrap: pretty;
54
- }
55
-
56
- h1,
57
- h2,
58
- h3,
59
- h4,
60
- h5,
61
- h6 {
62
- text-wrap: balance;
63
- }
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  BookConfig,
3
3
  ContentReferences,
4
+ ContentReferenceSource,
4
5
  GroupConfig,
5
6
  TopicConfig,
6
7
  } from '@erudit-js/cog/schema';
@@ -20,3 +21,7 @@ export function defineTopic(topic: Partial<TopicConfig>) {
20
21
  export function defineContentReferences(references: ContentReferences) {
21
22
  return references;
22
23
  }
24
+
25
+ export function defineContentSource(source: ContentReferenceSource) {
26
+ return source;
27
+ }
package/module/imports.ts CHANGED
@@ -27,6 +27,7 @@ export function setupGlobalImports() {
27
27
  'defineGroup',
28
28
  'defineTopic',
29
29
  'defineContentReferences',
30
+ 'defineContentSource',
30
31
  ];
31
32
  return imports.map((name) => ({
32
33
  name,
package/nuxt.config.ts CHANGED
@@ -53,16 +53,20 @@ export default defineNuxtConfig({
53
53
  projectPath(`contributors/${pattern}`),
54
54
  ),
55
55
  ],
56
- esbuild: {
57
- options: {
58
- charset: 'utf8',
59
- },
60
- },
61
56
  nitro: {
62
57
  preset: 'github-pages',
63
58
  plugins: [eruditPath('server/plugin')],
64
59
  prerender: {
60
+ crawlLinks: true,
65
61
  failOnError: false,
62
+ concurrency: 10,
63
+ ignore: [
64
+ (path: string) => {
65
+ const regexps = [/\?element=/gm, /#/gm, /\.json\?/gm];
66
+ const shouldIgnore = regexps.some((re) => re.test(path));
67
+ return shouldIgnore;
68
+ },
69
+ ],
66
70
  },
67
71
  output: {
68
72
  publicDir: projectPath('dist'),
@@ -94,6 +98,7 @@ export default defineNuxtConfig({
94
98
  ],
95
99
  esbuild: {
96
100
  options: {
101
+ charset: 'utf8',
97
102
  tsconfigRaw: {
98
103
  compilerOptions: {
99
104
  experimentalDecorators: true, // Make TypeORM work with Nuxt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "erudit",
3
- "version": "3.0.0-dev.11",
3
+ "version": "3.0.0-dev.13",
4
4
  "type": "module",
5
5
  "description": "🤓 CMS for perfect educational sites.",
6
6
  "license": "MIT",
@@ -15,14 +15,14 @@
15
15
  "erudit": "bin/erudit.mjs"
16
16
  },
17
17
  "peerDependencies": {
18
- "@erudit-js/cog": "3.0.0-dev.11",
19
- "@erudit-js/cli": "3.0.0-dev.11",
20
- "@erudit-js/bitran-elements": "3.0.0-dev.11"
18
+ "@erudit-js/cog": "3.0.0-dev.13",
19
+ "@erudit-js/cli": "3.0.0-dev.13",
20
+ "@erudit-js/bitran-elements": "3.0.0-dev.13"
21
21
  },
22
22
  "dependencies": {
23
- "@bitran-js/core": "1.0.0-dev.12",
24
- "@bitran-js/renderer-vue": "1.0.0-dev.12",
25
- "@bitran-js/transpiler": "1.0.0-dev.12",
23
+ "@bitran-js/core": "1.0.0-dev.13",
24
+ "@bitran-js/renderer-vue": "1.0.0-dev.13",
25
+ "@bitran-js/transpiler": "1.0.0-dev.13",
26
26
  "@floating-ui/vue": "^1.1.6",
27
27
  "chalk": "^5.4.1",
28
28
  "chokidar": "^4.0.3",
@@ -30,7 +30,7 @@
30
30
  "glob": "^11.0.1",
31
31
  "image-size": "^2.0.2",
32
32
  "jiti": "^2.4.2",
33
- "nuxt": "3.16.2",
33
+ "nuxt": "3.17.0",
34
34
  "nuxt-my-icons": "1.0.2",
35
35
  "sass": "^1.86.2",
36
36
  "sqlite3": "^5.1.7",
@@ -1,5 +1,5 @@
1
- import { ERUDIT_SERVER } from '@server/global';
1
+ import { getNavBookIds } from '@server/nav/utils';
2
2
 
3
3
  export default defineEventHandler(() => {
4
- return Object.keys(ERUDIT_SERVER.NAV_BOOKS || {});
4
+ return getNavBookIds('short');
5
5
  });