Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions core/modules/parsers/wikiparser/rules/hardlinebreaks.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ exports.init = function(parser) {
};

exports.parse = function() {
var start = this.match.index;
var reEnd = /(""")|(\r?\n)/mg,
tree = [],
match;
Expand All @@ -42,16 +43,20 @@ exports.parse = function() {
reEnd.lastIndex = this.parser.pos;
match = reEnd.exec(this.parser.source);
if(match) {
var start = this.parser.pos;
var brStart = this.parser.pos;
this.parser.pos = reEnd.lastIndex;
// Add a line break if the terminator was a line break
if(match[2]) {
tree.push({type: "element", tag: "br", start: start, end: this.parser.pos});
tree.push({type: "element", tag: "br", rule: "hardlinebreaks", start: brStart, end: this.parser.pos});
}
}
} while(match && !match[1]);
// Mark first and last node, and return the nodes
if(tree[0]) tree[0].isRuleStart = true;
if(tree[tree.length-1]) tree[tree.length-1].isRuleEnd = true;
return tree;
// Return a void wrapper so the inner nodes keep their own rule names,
// e.g. bold inside the region stays rule "bold"
return [{
type: "void",
children: tree,
start: start,
end: this.parser.pos
}];
};
2 changes: 1 addition & 1 deletion editions/test/tiddlers/tests/test-wikitext-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ describe("WikiText parser tests", function() {
it("should parse hard linebreak areas", function() {
expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual(

[ { type : "element", tag : "p", rule: "parseblock", children : [ { type : "text", text : "Something", start : 3, end : 12, rule: "hardlinebreaks", isRuleStart: true }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ]
[ { type : "element", tag : "p", rule: "parseblock", children : [ { type : "void", rule: "hardlinebreaks", start : 0, end : 37, children : [ { type : "text", text : "Something", start : 3, end : 12 }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19 }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33 }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34 } ] } ], start : 0, end : 37 } ]

);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
change-category: developer
change-type: bugfix
created: 20260712223504000
description: Hard linebreaks regions keep the rule names of their inner nodes
github-contributors: pmario
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/issues/9906
modified: 20260712223504000
release: 5.5.0
tags: $:/tags/ChangeNote
title: $:/changenotes/5.5.0/#9906
type: text/vnd.tiddlywiki

The wikitext parser stamps the name of the producing rule onto every parse tree node. The `hardlinebreaks` rule returned a flat array of foreign nodes, so every node inside a `"""` region was stamped `rule: "hardlinebreaks"`, hiding which rule actually produced it. The rule now returns a single wrapper node of type `void` spanning the region, so the inner nodes keep their own rule names. Void nodes render as a pass-through, so the rendered output is unchanged.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
title: $:/changenotes/5.5.0/#9906/impacts/hardlinebreaks-parse-tree
changenote: $:/changenotes/5.5.0/#9906
created: 20260712223504000
modified: 20260712223504000
tags: $:/tags/ImpactNote
description: The parse tree shape of `"""` hard linebreak regions has changed
impact-type: compatibility-break

Content of a `"""` region is now nested one level deeper inside a `void` wrapper node, and the `isRuleStart`/`isRuleEnd` flags (first shipped in v5.4.0) are no longer emitted. Third-party code walking these regions needs to follow the wrapper's children.
21 changes: 14 additions & 7 deletions plugins/tiddlywiki/wikitext-serialize/rules/hardlinebreaks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ module-type: wikiruleserializer

exports.name = "hardlinebreaks";

exports.serialize = function(tree,serialize) {
var text = tree.tag === "br" ? "\n" : (tree.text || "");
if(tree.isRuleStart) {
return '"""\n' + text;
exports.serialize = function(tree,serialize,options) {
options = options || {};
// A br the parser inserted for a line break inside the region
if(tree.tag === "br") {
return "\n";
}
if(tree.isRuleEnd) {
return text + '"""';
// The region can open inline ("""text) or with a line break; only the source knows which
var opener = '"""\n',
first = tree.children && tree.children[0];
if(options.source && typeof tree.start === "number" && first && typeof first.start === "number" && first.start > tree.start) {
var slice = options.source.substring(tree.start,first.start);
if(/^"""\s*$/.test(slice)) {
opener = slice;
}
}
return text + serialize(tree.children);
return opener + serialize(tree.children) + '"""';
};
Loading