diff options
Diffstat (limited to 'std/encoding/toml.ts')
-rw-r--r-- | std/encoding/toml.ts | 100 |
1 files changed, 70 insertions, 30 deletions
diff --git a/std/encoding/toml.ts b/std/encoding/toml.ts index 212c14bdc..62acc7db7 100644 --- a/std/encoding/toml.ts +++ b/std/encoding/toml.ts @@ -32,14 +32,82 @@ class Parser { for (let i = 0; i < this.tomlLines.length; i++) { const s = this.tomlLines[i]; const trimmed = s.trim(); - if (trimmed !== "" && trimmed[0] !== "#") { + if (trimmed !== "") { out.push(s); } } this.tomlLines = out; + this._removeComments(); this._mergeMultilines(); } + _removeComments(): void { + function isFullLineComment(line: string) { + return line.match(/^#/) ? true : false; + } + + function stringStart(line: string) { + const m = line.match(/(?:=\s*\[?\s*)("""|'''|"|')/); + if (!m) { + return false; + } + + // We want to know which syntax was used to open the string + openStringSyntax = m[1]; + return true; + } + + function stringEnd(line: string) { + // match the syntax used to open the string when searching for string close + // e.g. if we open with ''' we must close with a ''' + const reg = RegExp(`(?<!(=\\s*))${openStringSyntax}(?!(.*"))`); + if (!line.match(reg)) { + return false; + } + + openStringSyntax = ""; + return true; + } + + const cleaned = []; + let isOpenString = false; + let openStringSyntax = ""; + for (let i = 0; i < this.tomlLines.length; i++) { + const line = this.tomlLines[i]; + + // stringStart and stringEnd are separate conditions to + // support both single-line and multi-line strings + if (!isOpenString && stringStart(line)) { + isOpenString = true; + } + if (isOpenString && stringEnd(line)) { + isOpenString = false; + } + + if (!isOpenString && !isFullLineComment(line)) { + const out = line.split( + /(?<=([\,\[\]\{\}]|".*"|'.*'|\w(?!.*("|')+))\s*)#/gi, + ); + cleaned.push(out[0].trim()); + } else if (isOpenString || !isFullLineComment(line)) { + cleaned.push(line); + } + + // If a single line comment doesnt end on the same line, throw error + if ( + isOpenString && (openStringSyntax === "'" || openStringSyntax === '"') + ) { + throw new TOMLError(`Single-line string is not closed:\n${line}`); + } + } + + if (isOpenString) { + throw new TOMLError(`Incomplete string until EOF`); + } + + this.tomlLines = cleaned; + } + _mergeMultilines(): void { function arrayStart(line: string): boolean { const reg = /.*=\s*\[/g; @@ -236,7 +304,7 @@ class Parser { if (invalidArr) { dataString = dataString.replace(/,]/g, "]"); } - dataString = this._stripComment(dataString); + if (dataString[0] === "{" && dataString[dataString.length - 1] === "}") { const reg = /([a-zA-Z0-9-_\.]*) (=)/gi; let result; @@ -263,34 +331,6 @@ class Parser { } return eval(dataString); } - private _stripComment(dataString: string): string { - const isString = dataString.startsWith('"') || dataString.startsWith("'"); - if (isString) { - const [quote] = dataString; - let indexOfNextQuote = 0; - while ( - (indexOfNextQuote = dataString.indexOf(quote, indexOfNextQuote + 1)) !== - -1 - ) { - const isEscaped = dataString[indexOfNextQuote - 1] === "\\"; - if (!isEscaped) { - break; - } - } - if (indexOfNextQuote === -1) { - throw new TOMLError("imcomplete string literal"); - } - const endOfString = indexOfNextQuote + 1; - return dataString.slice(0, endOfString); - } - - const m = /(?:|\[|{).*(?:|\]|})\s*^((?!#).)*/g.exec(dataString); - if (m) { - return m[0].trim(); - } else { - return dataString; - } - } _isLocalTime(str: string): boolean { const reg = /(\d{2}):(\d{2}):(\d{2})/; return reg.test(str); |