| Index: third_party/pkg/markdown/lib/src/block_parser.dart
|
| diff --git a/third_party/pkg/markdown/lib/src/markdown/block_parser.dart b/third_party/pkg/markdown/lib/src/block_parser.dart
|
| similarity index 87%
|
| rename from third_party/pkg/markdown/lib/src/markdown/block_parser.dart
|
| rename to third_party/pkg/markdown/lib/src/block_parser.dart
|
| index 42b93533345b9ab8ceae524a7a4c7c0f8ba47e16..c34f7db61795f6ec2d462329a53ff6bbb38757f8 100644
|
| --- a/third_party/pkg/markdown/lib/src/markdown/block_parser.dart
|
| +++ b/third_party/pkg/markdown/lib/src/block_parser.dart
|
| @@ -2,7 +2,11 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -part of markdown;
|
| +library markdown.block_parser;
|
| +
|
| +import 'ast.dart';
|
| +import 'document.dart';
|
| +import 'util.dart';
|
|
|
| /// The line contains only whitespace or is empty.
|
| final _RE_EMPTY = new RegExp(r'^([ \t]*)$');
|
| @@ -19,8 +23,8 @@ final _RE_BLOCKQUOTE = new RegExp(r'^[ ]{0,3}>[ ]?(.*)$');
|
| /// A line indented four spaces. Used for code blocks and lists.
|
| final _RE_INDENT = new RegExp(r'^(?: |\t)(.*)$');
|
|
|
| -/// GitHub style triple quoted code block.
|
| -final _RE_CODE = new RegExp(r'^```(.*)$');
|
| +/// Fenced code block.
|
| +final _RE_CODE = new RegExp(r'^(`{3,}|~{3,})(.*)$');
|
|
|
| /// Three or more hyphens, asterisks or underscores by themselves. Note that
|
| /// a line like `----` is valid as both HR and SETEXT. In case of a tie,
|
| @@ -51,26 +55,26 @@ class BlockParser {
|
| final Document document;
|
|
|
| /// Index of the current line.
|
| - int pos;
|
| + int _pos;
|
|
|
| BlockParser(this.lines, this.document)
|
| - : pos = 0;
|
| + : _pos = 0;
|
|
|
| /// Gets the current line.
|
| - String get current => lines[pos];
|
| + String get current => lines[_pos];
|
|
|
| /// Gets the line after the current one or `null` if there is none.
|
| String get next {
|
| // Don't read past the end.
|
| - if (pos >= lines.length - 1) return null;
|
| - return lines[pos + 1];
|
| + if (_pos >= lines.length - 1) return null;
|
| + return lines[_pos + 1];
|
| }
|
|
|
| void advance() {
|
| - pos++;
|
| + _pos++;
|
| }
|
|
|
| - bool get isDone => pos >= lines.length;
|
| + bool get isDone => _pos >= lines.length;
|
|
|
| /// Gets whether or not the current line matches the given pattern.
|
| bool matches(RegExp regex) {
|
| @@ -88,28 +92,21 @@ class BlockParser {
|
| abstract class BlockSyntax {
|
| /// Gets the collection of built-in block parsers. To turn a series of lines
|
| /// into blocks, each of these will be tried in turn. Order matters here.
|
| - static List<BlockSyntax> get syntaxes {
|
| - // Lazy initialize.
|
| - if (_syntaxes == null) {
|
| - _syntaxes = [
|
| - new EmptyBlockSyntax(),
|
| - new BlockHtmlSyntax(),
|
| - new SetextHeaderSyntax(),
|
| - new HeaderSyntax(),
|
| - new CodeBlockSyntax(),
|
| - new GitHubCodeBlockSyntax(),
|
| - new BlockquoteSyntax(),
|
| - new HorizontalRuleSyntax(),
|
| - new UnorderedListSyntax(),
|
| - new OrderedListSyntax(),
|
| - new ParagraphSyntax()
|
| - ];
|
| - }
|
| -
|
| - return _syntaxes;
|
| - }
|
| -
|
| - static List<BlockSyntax> _syntaxes;
|
| + static const List<BlockSyntax> syntaxes = const[
|
| + const EmptyBlockSyntax(),
|
| + const BlockHtmlSyntax(),
|
| + const SetextHeaderSyntax(),
|
| + const HeaderSyntax(),
|
| + const CodeBlockSyntax(),
|
| + const FencedCodeBlockSyntax(),
|
| + const BlockquoteSyntax(),
|
| + const HorizontalRuleSyntax(),
|
| + const UnorderedListSyntax(),
|
| + const OrderedListSyntax(),
|
| + const ParagraphSyntax()
|
| + ];
|
| +
|
| + const BlockSyntax();
|
|
|
| /// Gets the regex used to identify the beginning of this block, if any.
|
| RegExp get pattern => null;
|
| @@ -146,6 +143,8 @@ abstract class BlockSyntax {
|
| class EmptyBlockSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_EMPTY;
|
|
|
| + const EmptyBlockSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| parser.advance();
|
|
|
| @@ -156,6 +155,9 @@ class EmptyBlockSyntax extends BlockSyntax {
|
|
|
| /// Parses setext-style headers.
|
| class SetextHeaderSyntax extends BlockSyntax {
|
| +
|
| + const SetextHeaderSyntax();
|
| +
|
| bool canParse(BlockParser parser) {
|
| // Note: matches *next* line, not the current one. We're looking for the
|
| // underlining after this line.
|
| @@ -178,6 +180,8 @@ class SetextHeaderSyntax extends BlockSyntax {
|
| class HeaderSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_HEADER;
|
|
|
| + const HeaderSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| final match = pattern.firstMatch(parser.current);
|
| parser.advance();
|
| @@ -191,6 +195,8 @@ class HeaderSyntax extends BlockSyntax {
|
| class BlockquoteSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_BLOCKQUOTE;
|
|
|
| + const BlockquoteSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| final childLines = parseChildLines(parser);
|
|
|
| @@ -205,6 +211,8 @@ class BlockquoteSyntax extends BlockSyntax {
|
| class CodeBlockSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_INDENT;
|
|
|
| + const CodeBlockSyntax();
|
| +
|
| List<String> parseChildLines(BlockParser parser) {
|
| final childLines = <String>[];
|
|
|
| @@ -244,16 +252,21 @@ class CodeBlockSyntax extends BlockSyntax {
|
| }
|
| }
|
|
|
| -/// Parses preformatted code blocks between two ``` sequences.
|
| -class GitHubCodeBlockSyntax extends BlockSyntax {
|
| +/// Parses preformatted code blocks between two ~~~ or ``` sequences.
|
| +/// [Pandoc's markdown documentation](http://johnmacfarlane.net/pandoc/demo/example9/pandocs-markdown.html).
|
| +class FencedCodeBlockSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_CODE;
|
|
|
| - List<String> parseChildLines(BlockParser parser) {
|
| + const FencedCodeBlockSyntax();
|
| +
|
| + List<String> parseChildLines(BlockParser parser, [String endBlock]) {
|
| + if(endBlock == null) endBlock = '';
|
| +
|
| final childLines = <String>[];
|
| parser.advance();
|
| while (!parser.isDone) {
|
| var match = pattern.firstMatch(parser.current);
|
| - if (match == null) {
|
| + if (match == null || !match[1].startsWith(endBlock)) {
|
| childLines.add(parser.current);
|
| parser.advance();
|
| } else {
|
| @@ -266,9 +279,11 @@ class GitHubCodeBlockSyntax extends BlockSyntax {
|
|
|
| Node parse(BlockParser parser) {
|
| // Get the syntax identifier, if there is one.
|
| - var syntax = pattern.firstMatch(parser.current).group(1);
|
| -
|
| - final childLines = parseChildLines(parser);
|
| + var match = pattern.firstMatch(parser.current);
|
| + var endBlock = match.group(1);
|
| + var syntax = match.group(2);
|
| +
|
| + final childLines = parseChildLines(parser, endBlock);
|
|
|
| // The Markdown tests expect a trailing newline.
|
| childLines.add('');
|
| @@ -276,7 +291,11 @@ class GitHubCodeBlockSyntax extends BlockSyntax {
|
| // Escape the code.
|
| final escaped = escapeHtml(childLines.join('\n'));
|
|
|
| - return new Element('pre', [new Element.text('code', escaped)]);
|
| + var element = new Element('pre', [new Element.text('code', escaped)]);
|
| + if (syntax != '') {
|
| + element.attributes['class'] = syntax;
|
| + }
|
| + return element;
|
| }
|
| }
|
|
|
| @@ -284,6 +303,8 @@ class GitHubCodeBlockSyntax extends BlockSyntax {
|
| class HorizontalRuleSyntax extends BlockSyntax {
|
| RegExp get pattern => _RE_HR;
|
|
|
| + const HorizontalRuleSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| final match = pattern.firstMatch(parser.current);
|
| parser.advance();
|
| @@ -306,6 +327,8 @@ class BlockHtmlSyntax extends BlockSyntax {
|
|
|
| bool get canEndBlock => false;
|
|
|
| + const BlockHtmlSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| final childLines = [];
|
|
|
| @@ -332,6 +355,8 @@ abstract class ListSyntax extends BlockSyntax {
|
|
|
| String get listTag;
|
|
|
| + const ListSyntax();
|
| +
|
| Node parse(BlockParser parser) {
|
| final items = <ListItem>[];
|
| var childLines = <String>[];
|
| @@ -474,18 +499,24 @@ abstract class ListSyntax extends BlockSyntax {
|
| class UnorderedListSyntax extends ListSyntax {
|
| RegExp get pattern => _RE_UL;
|
| String get listTag => 'ul';
|
| +
|
| + const UnorderedListSyntax();
|
| }
|
|
|
| /// Parses ordered lists.
|
| class OrderedListSyntax extends ListSyntax {
|
| RegExp get pattern => _RE_OL;
|
| String get listTag => 'ol';
|
| +
|
| + const OrderedListSyntax();
|
| }
|
|
|
| /// Parses paragraphs of regular text.
|
| class ParagraphSyntax extends BlockSyntax {
|
| bool get canEndBlock => false;
|
|
|
| + const ParagraphSyntax();
|
| +
|
| bool canParse(BlockParser parser) => true;
|
|
|
| Node parse(BlockParser parser) {
|
|
|