From 00927d2e13ece5a14bf8ec5364e3e3f5da85a846 Mon Sep 17 00:00:00 2001
From: "jeremy@jermolene.com"
Date: Wed, 23 Nov 2022 22:35:32 +0000
Subject: [PATCH] Add parsermode pragma
Fixes #7058
---
.../parsers/wikiparser/rules/parsermode.js | 68 +++++++++++++++++++
core/modules/parsers/wikiparser/wikiparser.js | 4 +-
.../tests/data/pragmas/Parsermode.tid | 36 ++++++++++
.../tiddlers/pragmas/Pragma_ _parsermode.tid | 17 +++++
.../wikitext/parser/WikiText Parser Modes.tid | 2 +-
5 files changed, 125 insertions(+), 2 deletions(-)
create mode 100644 core/modules/parsers/wikiparser/rules/parsermode.js
create mode 100644 editions/test/tiddlers/tests/data/pragmas/Parsermode.tid
create mode 100644 editions/tw5.com/tiddlers/pragmas/Pragma_ _parsermode.tid
diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js
new file mode 100644
index 000000000..ad4287f99
--- /dev/null
+++ b/core/modules/parsers/wikiparser/rules/parsermode.js
@@ -0,0 +1,68 @@
+/*\
+title: $:/core/modules/parsers/wikiparser/rules/parsermode.js
+type: application/javascript
+module-type: wikirule
+
+Wiki pragma rule for parser mode specifications
+
+```
+\parsermode block
+\parsermode inline
+```
+
+\*/
+(function(){
+
+/*jslint node: true, browser: true */
+/*global $tw: false */
+"use strict";
+
+exports.name = "parsermode";
+exports.types = {pragma: true};
+
+/*
+Instantiate parse rule
+*/
+exports.init = function(parser) {
+ this.parser = parser;
+ // Regexp to match
+ this.matchRegExp = /^\\parsermode[^\S\n]/mg;
+};
+
+/*
+Parse the most recent match
+*/
+exports.parse = function() {
+ // Move past the pragma invocation
+ this.parser.pos = this.matchRegExp.lastIndex;
+ // Parse whitespace delimited tokens terminated by a line break
+ var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
+ parserMode = undefined;
+ reMatch.lastIndex = this.parser.pos;
+ var match = reMatch.exec(this.parser.source);
+ while(match && match.index === this.parser.pos) {
+ this.parser.pos = reMatch.lastIndex;
+ // Exit if we've got the line break
+ if(match[2]) {
+ break;
+ }
+ // Process the token
+ if(match[1]) {
+ parserMode = match[1];
+ }
+ // Match the next token
+ match = reMatch.exec(this.parser.source);
+ }
+ // Process the tokens
+ if(parserMode !== undefined) {
+ if(parserMode === "block") {
+ this.parser.parseAsInline = false;
+ } else if(parserMode === "inline") {
+ this.parser.parseAsInline = true;
+ }
+ }
+ // No parse tree nodes to return
+ return [];
+};
+
+})();
diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
index 8d6c442de..4c7419030 100644
--- a/core/modules/parsers/wikiparser/wikiparser.js
+++ b/core/modules/parsers/wikiparser/wikiparser.js
@@ -47,6 +47,8 @@ var WikiParser = function(type,text,options) {
this.sourceLength = this.source.length;
// Flag for ignoring whitespace
this.configTrimWhiteSpace = false;
+ // Parser mode
+ this.parseAsInline = options.parseAsInline;
// Set current parse position
this.pos = 0;
// Start with empty output
@@ -83,7 +85,7 @@ var WikiParser = function(type,text,options) {
// Parse any pragmas
var topBranch = this.parsePragmas();
// Parse the text into inline runs or blocks
- if(options.parseAsInline) {
+ if(this.parseAsInline) {
topBranch.push.apply(topBranch,this.parseInlineRun());
} else {
topBranch.push.apply(topBranch,this.parseBlocks());
diff --git a/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid b/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid
new file mode 100644
index 000000000..57869e37a
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid
@@ -0,0 +1,36 @@
+title: Pragmas/Parsermode
+description: parsermode pragma
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: Output
+
+{{AlwaysInline}}
+
+{{AlwaysBlock}}
+
+{{AlwaysInline}}{{AlwaysBlock}}
+
++
+title: AlwaysInline
+
+\parsermode inline
+! Not Heading
+
+Text with ''bold''
++
+title: AlwaysBlock
+
+\parsermode block
+! Heading
+
+Text with ''bold''
++
+title: ExpectedResult
+
+! Not Heading
+
+Text with boldHeading
Text with bold
! Not Heading
+
+Text with bold
Heading
Text with bold
+
\ No newline at end of file
diff --git a/editions/tw5.com/tiddlers/pragmas/Pragma_ _parsermode.tid b/editions/tw5.com/tiddlers/pragmas/Pragma_ _parsermode.tid
new file mode 100644
index 000000000..2b0444ef4
--- /dev/null
+++ b/editions/tw5.com/tiddlers/pragmas/Pragma_ _parsermode.tid
@@ -0,0 +1,17 @@
+created: 20221123223127425
+modified: 20221123223127425
+tags: Pragmas
+title: Pragma: \parsermode
+type: text/vnd.tiddlywiki
+
+The ''\parsermode'' [[pragma|Pragmas]] adjusts whether the remaining text is parsed in block mode or inline mode. See [[WikiText Parser Modes]] for details of parser modes.
+
+```
+\parsermode block|inline
+```
+
+For example:
+
+```
+\parsermode inline
+```
diff --git a/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid b/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid
index 4a9c431b2..8056b9493 100644
--- a/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid
+++ b/editions/tw5.com/tiddlers/wikitext/parser/WikiText Parser Modes.tid
@@ -10,7 +10,7 @@ In order to display Tiddlers (usually the text field), the WikiText parser reads
* ''block mode'' - the parser will recognise only [[block mode WikiText|Block Mode WikiText]] punctuation
* ''inline mode'' - the parser will recognise only [[inline mode WikiText|Inline Mode WikiText]]
-The parser [[transitions between these modes|WikiText parser mode transitions]] based on the text it encounters. In addition, there are [[places where the parser ignores WikiText|Places where the parser ignores WikiText]] punctuation.
+The parser [[transitions between these modes|WikiText parser mode transitions]] based on the text it encounters. In addition, there are [[places where the parser ignores WikiText|Places where the parser ignores WikiText]] punctuation. The parser mode can also be set directly with the [[Pragma: \parsermode]].
<<.tip "The concept of inline vs block also exists for standard HTML elements. For HTML, these [[two layout modes|https://www.w3schools.com/html/html_blocks.asp]] determine if the output flows together on the same line or not.
Most [[block mode WikiText|Block Mode WikiText]] corresponds to [[block level HTML elements|https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements]] and most [[inline mode WikiText|Inline Mode WikiText]] corresponds to [[inline level HTML elements|https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements]]. However, for Wikitext the two modes are just as important for determining which syntax will be recognised by the parser as they are for determining how the output will flow.
">>
\ No newline at end of file