123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- import { sharedConfig, awaitSuspense, splitProps } from 'solid-js';
- export { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, mergeProps } from 'solid-js';
- import { Readable } from 'stream';
- const booleans = ["allowfullscreen", "allowpaymentrequest", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "ismap", "itemscope", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected", "truespeed"];
- const BooleanAttributes = new Set(booleans);
- const Aliases = {
- className: "class",
- htmlFor: "for"
- };
- function renderToString(code, options = {}) {
- sharedConfig.context = {
- id: "",
- count: 0
- };
- return {
- html: resolveSSRNode(code()),
- script: generateHydrationScript(options)
- };
- }
- function renderToStringAsync(code, options = {}) {
- options = {
- timeoutMs: 30000,
- ...options
- };
- let resources;
- sharedConfig.context = {
- id: "",
- count: 0,
- resources: resources = {},
- suspense: {},
- async: true
- };
- const timeout = new Promise((_, reject) => setTimeout(() => reject("renderToString timed out"), options.timeoutMs));
- return Promise.race([awaitSuspense(code), timeout]).then(res => {
- return {
- html: resolveSSRNode(res),
- script: generateHydrationScript({
- resources,
- ...options
- })
- };
- });
- }
- function renderToNodeStream(code, options = {}) {
- const stream = new Readable({
- read() {}
- });
- sharedConfig.context = {
- id: "",
- count: 0,
- streaming: true,
- suspense: {}
- };
- let count = 0,
- completed = 0,
- checkEnd = () => {
- if (completed === count) stream.push(null);
- };
- sharedConfig.context.writeResource = (id, p) => {
- count++;
- Promise.resolve().then(() => stream.push(`<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`));
- p.then(d => {
- stream.push(`<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${(JSON.stringify(d) || "undefined").replace(/'/g, "\\'").replace(/\\\"/g, '\\\\\\"')})</script>`);
- ++completed && checkEnd();
- });
- };
- stream.push(resolveSSRNode(code()));
- setTimeout(checkEnd);
- return {
- stream,
- script: generateHydrationScript({
- streaming: true,
- ...options
- })
- };
- }
- function renderToWebStream(code, options = {}) {
- let checkEnd;
- const tmp = [];
- const encoder = new TextEncoder();
- const done = new Promise(resolve => {
- checkEnd = () => {
- if (completed === count) resolve();
- };
- });
- sharedConfig.context = {
- id: "",
- count: 0,
- streaming: true
- };
- let count = 0,
- completed = 0,
- writer = {
- write(payload) {
- tmp.push(payload);
- }
- };
- sharedConfig.context.writeResource = (id, p) => {
- count++;
- Promise.resolve().then(() => writer.write(encoder.encode(`<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>_$HYDRATION.startResource("${id}")</script>`)));
- p.then(d => {
- writer.write(encoder.encode(`<script${options.nonce ? ` nonce="${options.nonce}"` : ""}>_$HYDRATION.resolveResource("${id}", ${(JSON.stringify(d) || "undefined").replace(/'/g, "\\'").replace(/\\\"/g, '\\\\\\"')})</script>`));
- ++completed && checkEnd();
- });
- };
- writer.write(encoder.encode(resolveSSRNode(code())));
- return {
- writeTo(w) {
- writer = w;
- tmp.map(chunk => writer.write(chunk));
- setTimeout(checkEnd);
- return done;
- },
- script: generateHydrationScript({
- streaming: true,
- ...options
- })
- };
- }
- function ssr(t, ...nodes) {
- if (nodes.length) {
- let result = "";
- for (let i = 0; i < t.length; i++) {
- result += t[i];
- const node = nodes[i];
- if (node !== undefined) result += resolveSSRNode(node);
- }
- t = result;
- }
- return {
- t
- };
- }
- function ssrClassList(value) {
- let classKeys = Object.keys(value),
- result = "";
- for (let i = 0, len = classKeys.length; i < len; i++) {
- const key = classKeys[i],
- classValue = !!value[key];
- if (!key || !classValue) continue;
- i && (result += " ");
- result += key;
- }
- return result;
- }
- function ssrStyle(value) {
- if (typeof value === "string") return value;
- let result = "";
- const k = Object.keys(value);
- for (let i = 0; i < k.length; i++) {
- const s = k[i];
- if (i) result += ";";
- result += `${s}:${escape(value[s], true)}`;
- }
- return result;
- }
- function ssrSpread(props, isSVG, skipChildren) {
- if (typeof props === "function") props = props();
- const keys = Object.keys(props);
- let result = "";
- for (let i = 0; i < keys.length; i++) {
- const prop = keys[i];
- if (prop === "children") {
- !skipChildren && console.warn(`SSR currently does not support spread children.`);
- continue;
- }
- const value = props[prop];
- if (prop === "style") {
- result += `style="${ssrStyle(value)}"`;
- } else if (prop === "classList") {
- result += `class="${ssrClassList(value)}"`;
- } else if (BooleanAttributes.has(prop)) {
- if (value) result += prop;else continue;
- } else {
- result += `${Aliases[prop] || prop}="${escape(value, true)}"`;
- }
- if (i !== keys.length - 1) result += " ";
- }
- return result;
- }
- function ssrBoolean(key, value) {
- return value ? " " + key : "";
- }
- function escape(s, attr) {
- const t = typeof s;
- if (t !== "string") {
- if (attr && t === "boolean") return String(s);
- return s;
- }
- const delim = attr ? '"' : "<";
- const escDelim = attr ? """ : "<";
- let iDelim = s.indexOf(delim);
- let iAmp = s.indexOf("&");
- if (iDelim < 0 && iAmp < 0) return s;
- let left = 0,
- out = "";
- while (iDelim >= 0 && iAmp >= 0) {
- if (iDelim < iAmp) {
- if (left < iDelim) out += s.substring(left, iDelim);
- out += escDelim;
- left = iDelim + 1;
- iDelim = s.indexOf(delim, left);
- } else {
- if (left < iAmp) out += s.substring(left, iAmp);
- out += "&";
- left = iAmp + 1;
- iAmp = s.indexOf("&", left);
- }
- }
- if (iDelim >= 0) {
- do {
- if (left < iDelim) out += s.substring(left, iDelim);
- out += escDelim;
- left = iDelim + 1;
- iDelim = s.indexOf(delim, left);
- } while (iDelim >= 0);
- } else while (iAmp >= 0) {
- if (left < iAmp) out += s.substring(left, iAmp);
- out += "&";
- left = iAmp + 1;
- iAmp = s.indexOf("&", left);
- }
- return left < s.length ? out + s.substring(left) : out;
- }
- function resolveSSRNode(node) {
- const t = typeof node;
- if (t === "string") return node;
- if (node == null || t === "boolean") return "";
- if (Array.isArray(node)) return node.map(resolveSSRNode).join("");
- if (t === "object") return resolveSSRNode(node.t);
- if (t === "function") return resolveSSRNode(node());
- return String(node);
- }
- function getHydrationKey() {
- const hydrate = sharedConfig.context;
- return `${hydrate.id}${hydrate.count++}`;
- }
- function generateHydrationScript({
- eventNames = ["click", "input"],
- streaming,
- resources,
- nonce
- } = {}) {
- let s = `<script${nonce ? ` nonce="${nonce}"` : ""}>(()=>{_$HYDRATION={events:[],completed:new WeakSet};const t=e=>e&&e.hasAttribute&&(e.hasAttribute("data-hk")&&e||t(e.host&&e.host instanceof Node?e.host:e.parentNode)),e=e=>{let o=e.composedPath&&e.composedPath()[0]||e.target,s=t(o);s&&!_$HYDRATION.completed.has(s)&&_$HYDRATION.events.push([s,e])};["${eventNames.join('","')}"].forEach(t=>document.addEventListener(t,e))})();`;
- if (streaming) {
- s += `(()=>{const e=_$HYDRATION,o={};e.startResource=e=>{let r;o[e]=[new Promise(e=>r=e),r]},e.resolveResource=(e,r)=>{const n=o[e];if(!n)return o[e]=[r];n[1](r)},e.loadResource=e=>{const r=o[e];if(r)return r[0]}})();`;
- }
- if (resources) s += `_$HYDRATION.resources = JSON.parse('${JSON.stringify(Object.keys(resources).reduce((r, k) => {
- r[k] = resources[k].data;
- return r;
- }, {})).replace(/'/g, "\\'").replace(/\\\"/g, '\\\\\\"')}');`;
- return s + `</script>`;
- }
- const isServer = true;
- function spread() {}
- function Dynamic(props) {
- const [p, others] = splitProps(props, ["component"]);
- const comp = p.component,
- t = typeof comp;
- if (comp) {
- if (t === "function") return comp(others);else if (t === "string") {
- const [local, sOthers] = splitProps(others, ["children"]);
- return ssr([`<${comp} `, ">", `</${comp}>`], ssrSpread(sOthers), local.children || "");
- }
- }
- }
- function Portal(props) {
- return "";
- }
- export { Dynamic, Portal, escape, getHydrationKey, isServer, renderToNodeStream, renderToString, renderToStringAsync, renderToWebStream, resolveSSRNode, spread, ssr, ssrBoolean, ssrClassList, ssrSpread, ssrStyle };
|