Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: [toml] adapted to TOML's key encoding spec #612

Merged
merged 3 commits into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 38 additions & 27 deletions encoding/toml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,18 @@ class Parser {
}
}

// Bare keys may only contain ASCII letters,
// ASCII digits, underscores, and dashes (A-Za-z0-9_-).
function joinKeys(keys: string[]): string {
// Dotted keys are a sequence of bare or quoted keys joined with a dot.
// This allows for grouping similar properties together:
return keys
.map((str: string): string => {
return str.match(/[^A-Za-z0-9_-]/) ? `"${str}"` : str;
})
.join(".");
}

class Dumper {
maxPad: number = 0;
srcObject: object;
Expand All @@ -400,7 +412,7 @@ class Dumper {
this.output = this._format();
return this.output;
}
_parse(obj: Record<string, unknown>, path: string = ""): string[] {
_parse(obj: Record<string, unknown>, keys: string[] = []): string[] {
const out = [];
const props = Object.keys(obj);
const propObj = props.filter((e: string): boolean => {
Expand All @@ -422,33 +434,33 @@ class Dumper {
const prop = k[i];
const value = obj[prop];
if (value instanceof Date) {
out.push(this._dateDeclaration(prop, value));
out.push(this._dateDeclaration([prop], value));
} else if (typeof value === "string" || value instanceof RegExp) {
out.push(this._strDeclaration(prop, value.toString()));
out.push(this._strDeclaration([prop], value.toString()));
} else if (typeof value === "number") {
out.push(this._numberDeclaration(prop, value));
out.push(this._numberDeclaration([prop], value));
} else if (
value instanceof Array &&
this._isSimplySerializable(value[0])
) {
// only if primitives types in the array
out.push(this._arrayDeclaration(prop, value));
out.push(this._arrayDeclaration([prop], value));
} else if (
value instanceof Array &&
!this._isSimplySerializable(value[0])
) {
// array of objects
for (let i = 0; i < value.length; i++) {
out.push("");
out.push(this._headerGroup(path + prop));
out.push(...this._parse(value[i], `${path}${prop}.`));
out.push(this._headerGroup([...keys, prop]));
out.push(...this._parse(value[i], [...keys, prop]));
}
} else if (typeof value === "object") {
out.push("");
out.push(this._header(path + prop));
out.push(this._header([...keys, prop]));
if (value) {
const toParse = value as Record<string, unknown>;
out.push(...this._parse(toParse, `${path}${prop}.`));
out.push(...this._parse(toParse, [...keys, prop]));
}
// out.push(...this._parse(value, `${path}${prop}.`));
}
Expand All @@ -465,35 +477,36 @@ class Dumper {
value instanceof Array
);
}
_header(title: string): string {
return `[${title}]`;
_header(keys: string[]): string {
return `[${joinKeys(keys)}]`;
}
_headerGroup(title: string): string {
return `[[${title}]]`;
_headerGroup(keys: string[]): string {
return `[[${joinKeys(keys)}]]`;
}
_declaration(title: string): string {
_declaration(keys: string[]): string {
const title = joinKeys(keys);
if (title.length > this.maxPad) {
this.maxPad = title.length;
}
return `${title} = `;
}
_arrayDeclaration(title: string, value: unknown[]): string {
return `${this._declaration(title)}${JSON.stringify(value)}`;
_arrayDeclaration(keys: string[], value: unknown[]): string {
return `${this._declaration(keys)}${JSON.stringify(value)}`;
}
_strDeclaration(title: string, value: string): string {
return `${this._declaration(title)}"${value}"`;
_strDeclaration(keys: string[], value: string): string {
return `${this._declaration(keys)}"${value}"`;
}
_numberDeclaration(title: string, value: number): string {
_numberDeclaration(keys: string[], value: number): string {
switch (value) {
case Infinity:
return `${this._declaration(title)}inf`;
return `${this._declaration(keys)}inf`;
case -Infinity:
return `${this._declaration(title)}-inf`;
return `${this._declaration(keys)}-inf`;
default:
return `${this._declaration(title)}${value}`;
return `${this._declaration(keys)}${value}`;
}
}
_dateDeclaration(title: string, value: Date): string {
_dateDeclaration(keys: string[], value: Date): string {
function dtPad(v: string, lPad: number = 2): string {
return pad(v, lPad, { char: "0" });
}
Expand All @@ -505,7 +518,7 @@ class Dumper {
const ms = dtPad(value.getUTCMilliseconds().toString(), 3);
// formated date
const fData = `${value.getUTCFullYear()}-${m}-${d}T${h}:${min}:${s}.${ms}`;
return `${this._declaration(title)}${fData}`;
return `${this._declaration(keys)}${fData}`;
}
_format(): string[] {
const rDeclaration = /(.*)\s=/;
Expand Down Expand Up @@ -542,9 +555,7 @@ class Dumper {
}

export function stringify(srcObj: object): string {
let out: string[] = [];
out = new Dumper(srcObj).dump();
return out.join("\n");
return new Dumper(srcObj).dump().join("\n");
}

export function parse(tomlString: string): object {
Expand Down
22 changes: 21 additions & 1 deletion encoding/toml_test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test } from "../testing/mod.ts";
import { runIfMain, test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts";
import { existsSync } from "../fs/exists.ts";
import { readFileStrSync } from "../fs/read_file_str.ts";
Expand Down Expand Up @@ -301,6 +301,17 @@ test({
const src = {
foo: { bar: "deno" },
this: { is: { nested: "denonono" } },
"https://deno.land/std": {
$: "doller"
},
"##": {
deno: {
"https://deno.land": {
proto: "https",
":80": "port"
}
}
},
arrayObjects: [{ stuff: "in" }, {}, { the: "array" }],
deno: "is",
not: "[node]",
Expand Down Expand Up @@ -376,6 +387,13 @@ bar = "deno"
[this.is]
nested = "denonono"

["https://deno.land/std"]
"$" = "doller"

["##".deno."https://deno.land"]
proto = "https"
":80" = "port"

[[arrayObjects]]
stuff = "in"

Expand All @@ -388,3 +406,5 @@ the = "array"
assertEquals(actual, expected);
}
});

runIfMain(import.meta);