@lcap/nasl
Version:
NetEase Application Specific Language
442 lines (427 loc) • 17.2 kB
JavaScript
"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