Browse Source

Move ParserHtml to TS

pull/4746/head
Artur Arseniev 4 years ago
parent
commit
8b43402306
  1. 66
      src/parser/model/ParserHtml.ts

66
src/parser/model/ParserHtml.js → src/parser/model/ParserHtml.ts

@ -1,7 +1,17 @@
import { each, isString, isFunction, isUndefined } from 'underscore'; import { each, isString, isFunction, isUndefined } from 'underscore';
import { CssRuleProperties } from '../../css_composer/model/CssRule';
import BrowserParserHtml from './BrowserParserHtml'; import BrowserParserHtml from './BrowserParserHtml';
export default config => { type AnyObject = Record<string, any>;
type StringObject = Record<string, string>;
type HTMLParseResult = {
html: null | Record<string, any> | Record<string, any>[]; // TODO replace with components
css: null | CssRuleProperties[];
};
export default (config: AnyObject = {}) => {
let c = config; let c = config;
const modelAttrStart = 'data-gjs-'; const modelAttrStart = 'data-gjs-';
const event = 'parse:html'; const event = 'parse:html';
@ -16,9 +26,9 @@ export default config => {
* @param {Object} attr * @param {Object} attr
* @returns {Object} An object containing props and attributes without them * @returns {Object} An object containing props and attributes without them
*/ */
splitPropsFromAttr(attr = {}) { splitPropsFromAttr(attr: AnyObject = {}) {
const props = {}; const props: StringObject = {};
const attrs = {}; const attrs: StringObject = {};
each(attr, (value, key) => { each(attr, (value, key) => {
if (key.indexOf(this.modelAttrStart) === 0) { if (key.indexOf(this.modelAttrStart) === 0) {
@ -61,15 +71,17 @@ export default config => {
* console.log(stl); * console.log(stl);
* // {color: 'black', width: '100px', test: 'value'} * // {color: 'black', width: '100px', test: 'value'}
*/ */
parseStyle(str) { parseStyle(str: string) {
var result = {}; const result: StringObject = {};
var decls = str.split(';'); const decls = str.split(';');
for (var i = 0, len = decls.length; i < len; i++) {
var decl = decls[i].trim(); for (let i = 0, len = decls.length; i < len; i++) {
const decl = decls[i].trim();
if (!decl) continue; if (!decl) continue;
var prop = decl.split(':'); const prop = decl.split(':');
result[prop[0].trim()] = prop.slice(1).join(':').trim(); result[prop[0].trim()] = prop.slice(1).join(':').trim();
} }
return result; return result;
}, },
@ -82,14 +94,16 @@ export default config => {
* console.log(res); * console.log(res);
* // ['test1', 'test2', 'test3'] * // ['test1', 'test2', 'test3']
*/ */
parseClass(str) { parseClass(str: string) {
const result = []; const result = [];
const cls = str.split(' '); const cls = str.split(' ');
for (let i = 0, len = cls.length; i < len; i++) { for (let i = 0, len = cls.length; i < len; i++) {
const cl = cls[i].trim(); const cl = cls[i].trim();
if (!cl) continue; if (!cl) continue;
result.push(cl); result.push(cl);
} }
return result; return result;
}, },
@ -98,22 +112,22 @@ export default config => {
* @param {HTMLElement} el DOM element to traverse * @param {HTMLElement} el DOM element to traverse
* @return {Array<Object>} * @return {Array<Object>}
*/ */
parseNode(el, opts = {}) { parseNode(el: HTMLElement, opts: AnyObject = {}) {
const result = []; const result = [];
const nodes = el.childNodes; const nodes = el.childNodes;
for (var i = 0, len = nodes.length; i < len; i++) { for (var i = 0, len = nodes.length; i < len; i++) {
const node = nodes[i]; const node = nodes[i] as HTMLElement;
const attrs = node.attributes || []; const attrs = node.attributes || [];
const attrsLen = attrs.length; const attrsLen = attrs.length;
const nodePrev = result[result.length - 1]; const nodePrev = result[result.length - 1];
const nodeChild = node.childNodes.length; const nodeChild = node.childNodes.length;
const ct = this.compTypes; const ct = this.compTypes;
let model = {}; let model: Record<string, any> = {}; // TODO use component properties
// Start with understanding what kind of component it is // Start with understanding what kind of component it is
if (ct) { if (ct) {
let obj = ''; let obj: any = '';
let type = node.getAttribute && node.getAttribute(`${modelAttrStart}type`); let type = node.getAttribute && node.getAttribute(`${modelAttrStart}type`);
// If the type is already defined, use it // If the type is already defined, use it
@ -124,10 +138,12 @@ export default config => {
// the first with a valid result will be that component // the first with a valid result will be that component
for (let it = 0; it < ct.length; it++) { for (let it = 0; it < ct.length; it++) {
const compType = ct[it]; const compType = ct[it];
// @ts-ignore
obj = compType.model.isComponent(node, opts); obj = compType.model.isComponent(node, opts);
if (obj) { if (obj) {
if (typeof obj !== 'object') { if (typeof obj !== 'object') {
// @ts-ignore
obj = { type: compType.id }; obj = { type: compType.id };
} }
break; break;
@ -152,7 +168,7 @@ export default config => {
// Parse attributes // Parse attributes
for (let j = 0; j < attrsLen; j++) { for (let j = 0; j < attrsLen; j++) {
const nodeName = attrs[j].nodeName; const nodeName = attrs[j].nodeName;
let nodeValue = attrs[j].nodeValue; let nodeValue: string | boolean = attrs[j].nodeValue!;
// Isolate attributes // Isolate attributes
if (nodeName == 'style') { if (nodeName == 'style') {
@ -175,13 +191,13 @@ export default config => {
try { try {
nodeValue = nodeValue =
(firstChar == '{' && lastChar == '}') || (firstChar == '[' && lastChar == ']') (firstChar == '{' && lastChar == '}') || (firstChar == '[' && lastChar == ']')
? JSON.parse(nodeValue) ? JSON.parse(nodeValue as string)
: nodeValue; : nodeValue;
} catch (e) {} } catch (e) {}
model[modelAttr] = nodeValue; model[modelAttr] = nodeValue;
} else { } else {
// Check for attributes from props (eg. required, disabled) // @ts-ignore Check for attributes from props (eg. required, disabled)
if (nodeValue === '' && node[nodeName] === true) { if (nodeValue === '' && node[nodeName] === true) {
nodeValue = true; nodeValue = true;
} }
@ -221,7 +237,7 @@ export default config => {
// Throw away empty nodes (keep spaces) // Throw away empty nodes (keep spaces)
if (!config.keepEmptyTextNodes) { if (!config.keepEmptyTextNodes) {
const content = node.nodeValue; const content = node.nodeValue;
if (content != ' ' && !content.trim()) { if (content != ' ' && !content!.trim()) {
continue; continue;
} }
} }
@ -275,11 +291,11 @@ export default config => {
* @param {ParserCss} parserCss In case there is style tags inside HTML * @param {ParserCss} parserCss In case there is style tags inside HTML
* @return {Object} * @return {Object}
*/ */
parse(str, parserCss, opts = {}) { parse(str: string, parserCss: any, opts = {}) {
const { em } = c; const { em } = c;
const conf = (em && em.get('Config')) || {}; const conf = (em && em.get('Config')) || {};
const res = { html: null, css: null }; const res: HTMLParseResult = { html: null, css: null };
const cf = { ...config, ...opts }; const cf: AnyObject = { ...config, ...opts };
const options = { const options = {
...config.optionsHtml, ...config.optionsHtml,
// Support previous `configParser.htmlType` option // Support previous `configParser.htmlType` option
@ -327,16 +343,16 @@ export default config => {
return res; return res;
}, },
__clearUnsafeAttr(node) { __clearUnsafeAttr(node: HTMLElement) {
const attrs = node.attributes || []; const attrs = node.attributes || [];
const nodes = node.childNodes || []; const nodes = node.childNodes || [];
const toRemove = []; const toRemove: string[] = [];
each(attrs, attr => { each(attrs, attr => {
const name = attr.nodeName || ''; const name = attr.nodeName || '';
name.indexOf('on') === 0 && toRemove.push(name); name.indexOf('on') === 0 && toRemove.push(name);
}); });
toRemove.map(name => node.removeAttribute(name)); toRemove.map(name => node.removeAttribute(name));
each(nodes, node => this.__clearUnsafeAttr(node)); each(nodes, node => this.__clearUnsafeAttr(node as HTMLElement));
}, },
}; };
}; };
Loading…
Cancel
Save