@absolutejs/absolute 0.20.0-beta.53 → 0.20.0-beta.55

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.
Files changed (37) hide show
  1. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  2. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  3. package/dist/angular/index.js +25 -4
  4. package/dist/angular/index.js.map +6 -5
  5. package/dist/angular/server.js +25 -4
  6. package/dist/angular/server.js.map +6 -5
  7. package/dist/build.js +56 -9
  8. package/dist/build.js.map +10 -9
  9. package/dist/cli/config/server.js +4 -1
  10. package/dist/client/index.js +126 -7
  11. package/dist/client/index.js.map +8 -6
  12. package/dist/index.js +279 -232
  13. package/dist/index.js.map +12 -11
  14. package/dist/islands/index.js +17 -2
  15. package/dist/islands/index.js.map +5 -4
  16. package/dist/react/index.js +19 -3
  17. package/dist/react/index.js.map +6 -5
  18. package/dist/react/server.js +17 -2
  19. package/dist/react/server.js.map +5 -4
  20. package/dist/src/client/browserTranslation.d.ts +19 -0
  21. package/dist/src/client/index.d.ts +1 -0
  22. package/dist/src/core/browserTranslation.d.ts +6 -0
  23. package/dist/src/ember/browser.d.ts +0 -16
  24. package/dist/src/vue/browser.d.ts +1 -0
  25. package/dist/src/vue/browserTranslation.d.ts +5 -0
  26. package/dist/src/vue/index.d.ts +1 -0
  27. package/dist/svelte/index.js +19 -3
  28. package/dist/svelte/index.js.map +6 -5
  29. package/dist/svelte/server.js +17 -2
  30. package/dist/svelte/server.js.map +5 -4
  31. package/dist/vue/browser.js +96 -1
  32. package/dist/vue/browser.js.map +5 -3
  33. package/dist/vue/index.js +114 -3
  34. package/dist/vue/index.js.map +8 -5
  35. package/dist/vue/server.js +17 -2
  36. package/dist/vue/server.js.map +5 -4
  37. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -6882,6 +6882,20 @@ var init_registerClientScript = __esm(() => {
6882
6882
  }
6883
6883
  });
6884
6884
 
6885
+ // src/core/browserTranslation.ts
6886
+ var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
6887
+ if (html.includes(BASELINE_MARKER))
6888
+ return html;
6889
+ const script = browserTranslationBaselineTag();
6890
+ const closingBodyIndex = html.lastIndexOf("</body>");
6891
+ if (closingBodyIndex < 0)
6892
+ return `${html}${script}`;
6893
+ return `${html.slice(0, closingBodyIndex)}${script}${html.slice(closingBodyIndex)}`;
6894
+ };
6895
+ var init_browserTranslation = __esm(() => {
6896
+ BROWSER_TRANSLATION_BASELINE_SCRIPT = "window.__ABSOLUTE_SSR_TEXT_BASELINES__=new WeakMap();" + "{const r=document.body,b=window.__ABSOLUTE_SSR_TEXT_BASELINES__;" + 'if(r)for(const e of [r,...r.querySelectorAll("*")]){' + "const t=new Map();for(const [i,n]of[...e.childNodes].entries())" + 'if(n.nodeType===3)t.set(i,n.nodeValue??"");if(t.size)b.set(e,t);}}';
6897
+ });
6898
+
6885
6899
  // src/angular/httpTransferCache.ts
