Compare commits
12 Commits
10341ed46a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b6b4383569 | |||
| d130ad1838 | |||
| b225dbe90c | |||
| 98f7f074cf | |||
| 592115c8f0 | |||
| 89fed62dcc | |||
| dac89497d0 | |||
| a799681194 | |||
| 14c8a3b910 | |||
| 2a9d9609ab | |||
| b7b4ab9ad1 | |||
| 1c9744eba6 |
@@ -1,8 +1,16 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = false
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{yml,yaml,tiny,yaml.txt,html}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|||||||
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -14,7 +14,8 @@
|
|||||||
"webpack:///./*": "${workspaceRoot}/*",
|
"webpack:///./*": "${workspaceRoot}/*",
|
||||||
"webpack:///*": "*"
|
"webpack:///*": "*"
|
||||||
},
|
},
|
||||||
"cwd": "D:/work/repositories/zombie/config/新配表",
|
"cwd": "C:/Users/Geequlim/Desktop/sheet",
|
||||||
|
// "cwd": "D:/work/repositories/zombie/config/新配表",
|
||||||
// "cwd": "${workspaceFolder}",
|
// "cwd": "${workspaceFolder}",
|
||||||
"program": "${workspaceFolder}/dist/binary.js",
|
"program": "${workspaceFolder}/dist/binary.js",
|
||||||
"args": [
|
"args": [
|
||||||
|
|||||||
29
.vscode/settings.json
vendored
Normal file
29
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.tiny": "yaml",
|
||||||
|
"*.yaml.txt": "yaml",
|
||||||
|
"*.js.txt": "javascript",
|
||||||
|
"*.meta": "yaml",
|
||||||
|
"*.manifest": "yaml",
|
||||||
|
"*.asset": "yaml",
|
||||||
|
"project.tiny": "yaml"
|
||||||
|
},
|
||||||
|
"files.exclude": {
|
||||||
|
"Library": true,
|
||||||
|
"Logs": true,
|
||||||
|
"Temp": true,
|
||||||
|
"**/*.meta": true,
|
||||||
|
"Packages/packages-lock.json": true,
|
||||||
|
".temp": true,
|
||||||
|
"UI/.objs": true,
|
||||||
|
"yarn.lock": true,
|
||||||
|
"TextToolDatas": true,
|
||||||
|
"ProjectSettings": true,
|
||||||
|
"UserSettings": true,
|
||||||
|
"node_modules": true,
|
||||||
|
"qrcodes": true,
|
||||||
|
"obj": true,
|
||||||
|
"*.csproj": true,
|
||||||
|
"*.sln": true
|
||||||
|
},
|
||||||
|
}
|
||||||
70
README.md
70
README.md
@@ -3,11 +3,11 @@
|
|||||||
将 Excel 配置表中的数据导出为方便程序读取和使用的数据。
|
将 Excel 配置表中的数据导出为方便程序读取和使用的数据。
|
||||||
|
|
||||||
## 支持将Excel配置表导出为:
|
## 支持将Excel配置表导出为:
|
||||||
- [x] JSON 文件
|
- [x] JSON 数据文件
|
||||||
- [x] YAML 文件
|
- [x] YAML 数据文件
|
||||||
- [x] C# 类型声明
|
- [x] C# 类型声明
|
||||||
- [x] TypeScript interface类型声明、class类型定义(可用 `instanceof` 进行类型检查)
|
- [x] TypeScript interface类型声明、class类型定义(可用 `instanceof` 进行类型检查)
|
||||||
- [ ] Godot 引擎的 GDScript 脚本文件
|
- [x] 能够扩展导出其他数据格式和代码声明
|
||||||
|
|
||||||
## 表格格式说明
|
## 表格格式说明
|
||||||
|
|
||||||
@@ -15,15 +15,46 @@
|
|||||||
* 表名为 `@skip` 或以 `@skip` 开头的表会被忽略,不会导出数据文件
|
* 表名为 `@skip` 或以 `@skip` 开头的表会被忽略,不会导出数据文件
|
||||||
* 第一列值为 `@skip` 的行会被忽略,视为无效数据行
|
* 第一列值为 `@skip` 的行会被忽略,视为无效数据行
|
||||||
* 整行所有列为空的行会被忽略,视为无效数据行
|
* 整行所有列为空的行会被忽略,视为无效数据行
|
||||||
* 每张表的**第一个有效数据行**用作字段名,决定了导出数据所拥有的属性,**字段名必须符合标识符命名规范**
|
* 第一列名为`@field`的行用作字段名,决定了导出数据所拥有的属性,**字段名必须符合标识符命名规范**;该行中不填名称的列视为空字段,该列的数据在导出时会被忽略,可以用于辅助数据列
|
||||||
* 字段名所在的行中不填名称的列视为空字段,该列的数据在导出时会被忽略
|
* 第一列名为`@comment`的行用作字段注释文档,用于描述其底下对应的字段
|
||||||
* 相同名称的字段导出时会被合并为数组
|
* 相同名称的字段导出时会被合并为数组
|
||||||
* 导出属性的数据类型由**整列所填写的数据类型**决定,支持以下数据类型
|
* 导出属性的数据类型由**整列所填写的数据类型**决定,支持以下数据类型
|
||||||
* 字符串
|
* 字符串
|
||||||
* 数值(优先使用整形)
|
* 数值(优先使用整形)
|
||||||
* 布尔值
|
* 布尔值
|
||||||
* 空(`null`)
|
* 空(`null`)
|
||||||
* 该工具设计原则是简单易用,表格字段可由策划自由调整,不支持数据引用,暂不支持结构体
|
* 该工具设计原则是简单易用,表格字段可由策划自由调整,不支持数据引用
|
||||||
|
|
||||||
|
### 表格式示例
|
||||||
|

