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