gazetta 0.5.0 → 0.6.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/admin-dist/assets/index-B6pVot0Y.css +1 -0
- package/admin-dist/assets/index-DniLwxJA.js +609 -0
- package/admin-dist/assets/{vendor-primevue-BnR1c_bQ.js → vendor-primevue-C0Q_YTCb.js} +330 -431
- package/admin-dist/assets/vendor-vue-D3wBSmDf.js +1 -0
- package/admin-dist/index.html +4 -4
- package/dist/admin-api/index.d.ts +19 -4
- package/dist/admin-api/index.d.ts.map +1 -1
- package/dist/admin-api/index.js +154 -18
- package/dist/admin-api/index.js.map +1 -1
- package/dist/admin-api/routes/compare.d.ts +2 -1
- package/dist/admin-api/routes/compare.d.ts.map +1 -1
- package/dist/admin-api/routes/compare.js +33 -24
- package/dist/admin-api/routes/compare.js.map +1 -1
- package/dist/admin-api/routes/fields.d.ts +2 -2
- package/dist/admin-api/routes/fields.d.ts.map +1 -1
- package/dist/admin-api/routes/fields.js +10 -3
- package/dist/admin-api/routes/fields.js.map +1 -1
- package/dist/admin-api/routes/fragments.d.ts +2 -3
- package/dist/admin-api/routes/fragments.d.ts.map +1 -1
- package/dist/admin-api/routes/fragments.js +92 -19
- package/dist/admin-api/routes/fragments.js.map +1 -1
- package/dist/admin-api/routes/history.d.ts +23 -0
- package/dist/admin-api/routes/history.d.ts.map +1 -0
- package/dist/admin-api/routes/history.js +143 -0
- package/dist/admin-api/routes/history.js.map +1 -0
- package/dist/admin-api/routes/pages.d.ts +2 -3
- package/dist/admin-api/routes/pages.d.ts.map +1 -1
- package/dist/admin-api/routes/pages.js +118 -20
- package/dist/admin-api/routes/pages.js.map +1 -1
- package/dist/admin-api/routes/preview.d.ts +2 -2
- package/dist/admin-api/routes/preview.d.ts.map +1 -1
- package/dist/admin-api/routes/preview.js +50 -15
- package/dist/admin-api/routes/preview.js.map +1 -1
- package/dist/admin-api/routes/publish.d.ts +2 -1
- package/dist/admin-api/routes/publish.d.ts.map +1 -1
- package/dist/admin-api/routes/publish.js +213 -66
- package/dist/admin-api/routes/publish.js.map +1 -1
- package/dist/admin-api/routes/site.d.ts +2 -2
- package/dist/admin-api/routes/site.d.ts.map +1 -1
- package/dist/admin-api/routes/site.js +27 -4
- package/dist/admin-api/routes/site.js.map +1 -1
- package/dist/admin-api/routes/templates.d.ts +2 -2
- package/dist/admin-api/routes/templates.d.ts.map +1 -1
- package/dist/admin-api/routes/templates.js +19 -9
- package/dist/admin-api/routes/templates.js.map +1 -1
- package/dist/admin-api/schemas/compare.d.ts +29 -0
- package/dist/admin-api/schemas/compare.d.ts.map +1 -0
- package/dist/admin-api/schemas/compare.js +30 -0
- package/dist/admin-api/schemas/compare.js.map +1 -0
- package/dist/admin-api/schemas/dependents.d.ts +15 -0
- package/dist/admin-api/schemas/dependents.d.ts.map +1 -0
- package/dist/admin-api/schemas/dependents.js +14 -0
- package/dist/admin-api/schemas/dependents.js.map +1 -0
- package/dist/admin-api/schemas/fetch.d.ts +12 -0
- package/dist/admin-api/schemas/fetch.d.ts.map +1 -0
- package/dist/admin-api/schemas/fetch.js +11 -0
- package/dist/admin-api/schemas/fetch.js.map +1 -0
- package/dist/admin-api/schemas/fields.d.ts +11 -0
- package/dist/admin-api/schemas/fields.d.ts.map +1 -0
- package/dist/admin-api/schemas/fields.js +11 -0
- package/dist/admin-api/schemas/fields.js.map +1 -0
- package/dist/admin-api/schemas/fragments.d.ts +27 -0
- package/dist/admin-api/schemas/fragments.d.ts.map +1 -0
- package/dist/admin-api/schemas/fragments.js +26 -0
- package/dist/admin-api/schemas/fragments.js.map +1 -0
- package/dist/admin-api/schemas/history.d.ts +73 -0
- package/dist/admin-api/schemas/history.d.ts.map +1 -0
- package/dist/admin-api/schemas/history.js +35 -0
- package/dist/admin-api/schemas/history.js.map +1 -0
- package/dist/admin-api/schemas/index.d.ts +32 -0
- package/dist/admin-api/schemas/index.d.ts.map +1 -0
- package/dist/admin-api/schemas/index.js +32 -0
- package/dist/admin-api/schemas/index.js.map +1 -0
- package/dist/admin-api/schemas/pages.d.ts +46 -0
- package/dist/admin-api/schemas/pages.d.ts.map +1 -0
- package/dist/admin-api/schemas/pages.js +47 -0
- package/dist/admin-api/schemas/pages.js.map +1 -0
- package/dist/admin-api/schemas/publish.d.ts +67 -0
- package/dist/admin-api/schemas/publish.d.ts.map +1 -0
- package/dist/admin-api/schemas/publish.js +60 -0
- package/dist/admin-api/schemas/publish.js.map +1 -0
- package/dist/admin-api/schemas/site.d.ts +28 -0
- package/dist/admin-api/schemas/site.d.ts.map +1 -0
- package/dist/admin-api/schemas/site.js +24 -0
- package/dist/admin-api/schemas/site.js.map +1 -0
- package/dist/admin-api/schemas/targets.d.ts +36 -0
- package/dist/admin-api/schemas/targets.d.ts.map +1 -0
- package/dist/admin-api/schemas/targets.js +19 -0
- package/dist/admin-api/schemas/targets.js.map +1 -0
- package/dist/admin-api/schemas/templates.d.ts +17 -0
- package/dist/admin-api/schemas/templates.d.ts.map +1 -0
- package/dist/admin-api/schemas/templates.js +16 -0
- package/dist/admin-api/schemas/templates.js.map +1 -0
- package/dist/admin-api/source-context.d.ts +165 -0
- package/dist/admin-api/source-context.d.ts.map +1 -0
- package/dist/admin-api/source-context.js +95 -0
- package/dist/admin-api/source-context.js.map +1 -0
- package/dist/app.js +1 -1
- package/dist/app.js.map +1 -1
- package/dist/assemble.d.ts.map +1 -1
- package/dist/assemble.js +4 -1
- package/dist/assemble.js.map +1 -1
- package/dist/cli/bootstrap.d.ts +48 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +85 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/history.d.ts +45 -0
- package/dist/cli/history.d.ts.map +1 -0
- package/dist/cli/history.js +165 -0
- package/dist/cli/history.js.map +1 -0
- package/dist/cli/index.js +630 -115
- package/dist/cli/index.js.map +1 -1
- package/dist/compare.d.ts +8 -5
- package/dist/compare.d.ts.map +1 -1
- package/dist/compare.js +53 -14
- package/dist/compare.js.map +1 -1
- package/dist/content-root.d.ts +38 -0
- package/dist/content-root.d.ts.map +1 -0
- package/dist/content-root.js +29 -0
- package/dist/content-root.js.map +1 -0
- package/dist/editor/mount.d.ts +1 -1
- package/dist/editor/mount.d.ts.map +1 -1
- package/dist/editor/mount.js +61 -29
- package/dist/editor/mount.js.map +1 -1
- package/dist/hash.d.ts +34 -3
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +64 -7
- package/dist/hash.js.map +1 -1
- package/dist/history-provider.d.ts +49 -0
- package/dist/history-provider.d.ts.map +1 -0
- package/dist/history-provider.js +226 -0
- package/dist/history-provider.js.map +1 -0
- package/dist/history-recorder.d.ts +98 -0
- package/dist/history-recorder.d.ts.map +1 -0
- package/dist/history-recorder.js +160 -0
- package/dist/history-recorder.js.map +1 -0
- package/dist/history-restorer.d.ts +46 -0
- package/dist/history-restorer.d.ts.map +1 -0
- package/dist/history-restorer.js +105 -0
- package/dist/history-restorer.js.map +1 -0
- package/dist/history.d.ts +111 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +25 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +26 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -3
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +74 -0
- package/dist/locale.d.ts.map +1 -0
- package/dist/locale.js +150 -0
- package/dist/locale.js.map +1 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +16 -1
- package/dist/manifest.js.map +1 -1
- package/dist/providers/azure-blob.d.ts.map +1 -1
- package/dist/providers/azure-blob.js.map +1 -1
- package/dist/providers/r2.d.ts.map +1 -1
- package/dist/providers/r2.js +7 -4
- package/dist/providers/r2.js.map +1 -1
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +23 -15
- package/dist/providers/s3.js.map +1 -1
- package/dist/publish-locale.d.ts +44 -0
- package/dist/publish-locale.d.ts.map +1 -0
- package/dist/publish-locale.js +103 -0
- package/dist/publish-locale.js.map +1 -0
- package/dist/publish-rendered.d.ts +16 -5
- package/dist/publish-rendered.d.ts.map +1 -1
- package/dist/publish-rendered.js +89 -36
- package/dist/publish-rendered.js.map +1 -1
- package/dist/publish.d.ts +5 -7
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +21 -12
- package/dist/publish.js.map +1 -1
- package/dist/renderer.d.ts +14 -4
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +35 -23
- package/dist/renderer.js.map +1 -1
- package/dist/resolver.d.ts +7 -2
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +66 -15
- package/dist/resolver.js.map +1 -1
- package/dist/robots.d.ts +22 -0
- package/dist/robots.d.ts.map +1 -0
- package/dist/robots.js +25 -0
- package/dist/robots.js.map +1 -0
- package/dist/seo.d.ts +56 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +72 -0
- package/dist/seo.js.map +1 -0
- package/dist/serve.d.ts +41 -3
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +206 -65
- package/dist/serve.js.map +1 -1
- package/dist/sidecars.d.ts +9 -5
- package/dist/sidecars.d.ts.map +1 -1
- package/dist/sidecars.js +112 -22
- package/dist/sidecars.js.map +1 -1
- package/dist/site-loader.d.ts +74 -6
- package/dist/site-loader.d.ts.map +1 -1
- package/dist/site-loader.js +138 -28
- package/dist/site-loader.js.map +1 -1
- package/dist/sitemap.d.ts +45 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/sitemap.js +67 -0
- package/dist/sitemap.js.map +1 -0
- package/dist/source-sidecars.d.ts +21 -2
- package/dist/source-sidecars.d.ts.map +1 -1
- package/dist/source-sidecars.js +51 -5
- package/dist/source-sidecars.js.map +1 -1
- package/dist/targets.d.ts +47 -1
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +78 -9
- package/dist/targets.js.map +1 -1
- package/dist/template-loader.d.ts +7 -3
- package/dist/template-loader.d.ts.map +1 -1
- package/dist/template-loader.js +27 -12
- package/dist/template-loader.js.map +1 -1
- package/dist/templates-scan-worker.js +1 -1
- package/dist/templates-scan-worker.js.map +1 -1
- package/dist/templates-scan.d.ts.map +1 -1
- package/dist/templates-scan.js +1 -1
- package/dist/templates-scan.js.map +1 -1
- package/dist/types.d.ts +116 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +28 -5
- package/dist/types.js.map +1 -1
- package/dist/workers/cloudflare-r2.d.ts +11 -2
- package/dist/workers/cloudflare-r2.d.ts.map +1 -1
- package/dist/workers/cloudflare-r2.js +120 -55
- package/dist/workers/cloudflare-r2.js.map +1 -1
- package/package.json +11 -2
- package/admin-dist/assets/index-BZAFKsUp.js +0 -608
- package/admin-dist/assets/index-BpRotMuK.css +0 -1
- package/admin-dist/assets/vendor-vue-DSjyxCX6.js +0 -1
package/dist/robots.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Robots.txt generation — produces a default robots.txt or copies
|
|
3
|
+
* a user-authored one from the site directory.
|
|
4
|
+
*
|
|
5
|
+
* SRP: this module owns robots.txt content resolution. The caller
|
|
6
|
+
* checks for a user file and writes the result to storage.
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* 1. If the site has a `robots.txt` file, use it verbatim.
|
|
10
|
+
* 2. Otherwise, generate a permissive default with a Sitemap
|
|
11
|
+
* reference (when siteUrl is available).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Generate a default robots.txt. Permissive (allow all crawlers)
|
|
15
|
+
* with a Sitemap reference when siteUrl is available.
|
|
16
|
+
*/
|
|
17
|
+
export function generateRobotsTxt(opts) {
|
|
18
|
+
const lines = ['User-agent: *', 'Allow: /'];
|
|
19
|
+
if (opts.siteUrl) {
|
|
20
|
+
const base = opts.siteUrl.replace(/\/+$/, '');
|
|
21
|
+
lines.push('', `Sitemap: ${base}/sitemap.xml`);
|
|
22
|
+
}
|
|
23
|
+
return lines.join('\n') + '\n';
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=robots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA2B;IAC3D,MAAM,KAAK,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IAC3C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,IAAI,cAAc,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAChC,CAAC"}
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEO tag resolution — computes `<head>` tags from a fallback chain:
|
|
3
|
+
* metadata field → content field → site default → omit
|
|
4
|
+
*
|
|
5
|
+
* Single responsibility: this module owns the fallback logic and HTML
|
|
6
|
+
* tag generation for SEO. The renderer calls `resolveSeoTags()` and
|
|
7
|
+
* injects the result into `<head>` — it doesn't know about title
|
|
8
|
+
* truncation, OG deduplication, or robots directives.
|
|
9
|
+
*
|
|
10
|
+
* Open for extension: adding a new tag type is a new block in
|
|
11
|
+
* `resolveSeoTags()`, not a change to the renderer.
|
|
12
|
+
*/
|
|
13
|
+
import type { PageMetadata } from './types.js';
|
|
14
|
+
/** Escape HTML attribute values — prevents XSS in generated meta tags. */
|
|
15
|
+
export declare function escapeAttr(s: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* SEO context for a rendering pass — assembled by the caller from
|
|
18
|
+
* whatever sources it has (site manifest, target config, etc.).
|
|
19
|
+
* The renderer and seo module depend on this interface only, not
|
|
20
|
+
* on SiteManifest or TargetConfig (DIP).
|
|
21
|
+
*/
|
|
22
|
+
export interface SeoContext {
|
|
23
|
+
/** Site name — appended to auto-generated titles ("Page — Site Name"). */
|
|
24
|
+
siteName?: string;
|
|
25
|
+
/** Target's public URL for canonical/og:url (e.g. "https://gazetta.studio"). */
|
|
26
|
+
siteUrl?: string;
|
|
27
|
+
/** Site locale for `<html lang>` (e.g. "en", "fr"). Default: "en". */
|
|
28
|
+
locale?: string;
|
|
29
|
+
/** Default OG image for pages that don't specify their own. */
|
|
30
|
+
defaultOgImage?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Locale alternates for hreflang — maps locale code to absolute URL.
|
|
33
|
+
* Only set for subpath targets (same domain, all locales).
|
|
34
|
+
* Cross-domain hreflang is handled via sitemap, not HTML tags.
|
|
35
|
+
* Example: { en: "https://example.com/about", fr: "https://example.com/fr/about" }
|
|
36
|
+
*/
|
|
37
|
+
hreflangAlternates?: Record<string, string>;
|
|
38
|
+
/** The default locale code — used for x-default hreflang. */
|
|
39
|
+
defaultLocale?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ResolveSeoTagsInput {
|
|
42
|
+
metadata?: PageMetadata;
|
|
43
|
+
content?: Record<string, unknown>;
|
|
44
|
+
route?: string;
|
|
45
|
+
seo: SeoContext;
|
|
46
|
+
/** Template-provided head HTML — tags already present won't be duplicated. */
|
|
47
|
+
templateHead?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve all SEO `<head>` tags using the fallback chain. Returns raw
|
|
51
|
+
* HTML string for injection. Template-provided tags are checked for
|
|
52
|
+
* duplicates — a metadata tag is only emitted when the template head
|
|
53
|
+
* doesn't already include it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveSeoTags(input: ResolveSeoTagsInput): string;
|
|
56
|
+
//# sourceMappingURL=seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,UAAU,CAAA;IACf,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAyEjE"}
|
package/dist/seo.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Escape HTML attribute values — prevents XSS in generated meta tags. */
|
|
2
|
+
export function escapeAttr(s) {
|
|
3
|
+
return s.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve all SEO `<head>` tags using the fallback chain. Returns raw
|
|
7
|
+
* HTML string for injection. Template-provided tags are checked for
|
|
8
|
+
* duplicates — a metadata tag is only emitted when the template head
|
|
9
|
+
* doesn't already include it.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveSeoTags(input) {
|
|
12
|
+
const { metadata: meta, content, route, seo, templateHead } = input;
|
|
13
|
+
const parts = [];
|
|
14
|
+
// Title: metadata.title → content.title + " — " + siteName → omit
|
|
15
|
+
const title = meta?.title || (content?.title ? `${content.title}${seo.siteName ? ` — ${seo.siteName}` : ''}` : undefined);
|
|
16
|
+
if (title && !templateHead?.includes('<title')) {
|
|
17
|
+
parts.push(`<title>${escapeAttr(title)}</title>`);
|
|
18
|
+
}
|
|
19
|
+
// Description: metadata.description → content.description → omit
|
|
20
|
+
const description = meta?.description || content?.description;
|
|
21
|
+
if (description && !templateHead?.includes('name="description"')) {
|
|
22
|
+
parts.push(`<meta name="description" content="${escapeAttr(description)}">`);
|
|
23
|
+
}
|
|
24
|
+
// Canonical: metadata.canonical → siteUrl + route → omit
|
|
25
|
+
const base = seo.siteUrl?.replace(/\/+$/, '');
|
|
26
|
+
const canonical = meta?.canonical || (base && route ? `${base}${route}` : undefined);
|
|
27
|
+
if (canonical) {
|
|
28
|
+
parts.push(`<link rel="canonical" href="${escapeAttr(canonical)}">`);
|
|
29
|
+
}
|
|
30
|
+
// OG image: metadata.ogImage → site.defaultOgImage → omit
|
|
31
|
+
const ogImage = meta?.ogImage || seo.defaultOgImage;
|
|
32
|
+
if (ogImage) {
|
|
33
|
+
parts.push(`<meta property="og:image" content="${escapeAttr(ogImage)}">`);
|
|
34
|
+
}
|
|
35
|
+
// OG title: same chain as <title>
|
|
36
|
+
if (title && !templateHead?.includes('property="og:title"')) {
|
|
37
|
+
parts.push(`<meta property="og:title" content="${escapeAttr(title)}">`);
|
|
38
|
+
}
|
|
39
|
+
// OG description: same chain as description
|
|
40
|
+
if (description && !templateHead?.includes('property="og:description"')) {
|
|
41
|
+
parts.push(`<meta property="og:description" content="${escapeAttr(description)}">`);
|
|
42
|
+
}
|
|
43
|
+
// OG URL: same as canonical
|
|
44
|
+
if (canonical && !templateHead?.includes('property="og:url"')) {
|
|
45
|
+
parts.push(`<meta property="og:url" content="${escapeAttr(canonical)}">`);
|
|
46
|
+
}
|
|
47
|
+
// OG type: always "website"
|
|
48
|
+
if (!templateHead?.includes('property="og:type"')) {
|
|
49
|
+
parts.push('<meta property="og:type" content="website">');
|
|
50
|
+
}
|
|
51
|
+
// Twitter card: summary_large_image when OG image present, summary otherwise
|
|
52
|
+
if (!templateHead?.includes('name="twitter:card"')) {
|
|
53
|
+
parts.push(`<meta name="twitter:card" content="${ogImage ? 'summary_large_image' : 'summary'}">`);
|
|
54
|
+
}
|
|
55
|
+
// Robots: only when explicitly set (absence = allow indexing)
|
|
56
|
+
if (meta?.robots) {
|
|
57
|
+
parts.push(`<meta name="robots" content="${escapeAttr(meta.robots)}">`);
|
|
58
|
+
}
|
|
59
|
+
// hreflang alternates (subpath targets only — cross-domain uses sitemap)
|
|
60
|
+
if (seo.hreflangAlternates && Object.keys(seo.hreflangAlternates).length > 1) {
|
|
61
|
+
for (const [locale, url] of Object.entries(seo.hreflangAlternates)) {
|
|
62
|
+
parts.push(`<link rel="alternate" hreflang="${escapeAttr(locale)}" href="${escapeAttr(url)}">`);
|
|
63
|
+
}
|
|
64
|
+
// x-default points to the default locale URL
|
|
65
|
+
const defaultUrl = seo.defaultLocale && seo.hreflangAlternates[seo.defaultLocale];
|
|
66
|
+
if (defaultUrl) {
|
|
67
|
+
parts.push(`<link rel="alternate" hreflang="x-default" href="${escapeAttr(defaultUrl)}">`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return parts.join('\n ');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=seo.js.map
|
package/dist/seo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.js","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.d.ts
CHANGED
|
@@ -2,13 +2,51 @@
|
|
|
2
2
|
* Gazetta Node production server — serves pages from any StorageProvider
|
|
3
3
|
* with ESI fragment assembly. Same role as the Cloudflare Worker, but
|
|
4
4
|
* runs on Node/Bun for self-hosted deployments (VPS, Docker, Fly.io).
|
|
5
|
+
*
|
|
6
|
+
* SOLID breakdown:
|
|
7
|
+
* - extractLocale: strips locale prefix from URL (SRP)
|
|
8
|
+
* - fetchFragment: reads a fragment file with locale fallback (SRP)
|
|
9
|
+
* - findPage: resolves a request path to page HTML (SRP)
|
|
10
|
+
* - acceptLanguageRedirect: middleware for language detection (SRP, OCP)
|
|
11
|
+
* - createServer: composes the above into a Hono app
|
|
5
12
|
*/
|
|
6
13
|
import { Hono } from 'hono';
|
|
7
|
-
import type { StorageProvider } from './types.js';
|
|
14
|
+
import type { StorageProvider, TargetType } from './types.js';
|
|
8
15
|
export interface ServeOptions {
|
|
9
16
|
storage: StorageProvider;
|
|
10
|
-
/**
|
|
11
|
-
|
|
17
|
+
/** Target type: 'dynamic' assembles fragments at request time (ESI), 'static' serves pre-rendered HTML directly */
|
|
18
|
+
type?: TargetType;
|
|
19
|
+
/** Supported locale codes (lowercase). When set, enables locale-prefix routing (e.g. /fr/about → pages/about/index.fr.html). */
|
|
20
|
+
locales?: string[];
|
|
21
|
+
/** Default locale — requests to the default locale have no URL prefix. Falls back to first in `locales`. */
|
|
22
|
+
defaultLocale?: string;
|
|
23
|
+
/** When true, redirects unlocalized requests to the best Accept-Language match (302). */
|
|
24
|
+
detection?: boolean;
|
|
12
25
|
}
|
|
26
|
+
export interface LocaleRoute {
|
|
27
|
+
/** The locale extracted from the URL prefix, or undefined for default locale requests. */
|
|
28
|
+
locale: string | undefined;
|
|
29
|
+
/** The request path with locale prefix stripped. */
|
|
30
|
+
path: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract a locale prefix from a request path. Returns the locale (if any)
|
|
34
|
+
* and the remaining path. Only matches against the provided supported set.
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractLocale(requestPath: string, locales: string[]): LocaleRoute;
|
|
37
|
+
/**
|
|
38
|
+
* Parse the Accept-Language header and return the best matching locale
|
|
39
|
+
* from the supported set. Returns undefined if no match.
|
|
40
|
+
*/
|
|
41
|
+
export declare function matchAcceptLanguage(header: string | undefined, locales: string[]): string | undefined;
|
|
42
|
+
export interface FindPageResult {
|
|
43
|
+
html: string;
|
|
44
|
+
locale: string | undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve a request path to page HTML. Handles locale-suffixed files
|
|
48
|
+
* (index.fr.html) and dynamic route segments ([param]).
|
|
49
|
+
*/
|
|
50
|
+
export declare function findPage(storage: StorageProvider, requestPath: string, locales?: string[]): Promise<FindPageResult | null>;
|
|
13
51
|
export declare function createServer(options: ServeOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
14
52
|
//# sourceMappingURL=serve.d.ts.map
|
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG7D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,eAAe,CAAA;IACxB,mHAAmH;IACnH,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,gIAAgI;IAChI,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,4GAA4G;IAC5G,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,yFAAyF;IACzF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAMD,MAAM,WAAW,WAAW;IAC1B,0FAA0F;IAC1F,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,CAOjF;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAkBrG;AAiCD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAqDhC;AAMD,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,8EA6HjD"}
|
package/dist/serve.js
CHANGED
|
@@ -2,18 +2,158 @@
|
|
|
2
2
|
* Gazetta Node production server — serves pages from any StorageProvider
|
|
3
3
|
* with ESI fragment assembly. Same role as the Cloudflare Worker, but
|
|
4
4
|
* runs on Node/Bun for self-hosted deployments (VPS, Docker, Fly.io).
|
|
5
|
+
*
|
|
6
|
+
* SOLID breakdown:
|
|
7
|
+
* - extractLocale: strips locale prefix from URL (SRP)
|
|
8
|
+
* - fetchFragment: reads a fragment file with locale fallback (SRP)
|
|
9
|
+
* - findPage: resolves a request path to page HTML (SRP)
|
|
10
|
+
* - acceptLanguageRedirect: middleware for language detection (SRP, OCP)
|
|
11
|
+
* - createServer: composes the above into a Hono app
|
|
5
12
|
*/
|
|
6
13
|
import { Hono } from 'hono';
|
|
7
14
|
import { logger } from 'hono/logger';
|
|
8
15
|
import { createHash } from 'node:crypto';
|
|
9
16
|
import { assembleEsi, parseCacheComment, splitFragment, findEsiPaths } from './assemble.js';
|
|
17
|
+
/**
|
|
18
|
+
* Extract a locale prefix from a request path. Returns the locale (if any)
|
|
19
|
+
* and the remaining path. Only matches against the provided supported set.
|
|
20
|
+
*/
|
|
21
|
+
export function extractLocale(requestPath, locales) {
|
|
22
|
+
if (locales.length === 0)
|
|
23
|
+
return { locale: undefined, path: requestPath };
|
|
24
|
+
const parts = requestPath.split('/').filter(Boolean);
|
|
25
|
+
if (parts.length > 0 && locales.includes(parts[0])) {
|
|
26
|
+
return { locale: parts[0], path: '/' + parts.slice(1).join('/') || '/' };
|
|
27
|
+
}
|
|
28
|
+
return { locale: undefined, path: requestPath };
|
|
29
|
+
}
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Accept-Language detection (SRP, OCP — pluggable middleware)
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Parse the Accept-Language header and return the best matching locale
|
|
35
|
+
* from the supported set. Returns undefined if no match.
|
|
36
|
+
*/
|
|
37
|
+
export function matchAcceptLanguage(header, locales) {
|
|
38
|
+
if (!header || locales.length === 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
// Parse Accept-Language: fr-FR,fr;q=0.9,en;q=0.8 → sorted by quality
|
|
41
|
+
const entries = header.split(',').map(part => {
|
|
42
|
+
const [lang, ...params] = part.trim().split(';');
|
|
43
|
+
const q = params.find(p => p.trim().startsWith('q='));
|
|
44
|
+
return { lang: lang.trim().toLowerCase(), q: q ? parseFloat(q.trim().slice(2)) : 1 };
|
|
45
|
+
});
|
|
46
|
+
entries.sort((a, b) => b.q - a.q);
|
|
47
|
+
for (const { lang } of entries) {
|
|
48
|
+
// Exact match (e.g. fr-fr → fr-fr)
|
|
49
|
+
if (locales.includes(lang))
|
|
50
|
+
return lang;
|
|
51
|
+
// Language-only match (e.g. fr-fr → fr)
|
|
52
|
+
const base = lang.split('-')[0];
|
|
53
|
+
if (locales.includes(base))
|
|
54
|
+
return base;
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
async function fetchFragment(storage, path) {
|
|
59
|
+
try {
|
|
60
|
+
return [path, splitFragment(await storage.readFile(path.slice(1)))];
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Locale fragment not found — fall back to default locale
|
|
64
|
+
// e.g. /fragments/header/index.fr.html → /fragments/header/index.html
|
|
65
|
+
const localeFallback = path.replace(/\/index\.[a-z-]+\.html$/, '/index.html');
|
|
66
|
+
if (localeFallback !== path) {
|
|
67
|
+
try {
|
|
68
|
+
return [path, splitFragment(await storage.readFile(localeFallback.slice(1)))];
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* fallback also missing */
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return [path, { head: '', body: `<!-- fragment not found: ${path} -->` }];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a request path to page HTML. Handles locale-suffixed files
|
|
79
|
+
* (index.fr.html) and dynamic route segments ([param]).
|
|
80
|
+
*/
|
|
81
|
+
export async function findPage(storage, requestPath, locales) {
|
|
82
|
+
const { locale, path: resolvedPath } = locales?.length
|
|
83
|
+
? extractLocale(requestPath, locales)
|
|
84
|
+
: { locale: undefined, path: requestPath };
|
|
85
|
+
const indexFile = locale ? `index.${locale}.html` : 'index.html';
|
|
86
|
+
// Try exact page path
|
|
87
|
+
const pagePath = resolvedPath === '/' ? `pages/home/${indexFile}` : `pages${resolvedPath}/${indexFile}`;
|
|
88
|
+
try {
|
|
89
|
+
return { html: await storage.readFile(pagePath), locale };
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Locale page not found — fall back to default locale file
|
|
93
|
+
if (locale) {
|
|
94
|
+
const fallback = resolvedPath === '/' ? 'pages/home/index.html' : `pages${resolvedPath}/index.html`;
|
|
95
|
+
try {
|
|
96
|
+
return { html: await storage.readFile(fallback), locale };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
/* fallback also missing — continue to dynamic routes */
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Dynamic segments — list parent dir, find [param] entries
|
|
104
|
+
const parts = resolvedPath.split('/').filter(Boolean);
|
|
105
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
106
|
+
const parentDir = parts.slice(0, i).join('/');
|
|
107
|
+
const prefix = parentDir ? `pages/${parentDir}` : 'pages';
|
|
108
|
+
try {
|
|
109
|
+
const entries = await storage.readDir(prefix);
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (entry.isDirectory && entry.name.startsWith('[') && entry.name.endsWith(']')) {
|
|
112
|
+
const dynamicParts = [...parts];
|
|
113
|
+
dynamicParts[i] = entry.name;
|
|
114
|
+
const dynamicPath = `pages/${dynamicParts.join('/')}/${indexFile}`;
|
|
115
|
+
try {
|
|
116
|
+
return { html: await storage.readFile(dynamicPath), locale };
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
if (locale) {
|
|
120
|
+
try {
|
|
121
|
+
return { html: await storage.readFile(`pages/${dynamicParts.join('/')}/index.html`), locale };
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
/* fallback also missing */
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
/* dir not found */
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// Server composition
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
10
140
|
export function createServer(options) {
|
|
11
|
-
const { storage,
|
|
141
|
+
const { storage, type = 'dynamic', locales, defaultLocale, detection } = options;
|
|
142
|
+
const nonDefaultLocales = locales?.filter(l => l !== (defaultLocale ?? locales?.[0])) ?? [];
|
|
12
143
|
const app = new Hono();
|
|
13
144
|
app.use(logger());
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
145
|
+
// Strip trailing slashes — normalize /fr/ to /fr, /about/ to /about.
|
|
146
|
+
// Re-dispatches through Hono router. No redirect — preserves POST body.
|
|
147
|
+
app.use(async (c, next) => {
|
|
148
|
+
const url = new URL(c.req.url);
|
|
149
|
+
if (url.pathname !== '/' && url.pathname.endsWith('/')) {
|
|
150
|
+
url.pathname = url.pathname.slice(0, -1);
|
|
151
|
+
return app.fetch(new Request(url, c.req.raw), c.env);
|
|
152
|
+
}
|
|
153
|
+
return next();
|
|
154
|
+
});
|
|
155
|
+
app.get('/health', c => c.json({ ok: true }));
|
|
156
|
+
if (type === 'static') {
|
|
17
157
|
app.get('*', async (c) => {
|
|
18
158
|
const requestPath = new URL(c.req.url).pathname;
|
|
19
159
|
const filePath = requestPath === '/' ? 'index.html' : `${requestPath.replace(/\/$/, '')}/index.html`;
|
|
@@ -22,10 +162,9 @@ export function createServer(options) {
|
|
|
22
162
|
const etag = `"${createHash('sha256').update(html).digest('hex').slice(0, 16)}"`;
|
|
23
163
|
if (c.req.header('If-None-Match') === etag)
|
|
24
164
|
return new Response(null, { status: 304, headers: { ETag: etag } });
|
|
25
|
-
return c.html(html, 200, { 'Cache-Control': 'public, max-age=0, must-revalidate',
|
|
165
|
+
return c.html(html, 200, { 'Cache-Control': 'public, max-age=0, must-revalidate', ETag: etag });
|
|
26
166
|
}
|
|
27
167
|
catch {
|
|
28
|
-
// Try without /index.html (bare file)
|
|
29
168
|
try {
|
|
30
169
|
const html = await storage.readFile(requestPath.slice(1));
|
|
31
170
|
return c.html(html);
|
|
@@ -38,52 +177,82 @@ export function createServer(options) {
|
|
|
38
177
|
return app;
|
|
39
178
|
}
|
|
40
179
|
// ESI mode — assemble fragments at request time
|
|
180
|
+
// Root-level files (sitemap.xml, robots.txt) — served from storage
|
|
181
|
+
app.get('/sitemap.xml', async (c) => {
|
|
182
|
+
try {
|
|
183
|
+
const content = await storage.readFile('sitemap.xml');
|
|
184
|
+
return new Response(content, {
|
|
185
|
+
headers: { 'Content-Type': 'application/xml; charset=utf-8', 'Cache-Control': 'public, max-age=3600' },
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return c.notFound();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
app.get('/robots.txt', async (c) => {
|
|
193
|
+
try {
|
|
194
|
+
const content = await storage.readFile('robots.txt');
|
|
195
|
+
return new Response(content, {
|
|
196
|
+
headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'public, max-age=3600' },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return c.notFound();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
41
203
|
// Hashed CSS/JS — immutable cache
|
|
42
204
|
app.get('/pages/*', async (c) => serveAsset(c, storage));
|
|
43
205
|
app.get('/fragments/*', async (c) => serveAsset(c, storage));
|
|
206
|
+
// Accept-Language detection — redirect unlocalized requests to best match
|
|
207
|
+
if (detection && nonDefaultLocales.length > 0) {
|
|
208
|
+
app.get('*', async (c, next) => {
|
|
209
|
+
const requestPath = new URL(c.req.url).pathname;
|
|
210
|
+
// Only redirect paths that don't already have a locale prefix
|
|
211
|
+
const { locale: existingLocale } = extractLocale(requestPath, nonDefaultLocales);
|
|
212
|
+
if (existingLocale)
|
|
213
|
+
return next();
|
|
214
|
+
// Check cookie opt-out (user explicitly chose a locale)
|
|
215
|
+
const localeCookie = c.req.header('Cookie')?.match(/(?:^|;\s*)locale=([a-z-]+)/)?.[1];
|
|
216
|
+
if (localeCookie && nonDefaultLocales.includes(localeCookie)) {
|
|
217
|
+
return c.redirect(`/${localeCookie}${requestPath === '/' ? '' : requestPath}`, 302);
|
|
218
|
+
}
|
|
219
|
+
// Match Accept-Language against non-default locales
|
|
220
|
+
const match = matchAcceptLanguage(c.req.header('Accept-Language'), nonDefaultLocales);
|
|
221
|
+
if (match)
|
|
222
|
+
return c.redirect(`/${match}${requestPath === '/' ? '' : requestPath}`, 302);
|
|
223
|
+
return next();
|
|
224
|
+
});
|
|
225
|
+
}
|
|
44
226
|
// Page serving with ESI assembly
|
|
45
227
|
app.get('*', async (c) => {
|
|
46
228
|
const requestPath = new URL(c.req.url).pathname;
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
const fragPaths = findEsiPaths(raw404);
|
|
54
|
-
const fragEntries = await Promise.all(fragPaths.map(async (p) => {
|
|
55
|
-
try {
|
|
56
|
-
return [p, splitFragment(await storage.readFile(p.slice(1)))];
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
return [p, { head: '', body: '' }];
|
|
60
|
-
}
|
|
61
|
-
}));
|
|
229
|
+
const result = await findPage(storage, requestPath, locales);
|
|
230
|
+
if (!result) {
|
|
231
|
+
const notFound = await findPage(storage, '/404');
|
|
232
|
+
if (notFound) {
|
|
233
|
+
const { html: raw404 } = parseCacheComment(notFound.html);
|
|
234
|
+
const fragEntries = await Promise.all(findEsiPaths(raw404).map(p => fetchFragment(storage, p)));
|
|
62
235
|
return c.html(assembleEsi(raw404, new Map(fragEntries)), 404);
|
|
63
236
|
}
|
|
64
237
|
return c.html('<h1>404 — Page not found</h1>', 404);
|
|
65
238
|
}
|
|
66
|
-
const { html: rawHtml, browser, edge } = parseCacheComment(
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
const fragmentEntries = await Promise.all(fragmentPaths.map(async (path) => {
|
|
70
|
-
try {
|
|
71
|
-
const html = await storage.readFile(path.slice(1));
|
|
72
|
-
return [path, splitFragment(html)];
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
return [path, { head: '', body: `<!-- fragment not found: ${path} -->` }];
|
|
76
|
-
}
|
|
77
|
-
}));
|
|
78
|
-
const html = assembleEsi(rawHtml, new Map(fragmentEntries));
|
|
239
|
+
const { html: rawHtml, browser, edge } = parseCacheComment(result.html);
|
|
240
|
+
const fragEntries = await Promise.all(findEsiPaths(rawHtml).map(p => fetchFragment(storage, p)));
|
|
241
|
+
const html = assembleEsi(rawHtml, new Map(fragEntries));
|
|
79
242
|
const etag = `"${createHash('sha256').update(html).digest('hex').slice(0, 16)}"`;
|
|
80
243
|
if (c.req.header('If-None-Match') === etag) {
|
|
81
244
|
return new Response(null, { status: 304, headers: { ETag: etag } });
|
|
82
245
|
}
|
|
83
|
-
|
|
246
|
+
const headers = {
|
|
84
247
|
'Cache-Control': `public, max-age=${browser}, s-maxage=${edge}`,
|
|
85
|
-
|
|
86
|
-
}
|
|
248
|
+
ETag: etag,
|
|
249
|
+
};
|
|
250
|
+
// Set locale cookie when visiting a locale-prefixed URL — persists the
|
|
251
|
+
// author's language choice so Accept-Language detection doesn't override it.
|
|
252
|
+
if (result.locale && nonDefaultLocales.length > 0) {
|
|
253
|
+
headers['Set-Cookie'] = `locale=${result.locale}; Path=/; SameSite=Lax; Max-Age=31536000`;
|
|
254
|
+
}
|
|
255
|
+
return c.html(html, 200, headers);
|
|
87
256
|
});
|
|
88
257
|
return app;
|
|
89
258
|
}
|
|
@@ -104,32 +273,4 @@ async function serveAsset(c, storage) {
|
|
|
104
273
|
return c.notFound();
|
|
105
274
|
}
|
|
106
275
|
}
|
|
107
|
-
async function findPage(storage, requestPath) {
|
|
108
|
-
const pagePath = requestPath === '/' ? 'pages/home/index.html' : `pages${requestPath}/index.html`;
|
|
109
|
-
try {
|
|
110
|
-
return await storage.readFile(pagePath);
|
|
111
|
-
}
|
|
112
|
-
catch { /* not found */ }
|
|
113
|
-
// Dynamic segments — list parent dir, find [param] entries
|
|
114
|
-
const parts = requestPath.split('/').filter(Boolean);
|
|
115
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
116
|
-
const parentDir = parts.slice(0, i).join('/');
|
|
117
|
-
const prefix = parentDir ? `pages/${parentDir}` : 'pages';
|
|
118
|
-
try {
|
|
119
|
-
const entries = await storage.readDir(prefix);
|
|
120
|
-
for (const entry of entries) {
|
|
121
|
-
if (entry.isDirectory && entry.name.startsWith('[') && entry.name.endsWith(']')) {
|
|
122
|
-
const dynamicParts = [...parts];
|
|
123
|
-
dynamicParts[i] = entry.name;
|
|
124
|
-
try {
|
|
125
|
-
return await storage.readFile(`pages/${dynamicParts.join('/')}/index.html`);
|
|
126
|
-
}
|
|
127
|
-
catch { /* not found */ }
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch { /* dir not found */ }
|
|
132
|
-
}
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
276
|
//# sourceMappingURL=serve.js.map
|
package/dist/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/sidecars.d.ts
CHANGED
|
@@ -16,11 +16,15 @@
|
|
|
16
16
|
* without touching every caller.
|
|
17
17
|
*/
|
|
18
18
|
import type { StorageProvider } from './types.js';
|
|
19
|
+
import { type PubSidecar } from './hash.js';
|
|
19
20
|
/** Full sidecar state for one page or fragment. */
|
|
20
21
|
export interface SidecarState {
|
|
21
22
|
hash: string;
|
|
22
23
|
uses: string[];
|
|
23
24
|
template: string | null;
|
|
25
|
+
/** Publish timestamp + noindex flag. Present only on target sidecars
|
|
26
|
+
* written by the publish pipeline; absent on source-side sidecars. */
|
|
27
|
+
pub: PubSidecar | null;
|
|
24
28
|
}
|
|
25
29
|
/**
|
|
26
30
|
* Read sidecar filenames for a single item directory. Returns null if
|
|
@@ -31,12 +35,12 @@ export interface SidecarState {
|
|
|
31
35
|
*/
|
|
32
36
|
export declare function readSidecars(storage: StorageProvider, dir: string): Promise<SidecarState | null>;
|
|
33
37
|
/**
|
|
34
|
-
* Write (or rewrite)
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* .uses
|
|
38
|
+
* Write (or rewrite) sidecars for one item, optionally locale-scoped.
|
|
39
|
+
* When `locale` is set, only locale-specific sidecars (.hash.fr, .pub.fr)
|
|
40
|
+
* are written/cleaned — default-locale sidecars are untouched. Structural
|
|
41
|
+
* sidecars (.uses-*, .tpl-*) are shared across locales (same components).
|
|
38
42
|
*/
|
|
39
|
-
export declare function writeSidecars(storage: StorageProvider, dir: string, state: SidecarState): Promise<void>;
|
|
43
|
+
export declare function writeSidecars(storage: StorageProvider, dir: string, state: SidecarState, locale?: string): Promise<void>;
|
|
40
44
|
/**
|
|
41
45
|
* Walk a directory tree collecting every sub-directory's sidecar state.
|
|
42
46
|
* Bounded-parallel recursion — flat Promise.all over 10k dirs would blow
|
package/dist/sidecars.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecars.d.ts","sourceRoot":"","sources":["../src/sidecars.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"sidecars.d.ts","sourceRoot":"","sources":["../src/sidecars.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAWL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAA;AAGlB,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB;2EACuE;IACvE,GAAG,EAAE,UAAU,GAAG,IAAI,CAAA;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAiCtG;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Cf;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAwBhH;AAoDD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAa/E"}
|