erudit 4.0.0-dev.3 → 4.0.0-dev.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.
@@ -0,0 +1,7 @@
1
+ <script lang="ts" setup>
2
+ const loadingSvg = useLoadingSvg();
3
+ </script>
4
+
5
+ <template>
6
+ <MyRuntimeIcon :svg="loadingSvg" />
7
+ </template>
@@ -10,6 +10,7 @@ const { element, storage, useHashUrl } = defineProps<{
10
10
  useHashUrl: boolean;
11
11
  }>();
12
12
 
13
+ const loadingSvg = useLoadingSvg();
13
14
  const route = useRoute();
14
15
 
15
16
  const hashUrl = computed(() => {
@@ -63,10 +63,7 @@ onUnmounted(() => {
63
63
  class="absolute top-0 left-0 grid h-full w-full
64
64
  place-items-center"
65
65
  >
66
- <MyRuntimeIcon
67
- :svg="loadingSvg"
68
- class="text-text-disabled text-[60px]"
69
- />
66
+ <Loading class="text-text-disabled text-[65px]" />
70
67
  </div>
71
68
  <div v-else></div>
72
69
  </template>
@@ -106,10 +106,10 @@ const pharse = await usePhrases('to_index', 'about_textbook');
106
106
  </div>
107
107
  <div
108
108
  v-else
109
- class="text-text-dimmed absolute top-0 left-0 flex h-full w-full
110
- items-center justify-center text-[50px] transition-opacity"
109
+ class="absolute top-0 left-0 flex h-full w-full items-center
110
+ justify-center transition-opacity"
111
111
  >
112
- <MyRuntimeIcon :svg="loadingSvg" />
112
+ <Loading class="text-text-dimmed text-[65px]" />
113
113
  </div>
114
114
  </TransitionFade>
115
115
  </AsideMajorPaneTemplate>
@@ -6,6 +6,8 @@ import SearchResult from './SearchResult.vue';
6
6
 
7
7
  const runtimeConfig = useRuntimeConfig();
8
8
 
9
+ const loadingSvg = useLoadingSvg();
10
+
9
11
  const phrase = await usePhrases(
10
12
  'no_results',
11
13
  'searching_more',
@@ -4,6 +4,7 @@ import { isContentType } from '@erudit-js/core/content/type';
4
4
  import type { MaybeMyIconName, MyIconName } from '#my-icons';
5
5
 
6
6
  const { result } = defineProps<{ result: SearchEntry }>();
7
+ const loadingSvg = useLoadingSvg();
7
8
 
8
9
  const ELEMENT_PREFIX = 'element:';
9
10
  const isElementCategory = result.category?.startsWith(ELEMENT_PREFIX);
@@ -33,6 +34,8 @@ watch(icon, () => {
33
34
  });
34
35
 
35
36
  async function requestElementIcon(elementName: string) {
37
+ icon.value = loadingSvg;
38
+
36
39
  try {
37
40
  icon.value = await getElementIcon(elementName);
38
41
  } catch {
@@ -1,6 +1,8 @@
1
1
  <script lang="ts" setup>
2
2
  import type { MaybeMyIconName } from '#my-icons';
3
3
 
4
+ const loadingSvg = useLoadingSvg();
5
+
4
6
  const icon = ref<MaybeMyIconName>(loadingSvg);
5
7
  const themeName = ref<string>();
6
8
 
@@ -66,18 +66,21 @@ const phrase = await usePhrases(
66
66
  icon="question-circle"
67
67
  :main="phrase.how_to_improve"
68
68
  :to="howToImproveLink"
69
+ target="_blank"
69
70
  />
70
71
  <AsideListItem
71
72
  v-if="reportIssueLink"
72
73
  icon="bug"
73
74
  :main="phrase.report_issue"
74
75
  :to="reportIssueLink"
76
+ target="_blank"
75
77
  />
76
78
  <AsideListItem
77
79
  v-if="editLink"
78
80
  icon="draw"
79
81
  :main="phrase.edit_page"
80
82
  :to="editLink"
83
+ target="_blank"
81
84
  />
82
85
  </div>
83
86
  <div
@@ -122,7 +122,7 @@ const phrase = await usePhrases('news', 'no_news', 'show_more');
122
122
  w-auto cursor-pointer items-center rounded border-2
123
123
  border-transparent text-sm transition-[border]"
124
124
  >
125
- <MyRuntimeIcon v-if="newsLoading" :svg="loadingSvg" />
125
+ <Loading v-if="newsLoading" />
126
126
  <span>{{ phrase.show_more }}</span>
127
127
  </button>
128
128
  </TransitionFade>
@@ -1,13 +1,19 @@
1
1
  <script lang="ts" setup>
2
2
  import type { MaybeMyIconName } from '#my-icons';
3
3
 
4
- defineProps<{ icon: MaybeMyIconName; label: string; link: string }>();
4
+ defineProps<{
5
+ icon: MaybeMyIconName;
6
+ label: string;
7
+ link: string;
8
+ newTab?: boolean;
9
+ }>();
5
10
  </script>
6
11
 
7
12
  <template>
8
13
  <section class="px-main py-main-half clear-both grid place-items-center">
9
14
  <EruditLink
10
15
  :to="link"
16
+ :target="newTab ? '_blank' : undefined"
11
17
  class="bg-brand gap-small micro:gap-normal px-normal text-main-lg
12
18
  shadow-brand/30 micro:h-[55px] hocus:bg-brand/80 flex h-[50px]
13
19
  items-center rounded font-bold text-white shadow-lg
@@ -4,11 +4,13 @@ import type { MaybeMyIconName, MyIconName } from '#my-icons';
4
4
 
5
5
  const { quote } = defineProps<{
6
6
  quote: Quote;
7
- hasBecomeLink?: boolean;
7
+ canJoin?: boolean;
8
8
  hasNextLink?: boolean;
9
9
  }>();
10
10
  const emit = defineEmits(['next']);
11
11
 
12
+ const loadingSvg = useLoadingSvg();
13
+
12
14
  const color = quote.color ?? stringColor(quote.name);
13
15
 
14
16
  const message = (() => {
@@ -126,12 +128,12 @@ const phrase = await usePhrases('add_quote', 'next_quote');
126
128
  />
127
129
  </div>
128
130
  <div
129
- v-if="hasBecomeLink || hasNextLink"
131
+ v-if="canJoin || hasNextLink"
130
132
  class="gap-normal micro:text-[1.5em] flex items-center
131
133
  text-[1.2em]"
132
134
  >
133
135
  <EruditLink
134
- v-if="hasBecomeLink"
136
+ v-if="canJoin"
135
137
  :to="PAGES.sponsors"
136
138
  :title="phrase.add_quote"
137
139
  class="hocus:text-(--colorIcon)
@@ -78,7 +78,7 @@ onMounted(() => {
78
78
  <section v-if="quote" :key="quoteKey" class="px-main py-main-half">
79
79
  <MainQuote
80
80
  :quote
81
- :hasBecomeLink="true"
81
+ :canJoin="ERUDIT.config.project.sponsors?.enabled"
82
82
  :hasNextLink="hasMultipleQuotes"
83
83
  @next="!loadingQuote && nextQuote()"
84
84
  />
@@ -114,12 +114,12 @@ await usePhrases(
114
114
  <div
115
115
  ref="preview"
116
116
  :class="[
117
- `border-border bg-bg-main micro:max-h-[70dvh]
118
- pointer-events-auto absolute bottom-0 max-h-[90dvh] w-full
119
- touch-auto overflow-hidden rounded-[25px] rounded-b-none
120
- border-t transition-[max-height,height,translate]`,
117
+ `bg-bg-main micro:max-h-[70dvh] pointer-events-auto absolute
118
+ bottom-0 max-h-[90dvh] w-full touch-auto overflow-hidden
119
+ rounded-[25px] rounded-b-none
120
+ transition-[max-height,height,translate]`,
121
121
  previewState.opened
122
- ? `translate-y-0
122
+ ? `border-border translate-y-0 border-t
123
123
  shadow-[0px_-10px_15px_5px_light-dark(rgba(0,0,0,0.1),rgba(255,255,255,0.05))]`
124
124
  : 'translate-y-full shadow-none',
125
125
  ]"
@@ -145,10 +145,7 @@ await usePhrases(
145
145
  class="bg-bg-main absolute bottom-0 flex h-full w-full
146
146
  items-center justify-center"
147
147
  >
148
- <MyRuntimeIcon
149
- :svg="loadingSvg"
150
- class="text-text-dimmed text-[50px]"
151
- />
148
+ <Loading class="text-text-dimmed text-[50px]" />
152
149
  </div>
153
150
  </TransitionFade>
154
151
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
2
  <div class="flex h-[230px] items-center justify-center">
3
- <MyRuntimeIcon :svg="loadingSvg" class="text-text-dimmed text-[50px]" />
3
+ <Loading class="text-text-dimmed text-[50px]" />
4
4
  </div>
5
5
  </template>
@@ -1,2 +1,26 @@
1
- export const loadingSvg =
2
- '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect width="10" height="10" x="1" y="1" fill="currentColor" rx="1"><animate id="svgSpinnersBlocksShuffle30" fill="freeze" attributeName="x" begin="0;svgSpinnersBlocksShuffle3b.end" dur="0.2s" values="1;13"/><animate id="svgSpinnersBlocksShuffle31" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle38.end" dur="0.2s" values="1;13"/><animate id="svgSpinnersBlocksShuffle32" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle39.end" dur="0.2s" values="13;1"/><animate id="svgSpinnersBlocksShuffle33" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle3a.end" dur="0.2s" values="13;1"/></rect><rect width="10" height="10" x="1" y="13" fill="currentColor" rx="1"><animate id="svgSpinnersBlocksShuffle34" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle30.end" dur="0.2s" values="13;1"/><animate id="svgSpinnersBlocksShuffle35" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle31.end" dur="0.2s" values="1;13"/><animate id="svgSpinnersBlocksShuffle36" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle32.end" dur="0.2s" values="1;13"/><animate id="svgSpinnersBlocksShuffle37" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle33.end" dur="0.2s" values="13;1"/></rect><rect width="10" height="10" x="13" y="13" fill="currentColor" rx="1"><animate id="svgSpinnersBlocksShuffle38" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle34.end" dur="0.2s" values="13;1"/><animate id="svgSpinnersBlocksShuffle39" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle35.end" dur="0.2s" values="13;1"/><animate id="svgSpinnersBlocksShuffle3a" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle36.end" dur="0.2s" values="1;13"/><animate id="svgSpinnersBlocksShuffle3b" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle37.end" dur="0.2s" values="1;13"/></rect></svg>';
1
+ const defaultLoadingSvg = `
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
3
+ <rect width="10" height="10" x="1" y="1" fill="currentColor" rx="1">
4
+ <animate id="svgSpinnersBlocksShuffle30" fill="freeze" attributeName="x" begin="0;svgSpinnersBlocksShuffle3b.end" dur="0.2s" values="1;13"/>
5
+ <animate id="svgSpinnersBlocksShuffle31" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle38.end" dur="0.2s" values="1;13"/>
6
+ <animate id="svgSpinnersBlocksShuffle32" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle39.end" dur="0.2s" values="13;1"/>
7
+ <animate id="svgSpinnersBlocksShuffle33" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle3a.end" dur="0.2s" values="13;1"/>
8
+ </rect>
9
+ <rect width="10" height="10" x="1" y="13" fill="currentColor" rx="1">
10
+ <animate id="svgSpinnersBlocksShuffle34" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle30.end" dur="0.2s" values="13;1"/>
11
+ <animate id="svgSpinnersBlocksShuffle35" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle31.end" dur="0.2s" values="1;13"/>
12
+ <animate id="svgSpinnersBlocksShuffle36" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle32.end" dur="0.2s" values="1;13"/>
13
+ <animate id="svgSpinnersBlocksShuffle37" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle33.end" dur="0.2s" values="13;1"/>
14
+ </rect>
15
+ <rect width="10" height="10" x="13" y="13" fill="currentColor" rx="1">
16
+ <animate id="svgSpinnersBlocksShuffle38" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle34.end" dur="0.2s" values="13;1"/>
17
+ <animate id="svgSpinnersBlocksShuffle39" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle35.end" dur="0.2s" values="13;1"/>
18
+ <animate id="svgSpinnersBlocksShuffle3a" fill="freeze" attributeName="x" begin="svgSpinnersBlocksShuffle36.end" dur="0.2s" values="1;13"/>
19
+ <animate id="svgSpinnersBlocksShuffle3b" fill="freeze" attributeName="y" begin="svgSpinnersBlocksShuffle37.end" dur="0.2s" values="1;13"/>
20
+ </rect>
21
+ </svg>
22
+ `;
23
+
24
+ export function useLoadingSvg() {
25
+ return ERUDIT.config.project.siteInfo.loadingSvg || defaultLoadingSvg;
26
+ }
@@ -45,8 +45,11 @@ useStandartSeo({
45
45
  <div class="h-main-half"></div>
46
46
  <MainAction
47
47
  icon="users"
48
+ :newTab="true"
48
49
  :label="phrase.become_contributor"
49
- :link="'https://google.com'"
50
+ :link="
51
+ ERUDIT.config.project.contributors!.becomeContributorLink
52
+ "
50
53
  />
51
54
  <div class="h-main-half"></div>
52
55
  </template>
@@ -33,6 +33,7 @@ useStandartSeo({
33
33
  <div class="h-main-half"></div>
34
34
  <MainAction
35
35
  icon="diamond"
36
+ :newTab="true"
36
37
  :label="phrase.become_sponsor"
37
38
  :link="ERUDIT.config.project.sponsors!.becomeSponsorLink"
38
39
  />
@@ -68,6 +68,7 @@ async function transferConfigData(
68
68
  ? { default: projectConfig.site?.favicon }
69
69
  : projectConfig.site?.favicon
70
70
  : undefined,
71
+ loadingSvg: projectConfig.site?.loadingSvg,
71
72
  },
72
73
  seo: projectConfig.seo,
73
74
  debug: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "erudit",
3
- "version": "4.0.0-dev.3",
3
+ "version": "4.0.0-dev.4",
4
4
  "type": "module",
5
5
  "description": "🤓 CMS for perfect educational sites.",
6
6
  "license": "MIT",
@@ -29,9 +29,9 @@
29
29
  "test": "bun vitest run"
30
30
  },
31
31
  "dependencies": {
32
- "@erudit-js/cli": "4.0.0-dev.3",
33
- "@erudit-js/core": "4.0.0-dev.3",
34
- "@erudit-js/prose": "4.0.0-dev.3",
32
+ "@erudit-js/cli": "4.0.0-dev.4",
33
+ "@erudit-js/core": "4.0.0-dev.4",
34
+ "@erudit-js/prose": "4.0.0-dev.4",
35
35
  "@floating-ui/vue": "^1.1.9",
36
36
  "@jsprose/core": "^1.0.0",
37
37
  "@tailwindcss/vite": "^4.1.17",
@@ -7,7 +7,7 @@ import {
7
7
  searchIndexSnippets,
8
8
  } from '@erudit/server/content/search';
9
9
 
10
- export default defineEventHandler(async () => {
10
+ export default defineEventHandler(async (event) => {
11
11
  const entryLists: SearchEntriesList[] = [
12
12
  await searchIndexContributors(),
13
13
  ...(await searchIndexContentTypes()),
@@ -69,5 +69,7 @@ export default defineEventHandler(async () => {
69
69
 
70
70
  const gzipped = await zip(JSON.stringify(exported));
71
71
 
72
+ setHeader(event, 'Content-Type', 'application/gzip');
73
+
72
74
  return gzipped;
73
75
  });
@@ -40,6 +40,7 @@ export interface EruditPublicRuntimeConfig {
40
40
  short?: string | false;
41
41
  logotype?: string | false;
42
42
  favicon?: EruditSiteFaviconResolved;
43
+ loadingSvg?: string;
43
44
  };
44
45
  seo?: EruditSeo;
45
46
  debug: {