UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

442 lines (427 loc) 17.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.applyDropComponent = exports.applyTemplate = exports.getRoles = exports.autoTemplate = void 0; const lodash_1 = require("lodash"); const nasl_concepts_1 = require("@lcap/nasl-concepts"); const utils_1 = require("./utils"); // import { unique, firstUpperCase } from '../../utils/string'; const uniqueName_1 = require("./uniqueName"); const operators_1 = require("./operators"); const myProcess_1 = require("../template/myProcess"); let id = 0; class TemplateMeta { constructor(node) { // this.name = `t_${uuidv4().replace(/-/g, '')}`; this.name = `t_${node.concept}_${node.name ? node.name.replace(/[-\.]/g, '') : 'unknown'}_${id++}`; this.node = node; this.isRoot = false; this.rootBinds = []; this.binds = []; this.callees = []; this.modules = []; this.rolebinds = []; this.templatebinds = []; // 前端全局变量 this.frontendVariables = []; } addRootBinds(propertyName, templateMeta) { // App.[propertyName].push(templateMeta.name) if (!this.rootBinds.find((b) => b.propertyName === propertyName)) { this.rootBinds.push({ propertyName, value: templateMeta.name, }); } } addBinds(type, propertyName, templateMeta) { // this.node.[propertyName] = templateMeta.name // this.node.[propertyName].push(templateMeta.name) this.binds.push({ type, propertyName, value: templateMeta.name, }); } addPlainBinds(propertyName, value) { // this.node.[propertyName] = value if (typeof value === 'string') { value = value .split(/\r?\n/) .map((c) => `"${c.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`) // .map((c) => `"${c.replace(/([^\\])"/g, '$1\\"')}"`) // .map((c) => `decodeURIComponent("${c.encodeURIComponent}")`) .join(' + "\\n" +\n'); } if (typeof value === 'object') { value = JSON.stringify(value); } this.binds.push({ type: utils_1.TRACK_TYPE.PLAIN, propertyName, value, }); } addModule(m) { this.modules.push({ name: m.name, belongs: m.parentKey, data: m._toJSON((source) => (0, lodash_1.omit)(source, utils_1.IGNORE_PROPERTY)), }); } addCallee(propertyName, relatedPropertyName, templateMeta) { // this.node.[propertyName] = [targetVar].getNamespace(); // this.node.[relatedPropertyName] = [targetVar].name; this.callees.push({ propertyName, relatedPropertyName, targetVar: templateMeta.name, }); } addCalleeTemplate(propertyName, relatedPropertyName, nstemplate, nametemplate, arguVars) { // this.node.[propertyName] = nstemplate([arguVars]); // this.node.[relatedPropertyName] = nametemplate([arguVars]); this.callees.push({ propertyName, relatedPropertyName, nstemplate, nametemplate, arguVars, }); } addRoleTemplate(propertyName, arguVars) { this.rolebinds.push({ propertyName, arguVars, }); } addTemplateBind(propertyName, relatedVar, relatedProperty) { this.templatebinds.push({ propertyName, relatedVar, relatedProperty, }); } genComment(part) { return `/*---------${this.node.concept} ${this.node.name} ${part} -----------*/`; } genCreate() { // [this.name] = create[this.node.concept](); // return `${this.genComment('create')} // _tempConstructor = getConceptConstructor("${this.node.concept}"); // const ${this.name} = new _tempConstructor();` return `${this.genComment('create')} let ${this.name} = _create("${this.node.concept}"); _templateObjects.push(${this.name})`; } genBind() { return this.binds.map((bind) => { const { type, propertyName, value } = bind; switch (type) { case utils_1.TRACK_TYPE.PROPERTY: return `_set(${this.name}, "${propertyName}", ${value}, (updatedObj) => { ${value} = updatedObj; })`; case utils_1.TRACK_TYPE.PLAIN: return `_set(${this.name}, "${propertyName}", ${value});`; case utils_1.TRACK_TYPE.ARRAY: return `_push(${this.name}, "${propertyName}", ${value});`; } return ''; }); } genRootBind() { return this.rootBinds.map((bind) => { const { propertyName, value } = bind; if (propertyName === 'roles') { return ` if(roleCallback) { ${value} = roleCallback(${value}) } else { _push(app, "roles", ${value}); }`; } // return `app.${propertyName}.push(${value}); return `_push(app, "${propertyName}", ${value});`; }); } genEntryBind() { if (this.isRoot) { return `rootBindCallback(${this.name})`; } return ''; } genRootReturn() { if (this.isRoot) { return `return ${this.name};`; } return ''; } genName() { // [this.name].name = this.parent.genUniqueXXXName(); // return `${this.name}.name = (${this.name}.parentNode.gen${this.node.concept}UniqueName ? ${this.name}.parentNode.gen${this.node.concept}UniqueName() : ${this.name}.name)` if (this.node.concept === 'Role') { return ''; } // if (this.node.concept === 'Entity') { // return `_set(${this.name}, "name", getGenUniqNameFunctionName(${this.name}, "${this.node.concept}"));`; // _setTableName(${this.name}, ${this.name}.name + '_' + app.id.slice(0,6));`; // } return `_set(${this.name}, "name", _uniqueName.getGenUniqNameFunctionName(${this.name}, "${this.node.concept}", app), (updatedObj) => { ${this.name} = updatedObj; })`; } genRoleBind() { return this.rolebinds.map((role) => { const { propertyName, arguVars } = role; return `_set(${this.name}, "${propertyName}", _bindRoles(${arguVars}), (updatedObj) => { ${this.name} = updatedObj; });`; }); } genCallee() { return this.callees.map((callee) => { const { propertyName, relatedPropertyName, targetVar, nstemplate, nametemplate, arguVars } = callee; if (arguVars && nstemplate && nametemplate) { // return `${this.name}.${propertyName} = (${nstemplate}(${arguVars})); // ${this.name}.${relatedPropertyName} = (${nametemplate}(${arguVars}))` return `_set(${this.name}, "${propertyName}", (${nstemplate}(${arguVars}))); _set(${this.name}, "${relatedPropertyName}", (${nametemplate}(${arguVars})))`; } else { // return `${this.name}.${propertyName} = ${targetVar}.getNamespace(); // ${this.name}.${relatedPropertyName} = ${targetVar}.name;` return `_set(${this.name}, "${propertyName}", ${targetVar}.getNamespace(), (updatedObj) => { ${this.name} = updatedObj; }); _set(${this.name}, "${relatedPropertyName}", ${targetVar}.name, (updatedObj) => { ${this.name} = updatedObj; });`; } }); } genModule() { return this.modules.map((meta) => { const { name, belongs, data } = meta; return `_addModule(app, "${name}", "${belongs}", ${JSON.stringify(data)});`; }); } genTemplateBind() { return this.templatebinds.map((meta) => { const { propertyName, relatedVar, relatedProperty } = meta; return `_set(${this.name}, "${propertyName}", ${relatedVar}.${relatedProperty})`; }); } } function autoScript(stack) { const createBlock = []; let rootBindBlock = []; let bindBlock = []; let rolebindBlock = []; let appBindBlock = []; const nameBlock = []; let calleeBlock = []; let moduleBlock = []; let returnBlock = []; let roleNASL = []; let templateBlock = []; stack.forEach((temp) => { createBlock.push(temp.genCreate()); if (temp.isRoot) { rootBindBlock = rootBindBlock.concat(temp.genEntryBind()); returnBlock = returnBlock.concat(temp.genRootReturn()); } if (temp.node.concept === 'Role') { roleNASL = roleNASL.concat(temp.node._toJSON((source) => (0, lodash_1.omit)(source, utils_1.IGNORE_PROPERTY))); } rolebindBlock = rolebindBlock.concat(temp.genRoleBind()); bindBlock = bindBlock.concat(temp.genBind()); appBindBlock = (0, lodash_1.uniq)(appBindBlock.concat(temp.genRootBind())); nameBlock.push(temp.genName()); calleeBlock = calleeBlock.concat(temp.genCallee()); moduleBlock = moduleBlock.concat(temp.genModule()); templateBlock = templateBlock.concat(temp.genTemplateBind()); }); const ideVersion = window.globalData.ideVersion; return ` (function () { const injectModule = {}; const exportRoles = function() { return ${JSON.stringify(roleNASL)}; } const execTemplate = function(app, frontend, getCtor, getCMeta, base, rootBindCallback, roleCallback, finalCallback) { let _templateObjects = []; const { _set, _push, _create, _addModule, _bindRoles, } = injectModule.operators; const _uniqueName = new injectModule.uniqueName(); _uniqueName.initAppUniqueNames(app, frontend); app.emit('collect:start', { actionMsg: '导入页面模板' }); /*---- create ---- */ ${createBlock.join('\n\t\t')} /*---- bind ---- */ ${bindBlock.join('\n\t\t')} /*---- reset name ---- */ ${nameBlock.join('\n\t\t')} /*--- root bind ---*/ ${rootBindBlock.join('\n\t\t')} /*---- appbind ---- */ ${appBindBlock.join('\n\t\t')} /*--- role bind ---*/ ${rolebindBlock.join('\n\t\t')} /*---- reset callee ---- */ ${calleeBlock.join('\n\t\t')} /*--- template bind ---- */ ${templateBlock.join('\n\t\t')} /*---- add module ----*/ ${moduleBlock.join('\n\t\t')} /*--- final callback ---*/ if(finalCallback) { finalCallback(_templateObjects) } app.emit('collect:end'); /*---- return root -----*/ ${returnBlock.join('\n\t\t')} } return { version: '${ideVersion}', execTemplate, exportRoles, importModule(key, m) { injectModule[key] = m; injectModule[key].templateVersion = '${ideVersion}' }, } })();`; } const i = 0; function autoTemplate(node) { const visitedMap = new WeakMap(); const stack = []; const startNode = node; let rootNode = true; const finalOps = []; function iterator(node) { if (node && !visitedMap.has(node)) { const meta = new TemplateMeta(node); if (rootNode) { meta.isRoot = true; } rootNode = false; stack.push(meta); visitedMap.set(node, meta); (0, utils_1.tracking)(node, startNode, (type, propertyName, property, options = {}) => { const { rootNode, calleeNode, relatedPropertyName, AppPropertyName, metaNodes } = options; switch (type) { case utils_1.TRACK_TYPE.PLAIN: meta.addPlainBinds(propertyName, property); break; case utils_1.TRACK_TYPE.PROPERTY: case utils_1.TRACK_TYPE.ARRAY: iterator(property); const pmeta = visitedMap.get(property); meta.addBinds(type, propertyName, pmeta); break; case utils_1.TRACK_TYPE.ARRAY_NO_FURTHER: finalOps.push(() => { const pmeta = visitedMap.get(property); if (pmeta) { meta.addBinds(utils_1.TRACK_TYPE.ARRAY, propertyName, pmeta); } }); break; case utils_1.TRACK_TYPE.CALLEE: iterator(rootNode); iterator(calleeNode); const cmeta = visitedMap.get(calleeNode); if (AppPropertyName) { meta.addRootBinds(AppPropertyName, visitedMap.get(rootNode)); } meta.addCallee(propertyName, relatedPropertyName, cmeta); break; case utils_1.TRACK_TYPE.MODULE: meta.addModule(property); break; case utils_1.TRACK_TYPE.CALLEE_TEMPLATE: const { nstemplate, nametemplate } = options; metaNodes.forEach((n) => { iterator(n); }); const arguVars = metaNodes.map((n) => visitedMap.get(n).name).join(','); if (AppPropertyName) { meta.addRootBinds(AppPropertyName, visitedMap.get(rootNode)); } meta.addCalleeTemplate(propertyName, relatedPropertyName, nstemplate, nametemplate, arguVars); break; case utils_1.TRACK_TYPE.ROLE_TEMPLATE: const roleMetaNames = []; metaNodes.forEach((node) => { iterator(node); const m = visitedMap.get(node); m.addRootBinds('roles', m); roleMetaNames.push(m.name); }); meta.addRoleTemplate(propertyName, roleMetaNames); break; case utils_1.TRACK_TYPE.PROPERTY_TEMPLATE: const relatedProperty = options.relatedProperty; const getRelatedVar = options.getRelatedVar; const t = getRelatedVar(); if (t) { iterator(t); const relatedMeta = visitedMap.get(t); meta.addTemplateBind(propertyName, relatedMeta.name, relatedProperty); } break; default: break; } }); return meta; } else if (node) { return visitedMap.get(node); } else { return null; } } iterator(node); finalOps.forEach((f) => { f(); }); return autoScript(stack); } exports.autoTemplate = autoTemplate; /* 使用模板的代码 */ /* const view = this.view; const app = view.rootNode; applyTemplate(script, app, (rootNode) => { const names = app.getViewExistingNames(); if(names.includes(rootNode.name)) { const name = app.getViewUniqueName(); rootNode.name = name; } app.addView(rootNode); }) */ function getRoles(script) { const { exportRoles } = eval(script); return exportRoles(); } exports.getRoles = getRoles; function applyTemplate(script, app, frontend, rootBindCallback, roleCallback, finalCallback) { operators_1.ops.upgraders.forEach((upgrader) => upgrader.replace && (script = upgrader.replace(script))); const { execTemplate, importModule } = eval(script); // 为了兼容 2.11 老模板 if (importModule) { importModule('operators', operators_1.ops); importModule('uniqueName', uniqueName_1.uniqueName); } execTemplate(app, frontend, nasl_concepts_1.getConceptConstructor, nasl_concepts_1.getConceptMeta, nasl_concepts_1.BaseNode, rootBindCallback, roleCallback, finalCallback); } exports.applyTemplate = applyTemplate; function applyDropComponent(app, frontend, view, element) { const { execTemplate, importModule } = myProcess_1.processComponent; // 为了兼容 2.11 老模板 if (importModule) { importModule('operators', operators_1.ComponentOps); importModule('uniqueName', uniqueName_1.componentUniqueName); } view.collectExistingViewElementName(); return execTemplate(app, frontend, view, element); } exports.applyDropComponent = applyDropComponent; //# sourceMappingURL=index.js.map