Skip to content

Commit aab3c3e

Browse files
authored
remark: rework list fields
* remark-parse: remove `loose` fields from `list`, `listItem` * remark-parse: add support for empty list-items in any non-pedantic mode * remark-parse: add `spread` to `list`, to signal that its items should have blank lines between them, set to true if any blank line exists between items * remark-parse: add `spread` to `listItem`, to signal that its children should have blank lines between them * remark-parse: fix bug where two lists, if they are both ordered or both not ordered, was seen in commonmark as one list * remark-stringify: add support for missing `ordered` field * remark-stringify: add support for missing `start` field * remark-stringify: add support for `list.spread` (default: false) * remark-stringify: add support for `listItem.spread` (default: true) * remark-stringify: fix bug where two lists, if they are both ordered or both not ordered, and in commonmark, were not properly stringified, resulting in a new parse seeing them as one list * remark-stringify: fix bug where a list followed by an indented code block, in commonmark, was not correctly stringified, resulting in a new parse seeing the code as content of the list * remark-stringify: remove trailing white-space on empty list-items * remark-stringify: add support for stringifying list-items without parent Related to syntax-tree/mdast#4. Related to syntax-tree/mdast-util-to-hast#23. Related to GH-349. Closes GH-332. Closes GH-350. Closes GH-358. Closes GH-364. Reviewed-by: Elijah Hamovitz <elijahhamovitz@gmail.com> Reviewed-by: Ika <ikatyang@gmail.com>
1 parent 3325c33 commit aab3c3e

File tree

171 files changed

+3155
-2695
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+3155
-2695
lines changed

