@stxt-lang/core 0.5.2 → 0.6.0

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.
Files changed (120) hide show
  1. package/README.md +116 -1
  2. package/out/all.d.ts +5 -0
  3. package/out/all.js +10 -4
  4. package/out/core/Constants.d.ts +8 -0
  5. package/out/core/Constants.js +8 -0
  6. package/out/core/Line.d.ts +20 -0
  7. package/out/core/Line.js +15 -0
  8. package/out/core/LineParser.d.ts +17 -0
  9. package/out/core/LineParser.js +27 -10
  10. package/out/core/NameNamespace.d.ts +9 -0
  11. package/out/core/NameNamespace.js +9 -0
  12. package/out/core/NameNamespaceParser.d.ts +11 -0
  13. package/out/core/NameNamespaceParser.js +16 -5
  14. package/out/core/NamespaceValidator.d.ts +18 -0
  15. package/out/core/NamespaceValidator.js +18 -0
  16. package/out/core/Node.d.ts +55 -0
  17. package/out/core/Node.js +56 -1
  18. package/out/core/NodeCreator.d.ts +11 -0
  19. package/out/core/NodeCreator.js +14 -3
  20. package/out/core/ParseResult.d.ts +26 -0
  21. package/out/core/ParseResult.js +26 -0
  22. package/out/core/Parser.d.ts +31 -0
  23. package/out/core/Parser.js +50 -19
  24. package/out/core/StringUtils.d.ts +31 -0
  25. package/out/core/StringUtils.js +40 -9
  26. package/out/discovery/DiscoveryEnvironment.d.ts +35 -0
  27. package/out/discovery/DiscoveryEnvironment.js +3 -0
  28. package/out/discovery/DiscoveryError.d.ts +30 -0
  29. package/out/discovery/DiscoveryError.js +36 -0
  30. package/out/discovery/DiscoveryFileSystem.d.ts +57 -0
  31. package/out/discovery/DiscoveryFileSystem.js +3 -0
  32. package/out/discovery/DiscoveryResolver.d.ts +74 -0
  33. package/out/discovery/DiscoveryResolver.js +232 -0
  34. package/out/discovery/DiscoveryResult.d.ts +94 -0
  35. package/out/discovery/DiscoveryResult.js +111 -0
  36. package/out/exceptions/ParseException.d.ts +14 -0
  37. package/out/exceptions/ParseException.js +12 -0
  38. package/out/exceptions/RuntimeException.d.ts +14 -0
  39. package/out/exceptions/RuntimeException.js +13 -0
  40. package/out/exceptions/ValidationException.d.ts +8 -0
  41. package/out/exceptions/ValidationException.js +8 -0
  42. package/out/processors/Observer.d.ts +29 -0
  43. package/out/processors/Validator.d.ts +9 -0
  44. package/out/runtime/ConditionalValidator.d.ts +15 -0
  45. package/out/runtime/ConditionalValidator.js +16 -2
  46. package/out/runtime/NodeWriter.d.ts +18 -0
  47. package/out/runtime/NodeWriter.js +18 -0
  48. package/out/runtime/UnifiedSchemaProvider.d.ts +23 -5
  49. package/out/runtime/UnifiedSchemaProvider.js +28 -10
  50. package/out/schema/ChildDefinition.d.ts +18 -0
  51. package/out/schema/ChildDefinition.js +18 -0
  52. package/out/schema/NodeDefinition.d.ts +44 -0
  53. package/out/schema/NodeDefinition.js +47 -3
  54. package/out/schema/Schema.d.ts +26 -0
  55. package/out/schema/Schema.js +26 -1
  56. package/out/schema/SchemaParser.d.ts +7 -0
  57. package/out/schema/SchemaParser.js +26 -16
  58. package/out/schema/SchemaProvider.d.ts +7 -0
  59. package/out/schema/SchemaProviderMemory.d.ts +27 -0
  60. package/out/schema/SchemaProviderMemory.js +27 -0
  61. package/out/schema/SchemaProviderMeta.d.ts +16 -0
  62. package/out/schema/SchemaProviderMeta.js +16 -0
  63. package/out/schema/SchemaValidator.d.ts +20 -0
  64. package/out/schema/SchemaValidator.js +27 -7
  65. package/out/schema/Type.d.ts +9 -0
  66. package/out/schema/TypeRegistry.d.ts +13 -0
  67. package/out/schema/TypeRegistry.js +18 -5
  68. package/out/schema/type/BASE64.d.ts +1 -0
  69. package/out/schema/type/BASE64.js +5 -4
  70. package/out/schema/type/BINARY.d.ts +1 -0
  71. package/out/schema/type/BINARY.js +2 -1
  72. package/out/schema/type/BLOCK.d.ts +1 -0
  73. package/out/schema/type/BLOCK.js +2 -1
  74. package/out/schema/type/BOOLEAN.d.ts +1 -0
  75. package/out/schema/type/BOOLEAN.js +1 -0
  76. package/out/schema/type/DATE.d.ts +1 -0
  77. package/out/schema/type/DATE.js +1 -0
  78. package/out/schema/type/EMAIL.d.ts +1 -0
  79. package/out/schema/type/EMAIL.js +1 -0
  80. package/out/schema/type/ENUM.d.ts +1 -0
  81. package/out/schema/type/ENUM.js +2 -1
  82. package/out/schema/type/GROUP.d.ts +1 -0
  83. package/out/schema/type/GROUP.js +2 -1
  84. package/out/schema/type/HEXADECIMAL.d.ts +1 -0
  85. package/out/schema/type/HEXADECIMAL.js +2 -1
  86. package/out/schema/type/INLINE.d.ts +1 -0
  87. package/out/schema/type/INLINE.js +2 -1
  88. package/out/schema/type/INTEGER.d.ts +1 -0
  89. package/out/schema/type/INTEGER.js +1 -0
  90. package/out/schema/type/MARKDOWN.d.ts +4 -0
  91. package/out/schema/type/MARKDOWN.js +4 -2
  92. package/out/schema/type/NATURAL.d.ts +1 -0
  93. package/out/schema/type/NATURAL.js +1 -0
  94. package/out/schema/type/NUMBER.d.ts +1 -0
  95. package/out/schema/type/NUMBER.js +1 -0
  96. package/out/schema/type/TEXT.d.ts +1 -0
  97. package/out/schema/type/TEXT.js +1 -0
  98. package/out/schema/type/TIME.d.ts +1 -0
  99. package/out/schema/type/TIME.js +1 -0
  100. package/out/schema/type/TIMESTAMP.d.ts +1 -0
  101. package/out/schema/type/TIMESTAMP.js +1 -0
  102. package/out/schema/type/URL.d.ts +1 -0
  103. package/out/schema/type/URL.js +2 -1
  104. package/out/schema/type/UUID.d.ts +1 -0
  105. package/out/schema/type/UUID.js +1 -0
  106. package/out/schema/type/binaryValue.d.ts +9 -0
  107. package/out/schema/type/binaryValue.js +9 -3
  108. package/out/schema/type/regexType.d.ts +8 -0
  109. package/out/schema/type/regexType.js +9 -1
  110. package/out/template/ChildLine.d.ts +14 -0
  111. package/out/template/ChildLine.js +14 -0
  112. package/out/template/ChildLineParser.d.ts +10 -0
  113. package/out/template/ChildLineParser.js +17 -8
  114. package/out/template/MetaTemplateSchemaProvider.d.ts +16 -0
  115. package/out/template/MetaTemplateSchemaProvider.js +17 -1
  116. package/out/template/TemplateParser.d.ts +8 -0
  117. package/out/template/TemplateParser.js +49 -39
  118. package/out/template/TemplateSchemaProviderMemory.d.ts +18 -0
  119. package/out/template/TemplateSchemaProviderMemory.js +21 -3
  120. package/package.json +2 -1
