diff --git a/src/parser/model/ParserHtml.js b/src/parser/model/ParserHtml.ts similarity index 86% rename from src/parser/model/ParserHtml.js rename to src/parser/model/ParserHtml.ts index c2e5c8ab3..aeaac40bf 100644 --- a/src/parser/model/ParserHtml.js +++ b/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; + +type StringObject = Record; + +type HTMLParseResult = { + html: null | Record | Record[]; // 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} */ - 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 = {}; // 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)); }, }; };