retypeset-odyssey 0.1.0
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/LICENSE +21 -0
- package/README.md +168 -0
- package/astro.config.ts +18 -0
- package/default-config.yaml +136 -0
- package/discover-collections.ts +160 -0
- package/integration.ts +394 -0
- package/package.json +105 -0
- package/patches/@qwik.dev__partytown@0.11.2.patch +98 -0
- package/public/_redirects +819 -0
- package/public/feeds/atom-style.xsl +105 -0
- package/public/feeds/rss-style.xsl +105 -0
- package/public/fonts/EarlySummer-VF-Split/00785494587e3487ac63a0e7e4fa30f0.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/08e5d941a4c76fad7b68e7a937ebb21f.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/1268e5072156188d601f1eeb4473655d.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/12a385475353c815d7a5add53ee51e37.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/12b11ca08223c65a21fc731d59dcfc11.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/16d6676d3cb645c520ee6df8a1f89afd.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/2912a75ffef95e7a5ae9e2b2311ad61d.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/298d96ea561e419a4104bc9fc18499ce.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/2a2c71acc17ec39f6780835899e53096.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/2a7e2d0e59d3f638074c50fab39fdef1.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/36931fc4370e1670ed76af5d3feccba2.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/3a68fdc792e4a9e0399a04e32d0cc2e3.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/4054d6a4d6b37719b51e0f71da6e7cd9.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/429cb25f825c3cbde6bfac5b36ae9675.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/42a9efc11298368ecdc1b85ab46f0b4f.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/432018d2bdc9df92a7662056eb2b1261.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/44a6fb782f2a01560faa0f95248b60ef.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/45367b060e8ba0aa2507e6b91b86620b.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/571db7564bda7c1a93542881b8976f4b.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/58d55eeef4cf455e86a1142b1f3110d3.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/59ea41e77309160a0f63cdc76a010202.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/5d19d9174e568db4755981aa2e4ab380.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/5e811eb3b4175ee93d7ec000bf4631c2.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/6268e0cd5d66d6fe05b331f259e7b9e4.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/6549844aa3d833ca06a68a8e839db465.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/714b459658a7321ceeb1e1386ce165c2.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/7511d97a469915013683eae06cb21cd9.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/7784b4ebe543d13f62f6f6e05beb0b2e.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/77c9bea70b3c6ab24e1497d5468c825b.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/789ebea9e81df623e930b86de98fbfab.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/885bb7ab0717e8a47fc17f953adcdbf1.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/896c58aff69a9a857764cee0663bc56d.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/8fb6fc01c59d1e3ad1910b58dec7f5e7.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/95be5462b91b9a0458797cdc89d94cb5.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/9a5b2724f983ca0fc0d5ff8d10c41396.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/9ffe17f9c0e4cc4356cb3f08ffdb9c6d.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/EarlySummer-VF-Subset.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/EarlySummerSerif License.txt +91 -0
- package/public/fonts/EarlySummer-VF-Split/a097ef49be62cd2565aca45600e1e3ac.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/a17a1ae6063088e5b3a48c06b816929a.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/a83fdcfc5ecf2f6996704b0c02758689.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/a8cf15ff9b71e59407d8406866ff6f99.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/af530ed51dd519e4456f8a5e259e908b.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/b195a8924915deec4aa9c3ec777cc93f.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/b4b6bb5df9239dd67b52ca858fd2a506.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/b7592e1e027923f19e0e55dfdac69668.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/b965859f69d8ccceaf0e2d6292afbcfb.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/bbe9333f1ff242bd96ecb23ff9e723b1.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/be758580e295339ea98f0240b9869f24.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/c07099e1d025617f6d40966986e1941b.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/c1b593dda62fdeb7dde3af02016da282.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/c89f0335910a68a0958f2846108370e8.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/ca49aa409fdedd3f2f894cd20a16640a.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/ccd4a28d2f63797e0183c87792e20b75.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/d2718da923fce8e7ea229d65e306e92c.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/d893e9b307d96041e9cfcbd03761b9f4.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/dafaedaee41b75e21479d4ff324b6a34.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/db392af65f1867e5fd580eed2195df99.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/dc7c73a9e5577143ccd11e05ab55cb39.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/de396881189f747eba67685298363242.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/df625b213228bba22a7733d4eff8f148.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/e6e60b384f220b893ef31a926ece829a.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/e6e8ce2c5972ab665630bb705383d0fb.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/e963c7ed7104c2d6d68fcb5f952fe2f5.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/e966b23b4cd7783f43e31032d41784f4.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/edaac57c3856ec13128f4c6c3e00975c.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/ee54e0d86edf068c6c9cbddb76a856fe.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/f612c78a5544ff2dd3e8296ac3e58344.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/f9e539bd9b7bf999c3da82f5403ec3b6.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/fa5863b923ac15993c52a619f699ee63.woff2 +0 -0
- package/public/fonts/EarlySummer-VF-Split/fc759e56ec6f6e6d3d4cb163d62fb557.woff2 +0 -0
- package/public/fonts/Font Subset List/CJK Common Characters.txt +7534 -0
- package/public/fonts/Font Subset List/EarlySummer Subset.txt +3 -0
- package/public/fonts/Font Subset List/Japanese Kana + Korean Letters.txt +6123 -0
- package/public/fonts/Font Subset List/Latin + Cyrillic + Greek + Arabic Glyphs.txt +121 -0
- package/public/fonts/Font Subset List/unicode_range.py +49 -0
- package/public/fonts/NotoSansSC-Bold.otf +0 -0
- package/public/fonts/NotoSansSC-Regular.otf +0 -0
- package/public/fonts/STIX-Italic-VF.woff2 +0 -0
- package/public/fonts/STIX-VF.woff2 +0 -0
- package/public/fonts/Snell-Black-SF.woff2 +0 -0
- package/public/fonts/Snell-Bold-SF.woff2 +0 -0
- package/public/giscus/theme-dark.css +208 -0
- package/public/giscus/theme-light.css +208 -0
- package/public/icons/favicon.svg +4 -0
- package/public/icons/og-logo.png +0 -0
- package/public/robots.txt +4 -0
- package/public/sounds/tap_01.wav +0 -0
- package/public/sounds/tap_02.wav +0 -0
- package/public/sounds/tap_03.wav +0 -0
- package/public/sounds/tap_04.wav +0 -0
- package/public/sounds/tap_05.wav +0 -0
- package/public/sounds/type_01.wav +0 -0
- package/public/sounds/type_02.wav +0 -0
- package/public/sounds/type_03.wav +0 -0
- package/public/sounds/type_04.wav +0 -0
- package/public/sounds/type_05.wav +0 -0
- package/scripts/apply-lqip.ts +276 -0
- package/scripts/format-posts.ts +105 -0
- package/scripts/migration/README.md +52 -0
- package/scripts/migration/migrate-hexo.ts +185 -0
- package/scripts/migration/validate-abbrlinks.ts +161 -0
- package/scripts/new-post.ts +52 -0
- package/scripts/seo/generate-legacy-redirects.ts +407 -0
- package/scripts/update-theme.ts +46 -0
- package/src/assets/icons/copy-check.svg +3 -0
- package/src/assets/icons/copy-icon.svg +4 -0
- package/src/assets/icons/go-back.svg +3 -0
- package/src/assets/icons/heading-anchor.svg +4 -0
- package/src/assets/icons/lang-en.svg +3 -0
- package/src/assets/icons/lang-ja.svg +5 -0
- package/src/assets/icons/lang-zh.svg +5 -0
- package/src/assets/icons/language-switcher.svg +3 -0
- package/src/assets/icons/pin-icon.svg +3 -0
- package/src/assets/icons/search-icon.svg +3 -0
- package/src/assets/icons/theme-toggle.svg +3 -0
- package/src/assets/icons/toc-icon.svg +3 -0
- package/src/assets/icons/top-icon.svg +3 -0
- package/src/assets/lqip-map.json +10 -0
- package/src/components/Button.astro +152 -0
- package/src/components/CategoryList.astro +66 -0
- package/src/components/Comment/Giscus.astro +119 -0
- package/src/components/Comment/Index.astro +30 -0
- package/src/components/Comment/Twikoo.astro +114 -0
- package/src/components/Comment/Waline.astro +149 -0
- package/src/components/FloatingButtons.astro +101 -0
- package/src/components/Footer.astro +74 -0
- package/src/components/Header.astro +62 -0
- package/src/components/JournalList.astro +56 -0
- package/src/components/Navbar.astro +69 -0
- package/src/components/NoteList.astro +56 -0
- package/src/components/Pagination.astro +267 -0
- package/src/components/PostDate.astro +80 -0
- package/src/components/PostList.astro +87 -0
- package/src/components/SearchModal.astro +340 -0
- package/src/components/TagList.astro +135 -0
- package/src/components/Widgets/BackButton.astro +43 -0
- package/src/components/Widgets/CodeCopyButton.astro +47 -0
- package/src/components/Widgets/GithubCard.astro +110 -0
- package/src/components/Widgets/ImageZoom.astro +135 -0
- package/src/components/Widgets/MediaEmbed.astro +127 -0
- package/src/components/Widgets/SoundEffect.astro +179 -0
- package/src/components/Widgets/TOC.astro +198 -0
- package/src/config-schema.ts +164 -0
- package/src/config.ts +127 -0
- package/src/config.ts.example +205 -0
- package/src/content/about/_example-about-en.md +6 -0
- package/src/content/about/about-en.md +21 -0
- package/src/content/about/about-ja.md +21 -0
- package/src/content/about/about-zh.md +24 -0
- package/src/content.config.ts +247 -0
- package/src/env.d.ts +25 -0
- package/src/i18n/config.ts +65 -0
- package/src/i18n/lang.ts +70 -0
- package/src/i18n/path.ts +160 -0
- package/src/i18n/ui.ts +214 -0
- package/src/layouts/Head.astro +203 -0
- package/src/layouts/Layout.astro +69 -0
- package/src/pages/404.astro +20 -0
- package/src/pages/[...lang]/[...page].astro +48 -0
- package/src/pages/[...lang]/about.astro +28 -0
- package/src/pages/[...lang]/atom.xml.ts +14 -0
- package/src/pages/[...lang]/categories/index.astro +35 -0
- package/src/pages/[...lang]/journals/[slug].astro +89 -0
- package/src/pages/[...lang]/journals/index.astro +55 -0
- package/src/pages/[...lang]/journals/page/[page].astro +66 -0
- package/src/pages/[...lang]/notes/[slug].astro +88 -0
- package/src/pages/[...lang]/notes/index.astro +55 -0
- package/src/pages/[...lang]/notes/page/[page].astro +66 -0
- package/src/pages/[...lang]/posts/[slug].astro +101 -0
- package/src/pages/[...lang]/rss.xml.ts +14 -0
- package/src/pages/[...lang]/search.astro +65 -0
- package/src/pages/[...lang]/tags/[tag].astro +53 -0
- package/src/pages/[...lang]/tags/index.astro +36 -0
- package/src/pages/_dynamic/list.astro +101 -0
- package/src/pages/_dynamic/slug.astro +100 -0
- package/src/pages/og/[...image].ts +114 -0
- package/src/pages/robots.txt.ts +20 -0
- package/src/plugins/rehype-code-copy-button.mjs +82 -0
- package/src/plugins/rehype-external-links.mjs +18 -0
- package/src/plugins/rehype-heading-anchor.mjs +55 -0
- package/src/plugins/rehype-image-processor.mjs +77 -0
- package/src/plugins/remark-container-directives.mjs +135 -0
- package/src/plugins/remark-leaf-directives.mjs +184 -0
- package/src/plugins/remark-reading-time.mjs +11 -0
- package/src/styles/comment.css +205 -0
- package/src/styles/extension.css +180 -0
- package/src/styles/font.css +111 -0
- package/src/styles/global.css +91 -0
- package/src/styles/lqip.css +71 -0
- package/src/styles/markdown.css +276 -0
- package/src/styles/transition.css +173 -0
- package/src/types/global.d.ts +22 -0
- package/src/types/index.d.ts +111 -0
- package/src/utils/cache.ts +32 -0
- package/src/utils/content.ts +819 -0
- package/src/utils/description.ts +147 -0
- package/src/utils/dynamic-collections.ts +155 -0
- package/src/utils/feed.ts +238 -0
- package/src/utils/page.ts +107 -0
- package/tsconfig.json +13 -0
- package/uno.config.ts +75 -0
package/integration.ts
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import type { AstroIntegration } from 'astro'
|
|
2
|
+
import mdx from '@astrojs/mdx'
|
|
3
|
+
import partytown from '@astrojs/partytown'
|
|
4
|
+
import sitemap from '@astrojs/sitemap'
|
|
5
|
+
import Compress from 'astro-compress'
|
|
6
|
+
import pagefind from 'astro-pagefind'
|
|
7
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
8
|
+
import { isAbsolute, resolve as resolvePath } from 'node:path'
|
|
9
|
+
import { fileURLToPath } from 'node:url'
|
|
10
|
+
import rehypeKatex from 'rehype-katex'
|
|
11
|
+
import rehypeMermaid from 'rehype-mermaid'
|
|
12
|
+
import rehypeSlug from 'rehype-slug'
|
|
13
|
+
import remarkDirective from 'remark-directive'
|
|
14
|
+
import remarkMath from 'remark-math'
|
|
15
|
+
import UnoCSS from 'unocss/astro'
|
|
16
|
+
import yaml from 'yaml'
|
|
17
|
+
import { discoverCollections } from './discover-collections'
|
|
18
|
+
import { ThemeConfigSchema } from './src/config-schema'
|
|
19
|
+
import { langMap } from './src/i18n/config'
|
|
20
|
+
import { rehypeCodeCopyButton } from './src/plugins/rehype-code-copy-button.mjs'
|
|
21
|
+
import { rehypeExternalLinks } from './src/plugins/rehype-external-links.mjs'
|
|
22
|
+
import { rehypeHeadingAnchor } from './src/plugins/rehype-heading-anchor.mjs'
|
|
23
|
+
import { rehypeImageProcessor } from './src/plugins/rehype-image-processor.mjs'
|
|
24
|
+
import { remarkContainerDirectives } from './src/plugins/remark-container-directives.mjs'
|
|
25
|
+
import { remarkLeafDirectives } from './src/plugins/remark-leaf-directives.mjs'
|
|
26
|
+
import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs'
|
|
27
|
+
|
|
28
|
+
interface RetypesetOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Path to a user `retypeset.config.yaml`.
|
|
31
|
+
*
|
|
32
|
+
* - Absolute path: used as-is.
|
|
33
|
+
* - Relative path: resolved against the consumer project root.
|
|
34
|
+
* - Omitted: looks for `retypeset.config.yaml` at the project root.
|
|
35
|
+
*/
|
|
36
|
+
config?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Minimal deep-merge for plain objects + arrays.
|
|
41
|
+
*
|
|
42
|
+
* Arrays are replaced wholesale (so a consumer overriding `footer.links`
|
|
43
|
+
* gets exactly what they wrote, not the defaults concatenated with their
|
|
44
|
+
* additions). Objects are merged key by key. Anything else is replaced.
|
|
45
|
+
*/
|
|
46
|
+
function deepMerge<T>(base: T, override: unknown): T {
|
|
47
|
+
if (override === undefined || override === null)
|
|
48
|
+
return base
|
|
49
|
+
if (
|
|
50
|
+
typeof base !== 'object'
|
|
51
|
+
|| base === null
|
|
52
|
+
|| Array.isArray(base)
|
|
53
|
+
|| typeof override !== 'object'
|
|
54
|
+
|| Array.isArray(override)
|
|
55
|
+
) {
|
|
56
|
+
return override as T
|
|
57
|
+
}
|
|
58
|
+
const out: Record<string, unknown> = { ...(base as Record<string, unknown>) }
|
|
59
|
+
for (const [key, value] of Object.entries(override as Record<string, unknown>)) {
|
|
60
|
+
out[key] = deepMerge((base as Record<string, unknown>)[key], value)
|
|
61
|
+
}
|
|
62
|
+
return out as T
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Retypeset Odyssey theme integration.
|
|
67
|
+
*
|
|
68
|
+
* Responsibilities:
|
|
69
|
+
*
|
|
70
|
+
* 1. Read `default-config.yaml` (shipped with the package) and optionally a
|
|
71
|
+
* consumer `retypeset.config.yaml` from the project root; deep-merge and
|
|
72
|
+
* Zod-validate them.
|
|
73
|
+
* 2. Expose the merged config via a Vite virtual module
|
|
74
|
+
* (`virtual:retypeset/config`) and re-route `@/config` imports to it, so
|
|
75
|
+
* every theme file that does `import ... from '@/config'` automatically
|
|
76
|
+
* sees consumer overrides without any code change.
|
|
77
|
+
* 3. Drive the Astro top-level config from the same YAML — `site`,
|
|
78
|
+
* `build.format`, `trailingSlash`, `prefetch`, `i18n`, and `image.domains`
|
|
79
|
+
* are all set from the validated config so the consumer's
|
|
80
|
+
* `astro.config.ts` can shrink to `integrations: [retypeset()]`.
|
|
81
|
+
* 4. Register UnoCSS, MDX, partytown, sitemap, pagefind, compress, and the
|
|
82
|
+
* markdown plugin pipeline, so consumers do not import any of those.
|
|
83
|
+
* 5. Inject all theme pages/routes.
|
|
84
|
+
*
|
|
85
|
+
* Usage in consumer's astro.config.ts:
|
|
86
|
+
* import retypeset from 'retypeset-odyssey/integration'
|
|
87
|
+
* export default defineConfig({ integrations: [retypeset()] })
|
|
88
|
+
*/
|
|
89
|
+
export default function retypesetTheme(options: RetypesetOptions = {}): AstroIntegration {
|
|
90
|
+
return {
|
|
91
|
+
name: 'retypeset-odyssey',
|
|
92
|
+
hooks: {
|
|
93
|
+
'astro:config:setup': ({ injectRoute, updateConfig, config }) => {
|
|
94
|
+
// Resolve paths relative to this package.
|
|
95
|
+
const themeUrl = (path: string) => new URL(path, import.meta.url)
|
|
96
|
+
const themePath = (path: string) => fileURLToPath(themeUrl(path))
|
|
97
|
+
|
|
98
|
+
// --- 1. Load + validate configuration ---
|
|
99
|
+
|
|
100
|
+
const defaultYamlPath = themePath('./default-config.yaml')
|
|
101
|
+
const defaultConfig = yaml.parse(readFileSync(defaultYamlPath, 'utf-8'))
|
|
102
|
+
|
|
103
|
+
const projectRoot = fileURLToPath(config.root)
|
|
104
|
+
let userConfigPath: string | null = null
|
|
105
|
+
if (options.config) {
|
|
106
|
+
userConfigPath = isAbsolute(options.config)
|
|
107
|
+
? options.config
|
|
108
|
+
: resolvePath(projectRoot, options.config)
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const candidate = resolvePath(projectRoot, 'retypeset.config.yaml')
|
|
112
|
+
if (existsSync(candidate))
|
|
113
|
+
userConfigPath = candidate
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let userConfig: unknown = {}
|
|
117
|
+
if (userConfigPath && existsSync(userConfigPath)) {
|
|
118
|
+
userConfig = yaml.parse(readFileSync(userConfigPath, 'utf-8')) ?? {}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const merged = deepMerge(defaultConfig, userConfig)
|
|
122
|
+
const validated = ThemeConfigSchema.parse(merged)
|
|
123
|
+
|
|
124
|
+
const base = validated.site.base === '/' ? '' : validated.site.base.replace(/\/$/, '')
|
|
125
|
+
const defaultLocale = validated.global.locale
|
|
126
|
+
const moreLocales = validated.global.moreLocales
|
|
127
|
+
const allLocales = [defaultLocale, ...moreLocales]
|
|
128
|
+
|
|
129
|
+
// --- 2. Build the virtual module body ---
|
|
130
|
+
//
|
|
131
|
+
// Mirrors the public surface of src/config.ts exactly so any file
|
|
132
|
+
// importing from '@/config' keeps working.
|
|
133
|
+
const configJson = JSON.stringify(validated)
|
|
134
|
+
const allLocalesJson = JSON.stringify(allLocales)
|
|
135
|
+
const moreLocalesJson = JSON.stringify(moreLocales)
|
|
136
|
+
const virtualConfigCode = `// Auto-generated by retypeset-odyssey integration. Do not edit.
|
|
137
|
+
export const themeConfig = ${configJson}
|
|
138
|
+
export const base = ${JSON.stringify(base)}
|
|
139
|
+
export const defaultLocale = ${JSON.stringify(defaultLocale)}
|
|
140
|
+
export const moreLocales = ${moreLocalesJson}
|
|
141
|
+
export const allLocales = ${allLocalesJson}
|
|
142
|
+
export const POSTS_PER_PAGE = 7
|
|
143
|
+
export const NOTES_PER_PAGE = 7
|
|
144
|
+
export const JOURNALS_PER_PAGE = 7
|
|
145
|
+
`
|
|
146
|
+
|
|
147
|
+
const VIRTUAL_ID = 'virtual:retypeset/config'
|
|
148
|
+
const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`
|
|
149
|
+
|
|
150
|
+
// --- Collection discovery ---
|
|
151
|
+
//
|
|
152
|
+
// Decide which built-in collection routes to inject and which dynamic
|
|
153
|
+
// folders need their own list+detail routes. Built-ins default to
|
|
154
|
+
// enabled; consumers turn them off with
|
|
155
|
+
// `collections.<name>.enabled: false` in retypeset.config.yaml.
|
|
156
|
+
const { enabledBuiltIns, dynamicFolders, skippedFolders } = discoverCollections(
|
|
157
|
+
projectRoot,
|
|
158
|
+
userConfigPath ?? undefined,
|
|
159
|
+
)
|
|
160
|
+
const builtInEnabled = (name: 'posts' | 'notes' | 'journals') =>
|
|
161
|
+
enabledBuiltIns.includes(name)
|
|
162
|
+
|
|
163
|
+
if (skippedFolders.length > 0) {
|
|
164
|
+
// eslint-disable-next-line no-console
|
|
165
|
+
console.warn(
|
|
166
|
+
`[retypeset-odyssey] Skipped content folders with unsupported names: ${skippedFolders.join(', ')}. `
|
|
167
|
+
+ `Folder names must match /^[a-zA-Z0-9][a-zA-Z0-9-]*$/ and must not be \`about\`.`,
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Expose the dynamic-collection list to template files via a virtual
|
|
172
|
+
// module so `getStaticPaths` knows which folders to enumerate.
|
|
173
|
+
const DYNAMIC_VIRTUAL_ID = 'virtual:retypeset/dynamic-collections'
|
|
174
|
+
const RESOLVED_DYNAMIC_VIRTUAL_ID = `\0${DYNAMIC_VIRTUAL_ID}`
|
|
175
|
+
const dynamicCollectionsCode = `// Auto-generated by retypeset-odyssey integration. Do not edit.
|
|
176
|
+
export const dynamicCollections = ${JSON.stringify(dynamicFolders)}
|
|
177
|
+
`
|
|
178
|
+
|
|
179
|
+
// --- 3. Inject all theme pages ---
|
|
180
|
+
|
|
181
|
+
// 404
|
|
182
|
+
injectRoute({ pattern: '/404', entrypoint: themeUrl('./src/pages/404.astro'), prerender: true })
|
|
183
|
+
|
|
184
|
+
// Homepage / paginated index
|
|
185
|
+
injectRoute({ pattern: '/[...lang]/[...page]', entrypoint: themeUrl('./src/pages/[...lang]/[...page].astro'), prerender: true })
|
|
186
|
+
|
|
187
|
+
// About
|
|
188
|
+
injectRoute({ pattern: '/[...lang]/about', entrypoint: themeUrl('./src/pages/[...lang]/about.astro'), prerender: true })
|
|
189
|
+
|
|
190
|
+
// Feeds
|
|
191
|
+
injectRoute({ pattern: '/[...lang]/atom.xml', entrypoint: themeUrl('./src/pages/[...lang]/atom.xml.ts'), prerender: true })
|
|
192
|
+
injectRoute({ pattern: '/[...lang]/rss.xml', entrypoint: themeUrl('./src/pages/[...lang]/rss.xml.ts'), prerender: true })
|
|
193
|
+
|
|
194
|
+
// Categories
|
|
195
|
+
injectRoute({ pattern: '/[...lang]/categories', entrypoint: themeUrl('./src/pages/[...lang]/categories/index.astro'), prerender: true })
|
|
196
|
+
|
|
197
|
+
// Posts (always injected; disabling `posts` only suppresses the navbar
|
|
198
|
+
// entry — the homepage and tag pages still depend on the collection).
|
|
199
|
+
if (builtInEnabled('posts')) {
|
|
200
|
+
injectRoute({ pattern: '/[...lang]/posts/[slug]', entrypoint: themeUrl('./src/pages/[...lang]/posts/[slug].astro'), prerender: true })
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Notes
|
|
204
|
+
if (builtInEnabled('notes')) {
|
|
205
|
+
injectRoute({ pattern: '/[...lang]/notes/[slug]', entrypoint: themeUrl('./src/pages/[...lang]/notes/[slug].astro'), prerender: true })
|
|
206
|
+
injectRoute({ pattern: '/[...lang]/notes', entrypoint: themeUrl('./src/pages/[...lang]/notes/index.astro'), prerender: true })
|
|
207
|
+
injectRoute({ pattern: '/[...lang]/notes/page/[page]', entrypoint: themeUrl('./src/pages/[...lang]/notes/page/[page].astro'), prerender: true })
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Journals
|
|
211
|
+
if (builtInEnabled('journals')) {
|
|
212
|
+
injectRoute({ pattern: '/[...lang]/journals/[slug]', entrypoint: themeUrl('./src/pages/[...lang]/journals/[slug].astro'), prerender: true })
|
|
213
|
+
injectRoute({ pattern: '/[...lang]/journals', entrypoint: themeUrl('./src/pages/[...lang]/journals/index.astro'), prerender: true })
|
|
214
|
+
injectRoute({ pattern: '/[...lang]/journals/page/[page]', entrypoint: themeUrl('./src/pages/[...lang]/journals/page/[page].astro'), prerender: true })
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Search
|
|
218
|
+
injectRoute({ pattern: '/[...lang]/search', entrypoint: themeUrl('./src/pages/[...lang]/search.astro'), prerender: true })
|
|
219
|
+
|
|
220
|
+
// Tags
|
|
221
|
+
injectRoute({ pattern: '/[...lang]/tags', entrypoint: themeUrl('./src/pages/[...lang]/tags/index.astro'), prerender: true })
|
|
222
|
+
injectRoute({ pattern: '/[...lang]/tags/[tag]', entrypoint: themeUrl('./src/pages/[...lang]/tags/[tag].astro'), prerender: true })
|
|
223
|
+
|
|
224
|
+
// OG images
|
|
225
|
+
injectRoute({ pattern: '/og/[...image]', entrypoint: themeUrl('./src/pages/og/[...image].ts'), prerender: true })
|
|
226
|
+
|
|
227
|
+
// robots.txt
|
|
228
|
+
injectRoute({ pattern: '/robots.txt', entrypoint: themeUrl('./src/pages/robots.txt.ts'), prerender: true })
|
|
229
|
+
|
|
230
|
+
// Dynamic folder routes. A single list pattern + single detail
|
|
231
|
+
// pattern cover all discovered folders; `getStaticPaths` in the
|
|
232
|
+
// template files only emits URLs for known folders, so Astro will
|
|
233
|
+
// not try to serve `/foo` unless `content/foo/` exists.
|
|
234
|
+
//
|
|
235
|
+
// Literal-segment routes (`/posts`, `/notes`, `/about`, `/tags`,
|
|
236
|
+
// etc.) take priority over single dynamic segments in Astro's
|
|
237
|
+
// router, so the built-ins are unaffected.
|
|
238
|
+
if (dynamicFolders.length > 0) {
|
|
239
|
+
injectRoute({
|
|
240
|
+
pattern: '/[...lang]/[collection]',
|
|
241
|
+
entrypoint: themeUrl('./src/pages/_dynamic/list.astro'),
|
|
242
|
+
prerender: true,
|
|
243
|
+
})
|
|
244
|
+
injectRoute({
|
|
245
|
+
pattern: '/[...lang]/[collection]/[slug]',
|
|
246
|
+
entrypoint: themeUrl('./src/pages/_dynamic/slug.astro'),
|
|
247
|
+
prerender: true,
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// --- 4. Compute optional image config ---
|
|
252
|
+
// Only set `image.domains` when the user provides a host.
|
|
253
|
+
const { imageHostURL } = validated.preload ?? {}
|
|
254
|
+
const imageConfig = imageHostURL
|
|
255
|
+
? {
|
|
256
|
+
image: {
|
|
257
|
+
domains: [imageHostURL],
|
|
258
|
+
remotePatterns: [{ protocol: 'https' as const }],
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
: {}
|
|
262
|
+
|
|
263
|
+
// --- 5. Push everything onto the Astro config ---
|
|
264
|
+
updateConfig({
|
|
265
|
+
site: validated.site.url,
|
|
266
|
+
base,
|
|
267
|
+
build: {
|
|
268
|
+
format: 'file', // Generates /posts/xxx.html instead of /posts/xxx/index.html
|
|
269
|
+
},
|
|
270
|
+
trailingSlash: 'never', // Required for build.format: 'file'
|
|
271
|
+
prefetch: {
|
|
272
|
+
prefetchAll: true,
|
|
273
|
+
defaultStrategy: 'viewport',
|
|
274
|
+
},
|
|
275
|
+
...imageConfig,
|
|
276
|
+
i18n: {
|
|
277
|
+
locales: allLocales.map(lang => ({
|
|
278
|
+
path: lang,
|
|
279
|
+
codes: [...langMap[lang]] as [string, ...string[]],
|
|
280
|
+
})),
|
|
281
|
+
defaultLocale,
|
|
282
|
+
// Provide an explicit routing object so mergeConfig does not leave
|
|
283
|
+
// it undefined (Astro's downstream code reads `routing.redirectToDefaultLocale`).
|
|
284
|
+
routing: {
|
|
285
|
+
prefixDefaultLocale: false,
|
|
286
|
+
redirectToDefaultLocale: false,
|
|
287
|
+
fallbackType: 'redirect',
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
integrations: [
|
|
291
|
+
UnoCSS({
|
|
292
|
+
configFile: themePath('./uno.config.ts'),
|
|
293
|
+
injectReset: true,
|
|
294
|
+
}),
|
|
295
|
+
mdx(),
|
|
296
|
+
partytown({
|
|
297
|
+
config: {
|
|
298
|
+
forward: ['dataLayer.push', 'gtag'],
|
|
299
|
+
},
|
|
300
|
+
}),
|
|
301
|
+
sitemap(),
|
|
302
|
+
pagefind(),
|
|
303
|
+
Compress({
|
|
304
|
+
CSS: true,
|
|
305
|
+
HTML: true,
|
|
306
|
+
Image: false,
|
|
307
|
+
JavaScript: true,
|
|
308
|
+
SVG: false,
|
|
309
|
+
}),
|
|
310
|
+
],
|
|
311
|
+
markdown: {
|
|
312
|
+
remarkPlugins: [
|
|
313
|
+
remarkDirective,
|
|
314
|
+
remarkMath,
|
|
315
|
+
remarkContainerDirectives,
|
|
316
|
+
remarkLeafDirectives,
|
|
317
|
+
remarkReadingTime,
|
|
318
|
+
],
|
|
319
|
+
rehypePlugins: [
|
|
320
|
+
rehypeKatex,
|
|
321
|
+
[rehypeMermaid, { strategy: 'pre-mermaid' }],
|
|
322
|
+
rehypeSlug,
|
|
323
|
+
rehypeHeadingAnchor,
|
|
324
|
+
rehypeImageProcessor,
|
|
325
|
+
rehypeExternalLinks,
|
|
326
|
+
rehypeCodeCopyButton,
|
|
327
|
+
],
|
|
328
|
+
syntaxHighlight: {
|
|
329
|
+
type: 'shiki',
|
|
330
|
+
excludeLangs: ['mermaid'],
|
|
331
|
+
},
|
|
332
|
+
shikiConfig: {
|
|
333
|
+
themes: {
|
|
334
|
+
light: 'github-light',
|
|
335
|
+
dark: 'github-dark',
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
// Astro internally calls fileURLToPath() on publicDir, so it must
|
|
340
|
+
// be a URL object.
|
|
341
|
+
publicDir: themeUrl('./public/') as any,
|
|
342
|
+
vite: {
|
|
343
|
+
plugins: [
|
|
344
|
+
{
|
|
345
|
+
// Vite 7 (Astro 6) is stricter about resolve.alias replacements:
|
|
346
|
+
// pointing an alias at a virtual module specifier (which then
|
|
347
|
+
// gets resolved by a separate plugin) is no longer reliable
|
|
348
|
+
// across all build environments (the content-collections /
|
|
349
|
+
// prerender bundle does not pick it up). Intercept the
|
|
350
|
+
// `@/config` import directly in `resolveId` so the virtual
|
|
351
|
+
// module always wins, regardless of alias evaluation order.
|
|
352
|
+
name: 'retypeset-config-loader',
|
|
353
|
+
enforce: 'pre',
|
|
354
|
+
resolveId(id) {
|
|
355
|
+
if (id === '@/config' || id === '@/config.ts' || id === VIRTUAL_ID)
|
|
356
|
+
return RESOLVED_VIRTUAL_ID
|
|
357
|
+
if (id === DYNAMIC_VIRTUAL_ID)
|
|
358
|
+
return RESOLVED_DYNAMIC_VIRTUAL_ID
|
|
359
|
+
return null
|
|
360
|
+
},
|
|
361
|
+
load(id) {
|
|
362
|
+
if (id === RESOLVED_VIRTUAL_ID)
|
|
363
|
+
return virtualConfigCode
|
|
364
|
+
if (id === RESOLVED_DYNAMIC_VIRTUAL_ID)
|
|
365
|
+
return dynamicCollectionsCode
|
|
366
|
+
return null
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'retypeset-prefix-font-urls-with-base',
|
|
371
|
+
transform(code, id) {
|
|
372
|
+
if (!id.endsWith('src/styles/font.css'))
|
|
373
|
+
return null
|
|
374
|
+
return code.replace(/url\("\/fonts\//g, `url("${base}/fonts/`)
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
resolve: {
|
|
379
|
+
// Generic `@/*` alias for all other source paths. `@/config` is
|
|
380
|
+
// handled by the plugin above (which runs in the `pre` phase,
|
|
381
|
+
// before alias resolution).
|
|
382
|
+
alias: [
|
|
383
|
+
{
|
|
384
|
+
find: /^@\/(.*)/,
|
|
385
|
+
replacement: `${themePath('./src/')}$1`,
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
})
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
}
|
|
394
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "retypeset-odyssey",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"packageManager": "pnpm@10.26.0",
|
|
6
|
+
"repository": "https://github.com/lifeodyssey/retypeset-odyssey",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./integration.ts",
|
|
9
|
+
"./integration": "./integration.ts",
|
|
10
|
+
"./config": "./src/config.ts",
|
|
11
|
+
"./content-config": "./src/content.config.ts",
|
|
12
|
+
"./astro.config": "./astro.config.ts",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"public",
|
|
18
|
+
"patches",
|
|
19
|
+
"scripts",
|
|
20
|
+
"integration.ts",
|
|
21
|
+
"discover-collections.ts",
|
|
22
|
+
"astro.config.ts",
|
|
23
|
+
"tsconfig.json",
|
|
24
|
+
"uno.config.ts",
|
|
25
|
+
"default-config.yaml"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"dev": "astro check && astro dev",
|
|
29
|
+
"build": "pnpm generate-legacy-redirects && astro check && astro build && pnpm apply-lqip",
|
|
30
|
+
"preview": "astro preview",
|
|
31
|
+
"test": "playwright test",
|
|
32
|
+
"test:ui": "playwright test --ui",
|
|
33
|
+
"astro": "astro",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"lint:fix": "eslint . --fix",
|
|
36
|
+
"new-post": "tsx scripts/new-post.ts",
|
|
37
|
+
"translate:new-posts": "node scripts/translation/run.mjs",
|
|
38
|
+
"generate-legacy-redirects": "tsx scripts/seo/generate-legacy-redirects.ts",
|
|
39
|
+
"apply-lqip": "tsx scripts/apply-lqip.ts",
|
|
40
|
+
"format-posts": "tsx scripts/format-posts.ts",
|
|
41
|
+
"update-theme": "tsx scripts/update-theme.ts"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@astrojs/mdx": "^5.0.6",
|
|
45
|
+
"@astrojs/partytown": "^2.1.7",
|
|
46
|
+
"@astrojs/sitemap": "^3.7.2",
|
|
47
|
+
"@unocss/astro": "^66.7.0",
|
|
48
|
+
"@unocss/reset": "66.7.0",
|
|
49
|
+
"@waline/client": "^3.13.0",
|
|
50
|
+
"astro": "^6.3.7",
|
|
51
|
+
"astro-compress": "^2.4.1",
|
|
52
|
+
"astro-og-canvas": "^0.11.1",
|
|
53
|
+
"astro-pagefind": "^2.0.0",
|
|
54
|
+
"canvaskit-wasm": "^0.41.1",
|
|
55
|
+
"feed": "^5.2.1",
|
|
56
|
+
"katex": "^0.17.0",
|
|
57
|
+
"lite-youtube-embed": "^0.3.4",
|
|
58
|
+
"markdown-it": "^14.1.1",
|
|
59
|
+
"mdast-util-to-string": "^4.0.0",
|
|
60
|
+
"mermaid": "^11.15.0",
|
|
61
|
+
"node-html-parser": "^7.1.0",
|
|
62
|
+
"playwright": "^1.60.0",
|
|
63
|
+
"reading-time": "^1.5.0",
|
|
64
|
+
"rehype-katex": "^7.0.1",
|
|
65
|
+
"rehype-mermaid": "^3.0.0",
|
|
66
|
+
"rehype-slug": "^6.0.0",
|
|
67
|
+
"remark-directive": "^4.0.0",
|
|
68
|
+
"remark-math": "^6.0.0",
|
|
69
|
+
"sanitize-html": "^2.17.4",
|
|
70
|
+
"sharp": "^0.34.5",
|
|
71
|
+
"twikoo": "^1.7.9",
|
|
72
|
+
"unist-util-visit": "^5.1.0",
|
|
73
|
+
"unocss": "66.7.0",
|
|
74
|
+
"unocss-preset-theme": "^0.14.1",
|
|
75
|
+
"yaml": "^2.9.0",
|
|
76
|
+
"zod": "^3.25.76"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@antfu/eslint-config": "^9.0.0",
|
|
80
|
+
"@astrojs/check": "^0.9.9",
|
|
81
|
+
"@playwright/test": "^1.60.0",
|
|
82
|
+
"@types/markdown-it": "^14.1.2",
|
|
83
|
+
"@types/node": "^25.9.1",
|
|
84
|
+
"@types/sanitize-html": "^2.16.1",
|
|
85
|
+
"@unocss/eslint-plugin": "66.7.0",
|
|
86
|
+
"@unocss/preset-attributify": "66.7.0",
|
|
87
|
+
"astro-eslint-parser": "^1.4.0",
|
|
88
|
+
"autocorrect-node": "^2.14.0",
|
|
89
|
+
"eslint": "^10.4.0",
|
|
90
|
+
"eslint-plugin-astro": "^1.7.0",
|
|
91
|
+
"fast-glob": "^3.3.3",
|
|
92
|
+
"lint-staged": "^17.0.5",
|
|
93
|
+
"opentype.js": "^2.0.0",
|
|
94
|
+
"simple-git-hooks": "^2.13.1",
|
|
95
|
+
"tsx": "^4.22.3",
|
|
96
|
+
"typescript": "~5.9.3"
|
|
97
|
+
},
|
|
98
|
+
"pnpm": {},
|
|
99
|
+
"simple-git-hooks": {
|
|
100
|
+
"pre-commit": "pnpm lint-staged"
|
|
101
|
+
},
|
|
102
|
+
"lint-staged": {
|
|
103
|
+
"*.{js,mjs,ts,astro}": "eslint --fix"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
diff --git a/integration/index.mjs b/integration/index.mjs
|
|
2
|
+
index f62d2c1f0f983ac6220716ea27edf453e1814672..a559b30a40f788fc6e84f29df0ffcc5c9ba0d444 100644
|
|
3
|
+
--- a/integration/index.mjs
|
|
4
|
+
+++ b/integration/index.mjs
|
|
5
|
+
@@ -1,4 +1,4 @@
|
|
6
|
+
-const PartytownSnippet = "/* Partytown 0.11.2 - MIT QwikDev */\nconst t={preserveBehavior:!1},e=e=>{if(\"string\"==typeof e)return[e,t];const[n,r=t]=e;return[n,{...t,...r}]},n=Object.freeze((t=>{const e=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((t=>{\"function\"==typeof n[t]&&e.add(t)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(e)})());!function(t,r,o,i,a,s,c,l,d,p,u=t,f){function h(){f||(f=1,\"/\"==(c=(s.lib||\"/~partytown/\")+(s.debug?\"debug/\":\"\"))[0]&&(d=r.querySelectorAll('script[type=\"text/partytown\"]'),i!=t?i.dispatchEvent(new CustomEvent(\"pt1\",{detail:t})):(l=setTimeout(v,(null==s?void 0:s.fallbackTimeout)||1e4),r.addEventListener(\"pt0\",w),a?y(1):o.serviceWorker?o.serviceWorker.register(c+(s.swPath||\"partytown-sw.js\"),{scope:c}).then((function(t){t.active?y():t.installing&&t.installing.addEventListener(\"statechange\",(function(t){\"activated\"==t.target.state&&y()}))}),console.error):v())))}function y(e){p=r.createElement(e?\"script\":\"iframe\"),t._pttab=Date.now(),e||(p.style.display=\"block\",p.style.width=\"0\",p.style.height=\"0\",p.style.border=\"0\",p.style.visibility=\"hidden\",p.setAttribute(\"aria-hidden\",!0)),p.src=c+\"partytown-\"+(e?\"atomics.js?v=0.11.2\":\"sandbox-sw.html?\"+t._pttab),r.querySelector(s.sandboxParent||\"body\").appendChild(p)}function v(n,o){for(w(),i==t&&(s.forward||[]).map((function(n){const[r]=e(n);delete t[r.split(\".\")[0]]})),n=0;n<d.length;n++)(o=r.createElement(\"script\")).innerHTML=d[n].innerHTML,o.nonce=s.nonce,r.head.appendChild(o);p&&p.parentNode.removeChild(p)}function w(){clearTimeout(l)}s=t.partytown||{},i==t&&(s.forward||[]).map((function(r){const[o,{preserveBehavior:i}]=e(r);u=t,o.split(\".\").map((function(e,r,o){var a;u=u[o[r]]=r+1<o.length?u[o[r]]||(a=o[r+1],n.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:n,thisObject:r}=((t,e)=>{let n=t;for(let t=0;t<e.length-1;t+=1)n=n[e[t]];return{thisObject:n,methodOrProperty:e.length>0?n[e[e.length-1]]:void 0}})(t,o);\"function\"==typeof n&&(e=(...t)=>n.apply(r,...t))}return function(){let n;return e&&(n=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),n}})()}))})),\"complete\"==r.readyState?h():(t.addEventListener(\"DOMContentLoaded\",h),t.addEventListener(\"load\",h))}(window,document,navigator,top,window.crossOriginIsolated);";
|
|
7
|
+
+const PartytownSnippet = "/* Partytown 0.11.2 - MIT QwikDev */\nconst tp={preserveBehavior:!1},ep=e=>{if(\"string\"==typeof e)return[e,tp];const[n,r=tp]=e;return[n,{...tp,...r}]},n=Object.freeze((t=>{const e=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((t=>{\"function\"==typeof n[t]&&e.add(t)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(e)})());!function(t,r,o,i,a,s,c,l,d,p,u=t,f){function h(){f||(f=1,\"/\"==(c=(s.lib||\"/~partytown/\")+(s.debug?\"debug/\":\"\"))[0]&&(d=r.querySelectorAll('script[type=\"text/partytown\"]'),i!=t?i.dispatchEvent(new CustomEvent(\"pt1\",{detail:t})):(l=setTimeout(v,(null==s?void 0:s.fallbackTimeout)||1e4),r.addEventListener(\"pt0\",w),a?y(1):o.serviceWorker?o.serviceWorker.register(c+(s.swPath||\"partytown-sw.js\"),{scope:c}).then((function(t){t.active?y():t.installing&&t.installing.addEventListener(\"statechange\",(function(t){\"activated\"==t.target.state&&y()}))}),console.error):v())))}function y(e){p=r.createElement(e?\"script\":\"iframe\"),t._pttab=Date.now(),e||(p.style.display=\"block\",p.style.width=\"0\",p.style.height=\"0\",p.style.border=\"0\",p.style.visibility=\"hidden\",p.setAttribute(\"aria-hidden\",!0)),p.src=c+\"partytown-\"+(e?\"atomics.js?v=0.11.2\":\"sandbox-sw.html?\"+t._pttab),r.querySelector(s.sandboxParent||\"body\").appendChild(p)}function v(n,o){for(w(),i==t&&(s.forward||[]).map((function(n){const[r]=ep(n);delete t[r.split(\".\")[0]]})),n=0;n<d.length;n++)(o=r.createElement(\"script\")).innerHTML=d[n].innerHTML,o.nonce=s.nonce,r.head.appendChild(o);p&&p.parentNode.removeChild(p)}function w(){clearTimeout(l)}s=t.partytown||{},i==t&&(s.forward||[]).map((function(r){const[o,{preserveBehavior:i}]=ep(r);u=t,o.split(\".\").map((function(e,r,o){var a;u=u[o[r]]=r+1<o.length?u[o[r]]||(a=o[r+1],n.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:n,thisObject:r}=((t,e)=>{let n=t;for(let t=0;t<e.length-1;t+=1)n=n[e[t]];return{thisObject:n,methodOrProperty:e.length>0?n[e[e.length-1]]:void 0}})(t,o);\"function\"==typeof n&&(e=(...t)=>n.apply(r,...t))}return function(){let n;return e&&(n=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),n}})()}))})),\"complete\"==r.readyState?h():(t.addEventListener(\"DOMContentLoaded\",h),t.addEventListener(\"load\",h))}(window,document,navigator,top,window.crossOriginIsolated);";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The `type` attribute for Partytown scripts, which does two things:
|
|
11
|
+
diff --git a/lib/partytown.js b/lib/partytown.js
|
|
12
|
+
index ee7034c7875950681205c89580f4d1513df1e385..5f61af194420ceb72fab9ada44fce4f744ab808b 100644
|
|
13
|
+
--- a/lib/partytown.js
|
|
14
|
+
+++ b/lib/partytown.js
|
|
15
|
+
@@ -1,2 +1,80 @@
|
|
16
|
+
-/* Partytown 0.11.2 - MIT QwikDev */
|
|
17
|
+
-const t={preserveBehavior:!1},e=e=>{if("string"==typeof e)return[e,t];const[n,r=t]=e;return[n,{...t,...r}]},n=Object.freeze((t=>{const e=new Set;let n=[];do{Object.getOwnPropertyNames(n).forEach((t=>{"function"==typeof n[t]&&e.add(t)}))}while((n=Object.getPrototypeOf(n))!==Object.prototype);return Array.from(e)})());!function(t,r,o,i,a,s,c,l,d,p,u=t,f){function h(){f||(f=1,"/"==(c=(s.lib||"/~partytown/")+(s.debug?"debug/":""))[0]&&(d=r.querySelectorAll('script[type="text/partytown"]'),i!=t?i.dispatchEvent(new CustomEvent("pt1",{detail:t})):(l=setTimeout(v,(null==s?void 0:s.fallbackTimeout)||1e4),r.addEventListener("pt0",w),a?y(1):o.serviceWorker?o.serviceWorker.register(c+(s.swPath||"partytown-sw.js"),{scope:c}).then((function(t){t.active?y():t.installing&&t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&y()}))}),console.error):v())))}function y(e){p=r.createElement(e?"script":"iframe"),t._pttab=Date.now(),e||(p.style.display="block",p.style.width="0",p.style.height="0",p.style.border="0",p.style.visibility="hidden",p.setAttribute("aria-hidden",!0)),p.src=c+"partytown-"+(e?"atomics.js?v=0.11.2":"sandbox-sw.html?"+t._pttab),r.querySelector(s.sandboxParent||"body").appendChild(p)}function v(n,o){for(w(),i==t&&(s.forward||[]).map((function(n){const[r]=e(n);delete t[r.split(".")[0]]})),n=0;n<d.length;n++)(o=r.createElement("script")).innerHTML=d[n].innerHTML,o.nonce=s.nonce,r.head.appendChild(o);p&&p.parentNode.removeChild(p)}function w(){clearTimeout(l)}s=t.partytown||{},i==t&&(s.forward||[]).map((function(r){const[o,{preserveBehavior:i}]=e(r);u=t,o.split(".").map((function(e,r,o){var a;u=u[o[r]]=r+1<o.length?u[o[r]]||(a=o[r+1],n.includes(a)?[]:{}):(()=>{let e=null;if(i){const{methodOrProperty:n,thisObject:r}=((t,e)=>{let n=t;for(let t=0;t<e.length-1;t+=1)n=n[e[t]];return{thisObject:n,methodOrProperty:e.length>0?n[e[e.length-1]]:void 0}})(t,o);"function"==typeof n&&(e=(...t)=>n.apply(r,...t))}return function(){let n;return e&&(n=e(arguments)),(t._ptf=t._ptf||[]).push(o,arguments),n}})()}))})),"complete"==r.readyState?h():(t.addEventListener("DOMContentLoaded",h),t.addEventListener("load",h))}(window,document,navigator,top,window.crossOriginIsolated);
|
|
18
|
+
|
|
19
|
+
+/* Partytown 0.11.2 - MIT QwikDev */
|
|
20
|
+
+const tg = {
|
|
21
|
+
+ preserveBehavior: !1
|
|
22
|
+
+},
|
|
23
|
+
+ eg = e => {
|
|
24
|
+
+ if ("string" == typeof e) return [e, tg];
|
|
25
|
+
+ const [n, r = tg] = e;
|
|
26
|
+
+ return [n, {
|
|
27
|
+
+ ...tg,
|
|
28
|
+
+ ...r
|
|
29
|
+
+ }]
|
|
30
|
+
+ },
|
|
31
|
+
+ n = Object.freeze((t => {
|
|
32
|
+
+ const e = new Set;
|
|
33
|
+
+ let n = [];
|
|
34
|
+
+ do {
|
|
35
|
+
+ Object.getOwnPropertyNames(n).forEach((t => {
|
|
36
|
+
+ "function" == typeof n[t] && e.add(t)
|
|
37
|
+
+ }))
|
|
38
|
+
+ } while ((n = Object.getPrototypeOf(n)) !== Object.prototype);
|
|
39
|
+
+ return Array.from(e)
|
|
40
|
+
+ })());
|
|
41
|
+
+! function (t, r, o, i, a, s, c, l, d, p, u = t, f) {
|
|
42
|
+
+ function h() {
|
|
43
|
+
+ f || (f = 1, "/" == (c = (s.lib || "/~partytown/") + (s.debug ? "debug/" : ""))[0] && (d = r.querySelectorAll('script[type="text/partytown"]'), i != t ? i.dispatchEvent(new CustomEvent("pt1", {
|
|
44
|
+
+ detail: t
|
|
45
|
+
+ })) : (l = setTimeout(v, (null == s ? void 0 : s.fallbackTimeout) || 1e4), r.addEventListener("pt0", w), a ? y(1) : o.serviceWorker ? o.serviceWorker.register(c + (s.swPath || "partytown-sw.js"), {
|
|
46
|
+
+ scope: c
|
|
47
|
+
+ }).then((function (t) {
|
|
48
|
+
+ t.active ? y() : t.installing && t.installing.addEventListener("statechange", (function (t) {
|
|
49
|
+
+ "activated" == t.target.state && y()
|
|
50
|
+
+ }))
|
|
51
|
+
+ }), console.error) : v())))
|
|
52
|
+
+ }
|
|
53
|
+
+
|
|
54
|
+
+ function y(e) {
|
|
55
|
+
+ p = r.createElement(e ? "script" : "iframe"), t._pttab = Date.now(), e || (p.style.display = "block", p.style.width = "0", p.style.height = "0", p.style.border = "0", p.style.visibility = "hidden", p.setAttribute("aria-hidden", !0)), p.src = c + "partytown-" + (e ? "atomics.js?v=0.11.2" : "sandbox-sw.html?" + t._pttab), r.querySelector(s.sandboxParent || "body").appendChild(p)
|
|
56
|
+
+ }
|
|
57
|
+
+
|
|
58
|
+
+ function v(n, o) {
|
|
59
|
+
+ for (w(), i == t && (s.forward || []).map((function (n) {
|
|
60
|
+
+ const [r] = eg(n);
|
|
61
|
+
+ delete t[r.split(".")[0]]
|
|
62
|
+
+ })), n = 0; n < d.length; n++)(o = r.createElement("script")).innerHTML = d[n].innerHTML, o.nonce = s.nonce, r.head.appendChild(o);
|
|
63
|
+
+ p && p.parentNode.removeChild(p)
|
|
64
|
+
+ }
|
|
65
|
+
+
|
|
66
|
+
+ function w() {
|
|
67
|
+
+ clearTimeout(l)
|
|
68
|
+
+ }
|
|
69
|
+
+ s = t.partytown || {}, i == t && (s.forward || []).map((function (r) {
|
|
70
|
+
+ const [o, {
|
|
71
|
+
+ preserveBehavior: i
|
|
72
|
+
+ }] = eg(r);
|
|
73
|
+
+ u = t, o.split(".").map((function (e, r, o) {
|
|
74
|
+
+ var a;
|
|
75
|
+
+ u = u[o[r]] = r + 1 < o.length ? u[o[r]] || (a = o[r + 1], n.includes(a) ? [] : {}) : (() => {
|
|
76
|
+
+ let e = null;
|
|
77
|
+
+ if (i) {
|
|
78
|
+
+ const {
|
|
79
|
+
+ methodOrProperty: n,
|
|
80
|
+
+ thisObject: r
|
|
81
|
+
+ } = ((t, e) => {
|
|
82
|
+
+ let n = t;
|
|
83
|
+
+ for (let t = 0; t < e.length - 1; t += 1) n = n[e[t]];
|
|
84
|
+
+ return {
|
|
85
|
+
+ thisObject: n,
|
|
86
|
+
+ methodOrProperty: e.length > 0 ? n[e[e.length - 1]] : void 0
|
|
87
|
+
+ }
|
|
88
|
+
+ })(t, o);
|
|
89
|
+
+ "function" == typeof n && (e = (...t) => n.apply(r, ...t))
|
|
90
|
+
+ }
|
|
91
|
+
+ return function () {
|
|
92
|
+
+ let n;
|
|
93
|
+
+ return e && (n = e(arguments)), (t._ptf = t._ptf || []).push(o, arguments), n
|
|
94
|
+
+ }
|
|
95
|
+
+ })()
|
|
96
|
+
+ }))
|
|
97
|
+
+ })), "complete" == r.readyState ? h() : (t.addEventListener("DOMContentLoaded", h), t.addEventListener("load", h))
|
|
98
|
+
+}(window, document, navigator, top, window.crossOriginIsolated);
|