Page MenuHomePhabricator

D10154.id24426.diff
No OneTemporary

D10154.id24426.diff

diff --git a/src/markup/engine/__tests__/remarkup/list-paragraphs.txt b/src/markup/engine/__tests__/remarkup/list-paragraphs.txt
new file mode 100644
--- /dev/null
+++ b/src/markup/engine/__tests__/remarkup/list-paragraphs.txt
@@ -0,0 +1,27 @@
+- This is a list item
+ with several paragraphs.
+
+ This is the second paragraph
+ of the first list item.
+- This is the second item
+ in the list.
+ - This is a sublist.
+- This is the third item in the list.
+
+~~~~~~~~~~
+<ul class="remarkup-list">
+<li class="remarkup-list-item">This is a list item with several paragraphs.
+<br /><br />
+This is the second paragraph of the first list item.</li>
+<li class="remarkup-list-item">This is the second item in the list.<ul class="remarkup-list">
+<li class="remarkup-list-item">This is a sublist.</li>
+</ul></li>
+<li class="remarkup-list-item">This is the third item in the list.</li>
+</ul>
+~~~~~~~~~~
+- This is a list item with several paragraphs.
+
+ This is the second paragraph of the first list item.
+- This is the second item in the list.
+ - This is a sublist.
+- This is the third item in the list.
diff --git a/src/markup/engine/remarkup/blockrule/PhutilRemarkupListBlockRule.php b/src/markup/engine/remarkup/blockrule/PhutilRemarkupListBlockRule.php
--- a/src/markup/engine/remarkup/blockrule/PhutilRemarkupListBlockRule.php
+++ b/src/markup/engine/remarkup/blockrule/PhutilRemarkupListBlockRule.php
@@ -31,14 +31,29 @@
continue;
}
- if (strlen(trim($lines[$cursor]))
- && strlen($lines[$cursor]) !== strlen(ltrim($lines[$cursor]))) {
- $num_lines++;
- $cursor++;
- continue;
+ // Allow lists to continue across multiple paragraphs, as long as lines
+ // are indented or a single empty line separates indented lines.
+
+ $this_empty = !strlen(trim($lines[$cursor]));
+ $this_indented = preg_match('/^ /', $lines[$cursor]);
+
+ $next_empty = true;
+ $next_indented = false;
+ if (isset($lines[$cursor + 1])) {
+ $next_empty = !strlen(trim($lines[$cursor + 1]));
+ $next_indented = preg_match('/^ /', $lines[$cursor + 1]);
+ }
+
+ if ($this_empty || $this_indented) {
+ if (($this_indented && !$this_empty) ||
+ ($next_indented && !$next_empty)) {
+ $num_lines++;
+ $cursor++;
+ continue;
+ }
}
- if (!strlen(trim($lines[$cursor]))) {
+ if ($this_empty) {
$num_lines++;
}
}
@@ -155,6 +170,9 @@
// Process each item to normalize the text, remove line wrapping, and
// determine its depth (indentation level) and style (ordered vs unordered).
//
+ // We preserve consecutive linebreaks and interpret them as paragraph
+ // breaks.
+ //
// Given the above example, the processed array will look like:
//
// array(
@@ -172,7 +190,14 @@
$has_marks = false;
foreach ($items as $key => $item) {
- $item = preg_replace('/\s*\n\s*/', ' ', implode("\n", $item));
+ // Trim space around newlines, to strip trailing whitespace and formatting
+ // indentation.
+ $item = preg_replace('/ *(\n+) */', '\1', implode("\n", $item));
+
+ // Replace single newlines with a space. Preserve multiple newlines as
+ // paragraph breaks.
+ $item = preg_replace('/(?<!\n)\n(?!\n)/', ' ', $item);
+
$item = rtrim($item);
if (!strlen($item)) {
@@ -425,7 +450,8 @@
if ($item['text'] === null) {
// Don't render anything.
} else {
- $out[] = str_repeat(' ', 2 * $level);
+ $indent = str_repeat(' ', 2 * $level);
+ $out[] = $indent;
if ($item['mark'] !== null) {
if ($item['mark']) {
$out[] = '[X] ';
@@ -443,7 +469,15 @@
break;
}
}
- $out[] = $this->applyRules($item['text'])."\n";
+
+ $parts = preg_split('/\n{2,}/', $item['text']);
+ foreach ($parts as $key => $part) {
+ if ($key != 0) {
+ $out[] = "\n\n ".$indent;
+ }
+ $out[] = $this->applyRules($part);
+ }
+ $out[] = "\n";
}
} else {
if ($item['text'] === null) {
@@ -469,7 +503,18 @@
$out[] = hsprintf('<li class="remarkup-list-item">');
}
- $out[] = $this->applyRules($item['text']);
+ $parts = preg_split('/\n{2,}/', $item['text']);
+ foreach ($parts as $key => $part) {
+ if ($key != 0) {
+ $out[] = array(
+ "\n",
+ phutil_tag('br'),
+ phutil_tag('br'),
+ "\n",
+ );
+ }
+ $out[] = $this->applyRules($part);
+ }
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jun 7, 4:38 PM (2 w, 18 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6276511
Default Alt Text
D10154.id24426.diff (4 KB)

Event Timeline