Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
walkerwzy committed Sep 13, 2017
0 parents commit 4208b72
Show file tree
Hide file tree
Showing 11 changed files with 1,538 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
61 changes: 61 additions & 0 deletions .gitignore
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
28 changes: 28 additions & 0 deletions README.md
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)
169 changes: 169 additions & 0 deletions app.js
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);
}
}
Loading

0 comments on commit 4208b72

Please sign in to comment.