document.dart 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
  2. // for details. All rights reserved. Use of this source code is governed by a
  3. // BSD-style license that can be found in the LICENSE file.
  4. import 'ast.dart';
  5. import 'block_parser.dart';
  6. import 'extension_set.dart';
  7. import 'inline_parser.dart';
  8. /// Maintains the context needed to parse a Markdown document.
  9. class Document {
  10. Document({
  11. Iterable<BlockSyntax>? blockSyntaxes,
  12. Iterable<InlineSyntax>? inlineSyntaxes,
  13. ExtensionSet? extensionSet,
  14. this.linkResolver,
  15. this.imageLinkResolver,
  16. }) : extensionSet = extensionSet ?? ExtensionSet.commonMark {
  17. _blockSyntaxes
  18. ..addAll(blockSyntaxes ?? [])
  19. ..addAll(this.extensionSet.blockSyntaxes);
  20. _inlineSyntaxes
  21. ..addAll(inlineSyntaxes ?? [])
  22. ..addAll(this.extensionSet.inlineSyntaxes);
  23. }
  24. final Map<String, LinkReference> linkReferences = <String, LinkReference>{};
  25. final ExtensionSet extensionSet;
  26. final Resolver? linkResolver;
  27. final Resolver? imageLinkResolver;
  28. final _blockSyntaxes = <BlockSyntax>{};
  29. final _inlineSyntaxes = <InlineSyntax>{};
  30. Iterable<BlockSyntax> get blockSyntaxes => _blockSyntaxes;
  31. Iterable<InlineSyntax> get inlineSyntaxes => _inlineSyntaxes;
  32. /// Parses the given [lines] of Markdown to a series of AST nodes.
  33. List<Node> parseLines(List<String> lines) {
  34. final nodes = BlockParser(lines, this).parseLines();
  35. // Make sure to mark the top level nodes as such.
  36. for (final n in nodes) {
  37. n.isToplevel = true;
  38. }
  39. _parseInlineContent(nodes);
  40. return nodes;
  41. }
  42. /// Parses the given inline Markdown [text] to a series of AST nodes.
  43. List<Node>? parseInline(String text) => InlineParser(text, this).parse();
  44. void _parseInlineContent(List<Node> nodes) {
  45. for (var i = 0; i < nodes.length; i++) {
  46. final node = nodes[i];
  47. if (node is UnparsedContent) {
  48. final inlineNodes = parseInline(node.textContent)!;
  49. nodes
  50. ..removeAt(i)
  51. ..insertAll(i, inlineNodes);
  52. i += inlineNodes.length - 1;
  53. } else if (node is Element && node.children != null) {
  54. _parseInlineContent(node.children!);
  55. }
  56. }
  57. }
  58. }
  59. /// A [link reference
  60. /// definition](http://spec.commonmark.org/0.28/#link-reference-definitions).
  61. class LinkReference {
  62. /// Construct a [LinkReference], with all necessary fields.
  63. ///
  64. /// If the parsed link reference definition does not include a title, use
  65. /// `null` for the [title] parameter.
  66. LinkReference(this.label, this.destination, this.title);
  67. /// The [link label](http://spec.commonmark.org/0.28/#link-label).
  68. ///
  69. /// Temporarily, this class is also being used to represent the link data for
  70. /// an inline link (the destination and title), but this should change before
  71. /// the package is released.
  72. final String label;
  73. /// The [link destination](http://spec.commonmark.org/0.28/#link-destination).
  74. final String destination;
  75. /// The [link title](http://spec.commonmark.org/0.28/#link-title).
  76. final String title;
  77. }