Merge branch 'excel-exporter' of https://github.com/Tiny-Fun-Technologies/excel-exporter into excel-exporter

This commit is contained in:
2020-07-24 15:13:06 +08:00
5 changed files with 131 additions and 7 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
dist/
output/
node_modules/
yarn.lock
package-lock.json

View File

@@ -5,7 +5,7 @@
## 支持将Excel配置表导出为:
- [x] JSON 文件
- [x] C# 类型声明
- [ ] TypeScript 声明文件、类型文件(可用 `instanceof` 进行类型检查)
- [x] TypeScript interface类型声明、class类型定义(可用 `instanceof` 进行类型检查)
- [ ] Godot 引擎的 GDScript 脚本文件
## 表格格式说明
@@ -42,8 +42,7 @@ npm run build
```json
{
"input": [
{ "file": "装备表.xlsx", "encode": "GBK"},
{ "file": "关卡表.xlsx", "encode": "GBK"},
{ "file": "配置表.xlsx", "encode": "GBK"}
],
"parser": {
"first_row_as_field_comment": true
@@ -51,16 +50,25 @@ npm run build
"output": {
"json": {
"enabled": true,
"directory": "../../client/Assets/Resources/data/json",
"directory": "output/json",
"indent": "\t"
},
"csharp": {
"enabled": true,
"directory": "../../client/Assets/Resources/data/csharp",
"directory": "output/csharp",
"namespace": "game.data",
"base_type": "tiny.data.UniqueIDObject",
"file_name": "data",
"ignore_id": true
},
"typescript": {
"enabled": true,
"declaration": false,
"type": "class",
"class_name_prefix": "",
"class_name_extension": "Data",
"directory": "output/typescript",
"file_name": "data"
}
}
}

View File

@@ -8,16 +8,25 @@
"output": {
"json": {
"enabled": true,
"directory": "../../client/Assets/Resources/data/json",
"directory": "output/json",
"indent": "\t"
},
"csharp": {
"enabled": true,
"directory": "../../client/Assets/Resources/data/csharp",
"directory": "output/csharp",
"namespace": "game.data",
"base_type": "tiny.data.UniqueIDObject",
"file_name": "data",
"ignore_id": true
},
"typescript": {
"enabled": true,
"declaration": false,
"type": "class",
"class_name_prefix": "",
"class_name_extension": "Data",
"directory": "output/typescript",
"file_name": "data"
}
}
}

View File

@@ -4,6 +4,7 @@ import { ExporterConfigs, TableExporter } from "./TableExporter";
import { JSONExporter } from "./exporters/JSONExporter";
import { CSharpExporter } from "./exporters/CSharpExporter";
import * as colors from "colors";
import { TypeScriptExporter } from "./exporters/TypeScriptExporter";
export interface Configurations {
/** 解析配置 */
@@ -18,6 +19,7 @@ export interface Configurations {
const exporters: {[key:string]: new(config: ExporterConfigs) => TableExporter } = {
json: JSONExporter,
csharp: CSharpExporter,
typescript: TypeScriptExporter,
}

View File

@@ -0,0 +1,104 @@
import { TableExporter, ExporterConfigs } from "excel-exporter/TableExporter";
import { TableData, DataType } from "excel-exporter/TableParser";
import * as colors from "colors";
import { path } from "tiny/path";
interface TypeScriptExporterConfigs extends ExporterConfigs {
type: "interface" | "class",
declaration: boolean,
file_name: string,
class_name_prefix: string,
class_name_extension: string,
}
export class TypeScriptExporter extends TableExporter {
classes: string[] = [];
constructor(configs: TypeScriptExporterConfigs) {
super(configs);
configs.class_name_prefix = configs.class_name_prefix || "";
configs.class_name_extension = configs.class_name_extension || "";
}
export (name: string, table: TableData) {
this.export_table(
name,
table,
(this.configs as TypeScriptExporterConfigs).type,
(this.configs as TypeScriptExporterConfigs).declaration,
);
}
protected export_table(name: string, table: TableData, export_type: "class" | "interface", declaration: boolean) {
let configs = (this.configs as TypeScriptExporterConfigs);
let class_name = `${configs.class_name_prefix}${name}${configs.class_name_extension}`;
let body = "";
for (const field of table.headers) {
let type = "any";
switch (field.type) {
case DataType.bool:
type = "boolean";
case DataType.string:
type = "string";
break;
case DataType.float:
case DataType.int:
type = "number";
break;
default:
type = "any";
break;
}
if (field.is_array) {
type += "[]";
}
if (field.comment) {
if (field.comment.trim().length) {
let comments = field.comment.split("\n");
if (comments.length > 1) {
body += this.line("/** ", 1);
for (const comment of comments) {
body += this.line(" * " + comment.trim() + " ", 1);
}
body += this.line(" */", 1);
} else {
body += this.line(`/** ${comments[0].trim()} */`, 1);
}
}
}
body += this.line(`${field.name}: ${type};`, 1);
}
if (export_type == "class" && !declaration) {
body += this.line();
body += this.line(`static $bind_rows(rows: object[]) {`, 1);
body += this.line(`for (const row of rows) {`, 2);
body += this.line(`Object.setPrototypeOf(row, ${class_name}.prototype);`, 3);
body += this.line("}", 2);
body += this.line("}", 1);
}
let export_method = declaration ? "declare" : "export";
let class_text = this.line(`${export_method} ${export_type} ${class_name} {\n${body}\n}`);
this.classes.push(class_text);
}
finalize() {
let configs = (this.configs as TypeScriptExporterConfigs);
const extension = configs.declaration ? ".d.ts" : ".ts";
let class_text = this.line("// Tool generated file DO NOT MODIFY");
class_text += this.line();
for (const cls of this.classes) {
class_text += cls;
class_text += this.line();
}
let file = path.join(this.configs.directory, (this.configs as TypeScriptExporterConfigs).file_name);
if (!file.endsWith(extension)) {
file += extension;
}
this.save_text(file, class_text);
console.log(colors.green(`\t${file}`));
}
}