new changes

This commit is contained in:
Niranjan
2026-04-07 05:05:28 +05:30
parent 7c070224bd
commit a18bba15f2
29975 changed files with 3247495 additions and 2761 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Yosuke Ota
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,182 @@
# toml-eslint-parser
A TOML parser that produces output [compatible with ESLint](https://eslint.org/docs/developer-guide/working-with-custom-parsers#all-nodes).
[![NPM license](https://img.shields.io/npm/l/toml-eslint-parser.svg)](https://www.npmjs.com/package/toml-eslint-parser)
[![NPM version](https://img.shields.io/npm/v/toml-eslint-parser.svg)](https://www.npmjs.com/package/toml-eslint-parser)
[![NPM downloads](https://img.shields.io/badge/dynamic/json.svg?label=downloads&colorB=green&suffix=/day&query=$.downloads&uri=https://api.npmjs.org//downloads/point/last-day/toml-eslint-parser&maxAge=3600)](http://www.npmtrends.com/toml-eslint-parser)
[![NPM downloads](https://img.shields.io/npm/dw/toml-eslint-parser.svg)](http://www.npmtrends.com/toml-eslint-parser)
[![NPM downloads](https://img.shields.io/npm/dm/toml-eslint-parser.svg)](http://www.npmtrends.com/toml-eslint-parser)
[![NPM downloads](https://img.shields.io/npm/dy/toml-eslint-parser.svg)](http://www.npmtrends.com/toml-eslint-parser)
[![NPM downloads](https://img.shields.io/npm/dt/toml-eslint-parser.svg)](http://www.npmtrends.com/toml-eslint-parser)
[![Build Status](https://github.com/ota-meshi/toml-eslint-parser/workflows/CI/badge.svg?branch=main)](https://github.com/ota-meshi/toml-eslint-parser/actions?query=workflow%3ACI)
## Features
- Converts TOML text to [AST](./docs/AST.md).
- Support for [TOML 1.0.0](https://toml.io/en/v1.0.0).
- Experimental support for TOML 1.1.0. (Specifications for November 2023)
## Installation
```bash
npm install --save-dev toml-eslint-parser
```
## Usage
### Configuration
Use `.eslintrc.*` file to configure parser. See also: [https://eslint.org/docs/user-guide/configuring](https://eslint.org/docs/user-guide/configuring).
Example **.eslintrc.js**:
```js
module.exports = {
overrides: [
{
files: ["*.toml"],
parser: "toml-eslint-parser",
},
],
};
```
### Advanced Configuration
The following additional configuration options are available by specifying them in [parserOptions](https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options) in your ESLint configuration file.
Example **.eslintrc.js**:
```js
module.exports = {
overrides: [
{
files: ["*.toml"],
parser: "toml-eslint-parser",
// Additional configuration options
parserOptions: {
tomlVersion: "1.0.0",
},
},
],
};
```
#### `parserOptions.tomlVersion`
Select the TOML version by setting `"1.0.0"`, `"1.1.0"`, `"1.0"`, `"1.1"`, `"latest"`, or `"next"`. By default `"1.0.0"` is used.
- `"1.0.0"` ... Parsed using [TOML v1.0.0 specifications](https://toml.io/en/v1.0.0).
- `"1.0"` ... Alias for `"1.0.0"`.
- `"1.1.0"` ... Parsed using the TOML v1.1.0 specification, which is currently [under development](https://github.com/toml-lang/toml/issues/928). TOML 1.1.0 has not been released yet, so `"1.1.0"` is still an experimental feature. Please note that this may be subject to breaking changes in minor version releases of this parser.
- `"1.1"` ... Alias for `"1.1.0"`.
- `"latest"` ... Currently an alias for `"1.0.0"`. When a new version of TOML is released, we plan to change to that version in a minor version release of this parser.
- `"next"` ... Currently an alias for `"1.1.0"`.
## Usage for Custom Rules / Plugins
- [AST.md](./docs/AST.md) is AST specification.
- [keys-order.ts](https://github.com/ota-meshi/eslint-plugin-toml/blob/main/src/rules/keys-order.ts) is an example.
- You can see the AST on the [Online DEMO](https://ota-meshi.github.io/toml-eslint-parser/).
## Usage for Directly
Example:
```ts
import type { AST } from "toml-eslint-parser";
import { parseTOML, getStaticTOMLValue } from "toml-eslint-parser";
const code = `
# This is a TOML document
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
enabled = true
ports = [ 8001, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }
[servers]
[servers.alpha]
ip = "10.0.0.1"
role = "frontend"
[servers.beta]
ip = "10.0.0.2"
role = "backend"
`;
const ast: AST.TOMLProgram = parseTOML(code);
console.log(ast);
// {
// type: 'Program',
// body: [
// {
// type: 'TOMLTopLevelTable',
// body: [
// {
// type: 'TOMLKeyValue',
// key: { /* ... */ },
// value: { /* ... */ },
// /* ... */
// },
// {
// type: 'TOMLTable',
// kind: 'standard',
// key: { /* ... */ },
// body: [ /* ... */ ],
// /* ... */
// },
// /* ... */
// ]
// /* ... */
// }
// ],
// tokens: [ /* ... */ ],
// comments: [
// {
// type: 'Block',
// value: ' This is a TOML document',
// // ...
// }
// ],
// }
const value = getStaticTOMLValue(ast);
console.log(value);
// {
// title: 'TOML Example',
// owner: { name: 'Tom Preston-Werner', dob: 1979-05-27T15:32:00.000Z },
// database: {
// enabled: true,
// ports: [ 8001, 8001, 8002 ],
// data: [ [ /* ... */ ], [ /* ... */ ] ],
// temp_targets: { cpu: 79.5, case: 72 }
// },
// servers: {
// alpha: { ip: '10.0.0.1', role: 'frontend' },
// beta: { ip: '10.0.0.2', role: 'backend' }
// }
// }
```
## Testing
This project uses files from [BurntSushi/toml-test](https://github.com/BurntSushi/toml-test) and [iarna/toml-spec-tests](https://github.com/iarna/toml-spec-tests) repositories for testing.
## Related Packages
- [eslint-plugin-jsonc](https://github.com/ota-meshi/eslint-plugin-jsonc) ... ESLint plugin for JSON, JSON with comments (JSONC) and JSON5.
- [eslint-plugin-yml](https://github.com/ota-meshi/eslint-plugin-yml) ... ESLint plugin for YAML.
- [eslint-plugin-toml](https://github.com/ota-meshi/eslint-plugin-toml) ... ESLint plugin for TOML.
- [eslint-plugin-json-schema-validator](https://github.com/ota-meshi/eslint-plugin-json-schema-validator) ... ESLint plugin that validates data using JSON Schema Validator.
- [jsonc-eslint-parser](https://github.com/ota-meshi/jsonc-eslint-parser) ... JSON, JSONC and JSON5 parser for use with ESLint plugins.
- [yaml-eslint-parser](https://github.com/ota-meshi/yaml-eslint-parser) ... YAML parser for use with ESLint plugins.

View File

@@ -0,0 +1,101 @@
import type { HasLocs } from "./loc";
import type { Comment, Token } from "./token";
interface BaseTOMLNode extends HasLocs {
type: string;
}
export type TOMLNode = TOMLProgram | TOMLTopLevelTable | TOMLTable | TOMLKeyValue | TOMLKey | TOMLBare | TOMLQuoted | TOMLContentNode;
export type TOMLContentNode = TOMLValue | TOMLArray | TOMLInlineTable;
export interface TOMLProgram extends BaseTOMLNode {
type: "Program";
body: [TOMLTopLevelTable];
sourceType: "module";
comments: Comment[];
tokens: Token[];
parent: null;
}
export interface TOMLTopLevelTable extends BaseTOMLNode {
type: "TOMLTopLevelTable";
body: (TOMLKeyValue | TOMLTable)[];
parent: TOMLProgram;
}
export interface TOMLTable extends BaseTOMLNode {
type: "TOMLTable";
kind: "standard" | "array";
key: TOMLKey;
resolvedKey: (string | number)[];
body: TOMLKeyValue[];
parent: TOMLTopLevelTable;
}
export interface TOMLKeyValue extends BaseTOMLNode {
type: "TOMLKeyValue";
key: TOMLKey;
value: TOMLContentNode;
parent: TOMLTopLevelTable | TOMLTable | TOMLInlineTable;
}
export interface TOMLKey extends BaseTOMLNode {
type: "TOMLKey";
keys: (TOMLBare | TOMLQuoted)[];
parent: TOMLKeyValue | TOMLTable;
}
export interface TOMLArray extends BaseTOMLNode {
type: "TOMLArray";
elements: TOMLContentNode[];
parent: TOMLKeyValue | TOMLArray;
}
export interface TOMLInlineTable extends BaseTOMLNode {
type: "TOMLInlineTable";
body: TOMLKeyValue[];
parent: TOMLKeyValue | TOMLArray;
}
export interface TOMLBare extends BaseTOMLNode {
type: "TOMLBare";
name: string;
parent: TOMLKey;
}
export interface TOMLQuoted extends BaseTOMLNode {
type: "TOMLQuoted";
value: string;
style: "basic" | "literal";
parent: TOMLKey;
kind: "string";
multiline: false;
}
export type TOMLValue = TOMLStringValue | TOMLNumberValue | TOMLBooleanValue | TOMLDateTimeValue;
export interface TOMLStringValue extends BaseTOMLNode {
type: "TOMLValue";
kind: "string";
value: string;
style: "basic" | "literal";
multiline: boolean;
parent: TOMLKeyValue | TOMLArray;
}
export interface TOMLIntegerValue extends BaseTOMLNode {
type: "TOMLValue";
kind: "integer";
value: number;
bigint: bigint;
number: string;
parent: TOMLKeyValue | TOMLArray;
}
export interface TOMLFloatValue extends BaseTOMLNode {
type: "TOMLValue";
kind: "float";
value: number;
number: string;
parent: TOMLKeyValue | TOMLArray;
}
export type TOMLNumberValue = TOMLIntegerValue | TOMLFloatValue;
export interface TOMLBooleanValue extends BaseTOMLNode {
type: "TOMLValue";
kind: "boolean";
value: boolean;
parent: TOMLKeyValue | TOMLArray;
}
export interface TOMLDateTimeValue extends BaseTOMLNode {
type: "TOMLValue";
kind: "offset-date-time" | "local-date-time" | "local-date" | "local-time";
value: Date;
datetime: string;
parent: TOMLKeyValue | TOMLArray;
}
export {};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,3 @@
export * from "./token";
export * from "./ast";
export * from "./loc";

View File

@@ -0,0 +1,19 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./token"), exports);
__exportStar(require("./ast"), exports);
__exportStar(require("./loc"), exports);

View File

@@ -0,0 +1,15 @@
export type Range = [number, number];
export interface Position {
/** >= 1 */
line: number;
/** >= 0 */
column: number;
}
export interface SourceLocation {
start: Position;
end: Position;
}
export interface HasLocs {
loc: SourceLocation;
range: Range;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,52 @@
import type { HasLocs } from "./loc";
export interface Comment extends HasLocs {
type: "Block";
value: string;
}
export type TokenType = "Punctuator" | "Bare" | "BasicString" | "MultiLineBasicString" | "LiteralString" | "MultiLineLiteralString" | "Integer" | "Float" | "Boolean" | "OffsetDateTime" | "LocalDateTime" | "LocalDate" | "LocalTime";
interface BaseTOMLToken extends HasLocs {
type: TokenType;
value: string;
}
export type Token = PunctuatorToken | BareToken | StringToken | MultiLineStringToken | NumberToken | BooleanToken | DateTimeToken;
export interface PunctuatorToken extends BaseTOMLToken {
type: "Punctuator";
value: string;
}
export interface BareToken extends BaseTOMLToken {
type: "Bare";
value: string;
}
export interface StringToken extends BaseTOMLToken {
type: "BasicString" | "LiteralString";
value: string;
string: string;
}
export interface MultiLineStringToken extends BaseTOMLToken {
type: "MultiLineBasicString" | "MultiLineLiteralString";
value: string;
string: string;
}
export interface IntegerToken extends BaseTOMLToken {
type: "Integer";
value: string;
number: number;
bigint: bigint;
}
export interface FloatToken extends BaseTOMLToken {
type: "Float";
value: string;
number: number;
}
export type NumberToken = IntegerToken | FloatToken;
export interface BooleanToken extends BaseTOMLToken {
type: "Boolean";
value: string;
boolean: boolean;
}
export interface DateTimeToken extends BaseTOMLToken {
type: "OffsetDateTime" | "LocalDateTime" | "LocalDate" | "LocalTime";
value: string;
date: Date;
}
export {};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,44 @@
declare const MESSAGES: {
"unterminated-string": string;
"unterminated-table-key": string;
"unterminated-array": string;
"unterminated-inline-table": string;
"missing-key": string;
"missing-newline": string;
"missing-equals-sign": string;
"missing-value": string;
"missing-comma": string;
"dupe-keys": string;
"unexpected-char": string;
"unexpected-token": string;
"invalid-control-character": string;
"invalid-comment-character": string;
"invalid-key-value-newline": string;
"invalid-inline-table-newline": string;
"invalid-underscore": string;
"invalid-space": string;
"invalid-three-quotes": string;
"invalid-date": string;
"invalid-time": string;
"invalid-leading-zero": string;
"invalid-trailing-comma-in-inline-table": string;
"invalid-char-in-escape-sequence": string;
"invalid-code-point": string;
};
/**
* TOML parse errors.
*/
export declare class ParseError extends SyntaxError {
index: number;
lineNumber: number;
column: number;
/**
* Initialize this ParseError instance.
*
*/
constructor(code: ErrorCode, offset: number, line: number, column: number, data?: {
[key: string]: any;
});
}
export type ErrorCode = keyof typeof MESSAGES;
export {};

View File

@@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseError = void 0;
const MESSAGES = {
"unterminated-string": "Unterminated string constant",
"unterminated-table-key": "Unterminated table-key",
"unterminated-array": "Unterminated array",
"unterminated-inline-table": "Unterminated inline table",
"missing-key": "Empty bare keys are not allowed",
"missing-newline": "Must be a newline",
"missing-equals-sign": "Expected equal (=) token",
"missing-value": "Unspecified values are invalid",
"missing-comma": "Expected comma (,) token",
"dupe-keys": "Defining a key multiple times is invalid",
"unexpected-char": "Unexpected character",
"unexpected-token": "Unexpected token",
"invalid-control-character": "Control characters (codes < 0x1f and 0x7f) are not allowed",
"invalid-comment-character": "Invalid code point {{cp}} within comments",
"invalid-key-value-newline": "The key, equals sign, and value must be on the same line",
"invalid-inline-table-newline": "No newlines are allowed between the curly braces unless they are valid within a value",
"invalid-underscore": "Underscores are allowed between digits",
"invalid-space": "Unexpected spaces",
"invalid-three-quotes": "Three or more quotes are not permitted",
"invalid-date": "Unexpected invalid date",
"invalid-time": "Unexpected invalid time",
"invalid-leading-zero": "Leading zeros are not allowed",
"invalid-trailing-comma-in-inline-table": "Trailing comma is not permitted in an inline table",
"invalid-char-in-escape-sequence": "Invalid character in escape sequence",
"invalid-code-point": "Invalid code point {{cp}}",
};
/**
* Get message from error code
*/
function getMessage(code, data) {
if (data) {
return MESSAGES[code].replace(/\{\{(.*?)\}\}/gu, (_, name) => {
if (name in data) {
return data[name];
}
return `{{${name}}}`;
});
}
return MESSAGES[code];
}
/**
* TOML parse errors.
*/
class ParseError extends SyntaxError {
/**
* Initialize this ParseError instance.
*
*/
constructor(code, offset, line, column, data) {
super(getMessage(code, data));
this.index = offset;
this.lineNumber = line;
this.column = column;
}
}
exports.ParseError = ParseError;

View File

@@ -0,0 +1,16 @@
import { parseForESLint } from "./parser";
import type * as AST from "./ast";
import { traverseNodes } from "./traverse";
import { getStaticTOMLValue } from "./utils";
import { ParseError } from "./errors";
import type { ParserOptions } from "./parser-options";
export * as meta from "./meta";
export { name } from "./meta";
export { AST, ParseError };
export { parseForESLint };
export declare const VisitorKeys: import("eslint").SourceCode.VisitorKeys;
export { traverseNodes, getStaticTOMLValue };
/**
* Parse TOML source code
*/
export declare function parseTOML(code: string, options?: ParserOptions): AST.TOMLProgram;

View File

@@ -0,0 +1,58 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStaticTOMLValue = exports.traverseNodes = exports.VisitorKeys = exports.parseForESLint = exports.ParseError = exports.name = exports.meta = void 0;
exports.parseTOML = parseTOML;
const parser_1 = require("./parser");
Object.defineProperty(exports, "parseForESLint", { enumerable: true, get: function () { return parser_1.parseForESLint; } });
const traverse_1 = require("./traverse");
Object.defineProperty(exports, "traverseNodes", { enumerable: true, get: function () { return traverse_1.traverseNodes; } });
const utils_1 = require("./utils");
Object.defineProperty(exports, "getStaticTOMLValue", { enumerable: true, get: function () { return utils_1.getStaticTOMLValue; } });
const visitor_keys_1 = require("./visitor-keys");
const errors_1 = require("./errors");
Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return errors_1.ParseError; } });
exports.meta = __importStar(require("./meta"));
var meta_1 = require("./meta");
Object.defineProperty(exports, "name", { enumerable: true, get: function () { return meta_1.name; } });
// Keys
// eslint-disable-next-line @typescript-eslint/naming-convention -- ignore
exports.VisitorKeys = visitor_keys_1.KEYS;
/**
* Parse TOML source code
*/
function parseTOML(code, options) {
return (0, parser_1.parseForESLint)(code, options).ast;
}

View File

@@ -0,0 +1,9 @@
import type { TOMLBare, TOMLQuoted } from "../ast";
/**
* Get the last element from given array
*/
export declare function last<T>(arr: T[]): T | null;
/**
* Node to key name
*/
export declare function toKeyName(node: TOMLBare | TOMLQuoted): string;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.last = last;
exports.toKeyName = toKeyName;
/**
* Get the last element from given array
*/
function last(arr) {
var _a;
return (_a = arr[arr.length - 1]) !== null && _a !== void 0 ? _a : null;
}
/**
* Node to key name
*/
function toKeyName(node) {
return node.type === "TOMLBare" ? node.name : node.value;
}

View File

@@ -0,0 +1,2 @@
export declare const name: "toml-eslint-parser";
export declare const version: "0.10.1";

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = exports.name = void 0;
// IMPORTANT!
// This file has been automatically generated,
// in order to update its content execute "npm run build:meta"
exports.name = "toml-eslint-parser";
exports.version = "0.10.1";

View File

@@ -0,0 +1,13 @@
export type TOMLVersionOption = "1.0" | "1.1" | "1.0.0" | "1.1.0" | "latest" | "next";
export interface TOMLVer {
lt(major: number, minor: number): boolean;
gte(major: number, minor: number): boolean;
}
export interface ParserOptions {
filePath?: string;
tomlVersion?: TOMLVersionOption;
}
/**
* Get TOML version object from given TOML version string.
*/
export declare function getTOMLVer(v: TOMLVersionOption | undefined | null): TOMLVer;

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTOMLVer = getTOMLVer;
class TOMLVerImpl {
constructor(major, minor) {
this.major = major;
this.minor = minor;
}
lt(major, minor) {
return this.major < major || (this.major === major && this.minor < minor);
}
gte(major, minor) {
return this.major > major || (this.major === major && this.minor >= minor);
}
}
const TOML_VERSION_1_0 = new TOMLVerImpl(1, 0);
const TOML_VERSION_1_1 = new TOMLVerImpl(1, 1);
const DEFAULT_TOML_VERSION = TOML_VERSION_1_0;
const SUPPORTED_TOML_VERSIONS = {
"1.0": TOML_VERSION_1_0,
"1.0.0": TOML_VERSION_1_0,
"1.1": TOML_VERSION_1_1,
"1.1.0": TOML_VERSION_1_1,
latest: TOML_VERSION_1_0,
next: TOML_VERSION_1_1,
};
/**
* Get TOML version object from given TOML version string.
*/
function getTOMLVer(v) {
return SUPPORTED_TOML_VERSIONS[v || "latest"] || DEFAULT_TOML_VERSION;
}

View File

@@ -0,0 +1,13 @@
import type { SourceCode } from "eslint";
import type { TOMLProgram } from "./ast";
import type { ParserOptions } from "./parser-options";
/**
* Parse source code
*/
export declare function parseForESLint(code: string, options?: ParserOptions): {
ast: TOMLProgram;
visitorKeys: SourceCode.VisitorKeys;
services: {
isTOML: boolean;
};
};

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseForESLint = parseForESLint;
const toml_parser_1 = require("./toml-parser");
const visitor_keys_1 = require("./visitor-keys");
/**
* Parse source code
*/
function parseForESLint(code, options) {
const parser = new toml_parser_1.TOMLParser(code, options);
const ast = parser.parse();
return {
ast,
visitorKeys: visitor_keys_1.KEYS,
services: {
isTOML: true,
},
};
}

View File

@@ -0,0 +1,18 @@
export declare class CodePointIterator {
readonly text: string;
private readonly locs;
private lastCodePoint;
start: number;
end: number;
/**
* Initialize this char iterator.
*/
constructor(text: string);
next(): number;
getLocFromIndex(index: number): {
line: number;
column: number;
};
eat(cp: number): boolean;
moveAt(offset: number): number;
}

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodePointIterator = void 0;
const locs_1 = require("./locs");
class CodePointIterator {
/**
* Initialize this char iterator.
*/
constructor(text) {
this.locs = new locs_1.Locations();
this.lastCodePoint = 0 /* CodePoint.NULL */;
this.start = -1;
this.end = 0;
this.text = text;
}
next() {
if (this.lastCodePoint === -1 /* CodePoint.EOF */) {
return -1 /* CodePoint.EOF */;
}
return (this.lastCodePoint = this.moveAt(this.end));
}
getLocFromIndex(index) {
return this.locs.getLocFromIndex(index);
}
eat(cp) {
if (this.text.codePointAt(this.end) === cp) {
this.next();
return true;
}
return false;
}
moveAt(offset) {
var _a;
this.start = this.end = offset;
const cp = (_a = this.text.codePointAt(this.start)) !== null && _a !== void 0 ? _a : -1 /* CodePoint.EOF */;
if (cp === -1 /* CodePoint.EOF */) {
this.end = this.start;
return cp;
}
const shift = cp >= 0x10000 ? 2 : 1;
this.end += shift;
if (cp === 10 /* CodePoint.LINE_FEED */) {
this.locs.addOffset(this.end);
}
else if (cp === 13 /* CodePoint.CARRIAGE_RETURN */) {
if (this.text.codePointAt(this.end) === 10 /* CodePoint.LINE_FEED */) {
this.end++;
this.locs.addOffset(this.end);
}
return 10 /* CodePoint.LINE_FEED */;
}
return cp;
}
}
exports.CodePointIterator = CodePointIterator;

View File

@@ -0,0 +1,134 @@
export declare const enum CodePoint {
EOF = -1,
NULL = 0,
SOH = 1,
BACKSPACE = 8,
TABULATION = 9,
LINE_FEED = 10,
FORM_FEED = 12,
CARRIAGE_RETURN = 13,
ESCAPE = 27,
SO = 14,
US = 31,
SPACE = 32,
QUOTATION_MARK = 34,
HASH = 35,
SINGLE_QUOTE = 39,
PLUS_SIGN = 43,
COMMA = 44,
DASH = 45,
DOT = 46,
DIGIT_0 = 48,
DIGIT_1 = 49,
DIGIT_2 = 50,
DIGIT_3 = 51,
DIGIT_7 = 55,
DIGIT_9 = 57,
COLON = 58,
EQUALS_SIGN = 61,
LATIN_CAPITAL_A = 65,
LATIN_CAPITAL_E = 69,
LATIN_CAPITAL_F = 70,
LATIN_CAPITAL_T = 84,
LATIN_CAPITAL_U = 85,
LATIN_CAPITAL_Z = 90,
LEFT_BRACKET = 91,// [
BACKSLASH = 92,
RIGHT_BRACKET = 93,// ]
UNDERSCORE = 95,
LATIN_SMALL_A = 97,
LATIN_SMALL_B = 98,
LATIN_SMALL_E = 101,
LATIN_SMALL_F = 102,
LATIN_SMALL_I = 105,
LATIN_SMALL_L = 108,
LATIN_SMALL_N = 110,
LATIN_SMALL_O = 111,
LATIN_SMALL_R = 114,
LATIN_SMALL_S = 115,
LATIN_SMALL_T = 116,
LATIN_SMALL_U = 117,
LATIN_SMALL_X = 120,
LATIN_SMALL_Z = 122,
LEFT_BRACE = 123,// {
RIGHT_BRACE = 125,// }
DELETE = 127,
PAD = 128,
SUPERSCRIPT_TWO = 178,
SUPERSCRIPT_THREE = 179,
SUPERSCRIPT_ONE = 185,
VULGAR_FRACTION_ONE_QUARTER = 188,
VULGAR_FRACTION_THREE_QUARTERS = 190,
LATIN_CAPITAL_LETTER_A_WITH_GRAVE = 192,
LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS = 214,
LATIN_CAPITAL_LETTER_O_WITH_STROKE = 216,
LATIN_SMALL_LETTER_O_WITH_DIAERESIS = 246,
LATIN_SMALL_LETTER_O_WITH_STROKE = 248,
GREEK_SMALL_REVERSED_DOTTED_LUNATE_SIGMA_SYMBOL = 891,
GREEK_CAPITAL_LETTER_YOT = 895,
CP_1FFF = 8191,
ZERO_WIDTH_NON_JOINER = 8204,
ZERO_WIDTH_JOINER = 8205,
UNDERTIE = 8255,
CHARACTER_TIE = 8256,
SUPERSCRIPT_ZERO = 8304,
CP_218F = 8591,
CIRCLED_DIGIT_ONE = 9312,
NEGATIVE_CIRCLED_DIGIT_ZERO = 9471,
GLAGOLITIC_CAPITAL_LETTER_AZU = 11264,
CP_2FEF = 12271,
IDEOGRAPHIC_COMMA = 12289,
CP_D7FF = 55295,
CP_E000 = 57344,
CJK_COMPATIBILITY_IDEOGRAPH_F900 = 63744,
ARABIC_LIGATURE_SALAAMUHU_ALAYNAA = 64975,
ARABIC_LIGATURE_SALLA_USED_AS_KORANIC_STOP_SIGN_ISOLATED_FORM = 65008,
REPLACEMENT_CHARACTER = 65533,
LINEAR_B_SYLLABLE_B008_A = 65536,
CP_EFFFF = 983039,
CP_10FFFF = 1114111
}
/**
* Check whether the code point is a control character.
*/
export declare function isControl(cp: number): boolean;
/**
* Check whether the code point is a whitespace.
*/
export declare function isWhitespace(cp: number): boolean;
/**
* Check whether the code point is a end of line.
*/
export declare function isEOL(cp: number): boolean;
/**
* Check whether the code point is a letter character.
*/
export declare function isLetter(cp: number): boolean;
/**
* Check whether the code point is a digit character.
*/
export declare function isDigit(cp: number): boolean;
/**
* Check whether the code point is a hex digit character.
*/
export declare function isHexDig(cp: number): boolean;
/**
* Check whether the code point is a octal digit character.
*/
export declare function isOctalDig(cp: number): boolean;
/**
* Check whether the code point is a high-surrogate code point.
*/
export declare function isHighSurrogate(cp: number): boolean;
/**
* Check whether the code point is a low-surrogate code point.
*/
export declare function isLowSurrogate(cp: number): boolean;
/**
* Check whether the code point is valid code point.
*
* see
* - https://unicode.org/glossary/#unicode_scalar_value
* - https://toml.io/en/v1.0.0#string
*/
export declare function isUnicodeScalarValue(cp: number): boolean;

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isControl = isControl;
exports.isWhitespace = isWhitespace;
exports.isEOL = isEOL;
exports.isLetter = isLetter;
exports.isDigit = isDigit;
exports.isHexDig = isHexDig;
exports.isOctalDig = isOctalDig;
exports.isHighSurrogate = isHighSurrogate;
exports.isLowSurrogate = isLowSurrogate;
exports.isUnicodeScalarValue = isUnicodeScalarValue;
/**
* Check whether the code point is a control character.
*/
function isControl(cp) {
return cp >= 0 /* CodePoint.NULL */ && cp <= 31 /* CodePoint.US */;
}
/**
* Check whether the code point is a whitespace.
*/
function isWhitespace(cp) {
return cp === 9 /* CodePoint.TABULATION */ || cp === 32 /* CodePoint.SPACE */;
}
/**
* Check whether the code point is a end of line.
*/
function isEOL(cp) {
return cp === 10 /* CodePoint.LINE_FEED */ || cp === 13 /* CodePoint.CARRIAGE_RETURN */;
}
/**
* Check whether the code point is an uppercase letter character.
*/
function isUpperLetter(cp) {
return cp >= 65 /* CodePoint.LATIN_CAPITAL_A */ && cp <= 90 /* CodePoint.LATIN_CAPITAL_Z */;
}
/**
* Check whether the code point is a lowercase letter character.
*/
function isLowerLetter(cp) {
return cp >= 97 /* CodePoint.LATIN_SMALL_A */ && cp <= 122 /* CodePoint.LATIN_SMALL_Z */;
}
/**
* Check whether the code point is a letter character.
*/
function isLetter(cp) {
return isLowerLetter(cp) || isUpperLetter(cp);
}
/**
* Check whether the code point is a digit character.
*/
function isDigit(cp) {
return cp >= 48 /* CodePoint.DIGIT_0 */ && cp <= 57 /* CodePoint.DIGIT_9 */;
}
/**
* Check whether the code point is a hex digit character.
*/
function isHexDig(cp) {
return (isDigit(cp) ||
(cp >= 97 /* CodePoint.LATIN_SMALL_A */ && cp <= 102 /* CodePoint.LATIN_SMALL_F */) ||
(cp >= 65 /* CodePoint.LATIN_CAPITAL_A */ && cp <= 70 /* CodePoint.LATIN_CAPITAL_F */));
}
/**
* Check whether the code point is a octal digit character.
*/
function isOctalDig(cp) {
return cp >= 48 /* CodePoint.DIGIT_0 */ && cp <= 55 /* CodePoint.DIGIT_7 */;
}
/**
* Check whether the code point is a high-surrogate code point.
*/
function isHighSurrogate(cp) {
return cp >= 0xd800 && cp <= 0xdfff;
}
/**
* Check whether the code point is a low-surrogate code point.
*/
function isLowSurrogate(cp) {
return cp >= 0xdc00 && cp <= 0xdfff;
}
/**
* Check whether the code point is valid code point.
*
* see
* - https://unicode.org/glossary/#unicode_scalar_value
* - https://toml.io/en/v1.0.0#string
*/
function isUnicodeScalarValue(cp) {
return (cp >= 0 && cp <= 0xd7ff) || (cp >= 0xe000 && cp <= 0x10ffff);
}

View File

@@ -0,0 +1 @@
export * from "./tokenizer";

View File

@@ -0,0 +1,17 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./tokenizer"), exports);

View File

@@ -0,0 +1,18 @@
type Location = {
line: number;
column: number;
};
/**
* A class for getting lines and columns location.
*/
export declare class Locations {
private readonly offsets;
addOffset(offset: number): void;
/**
* Calculate the location of the given index.
* @param index The index to calculate their location.
* @returns The location of the index.
*/
getLocFromIndex(offset: number): Location;
}
export {};

View File

@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Locations = void 0;
/**
* Find the last index of the array that is less than or equal to the value.
*/
function sortedLastIndex(array, value) {
let low = 0;
let high = array.length;
while (low < high) {
const mid = (low + high) >>> 1;
const val = array[mid];
if (val === value)
return mid + 1;
if (val < value) {
low = mid + 1;
}
else {
high = mid;
}
}
return low;
}
/**
* A class for getting lines and columns location.
*/
class Locations {
constructor() {
this.offsets = [];
}
addOffset(offset) {
// Check for dupe offset
for (let i = this.offsets.length - 1; i >= 0; i--) {
const element = this.offsets[i];
if (element === offset)
return;
if (element < offset)
break;
}
this.offsets.push(offset);
}
/**
* Calculate the location of the given index.
* @param index The index to calculate their location.
* @returns The location of the index.
*/
getLocFromIndex(offset) {
const line = sortedLastIndex(this.offsets, offset) + 1;
const column = offset - (line === 1 ? 0 : this.offsets[line - 2]);
return { line, column };
}
}
exports.Locations = Locations;

View File

@@ -0,0 +1,87 @@
import type { Comment, Token } from "../ast";
import { type ParserOptions } from "../parser-options";
/**
* Tokenizer for TOML.
*/
export declare class Tokenizer {
readonly text: string;
private readonly parserOptions;
private readonly tomlVersion;
private readonly ESCAPES;
private readonly codePointIterator;
private backCode;
private lastCodePoint;
private state;
private token;
private tokenStart;
private data?;
/**
* The flag which enables values tokens.
* If this is true, this tokenizer will generate Integer, Float, Boolean, Offset Date-Time, Local Date-Time ,Local Date, Local Time, Array and Inline Table tokens.
*/
valuesEnabled: boolean;
/**
* Initialize this tokenizer.
*/
constructor(text: string, parserOptions?: ParserOptions);
get start(): number;
get end(): number;
getLocFromIndex(index: number): {
line: number;
column: number;
};
/**
* Report an invalid character error.
*/
private reportParseError;
/**
* Get the next token.
*/
nextToken(): Token | Comment | null;
/**
* Get the next code point.
*/
private nextCode;
/**
* Eat the next code point.
*/
private eatCode;
/**
* Moves the character position to the given position.
*/
private moveAt;
/**
* Back the current code point as the given state.
*/
private back;
private punctuatorToken;
private startToken;
private endToken;
private DATA;
private COMMENT;
private BARE;
private BASIC_STRING;
private MULTI_LINE_BASIC_STRING;
private LITERAL_STRING;
private MULTI_LINE_LITERAL_STRING;
private SIGN;
private NAN_OR_INF;
private NUMBER;
private HEX;
private OCTAL;
private BINARY;
private FRACTIONAL_RIGHT;
private EXPONENT_RIGHT;
private BOOLEAN;
private DATE_MONTH;
private DATE_DAY;
private TIME_HOUR;
private TIME_MINUTE;
private TIME_SECOND;
private TIME_SEC_FRAC;
private processTimeEnd;
private TIME_OFFSET;
private parseDigits;
private parseUnicode;
private reportParseErrorControlChar;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
import type { ErrorCode } from "../errors";
import { Tokenizer } from "../tokenizer";
import type { Comment, Token, TOMLArray, TOMLContentNode, TOMLKeyValue, TOMLNode, TOMLTable, TOMLTopLevelTable } from "../ast";
import type { ParserOptions } from "../parser-options";
export type ValueContainer = {
parent: TOMLKeyValue | TOMLArray;
set(valueNode: TOMLContentNode): ParserState[];
};
export type ParserState = "TABLE" | "VALUE";
export declare class Context {
readonly tokenizer: Tokenizer;
readonly tokens: Token[];
readonly comments: Comment[];
private back;
stateStack: ParserState[];
needNewLine: boolean;
needSameLine: false | ErrorCode;
private currToken;
private prevToken;
topLevelTable: TOMLTopLevelTable;
table: TOMLTopLevelTable | TOMLTable;
private readonly keysResolver;
private readonly valueContainerStack;
constructor(data: {
text: string;
parserOptions?: ParserOptions;
topLevelTable: TOMLTopLevelTable;
});
/**
* Get the next token.
*/
nextToken(option?: {
needSameLine?: ErrorCode;
valuesEnabled?: boolean;
}): Token | null;
private _nextTokenFromTokenizer;
backToken(): void;
addValueContainer(valueContainer: ValueContainer): void;
consumeValueContainer(): ValueContainer;
applyResolveKeyForTable(node: TOMLTable): void;
verifyDuplicateKeys(): void;
/**
* Report an invalid token error.
*/
reportParseError(code: ErrorCode, token: Token | TOMLNode | null): any;
}

View File

@@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = void 0;
const errors_1 = require("../errors");
const tokenizer_1 = require("../tokenizer");
const keys_resolver_1 = require("./keys-resolver");
class Context {
constructor(data) {
this.tokens = [];
this.comments = [];
this.back = null;
this.stateStack = [];
this.needNewLine = false;
this.needSameLine = false;
this.currToken = null;
this.prevToken = null;
this.valueContainerStack = [];
this.tokenizer = new tokenizer_1.Tokenizer(data.text, data.parserOptions);
this.topLevelTable = data.topLevelTable;
this.table = data.topLevelTable;
this.keysResolver = new keys_resolver_1.KeysResolver(this);
}
/**
* Get the next token.
*/
nextToken(option) {
this.prevToken = this.currToken;
if (this.back) {
this.currToken = this.back;
this.back = null;
}
else {
this.currToken = this._nextTokenFromTokenizer(option);
}
if ((this.needNewLine || this.needSameLine || (option === null || option === void 0 ? void 0 : option.needSameLine)) &&
this.prevToken &&
this.currToken) {
if (this.prevToken.loc.end.line === this.currToken.loc.start.line) {
if (this.needNewLine) {
return this.reportParseError("missing-newline", this.currToken);
}
}
else {
const needSameLine = this.needSameLine || (option === null || option === void 0 ? void 0 : option.needSameLine);
if (needSameLine) {
return this.reportParseError(needSameLine, this.currToken);
}
}
}
this.needNewLine = false;
this.needSameLine = false;
return this.currToken;
}
_nextTokenFromTokenizer(option) {
const valuesEnabled = this.tokenizer.valuesEnabled;
if (option === null || option === void 0 ? void 0 : option.valuesEnabled) {
this.tokenizer.valuesEnabled = option.valuesEnabled;
}
let token = this.tokenizer.nextToken();
while (token && token.type === "Block") {
this.comments.push(token);
token = this.tokenizer.nextToken();
}
if (token) {
this.tokens.push(token);
}
this.tokenizer.valuesEnabled = valuesEnabled;
return token;
}
backToken() {
if (this.back) {
throw new Error("Illegal state");
}
this.back = this.currToken;
this.currToken = this.prevToken;
}
addValueContainer(valueContainer) {
this.valueContainerStack.push(valueContainer);
this.tokenizer.valuesEnabled = true;
}
consumeValueContainer() {
const valueContainer = this.valueContainerStack.pop();
this.tokenizer.valuesEnabled = this.valueContainerStack.length > 0;
return valueContainer;
}
applyResolveKeyForTable(node) {
this.keysResolver.applyResolveKeyForTable(node);
}
verifyDuplicateKeys() {
this.keysResolver.verifyDuplicateKeys(this.topLevelTable);
}
/**
* Report an invalid token error.
*/
reportParseError(code, token) {
let offset, line, column;
if (token) {
offset = token.range[0];
line = token.loc.start.line;
column = token.loc.start.column;
}
else {
offset = this.tokenizer.start;
const startPos = this.tokenizer.getLocFromIndex(offset);
line = startPos.line;
column = startPos.column;
}
throw new errors_1.ParseError(code, offset, line, column);
}
}
exports.Context = Context;

View File

@@ -0,0 +1,30 @@
import type { TOMLProgram } from "../ast";
import { type ParserOptions } from "../parser-options";
export declare class TOMLParser {
private readonly text;
private readonly parserOptions;
private readonly tomlVersion;
/**
* Initialize this parser.
*/
constructor(text: string, parserOptions?: ParserOptions);
/**
* Parse TOML
*/
parse(): TOMLProgram;
private TABLE;
private VALUE;
private processTable;
private processKeyValue;
private processKeyNode;
private processBareKey;
private processStringKey;
private processStringValue;
private processNumberValue;
private processBooleanValue;
private processDateTimeValue;
private processArray;
private processArrayValue;
private processInlineTable;
private processInlineTableKeyValue;
}

View File

@@ -0,0 +1,597 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TOMLParser = void 0;
const internal_utils_1 = require("../internal-utils");
const parser_options_1 = require("../parser-options");
const context_1 = require("./context");
const STATE_FOR_ERROR = {
VALUE: "missing-value",
};
const STRING_VALUE_STYLE_MAP = {
BasicString: "basic",
MultiLineBasicString: "basic",
LiteralString: "literal",
MultiLineLiteralString: "literal",
};
const STRING_KEY_STYLE_MAP = {
BasicString: "basic",
LiteralString: "literal",
};
const DATETIME_VALUE_KIND_MAP = {
OffsetDateTime: "offset-date-time",
LocalDateTime: "local-date-time",
LocalDate: "local-date",
LocalTime: "local-time",
};
class TOMLParser {
/**
* Initialize this parser.
*/
constructor(text, parserOptions) {
this.text = text;
this.parserOptions = parserOptions || {};
this.tomlVersion = (0, parser_options_1.getTOMLVer)(this.parserOptions.tomlVersion);
}
/**
* Parse TOML
*/
parse() {
const ast = {
type: "Program",
body: [],
sourceType: "module",
tokens: [],
comments: [],
parent: null,
range: [0, 0],
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 0,
},
},
};
const node = {
type: "TOMLTopLevelTable",
body: [],
parent: ast,
range: cloneRange(ast.range),
loc: cloneLoc(ast.loc),
};
ast.body = [node];
const ctx = new context_1.Context({
text: this.text,
parserOptions: this.parserOptions,
topLevelTable: node,
});
let token = ctx.nextToken();
if (token) {
node.range[0] = token.range[0];
node.loc.start = clonePos(token.loc.start);
while (token) {
const state = ctx.stateStack.pop() || "TABLE";
ctx.stateStack.push(...this[state](token, ctx));
token = ctx.nextToken();
}
const state = ctx.stateStack.pop() || "TABLE";
if (state in STATE_FOR_ERROR) {
return ctx.reportParseError(STATE_FOR_ERROR[state], null);
}
if (ctx.table.type === "TOMLTable") {
applyEndLoc(ctx.table, (0, internal_utils_1.last)(ctx.table.body));
}
applyEndLoc(node, (0, internal_utils_1.last)(node.body));
}
ctx.verifyDuplicateKeys();
ast.tokens = ctx.tokens;
ast.comments = ctx.comments;
const endOffset = ctx.tokenizer.end;
const endPos = ctx.tokenizer.getLocFromIndex(endOffset);
ast.range[1] = endOffset;
ast.loc.end = {
line: endPos.line,
column: endPos.column,
};
return ast;
}
TABLE(token, ctx) {
if (isBare(token) || isString(token)) {
return this.processKeyValue(token, ctx.table, ctx);
}
if (isLeftBracket(token)) {
return this.processTable(token, ctx.topLevelTable, ctx);
}
return ctx.reportParseError("unexpected-token", token);
}
VALUE(token, ctx) {
if (isString(token) || isMultiLineString(token)) {
return this.processStringValue(token, ctx);
}
if (isNumber(token)) {
return this.processNumberValue(token, ctx);
}
if (isBoolean(token)) {
return this.processBooleanValue(token, ctx);
}
if (isDateTime(token)) {
return this.processDateTimeValue(token, ctx);
}
if (isLeftBracket(token)) {
return this.processArray(token, ctx);
}
if (isLeftBrace(token)) {
return this.processInlineTable(token, ctx);
}
return ctx.reportParseError("unexpected-token", token);
}
processTable(token, topLevelTableNode, ctx) {
const tableNode = {
type: "TOMLTable",
kind: "standard",
key: null,
resolvedKey: [],
body: [],
parent: topLevelTableNode,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
if (ctx.table.type === "TOMLTable") {
applyEndLoc(ctx.table, (0, internal_utils_1.last)(ctx.table.body));
}
topLevelTableNode.body.push(tableNode);
ctx.table = tableNode;
let targetToken = ctx.nextToken({
needSameLine: "invalid-key-value-newline",
});
if (isLeftBracket(targetToken)) {
if (token.range[1] < targetToken.range[0]) {
return ctx.reportParseError("invalid-space", targetToken);
}
tableNode.kind = "array";
targetToken = ctx.nextToken({
needSameLine: "invalid-key-value-newline",
});
}
if (isRightBracket(targetToken)) {
return ctx.reportParseError("missing-key", targetToken);
}
if (!targetToken) {
return ctx.reportParseError("unterminated-table-key", null);
}
const keyNodeData = this.processKeyNode(targetToken, tableNode, ctx);
targetToken = keyNodeData.nextToken;
if (!isRightBracket(targetToken)) {
return ctx.reportParseError("unterminated-table-key", targetToken);
}
if (tableNode.kind === "array") {
const rightBracket = targetToken;
targetToken = ctx.nextToken({
needSameLine: "invalid-key-value-newline",
});
if (!isRightBracket(targetToken)) {
return ctx.reportParseError("unterminated-table-key", targetToken);
}
if (rightBracket.range[1] < targetToken.range[0]) {
return ctx.reportParseError("invalid-space", targetToken);
}
}
applyEndLoc(tableNode, targetToken);
ctx.applyResolveKeyForTable(tableNode);
ctx.needNewLine = true;
return [];
}
processKeyValue(token, tableNode, ctx) {
const keyValueNode = {
type: "TOMLKeyValue",
key: null,
value: null,
parent: tableNode,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
tableNode.body.push(keyValueNode);
const { nextToken: targetToken } = this.processKeyNode(token, keyValueNode, ctx);
if (!isEq(targetToken)) {
return ctx.reportParseError("missing-equals-sign", targetToken);
}
ctx.addValueContainer({
parent: keyValueNode,
set: (valNode) => {
keyValueNode.value = valNode;
applyEndLoc(keyValueNode, valNode);
ctx.needNewLine = true;
return [];
},
});
ctx.needSameLine = "invalid-key-value-newline";
return ["VALUE"];
}
processKeyNode(token, parent, ctx) {
const keyNode = {
type: "TOMLKey",
keys: [],
parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
parent.key = keyNode;
let targetToken = token;
while (targetToken) {
if (isBare(targetToken)) {
this.processBareKey(targetToken, keyNode);
}
else if (isString(targetToken)) {
this.processStringKey(targetToken, keyNode);
}
else {
break;
}
targetToken = ctx.nextToken({
needSameLine: "invalid-key-value-newline",
});
if (isDot(targetToken)) {
targetToken = ctx.nextToken({
needSameLine: "invalid-key-value-newline",
});
}
else {
break;
}
}
applyEndLoc(keyNode, (0, internal_utils_1.last)(keyNode.keys));
return { keyNode, nextToken: targetToken };
}
processBareKey(token, keyNode) {
const node = {
type: "TOMLBare",
name: token.value,
parent: keyNode,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
keyNode.keys.push(node);
}
processStringKey(token, keyNode) {
const node = {
type: "TOMLQuoted",
kind: "string",
value: token.string,
style: STRING_KEY_STYLE_MAP[token.type],
multiline: false,
parent: keyNode,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
keyNode.keys.push(node);
}
processStringValue(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const node = {
type: "TOMLValue",
kind: "string",
value: token.string,
style: STRING_VALUE_STYLE_MAP[token.type],
multiline: isMultiLineString(token),
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
return valueContainer.set(node);
}
processNumberValue(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const text = this.text;
const [startRange, endRange] = token.range;
let numberString = null;
/**
* Get the text of number
*/
// eslint-disable-next-line func-style -- ignore
const getNumberText = () => {
return (numberString !== null && numberString !== void 0 ? numberString : (numberString = text.slice(startRange, endRange).replace(/_/g, "")));
};
let node;
if (token.type === "Integer") {
node = {
type: "TOMLValue",
kind: "integer",
value: token.number,
bigint: token.bigint,
get number() {
return getNumberText();
},
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
}
else {
node = {
type: "TOMLValue",
kind: "float",
value: token.number,
get number() {
return getNumberText();
},
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
}
return valueContainer.set(node);
}
processBooleanValue(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const node = {
type: "TOMLValue",
kind: "boolean",
value: token.boolean,
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
return valueContainer.set(node);
}
processDateTimeValue(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const node = {
type: "TOMLValue",
kind: DATETIME_VALUE_KIND_MAP[token.type],
value: token.date,
datetime: token.value,
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
return valueContainer.set(node);
}
processArray(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const node = {
type: "TOMLArray",
elements: [],
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
const nextToken = ctx.nextToken({ valuesEnabled: true });
if (isRightBracket(nextToken)) {
applyEndLoc(node, nextToken);
return valueContainer.set(node);
}
// Back token
ctx.backToken();
return this.processArrayValue(node, valueContainer, ctx);
}
processArrayValue(node, valueContainer, ctx) {
ctx.addValueContainer({
parent: node,
set: (valNode) => {
node.elements.push(valNode);
let nextToken = ctx.nextToken({ valuesEnabled: true });
const hasComma = isComma(nextToken);
if (hasComma) {
nextToken = ctx.nextToken({ valuesEnabled: true });
}
if (isRightBracket(nextToken)) {
applyEndLoc(node, nextToken);
return valueContainer.set(node);
}
if (hasComma) {
// Back token
ctx.backToken();
// setup next value container
return this.processArrayValue(node, valueContainer, ctx);
}
return ctx.reportParseError(nextToken ? "missing-comma" : "unterminated-array", nextToken);
},
});
return ["VALUE"];
}
processInlineTable(token, ctx) {
const valueContainer = ctx.consumeValueContainer();
const node = {
type: "TOMLInlineTable",
body: [],
parent: valueContainer.parent,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
const needSameLine = this.tomlVersion.gte(1, 1)
? // Line breaks in inline tables are allowed.
// Added in TOML 1.1
undefined
: "invalid-inline-table-newline";
const nextToken = ctx.nextToken({
needSameLine,
});
if (nextToken) {
if (isBare(nextToken) || isString(nextToken)) {
return this.processInlineTableKeyValue(nextToken, node, valueContainer, ctx);
}
if (isRightBrace(nextToken)) {
applyEndLoc(node, nextToken);
return valueContainer.set(node);
}
}
return ctx.reportParseError("unexpected-token", nextToken);
}
processInlineTableKeyValue(token, inlineTableNode, valueContainer, ctx) {
const keyValueNode = {
type: "TOMLKeyValue",
key: null,
value: null,
parent: inlineTableNode,
range: cloneRange(token.range),
loc: cloneLoc(token.loc),
};
inlineTableNode.body.push(keyValueNode);
const { nextToken: targetToken } = this.processKeyNode(token, keyValueNode, ctx);
if (!isEq(targetToken)) {
return ctx.reportParseError("missing-equals-sign", targetToken);
}
const needSameLine = this.tomlVersion.gte(1, 1)
? // Line breaks in inline tables are allowed.
// Added in TOML 1.1
undefined
: "invalid-inline-table-newline";
ctx.addValueContainer({
parent: keyValueNode,
set: (valNode) => {
keyValueNode.value = valNode;
applyEndLoc(keyValueNode, valNode);
let nextToken = ctx.nextToken({ needSameLine });
if (isComma(nextToken)) {
nextToken = ctx.nextToken({ needSameLine });
if (nextToken && (isBare(nextToken) || isString(nextToken))) {
// setup next value container
return this.processInlineTableKeyValue(nextToken, inlineTableNode, valueContainer, ctx);
}
if (isRightBrace(nextToken)) {
if (this.tomlVersion.lt(1, 1)) {
return ctx.reportParseError("invalid-trailing-comma-in-inline-table", nextToken);
}
// Trailing commas in inline tables are allowed.
// Added in TOML 1.1
}
else {
return ctx.reportParseError(nextToken ? "unexpected-token" : "unterminated-inline-table", nextToken);
}
}
if (isRightBrace(nextToken)) {
applyEndLoc(inlineTableNode, nextToken);
return valueContainer.set(inlineTableNode);
}
return ctx.reportParseError(nextToken ? "missing-comma" : "unterminated-inline-table", nextToken);
},
});
ctx.needSameLine = "invalid-key-value-newline";
return ["VALUE"];
}
}
exports.TOMLParser = TOMLParser;
/**
* Check whether the given token is a dot.
*/
function isDot(token) {
return isPunctuator(token) && token.value === ".";
}
/**
* Check whether the given token is an equal sign.
*/
function isEq(token) {
return isPunctuator(token) && token.value === "=";
}
/**
* Check whether the given token is a left bracket.
*/
function isLeftBracket(token) {
return isPunctuator(token) && token.value === "[";
}
/**
* Check whether the given token is a right bracket.
*/
function isRightBracket(token) {
return isPunctuator(token) && token.value === "]";
}
/**
* Check whether the given token is a left brace.
*/
function isLeftBrace(token) {
return isPunctuator(token) && token.value === "{";
}
/**
* Check whether the given token is a right brace.
*/
function isRightBrace(token) {
return isPunctuator(token) && token.value === "}";
}
/**
* Check whether the given token is a comma.
*/
function isComma(token) {
return isPunctuator(token) && token.value === ",";
}
/**
* Check whether the given token is a punctuator.
*/
function isPunctuator(token) {
return Boolean(token && token.type === "Punctuator");
}
/**
* Check whether the given token is a bare token.
*/
function isBare(token) {
return token.type === "Bare";
}
/**
* Check whether the given token is a string.
*/
function isString(token) {
return token.type === "BasicString" || token.type === "LiteralString";
}
/**
* Check whether the given token is a multi-line string.
*/
function isMultiLineString(token) {
return (token.type === "MultiLineBasicString" ||
token.type === "MultiLineLiteralString");
}
/**
* Check whether the given token is a number.
*/
function isNumber(token) {
return token.type === "Integer" || token.type === "Float";
}
/**
* Check whether the given token is a boolean.
*/
function isBoolean(token) {
return token.type === "Boolean";
}
/**
* Check whether the given token is a date time.
*/
function isDateTime(token) {
return (token.type === "OffsetDateTime" ||
token.type === "LocalDateTime" ||
token.type === "LocalDate" ||
token.type === "LocalTime");
}
/**
* Apply end locations
*/
function applyEndLoc(node, child) {
if (child) {
node.range[1] = child.range[1];
node.loc.end = clonePos(child.loc.end);
}
}
/**
* clone the location.
*/
function cloneRange(range) {
return [range[0], range[1]];
}
/**
* clone the location.
*/
function cloneLoc(loc) {
return {
start: clonePos(loc.start),
end: clonePos(loc.end),
};
}
/**
* clone the location.
*/
function clonePos(pos) {
return {
line: pos.line,
column: pos.column,
};
}

View File

@@ -0,0 +1,10 @@
import type { TOMLTable, TOMLTopLevelTable } from "../ast";
import type { Context } from "./context";
export declare class KeysResolver {
private readonly rootKeys;
private readonly tables;
private readonly ctx;
constructor(ctx: Context);
applyResolveKeyForTable(node: TOMLTable): void;
verifyDuplicateKeys(node: TOMLTopLevelTable): void;
}

View File

@@ -0,0 +1,216 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeysResolver = void 0;
const internal_utils_1 = require("../internal-utils");
class KeysResolver {
constructor(ctx) {
this.rootKeys = new Map();
this.tables = [];
this.ctx = ctx;
}
applyResolveKeyForTable(node) {
let keys = this.rootKeys;
const peekKeyIndex = node.key.keys.length - 1;
for (let index = 0; index < peekKeyIndex; index++) {
const keyNode = node.key.keys[index];
const keyName = (0, internal_utils_1.toKeyName)(keyNode);
node.resolvedKey.push(keyName);
let keyStore = keys.get(keyName);
if (!keyStore) {
keyStore = { node: keyNode, keys: new Map() };
keys.set(keyName, keyStore);
}
else if (keyStore.table === "array") {
const peekIndex = keyStore.peekIndex;
node.resolvedKey.push(peekIndex);
keyStore = keyStore.keys.get(peekIndex);
}
keys = keyStore.keys;
}
const lastKeyNode = node.key.keys[peekKeyIndex];
const lastKeyName = (0, internal_utils_1.toKeyName)(lastKeyNode);
node.resolvedKey.push(lastKeyName);
const lastKeyStore = keys.get(lastKeyName);
if (!lastKeyStore) {
if (node.kind === "array") {
node.resolvedKey.push(0);
const newKeyStore = {
node: lastKeyNode,
keys: new Map(),
};
keys.set(lastKeyName, {
table: node.kind,
node: lastKeyNode,
keys: new Map([[0, newKeyStore]]),
peekIndex: 0,
});
this.tables.push({ node, keys: newKeyStore.keys });
}
else {
const newKeyStore = {
table: node.kind,
node: lastKeyNode,
keys: new Map(),
};
keys.set(lastKeyName, newKeyStore);
this.tables.push({ node, keys: newKeyStore.keys });
}
}
else if (!lastKeyStore.table) {
if (node.kind === "array") {
// e.g.
// [key.foo]
// [[key]]
this.ctx.reportParseError("dupe-keys", lastKeyNode);
}
else {
const transformKey = {
table: node.kind,
node: lastKeyNode,
keys: lastKeyStore.keys,
};
keys.set(lastKeyName, transformKey);
this.tables.push({ node, keys: transformKey.keys });
}
}
else if (lastKeyStore.table === "array") {
if (node.kind === "array") {
const newKeyStore = {
node: lastKeyNode,
keys: new Map(),
};
const newIndex = lastKeyStore.peekIndex + 1;
node.resolvedKey.push(newIndex);
lastKeyStore.keys.set(newIndex, newKeyStore);
lastKeyStore.peekIndex = newIndex;
this.tables.push({ node, keys: newKeyStore.keys });
}
else {
// e.g.
// [[key]]
// [key]
this.ctx.reportParseError("dupe-keys", lastKeyNode);
}
}
else {
// e.g.
// [key]
// [key]
this.ctx.reportParseError("dupe-keys", lastKeyNode);
}
}
verifyDuplicateKeys(node) {
for (const body of node.body) {
if (body.type === "TOMLKeyValue") {
verifyDuplicateKeysForKeyValue(this.ctx, this.rootKeys, body);
}
}
for (const { node: tableNode, keys } of this.tables) {
for (const body of tableNode.body) {
verifyDuplicateKeysForKeyValue(this.ctx, keys, body);
}
}
}
}
exports.KeysResolver = KeysResolver;
/**
* Verify duplicate keys from TOMLKeyValue
*/
function verifyDuplicateKeysForKeyValue(ctx, defineKeys, node) {
let keys = defineKeys;
const lastKey = (0, internal_utils_1.last)(node.key.keys);
for (const keyNode of node.key.keys) {
const key = (0, internal_utils_1.toKeyName)(keyNode);
let defineKey = keys.get(key);
if (defineKey) {
if (defineKey.value === 0 /* ValueKind.VALUE */) {
// e.g.
// key = 42
// key.foo = 42
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
}
else if (lastKey === keyNode) {
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
}
else if (defineKey.table) {
// e.g.
// key = 42
// [key]
// ---
// [key.foo]
// [key]
// foo.bar = 42
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
}
defineKey.value = 1 /* ValueKind.INTERMEDIATE */;
}
else {
if (lastKey === keyNode) {
const keyStore = {
value: 0 /* ValueKind.VALUE */,
node: keyNode,
keys: new Map(),
};
defineKey = keyStore;
}
else {
const keyStore = {
value: 1 /* ValueKind.INTERMEDIATE */,
node: keyNode,
keys: new Map(),
};
defineKey = keyStore;
}
keys.set(key, defineKey);
}
keys = defineKey.keys;
}
if (node.value.type === "TOMLInlineTable") {
verifyDuplicateKeysForInlineTable(ctx, keys, node.value);
}
else if (node.value.type === "TOMLArray") {
verifyDuplicateKeysForArray(ctx, keys, node.value);
}
}
/**
* Verify duplicate keys from TOMLInlineTable
*/
function verifyDuplicateKeysForInlineTable(ctx, defineKeys, node) {
for (const body of node.body) {
verifyDuplicateKeysForKeyValue(ctx, defineKeys, body);
}
}
/**
* Verify duplicate keys from TOMLArray
*/
function verifyDuplicateKeysForArray(ctx, defineKeys, node) {
const keys = defineKeys;
for (let index = 0; index < node.elements.length; index++) {
const element = node.elements[index];
let defineKey = keys.get(index);
if (defineKey) {
// Probably not possible.
ctx.reportParseError("dupe-keys", getAfterNode(element, defineKey.node));
}
else {
defineKey = {
value: 0 /* ValueKind.VALUE */,
node: element,
keys: new Map(),
};
defineKeys.set(index, defineKey);
if (element.type === "TOMLInlineTable") {
verifyDuplicateKeysForInlineTable(ctx, defineKey.keys, element);
}
else if (element.type === "TOMLArray") {
verifyDuplicateKeysForArray(ctx, defineKey.keys, element);
}
}
}
}
/**
* Get the after node
*/
function getAfterNode(a, b) {
return a.range[0] <= b.range[0] ? b : a;
}

View File

@@ -0,0 +1,25 @@
import type { VisitorKeys } from "eslint-visitor-keys";
import type { TOMLNode } from "./ast";
/**
* Get the keys of the given node to traverse it.
* @param node The node to get.
* @returns The keys to traverse.
*/
export declare function getFallbackKeys(node: any): string[];
/**
* Get the keys of the given node to traverse it.
* @param node The node to get.
* @returns The keys to traverse.
*/
export declare function getKeys(node: any, visitorKeys?: VisitorKeys): string[];
/**
* Get the nodes of the given node.
* @param node The node to get.
*/
export declare function getNodes(node: any, key: string): IterableIterator<TOMLNode>;
export interface Visitor<N> {
visitorKeys?: VisitorKeys;
enterNode(node: N, parent: N | null): void;
leaveNode(node: N, parent: N | null): void;
}
export declare function traverseNodes(node: TOMLNode, visitor: Visitor<TOMLNode>): void;

View File

@@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFallbackKeys = getFallbackKeys;
exports.getKeys = getKeys;
exports.getNodes = getNodes;
exports.traverseNodes = traverseNodes;
const visitor_keys_1 = require("./visitor-keys");
/**
* Check that the given key should be traversed or not.
* @this {Traversable}
* @param key The key to check.
* @returns `true` if the key should be traversed.
*/
function fallbackKeysFilter(key) {
let value = null;
return (key !== "comments" &&
key !== "leadingComments" &&
key !== "loc" &&
key !== "parent" &&
key !== "range" &&
key !== "tokens" &&
key !== "trailingComments" &&
(value = this[key]) !== null &&
typeof value === "object" &&
(typeof value.type === "string" || Array.isArray(value)));
}
/**
* Get the keys of the given node to traverse it.
* @param node The node to get.
* @returns The keys to traverse.
*/
function getFallbackKeys(node) {
return Object.keys(node).filter(fallbackKeysFilter, node);
}
/**
* Get the keys of the given node to traverse it.
* @param node The node to get.
* @returns The keys to traverse.
*/
function getKeys(node, visitorKeys) {
const keys = (visitorKeys || visitor_keys_1.KEYS)[node.type] || getFallbackKeys(node);
return keys.filter((key) => !getNodes(node, key).next().done);
}
/**
* Get the nodes of the given node.
* @param node The node to get.
*/
function* getNodes(node, key) {
const child = node[key];
if (Array.isArray(child)) {
for (const c of child) {
if (isNode(c)) {
yield c;
}
}
}
else if (isNode(child)) {
yield child;
}
}
/**
* Check whether a given value is a node.
* @param x The value to check.
* @returns `true` if the value is a node.
*/
function isNode(x) {
return x !== null && typeof x === "object" && typeof x.type === "string";
}
/**
* Traverse the given node.
* @param node The node to traverse.
* @param parent The parent node.
* @param visitor The node visitor.
*/
function traverse(node, parent, visitor) {
visitor.enterNode(node, parent);
const keys = getKeys(node, visitor.visitorKeys);
for (const key of keys) {
for (const child of getNodes(node, key)) {
traverse(child, node, visitor);
}
}
visitor.leaveNode(node, parent);
}
/**
* Traverse the given AST tree.
* @param node Root node to traverse.
* @param visitor Visitor.
*/
function traverseNodes(node, visitor) {
traverse(node, null, visitor);
}

View File

@@ -0,0 +1,22 @@
import type { TOMLArray, TOMLBare, TOMLContentNode, TOMLInlineTable, TOMLKey, TOMLKeyValue, TOMLNode, TOMLProgram, TOMLQuoted, TOMLStringValue, TOMLTable, TOMLTopLevelTable, TOMLValue } from "./ast";
type TOMLContentValue<V> = V | TOMLContentValue<V>[] | TOMLTableValue<V>;
type TOMLTableValue<V> = {
[key: string]: TOMLContentValue<V>;
};
export type ConvertTOMLValue<V> = {
(node: TOMLValue): V;
(node: TOMLArray): TOMLContentValue<V>[];
(node: TOMLContentNode): TOMLContentValue<V>;
(node: TOMLProgram | TOMLTopLevelTable | TOMLTable | TOMLKeyValue | TOMLInlineTable): TOMLTableValue<V>;
(node: TOMLStringValue | TOMLBare | TOMLQuoted): string;
(node: TOMLKey): string[];
(node: TOMLNode): TOMLContentValue<V> | string | string[];
};
export type GetStaticTOMLValue = ConvertTOMLValue<TOMLValue["value"]>;
/**
* Gets the static value for the given node.
*/
export declare const getStaticTOMLValue: GetStaticTOMLValue;
/** Generates a converter to convert from a node. */
export declare function generateConvertTOMLValue<V>(convertValue: (node: TOMLValue) => V): ConvertTOMLValue<V>;
export {};

View File

@@ -0,0 +1,167 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStaticTOMLValue = void 0;
exports.generateConvertTOMLValue = generateConvertTOMLValue;
const internal_utils_1 = require("./internal-utils");
/**
* Gets the static value for the given node.
*/
exports.getStaticTOMLValue = generateConvertTOMLValue((node) => node.value);
/** Generates a converter to convert from a node. */
function generateConvertTOMLValue(convertValue) {
/**
* Resolve TOML value
*/
function resolveValue(node, baseTable) {
return resolver[node.type](node, baseTable);
}
const resolver = {
Program(node, baseTable = {}) {
return resolveValue(node.body[0], baseTable);
},
TOMLTopLevelTable(node, baseTable = {}) {
for (const body of node.body) {
resolveValue(body, baseTable);
}
return baseTable;
},
TOMLKeyValue(node, baseTable = {}) {
const value = resolveValue(node.value);
set(baseTable, resolveValue(node.key), value);
return baseTable;
},
TOMLTable(node, baseTable = {}) {
const table = getTable(baseTable, resolveValue(node.key), node.kind === "array");
for (const body of node.body) {
resolveValue(body, table);
}
return baseTable;
},
TOMLArray(node) {
return node.elements.map((e) => resolveValue(e));
},
TOMLInlineTable(node) {
const table = {};
for (const body of node.body) {
resolveValue(body, table);
}
return table;
},
TOMLKey(node) {
return node.keys.map((key) => resolveValue(key));
},
TOMLBare(node) {
return node.name;
},
TOMLQuoted(node) {
return node.value;
},
TOMLValue(node) {
return convertValue(node);
},
};
return (node) => resolveValue(node);
}
/**
* Get the table from the table.
*/
function getTable(baseTable, keys, array) {
let target = baseTable;
for (let index = 0; index < keys.length - 1; index++) {
const key = keys[index];
target = getNextTargetFromKey(target, key);
}
const lastKey = (0, internal_utils_1.last)(keys);
const lastTarget = target[lastKey];
if (lastTarget == null) {
const tableValue = {};
target[lastKey] = array ? [tableValue] : tableValue;
return tableValue;
}
if (isValue(lastTarget)) {
// Update because it is an invalid value.
const tableValue = {};
target[lastKey] = array ? [tableValue] : tableValue;
return tableValue;
}
if (!array) {
if (Array.isArray(lastTarget)) {
// Update because it is an invalid value.
const tableValue = {};
target[lastKey] = tableValue;
return tableValue;
}
return lastTarget;
}
if (Array.isArray(lastTarget)) {
// New record
const tableValue = {};
lastTarget.push(tableValue);
return tableValue;
}
// Update because it is an invalid value.
const tableValue = {};
target[lastKey] = [tableValue];
return tableValue;
/** Get next target from key */
function getNextTargetFromKey(currTarget, key) {
const nextTarget = currTarget[key];
if (nextTarget == null) {
const val = {};
currTarget[key] = val;
return val;
}
if (isValue(nextTarget)) {
// Update because it is an invalid value.
const val = {};
currTarget[key] = val;
return val;
}
let resultTarget = nextTarget;
while (Array.isArray(resultTarget)) {
const lastIndex = resultTarget.length - 1;
const nextElement = resultTarget[lastIndex];
if (isValue(nextElement)) {
// Update because it is an invalid value.
const val = {};
resultTarget[lastIndex] = val;
return val;
}
resultTarget = nextElement;
}
return resultTarget;
}
}
/**
* Set the value to the table.
*/
function set(baseTable, keys, value) {
let target = baseTable;
for (let index = 0; index < keys.length - 1; index++) {
const key = keys[index];
const nextTarget = target[key];
if (nextTarget == null) {
const val = {};
target[key] = val;
target = val;
}
else {
if (isValue(nextTarget) || Array.isArray(nextTarget)) {
// Update because it is an invalid value.
const val = {};
target[key] = val;
target = val;
}
else {
target = nextTarget;
}
}
}
target[(0, internal_utils_1.last)(keys)] = value;
}
/**
* Check whether the given value is a value.
*/
function isValue(value) {
return typeof value !== "object" || value instanceof Date;
}

View File

@@ -0,0 +1,2 @@
import type { SourceCode } from "eslint";
export declare const KEYS: SourceCode.VisitorKeys;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KEYS = void 0;
const eslint_visitor_keys_1 = require("eslint-visitor-keys");
const tomlKeys = {
Program: ["body"],
TOMLTopLevelTable: ["body"],
TOMLTable: ["key", "body"],
TOMLKeyValue: ["key", "value"],
TOMLKey: ["keys"],
TOMLArray: ["elements"],
TOMLInlineTable: ["body"],
TOMLBare: [],
TOMLQuoted: [],
TOMLValue: [],
};
exports.KEYS = (0, eslint_visitor_keys_1.unionWith)(tomlKeys);

View File

@@ -0,0 +1,93 @@
{
"name": "toml-eslint-parser",
"version": "0.10.1",
"description": "A TOML parser that produces output compatible with ESLint",
"main": "lib/index.js",
"files": [
"lib"
],
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"scripts": {
"setup": "git submodule update --init",
"prebuild": "npm run -s clean",
"build": "npm run build:meta && npm run build:tsc",
"build:meta": "ts-node --transpile-only ./tools/update-meta.ts",
"build:tsc": "tsc --project ./tsconfig.build.json",
"clean": "rimraf .nyc_output lib coverage",
"lint": "eslint .",
"eslint-fix": "npm run lint -- --fix",
"test": "env-cmd -e tz mocha --require ts-node/register \"tests/src/**/*.ts\" --reporter dot --timeout 60000",
"cover": "nyc --reporter=lcov npm run test",
"debug": "env-cmd -e tz mocha --require ts-node/register/transpile-only \"tests/src/**/*.ts\" --reporter dot",
"preversion": "npm run lint && npm test",
"update-fixtures": "env-cmd -e tz ts-node --transpile-only ./tools/update-fixtures.ts",
"benchmark": "ts-node --transpile-only benchmark/index.ts",
"prerelease": "npm run clean && npm run build",
"release": "changeset publish",
"version:ci": "env-cmd -e version-ci npm run build:meta && changeset version"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ota-meshi/toml-eslint-parser.git"
},
"keywords": [
"toml",
"eslint",
"parser",
"ast"
],
"author": "Yosuke Ota",
"funding": "https://github.com/sponsors/ota-meshi",
"license": "MIT",
"bugs": {
"url": "https://github.com/ota-meshi/toml-eslint-parser/issues"
},
"homepage": "https://github.com/ota-meshi/toml-eslint-parser#readme",
"dependencies": {
"eslint-visitor-keys": "^3.0.0"
},
"devDependencies": {
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.24.2",
"@eslint-community/eslint-plugin-eslint-comments": "^4.3.0",
"@iarna/toml": "^3.0.0",
"@ota-meshi/eslint-plugin": "^0.18.0",
"@types/benchmark": "^2.1.1",
"@types/eslint": "^9.0.0",
"@types/eslint-visitor-keys": "^3.0.0",
"@types/js-yaml": "^4.0.0",
"@types/mocha": "^10.0.0",
"@types/node": "^22.0.0",
"@types/semver": "^7.3.4",
"@typescript-eslint/parser": "^8.0.0",
"benchmark": "^2.1.4",
"env-cmd": "^10.1.0",
"eslint": "^9.5.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-jsdoc": "^50.0.0",
"eslint-plugin-json-schema-validator": "^5.0.0",
"eslint-plugin-jsonc": "^2.0.0",
"eslint-plugin-n": "^17.2.0",
"eslint-plugin-node-dependencies": "^0.12.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-regexp": "^2.0.0",
"eslint-plugin-vue": "^9.0.0",
"eslint-plugin-yml": "^1.0.0",
"js-yaml": "^4.0.0",
"mocha": "^11.0.0",
"nyc": "^17.0.0",
"prettier": "^3.0.0",
"semver": "^7.3.4",
"toml-eslint-parser": "^0.10.0",
"ts-node": "^10.0.0",
"typescript": "~5.8.0",
"typescript-eslint": "^8.0.0",
"vue-eslint-parser": "^10.0.0"
},
"publishConfig": {
"access": "public"
}
}