@ray-core/runtime
Version:
Ray 是一个全新的基于 React 的小程序开发框架
225 lines (224 loc) • 7.81 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
import * as htmlparser2 from '@ray-core/htmlparser2';
function fixedEncodeURIComponent(str) {
str = str.replace(/[\n\s]+/mg, ' ').replace(/^\s|\s$/g, '');
var res = encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
});
return res;
}
var sizeKeys = ['width', 'height', 'mini-height', 'max-height', 'mini-width', 'max-width'];
function extraSizeFromStyle(style) {
var props = {};
var reg = /(?:^|\s)*((?:max-|mini-)?(?:width|height))\s*:\s*([^;]+);?/g;
var m;
while (m = reg.exec(style)) {
var _a = __read(m, 3), _1 = _a[0], k = _a[1], v = _a[2];
props[k] = v;
}
return props;
}
function concatStyle(size) {
var style = '';
sizeKeys.forEach(function (k) {
if (size.hasOwnProperty(k)) {
var v = size[k];
style += "".concat(k, ":").concat(/\d$/.test(v) ? v + 'px' : v, ";");
}
});
return style;
}
function findSvgAndToImage(str) {
var reg = /<svg([^>]*)>([\s\S]*?)<\/svg>/gm;
var regRes;
var attributes = ['style', 'class', 'className', 'width', 'height'];
// 提取所有的 svg 标签
while ((regRes = reg.exec(str))) {
var _a = __read(regRes, 1), matched = _a[0];
var _b = __read(regRes, 3), _2 = _b[0], attrs = _b[1], content = _b[2];
content = content.replace(/[\s\n]/gm, '');
// 去除无效的标签
if (!content) {
str = str.replace(matched, '');
reg.lastIndex = 0;
continue;
}
if (matched) {
attrs = attrs.replace(/^\s*|\s*$/g, '');
var props = {};
if (attrs) {
// 提取属性及值
var reg_1 = /\s*([^=\s"']+)(?:\s*=\s*["']([^="']*?)["'])?/g;
var regRes_1 = void 0;
while (regRes_1 = reg_1.exec(attrs)) {
var _c = __read(regRes_1, 3), _3 = _c[0], k = _c[1], v = _c[2];
if (attributes.indexOf(k) !== -1) {
props[k] = v ? v : true;
}
}
}
// 提取样式中的尺寸信息
if (props.style) { // style 中的尺寸优先级高于属性
var size = extraSizeFromStyle(props.style);
props = __assign(__assign({}, props), size);
}
var className = "".concat(props.className || '', " ").concat(props.class || '').replace(/^\s*|\s*$/g, '');
var svg = fixedEncodeURIComponent(matched);
var img = "<image src=\"data:image/svg+xml,".concat(svg, "\"");
var style = concatStyle(props);
if (style) {
img += " style=\"".concat(style, "\"");
}
if (className) {
img += " class=\"".concat(className, "\"");
}
img += ' />';
str = str.replace(matched, img);
reg.lastIndex = img.length;
}
}
return str;
}
var isDebug = process.env.REMAX_DEBUG === 'true';
var CACHES = {};
export function parseHTML(xmlContent) {
if (CACHES[xmlContent]) {
return CACHES[xmlContent];
}
var xml = null;
var data = [];
if (!xmlContent)
return data;
xmlContent = findSvgAndToImage(xmlContent);
if (!xmlContent)
return data;
var parser = new htmlparser2.Parser({
onopentag: function (type, props) {
if (isDebug) {
console.log('[html slice parser] html tag: %s, original props: %o', type, props, parser);
}
props = Object.keys(props).reduce(function (acc, key) {
var k = key;
var v = props[key];
if (k === 'class') {
k = 'className';
}
v = v === 'false' ? false : v === 'true' ? true : v;
acc[k] = v;
return acc;
}, {});
if (isDebug) {
console.log('[html slice parser] html tag: %s, props handled: %o', type, props);
}
var children = (xml === null || xml === void 0 ? void 0 : xml.children) || [];
var isRoot = xml === null;
if (!isRoot)
xml.children = children;
xml = { type: type, props: props, parent: xml };
if (isRoot) {
data.push(xml);
return;
}
children.push(xml);
},
ontext: function (text) {
if (!text) {
return;
}
if (!xml) {
data.push(text);
return;
}
var children = xml.children || [];
children.push(text);
xml.children = children;
},
onclosetag: function () {
xml = xml.parent;
},
}, { lowerCaseAttributeNames: false, xmlMode: true });
parser.reset();
parser.write(xmlContent);
parser.end();
CACHES[xmlContent] = data;
return data;
}
export function svgVNodeToImage(vNode) {
var isEmpty = vNode.children.length === 0;
function helper(node, str) {
if (node.type === 'plain-text') {
var text = node.text || '';
return text;
}
str = str + "<".concat(node.type);
var p = node.props || {};
var children = node.children || [];
delete p.__instid__;
var attrs = Object.entries(p).map(function (_a) {
var _b = __read(_a, 2), k = _b[0], v = _b[1];
return "".concat(k, "=\"").concat(v, "\"");
}).join(' ');
if (attrs) {
str = str + " ".concat(attrs, ">");
}
else {
str = str + '>';
}
if (children.length && node.nodes) {
str = str + children.map(function (child) { return helper(node.nodes[child], ''); }).join('');
}
return str + '</' + node.type + '>';
}
// 此处 true 为跳过将 svg 及其子节点转成小程序标签
var json = vNode.toJSON(true);
// 将序列化后的svg 数据转成 svg 字符串(一串html字符串 <svg ...></svg>)
var svgStr = helper(json, '').replace(/&(?!amp;)/g, '&');
console.log('svgStr', svgStr);
var encoded = fixedEncodeURIComponent(svgStr);
var props = __assign({}, json.props);
if (props.style) {
var size = extraSizeFromStyle(props.style);
props = __assign(__assign({}, props), size);
}
var _p = {
src: isEmpty ? '' : "data:image/svg+xml;charset=UTF-8,".concat(encoded),
alt: 'svg',
};
if (props.className) {
_p.class = props.className;
}
var style = concatStyle(props);
if (style) {
_p.style = style;
}
vNode.type = 'image';
vNode.props = _p;
vNode.children = [];
return vNode;
}