import {ComponentInfo} from "./ComponentInfo"; import * as convert from 'xml-js' import * as fs from 'fs' import * as path from 'path' /** * N.B. 5/24/21 -- COMPACT IS TRUE * Originally coded with js/xml convert using option compact:true, but then changed to compact:false because similar * treatment for pages was not keeping the correct ordering of multiple mixed elements, so everything got changed to * compact:false, which solved the page problem, but caused component conversion (Nativescript) to fail because * the code there interprets the format directly. * So because of that compact:true is in effect again for components (but not pages) */ let actMethods = {} export function writeRiotFile(info:ComponentInfo, pathname:string) { const layin = Object.assign({}, info.layout) const xml = convert.js2xml(layin, { compact:true, spaces: 4, attributeValueFn:riotProp, textFn:riotProp }) // Object.getOwnPropertyNames(actMethods).forEach(p => { // // @ts-ignore // info.methods[p] = actMethods[p] // info.params[p] = 'ev' // }) let page = `<${info.id} bind="${info.bind}">\n` page += xml page += '\n\n' page += `` page += `\n\n` // New per ticket: https://github.com/tremho/thunderbolt-common/projects/1#card-60937753 let srcDir = pathname.substring(0, pathname.lastIndexOf(path.sep)) pathname = pathname.replace('src'+path.sep, '.gen'+path.sep) let dir = pathname.substring(0,pathname.lastIndexOf(path.sep)) if(!fs.existsSync(dir)) { fs.mkdirSync(dir, {recursive:true}) } fs.writeFileSync(pathname, page) // copy code-back file if(info.codeBack) { const relPath = info.codeBack.substring(info.codeBack.lastIndexOf(path.sep) + 1) // relative let src = path.join(srcDir, relPath) let dest = path.join(dir, relPath) fs.copyFileSync(src, dest) } } function scriptInnards(codeBackFile:string) { let tagCode = '' // Object.getOwnPropertyNames(methods).forEach(key => { // let prm = params[key] // let code = methods[key] // let lines = code.split('\n') // code = lines.join('\n ').trim() // let value = '' // if(key === 'handleAction') { // value = '{\n ' +lines.join('\n ').trim() // } else { // value = '{\n try ' + code + ' catch(e) {\n console.error("error executing \'' + key + '\':",e)\n }\n }' // } // tagCode += `${key}(${prm}) ${value},\n ` // }) let script if(codeBackFile) { const baseName = codeBackFile.substring(codeBackFile.lastIndexOf(path.sep)+1, codeBackFile.lastIndexOf('.')) script = `\n import CCB from "./${baseName}"` } else { script = `\n // no code back` } script += ` let ccb = null let lastInit import StdComp from 'Framework/app-core/StdComp' const sc = Object.assign({` if(codeBackFile) script += ` postStdOnBeforeMount() { try { if(Date.now() !== lastInit) { ccb = new CCB() ccb.component = this this.controlApi = ccb; lastInit = Date.now() } } catch(e) { console.error('error in constructor for custom component '+this.root.tagName, e) } },` script += ` preStdOnMounted() { try { ccb && ccb.beforeLayout && ccb.beforeLayout.call(ccb) } catch(e) { console.error('error in beforeLayout for custom component '+this.root.tagName, e) } }, postStdOnMounted() { try { ccb && ccb.afterLayout && ccb.afterLayout.call(ccb) } catch(e) { console.error('error in afterLayout for custom component '+this.root.tagName, e) } }, preStdOnBeforeUpdate() { try { ccb && ccb.beforeUpdate && ccb.beforeUpdate.call(ccb) } catch(e) { console.error('error in beforeUpdate for custom component '+this.root.tagName, e) } }, handleAction(ev) { try { if(ccb && ccb.onAction) { ccb.onAction(ev) } else { // default if no special handler is specified in code back this.cm.app.callEventHandler('action', ev) } } catch(e) { console.error('Error in "'+this.root.tagName+' action handler"', e) } } }, StdComp) console.log(sc) export default sc ` return script } function riotProp(val:string) { if(val.charAt(0) === val.charAt(val.length-1) && val.charAt(0) === '"' || val.charAt(0) === "'") { val = val.substring(1, val.length-1) } if(val.charAt(0) === '$') { if(val.charAt(1) === '$') { let name = val.substring(2) val = `{b('data.${name}')}` } else { let name = val.substring(1) val = `{b('${name}')}` } } return val } function mapAction(tag: string) { switch(tag.trim().toLowerCase()) { case 'onclick': case 'click': case 'tap': case 'press': return 'onclick' default: return tag } }