package/out/core/Node.js CHANGED
@@ -5,7 +5,25 @@ const ParseException_1 = require("../exceptions/ParseException");
5
5
  const RuntimeException_1 = require("../exceptions/RuntimeException");
6
6
  const NamespaceValidator_1 = require("./NamespaceValidator");
7
7
  const StringUtils_1 = require("./StringUtils");
8
+ /**
9
+ * Node of the STXT tree. Mutable while parsing ({@link Node.addChild}/{@link Node.addTextLine}
10
+ * are public); once the document is closed it must be treated as read-only. It represents both
11
+ * INLINE nodes (with {@link Node.getValue}) and BLOCK text nodes (with {@link Node.getTextLines}),
12
+ * as told apart by {@link Node.isTextNode}.
13
+ */
8
14
  class Node {
15
+ /**
16
+ * Creates a node with its full position in the document. This is the constructor the
17
+ * {@link Parser} uses while parsing.
18
+ *
19
+ * @param line line number of the document where the node opens.
20
+ * @param level indentation level of the node (0 for root nodes).
21
+ * @param name name of the node.
22
+ * @param namespace namespace of the node, or null/undefined if it has none.
23
+ * @param textNode true if it is a text block node (BLOCK); false if it is INLINE.
24
+ * @param value inline value of the node (INLINE node), ignored when it is BLOCK.
25
+ * @throws ParseException if the name or the namespace are not valid.
26
+ */
9
27
  constructor(line, level, name, namespace, textNode, value) {
10
28
  this.textLines = [];
11
29
  this.children = [];
@@ -27,47 +45,76 @@ class Node {
27
45
  throw new ParseException_1.ParseException(line, "INVALID_NODE_NAME", `Node name not valid: ${name}`);
28
46
  }
29
47
  }
48
+ /**
49
+ * Appends a text line to a BLOCK node.
50
+ *
51
+ * @param line text line to append to a BLOCK node ({@link Node.isTextNode}).
52
+ */
30
53
  addTextLine(line) {
31
54
  this.textLines.push(line);
32
55
  }
56
+ /** @returns the original name of the node as it appears in the document (with spaces compacted). */
33
57
  getName() {
34
58
  return this.name;
35
59
  }
60
+ /** @returns the canonical name of the node, used to compare/look up by structural identity. */
36
61
  getNormalizedName() {
37
62
  return this.normalizedName;
38
63
  }
64
+ /** @returns the canonical name prefixed by its namespace (`namespace:name`), or just the name when there is no namespace. */
39
65
  getQualifiedName() {
40
66
  return this.namespace.length === 0
41
67
  ? this.normalizedName
42
68
  : `${this.namespace}:${this.normalizedName}`;
43
69
  }
70
+ /** @returns the effective namespace of the node (its own or inherited from the parent), lower-cased, or the empty string if it has none. */
44
71
  getNamespace() {
45
72
  return this.namespace;
46
73
  }
74
+ /** @returns the children of the node in order of appearance, as a read-only view. */
47
75
  getChildren() {
48
76
  return this.children;
49
77
  }
78
+ /**
79
+ * Appends an already closed child to this node.
80
+ *
81
+ * @param node already closed child to append at the end of this node's list of children.
82
+ */
50
83
  addChild(node) {
51
84
  this.children.push(node);
52
85
  }
86
+ /** @returns the inline value of the node (INLINE node), or the empty string if it is a BLOCK node. */
53
87
  getValue() {
54
88
  return this.value;
55
89
  }
90
+ /** @returns the text lines of a BLOCK node ({@link Node.isTextNode}), in order of appearance. */
56
91
  getTextLines() {
57
92
  return this.textLines;
58
93
  }
94
+ /** @returns the line number of the document where this node was opened. */
59
95
  getLine() {
60
96
  return this.line;
61
97
  }
98
+ /** @returns the indentation level of the node (0 for root nodes). */
62
99
  getLevel() {
63
100
  return this.level;
64
101
  }
102
+ /** @returns true if the node is a text block (BLOCK, `>>`); false if it is INLINE. */
65
103
  isTextNode() {
66
104
  return this.textNode;
67
105
  }
106
+ /** @returns the textual content of the node: the text lines joined with '\n' if it is BLOCK, or the inline value otherwise. */
68
107
  getText() {
69
108
  return this.isTextNode() ? this.textLines.join("\n") : this.value;
70
109
  }
110
+ /**
111
+ * Looks up the only direct child with that name.
112
+ *
113
+ * @param cname name of the child to look for.
114
+ * @param namespace namespace to search in; this node's own namespace when omitted.
115
+ * @returns the only direct child with that name, or null if there is none.
116
+ * @throws RuntimeException with code `AMBIGUOUS_CHILD` if there is more than one; use {@link Node.getChildrenByName} then.
117
+ */
71
118
  getChild(cname, namespace) {
72
119
  const result = this.getChildrenByName(cname, namespace);
73
120
  if (result.length > 1) {
@@ -79,6 +126,13 @@ class Node {
79
126
  return result[0];
80
127
  }
81
128
  // Fast access methods to children
129
+ /**
130
+ * Looks up every direct child with that name.
131
+ *
132
+ * @param cname name of the child to look for.
133
+ * @param namespace namespace to search in; this node's own namespace when omitted.
134
+ * @returns every direct child with that name in the given namespace, in order of appearance.
135
+ */
82
136
  getChildrenByName(cname, namespace) {
83
137
  const key = StringUtils_1.StringUtils.normalize(cname);
84
138
  const targetNamespace = namespace !== undefined ? namespace : this.namespace;
@@ -90,6 +144,7 @@ class Node {
90
144
  }
91
145
  return result;
92
146
  }
147
+ /** @returns a readable representation of the node, for debugging and error messages. */
93
148
  toString() {
94
149
  let s = "Node{";
95
150
  s += `line=${this.line}`;
@@ -111,6 +166,6 @@ class Node {
111
166
  }
112
167
  }
113
168
  exports.Node = Node;
114
- // STXT-SPEC 4.2: letras y dígitos Unicode (categorías L y Nd) más '-', '_' y espacio
169
+ // STXT-SPEC 4.2: Unicode letters and digits (categories L and Nd) plus '-', '_' and space
115
170
  Node.VALID_NAME = /^[\p{L}\p{Nd}\-_ ]+$/u;
116
171
  //# sourceMappingURL=Node.js.map
@@ -1,3 +1,14 @@
1
1
  import { Line } from "./Line";
2
2
  import { Node } from "./Node";
3
+ /**
4
+ * Builds the node a line opens, telling apart the INLINE form (`Name: value`) from the BLOCK one
5
+ * (`Name >>`) and resolving the namespace against the parent.
6
+ *
7
+ * @param lineIndent line already split into indentation and content.
8
+ * @param lineNumber line number of the document where the node opens.
9
+ * @param level indentation level of the node.
10
+ * @param parent node currently open, whose namespace is inherited, or null at root level.
11
+ * @returns the node the line opens, still with no children and no text lines.
12
+ * @throws ParseException if the line is not a valid node declaration.
13
+ */
3
14
  export declare function createNode(lineIndent: Line, lineNumber: number, level: number, parent: Node | null): Node;
@@ -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
- // Namespace por defecto: heredado del padre
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
- // Validamos nombre
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
- // Creamos nodo
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
  }
@@ -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
  }
@@ -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;
@@ -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
- // El salto de línea final es terminador de la última línea, no una línea
35
- // vacía adicional (evita añadir una línea espuria a un bloque >> en EOF, spec 10.3)
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
- // Cerrar todos los nodos pendientes al EOF
74
+ // Close every node still open at EOF
44
75
  this.closeToLevel(stack, documents, 0, result);
45
- // Agregar nodos al resultado
76
+ // Add the nodes to the result
46
77
  for (const doc of documents) {
47
78
  result.addNode(doc);
48
79
  }
49
- // Retorno resultado
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
- // Parseamos línea
88
+ // Parse the line
58
89
  const line = (0, LineParser_1.parseLine)(lineString, lastNodeText, lastLevel, lineNumber);
59
90
  if (line.isComment) {
60
- // Pasamos a observers
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
- // Si estamos dentro de un nodo texto, y el nivel indica que sigue siendo texto,
68
- // añadimos línea de texto y no creamos nodo.
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
- // Notificar a observers sobre la línea de texto
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
- // Si es línea vacía no hacemos nada
108
+ // Empty lines are ignored
78
109
  if (line.isEmpty()) {
79
110
  return;
80
111
  }
81
- // Cerramos nodos hasta el nivel actual (esto "finaliza" y adjunta al padre/documentos)
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
- // Creamos el nuevo nodo y lo dejamos "abierto" en la pila (NO lo adjuntamos aún)
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
- // Pasamos a observers
117
+ // Hand it over to the observers
87
118
  this.observers.forEach(observer => {
88
119
  observer.onCreate(node, lineString);
89
120
  });
90
- // Añadimos a stack
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
- // Convertir errores genéricos a ParseException
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
- // Error desconocido
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
- // Pasamos validators
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
- // Pasamos a observers
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
  }
@@ -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
- // Usado para nodos name>>
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
- // Usado para nodos tipo Base64 y Hex
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
- // Usado para normalizar namespace
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
- // Equivalente práctico a Locale.ROOT en JS: evitar dependencias de locale del usuario
41
+ // Practical equivalent of Locale.ROOT in JS: keep the user's locale out of it
23
42
  return (input ?? "").toLowerCase();
24
43
  }