6886
6900
  var ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER = "x-skip-transfer-cache", buildAbsoluteHttpTransferCacheOptions = (options = {}) => {
6887
6901
  const {
@@ -6934,7 +6948,7 @@ var routeContextCache, cacheRouteData = (pagePath, data) => {
6934
6948
  }
6935
6949
  return html + snippet;
6936
6950
  }, injectSsrScripts = (html, requestId, indexPath, requestContext) => {
6937
- let result = html;
6951
+ let result = injectBeforeClose(html, browserTranslationBaselineTag());
6938
6952
  const registeredScripts = getAndClearClientScripts(requestId);
6939
6953
  if (registeredScripts.length > 0) {
6940
6954
  result = injectBeforeClose(result, generateClientScriptCode(registeredScripts));
@@ -6970,6 +6984,7 @@ var routeContextCache, cacheRouteData = (pagePath, data) => {
6970
6984
  };
6971
6985
  var init_ssrRender = __esm(() => {
6972
6986
  init_registerClientScript();
6987
+ init_browserTranslation();
6973
6988
  routeContextCache = new Map;
6974
6989
  selectorCache = new Map;
6975
6990
  });
@@ -10308,10 +10323,14 @@ var indexContentCache, resolveDevClientDir = () => {
10308
10323
  ] : [];
10309
10324
  const reactImports = isDev2 ? [
10310
10325
  `import { hydrateRoot, createRoot } from 'react-dom/client';`,
10311
- `import { createElement, Component } from 'react';`
10326
+ `import { flushSync } from 'react-dom';`,
10327
+ `import { createElement, Component } from 'react';`,
10328
+ `import { prepareBrowserTranslationHydration } from '@absolutejs/absolute/client';`
10312
10329
  ] : [
10313
10330
  `import { hydrateRoot, createRoot } from 'react-dom/client';`,
10314
- `import { createElement } from 'react';`
10331
+ `import { flushSync } from 'react-dom';`,
10332
+ `import { createElement } from 'react';`,
10333
+ `import { prepareBrowserTranslationHydration } from '@absolutejs/absolute/client';`
10315
10334
  ];
10316
10335
  const errorBoundaryDef = isDev2 ? [
10317
10336
  `
@@ -10506,8 +10525,10 @@ var indexContentCache, resolveDevClientDir = () => {
10506
10525
  ` root.render(${isDev2 ? `createElement(ErrorBoundary, null, createElement(PageComponent, mergedProps))` : `createElement(PageComponent, mergedProps)`});`,
10507
10526
  ` window.__REACT_ROOT__ = root;`,
10508
10527
  ` } else {`,
10528
+ ` const restoreTranslation = prepareBrowserTranslationHydration(container);`,
10509
10529
  ` try {`,
10510
10530
  ` // Use onRecoverableError to catch hydration errors (React 19)`,
10531
+ ` const startHydration = () => {`,
10511
10532
  ` root = hydrateRoot(`,
10512
10533
  ` container,`,
10513
10534
  ` ${isDev2 ? `createElement(ErrorBoundary, null, createElement(PageComponent, mergedProps))` : `createElement(PageComponent, mergedProps)`},`,
@@ -10544,8 +10565,13 @@ var indexContentCache, resolveDevClientDir = () => {
10544
10565
  ` }`,
10545
10566
  ` }`,
10546
10567
  ` );`,
10568
+ ` };`,
10569
+ ` if (restoreTranslation.hasTranslation) flushSync(startHydration);`,
10570
+ ` else startHydration();`,
10571
+ ` restoreTranslation();`,
10547
10572
  ` window.__REACT_ROOT__ = root;`,
10548
10573
  ` } catch (error) {`,
10574
+ ` restoreTranslation();`,
10549
10575
  ` // Catch synchronous errors (shouldn't happen with hydrateRoot, but safety net)`,
10550
10576
  ` if (isDev && isHydrationError(error)) {`,
10551
10577
  ` handleHydrationFallback(error);`,
@@ -15101,6 +15127,7 @@ import "${hmrClientPath3}";
15101
15127
  ` : "";
15102
15128
  const bootstrap = `${hmrImports}import Component from "${importPath}";
15103
15129
  import { hydrate, mount, unmount } from "svelte";
15130
+ import { prepareBrowserTranslationHydration } from "@absolutejs/absolute/client";
15104
15131
 
15105
15132
  var initialProps = (typeof window !== "undefined" && window.__INITIAL_PROPS__) ? window.__INITIAL_PROPS__ : {};
15106
15133
  var isHMR = typeof window !== "undefined" && window.__SVELTE_COMPONENT__ !== undefined;
@@ -15145,7 +15172,12 @@ if (isHMR) {
15145
15172
  } else if (isSsrDirty || hasIslandHtml) {
15146
15173
  component = mount(Component, { target, props: initialProps });
15147
15174
  } else {
15148
- component = hydrate(Component, { target, props: initialProps });
15175
+ var restoreTranslation = prepareBrowserTranslationHydration(target);
15176
+ try {
15177
+ component = hydrate(Component, { target, props: initialProps });
15178
+ } finally {
15179
+ restoreTranslation();
15180
+ }
15149
15181
  }
15150
15182
 
15151
15183
  if (typeof window !== "undefined") {
@@ -16088,6 +16120,7 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
16088
16120
  ...vueHmrImports,
16089
16121
  `import Comp, * as PageModule from "${relative13(dirname20(indexOutputFile), clientOutputFile).replace(/\\/g, "/")}";`,
16090
16122
  'import { createSSRApp, createApp } from "vue";',
16123
+ 'import { prepareBrowserTranslationHydration } from "@absolutejs/absolute/vue";',
16091
16124
  "",
16092
16125
  "// HMR State Preservation: Check for preserved state from HMR",
16093
16126
  'let preservedState = (typeof window !== "undefined" && window.__HMR_PRESERVED_STATE__) ? window.__HMR_PRESERVED_STATE__ : {};',
@@ -16150,7 +16183,14 @@ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
16150
16183
  " url: clientUrl",
16151
16184
  " });",
16152
16185
  " }",
16153
- ' app.mount("#root");',
16186
+ " const restoreBrowserTranslation = shouldHydrate",
16187
+ ' ? prepareBrowserTranslationHydration(document.querySelector("#root"))',
16188
+ " : () => undefined;",
16189
+ " try {",
16190
+ ' app.mount("#root");',
16191
+ " } finally {",
16192
+ " restoreBrowserTranslation();",
16193
+ " }",
16154
16194
  "}",
16155
16195
  "const absolutePageReady = bootstrapApp();",
16156
16196
  "",
@@ -17911,6 +17951,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
17911
17951
  import { provideClientHydration } from '@angular/platform-browser';
17912
17952
  import { withHttpTransferCacheOptions } from '@angular/platform-browser';
17913
17953
  import { provideZonelessChangeDetection, REQUEST_CONTEXT } from '@angular/core';
17954
+ import { prepareBrowserTranslationHydration } from '@absolutejs/absolute/client';
17914
17955
  import * as pageModule from '${normalizedImportPath}';
17915
17956
  var ${componentClassName} = pageModule.default;
17916
17957
  // REQUEST_CONTEXT is hydrated from the SSR-serialized payload so client-side
@@ -17974,8 +18015,10 @@ if (!document.querySelector(_sel)) {
17974
18015
  }
17975
18016
 
17976
18017
  var providers = [provideZonelessChangeDetection()];
18018
+ var restoreTranslation = function() {};
17977
18019
  if (!isClientRender && !window.__HMR_SKIP_HYDRATION__ && !pageHasIslands) {
17978
18020
  providers.push(provideClientHydration(withHttpTransferCacheOptions(absoluteHttpTransferCacheOptions)));
18021
+ restoreTranslation = prepareBrowserTranslationHydration(document.querySelector(_sel));
17979
18022
  }
17980
18023
  delete window.__HMR_SKIP_HYDRATION__;
17981
18024
  providers.push.apply(providers, pageProviders);
@@ -18002,7 +18045,7 @@ if (pageHasRawStreamingSlots) {
18002
18045
  });
18003
18046
  }
18004
18047
  return appRef;
18005
- });
18048
+ }).finally(restoreTranslation);
18006
18049
  }