|
||||||
|
以 TypeScript 为例,上图所示的表格将被导出为下面的数据格式,每行数据可被表示为一个 `EffectSequenceData` 类型的对象
|
||||||
|
```ts
|
||||||
|
export class EffectSequenceData {
|
||||||
|
readonly id: number;
|
||||||
|
/** 关键帧 */
|
||||||
|
readonly frames: readonly {
|
||||||
|
/** 时间 */
|
||||||
|
readonly time: number;
|
||||||
|
/** 事件 */
|
||||||
|
readonly event: string;
|
||||||
|
/** 特效 */
|
||||||
|
readonly effect: string;
|
||||||
|
/** 音效 */
|
||||||
|
readonly audio: string;
|
||||||
|
}[];
|
||||||
|
/** 动作 */
|
||||||
|
readonly animation: string;
|
||||||
|
/** 时长 */
|
||||||
|
readonly length: number;
|
||||||
|
|
||||||
|
static $bind_rows(rows: object[]) {
|
||||||
|
for (const row of rows) {
|
||||||
|
Object.setPrototypeOf(row, EffectSequenceData.prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
- 安装 NodeJS 和 NPM, 注意将 Node 和 NPM 添加到环境变量 `PATH` 中
|
- 安装 NodeJS 和 NPM, 注意将 Node 和 NPM 添加到环境变量 `PATH` 中
|
||||||
@@ -41,33 +72,28 @@ npm run build
|
|||||||
### 配置示例
|
### 配置示例
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
parser:
|
|
||||||
first_row_as_field_comment: true
|
|
||||||
input:
|
input:
|
||||||
- file: 配置表.xlsx
|
- 特效表.xlsx
|
||||||
encode: GBK
|
parser:
|
||||||
|
first_column_as_id: true # 第一列用作 ID 列
|
||||||
|
constant_array_length: [
|
||||||
|
# 这里填入需要固定数组长度的表名称
|
||||||
|
]
|
||||||
output:
|
output:
|
||||||
json:
|
json:
|
||||||
enabled: true
|
enabled: false
|
||||||
directory: output/json
|
directory: "../../project/Assets/res/data/excel"
|
||||||
indent: "\t"
|
indent: "\t"
|
||||||
yaml:
|
yaml:
|
||||||
enabled: true
|
enabled: true
|
||||||
directory: output/yaml
|
directory: "../../project/Assets/res/data/excel"
|
||||||
indent: 2
|
indent: 2
|
||||||
csharp:
|
|
||||||
enabled: true
|
|
||||||
directory: output/csharp
|
|
||||||
namespace: game.data
|
|
||||||
base_type: tiny.data.UniqueIDObject
|
|
||||||
file_name: data
|
|
||||||
ignore_id: true
|
|
||||||
typescript:
|
typescript:
|
||||||
enabled: true
|
enabled: true
|
||||||
declaration: false
|
declaration: false
|
||||||
type: class
|
type: class
|
||||||
class_name_prefix: ''
|
class_name_prefix: ''
|
||||||
class_name_extension: Data
|
class_name_extension: Data
|
||||||
directory: output/typescript
|
directory: "../../project/Scripts/src/game/configs"
|
||||||
file_name: data
|
file_name: excel
|
||||||
```
|
```
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
input:
|
input:
|
||||||
- 配置表.xlsx
|
# - 配置表.xlsx
|
||||||
|
- 车辆.xlsx
|
||||||
parser:
|
parser:
|
||||||
first_column_as_id: true # 第一列用作 ID 列
|
first_column_as_id: true # 第一列用作 ID 列
|
||||||
constant_array_length: [
|
constant_array_length: [
|
||||||
# 这里填入需要固定数组长度的表名称
|
# 这里填入需要固定数组长度的表名称
|
||||||
]
|
]
|
||||||
|
|
||||||
output:
|
output:
|
||||||
json:
|
json:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -14,13 +16,6 @@ output:
|
|||||||
enabled: true
|
enabled: true
|
||||||
directory: output/yaml
|
directory: output/yaml
|
||||||
indent: 2
|
indent: 2
|
||||||
csharp:
|
|
||||||
enabled: true
|
|
||||||
directory: output/csharp
|
|
||||||
namespace: game.data
|
|
||||||
base_type: tiny.data.UniqueIDObject
|
|
||||||
file_name: data
|
|
||||||
ignore_id: true
|
|
||||||
typescript:
|
typescript:
|
||||||
enabled: true
|
enabled: true
|
||||||
declaration: false
|
declaration: false
|
||||||
@@ -28,4 +23,7 @@ output:
|
|||||||
class_name_prefix: ''
|
class_name_prefix: ''
|
||||||
class_name_extension: Data
|
class_name_extension: Data
|
||||||
directory: output/typescript
|
directory: output/typescript
|
||||||
file_name: data
|
file_name: data
|
||||||
|
|
||||||
|
override:
|
||||||
|
车辆/Vehicle: output/车辆/Vehicle
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"js-yaml": "^3.14.0",
|
"js-yaml": "^3.14.0",
|
||||||
|
"source-map-support": "^0.5.21",
|
||||||
"xlsx": "^0.16.0"
|
"xlsx": "^0.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
project.tiny
Normal file
10
project.tiny
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
develop:
|
||||||
|
actions:
|
||||||
|
- name: dev
|
||||||
|
title: 脚本编译服务
|
||||||
|
description: 脚本编译服务
|
||||||
|
command: yarn dev
|
||||||
|
- name: test
|
||||||
|
title: 单元测试
|
||||||
|
description: 单元测试
|
||||||
|
command: node ./dist/binary.js ./excel-exporter.yaml
|
||||||
BIN
screentshot-sheet-example.png
Normal file
BIN
screentshot-sheet-example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
@@ -2,25 +2,28 @@ import { FileAccess, ModeFlags } from "tiny/io";
|
|||||||
import { ParserConfigs, TableParser, TableData } from "./TableParser";
|
import { ParserConfigs, TableParser, TableData } from "./TableParser";
|
||||||
import { ExporterConfigs, TableExporter } from "./TableExporter";
|
import { ExporterConfigs, TableExporter } from "./TableExporter";
|
||||||
import { JSONExporter } from "./exporters/JSONExporter";
|
import { JSONExporter } from "./exporters/JSONExporter";
|
||||||
import { CSharpExporter } from "./exporters/CSharpExporter";
|
|
||||||
import * as colors from "colors";
|
import * as colors from "colors";
|
||||||
import { TypeScriptExporter } from "./exporters/TypeScriptExporter";
|
import { TypeScriptExporter } from "./exporters/TypeScriptExporter";
|
||||||
import * as yaml from "js-yaml";
|
import * as yaml from "js-yaml";
|
||||||
import { YAMLExporter } from "./exporters/YAMLExporter";
|
import { YAMLExporter } from "./exporters/YAMLExporter";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
export interface Configurations {
|
export interface Configurations {
|
||||||
/** 解析配置 */
|
/** 解析配置 */
|
||||||
parser?: ParserConfigs,
|
parser?: ParserConfigs,
|
||||||
/** 要读取的 XLSL 文档 */
|
/** 要读取的 XLSL 文档 */
|
||||||
input: {"file": string, encode: string}[],
|
input: string[],
|
||||||
/** 导出配置 */
|
/** 导出配置 */
|
||||||
output: { [key: string]: ExporterConfigs }
|
output: {
|
||||||
|
[key: string]: ExporterConfigs,
|
||||||
|
}
|
||||||
|
override?: Record<string, string>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const exporters: {[key:string]: new(config: ExporterConfigs) => TableExporter } = {
|
const exporters: {[key:string]: new(config: ExporterConfigs) => TableExporter } = {
|
||||||
json: JSONExporter,
|
json: JSONExporter,
|
||||||
csharp: CSharpExporter,
|
|
||||||
typescript: TypeScriptExporter,
|
typescript: TypeScriptExporter,
|
||||||
yaml: YAMLExporter,
|
yaml: YAMLExporter,
|
||||||
}
|
}
|
||||||
@@ -53,8 +56,14 @@ export class ExcelExporterApplication {
|
|||||||
for (const file of this.configs.input) {
|
for (const file of this.configs.input) {
|
||||||
console.log(colors.grey(`解析配表文件: ${file}`));
|
console.log(colors.grey(`解析配表文件: ${file}`));
|
||||||
let sheets = this.parser.parse_xlsl(file);
|
let sheets = this.parser.parse_xlsl(file);
|
||||||
|
const base = path.basename(file).replace(/\.xlsx?$/, '');
|
||||||
for (const name in sheets) {
|
for (const name in sheets) {
|
||||||
this.tables[name] = sheets[name];
|
const table = sheets[name];
|
||||||
|
if (this.configs.override) {
|
||||||
|
const override = this.configs.override[`${base}/${name}`];
|
||||||
|
table.output = override;
|
||||||
|
}
|
||||||
|
this.tables[name] = table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(colors.green(`解析所有配表文件完成`));
|
console.log(colors.green(`解析所有配表文件完成`));
|
||||||
@@ -66,11 +75,22 @@ export class ExcelExporterApplication {
|
|||||||
if (exporter.configs.enabled) {
|
if (exporter.configs.enabled) {
|
||||||
console.log(colors.white(`执行 ${exporter.name} 导出:`));
|
console.log(colors.white(`执行 ${exporter.name} 导出:`));
|
||||||
for (const name in this.tables) {
|
for (const name in this.tables) {
|
||||||
exporter.export(name, this.tables[name]);
|
const table = this.tables[name];
|
||||||
|
const data = exporter.export(name, table);
|
||||||
|
if (data) {
|
||||||
|
let file = path.join(exporter.configs.directory, `${name}.${exporter.extension}`);
|
||||||
|
if (table.output) {
|
||||||
|
file = table.output + `.${exporter.extension}`;
|
||||||
|
}
|
||||||
|
const dir = path.dirname(file);
|
||||||
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||||
|
fs.writeFileSync(file, data);
|
||||||
|
console.log(colors.white(`\t ${name} => ${file}`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exporter.finalize();
|
exporter.finalize();
|
||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { path } from "tiny/path";
|
|||||||
export interface ExporterConfigs {
|
export interface ExporterConfigs {
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
directory: string,
|
directory: string,
|
||||||
|
extension?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableExporter {
|
export class TableExporter {
|
||||||
@@ -15,7 +16,7 @@ export class TableExporter {
|
|||||||
this.configs = configs;
|
this.configs = configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
get extension(): string { return ''}
|
get extension(): string { return this.configs.extension || ''; }
|
||||||
|
|
||||||
protected line(text = "", indent = 0) {
|
protected line(text = "", indent = 0) {
|
||||||
return this.indent_text(text, indent) + '\n';
|
return this.indent_text(text, indent) + '\n';
|
||||||
@@ -44,8 +45,10 @@ export class TableExporter {
|
|||||||
* @param name 表名称
|
* @param name 表名称
|
||||||
* @param table 表数据
|
* @param table 表数据
|
||||||
*/
|
*/
|
||||||
export(name: string, table: TableData) { }
|
export(name: string, table: TableData): string | Buffer {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/** 全部配置表导出完毕后保存文件 */
|
/** 全部配置表导出完毕后保存文件 */
|
||||||
finalize() {}
|
finalize() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as xlsl from "xlsx";
|
import * as xlsl from "xlsx";
|
||||||
import { FileAccess, ModeFlags } from "tiny/io";
|
import { FileAccess, ModeFlags } from "tiny/io";
|
||||||
import * as colors from "colors";
|
import * as colors from "colors";
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
export enum Keywords {
|
export enum Keywords {
|
||||||
SKIP = '@skip',
|
SKIP = '@skip',
|
||||||
@@ -29,6 +30,12 @@ interface RawTableCell extends xlsl.CellObject {
|
|||||||
|
|
||||||
type RawTableData = RawTableCell[][];
|
type RawTableData = RawTableCell[][];
|
||||||
|
|
||||||
|
export interface TableData {
|
||||||
|
struct: Field;
|
||||||
|
data: {[key: string]: any}[];
|
||||||
|
output?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ParserConfigs {
|
export interface ParserConfigs {
|
||||||
/** 第一列作为ID */
|
/** 第一列作为ID */
|
||||||
first_column_as_id: boolean;
|
first_column_as_id: boolean;
|
||||||
@@ -52,6 +59,8 @@ export class Field {
|
|||||||
type?: DataType;
|
type?: DataType;
|
||||||
/** 保持数组长度和配置表中的列数量一致,没填的数据使用 null 填充 */
|
/** 保持数组长度和配置表中的列数量一致,没填的数据使用 null 填充 */
|
||||||
constant_array_length?: boolean;
|
constant_array_length?: boolean;
|
||||||
|
/** 所属字段 */
|
||||||
|
parent: Field;
|
||||||
|
|
||||||
/** 添加子字段 */
|
/** 添加子字段 */
|
||||||
add_field(field: Field) {
|
add_field(field: Field) {
|
||||||
@@ -126,11 +135,18 @@ export class Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (type === DataType.null) {
|
||||||
|
console.log(colors.red(`\t\t${name}(${xlsl.utils.encode_col(fields[0].columns.start)}列) 没有填入有效数据, 无法推断其数据类型`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const c of this.children) {
|
for (const c of this.children) {
|
||||||
c.constant_array_length = this.constant_array_length;
|
c.constant_array_length = this.constant_array_length;
|
||||||
|
c.parent = this;
|
||||||
c.build();
|
c.build();
|
||||||
|
if (c.type === DataType.null && !c._is_array) {
|
||||||
|
console.log(colors.red(`\t\t${c.name}(${xlsl.utils.encode_col(c.columns.start)}列) 没有填入有效数据, 无法推断其数据类型`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,17 +171,18 @@ export class Field {
|
|||||||
let obj = {};
|
let obj = {};
|
||||||
let isAllNullish = true;
|
let isAllNullish = true;
|
||||||
for (const c of this.children) {
|
for (const c of this.children) {
|
||||||
let value = c.parse_row(row);
|
const value = c.parse_row(row);
|
||||||
|
const is_null = this.check_is_null(row);
|
||||||
if (c.is_array) {
|
if (c.is_array) {
|
||||||
let arr: any[] = obj[c.name] || [];
|
let arr: any[] = obj[c.name] || [];
|
||||||
if (this.constant_array_length || value != null) {
|
if (this.constant_array_length || value !== null) {
|
||||||
arr.push(value);
|
arr.push(value);
|
||||||
}
|
}
|
||||||
obj[c.name] = arr;
|
obj[c.name] = arr;
|
||||||
} else {
|
} else {
|
||||||
obj[c.name] = value;
|
obj[c.name] = value;
|
||||||
}
|
}
|
||||||
isAllNullish = isAllNullish && value == null;
|
isAllNullish = isAllNullish && is_null;
|
||||||
}
|
}
|
||||||
return isAllNullish ? null : obj;
|
return isAllNullish ? null : obj;
|
||||||
}
|
}
|
||||||
@@ -174,7 +191,7 @@ export class Field {
|
|||||||
protected get_cell_value(cell: RawTableCell, type: DataType) {
|
protected get_cell_value(cell: RawTableCell, type: DataType) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DataType.bool:
|
case DataType.bool:
|
||||||
return cell && cell.v as boolean == true;
|
return cell ? cell.v as boolean == true : false;
|
||||||
case DataType.int:
|
case DataType.int:
|
||||||
return cell ? cell.v as number : 0;
|
return cell ? cell.v as number : 0;
|
||||||
case DataType.float:
|
case DataType.float:
|
||||||
@@ -185,26 +202,22 @@ export class Field {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const TypeCompatibility = {
|
protected check_is_null(row: RawTableCell[]): boolean {
|
||||||
string: 5,
|
if (this.children) {
|
||||||
float: 4,
|
let isAllNullish = true;
|
||||||
int: 3,
|
for (const c of this.children) {
|
||||||
bool: 2,
|
isAllNullish = isAllNullish && c.check_is_null(row);
|
||||||
null: 1
|
if (!isAllNullish) {
|
||||||
};
|
return false;
|
||||||
|
}
|
||||||
export interface ColumnDescription {
|
}
|
||||||
type: DataType;
|
return isAllNullish;
|
||||||
name: string;
|
} else {
|
||||||
is_array?: boolean;
|
let cell = row[this.columns.start];
|
||||||
comment?: string;
|
return !cell || cell.t === 'z';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
export interface TableData {
|
|
||||||
struct: Field;
|
|
||||||
data: {[key: string]: any}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableParser {
|
export class TableParser {
|
||||||
@@ -219,8 +232,8 @@ export class TableParser {
|
|||||||
return this.load_raw_xlsl_data(path);
|
return this.load_raw_xlsl_data(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected load_raw_xlsl_data(path: string): { [key: string]: TableData } {
|
protected load_raw_xlsl_data(filePath: string): { [key: string]: TableData } {
|
||||||
var file = FileAccess.open(path, ModeFlags.READ);
|
var file = FileAccess.open(filePath, ModeFlags.READ);
|
||||||
let wb = xlsl.read(file.get_as_array());
|
let wb = xlsl.read(file.get_as_array());
|
||||||
file.close();
|
file.close();
|
||||||
let raw_tables: {[key: string]: RawTableData } = {};
|
let raw_tables: {[key: string]: RawTableData } = {};
|
||||||
@@ -433,4 +446,4 @@ export class TableParser {
|
|||||||
protected format_cell_position(cell: RawTableCell): string {
|
protected format_cell_position(cell: RawTableCell): string {
|
||||||
return xlsl.utils.encode_cell({c: cell.column, r: cell.row});
|
return xlsl.utils.encode_cell({c: cell.column, r: cell.row});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { TableExporter, ExporterConfigs } from "excel-exporter/TableExporter";
|
|
||||||
import { TableData, DataType } from "excel-exporter/TableParser";
|
|
||||||
import { path } from "tiny/path";
|
|
||||||
import * as colors from "colors";
|
|
||||||
|
|
||||||
interface CSharpExporterConfigs extends ExporterConfigs {
|
|
||||||
namespace: string,
|
|
||||||
base_type: string,
|
|
||||||
file_name: string,
|
|
||||||
ignore_id: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CSharpExporter extends TableExporter {
|
|
||||||
protected declear_content = "";
|
|
||||||
protected classes: string[] = [];
|
|
||||||
get extension(): string { return 'cs' }
|
|
||||||
|
|
||||||
constructor(configs: ExporterConfigs) {
|
|
||||||
super(configs);
|
|
||||||
if ( typeof ((this.configs as CSharpExporterConfigs).namespace) != 'string') {
|
|
||||||
(this.configs as CSharpExporterConfigs).namespace = "game.data";
|
|
||||||
}
|
|
||||||
if ( typeof ((this.configs as CSharpExporterConfigs).base_type) != 'string') {
|
|
||||||
(this.configs as CSharpExporterConfigs).namespace = "object";
|
|
||||||
}
|
|
||||||
if ( typeof ((this.configs as CSharpExporterConfigs).file_name) != 'string') {
|
|
||||||
(this.configs as CSharpExporterConfigs).file_name = "data";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.declear_content += this.line("// Tool generated file DO NOT MODIFY");
|
|
||||||
this.declear_content += this.line("using System;");
|
|
||||||
this.declear_content += this.line();
|
|
||||||
this.declear_content += this.line("namespace " + (this.configs as CSharpExporterConfigs).namespace + " {")
|
|
||||||
this.declear_content += this.line("%CLASSES%");
|
|
||||||
this.declear_content += this.line("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
export(name: string, table: TableData) {
|
|
||||||
const base_type = (this.configs as CSharpExporterConfigs).base_type;
|
|
||||||
let body = "";
|
|
||||||
for (const field of table.headers) {
|
|
||||||
if (field.name == 'id' && (this.configs as CSharpExporterConfigs).ignore_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let type = "object";
|
|
||||||
switch (field.type) {
|
|
||||||
case DataType.bool:
|
|
||||||
case DataType.float:
|
|
||||||
case DataType.string:
|
|
||||||
case DataType.int:
|
|
||||||
type = field.type;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type = "object";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (field.is_array) {
|
|
||||||
type += "[]";
|
|
||||||
}
|
|
||||||
if (field.comment) {
|
|
||||||
let comment = field.comment.split("\r\n").join("\t");
|
|
||||||
comment = comment.split("\n").join("\t");
|
|
||||||
body += this.line(`/// <summary>${comment}</summary>`, 1);
|
|
||||||
}
|
|
||||||
body += this.line(`public ${type} ${field.name};`, 1);
|
|
||||||
}
|
|
||||||
let class_text = this.line(`public class ${name} : ${base_type} {\n${body}\n}`);
|
|
||||||
this.classes.push(class_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
finalize() {
|
|
||||||
let class_text = "";
|
|
||||||
for (const cls of this.classes) {
|
|
||||||
class_text += cls;
|
|
||||||
class_text += this.line();
|
|
||||||
}
|
|
||||||
|
|
||||||
let file = path.join(this.configs.directory, (this.configs as CSharpExporterConfigs).file_name);
|
|
||||||
if (!file.endsWith(".cs")) {
|
|
||||||
file += "." + this.extension;
|
|
||||||
}
|
|
||||||
this.save_text(file, this.declear_content.replace("%CLASSES%", class_text));
|
|
||||||
console.log(colors.green(`\t${file}`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,7 @@ export class JSONExporter extends TableExporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get extension(): string { return 'json'}
|
get extension(): string { return this.configs.extension || 'json'; }
|
||||||
|
|
||||||
protected recursively_order_keys(unordered: object | Array<object>) {
|
protected recursively_order_keys(unordered: object | Array<object>) {
|
||||||
// If it's an array - recursively order any
|
// If it's an array - recursively order any
|
||||||
@@ -59,9 +59,7 @@ export class JSONExporter extends TableExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export(name: string, table: TableData) {
|
export(name: string, table: TableData) {
|
||||||
const file = path.join(this.configs.directory, `${name}.${this.extension}`);
|
|
||||||
const text = JSON.stringify(this.export_json_object(name, table), null, this.indent);
|
const text = JSON.stringify(this.export_json_object(name, table), null, this.indent);
|
||||||
this.save_text(file, text);
|
return text;
|
||||||
console.log(colors.green(`\t ${name} ==> ${file}`));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export class TypeScriptExporter extends TableExporter {
|
|||||||
(this.configs as TypeScriptExporterConfigs).type,
|
(this.configs as TypeScriptExporterConfigs).type,
|
||||||
(this.configs as TypeScriptExporterConfigs).declaration,
|
(this.configs as TypeScriptExporterConfigs).declaration,
|
||||||
);
|
);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected export_field(field: Field, indent = 0, ignore_root = false) {
|
protected export_field(field: Field, indent = 0, ignore_root = false) {
|
||||||
@@ -57,6 +58,9 @@ export class TypeScriptExporter extends TableExporter {
|
|||||||
}
|
}
|
||||||
type += ignore_root ? '' : this.indent_text('}', indent);
|
type += ignore_root ? '' : this.indent_text('}', indent);
|
||||||
} break;
|
} break;
|
||||||
|
case DataType.null:
|
||||||
|
type = "null";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
type = "any";
|
type = "any";
|
||||||
break;
|
break;
|
||||||
@@ -116,4 +120,4 @@ export class TypeScriptExporter extends TableExporter {
|
|||||||
console.log(colors.green(`\t${file}`));
|
console.log(colors.green(`\t${file}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ interface YAMLExporterConfigs extends ExporterConfigs {
|
|||||||
|
|
||||||
export class YAMLExporter extends JSONExporter {
|
export class YAMLExporter extends JSONExporter {
|
||||||
|
|
||||||
get extension(): string { return 'yaml'}
|
get extension(): string { return this.configs.extension || 'yaml'; }
|
||||||
|
|
||||||
constructor(configs: ExporterConfigs) {
|
constructor(configs: ExporterConfigs) {
|
||||||
super(configs);
|
super(configs);
|
||||||
@@ -22,7 +22,6 @@ export class YAMLExporter extends JSONExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export(name: string, table: TableData) {
|
export(name: string, table: TableData) {
|
||||||
const file = path.join(this.configs.directory, `${name}.${this.extension}`);
|
|
||||||
const text = yaml.dump(
|
const text = yaml.dump(
|
||||||
this.export_json_object(name, table),
|
this.export_json_object(name, table),
|
||||||
{
|
{
|
||||||
@@ -30,7 +29,6 @@ export class YAMLExporter extends JSONExporter {
|
|||||||
sortKeys: true,
|
sortKeys: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.save_text(file, text);
|
return text;
|
||||||
console.log(colors.green(`\t ${name} ==> ${file}`));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ module.exports = (env) => {
|
|||||||
console.log("Compile environment:", env);
|
console.log("Compile environment:", env);
|
||||||
return ({
|
return ({
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: path.join(workSpaceDir, 'src/main.ts'),
|
entry: [
|
||||||
|
'source-map-support/register',
|
||||||
|
path.join(workSpaceDir, 'src/main.ts'),
|
||||||
|
],
|
||||||
output: {
|
output: {
|
||||||
path: path.join(workSpaceDir, 'dist'),
|
path: path.join(workSpaceDir, 'dist'),
|
||||||
filename: 'binary.js'
|
filename: 'binary.js'
|
||||||
@@ -35,4 +38,4 @@ module.exports = (env) => {
|
|||||||
devtool: env.production ? "" : "source-map",
|
devtool: env.production ? "" : "source-map",
|
||||||
mode: "development",
|
mode: "development",
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user