@stxt-lang/core 0.14.1 → 0.15.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.
- package/README.md +1 -1
- package/out/core/LineParser.js +1 -1
- package/out/core/Parser.js +7 -0
- package/out/core/TextNode.d.ts +7 -0
- package/out/core/TextNode.js +11 -0
- package/out/runtime/Formatter.d.ts +4 -4
- package/out/runtime/Formatter.js +15 -8
- package/out/runtime/NodeWriter.js +10 -2
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Parser and schema validator for **STXT**, an indentation-based structured-text f
|
|
|
5
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
6
|
|
|
7
7
|
- Website and language reference: <https://stxt.dev>
|
|
8
|
-
- VSCode extension: [STXT
|
|
8
|
+
- VSCode extension: [STXT Language](https://marketplace.visualstudio.com/items?itemName=stxt-lang.stxt)
|
|
9
9
|
- Java implementation: [`dev.stxt:stxt-core`](https://central.sonatype.com/artifact/dev.stxt/stxt-core) on Maven Central
|
|
10
10
|
- Python implementation: [`stxt`](https://pypi.org/project/stxt/) on PyPI
|
|
11
11
|
|
package/out/core/LineParser.js
CHANGED
|
@@ -64,7 +64,7 @@ function parseLine(line, lastNodeBlock, lastLevel, numLine, validate = true) {
|
|
|
64
64
|
if (lastNodeBlock && level > lastLevel) {
|
|
65
65
|
const text = StringUtils_1.StringUtils.rightTrim(line.substring(pointer + 1));
|
|
66
66
|
// The prefix covering the block level must be homogeneous (spec 10.2, rule 2);
|
|
67
|
-
// empty lines are
|
|
67
|
+
// empty lines are never an error and are exempt from it (spec 10.3)
|
|
68
68
|
if (validate && sawSpace && sawTab && text.length > 0) {
|
|
69
69
|
throw new ParseException_1.ParseException(numLine, "INDENTATION_MIXED", `Mixed tabs and spaces in indentation`);
|
|
70
70
|
}
|
package/out/core/Parser.js
CHANGED
|
@@ -257,6 +257,13 @@ class Parser {
|
|
|
257
257
|
closeToLevel(stack, targetLevel, result) {
|
|
258
258
|
while (stack.length > targetLevel) {
|
|
259
259
|
const completed = stack.pop();
|
|
260
|
+
// A closing block node drops its final empty lines (STXT-SPEC §10.3): they are not
|
|
261
|
+
// content, only visual separation or an editor's final line breaks. The validators
|
|
262
|
+
// and observers below already see the trimmed node; onTextLine did fire for these
|
|
263
|
+
// lines while the block was open, as process observation of the source.
|
|
264
|
+
if (completed instanceof TextNode_1.TextNode) {
|
|
265
|
+
completed.removeTrailingEmptyLines();
|
|
266
|
+
}
|
|
260
267
|
// Hand it over to the validators
|
|
261
268
|
this.validators.forEach(validator => {
|
|
262
269
|
try {
|
package/out/core/TextNode.d.ts
CHANGED
|
@@ -56,6 +56,13 @@ export declare class TextNode extends Node {
|
|
|
56
56
|
addTextLine(line: string): void;
|
|
57
57
|
/** Removes every text line. */
|
|
58
58
|
clearText(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Removes the final empty lines (`""` elements at the end of the lines). The {@link Parser}
|
|
61
|
+
* calls it when the block closes (STXT-SPEC §10.3: the final empty lines of a block are not
|
|
62
|
+
* content); it is public because a programmatically built node may want the same
|
|
63
|
+
* normalization before writing.
|
|
64
|
+
*/
|
|
65
|
+
removeTrailingEmptyLines(): void;
|
|
59
66
|
getText(): string;
|
|
60
67
|
isTextNode(): boolean;
|
|
61
68
|
private static splitLines;
|
package/out/core/TextNode.js
CHANGED
|
@@ -61,6 +61,17 @@ class TextNode extends Node_1.Node {
|
|
|
61
61
|
clearText() {
|
|
62
62
|
this.lines.length = 0;
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Removes the final empty lines (`""` elements at the end of the lines). The {@link Parser}
|
|
66
|
+
* calls it when the block closes (STXT-SPEC §10.3: the final empty lines of a block are not
|
|
67
|
+
* content); it is public because a programmatically built node may want the same
|
|
68
|
+
* normalization before writing.
|
|
69
|
+
*/
|
|
70
|
+
removeTrailingEmptyLines() {
|
|
71
|
+
while (this.lines.length > 0 && this.lines[this.lines.length - 1] === "") {
|
|
72
|
+
this.lines.pop();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
64
75
|
getText() {
|
|
65
76
|
return this.lines.join("\n");
|
|
66
77
|
}
|
|
@@ -33,10 +33,10 @@ export interface FormatResult {
|
|
|
33
33
|
* - A **text line of a block** gets the indentation of the block (its level plus one) in the
|
|
34
34
|
* requested style, followed by its content; any indentation the line had beyond the block's
|
|
35
35
|
* is content (STXT-SPEC §10.2, relative indentation is preserved) and is kept exactly. A
|
|
36
|
-
* blank line
|
|
37
|
-
* (STXT-SPEC §10.3), so it is written with the indentation of the block too: the
|
|
38
|
-
* as one piece
|
|
39
|
-
*
|
|
36
|
+
* blank line that precedes more block text is `""` in the content whatever it looks like in
|
|
37
|
+
* the source (STXT-SPEC §10.3), so it is written with the indentation of the block too: the
|
|
38
|
+
* block reads as one piece. The final blank lines of a block are not content (STXT-SPEC
|
|
39
|
+
* §10.3: the parser drops them when the block closes) and fall under the next rule.
|
|
40
40
|
* - Every **other line** — a comment, a blank line outside a block, or a line the parse tree
|
|
41
41
|
* does not describe because of a syntax error — is kept as the author wrote it, except that
|
|
42
42
|
* its trailing blanks are removed and the whole indentation units at its start are converted
|
package/out/runtime/Formatter.js
CHANGED
|
@@ -23,10 +23,10 @@ const NodeWriter_1 = require("./NodeWriter");
|
|
|
23
23
|
* - A **text line of a block** gets the indentation of the block (its level plus one) in the
|
|
24
24
|
* requested style, followed by its content; any indentation the line had beyond the block's
|
|
25
25
|
* is content (STXT-SPEC §10.2, relative indentation is preserved) and is kept exactly. A
|
|
26
|
-
* blank line
|
|
27
|
-
* (STXT-SPEC §10.3), so it is written with the indentation of the block too: the
|
|
28
|
-
* as one piece
|
|
29
|
-
*
|
|
26
|
+
* blank line that precedes more block text is `""` in the content whatever it looks like in
|
|
27
|
+
* the source (STXT-SPEC §10.3), so it is written with the indentation of the block too: the
|
|
28
|
+
* block reads as one piece. The final blank lines of a block are not content (STXT-SPEC
|
|
29
|
+
* §10.3: the parser drops them when the block closes) and fall under the next rule.
|
|
30
30
|
* - Every **other line** — a comment, a blank line outside a block, or a line the parse tree
|
|
31
31
|
* does not describe because of a syntax error — is kept as the author wrote it, except that
|
|
32
32
|
* its trailing blanks are removed and the whole indentation units at its start are converted
|
|
@@ -85,8 +85,11 @@ class Formatter {
|
|
|
85
85
|
if (node) {
|
|
86
86
|
return Formatter.renderNode(node, line, style);
|
|
87
87
|
}
|
|
88
|
+
// A final empty line of a block is not content (STXT-SPEC §10.3): the parser removed it
|
|
89
|
+
// from the node when the block closed, so its index falls beyond the logical lines. It
|
|
90
|
+
// is kept as any other line: blank, unindented.
|
|
88
91
|
const text = sourceLines.textAt(lineNumber);
|
|
89
|
-
if (text) {
|
|
92
|
+
if (text && text.index < text.node.getTextLines().length) {
|
|
90
93
|
return Formatter.indent(text.node.getLevel() + 1, style) + text.line.content;
|
|
91
94
|
}
|
|
92
95
|
return Formatter.convertUnits(StringUtils_1.StringUtils.rightTrim(line), style);
|
|
@@ -172,7 +175,10 @@ class SourceLines {
|
|
|
172
175
|
// Comment lines need no bookkeeping: every line that opens no node is treated alike.
|
|
173
176
|
}
|
|
174
177
|
onTextLine(node, lineNumber, lineString, line) {
|
|
175
|
-
|
|
178
|
+
// The line was just appended: its 0-based index in the block is the current last. After
|
|
179
|
+
// the block closes and drops its final empty lines (STXT-SPEC §10.3), an index beyond
|
|
180
|
+
// getTextLines() marks the line as a final empty line, not content.
|
|
181
|
+
this.textByLine.set(lineNumber, { node, line, index: node.getTextLines().length - 1 });
|
|
176
182
|
}
|
|
177
183
|
/**
|
|
178
184
|
* @param lineNumber line number, 1-indexed.
|
|
@@ -183,8 +189,9 @@ class SourceLines {
|
|
|
183
189
|
}
|
|
184
190
|
/**
|
|
185
191
|
* @param lineNumber line number, 1-indexed.
|
|
186
|
-
* @returns the block node this line is text of
|
|
187
|
-
*
|
|
192
|
+
* @returns the block node this line is text of, the line already split into indentation and
|
|
193
|
+
* content, and its 0-based index in the block; or undefined if the line is not text
|
|
194
|
+
* of a block.
|
|
188
195
|
*/
|
|
189
196
|
textAt(lineNumber) {
|
|
190
197
|
return this.textByLine.get(lineNumber);
|
|
@@ -59,9 +59,17 @@ class NodeWriter {
|
|
|
59
59
|
}
|
|
60
60
|
if (n instanceof TextNode_1.TextNode) {
|
|
61
61
|
out.push(" >>\n");
|
|
62
|
-
|
|
62
|
+
// Final empty lines are not emitted (STXT-TREE-SPEC 11.1 rule 6): parsing never
|
|
63
|
+
// produces them (STXT-SPEC 10.3), and on a programmatically built node they would
|
|
64
|
+
// not survive the round trip.
|
|
65
|
+
const lines = n.getTextLines();
|
|
66
|
+
let last = lines.length;
|
|
67
|
+
while (last > 0 && lines[last - 1] === "") {
|
|
68
|
+
last--;
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i < last; i++) {
|
|
63
71
|
NodeWriter.indent(out, depth + 1, style);
|
|
64
|
-
out.push(
|
|
72
|
+
out.push(lines[i], "\n");
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
else if (n instanceof InlineNode_1.InlineNode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stxt-lang/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Parser and schema validator for STXT, an indentation-based structured-text format.",
|
|
5
5
|
"main": "out/all.js",
|
|
6
6
|
"types": "out/all.d.ts",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"stxt",
|
|
37
|
-
"semantic text",
|
|
38
37
|
"parser",
|
|
39
38
|
"schema",
|
|
40
39
|
"validation",
|