preact-render-to-string 5.1.7 → 5.1.11
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/index.d.ts +10 -6
- package/dist/index.js +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/jsx.d.ts +7 -7
- package/dist/jsx.js +1 -1
- package/dist/jsx.js.map +1 -1
- package/dist/jsx.mjs +1 -1
- package/dist/jsx.module.js +1 -1
- package/dist/jsx.module.js.map +1 -1
- package/package.json +126 -102
- package/src/index.d.ts +10 -6
- package/src/index.js +167 -79
- package/src/jsx.d.ts +7 -7
- package/src/jsx.js +22 -16
- package/src/polyfills.js +4 -3
- package/src/util.js +30 -12
package/src/index.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
encodeEntities,
|
|
3
|
+
indent,
|
|
4
|
+
isLargeString,
|
|
5
|
+
styleObjToCss,
|
|
6
|
+
assign,
|
|
7
|
+
getChildren
|
|
8
|
+
} from './util';
|
|
2
9
|
import { options, Fragment, createElement } from 'preact';
|
|
3
10
|
|
|
4
11
|
const SHALLOW = { shallow: true };
|
|
@@ -10,7 +17,6 @@ const VOID_ELEMENTS = /^(area|base|br|col|embed|hr|img|input|link|meta|param|sou
|
|
|
10
17
|
|
|
11
18
|
const noop = () => {};
|
|
12
19
|
|
|
13
|
-
|
|
14
20
|
/** Render Preact JSX + Components to an HTML string.
|
|
15
21
|
* @name render
|
|
16
22
|
* @function
|
|
@@ -20,10 +26,10 @@ const noop = () => {};
|
|
|
20
26
|
* @param {Boolean} [options.shallow=false] If `true`, renders nested Components as HTML elements (`<Foo a="b" />`).
|
|
21
27
|
* @param {Boolean} [options.xml=false] If `true`, uses self-closing tags for elements without children.
|
|
22
28
|
* @param {Boolean} [options.pretty=false] If `true`, adds whitespace for readability
|
|
29
|
+
* @param {RegEx|undefined} [options.voidElements] RegeEx that matches elements that are considered void (self-closing)
|
|
23
30
|
*/
|
|
24
31
|
renderToString.render = renderToString;
|
|
25
32
|
|
|
26
|
-
|
|
27
33
|
/** Only render elements, leaving Components inline as `<ComponentName ... />`.
|
|
28
34
|
* This method is just a convenience alias for `render(vnode, context, { shallow:true })`
|
|
29
35
|
* @name shallow
|
|
@@ -33,10 +39,9 @@ renderToString.render = renderToString;
|
|
|
33
39
|
*/
|
|
34
40
|
let shallowRender = (vnode, context) => renderToString(vnode, context, SHALLOW);
|
|
35
41
|
|
|
36
|
-
|
|
37
42
|
/** The default export is an alias of `render()`. */
|
|
38
43
|
function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
39
|
-
if (vnode==null || typeof vnode==='boolean') {
|
|
44
|
+
if (vnode == null || typeof vnode === 'boolean') {
|
|
40
45
|
return '';
|
|
41
46
|
}
|
|
42
47
|
|
|
@@ -52,33 +57,40 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
52
57
|
opts = opts || {};
|
|
53
58
|
|
|
54
59
|
let pretty = opts.pretty,
|
|
55
|
-
indentChar = pretty && typeof pretty==='string' ? pretty : '\t';
|
|
60
|
+
indentChar = pretty && typeof pretty === 'string' ? pretty : '\t';
|
|
56
61
|
|
|
57
62
|
// #text nodes
|
|
58
|
-
if (typeof vnode!=='object' && !nodeName) {
|
|
63
|
+
if (typeof vnode !== 'object' && !nodeName) {
|
|
59
64
|
return encodeEntities(vnode);
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
// components
|
|
63
|
-
if (typeof nodeName==='function') {
|
|
68
|
+
if (typeof nodeName === 'function') {
|
|
64
69
|
isComponent = true;
|
|
65
|
-
if (opts.shallow && (inner || opts.renderRootComponent===false)) {
|
|
70
|
+
if (opts.shallow && (inner || opts.renderRootComponent === false)) {
|
|
66
71
|
nodeName = getComponentName(nodeName);
|
|
67
|
-
}
|
|
68
|
-
else if (nodeName===Fragment) {
|
|
72
|
+
} else if (nodeName === Fragment) {
|
|
69
73
|
let rendered = '';
|
|
70
74
|
let children = [];
|
|
71
75
|
getChildren(children, vnode.props.children);
|
|
72
76
|
|
|
73
77
|
for (let i = 0; i < children.length; i++) {
|
|
74
|
-
rendered +=
|
|
78
|
+
rendered +=
|
|
79
|
+
(i > 0 && pretty ? '\n' : '') +
|
|
80
|
+
renderToString(
|
|
81
|
+
children[i],
|
|
82
|
+
context,
|
|
83
|
+
opts,
|
|
84
|
+
opts.shallowHighOrder !== false,
|
|
85
|
+
isSvgMode,
|
|
86
|
+
selectValue
|
|
87
|
+
);
|
|
75
88
|
}
|
|
76
89
|
return rendered;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
90
|
+
} else {
|
|
79
91
|
let rendered;
|
|
80
92
|
|
|
81
|
-
let c = vnode.__c = {
|
|
93
|
+
let c = (vnode.__c = {
|
|
82
94
|
__v: vnode,
|
|
83
95
|
context,
|
|
84
96
|
props: vnode.props,
|
|
@@ -87,26 +99,41 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
87
99
|
forceUpdate: noop,
|
|
88
100
|
// hooks
|
|
89
101
|
__h: []
|
|
90
|
-
};
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// options._diff
|
|
105
|
+
if (options.__b) options.__b(vnode);
|
|
91
106
|
|
|
92
|
-
// options.
|
|
107
|
+
// options._render
|
|
93
108
|
if (options.__r) options.__r(vnode);
|
|
94
109
|
|
|
95
|
-
if (
|
|
110
|
+
if (
|
|
111
|
+
!nodeName.prototype ||
|
|
112
|
+
typeof nodeName.prototype.render !== 'function'
|
|
113
|
+
) {
|
|
96
114
|
// Necessary for createContext api. Setting this property will pass
|
|
97
115
|
// the context value as `this.context` just for this component.
|
|
98
116
|
let cxType = nodeName.contextType;
|
|
99
117
|
let provider = cxType && context[cxType.__c];
|
|
100
|
-
let cctx =
|
|
118
|
+
let cctx =
|
|
119
|
+
cxType != null
|
|
120
|
+
? provider
|
|
121
|
+
? provider.props.value
|
|
122
|
+
: cxType.__
|
|
123
|
+
: context;
|
|
101
124
|
|
|
102
125
|
// stateless functional components
|
|
103
126
|
rendered = nodeName.call(vnode.__c, props, cctx);
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
127
|
+
} else {
|
|
106
128
|
// class-based components
|
|
107
129
|
let cxType = nodeName.contextType;
|
|
108
130
|
let provider = cxType && context[cxType.__c];
|
|
109
|
-
let cctx =
|
|
131
|
+
let cctx =
|
|
132
|
+
cxType != null
|
|
133
|
+
? provider
|
|
134
|
+
? provider.props.value
|
|
135
|
+
: cxType.__
|
|
136
|
+
: context;
|
|
110
137
|
|
|
111
138
|
// c = new nodeName(props, context);
|
|
112
139
|
c = vnode.__c = new nodeName(props, cctx);
|
|
@@ -114,21 +141,30 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
114
141
|
// turn off stateful re-rendering:
|
|
115
142
|
c._dirty = c.__d = true;
|
|
116
143
|
c.props = props;
|
|
117
|
-
if (c.state==null) c.state = {};
|
|
144
|
+
if (c.state == null) c.state = {};
|
|
118
145
|
|
|
119
|
-
if (c._nextState==null && c.__s==null) {
|
|
146
|
+
if (c._nextState == null && c.__s == null) {
|
|
120
147
|
c._nextState = c.__s = c.state;
|
|
121
148
|
}
|
|
122
149
|
|
|
123
150
|
c.context = cctx;
|
|
124
|
-
if (nodeName.getDerivedStateFromProps)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
151
|
+
if (nodeName.getDerivedStateFromProps)
|
|
152
|
+
c.state = assign(
|
|
153
|
+
assign({}, c.state),
|
|
154
|
+
nodeName.getDerivedStateFromProps(c.props, c.state)
|
|
155
|
+
);
|
|
156
|
+
else if (c.componentWillMount) {
|
|
157
|
+
c.componentWillMount();
|
|
158
|
+
|
|
159
|
+
// If the user called setState in cWM we need to flush pending,
|
|
160
|
+
// state updates. This is the same behaviour in React.
|
|
161
|
+
c.state =
|
|
162
|
+
c._nextState !== c.state
|
|
163
|
+
? c._nextState
|
|
164
|
+
: c.__s !== c.state
|
|
165
|
+
? c.__s
|
|
166
|
+
: c.state;
|
|
167
|
+
}
|
|
132
168
|
|
|
133
169
|
rendered = c.render(c.props, c.state, c.context);
|
|
134
170
|
}
|
|
@@ -137,51 +173,85 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
137
173
|
context = assign(assign({}, context), c.getChildContext());
|
|
138
174
|
}
|
|
139
175
|
|
|
140
|
-
return renderToString(
|
|
176
|
+
return renderToString(
|
|
177
|
+
rendered,
|
|
178
|
+
context,
|
|
179
|
+
opts,
|
|
180
|
+
opts.shallowHighOrder !== false,
|
|
181
|
+
isSvgMode,
|
|
182
|
+
selectValue
|
|
183
|
+
);
|
|
141
184
|
}
|
|
142
185
|
}
|
|
143
186
|
|
|
144
187
|
// render JSX to HTML
|
|
145
|
-
let s = '',
|
|
188
|
+
let s = '',
|
|
189
|
+
propChildren,
|
|
190
|
+
html;
|
|
146
191
|
|
|
147
192
|
if (props) {
|
|
148
193
|
let attrs = Object.keys(props);
|
|
149
194
|
|
|
150
195
|
// allow sorting lexicographically for more determinism (useful for tests, such as via preact-jsx-chai)
|
|
151
|
-
if (opts && opts.sortAttributes===true) attrs.sort();
|
|
196
|
+
if (opts && opts.sortAttributes === true) attrs.sort();
|
|
152
197
|
|
|
153
|
-
for (let i=0; i<attrs.length; i++) {
|
|
198
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
154
199
|
let name = attrs[i],
|
|
155
200
|
v = props[name];
|
|
156
|
-
if (name==='children')
|
|
201
|
+
if (name === 'children') {
|
|
202
|
+
propChildren = v;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
157
205
|
|
|
158
206
|
if (name.match(/[\s\n\\/='"\0<>]/)) continue;
|
|
159
207
|
|
|
160
|
-
if (
|
|
208
|
+
if (
|
|
209
|
+
!(opts && opts.allAttributes) &&
|
|
210
|
+
(name === 'key' ||
|
|
211
|
+
name === 'ref' ||
|
|
212
|
+
name === '__self' ||
|
|
213
|
+
name === '__source' ||
|
|
214
|
+
name === 'defaultValue')
|
|
215
|
+
)
|
|
216
|
+
continue;
|
|
161
217
|
|
|
162
|
-
if (name==='className') {
|
|
218
|
+
if (name === 'className') {
|
|
163
219
|
if (props.class) continue;
|
|
164
220
|
name = 'class';
|
|
165
|
-
}
|
|
166
|
-
else if (isSvgMode && name.match(/^xlink:?./)) {
|
|
221
|
+
} else if (isSvgMode && name.match(/^xlink:?./)) {
|
|
167
222
|
name = name.toLowerCase().replace(/^xlink:?/, 'xlink:');
|
|
168
223
|
}
|
|
169
224
|
|
|
170
|
-
if (name===
|
|
225
|
+
if (name === 'htmlFor') {
|
|
226
|
+
if (props.for) continue;
|
|
227
|
+
name = 'for';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (name === 'style' && v && typeof v === 'object') {
|
|
171
231
|
v = styleObjToCss(v);
|
|
172
232
|
}
|
|
173
233
|
|
|
174
|
-
|
|
175
|
-
|
|
234
|
+
// always use string values instead of booleans for aria attributes
|
|
235
|
+
// also see https://github.com/preactjs/preact/pull/2347/files
|
|
236
|
+
if (name[0] === 'a' && name['1'] === 'r' && typeof v === 'boolean') {
|
|
237
|
+
v = String(v);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let hooked =
|
|
241
|
+
opts.attributeHook &&
|
|
242
|
+
opts.attributeHook(name, v, context, opts, isComponent);
|
|
243
|
+
if (hooked || hooked === '') {
|
|
176
244
|
s += hooked;
|
|
177
245
|
continue;
|
|
178
246
|
}
|
|
179
247
|
|
|
180
|
-
if (name==='dangerouslySetInnerHTML') {
|
|
248
|
+
if (name === 'dangerouslySetInnerHTML') {
|
|
181
249
|
html = v && v.__html;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
250
|
+
} else if (nodeName === 'textarea' && name === 'value') {
|
|
251
|
+
// <textarea value="a&b"> --> <textarea>a&b</textarea>
|
|
252
|
+
propChildren = v;
|
|
253
|
+
} else if ((v || v === 0 || v === '') && typeof v !== 'function') {
|
|
254
|
+
if (v === true || v === '') {
|
|
185
255
|
v = name;
|
|
186
256
|
// in non-xml mode, allow boolean attributes
|
|
187
257
|
if (!opts || !opts.xml) {
|
|
@@ -190,12 +260,11 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
190
260
|
}
|
|
191
261
|
}
|
|
192
262
|
|
|
193
|
-
if (name==='value') {
|
|
194
|
-
if (nodeName==='select') {
|
|
263
|
+
if (name === 'value') {
|
|
264
|
+
if (nodeName === 'select') {
|
|
195
265
|
selectValue = v;
|
|
196
266
|
continue;
|
|
197
|
-
}
|
|
198
|
-
else if (nodeName==='option' && selectValue==v) {
|
|
267
|
+
} else if (nodeName === 'option' && selectValue == v) {
|
|
199
268
|
s += ` selected`;
|
|
200
269
|
}
|
|
201
270
|
}
|
|
@@ -207,16 +276,17 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
207
276
|
// account for >1 multiline attribute
|
|
208
277
|
if (pretty) {
|
|
209
278
|
let sub = s.replace(/^\n\s*/, ' ');
|
|
210
|
-
if (sub!==s && !~sub.indexOf('\n')) s = sub;
|
|
279
|
+
if (sub !== s && !~sub.indexOf('\n')) s = sub;
|
|
211
280
|
else if (pretty && ~s.indexOf('\n')) s += '\n';
|
|
212
281
|
}
|
|
213
282
|
|
|
214
283
|
s = `<${nodeName}${s}>`;
|
|
215
|
-
if (String(nodeName).match(/[\s\n\\/='"\0<>]/))
|
|
216
|
-
|
|
217
|
-
let isVoid = String(nodeName).match(VOID_ELEMENTS);
|
|
218
|
-
if (isVoid) s = s.replace(/>$/, ' />');
|
|
284
|
+
if (String(nodeName).match(/[\s\n\\/='"\0<>]/))
|
|
285
|
+
throw new Error(`${nodeName} is not a valid HTML tag name in ${s}`);
|
|
219
286
|
|
|
287
|
+
let isVoid =
|
|
288
|
+
String(nodeName).match(VOID_ELEMENTS) ||
|
|
289
|
+
(opts.voidElements && String(nodeName).match(opts.voidElements));
|
|
220
290
|
let pieces = [];
|
|
221
291
|
|
|
222
292
|
let children;
|
|
@@ -226,44 +296,56 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
226
296
|
html = '\n' + indentChar + indent(html, indentChar);
|
|
227
297
|
}
|
|
228
298
|
s += html;
|
|
229
|
-
}
|
|
230
|
-
|
|
299
|
+
} else if (
|
|
300
|
+
propChildren != null &&
|
|
301
|
+
getChildren((children = []), propChildren).length
|
|
302
|
+
) {
|
|
231
303
|
let hasLarge = pretty && ~s.indexOf('\n');
|
|
232
304
|
let lastWasText = false;
|
|
233
305
|
|
|
234
|
-
for (let i=0; i<children.length; i++) {
|
|
306
|
+
for (let i = 0; i < children.length; i++) {
|
|
235
307
|
let child = children[i];
|
|
236
308
|
|
|
237
|
-
if (child!=null && child!==false) {
|
|
238
|
-
let childSvgMode =
|
|
239
|
-
|
|
309
|
+
if (child != null && child !== false) {
|
|
310
|
+
let childSvgMode =
|
|
311
|
+
nodeName === 'svg'
|
|
312
|
+
? true
|
|
313
|
+
: nodeName === 'foreignObject'
|
|
314
|
+
? false
|
|
315
|
+
: isSvgMode,
|
|
316
|
+
ret = renderToString(
|
|
317
|
+
child,
|
|
318
|
+
context,
|
|
319
|
+
opts,
|
|
320
|
+
true,
|
|
321
|
+
childSvgMode,
|
|
322
|
+
selectValue
|
|
323
|
+
);
|
|
240
324
|
|
|
241
325
|
if (pretty && !hasLarge && isLargeString(ret)) hasLarge = true;
|
|
242
326
|
|
|
243
327
|
// Skip if we received an empty string
|
|
244
328
|
if (ret) {
|
|
245
329
|
if (pretty) {
|
|
246
|
-
let isText = ret.length > 0 && ret[0]!='<';
|
|
247
|
-
|
|
330
|
+
let isText = ret.length > 0 && ret[0] != '<';
|
|
331
|
+
|
|
248
332
|
// We merge adjacent text nodes, otherwise each piece would be printed
|
|
249
333
|
// on a new line.
|
|
250
334
|
if (lastWasText && isText) {
|
|
251
|
-
pieces[pieces.length -1] += ret;
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
335
|
+
pieces[pieces.length - 1] += ret;
|
|
336
|
+
} else {
|
|
254
337
|
pieces.push(ret);
|
|
255
338
|
}
|
|
256
339
|
|
|
257
340
|
lastWasText = isText;
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
341
|
+
} else {
|
|
260
342
|
pieces.push(ret);
|
|
261
343
|
}
|
|
262
344
|
}
|
|
263
345
|
}
|
|
264
346
|
}
|
|
265
347
|
if (pretty && hasLarge) {
|
|
266
|
-
for (let i=pieces.length; i--; ) {
|
|
348
|
+
for (let i = pieces.length; i--; ) {
|
|
267
349
|
pieces[i] = '\n' + indentChar + indent(pieces[i], indentChar);
|
|
268
350
|
}
|
|
269
351
|
}
|
|
@@ -271,12 +353,13 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
271
353
|
|
|
272
354
|
if (pieces.length) {
|
|
273
355
|
s += pieces.join('');
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return s.substring(0, s.length-1) + ' />';
|
|
356
|
+
} else if (opts && opts.xml) {
|
|
357
|
+
return s.substring(0, s.length - 1) + ' />';
|
|
277
358
|
}
|
|
278
359
|
|
|
279
|
-
if (!
|
|
360
|
+
if (isVoid && !children) {
|
|
361
|
+
s = s.replace(/>$/, ' />');
|
|
362
|
+
} else {
|
|
280
363
|
if (pretty && ~s.indexOf('\n')) s += '\n';
|
|
281
364
|
s += `</${nodeName}>`;
|
|
282
365
|
}
|
|
@@ -285,7 +368,11 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
|
|
|
285
368
|
}
|
|
286
369
|
|
|
287
370
|
function getComponentName(component) {
|
|
288
|
-
return
|
|
371
|
+
return (
|
|
372
|
+
component.displayName ||
|
|
373
|
+
(component !== Function && component.name) ||
|
|
374
|
+
getFallbackComponentName(component)
|
|
375
|
+
);
|
|
289
376
|
}
|
|
290
377
|
|
|
291
378
|
function getFallbackComponentName(component) {
|
|
@@ -294,14 +381,14 @@ function getFallbackComponentName(component) {
|
|
|
294
381
|
if (!name) {
|
|
295
382
|
// search for an existing indexed name for the given component:
|
|
296
383
|
let index = -1;
|
|
297
|
-
for (let i=UNNAMED.length; i--; ) {
|
|
298
|
-
if (UNNAMED[i]===component) {
|
|
384
|
+
for (let i = UNNAMED.length; i--; ) {
|
|
385
|
+
if (UNNAMED[i] === component) {
|
|
299
386
|
index = i;
|
|
300
387
|
break;
|
|
301
388
|
}
|
|
302
389
|
}
|
|
303
390
|
// not found, create a new indexed name:
|
|
304
|
-
if (index<0) {
|
|
391
|
+
if (index < 0) {
|
|
305
392
|
index = UNNAMED.push(component) - 1;
|
|
306
393
|
}
|
|
307
394
|
name = `UnnamedComponent${index}`;
|
|
@@ -314,6 +401,7 @@ export default renderToString;
|
|
|
314
401
|
|
|
315
402
|
export {
|
|
316
403
|
renderToString as render,
|
|
404
|
+
renderToString as renderToStaticMarkup,
|
|
317
405
|
renderToString,
|
|
318
406
|
shallowRender
|
|
319
407
|
};
|
package/src/jsx.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { VNode } from 'preact';
|
|
2
2
|
|
|
3
3
|
interface Options {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
jsx?: boolean;
|
|
5
|
+
xml?: boolean;
|
|
6
|
+
functions?: boolean;
|
|
7
|
+
functionNames?: boolean;
|
|
8
|
+
skipFalseAttributes?: boolean;
|
|
9
|
+
pretty?: boolean | string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function render(vnode: VNode, context?: any, options?: Options):string;
|
|
12
|
+
export function render(vnode: VNode, context?: any, options?: Options): string;
|
|
13
13
|
export default render;
|
package/src/jsx.js
CHANGED
|
@@ -3,45 +3,53 @@ import renderToString from './index';
|
|
|
3
3
|
import { indent, encodeEntities, assign } from './util';
|
|
4
4
|
import prettyFormat from 'pretty-format';
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
// we have to patch in Array support, Possible issue in npm.im/pretty-format
|
|
8
7
|
let preactPlugin = {
|
|
9
8
|
test(object) {
|
|
10
|
-
return
|
|
9
|
+
return (
|
|
10
|
+
object &&
|
|
11
|
+
typeof object === 'object' &&
|
|
12
|
+
'type' in object &&
|
|
13
|
+
'props' in object &&
|
|
14
|
+
'key' in object
|
|
15
|
+
);
|
|
11
16
|
},
|
|
12
17
|
print(val, print, indent) {
|
|
13
18
|
return renderToString(val, preactPlugin.context, preactPlugin.opts, true);
|
|
14
19
|
}
|
|
15
20
|
};
|
|
16
21
|
|
|
17
|
-
|
|
18
22
|
let prettyFormatOpts = {
|
|
19
23
|
plugins: [preactPlugin]
|
|
20
24
|
};
|
|
21
25
|
|
|
22
|
-
|
|
23
26
|
function attributeHook(name, value, context, opts, isComponent) {
|
|
24
27
|
let type = typeof value;
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
// Use render-to-string's built-in handling for these properties
|
|
27
|
-
if (name==='dangerouslySetInnerHTML') return false;
|
|
30
|
+
if (name === 'dangerouslySetInnerHTML') return false;
|
|
28
31
|
|
|
29
32
|
// always skip null & undefined values, skip false DOM attributes, skip functions if told to
|
|
30
|
-
if (value==null || (type==='function' && !opts.functions)) return '';
|
|
33
|
+
if (value == null || (type === 'function' && !opts.functions)) return '';
|
|
31
34
|
|
|
32
|
-
if (
|
|
35
|
+
if (
|
|
36
|
+
opts.skipFalseAttributes &&
|
|
37
|
+
!isComponent &&
|
|
38
|
+
(value === false ||
|
|
39
|
+
((name === 'class' || name === 'style') && value === ''))
|
|
40
|
+
)
|
|
41
|
+
return '';
|
|
33
42
|
|
|
34
|
-
let indentChar = typeof opts.pretty==='string' ? opts.pretty : '\t';
|
|
35
|
-
if (type!=='string') {
|
|
36
|
-
if (type==='function' && !opts.functionNames) {
|
|
43
|
+
let indentChar = typeof opts.pretty === 'string' ? opts.pretty : '\t';
|
|
44
|
+
if (type !== 'string') {
|
|
45
|
+
if (type === 'function' && !opts.functionNames) {
|
|
37
46
|
value = 'Function';
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
47
|
+
} else {
|
|
40
48
|
preactPlugin.context = context;
|
|
41
49
|
preactPlugin.opts = opts;
|
|
42
50
|
value = prettyFormat(value, prettyFormatOpts);
|
|
43
51
|
if (~value.indexOf('\n')) {
|
|
44
|
-
value = `${indent('\n'+value, indentChar)}\n`;
|
|
52
|
+
value = `${indent('\n' + value, indentChar)}\n`;
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
55
|
return indent(`\n${name}={${value}}`, indentChar);
|
|
@@ -49,7 +57,6 @@ function attributeHook(name, value, context, opts, isComponent) {
|
|
|
49
57
|
return `\n${indentChar}${name}="${encodeEntities(value)}"`;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
|
-
|
|
53
60
|
let defaultOpts = {
|
|
54
61
|
attributeHook,
|
|
55
62
|
jsx: true,
|
|
@@ -60,7 +67,6 @@ let defaultOpts = {
|
|
|
60
67
|
pretty: ' '
|
|
61
68
|
};
|
|
62
69
|
|
|
63
|
-
|
|
64
70
|
function renderToJsxString(vnode, context, opts, inner) {
|
|
65
71
|
opts = assign(assign({}, defaultOpts), opts || {});
|
|
66
72
|
return renderToString(vnode, context, opts, inner);
|
package/src/polyfills.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
if (typeof Symbol!=='function') {
|
|
1
|
+
if (typeof Symbol !== 'function') {
|
|
2
2
|
let c = 0;
|
|
3
|
-
|
|
3
|
+
// eslint-disable-next-line
|
|
4
|
+
Symbol = function (s) {
|
|
4
5
|
return `@@${s}${++c}`;
|
|
5
6
|
};
|
|
6
|
-
Symbol.for = s => `@@${s}`;
|
|
7
|
+
Symbol.for = (s) => `@@${s}`;
|
|
7
8
|
}
|
package/src/util.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
// DOM properties that should NOT have "px" added when numeric
|
|
2
2
|
export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|^--/i;
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export function encodeEntities(s) {
|
|
5
|
+
if (typeof s !== 'string') s = String(s);
|
|
6
|
+
let out = '';
|
|
7
|
+
for (let i = 0; i < s.length; i++) {
|
|
8
|
+
let ch = s[i];
|
|
9
|
+
// prettier-ignore
|
|
10
|
+
switch (ch) {
|
|
11
|
+
case '<': out += '<'; break;
|
|
12
|
+
case '>': out += '>'; break;
|
|
13
|
+
case '"': out += '"'; break;
|
|
14
|
+
case '&': out += '&'; break;
|
|
15
|
+
default: out += ch;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
9
20
|
|
|
10
|
-
export let indent = (s, char) =>
|
|
21
|
+
export let indent = (s, char) =>
|
|
22
|
+
String(s).replace(/(\n+)/g, '$1' + (char || '\t'));
|
|
11
23
|
|
|
12
|
-
export let isLargeString = (s, length, ignoreLines) =>
|
|
24
|
+
export let isLargeString = (s, length, ignoreLines) =>
|
|
25
|
+
String(s).length > (length || 40) ||
|
|
26
|
+
(!ignoreLines && String(s).indexOf('\n') !== -1) ||
|
|
27
|
+
String(s).indexOf('<') !== -1;
|
|
13
28
|
|
|
14
29
|
const JS_TO_CSS = {};
|
|
15
30
|
|
|
@@ -18,13 +33,17 @@ export function styleObjToCss(s) {
|
|
|
18
33
|
let str = '';
|
|
19
34
|
for (let prop in s) {
|
|
20
35
|
let val = s[prop];
|
|
21
|
-
if (val!=null) {
|
|
36
|
+
if (val != null) {
|
|
22
37
|
if (str) str += ' ';
|
|
23
38
|
// str += jsToCss(prop);
|
|
24
|
-
str +=
|
|
39
|
+
str +=
|
|
40
|
+
prop[0] == '-'
|
|
41
|
+
? prop
|
|
42
|
+
: JS_TO_CSS[prop] ||
|
|
43
|
+
(JS_TO_CSS[prop] = prop.replace(/([A-Z])/g, '-$1').toLowerCase());
|
|
25
44
|
str += ': ';
|
|
26
45
|
str += val;
|
|
27
|
-
if (typeof val==='number' && IS_NON_DIMENSIONAL.test(prop)===false) {
|
|
46
|
+
if (typeof val === 'number' && IS_NON_DIMENSIONAL.test(prop) === false) {
|
|
28
47
|
str += 'px';
|
|
29
48
|
}
|
|
30
49
|
str += ';';
|
|
@@ -55,8 +74,7 @@ export function assign(obj, props) {
|
|
|
55
74
|
export function getChildren(accumulator, children) {
|
|
56
75
|
if (Array.isArray(children)) {
|
|
57
76
|
children.reduce(getChildren, accumulator);
|
|
58
|
-
}
|
|
59
|
-
else if (children!=null && children!==false) {
|
|
77
|
+
} else if (children != null && children !== false) {
|
|
60
78
|
accumulator.push(children);
|
|
61
79
|
}
|
|
62
80
|
return accumulator;
|