Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit cc972b7

Browse files
authored
Merge 43653d3 into ee3f4e9
2 parents ee3f4e9 + 43653d3 commit cc972b7

22 files changed

+239
-101
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66
`indicatorForCheckedCheckBox`, and `indicatorForUncheckedCheckBox`.
77
* **Breaking change**: Removed `BlockHtmlSyntax`, `BlockTagBlockHtmlSyntax`,
88
`LongBlockHtmlSyntax`, and `OtherTagBlockHtmlSyntax`.
9+
* **Breaking change**: Change the `line` properties of type `String` to `Line`.
10+
* **Breaking change**: Change the `lines` properties of type `List<String>` to
11+
`List<Line>`.
912
* Add a new syntax `HtmlBlockSyntax` to parse HTML blocks.
1013
* Add a new syntax `DecodeHtmlSyntax` to decode HTML entity and numeric
1114
character references.
1215
* Add a new syntax `SoftLineBreakSyntax` to remove the single space before the
1316
line ending.
1417
* Add a new syntax `EscapeHtmlSyntax` to encode (`"`), (`<`), (`>`) and (`&`).
1518
* Add an option `caseSensitive` to `TextSyntax`.
19+
* Add a new public method `parse(String text)` for `Document`.
20+
* Add a new public method `parseLineList(List<Line> text)` for `Document`.
21+
* Add a new type: `Line`.
1622

1723
## 6.0.1
1824

lib/markdown.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,6 @@ export 'src/inline_syntaxes/link_syntax.dart';
8282
export 'src/inline_syntaxes/soft_line_break_syntax.dart';
8383
export 'src/inline_syntaxes/strikethrough_syntax.dart';
8484
export 'src/inline_syntaxes/text_syntax.dart';
85+
export 'src/line.dart';
8586

8687
const version = packageVersion;

lib/src/block_parser.dart

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ import 'block_syntaxes/paragraph_syntax.dart';
1616
import 'block_syntaxes/setext_header_syntax.dart';
1717
import 'block_syntaxes/unordered_list_syntax.dart';
1818
import 'document.dart';
19+
import 'line.dart';
1920