18007
18050
  window.__ABSOLUTE_PAGE_READY__ = absolutePageReady;
18008
18051
  window.__ABSOLUTE_PAGE_DISPOSE__ = async function() {
@@ -18018,6 +18061,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
18018
18061
  import { provideClientHydration } from '@angular/platform-browser';
18019
18062
  import { withHttpTransferCacheOptions } from '@angular/platform-browser';
18020
18063
  import { enableProdMode, provideZonelessChangeDetection, REQUEST_CONTEXT } from '@angular/core';
18064
+ import { prepareBrowserTranslationHydration } from '@absolutejs/absolute/client';
18021
18065
  import * as pageModule from '${normalizedImportPath}';
18022
18066
  var ${componentClassName} = pageModule.default;
18023
18067
  // REQUEST_CONTEXT is hydrated from the SSR-serialized payload so client-side
@@ -18060,8 +18104,10 @@ if (!document.querySelector(_sel)) {
18060
18104
  }
18061
18105
 
18062
18106
  var providers = [provideZonelessChangeDetection()].concat(pageProviders).concat(contextProviders);
18107
+ var restoreTranslation = function() {};
18063
18108
  if (!isClientRender && !pageHasIslands) {
18064
18109
  providers.unshift(provideClientHydration(withHttpTransferCacheOptions(absoluteHttpTransferCacheOptions)));
18110
+ restoreTranslation = prepareBrowserTranslationHydration(document.querySelector(_sel));
18065
18111
  }
18066
18112
  window.__ABS_SLOT_HYDRATION_PENDING__ = pageHasRawStreamingSlots;
18067
18113
  var absolutePageReady = Promise.resolve();
@@ -18085,7 +18131,7 @@ if (pageHasRawStreamingSlots) {
18085
18131
  });