contributing.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ next to their day job: you are not entitled to free customer service.
1515
* [Ecosystem](#ecosystem)
1616
* [Questions](#questions)
1717
* [Contributions](#contributions)
18+
1819
* [Improve documentation](#improve-documentation)
1920
* [Improve issues](#improve-issues)
2021
* [Give feedback on issues](#give-feedback-on-issues)

packages/remark-parse/lib/tokenize/list.js

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function list(eat, value, silent) {
8080
var item;
8181
var enterTop;
8282
var exitBlockquote;
83-
var isLoose;
83+
var spread = false;
8484
var node;
8585
var now;
8686
var end;
@@ -143,7 +143,7 @@ function list(eat, value, silent) {
143143
if (
144144
character !== C_SPACE &&
145145
character !== C_TAB &&
146-
(!commonmark || (character !== C_NEWLINE && character !== C_EMPTY))
146+
(pedantic || (character !== C_NEWLINE && character !== C_EMPTY))
147147
) {
148148
return;
149149
}
@@ -282,14 +282,15 @@ function list(eat, value, silent) {
282282
}
283283

284284
prevEmpty = empty;
285-
empty = !trim(content).length;
285+
empty = !prefixed && !trim(content).length;
286286

287287
if (indented && item) {
288288
item.value = item.value.concat(emptyLines, line);
289289
allLines = allLines.concat(emptyLines, line);
290290
emptyLines = [];
291291
} else if (prefixed) {
292292
if (emptyLines.length !== 0) {
293+
spread = true;
293294
item.value.push('');
294295
item.trail = emptyLines.concat();
295296
}
@@ -304,7 +305,7 @@ function list(eat, value, silent) {
304305
allLines = allLines.concat(emptyLines, line);
305306
emptyLines = [];
306307
} else if (empty) {
307-
if (prevEmpty) {
308+
if (prevEmpty && !commonmark) {
308309
break;
309310
}
310311

@@ -330,25 +331,20 @@ function list(eat, value, silent) {
330331
type: 'list',
331332
ordered: ordered,
332333
start: start,
333-
loose: null,
334+
spread: spread,
334335
children: []
335336
});
336337

337338
enterTop = self.enterList();
338339
exitBlockquote = self.enterBlock();
339-
isLoose = false;
340340
index = -1;
341341
length = items.length;
342342

343343
while (++index < length) {
344344
item = items[index].value.join(C_NEWLINE);
345345
now = eat.now();
346346

347-
item = eat(item)(listItem(self, item, now), node);
348-
349-
if (item.loose) {
350-
isLoose = true;
351-
}
347+
eat(item)(listItem(self, item, now), node);
352348

353349
item = items[index].trail.join(C_NEWLINE);
354350

@@ -362,8 +358,6 @@ function list(eat, value, silent) {
362358
enterTop();
363359
exitBlockquote();
364360

365-
node.loose = isLoose;
366-
367361
return node;
368362
}
369363

@@ -389,8 +383,7 @@ function listItem(ctx, value, position) {
389383

390384
return {
391385
type: 'listItem',
392-
loose: EXPRESSION_LOOSE_LIST_ITEM.test(value) ||
393-
value.charAt(value.length - 1) === C_NEWLINE,
386+
spread: EXPRESSION_LOOSE_LIST_ITEM.test(value),
394387
checked: checked,
395388
children: ctx.tokenizeBlock(value, position)
396389
};

packages/remark-parse/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ process.stdin
3333
## Table of Contents
3434

3535
* [API](#api)
36+
3637
* [processor.use(parse\[, options\])](#processoruseparse-options)
3738
* [parse.Parser](#parseparser)
3839
* [Extending the Parser](#extending-the-parser)
40+
3941
* [Parser#blockTokenizers](#parserblocktokenizers)
4042
* [Parser#blockMethods](#parserblockmethods)
4143
* [Parser#inlineTokenizers](#parserinlinetokenizers)

packages/remark-stringify/lib/macro/block.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,55 @@
22

33
module.exports = block;
44

5+
var newline = '\n';
6+
var double = newline + newline;
7+
var triple = double + newline;
8+
var comment = double + '<!---->' + double;
9+
510
/* Stringify a block node with block children (e.g., `root`
611
* or `blockquote`).
712
* Knows about code following a list, or adjacent lists
813
* with similar bullets, and places an extra newline
914
* between them. */
1015
function block(node) {
1116
var self = this;
17+
var options = self.options;
18+
var fences = options.fences;
19+
var gap = options.commonmark ? comment : triple;
1220
var values = [];
1321
var children = node.children;
1422
var length = children.length;
1523
var index = -1;
16-
var child;
1724
var prev;
25+
var child;
1826

1927
while (++index < length) {
28+
prev = child;
2029
child = children[index];
2130

2231
if (prev) {
23-
/* Duplicate nodes, such as a list
24-
* directly following another list,
25-
* often need multiple new lines.
26-
*
27-
* Additionally, code blocks following a list
28-
* might easily be mistaken for a paragraph
29-
* in the list itself. */
30-
if (child.type === prev.type && prev.type === 'list') {
31-
values.push(prev.ordered === child.ordered ? '\n\n\n' : '\n\n');
32-
} else if (prev.type === 'list' && child.type === 'code' && !child.lang) {
33-
values.push('\n\n\n');
32+
// A list preceding another list that are equally ordered, or a
33+
// list preceding an indented code block, need a gap between them,
34+
// so as not to see them as one list, or content of the list,
35+
// respectively.
36+
//
37+
// In commonmark, only something that breaks both up can do that,
38+
// so we opt for an empty, invisible comment. In other flavours,
39+
// two blank lines are fine.
40+
if (
41+
prev.type === 'list' &&
42+
(
43+
(child.type === 'list' && prev.ordered === child.ordered) ||
44+
(child.type === 'code' && (!child.lang && !fences))
45+
)
46+
) {
47+
values.push(gap);
3448
} else {
35-
values.push('\n\n');
49+
values.push(double);
3650
}
3751
}
3852

3953
values.push(self.visit(child, node));
40-
41-
prev = child;
4254
}
4355

4456
return values.join('');

packages/remark-stringify/lib/macro/ordered-items.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ function orderedItems(node) {
2828
var index = -1;
2929
var bullet;
3030

31+
start = start == null ? 1 : start;
32+
3133
while (++index < length) {
3234
bullet = (increment ? start + index : start) + '.';
3335
values[index] = fn.call(self, children[index], node, index, bullet);
3436
}
3537

36-
return values.join('\n');
38+
return values.join(node.spread ? '\n\n' : '\n');
3739
}

packages/remark-stringify/lib/macro/unordered-items.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ function unorderedItems(node) {
1818
values[index] = fn.call(self, children[index], node, index, bullet);
1919
}
2020

21-
return values.join('\n');
21+
return values.join(node.spread ? '\n\n' : '\n');
2222
}

packages/remark-stringify/lib/visitors/list-item.js

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ var pad = require('../util/pad');
55

66
module.exports = listItem;
77

8-
/* Which checkbox to use. */
9-
var CHECKBOX_MAP = {
10-
undefined: '',
11-
null: '',
12-
true: '[x] ',
13-
false: '[ ] '
14-
};
15-
168
/* Stringify a list item.
179
*
1810
* Prefixes the content with a checked checkbox when
@@ -28,7 +20,9 @@ var CHECKBOX_MAP = {
2820
function listItem(node, parent, position, bullet) {
2921
var self = this;
3022
var style = self.options.listItemIndent;
31-
var loose = node.loose;
23+
var marker = bullet || self.options.bullet;
24+
var spread = node.spread == null ? true : node.spread;
25+
var checked = node.checked;
3226
var children = node.children;
3327
var length = children.length;
3428
var values = [];
@@ -41,21 +35,22 @@ function listItem(node, parent, position, bullet) {
4135
values[index] = self.visit(children[index], node);
4236
}
4337

44-
value = CHECKBOX_MAP[node.checked] + values.join(loose ? '\n\n' : '\n');
38+
value = values.join(spread ? '\n\n' : '\n');
39+
40+
if (typeof checked === 'boolean') {
41+
// Note: I’d like to be able to only add the space between the check and
42+
// the value, but unfortunately github does not support empty list-items
43+
// with a checkbox :(
44+
value = '[' + (checked ? 'x' : ' ') + '] ' + value;
45+
}
4546

4647
if (style === '1' || (style === 'mixed' && value.indexOf('\n') === -1)) {
47-
indent = bullet.length + 1;
48+
indent = marker.length + 1;
4849
spacing = ' ';
4950
} else {
50-
indent = Math.ceil((bullet.length + 1) / 4) * 4;
51-
spacing = repeat(' ', indent - bullet.length);
52-
}
53-
54-
value = bullet + spacing + pad(value, indent / 4).slice(indent);
55-
56-
if (loose && parent.children.length - 1 !== position) {
57-
value += '\n';
51+
indent = Math.ceil((marker.length + 1) / 4) * 4;
52+
spacing = repeat(' ', indent - marker.length);
5853
}
5954

60-
return value;
55+
return value ? marker + spacing + pad(value, indent / 4).slice(indent) : marker;
6156
}

packages/remark-stringify/lib/visitors/list.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ var ORDERED_MAP = {
99
};
1010

1111
function list(node) {
12-
return this[ORDERED_MAP[node.ordered]](node);
12+
var ordered = node.ordered;
13+
return this[ORDERED_MAP[ordered == null ? false : ordered]](node);
1314
}

packages/remark-stringify/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ process.stdin
4040
## Table of Contents
4141

4242
* [API](#api)
43+
4344
* [processor.use(stringify\[, options\])](#processorusestringify-options)
4445
* [stringify.Compiler](#stringifycompiler)
4546
* [Extending the Compiler](#extending-the-compiler)
47+
4648
* [Compiler#visitors](#compilervisitors)
4749
* [function visitor(node\[, parent\])](#function-visitornode-parent)
4850
* [License](#license)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-

test/fixtures/tree/auto-link.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,11 @@
344344
"type": "list",
345345
"ordered": false,
346346
"start": null,
347-
"loose": false,
347+
"spread": false,
348348
"children": [
349349
{
350350
"type": "listItem",
351-
"loose": false,
351+
"spread": false,
352352
"checked": null,
353353
"children": [
354354
{
@@ -403,7 +403,7 @@
403403
},
404404
{
405405
"type": "listItem",
406-
"loose": false,
406+
"spread": false,
407407
"checked": null,
408408
"children": [
409409
{
@@ -478,7 +478,7 @@
478478
},
479479
{
480480
"type": "listItem",
481-
"loose": false,
481+
"spread": false,
482482
"checked": null,
483483
"children": [
484484
{

0 commit comments

Comments
 (0)