@stxt-lang/core 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +157 -0
- package/out/all.d.ts +1 -0
- package/out/all.js +6 -4
- package/out/core/Constants.d.ts +8 -0
- package/out/core/Constants.js +8 -0
- package/out/core/Line.d.ts +20 -0
- package/out/core/Line.js +15 -0
- package/out/core/LineParser.d.ts +17 -0
- package/out/core/LineParser.js +27 -10
- package/out/core/NameNamespace.d.ts +9 -0
- package/out/core/NameNamespace.js +9 -0
- package/out/core/NameNamespaceParser.d.ts +11 -0
- package/out/core/NameNamespaceParser.js +16 -5
- package/out/core/NamespaceValidator.d.ts +18 -0
- package/out/core/NamespaceValidator.js +18 -0
- package/out/core/Node.d.ts +55 -0
- package/out/core/Node.js +56 -1
- package/out/core/NodeCreator.d.ts +11 -0
- package/out/core/NodeCreator.js +14 -3
- package/out/core/ParseResult.d.ts +26 -0
- package/out/core/ParseResult.js +26 -0
- package/out/core/Parser.d.ts +31 -0
- package/out/core/Parser.js +50 -19
- package/out/core/StringUtils.d.ts +31 -0
- package/out/core/StringUtils.js +40 -9
- package/out/exceptions/ParseException.d.ts +14 -0
- package/out/exceptions/ParseException.js +12 -0
- package/out/exceptions/RuntimeException.d.ts +14 -0
- package/out/exceptions/RuntimeException.js +13 -0
- package/out/exceptions/ValidationException.d.ts +8 -0
- package/out/exceptions/ValidationException.js +8 -0
- package/out/processors/Observer.d.ts +29 -0
- package/out/processors/Validator.d.ts +9 -0
- package/out/runtime/ConditionalValidator.d.ts +15 -0
- package/out/runtime/ConditionalValidator.js +16 -2
- package/out/runtime/NodeWriter.d.ts +18 -0
- package/out/runtime/NodeWriter.js +18 -0
- package/out/runtime/UnifiedSchemaProvider.d.ts +23 -5
- package/out/runtime/UnifiedSchemaProvider.js +28 -10
- package/out/schema/ChildDefinition.d.ts +18 -0
- package/out/schema/ChildDefinition.js +18 -0
- package/out/schema/NodeDefinition.d.ts +44 -0
- package/out/schema/NodeDefinition.js +47 -3
- package/out/schema/Schema.d.ts +26 -0
- package/out/schema/Schema.js +26 -1
- package/out/schema/SchemaParser.d.ts +7 -0
- package/out/schema/SchemaParser.js +26 -16
- package/out/schema/SchemaProvider.d.ts +7 -0
- package/out/schema/SchemaProviderMemory.d.ts +27 -0
- package/out/schema/SchemaProviderMemory.js +27 -0
- package/out/schema/SchemaProviderMeta.d.ts +16 -0
- package/out/schema/SchemaProviderMeta.js +78 -62
- package/out/schema/SchemaValidator.d.ts +20 -0
- package/out/schema/SchemaValidator.js +27 -7
- package/out/schema/Type.d.ts +9 -0
- package/out/schema/TypeRegistry.d.ts +13 -0
- package/out/schema/TypeRegistry.js +18 -5
- package/out/schema/type/BASE64.d.ts +1 -0
- package/out/schema/type/BASE64.js +5 -4
- package/out/schema/type/BINARY.d.ts +1 -0
- package/out/schema/type/BINARY.js +2 -1
- package/out/schema/type/BLOCK.d.ts +1 -0
- package/out/schema/type/BLOCK.js +2 -1
- package/out/schema/type/BOOLEAN.d.ts +1 -0
- package/out/schema/type/BOOLEAN.js +1 -0
- package/out/schema/type/DATE.d.ts +1 -0
- package/out/schema/type/DATE.js +1 -0
- package/out/schema/type/EMAIL.d.ts +1 -0
- package/out/schema/type/EMAIL.js +1 -0
- package/out/schema/type/ENUM.d.ts +1 -0
- package/out/schema/type/ENUM.js +2 -1
- package/out/schema/type/GROUP.d.ts +1 -0
- package/out/schema/type/GROUP.js +2 -1
- package/out/schema/type/HEXADECIMAL.d.ts +1 -0
- package/out/schema/type/HEXADECIMAL.js +2 -1
- package/out/schema/type/INLINE.d.ts +1 -0
- package/out/schema/type/INLINE.js +2 -1
- package/out/schema/type/INTEGER.d.ts +1 -0
- package/out/schema/type/INTEGER.js +1 -0
- package/out/schema/type/MARKDOWN.d.ts +4 -0
- package/out/schema/type/MARKDOWN.js +4 -2
- package/out/schema/type/NATURAL.d.ts +1 -0
- package/out/schema/type/NATURAL.js +1 -0
- package/out/schema/type/NUMBER.d.ts +1 -0
- package/out/schema/type/NUMBER.js +1 -0
- package/out/schema/type/TEXT.d.ts +1 -0
- package/out/schema/type/TEXT.js +1 -0
- package/out/schema/type/TIME.d.ts +1 -0
- package/out/schema/type/TIME.js +1 -0
- package/out/schema/type/TIMESTAMP.d.ts +1 -0
- package/out/schema/type/TIMESTAMP.js +1 -0
- package/out/schema/type/URL.d.ts +1 -0
- package/out/schema/type/URL.js +2 -1
- package/out/schema/type/UUID.d.ts +1 -0
- package/out/schema/type/UUID.js +1 -0
- package/out/schema/type/binaryValue.d.ts +9 -0
- package/out/schema/type/binaryValue.js +9 -3
- package/out/schema/type/regexType.d.ts +8 -0
- package/out/schema/type/regexType.js +9 -1
- package/out/template/ChildLine.d.ts +14 -0
- package/out/template/ChildLine.js +14 -0
- package/out/template/ChildLineParser.d.ts +10 -0
- package/out/template/ChildLineParser.js +17 -8
- package/out/template/MetaTemplateSchemaProvider.d.ts +16 -0
- package/out/template/MetaTemplateSchemaProvider.js +22 -6
- package/out/template/TemplateParser.d.ts +8 -0
- package/out/template/TemplateParser.js +49 -39
- package/out/template/TemplateSchemaProviderMemory.d.ts +18 -0
- package/out/template/TemplateSchemaProviderMemory.js +21 -3
- package/package.json +60 -45
- package/out/all.js.map +0 -1
- package/out/core/Constants.js.map +0 -1
- package/out/core/Line.js.map +0 -1
- package/out/core/LineParser.js.map +0 -1
- package/out/core/NameNamespace.js.map +0 -1
- package/out/core/NameNamespaceParser.js.map +0 -1
- package/out/core/NamespaceValidator.js.map +0 -1
- package/out/core/Node.js.map +0 -1
- package/out/core/NodeCreator.js.map +0 -1
- package/out/core/ParseResult.js.map +0 -1
- package/out/core/Parser.js.map +0 -1
- package/out/core/StringUtils.js.map +0 -1
- package/out/exceptions/ParseException.js.map +0 -1
- package/out/exceptions/RuntimeException.js.map +0 -1
- package/out/exceptions/ValidationException.js.map +0 -1
- package/out/processors/Observer.js.map +0 -1
- package/out/processors/Validator.js.map +0 -1
- package/out/runtime/ConditionalValidator.js.map +0 -1
- package/out/runtime/NodeWriter.js.map +0 -1
- package/out/runtime/UnifiedSchemaProvider.js.map +0 -1
- package/out/schema/ChildDefinition.js.map +0 -1
- package/out/schema/NodeDefinition.js.map +0 -1
- package/out/schema/Schema.js.map +0 -1
- package/out/schema/SchemaParser.js.map +0 -1
- package/out/schema/SchemaProvider.js.map +0 -1
- package/out/schema/SchemaProviderMemory.js.map +0 -1
- package/out/schema/SchemaProviderMeta.js.map +0 -1
- package/out/schema/SchemaValidator.js.map +0 -1
- package/out/schema/Type.js.map +0 -1
- package/out/schema/TypeRegistry.js.map +0 -1
- package/out/schema/type/BASE64.js.map +0 -1
- package/out/schema/type/BINARY.js.map +0 -1
- package/out/schema/type/BLOCK.js.map +0 -1
- package/out/schema/type/BOOLEAN.js.map +0 -1
- package/out/schema/type/DATE.js.map +0 -1
- package/out/schema/type/EMAIL.js.map +0 -1
- package/out/schema/type/ENUM.js.map +0 -1
- package/out/schema/type/GROUP.js.map +0 -1
- package/out/schema/type/HEXADECIMAL.js.map +0 -1
- package/out/schema/type/INLINE.js.map +0 -1
- package/out/schema/type/INTEGER.js.map +0 -1
- package/out/schema/type/MARKDOWN.js.map +0 -1
- package/out/schema/type/NATURAL.js.map +0 -1
- package/out/schema/type/NUMBER.js.map +0 -1
- package/out/schema/type/TEXT.js.map +0 -1
- package/out/schema/type/TIME.js.map +0 -1
- package/out/schema/type/TIMESTAMP.js.map +0 -1
- package/out/schema/type/URL.js.map +0 -1
- package/out/schema/type/UUID.js.map +0 -1
- package/out/schema/type/binaryValue.js.map +0 -1
- package/out/schema/type/regexType.js.map +0 -1
- package/out/template/ChildLine.js.map +0 -1
- package/out/template/ChildLineParser.js.map +0 -1
- package/out/template/MetaTemplateSchemaProvider.js.map +0 -1
- package/out/template/TemplateParser.js.map +0 -1
- package/out/template/TemplateSchemaProviderMemory.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 stxt-lang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @stxt-lang/core
|
|
2
|
+
|
|
3
|
+
Parser and schema validator for **STXT**, an indentation-based structured-text format.
|
|
4
|
+
|
|
5
|
+
STXT is a plain-text format for writing structured, semantic documents: no braces, no closing tags, just indentation. It is designed to be equally readable by humans and by machines, and it comes with an optional schema layer so documents can be validated.
|
|
6
|
+
|
|
7
|
+
- Website and language reference: <https://stxt.dev>
|
|
8
|
+
- VSCode extension: [STXT - Semantic Text](https://marketplace.visualstudio.com/items?itemName=stxt-lang.stxt)
|
|
9
|
+
- Java implementation: [`dev.stxt:stxt-core`](https://central.sonatype.com/artifact/dev.stxt/stxt-core) on Maven Central
|
|
10
|
+
|
|
11
|
+
## What STXT looks like
|
|
12
|
+
|
|
13
|
+
```stxt
|
|
14
|
+
# A line starting with '#' is a comment
|
|
15
|
+
|
|
16
|
+
Article (blog.post):
|
|
17
|
+
Title: Getting started with STXT
|
|
18
|
+
Author: Joan
|
|
19
|
+
Published: 2026-07-28
|
|
20
|
+
Tags:
|
|
21
|
+
Tag: parser
|
|
22
|
+
Tag: text-format
|
|
23
|
+
Body >>
|
|
24
|
+
Everything indented under a '>>' node is kept verbatim
|
|
25
|
+
as a block of text lines.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `Name: value` declares an **inline node**.
|
|
29
|
+
- `Name >>` opens a **text block**; every deeper-indented line belongs to it.
|
|
30
|
+
- Indentation is **one level per tab or per 4 spaces**.
|
|
31
|
+
- `Name (a.b.c):` attaches a **namespace** to a node; children inherit it unless they declare their own.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @stxt-lang/core
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The package ships CommonJS plus type declarations, so it works from both TypeScript and plain Node.
|
|
40
|
+
|
|
41
|
+
## Parsing
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { Parser, ParseResult, Node } from '@stxt-lang/core';
|
|
45
|
+
|
|
46
|
+
const text = [
|
|
47
|
+
'Article (blog.post):',
|
|
48
|
+
'\tTitle: Getting started with STXT',
|
|
49
|
+
'\tAuthor: Joan',
|
|
50
|
+
].join('\n');
|
|
51
|
+
|
|
52
|
+
const parser = new Parser();
|
|
53
|
+
|
|
54
|
+
// parseResult() collects every error instead of stopping at the first one
|
|
55
|
+
const result: ParseResult = parser.parseResult(text);
|
|
56
|
+
|
|
57
|
+
if (result.hasErrors()) {
|
|
58
|
+
for (const error of result.getErrors()) {
|
|
59
|
+
console.error(`line ${error.line} [${error.code}]: ${error.message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const article: Node = result.getNodes()[0];
|
|
64
|
+
|
|
65
|
+
console.log(article.getName()); // "Article"
|
|
66
|
+
console.log(article.getNamespace()); // "blog.post"
|
|
67
|
+
console.log(article.getChild('Title')?.getValue()); // "Getting started with STXT"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use `parser.parse(text)` instead if you prefer an exception (`ParseException`) on the first error.
|
|
71
|
+
|
|
72
|
+
Nodes are **frozen once parsed** — treat the tree as immutable.
|
|
73
|
+
|
|
74
|
+
## Validating against a schema
|
|
75
|
+
|
|
76
|
+
Schemas are themselves STXT documents, written in the reserved `@stxt.schema` namespace (or in the friendlier `@stxt.template` form, which compiles to a schema). `UnifiedSchemaProvider` loads either kind, validates it against the corresponding meta-schema, and registers it by namespace.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import {
|
|
80
|
+
Parser,
|
|
81
|
+
UnifiedSchemaProvider,
|
|
82
|
+
SchemaValidator,
|
|
83
|
+
ConditionalValidator,
|
|
84
|
+
ValidationException,
|
|
85
|
+
} from '@stxt-lang/core';
|
|
86
|
+
|
|
87
|
+
const schemaText = `
|
|
88
|
+
Schema (@stxt.schema): blog.post
|
|
89
|
+
\tNode: Article
|
|
90
|
+
\t\tChildren:
|
|
91
|
+
\t\t\tChild: Title
|
|
92
|
+
\t\t\t\tMin: 1
|
|
93
|
+
\t\t\t\tMax: 1
|
|
94
|
+
\t\t\tChild: Author
|
|
95
|
+
\t\t\t\tMin: 1
|
|
96
|
+
\tNode: Title
|
|
97
|
+
\tNode: Author
|
|
98
|
+
`;
|
|
99
|
+
|
|
100
|
+
const provider = new UnifiedSchemaProvider();
|
|
101
|
+
provider.addFile(schemaText);
|
|
102
|
+
|
|
103
|
+
const parser = new Parser();
|
|
104
|
+
// ConditionalValidator only validates nodes that carry a namespace
|
|
105
|
+
parser.registerValidator(new ConditionalValidator(new SchemaValidator(provider)));
|
|
106
|
+
|
|
107
|
+
const result = parser.parseResult(documentText);
|
|
108
|
+
|
|
109
|
+
for (const error of result.getErrors()) {
|
|
110
|
+
// Schema problems are ValidationException; syntax problems are plain ParseException
|
|
111
|
+
const severity = error instanceof ValidationException ? 'warning' : 'error';
|
|
112
|
+
console.log(`${severity} at line ${error.line} [${error.code}]: ${error.message}`);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Available value types: `INLINE`, `BLOCK`, `TEXT`, `BOOLEAN`, `INTEGER`, `NATURAL`, `NUMBER`, `DATE`, `TIMESTAMP`, `EMAIL`, `URL`, `HEXADECIMAL`, `BASE64`, `GROUP`, `ENUM`.
|
|
117
|
+
|
|
118
|
+
## Observing the parse
|
|
119
|
+
|
|
120
|
+
`Observer` receives streaming callbacks while the document is parsed — useful for syntax highlighting, indexes or any per-line bookkeeping.
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { Parser, Observer, Node, Line } from '@stxt-lang/core';
|
|
124
|
+
|
|
125
|
+
class LoggingObserver implements Observer {
|
|
126
|
+
onCreate(node: Node, line: string): void {
|
|
127
|
+
console.log('open', node.getQualifiedName());
|
|
128
|
+
}
|
|
129
|
+
onFinish(node: Node): void {
|
|
130
|
+
console.log('close', node.getQualifiedName());
|
|
131
|
+
}
|
|
132
|
+
onComment(lineNumber: number, line: string): void { /* ... */ }
|
|
133
|
+
onTextLine(node: Node, lineNumber: number, lineString: string, line: Line): void { /* ... */ }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const parser = new Parser();
|
|
137
|
+
parser.registerObserver(new LoggingObserver());
|
|
138
|
+
parser.parseResult(text);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Writing STXT back out
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { NodeWriter, IndentStyle } from '@stxt-lang/core';
|
|
145
|
+
|
|
146
|
+
// A single node, or a whole document list
|
|
147
|
+
const text = NodeWriter.toSTXT(node, IndentStyle.TABS);
|
|
148
|
+
const doc = NodeWriter.toSTXTDocs(result.getNodes(), IndentStyle.SPACES_4);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## API surface
|
|
152
|
+
|
|
153
|
+
Everything importable from the package: `Node`, `Parser`, `ParseResult`, `Line`, `Constants`, `parseLine`, `StringUtils`, `ParseException`, `ValidationException`, `Observer`, `Schema`, `SchemaValidator`, `SchemaProvider`, `NodeDefinition`, `ChildDefinition`, `transformNodeToSchema`, `UnifiedSchemaProvider`, `ConditionalValidator`, `NodeWriter`, `IndentStyle`, `transformTemplateNodeToSchema`.
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT — see [LICENSE](LICENSE).
|
package/out/all.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { Constants } from "./core/Constants";
|
|
|
6
6
|
export { parseLine } from "./core/LineParser";
|
|
7
7
|
export { StringUtils } from "./core/StringUtils";
|
|
8
8
|
export { ParseException } from "./exceptions/ParseException";
|
|
9
|
+
export { ValidationException } from "./exceptions/ValidationException";
|
|
9
10
|
export { Observer } from "./processors/Observer";
|
|
10
11
|
export { Schema } from "./schema/Schema";
|
|
11
12
|
export { SchemaValidator } from "./schema/SchemaValidator";
|
package/out/all.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// Public entry point of the package (out/all.js / out/all.d.ts).
|
|
3
|
+
// Anything that should be consumable by third parties (e.g. the VSCode extension)
|
|
4
|
+
// has to be re-exported from here.
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.transformTemplateNodeToSchema = exports.IndentStyle = exports.NodeWriter = exports.ConditionalValidator = exports.UnifiedSchemaProvider = exports.transformNodeToSchema = exports.ChildDefinition = exports.NodeDefinition = exports.SchemaValidator = exports.Schema = exports.ParseException = exports.StringUtils = exports.parseLine = exports.Constants = exports.Line = exports.ParseResult = exports.Parser = exports.Node = void 0;
|
|
6
|
+
exports.transformTemplateNodeToSchema = exports.IndentStyle = exports.NodeWriter = exports.ConditionalValidator = exports.UnifiedSchemaProvider = exports.transformNodeToSchema = exports.ChildDefinition = exports.NodeDefinition = exports.SchemaValidator = exports.Schema = exports.ValidationException = exports.ParseException = exports.StringUtils = exports.parseLine = exports.Constants = exports.Line = exports.ParseResult = exports.Parser = exports.Node = void 0;
|
|
7
7
|
var Node_1 = require("./core/Node");
|
|
8
8
|
Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return Node_1.Node; } });
|
|
9
9
|
var Parser_1 = require("./core/Parser");
|
|
@@ -20,6 +20,8 @@ var StringUtils_1 = require("./core/StringUtils");
|
|
|
20
20
|
Object.defineProperty(exports, "StringUtils", { enumerable: true, get: function () { return StringUtils_1.StringUtils; } });
|
|
21
21
|
var ParseException_1 = require("./exceptions/ParseException");
|
|
22
22
|
Object.defineProperty(exports, "ParseException", { enumerable: true, get: function () { return ParseException_1.ParseException; } });
|
|
23
|
+
var ValidationException_1 = require("./exceptions/ValidationException");
|
|
24
|
+
Object.defineProperty(exports, "ValidationException", { enumerable: true, get: function () { return ValidationException_1.ValidationException; } });
|
|
23
25
|
var Schema_1 = require("./schema/Schema");
|
|
24
26
|
Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return Schema_1.Schema; } });
|
|
25
27
|
var SchemaValidator_1 = require("./schema/SchemaValidator");
|
package/out/core/Constants.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
/** Characters and sizes fixed by STXT-SPEC that the parser and the writer share. */
|
|
1
2
|
export declare class Constants {
|
|
3
|
+
/** Character that opens a comment line. */
|
|
2
4
|
static readonly COMMENT_CHAR: string;
|
|
5
|
+
/** Number of spaces that make up one indentation level. */
|
|
3
6
|
static readonly TAB_SPACES: number;
|
|
7
|
+
/** Tab character, the other way of indenting one level. */
|
|
4
8
|
static readonly TAB: string;
|
|
9
|
+
/** Space character. */
|
|
5
10
|
static readonly SPACE: string;
|
|
11
|
+
/** Separator between the name and the value of an INLINE node. */
|
|
6
12
|
static readonly SEP_NODE: string;
|
|
13
|
+
/** Marker that turns a node into a BLOCK text node. */
|
|
7
14
|
static readonly SEP_TEXT_NODE: string;
|
|
15
|
+
/** Namespace of a node that declares none and inherits none. */
|
|
8
16
|
static readonly EMPTY_NAMESPACE: string;
|
|
9
17
|
}
|
package/out/core/Constants.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Constants = void 0;
|
|
4
|
+
/** Characters and sizes fixed by STXT-SPEC that the parser and the writer share. */
|
|
4
5
|
class Constants {
|
|
5
6
|
}
|
|
6
7
|
exports.Constants = Constants;
|
|
8
|
+
/** Character that opens a comment line. */
|
|
7
9
|
Constants.COMMENT_CHAR = "#";
|
|
10
|
+
/** Number of spaces that make up one indentation level. */
|
|
8
11
|
Constants.TAB_SPACES = 4;
|
|
12
|
+
/** Tab character, the other way of indenting one level. */
|
|
9
13
|
Constants.TAB = "\t";
|
|
14
|
+
/** Space character. */
|
|
10
15
|
Constants.SPACE = " ";
|
|
16
|
+
/** Separator between the name and the value of an INLINE node. */
|
|
11
17
|
Constants.SEP_NODE = ":";
|
|
18
|
+
/** Marker that turns a node into a BLOCK text node. */
|
|
12
19
|
Constants.SEP_TEXT_NODE = ">>";
|
|
20
|
+
/** Namespace of a node that declares none and inherits none. */
|
|
13
21
|
Constants.EMPTY_NAMESPACE = "";
|
|
14
22
|
//# sourceMappingURL=Constants.js.map
|
package/out/core/Line.d.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A source line already split into its indentation and its content, as produced by
|
|
3
|
+
* {@link parseLine}. It is what tells the {@link Parser} whether the line opens a node, continues
|
|
4
|
+
* a text block or is just a comment.
|
|
5
|
+
*/
|
|
1
6
|
export declare class Line {
|
|
7
|
+
/** Indentation level of the line (one level per tab or per {@link Constants.TAB_SPACES} spaces). */
|
|
2
8
|
readonly level: number;
|
|
9
|
+
/** Content of the line with the indentation already removed. */
|
|
3
10
|
readonly content: string;
|
|
11
|
+
/** True if the line is a comment (`#`). */
|
|
4
12
|
readonly isComment: boolean;
|
|
13
|
+
/** True if the line is a text line belonging to an open BLOCK node (`>>`). */
|
|
5
14
|
readonly isBlock: boolean;
|
|
15
|
+
/** Number of characters the indentation took up. */
|
|
6
16
|
readonly indentLength: number;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a line already split into indentation and content.
|
|
19
|
+
*
|
|
20
|
+
* @param level indentation level of the line.
|
|
21
|
+
* @param content content of the line without its indentation.
|
|
22
|
+
* @param isComment true if the line is a comment.
|
|
23
|
+
* @param isBlock true if the line belongs to an open text block.
|
|
24
|
+
* @param indentLength number of characters the indentation took up.
|
|
25
|
+
*/
|
|
7
26
|
constructor(level: number, content: string, isComment: boolean, isBlock: boolean, indentLength: number);
|
|
27
|
+
/** @returns true if the line has no content beyond whitespace. */
|
|
8
28
|
isEmpty(): boolean;
|
|
9
29
|
}
|
package/out/core/Line.js
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Line = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A source line already split into its indentation and its content, as produced by
|
|
6
|
+
* {@link parseLine}. It is what tells the {@link Parser} whether the line opens a node, continues
|
|
7
|
+
* a text block or is just a comment.
|
|
8
|
+
*/
|
|
4
9
|
class Line {
|
|
10
|
+
/**
|
|
11
|
+
* Creates a line already split into indentation and content.
|
|
12
|
+
*
|
|
13
|
+
* @param level indentation level of the line.
|
|
14
|
+
* @param content content of the line without its indentation.
|
|
15
|
+
* @param isComment true if the line is a comment.
|
|
16
|
+
* @param isBlock true if the line belongs to an open text block.
|
|
17
|
+
* @param indentLength number of characters the indentation took up.
|
|
18
|
+
*/
|
|
5
19
|
constructor(level, content, isComment, isBlock, indentLength) {
|
|
6
20
|
this.level = level;
|
|
7
21
|
this.content = content;
|
|
@@ -9,6 +23,7 @@ class Line {
|
|
|
9
23
|
this.isBlock = isBlock;
|
|
10
24
|
this.indentLength = indentLength;
|
|
11
25
|
}
|
|
26
|
+
/** @returns true if the line has no content beyond whitespace. */
|
|
12
27
|
isEmpty() {
|
|
13
28
|
return this.content.trim() === "";
|
|
14
29
|
}
|
package/out/core/LineParser.d.ts
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
1
|
import { Line } from "./Line";
|
|
2
|
+
/**
|
|
3
|
+
* Splits a source line into its indentation and its content, and classifies it as a comment, a
|
|
4
|
+
* text line of an open block or a regular line.
|
|
5
|
+
*
|
|
6
|
+
* Indentation is one level per tab or per {@link Constants.TAB_SPACES} spaces; mixing both, using
|
|
7
|
+
* a number of spaces that is not a multiple of four or going more than one level deeper than the
|
|
8
|
+
* previous node are errors (spec 8.1 and 8.3).
|
|
9
|
+
*
|
|
10
|
+
* @param line source line, with its indentation.
|
|
11
|
+
* @param lastNodeBlock true if the node currently open is a BLOCK text node.
|
|
12
|
+
* @param lastLevel indentation level of the node currently open.
|
|
13
|
+
* @param numLine line number, for the error messages.
|
|
14
|
+
* @param validate false to split the line without enforcing the indentation rules.
|
|
15
|
+
* @returns the line already split into indentation and content.
|
|
16
|
+
* @throws ParseException with code `MIXED_INDENTATION`, `INVALID_NUMBER_SPACES` or
|
|
17
|
+
* `INDENTATION_LEVEL_NOT_VALID` if the indentation is not valid.
|
|
18
|
+
*/
|
|
2
19
|
export declare function parseLine(line: string, lastNodeBlock: boolean, lastLevel: number, numLine: number, validate?: boolean): Line;
|
package/out/core/LineParser.js
CHANGED
|
@@ -5,6 +5,23 @@ const Constants_1 = require("./Constants");
|
|
|
5
5
|
const StringUtils_1 = require("./StringUtils");
|
|
6
6
|
const ParseException_1 = require("../exceptions/ParseException");
|
|
7
7
|
const Line_1 = require("./Line");
|
|
8
|
+
/**
|
|
9
|
+
* Splits a source line into its indentation and its content, and classifies it as a comment, a
|
|
10
|
+
* text line of an open block or a regular line.
|
|
11
|
+
*
|
|
12
|
+
* Indentation is one level per tab or per {@link Constants.TAB_SPACES} spaces; mixing both, using
|
|
13
|
+
* a number of spaces that is not a multiple of four or going more than one level deeper than the
|
|
14
|
+
* previous node are errors (spec 8.1 and 8.3).
|
|
15
|
+
*
|
|
16
|
+
* @param line source line, with its indentation.
|
|
17
|
+
* @param lastNodeBlock true if the node currently open is a BLOCK text node.
|
|
18
|
+
* @param lastLevel indentation level of the node currently open.
|
|
19
|
+
* @param numLine line number, for the error messages.
|
|
20
|
+
* @param validate false to split the line without enforcing the indentation rules.
|
|
21
|
+
* @returns the line already split into indentation and content.
|
|
22
|
+
* @throws ParseException with code `MIXED_INDENTATION`, `INVALID_NUMBER_SPACES` or
|
|
23
|
+
* `INDENTATION_LEVEL_NOT_VALID` if the indentation is not valid.
|
|
24
|
+
*/
|
|
8
25
|
function parseLine(line, lastNodeBlock, lastLevel, numLine, validate = true) {
|
|
9
26
|
let level = 0;
|
|
10
27
|
let spaces = 0;
|
|
@@ -30,23 +47,23 @@ function parseLine(line, lastNodeBlock, lastLevel, numLine, validate = true) {
|
|
|
30
47
|
return new Line_1.Line(level, line.substring(pointer + 1), true, false, pointer);
|
|
31
48
|
}
|
|
32
49
|
else {
|
|
33
|
-
//
|
|
50
|
+
// First character that is not space/tab/comment => end of indentation
|
|
34
51
|
break;
|
|
35
52
|
}
|
|
36
|
-
//
|
|
53
|
+
// Inside the text block
|
|
37
54
|
if (lastNodeBlock && level > lastLevel) {
|
|
38
55
|
const text = StringUtils_1.StringUtils.rightTrim(line.substring(pointer + 1));
|
|
39
|
-
//
|
|
40
|
-
//
|
|
56
|
+
// The prefix covering the block level must be homogeneous (spec 10.2, rule 2);
|
|
57
|
+
// empty lines are always preserved and are exempt from it (spec 10.3)
|
|
41
58
|
if (validate && sawSpace && sawTab && text.length > 0) {
|
|
42
59
|
throw new ParseException_1.ParseException(numLine, "MIXED_INDENTATION", `Mixed tabs and spaces in indentation`);
|
|
43
60
|
}
|
|
44
61
|
return new Line_1.Line(level, text, false, true, pointer);
|
|
45
62
|
}
|
|
46
|
-
//
|
|
63
|
+
// Move the pointer forward
|
|
47
64
|
pointer++;
|
|
48
65
|
}
|
|
49
|
-
//
|
|
66
|
+
// From here on we are outside the text block (if there was one)
|
|
50
67
|
// Empty
|
|
51
68
|
if (pointer === line.length) {
|
|
52
69
|
if (lastNodeBlock) {
|
|
@@ -54,19 +71,19 @@ function parseLine(line, lastNodeBlock, lastLevel, numLine, validate = true) {
|
|
|
54
71
|
}
|
|
55
72
|
return new Line_1.Line(level, "", false, false, pointer);
|
|
56
73
|
}
|
|
57
|
-
//
|
|
74
|
+
// Tabs and spaces mixed in the indentation (spec 8.1 and 8.3)
|
|
58
75
|
if (validate && sawSpace && sawTab) {
|
|
59
76
|
throw new ParseException_1.ParseException(numLine, "MIXED_INDENTATION", `Mixed tabs and spaces in indentation`);
|
|
60
77
|
}
|
|
61
|
-
//
|
|
78
|
+
// Indentation with spaces that is not a multiple of 4
|
|
62
79
|
if (validate && spaces > 0) {
|
|
63
80
|
throw new ParseException_1.ParseException(numLine, "INVALID_NUMBER_SPACES", `There are ${spaces} spaces before node`);
|
|
64
81
|
}
|
|
65
|
-
//
|
|
82
|
+
// Validate the level
|
|
66
83
|
if (validate && level > lastLevel + 1) {
|
|
67
84
|
throw new ParseException_1.ParseException(numLine, "INDENTATION_LEVEL_NOT_VALID", `Level of indent incorrect: ${level}`);
|
|
68
85
|
}
|
|
69
|
-
//
|
|
86
|
+
// General case: return the line without the indentation already consumed
|
|
70
87
|
return new Line_1.Line(level, line.substring(pointer).trim(), false, false, pointer);
|
|
71
88
|
}
|
|
72
89
|
//# sourceMappingURL=LineParser.js.map
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
/** Result of splitting a raw node name into its resolved name and namespace. */
|
|
1
2
|
export declare class NameNamespace {
|
|
2
3
|
private readonly name;
|
|
3
4
|
private readonly namespace;
|
|
5
|
+
/**
|
|
6
|
+
* Creates a resolved name and namespace pair.
|
|
7
|
+
*
|
|
8
|
+
* @param name name of the node without the namespace part.
|
|
9
|
+
* @param namespace resolved namespace (its own or inherited).
|
|
10
|
+
*/
|
|
4
11
|
constructor(name: string, namespace: string);
|
|
12
|
+
/** @returns the name of the node, without the namespace part. */
|
|
5
13
|
getName(): string;
|
|
14
|
+
/** @returns the resolved namespace (its own or inherited from the parent), or the empty string if it has none. */
|
|
6
15
|
getNamespace(): string;
|
|
7
16
|
}
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NameNamespace = void 0;
|
|
4
|
+
/** Result of splitting a raw node name into its resolved name and namespace. */
|
|
4
5
|
class NameNamespace {
|
|
6
|
+
/**
|
|
7
|
+
* Creates a resolved name and namespace pair.
|
|
8
|
+
*
|
|
9
|
+
* @param name name of the node without the namespace part.
|
|
10
|
+
* @param namespace resolved namespace (its own or inherited).
|
|
11
|
+
*/
|
|
5
12
|
constructor(name, namespace) {
|
|
6
13
|
this.name = name;
|
|
7
14
|
this.namespace = namespace;
|
|
8
15
|
}
|
|
16
|
+
/** @returns the name of the node, without the namespace part. */
|
|
9
17
|
getName() {
|
|
10
18
|
return this.name;
|
|
11
19
|
}
|
|
20
|
+
/** @returns the resolved namespace (its own or inherited from the parent), or the empty string if it has none. */
|
|
12
21
|
getNamespace() {
|
|
13
22
|
return this.namespace;
|
|
14
23
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { NameNamespace } from "./NameNamespace";
|
|
2
|
+
/** Extracts the name and the namespace `(a.b.c)` from the left-hand side of an STXT line. */
|
|
2
3
|
export declare class NameNamespaceParser {
|
|
3
4
|
private constructor();
|
|
5
|
+
/**
|
|
6
|
+
* Splits a raw node name into its name and its namespace.
|
|
7
|
+
*
|
|
8
|
+
* @param rawName raw name, with the namespace in parentheses if it carries one.
|
|
9
|
+
* @param inheritedNs namespace inherited from the parent, used when `rawName` brings none of its own.
|
|
10
|
+
* @param lineNumber line number, for the error messages.
|
|
11
|
+
* @param fullLine original full line, for the error messages.
|
|
12
|
+
* @returns the name and the namespace, already split apart and resolved.
|
|
13
|
+
* @throws ParseException if the name or the namespace are not well formed.
|
|
14
|
+
*/
|
|
4
15
|
static parse(rawName: string | null | undefined, inheritedNs: string | null | undefined, lineNumber: number, fullLine: string): NameNamespace;
|
|
5
16
|
}
|
|
@@ -3,9 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NameNamespaceParser = void 0;
|
|
4
4
|
const ParseException_1 = require("../exceptions/ParseException");
|
|
5
5
|
const NameNamespace_1 = require("./NameNamespace");
|
|
6
|
+
/** Extracts the name and the namespace `(a.b.c)` from the left-hand side of an STXT line. */
|
|
6
7
|
class NameNamespaceParser {
|
|
7
8
|
constructor() {
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Splits a raw node name into its name and its namespace.
|
|
12
|
+
*
|
|
13
|
+
* @param rawName raw name, with the namespace in parentheses if it carries one.
|
|
14
|
+
* @param inheritedNs namespace inherited from the parent, used when `rawName` brings none of its own.
|
|
15
|
+
* @param lineNumber line number, for the error messages.
|
|
16
|
+
* @param fullLine original full line, for the error messages.
|
|
17
|
+
* @returns the name and the namespace, already split apart and resolved.
|
|
18
|
+
* @throws ParseException if the name or the namespace are not well formed.
|
|
19
|
+
*/
|
|
9
20
|
static parse(rawName, inheritedNs, lineNumber, fullLine) {
|
|
10
21
|
if (rawName === null || rawName === undefined) {
|
|
11
22
|
throw new ParseException_1.ParseException(lineNumber, "INVALID_LINE", `Line not valid: ${fullLine}`);
|
|
@@ -15,27 +26,27 @@ class NameNamespaceParser {
|
|
|
15
26
|
const endIndex = rawName.indexOf(")");
|
|
16
27
|
let name;
|
|
17
28
|
let namespace = inheritedNs ?? "";
|
|
18
|
-
//
|
|
29
|
+
// Both of them found
|
|
19
30
|
if (startIndex !== -1 && endIndex !== -1) {
|
|
20
31
|
if (startIndex > endIndex || endIndex !== rawName.length - 1) {
|
|
21
32
|
throw new ParseException_1.ParseException(lineNumber, "INVALID_NAMESPACE", `Line not valid: ${fullLine}`);
|
|
22
33
|
}
|
|
23
34
|
name = rawName.substring(0, startIndex).trim();
|
|
24
|
-
//
|
|
35
|
+
// No trim: the grammar (STXT-SPEC 7/16) does not allow spaces inside '( )'
|
|
25
36
|
namespace = rawName.substring(startIndex + 1, endIndex);
|
|
26
37
|
if (namespace.length === 0) {
|
|
27
38
|
throw new ParseException_1.ParseException(lineNumber, "INVALID_NAMESPACE", `Line not valid: ${fullLine}`);
|
|
28
39
|
}
|
|
29
40
|
}
|
|
30
|
-
//
|
|
41
|
+
// Neither of them
|
|
31
42
|
else if (startIndex === -1 && endIndex === -1) {
|
|
32
43
|
name = rawName;
|
|
33
44
|
}
|
|
34
|
-
//
|
|
45
|
+
// Only one of the two
|
|
35
46
|
else {
|
|
36
47
|
throw new ParseException_1.ParseException(lineNumber, "INVALID_NAMESPACE", `Line not valid: ${fullLine}`);
|
|
37
48
|
}
|
|
38
|
-
//
|
|
49
|
+
// Return
|
|
39
50
|
return new NameNamespace_1.NameNamespace(name, namespace.toLowerCase());
|
|
40
51
|
}
|
|
41
52
|
}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
+
/** Validates the format of STXT `(a.b.c)` namespaces. */
|
|
1
2
|
export declare class NamespaceValidator {
|
|
3
|
+
/**
|
|
4
|
+
* Format of the logical namespace.
|
|
5
|
+
*
|
|
6
|
+
* Rules:
|
|
7
|
+
* - Lower-case letters, digits and dot only.
|
|
8
|
+
* - It may optionally start with '@'.
|
|
9
|
+
* - It must be one or more domain-style labels separated by '.':
|
|
10
|
+
* label := [a-z0-9]+
|
|
11
|
+
* valid examples: "xxx", "xxx.ddd", "zzz.ttt.ooo", "@xxx", "@xxx.ddd".
|
|
12
|
+
*/
|
|
2
13
|
private static readonly NAMESPACE_FORMAT;
|
|
14
|
+
/**
|
|
15
|
+
* Validates the format of a namespace.
|
|
16
|
+
*
|
|
17
|
+
* @param namespace already normalized namespace to validate; ignored when null or empty.
|
|
18
|
+
* @param lineNumber line number, for the error message.
|
|
19
|
+
* @throws ParseException with code `INVALID_NAMESPACE` if it does not match the format.
|
|
20
|
+
*/
|
|
3
21
|
static validateNamespaceFormat(namespace: string | null | undefined, lineNumber: number): void;
|
|
4
22
|
}
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NamespaceValidator = void 0;
|
|
4
4
|
const ParseException_1 = require("../exceptions/ParseException");
|
|
5
|
+
/** Validates the format of STXT `(a.b.c)` namespaces. */
|
|
5
6
|
class NamespaceValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates the format of a namespace.
|
|
9
|
+
*
|
|
10
|
+
* @param namespace already normalized namespace to validate; ignored when null or empty.
|
|
11
|
+
* @param lineNumber line number, for the error message.
|
|
12
|
+
* @throws ParseException with code `INVALID_NAMESPACE` if it does not match the format.
|
|
13
|
+
*/
|
|
6
14
|
static validateNamespaceFormat(namespace, lineNumber) {
|
|
7
15
|
if (!namespace) {
|
|
8
16
|
return;
|
|
@@ -13,5 +21,15 @@ class NamespaceValidator {
|
|
|
13
21
|
}
|
|
14
22
|
}
|
|
15
23
|
exports.NamespaceValidator = NamespaceValidator;
|
|
24
|
+
/**
|
|
25
|
+
* Format of the logical namespace.
|
|
26
|
+
*
|
|
27
|
+
* Rules:
|
|
28
|
+
* - Lower-case letters, digits and dot only.
|
|
29
|
+
* - It may optionally start with '@'.
|
|
30
|
+
* - It must be one or more domain-style labels separated by '.':
|
|
31
|
+
* label := [a-z0-9]+
|
|
32
|
+
* valid examples: "xxx", "xxx.ddd", "zzz.ttt.ooo", "@xxx", "@xxx.ddd".
|
|
33
|
+
*/
|
|
16
34
|
NamespaceValidator.NAMESPACE_FORMAT = /^@?[a-z0-9]+(\.[a-z0-9]+)+$/;
|
|
17
35
|
//# sourceMappingURL=NamespaceValidator.js.map
|