18086
18132
  }
18087
18133
  return appRef;
18088
- });
18134
+ }).finally(restoreTranslation);
18089
18135
  }
18090
18136
  window.__ABSOLUTE_PAGE_READY__ = absolutePageReady;
18091
18137
  window.__ABSOLUTE_PAGE_DISPOSE__ = async function() {
@@ -26982,7 +27028,7 @@ var resolveRequestPathname = (request) => {
26982
27028
  }, buildHtmlShell = (headTag, bodyContent, indexPath, props, hmrShim) => {
26983
27029
  const propsScript = `window.__INITIAL_PROPS__=${JSON.stringify(props ?? {})};`;
26984
27030
  const indexImport = indexPath ? `<script type="module" src="${indexPath}"></script>` : "";
26985
- return `<!DOCTYPE html><html>${headTag}<body>` + `<div id="ember-root">${bodyContent}</div>` + `<script>${propsScript}</script>${indexImport}${hmrShim}</body></html>`;
27031
+ return injectBrowserTranslationBaseline(`<!DOCTYPE html><html>${headTag}<body>` + `<div id="ember-root">${bodyContent}</div>` + `<script>${propsScript}</script>${indexImport}${hmrShim}</body></html>`);
26986
27032
  }, cachedEmberHmrShim = null, getEmberHmrShim = () => {
26987
27033
  if (cachedEmberHmrShim)
26988
27034
  return cachedEmberHmrShim;
@@ -27019,6 +27065,7 @@ var resolveRequestPathname = (request) => {
27019
27065
  };
27020
27066
  var init_pageHandler = __esm(() => {
27021
27067
  init_pageResponseCache();
27068
+ init_browserTranslation();
27022
27069
  });
27023
27070
 
27024
27071
  // src/ember/index.ts
@@ -31945,230 +31992,9 @@ init_islands();
31945
31992
 
31946
31993
  // src/core/pageHandlers.ts
31947
31994
  init_staticIslandPages();
31948
- var {file } = globalThis.Bun;
31949
-
31950
- // src/core/islandPageContext.ts
31951
- var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient";
31952
- var ISLAND_MARKER = 'data-island="true"';
31953
- var MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__";
31954
- var ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__";
31955
- var CLOSING_HEAD_TAG2 = "</head>";
31956
- var buildIslandsHeadMarkup = (manifest) => {
31957
- const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
31958
- const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
31959
- const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
31960
- const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
31961
- return `${manifestScript}${islandStateScript}${bootstrapScript}`;
31962
- };
31963
- var injectHeadMarkup = (html, markup) => {
31964
- const closingHeadIndex = html.indexOf("</head>");
31965
- if (closingHeadIndex >= 0) {
31966
- return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
31967
- }
31968
- const openingBodyIndex = html.indexOf("<body");
31969
- if (openingBodyIndex >= 0) {
31970
- const bodyStart = html.indexOf(">", openingBodyIndex);
31971
- if (bodyStart >= 0) {
31972
- return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
31973
- }
31974
- }
31975
- return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
31976
- };
31977
- var streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
31978
- var flushSafePendingText = (controller, encoder, pending, lookbehind) => {
31979
- if (pending.length <= lookbehind) {
31980
- return pending;
31981
- }
31982
- const safeText = pending.slice(0, pending.length - lookbehind);
31983
- controller.enqueue(encoder.encode(safeText));
31984
- return pending.slice(-lookbehind);
31985
- };
31986
- var updateInjectedState = (consumed, injected, pending) => {
31987
- if (consumed.done) {
31988
- return { done: true, injected, pending };
31989
- }
31990
- return {
31991
- done: false,
31992
- injected: consumed.injected,
31993
- pending: consumed.pending
31994
- };
31995
- };
31996
- var readStreamChunk = async (reader) => {
31997
- const { done, value } = await reader.read();
31998
- if (done || !value) {
31999
- return { done, value: undefined };
32000
- }
32001
- return { done, value };
32002
- };
32003
- var pipeStreamWithHeadInjection = (stream, markup) => {
32004
- const encoder = new TextEncoder;
32005
- const decoder = new TextDecoder;
32006
- const lookbehind = CLOSING_HEAD_TAG2.length - 1;
32007
- const processPending = (controller, pending, injected) => {
32008
- if (injected) {
32009
- controller.enqueue(encoder.encode(pending));
32010
- return { injected, pending: "" };
32011
- }
32012
- const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
32013
- if (headIndex >= 0) {
32014
- const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
32015
- controller.enqueue(encoder.encode(next));
32016
- return { injected: true, pending: "" };
32017
- }
32018
- return {
32019
- injected,
32020
- pending: flushSafePendingText(controller, encoder, pending, lookbehind)
32021
- };
32022
- };
32023
- const finishHeadInjectionStream = (controller, pending, injected) => {
32024
- let finalPending = pending + decoder.decode();
32025
- if (!injected) {
32026
- finalPending = injectHeadMarkup(finalPending, markup);
32027
- }
32028
- if (finalPending.length > 0) {
32029
- controller.enqueue(encoder.encode(finalPending));
32030
- }
32031
- controller.close();
32032
- };
32033
- const consumeHeadChunk = async (controller, reader, pending, injected) => {
32034
- const { done, value } = await readStreamChunk(reader);
32035
- if (done || !value) {
32036
- return { done, injected, pending };
32037
- }
32038
- const processed = processPending(controller, pending + streamChunkToString2(value, decoder), injected);
32039
- return {
32040
- done,
32041
- injected: processed.injected,
32042
- pending: processed.pending
32043
- };
32044
- };
32045
- const runHeadInjectionLoop = async (controller, reader) => {
32046
- const consumeNextHeadChunk = async (injected, pending) => {
32047
- const consumed = await consumeHeadChunk(controller, reader, pending, injected);
32048
- const nextState = updateInjectedState(consumed, injected, pending);
32049
- if (nextState.done) {
32050
- return { injected, pending };
32051
- }
32052
- return consumeNextHeadChunk(nextState.injected, nextState.pending);
32053
- };
32054
- return consumeNextHeadChunk(false, "");
32055
- };
32056
- return new ReadableStream({
32057
- async start(controller) {
32058
- const reader = stream.getReader();
32059
- try {
32060
- const { injected, pending } = await runHeadInjectionLoop(controller, reader);
32061
- finishHeadInjectionStream(controller, pending, injected);
32062
- } catch (error) {
32063
- controller.error(error);
32064
- }
32065
- }
32066
- });
32067
- };
32068
- var pipeStreamWithIslandMarkerDetection = (stream, markup) => {
32069
- const encoder = new TextEncoder;
32070
- const decoder = new TextDecoder;
32071
- const headLookbehind = CLOSING_HEAD_TAG2.length - 1;
32072
- const enqueue = (controller, text) => {
32073
- if (text.length > 0) {
32074
- controller.enqueue(encoder.encode(text));
32075
- }
32076
- };
32077
- const processHolding = (controller, held) => {
32078
- if (!held.includes(ISLAND_MARKER)) {
32079
- return { held, injected: false, pending: "", sawHead: true };
32080
- }
32081
- enqueue(controller, `${markup}${held}`);
32082
- return { held: "", injected: true, pending: "", sawHead: true };
32083
- };
32084
- const processHead = (controller, pending) => {
32085
- const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
32086
- if (headIndex < 0) {
32087
- return {
32088
- held: "",
32089
- injected: false,
32090
- pending: flushSafePendingText(controller, encoder, pending, headLookbehind),
32091
- sawHead: false
32092
- };
32093
- }
32094
- enqueue(controller, pending.slice(0, headIndex));
32095
- return processHolding(controller, pending.slice(headIndex));
32096
- };
32097
- const processChunk = (controller, state, chunk) => {
32098
- if (state.injected) {
32099
- enqueue(controller, chunk);
32100
- return state;
32101
- }
32102
- if (!state.sawHead) {
32103
- return processHead(controller, state.pending + chunk);
32104
- }
32105
- return processHolding(controller, state.held + chunk);
32106
- };
32107
- const finishMarkerStream = (controller, state) => {
32108
- const tail = decoder.decode();
32109
- const remainder = state.injected ? tail : (state.sawHead ? state.held : state.pending) + tail;
32110
- enqueue(controller, remainder);
32111
- controller.close();
32112
- };
32113
- const runMarkerLoop = (controller, reader) => {
32114
- const consumeNext = async (state) => {
32115
- const { done, value } = await readStreamChunk(reader);
32116
- if (done || !value) {
32117
- return state;
32118
- }
32119
- return consumeNext(processChunk(controller, state, streamChunkToString2(value, decoder)));
32120
- };
32121
- return consumeNext({
32122
- held: "",
32123
- injected: false,
32124
- pending: "",
32125
- sawHead: false
32126
- });
32127
- };
32128
- return new ReadableStream({
32129
- async start(controller) {
32130
- const reader = stream.getReader();
32131
- try {
32132
- const finalState = await runMarkerLoop(controller, reader);
32133
- finishMarkerStream(controller, finalState);
32134
- } catch (error) {
32135
- controller.error(error);
32136
- }
32137
- }
32138
- });
32139
- };
32140
- var htmlContainsIslands = (html) => html.includes(ISLAND_MARKER);
32141
- var injectIslandPageContext = (html, options) => {
32142
- const manifest = globalThis.__absoluteManifest;
32143
- const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
32144
- if (!manifest || !hasIslands) {
32145
- return html;
32146
- }
32147
- if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
32148
- return html;
32149
- }
32150
- return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
32151
- };
32152
- var injectIslandPageContextStream = (stream, options) => {
32153
- const manifest = globalThis.__absoluteManifest;
32154
- if (!manifest)
32155
- return stream;
32156
- const markup = buildIslandsHeadMarkup(manifest);
32157
- if (options?.hasIslands === true) {
32158
- return pipeStreamWithHeadInjection(stream, markup);
32159
- }
32160
- if (options?.hasIslands === false) {
32161
- return stream;
32162
- }
32163
- return pipeStreamWithIslandMarkerDetection(stream, markup);
32164
- };
32165
- var setCurrentIslandManifest = (manifest) => {
32166
- globalThis.__absoluteManifest = manifest;
32167
- };
32168
-
32169
- // src/core/pageHandlers.ts
32170
31995
  init_pageResponseCache();
32171
31996
  init_staticStreaming();
31997
+ var {file } = globalThis.Bun;
32172
31998
 
32173
31999
  // src/core/responseEnhancers.ts
32174
32000
  init_streamingSlots();
@@ -32527,7 +32353,227 @@ var finalizeAbsoluteMobilePage = (input) => {
32527
32353
  }
32528
32354
  };
