Page MenuHomePhabricator

remarkup literal block requires text on beginning line
Closed, ResolvedPublic

Description

Hi,

this is at least odd:

%%%
This is **not** literal, but the %%% are swallowed.
%%%

Result (the "not" is bold, the outer %%% are not visible):


This is **not** literal, but the %%% are swallowed.

%%% This **is** literal.
%%%

Result (asterisk, asterisk, "is", asterisk, asterisk):

This **is** literal.

I'd expect both variants worked, or at least the %%% survive to make it clear that they were not parsed as literal block.

Version:

Event Timeline

This rule is constructed very awkwardly and I'd sort of prefer to remove it entirely, but I think we can technically fix this without really disrupting things.

The %%% on its own line is sufficient to both start and terminate the block. This is silly and presumably never intended.

It looks like the existing test cases in master fail on PHP 7.1, presumably because of T10929, so that needs to be fixed before I can fix this.

This is probably the fix:

commit 9d3f1aa466b2052c780e907cf84b6257ffc91cd1
Author: epriestley <git@epriestley.com>
Date:   Sat Apr 22 09:10:47 2017 -0700

    WIP

diff --git a/src/markup/engine/__tests__/remarkup/percent-block-solo.txt b/src/markup/engine/__tests__/remarkup/percent-block-solo.txt
new file mode 100644
index 0000000..eb9a2ef
--- /dev/null
+++ b/src/markup/engine/__tests__/remarkup/percent-block-solo.txt
@@ -0,0 +1,11 @@
+%%%
+**x**
+%%%
+~~~~~~~~~~
+<p class="remarkup-literal">
+<br />**x**
+<br /></p>
+~~~~~~~~~~
+
+**x**
+
diff --git a/src/markup/engine/remarkup/blockrule/PhutilRemarkupLiteralBlockRule.php b/src/markup/engine/remarkup/blockrule/PhutilRemarkupLiteralBlockRule.php
index c1d4a0a..2cb8ee2 100644
--- a/src/markup/engine/remarkup/blockrule/PhutilRemarkupLiteralBlockRule.php
+++ b/src/markup/engine/remarkup/blockrule/PhutilRemarkupLiteralBlockRule.php
@@ -22,6 +22,13 @@ final class PhutilRemarkupLiteralBlockRule extends PhutilRemarkupBlockRule {
     while (preg_match('/^\s*%%%/', $lines[$cursor])) {
       $num_lines++;
 
+      // If the line has ONLY "%%%", the block opener doesn't get to double
+      // up as a block terminator.
+      if (preg_match('/^\s*%%%\s*\z/', $lines[$cursor])) {
+        $num_lines++;
+        $cursor++;
+      }
+
       while (isset($lines[$cursor])) {
         if (!preg_match('/%%%\s*$/', $lines[$cursor])) {
           $num_lines++;