2021
/// Maintains the internal state needed to parse a series of lines into blocks
2122
/// of Markdown suitable for further inline parsing.
2223
class BlockParser {
23-
final List<String> lines;
24+
final List<Line> lines;
2425

2526
/// The Markdown document this parser is parsing.
2627
final Document document;
@@ -63,10 +64,10 @@ class BlockParser {
6364
}
6465

6566
/// Gets the current line.
66-
String get current => lines[_pos];
67+
Line get current => lines[_pos];
6768

6869
/// Gets the line after the current one or `null` if there is none.
69-
String? get next {
70+
Line? get next {
7071
// Don't read past the end.
7172
if (_pos >= lines.length - 1) return null;
7273
return lines[_pos + 1];
@@ -78,7 +79,7 @@ class BlockParser {
7879
/// `peek(0)` is equivalent to [current].
7980
///
8081
/// `peek(1)` is equivalent to [next].
81-
String? peek(int linesAhead) {
82+
Line? peek(int linesAhead) {
8283
if (linesAhead < 0) {
8384
throw ArgumentError('Invalid linesAhead: $linesAhead; must be >= 0.');
8485
}
@@ -100,13 +101,13 @@ class BlockParser {
100101
/// Gets whether or not the current line matches the given pattern.
101102
bool matches(RegExp regex) {
102103
if (isDone) return false;
103-
return regex.hasMatch(current);
104+
return regex.hasMatch(current.content);
104105
}
105106

106107
/// Gets whether or not the next line matches the given pattern.
107108
bool matchesNext(RegExp regex) {
108109
if (next == null) return false;
109-
return regex.hasMatch(next!);
110+
return regex.hasMatch(next!.content);
110111
}
111112

112113
List<Node> parseLines() {

lib/src/block_syntaxes/block_syntax.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import '../ast.dart';
66
import '../block_parser.dart';
7+
import '../line.dart';
78

89
abstract class BlockSyntax {
910
const BlockSyntax();
@@ -14,19 +15,19 @@ abstract class BlockSyntax {
1415
bool canEndBlock(BlockParser parser) => true;
1516

1617
bool canParse(BlockParser parser) {
17-
return pattern.hasMatch(parser.current);
18+
return pattern.hasMatch(parser.current.content);
1819
}
1920

2021
Node? parse(BlockParser parser);
2122

22-
List<String?> parseChildLines(BlockParser parser) {
23+
List<Line?> parseChildLines(BlockParser parser) {
2324
// Grab all of the lines that form the block element.
24-
final childLines = <String?>[];
25+
final childLines = <Line?>[];
2526

2627
while (!parser.isDone) {
27-
final match = pattern.firstMatch(parser.current);
28+
final match = pattern.firstMatch(parser.current.content);
2829
if (match == null) break;
29-
childLines.add(match[1]);
30+
childLines.add(parser.current);
3031
parser.advance();
3132
}
3233

lib/src/block_syntaxes/blockquote_syntax.dart

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import '../ast.dart';
66
import '../block_parser.dart';
77
import '../charcode.dart';
8+
import '../line.dart';
89
import '../patterns.dart';
910
import '../util.dart';
1011
import 'block_syntax.dart';
@@ -19,32 +20,32 @@ class BlockquoteSyntax extends BlockSyntax {
1920
const BlockquoteSyntax();
2021

2122
@override
22-
List<String> parseChildLines(BlockParser parser) {
23+
List<Line> parseChildLines(BlockParser parser) {
2324
// Grab all of the lines that form the blockquote, stripping off the ">".
24-
final childLines = <String>[];
25+
final childLines = <Line>[];
2526

2627
while (!parser.isDone) {
2728
final currentLine = parser.current;
28-
final match = pattern.firstMatch(parser.current);
29+
final match = pattern.firstMatch(parser.current.content);
2930
if (match != null) {
3031
// A block quote marker consists of a `>` together with an optional
3132
// following space of indentation, see
3233
// https://spec.commonmark.org/0.30/#block-quote-marker.
3334
final markerStart = match.match.indexOf('>');
3435
int markerEnd;
35-
if (currentLine.length > 1) {
36+
if (currentLine.content.length > 1) {
3637
var hasSpace = false;
3738
// Check if there is a following space if the marker is not at the end
3839
// of this line.
39-
if (markerStart < currentLine.length - 1) {
40-
final nextChar = currentLine.codeUnitAt(markerStart + 1);
40+
if (markerStart < currentLine.content.length - 1) {
41+
final nextChar = currentLine.content.codeUnitAt(markerStart + 1);
4142
hasSpace = nextChar == $tab || nextChar == $space;
4243
}
4344
markerEnd = markerStart + (hasSpace ? 2 : 1);
4445
} else {
4546
markerEnd = markerStart + 1;
4647
}
47-
childLines.add(currentLine.substring(markerEnd));
48+
childLines.add(Line(currentLine.content.substring(markerEnd)));
4849
parser.advance();
4950
continue;
5051
}
@@ -59,10 +60,10 @@ class BlockquoteSyntax extends BlockSyntax {
5960
final otherMatched =
6061
parser.blockSyntaxes.firstWhere((s) => s.canParse(parser));
6162
if ((otherMatched is ParagraphSyntax &&
62-
lastLine.isNotEmpty &&
63-
!codeFencePattern.hasMatch(lastLine)) ||
63+
!lastLine.isBlankLine &&
64+
!codeFencePattern.hasMatch(lastLine.content)) ||
6465
(otherMatched is CodeBlockSyntax &&
65-
!indentPattern.hasMatch(lastLine))) {
66+
!indentPattern.hasMatch(lastLine.content))) {
6667
childLines.add(parser.current);
6768
parser.advance();
6869
} else {

lib/src/block_syntaxes/code_block_syntax.dart

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import '../ast.dart';
66
import '../block_parser.dart';
7+
import '../line.dart';
78
import '../patterns.dart';
89
import '../util.dart';
910
import 'block_syntax.dart';
@@ -19,21 +20,21 @@ class CodeBlockSyntax extends BlockSyntax {
1920
const CodeBlockSyntax();
2021

2122
@override
22-
List<String?> parseChildLines(BlockParser parser) {
23-
final childLines = <String?>[];
23+
List<Line> parseChildLines(BlockParser parser) {
24+
final childLines = <Line>[];
2425

2526
while (!parser.isDone) {
26-
final isBlankLine = parser.current.isBlank;
27+
final isBlankLine = parser.current.isBlankLine;
2728
if (isBlankLine && _shouldEnd(parser)) {
2829
break;
2930
}
3031

3132
if (!isBlankLine &&
3233
childLines.isNotEmpty &&
33-
pattern.hasMatch(parser.current) != true) {
34+
pattern.hasMatch(parser.current.content) != true) {
3435
break;
3536
}
36-
childLines.add(parser.current.dedent().text);
37+
childLines.add(Line(parser.current.content.dedent().text));
3738

3839
parser.advance();
3940
}
@@ -46,9 +47,9 @@ class CodeBlockSyntax extends BlockSyntax {
4647
final childLines = parseChildLines(parser);
4748

4849
// The Markdown tests expect a trailing newline.
49-
childLines.add('');
50+
childLines.add(Line(''));
5051

51-
var content = childLines.join('\n');
52+
var content = childLines.map((e) => e.content).join('\n');
5253
if (parser.document.encodeHtml) {
5354
content = escapeHtml(content);
5455
}
@@ -67,12 +68,12 @@ class CodeBlockSyntax extends BlockSyntax {
6768

6869
// It does not matter how many blank lines between chunks:
6970
// https://spec.commonmark.org/0.30/#example-111
70-
if (nextLine.isBlank) {
71+
if (nextLine.isBlankLine) {
7172
i++;
7273
continue;
7374
}
7475

75-
return pattern.hasMatch(nextLine) == false;
76+
return pattern.hasMatch(nextLine.content) == false;
7677
}
7778
}
7879
}

lib/src/block_syntaxes/dummy_block_syntax.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class DummyBlockSyntax extends BlockSyntax {
2727
final childLines = <String>[];
2828

2929
while (!BlockSyntax.isAtBlockEnd(parser)) {
30-
childLines.add(parser.current);
30+
childLines.add(parser.current.content);
3131
parser.advance();
3232
}
3333

lib/src/block_syntaxes/fenced_blockquote_syntax.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import '../ast.dart';
66
import '../block_parser.dart';
7+
import '../line.dart';
78
import '../patterns.dart';
89
import 'block_syntax.dart';
910

@@ -15,12 +16,12 @@ class FencedBlockquoteSyntax extends BlockSyntax {
1516
RegExp get pattern => blockquoteFencePattern;
1617

1718
@override
18-
List<String> parseChildLines(BlockParser parser) {
19-
final childLines = <String>[];
19+
List<Line> parseChildLines(BlockParser parser) {
20+
final childLines = <Line>[];
2021
parser.advance();
2122

2223
while (!parser.isDone) {
23-
final match = pattern.hasMatch(parser.current);
24+
final match = pattern.hasMatch(parser.current.content);
2425
if (!match) {
2526
childLines.add(parser.current);
2627
parser.advance();

lib/src/block_syntaxes/fenced_code_block_syntax.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import '../ast.dart';
66
import '../block_parser.dart';
7+
import '../line.dart';
78
import '../patterns.dart';
89
import '../util.dart';
910
import 'block_syntax.dart';
@@ -20,14 +21,14 @@ class FencedCodeBlockSyntax extends BlockSyntax {
2021
@override
2122
Node parse(BlockParser parser) {
2223
final openingFence = _FenceMatch.fromMatch(pattern.firstMatch(
23-
escapePunctuation(parser.current),
24+
escapePunctuation(parser.current.content),
2425
)!);
2526

2627
var text = parseChildLines(
2728
parser,
2829
openingFence.marker,
2930
openingFence.indent,
30-
).join('\n');
31+
).map((e) => e.content).join('\n');
3132

3233
if (parser.document.encodeHtml) {
3334
text = escapeHtml(text);
@@ -54,26 +55,28 @@ class FencedCodeBlockSyntax extends BlockSyntax {
5455
}
5556

5657
@override
57-
List<String> parseChildLines(
58+
List<Line> parseChildLines(
5859
BlockParser parser, [
5960
String openingMarker = '',
6061
int indent = 0,
6162
]) {
62-
final childLines = <String>[];
63+
final childLines = <Line>[];
6364

6465
parser.advance();
6566

6667
_FenceMatch? closingFence;
6768
while (!parser.isDone) {
68-
final match = pattern.firstMatch(parser.current);
69+
final match = pattern.firstMatch(parser.current.content);
6970
closingFence = match == null ? null : _FenceMatch.fromMatch(match);
7071

7172
// Closing code fences cannot have info strings:
7273
// https://spec.commonmark.org/0.30/#example-147
7374
if (closingFence == null ||
7475
!closingFence.marker.startsWith(openingMarker) ||
7576
closingFence.hasInfo) {
76-
childLines.add(_removeIndentation(parser.current, indent));
77+
childLines.add(
78+
Line(_removeIndentation(parser.current.content, indent)),
79+
);
7780
parser.advance();
7881
} else {
7982
parser.advance();
@@ -85,7 +88,7 @@ class FencedCodeBlockSyntax extends BlockSyntax {
8588
// https://spec.commonmark.org/0.30/#example-128
8689
if (closingFence == null &&
8790
childLines.isNotEmpty &&
88-
childLines.last.trim().isEmpty) {
91+
childLines.last.isBlankLine) {
8992
childLines.removeLast();
9093
}
9194

lib/src/block_syntaxes/header_syntax.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class HeaderSyntax extends BlockSyntax {
1616

1717
@override
1818
Node parse(BlockParser parser) {
19-
final match = pattern.firstMatch(parser.current)!;
19+
final match = pattern.firstMatch(parser.current.content)!;
2020
final matchedText = match[0]!;
2121
final openMarker = match[1]!;
2222
final closeMarker = match[2];
@@ -26,10 +26,13 @@ class HeaderSyntax extends BlockSyntax {
2626

2727
String? content;
2828
if (closeMarker == null) {
29-
content = parser.current.substring(openMarkerEnd);
29+
content = parser.current.content.substring(openMarkerEnd);
3030
} else {
3131
final closeMarkerStart = matchedText.lastIndexOf(closeMarker);
32-
content = parser.current.substring(openMarkerEnd, closeMarkerStart);
32+
content = parser.current.content.substring(
33+
openMarkerEnd,
34+
closeMarkerStart,
35+
);
3336
}
3437
content = content.trim();
3538

0 commit comments

Comments
 (0)