@timber-js/app 0.1.57 → 0.2.0-alpha.10
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/dist/_chunks/{als-registry-k-AtAQ9R.js → als-registry-B7DbZ2hS.js} +1 -1
- package/dist/_chunks/{als-registry-k-AtAQ9R.js.map → als-registry-B7DbZ2hS.js.map} +1 -1
- package/dist/_chunks/debug-gwlJkDuf.js +108 -0
- package/dist/_chunks/debug-gwlJkDuf.js.map +1 -0
- package/dist/_chunks/{format-DNt20Kt8.js → format-DviM89f0.js} +3 -2
- package/dist/_chunks/format-DviM89f0.js.map +1 -0
- package/dist/_chunks/{interception-DGDIjDbR.js → interception-BOoWmLUA.js} +2 -2
- package/dist/_chunks/{interception-DGDIjDbR.js.map → interception-BOoWmLUA.js.map} +1 -1
- package/dist/_chunks/{metadata-routes-CQCnF4VK.js → metadata-routes-Cjmvi3rQ.js} +1 -1
- package/dist/_chunks/{metadata-routes-CQCnF4VK.js.map → metadata-routes-Cjmvi3rQ.js.map} +1 -1
- package/dist/_chunks/{request-context-CRj2Zh1E.js → request-context-DIkVh_jG.js} +5 -4
- package/dist/_chunks/request-context-DIkVh_jG.js.map +1 -0
- package/dist/_chunks/{ssr-data-DLnbYpj1.js → ssr-data-MjmprTmO.js} +1 -1
- package/dist/_chunks/{ssr-data-DLnbYpj1.js.map → ssr-data-MjmprTmO.js.map} +1 -1
- package/dist/_chunks/{tracing-DF0G3FB7.js → tracing-CemImE6h.js} +17 -3
- package/dist/_chunks/{tracing-DF0G3FB7.js.map → tracing-CemImE6h.js.map} +1 -1
- package/dist/_chunks/{use-cookie-dDbpCTx-.js → use-cookie-DX-l1_5E.js} +2 -2
- package/dist/_chunks/{use-cookie-dDbpCTx-.js.map → use-cookie-DX-l1_5E.js.map} +1 -1
- package/dist/_chunks/{use-query-states-DAhgj8Gx.js → use-query-states-D5KaffOK.js} +1 -1
- package/dist/_chunks/{use-query-states-DAhgj8Gx.js.map → use-query-states-D5KaffOK.js.map} +1 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/fast-hash.d.ts +22 -0
- package/dist/cache/fast-hash.d.ts.map +1 -0
- package/dist/cache/index.js +52 -10
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/register-cached-function.d.ts.map +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/browser-entry.d.ts +1 -2
- package/dist/client/browser-entry.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +136 -94
- package/dist/client/index.js.map +1 -1
- package/dist/client/link.d.ts +12 -9
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +9 -3
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/segment-context.d.ts +1 -1
- package/dist/client/segment-context.d.ts.map +1 -1
- package/dist/client/segment-merger.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/transition-root.d.ts +1 -1
- package/dist/client/transition-root.d.ts.map +1 -1
- package/dist/cookies/index.js +4 -4
- package/dist/fonts/local.d.ts +4 -2
- package/dist/fonts/local.d.ts.map +1 -1
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +255 -21
- package/dist/index.js.map +1 -1
- package/dist/plugins/build-report.d.ts +11 -1
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/chunks.d.ts +9 -1
- package/dist/plugins/chunks.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +7 -0
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +9 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +6 -0
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/search-params/index.js +1 -1
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/debug.d.ts +82 -0
- package/dist/server/debug.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/index.js +22 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/response-cache.d.ts +54 -0
- package/dist/server/response-cache.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +6 -0
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-prop-warnings.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +10 -0
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/waituntil-bridge.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/nitro.ts +6 -1
- package/src/cache/fast-hash.ts +34 -0
- package/src/cache/register-cached-function.ts +7 -3
- package/src/cache/timber-cache.ts +17 -10
- package/src/client/browser-entry.ts +16 -24
- package/src/client/index.ts +1 -1
- package/src/client/link.tsx +97 -34
- package/src/client/navigation-context.ts +54 -14
- package/src/client/router.ts +4 -6
- package/src/client/segment-context.ts +6 -1
- package/src/client/segment-merger.ts +2 -8
- package/src/client/stale-reload.ts +5 -7
- package/src/client/top-loader.tsx +23 -15
- package/src/client/transition-root.tsx +7 -1
- package/src/fonts/local.ts +7 -3
- package/src/index.ts +41 -0
- package/src/plugins/build-report.ts +23 -3
- package/src/plugins/chunks.ts +9 -1
- package/src/plugins/entries.ts +10 -4
- package/src/plugins/fonts.ts +171 -19
- package/src/plugins/mdx.ts +9 -5
- package/src/plugins/server-bundle.ts +4 -0
- package/src/server/access-gate.tsx +3 -2
- package/src/server/action-client.ts +15 -5
- package/src/server/debug.ts +137 -0
- package/src/server/deny-renderer.ts +3 -2
- package/src/server/dev-warnings.ts +2 -1
- package/src/server/logger.ts +4 -3
- package/src/server/pipeline.ts +7 -0
- package/src/server/primitives.ts +2 -1
- package/src/server/request-context.ts +3 -2
- package/src/server/response-cache.ts +410 -0
- package/src/server/route-element-builder.ts +1 -6
- package/src/server/rsc-entry/index.ts +61 -14
- package/src/server/rsc-entry/rsc-payload.ts +42 -7
- package/src/server/rsc-entry/rsc-stream.ts +10 -5
- package/src/server/rsc-entry/ssr-renderer.ts +12 -5
- package/src/server/rsc-prop-warnings.ts +3 -1
- package/src/server/tracing.ts +23 -0
- package/src/server/waituntil-bridge.ts +4 -1
- package/dist/_chunks/format-DNt20Kt8.js.map +0 -1
- package/dist/_chunks/request-context-CRj2Zh1E.js.map +0 -1
- package/dist/client/browser-links.d.ts +0 -32
- package/dist/client/browser-links.d.ts.map +0 -1
- package/dist/client/link-navigate-interceptor.d.ts +0 -28
- package/dist/client/link-navigate-interceptor.d.ts.map +0 -1
- package/src/client/browser-links.ts +0 -90
- package/src/client/link-navigate-interceptor.tsx +0 -62
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as setViteServer, t as formatSize } from "./_chunks/format-
|
|
2
|
-
import { i as scanRoutes, n as generateRouteMap, t as collectInterceptionRewrites } from "./_chunks/interception-
|
|
1
|
+
import { r as setViteServer, t as formatSize } from "./_chunks/format-DviM89f0.js";
|
|
2
|
+
import { i as scanRoutes, n as generateRouteMap, t as collectInterceptionRewrites } from "./_chunks/interception-BOoWmLUA.js";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
-
import { dirname, extname, join, resolve } from "node:path";
|
|
4
|
+
import { dirname, extname, join, normalize, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import react from "@vitejs/plugin-react";
|
|
@@ -11933,7 +11933,9 @@ function generateConfigModule(ctx) {
|
|
|
11933
11933
|
slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,
|
|
11934
11934
|
slowRequestMs: ctx.config.slowRequestMs ?? 3e3,
|
|
11935
11935
|
cookieSecrets,
|
|
11936
|
-
topLoader: ctx.config.topLoader
|
|
11936
|
+
topLoader: ctx.config.topLoader,
|
|
11937
|
+
responseCache: ctx.config.responseCache,
|
|
11938
|
+
debug: ctx.config.debug ?? false
|
|
11937
11939
|
};
|
|
11938
11940
|
return [
|
|
11939
11941
|
"// Auto-generated runtime config — do not edit.",
|
|
@@ -11951,12 +11953,14 @@ function generateConfigModule(ctx) {
|
|
|
11951
11953
|
* extensions as timber.config.ts detection.
|
|
11952
11954
|
*/
|
|
11953
11955
|
function detectInstrumentationFile(root) {
|
|
11954
|
-
|
|
11956
|
+
const extensions = [
|
|
11955
11957
|
".ts",
|
|
11956
11958
|
".js",
|
|
11957
11959
|
".mjs"
|
|
11958
|
-
]
|
|
11959
|
-
|
|
11960
|
+
];
|
|
11961
|
+
const dirs = [root, resolve(root, "src")];
|
|
11962
|
+
for (const dir of dirs) for (const ext of extensions) {
|
|
11963
|
+
const candidate = resolve(dir, `instrumentation${ext}`);
|
|
11960
11964
|
if (existsSync(candidate)) return candidate;
|
|
11961
11965
|
}
|
|
11962
11966
|
return null;
|
|
@@ -12016,17 +12020,20 @@ function timberEntries(ctx) {
|
|
|
12016
12020
|
//#region src/plugins/mdx.ts
|
|
12017
12021
|
var MDX_EXTENSIONS = ["mdx", "md"];
|
|
12018
12022
|
/**
|
|
12019
|
-
* Check if mdx-components.tsx (or .ts, .jsx, .js) exists at the project root
|
|
12023
|
+
* Check if mdx-components.tsx (or .ts, .jsx, .js) exists at the project root
|
|
12024
|
+
* or in src/. Root takes precedence, matching Next.js behavior.
|
|
12020
12025
|
* Returns the absolute path if found, otherwise undefined.
|
|
12021
12026
|
*/
|
|
12022
12027
|
function findMdxComponents(root) {
|
|
12023
|
-
|
|
12028
|
+
const candidates = [
|
|
12024
12029
|
"mdx-components.tsx",
|
|
12025
12030
|
"mdx-components.ts",
|
|
12026
12031
|
"mdx-components.jsx",
|
|
12027
12032
|
"mdx-components.js"
|
|
12028
|
-
]
|
|
12029
|
-
|
|
12033
|
+
];
|
|
12034
|
+
const dirs = [root, join(root, "src")];
|
|
12035
|
+
for (const dir of dirs) for (const name of candidates) {
|
|
12036
|
+
const p = join(dir, name);
|
|
12030
12037
|
if (existsSync(p)) return p;
|
|
12031
12038
|
}
|
|
12032
12039
|
}
|
|
@@ -12540,6 +12547,58 @@ export const coerce = stub;
|
|
|
12540
12547
|
};
|
|
12541
12548
|
}
|
|
12542
12549
|
//#endregion
|
|
12550
|
+
//#region src/fonts/css.ts
|
|
12551
|
+
/**
|
|
12552
|
+
* Generate a single `@font-face` CSS rule from a descriptor.
|
|
12553
|
+
*/
|
|
12554
|
+
function generateFontFace(desc) {
|
|
12555
|
+
const lines = [];
|
|
12556
|
+
lines.push("@font-face {");
|
|
12557
|
+
lines.push(` font-family: '${desc.family}';`);
|
|
12558
|
+
lines.push(` src: ${desc.src};`);
|
|
12559
|
+
if (desc.weight) lines.push(` font-weight: ${desc.weight};`);
|
|
12560
|
+
if (desc.style) lines.push(` font-style: ${desc.style};`);
|
|
12561
|
+
if (desc.display) lines.push(` font-display: ${desc.display};`);
|
|
12562
|
+
if (desc.unicodeRange) lines.push(` unicode-range: ${desc.unicodeRange};`);
|
|
12563
|
+
lines.push("}");
|
|
12564
|
+
return lines.join("\n");
|
|
12565
|
+
}
|
|
12566
|
+
/**
|
|
12567
|
+
* Generate multiple `@font-face` rules from an array of descriptors.
|
|
12568
|
+
*/
|
|
12569
|
+
function generateFontFaces(descriptors) {
|
|
12570
|
+
return descriptors.map(generateFontFace).join("\n\n");
|
|
12571
|
+
}
|
|
12572
|
+
/**
|
|
12573
|
+
* Generate a scoped CSS class that sets a CSS custom property for the font.
|
|
12574
|
+
*
|
|
12575
|
+
* Example output:
|
|
12576
|
+
* ```css
|
|
12577
|
+
* .timber-font-inter {
|
|
12578
|
+
* --font-sans: 'Inter', 'Inter Fallback', system-ui, sans-serif;
|
|
12579
|
+
* }
|
|
12580
|
+
* ```
|
|
12581
|
+
*/
|
|
12582
|
+
function generateVariableClass(className, variable, fontFamily) {
|
|
12583
|
+
return `.${className} {\n ${variable}: ${fontFamily};\n}`;
|
|
12584
|
+
}
|
|
12585
|
+
/**
|
|
12586
|
+
* Generate a scoped CSS class that applies font-family directly.
|
|
12587
|
+
*
|
|
12588
|
+
* Used when no `variable` is specified — the className applies
|
|
12589
|
+
* the font-family inline instead of through a CSS custom property.
|
|
12590
|
+
*
|
|
12591
|
+
* Example output:
|
|
12592
|
+
* ```css
|
|
12593
|
+
* .timber-font-inter {
|
|
12594
|
+
* font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;
|
|
12595
|
+
* }
|
|
12596
|
+
* ```
|
|
12597
|
+
*/
|
|
12598
|
+
function generateFontFamilyClass(className, fontFamily) {
|
|
12599
|
+
return `.${className} {\n font-family: ${fontFamily};\n}`;
|
|
12600
|
+
}
|
|
12601
|
+
//#endregion
|
|
12543
12602
|
//#region src/fonts/fallbacks.ts
|
|
12544
12603
|
/**
|
|
12545
12604
|
* Lookup table for commonly used Google Fonts.
|
|
@@ -12678,6 +12737,26 @@ function getGenericFamily(family) {
|
|
|
12678
12737
|
return "sans-serif";
|
|
12679
12738
|
}
|
|
12680
12739
|
/**
|
|
12740
|
+
* Generate the full CSS for a size-adjusted fallback font.
|
|
12741
|
+
*
|
|
12742
|
+
* This produces a complete @font-face block with override descriptors
|
|
12743
|
+
* that FontFaceDescriptor doesn't natively support.
|
|
12744
|
+
*/
|
|
12745
|
+
function generateFallbackCss(family) {
|
|
12746
|
+
const metrics = FALLBACK_METRICS[family.toLowerCase()];
|
|
12747
|
+
if (!metrics) return null;
|
|
12748
|
+
return [
|
|
12749
|
+
"@font-face {",
|
|
12750
|
+
` font-family: '${`${family} Fallback`}';`,
|
|
12751
|
+
` src: local('${metrics.fallbackFont}');`,
|
|
12752
|
+
` size-adjust: ${metrics.sizeAdjust}%;`,
|
|
12753
|
+
` ascent-override: ${metrics.ascentOverride}%;`,
|
|
12754
|
+
` descent-override: ${metrics.descentOverride}%;`,
|
|
12755
|
+
` line-gap-override: ${metrics.lineGapOverride}%;`,
|
|
12756
|
+
"}"
|
|
12757
|
+
].join("\n");
|
|
12758
|
+
}
|
|
12759
|
+
/**
|
|
12681
12760
|
* Check whether fallback metrics are available for a font family.
|
|
12682
12761
|
*/
|
|
12683
12762
|
function hasFallbackMetrics(family) {
|
|
@@ -13026,6 +13105,26 @@ function generateFamilyName(sources) {
|
|
|
13026
13105
|
return stem.replace(/[-_]?(Regular|Bold|Italic|Light|Medium|SemiBold|ExtraBold|Thin|Black|Heavy)$/i, "") || stem;
|
|
13027
13106
|
}
|
|
13028
13107
|
/**
|
|
13108
|
+
* Generate @font-face descriptors for local font sources.
|
|
13109
|
+
*
|
|
13110
|
+
* Each source entry produces one @font-face rule. The `src` descriptor
|
|
13111
|
+
* uses a `url()` pointing to the served path under `/_timber/fonts/`.
|
|
13112
|
+
* The `urlPrefix` defaults to `/_timber/fonts` — the path used by both
|
|
13113
|
+
* the dev server middleware and the production build output.
|
|
13114
|
+
*/
|
|
13115
|
+
function generateLocalFontFaces(family, sources, display, urlPrefix = "/_timber/fonts") {
|
|
13116
|
+
return sources.map((entry) => {
|
|
13117
|
+
const format = inferFontFormat(entry.path);
|
|
13118
|
+
return {
|
|
13119
|
+
family,
|
|
13120
|
+
src: `url('${urlPrefix}/${entry.path.split("/").pop() ?? entry.path}') format('${format}')`,
|
|
13121
|
+
weight: entry.weight,
|
|
13122
|
+
style: entry.style,
|
|
13123
|
+
display
|
|
13124
|
+
};
|
|
13125
|
+
});
|
|
13126
|
+
}
|
|
13127
|
+
/**
|
|
13029
13128
|
* Build the className for a local font, following the same convention
|
|
13030
13129
|
* as Google fonts: `timber-font-<lowercase-hyphenated-family>`.
|
|
13031
13130
|
*/
|
|
@@ -13261,6 +13360,22 @@ var VIRTUAL_LOCAL = "@timber/fonts/local";
|
|
|
13261
13360
|
var RESOLVED_GOOGLE = "\0@timber/fonts/google";
|
|
13262
13361
|
var RESOLVED_LOCAL = "\0@timber/fonts/local";
|
|
13263
13362
|
/**
|
|
13363
|
+
* Virtual side-effect module that registers font CSS on globalThis.
|
|
13364
|
+
*
|
|
13365
|
+
* When a file calls localFont() or a Google font function, the transform
|
|
13366
|
+
* hook injects `import 'virtual:timber-font-css-register'` into that file.
|
|
13367
|
+
* This virtual module sets `globalThis.__timber_font_css` with the combined
|
|
13368
|
+
* @font-face CSS. The RSC entry reads it at render time to inline a <style> tag.
|
|
13369
|
+
*
|
|
13370
|
+
* This approach avoids timing issues because:
|
|
13371
|
+
* 1. The font file is in the RSC module graph (imported by layout.tsx)
|
|
13372
|
+
* 2. The side-effect import is added to the font file during transform
|
|
13373
|
+
* 3. When layout.tsx is loaded, fonts.ts runs → side-effect module runs → globalThis is set
|
|
13374
|
+
* 4. RSC entry renders → reads globalThis → inlines <style>
|
|
13375
|
+
*/
|
|
13376
|
+
var VIRTUAL_FONT_CSS_REGISTER = "virtual:timber-font-css-register";
|
|
13377
|
+
var RESOLVED_FONT_CSS_REGISTER = "\0virtual:timber-font-css-register";
|
|
13378
|
+
/**
|
|
13264
13379
|
* Convert a font family name to a PascalCase export name.
|
|
13265
13380
|
* e.g. "JetBrains Mono" → "JetBrains_Mono"
|
|
13266
13381
|
*/
|
|
@@ -13407,6 +13522,35 @@ function generateLocalVirtualModule() {
|
|
|
13407
13522
|
].join("\n");
|
|
13408
13523
|
}
|
|
13409
13524
|
/**
|
|
13525
|
+
* Generate CSS for a single extracted font.
|
|
13526
|
+
*
|
|
13527
|
+
* Includes @font-face rules (for local fonts), fallback @font-face,
|
|
13528
|
+
* and the scoped class rule.
|
|
13529
|
+
*/
|
|
13530
|
+
function generateFontCss(font) {
|
|
13531
|
+
const cssParts = [];
|
|
13532
|
+
if (font.provider === "local" && font.localSources) {
|
|
13533
|
+
const faceCss = generateFontFaces(generateLocalFontFaces(font.family, font.localSources, font.display));
|
|
13534
|
+
if (faceCss) cssParts.push(faceCss);
|
|
13535
|
+
}
|
|
13536
|
+
const fallbackCss = generateFallbackCss(font.family);
|
|
13537
|
+
if (fallbackCss) cssParts.push(fallbackCss);
|
|
13538
|
+
if (font.variable) cssParts.push(generateVariableClass(font.className, font.variable, font.fontFamily));
|
|
13539
|
+
else cssParts.push(generateFontFamilyClass(font.className, font.fontFamily));
|
|
13540
|
+
return cssParts.join("\n\n");
|
|
13541
|
+
}
|
|
13542
|
+
/**
|
|
13543
|
+
* Generate the CSS output for all extracted fonts.
|
|
13544
|
+
*
|
|
13545
|
+
* Includes @font-face rules for local fonts, fallback @font-face rules,
|
|
13546
|
+
* and scoped classes.
|
|
13547
|
+
*/
|
|
13548
|
+
function generateAllFontCss(registry) {
|
|
13549
|
+
const cssParts = [];
|
|
13550
|
+
for (const font of registry.values()) cssParts.push(generateFontCss(font));
|
|
13551
|
+
return cssParts.join("\n\n");
|
|
13552
|
+
}
|
|
13553
|
+
/**
|
|
13410
13554
|
* Parse the local name used for the default import of `@timber/fonts/local`.
|
|
13411
13555
|
*
|
|
13412
13556
|
* Handles:
|
|
@@ -13457,15 +13601,63 @@ function timberFonts(ctx) {
|
|
|
13457
13601
|
return {
|
|
13458
13602
|
name: "timber-fonts",
|
|
13459
13603
|
resolveId(id) {
|
|
13460
|
-
|
|
13461
|
-
if (
|
|
13604
|
+
let cleanId = id.startsWith("\0") ? id.slice(1) : id;
|
|
13605
|
+
if (cleanId.startsWith(ctx.root)) {
|
|
13606
|
+
const stripped = cleanId.slice(ctx.root.length);
|
|
13607
|
+
if (stripped.startsWith("/") || stripped.startsWith("\\")) cleanId = stripped.slice(1);
|
|
13608
|
+
else cleanId = stripped;
|
|
13609
|
+
}
|
|
13610
|
+
if (cleanId === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;
|
|
13611
|
+
if (cleanId === VIRTUAL_LOCAL) return RESOLVED_LOCAL;
|
|
13612
|
+
if (cleanId === VIRTUAL_FONT_CSS_REGISTER) return RESOLVED_FONT_CSS_REGISTER;
|
|
13462
13613
|
return null;
|
|
13463
13614
|
},
|
|
13464
13615
|
load(id) {
|
|
13465
13616
|
if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(registry);
|
|
13466
13617
|
if (id === RESOLVED_LOCAL) return generateLocalVirtualModule();
|
|
13618
|
+
if (id === RESOLVED_FONT_CSS_REGISTER) {
|
|
13619
|
+
const css = generateAllFontCss(registry);
|
|
13620
|
+
return `globalThis.__timber_font_css = ${JSON.stringify(css)};`;
|
|
13621
|
+
}
|
|
13467
13622
|
return null;
|
|
13468
13623
|
},
|
|
13624
|
+
configureServer(server) {
|
|
13625
|
+
server.middlewares.use((req, res, next) => {
|
|
13626
|
+
const url = req.url;
|
|
13627
|
+
if (!url || !url.startsWith("/_timber/fonts/")) return next();
|
|
13628
|
+
const requestedFilename = url.slice(15);
|
|
13629
|
+
if (requestedFilename.includes("..") || requestedFilename.includes("/")) {
|
|
13630
|
+
res.statusCode = 400;
|
|
13631
|
+
res.end("Bad request");
|
|
13632
|
+
return;
|
|
13633
|
+
}
|
|
13634
|
+
for (const font of registry.values()) {
|
|
13635
|
+
if (font.provider !== "local" || !font.localSources) continue;
|
|
13636
|
+
for (const src of font.localSources) if ((src.path.split("/").pop() ?? "") === requestedFilename) {
|
|
13637
|
+
const absolutePath = normalize(resolve(src.path));
|
|
13638
|
+
if (!existsSync(absolutePath)) {
|
|
13639
|
+
res.statusCode = 404;
|
|
13640
|
+
res.end("Not found");
|
|
13641
|
+
return;
|
|
13642
|
+
}
|
|
13643
|
+
const data = readFileSync(absolutePath);
|
|
13644
|
+
const ext = absolutePath.split(".").pop()?.toLowerCase();
|
|
13645
|
+
res.setHeader("Content-Type", {
|
|
13646
|
+
woff2: "font/woff2",
|
|
13647
|
+
woff: "font/woff",
|
|
13648
|
+
ttf: "font/ttf",
|
|
13649
|
+
otf: "font/otf",
|
|
13650
|
+
eot: "application/vnd.ms-fontopen"
|
|
13651
|
+
}[ext ?? ""] ?? "application/octet-stream");
|
|
13652
|
+
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
13653
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
13654
|
+
res.end(data);
|
|
13655
|
+
return;
|
|
13656
|
+
}
|
|
13657
|
+
}
|
|
13658
|
+
next();
|
|
13659
|
+
});
|
|
13660
|
+
},
|
|
13469
13661
|
async buildStart() {
|
|
13470
13662
|
if (ctx.dev) return;
|
|
13471
13663
|
const googleFonts = [...registry.values()].filter((f) => f.provider === "google");
|
|
@@ -13521,10 +13713,13 @@ function timberFonts(ctx) {
|
|
|
13521
13713
|
}
|
|
13522
13714
|
}
|
|
13523
13715
|
if (hasLocalImport) transformedCode = transformLocalFonts(transformedCode, code, id, registry, this.error.bind(this));
|
|
13524
|
-
if (transformedCode !== code)
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13716
|
+
if (transformedCode !== code) {
|
|
13717
|
+
if (registry.size > 0) transformedCode = `import '${VIRTUAL_FONT_CSS_REGISTER}';\n` + transformedCode;
|
|
13718
|
+
return {
|
|
13719
|
+
code: transformedCode,
|
|
13720
|
+
map: null
|
|
13721
|
+
};
|
|
13722
|
+
}
|
|
13528
13723
|
return null;
|
|
13529
13724
|
},
|
|
13530
13725
|
generateBundle() {
|
|
@@ -13533,6 +13728,23 @@ function timberFonts(ctx) {
|
|
|
13533
13728
|
fileName: `_timber/fonts/${cf.hashedFilename}`,
|
|
13534
13729
|
source: cf.data
|
|
13535
13730
|
});
|
|
13731
|
+
for (const font of registry.values()) {
|
|
13732
|
+
if (font.provider !== "local" || !font.localSources) continue;
|
|
13733
|
+
for (const src of font.localSources) {
|
|
13734
|
+
const absolutePath = normalize(resolve(src.path));
|
|
13735
|
+
if (!existsSync(absolutePath)) {
|
|
13736
|
+
this.warn(`Local font file not found: ${absolutePath}`);
|
|
13737
|
+
continue;
|
|
13738
|
+
}
|
|
13739
|
+
const basename = src.path.split("/").pop() ?? src.path;
|
|
13740
|
+
const data = readFileSync(absolutePath);
|
|
13741
|
+
this.emitFile({
|
|
13742
|
+
type: "asset",
|
|
13743
|
+
fileName: `_timber/fonts/${basename}`,
|
|
13744
|
+
source: data
|
|
13745
|
+
});
|
|
13746
|
+
}
|
|
13747
|
+
}
|
|
13536
13748
|
if (!ctx.buildManifest) return;
|
|
13537
13749
|
const cachedByFamily = /* @__PURE__ */ new Map();
|
|
13538
13750
|
for (const cf of cachedFonts) {
|
|
@@ -14237,7 +14449,15 @@ function timberReactProd() {
|
|
|
14237
14449
|
*
|
|
14238
14450
|
* Currently a no-op — Rolldown's default splitting produces the desired
|
|
14239
14451
|
* output (one main bundle + per-route chunks). The plugin is retained as
|
|
14240
|
-
* a hook point for future chunking adjustments
|
|
14452
|
+
* a hook point for future chunking adjustments.
|
|
14453
|
+
*
|
|
14454
|
+
* NOTE: Ideally we'd use Rolldown's `format: 'app'` (module registry format)
|
|
14455
|
+
* which guarantees single-copy module semantics like webpack/Turbopack.
|
|
14456
|
+
* However, `format: 'app'` is not yet implemented in Rolldown rc.10.
|
|
14457
|
+
* Until it ships, singleton state in navigation-context.ts uses
|
|
14458
|
+
* globalThis + Symbol.for as a cross-chunk safety net.
|
|
14459
|
+
*
|
|
14460
|
+
* Design docs: 27-chunking-strategy.md
|
|
14241
14461
|
*/
|
|
14242
14462
|
function timberChunks() {
|
|
14243
14463
|
return { name: "timber-chunks" };
|
|
@@ -14392,7 +14612,17 @@ function classifyRoute(segments, outputMode = "server") {
|
|
|
14392
14612
|
function green(text) {
|
|
14393
14613
|
return `\x1b[92m${text}\x1b[39m`;
|
|
14394
14614
|
}
|
|
14395
|
-
/**
|
|
14615
|
+
/**
|
|
14616
|
+
* Walk the route tree and collect all leaf routes (pages + API endpoints).
|
|
14617
|
+
*
|
|
14618
|
+
* Parallel slots (`@artists`, `@shows`, etc.) are intentionally skipped —
|
|
14619
|
+
* they render alongside the parent page at the same URL and are not
|
|
14620
|
+
* separately URL-addressable. Their JS is captured in shared/layout chunks.
|
|
14621
|
+
*
|
|
14622
|
+
* After collection, entries are deduplicated by URL path so that overlapping
|
|
14623
|
+
* route groups (e.g. `(browse)` and `(marketing)` both producing `/`) only
|
|
14624
|
+
* appear once. The entry with the largest route-specific size wins.
|
|
14625
|
+
*/
|
|
14396
14626
|
function collectRoutes(tree) {
|
|
14397
14627
|
const routes = [];
|
|
14398
14628
|
function walk(node, chain) {
|
|
@@ -14409,10 +14639,14 @@ function collectRoutes(tree) {
|
|
|
14409
14639
|
entryFilePath: node.route.filePath
|
|
14410
14640
|
});
|
|
14411
14641
|
for (const child of node.children) walk(child, currentChain);
|
|
14412
|
-
for (const slot of node.slots.values()) walk(slot, currentChain);
|
|
14413
14642
|
}
|
|
14414
14643
|
walk(tree.root, []);
|
|
14415
|
-
|
|
14644
|
+
const seen = /* @__PURE__ */ new Map();
|
|
14645
|
+
for (const route of routes) {
|
|
14646
|
+
const existing = seen.get(route.path);
|
|
14647
|
+
if (!existing || route.segments.length > existing.segments.length) seen.set(route.path, route);
|
|
14648
|
+
}
|
|
14649
|
+
return Array.from(seen.values());
|
|
14416
14650
|
}
|
|
14417
14651
|
/** Produce formatted report lines for the Vite logger. */
|
|
14418
14652
|
function buildRouteReport(entries, sharedSize) {
|