Auto-commit 2026-04-29 16:31
This commit is contained in:
16
node_modules/preact-render-to-string/src/constants.js
generated
vendored
Normal file
16
node_modules/preact-render-to-string/src/constants.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Options hooks
|
||||
export const DIFF = '__b';
|
||||
export const RENDER = '__r';
|
||||
export const DIFFED = 'diffed';
|
||||
export const COMMIT = '__c';
|
||||
export const SKIP_EFFECTS = '__s';
|
||||
|
||||
// VNode properties
|
||||
export const COMPONENT = '__c';
|
||||
export const CHILDREN = '__k';
|
||||
export const PARENT = '__';
|
||||
|
||||
// Component properties
|
||||
export const VNODE = '__v';
|
||||
export const DIRTY = '__d';
|
||||
export const NEXT_STATE = '__s';
|
||||
16
node_modules/preact-render-to-string/src/index.d.ts
generated
vendored
Normal file
16
node_modules/preact-render-to-string/src/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { VNode } from 'preact';
|
||||
|
||||
interface Options {
|
||||
shallow?: boolean;
|
||||
xml?: boolean;
|
||||
pretty?: boolean | string;
|
||||
}
|
||||
|
||||
export function render(vnode: VNode, context?: any, options?: Options): string;
|
||||
export function renderToString(
|
||||
vnode: VNode,
|
||||
context?: any,
|
||||
options?: Options
|
||||
): string;
|
||||
export function shallowRender(vnode: VNode, context?: any): string;
|
||||
export default render;
|
||||
457
node_modules/preact-render-to-string/src/index.js
generated
vendored
Normal file
457
node_modules/preact-render-to-string/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,457 @@
|
||||
import {
|
||||
encodeEntities,
|
||||
styleObjToCss,
|
||||
getContext,
|
||||
createComponent,
|
||||
UNSAFE_NAME,
|
||||
XLINK,
|
||||
VOID_ELEMENTS
|
||||
} from './util';
|
||||
import { options, h, Fragment } from 'preact';
|
||||
import { _renderToStringPretty } from './pretty';
|
||||
import {
|
||||
COMMIT,
|
||||
COMPONENT,
|
||||
DIFF,
|
||||
DIFFED,
|
||||
DIRTY,
|
||||
NEXT_STATE,
|
||||
PARENT,
|
||||
RENDER,
|
||||
SKIP_EFFECTS,
|
||||
VNODE,
|
||||
CHILDREN
|
||||
} from './constants';
|
||||
|
||||
/** @typedef {import('preact').VNode} VNode */
|
||||
|
||||
const SHALLOW = { shallow: true };
|
||||
|
||||
/** Render Preact JSX + Components to an HTML string.
|
||||
* @name render
|
||||
* @function
|
||||
* @param {VNode} vnode JSX VNode to render.
|
||||
* @param {Object} [context={}] Optionally pass an initial context object through the render path.
|
||||
* @param {Object} [options={}] Rendering options
|
||||
* @param {Boolean} [options.shallow=false] If `true`, renders nested Components as HTML elements (`<Foo a="b" />`).
|
||||
* @param {Boolean} [options.xml=false] If `true`, uses self-closing tags for elements without children.
|
||||
* @param {Boolean} [options.pretty=false] If `true`, adds whitespace for readability
|
||||
* @param {RegExp|undefined} [options.voidElements] RegeEx that matches elements that are considered void (self-closing)
|
||||
*/
|
||||
renderToString.render = renderToString;
|
||||
|
||||
/** Only render elements, leaving Components inline as `<ComponentName ... />`.
|
||||
* This method is just a convenience alias for `render(vnode, context, { shallow:true })`
|
||||
* @name shallow
|
||||
* @function
|
||||
* @param {VNode} vnode JSX VNode to render.
|
||||
* @param {Object} [context={}] Optionally pass an initial context object through the render path.
|
||||
*/
|
||||
let shallowRender = (vnode, context) => renderToString(vnode, context, SHALLOW);
|
||||
|
||||
const EMPTY_ARR = [];
|
||||
function renderToString(vnode, context, opts) {
|
||||
context = context || {};
|
||||
|
||||
// Performance optimization: `renderToString` is synchronous and we
|
||||
// therefore don't execute any effects. To do that we pass an empty
|
||||
// array to `options._commit` (`__c`). But we can go one step further
|
||||
// and avoid a lot of dirty checks and allocations by setting
|
||||
// `options._skipEffects` (`__s`) too.
|
||||
const previousSkipEffects = options[SKIP_EFFECTS];
|
||||
options[SKIP_EFFECTS] = true;
|
||||
|
||||
const parent = h(Fragment, null);
|
||||
parent[CHILDREN] = [vnode];
|
||||
|
||||
let res;
|
||||
if (
|
||||
opts &&
|
||||
(opts.pretty ||
|
||||
opts.voidElements ||
|
||||
opts.sortAttributes ||
|
||||
opts.shallow ||
|
||||
opts.allAttributes ||
|
||||
opts.xml ||
|
||||
opts.attributeHook)
|
||||
) {
|
||||
res = _renderToStringPretty(vnode, context, opts);
|
||||
} else {
|
||||
res = _renderToString(vnode, context, false, undefined, parent);
|
||||
}
|
||||
|
||||
// options._commit, we don't schedule any effects in this library right now,
|
||||
// so we can pass an empty queue to this hook.
|
||||
if (options[COMMIT]) options[COMMIT](vnode, EMPTY_ARR);
|
||||
options[SKIP_EFFECTS] = previousSkipEffects;
|
||||
EMPTY_ARR.length = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VNode} vnode
|
||||
* @param {Record<string, unknown>} context
|
||||
* @returns {string}
|
||||
*/
|
||||
function renderFunctionComponent(vnode, context) {
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
/** @type {string} */
|
||||
let rendered,
|
||||
c = createComponent(vnode, context),
|
||||
cctx = getContext(vnode.type, context);
|
||||
|
||||
vnode[COMPONENT] = c;
|
||||
|
||||
// If a hook invokes setState() to invalidate the component during rendering,
|
||||
// re-render it up to 25 times to allow "settling" of memoized states.
|
||||
// Note:
|
||||
// This will need to be updated for Preact 11 to use internal.flags rather than component._dirty:
|
||||
// https://github.com/preactjs/preact/blob/d4ca6fdb19bc715e49fd144e69f7296b2f4daa40/src/diff/component.js#L35-L44
|
||||
let renderHook = options[RENDER];
|
||||
let count = 0;
|
||||
while (c[DIRTY] && count++ < 25) {
|
||||
c[DIRTY] = false;
|
||||
|
||||
if (renderHook) renderHook(vnode);
|
||||
|
||||
// stateless functional components
|
||||
rendered = vnode.type.call(c, vnode.props, cctx);
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VNode} vnode
|
||||
* @param {Record<string, unknown>} context
|
||||
* @returns {VNode}
|
||||
*/
|
||||
function renderClassComponent(vnode, context) {
|
||||
let nodeName = vnode.type,
|
||||
cctx = getContext(nodeName, context);
|
||||
|
||||
/** @type {import("preact").Component} */
|
||||
let c = new nodeName(vnode.props, cctx);
|
||||
vnode[COMPONENT] = c;
|
||||
c[VNODE] = vnode;
|
||||
// turn off stateful re-rendering:
|
||||
c[DIRTY] = true;
|
||||
c.props = vnode.props;
|
||||
if (c.state == null) c.state = {};
|
||||
|
||||
if (c[NEXT_STATE] == null) {
|
||||
c[NEXT_STATE] = c.state;
|
||||
}
|
||||
|
||||
c.context = cctx;
|
||||
if (nodeName.getDerivedStateFromProps) {
|
||||
c.state = assign(
|
||||
{},
|
||||
c.state,
|
||||
nodeName.getDerivedStateFromProps(c.props, c.state)
|
||||
);
|
||||
} else if (c.componentWillMount) {
|
||||
c.componentWillMount();
|
||||
|
||||
// If the user called setState in cWM we need to flush pending,
|
||||
// state updates. This is the same behaviour in React.
|
||||
c.state = c[NEXT_STATE] !== c.state ? c[NEXT_STATE] : c.state;
|
||||
}
|
||||
|
||||
let renderHook = options[RENDER];
|
||||
if (renderHook) renderHook(vnode);
|
||||
|
||||
return c.render(c.props, c.state, c.context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} vnode
|
||||
* @returns {VNode}
|
||||
*/
|
||||
function normalizeVNode(vnode) {
|
||||
if (vnode == null || typeof vnode == 'boolean') {
|
||||
return null;
|
||||
} else if (
|
||||
typeof vnode == 'string' ||
|
||||
typeof vnode == 'number' ||
|
||||
typeof vnode == 'bigint'
|
||||
) {
|
||||
return h(null, null, vnode);
|
||||
}
|
||||
return vnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {boolean} isSvgMode
|
||||
* @returns {string}
|
||||
*/
|
||||
function normalizePropName(name, isSvgMode) {
|
||||
if (name === 'className') {
|
||||
return 'class';
|
||||
} else if (name === 'htmlFor') {
|
||||
return 'for';
|
||||
} else if (name === 'defaultValue') {
|
||||
return 'value';
|
||||
} else if (name === 'defaultChecked') {
|
||||
return 'checked';
|
||||
} else if (name === 'defaultSelected') {
|
||||
return 'selected';
|
||||
} else if (isSvgMode && XLINK.test(name)) {
|
||||
return name.toLowerCase().replace(/^xlink:?/, 'xlink:');
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {string | Record<string, unknown>} v
|
||||
* @returns {string}
|
||||
*/
|
||||
function normalizePropValue(name, v) {
|
||||
if (name === 'style' && v != null && typeof v === 'object') {
|
||||
return styleObjToCss(v);
|
||||
} else if (name[0] === 'a' && name[1] === 'r' && typeof v === 'boolean') {
|
||||
// always use string values instead of booleans for aria attributes
|
||||
// also see https://github.com/preactjs/preact/pull/2347/files
|
||||
return String(v);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
const isArray = Array.isArray;
|
||||
const assign = Object.assign;
|
||||
|
||||
/**
|
||||
* The default export is an alias of `render()`.
|
||||
* @param {any} vnode
|
||||
* @param {Record<string, unknown>} context
|
||||
* @param {boolean} isSvgMode
|
||||
* @param {any} selectValue
|
||||
* @param {VNode | null} parent
|
||||
* @returns {string}
|
||||
*/
|
||||
function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
|
||||
// Ignore non-rendered VNodes/values
|
||||
if (vnode == null || vnode === true || vnode === false || vnode === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Text VNodes: escape as HTML
|
||||
if (typeof vnode !== 'object') {
|
||||
if (typeof vnode === 'function') return '';
|
||||
return encodeEntities(vnode);
|
||||
}
|
||||
|
||||
// Recurse into children / Arrays
|
||||
if (isArray(vnode)) {
|
||||
let rendered = '';
|
||||
parent[CHILDREN] = vnode;
|
||||
for (let i = 0; i < vnode.length; i++) {
|
||||
rendered =
|
||||
rendered +
|
||||
_renderToString(vnode[i], context, isSvgMode, selectValue, parent);
|
||||
|
||||
vnode[i] = normalizeVNode(vnode[i]);
|
||||
}
|
||||
return rendered;
|
||||
}
|
||||
|
||||
// VNodes have {constructor:undefined} to prevent JSON injection:
|
||||
if (vnode.constructor !== undefined) return '';
|
||||
|
||||
vnode[PARENT] = parent;
|
||||
if (options[DIFF]) options[DIFF](vnode);
|
||||
|
||||
let type = vnode.type,
|
||||
props = vnode.props;
|
||||
|
||||
// Invoke rendering on Components
|
||||
const isComponent = typeof type === 'function';
|
||||
if (isComponent) {
|
||||
let rendered;
|
||||
if (type === Fragment) {
|
||||
rendered = props.children;
|
||||
} else {
|
||||
if (type.prototype && typeof type.prototype.render === 'function') {
|
||||
rendered = renderClassComponent(vnode, context);
|
||||
} else {
|
||||
rendered = renderFunctionComponent(vnode, context);
|
||||
}
|
||||
|
||||
let component = vnode[COMPONENT];
|
||||
if (component.getChildContext) {
|
||||
context = assign({}, context, component.getChildContext());
|
||||
}
|
||||
}
|
||||
|
||||
// When a component returns a Fragment node we flatten it in core, so we
|
||||
// need to mirror that logic here too
|
||||
let isTopLevelFragment =
|
||||
rendered != null && rendered.type === Fragment && rendered.key == null;
|
||||
rendered = isTopLevelFragment ? rendered.props.children : rendered;
|
||||
|
||||
// Recurse into children before invoking the after-diff hook
|
||||
const str = _renderToString(
|
||||
rendered,
|
||||
context,
|
||||
isSvgMode,
|
||||
selectValue,
|
||||
vnode
|
||||
);
|
||||
|
||||
if (options[DIFFED]) options[DIFFED](vnode);
|
||||
vnode[PARENT] = undefined;
|
||||
|
||||
if (options.unmount) options.unmount(vnode);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// Serialize Element VNodes to HTML
|
||||
let s = '<',
|
||||
children,
|
||||
html;
|
||||
|
||||
s = s + type;
|
||||
|
||||
if (props) {
|
||||
children = props.children;
|
||||
for (let name in props) {
|
||||
let v = props[name];
|
||||
|
||||
if (
|
||||
name === 'key' ||
|
||||
name === 'ref' ||
|
||||
name === '__self' ||
|
||||
name === '__source' ||
|
||||
name === 'children' ||
|
||||
(name === 'className' && 'class' in props) ||
|
||||
(name === 'htmlFor' && 'for' in props)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UNSAFE_NAME.test(name)) continue;
|
||||
|
||||
name = normalizePropName(name, isSvgMode);
|
||||
v = normalizePropValue(name, v);
|
||||
|
||||
if (name === 'dangerouslySetInnerHTML') {
|
||||
html = v && v.__html;
|
||||
} else if (type === 'textarea' && name === 'value') {
|
||||
// <textarea value="a&b"> --> <textarea>a&b</textarea>
|
||||
children = v;
|
||||
} else if ((v || v === 0 || v === '') && typeof v !== 'function') {
|
||||
if (v === true || v === '') {
|
||||
v = name;
|
||||
s = s + ' ' + name;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name === 'value') {
|
||||
if (type === 'select') {
|
||||
selectValue = v;
|
||||
continue;
|
||||
} else if (
|
||||
// If we're looking at an <option> and it's the currently selected one
|
||||
type === 'option' &&
|
||||
selectValue == v &&
|
||||
// and the <option> doesn't already have a selected attribute on it
|
||||
!('selected' in props)
|
||||
) {
|
||||
s = s + ' selected';
|
||||
}
|
||||
}
|
||||
s = s + ' ' + name + '="' + encodeEntities(v) + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let startElement = s;
|
||||
s = s + '>';
|
||||
|
||||
if (UNSAFE_NAME.test(type)) {
|
||||
throw new Error(`${type} is not a valid HTML tag name in ${s}`);
|
||||
}
|
||||
|
||||
let pieces = '';
|
||||
let hasChildren = false;
|
||||
|
||||
if (html) {
|
||||
pieces = pieces + html;
|
||||
hasChildren = true;
|
||||
} else if (typeof children === 'string') {
|
||||
pieces = pieces + encodeEntities(children);
|
||||
hasChildren = true;
|
||||
} else if (isArray(children)) {
|
||||
vnode[CHILDREN] = children;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
children[i] = normalizeVNode(child);
|
||||
|
||||
if (child != null && child !== false) {
|
||||
let childSvgMode =
|
||||
type === 'svg' || (type !== 'foreignObject' && isSvgMode);
|
||||
let ret = _renderToString(
|
||||
child,
|
||||
context,
|
||||
childSvgMode,
|
||||
selectValue,
|
||||
vnode
|
||||
);
|
||||
|
||||
// Skip if we received an empty string
|
||||
if (ret) {
|
||||
pieces = pieces + ret;
|
||||
hasChildren = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (children != null && children !== false && children !== true) {
|
||||
vnode[CHILDREN] = [normalizeVNode(children)];
|
||||
let childSvgMode =
|
||||
type === 'svg' || (type !== 'foreignObject' && isSvgMode);
|
||||
let ret = _renderToString(
|
||||
children,
|
||||
context,
|
||||
childSvgMode,
|
||||
selectValue,
|
||||
vnode
|
||||
);
|
||||
|
||||
// Skip if we received an empty string
|
||||
if (ret) {
|
||||
pieces = pieces + ret;
|
||||
hasChildren = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (options[DIFFED]) options[DIFFED](vnode);
|
||||
vnode[PARENT] = undefined;
|
||||
if (options.unmount) options.unmount(vnode);
|
||||
|
||||
if (hasChildren) {
|
||||
s = s + pieces;
|
||||
} else if (VOID_ELEMENTS.test(type)) {
|
||||
return startElement + ' />';
|
||||
}
|
||||
|
||||
return s + '</' + type + '>';
|
||||
}
|
||||
|
||||
/** The default export is an alias of `render()`. */
|
||||
|
||||
renderToString.shallowRender = shallowRender;
|
||||
|
||||
export default renderToString;
|
||||
|
||||
export {
|
||||
renderToString as render,
|
||||
renderToString as renderToStaticMarkup,
|
||||
renderToString,
|
||||
shallowRender
|
||||
};
|
||||
13
node_modules/preact-render-to-string/src/jsx.d.ts
generated
vendored
Normal file
13
node_modules/preact-render-to-string/src/jsx.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { VNode } from 'preact';
|
||||
|
||||
interface Options {
|
||||
jsx?: boolean;
|
||||
xml?: boolean;
|
||||
functions?: boolean;
|
||||
functionNames?: boolean;
|
||||
skipFalseAttributes?: boolean;
|
||||
pretty?: boolean | string;
|
||||
}
|
||||
|
||||
export function render(vnode: VNode, context?: any, options?: Options): string;
|
||||
export default render;
|
||||
76
node_modules/preact-render-to-string/src/jsx.js
generated
vendored
Normal file
76
node_modules/preact-render-to-string/src/jsx.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import './polyfills';
|
||||
import renderToString from './index';
|
||||
import { indent, encodeEntities } from './util';
|
||||
import prettyFormat from 'pretty-format';
|
||||
|
||||
// we have to patch in Array support, Possible issue in npm.im/pretty-format
|
||||
let preactPlugin = {
|
||||
test(object) {
|
||||
return (
|
||||
object &&
|
||||
typeof object === 'object' &&
|
||||
'type' in object &&
|
||||
'props' in object &&
|
||||
'key' in object
|
||||
);
|
||||
},
|
||||
print(val, print, indent) {
|
||||
return renderToString(val, preactPlugin.context, preactPlugin.opts, true);
|
||||
}
|
||||
};
|
||||
|
||||
let prettyFormatOpts = {
|
||||
plugins: [preactPlugin]
|
||||
};
|
||||
|
||||
function attributeHook(name, value, context, opts, isComponent) {
|
||||
let type = typeof value;
|
||||
|
||||
// Use render-to-string's built-in handling for these properties
|
||||
if (name === 'dangerouslySetInnerHTML') return false;
|
||||
|
||||
// always skip null & undefined values, skip false DOM attributes, skip functions if told to
|
||||
if (value == null || (type === 'function' && !opts.functions)) return '';
|
||||
|
||||
if (
|
||||
opts.skipFalseAttributes &&
|
||||
!isComponent &&
|
||||
(value === false ||
|
||||
((name === 'class' || name === 'style') && value === ''))
|
||||
)
|
||||
return '';
|
||||
|
||||
let indentChar = typeof opts.pretty === 'string' ? opts.pretty : '\t';
|
||||
if (type !== 'string') {
|
||||
if (type === 'function' && !opts.functionNames) {
|
||||
value = 'Function';
|
||||
} else {
|
||||
preactPlugin.context = context;
|
||||
preactPlugin.opts = opts;
|
||||
value = prettyFormat(value, prettyFormatOpts);
|
||||
if (~value.indexOf('\n')) {
|
||||
value = `${indent('\n' + value, indentChar)}\n`;
|
||||
}
|
||||
}
|
||||
return indent(`\n${name}={${value}}`, indentChar);
|
||||
}
|
||||
return `\n${indentChar}${name}="${encodeEntities(value)}"`;
|
||||
}
|
||||
|
||||
let defaultOpts = {
|
||||
attributeHook,
|
||||
jsx: true,
|
||||
xml: false,
|
||||
functions: true,
|
||||
functionNames: true,
|
||||
skipFalseAttributes: true,
|
||||
pretty: ' '
|
||||
};
|
||||
|
||||
function renderToJsxString(vnode, context, opts, inner) {
|
||||
opts = Object.assign({}, defaultOpts, opts || {});
|
||||
return renderToString(vnode, context, opts, inner);
|
||||
}
|
||||
|
||||
export default renderToJsxString;
|
||||
export { renderToJsxString as render };
|
||||
8
node_modules/preact-render-to-string/src/polyfills.js
generated
vendored
Normal file
8
node_modules/preact-render-to-string/src/polyfills.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
if (typeof Symbol !== 'function') {
|
||||
let c = 0;
|
||||
// eslint-disable-next-line
|
||||
Symbol = function (s) {
|
||||
return `@@${s}${++c}`;
|
||||
};
|
||||
Symbol.for = (s) => `@@${s}`;
|
||||
}
|
||||
1
node_modules/preact-render-to-string/src/preact-render-to-string-tests.d.ts
generated
vendored
Normal file
1
node_modules/preact-render-to-string/src/preact-render-to-string-tests.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
389
node_modules/preact-render-to-string/src/pretty.js
generated
vendored
Normal file
389
node_modules/preact-render-to-string/src/pretty.js
generated
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
import {
|
||||
encodeEntities,
|
||||
indent,
|
||||
isLargeString,
|
||||
styleObjToCss,
|
||||
getChildren,
|
||||
createComponent,
|
||||
getContext,
|
||||
UNSAFE_NAME,
|
||||
XLINK,
|
||||
VOID_ELEMENTS
|
||||
} from './util';
|
||||
import { options, Fragment } from 'preact';
|
||||
|
||||
// components without names, kept as a hash for later comparison to return consistent UnnamedComponentXX names.
|
||||
const UNNAMED = [];
|
||||
|
||||
export function _renderToStringPretty(
|
||||
vnode,
|
||||
context,
|
||||
opts,
|
||||
inner,
|
||||
isSvgMode,
|
||||
selectValue
|
||||
) {
|
||||
if (vnode == null || typeof vnode === 'boolean') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// #text nodes
|
||||
if (typeof vnode !== 'object') {
|
||||
if (typeof vnode === 'function') return '';
|
||||
return encodeEntities(vnode);
|
||||
}
|
||||
|
||||
let pretty = opts.pretty,
|
||||
indentChar = pretty && typeof pretty === 'string' ? pretty : '\t';
|
||||
|
||||
if (Array.isArray(vnode)) {
|
||||
let rendered = '';
|
||||
for (let i = 0; i < vnode.length; i++) {
|
||||
if (pretty && i > 0) rendered = rendered + '\n';
|
||||
rendered =
|
||||
rendered +
|
||||
_renderToStringPretty(
|
||||
vnode[i],
|
||||
context,
|
||||
opts,
|
||||
inner,
|
||||
isSvgMode,
|
||||
selectValue
|
||||
);
|
||||
}
|
||||
return rendered;
|
||||
}
|
||||
|
||||
// VNodes have {constructor:undefined} to prevent JSON injection:
|
||||
if (vnode.constructor !== undefined) return '';
|
||||
|
||||
let nodeName = vnode.type,
|
||||
props = vnode.props,
|
||||
isComponent = false;
|
||||
|
||||
// components
|
||||
if (typeof nodeName === 'function') {
|
||||
isComponent = true;
|
||||
if (opts.shallow && (inner || opts.renderRootComponent === false)) {
|
||||
nodeName = getComponentName(nodeName);
|
||||
} else if (nodeName === Fragment) {
|
||||
const children = [];
|
||||
getChildren(children, vnode.props.children);
|
||||
return _renderToStringPretty(
|
||||
children,
|
||||
context,
|
||||
opts,
|
||||
opts.shallowHighOrder !== false,
|
||||
isSvgMode,
|
||||
selectValue
|
||||
);
|
||||
} else {
|
||||
let rendered;
|
||||
|
||||
let c = (vnode.__c = createComponent(vnode, context));
|
||||
|
||||
// options._diff
|
||||
if (options.__b) options.__b(vnode);
|
||||
|
||||
// options._render
|
||||
let renderHook = options.__r;
|
||||
|
||||
if (
|
||||
!nodeName.prototype ||
|
||||
typeof nodeName.prototype.render !== 'function'
|
||||
) {
|
||||
let cctx = getContext(nodeName, context);
|
||||
|
||||
// If a hook invokes setState() to invalidate the component during rendering,
|
||||
// re-render it up to 25 times to allow "settling" of memoized states.
|
||||
// Note:
|
||||
// This will need to be updated for Preact 11 to use internal.flags rather than component._dirty:
|
||||
// https://github.com/preactjs/preact/blob/d4ca6fdb19bc715e49fd144e69f7296b2f4daa40/src/diff/component.js#L35-L44
|
||||
let count = 0;
|
||||
while (c.__d && count++ < 25) {
|
||||
c.__d = false;
|
||||
|
||||
if (renderHook) renderHook(vnode);
|
||||
|
||||
// stateless functional components
|
||||
rendered = nodeName.call(vnode.__c, props, cctx);
|
||||
}
|
||||
} else {
|
||||
let cctx = getContext(nodeName, context);
|
||||
|
||||
// c = new nodeName(props, context);
|
||||
c = vnode.__c = new nodeName(props, cctx);
|
||||
c.__v = vnode;
|
||||
// turn off stateful re-rendering:
|
||||
c._dirty = c.__d = true;
|
||||
c.props = props;
|
||||
if (c.state == null) c.state = {};
|
||||
|
||||
if (c._nextState == null && c.__s == null) {
|
||||
c._nextState = c.__s = c.state;
|
||||
}
|
||||
|
||||
c.context = cctx;
|
||||
if (nodeName.getDerivedStateFromProps)
|
||||
c.state = Object.assign(
|
||||
{},
|
||||
c.state,
|
||||
nodeName.getDerivedStateFromProps(c.props, c.state)
|
||||
);
|
||||
else if (c.componentWillMount) {
|
||||
c.componentWillMount();
|
||||
|
||||
// If the user called setState in cWM we need to flush pending,
|
||||
// state updates. This is the same behaviour in React.
|
||||
c.state =
|
||||
c._nextState !== c.state
|
||||
? c._nextState
|
||||
: c.__s !== c.state
|
||||
? c.__s
|
||||
: c.state;
|
||||
}
|
||||
|
||||
if (renderHook) renderHook(vnode);
|
||||
|
||||
rendered = c.render(c.props, c.state, c.context);
|
||||
}
|
||||
|
||||
if (c.getChildContext) {
|
||||
context = Object.assign({}, context, c.getChildContext());
|
||||
}
|
||||
|
||||
if (options.diffed) options.diffed(vnode);
|
||||
return _renderToStringPretty(
|
||||
rendered,
|
||||
context,
|
||||
opts,
|
||||
opts.shallowHighOrder !== false,
|
||||
isSvgMode,
|
||||
selectValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// render JSX to HTML
|
||||
let s = '<' + nodeName,
|
||||
propChildren,
|
||||
html;
|
||||
|
||||
if (props) {
|
||||
let attrs = Object.keys(props);
|
||||
|
||||
// allow sorting lexicographically for more determinism (useful for tests, such as via preact-jsx-chai)
|
||||
if (opts && opts.sortAttributes === true) attrs.sort();
|
||||
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
let name = attrs[i],
|
||||
v = props[name];
|
||||
if (name === 'children') {
|
||||
propChildren = v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UNSAFE_NAME.test(name)) continue;
|
||||
|
||||
if (
|
||||
!(opts && opts.allAttributes) &&
|
||||
(name === 'key' ||
|
||||
name === 'ref' ||
|
||||
name === '__self' ||
|
||||
name === '__source')
|
||||
)
|
||||
continue;
|
||||
|
||||
if (name === 'defaultValue') {
|
||||
name = 'value';
|
||||
} else if (name === 'defaultChecked') {
|
||||
name = 'checked';
|
||||
} else if (name === 'defaultSelected') {
|
||||
name = 'selected';
|
||||
} else if (name === 'className') {
|
||||
if (typeof props.class !== 'undefined') continue;
|
||||
name = 'class';
|
||||
} else if (isSvgMode && XLINK.test(name)) {
|
||||
name = name.toLowerCase().replace(/^xlink:?/, 'xlink:');
|
||||
}
|
||||
|
||||
if (name === 'htmlFor') {
|
||||
if (props.for) continue;
|
||||
name = 'for';
|
||||
}
|
||||
|
||||
if (name === 'style' && v && typeof v === 'object') {
|
||||
v = styleObjToCss(v);
|
||||
}
|
||||
|
||||
// always use string values instead of booleans for aria attributes
|
||||
// also see https://github.com/preactjs/preact/pull/2347/files
|
||||
if (name[0] === 'a' && name['1'] === 'r' && typeof v === 'boolean') {
|
||||
v = String(v);
|
||||
}
|
||||
|
||||
let hooked =
|
||||
opts.attributeHook &&
|
||||
opts.attributeHook(name, v, context, opts, isComponent);
|
||||
if (hooked || hooked === '') {
|
||||
s = s + hooked;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name === 'dangerouslySetInnerHTML') {
|
||||
html = v && v.__html;
|
||||
} else if (nodeName === 'textarea' && name === 'value') {
|
||||
// <textarea value="a&b"> --> <textarea>a&b</textarea>
|
||||
propChildren = v;
|
||||
} else if ((v || v === 0 || v === '') && typeof v !== 'function') {
|
||||
if (v === true || v === '') {
|
||||
v = name;
|
||||
// in non-xml mode, allow boolean attributes
|
||||
if (!opts || !opts.xml) {
|
||||
s = s + ' ' + name;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (name === 'value') {
|
||||
if (nodeName === 'select') {
|
||||
selectValue = v;
|
||||
continue;
|
||||
} else if (
|
||||
// If we're looking at an <option> and it's the currently selected one
|
||||
nodeName === 'option' &&
|
||||
selectValue == v &&
|
||||
// and the <option> doesn't already have a selected attribute on it
|
||||
typeof props.selected === 'undefined'
|
||||
) {
|
||||
s = s + ` selected`;
|
||||
}
|
||||
}
|
||||
s = s + ` ${name}="${encodeEntities(v)}"`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// account for >1 multiline attribute
|
||||
if (pretty) {
|
||||
let sub = s.replace(/\n\s*/, ' ');
|
||||
if (sub !== s && !~sub.indexOf('\n')) s = sub;
|
||||
else if (pretty && ~s.indexOf('\n')) s = s + '\n';
|
||||
}
|
||||
|
||||
s = s + '>';
|
||||
|
||||
if (UNSAFE_NAME.test(nodeName))
|
||||
throw new Error(`${nodeName} is not a valid HTML tag name in ${s}`);
|
||||
|
||||
let isVoid =
|
||||
VOID_ELEMENTS.test(nodeName) ||
|
||||
(opts.voidElements && opts.voidElements.test(nodeName));
|
||||
let pieces = [];
|
||||
|
||||
let children;
|
||||
if (html) {
|
||||
// if multiline, indent.
|
||||
if (pretty && isLargeString(html)) {
|
||||
html = '\n' + indentChar + indent(html, indentChar);
|
||||
}
|
||||
s = s + html;
|
||||
} else if (
|
||||
propChildren != null &&
|
||||
getChildren((children = []), propChildren).length
|
||||
) {
|
||||
let hasLarge = pretty && ~s.indexOf('\n');
|
||||
let lastWasText = false;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
|
||||
if (child != null && child !== false) {
|
||||
let childSvgMode =
|
||||
nodeName === 'svg'
|
||||
? true
|
||||
: nodeName === 'foreignObject'
|
||||
? false
|
||||
: isSvgMode,
|
||||
ret = _renderToStringPretty(
|
||||
child,
|
||||
context,
|
||||
opts,
|
||||
true,
|
||||
childSvgMode,
|
||||
selectValue
|
||||
);
|
||||
|
||||
if (pretty && !hasLarge && isLargeString(ret)) hasLarge = true;
|
||||
|
||||
// Skip if we received an empty string
|
||||
if (ret) {
|
||||
if (pretty) {
|
||||
let isText = ret.length > 0 && ret[0] != '<';
|
||||
|
||||
// We merge adjacent text nodes, otherwise each piece would be printed
|
||||
// on a new line.
|
||||
if (lastWasText && isText) {
|
||||
pieces[pieces.length - 1] += ret;
|
||||
} else {
|
||||
pieces.push(ret);
|
||||
}
|
||||
|
||||
lastWasText = isText;
|
||||
} else {
|
||||
pieces.push(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pretty && hasLarge) {
|
||||
for (let i = pieces.length; i--; ) {
|
||||
pieces[i] = '\n' + indentChar + indent(pieces[i], indentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pieces.length || html) {
|
||||
s = s + pieces.join('');
|
||||
} else if (opts && opts.xml) {
|
||||
return s.substring(0, s.length - 1) + ' />';
|
||||
}
|
||||
|
||||
if (isVoid && !children && !html) {
|
||||
s = s.replace(/>$/, ' />');
|
||||
} else {
|
||||
if (pretty && ~s.indexOf('\n')) s = s + '\n';
|
||||
s = s + `</${nodeName}>`;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function getComponentName(component) {
|
||||
return (
|
||||
component.displayName ||
|
||||
(component !== Function && component.name) ||
|
||||
getFallbackComponentName(component)
|
||||
);
|
||||
}
|
||||
|
||||
function getFallbackComponentName(component) {
|
||||
let str = Function.prototype.toString.call(component),
|
||||
name = (str.match(/^\s*function\s+([^( ]+)/) || '')[1];
|
||||
if (!name) {
|
||||
// search for an existing indexed name for the given component:
|
||||
let index = -1;
|
||||
for (let i = UNNAMED.length; i--; ) {
|
||||
if (UNNAMED[i] === component) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// not found, create a new indexed name:
|
||||
if (index < 0) {
|
||||
index = UNNAMED.push(component) - 1;
|
||||
}
|
||||
name = `UnnamedComponent${index}`;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
125
node_modules/preact-render-to-string/src/util.js
generated
vendored
Normal file
125
node_modules/preact-render-to-string/src/util.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// DOM properties that should NOT have "px" added when numeric
|
||||
export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|^--/i;
|
||||
export const VOID_ELEMENTS = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/;
|
||||
export const UNSAFE_NAME = /[\s\n\\/='"\0<>]/;
|
||||
export const XLINK = /^xlink:?./;
|
||||
|
||||
const ENCODED_ENTITIES = /["&<]/;
|
||||
|
||||
export function encodeEntities(str) {
|
||||
// Ensure we're always parsing and returning a string:
|
||||
str += '';
|
||||
|
||||
// Skip all work for strings with no entities needing encoding:
|
||||
if (ENCODED_ENTITIES.test(str) === false) return str;
|
||||
|
||||
let last = 0,
|
||||
i = 0,
|
||||
out = '',
|
||||
ch = '';
|
||||
|
||||
// Seek forward in str until the next entity char:
|
||||
for (; i < str.length; i++) {
|
||||
switch (str.charCodeAt(i)) {
|
||||
case 34:
|
||||
ch = '"';
|
||||
break;
|
||||
case 38:
|
||||
ch = '&';
|
||||
break;
|
||||
case 60:
|
||||
ch = '<';
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
// Append skipped/buffered characters and the encoded entity:
|
||||
if (i !== last) out += str.slice(last, i);
|
||||
out += ch;
|
||||
// Start the next seek/buffer after the entity's offset:
|
||||
last = i + 1;
|
||||
}
|
||||
if (i !== last) out += str.slice(last, i);
|
||||
return out;
|
||||
}
|
||||
|
||||
export let indent = (s, char) =>
|
||||
String(s).replace(/(\n+)/g, '$1' + (char || '\t'));
|
||||
|
||||
export let isLargeString = (s, length, ignoreLines) =>
|
||||
String(s).length > (length || 40) ||
|
||||
(!ignoreLines && String(s).indexOf('\n') !== -1) ||
|
||||
String(s).indexOf('<') !== -1;
|
||||
|
||||
const JS_TO_CSS = {};
|
||||
|
||||
const CSS_REGEX = /([A-Z])/g;
|
||||
// Convert an Object style to a CSSText string
|
||||
export function styleObjToCss(s) {
|
||||
let str = '';
|
||||
for (let prop in s) {
|
||||
let val = s[prop];
|
||||
if (val != null && val !== '') {
|
||||
if (str) str += ' ';
|
||||
// str += jsToCss(prop);
|
||||
str +=
|
||||
prop[0] == '-'
|
||||
? prop
|
||||
: JS_TO_CSS[prop] ||
|
||||
(JS_TO_CSS[prop] = prop.replace(CSS_REGEX, '-$1').toLowerCase());
|
||||
|
||||
if (typeof val === 'number' && IS_NON_DIMENSIONAL.test(prop) === false) {
|
||||
str = str + ': ' + val + 'px;';
|
||||
} else {
|
||||
str = str + ': ' + val + ';';
|
||||
}
|
||||
}
|
||||
}
|
||||
return str || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flattened children from the children prop
|
||||
* @param {Array} accumulator
|
||||
* @param {any} children A `props.children` opaque object.
|
||||
* @returns {Array} accumulator
|
||||
* @private
|
||||
*/
|
||||
export function getChildren(accumulator, children) {
|
||||
if (Array.isArray(children)) {
|
||||
children.reduce(getChildren, accumulator);
|
||||
} else if (children != null && children !== false) {
|
||||
accumulator.push(children);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
function markAsDirty() {
|
||||
this.__d = true;
|
||||
}
|
||||
|
||||
export function createComponent(vnode, context) {
|
||||
return {
|
||||
__v: vnode,
|
||||
context,
|
||||
props: vnode.props,
|
||||
// silently drop state updates
|
||||
setState: markAsDirty,
|
||||
forceUpdate: markAsDirty,
|
||||
__d: true,
|
||||
// hooks
|
||||
__h: []
|
||||
};
|
||||
}
|
||||
|
||||
// Necessary for createContext api. Setting this property will pass
|
||||
// the context value as `this.context` just for this component.
|
||||
export function getContext(nodeName, context) {
|
||||
let cxType = nodeName.contextType;
|
||||
let provider = cxType && context[cxType.__c];
|
||||
return cxType != null
|
||||
? provider
|
||||
? provider.props.value
|
||||
: cxType.__
|
||||
: context;
|
||||
}
|
||||
Reference in New Issue
Block a user