32529
32355
 
32356
+ // src/core/islandPageContext.ts
32357
+ var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient";
32358
+ var ISLAND_MARKER = 'data-island="true"';
32359
+ var MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__";
32360
+ var ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__";
32361
+ var CLOSING_HEAD_TAG2 = "</head>";
32362
+ var buildIslandsHeadMarkup = (manifest) => {
32363
+ const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
32364
+ const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
32365
+ const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
32366
+ const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
32367
+ return `${manifestScript}${islandStateScript}${bootstrapScript}`;
32368
+ };
32369
+ var injectHeadMarkup = (html, markup) => {
32370
+ const closingHeadIndex = html.indexOf("</head>");
32371
+ if (closingHeadIndex >= 0) {
32372
+ return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
32373
+ }
32374
+ const openingBodyIndex = html.indexOf("<body");
32375
+ if (openingBodyIndex >= 0) {
32376
+ const bodyStart = html.indexOf(">", openingBodyIndex);
32377
+ if (bodyStart >= 0) {
32378
+ return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
32379
+ }
32380
+ }
32381
+ return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
32382
+ };
32383
+ var streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
32384
+ var flushSafePendingText = (controller, encoder, pending, lookbehind) => {
32385
+ if (pending.length <= lookbehind) {
32386
+ return pending;
32387
+ }
32388
+ const safeText = pending.slice(0, pending.length - lookbehind);
32389
+ controller.enqueue(encoder.encode(safeText));
32390
+ return pending.slice(-lookbehind);
32391
+ };
32392
+ var updateInjectedState = (consumed, injected, pending) => {
32393
+ if (consumed.done) {
32394
+ return { done: true, injected, pending };
32395
+ }
32396
+ return {
32397
+ done: false,
32398
+ injected: consumed.injected,
32399
+ pending: consumed.pending
32400
+ };
32401
+ };
32402
+ var readStreamChunk = async (reader) => {
32403
+ const { done, value } = await reader.read();
32404
+ if (done || !value) {
32405
+ return { done, value: undefined };
32406
+ }
32407
+ return { done, value };
32408
+ };
32409
+ var pipeStreamWithHeadInjection = (stream, markup) => {
32410
+ const encoder = new TextEncoder;
32411
+ const decoder = new TextDecoder;
32412
+ const lookbehind = CLOSING_HEAD_TAG2.length - 1;
32413
+ const processPending = (controller, pending, injected) => {
32414
+ if (injected) {
32415
+ controller.enqueue(encoder.encode(pending));
32416
+ return { injected, pending: "" };
32417
+ }
32418
+ const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
32419
+ if (headIndex >= 0) {
32420
+ const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
32421
+ controller.enqueue(encoder.encode(next));
32422
+ return { injected: true, pending: "" };
32423
+ }
32424
+ return {
32425
+ injected,
32426
+ pending: flushSafePendingText(controller, encoder, pending, lookbehind)
32427
+ };
32428
+ };
32429
+ const finishHeadInjectionStream = (controller, pending, injected) => {
32430
+ let finalPending = pending + decoder.decode();
32431
+ if (!injected) {
32432
+ finalPending = injectHeadMarkup(finalPending, markup);
32433
+ }
32434
+ if (finalPending.length > 0) {
32435
+ controller.enqueue(encoder.encode(finalPending));
32436
+ }
32437
+ controller.close();
32438
+ };
32439
+ const consumeHeadChunk = async (controller, reader, pending, injected) => {
32440
+ const { done, value } = await readStreamChunk(reader);
32441
+ if (done || !value) {
32442
+ return { done, injected, pending };
32443
+ }
32444
+ const processed = processPending(controller, pending + streamChunkToString2(value, decoder), injected);
32445
+ return {
32446
+ done,
32447
+ injected: processed.injected,
32448
+ pending: processed.pending
32449
+ };
32450
+ };
32451
+ const runHeadInjectionLoop = async (controller, reader) => {
32452
+ const consumeNextHeadChunk = async (injected, pending) => {
32453
+ const consumed = await consumeHeadChunk(controller, reader, pending, injected);
32454
+ const nextState = updateInjectedState(consumed, injected, pending);
32455
+ if (nextState.done) {
32456
+ return { injected, pending };
32457
+ }
32458
+ return consumeNextHeadChunk(nextState.injected, nextState.pending);
32459
+ };
32460
+ return consumeNextHeadChunk(false, "");
32461
+ };
32462
+ return new ReadableStream({
32463
+ async start(controller) {
32464
+ const reader = stream.getReader();
32465
+ try {
32466
+ const { injected, pending } = await runHeadInjectionLoop(controller, reader);
32467
+ finishHeadInjectionStream(controller, pending, injected);
32468
+ } catch (error) {
32469
+ controller.error(error);
32470
+ }
32471
+ }
32472
+ });
32473
+ };
32474
+ var pipeStreamWithIslandMarkerDetection = (stream, markup) => {
32475
+ const encoder = new TextEncoder;
32476
+ const decoder = new TextDecoder;
32477
+ const headLookbehind = CLOSING_HEAD_TAG2.length - 1;
32478
+ const enqueue = (controller, text) => {
32479
+ if (text.length > 0) {
32480
+ controller.enqueue(encoder.encode(text));
32481
+ }
32482
+ };
32483
+ const processHolding = (controller, held) => {
32484
+ if (!held.includes(ISLAND_MARKER)) {
32485
+ return { held, injected: false, pending: "", sawHead: true };
32486
+ }
32487
+ enqueue(controller, `${markup}${held}`);
32488
+ return { held: "", injected: true, pending: "", sawHead: true };
32489
+ };
32490
+ const processHead = (controller, pending) => {
32491
+ const headIndex = pending.indexOf(CLOSING_HEAD_TAG2);
32492
+ if (headIndex < 0) {
32493
+ return {
32494
+ held: "",
32495
+ injected: false,
32496
+ pending: flushSafePendingText(controller, encoder, pending, headLookbehind),
32497
+ sawHead: false
32498
+ };
32499
+ }
32500
+ enqueue(controller, pending.slice(0, headIndex));
32501
+ return processHolding(controller, pending.slice(headIndex));
32502
+ };
32503
+ const processChunk = (controller, state, chunk) => {
32504
+ if (state.injected) {
32505
+ enqueue(controller, chunk);
32506
+ return state;
32507
+ }
32508
+ if (!state.sawHead) {
32509
+ return processHead(controller, state.pending + chunk);
32510
+ }
32511
+ return processHolding(controller, state.held + chunk);
32512
+ };
32513
+ const finishMarkerStream = (controller, state) => {
32514
+ const tail = decoder.decode();
32515
+ const remainder = state.injected ? tail : (state.sawHead ? state.held : state.pending) + tail;
32516
+ enqueue(controller, remainder);
32517
+ controller.close();
32518
+ };
32519
+ const runMarkerLoop = (controller, reader) => {
32520
+ const consumeNext = async (state) => {
32521
+ const { done, value } = await readStreamChunk(reader);
32522
+ if (done || !value) {
32523
+ return state;
32524
+ }
32525
+ return consumeNext(processChunk(controller, state, streamChunkToString2(value, decoder)));
32526
+ };
32527
+ return consumeNext({
32528
+ held: "",
32529
+ injected: false,
32530
+ pending: "",
32531
+ sawHead: false
32532
+ });
32533
+ };
32534
+ return new ReadableStream({
32535
+ async start(controller) {
32536
+ const reader = stream.getReader();
32537
+ try {
32538
+ const finalState = await runMarkerLoop(controller, reader);
32539
+ finishMarkerStream(controller, finalState);
32540
+ } catch (error) {
32541
+ controller.error(error);
32542
+ }
32543
+ }
32544
+ });
32545
+ };
32546
+ var htmlContainsIslands = (html) => html.includes(ISLAND_MARKER);
32547
+ var injectIslandPageContext = (html, options) => {
32548
+ const manifest = globalThis.__absoluteManifest;
32549
+ const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
32550
+ if (!manifest || !hasIslands) {
32551
+ return html;
32552
+ }
32553
+ if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
32554
+ return html;
32555
+ }
32556
+ return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
32557
+ };
32558
+ var injectIslandPageContextStream = (stream, options) => {
32559
+ const manifest = globalThis.__absoluteManifest;
32560
+ if (!manifest)
32561
+ return stream;
32562
+ const markup = buildIslandsHeadMarkup(manifest);
32563
+ if (options?.hasIslands === true) {
32564
+ return pipeStreamWithHeadInjection(stream, markup);
32565
+ }
32566
+ if (options?.hasIslands === false) {
32567
+ return stream;
32568
+ }
32569
+ return pipeStreamWithIslandMarkerDetection(stream, markup);
32570
+ };
32571
+ var setCurrentIslandManifest = (manifest) => {
32572
+ globalThis.__absoluteManifest = manifest;
32573
+ };
32574
+
32530
32575
  // src/core/pageHandlers.ts
