-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4208b72
Showing
11 changed files
with
1,538 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
output/ | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# 基本使用 | ||
|
||
``` | ||
./app.js -C aaa,bbb,ccc -K aaa,bbb,ccc -P aaa,bbb,ccc | ||
``` | ||
|
||
或 | ||
|
||
``` | ||
./app.js -c aaa -c bbb -k aaa -k bbb -p aaa -p ccc | ||
``` | ||
|
||
视参数多少自行使用, | ||
|
||
或者将带参数命令写入`run.sh`文件并执行该文件 | ||
|
||
# 参数介绍 | ||
|
||
+ 类名: 本次生成所需要用到的所有自定义类名, 请按文档顺序自上而下. 目前请保证参数个数与需要的个数一致, 用`-c`一次一个, 可重复, 或`-C`, 逗号分隔, 不支持空格 | ||
+ 基类名: 见示例. 目前只支持两个基类 `-b` | ||
+ 不处理的键: 跳过, 不写到文件, 如果有基类的情况, 适用此属性. `-p, -P` | ||
+ 子类对应的键: 如果该键对应的是一个对象或对象数组, 请传入键名. `-k, -K` | ||
|
||
请用`-h`命令查看更多帮助 | ||
|
||
# 模板介绍 | ||
|
||
模板文件用ES2015的模板字符串语法编写, 请参阅[文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
#!/usr/bin/env node | ||
|
||
let fs = require('fs-extra'), | ||
path = require('path'), | ||
program = require('commander'), | ||
cheerio = require('cheerio'), | ||
$; | ||
|
||
// 命令行参数 | ||
let collect = function(val, col) { | ||
col.push(val); | ||
return col; | ||
}; | ||
let batchCollect = function(val) { | ||
return val.split(','); | ||
}; | ||
program | ||
.version('0.0.1') | ||
.option('-f, --file [type]', 'set input file name','index.html') | ||
.option('-k, --datakeys [keys]', 'set data key names', collect, []) | ||
.option('-K, --batchdatakeys <key,key,key>', 'batch set data keys', batchCollect) | ||
.option('-b, --base [name]', 'set the base class names', collect, []) | ||
.option('-c, --classes [name]', 'set the sub class names', collect, []) | ||
.option('-C, --batchclasses <name,name,name>', 'batch set sub class names', batchCollect) | ||
.option('-p, --passkeys [key]', 'set exclued keys', collect, []) | ||
.option('-P, --batchpasskeys <key,key,key>', 'batch set exclued keys', batchCollect) | ||
.parse(process.argv); | ||
|
||
let baseClasses = program.base.length || ['PMLResponseBaseHD', 'PMLModelBase'], | ||
classCollect = program.classes.length?program.classes : program.batchclasses||[], | ||
dataKeys = program.datakeys.length?program.datakeys : program.batchdatakeys||[], | ||
passKeys = program.passkeys.length?program.passkeys : program.batchpasskeys||[], | ||
nameFactory = classNameGenerator(); | ||
dataKeys.push('data'); // 添加一个默认的 data 键, 要通用性的话, 这里不应该加 | ||
(async () => { | ||
let content = await readFile(program.file), | ||
$ = cheerio.load(content), | ||
contentJSON = []; | ||
await $(".wiki-content>.table-wrap").each(async (i, table) => { | ||
if(i%2 == 0) return; | ||
processTable(table); | ||
}); | ||
await fs.writeJson('./output.json', contentJSON); // for test | ||
await parseTemplate(contentJSON); | ||
console.log("done!"); | ||
|
||
function processTable(table, classMeta) { | ||
let modelName = "", | ||
baseName = baseClasses[0], | ||
isRoot = true; // 子类如果需要继承不同的基类, 则利用此标识 | ||
if(classMeta) { | ||
// 有classMeta, 说明是一个子类 | ||
modelName = classMeta["model"]; | ||
baseName = baseClasses[1]; | ||
isRoot = false; | ||
}else{ | ||
modelName = nameFactory.next().value; | ||
} | ||
let fileName_h = modelName + ".h", | ||
fileName_m = modelName + ".m", | ||
rowIsTable = false, | ||
props = [], | ||
complexProperty; // 如果当前行表示是个对象或数据, 把元数据保存, 用来生成子表格对应的类 | ||
$(table).children(".confluenceTable").children("tbody").children("tr") | ||
.each(async (i,tr) => { | ||
if(rowIsTable){ | ||
// 进入这个方法,说明上一行标识这一行是子类 | ||
rowIsTable = false; | ||
return processTable($(tr).children("td").children(".table-wrap"), complexProperty); | ||
} | ||
let tds = $(tr).children('td'); | ||
let nameMatch = /[a-z]+/ig.exec(tds.eq(0).text()); | ||
if(!nameMatch) return; // 非英文则理解为不是属性名 | ||
if(passKeys.indexOf(nameMatch[0])>=0) return; // 包含预设排除关键字, 不需要处理 | ||
let isComplexObj = dataKeys.indexOf(nameMatch[0])>=0; // 包含预设子类关键字, 理解为复杂对象 | ||
// 记录属性名, 类型, 注释等 | ||
let pname = tds.eq(0).text().trim(); | ||
let ptype = tds.eq(2).text().trim(); | ||
let isArray = ptype.toLowerCase() == 'list'; | ||
if(isComplexObj) ptype = nameFactory.next().value; | ||
let assume_type = assumeVarType(ptype, isArray, ptype); | ||
let prop = { | ||
"name": pname, | ||
"des": tds.eq(1).text(), | ||
"type": assume_type[0], | ||
"isArray": isArray | ||
}; | ||
if(tds.eq(3).text().trim()) { | ||
prop["des"] = prop["des"] + " " + tds.eq(3).text(); | ||
} | ||
if(isComplexObj){ | ||
prop["model"] = assume_type[1]; | ||
rowIsTable = true; | ||
complexProperty = prop; | ||
} | ||
props.push(prop); | ||
}); // end of basetable > tr > foreach | ||
contentJSON.push({"isRoot": isRoot, "className": modelName,"baseName": baseName, "props": props}); | ||
console.log("生成模型:", modelName) | ||
} | ||
})(); | ||
|
||
|
||
// 类名生成器 | ||
function* classNameGenerator() { | ||
yield* classCollect; | ||
} | ||
|
||
async function readFile(filename) { | ||
let fullpath = path.join(__dirname, filename); | ||
console.log('start processing file:', fullpath); | ||
return await fs.readFile(fullpath, 'utf8') | ||
.catch(console.log); | ||
} | ||
|
||
async function createFile(filename) { | ||
let fullpath = path.join(__dirname, filename), | ||
stat = await fs.stat(fullpath).catch(e=>{ | ||
console.log('create file', fullpath); | ||
}); | ||
await fs.writeFile(fullpath, 'hey there') | ||
.catch(console.log); | ||
} | ||
|
||
/** | ||
* 根据关键字推断类型 | ||
* @prarm str: 关键字 | ||
* @param isArray: 是否数组类型 | ||
* @param model: 自定义类型 | ||
* @return 返回[变量类型, 模型类型] | ||
* 比如 [NSArray<Doctor *> *, Doctor *] | ||
* 一个用于建模, 一个用于写属性 | ||
*/ | ||
function assumeVarType(str, isArray, model) { | ||
let l_str = str.toLowerCase(), | ||
model_type = str, // 类型 | ||
var_type = str; // 字段 | ||
if(l_str.indexOf('string') >= 0) model_type = "NSString *"; | ||
else if(['int', 'integer', 'long'].findIndex(v=>(new RegExp(v,'ig')).test(l_str)) >= 0) model_type = "NSInteger"; | ||
else { | ||
console.log("====undefined type: =====", str); | ||
model_type = model + " *"; | ||
} | ||
var_type = isArray ? "NSArray<"+model_type+"> *" : model_type;; | ||
model_type = model_type.replace(' *',''); | ||
return [var_type, model_type]; | ||
} | ||
|
||
async function parseTemplate(data) { | ||
console.log("开始应用模板"); | ||
// 暂时不支持别的语言, 为本项目使用(3个模板文件) | ||
// 以后要优化则要根据模板文件的个数有所个性化 | ||
let copyright = "民康", | ||
projectname = "项目名", | ||
date = (new Date()).toLocaleDateString(), | ||
author = "walker", | ||
// 模板内容 | ||
h_content = await fs.readFile(path.join(__dirname, 'template.h'), 'utf8').catch(console.log), | ||
m_content1 = await fs.readFile(path.join(__dirname, 'template.m'), 'utf8').catch(console.log), | ||
m_content2 = await fs.readFile(path.join(__dirname, 'templatebase.m'), 'utf8').catch(console.log); | ||
for(let model of data) { | ||
let m_content = model.isRoot ? m_content2 : m_content1; | ||
// 输出路径 | ||
let h_file = path.join(__dirname, 'output', model.className+'.h'), | ||
m_file = path.join(__dirname, 'output', model.className+'.m'); | ||
await fs.writeFile(h_file, eval(h_content), 'utf8').catch(console.log); | ||
await fs.writeFile(m_file, eval(m_content), 'utf8').catch(console.log); | ||
} | ||
} |
Oops, something went wrong.