126 lines
3.1 KiB
JavaScript
126 lines
3.1 KiB
JavaScript
// 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;
|
|
}
|