TOML: Full support of inline table (#320)

This commit is contained in:
Vincent LE GOFF 2019-04-04 12:00:24 +02:00 committed by Ryan Dahl
parent a0ff487a12
commit d16072a334
4 changed files with 95 additions and 9 deletions

View File

@ -22,7 +22,7 @@ TypeScript side is a bit different.
- :heavy_check_mark: [Local Date](https://github.com/toml-lang/toml#local-date)
- :exclamation: [Local Time](https://github.com/toml-lang/toml#local-time)
- :heavy_check_mark: [Table](https://github.com/toml-lang/toml#table)
- :exclamation: [Inline Table](https://github.com/toml-lang/toml#inline-table)
- :heavy_check_mark: [Inline Table](https://github.com/toml-lang/toml#inline-table)
- :exclamation: [Array of Tables](https://github.com/toml-lang/toml#array-of-tables)
:exclamation: _Supported with warnings see [Warning](#Warning)._
@ -45,12 +45,18 @@ Because local time does not exist in JavaScript, the local time is stored as a s
#### Inline Table
Inline tables are supported but nested inline property name are **not**. See below:
Inline tables are supported. See below:
```toml
animal = { type = { name = "pug" } } # Supported
animal = { type = { name = "pug" } }
# Output
animal = { type.name = "pug" }
# not supported. Will output { "animal" : {"type.name":"pug"} }
# Output { animal : { type : { name : "pug" } }
animal.as.leaders = "tosin"
# Output { animal: { as: { leaders: "tosin" } } }
"tosin.abasi" = "guitarist"
# Output
"tosin.abasi" : "guitarist"
```
#### Array of Tables

View File

@ -238,7 +238,6 @@ class Parser {
.replace(result[2], ":");
dataString = dataString.replace(ogVal, newVal);
}
// TODO : unflat if necessary
return JSON.parse(dataString);
}
@ -271,6 +270,38 @@ class Parser {
const reg = /\d{4}-\d{2}-\d{2}/;
return reg.test(dateStr);
}
_parseDeclarationName(declaration: string): string[] {
const out = [];
let acc = [];
let inLitteral = false;
for (let i = 0; i < declaration.length; i++) {
const c = declaration[i];
switch (c) {
case ".":
if (!inLitteral) {
out.push(acc.join(""));
acc = [];
} else {
acc.push(c);
}
break;
case `"`:
if (inLitteral) {
inLitteral = false;
} else {
inLitteral = true;
}
break;
default:
acc.push(c);
break;
}
}
if (acc.length !== 0) {
out.push(acc.join(""));
}
return out;
}
_parseLines(): void {
for (let i = 0; i < this.tomlLines.length; i++) {
const line = this.tomlLines[i];
@ -301,10 +332,12 @@ class Parser {
}
if (this._isDeclaration(line)) {
let kv = this._processDeclaration(line);
let key = kv.key;
let value = kv.value;
if (!this.context.currentGroup) {
this.context.output[kv.key] = kv.value;
this.context.output[key] = value;
} else {
this.context.currentGroup.objValues[kv.key] = kv.value;
this.context.currentGroup.objValues[key] = value;
}
}
}
@ -317,9 +350,33 @@ class Parser {
this._groupToOutput();
}
}
_cleanOutput(): void {
this._propertyClean(this.context.output);
}
_propertyClean(obj: object): void {
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
let k = keys[i];
let v = obj[k];
let pathDeclaration = this._parseDeclarationName(k);
delete obj[k];
if (pathDeclaration.length > 1) {
k = pathDeclaration.shift();
k = k.replace(/"/g, "");
v = this._unflat(pathDeclaration, v as object);
} else {
k = k.replace(/"/g, "");
}
obj[k] = v;
if (v instanceof Object) {
this._propertyClean(v);
}
}
}
parse(): object {
this._sanitize();
this._parseLines();
this._cleanOutput();
return this.context.output;
}
}

View File

@ -181,6 +181,20 @@ test({
fn() {
const expected = {
inlinetable: {
nile: {
also: {
malevolant: {
creation: {
drum: {
kit: "Tama"
}
}
}
},
derek: {
roddy: "drummer"
}
},
name: {
first: "Tom",
last: "Preston-Werner"
@ -189,10 +203,16 @@ test({
x: 1,
y: 2
},
animal: {
dog: {
type: {
name: "pug"
}
},
"tosin.abasi": "guitarist",
animal: {
as: {
leaders: "tosin"
}
}
}
};

View File

@ -1,4 +1,7 @@
[inlinetable]
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type = { name = "pug" } }
dog = { type = { name = "pug" } }
animal.as.leaders = "tosin"
"tosin.abasi" = "guitarist"
nile = { derek.roddy = "drummer", also = { malevolant.creation = { drum.kit = "Tama" } } }