25
- // Usados para name de los nodos
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
- // Usados para name normalizado de nodos (STXT-SPEC 4.3): NFC + minúsculas,
30
- // conservando diacríticos y alfabetos no latinos (modelo IDN)
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
- // toda secuencia de separadores ('-', '_', espacios) => un solo '-'
69
+ // every run of separators ('-', '_', spaces) => a single '-'
39
70
  s = s.replace(/[-_\s]+/g, "-");
40
- // trim de '-'
71
+ // trim the '-'
41
72
  s = s.replace(/^-+|-+$/g, "");
42
73
  return s;
43
74
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Environment abstraction used by {@link DiscoveryResolver} (STXT-DISCOVERY-SPEC).
3
+ *
4
+ * It answers the three questions that depend on the platform and the process environment:
5
+ * the `STXT_PATH` override, the user-level directory and the system-level directory.
6
+ * Injecting it keeps the resolver free of `process`/`os` access, deterministic in tests
7
+ * and usable from any host (Node, editor extension, browser).
8
+ */
9
+ export interface DiscoveryEnvironment {
10
+ /**
11
+ * The value of the `STXT_PATH` environment variable, already split into entries.
12
+ *
13
+ * The distinction between "not defined" and "defined but empty" is normative
14
+ * (STXT-DISCOVERY-SPEC section 6): when defined, `STXT_PATH` completely replaces the
15
+ * resolution chain, and an empty value leaves the chain empty.
16
+ *
17
+ * @returns the list of directories (highest precedence first), an empty array when the
18
+ * variable is defined but empty, or null when it is not defined at all.
19
+ */
20
+ getStxtPath(): string[] | null;
21
+ /**
22
+ * The user-level resolution directory (`$HOME/.stxt` on Unix, `%USERPROFILE%\.stxt` on
23
+ * Windows), already resolved to a full path.
24
+ *
25
+ * @returns the user-level directory, or null when the host has no notion of a user home.
26
+ */
27
+ getUserLevelDir(): string | null;
28
+ /**
29
+ * The system-level resolution directory (`/etc/stxt` on Unix, `%ProgramData%\stxt` on
30
+ * Windows), already resolved to a full path.
31
+ *
32
+ * @returns the system-level directory, or null when the host has no system level.
33
+ */
34
+ getSystemLevelDir(): string | null;
35
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=DiscoveryEnvironment.js.map