preact-render-to-string 6.4.2 → 6.5.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/dist/commonjs.js +1 -1
- package/dist/commonjs.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/internal.d.ts +35 -0
- package/dist/jsx-entry.js +1 -1
- package/dist/jsx-entry.js.map +1 -1
- package/dist/jsx.js.map +1 -1
- package/dist/jsx.mjs +1 -1
- package/dist/jsx.mjs.map +1 -1
- package/dist/jsx.module.js +1 -1
- package/dist/jsx.module.js.map +1 -1
- package/dist/jsx.umd.js +1 -1
- package/dist/jsx.umd.js.map +1 -1
- package/dist/stream-node.js +786 -0
- package/dist/stream-node.js.map +1 -0
- package/dist/stream-node.module.js +786 -0
- package/dist/stream-node.module.js.map +1 -0
- package/dist/stream-node.umd.js +790 -0
- package/dist/stream-node.umd.js.map +1 -0
- package/dist/stream.js +2 -0
- package/dist/stream.js.map +1 -0
- package/dist/stream.module.js +2 -0
- package/dist/stream.module.js.map +1 -0
- package/dist/stream.umd.js +2 -0
- package/dist/stream.umd.js.map +1 -0
- package/jsx.d.ts +1 -1
- package/package.json +166 -157
- package/src/index.js +54 -18
- package/src/internal.d.ts +35 -0
- package/src/jsx.js +2 -4
- package/src/lib/chunked.js +97 -0
- package/src/lib/client.js +61 -0
- package/src/{constants.js → lib/constants.js} +3 -0
- package/src/{util.js → lib/util.js} +13 -1
- package/src/pretty.js +13 -13
- package/src/stream-node.js +60 -0
- package/src/stream.js +43 -0
- /package/src/{polyfills.js → lib/polyfills.js} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/* eslint-disable no-var, key-spacing, object-curly-spacing, prefer-arrow-callback, semi, keyword-spacing */
|
|
2
|
+
|
|
3
|
+
function initPreactIslandElement() {
|
|
4
|
+
class PreactIslandElement extends HTMLElement {
|
|
5
|
+
connectedCallback() {
|
|
6
|
+
var d = this;
|
|
7
|
+
if (!d.isConnected) return;
|
|
8
|
+
|
|
9
|
+
let i = this.getAttribute('data-target');
|
|
10
|
+
if (!i) return;
|
|
11
|
+
|
|
12
|
+
var s,
|
|
13
|
+
e,
|
|
14
|
+
c = document.createNodeIterator(document, 128);
|
|
15
|
+
while (c.nextNode()) {
|
|
16
|
+
let n = c.referenceNode;
|
|
17
|
+
|
|
18
|
+
if (n.data == 'preact-island:' + i) s = n;
|
|
19
|
+
else if (n.data == '/preact-island:' + i) e = n;
|
|
20
|
+
if (s && e) break;
|
|
21
|
+
}
|
|
22
|
+
if (s && e) {
|
|
23
|
+
var p = e.previousSibling;
|
|
24
|
+
while (p != s) {
|
|
25
|
+
if (!p || p == s) break;
|
|
26
|
+
e.parentNode.removeChild(p);
|
|
27
|
+
p = e.previousSibling;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
requestAnimationFrame(() => {
|
|
31
|
+
for (let i = 0; i <= d.children.length; i++) {
|
|
32
|
+
const child = d.children[i];
|
|
33
|
+
e.parentNode.insertBefore(child, e);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
d.parentNode.removeChild(d);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
customElements.define('preact-island', PreactIslandElement);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const fn = initPreactIslandElement.toString();
|
|
46
|
+
const INIT_SCRIPT = fn
|
|
47
|
+
.slice(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
|
|
48
|
+
.replace(/\n\s+/gm, '');
|
|
49
|
+
|
|
50
|
+
export function createInitScript() {
|
|
51
|
+
return `<script>(function(){${INIT_SCRIPT}}())</script>`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} id
|
|
56
|
+
* @param {string} content
|
|
57
|
+
* @returns {string}
|
|
58
|
+
*/
|
|
59
|
+
export function createSubtree(id, content) {
|
|
60
|
+
return `<preact-island hidden data-target="${id}">${content}</preact-island>`;
|
|
61
|
+
}
|
|
@@ -4,13 +4,16 @@ export const RENDER = '__r';
|
|
|
4
4
|
export const DIFFED = 'diffed';
|
|
5
5
|
export const COMMIT = '__c';
|
|
6
6
|
export const SKIP_EFFECTS = '__s';
|
|
7
|
+
export const CATCH_ERROR = '__e';
|
|
7
8
|
|
|
8
9
|
// VNode properties
|
|
9
10
|
export const COMPONENT = '__c';
|
|
10
11
|
export const CHILDREN = '__k';
|
|
11
12
|
export const PARENT = '__';
|
|
13
|
+
export const MASK = '__m';
|
|
12
14
|
|
|
13
15
|
// Component properties
|
|
14
16
|
export const VNODE = '__v';
|
|
15
17
|
export const DIRTY = '__d';
|
|
16
18
|
export const NEXT_STATE = '__s';
|
|
19
|
+
export const CHILD_DID_SUSPEND = '__c';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/;
|
|
2
2
|
export const UNSAFE_NAME = /[\s\n\\/='"\0<>]/;
|
|
3
3
|
export const NAMESPACE_REPLACE_REGEX = /^(xlink|xmlns|xml)([A-Z])/;
|
|
4
|
-
export const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|readO|rowS|spellC|src[A-Z]|tabI|item[A-Z]/;
|
|
4
|
+
export const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^cell|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|popoverT|readO|rowS|spellC|src[A-Z]|tabI|useM|item[A-Z]/;
|
|
5
5
|
export const SVG_CAMEL_CASE = /^ac|^ali|arabic|basel|cap|clipPath$|clipRule$|color|dominant|enable|fill|flood|font|glyph[^R]|horiz|image|letter|lighting|marker[^WUH]|overline|panose|pointe|paint|rendering|shape|stop|strikethrough|stroke|text[^L]|transform|underline|unicode|units|^v[^i]|^w|^xH/;
|
|
6
6
|
|
|
7
7
|
// DOM properties that should NOT have "px" added when numeric
|
|
@@ -151,6 +151,18 @@ export function createComponent(vnode, context) {
|
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
// Necessary for createContext api. Setting this property will pass
|
|
155
|
+
// the context value as `this.context` just for this component.
|
|
156
|
+
export function getContext(nodeName, context) {
|
|
157
|
+
let cxType = nodeName.contextType;
|
|
158
|
+
let provider = cxType && context[cxType.__c];
|
|
159
|
+
return cxType != null
|
|
160
|
+
? provider
|
|
161
|
+
? provider.props.value
|
|
162
|
+
: cxType.__
|
|
163
|
+
: context;
|
|
164
|
+
}
|
|
165
|
+
|
|
154
166
|
/**
|
|
155
167
|
* @template T
|
|
156
168
|
*/
|
package/src/pretty.js
CHANGED
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
UNSAFE_NAME,
|
|
9
9
|
VOID_ELEMENTS,
|
|
10
10
|
NAMESPACE_REPLACE_REGEX,
|
|
11
|
+
SVG_CAMEL_CASE,
|
|
11
12
|
HTML_LOWER_CASE,
|
|
12
|
-
|
|
13
|
-
} from './util.js';
|
|
14
|
-
import { COMMIT, DIFF, DIFFED, RENDER, SKIP_EFFECTS } from './constants.js';
|
|
13
|
+
getContext
|
|
14
|
+
} from './lib/util.js';
|
|
15
|
+
import { COMMIT, DIFF, DIFFED, RENDER, SKIP_EFFECTS } from './lib/constants.js';
|
|
15
16
|
import { options, Fragment } from 'preact';
|
|
16
17
|
|
|
17
|
-
/** @typedef {import('preact').VNode} VNode */
|
|
18
|
-
|
|
19
18
|
// components without names, kept as a hash for later comparison to return consistent UnnamedComponentXX names.
|
|
20
19
|
const UNNAMED = [];
|
|
21
20
|
|
|
@@ -104,7 +103,11 @@ function _renderToStringPretty(
|
|
|
104
103
|
// components
|
|
105
104
|
if (typeof nodeName === 'function') {
|
|
106
105
|
isComponent = true;
|
|
107
|
-
if (
|
|
106
|
+
if (
|
|
107
|
+
opts.shallow &&
|
|
108
|
+
(inner || opts.renderRootComponent === false) &&
|
|
109
|
+
nodeName !== Fragment
|
|
110
|
+
) {
|
|
108
111
|
nodeName = getComponentName(nodeName);
|
|
109
112
|
} else if (nodeName === Fragment) {
|
|
110
113
|
const children = [];
|
|
@@ -124,17 +127,12 @@ function _renderToStringPretty(
|
|
|
124
127
|
|
|
125
128
|
let renderHook = options[RENDER];
|
|
126
129
|
|
|
127
|
-
let cctx = context;
|
|
128
|
-
let cxType = nodeName.contextType;
|
|
129
|
-
if (cxType != null) {
|
|
130
|
-
let provider = context[cxType.__c];
|
|
131
|
-
cctx = provider ? provider.props.value : cxType.__;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
130
|
if (
|
|
135
131
|
!nodeName.prototype ||
|
|
136
132
|
typeof nodeName.prototype.render !== 'function'
|
|
137
133
|
) {
|
|
134
|
+
let cctx = getContext(nodeName, context);
|
|
135
|
+
|
|
138
136
|
// If a hook invokes setState() to invalidate the component during rendering,
|
|
139
137
|
// re-render it up to 25 times to allow "settling" of memoized states.
|
|
140
138
|
// Note:
|
|
@@ -150,6 +148,8 @@ function _renderToStringPretty(
|
|
|
150
148
|
rendered = nodeName.call(vnode.__c, props, cctx);
|
|
151
149
|
}
|
|
152
150
|
} else {
|
|
151
|
+
let cctx = getContext(nodeName, context);
|
|
152
|
+
|
|
153
153
|
// c = new nodeName(props, context);
|
|
154
154
|
c = vnode.__c = new nodeName(props, cctx);
|
|
155
155
|
c.__v = vnode;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { PassThrough } from 'node:stream';
|
|
2
|
+
import { renderToChunks } from './lib/chunked.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} RenderToPipeableStreamOptions
|
|
6
|
+
* @property {() => void} [onShellReady]
|
|
7
|
+
* @property {() => void} [onAllReady]
|
|
8
|
+
* @property {(error) => void} [onError]
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {import('preact').VNode} vnode
|
|
13
|
+
* @param {RenderToPipeableStreamOptions} options
|
|
14
|
+
* @param {any} [context]
|
|
15
|
+
* @returns {{}}
|
|
16
|
+
*/
|
|
17
|
+
export function renderToPipeableStream(vnode, options, context) {
|
|
18
|
+
const encoder = new TextEncoder('utf-8');
|
|
19
|
+
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const stream = new PassThrough();
|
|
22
|
+
|
|
23
|
+
renderToChunks(vnode, {
|
|
24
|
+
context,
|
|
25
|
+
abortSignal: controller.signal,
|
|
26
|
+
onError: (error) => {
|
|
27
|
+
if (options.onError) {
|
|
28
|
+
options.onError(error);
|
|
29
|
+
}
|
|
30
|
+
controller.abort(error);
|
|
31
|
+
},
|
|
32
|
+
onWrite(s) {
|
|
33
|
+
stream.write(encoder.encode(s));
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
.then(() => {
|
|
37
|
+
options.onAllReady && options.onAllReady();
|
|
38
|
+
stream.end();
|
|
39
|
+
})
|
|
40
|
+
.catch((error) => {
|
|
41
|
+
stream.destroy(error);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
Promise.resolve().then(() => {
|
|
45
|
+
options.onShellReady && options.onShellReady();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
abort() {
|
|
50
|
+
controller.abort();
|
|
51
|
+
stream.destroy(new Error('aborted'));
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* @param {import("stream").Writable} writable
|
|
55
|
+
*/
|
|
56
|
+
pipe(writable) {
|
|
57
|
+
stream.pipe(writable, { end: true });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
package/src/stream.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Deferred } from './lib/util.js';
|
|
2
|
+
import { renderToChunks } from './lib/chunked.js';
|
|
3
|
+
|
|
4
|
+
/** @typedef {ReadableStream<Uint8Array> & { allReady: Promise<void>}} RenderStream */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {import('preact').VNode} vnode
|
|
8
|
+
* @param {any} [context]
|
|
9
|
+
* @returns {RenderStream}
|
|
10
|
+
*/
|
|
11
|
+
export function renderToReadableStream(vnode, context) {
|
|
12
|
+
/** @type {Deferred<void>} */
|
|
13
|
+
const allReady = new Deferred();
|
|
14
|
+
const encoder = new TextEncoder('utf-8');
|
|
15
|
+
|
|
16
|
+
/** @type {RenderStream} */
|
|
17
|
+
const stream = new ReadableStream({
|
|
18
|
+
start(controller) {
|
|
19
|
+
renderToChunks(vnode, {
|
|
20
|
+
context,
|
|
21
|
+
onError: (error) => {
|
|
22
|
+
allReady.reject(error);
|
|
23
|
+
controller.abort(error);
|
|
24
|
+
},
|
|
25
|
+
onWrite(s) {
|
|
26
|
+
controller.enqueue(encoder.encode(s));
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
.then(() => {
|
|
30
|
+
controller.close();
|
|
31
|
+
allReady.resolve();
|
|
32
|
+
})
|
|
33
|
+
.catch((error) => {
|
|
34
|
+
controller.error(error);
|
|
35
|
+
allReady.reject(error);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
stream.allReady = allReady.promise;
|
|
41
|
+
|
|
42
|
+
return stream;
|
|
43
|
+
}
|
|
File without changes
|