32576
+ init_browserTranslation();
32531
32577
  var finalizeStaticMobilePage = (framework, pagePath, metadata2) => {
32532
32578
  const pageId = metadata2?.pageId ?? `${framework}:${pagePath}`;
32533
32579
  const contract = metadata2?.contract ?? `${framework}:${pageId}:${ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION}`;
@@ -32545,7 +32591,8 @@ var finalizeStaticMobilePage = (framework, pagePath, metadata2) => {
32545
32591
  var handleStaticPageRequest = async (pagePath, options = {}, settings = {}) => {
32546
32592
  const html = await file(pagePath).text();
32547
32593
  const transformedHtml = await transformCurrentStaticPageHtml(html, settings);
32548
- return withPageCacheHeaders(await withStreamingSlots(new Response(injectIslandPageContext(transformedHtml), {
32594
+ const htmlWithTranslationBaseline = htmlContainsIslands(transformedHtml) ? injectBrowserTranslationBaseline(transformedHtml) : transformedHtml;
32595
+ return withPageCacheHeaders(await withStreamingSlots(new Response(injectIslandPageContext(htmlWithTranslationBaseline), {
32549
32596
  headers: { "Content-Type": "text/html" }
32550
32597
  }), {
32551
32598
  ...options,
@@ -41114,5 +41161,5 @@ export {
41114
41161
  wrapPageHandlerWithStreamingSlots
41115
41162
  };
41116
41163
 
41117
- //# debugId=B3A531CE0B0E139B64756E2164756E21
41164
+ //# debugId=2FE5D4DBD640F62964756E2164756E21
41118
41165
  //# sourceMappingURL=index.js.map