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 bold

Heading

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