erudit 4.0.0-dev.5 → 4.0.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/app.vue +34 -34
- package/app/assets/icons/array-check.svg +2 -2
- package/app/assets/icons/array-lines.svg +2 -2
- package/app/assets/icons/array-star.svg +2 -2
- package/app/assets/icons/arrow/from-circle.svg +2 -2
- package/app/assets/icons/arrow/left.svg +2 -2
- package/app/assets/icons/arrow/outward.svg +2 -2
- package/app/assets/icons/arrow/to-circle.svg +2 -2
- package/app/assets/icons/arrow/up-to-right.svg +2 -2
- package/app/assets/icons/aside-open.svg +2 -2
- package/app/assets/icons/asterisk.svg +2 -2
- package/app/assets/icons/book-question.svg +2 -2
- package/app/assets/icons/construction.svg +2 -2
- package/app/assets/icons/draw.svg +2 -2
- package/app/assets/icons/erudit.svg +2 -2
- package/app/assets/icons/file-lines.svg +2 -2
- package/app/assets/icons/files.svg +2 -2
- package/app/assets/icons/folder-open.svg +2 -2
- package/app/assets/icons/folder.svg +2 -2
- package/app/assets/icons/graduation.svg +2 -2
- package/app/assets/icons/handshake.svg +2 -2
- package/app/assets/icons/lines.svg +2 -2
- package/app/assets/icons/plus-circle.svg +2 -2
- package/app/assets/icons/puzzle.svg +2 -2
- package/app/assets/icons/rocket.svg +2 -2
- package/app/assets/icons/search/check.svg +2 -2
- package/app/assets/icons/search/dead.svg +2 -2
- package/app/assets/icons/search/glass.svg +2 -2
- package/app/assets/icons/search/wtf.svg +2 -2
- package/app/assets/icons/sun-moon.svg +2 -2
- package/app/assets/icons/translate.svg +2 -2
- package/app/assets/icons/warning.svg +2 -2
- package/app/components/EruditLink.ts +9 -9
- package/app/components/FancyBold.vue +16 -16
- package/app/components/FancyCard.vue +52 -52
- package/app/components/FancyCardTag.vue +16 -16
- package/app/components/Loading.vue +7 -7
- package/app/components/Prose.vue +55 -55
- package/app/components/ScrollHolder.vue +20 -20
- package/app/components/SmartMedia.vue +107 -107
- package/app/components/ads/Ads.vue +39 -39
- package/app/components/ads/AdsBannerAside.vue +45 -45
- package/app/components/ads/AdsBannerBottom.vue +17 -17
- package/app/components/ads/AdsReplacer.vue +26 -26
- package/app/components/ads/provider/Custom.vue +19 -19
- package/app/components/ads/provider/Yandex.vue +84 -84
- package/app/components/aside/AsideListItem.vue +61 -61
- package/app/components/aside/AsideMajor.vue +8 -8
- package/app/components/aside/AsideMinor.vue +68 -68
- package/app/components/aside/AsidePlainMessage.vue +9 -9
- package/app/components/aside/AsideSwitch.vue +76 -76
- package/app/components/aside/major/PaneHolder.vue +106 -106
- package/app/components/aside/major/PaneSwitcher.vue +68 -68
- package/app/components/aside/major/PaneSwitcherButton.vue +38 -38
- package/app/components/aside/major/PaneTemplate.vue +5 -5
- package/app/components/aside/major/SiteInfo.vue +66 -66
- package/app/components/aside/major/contentNav/PaneBookNav.vue +107 -107
- package/app/components/aside/major/contentNav/PaneGlobalNav.vue +19 -19
- package/app/components/aside/major/contentNav/items/ContentNavBook.vue +21 -21
- package/app/components/aside/major/contentNav/items/ContentNavFolder.vue +91 -91
- package/app/components/aside/major/contentNav/items/ContentNavItem.vue +33 -33
- package/app/components/aside/major/contentNav/items/ContentNavPage.vue +14 -14
- package/app/components/aside/major/contentNav/items/ContentNavSeparator.vue +61 -61
- package/app/components/aside/major/contentNav/items/ContentNavTopic.vue +18 -18
- package/app/components/aside/major/contentNav/items/Flags.vue +50 -50
- package/app/components/aside/major/contentNav/items/ItemTemplate.vue +27 -27
- package/app/components/aside/major/languages/PaneLanguages.vue +55 -55
- package/app/components/aside/major/pages/PanePages.vue +60 -60
- package/app/components/aside/major/search/PaneSearch.vue +156 -156
- package/app/components/aside/major/search/SearchInput.vue +103 -103
- package/app/components/aside/major/search/SearchResult.vue +154 -154
- package/app/components/aside/major/search/SearchStatus.vue +48 -48
- package/app/components/aside/major/search/search.worker.ts +164 -164
- package/app/components/aside/major/settings/BuildTime.vue +25 -25
- package/app/components/aside/major/settings/EngineVersion.vue +14 -14
- package/app/components/aside/major/settings/PaneSettings.vue +17 -17
- package/app/components/aside/major/settings/ThemeSwitcher.vue +55 -55
- package/app/components/aside/major/settings/repository/Repository.vue +33 -33
- package/app/components/aside/major/settings/repository/SecondaryGitHub.vue +71 -71
- package/app/components/aside/minor/AsideMinorPane.vue +5 -5
- package/app/components/aside/minor/AsideMinorPlainHeader.vue +20 -20
- package/app/components/aside/minor/content/AsideMinorContentContributions.vue +47 -47
- package/app/components/aside/minor/content/AsideMinorContentPage.vue +37 -37
- package/app/components/aside/minor/content/AsideMinorContentTopic.vue +61 -61
- package/app/components/aside/minor/content/ButtonPaneContributions.vue +101 -101
- package/app/components/aside/minor/content/ButtonPaneImprove.vue +112 -112
- package/app/components/aside/minor/content/Contribution.vue +36 -36
- package/app/components/aside/minor/content/Toc.vue +163 -163
- package/app/components/aside/minor/content/TocItem.vue +91 -91
- package/app/components/aside/minor/content/TopicPartButton.vue +35 -35
- package/app/components/aside/minor/contributor/AsideMinorContributor.vue +36 -36
- package/app/components/aside/minor/contributor/ItemBook.vue +33 -33
- package/app/components/aside/minor/contributor/ItemContent.vue +17 -17
- package/app/components/aside/minor/news/AsideMinorNews.vue +132 -132
- package/app/components/aside/minor/news/NewsItem.vue +69 -69
- package/app/components/aside/minor/news/RenderNewsElement.vue +42 -42
- package/app/components/aside/minor/news/elements/Mix.vue +11 -11
- package/app/components/aside/minor/news/elements/P.vue +14 -14
- package/app/components/aside/minor/news/elements/Ref.vue +59 -59
- package/app/components/aside/minor/news/elements/Text.vue +18 -18
- package/app/components/indexPage/IndexPagePersons.vue +116 -116
- package/app/components/main/MainAction.vue +26 -26
- package/app/components/main/MainBreadcrumbs.vue +28 -28
- package/app/components/main/MainContentChild.vue +44 -44
- package/app/components/main/MainContentChildren.vue +13 -13
- package/app/components/main/MainDecoration.vue +15 -15
- package/app/components/main/MainDescription.vue +13 -13
- package/app/components/main/MainFlag.vue +129 -129
- package/app/components/main/MainFlags.vue +17 -17
- package/app/components/main/MainGlow.vue +12 -12
- package/app/components/main/MainQuickLink.vue +90 -90
- package/app/components/main/MainQuickLinks.vue +40 -40
- package/app/components/main/MainQuote.vue +149 -149
- package/app/components/main/MainQuoteLoader.vue +86 -86
- package/app/components/main/MainSection.vue +44 -44
- package/app/components/main/MainSectionPreamble.vue +5 -5
- package/app/components/main/MainSubTitle.vue +11 -11
- package/app/components/main/MainTitle.vue +32 -32
- package/app/components/main/MainTopicPartPage.vue +88 -88
- package/app/components/main/MainTopicPartSwitch.vue +67 -67
- package/app/components/main/connections/Deps.vue +30 -30
- package/app/components/main/connections/Externals.vue +80 -80
- package/app/components/main/connections/MainConnections.vue +90 -90
- package/app/components/main/connections/MainConnectionsButton.vue +81 -81
- package/app/components/main/connections/ScrollPane.vue +10 -10
- package/app/components/main/contentStats/Item.vue +28 -28
- package/app/components/main/contentStats/ItemElement.vue +19 -19
- package/app/components/main/contentStats/ItemMaterials.vue +11 -11
- package/app/components/main/contentStats/MainContentStats.vue +50 -50
- package/app/components/preview/Preview.vue +161 -161
- package/app/components/preview/PreviewError.vue +10 -10
- package/app/components/preview/PreviewLoading.vue +5 -5
- package/app/components/preview/PreviewScreen.vue +64 -64
- package/app/components/preview/PreviewScreenButton.vue +39 -39
- package/app/components/preview/screen/ContentPage.vue +47 -47
- package/app/components/preview/screen/DirectLink.vue +23 -23
- package/app/components/preview/screen/Unique.vue +53 -53
- package/app/components/site/SiteAside.vue +67 -67
- package/app/components/site/SiteAsideOverlay.vue +21 -21
- package/app/components/site/SiteMain.vue +13 -13
- package/app/components/transition/Fade.vue +30 -30
- package/app/components/transition/Slide.vue +47 -47
- package/app/components/tree/TreeContainer.vue +5 -5
- package/app/components/tree/TreeItem.vue +36 -36
- package/app/composables/ads.ts +23 -23
- package/app/composables/analytics.ts +102 -102
- package/app/composables/appElements.ts +40 -40
- package/app/composables/aside.ts +28 -28
- package/app/composables/asideMajorPane.ts +135 -135
- package/app/composables/asideMinor.ts +109 -109
- package/app/composables/contentNav.ts +7 -7
- package/app/composables/favicon.ts +103 -103
- package/app/composables/file.ts +4 -4
- package/app/composables/formatText.ts +100 -100
- package/app/composables/loading.ts +26 -26
- package/app/composables/mainContent.ts +31 -31
- package/app/composables/og.ts +184 -184
- package/app/composables/phrases.ts +126 -126
- package/app/composables/preview.ts +53 -53
- package/app/composables/route.ts +6 -6
- package/app/composables/theme.ts +67 -67
- package/app/composables/url.ts +30 -30
- package/app/formatters/ru.ts +14 -14
- package/app/pages/article/[...articleId].vue +12 -12
- package/app/pages/book/[...bookId].vue +56 -56
- package/app/pages/contributor/[contributorId].vue +144 -144
- package/app/pages/contributors.vue +95 -95
- package/app/pages/group/[...groupId].vue +58 -58
- package/app/pages/index.vue +113 -113
- package/app/pages/page/[...pageId].vue +60 -60
- package/app/pages/practice/[...practiceId].vue +12 -12
- package/app/pages/sponsors.vue +88 -88
- package/app/pages/summary/[...summaryId].vue +12 -12
- package/app/plugins/appSetup/client/htmlBranding.ts +6 -6
- package/app/plugins/appSetup/client/welcome.ts +37 -37
- package/app/plugins/appSetup/config.ts +6 -6
- package/app/plugins/appSetup/global.ts +3 -3
- package/app/plugins/appSetup/index.ts +27 -27
- package/app/plugins/prerender.server.ts +40 -40
- package/app/router.options.ts +5 -5
- package/app/scripts/theme.js +30 -30
- package/app/styles/main.css +176 -176
- package/bin/erudit.js +12 -12
- package/modules/erudit/env.ts +8 -8
- package/modules/erudit/globals/content.ts +4 -4
- package/modules/erudit/globals/contributor.ts +1 -1
- package/modules/erudit/globals/eruditConfig.ts +5 -5
- package/modules/erudit/globals/problem.ts +1 -1
- package/modules/erudit/globals/prose.ts +5 -1
- package/modules/erudit/globals/public.ts +18 -18
- package/modules/erudit/index.ts +50 -50
- package/modules/erudit/logger.ts +10 -10
- package/modules/erudit/setup/elements/appTemplate.ts +44 -44
- package/modules/erudit/setup/elements/globalTemplate.ts +82 -82
- package/modules/erudit/setup/elements/globalTypes.ts +259 -259
- package/modules/erudit/setup/elements/setup.ts +163 -163
- package/modules/erudit/setup/elements/shared.ts +10 -10
- package/modules/erudit/setup/elements/tagsTable.ts +28 -28
- package/modules/erudit/setup/fullRestart.ts +61 -61
- package/modules/erudit/setup/globals.ts +210 -206
- package/modules/erudit/setup/publicAssets.ts +43 -43
- package/modules/erudit/setup/runtimeConfig.ts +106 -106
- package/modules/erudit/watcher.ts +20 -20
- package/nuxt.config.ts +102 -102
- package/package.json +5 -5
- package/proxy/prose.app.ts +1 -1
- package/proxy/prose.ts +1 -1
- package/server/api/aside/major/frontNav/book/[...shortId].ts +10 -10
- package/server/api/aside/major/frontNav/global.ts +5 -5
- package/server/api/aside/major/pages.ts +6 -6
- package/server/api/contributor/list.ts +60 -60
- package/server/api/contributor/page/[contributorId].ts +68 -68
- package/server/api/indexPage.ts +81 -81
- package/server/api/language/functions.ts +11 -11
- package/server/api/language/phrase/[phraseKey].ts +35 -35
- package/server/api/main/content/[...contentTypePath].ts +149 -149
- package/server/api/news/batch/[batchIndex].ts +5 -5
- package/server/api/pageSponsors.ts +56 -56
- package/server/api/prerender/content.ts +79 -79
- package/server/api/prerender/default.ts +35 -35
- package/server/api/prerender/files.ts +10 -10
- package/server/api/prerender/frontNav.ts +13 -13
- package/server/api/prerender/language.ts +7 -7
- package/server/api/prerender/news.ts +8 -8
- package/server/api/prerender/quotes.ts +15 -15
- package/server/api/preview/contentPage/[...contentTypePath].ts +63 -63
- package/server/api/preview/contentUnique/[...contentTypePathUnique].ts +73 -73
- package/server/api/problemScript/[...problemScriptPath].ts +88 -88
- package/server/api/quote/data/[quoteId].ts +84 -84
- package/server/api/quote/ids.ts +3 -3
- package/server/erudit/build.ts +132 -132
- package/server/erudit/cameos/build.ts +161 -161
- package/server/erudit/config.ts +13 -13
- package/server/erudit/content/global/build.ts +300 -300
- package/server/erudit/content/global/singleton.ts +5 -5
- package/server/erudit/content/nav/build.ts +459 -459
- package/server/erudit/content/nav/front.ts +125 -125
- package/server/erudit/content/nav/repository/books.ts +37 -37
- package/server/erudit/content/nav/repository/get.ts +33 -33
- package/server/erudit/content/nav/repository/hasChildren.ts +5 -5
- package/server/erudit/content/nav/repository/hasNav.ts +3 -3
- package/server/erudit/content/nav/repository/hasParent.ts +5 -5
- package/server/erudit/content/nav/repository/id.ts +9 -9
- package/server/erudit/content/nav/repository/index.ts +9 -9
- package/server/erudit/content/nav/repository/order.ts +14 -14
- package/server/erudit/content/nav/repository/previousNext.ts +35 -35
- package/server/erudit/content/nav/repository/walk.ts +127 -127
- package/server/erudit/content/nav/setup.ts +13 -13
- package/server/erudit/content/nav/types.ts +24 -24
- package/server/erudit/content/repository/breadcrumbs.ts +24 -24
- package/server/erudit/content/repository/children.ts +47 -47
- package/server/erudit/content/repository/connections.ts +35 -35
- package/server/erudit/content/repository/contentLink.ts +16 -16
- package/server/erudit/content/repository/decoration.ts +23 -23
- package/server/erudit/content/repository/deps.ts +121 -121
- package/server/erudit/content/repository/description.ts +11 -11
- package/server/erudit/content/repository/elementSnippets.ts +105 -105
- package/server/erudit/content/repository/externals.ts +50 -50
- package/server/erudit/content/repository/flags.ts +33 -33
- package/server/erudit/content/repository/seo.ts +12 -12
- package/server/erudit/content/repository/stats.ts +97 -97
- package/server/erudit/content/repository/title.ts +27 -27
- package/server/erudit/content/repository/topicParts.ts +39 -39
- package/server/erudit/content/repository/unique.ts +76 -76
- package/server/erudit/content/resolve/book.ts +29 -29
- package/server/erudit/content/resolve/group.ts +34 -34
- package/server/erudit/content/resolve/index.ts +272 -272
- package/server/erudit/content/resolve/page.ts +80 -80
- package/server/erudit/content/resolve/topic.ts +220 -220
- package/server/erudit/content/resolve/utils/contentError.ts +10 -10
- package/server/erudit/content/resolve/utils/insertContentItem.ts +113 -113
- package/server/erudit/content/resolve/utils/insertContentResolved.ts +126 -126
- package/server/erudit/content/search.ts +146 -146
- package/server/erudit/contributors/build.ts +158 -158
- package/server/erudit/contributors/global.ts +3 -3
- package/server/erudit/contributors/repository/avatarUrl.ts +10 -10
- package/server/erudit/contributors/repository/contributions.ts +171 -171
- package/server/erudit/contributors/repository/count.ts +3 -3
- package/server/erudit/contributors/search.ts +34 -34
- package/server/erudit/db/repository/pushFile.ts +23 -23
- package/server/erudit/db/repository/pushProblemScript.ts +19 -19
- package/server/erudit/db/repository/pushProseLink.ts +40 -40
- package/server/erudit/db/schema/cameos.ts +7 -7
- package/server/erudit/db/schema/content.ts +18 -18
- package/server/erudit/db/schema/contentContributions.ts +15 -15
- package/server/erudit/db/schema/contentDeps.ts +21 -21
- package/server/erudit/db/schema/contentElementStats.ts +20 -20
- package/server/erudit/db/schema/contentProseLinks.ts +23 -23
- package/server/erudit/db/schema/contentSnippets.ts +15 -15
- package/server/erudit/db/schema/contentToc.ts +16 -16
- package/server/erudit/db/schema/contentUniques.ts +19 -19
- package/server/erudit/db/schema/contributors.ts +12 -12
- package/server/erudit/db/schema/files.ts +11 -11
- package/server/erudit/db/schema/groups.ts +6 -6
- package/server/erudit/db/schema/index.ts +17 -17
- package/server/erudit/db/schema/news.ts +7 -7
- package/server/erudit/db/schema/pages.ts +7 -7
- package/server/erudit/db/schema/problemScripts.ts +14 -14
- package/server/erudit/db/schema/sponsors.ts +9 -9
- package/server/erudit/db/schema/topics.ts +9 -9
- package/server/erudit/db/setup.ts +62 -62
- package/server/erudit/db/types.ts +10 -10
- package/server/erudit/global.ts +38 -38
- package/server/erudit/importer.ts +94 -94
- package/server/erudit/index.ts +96 -96
- package/server/erudit/language/list/en.ts +116 -116
- package/server/erudit/language/list/ru.ts +120 -120
- package/server/erudit/language/list.ts +6 -6
- package/server/erudit/language/setup.ts +36 -36
- package/server/erudit/language/types.ts +16 -16
- package/server/erudit/logger.ts +73 -73
- package/server/erudit/news/build.ts +112 -112
- package/server/erudit/news/repository/batch.ts +61 -61
- package/server/erudit/path.ts +19 -19
- package/server/erudit/prose/repository/finalize.ts +68 -68
- package/server/erudit/prose/repository/get.ts +54 -54
- package/server/erudit/prose/repository/resolve.ts +17 -17
- package/server/erudit/prose/storage/callout.ts +16 -16
- package/server/erudit/prose/storage/image.ts +22 -22
- package/server/erudit/prose/storage/link.ts +222 -222
- package/server/erudit/prose/storage/problemScript.ts +23 -23
- package/server/erudit/prose/storage/video.ts +16 -16
- package/server/erudit/prose/transform/bundleProblemScript.ts +6 -6
- package/server/erudit/prose/transform/extensions.ts +15 -15
- package/server/erudit/quote/repository/ids.ts +31 -31
- package/server/erudit/repository.ts +96 -96
- package/server/erudit/sponsors/build.ts +161 -161
- package/server/erudit/sponsors/repository/avatarUrl.ts +10 -10
- package/server/erudit/sponsors/repository/count.ts +4 -4
- package/server/erudit/staticFile.ts +28 -28
- package/server/plugins/augmentCss.ts +17 -17
- package/server/plugins/lang.ts +5 -5
- package/server/plugins/metaViewport.ts +15 -15
- package/server/plugins/theme.ts +13 -13
- package/server/routes/file/[...path].ts +18 -18
- package/server/routes/robots.txt.ts +9 -9
- package/server/routes/search.json.gz.ts +76 -76
- package/server/routes/sitemap.xml.ts +83 -83
- package/shared/search/encoders.ts +20 -20
- package/shared/types/asideMajorPages.ts +4 -4
- package/shared/types/breadcrumbs.ts +9 -9
- package/shared/types/contentChildren.ts +10 -10
- package/shared/types/contentConnections.ts +27 -27
- package/shared/types/contentStats.ts +6 -6
- package/shared/types/elementSnippet.ts +14 -14
- package/shared/types/frontContentNav.ts +38 -38
- package/shared/types/indexPage.ts +20 -20
- package/shared/types/language.ts +191 -191
- package/shared/types/mainContent.ts +69 -69
- package/shared/types/news.ts +13 -13
- package/shared/types/preview.ts +28 -28
- package/shared/types/runtimeConfig.ts +46 -46
- package/shared/types/search.ts +79 -79
- package/shared/utils/contentTypePath.ts +63 -63
- package/shared/utils/icons.ts +11 -11
- package/shared/utils/pages.ts +23 -23
- package/shared/utils/stringColor.ts +13 -13
- package/shared/utils/toStringEqual.ts +21 -21
- package/shared/utils/zip.ts +64 -64
- package/test/shared/utils/zip.test.ts +8 -8
- package/tsconfig.json +17 -17
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import type { EruditAdsBanners } from '@erudit-js/core/eruditConfig/ads';
|
|
2
|
-
import type { EruditLanguage } from '@erudit-js/core/eruditConfig/language';
|
|
3
|
-
import type { EruditCustomLinks } from '@erudit-js/core/eruditConfig/links';
|
|
4
|
-
import type { EruditRepository } from '@erudit-js/core/eruditConfig/repository';
|
|
5
|
-
import type { EruditSponsors } from '@erudit-js/core/sponsor';
|
|
6
|
-
import type { EruditContributors } from '@erudit-js/core/contributor';
|
|
7
|
-
import type { EruditIndexPage } from '@erudit-js/core/eruditConfig/indexPage';
|
|
8
|
-
import type { EruditSiteFaviconResolved } from '@erudit-js/core/eruditConfig/site';
|
|
9
|
-
import type { EruditSeo } from '@erudit-js/core/eruditConfig/seo';
|
|
10
|
-
import type { EruditAnalytics } from '@erudit-js/core/eruditConfig/analytics';
|
|
11
|
-
|
|
12
|
-
export interface EruditRuntimeConfig {
|
|
13
|
-
elements: string[];
|
|
14
|
-
countElements: (string | string[])[];
|
|
15
|
-
indexPage?: EruditIndexPage;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface EruditPublicRuntimeConfig {
|
|
19
|
-
language: EruditLanguage;
|
|
20
|
-
siteInfo: {
|
|
21
|
-
title?: string;
|
|
22
|
-
short?: string | false;
|
|
23
|
-
logotype?: string | false;
|
|
24
|
-
favicon?: EruditSiteFaviconResolved;
|
|
25
|
-
loadingSvg?: string;
|
|
26
|
-
};
|
|
27
|
-
seo?: EruditSeo;
|
|
28
|
-
debug: {
|
|
29
|
-
log: boolean;
|
|
30
|
-
slowTransition: boolean;
|
|
31
|
-
ads: boolean;
|
|
32
|
-
fakeApi: {
|
|
33
|
-
repository: boolean;
|
|
34
|
-
};
|
|
35
|
-
analytics?: boolean;
|
|
36
|
-
};
|
|
37
|
-
repository?: EruditRepository & { _link: string };
|
|
38
|
-
style?: {
|
|
39
|
-
brandColor?: string;
|
|
40
|
-
};
|
|
41
|
-
customLinks?: EruditCustomLinks;
|
|
42
|
-
contributors?: EruditContributors;
|
|
43
|
-
sponsors?: EruditSponsors;
|
|
44
|
-
ads?: EruditAdsBanners;
|
|
45
|
-
analytics?: EruditAnalytics;
|
|
46
|
-
}
|
|
1
|
+
import type { EruditAdsBanners } from '@erudit-js/core/eruditConfig/ads';
|
|
2
|
+
import type { EruditLanguage } from '@erudit-js/core/eruditConfig/language';
|
|
3
|
+
import type { EruditCustomLinks } from '@erudit-js/core/eruditConfig/links';
|
|
4
|
+
import type { EruditRepository } from '@erudit-js/core/eruditConfig/repository';
|
|
5
|
+
import type { EruditSponsors } from '@erudit-js/core/sponsor';
|
|
6
|
+
import type { EruditContributors } from '@erudit-js/core/contributor';
|
|
7
|
+
import type { EruditIndexPage } from '@erudit-js/core/eruditConfig/indexPage';
|
|
8
|
+
import type { EruditSiteFaviconResolved } from '@erudit-js/core/eruditConfig/site';
|
|
9
|
+
import type { EruditSeo } from '@erudit-js/core/eruditConfig/seo';
|
|
10
|
+
import type { EruditAnalytics } from '@erudit-js/core/eruditConfig/analytics';
|
|
11
|
+
|
|
12
|
+
export interface EruditRuntimeConfig {
|
|
13
|
+
elements: string[];
|
|
14
|
+
countElements: (string | string[])[];
|
|
15
|
+
indexPage?: EruditIndexPage;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface EruditPublicRuntimeConfig {
|
|
19
|
+
language: EruditLanguage;
|
|
20
|
+
siteInfo: {
|
|
21
|
+
title?: string;
|
|
22
|
+
short?: string | false;
|
|
23
|
+
logotype?: string | false;
|
|
24
|
+
favicon?: EruditSiteFaviconResolved;
|
|
25
|
+
loadingSvg?: string;
|
|
26
|
+
};
|
|
27
|
+
seo?: EruditSeo;
|
|
28
|
+
debug: {
|
|
29
|
+
log: boolean;
|
|
30
|
+
slowTransition: boolean;
|
|
31
|
+
ads: boolean;
|
|
32
|
+
fakeApi: {
|
|
33
|
+
repository: boolean;
|
|
34
|
+
};
|
|
35
|
+
analytics?: boolean;
|
|
36
|
+
};
|
|
37
|
+
repository?: EruditRepository & { _link: string };
|
|
38
|
+
style?: {
|
|
39
|
+
brandColor?: string;
|
|
40
|
+
};
|
|
41
|
+
customLinks?: EruditCustomLinks;
|
|
42
|
+
contributors?: EruditContributors;
|
|
43
|
+
sponsors?: EruditSponsors;
|
|
44
|
+
ads?: EruditAdsBanners;
|
|
45
|
+
analytics?: EruditAnalytics;
|
|
46
|
+
}
|
package/shared/types/search.ts
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Commands
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import type { MaybeMyIconName } from '#my-icons';
|
|
6
|
-
|
|
7
|
-
export interface SearchCommandInit {
|
|
8
|
-
type: 'init';
|
|
9
|
-
baseUrl: string;
|
|
10
|
-
cacheId: string;
|
|
11
|
-
language: LanguageCode;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface SearchCommandSearch {
|
|
15
|
-
type: 'search';
|
|
16
|
-
id: number;
|
|
17
|
-
query: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface SearchCommandMore {
|
|
21
|
-
type: 'more';
|
|
22
|
-
id: number; // added: identify which search to paginate
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type SearchCommand =
|
|
26
|
-
| SearchCommandInit
|
|
27
|
-
| SearchCommandSearch
|
|
28
|
-
| SearchCommandMore;
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
// Responses
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
export interface SearchResponseError {
|
|
35
|
-
type: 'error';
|
|
36
|
-
message: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface SearchResponseResults {
|
|
40
|
-
type: 'results';
|
|
41
|
-
entries: SearchEntry[];
|
|
42
|
-
hasMore: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type SearchResponse = SearchResponseError | SearchResponseResults;
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
export interface SearchStatusVariant {
|
|
52
|
-
id: string;
|
|
53
|
-
icon?: MaybeMyIconName;
|
|
54
|
-
message?: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface SearchEntry {
|
|
58
|
-
category: string;
|
|
59
|
-
title: string;
|
|
60
|
-
link: string;
|
|
61
|
-
description?: string;
|
|
62
|
-
synonyms?: string[];
|
|
63
|
-
location?: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export type ResolvedSearchEntry = SearchEntry & {
|
|
67
|
-
id: number;
|
|
68
|
-
categoryPriority: number;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export interface SearchEntryCategory {
|
|
72
|
-
id: string;
|
|
73
|
-
priority: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface SearchEntriesList {
|
|
77
|
-
category: SearchEntryCategory;
|
|
78
|
-
entries: SearchEntry[];
|
|
79
|
-
}
|
|
1
|
+
//
|
|
2
|
+
// Commands
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import type { MaybeMyIconName } from '#my-icons';
|
|
6
|
+
|
|
7
|
+
export interface SearchCommandInit {
|
|
8
|
+
type: 'init';
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
cacheId: string;
|
|
11
|
+
language: LanguageCode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SearchCommandSearch {
|
|
15
|
+
type: 'search';
|
|
16
|
+
id: number;
|
|
17
|
+
query: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SearchCommandMore {
|
|
21
|
+
type: 'more';
|
|
22
|
+
id: number; // added: identify which search to paginate
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type SearchCommand =
|
|
26
|
+
| SearchCommandInit
|
|
27
|
+
| SearchCommandSearch
|
|
28
|
+
| SearchCommandMore;
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
// Responses
|
|
32
|
+
//
|
|
33
|
+
|
|
34
|
+
export interface SearchResponseError {
|
|
35
|
+
type: 'error';
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface SearchResponseResults {
|
|
40
|
+
type: 'results';
|
|
41
|
+
entries: SearchEntry[];
|
|
42
|
+
hasMore: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type SearchResponse = SearchResponseError | SearchResponseResults;
|
|
46
|
+
|
|
47
|
+
//
|
|
48
|
+
//
|
|
49
|
+
//
|
|
50
|
+
|
|
51
|
+
export interface SearchStatusVariant {
|
|
52
|
+
id: string;
|
|
53
|
+
icon?: MaybeMyIconName;
|
|
54
|
+
message?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface SearchEntry {
|
|
58
|
+
category: string;
|
|
59
|
+
title: string;
|
|
60
|
+
link: string;
|
|
61
|
+
description?: string;
|
|
62
|
+
synonyms?: string[];
|
|
63
|
+
location?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type ResolvedSearchEntry = SearchEntry & {
|
|
67
|
+
id: number;
|
|
68
|
+
categoryPriority: number;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export interface SearchEntryCategory {
|
|
72
|
+
id: string;
|
|
73
|
+
priority: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface SearchEntriesList {
|
|
77
|
+
category: SearchEntryCategory;
|
|
78
|
+
entries: SearchEntry[];
|
|
79
|
+
}
|
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
import { type TopicPart, isTopicPart } from '@erudit-js/core/content/topic';
|
|
2
|
-
import { type ContentType, isContentType } from '@erudit-js/core/content/type';
|
|
3
|
-
|
|
4
|
-
interface OtherContentTypePath {
|
|
5
|
-
type: 'book' | 'group' | 'page';
|
|
6
|
-
contentId: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface TopicContentTypePath {
|
|
10
|
-
type: 'topic';
|
|
11
|
-
topicPart: TopicPart;
|
|
12
|
-
contentId: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type ContentTypePath = OtherContentTypePath | TopicContentTypePath;
|
|
16
|
-
|
|
17
|
-
export function parseContentTypePath(contentPath: string): ContentTypePath {
|
|
18
|
-
const contentPathArray = contentPath.split('/');
|
|
19
|
-
const typeOrPart = contentPathArray.shift();
|
|
20
|
-
|
|
21
|
-
if (!isTopicPart(typeOrPart) && !isContentType(typeOrPart)) {
|
|
22
|
-
throw createError({
|
|
23
|
-
status: 400,
|
|
24
|
-
statusMessage: `Invalid content path type/topic part: "${contentPath}"!`,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (typeOrPart === 'topic') {
|
|
29
|
-
throw createError({
|
|
30
|
-
status: 400,
|
|
31
|
-
statusMessage: `Instead of "topic", use specific topic part (article, summary or practice) in content path: "${contentPath}"!`,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const fullOrShortId = contentPathArray.join('/');
|
|
36
|
-
|
|
37
|
-
if (!fullOrShortId) {
|
|
38
|
-
throw createError({
|
|
39
|
-
status: 400,
|
|
40
|
-
statusMessage: `Falsy content path full/short ID: "${contentPath}"!`,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (isTopicPart(typeOrPart)) {
|
|
45
|
-
return {
|
|
46
|
-
type: 'topic',
|
|
47
|
-
topicPart: typeOrPart,
|
|
48
|
-
contentId: fullOrShortId,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
type: typeOrPart,
|
|
54
|
-
contentId: fullOrShortId,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function stringifyContentTypePath(
|
|
59
|
-
typeOrPart: Omit<ContentType | TopicPart, 'topic'>,
|
|
60
|
-
fullOrShortId: string,
|
|
61
|
-
): string {
|
|
62
|
-
return `${typeOrPart}/${fullOrShortId}`;
|
|
63
|
-
}
|
|
1
|
+
import { type TopicPart, isTopicPart } from '@erudit-js/core/content/topic';
|
|
2
|
+
import { type ContentType, isContentType } from '@erudit-js/core/content/type';
|
|
3
|
+
|
|
4
|
+
interface OtherContentTypePath {
|
|
5
|
+
type: 'book' | 'group' | 'page';
|
|
6
|
+
contentId: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface TopicContentTypePath {
|
|
10
|
+
type: 'topic';
|
|
11
|
+
topicPart: TopicPart;
|
|
12
|
+
contentId: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ContentTypePath = OtherContentTypePath | TopicContentTypePath;
|
|
16
|
+
|
|
17
|
+
export function parseContentTypePath(contentPath: string): ContentTypePath {
|
|
18
|
+
const contentPathArray = contentPath.split('/');
|
|
19
|
+
const typeOrPart = contentPathArray.shift();
|
|
20
|
+
|
|
21
|
+
if (!isTopicPart(typeOrPart) && !isContentType(typeOrPart)) {
|
|
22
|
+
throw createError({
|
|
23
|
+
status: 400,
|
|
24
|
+
statusMessage: `Invalid content path type/topic part: "${contentPath}"!`,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeOrPart === 'topic') {
|
|
29
|
+
throw createError({
|
|
30
|
+
status: 400,
|
|
31
|
+
statusMessage: `Instead of "topic", use specific topic part (article, summary or practice) in content path: "${contentPath}"!`,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const fullOrShortId = contentPathArray.join('/');
|
|
36
|
+
|
|
37
|
+
if (!fullOrShortId) {
|
|
38
|
+
throw createError({
|
|
39
|
+
status: 400,
|
|
40
|
+
statusMessage: `Falsy content path full/short ID: "${contentPath}"!`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (isTopicPart(typeOrPart)) {
|
|
45
|
+
return {
|
|
46
|
+
type: 'topic',
|
|
47
|
+
topicPart: typeOrPart,
|
|
48
|
+
contentId: fullOrShortId,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
type: typeOrPart,
|
|
54
|
+
contentId: fullOrShortId,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function stringifyContentTypePath(
|
|
59
|
+
typeOrPart: Omit<ContentType | TopicPart, 'topic'>,
|
|
60
|
+
fullOrShortId: string,
|
|
61
|
+
): string {
|
|
62
|
+
return `${typeOrPart}/${fullOrShortId}`;
|
|
63
|
+
}
|
package/shared/utils/icons.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { MaybeMyIconName } from '#my-icons';
|
|
2
|
-
|
|
3
|
-
export const ICONS = {
|
|
4
|
-
['book']: 'book-outline',
|
|
5
|
-
['group']: 'folder-open',
|
|
6
|
-
['page']: 'lines',
|
|
7
|
-
['topic']: 'array-lines',
|
|
8
|
-
['article']: 'array-lines',
|
|
9
|
-
['summary']: 'array-star',
|
|
10
|
-
['practice']: 'array-check',
|
|
11
|
-
} satisfies Record<string, MaybeMyIconName>;
|
|
1
|
+
import type { MaybeMyIconName } from '#my-icons';
|
|
2
|
+
|
|
3
|
+
export const ICONS = {
|
|
4
|
+
['book']: 'book-outline',
|
|
5
|
+
['group']: 'folder-open',
|
|
6
|
+
['page']: 'lines',
|
|
7
|
+
['topic']: 'array-lines',
|
|
8
|
+
['article']: 'array-lines',
|
|
9
|
+
['summary']: 'array-star',
|
|
10
|
+
['practice']: 'array-check',
|
|
11
|
+
} satisfies Record<string, MaybeMyIconName>;
|
package/shared/utils/pages.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { sn } from 'unslash';
|
|
2
|
-
import type { TopicPart } from '@erudit-js/core/content/topic';
|
|
3
|
-
|
|
4
|
-
export const PAGES = {
|
|
5
|
-
index: '/',
|
|
6
|
-
contributors: '/contributors/',
|
|
7
|
-
contributor: (contributorId?: string) => {
|
|
8
|
-
return sn(`/contributor/${contributorId ?? ''}/`);
|
|
9
|
-
},
|
|
10
|
-
sponsors: '/sponsors/',
|
|
11
|
-
['book']: (shortId: string) => {
|
|
12
|
-
return sn(`/book/${shortId}/`);
|
|
13
|
-
},
|
|
14
|
-
['group']: (shortId: string) => {
|
|
15
|
-
return sn(`/group/${shortId}/`);
|
|
16
|
-
},
|
|
17
|
-
['page']: (shortId: string, elementId?: string) => {
|
|
18
|
-
return sn(`/page/${shortId}/${elementId ? '#' + elementId : ''}`);
|
|
19
|
-
},
|
|
20
|
-
['topic']: (part: TopicPart, shortId: string, elementId?: string) => {
|
|
21
|
-
return sn(`/${part}/${shortId}/${elementId ? '#' + elementId : ''}`);
|
|
22
|
-
},
|
|
23
|
-
};
|
|
1
|
+
import { sn } from 'unslash';
|
|
2
|
+
import type { TopicPart } from '@erudit-js/core/content/topic';
|
|
3
|
+
|
|
4
|
+
export const PAGES = {
|
|
5
|
+
index: '/',
|
|
6
|
+
contributors: '/contributors/',
|
|
7
|
+
contributor: (contributorId?: string) => {
|
|
8
|
+
return sn(`/contributor/${contributorId ?? ''}/`);
|
|
9
|
+
},
|
|
10
|
+
sponsors: '/sponsors/',
|
|
11
|
+
['book']: (shortId: string) => {
|
|
12
|
+
return sn(`/book/${shortId}/`);
|
|
13
|
+
},
|
|
14
|
+
['group']: (shortId: string) => {
|
|
15
|
+
return sn(`/group/${shortId}/`);
|
|
16
|
+
},
|
|
17
|
+
['page']: (shortId: string, elementId?: string) => {
|
|
18
|
+
return sn(`/page/${shortId}/${elementId ? '#' + elementId : ''}`);
|
|
19
|
+
},
|
|
20
|
+
['topic']: (part: TopicPart, shortId: string, elementId?: string) => {
|
|
21
|
+
return sn(`/${part}/${shortId}/${elementId ? '#' + elementId : ''}`);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export function stringColor(text: string) {
|
|
2
|
-
let hash = 0;
|
|
3
|
-
|
|
4
|
-
for (let i = 0; i < text.length; i++) {
|
|
5
|
-
hash = text.charCodeAt(i) + ((hash << 5) - hash);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const hue = hash % 360;
|
|
9
|
-
const lightColor = `hsl(${hue}, 70%, 35%)`; // Darker for white background
|
|
10
|
-
const darkColor = `hsl(${hue}, 75%, 70%)`; // Lighter for black background
|
|
11
|
-
|
|
12
|
-
return `light-dark(${lightColor}, ${darkColor})`;
|
|
13
|
-
}
|
|
1
|
+
export function stringColor(text: string) {
|
|
2
|
+
let hash = 0;
|
|
3
|
+
|
|
4
|
+
for (let i = 0; i < text.length; i++) {
|
|
5
|
+
hash = text.charCodeAt(i) + ((hash << 5) - hash);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const hue = hash % 360;
|
|
9
|
+
const lightColor = `hsl(${hue}, 70%, 35%)`; // Darker for white background
|
|
10
|
+
const darkColor = `hsl(${hue}, 75%, 70%)`; // Lighter for black background
|
|
11
|
+
|
|
12
|
+
return `light-dark(${lightColor}, ${darkColor})`;
|
|
13
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
function stringifyValue(value: unknown): string {
|
|
2
|
-
if (value === null || typeof value !== 'object') {
|
|
3
|
-
return JSON.stringify(value);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
if (Array.isArray(value)) {
|
|
7
|
-
return '[' + value.map(stringifyValue).join(',') + ']';
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const obj = value as Record<string, unknown>;
|
|
11
|
-
const keys = Object.keys(obj).sort();
|
|
12
|
-
const props = keys.map(
|
|
13
|
-
(k) => JSON.stringify(k) + ':' + stringifyValue(obj[k]),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
return '{' + props.join(',') + '}';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function toStringEqual(a: unknown, b: unknown): boolean {
|
|
20
|
-
return stringifyValue(a) === stringifyValue(b);
|
|
21
|
-
}
|
|
1
|
+
function stringifyValue(value: unknown): string {
|
|
2
|
+
if (value === null || typeof value !== 'object') {
|
|
3
|
+
return JSON.stringify(value);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return '[' + value.map(stringifyValue).join(',') + ']';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const obj = value as Record<string, unknown>;
|
|
11
|
+
const keys = Object.keys(obj).sort();
|
|
12
|
+
const props = keys.map(
|
|
13
|
+
(k) => JSON.stringify(k) + ':' + stringifyValue(obj[k]),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
return '{' + props.join(',') + '}';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function toStringEqual(a: unknown, b: unknown): boolean {
|
|
20
|
+
return stringifyValue(a) === stringifyValue(b);
|
|
21
|
+
}
|
package/shared/utils/zip.ts
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
export async function zip(text: string): Promise<string> {
|
|
2
|
-
const encoded = new TextEncoder().encode(text);
|
|
3
|
-
const compressedStream = new Blob([encoded.buffer as ArrayBuffer])
|
|
4
|
-
.stream()
|
|
5
|
-
.pipeThrough(new CompressionStream('gzip'));
|
|
6
|
-
const compressedBuffer = await new Response(compressedStream).arrayBuffer();
|
|
7
|
-
|
|
8
|
-
return toBase64(new Uint8Array(compressedBuffer));
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function unzip(input: string): Promise<string> {
|
|
12
|
-
const gzBinary = fromBase64(input);
|
|
13
|
-
const decompressedStream = new Blob([gzBinary.buffer as ArrayBuffer])
|
|
14
|
-
.stream()
|
|
15
|
-
.pipeThrough(new DecompressionStream('gzip'));
|
|
16
|
-
const decompressedBuffer = await new Response(
|
|
17
|
-
decompressedStream,
|
|
18
|
-
).arrayBuffer();
|
|
19
|
-
|
|
20
|
-
return new TextDecoder().decode(decompressedBuffer);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Convert Uint8Array to base64 safely in both browser and Node.
|
|
25
|
-
*/
|
|
26
|
-
function toBase64(bytes: Uint8Array): string {
|
|
27
|
-
if (typeof Buffer !== 'undefined') {
|
|
28
|
-
// Node environment
|
|
29
|
-
return Buffer.from(bytes).toString('base64');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (typeof btoa !== 'undefined') {
|
|
33
|
-
// Browser environment
|
|
34
|
-
let binary = '';
|
|
35
|
-
const chunkSize = 0x8000;
|
|
36
|
-
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
37
|
-
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
38
|
-
}
|
|
39
|
-
return btoa(binary);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
throw new Error('No base64 encoding function available.');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Convert base64 string to Uint8Array safely in both browser and Node.
|
|
47
|
-
*/
|
|
48
|
-
function fromBase64(b64: string): Uint8Array {
|
|
49
|
-
if (typeof Buffer !== 'undefined') {
|
|
50
|
-
// Node environment
|
|
51
|
-
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (typeof atob !== 'undefined') {
|
|
55
|
-
// Browser environment
|
|
56
|
-
const binary = atob(b64);
|
|
57
|
-
const len = binary.length;
|
|
58
|
-
const out = new Uint8Array(len);
|
|
59
|
-
for (let i = 0; i < len; i++) out[i] = binary.charCodeAt(i);
|
|
60
|
-
return out;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
throw new Error('No base64 decoding function available.');
|
|
64
|
-
}
|
|
1
|
+
export async function zip(text: string): Promise<string> {
|
|
2
|
+
const encoded = new TextEncoder().encode(text);
|
|
3
|
+
const compressedStream = new Blob([encoded.buffer as ArrayBuffer])
|
|
4
|
+
.stream()
|
|
5
|
+
.pipeThrough(new CompressionStream('gzip'));
|
|
6
|
+
const compressedBuffer = await new Response(compressedStream).arrayBuffer();
|
|
7
|
+
|
|
8
|
+
return toBase64(new Uint8Array(compressedBuffer));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function unzip(input: string): Promise<string> {
|
|
12
|
+
const gzBinary = fromBase64(input);
|
|
13
|
+
const decompressedStream = new Blob([gzBinary.buffer as ArrayBuffer])
|
|
14
|
+
.stream()
|
|
15
|
+
.pipeThrough(new DecompressionStream('gzip'));
|
|
16
|
+
const decompressedBuffer = await new Response(
|
|
17
|
+
decompressedStream,
|
|
18
|
+
).arrayBuffer();
|
|
19
|
+
|
|
20
|
+
return new TextDecoder().decode(decompressedBuffer);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Convert Uint8Array to base64 safely in both browser and Node.
|
|
25
|
+
*/
|
|
26
|
+
function toBase64(bytes: Uint8Array): string {
|
|
27
|
+
if (typeof Buffer !== 'undefined') {
|
|
28
|
+
// Node environment
|
|
29
|
+
return Buffer.from(bytes).toString('base64');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (typeof btoa !== 'undefined') {
|
|
33
|
+
// Browser environment
|
|
34
|
+
let binary = '';
|
|
35
|
+
const chunkSize = 0x8000;
|
|
36
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
37
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
38
|
+
}
|
|
39
|
+
return btoa(binary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new Error('No base64 encoding function available.');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Convert base64 string to Uint8Array safely in both browser and Node.
|
|
47
|
+
*/
|
|
48
|
+
function fromBase64(b64: string): Uint8Array {
|
|
49
|
+
if (typeof Buffer !== 'undefined') {
|
|
50
|
+
// Node environment
|
|
51
|
+
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof atob !== 'undefined') {
|
|
55
|
+
// Browser environment
|
|
56
|
+
const binary = atob(b64);
|
|
57
|
+
const len = binary.length;
|
|
58
|
+
const out = new Uint8Array(len);
|
|
59
|
+
for (let i = 0; i < len; i++) out[i] = binary.charCodeAt(i);
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error('No base64 decoding function available.');
|
|
64
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { test, expect } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { zip, unzip } from '../../../shared/utils/zip';
|
|
4
|
-
|
|
5
|
-
test('zip/unzip', async () => {
|
|
6
|
-
const text = 'Hello мир 🌍!';
|
|
7
|
-
expect(await unzip(await zip(text))).toBe(text);
|
|
8
|
-
});
|
|
1
|
+
import { test, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { zip, unzip } from '../../../shared/utils/zip';
|
|
4
|
+
|
|
5
|
+
test('zip/unzip', async () => {
|
|
6
|
+
const text = 'Hello мир 🌍!';
|
|
7
|
+
expect(await unzip(await zip(text))).toBe(text);
|
|
8
|
+
});
|