@stxt-lang/core 0.5.2 → 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/README.md +1 -0
- package/out/all.js +3 -3
- 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 +16 -0
- 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 +17 -1
- 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 +1 -1
package/out/core/NodeCreator.js
CHANGED
|
@@ -5,6 +5,17 @@ const NameNamespaceParser_1 = require("./NameNamespaceParser");
|
|
|
5
5
|
const Node_1 = require("./Node");
|
|
6
6
|
const ParseException_1 = require("../exceptions/ParseException");
|
|
7
7
|
const Constants_1 = require("./Constants");
|
|
8
|
+
/**
|
|
9
|
+
* Builds the node a line opens, telling apart the INLINE form (`Name: value`) from the BLOCK one
|
|
10
|
+
* (`Name >>`) and resolving the namespace against the parent.
|
|
11
|
+
*
|
|
12
|
+
* @param lineIndent line already split into indentation and content.
|
|
13
|
+
* @param lineNumber line number of the document where the node opens.
|
|
14
|
+
* @param level indentation level of the node.
|
|
15
|
+
* @param parent node currently open, whose namespace is inherited, or null at root level.
|
|
16
|
+
* @returns the node the line opens, still with no children and no text lines.
|
|
17
|
+
* @throws ParseException if the line is not a valid node declaration.
|
|
18
|
+
*/
|
|
8
19
|
function createNode(lineIndent, lineNumber, level, parent) {
|
|
9
20
|
const line = lineIndent.content;
|
|
10
21
|
let name;
|
|
@@ -38,15 +49,15 @@ function createNode(lineIndent, lineNumber, level, parent) {
|
|
|
38
49
|
if (textNode && value.trim().length > 0) {
|
|
39
50
|
throw new ParseException_1.ParseException(lineNumber, "INLINE_VALUE_NOT_VALID", `Line not valid: ${line}`);
|
|
40
51
|
}
|
|
41
|
-
//
|
|
52
|
+
// Default namespace: inherited from the parent
|
|
42
53
|
const nameNamespace = NameNamespaceParser_1.NameNamespaceParser.parse(name, parent ? parent.getNamespace() : null, lineNumber, line);
|
|
43
54
|
name = nameNamespace.getName();
|
|
44
55
|
const namespace = nameNamespace.getNamespace();
|
|
45
|
-
//
|
|
56
|
+
// Validate the name
|
|
46
57
|
if (name.length === 0) {
|
|
47
58
|
throw new ParseException_1.ParseException(lineNumber, "INVALID_LINE", `Line not valid: ${line}`);
|
|
48
59
|
}
|
|
49
|
-
//
|
|
60
|
+
// Create the node
|
|
50
61
|
return new Node_1.Node(lineNumber, level, name, namespace, textNode, value);
|
|
51
62
|
}
|
|
52
63
|
//# sourceMappingURL=NodeCreator.js.map
|
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
import { Node } from "./Node";
|
|
2
2
|
import { ParseException } from "../exceptions/ParseException";
|
|
3
|
+
/**
|
|
4
|
+
* Result of a parse in multi-error mode: it collects the root nodes obtained and every error
|
|
5
|
+
* found (both syntax and validation ones), without bailing out on the first one.
|
|
6
|
+
*
|
|
7
|
+
* See {@link Parser.parseResult}. For the traditional fail-fast mode use {@link Parser.parse},
|
|
8
|
+
* which internally uses this result and throws the first error.
|
|
9
|
+
*/
|
|
3
10
|
export declare class ParseResult {
|
|
4
11
|
private readonly nodes;
|
|
5
12
|
private readonly errors;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a result, empty by default.
|
|
15
|
+
*
|
|
16
|
+
* @param nodes root nodes to start from.
|
|
17
|
+
* @param errors errors to start from.
|
|
18
|
+
*/
|
|
6
19
|
constructor(nodes?: Node[], errors?: ParseException[]);
|
|
20
|
+
/** @returns the root nodes collected so far. */
|
|
7
21
|
getNodes(): Node[];
|
|
22
|
+
/** @returns the syntax or validation errors collected so far, in order of appearance. */
|
|
8
23
|
getErrors(): ParseException[];
|
|
24
|
+
/** @returns true if at least one error has been collected. */
|
|
9
25
|
hasErrors(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Adds an error found while parsing.
|
|
28
|
+
*
|
|
29
|
+
* @param error error found while parsing, without aborting the traversal.
|
|
30
|
+
*/
|
|
10
31
|
addError(error: ParseException): void;
|
|
32
|
+
/**
|
|
33
|
+
* Adds a root node to the result.
|
|
34
|
+
*
|
|
35
|
+
* @param node already closed root node to add to the result.
|
|
36
|
+
*/
|
|
11
37
|
addNode(node: Node): void;
|
|
12
38
|
}
|
package/out/core/ParseResult.js
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ParseResult = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Result of a parse in multi-error mode: it collects the root nodes obtained and every error
|
|
6
|
+
* found (both syntax and validation ones), without bailing out on the first one.
|
|
7
|
+
*
|
|
8
|
+
* See {@link Parser.parseResult}. For the traditional fail-fast mode use {@link Parser.parse},
|
|
9
|
+
* which internally uses this result and throws the first error.
|
|
10
|
+
*/
|
|
4
11
|
class ParseResult {
|
|
12
|
+
/**
|
|
13
|
+
* Creates a result, empty by default.
|
|
14
|
+
*
|
|
15
|
+
* @param nodes root nodes to start from.
|
|
16
|
+
* @param errors errors to start from.
|
|
17
|
+
*/
|
|
5
18
|
constructor(nodes = [], errors = []) {
|
|
6
19
|
this.nodes = nodes;
|
|
7
20
|
this.errors = errors;
|
|
8
21
|
}
|
|
22
|
+
/** @returns the root nodes collected so far. */
|
|
9
23
|
getNodes() {
|
|
10
24
|
return this.nodes;
|
|
11
25
|
}
|
|
26
|
+
/** @returns the syntax or validation errors collected so far, in order of appearance. */
|
|
12
27
|
getErrors() {
|
|
13
28
|
return this.errors;
|
|
14
29
|
}
|
|
30
|
+
/** @returns true if at least one error has been collected. */
|
|
15
31
|
hasErrors() {
|
|
16
32
|
return this.errors.length > 0;
|
|
17
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Adds an error found while parsing.
|
|
36
|
+
*
|
|
37
|
+
* @param error error found while parsing, without aborting the traversal.
|
|
38
|
+
*/
|
|
18
39
|
addError(error) {
|
|
19
40
|
this.errors.push(error);
|
|
20
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Adds a root node to the result.
|
|
44
|
+
*
|
|
45
|
+
* @param node already closed root node to add to the result.
|
|
46
|
+
*/
|
|
21
47
|
addNode(node) {
|
|
22
48
|
this.nodes.push(node);
|
|
23
49
|
}
|
package/out/core/Parser.d.ts
CHANGED
|
@@ -2,12 +2,43 @@ import { Node } from "./Node";
|
|
|
2
2
|
import { Observer } from "../processors/Observer";
|
|
3
3
|
import { Validator } from "../processors/Validator";
|
|
4
4
|
import { ParseResult } from "./ParseResult";
|
|
5
|
+
/**
|
|
6
|
+
* Line-by-line STXT parsing engine. It knows nothing about schemas: semantic validation is
|
|
7
|
+
* plugged in through {@link Parser.registerValidator} and {@link Parser.registerObserver}.
|
|
8
|
+
* See {@link UnifiedSchemaProvider} for the usual way of building the validators to register.
|
|
9
|
+
*/
|
|
5
10
|
export declare class Parser {
|
|
6
11
|
private observers;
|
|
7
12
|
private validators;
|
|
13
|
+
/**
|
|
14
|
+
* Registers an observer, notified when each node is opened and closed.
|
|
15
|
+
*
|
|
16
|
+
* @param observer the {@link Observer} to register, notified while parsing.
|
|
17
|
+
*/
|
|
8
18
|
registerObserver(observer: Observer): void;
|
|
19
|
+
/**
|
|
20
|
+
* Registers a validator, invoked when each node is closed.
|
|
21
|
+
*
|
|
22
|
+
* @param validator the {@link Validator} to register, invoked when each node is closed during parsing.
|
|
23
|
+
*/
|
|
9
24
|
registerValidator(validator: Validator): void;
|
|
25
|
+
/**
|
|
26
|
+
* Traditional fail-fast mode: throws the first error found (either syntax or validation).
|
|
27
|
+
* Internally it reuses the same traversal as {@link Parser.parseResult}, and throws the first
|
|
28
|
+
* error it collected.
|
|
29
|
+
*
|
|
30
|
+
* @param content the whole STXT document to parse.
|
|
31
|
+
* @returns the root nodes of the document.
|
|
32
|
+
* @throws ParseException the first error found, be it syntax or validation.
|
|
33
|
+
*/
|
|
10
34
|
parse(content: string): Node[];
|
|
35
|
+
/**
|
|
36
|
+
* Multi-error mode: parses the whole content collecting every error found (both syntax and
|
|
37
|
+
* validation) without bailing out on the first one. See {@link ParseResult}.
|
|
38
|
+
*
|
|
39
|
+
* @param content the whole STXT document to parse.
|
|
40
|
+
* @returns the collected result, with the root nodes obtained and every error found.
|
|
41
|
+
*/
|
|
11
42
|
parseResult(content: string): ParseResult;
|
|
12
43
|
private processLine;
|
|
13
44
|
private handleError;
|
package/out/core/Parser.js
CHANGED
|
@@ -5,17 +5,41 @@ const LineParser_1 = require("./LineParser");
|
|
|
5
5
|
const NodeCreator_1 = require("./NodeCreator");
|
|
6
6
|
const ParseResult_1 = require("./ParseResult");
|
|
7
7
|
const ParseException_1 = require("../exceptions/ParseException");
|
|
8
|
+
/**
|
|
9
|
+
* Line-by-line STXT parsing engine. It knows nothing about schemas: semantic validation is
|
|
10
|
+
* plugged in through {@link Parser.registerValidator} and {@link Parser.registerObserver}.
|
|
11
|
+
* See {@link UnifiedSchemaProvider} for the usual way of building the validators to register.
|
|
12
|
+
*/
|
|
8
13
|
class Parser {
|
|
9
14
|
constructor() {
|
|
10
15
|
this.observers = [];
|
|
11
16
|
this.validators = [];
|
|
12
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Registers an observer, notified when each node is opened and closed.
|
|
20
|
+
*
|
|
21
|
+
* @param observer the {@link Observer} to register, notified while parsing.
|
|
22
|
+
*/
|
|
13
23
|
registerObserver(observer) {
|
|
14
24
|
this.observers.push(observer);
|
|
15
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Registers a validator, invoked when each node is closed.
|
|
28
|
+
*
|
|
29
|
+
* @param validator the {@link Validator} to register, invoked when each node is closed during parsing.
|
|
30
|
+
*/
|
|
16
31
|
registerValidator(validator) {
|
|
17
32
|
this.validators.push(validator);
|
|
18
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Traditional fail-fast mode: throws the first error found (either syntax or validation).
|
|
36
|
+
* Internally it reuses the same traversal as {@link Parser.parseResult}, and throws the first
|
|
37
|
+
* error it collected.
|
|
38
|
+
*
|
|
39
|
+
* @param content the whole STXT document to parse.
|
|
40
|
+
* @returns the root nodes of the document.
|
|
41
|
+
* @throws ParseException the first error found, be it syntax or validation.
|
|
42
|
+
*/
|
|
19
43
|
parse(content) {
|
|
20
44
|
const result = this.parseResult(content);
|
|
21
45
|
if (result.hasErrors()) {
|
|
@@ -24,6 +48,13 @@ class Parser {
|
|
|
24
48
|
}
|
|
25
49
|
return result.getNodes();
|
|
26
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Multi-error mode: parses the whole content collecting every error found (both syntax and
|
|
53
|
+
* validation) without bailing out on the first one. See {@link ParseResult}.
|
|
54
|
+
*
|
|
55
|
+
* @param content the whole STXT document to parse.
|
|
56
|
+
* @returns the collected result, with the root nodes obtained and every error found.
|
|
57
|
+
*/
|
|
27
58
|
parseResult(content) {
|
|
28
59
|
content = this.removeUTF8BOM(content);
|
|
29
60
|
const result = new ParseResult_1.ParseResult();
|
|
@@ -31,8 +62,8 @@ class Parser {
|
|
|
31
62
|
const documents = [];
|
|
32
63
|
let lineNumber = 0;
|
|
33
64
|
const lines = content.split(/\r?\n/);
|
|
34
|
-
//
|
|
35
|
-
//
|
|
65
|
+
// The final line break terminates the last line, it is not an extra empty line
|
|
66
|
+
// (this avoids adding a spurious line to a >> block at EOF, spec 10.3)
|
|
36
67
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
37
68
|
lines.pop();
|
|
38
69
|
}
|
|
@@ -40,13 +71,13 @@ class Parser {
|
|
|
40
71
|
lineNumber++;
|
|
41
72
|
this.processLine(line, lineNumber, stack, documents, result);
|
|
42
73
|
}
|
|
43
|
-
//
|
|
74
|
+
// Close every node still open at EOF
|
|
44
75
|
this.closeToLevel(stack, documents, 0, result);
|
|
45
|
-
//
|
|
76
|
+
// Add the nodes to the result
|
|
46
77
|
for (const doc of documents) {
|
|
47
78
|
result.addNode(doc);
|
|
48
79
|
}
|
|
49
|
-
//
|
|
80
|
+
// Return the result
|
|
50
81
|
return result;
|
|
51
82
|
}
|
|
52
83
|
processLine(lineString, lineNumber, stack, documents, result) {
|
|
@@ -54,40 +85,40 @@ class Parser {
|
|
|
54
85
|
const lastNode = stack.length === 0 ? null : stack[stack.length - 1];
|
|
55
86
|
const lastLevel = lastNode ? lastNode.getLevel() : 0;
|
|
56
87
|
const lastNodeText = lastNode ? lastNode.isTextNode() : false;
|
|
57
|
-
//
|
|
88
|
+
// Parse the line
|
|
58
89
|
const line = (0, LineParser_1.parseLine)(lineString, lastNodeText, lastLevel, lineNumber);
|
|
59
90
|
if (line.isComment) {
|
|
60
|
-
//
|
|
91
|
+
// Hand it over to the observers
|
|
61
92
|
this.observers.forEach(observer => {
|
|
62
93
|
observer.onComment(lineNumber, lineString);
|
|
63
94
|
});
|
|
64
95
|
return;
|
|
65
96
|
}
|
|
66
97
|
const currentLevel = line.level;
|
|
67
|
-
//
|
|
68
|
-
//
|
|
98
|
+
// When we are inside a text node and the level says it is still text,
|
|
99
|
+
// append the text line instead of creating a node.
|
|
69
100
|
if (line.isBlock) {
|
|
70
101
|
lastNode.addTextLine(line.content);
|
|
71
|
-
//
|
|
102
|
+
// Notify the observers about the text line
|
|
72
103
|
this.observers.forEach(observer => {
|
|
73
104
|
observer.onTextLine(lastNode, lineNumber, lineString, line);
|
|
74
105
|
});
|
|
75
106
|
return;
|
|
76
107
|
}
|
|
77
|
-
//
|
|
108
|
+
// Empty lines are ignored
|
|
78
109
|
if (line.isEmpty()) {
|
|
79
110
|
return;
|
|
80
111
|
}
|
|
81
|
-
//
|
|
112
|
+
// Close the nodes down to the current level (this "finishes" them and attaches them to the parent/documents)
|
|
82
113
|
this.closeToLevel(stack, documents, currentLevel, result);
|
|
83
|
-
//
|
|
114
|
+
// Create the new node and leave it "open" on the stack (do NOT attach it yet)
|
|
84
115
|
const parent = stack.length === 0 ? null : stack[stack.length - 1];
|
|
85
116
|
const node = (0, NodeCreator_1.createNode)(line, lineNumber, currentLevel, parent);
|
|
86
|
-
//
|
|
117
|
+
// Hand it over to the observers
|
|
87
118
|
this.observers.forEach(observer => {
|
|
88
119
|
observer.onCreate(node, lineString);
|
|
89
120
|
});
|
|
90
|
-
//
|
|
121
|
+
// Push it onto the stack
|
|
91
122
|
stack.push(node);
|
|
92
123
|
}
|
|
93
124
|
catch (e) {
|
|
@@ -99,18 +130,18 @@ class Parser {
|
|
|
99
130
|
result.addError(e);
|
|
100
131
|
}
|
|
101
132
|
else if (e instanceof Error) {
|
|
102
|
-
//
|
|
133
|
+
// Turn generic errors into a ParseException
|
|
103
134
|
result.addError(new ParseException_1.ParseException(line, errorCode, e.message));
|
|
104
135
|
}
|
|
105
136
|
else {
|
|
106
|
-
//
|
|
137
|
+
// Unknown error
|
|
107
138
|
result.addError(new ParseException_1.ParseException(line, unknownErrorCode, String(e)));
|
|
108
139
|
}
|
|
109
140
|
}
|
|
110
141
|
closeToLevel(stack, documents, targetLevel, result) {
|
|
111
142
|
while (stack.length > targetLevel) {
|
|
112
143
|
const completed = stack.pop();
|
|
113
|
-
//
|
|
144
|
+
// Hand it over to the validators
|
|
114
145
|
this.validators.forEach(validator => {
|
|
115
146
|
try {
|
|
116
147
|
const errors = validator.validate(completed);
|
|
@@ -128,7 +159,7 @@ class Parser {
|
|
|
128
159
|
else {
|
|
129
160
|
stack[stack.length - 1].addChild(completed);
|
|
130
161
|
}
|
|
131
|
-
//
|
|
162
|
+
// Hand it over to the observers
|
|
132
163
|
this.observers.forEach(observer => {
|
|
133
164
|
observer.onFinish(completed);
|
|
134
165
|
});
|
|
@@ -1,8 +1,39 @@
|
|
|
1
|
+
/** String normalization helpers used for names, namespaces and values. */
|
|
1
2
|
export declare class StringUtils {
|
|
2
3
|
private constructor();
|
|
4
|
+
/**
|
|
5
|
+
* Removes the trailing whitespace of a string.
|
|
6
|
+
*
|
|
7
|
+
* @param s string to strip the trailing spaces from.
|
|
8
|
+
* @returns the string without trailing whitespace; null/undefined is treated as the empty string.
|
|
9
|
+
*/
|
|
3
10
|
static rightTrim(s: string | null | undefined): string;
|
|
11
|
+
/**
|
|
12
|
+
* Removes every whitespace character of a string.
|
|
13
|
+
*
|
|
14
|
+
* @param input string to remove the spaces from.
|
|
15
|
+
* @returns the string without any whitespace at all.
|
|
16
|
+
*/
|
|
4
17
|
static cleanSpaces(input: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Lower-cases a string.
|
|
20
|
+
*
|
|
21
|
+
* @param input string to lower-case.
|
|
22
|
+
* @returns the lower-cased string; null/undefined is treated as the empty string.
|
|
23
|
+
*/
|
|
5
24
|
static lowerCase(input: string | null | undefined): string;
|
|
25
|
+
/**
|
|
26
|
+
* Trims a string and collapses its inner whitespace.
|
|
27
|
+
*
|
|
28
|
+
* @param s string to compact.
|
|
29
|
+
* @returns the string with the outer spaces trimmed and the inner ones collapsed into a single one; null/undefined is treated as the empty string.
|
|
30
|
+
*/
|
|
6
31
|
static compactSpaces(s: string | null | undefined): string;
|
|
32
|
+
/**
|
|
33
|
+
* Builds the canonical name of a node, as defined by STXT-SPEC 4.3.
|
|
34
|
+
*
|
|
35
|
+
* @param input string to normalize.
|
|
36
|
+
* @returns the canonical name of a node: NFC + lower case, with separators collapsed into '-'; null/undefined is treated as the empty string.
|
|
37
|
+
*/
|
|
7
38
|
static normalize(input: string | null | undefined): string;
|
|
8
39
|
}
|
package/out/core/StringUtils.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StringUtils = void 0;
|
|
4
|
+
/** String normalization helpers used for names, namespaces and values. */
|
|
4
5
|
class StringUtils {
|
|
5
6
|
constructor() {
|
|
6
7
|
}
|
|
7
|
-
//
|
|
8
|
+
// Used for name>> nodes
|
|
9
|
+
/**
|
|
10
|
+
* Removes the trailing whitespace of a string.
|
|
11
|
+
*
|
|
12
|
+
* @param s string to strip the trailing spaces from.
|
|
13
|
+
* @returns the string without trailing whitespace; null/undefined is treated as the empty string.
|
|
14
|
+
*/
|
|
8
15
|
static rightTrim(s) {
|
|
9
16
|
const value = s ?? "";
|
|
10
17
|
let i = value.length - 1;
|
|
@@ -13,21 +20,45 @@ class StringUtils {
|
|
|
13
20
|
}
|
|
14
21
|
return value.substring(0, i + 1);
|
|
15
22
|
}
|
|
16
|
-
//
|
|
23
|
+
// Used for BASE64 and HEXADECIMAL nodes
|
|
24
|
+
/**
|
|
25
|
+
* Removes every whitespace character of a string.
|
|
26
|
+
*
|
|
27
|
+
* @param input string to remove the spaces from.
|
|
28
|
+
* @returns the string without any whitespace at all.
|
|
29
|
+
*/
|
|
17
30
|
static cleanSpaces(input) {
|
|
18
31
|
return input.replace(/\s+/g, "");
|
|
19
32
|
}
|
|
20
|
-
//
|
|
33
|
+
// Used to normalize namespaces
|
|
34
|
+
/**
|
|
35
|
+
* Lower-cases a string.
|
|
36
|
+
*
|
|
37
|
+
* @param input string to lower-case.
|
|
38
|
+
* @returns the lower-cased string; null/undefined is treated as the empty string.
|
|
39
|
+
*/
|
|
21
40
|
static lowerCase(input) {
|
|
22
|
-
//
|
|
41
|
+
// Practical equivalent of Locale.ROOT in JS: keep the user's locale out of it
|
|
23
42
|
return (input ?? "").toLowerCase();
|
|
24
43
|
}
|
|
25
|
-
//
|
|
44
|
+
// Used for the name of the nodes
|
|
45
|
+
/**
|
|
46
|
+
* Trims a string and collapses its inner whitespace.
|
|
47
|
+
*
|
|
48
|
+
* @param s string to compact.
|
|
49
|
+
* @returns the string with the outer spaces trimmed and the inner ones collapsed into a single one; null/undefined is treated as the empty string.
|
|
50
|
+
*/
|
|
26
51
|
static compactSpaces(s) {
|
|
27
52
|
return (s ?? "").trim().replace(/\s+/g, " ");
|
|
28
53
|
}
|
|
29
|
-
//
|
|
30
|
-
//
|
|
54
|
+
// Used for the normalized name of the nodes (STXT-SPEC 4.3): NFC + lower case,
|
|
55
|
+
// keeping diacritics and non-Latin alphabets (IDN model)
|
|
56
|
+
/**
|
|
57
|
+
* Builds the canonical name of a node, as defined by STXT-SPEC 4.3.
|
|
58
|
+
*
|
|
59
|
+
* @param input string to normalize.
|
|
60
|
+
* @returns the canonical name of a node: NFC + lower case, with separators collapsed into '-'; null/undefined is treated as the empty string.
|
|
61
|
+
*/
|
|
31
62
|
static normalize(input) {
|
|
32
63
|
let s = (input ?? "").trim();
|
|
33
64
|
if (s.length === 0) {
|
|
@@ -35,9 +66,9 @@ class StringUtils {
|
|
|
35
66
|
}
|
|
36
67
|
s = s.normalize("NFC");
|
|
37
68
|
s = s.toLowerCase();
|
|
38
|
-
//
|
|
69
|
+
// every run of separators ('-', '_', spaces) => a single '-'
|
|
39
70
|
s = s.replace(/[-_\s]+/g, "-");
|
|
40
|
-
// trim
|
|
71
|
+
// trim the '-'
|
|
41
72
|
s = s.replace(/^-+|-+$/g, "");
|
|
42
73
|
return s;
|
|
43
74
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax error detected while parsing (lexical/structural phase, not schema). Every exception
|
|
3
|
+
* carries an UPPERCASE code and the line of the document where it was detected.
|
|
4
|
+
*/
|
|
1
5
|
export declare class ParseException extends Error {
|
|
6
|
+
/** Line number of the document where the error was detected. */
|
|
2
7
|
readonly line: number;
|
|
8
|
+
/** Error code in UPPERCASE (e.g. `INVALID_LINE`). */
|
|
3
9
|
readonly code: string;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a syntax error located at a line of the document.
|
|
12
|
+
*
|
|
13
|
+
* @param line line number where the error was detected.
|
|
14
|
+
* @param code error code in UPPERCASE.
|
|
15
|
+
* @param message descriptive message.
|
|
16
|
+
*/
|
|
4
17
|
constructor(line: number, code: string, message: string);
|
|
18
|
+
/** @returns a readable representation of the error, with its line and its code. */
|
|
5
19
|
toString(): string;
|
|
6
20
|
}
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ParseException = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Syntax error detected while parsing (lexical/structural phase, not schema). Every exception
|
|
6
|
+
* carries an UPPERCASE code and the line of the document where it was detected.
|
|
7
|
+
*/
|
|
4
8
|
class ParseException extends Error {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a syntax error located at a line of the document.
|
|
11
|
+
*
|
|
12
|
+
* @param line line number where the error was detected.
|
|
13
|
+
* @param code error code in UPPERCASE.
|
|
14
|
+
* @param message descriptive message.
|
|
15
|
+
*/
|
|
5
16
|
constructor(line, code, message) {
|
|
6
17
|
super(message);
|
|
7
18
|
this.name = "ParseException";
|
|
@@ -9,6 +20,7 @@ class ParseException extends Error {
|
|
|
9
20
|
this.code = code;
|
|
10
21
|
Object.setPrototypeOf(this, ParseException.prototype);
|
|
11
22
|
}
|
|
23
|
+
/** @returns a readable representation of the error, with its line and its code. */
|
|
12
24
|
toString() {
|
|
13
25
|
return `${this.name} [line=${this.line}, code=${this.code}]: ${this.message}`;
|
|
14
26
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error that is not tied to a line of the document: a wrong use of the API or an inconsistency
|
|
3
|
+
* found at runtime (e.g. an ambiguous child, a type registered twice). It carries an UPPERCASE
|
|
4
|
+
* code, like the rest of the STXT exceptions.
|
|
5
|
+
*/
|
|
1
6
|
export declare class RuntimeException extends Error {
|
|
7
|
+
/** Error code in UPPERCASE (e.g. `AMBIGUOUS_CHILD`). */
|
|
2
8
|
readonly code: string;
|
|
9
|
+
/**
|
|
10
|
+
* Creates an error with an error code and a message.
|
|
11
|
+
*
|
|
12
|
+
* @param code error code in UPPERCASE.
|
|
13
|
+
* @param message descriptive message.
|
|
14
|
+
*/
|
|
3
15
|
constructor(code: string, message: string);
|
|
16
|
+
/** @returns the error code in UPPERCASE. */
|
|
4
17
|
getCode(): string;
|
|
18
|
+
/** @returns a readable representation of the error, with its code. */
|
|
5
19
|
toString(): string;
|
|
6
20
|
}
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RuntimeException = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error that is not tied to a line of the document: a wrong use of the API or an inconsistency
|
|
6
|
+
* found at runtime (e.g. an ambiguous child, a type registered twice). It carries an UPPERCASE
|
|
7
|
+
* code, like the rest of the STXT exceptions.
|
|
8
|
+
*/
|
|
4
9
|
class RuntimeException extends Error {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an error with an error code and a message.
|
|
12
|
+
*
|
|
13
|
+
* @param code error code in UPPERCASE.
|
|
14
|
+
* @param message descriptive message.
|
|
15
|
+
*/
|
|
5
16
|
constructor(code, message) {
|
|
6
17
|
super(message);
|
|
7
18
|
this.name = "RuntimeException";
|
|
8
19
|
this.code = code;
|
|
9
20
|
Object.setPrototypeOf(this, RuntimeException.prototype);
|
|
10
21
|
}
|
|
22
|
+
/** @returns the error code in UPPERCASE. */
|
|
11
23
|
getCode() {
|
|
12
24
|
return this.code;
|
|
13
25
|
}
|
|
26
|
+
/** @returns a readable representation of the error, with its code. */
|
|
14
27
|
toString() {
|
|
15
28
|
const message = this.message;
|
|
16
29
|
return `${this.name}[${this.code}]${message ? `: ${message}` : ""}`;
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { ParseException } from "./ParseException";
|
|
2
|
+
/** Semantic validation error (schema, type or cardinality), detected when a node is closed. */
|
|
2
3
|
export declare class ValidationException extends ParseException {
|
|
4
|
+
/**
|
|
5
|
+
* Creates a validation error located at a line of the document.
|
|
6
|
+
*
|
|
7
|
+
* @param line line number where the error was detected.
|
|
8
|
+
* @param code error code in UPPERCASE.
|
|
9
|
+
* @param message descriptive message.
|
|
10
|
+
*/
|
|
3
11
|
constructor(line: number, code: string, message: string);
|
|
4
12
|
}
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ValidationException = void 0;
|
|
4
4
|
const ParseException_1 = require("./ParseException");
|
|
5
|
+
/** Semantic validation error (schema, type or cardinality), detected when a node is closed. */
|
|
5
6
|
class ValidationException extends ParseException_1.ParseException {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a validation error located at a line of the document.
|
|
9
|
+
*
|
|
10
|
+
* @param line line number where the error was detected.
|
|
11
|
+
* @param code error code in UPPERCASE.
|
|
12
|
+
* @param message descriptive message.
|
|
13
|
+
*/
|
|
6
14
|
constructor(line, code, message) {
|
|
7
15
|
super(line, code, message);
|
|
8
16
|
this.name = "ValidationException";
|
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import { Line } from "../core/Line";
|
|
2
2
|
import { Node } from "../core/Node";
|
|
3
|
+
/**
|
|
4
|
+
* Process hook notified by the {@link Parser} while parsing: when each node is opened and closed,
|
|
5
|
+
* and for every comment and text line it reads. Register it with {@link Parser.registerObserver}.
|
|
6
|
+
*/
|
|
3
7
|
export interface Observer {
|
|
8
|
+
/**
|
|
9
|
+
* Called when a node is opened.
|
|
10
|
+
*
|
|
11
|
+
* @param node node just opened (its children and its text lines are not complete yet).
|
|
12
|
+
* @param line source line that opened the node, as it appears in the document.
|
|
13
|
+
*/
|
|
4
14
|
onCreate(node: Node, line: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Called when a node is closed.
|
|
17
|
+
*
|
|
18
|
+
* @param node node just closed, with all its children and its value already complete.
|
|
19
|
+
*/
|
|
5
20
|
onFinish(node: Node): void;
|
|
21
|
+
/**
|
|
22
|
+
* Called for every comment line, which produces no node.
|
|
23
|
+
*
|
|
24
|
+
* @param lineNumber line number of the comment.
|
|
25
|
+
* @param line source line of the comment, as it appears in the document.
|
|
26
|
+
*/
|
|
6
27
|
onComment(lineNumber: number, line: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Called for every text line appended to an open BLOCK node.
|
|
30
|
+
*
|
|
31
|
+
* @param node BLOCK node the line was appended to.
|
|
32
|
+
* @param lineNumber line number of the text line.
|
|
33
|
+
* @param lineString source line, as it appears in the document.
|
|
34
|
+
* @param line the same line already split into indentation and content.
|
|
35
|
+
*/
|
|
7
36
|
onTextLine(node: Node, lineNumber: number, lineString: string, line: Line): void;
|
|
8
37
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { Node } from "../core/Node";
|
|
2
2
|
import { ValidationException } from "../exceptions/ValidationException";
|
|
3
|
+
/** Process hook invoked by the {@link Parser} when each node is closed, to validate in streaming. */
|
|
3
4
|
export interface Validator {
|
|
5
|
+
/**
|
|
6
|
+
* Validates a node and returns every error found (without throwing), letting the caller
|
|
7
|
+
* collect errors from several nodes instead of bailing out on the first one. An empty array
|
|
8
|
+
* means the node is valid.
|
|
9
|
+
*
|
|
10
|
+
* @param node already closed node to validate.
|
|
11
|
+
* @returns the validation errors found, or an empty array if the node is valid.
|
|
12
|
+
*/
|
|
4
13
|
validate(node: Node): ValidationException[];
|
|
5
14
|
}
|