@b-side/parser
Version:
HTML Parser used to parse HTML string and bind data to it.
404 lines • 15 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _bsElement_dom, _bsFragment_dom, _bsNode_dom, _bsText_dom, _bsExpression_dom;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateElement = exports.bsExpression = exports.bsText = exports.bsNode = exports.bsIteration = exports.bsFragment = exports.bsCondition = exports.bsElement = exports.SelfClosingTags = void 0;
const expression_1 = require("./expression");
const side_effects_1 = require("./side-effects");
const utils_1 = require("./utils");
const prefixLogicalTags = 'bs-';
const prefixLogicalAttributes = prefixLogicalTags;
const prefixEvents = 'on-';
exports.SelfClosingTags = [
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr',
];
const getLogic = (element) => {
return {
elements: element.nodeName === `${prefixLogicalAttributes}if` ? [element] : [],
resolved: [],
isDefault: element.nodeName === `${prefixLogicalAttributes}else`,
};
};
const getFragment = () => {
const template = (0, utils_1.getDocument)().createElement('template');
return { dom: template.content, template };
};
const findConditionalSiblings = (element, parent) => {
for (let x = parent.childs.length - 1; x >= 0; x--) {
const child = parent.childs[x];
if (child instanceof bsCondition) {
child.logic.elements.push(element);
element.logic.elements = child.logic.elements;
element.logic.resolved = child.logic.resolved;
break;
}
}
};
class bsElement {
constructor() {
this.attributesMap = {
static: new Map(),
};
this.childs = [];
this.dependancies = new side_effects_1.Effects();
this.nodeName = '';
this.strAttributes = '';
_bsElement_dom.set(this, void 0);
}
set dom(value) {
__classPrivateFieldSet(this, _bsElement_dom, value, "f");
}
get dom() {
return __classPrivateFieldGet(this, _bsElement_dom, "f");
}
appendText(string) {
if (!string || !string.trim().length) {
return;
}
const element = (0, exports.CreateElement)('text', string.replace(/\s+/g, ' '));
this.append(element);
}
appendExpression(string) {
if (!string || !string.trim().length) {
return;
}
const element = (0, exports.CreateElement)('expression', string.replace(/\s+/g, ' '));
this.append(element);
}
append(element) {
if (element instanceof bsCondition) {
element.logic = getLogic(element);
if (!element.logic.elements.length) {
findConditionalSiblings(element, this);
}
}
this.childs.push(element);
if (this.attributesMap.static.has('xmlns')) {
element.attributesMap.static.set('xmlns', this.attributesMap.static.get('xmlns') || '');
}
element.parent = this;
}
clone(parent) {
const clone = (0, exports.CreateElement)(this.nodeName, this.strAttributes);
clone.childs.length = 0;
clone.dependancies = this.dependancies.clone();
clone.dom = this.dom?.cloneNode(false);
clone.nodeName = this.nodeName;
clone.parent = parent ? parent : this.parent;
clone.strAttributes = this.strAttributes;
clone.attributesMap.dynamic = new Map();
clone.attributesMap.static = new Map(this.attributesMap.static);
for (const [key, expression] of this.attributesMap.dynamic || []) {
clone.attributesMap.dynamic.set(key, expression.clone());
}
this.childs.forEach((child) => {
const childClone = child.clone(clone);
childClone.parent = parent ? clone : this;
clone.childs.push(childClone);
});
return clone;
}
updateDependancies(context, contextSnapshot, newKeys = []) {
let foundNewDependancies = false;
if (contextSnapshot) {
foundNewDependancies = this.dependancies.eval(context, contextSnapshot);
}
else {
newKeys = this.dependancies.updateDependancies(context);
}
if (!newKeys.length && !foundNewDependancies) {
return newKeys;
}
this.childs.forEach(async (child) => {
const newChildKeys = child.updateDependancies(context, this.dependancies.contextSnapshot, newKeys);
if (newChildKeys.length) {
this.dependancies.merge(child.dependancies);
}
});
this.attributesMap.dynamic?.forEach((attribute) => {
if (attribute.dependancies.eval(context, contextSnapshot)) {
this.dependancies.merge(attribute.dependancies);
}
});
return newKeys;
}
toString() {
const clone = (element) => {
let html = '';
if (element instanceof bsText) {
html += element.content;
}
else if (element instanceof bsExpression) {
html += `{{${element.expression.raw}}}`;
}
else {
if (!(element instanceof bsFragment)) {
html += `<${element.nodeName}${element.strAttributes}`;
}
html += element.childs.map((child) => clone(child)).join('');
if (!(element instanceof bsFragment)) {
if (!exports.SelfClosingTags.includes(element.nodeName || '') &&
!element.strAttributes.match(/\/>$/)) {
html += `</${element.nodeName}>`;
}
}
}
return html;
};
return clone(this);
}
}
exports.bsElement = bsElement;
_bsElement_dom = new WeakMap();
class bsCondition extends bsElement {
constructor(attributes) {
super();
this.logic = { elements: [], resolved: [], isDefault: false };
if (attributes.size > 1) {
throw new Error(`Only ONE attribute can and MUST be assigned to a Condition or Iteration.`);
}
this.expression = new expression_1.Expression(attributes.get('@__0__@')?.expression || '');
}
clone(parent) {
const clone = super.clone(parent);
clone.logic = getLogic(clone);
clone.expression = this.expression.clone();
if (!clone.logic.elements.length) {
findConditionalSiblings(clone, parent || this);
}
return clone;
}
updateDependancies(context, contextSnapshot, newKeys = []) {
newKeys = super.updateDependancies(context, contextSnapshot, newKeys);
contextSnapshot = contextSnapshot || this.dependancies.contextSnapshot;
if (this.expression.dependancies.eval(context, contextSnapshot)) {
this.dependancies.merge(this.expression.dependancies);
}
return newKeys;
}
}
exports.bsCondition = bsCondition;
class bsFragment extends bsElement {
constructor() {
super(...arguments);
_bsFragment_dom.set(this, void 0);
}
set dom(value) {
__classPrivateFieldSet(this, _bsFragment_dom, value, "f");
}
get dom() {
if (__classPrivateFieldGet(this, _bsFragment_dom, "f") !== undefined) {
return __classPrivateFieldGet(this, _bsFragment_dom, "f");
}
__classPrivateFieldSet(this, _bsFragment_dom, this.createDomElement(), "f");
return __classPrivateFieldGet(this, _bsFragment_dom, "f");
}
createDomElement() {
return (0, utils_1.getDocument)().createDocumentFragment();
}
}
exports.bsFragment = bsFragment;
_bsFragment_dom = new WeakMap();
class bsIteration extends bsCondition {
constructor() {
super(...arguments);
this.clones = [];
}
clone(parent) {
const clone = super.clone(parent);
clone.clones.length = 0;
return clone;
}
}
exports.bsIteration = bsIteration;
class bsNode extends bsElement {
constructor(attributes) {
super();
this.attributesMap = {
static: new Map(),
dynamic: new Map(),
};
this.eventsMap = {
static: new Map(),
dynamic: new Map(),
};
_bsNode_dom.set(this, void 0);
if (attributes) {
this.setAttributesMap(attributes);
}
}
set dom(value) {
__classPrivateFieldSet(this, _bsNode_dom, value, "f");
}
get dom() {
if (__classPrivateFieldGet(this, _bsNode_dom, "f") !== undefined) {
return __classPrivateFieldGet(this, _bsNode_dom, "f");
}
__classPrivateFieldSet(this, _bsNode_dom, this.createDomElement(), "f");
if (this.attributesMap?.static) {
for (const [name, value] of this.attributesMap.static) {
__classPrivateFieldGet(this, _bsNode_dom, "f").setAttribute(name, value);
}
}
return __classPrivateFieldGet(this, _bsNode_dom, "f");
}
clone(parent) {
const clone = super.clone(parent);
clone.eventsMap.dynamic = new Map();
clone.eventsMap.static = new Map(this.eventsMap.static);
for (const [key, expression] of this.eventsMap.dynamic || []) {
clone.eventsMap.dynamic.set(key, expression.clone());
}
return clone;
}
createDomElement() {
const extendsElement = this.attributesMap?.static.has('is')
? { is: this.attributesMap.static.get('is') }
: undefined;
const namespace = this.attributesMap?.static.get('xmlns');
let domElement = null;
if (namespace) {
domElement = (0, utils_1.getDocument)().createElementNS(namespace, this.nodeName, extendsElement);
}
else {
domElement = (0, utils_1.getDocument)().createElement(this.nodeName, extendsElement);
}
return domElement;
}
setAttributesMap(attributes) {
this.attributesMap = { static: new Map(), dynamic: new Map() };
this.eventsMap = { static: new Map(), dynamic: new Map() };
for (const item of attributes) {
const [name, { value, expression }] = item;
if (expression) {
if (name.indexOf(prefixEvents) === 0) {
this.eventsMap.dynamic.set(name.substring(3), new expression_1.Expression(expression));
}
else {
this.attributesMap.dynamic.set(name, new expression_1.Expression(expression));
}
}
else {
this.attributesMap.static.set(name, value === undefined ? '' : value);
}
}
}
}
exports.bsNode = bsNode;
_bsNode_dom = new WeakMap();
class bsText extends bsElement {
constructor(text) {
super();
this.content = '';
_bsText_dom.set(this, void 0);
if (text !== undefined) {
this.content = text;
}
}
set dom(value) {
__classPrivateFieldSet(this, _bsText_dom, value, "f");
}
get dom() {
if (__classPrivateFieldGet(this, _bsText_dom, "f") !== undefined) {
return __classPrivateFieldGet(this, _bsText_dom, "f");
}
__classPrivateFieldSet(this, _bsText_dom, this.createDomElement(), "f");
return __classPrivateFieldGet(this, _bsText_dom, "f");
}
clone(parent) {
const clone = super.clone(parent);
clone.content = this.content;
return clone;
}
createDomElement() {
return (0, utils_1.getDocument)().createTextNode(this.content);
}
}
exports.bsText = bsText;
_bsText_dom = new WeakMap();
class bsExpression extends bsElement {
constructor(text = '') {
super();
this.siblings = [];
_bsExpression_dom.set(this, void 0);
const { template } = getFragment();
this.template = template;
this.expression = new expression_1.Expression(text);
}
set dom(value) {
__classPrivateFieldSet(this, _bsExpression_dom, value, "f");
}
get dom() {
return __classPrivateFieldGet(this, _bsExpression_dom, "f");
}
clone(parent) {
const clone = super.clone(parent);
clone.expression = this.expression.clone();
return clone;
}
updateDependancies(context, contextSnapshot, newKeys = []) {
newKeys = super.updateDependancies(context, contextSnapshot, newKeys);
contextSnapshot = contextSnapshot || this.dependancies.contextSnapshot;
if (this.expression.dependancies.eval(context, contextSnapshot)) {
this.dependancies.merge(this.expression.dependancies);
}
return newKeys;
}
}
exports.bsExpression = bsExpression;
_bsExpression_dom = new WeakMap();
const CreateElement = function (tagName, strAttributes, attributes) {
let element;
if (tagName === 'fragment') {
element = new bsFragment();
}
else if (tagName === 'text') {
element = new bsText(strAttributes);
}
else if (tagName === 'expression') {
element = new bsExpression(strAttributes);
}
else if ([
`${prefixLogicalAttributes}if`,
`${prefixLogicalAttributes}elseif`,
`${prefixLogicalAttributes}else`,
].indexOf(tagName) > -1) {
element = new bsCondition(attributes || new Map());
}
else if ([`${prefixLogicalAttributes}for`].indexOf(tagName) > -1) {
element = new bsIteration(attributes || new Map());
}
else {
element = new bsNode(attributes);
}
element.nodeName = tagName;
element.strAttributes = strAttributes === undefined ? '' : strAttributes;
return element;
};
exports.CreateElement = CreateElement;
//# sourceMappingURL=element.js.map