Merge `package:markdown` (#1208)

- [x] Move and fix workflow files, labeler.yaml, and badges in the
README.md
- [x] Rev the version of the package, so that pub.dev points to the
correct site
- [x] Add a line to the changelog:
```
* Move to `dart-lang/tools` monorepo.
```

- [x] Add the package to the top-level readme of the monorepo:
```
| [markdown](pkgs/markdown/) | A portable Markdown library written in Dart that can parse Markdown into HTML. | [![pub package](https://img.shields.io/pub/v/markdown.svg)](https://pub.dev/packages/markdown) |
```

- [ ] **Important!** Merge the PR with 'Create a merge commit' (enabling
then disabling the `Allow merge commits` admin setting)
- [x] Update the auto-publishing settings on
https://pub.dev/packages/markdown/admin
- [x] Add the following text to https://github.com/dart-lang/markdown/:'

```
> [!IMPORTANT]  
> This repo has moved to https://github.com/dart-lang/tools/tree/main/pkgs/markdown
```

- [ ] Publish using the autopublish workflow
- [ ] Push tags to GitHub using
```git tag --list 'markdown*' | xargs git push origin```

- [x] Close open PRs in dart-lang/markdown with the following message:

```
Closing as the
[dart-lang/markdown](https://github.com/dart-lang/markdown) repository
is merged into the [dart-lang/tools](https://github.com/dart-lang/tools)
monorepo. Please re-open this PR there!
```
      
- [x] Transfer issues by running
```dart run pkgs/repo_manage/bin/report.dart transfer-issues
--source-repo dart-lang/markdown --target-repo dart-lang/tools
--add-label package:markdown --apply-changes```

- [ ] Archive https://github.com/dart-lang/markdown/


---

- [x] I’ve reviewed the contributor guide and applied the relevant
portions to this PR.

<details>
  <summary>Contribution guidelines:</summary><br>

- See our [contributor
guide](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md)
for general expectations for PRs.
- Larger or significant changes should be discussed in an issue before
creating a PR.
- Contributions to our repos should follow the [Dart style
guide](https://dart.dev/guides/language/effective-dart) and use `dart
format`.
- Most changes should add an entry to the changelog and may need to [rev
the pubspec package
version](https://github.com/dart-lang/sdk/blob/main/docs/External-Package-Maintenance.md#making-a-change).
- Changes to packages require [corresponding
tests](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md#Testing).

Note that many Dart repos have a weekly cadence for reviewing PRs -
please allow for some latency before initial review feedback.
</details>
diff --git a/.github/ISSUE_TEMPLATE/markdown.md b/.github/ISSUE_TEMPLATE/markdown.md
new file mode 100644
index 0000000..24e9f16
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/markdown.md
@@ -0,0 +1,5 @@
+---
+name: "package:markdown"
+about: "Create a bug or file a feature request against package:markdown."
+labels: "package:markdown"
+---
\ No newline at end of file
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 248532b..0bb7feb 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -72,6 +72,10 @@
   - changed-files:
     - any-glob-to-any-file: 'pkgs/json_rpc_2/**'
 
+'package:markdown':
+  - changed-files:
+    - any-glob-to-any-file: 'pkgs/markdown/**'
+
 'package:mime':
   - changed-files:
     - any-glob-to-any-file: 'pkgs/mime/**'
diff --git a/.github/workflows/health.yaml b/.github/workflows/health.yaml
index f258f8b..3ac7e89 100644
--- a/.github/workflows/health.yaml
+++ b/.github/workflows/health.yaml
@@ -9,6 +9,6 @@
     uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
     with:
       ignore_coverage: "**.mock.dart,**.g.dart"
-      ignore_license: "**.mock.dart,**.g.dart,**.mocks.dart"
+      ignore_license: "**.mock.dart,**.g.dart,**.mocks.dart,pkgs/markdown/**"
     permissions:
       pull-requests: write
diff --git a/.github/workflows/markdown.yaml b/.github/workflows/markdown.yaml
new file mode 100644
index 0000000..59654b7
--- /dev/null
+++ b/.github/workflows/markdown.yaml
@@ -0,0 +1,93 @@
+name: package:markdown
+
+on:
+  # Run on PRs and pushes to the default branch.
+  push:
+    branches: [ main ]
+    paths:
+      - '.github/workflows/markdown.yaml'
+      - 'pkgs/markdown/**'
+  pull_request:
+    branches: [ main ]
+    paths:
+      - '.github/workflows/markdown.yaml'
+      - 'pkgs/markdown/**'
+  schedule:
+    - cron: "0 0 * * 0"
+
+env:
+  PUB_ENVIRONMENT: bot.github
+
+
+defaults:
+  run:
+    working-directory: pkgs/markdown/
+
+
+jobs:
+  # Check code formatting and static analysis on a single OS (linux)
+  # against Dart dev.
+  analyze:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        sdk: [dev]
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+        with:
+          sdk: ${{ matrix.sdk }}
+      - id: install
+        name: Install dependencies
+        run: dart pub get
+      - name: Check formatting
+        run: dart format --output=none --set-exit-if-changed .
+        if: always() && steps.install.outcome == 'success'
+      - name: Analyze code
+        run: dart analyze --fatal-infos
+        if: always() && steps.install.outcome == 'success'
+
+  # Run tests on a matrix consisting of two dimensions:
+  # 1. OS: ubuntu-latest, (macos-latest, windows-latest)
+  # 2. release channel: dev
+  test:
+    needs: analyze
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        # Add macos-latest and/or windows-latest if relevant for this package.
+        os: [ubuntu-latest]
+        sdk: [3.2, dev]
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+        with:
+          sdk: ${{ matrix.sdk }}
+      - id: install
+        name: Install dependencies
+        run: dart pub get
+      - name: Run VM tests
+        run: dart test --platform vm
+        if: always() && steps.install.outcome == 'success'
+
+  coverage:
+    needs: test
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+    - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+      with:
+        sdk: dev
+    - name: Install dependencies
+      run: dart pub get
+    - name: Install coverage
+      run: dart pub global activate coverage
+    - name: Collect and report coverage
+      run: dart pub global run coverage:test_with_coverage
+    - name: Upload coverage
+      uses: coverallsapp/github-action@master
+      with:
+        github-token: ${{ secrets.GITHUB_TOKEN }}
+        path-to-lcov: pkgs/markdown/coverage/lcov.info
diff --git a/.github/workflows/markdown_crash_test.yaml b/.github/workflows/markdown_crash_test.yaml
new file mode 100644
index 0000000..ceacd77
--- /dev/null
+++ b/.github/workflows/markdown_crash_test.yaml
@@ -0,0 +1,27 @@
+# Run against all markdown files in latest version of packages on pub.dev to
+# see if any can provoke a crash
+
+name: package:markdown: crash tests
+
+on:
+  schedule:
+    # “At 00:00 (UTC) on Sunday.”
+    - cron: '0 0 * * 0'
+    
+defaults:
+  run:
+    working-directory: pkgs/markdown/
+
+jobs:
+  crash-test:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      
+      - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94
+      
+      - name: Install dependencies
+        run: dart pub get
+
+      - name: Run crash_test.dart
+        run: dart test -P crash_test test/crash_test.dart
diff --git a/.github/workflows/markdown_flutter.yaml b/.github/workflows/markdown_flutter.yaml
new file mode 100644
index 0000000..1a6ad5d
--- /dev/null
+++ b/.github/workflows/markdown_flutter.yaml
@@ -0,0 +1,66 @@
+# Run a smoke test against package:flutter_markdown.
+
+name: package:markdown: flutter
+
+on:
+  # Run on PRs and pushes to the default branch.
+  push:
+    branches: [ main ]
+    paths:
+      - '.github/workflows/markdown_flutter.yaml'
+      - 'pkgs/markdown/**'
+  pull_request:
+    branches: [ main ]
+    paths:
+      - '.github/workflows/markdown_flutter.yaml'
+      - 'pkgs/markdown/**'
+  schedule:
+    - cron: "0 0 * * 0"
+
+env:
+  PUB_ENVIRONMENT: bot.github
+
+jobs:
+  smoke-test:
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: clone dart-lang/tools
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+        with:
+          repository: dart-lang/tools
+          path: tools_repo
+
+      - name: clone flutter/packages
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+        with:
+          repository: flutter/packages
+          path: flutter_packages
+
+      # Install the Flutter SDK using the subosito/flutter-action GitHub action.
+      - name: install the flutter sdk
+        uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3
+        with:
+          channel: beta
+      
+      - name: flutter --version
+        run: flutter --version
+
+      - name: create pubspec_overrides.yaml
+        working-directory: flutter_packages/packages/flutter_markdown
+        run: |
+          echo "dependency_overrides:"        > pubspec_overrides.yaml
+          echo "  markdown:"                 >> pubspec_overrides.yaml
+          echo "    path: ../../../tools_repo/pkgs/markdown" >> pubspec_overrides.yaml
+
+      - name: flutter pub get
+        working-directory: flutter_packages/packages/flutter_markdown
+        run: flutter pub get
+  
+      - name: flutter analyze package:flutter_markdown
+        working-directory: flutter_packages/packages/flutter_markdown
+        run: flutter analyze
+
+      - name: flutter test package:flutter_markdown
+        working-directory: flutter_packages/packages/flutter_markdown
+        run: flutter test
diff --git a/README.md b/README.md
index 01702e8..f3281a8 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@
 | [html](pkgs/html/) | APIs for parsing and manipulating HTML content outside the browser. | [![package issues](https://img.shields.io/badge/package:html-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ahtml) | [![pub package](https://img.shields.io/pub/v/html.svg)](https://pub.dev/packages/html) |
 | [io](pkgs/io/) | Utilities for the Dart VM Runtime including support for ANSI colors, file copying, and standard exit code values. | [![pub package](https://img.shields.io/pub/v/io.svg)](https://pub.dev/packages/io) |
 | [json_rpc_2](pkgs/json_rpc_2/) | Utilities to write a client or server using the JSON-RPC 2.0 spec. | [![package issues](https://img.shields.io/badge/package:json_rpc_2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ajson_rpc_2) | [![pub package](https://img.shields.io/pub/v/json_rpc_2.svg)](https://pub.dev/packages/json_rpc_2) |
+| [markdown](pkgs/markdown/) | A portable Markdown library written in Dart that can parse Markdown into HTML. | [![pub package](https://img.shields.io/pub/v/markdown.svg)](https://pub.dev/packages/markdown) |
 | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) |
 | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) |
 | [package_config](pkgs/package_config/) | Support for reading and writing Dart Package Configuration files. | [![package issues](https://img.shields.io/badge/package:package_config-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apackage_config) | [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) |
diff --git a/pkgs/markdown/.gitignore b/pkgs/markdown/.gitignore
new file mode 100644
index 0000000..6ff0be3
--- /dev/null
+++ b/pkgs/markdown/.gitignore
@@ -0,0 +1,5 @@
+.dart_tool
+.packages
+.pub
+pubspec.lock
+doc/
diff --git a/pkgs/markdown/AUTHORS b/pkgs/markdown/AUTHORS
new file mode 100644
index 0000000..ca5b46b
--- /dev/null
+++ b/pkgs/markdown/AUTHORS
@@ -0,0 +1,13 @@
+# Below is a list of people and organizations that have contributed
+# to the Dart project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
+
+David Peek <ninjascript@gmail.com>
+Daniel Schubert <daniel.schubert+github.com@gmail.com>
+Jirka Daněk <dnk@mail.muni.cz>
+Seth Westphal <westy92@gmail.com>
+Tim Maffett <timmaffett@gmail.com>
+Alex Li <alexv.525.li@gmail.com>
diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md
new file mode 100644
index 0000000..5f9f48a
--- /dev/null
+++ b/pkgs/markdown/CHANGELOG.md
@@ -0,0 +1,409 @@
+## 7.3.0
+
+* Move to `dart-lang/tools` monorepo.
+* Fix an issue with checkbox list items separated with blank lines (#602).
+* Require package `web: '>=0.4.2 <2.0.0'`.
+* Fix several `RangeError` hazards in links (#623).
+* Export `LinkReferenceDefinitionSyntax` publicly (#626).
+
+## 7.2.2
+
+* Fix a crash parsing alert block syntax (#584).
+* Have alert block syntax support multiple paragraphs (#577).
+* Require Dart `^3.2.0`.
+
+## 7.2.1
+
+* Address a termination issue with GitHub alert syntax parsing.
+
+## 7.2.0
+
+* Require Dart `^3.1.0`.
+* Update all CommonMark specification links to 0.30.
+* Fix beginning of line detection in `AutolinkExtensionSyntax`.
+* Add a new syntax `AlertBlockSyntax` to parse GitHub Alerts.
+
+## 7.1.1
+
+* Fix delimiter row matching pattern for tables.
+* Tables are now able to interrupt other blocks.
+* Fix an obscure issue with HtmlBlockSyntax.
+
+## 7.1.0
+
+* Support for [footnotes](https://pandoc.org/MANUAL.html#footnotes).
+* Fixed bug causing infinite loop for links inside tables.
+
+## 7.0.2
+
+* Require Dart 2.19
+* Fix an issue in `HeaderWithIdSyntax`, do not generate heading IDs for headings
+  with no content.
+
+## 7.0.1
+
+* Remove RegExp lookarounds from autolink extension patterns. (Fixes issues when
+  running on Safari.)
+
+## 7.0.0
+
+* **Breaking change**: `close()` of `DelimiterSyntax` and `LinkSyntax`
+  returns multiple nodes instead of single one.
+* **Breaking change**: Remove deprecated APIs, including `TagSyntax`,
+  `indicatorForCheckedCheckBox`, and `indicatorForUncheckedCheckBox`.
+* **Breaking change**: Removed `BlockHtmlSyntax`, `BlockTagBlockHtmlSyntax`,
+  `LongBlockHtmlSyntax`, and `OtherTagBlockHtmlSyntax`.
+* **Breaking change**: Change the `line` properties of type `String` to `Line`.
+* **Breaking change**: Change the `lines` properties of type `List<String>` to
+  `List<Line>`.
+* Add a new syntax `HtmlBlockSyntax` to parse HTML blocks.
+* Add an `enableTagfilter` option to `HtmlRenderer` to eanble GFM `tagfilter`
+  extension.
+* Add a new syntax `DecodeHtmlSyntax` to decode HTML entity and numeric
+  character references.
+* Add a new syntax `SoftLineBreakSyntax` to remove the single space before the
+  line ending.
+* Add a new syntax `EscapeHtmlSyntax` to encode (`"`), (`<`), (`>`) and (`&`).
+* Add an option `caseSensitive` to `TextSyntax`.
+* Add a new public method `parse(String text)` for `Document`.
+* Add a new public method `parseLineList(List<Line> text)` for `Document`.
+* Add a new type: `Line`.
+* Add a new optional parameter `parentSyntax` for `parseLines()` of
+  `BlockParser`, which can be used when parsing nested blocks.
+* Add a new optional parameter `disabledSetextHeading` for `parseLines()` of
+  `BlockParser`, which is used to disable the `SetextHeaderSyntax`.
+* Add a new public property `previousSyntax` for `BlockParser`.
+
+## 6.0.1
+
+* Fix a crash in checkbox lists when mixing checkbox items with
+  non-checkbox items.
+
+## 6.0.0
+
+* Require Dart 2.17
+* Add support to GFM extension for GitHub task lists (aka checkboxes).  These
+  are only active in the `gitHubFlavored` and `gitHubWeb` extension sets.
+* Add support for `#ff0000` color swatches.
+* Change emoji list do be derived from the GitHub API. The only two emoji that
+  visually change are `:cricket:` and `:beetle:`. There are alternate emoji
+  `:cricket_game:` and `:lady_beetle:` which can be used to access the previous
+  emoji.  `update_github_emoji.dart` now pulls all emoji info directly from
+  GitHub API and as a result we have now support the entire GitHub emoji set
+  (excluding the 19 custom GitHub specific emoji which have no Unicode support).
+* **Breaking change**: The `TagSyntax` is _deprecated_.
+* Add new syntax `DelimiterSyntax`.
+* **Breaking change**: `StrikethroughSyntax` now extends `DelimiterSyntax`
+  instead of `TagSyntax`.
+* **Breaking change**: `LinkSyntax` now extends `DelimiterSyntax`
+  instead of `TagSyntax`.
+* Add two new emphasis syntaxes `EmphasisSyntax.underscore` and 
+  `EmphasisSyntax.asterisk`.
+
+## 5.0.0
+
+* Breaking change: Change the type of `parseInline`'s parameter from `String?`
+  to `String`.
+* Fix table-rendering bug when table rows have trailing whitespace.
+  [#368](https://github.com/dart-lang/markdown/issues/368).
+* Do not allow reference link labels to contain left brackets. Thanks
+  @chenzhiguang.
+  [#335](https://github.com/dart-lang/markdown/issues/335).
+* Treat lines matching a code block syntax as continuations of paragraphs,
+  inside blockquotes. Thanks @chenzhiguang.
+  [#358](https://github.com/dart-lang/markdown/issues/358).
+* Add a syntax for GitLab-flavored fenced blockquotes. GitLab-flavored Markdown
+  will be evaluated into an ExtensionSet, in a future release. Thanks
+  @chenzhiguang.
+  [#359](https://github.com/dart-lang/markdown/issues/359).
+* Add `bool withDefaultInlineSyntaxes` and `bool withDefaultBlockSyntaxes`
+  parameters to `markdownToHtml` and `Document` to support the case of
+  specifying exactly the list of desired syntaxes. Thanks @chenzhiguang.
+  [#393](https://github.com/dart-lang/markdown/issues/393).
+
+## 4.0.1
+
+* Export `src/emojis.dart` in public API.
+* Update version of example page.
+* Internal: enforce lint rules found in the lints package.
+* Bump io dependency to `^1.0.0`.
+
+## 4.0.0
+
+* Stable null safety release.
+* Require the latest `args`, update the markdown executable to be opted in.
+
+## 4.0.0-nullsafety.0
+
+* Migrate package to Dart's null safety language feature, requiring Dart
+  2.12 or higher.
+* **Breaking change:** The TagSyntax constructor no longer takes an `end`
+  parameter. TagSyntax no longer implements `onMatchEnd`. Instead, TagSyntax
+  implements a method called `close` which creates and returns a Node, if a
+  Node can be created and closed at the current position. If the TagSyntax
+  instance cannot create a Node at the current position, the method should
+  return `null`. Some TagSyntax subclasses will unconditionally create a tag in
+  `close`, while others may be unable to, such as LinkSyntax, if an inline or
+  reference link could not be resolved.
+* Improved parsing of nested links, images, and emphasis. CommonMark compliance
+  of emphasis-parsing improves to 99%, and link-parsing compliance rises to
+  93%. Overall compliance improves to 94% and overall GitHub-flavored Markdown
+  improves to 93%.
+
+## 3.0.0
+
+* **Breaking change:** Remove `ListSyntax.removeLeadingEmptyLine`,
+  `ListSyntax.removeTrailingEmptyLines`, `TableSyntax.parseAlignments`,
+  `TableSyntax.parseRow`.
+* Allow intra-word strikethrough in GFM
+  ([#300](https://github.com/dart-lang/markdown/issues/300)).
+* **Breaking change:** Change `BlockSyntax.canEndBlock` from a getter to a
+  method accepting a BlockParser.
+
+## 2.1.8
+
+* Deprecate the _public_ methods `ListSyntax.removeLeadingEmptyLine`,
+  `ListSyntax.removeTrailingEmptyLines`, `TableSyntax.parseAlignments`,
+  `TableSyntax.parseRow`. These will be made private in a major version bump as
+  early as 3.0.0.
+
+## 2.1.7
+
+* Add dependency on the meta package
+
+## 2.1.6
+
+* Fix for custom link resolvers
+  ([#295](https://github.com/dart-lang/markdown/issues/295)).
+* Add missing HTML 5 block-level items
+  ([#294](https://github.com/dart-lang/markdown/pull/294)).
+
+## 2.1.5
+
+* Overhaul table row parsing. This does not have many consequences, except that
+  whitespace around escaped pipes is handled better.
+  ([#287](https://github.com/dart-lang/markdown/issues/287)).
+
+## 2.1.4
+
+* Correctly parse a reference link with a newline in the link reference part
+  ([#281](https://github.com/dart-lang/markdown/issues/281)).
+
+## 2.1.3
+
+* Do not encode HTML in link URLs. Also do not encode HTML in link text when
+  `encodeHtml` is false (e.g. when used in Flutter).
+
+## 2.1.2
+
+* Drop support for Dart 2.0.0 through 2.1.0.
+* Recognize Unicode ellipsis (…) and other Unicode punctuation as punctuation
+  when parsing potential emphasis.
+* Reduce time to parse a large HTML-block-free Markdown document (such as that
+  in #271) by more than half.
+* Add a new optional parameter for InlineSyntax(), `startCharacter`, where a
+  subclass can specify a single character to try to match, before matching with
+  more expensive regular expressions.
+
+## 2.1.1
+
+* Fix for encoding HTML for text string that contains `<pre>`
+  ([#263](https://github.com/dart-lang/markdown/issues/263)).
+
+## 2.1.0
+
+* Improve strict spec compliance of `>` handling by always encoding as `&gt;`
+  – unless preceded by `/`.
+* Improve strict spec compliance for `blockquote` by always putting the closing
+  tag on a new line.
+* Improve strict spec compliance for `code` elements defined with "\`".
+* Properly encode `<`, `>`, and `"` as their respective HTML entities when
+  interpreted as text.
+* Improve inline code parsing when using multiple backticks.
+* Do not encode HTML in indented code blocks when `encodeHtml` is false (e.g.
+  when used in Flutter).
+
+## 2.0.3
+
+* Render element attributes in the order they were defined.
+  Aligns more closely with the strict spec definition.
+* Correctly render `&` within inline image titles.
+* Add 68 new GitHub emoji.
+* Escape HTML attribute for fenced code blocks, in the info string.
+
+## 2.0.2
+
+* Set max SDK version to `<3.0.0`, and adjust other dependencies.
+
+## 2.0.1
+
+* Require Dart 2.0.0-dev.
+
+## 2.0.0
+
+* **Breaking change:** The `Link` class has been renamed `LinkReference`, and
+  the `Document` field, `refLinks`, has been renamed `linkReferences`.
+* **Breaking change:** Remove the deprecated `ExtensionSet.gitHub` field.
+  Use `ExtensionSet.gitHubFlavored` instead.
+* **Breaking change:** Make all of the fields on `Document` read-only.
+* Overhaul support for emphasis (`*foo*` and `_foo_`) and strong emphasis
+  (`**foo**` and `__foo__`), dramatically improving CommonMark compliance.
+* Overhaul support for links and images, again dramatically improving CommonMark
+  compliance.
+* Improve support for tab characters, and horizontal rules.
+* Add support for GitHub Flavored Markdown's Strikethrough extension. See the
+  [GFM spec][strikethrough].
+* The above fixes raise compliance with the CommonMark specs to 93%, and
+  compliance with the GFM specs to 92%.
+* Add an `encodeHtml` parameter to `Document`, which defaults to true. When
+  false, HTML entities (such as `&copy;` and the `<` character) will not be
+  escaped, useful when rendering Markdown in some output format other than HTML.
+* Allow the binary script to take a `--extension-set` option.
+
+  A reminder: You can [run `bin/markdown.dart` from anywhere][pub-global] via:
+
+  ```shell
+  $ pub global activate markdown
+  $ markdown
+  ```
+
+[strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
+[pub-global]: https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path
+
+## 1.1.1
+
+* Add support for GitHub's colon-based Emoji syntax. :tada:! This is available
+  in the `gitHubWeb` extension set.
+
+## 1.1.0
+
+* Make the constructor for ExtensionSet public, for tools like dartdoc.
+* Split the `gitHub` ExtensionSet into two sets: `gitHubFlavored`, which
+  represents the GitHub Flavored Markdown spec, and `gitHubWeb`, which
+  represents what GitHub actually renders Markdown.
+
+## 1.0.0
+
+* Fix issue where `accept` could cause an exception.
+* Remove deprecated `escapeHtml` function.
+* Fix compliance with auto-links, including support for email addresses.
+* Updated `ExtensionSet.gitHub` to more closely align with GitHub markdown.
+
+## 0.11.4
+
+* Fix bug with lazy blockquote continuations (#162)
+* Fix bug with list item continuations (#156)
+
+## 0.11.3
+
+* Deprecate `escapeHtml`. This code exists in `dart:convert`.
+
+## 0.11.2
+
+* Fix reference code links inside blockquotes.
+* Add src/util.dart to exports.
+
+## 0.11.1
+
+* Add version information:
+  * `dart bin/markdown.dart --version` now shows the package version number.
+  * The playground app now shows the version number.
+* Improve autolink parsing.
+* Add new table syntax: `TableSyntax`.
+* Add new ExtensionSet that includes the table syntax: `ExtensionSet.gitHub`.
+* For development: added `tool/travis.sh`.
+* Support multiline Setext headers.
+* Handle loose-vs-strict list items better.
+* Support ordered lists that start with a number other than 1.
+
+## 0.11.0+1
+
+* Add playground app at https://dart-lang.github.io/markdown.
+
+## 0.11.0
+
+* Parse HTML blocks more accurately, according to
+  [CommonMark](https://spec.commonmark.org/0.24/#html-blocks).
+* Support [shortcut reference
+  links](https://spec.commonmark.org/0.24/#reference-link).
+* Don't allow an indented code block to interrupt a paragraph.
+* Change definition of "loose" and "strict" lists (items wrapped in
+  paragraph tags vs not) to CommonMark's. The primary difference is that any
+  single list item can trigger the entire list to be marked as "loose", rather
+  than defining "looseness" on each specific item.
+* Fix paragraph continuations in blockquotes and list items.
+* Fix silly typing bug with `tool/common_mark_stats.dart`, which resulted in
+  a dramatic overestimate of our CommonMark compliance.
+* There are now 427/613 (69%) passing CommonMark v0.25 specs.
+
+## 0.10.1
+
+* Parse [hard line breaks](https://spec.commonmark.org/0.24/#hard-line-breaks)
+  properly (#86). Thanks @mehaase!
+* Fix processing of `[ ... ]` syntax when no resolver is specified (#92).
+* There are now 401/613 (65%) passing CommonMark v0.24 specs.
+  (_Actually: after 0f64c8f the actual number of passing tests was 352/613
+  (57%)._)
+
+## 0.10.0
+
+* BREAKING: Now following the CommonMark spec for fenced code blocks.
+  If a language (info string) is provided, it is added as a class to the `code`
+  element with a `language-` prefix.
+* BREAKING: Now following the CommonMark spec for images. Previously,
+  `![text](img.png)` would compile too
+  `<a href="img.prg"><img src="img.prg" alt="text"></img></a>`. That same code
+  will now compile to `<img src="img.png" alt="text" />`.
+* Fix all [strong mode][] errors.
+
+[strong mode]: https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
+
+## 0.9.0
+
+* BREAKING: The text `[foo] (bar)` no longer renders as an inline link (#53).
+* BREAKING: Change list parsing to allow lists to begin immediately after a
+  preceding block element, without a blank line in between.
+* Formalize an API for Markdown extensions (#43).
+* Introduce ExtensionSets. FencedCodeBlock is considered an extension, but
+  existing usage of `markdownToHtml()` and `new Document()` will use the
+  default extension set, which is `ExtensionSet.commonMark`, which includes
+  FencedCodeBlock.
+* Inline HTML syntax support; This is also considered an extension (#18).
+* The text `[foo]()` now renders as an inline link.
+* Whitespace now allowed between a link's destination and title (#65).
+* Header identifier support in the HeaderWithIdSyntax and
+  SetextHeaderWithIdSyntax extensions.
+* Implement backslash-escaping so that Markdown syntax can be escaped, such as
+  `[foo]\(bar) ==> <p>[foo](bar)</p>`.
+* Support for hard line breaks with either `\\\n` or <code>  \n</code> (#30,
+  #60).
+* New public method for BlockParser: `peek(int linesAhead)`, meant for use in
+  subclasses.
+* New public members for ListSyntax: `blocksInList` and `determineBlockItems()`,
+  meant for use in subclasses.
+* Improve public docs (better, and more of them).
+
+## 0.8.0
+
+* **Breaking:** Remove (probably unused) fields: `LinkSyntax.resolved`,
+  `InlineParser.currentSource`.
+* Switch tests to use [test][] instead of [unittest][].
+* Fix a few bugs in inline code syntax.
+* Ignore underscores inside words (#41).
+
+[test]: https://pub.dev/packages/test
+[unittest]: https://pub.dev/packages/unittest
+
+## 0.7.2
+
+* Allow resolving links that contain inline syntax (#42).
+
+## 0.7.1+3
+
+* Updated homepage.
+
+## 0.7.1+2
+
+* Formatted code.
+
+* Updated readme.
diff --git a/pkgs/markdown/LICENSE b/pkgs/markdown/LICENSE
new file mode 100644
index 0000000..c2730c9
--- /dev/null
+++ b/pkgs/markdown/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2012, the Dart project authors. 
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google LLC nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/markdown/README.md b/pkgs/markdown/README.md
new file mode 100644
index 0000000..3b87484
--- /dev/null
+++ b/pkgs/markdown/README.md
@@ -0,0 +1,173 @@
+[![Build Status](https://github.com/dart-lang/tools/actions/workflows/markdown.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/markdown.yaml)
+[![pub package](https://img.shields.io/pub/v/markdown.svg)](https://pub.dev/packages/markdown)
+[![package publisher](https://img.shields.io/pub/publisher/markdown.svg)](https://pub.dev/packages/markdown/publisher)
+
+A portable Markdown library written in Dart. It can parse Markdown into
+HTML on both the client and server.
+
+Play with it at
+[dart-lang.github.io/markdown](https://dart-lang.github.io/markdown).
+
+### Usage
+
+```dart
+import 'package:markdown/markdown.dart';
+
+void main() {
+  print(markdownToHtml('Hello *Markdown*'));
+  //=> <p>Hello <em>Markdown</em></p>
+}
+```
+
+### Syntax extensions
+
+A few Markdown extensions, beyond what was specified in the original
+[Perl Markdown][] implementation, are supported. By default, the ones supported
+in [CommonMark] are enabled. Any individual extension can be enabled by
+specifying an Array of extension syntaxes in the `blockSyntaxes` or
+`inlineSyntaxes` argument of `markdownToHtml`.
+
+The currently supported inline extension syntaxes are:
+
+* `InlineHtmlSyntax()` - approximately CommonMark's
+  [definition][commonmark-raw-html] of "Raw HTML".
+
+The currently supported block extension syntaxes are:
+
+* `const FencedCodeBlockSyntax()` - Code blocks familiar to Pandoc and PHP
+  Markdown Extra users.
+* `const HeaderWithIdSyntax()` - ATX-style headers have generated IDs, for link
+  anchors (akin to Pandoc's [`auto_identifiers`][pandoc-auto_identifiers]).
+* `const SetextHeaderWithIdSyntax()` - Setext-style headers have generated IDs
+  for link anchors (akin to Pandoc's
+  [`auto_identifiers`][pandoc-auto_identifiers]).
+* `const TableSyntax()` - Table syntax familiar to GitHub, PHP Markdown Extra,
+  and Pandoc users.
+
+For example:
+
+```dart
+import 'package:markdown/markdown.dart';
+
+void main() {
+  print(markdownToHtml('Hello <span class="green">Markdown</span>',
+      inlineSyntaxes: [InlineHtmlSyntax()]));
+  //=> <p>Hello <span class="green">Markdown</span></p>
+}
+```
+
+### Extension sets
+
+To make extension management easy, you can also just specify an extension set.
+Both `markdownToHtml()` and `Document()` accept an `extensionSet` named
+parameter. Currently, there are four pre-defined extension sets:
+
+* `ExtensionSet.none` includes no extensions. With no extensions, Markdown
+  documents will be parsed with a default set of block and inline syntax
+  parsers that closely match how the document might be parsed by the original
+  [Perl Markdown][] implementation.
+
+* `ExtensionSet.commonMark` includes two extensions in addition to the default
+  parsers to bring the parsed output closer to the [CommonMark] specification:
+
+  * Block Syntax Parser
+    * `const FencedCodeBlockSyntax()`
+  
+  * Inline Syntax Parser
+    * `InlineHtmlSyntax()`
+
+* `ExtensionSet.gitHubFlavored` includes five extensions in addition to the default
+  parsers to bring the parsed output close to the [GitHub Flavored] Markdown
+  specification: 
+
+  * Block Syntax Parser
+    * `const FencedCodeBlockSyntax()`
+    * `const TableSyntax()`
+  
+  * Inline Syntax Parser
+    * `InlineHtmlSyntax()`
+    * `StrikethroughSyntax()`
+    * `AutolinkExtensionSyntax()`
+
+* `ExtensionSet.gitHubWeb` includes eight extensions. The same set of parsers use
+   in the `gitHubFlavored` extension set with the addition of the block syntax parsers,
+   HeaderWithIdSyntax and SetextHeaderWithIdSyntax, which add `id` attributes to
+   headers and inline syntax parser, EmojiSyntax, for parsing GitHub style emoji
+   characters:
+
+  * Block Syntax Parser
+    * `const FencedCodeBlockSyntax()`
+    * `const HeaderWithIdSyntax()`, which adds `id` attributes to ATX-style
+      headers, for easy intra-document linking.
+    * `const SetextHeaderWithIdSyntax()`, which adds `id` attributes to
+      Setext-style headers, for easy intra-document linking.
+    * `const TableSyntax()`
+  
+  * Inline Syntax Parser
+    * `InlineHtmlSyntax()`
+    * `StrikethroughSyntax()`
+    * `EmojiSyntax()`
+    * `AutolinkExtensionSyntax()`
+
+### Custom syntax extensions
+
+You can create and use your own syntaxes.
+
+```dart
+import 'package:markdown/markdown.dart';
+
+void main() {
+  var syntaxes = [TextSyntax('nyan', sub: '~=[,,_,,]:3')];
+  print(markdownToHtml('nyan', inlineSyntaxes: syntaxes));
+  //=> <p>~=[,,_,,]:3</p>
+}
+```
+
+### HTML sanitization
+
+This package offers no features in the way of HTML sanitization. Read Estevão
+Soares dos Santos's great article, ["Markdown's XSS Vulnerability (and how to
+mitigate it)"], to learn more.
+
+The authors recommend that you perform any necessary sanitization on the
+resulting HTML, for example via `dart:html`'s [NodeValidator].
+
+### CommonMark compliance
+
+This package contains a number of files in the `tool` directory for tracking
+compliance with [CommonMark].
+
+#### Updating CommonMark stats when changing the implementation
+
+ 1. Update the library and test code, making sure that tests still pass.
+ 2. Run `dart run tool/stats.dart --update-files` to update the
+    per-test results `tool/common_mark_stats.json` and the test summary
+    `tool/common_mark_stats.txt`.
+ 3. Verify that more tests now pass – or at least, no more tests fail.
+ 4. Make sure you include the updated stats files in your commit.
+
+#### Updating the CommonMark test file for a spec update
+
+ 1. Check out the [CommonMark source]. Make sure you checkout a *major* release.
+ 2. Dump the test output overwriting the existing tests file.
+
+    ```console
+    > cd /path/to/common_mark_dir
+    > python3 test/spec_tests.py --dump-tests > \
+      /path/to/markdown.dart/tool/common_mark_tests.json
+    ```
+
+ 3. Update the stats files as described above. Note any changes in the results.
+ 4. Update any references to the existing spec by search for
+    `https://spec.commonmark.org/0.30/` in the repository. (Including this one.)
+    Verify the updated links are still valid.
+ 5. Commit changes, including a corresponding note in `CHANGELOG.md`.
+
+[Perl Markdown]: https://daringfireball.net/projects/markdown/
+[CommonMark]: https://commonmark.org/
+[commonMark-raw-html]: https://spec.commonmark.org/0.30/#raw-html
+[CommonMark source]: https://github.com/commonmark/commonmark-spec
+[GitHub Flavored]: https://github.github.io/gfm/
+[pandoc-auto_identifiers]: https://pandoc.org/MANUAL.html#extension-auto_identifiers
+["Markdown's XSS Vulnerability (and how to mitigate it)"]: https://github.com/showdownjs/showdown/wiki/Markdown%27s-XSS-Vulnerability-(and-how-to-mitigate-it)
+[NodeValidator]: https://api.dart.dev/stable/dart-html/NodeValidator-class.html
diff --git a/pkgs/markdown/analysis_options.yaml b/pkgs/markdown/analysis_options.yaml
new file mode 100644
index 0000000..e7748f5
--- /dev/null
+++ b/pkgs/markdown/analysis_options.yaml
@@ -0,0 +1,36 @@
+# https://dart.dev/tools/analysis
+include: package:dart_flutter_team_lints/analysis_options.yaml
+
+analyzer:
+  language:
+    strict-casts: true
+    strict-inference: true
+    strict-raw-types: true
+
+  errors:
+    # The example app explicitly takes a String of user-generated HTML and
+    # inserts it straight into a <div> using innerHtml.
+    unsafe_html: ignore
+    # Waiting on a couple of bug fixes and new features before this should be enabled
+    comment_references: ignore
+
+linter:
+  rules:
+    # https://github.com/dart-lang/linter/issues/574
+    #- comment_references
+    - avoid_private_typedef_functions
+    - avoid_redundant_argument_values
+    - avoid_unused_constructor_parameters
+    - avoid_void_async
+    - cancel_subscriptions
+    - literal_only_boolean_expressions
+    - missing_whitespace_between_adjacent_strings
+    - no_adjacent_strings_in_list
+    - prefer_const_declarations
+    - prefer_final_locals
+    - prefer_final_in_for_each
+    - unnecessary_await_in_return
+    - unnecessary_raw_strings
+    - use_if_null_to_convert_nulls_to_bools
+    - use_raw_strings
+    - use_string_buffers
diff --git a/pkgs/markdown/benchmark/benchmark.dart b/pkgs/markdown/benchmark/benchmark.dart
new file mode 100644
index 0000000..aaf8112
--- /dev/null
+++ b/pkgs/markdown/benchmark/benchmark.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:io';
+
+import 'package:markdown/markdown.dart';
+import 'package:path/path.dart' as p;
+
+const numTrials = 100;
+const runsPerTrial = 50;
+
+final source = _loadFile('input.md');
+final expected = _loadFile('output.html');
+
+void main() {
+  var best = double.infinity;
+
+  // Run the benchmark several times. This ensures the VM is warmed up and lets
+  // us see how much variance there is.
+  for (var i = 0; i <= numTrials; i++) {
+    final stopwatch = Stopwatch()..start();
+
+    // For a single benchmark, convert the source multiple times.
+    late String result;
+    for (var j = 0; j < runsPerTrial; j++) {
+      result = markdownToHtml(source);
+    }
+
+    stopwatch.stop();
+    final elapsed = stopwatch.elapsedMilliseconds / runsPerTrial;
+
+    // Keep track of the best run so far.
+    if (elapsed >= best) continue;
+    best = elapsed;
+
+    // Sanity check to make sure the output is what we expect and to make sure
+    // the VM doesn't optimize "dead" code away.
+    if (result != expected) {
+      print('Incorrect output:\n$result');
+      exitCode = 1;
+      return;
+    }
+
+    // Don't print the first run. It's always terrible since the VM hasn't
+    // warmed up yet.
+    if (i == 0) continue;
+    _printResult("Run ${'#$i'.padLeft(3)}", elapsed);
+  }
+
+  _printResult('Best   ', best);
+}
+
+String _loadFile(String name) {
+  final path = p.join(p.dirname(p.fromUri(Platform.script)), name);
+  return File(path).readAsStringSync();
+}
+
+void _printResult(String label, double time) {
+  print(
+    '$label: ${time.toStringAsFixed(2).padLeft(4)}ms '
+    "${'=' * ((time * 20).toInt())}",
+  );
+}
diff --git a/pkgs/markdown/benchmark/input.md b/pkgs/markdown/benchmark/input.md
new file mode 100644
index 0000000..2dd9df5
--- /dev/null
+++ b/pkgs/markdown/benchmark/input.md
@@ -0,0 +1,421 @@
+**TODO: Add more examples to cover all of the syntax.**
+
+# Regressions
+
+Bad backtracking in the HR parser:
+
+-------------------------- | -------------------------------------------------
+
+# Real-world sample
+
+This input was taken from the test package's README to get a representative
+sample of real-world markdown:
+
+Tests are specified using the top-level [`test()`][test] function, and test
+assertions are made using [`expect()`][expect]:
+
+[test]: https://pub.dev/documentation/test_core/latest/test_core/test.html
+[expect]: https://pub.dev/documentation/test_api/latest/test_api/expect.html
+
+```dart
+import "package:test/test.dart";
+
+void main() {
+  test("String.split() splits the string on the delimiter", () {
+    var string = "foo,bar,baz";
+    expect(string.split(","), equals(["foo", "bar", "baz"]));
+  });
+
+  test("String.trim() removes surrounding whitespace", () {
+    var string = "  foo ";
+    expect(string.trim(), equals("foo"));
+  });
+}
+```
+
+Tests can be grouped together using the [`group()`] function. Each group's
+description is added to the beginning of its test's descriptions.
+
+```dart
+import "package:test/test.dart";
+
+void main() {
+  group("String", () {
+    test(".split() splits the string on the delimiter", () {
+      var string = "foo,bar,baz";
+      expect(string.split(","), equals(["foo", "bar", "baz"]));
+    });
+
+    test(".trim() removes surrounding whitespace", () {
+      var string = "  foo ";
+      expect(string.trim(), equals("foo"));
+    });
+  });
+
+  group("int", () {
+    test(".remainder() returns the remainder of division", () {
+      expect(11.remainder(3), equals(2));
+    });
+
+    test(".toRadixString() returns a hex string", () {
+      expect(11.toRadixString(16), equals("b"));
+    });
+  });
+}
+```
+
+Any matchers from the [`matcher`][matcher] package can be used with `expect()`
+to do complex validations:
+
+[matcher]: https://pub.dev/documentation/matcher/latest/matcher/matcher-library.html
+
+```dart
+import "package:test/test.dart";
+
+void main() {
+  test(".split() splits the string on the delimiter", () {
+    expect("foo,bar,baz", allOf([
+      contains("foo"),
+      isNot(startsWith("bar")),
+      endsWith("baz")
+    ]));
+  });
+}
+```
+
+## Running Tests
+
+A single test file can be run just using `dart run test path/to/test.dart`.
+
+Many tests can be run at a time using `dart run test path/to/dir`.
+
+It's also possible to run a test on the Dart VM only by invoking it using `dart
+path/to/test.dart`, but this doesn't load the full test runner and will be
+missing some features.
+
+The test runner considers any file that ends with `_test.dart` to be a test
+file. If you don't pass any paths, it will run all the test files in your
+`test/` directory, making it easy to test your entire application at once.
+
+By default, tests are run in the Dart VM, but you can run them in the browser as
+well by passing `dart run test -p chrome path/to/test.dart`.
+`test` will take care of starting the browser and loading the tests, and all
+the results will be reported on the command line just like for VM tests. In
+fact, you can even run tests on both platforms with a single command: `dart run
+test -p chrome,vm path/to/test.dart`.
+
+### Restricting Tests to Certain Platforms
+
+Some test files only make sense to run on particular platforms. They may use
+`dart:html` or `dart:io`, they might test Windows' particular filesystem
+behavior, or they might use a feature that's only available in Chrome. The
+[`@TestOn`][TestOn] annotation makes it easy to declare exactly which platforms
+a test file should run on. Just put it at the top of your file, before any
+`library` or `import` declarations:
+
+```dart
+@TestOn("vm")
+
+import "dart:io";
+
+import "package:test/test.dart";
+
+void main() {
+  // ...
+}
+```
+
+[TestOn]: https://pub.dev/documentation/test_api/latest/test_api/TestOn-class.html
+
+The string you pass to `@TestOn` is what's called a "platform selector", and it
+specifies exactly which platforms a test can run on. It can be as simple as the
+name of a platform, or a more complex Dart-like boolean expression involving
+these platform names.
+
+### Platform Selector Syntax
+
+Platform selectors can contain identifiers, parentheses, and operators. When
+loading a test, each identifier is set to `true` or `false` based on the current
+platform, and the test is only loaded if the platform selector returns `true`.
+The operators `||`, `&&`, `!`, and `? :` all work just like they do in Dart. The
+valid identifiers are:
+
+* `vm`: Whether the test is running on the command-line Dart VM.
+
+* `dartium`: Whether the test is running on Dartium.
+
+* `content-shell`: Whether the test is running on the headless Dartium content
+  shell.
+
+* `chrome`: Whether the test is running on Google Chrome.
+
+* `phantomjs`: Whether the test is running on
+  [PhantomJS](http://phantomjs.org/).
+
+* `firefox`: Whether the test is running on Mozilla Firefox.
+
+* `safari`: Whether the test is running on Apple Safari.
+
+* `ie`: Whether the test is running on Microsoft Internet Explorer.
+
+* `dart-vm`: Whether the test is running on the Dart VM in any context,
+  including Dartium. It's identical to `!js`.
+
+* `browser`: Whether the test is running in any browser.
+
+* `js`: Whether the test has been compiled to JS. This is identical to
+  `!dart-vm`.
+
+* `blink`: Whether the test is running in a browser that uses the Blink
+  rendering engine.
+
+* `windows`: Whether the test is running on Windows. If `vm` is false, this will
+  be `false` as well.
+
+* `mac-os`: Whether the test is running on Mac OS. If `vm` is false, this will
+  be `false` as well.
+
+* `linux`: Whether the test is running on Linux. If `vm` is false, this will be
+  `false` as well.
+
+* `android`: Whether the test is running on Android. If `vm` is false, this will
+  be `false` as well, which means that this *won't* be true if the test is
+  running on an Android browser.
+
+* `posix`: Whether the test is running on a POSIX operating system. This is
+  equivalent to `!windows`.
+
+For example, if you wanted to run a test on every browser but Chrome, you would
+write `@TestOn("browser && !chrome")`.
+
+## Asynchronous Tests
+
+Tests written with `async`/`await` will work automatically. The test runner
+won't consider the test finished until the returned `Future` completes.
+
+```dart
+import "dart:async";
+
+import "package:test/test.dart";
+
+void main() {
+  test("new Future.value() returns the value", () async {
+    var value = await new Future.value(10);
+    expect(value, equals(10));
+  });
+}
+```
+
+There are also a number of useful functions and matchers for more advanced
+asynchrony. The [`completion()`][completion] matcher can be used to test
+`Futures`; it ensures that the test doesn't finish until the `Future` completes,
+and runs a matcher against that `Future`'s value.
+
+[completion]: https://pub.dev/documentation/test_api/latest/test_api/completion.html
+
+```dart
+import "dart:async";
+
+import "package:test/test.dart";
+
+void main() {
+  test("new Future.value() returns the value", () {
+    expect(new Future.value(10), completion(equals(10)));
+  });
+}
+```
+
+The [`throwsA()`][throwsA] matcher and the various `throwsExceptionType`
+matchers work with both synchronous callbacks and asynchronous `Future`s. They
+ensure that a particular type of exception is thrown:
+
+[throwsA]: https://pub.dev/documentation/test_api/latest/test_api/throwsA.html
+
+```dart
+import "dart:async";
+
+import "package:test/test.dart";
+
+void main() {
+  test("new Future.error() throws the error", () {
+    expect(new Future.error("oh no"), throwsA(equals("oh no")));
+    expect(new Future.error(new StateError("bad state")), throwsStateError);
+  });
+}
+```
+
+The [`expectAsync()`][expectAsync] function wraps another function and has two
+jobs. First, it asserts that the wrapped function is called a certain number of
+times, and will cause the test to fail if it's called too often; second, it
+keeps the test from finishing until the function is called the requisite number
+of times.
+
+```dart
+import "dart:async";
+
+import "package:test/test.dart";
+
+void main() {
+  test("Stream.fromIterable() emits the values in the iterable", () {
+    var stream = new Stream.fromIterable([1, 2, 3]);
+
+    stream.listen(expectAsync((number) {
+      expect(number, inInclusiveRange(1, 3));
+    }, count: 3));
+  });
+}
+```
+
+[expectAsync]: https://pub.dev/documentation/test_api/latest/test_api/expectAsync.html
+
+## Running Tests with Custom HTML
+
+By default, the test runner will generate its own empty HTML file for browser
+tests. However, tests that need custom HTML can create their own files. These
+files have three requirements:
+
+* They must have the same name as the test, with `.dart` replaced by `.html`.
+
+* They must contain a `link` tag with `rel="x-dart-test"` and an `href`
+  attribute pointing to the test script.
+
+* They must contain `<script src="packages/test/dart.js"></script>`.
+
+For example, if you had a test called `custom_html_test.dart`, you might write
+the following HTML file:
+
+```html
+<!doctype html>
+<!-- custom_html_test.html -->
+<html>
+  <head>
+    <title>Custom HTML Test</title>
+    <link rel="x-dart-test" href="custom_html_test.dart">
+    <script src="packages/test/dart.js"></script>
+  </head>
+  <body>
+    // ...
+  </body>
+</html>
+```
+
+## Configuring Tests
+
+### Skipping Tests
+
+If a test, group, or entire suite isn't working yet and you just want it to stop
+complaining, you can mark it as "skipped". The test or tests won't be run, and,
+if you supply a reason why, that reason will be printed. In general, skipping
+tests indicates that they should run but is temporarily not working. If they're
+is fundamentally incompatible with a platform, [`@TestOn`/`testOn`][TestOn]
+should be used instead.
+
+[TestOn]: #restricting-tests-to-certain-platforms
+
+To skip a test suite, put a `@Skip` annotation at the top of the file:
+
+```dart
+@Skip("currently failing (see issue 1234)")
+
+import "package:test/test.dart";
+
+void main() {
+  // ...
+}
+```
+
+The string you pass should describe why the test is skipped. You don't have to
+include it, but it's a good idea to document why the test isn't running.
+
+Groups and individual tests can be skipped by passing the `skip` parameter. This
+can be either `true` or a String describing why the test is skipped. For example:
+
+```dart
+import "package:test/test.dart";
+
+void main() {
+  group("complicated algorithm tests", () {
+    // ...
+  }, skip: "the algorithm isn't quite right");
+
+  test("error-checking test", () {
+    // ...
+  }, skip: "TODO: add error-checking.");
+}
+```
+
+### Timeouts
+
+By default, tests will time out after 30 seconds of inactivity. However, this
+can be configured on a per-test, -group, or -suite basis. To change the timeout
+for a test suite, put a `@Timeout` annotation at the top of the file:
+
+```dart
+@Timeout(const Duration(seconds: 45))
+
+import "package:test/test.dart";
+
+void main() {
+  // ...
+}
+```
+
+In addition to setting an absolute timeout, you can set the timeout relative to
+the default using `@Timeout.factor`. For example, `@Timeout.factor(1.5)` will
+set the timeout to one and a half times as long as the default—45 seconds.
+
+Timeouts can be set for tests and groups using the `timeout` parameter. This
+parameter takes a `Timeout` object just like the annotation. For example:
+
+```dart
+import "package:test/test.dart";
+
+void main() {
+  group("slow tests", () {
+    // ...
+
+    test("even slower test", () {
+      // ...
+    }, timeout: new Timeout.factor(2))
+  }, timeout: new Timeout(new Duration(minutes: 1)));
+}
+```
+
+Nested timeouts apply in order from outermost to innermost. That means that
+"even slower test" will take two minutes to time out, since it multiplies the
+group's timeout by 2.
+
+### Platform-Specific Configuration
+
+Sometimes a test may need to be configured differently for different platforms.
+Windows might run your code slower than other platforms, or your DOM
+manipulation might not work right on Safari yet. For these cases, you can use
+the `@OnPlatform` annotation and the `onPlatform` named parameter to `test()`
+and `group()`. For example:
+
+```dart
+@OnPlatform(const {
+  // Give Windows some extra wiggle-room before timing out.
+  "windows": const Timeout.factor(2)
+})
+
+import "package:test/test.dart";
+
+void main() {
+  test("do a thing", () {
+    // ...
+  }, onPlatform: {
+    "safari": new Skip("Safari is currently broken (see #1234)")
+  });
+}
+```
+
+Both the annotation and the parameter take a map. The map's keys are [platform
+selectors](#platform-selector-syntax) which describe the platforms for which the
+specialized configuration applies. Its values are instances of some of the same
+annotation classes that can be used for a suite: `Skip` and `Timeout`. A value
+can also be a list of these values.
+
+If multiple platforms match, the configuration is applied in order from first to
+last, just as they would in nested groups. This means that for configuration
+like duration-based timeouts, the last matching value wins.
diff --git a/pkgs/markdown/benchmark/output.html b/pkgs/markdown/benchmark/output.html
new file mode 100644
index 0000000..200e4bd
--- /dev/null
+++ b/pkgs/markdown/benchmark/output.html
@@ -0,0 +1,360 @@
+<p><strong>TODO: Add more examples to cover all of the syntax.</strong></p>
+<h1>Regressions</h1>
+<p>Bad backtracking in the HR parser:</p>
+<p>-------------------------- | -------------------------------------------------</p>
+<h1>Real-world sample</h1>
+<p>This input was taken from the test package's README to get a representative
+sample of real-world markdown:</p>
+<p>Tests are specified using the top-level <a href="https://pub.dev/documentation/test_core/latest/test_core/test.html"><code>test()</code></a> function, and test
+assertions are made using <a href="https://pub.dev/documentation/test_api/latest/test_api/expect.html"><code>expect()</code></a>:</p>
+<pre><code class="language-dart">import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;String.split() splits the string on the delimiter&quot;, () {
+    var string = &quot;foo,bar,baz&quot;;
+    expect(string.split(&quot;,&quot;), equals([&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;]));
+  });
+
+  test(&quot;String.trim() removes surrounding whitespace&quot;, () {
+    var string = &quot;  foo &quot;;
+    expect(string.trim(), equals(&quot;foo&quot;));
+  });
+}
+</code></pre>
+<p>Tests can be grouped together using the [<code>group()</code>] function. Each group's
+description is added to the beginning of its test's descriptions.</p>
+<pre><code class="language-dart">import &quot;package:test/test.dart&quot;;
+
+void main() {
+  group(&quot;String&quot;, () {
+    test(&quot;.split() splits the string on the delimiter&quot;, () {
+      var string = &quot;foo,bar,baz&quot;;
+      expect(string.split(&quot;,&quot;), equals([&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;]));
+    });
+
+    test(&quot;.trim() removes surrounding whitespace&quot;, () {
+      var string = &quot;  foo &quot;;
+      expect(string.trim(), equals(&quot;foo&quot;));
+    });
+  });
+
+  group(&quot;int&quot;, () {
+    test(&quot;.remainder() returns the remainder of division&quot;, () {
+      expect(11.remainder(3), equals(2));
+    });
+
+    test(&quot;.toRadixString() returns a hex string&quot;, () {
+      expect(11.toRadixString(16), equals(&quot;b&quot;));
+    });
+  });
+}
+</code></pre>
+<p>Any matchers from the <a href="https://pub.dev/documentation/matcher/latest/matcher/matcher-library.html"><code>matcher</code></a> package can be used with <code>expect()</code>
+to do complex validations:</p>
+<pre><code class="language-dart">import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;.split() splits the string on the delimiter&quot;, () {
+    expect(&quot;foo,bar,baz&quot;, allOf([
+      contains(&quot;foo&quot;),
+      isNot(startsWith(&quot;bar&quot;)),
+      endsWith(&quot;baz&quot;)
+    ]));
+  });
+}
+</code></pre>
+<h2>Running Tests</h2>
+<p>A single test file can be run just using <code>pub run test:test path/to/test.dart</code>
+(on Dart 1.10, this can be shortened to <code>pub run test path/to/test.dart</code>).</p>
+<p><img src="https://raw.githubusercontent.com/dart-lang/test/master/image/test1.gif" alt="Single file being run via pub run&quot;" /></p>
+<p>Many tests can be run at a time using <code>pub run test:test path/to/dir</code>.</p>
+<p><img src="https://raw.githubusercontent.com/dart-lang/test/master/image/test2.gif" alt="Directory being run via &quot;pub run&quot;." /></p>
+<p>It's also possible to run a test on the Dart VM only by invoking it using <code>dart path/to/test.dart</code>, but this doesn't load the full test runner and will be
+missing some features.</p>
+<p>The test runner considers any file that ends with <code>_test.dart</code> to be a test
+file. If you don't pass any paths, it will run all the test files in your
+<code>test/</code> directory, making it easy to test your entire application at once.</p>
+<p>By default, tests are run in the Dart VM, but you can run them in the browser as
+well by passing <code>pub run test:test -p chrome path/to/test.dart</code>.
+<code>test</code> will take care of starting the browser and loading the tests, and all
+the results will be reported on the command line just like for VM tests. In
+fact, you can even run tests on both platforms with a single command: <code>pub run test:test -p &quot;chrome,vm&quot; path/to/test.dart</code>.</p>
+<h3>Restricting Tests to Certain Platforms</h3>
+<p>Some test files only make sense to run on particular platforms. They may use
+<code>dart:html</code> or <code>dart:io</code>, they might test Windows' particular filesystem
+behavior, or they might use a feature that's only available in Chrome. The
+<a href="https://pub.dev/documentation/test_api/latest/test_api/TestOn-class.html"><code>@TestOn</code></a> annotation makes it easy to declare exactly which platforms
+a test file should run on. Just put it at the top of your file, before any
+<code>library</code> or <code>import</code> declarations:</p>
+<pre><code class="language-dart">@TestOn(&quot;vm&quot;)
+
+import &quot;dart:io&quot;;
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  // ...
+}
+</code></pre>
+<p>The string you pass to <code>@TestOn</code> is what's called a &quot;platform selector&quot;, and it
+specifies exactly which platforms a test can run on. It can be as simple as the
+name of a platform, or a more complex Dart-like boolean expression involving
+these platform names.</p>
+<h3>Platform Selector Syntax</h3>
+<p>Platform selectors can contain identifiers, parentheses, and operators. When
+loading a test, each identifier is set to <code>true</code> or <code>false</code> based on the current
+platform, and the test is only loaded if the platform selector returns <code>true</code>.
+The operators <code>||</code>, <code>&amp;&amp;</code>, <code>!</code>, and <code>? :</code> all work just like they do in Dart. The
+valid identifiers are:</p>
+<ul>
+<li>
+<p><code>vm</code>: Whether the test is running on the command-line Dart VM.</p>
+</li>
+<li>
+<p><code>dartium</code>: Whether the test is running on Dartium.</p>
+</li>
+<li>
+<p><code>content-shell</code>: Whether the test is running on the headless Dartium content
+shell.</p>
+</li>
+<li>
+<p><code>chrome</code>: Whether the test is running on Google Chrome.</p>
+</li>
+<li>
+<p><code>phantomjs</code>: Whether the test is running on
+<a href="http://phantomjs.org/">PhantomJS</a>.</p>
+</li>
+<li>
+<p><code>firefox</code>: Whether the test is running on Mozilla Firefox.</p>
+</li>
+<li>
+<p><code>safari</code>: Whether the test is running on Apple Safari.</p>
+</li>
+<li>
+<p><code>ie</code>: Whether the test is running on Microsoft Internet Explorer.</p>
+</li>
+<li>
+<p><code>dart-vm</code>: Whether the test is running on the Dart VM in any context,
+including Dartium. It's identical to <code>!js</code>.</p>
+</li>
+<li>
+<p><code>browser</code>: Whether the test is running in any browser.</p>
+</li>
+<li>
+<p><code>js</code>: Whether the test has been compiled to JS. This is identical to
+<code>!dart-vm</code>.</p>
+</li>
+<li>
+<p><code>blink</code>: Whether the test is running in a browser that uses the Blink
+rendering engine.</p>
+</li>
+<li>
+<p><code>windows</code>: Whether the test is running on Windows. If <code>vm</code> is false, this will
+be <code>false</code> as well.</p>
+</li>
+<li>
+<p><code>mac-os</code>: Whether the test is running on Mac OS. If <code>vm</code> is false, this will
+be <code>false</code> as well.</p>
+</li>
+<li>
+<p><code>linux</code>: Whether the test is running on Linux. If <code>vm</code> is false, this will be
+<code>false</code> as well.</p>
+</li>
+<li>
+<p><code>android</code>: Whether the test is running on Android. If <code>vm</code> is false, this will
+be <code>false</code> as well, which means that this <em>won't</em> be true if the test is
+running on an Android browser.</p>
+</li>
+<li>
+<p><code>posix</code>: Whether the test is running on a POSIX operating system. This is
+equivalent to <code>!windows</code>.</p>
+</li>
+</ul>
+<p>For example, if you wanted to run a test on every browser but Chrome, you would
+write <code>@TestOn(&quot;browser &amp;&amp; !chrome&quot;)</code>.</p>
+<h2>Asynchronous Tests</h2>
+<p>Tests written with <code>async</code>/<code>await</code> will work automatically. The test runner
+won't consider the test finished until the returned <code>Future</code> completes.</p>
+<pre><code class="language-dart">import &quot;dart:async&quot;;
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;new Future.value() returns the value&quot;, () async {
+    var value = await new Future.value(10);
+    expect(value, equals(10));
+  });
+}
+</code></pre>
+<p>There are also a number of useful functions and matchers for more advanced
+asynchrony. The <a href="https://pub.dev/documentation/test_api/latest/test_api/completion.html"><code>completion()</code></a> matcher can be used to test
+<code>Futures</code>; it ensures that the test doesn't finish until the <code>Future</code> completes,
+and runs a matcher against that <code>Future</code>'s value.</p>
+<pre><code class="language-dart">import &quot;dart:async&quot;;
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;new Future.value() returns the value&quot;, () {
+    expect(new Future.value(10), completion(equals(10)));
+  });
+}
+</code></pre>
+<p>The <a href="https://pub.dev/documentation/test_api/latest/test_api/throwsA.html"><code>throwsA()</code></a> matcher and the various <code>throwsExceptionType</code>
+matchers work with both synchronous callbacks and asynchronous <code>Future</code>s. They
+ensure that a particular type of exception is thrown:</p>
+<pre><code class="language-dart">import &quot;dart:async&quot;;
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;new Future.error() throws the error&quot;, () {
+    expect(new Future.error(&quot;oh no&quot;), throwsA(equals(&quot;oh no&quot;)));
+    expect(new Future.error(new StateError(&quot;bad state&quot;)), throwsStateError);
+  });
+}
+</code></pre>
+<p>The <a href="https://pub.dev/documentation/test_api/latest/test_api/expectAsync.html"><code>expectAsync()</code></a> function wraps another function and has two
+jobs. First, it asserts that the wrapped function is called a certain number of
+times, and will cause the test to fail if it's called too often; second, it
+keeps the test from finishing until the function is called the requisite number
+of times.</p>
+<pre><code class="language-dart">import &quot;dart:async&quot;;
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;Stream.fromIterable() emits the values in the iterable&quot;, () {
+    var stream = new Stream.fromIterable([1, 2, 3]);
+
+    stream.listen(expectAsync((number) {
+      expect(number, inInclusiveRange(1, 3));
+    }, count: 3));
+  });
+}
+</code></pre>
+<h2>Running Tests with Custom HTML</h2>
+<p>By default, the test runner will generate its own empty HTML file for browser
+tests. However, tests that need custom HTML can create their own files. These
+files have three requirements:</p>
+<ul>
+<li>
+<p>They must have the same name as the test, with <code>.dart</code> replaced by <code>.html</code>.</p>
+</li>
+<li>
+<p>They must contain a <code>link</code> tag with <code>rel=&quot;x-dart-test&quot;</code> and an <code>href</code>
+attribute pointing to the test script.</p>
+</li>
+<li>
+<p>They must contain <code>&lt;script src=&quot;packages/test/dart.js&quot;&gt;&lt;/script&gt;</code>.</p>
+</li>
+</ul>
+<p>For example, if you had a test called <code>custom_html_test.dart</code>, you might write
+the following HTML file:</p>
+<pre><code class="language-html">&lt;!doctype html&gt;
+&lt;!-- custom_html_test.html --&gt;
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;Custom HTML Test&lt;/title&gt;
+    &lt;link rel=&quot;x-dart-test&quot; href=&quot;custom_html_test.dart&quot;&gt;
+    &lt;script src=&quot;packages/test/dart.js&quot;&gt;&lt;/script&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+    // ...
+  &lt;/body&gt;
+&lt;/html&gt;
+</code></pre>
+<h2>Configuring Tests</h2>
+<h3>Skipping Tests</h3>
+<p>If a test, group, or entire suite isn't working yet and you just want it to stop
+complaining, you can mark it as &quot;skipped&quot;. The test or tests won't be run, and,
+if you supply a reason why, that reason will be printed. In general, skipping
+tests indicates that they should run but is temporarily not working. If they're
+is fundamentally incompatible with a platform, <a href="https://pub.dev/documentation/test_api/latest/test_api/TestOn-class.html"><code>@TestOn</code>/<code>testOn</code></a>
+should be used instead.</p>
+<p>To skip a test suite, put a <code>@Skip</code> annotation at the top of the file:</p>
+<pre><code class="language-dart">@Skip(&quot;currently failing (see issue 1234)&quot;)
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  // ...
+}
+</code></pre>
+<p>The string you pass should describe why the test is skipped. You don't have to
+include it, but it's a good idea to document why the test isn't running.</p>
+<p>Groups and individual tests can be skipped by passing the <code>skip</code> parameter. This
+can be either <code>true</code> or a String describing why the test is skipped. For example:</p>
+<pre><code class="language-dart">import &quot;package:test/test.dart&quot;;
+
+void main() {
+  group(&quot;complicated algorithm tests&quot;, () {
+    // ...
+  }, skip: &quot;the algorithm isn't quite right&quot;);
+
+  test(&quot;error-checking test&quot;, () {
+    // ...
+  }, skip: &quot;TODO: add error-checking.&quot;);
+}
+</code></pre>
+<h3>Timeouts</h3>
+<p>By default, tests will time out after 30 seconds of inactivity. However, this
+can be configured on a per-test, -group, or -suite basis. To change the timeout
+for a test suite, put a <code>@Timeout</code> annotation at the top of the file:</p>
+<pre><code class="language-dart">@Timeout(const Duration(seconds: 45))
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  // ...
+}
+</code></pre>
+<p>In addition to setting an absolute timeout, you can set the timeout relative to
+the default using <code>@Timeout.factor</code>. For example, <code>@Timeout.factor(1.5)</code> will
+set the timeout to one and a half times as long as the default—45 seconds.</p>
+<p>Timeouts can be set for tests and groups using the <code>timeout</code> parameter. This
+parameter takes a <code>Timeout</code> object just like the annotation. For example:</p>
+<pre><code class="language-dart">import &quot;package:test/test.dart&quot;;
+
+void main() {
+  group(&quot;slow tests&quot;, () {
+    // ...
+
+    test(&quot;even slower test&quot;, () {
+      // ...
+    }, timeout: new Timeout.factor(2))
+  }, timeout: new Timeout(new Duration(minutes: 1)));
+}
+</code></pre>
+<p>Nested timeouts apply in order from outermost to innermost. That means that
+&quot;even slower test&quot; will take two minutes to time out, since it multiplies the
+group's timeout by 2.</p>
+<h3>Platform-Specific Configuration</h3>
+<p>Sometimes a test may need to be configured differently for different platforms.
+Windows might run your code slower than other platforms, or your DOM
+manipulation might not work right on Safari yet. For these cases, you can use
+the <code>@OnPlatform</code> annotation and the <code>onPlatform</code> named parameter to <code>test()</code>
+and <code>group()</code>. For example:</p>
+<pre><code class="language-dart">@OnPlatform(const {
+  // Give Windows some extra wiggle-room before timing out.
+  &quot;windows&quot;: const Timeout.factor(2)
+})
+
+import &quot;package:test/test.dart&quot;;
+
+void main() {
+  test(&quot;do a thing&quot;, () {
+    // ...
+  }, onPlatform: {
+    &quot;safari&quot;: new Skip(&quot;Safari is currently broken (see #1234)&quot;)
+  });
+}
+</code></pre>
+<p>Both the annotation and the parameter take a map. The map's keys are <a href="#platform-selector-syntax">platform
+selectors</a> which describe the platforms for which the
+specialized configuration applies. Its values are instances of some of the same
+annotation classes that can be used for a suite: <code>Skip</code> and <code>Timeout</code>. A value
+can also be a list of these values.</p>
+<p>If multiple platforms match, the configuration is applied in order from first to
+last, just as they would in nested groups. This means that for configuration
+like duration-based timeouts, the last matching value wins.</p>
diff --git a/pkgs/markdown/bin/markdown.dart b/pkgs/markdown/bin/markdown.dart
new file mode 100644
index 0000000..76926c6
--- /dev/null
+++ b/pkgs/markdown/bin/markdown.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:markdown/markdown.dart';
+
+final extensionSets = <String, ExtensionSet>{
+  'none': ExtensionSet.none,
+  'CommonMark': ExtensionSet.commonMark,
+  'GitHubFlavored': ExtensionSet.gitHubFlavored,
+  'GitHubWeb': ExtensionSet.gitHubWeb,
+};
+
+Future<void> main(List<String> args) async {
+  final parser = ArgParser()
+    ..addFlag('help', negatable: false, help: 'Print help text and exit')
+    ..addFlag('version', negatable: false, help: 'Print version and exit')
+    ..addOption(
+      'extension-set',
+      allowed: ['none', 'CommonMark', 'GitHubFlavored', 'GitHubWeb'],
+      defaultsTo: 'CommonMark',
+      help: 'Specify a set of extensions',
+      allowedHelp: {
+        'none': 'No extensions; similar to Markdown.pl',
+        'CommonMark': 'Parse like CommonMark Markdown (default)',
+        'GitHubFlavored': 'Parse like GitHub Flavored Markdown',
+        'GitHubWeb': 'Parse like GitHub\'s Markdown-enabled web input fields',
+      },
+    );
+  final results = parser.parse(args);
+
+  if (results['help'] as bool) {
+    printUsage(parser);
+    return;
+  }
+
+  if (results['version'] as bool) {
+    print(version);
+    return;
+  }
+
+  final extensionSet = extensionSets[results['extension-set']];
+
+  if (results.rest.length > 1) {
+    printUsage(parser);
+    exitCode = 1;
+    return;
+  }
+
+  if (results.rest.length == 1) {
+    // Read argument as a file path.
+    final input = File(results.rest.first).readAsStringSync();
+    print(markdownToHtml(input, extensionSet: extensionSet));
+    return;
+  }
+
+  // Read from stdin.
+  final buffer = StringBuffer();
+  String? line;
+  while ((line = stdin.readLineSync()) != null) {
+    buffer.writeln(line);
+  }
+  print(markdownToHtml(buffer.toString(), extensionSet: extensionSet));
+}
+
+void printUsage(ArgParser parser) {
+  print('''Usage: markdown.dart [options] [file]
+
+Parse [file] as Markdown and print resulting HTML. If [file] is omitted,
+use stdin as input.
+
+By default, CommonMark Markdown will be parsed. This can be changed with
+the --extensionSet flag.
+
+${parser.usage}
+''');
+}
diff --git a/pkgs/markdown/dart_test.yaml b/pkgs/markdown/dart_test.yaml
new file mode 100644
index 0000000..588b409
--- /dev/null
+++ b/pkgs/markdown/dart_test.yaml
@@ -0,0 +1,6 @@
+tags:
+  crash_test:
+    skip: 'Only run crash_test tests manually with `dart test -P crash_test`'
+    presets:
+      crash_test:
+        skip: false # Don't skip when running in -P crash_test
diff --git a/pkgs/markdown/example/app.dart b/pkgs/markdown/example/app.dart
new file mode 100644
index 0000000..14b8f19
--- /dev/null
+++ b/pkgs/markdown/example/app.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:async';
+import 'dart:js_interop';
+
+import 'package:markdown/markdown.dart' as md;
+import 'package:web/web.dart';
+
+import 'highlight.dart';
+
+final markdownInput =
+    document.querySelector('#markdown') as HTMLTextAreaElement;
+final htmlDiv = document.querySelector('#html') as HTMLDivElement;
+final versionSpan = document.querySelector('.version') as HTMLSpanElement;
+
+const typing = Duration(milliseconds: 150);
+const introText = '''Markdown is the **best**!
+
+* It has lists.
+* It has [links](https://dart.dev).
+* It has...
+  ```dart
+  void sourceCode() {}
+  ```
+* ...and _so much more_...''';
+
+// Flavor support.
+final basicRadio = document.querySelector('#basic-radio') as HTMLElement;
+final commonmarkRadio =
+    document.querySelector('#commonmark-radio') as HTMLElement;
+final gfmRadio = document.querySelector('#gfm-radio') as HTMLElement;
+md.ExtensionSet? extensionSet;
+
+final extensionSets = {
+  'basic-radio': md.ExtensionSet.none,
+  'commonmark-radio': md.ExtensionSet.commonMark,
+  'gfm-radio': md.ExtensionSet.gitHubWeb,
+};
+
+void main() {
+  versionSpan.text = 'v${md.version}';
+  markdownInput.onKeyUp.listen(_renderMarkdown);
+
+  final savedMarkdown = window.localStorage['markdown'];
+
+  if (savedMarkdown != null &&
+      savedMarkdown.isNotEmpty &&
+      savedMarkdown != introText) {
+    markdownInput.value = savedMarkdown;
+    markdownInput.focus();
+    _renderMarkdown();
+  } else {
+    _typeItOut(introText, 82);
+  }
+
+  // GitHub is the default extension set.
+  gfmRadio.attributes.getNamedItem('checked')?.value = '';
+  gfmRadio.querySelector('.glyph')!.text = 'radio_button_checked';
+  extensionSet = extensionSets[gfmRadio.id];
+  _renderMarkdown();
+
+  basicRadio.onClick.listen(_switchFlavor);
+  commonmarkRadio.onClick.listen(_switchFlavor);
+  gfmRadio.onClick.listen(_switchFlavor);
+}
+
+void _renderMarkdown([Event? event]) {
+  final markdown = markdownInput.value;
+
+  htmlDiv.innerHtml = md.markdownToHtml(markdown, extensionSet: extensionSet);
+
+  for (final block in htmlDiv.querySelectorAll('pre code').items) {
+    try {
+      highlightElement(block);
+    } catch (e) {
+      console.error('Error highlighting markdown:'.toJS);
+      console.error(e.toString().toJS);
+    }
+  }
+
+  if (event != null) {
+    // Not simulated typing. Store it.
+    window.localStorage['markdown'] = markdown;
+  }
+}
+
+void _typeItOut(String msg, int pos) {
+  late Timer timer;
+  markdownInput.onKeyUp.listen((_) {
+    timer.cancel();
+  });
+  void addCharacter() {
+    if (pos > msg.length) {
+      return;
+    }
+    markdownInput.value = msg.substring(0, pos);
+    markdownInput.focus();
+    _renderMarkdown();
+    pos++;
+    timer = Timer(typing, addCharacter);
+  }
+
+  timer = Timer(typing, addCharacter);
+}
+
+void _switchFlavor(Event e) {
+  final target = e.currentTarget as HTMLElement;
+  if (target.attributes.getNamedItem('checked') == null) {
+    if (basicRadio != target) {
+      basicRadio.attributes.safeRemove('checked');
+      basicRadio.querySelector('.glyph')!.text = 'radio_button_unchecked';
+    }
+    if (commonmarkRadio != target) {
+      commonmarkRadio.attributes.safeRemove('checked');
+      commonmarkRadio.querySelector('.glyph')!.text = 'radio_button_unchecked';
+    }
+    if (gfmRadio != target) {
+      gfmRadio.attributes.safeRemove('checked');
+      gfmRadio.querySelector('.glyph')!.text = 'radio_button_unchecked';
+    }
+
+    target.attributes.getNamedItem('checked')?.value = '';
+    target.querySelector('.glyph')!.text = 'radio_button_checked';
+    extensionSet = extensionSets[target.id];
+    _renderMarkdown();
+  }
+}
+
+extension on NodeList {
+  List<Node> get items => [
+        for (var i = 0; i < length; i++) item(i)!,
+      ];
+}
+
+extension on NamedNodeMap {
+  void safeRemove(String qualifiedName) {
+    if (getNamedItem(qualifiedName) != null) removeNamedItem(qualifiedName);
+  }
+}
+
+extension on HTMLDivElement {
+  // The default implementation allows `JSAny` to support trusted types. We only
+  // use `String`s, so prefer this to avoid manual conversions.
+  @JS('innerHTML')
+  external set innerHtml(String value);
+}
diff --git a/pkgs/markdown/example/favicon.png b/pkgs/markdown/example/favicon.png
new file mode 100644
index 0000000..43d2ffa
--- /dev/null
+++ b/pkgs/markdown/example/favicon.png
Binary files differ
diff --git a/pkgs/markdown/example/highlight.dart b/pkgs/markdown/example/highlight.dart
new file mode 100644
index 0000000..b54c447
--- /dev/null
+++ b/pkgs/markdown/example/highlight.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+@JS('hljs')
+library;
+
+import 'dart:js_interop';
+
+import 'package:web/web.dart';
+
+@JS()
+external void highlightElement(Node block);
diff --git a/pkgs/markdown/example/index.html b/pkgs/markdown/example/index.html
new file mode 100644
index 0000000..82650a6
--- /dev/null
+++ b/pkgs/markdown/example/index.html
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <link rel="icon" sizes="64x64" href="favicon.png">
+    <link rel="stylesheet" href="style.css">
+    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono|Roboto">
+    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons+Extended">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown-light.min.css" integrity="sha512-zb2pp+R+czM7GAemdSUQt6jFmr3qCo6ikvBgVU6F5GvwEDR0C2sefFiPEJ9QUpmAKdD5EqDUdNRtbOYnbF/eyQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js" integrity="sha512-yUUc0qWm2rhM7X0EFe82LNnv2moqArj5nro/w1bi05A09hRVeIZbN6jlMoyu0+4I/Bu4Ck/85JQIU82T82M28w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/dart.min.js" integrity="sha512-14QR6tzX5xTNeMJKXzSK+xCquDvtNEr1jM5NlKy/149BBY50Kv70qqxHtzo6zClbtc1gIG7G0CGWXuMgPIMt0g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+    <script defer src="app.dart.js"></script>
+    <title>Dart Markdown Live Editor</title>
+    <style>
+.gfm-color_chip span {
+  display: inline-block;
+  line-height: 1;
+  margin: 0 0 2px 4px;
+  vertical-align: middle;
+  border-radius: 3px;
+  width: 0.9em;
+  height: 0.9em;
+  background: #fff;
+}
+
+code.gfm-color_chip {
+  padding: 2px 4px;
+  color: #1f1f1f;
+  background-color: #f0f0f0;
+  border-radius: 4px;
+}
+
+ul.contains-task-list, ol.contains-task-list {
+  margin-left: -1em;
+  list-style-type: none;
+}
+
+.task-list-item {
+  list-style-type: none;
+}
+    </style>
+  </head>
+  <body>
+    <div class="container">
+      <header>
+        <div class="toolbar">
+          <h2>Dart Markdown Live Editor</h2>
+          <span style="display: flex; flex: 1;"></span>
+          <span class="version"></span>
+          <a href="https://github.com/dart-lang/markdown" title="Open Source on GitHub">
+            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="32" height="32">
+              <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
+            </svg>
+          </a>
+        </div>
+      </header>
+      <div class="main">
+        <div class="card">
+          <div class="toolbar">
+            <h2>Markdown</h2>
+          </div>
+          <div style="padding: 8px; display: flex; height: 100%;">
+            <textarea id="markdown"></textarea>
+          </div>
+        </div>
+        <div class="card">
+          <div class="toolbar">
+            <h2>HTML</h2>
+          </div>
+          <div id="html" class="markdown-body"></div>
+        </div>
+      </div>
+      <footer>
+        <span style="margin-right: 16px;">Markdown Flavor:</span>
+        <div class="radio" id="basic-radio">
+          <i class="glyph">radio_button_unchecked</i>
+          Basic Markdown
+        </div>
+        <div class="radio" id="commonmark-radio">
+          <i class="glyph">radio_button_unchecked</i>
+          CommonMark
+        </div>
+        <div class="radio" id="gfm-radio">
+          <i class="glyph">radio_button_unchecked</i>
+          GitHub Flavored Markdown
+        </div>
+        <span style="display: flex; flex: 1;"></span>
+        <a href="https://github.com/dart-lang/markdown#extension-sets"
+           target="_blank"
+           title="More info">
+          <i class="big glyph">help</i>
+        </a>
+      </footer>
+    </div>
+  </body>
+</html>
diff --git a/pkgs/markdown/example/style.css b/pkgs/markdown/example/style.css
new file mode 100644
index 0000000..bfacfb0
--- /dev/null
+++ b/pkgs/markdown/example/style.css
@@ -0,0 +1,152 @@
+html, body {
+  background-color: rgb(250, 250, 250);
+  font-family: Roboto,"Helvetica Neue",sans-serif;
+  font-size: 16px;
+  margin: 0;
+}
+
+.container {
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  width: 100%;
+}
+
+.main {
+  align-items: stretch;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: row;
+  height: 100%;
+  margin: 32px;
+}
+
+.version {
+  color: rgba(0, 0, 0, 0.54);
+  margin-right: 16px;
+}
+
+.card {
+  /* Styled like Material Cards. */
+  color: rgba(0, 0, 0, 0.87);
+  background-color: white;
+  border-radius: 2px;
+  box-sizing: border-box;
+  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .2),
+              0 1px 1px 0 rgba(0, 0, 0, .14),
+              0 2px 1px -1px rgba(0, 0, 0, .12);
+  margin: 8px;
+
+  /* Positioned next to each other. */
+  display: flex;
+  flex: 1 1 50%;
+  flex-direction: column;
+  max-height: 100%;
+  max-width: 50%;
+  min-height: 400px;
+}
+
+.toolbar {
+  /* Styled like Material Toolbar. */
+  align-items: center;
+  background-color: #22d3c5;
+  box-sizing: border-box;
+  color: rgba(0, 0, 0, 0.87);
+  display: flex;
+  font-size: 20px;
+  line-height: 1.4;
+  margin: 0;
+  min-height: 64px;
+  padding: 0 16px;
+  position: relative;
+  width: 100%;
+}
+
+.toolbar h2 {
+  font-size: inherit;
+  font-weight: inherit;
+  margin: inherit;
+}
+
+.toolbar a:link,
+.toolbar a:visited {
+  color: rgba(0, 0, 0, 0.87);
+}
+
+.toolbar svg {
+  fill: currentColor;
+}
+
+.card .toolbar {
+  border-radius: 3px 3px 0 0;
+}
+
+.textarea-container {
+  display: flex;
+  height: 100%;
+  padding: 8px;
+}
+
+textarea {
+  border-color: rgba(0, 0, 0, 0.12);
+  border-width: 0 0 1px;
+  box-sizing: border-box;
+  color: rgba(0, 0, 0, 0.87);
+  font-family: "Roboto Mono",monospace;
+  font-size: 100%;
+  line-height: 26px;
+  overflow: auto;
+  padding: 2px 2px 1px;
+  width: 100%;
+}
+
+textarea:focus {
+  border-color: #22d3c5;
+  border-width: 0 0 2px;
+  outline: 0;
+  padding-bottom: 0;
+}
+
+#html {
+  overflow: auto;
+  padding: 8px;
+}
+
+footer {
+  box-sizing: border-box;
+  display: flex;
+  font-size: 20px;
+  height: 64px;
+  padding: 0 16px;
+}
+
+footer a:link,
+footer a:visited {
+  color: rgba(0, 0, 0, 0.87);
+}
+
+.radio {
+  cursor: pointer;
+  display: inline-block;
+  margin-right: 16px;
+}
+
+i.glyph {
+  display: inline-block;
+  font-family: 'Material Icons Extended';
+  font-size: 16px;
+  font-style: normal;
+  font-weight: normal;
+  line-height: 1;
+}
+
+.radio[checked] i.glyph {
+  color: #22d3c5;
+}
+
+i.glyph.big {
+  font-size: 32px;
+  height: 32px;
+  width: 32px;
+}
diff --git a/pkgs/markdown/lib/markdown.dart b/pkgs/markdown/lib/markdown.dart
new file mode 100644
index 0000000..9fac732
--- /dev/null
+++ b/pkgs/markdown/lib/markdown.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+/// Parses text in a Markdown-like format building an
+/// [AST tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree)
+/// that can then be rendered to HTML.
+///
+/// If you are only interested in rendering Markdown to HTML please refer
+/// to the [README](../index.html) which explains the use of [markdownToHtml].
+///
+/// The main entrypoint to the library is the [Document] which
+/// encapsulates the parsing process converting a Markdown text into
+/// a tree of [Node] (`List<Node>`).
+///
+/// The two main parsing mechanics used are:
+///
+/// - Blocks, representing top-level elements
+///   implemented via [BlockSyntax] subclasses,
+///   such as headers, paragraphs, blockquotes, and code blocks.
+/// - Inlines, representing chunks of text within a block with special meaning,
+///   implemented via [InlineSyntax] subclasses,
+///   such as links, emphasis, and inlined code.
+///
+/// Looking closely at [Document.new] a few other concepts merit a mention:
+///
+/// - [ExtensionSet] that provide configurations for common Markdown flavors
+/// - [Resolver] which aid in resolving links and images
+///
+/// If you are looking at extending the library to support custom formatting
+/// what you might want is to:
+///
+/// - Implement your own [InlineSyntax] subclasses
+/// - Implement your own [BlockSyntax] subclasses
+/// - Instruct the library to use those by:
+///   - Creating a new [ExtensionSet] from one of the existing flavors
+///     and adding your syntaxes.
+///   - Passing your syntaxes to [Document] or [markdownToHtml] as parameters.
+library;
+
+import 'src/version.dart';
+
+export 'src/ast.dart';
+export 'src/block_parser.dart';
+export 'src/block_syntaxes/alert_block_syntax.dart';
+export 'src/block_syntaxes/block_syntax.dart';
+export 'src/block_syntaxes/blockquote_syntax.dart';
+export 'src/block_syntaxes/code_block_syntax.dart';
+export 'src/block_syntaxes/dummy_block_syntax.dart';
+export 'src/block_syntaxes/empty_block_syntax.dart';
+export 'src/block_syntaxes/fenced_blockquote_syntax.dart';
+export 'src/block_syntaxes/fenced_code_block_syntax.dart';
+export 'src/block_syntaxes/footnote_def_syntax.dart';
+export 'src/block_syntaxes/header_syntax.dart';
+export 'src/block_syntaxes/header_with_id_syntax.dart';
+export 'src/block_syntaxes/horizontal_rule_syntax.dart';
+export 'src/block_syntaxes/html_block_syntax.dart';
+export 'src/block_syntaxes/link_reference_definition_syntax.dart';
+export 'src/block_syntaxes/list_syntax.dart';
+export 'src/block_syntaxes/ordered_list_syntax.dart';
+export 'src/block_syntaxes/ordered_list_with_checkbox_syntax.dart';
+export 'src/block_syntaxes/paragraph_syntax.dart';
+export 'src/block_syntaxes/setext_header_syntax.dart';
+export 'src/block_syntaxes/setext_header_with_id_syntax.dart';
+export 'src/block_syntaxes/table_syntax.dart';
+export 'src/block_syntaxes/unordered_list_syntax.dart';
+export 'src/block_syntaxes/unordered_list_with_checkbox_syntax.dart';
+export 'src/document.dart';
+export 'src/emojis.dart';
+export 'src/extension_set.dart';
+export 'src/html_renderer.dart';
+export 'src/inline_parser.dart';
+export 'src/inline_syntaxes/autolink_extension_syntax.dart';
+export 'src/inline_syntaxes/autolink_syntax.dart';
+export 'src/inline_syntaxes/code_syntax.dart';
+export 'src/inline_syntaxes/color_swatch_syntax.dart';
+export 'src/inline_syntaxes/decode_html_syntax.dart';
+export 'src/inline_syntaxes/delimiter_syntax.dart';
+export 'src/inline_syntaxes/email_autolink_syntax.dart';
+export 'src/inline_syntaxes/emoji_syntax.dart';
+export 'src/inline_syntaxes/emphasis_syntax.dart';
+export 'src/inline_syntaxes/escape_html_syntax.dart';
+export 'src/inline_syntaxes/escape_syntax.dart';
+export 'src/inline_syntaxes/image_syntax.dart';
+export 'src/inline_syntaxes/inline_html_syntax.dart';
+export 'src/inline_syntaxes/inline_syntax.dart';
+export 'src/inline_syntaxes/line_break_syntax.dart';
+export 'src/inline_syntaxes/link_syntax.dart';
+export 'src/inline_syntaxes/soft_line_break_syntax.dart';
+export 'src/inline_syntaxes/strikethrough_syntax.dart';
+export 'src/inline_syntaxes/text_syntax.dart';
+export 'src/line.dart';
+
+const version = packageVersion;
diff --git a/pkgs/markdown/lib/src/assets/case_folding.dart b/pkgs/markdown/lib/src/assets/case_folding.dart
new file mode 100644
index 0000000..09081aa
--- /dev/null
+++ b/pkgs/markdown/lib/src/assets/case_folding.dart
@@ -0,0 +1,1316 @@
+// Generated file. do not edit.
+//
+// Source: tool/case_folding.txt
+// Script: tool/update_case_folding.dart
+// ignore_for_file: prefer_single_quotes
+
+const caseFoldingMap = {
+  "A": "a",
+  "B": "b",
+  "C": "c",
+  "D": "d",
+  "E": "e",
+  "F": "f",
+  "G": "g",
+  "H": "h",
+  "I": "i",
+  "J": "j",
+  "K": "k",
+  "L": "l",
+  "M": "m",
+  "N": "n",
+  "O": "o",
+  "P": "p",
+  "Q": "q",
+  "R": "r",
+  "S": "s",
+  "T": "t",
+  "U": "u",
+  "V": "v",
+  "W": "w",
+  "X": "x",
+  "Y": "y",
+  "Z": "z",
+  "À": "à",
+  "Á": "á",
+  "Â": "â",
+  "Ã": "ã",
+  "Ä": "ä",
+  "Å": "å",
+  "Æ": "æ",
+  "Ç": "ç",
+  "È": "è",
+  "É": "é",
+  "Ê": "ê",
+  "Ë": "ë",
+  "Ì": "ì",
+  "Í": "í",
+  "Î": "î",
+  "Ï": "ï",
+  "Ð": "ð",
+  "Ñ": "ñ",
+  "Ò": "ò",
+  "Ó": "ó",
+  "Ô": "ô",
+  "Õ": "õ",
+  "Ö": "ö",
+  "Ø": "ø",
+  "Ù": "ù",
+  "Ú": "ú",
+  "Û": "û",
+  "Ü": "ü",
+  "Ý": "ý",
+  "Þ": "þ",
+  "Ā": "ā",
+  "Ă": "ă",
+  "Ą": "ą",
+  "Ć": "ć",
+  "Ĉ": "ĉ",
+  "Ċ": "ċ",
+  "Č": "č",
+  "Ď": "ď",
+  "Đ": "đ",
+  "Ē": "ē",
+  "Ĕ": "ĕ",
+  "Ė": "ė",
+  "Ę": "ę",
+  "Ě": "ě",
+  "Ĝ": "ĝ",
+  "Ğ": "ğ",
+  "Ġ": "ġ",
+  "Ģ": "ģ",
+  "Ĥ": "ĥ",
+  "Ħ": "ħ",
+  "Ĩ": "ĩ",
+  "Ī": "ī",
+  "Ĭ": "ĭ",
+  "Į": "į",
+  "İ": "i̇",
+  "Ĵ": "ĵ",
+  "Ķ": "ķ",
+  "Ĺ": "ĺ",
+  "Ļ": "ļ",
+  "Ľ": "ľ",
+  "Ŀ": "ŀ",
+  "Ł": "ł",
+  "Ń": "ń",
+  "Ņ": "ņ",
+  "Ň": "ň",
+  "Ŋ": "ŋ",
+  "Ō": "ō",
+  "Ŏ": "ŏ",
+  "Ő": "ő",
+  "Ŕ": "ŕ",
+  "Ŗ": "ŗ",
+  "Ř": "ř",
+  "Ś": "ś",
+  "Ŝ": "ŝ",
+  "Ş": "ş",
+  "Š": "š",
+  "Ţ": "ţ",
+  "Ť": "ť",
+  "Ŧ": "ŧ",
+  "Ũ": "ũ",
+  "Ū": "ū",
+  "Ŭ": "ŭ",
+  "Ů": "ů",
+  "Ű": "ű",
+  "Ų": "ų",
+  "Ŵ": "ŵ",
+  "Ŷ": "ŷ",
+  "Ÿ": "ÿ",
+  "Ź": "ź",
+  "Ż": "ż",
+  "Ž": "ž",
+  "Ɓ": "ɓ",
+  "Ƃ": "ƃ",
+  "Ƅ": "ƅ",
+  "Ɔ": "ɔ",
+  "Ƈ": "ƈ",
+  "Ɖ": "ɖ",
+  "Ɗ": "ɗ",
+  "Ƌ": "ƌ",
+  "Ǝ": "ǝ",
+  "Ə": "ə",
+  "Ɛ": "ɛ",
+  "Ƒ": "ƒ",
+  "Ɠ": "ɠ",
+  "Ɣ": "ɣ",
+  "Ɩ": "ɩ",
+  "Ɨ": "ɨ",
+  "Ƙ": "ƙ",
+  "Ɯ": "ɯ",
+  "Ɲ": "ɲ",
+  "Ɵ": "ɵ",
+  "Ơ": "ơ",
+  "Ƣ": "ƣ",
+  "Ƥ": "ƥ",
+  "Ƨ": "ƨ",
+  "Ʃ": "ʃ",
+  "Ƭ": "ƭ",
+  "Ʈ": "ʈ",
+  "Ư": "ư",
+  "Ʊ": "ʊ",
+  "Ʋ": "ʋ",
+  "Ƴ": "ƴ",
+  "Ƶ": "ƶ",
+  "Ʒ": "ʒ",
+  "Ƹ": "ƹ",
+  "Ƽ": "ƽ",
+  "DŽ": "dž",
+  "Dž": "dž",
+  "LJ": "lj",
+  "Lj": "lj",
+  "NJ": "nj",
+  "Nj": "nj",
+  "Ǎ": "ǎ",
+  "Ǐ": "ǐ",
+  "Ǒ": "ǒ",
+  "Ǔ": "ǔ",
+  "Ǖ": "ǖ",
+  "Ǘ": "ǘ",
+  "Ǚ": "ǚ",
+  "Ǜ": "ǜ",
+  "Ǟ": "ǟ",
+  "Ǡ": "ǡ",
+  "Ǣ": "ǣ",
+  "Ǥ": "ǥ",
+  "Ǧ": "ǧ",
+  "Ǩ": "ǩ",
+  "Ǫ": "ǫ",
+  "Ǭ": "ǭ",
+  "Ǯ": "ǯ",
+  "DZ": "dz",
+  "Dz": "dz",
+  "Ǵ": "ǵ",
+  "Ƕ": "ƕ",
+  "Ƿ": "ƿ",
+  "Ǹ": "ǹ",
+  "Ǻ": "ǻ",
+  "Ǽ": "ǽ",
+  "Ǿ": "ǿ",
+  "Ȁ": "ȁ",
+  "Ȃ": "ȃ",
+  "Ȅ": "ȅ",
+  "Ȇ": "ȇ",
+  "Ȉ": "ȉ",
+  "Ȋ": "ȋ",
+  "Ȍ": "ȍ",
+  "Ȏ": "ȏ",
+  "Ȑ": "ȑ",
+  "Ȓ": "ȓ",
+  "Ȕ": "ȕ",
+  "Ȗ": "ȗ",
+  "Ș": "ș",
+  "Ț": "ț",
+  "Ȝ": "ȝ",
+  "Ȟ": "ȟ",
+  "Ƞ": "ƞ",
+  "Ȣ": "ȣ",
+  "Ȥ": "ȥ",
+  "Ȧ": "ȧ",
+  "Ȩ": "ȩ",
+  "Ȫ": "ȫ",
+  "Ȭ": "ȭ",
+  "Ȯ": "ȯ",
+  "Ȱ": "ȱ",
+  "Ȳ": "ȳ",
+  "Ⱥ": "ⱥ",
+  "Ȼ": "ȼ",
+  "Ƚ": "ƚ",
+  "Ⱦ": "ⱦ",
+  "Ɂ": "ɂ",
+  "Ƀ": "ƀ",
+  "Ʉ": "ʉ",
+  "Ʌ": "ʌ",
+  "Ɇ": "ɇ",
+  "Ɉ": "ɉ",
+  "Ɋ": "ɋ",
+  "Ɍ": "ɍ",
+  "Ɏ": "ɏ",
+  "Ͱ": "ͱ",
+  "Ͳ": "ͳ",
+  "Ͷ": "ͷ",
+  "Ϳ": "ϳ",
+  "Ά": "ά",
+  "Έ": "έ",
+  "Ή": "ή",
+  "Ί": "ί",
+  "Ό": "ό",
+  "Ύ": "ύ",
+  "Ώ": "ώ",
+  "Α": "α",
+  "Β": "β",
+  "Γ": "γ",
+  "Δ": "δ",
+  "Ε": "ε",
+  "Ζ": "ζ",
+  "Η": "η",
+  "Θ": "θ",
+  "Ι": "ι",
+  "Κ": "κ",
+  "Λ": "λ",
+  "Μ": "μ",
+  "Ν": "ν",
+  "Ξ": "ξ",
+  "Ο": "ο",
+  "Π": "π",
+  "Ρ": "ρ",
+  "Σ": "σ",
+  "Τ": "τ",
+  "Υ": "υ",
+  "Φ": "φ",
+  "Χ": "χ",
+  "Ψ": "ψ",
+  "Ω": "ω",
+  "Ϊ": "ϊ",
+  "Ϋ": "ϋ",
+  "Ϣ": "ϣ",
+  "Ϥ": "ϥ",
+  "Ϧ": "ϧ",
+  "Ϩ": "ϩ",
+  "Ϫ": "ϫ",
+  "Ϭ": "ϭ",
+  "Ϯ": "ϯ",
+  "Ϸ": "ϸ",
+  "Ϻ": "ϻ",
+  "Ѐ": "ѐ",
+  "Ё": "ё",
+  "Ђ": "ђ",
+  "Ѓ": "ѓ",
+  "Є": "є",
+  "Ѕ": "ѕ",
+  "І": "і",
+  "Ї": "ї",
+  "Ј": "ј",
+  "Љ": "љ",
+  "Њ": "њ",
+  "Ћ": "ћ",
+  "Ќ": "ќ",
+  "Ѝ": "ѝ",
+  "Ў": "ў",
+  "Џ": "џ",
+  "А": "а",
+  "Б": "б",
+  "В": "в",
+  "Г": "г",
+  "Д": "д",
+  "Е": "е",
+  "Ж": "ж",
+  "З": "з",
+  "И": "и",
+  "Й": "й",
+  "К": "к",
+  "Л": "л",
+  "М": "м",
+  "Н": "н",
+  "О": "о",
+  "П": "п",
+  "Р": "р",
+  "С": "с",
+  "Т": "т",
+  "У": "у",
+  "Ф": "ф",
+  "Х": "х",
+  "Ц": "ц",
+  "Ч": "ч",
+  "Ш": "ш",
+  "Щ": "щ",
+  "Ъ": "ъ",
+  "Ы": "ы",
+  "Ь": "ь",
+  "Э": "э",
+  "Ю": "ю",
+  "Я": "я",
+  "Ѡ": "ѡ",
+  "Ѣ": "ѣ",
+  "Ѥ": "ѥ",
+  "Ѧ": "ѧ",
+  "Ѩ": "ѩ",
+  "Ѫ": "ѫ",
+  "Ѭ": "ѭ",
+  "Ѯ": "ѯ",
+  "Ѱ": "ѱ",
+  "Ѳ": "ѳ",
+  "Ѵ": "ѵ",
+  "Ѷ": "ѷ",
+  "Ѹ": "ѹ",
+  "Ѻ": "ѻ",
+  "Ѽ": "ѽ",
+  "Ѿ": "ѿ",
+  "Ҁ": "ҁ",
+  "Ҋ": "ҋ",
+  "Ҍ": "ҍ",
+  "Ҏ": "ҏ",
+  "Ґ": "ґ",
+  "Ғ": "ғ",
+  "Ҕ": "ҕ",
+  "Җ": "җ",
+  "Ҙ": "ҙ",
+  "Қ": "қ",
+  "Ҝ": "ҝ",
+  "Ҟ": "ҟ",
+  "Ҡ": "ҡ",
+  "Ң": "ң",
+  "Ҧ": "ҧ",
+  "Ҩ": "ҩ",
+  "Ҫ": "ҫ",
+  "Ҭ": "ҭ",
+  "Ү": "ү",
+  "Ұ": "ұ",
+  "Ҳ": "ҳ",
+  "Ҷ": "ҷ",
+  "Ҹ": "ҹ",
+  "Һ": "һ",
+  "Ҽ": "ҽ",
+  "Ҿ": "ҿ",
+  "Ӂ": "ӂ",
+  "Ӄ": "ӄ",
+  "Ӆ": "ӆ",
+  "Ӈ": "ӈ",
+  "Ӊ": "ӊ",
+  "Ӌ": "ӌ",
+  "Ӎ": "ӎ",
+  "Ӑ": "ӑ",
+  "Ӓ": "ӓ",
+  "Ӗ": "ӗ",
+  "Ә": "ә",
+  "Ӛ": "ӛ",
+  "Ӝ": "ӝ",
+  "Ӟ": "ӟ",
+  "Ӡ": "ӡ",
+  "Ӣ": "ӣ",
+  "Ӥ": "ӥ",
+  "Ӧ": "ӧ",
+  "Ө": "ө",
+  "Ӫ": "ӫ",
+  "Ӭ": "ӭ",
+  "Ӯ": "ӯ",
+  "Ӱ": "ӱ",
+  "Ӳ": "ӳ",
+  "Ӵ": "ӵ",
+  "Ӷ": "ӷ",
+  "Ӹ": "ӹ",
+  "Ӻ": "ӻ",
+  "Ӽ": "ӽ",
+  "Ӿ": "ӿ",
+  "Ԁ": "ԁ",
+  "Ԃ": "ԃ",
+  "Ԅ": "ԅ",
+  "Ԇ": "ԇ",
+  "Ԉ": "ԉ",
+  "Ԋ": "ԋ",
+  "Ԍ": "ԍ",
+  "Ԏ": "ԏ",
+  "Ԑ": "ԑ",
+  "Ԓ": "ԓ",
+  "Ԕ": "ԕ",
+  "Ԗ": "ԗ",
+  "Ԙ": "ԙ",
+  "Ԛ": "ԛ",
+  "Ԝ": "ԝ",
+  "Ԟ": "ԟ",
+  "Ԡ": "ԡ",
+  "Ԣ": "ԣ",
+  "Ԥ": "ԥ",
+  "Ԧ": "ԧ",
+  "Ԩ": "ԩ",
+  "Ԫ": "ԫ",
+  "Ԭ": "ԭ",
+  "Ԯ": "ԯ",
+  "Ա": "ա",
+  "Բ": "բ",
+  "Գ": "գ",
+  "Դ": "դ",
+  "Ե": "ե",
+  "Զ": "զ",
+  "Է": "է",
+  "Ը": "ը",
+  "Թ": "թ",
+  "Ժ": "ժ",
+  "Ի": "ի",
+  "Լ": "լ",
+  "Խ": "խ",
+  "Ծ": "ծ",
+  "Կ": "կ",
+  "Հ": "հ",
+  "Ձ": "ձ",
+  "Ղ": "ղ",
+  "Ճ": "ճ",
+  "Մ": "մ",
+  "Յ": "յ",
+  "Ն": "ն",
+  "Շ": "շ",
+  "Ո": "ո",
+  "Չ": "չ",
+  "Պ": "պ",
+  "Ջ": "ջ",
+  "Ռ": "ռ",
+  "Ս": "ս",
+  "Վ": "վ",
+  "Տ": "տ",
+  "Ր": "ր",
+  "Ց": "ց",
+  "Ւ": "ւ",
+  "Փ": "փ",
+  "Ք": "ք",
+  "Օ": "օ",
+  "Ֆ": "ֆ",
+  "Ⴀ": "ⴀ",
+  "Ⴁ": "ⴁ",
+  "Ⴂ": "ⴂ",
+  "Ⴃ": "ⴃ",
+  "Ⴄ": "ⴄ",
+  "Ⴅ": "ⴅ",
+  "Ⴆ": "ⴆ",
+  "Ⴇ": "ⴇ",
+  "Ⴈ": "ⴈ",
+  "Ⴉ": "ⴉ",
+  "Ⴊ": "ⴊ",
+  "Ⴋ": "ⴋ",
+  "Ⴌ": "ⴌ",
+  "Ⴍ": "ⴍ",
+  "Ⴎ": "ⴎ",
+  "Ⴏ": "ⴏ",
+  "Ⴐ": "ⴐ",
+  "Ⴑ": "ⴑ",
+  "Ⴒ": "ⴒ",
+  "Ⴓ": "ⴓ",
+  "Ⴔ": "ⴔ",
+  "Ⴕ": "ⴕ",
+  "Ⴖ": "ⴖ",
+  "Ⴗ": "ⴗ",
+  "Ⴘ": "ⴘ",
+  "Ⴙ": "ⴙ",
+  "Ⴚ": "ⴚ",
+  "Ⴛ": "ⴛ",
+  "Ⴜ": "ⴜ",
+  "Ⴝ": "ⴝ",
+  "Ⴞ": "ⴞ",
+  "Ⴟ": "ⴟ",
+  "Ⴠ": "ⴠ",
+  "Ⴡ": "ⴡ",
+  "Ⴢ": "ⴢ",
+  "Ⴣ": "ⴣ",
+  "Ⴤ": "ⴤ",
+  "Ⴥ": "ⴥ",
+  "Ⴧ": "ⴧ",
+  "Ⴭ": "ⴭ",
+  "Ა": "ა",
+  "Ბ": "ბ",
+  "Გ": "გ",
+  "Დ": "დ",
+  "Ე": "ე",
+  "Ვ": "ვ",
+  "Ზ": "ზ",
+  "Თ": "თ",
+  "Ი": "ი",
+  "Კ": "კ",
+  "Ლ": "ლ",
+  "Მ": "მ",
+  "Ნ": "ნ",
+  "Ო": "ო",
+  "Პ": "პ",
+  "Ჟ": "ჟ",
+  "Რ": "რ",
+  "Ს": "ს",
+  "Ტ": "ტ",
+  "Უ": "უ",
+  "Ფ": "ფ",
+  "Ქ": "ქ",
+  "Ღ": "ღ",
+  "Ყ": "ყ",
+  "Შ": "შ",
+  "Ჩ": "ჩ",
+  "Ც": "ც",
+  "Ძ": "ძ",
+  "Წ": "წ",
+  "Ჭ": "ჭ",
+  "Ხ": "ხ",
+  "Ჯ": "ჯ",
+  "Ჰ": "ჰ",
+  "Ჱ": "ჱ",
+  "Ჲ": "ჲ",
+  "Ჳ": "ჳ",
+  "Ჴ": "ჴ",
+  "Ჵ": "ჵ",
+  "Ჶ": "ჶ",
+  "Ჷ": "ჷ",
+  "Ჸ": "ჸ",
+  "Ჹ": "ჹ",
+  "Ჺ": "ჺ",
+  "Ჽ": "ჽ",
+  "Ჾ": "ჾ",
+  "Ჿ": "ჿ",
+  "Ḁ": "ḁ",
+  "Ḃ": "ḃ",
+  "Ḅ": "ḅ",
+  "Ḇ": "ḇ",
+  "Ḉ": "ḉ",
+  "Ḋ": "ḋ",
+  "Ḍ": "ḍ",
+  "Ḏ": "ḏ",
+  "Ḑ": "ḑ",
+  "Ḓ": "ḓ",
+  "Ḕ": "ḕ",
+  "Ḗ": "ḗ",
+  "Ḙ": "ḙ",
+  "Ḛ": "ḛ",
+  "Ḝ": "ḝ",
+  "Ḟ": "ḟ",
+  "Ḡ": "ḡ",
+  "Ḣ": "ḣ",
+  "Ḥ": "ḥ",
+  "Ḧ": "ḧ",
+  "Ḩ": "ḩ",
+  "Ḫ": "ḫ",
+  "Ḭ": "ḭ",
+  "Ḯ": "ḯ",
+  "Ḱ": "ḱ",
+  "Ḳ": "ḳ",
+  "Ḵ": "ḵ",
+  "Ḷ": "ḷ",
+  "Ḹ": "ḹ",
+  "Ḻ": "ḻ",
+  "Ḽ": "ḽ",
+  "Ḿ": "ḿ",
+  "Ṁ": "ṁ",
+  "Ṃ": "ṃ",
+  "Ṅ": "ṅ",
+  "Ṇ": "ṇ",
+  "Ṉ": "ṉ",
+  "Ṋ": "ṋ",
+  "Ṍ": "ṍ",
+  "Ṏ": "ṏ",
+  "Ṑ": "ṑ",
+  "Ṓ": "ṓ",
+  "Ṕ": "ṕ",
+  "Ṗ": "ṗ",
+  "Ṙ": "ṙ",
+  "Ṛ": "ṛ",
+  "Ṝ": "ṝ",
+  "Ṟ": "ṟ",
+  "Ṡ": "ṡ",
+  "Ṣ": "ṣ",
+  "Ṥ": "ṥ",
+  "Ṧ": "ṧ",
+  "Ṩ": "ṩ",
+  "Ṫ": "ṫ",
+  "Ṭ": "ṭ",
+  "Ṯ": "ṯ",
+  "Ṱ": "ṱ",
+  "Ṳ": "ṳ",
+  "Ṵ": "ṵ",
+  "Ṷ": "ṷ",
+  "Ṹ": "ṹ",
+  "Ṻ": "ṻ",
+  "Ṽ": "ṽ",
+  "Ṿ": "ṿ",
+  "Ẁ": "ẁ",
+  "Ẃ": "ẃ",
+  "Ẅ": "ẅ",
+  "Ẇ": "ẇ",
+  "Ẉ": "ẉ",
+  "Ẋ": "ẋ",
+  "Ẍ": "ẍ",
+  "Ẏ": "ẏ",
+  "Ẑ": "ẑ",
+  "Ẓ": "ẓ",
+  "Ẕ": "ẕ",
+  "ẞ": "ss",
+  "Ạ": "ạ",
+  "Ả": "ả",
+  "Ấ": "ấ",
+  "Ầ": "ầ",
+  "Ẩ": "ẩ",
+  "Ẫ": "ẫ",
+  "Ậ": "ậ",
+  "Ắ": "ắ",
+  "Ằ": "ằ",
+  "Ẳ": "ẳ",
+  "Ẵ": "ẵ",
+  "Ặ": "ặ",
+  "Ẹ": "ẹ",
+  "Ẻ": "ẻ",
+  "Ẽ": "ẽ",
+  "Ế": "ế",
+  "Ề": "ề",
+  "Ể": "ể",
+  "Ễ": "ễ",
+  "Ệ": "ệ",
+  "Ỉ": "ỉ",
+  "Ị": "ị",
+  "Ọ": "ọ",
+  "Ỏ": "ỏ",
+  "Ố": "ố",
+  "Ồ": "ồ",
+  "Ổ": "ổ",
+  "Ỗ": "ỗ",
+  "Ộ": "ộ",
+  "Ớ": "ớ",
+  "Ờ": "ờ",
+  "Ở": "ở",
+  "Ỡ": "ỡ",
+  "Ợ": "ợ",
+  "Ụ": "ụ",
+  "Ủ": "ủ",
+  "Ứ": "ứ",
+  "Ừ": "ừ",
+  "Ử": "ử",
+  "Ữ": "ữ",
+  "Ự": "ự",
+  "Ỳ": "ỳ",
+  "Ỵ": "ỵ",
+  "Ỷ": "ỷ",
+  "Ỹ": "ỹ",
+  "Ỻ": "ỻ",
+  "Ỽ": "ỽ",
+  "Ỿ": "ỿ",
+  "Ἀ": "ἀ",
+  "Ἁ": "ἁ",
+  "Ἂ": "ἂ",
+  "Ἃ": "ἃ",
+  "Ἄ": "ἄ",
+  "Ἅ": "ἅ",
+  "Ἆ": "ἆ",
+  "Ἇ": "ἇ",
+  "Ἐ": "ἐ",
+  "Ἑ": "ἑ",
+  "Ἒ": "ἒ",
+  "Ἓ": "ἓ",
+  "Ἔ": "ἔ",
+  "Ἕ": "ἕ",
+  "Ἠ": "ἠ",
+  "Ἡ": "ἡ",
+  "Ἢ": "ἢ",
+  "Ἣ": "ἣ",
+  "Ἤ": "ἤ",
+  "Ἥ": "ἥ",
+  "Ἦ": "ἦ",
+  "Ἧ": "ἧ",
+  "Ἰ": "ἰ",
+  "Ἱ": "ἱ",
+  "Ἲ": "ἲ",
+  "Ἳ": "ἳ",
+  "Ἴ": "ἴ",
+  "Ἵ": "ἵ",
+  "Ἶ": "ἶ",
+  "Ἷ": "ἷ",
+  "Ὀ": "ὀ",
+  "Ὁ": "ὁ",
+  "Ὂ": "ὂ",
+  "Ὃ": "ὃ",
+  "Ὄ": "ὄ",
+  "Ὅ": "ὅ",
+  "Ὑ": "ὑ",
+  "Ὓ": "ὓ",
+  "Ὕ": "ὕ",
+  "Ὗ": "ὗ",
+  "Ὠ": "ὠ",
+  "Ὡ": "ὡ",
+  "Ὢ": "ὢ",
+  "Ὣ": "ὣ",
+  "Ὤ": "ὤ",
+  "Ὥ": "ὥ",
+  "Ὦ": "ὦ",
+  "Ὧ": "ὧ",
+  "ᾈ": "ἀι",
+  "ᾉ": "ἁι",
+  "ᾊ": "ἂι",
+  "ᾋ": "ἃι",
+  "ᾌ": "ἄι",
+  "ᾍ": "ἅι",
+  "ᾎ": "ἆι",
+  "ᾏ": "ἇι",
+  "ᾘ": "ἠι",
+  "ᾙ": "ἡι",
+  "ᾚ": "ἢι",
+  "ᾛ": "ἣι",
+  "ᾜ": "ἤι",
+  "ᾝ": "ἥι",
+  "ᾞ": "ἦι",
+  "ᾟ": "ἧι",
+  "ᾨ": "ὠι",
+  "ᾩ": "ὡι",
+  "ᾪ": "ὢι",
+  "ᾫ": "ὣι",
+  "ᾬ": "ὤι",
+  "ᾭ": "ὥι",
+  "ᾮ": "ὦι",
+  "ᾯ": "ὧι",
+  "Ᾰ": "ᾰ",
+  "Ᾱ": "ᾱ",
+  "Ὰ": "ὰ",
+  "Ά": "ά",
+  "ᾼ": "αι",
+  "Ὲ": "ὲ",
+  "Έ": "έ",
+  "Ὴ": "ὴ",
+  "Ή": "ή",
+  "ῌ": "ηι",
+  "Ῐ": "ῐ",
+  "Ῑ": "ῑ",
+  "Ὶ": "ὶ",
+  "Ί": "ί",
+  "Ῠ": "ῠ",
+  "Ῡ": "ῡ",
+  "Ὺ": "ὺ",
+  "Ύ": "ύ",
+  "Ῥ": "ῥ",
+  "Ὸ": "ὸ",
+  "Ό": "ό",
+  "Ὼ": "ὼ",
+  "Ώ": "ώ",
+  "ῼ": "ωι",
+  "Ⓐ": "ⓐ",
+  "Ⓑ": "ⓑ",
+  "Ⓒ": "ⓒ",
+  "Ⓓ": "ⓓ",
+  "Ⓔ": "ⓔ",
+  "Ⓕ": "ⓕ",
+  "Ⓖ": "ⓖ",
+  "Ⓗ": "ⓗ",
+  "Ⓘ": "ⓘ",
+  "Ⓙ": "ⓙ",
+  "Ⓚ": "ⓚ",
+  "Ⓛ": "ⓛ",
+  "Ⓜ": "ⓜ",
+  "Ⓝ": "ⓝ",
+  "Ⓞ": "ⓞ",
+  "Ⓟ": "ⓟ",
+  "Ⓠ": "ⓠ",
+  "Ⓡ": "ⓡ",
+  "Ⓢ": "ⓢ",
+  "Ⓣ": "ⓣ",
+  "Ⓤ": "ⓤ",
+  "Ⓥ": "ⓥ",
+  "Ⓦ": "ⓦ",
+  "Ⓧ": "ⓧ",
+  "Ⓨ": "ⓨ",
+  "Ⓩ": "ⓩ",
+  "Ⰰ": "ⰰ",
+  "Ⰱ": "ⰱ",
+  "Ⰲ": "ⰲ",
+  "Ⰳ": "ⰳ",
+  "Ⰴ": "ⰴ",
+  "Ⰵ": "ⰵ",
+  "Ⰶ": "ⰶ",
+  "Ⰷ": "ⰷ",
+  "Ⰸ": "ⰸ",
+  "Ⰹ": "ⰹ",
+  "Ⰺ": "ⰺ",
+  "Ⰻ": "ⰻ",
+  "Ⰼ": "ⰼ",
+  "Ⰽ": "ⰽ",
+  "Ⰾ": "ⰾ",
+  "Ⰿ": "ⰿ",
+  "Ⱀ": "ⱀ",
+  "Ⱁ": "ⱁ",
+  "Ⱂ": "ⱂ",
+  "Ⱃ": "ⱃ",
+  "Ⱄ": "ⱄ",
+  "Ⱅ": "ⱅ",
+  "Ⱆ": "ⱆ",
+  "Ⱇ": "ⱇ",
+  "Ⱈ": "ⱈ",
+  "Ⱉ": "ⱉ",
+  "Ⱊ": "ⱊ",
+  "Ⱋ": "ⱋ",
+  "Ⱌ": "ⱌ",
+  "Ⱍ": "ⱍ",
+  "Ⱎ": "ⱎ",
+  "Ⱏ": "ⱏ",
+  "Ⱐ": "ⱐ",
+  "Ⱑ": "ⱑ",
+  "Ⱒ": "ⱒ",
+  "Ⱓ": "ⱓ",
+  "Ⱔ": "ⱔ",
+  "Ⱕ": "ⱕ",
+  "Ⱖ": "ⱖ",
+  "Ⱗ": "ⱗ",
+  "Ⱘ": "ⱘ",
+  "Ⱙ": "ⱙ",
+  "Ⱚ": "ⱚ",
+  "Ⱛ": "ⱛ",
+  "Ⱜ": "ⱜ",
+  "Ⱝ": "ⱝ",
+  "Ⱞ": "ⱞ",
+  "Ⱟ": "ⱟ",
+  "Ⱡ": "ⱡ",
+  "Ɫ": "ɫ",
+  "Ᵽ": "ᵽ",
+  "Ɽ": "ɽ",
+  "Ⱨ": "ⱨ",
+  "Ⱪ": "ⱪ",
+  "Ⱬ": "ⱬ",
+  "Ɑ": "ɑ",
+  "Ɱ": "ɱ",
+  "Ɐ": "ɐ",
+  "Ɒ": "ɒ",
+  "Ⱳ": "ⱳ",
+  "Ⱶ": "ⱶ",
+  "Ȿ": "ȿ",
+  "Ɀ": "ɀ",
+  "Ⲁ": "ⲁ",
+  "Ⲃ": "ⲃ",
+  "Ⲅ": "ⲅ",
+  "Ⲇ": "ⲇ",
+  "Ⲉ": "ⲉ",
+  "Ⲋ": "ⲋ",
+  "Ⲍ": "ⲍ",
+  "Ⲏ": "ⲏ",
+  "Ⲑ": "ⲑ",
+  "Ⲓ": "ⲓ",
+  "Ⲕ": "ⲕ",
+  "Ⲗ": "ⲗ",
+  "Ⲙ": "ⲙ",
+  "Ⲛ": "ⲛ",
+  "Ⲝ": "ⲝ",
+  "Ⲟ": "ⲟ",
+  "Ⲡ": "ⲡ",
+  "Ⲣ": "ⲣ",
+  "Ⲥ": "ⲥ",
+  "Ⲧ": "ⲧ",
+  "Ⲩ": "ⲩ",
+  "Ⲫ": "ⲫ",
+  "Ⲭ": "ⲭ",
+  "Ⲯ": "ⲯ",
+  "Ⲱ": "ⲱ",
+  "Ⲳ": "ⲳ",
+  "Ⲵ": "ⲵ",
+  "Ⲷ": "ⲷ",
+  "Ⲹ": "ⲹ",
+  "Ⲻ": "ⲻ",
+  "Ⲽ": "ⲽ",
+  "Ⲿ": "ⲿ",
+  "Ⳁ": "ⳁ",
+  "Ⳃ": "ⳃ",
+  "Ⳅ": "ⳅ",
+  "Ⳇ": "ⳇ",
+  "Ⳉ": "ⳉ",
+  "Ⳋ": "ⳋ",
+  "Ⳍ": "ⳍ",
+  "Ⳏ": "ⳏ",
+  "Ⳑ": "ⳑ",
+  "Ⳓ": "ⳓ",
+  "Ⳕ": "ⳕ",
+  "Ⳗ": "ⳗ",
+  "Ⳙ": "ⳙ",
+  "Ⳛ": "ⳛ",
+  "Ⳝ": "ⳝ",
+  "Ⳟ": "ⳟ",
+  "Ⳡ": "ⳡ",
+  "Ⳣ": "ⳣ",
+  "Ⳬ": "ⳬ",
+  "Ⳮ": "ⳮ",
+  "Ⳳ": "ⳳ",
+  "Ꙁ": "ꙁ",
+  "Ꙃ": "ꙃ",
+  "Ꙅ": "ꙅ",
+  "Ꙇ": "ꙇ",
+  "Ꙉ": "ꙉ",
+  "Ꙋ": "ꙋ",
+  "Ꙍ": "ꙍ",
+  "Ꙏ": "ꙏ",
+  "Ꙑ": "ꙑ",
+  "Ꙓ": "ꙓ",
+  "Ꙕ": "ꙕ",
+  "Ꙗ": "ꙗ",
+  "Ꙙ": "ꙙ",
+  "Ꙛ": "ꙛ",
+  "Ꙝ": "ꙝ",
+  "Ꙟ": "ꙟ",
+  "Ꙡ": "ꙡ",
+  "Ꙣ": "ꙣ",
+  "Ꙥ": "ꙥ",
+  "Ꙧ": "ꙧ",
+  "Ꙩ": "ꙩ",
+  "Ꙫ": "ꙫ",
+  "Ꙭ": "ꙭ",
+  "Ꚁ": "ꚁ",
+  "Ꚃ": "ꚃ",
+  "Ꚅ": "ꚅ",
+  "Ꚇ": "ꚇ",
+  "Ꚉ": "ꚉ",
+  "Ꚋ": "ꚋ",
+  "Ꚍ": "ꚍ",
+  "Ꚏ": "ꚏ",
+  "Ꚑ": "ꚑ",
+  "Ꚓ": "ꚓ",
+  "Ꚕ": "ꚕ",
+  "Ꚗ": "ꚗ",
+  "Ꚙ": "ꚙ",
+  "Ꚛ": "ꚛ",
+  "Ꜣ": "ꜣ",
+  "Ꜥ": "ꜥ",
+  "Ꜧ": "ꜧ",
+  "Ꜩ": "ꜩ",
+  "Ꜫ": "ꜫ",
+  "Ꜭ": "ꜭ",
+  "Ꜯ": "ꜯ",
+  "Ꜳ": "ꜳ",
+  "Ꜵ": "ꜵ",
+  "Ꜷ": "ꜷ",
+  "Ꜹ": "ꜹ",
+  "Ꜻ": "ꜻ",
+  "Ꜽ": "ꜽ",
+  "Ꜿ": "ꜿ",
+  "Ꝁ": "ꝁ",
+  "Ꝃ": "ꝃ",
+  "Ꝅ": "ꝅ",
+  "Ꝇ": "ꝇ",
+  "Ꝉ": "ꝉ",
+  "Ꝋ": "ꝋ",
+  "Ꝍ": "ꝍ",
+  "Ꝏ": "ꝏ",
+  "Ꝑ": "ꝑ",
+  "Ꝓ": "ꝓ",
+  "Ꝕ": "ꝕ",
+  "Ꝗ": "ꝗ",
+  "Ꝙ": "ꝙ",
+  "Ꝛ": "ꝛ",
+  "Ꝝ": "ꝝ",
+  "Ꝟ": "ꝟ",
+  "Ꝡ": "ꝡ",
+  "Ꝣ": "ꝣ",
+  "Ꝥ": "ꝥ",
+  "Ꝧ": "ꝧ",
+  "Ꝩ": "ꝩ",
+  "Ꝫ": "ꝫ",
+  "Ꝭ": "ꝭ",
+  "Ꝯ": "ꝯ",
+  "Ꝺ": "ꝺ",
+  "Ꝼ": "ꝼ",
+  "Ᵹ": "ᵹ",
+  "Ꝿ": "ꝿ",
+  "Ꞁ": "ꞁ",
+  "Ꞃ": "ꞃ",
+  "Ꞅ": "ꞅ",
+  "Ꞇ": "ꞇ",
+  "Ꞌ": "ꞌ",
+  "Ɥ": "ɥ",
+  "Ꞑ": "ꞑ",
+  "Ꞓ": "ꞓ",
+  "Ꞗ": "ꞗ",
+  "Ꞙ": "ꞙ",
+  "Ꞛ": "ꞛ",
+  "Ꞝ": "ꞝ",
+  "Ꞟ": "ꞟ",
+  "Ꞡ": "ꞡ",
+  "Ꞣ": "ꞣ",
+  "Ꞥ": "ꞥ",
+  "Ꞧ": "ꞧ",
+  "Ꞩ": "ꞩ",
+  "Ɦ": "ɦ",
+  "Ɜ": "ɜ",
+  "Ɡ": "ɡ",
+  "Ɬ": "ɬ",
+  "Ɪ": "ɪ",
+  "Ʞ": "ʞ",
+  "Ʇ": "ʇ",
+  "Ʝ": "ʝ",
+  "Ꭓ": "ꭓ",
+  "Ꞵ": "ꞵ",
+  "Ꞷ": "ꞷ",
+  "Ꞹ": "ꞹ",
+  "Ꞻ": "ꞻ",
+  "Ꞽ": "ꞽ",
+  "Ꞿ": "ꞿ",
+  "Ꟁ": "ꟁ",
+  "Ꟃ": "ꟃ",
+  "Ꞔ": "ꞔ",
+  "Ʂ": "ʂ",
+  "Ᶎ": "ᶎ",
+  "Ꟈ": "ꟈ",
+  "Ꟊ": "ꟊ",
+  "Ꟑ": "ꟑ",
+  "Ꟗ": "ꟗ",
+  "Ꟙ": "ꟙ",
+  "Ꟶ": "ꟶ",
+  "A": "a",
+  "B": "b",
+  "C": "c",
+  "D": "d",
+  "E": "e",
+  "F": "f",
+  "G": "g",
+  "H": "h",
+  "I": "i",
+  "J": "j",
+  "K": "k",
+  "L": "l",
+  "M": "m",
+  "N": "n",
+  "O": "o",
+  "P": "p",
+  "Q": "q",
+  "R": "r",
+  "S": "s",
+  "T": "t",
+  "U": "u",
+  "V": "v",
+  "W": "w",
+  "X": "x",
+  "Y": "y",
+  "Z": "z",
+  "𐐀": "𐐨",
+  "𐐁": "𐐩",
+  "𐐂": "𐐪",
+  "𐐃": "𐐫",
+  "𐐄": "𐐬",
+  "𐐅": "𐐭",
+  "𐐆": "𐐮",
+  "𐐇": "𐐯",
+  "𐐈": "𐐰",
+  "𐐉": "𐐱",
+  "𐐊": "𐐲",
+  "𐐋": "𐐳",
+  "𐐌": "𐐴",
+  "𐐍": "𐐵",
+  "𐐎": "𐐶",
+  "𐐏": "𐐷",
+  "𐐐": "𐐸",
+  "𐐑": "𐐹",
+  "𐐒": "𐐺",
+  "𐐓": "𐐻",
+  "𐐔": "𐐼",
+  "𐐕": "𐐽",
+  "𐐖": "𐐾",
+  "𐐗": "𐐿",
+  "𐐘": "𐑀",
+  "𐐙": "𐑁",
+  "𐐚": "𐑂",
+  "𐐛": "𐑃",
+  "𐐜": "𐑄",
+  "𐐝": "𐑅",
+  "𐐞": "𐑆",
+  "𐐟": "𐑇",
+  "𐐠": "𐑈",
+  "𐐡": "𐑉",
+  "𐐢": "𐑊",
+  "𐐣": "𐑋",
+  "𐐤": "𐑌",
+  "𐐥": "𐑍",
+  "𐐦": "𐑎",
+  "𐐧": "𐑏",
+  "𐒰": "𐓘",
+  "𐒱": "𐓙",
+  "𐒲": "𐓚",
+  "𐒳": "𐓛",
+  "𐒴": "𐓜",
+  "𐒵": "𐓝",
+  "𐒶": "𐓞",
+  "𐒷": "𐓟",
+  "𐒸": "𐓠",
+  "𐒹": "𐓡",
+  "𐒺": "𐓢",
+  "𐒻": "𐓣",
+  "𐒼": "𐓤",
+  "𐒽": "𐓥",
+  "𐒾": "𐓦",
+  "𐒿": "𐓧",
+  "𐓀": "𐓨",
+  "𐓁": "𐓩",
+  "𐓂": "𐓪",
+  "𐓃": "𐓫",
+  "𐓄": "𐓬",
+  "𐓅": "𐓭",
+  "𐓆": "𐓮",
+  "𐓇": "𐓯",
+  "𐓈": "𐓰",
+  "𐓉": "𐓱",
+  "𐓊": "𐓲",
+  "𐓋": "𐓳",
+  "𐓌": "𐓴",
+  "𐓍": "𐓵",
+  "𐓎": "𐓶",
+  "𐓏": "𐓷",
+  "𐓐": "𐓸",
+  "𐓑": "𐓹",
+  "𐓒": "𐓺",
+  "𐓓": "𐓻",
+  "𐕰": "𐖗",
+  "𐕱": "𐖘",
+  "𐕲": "𐖙",
+  "𐕳": "𐖚",
+  "𐕴": "𐖛",
+  "𐕵": "𐖜",
+  "𐕶": "𐖝",
+  "𐕷": "𐖞",
+  "𐕸": "𐖟",
+  "𐕹": "𐖠",
+  "𐕺": "𐖡",
+  "𐕼": "𐖣",
+  "𐕽": "𐖤",
+  "𐕾": "𐖥",
+  "𐕿": "𐖦",
+  "𐖀": "𐖧",
+  "𐖁": "𐖨",
+  "𐖂": "𐖩",
+  "𐖃": "𐖪",
+  "𐖄": "𐖫",
+  "𐖅": "𐖬",
+  "𐖆": "𐖭",
+  "𐖇": "𐖮",
+  "𐖈": "𐖯",
+  "𐖉": "𐖰",
+  "𐖊": "𐖱",
+  "𐖌": "𐖳",
+  "𐖍": "𐖴",
+  "𐖎": "𐖵",
+  "𐖏": "𐖶",
+  "𐖐": "𐖷",
+  "𐖑": "𐖸",
+  "𐖒": "𐖹",
+  "𐖔": "𐖻",
+  "𐖕": "𐖼",
+  "𐲀": "𐳀",
+  "𐲁": "𐳁",
+  "𐲂": "𐳂",
+  "𐲃": "𐳃",
+  "𐲄": "𐳄",
+  "𐲅": "𐳅",
+  "𐲆": "𐳆",
+  "𐲇": "𐳇",
+  "𐲈": "𐳈",
+  "𐲉": "𐳉",
+  "𐲊": "𐳊",
+  "𐲋": "𐳋",
+  "𐲌": "𐳌",
+  "𐲍": "𐳍",
+  "𐲎": "𐳎",
+  "𐲏": "𐳏",
+  "𐲐": "𐳐",
+  "𐲑": "𐳑",
+  "𐲒": "𐳒",
+  "𐲓": "𐳓",
+  "𐲔": "𐳔",
+  "𐲕": "𐳕",
+  "𐲖": "𐳖",
+  "𐲗": "𐳗",
+  "𐲘": "𐳘",
+  "𐲙": "𐳙",
+  "𐲚": "𐳚",
+  "𐲛": "𐳛",
+  "𐲜": "𐳜",
+  "𐲝": "𐳝",
+  "𐲞": "𐳞",
+  "𐲟": "𐳟",
+  "𐲠": "𐳠",
+  "𐲡": "𐳡",
+  "𐲢": "𐳢",
+  "𐲣": "𐳣",
+  "𐲤": "𐳤",
+  "𐲥": "𐳥",
+  "𐲦": "𐳦",
+  "𐲧": "𐳧",
+  "𐲨": "𐳨",
+  "𐲩": "𐳩",
+  "𐲪": "𐳪",
+  "𐲫": "𐳫",
+  "𐲬": "𐳬",
+  "𐲭": "𐳭",
+  "𐲮": "𐳮",
+  "𐲯": "𐳯",
+  "𐲰": "𐳰",
+  "𐲱": "𐳱",
+  "𐲲": "𐳲",
+  "𑢠": "𑣀",
+  "𑢡": "𑣁",
+  "𑢢": "𑣂",
+  "𑢣": "𑣃",
+  "𑢤": "𑣄",
+  "𑢥": "𑣅",
+  "𑢦": "𑣆",
+  "𑢧": "𑣇",
+  "𑢨": "𑣈",
+  "𑢩": "𑣉",
+  "𑢪": "𑣊",
+  "𑢫": "𑣋",
+  "𑢬": "𑣌",
+  "𑢭": "𑣍",
+  "𑢮": "𑣎",
+  "𑢯": "𑣏",
+  "𑢰": "𑣐",
+  "𑢱": "𑣑",
+  "𑢲": "𑣒",
+  "𑢳": "𑣓",
+  "𑢴": "𑣔",
+  "𑢵": "𑣕",
+  "𑢶": "𑣖",
+  "𑢷": "𑣗",
+  "𑢸": "𑣘",
+  "𑢹": "𑣙",
+  "𑢺": "𑣚",
+  "𑢻": "𑣛",
+  "𑢼": "𑣜",
+  "𑢽": "𑣝",
+  "𑢾": "𑣞",
+  "𑢿": "𑣟",
+  "𖹀": "𖹠",
+  "𖹁": "𖹡",
+  "𖹂": "𖹢",
+  "𖹃": "𖹣",
+  "𖹄": "𖹤",
+  "𖹅": "𖹥",
+  "𖹆": "𖹦",
+  "𖹇": "𖹧",
+  "𖹈": "𖹨",
+  "𖹉": "𖹩",
+  "𖹊": "𖹪",
+  "𖹋": "𖹫",
+  "𖹌": "𖹬",
+  "𖹍": "𖹭",
+  "𖹎": "𖹮",
+  "𖹏": "𖹯",
+  "𖹐": "𖹰",
+  "𖹑": "𖹱",
+  "𖹒": "𖹲",
+  "𖹓": "𖹳",
+  "𖹔": "𖹴",
+  "𖹕": "𖹵",
+  "𖹖": "𖹶",
+  "𖹗": "𖹷",
+  "𖹘": "𖹸",
+  "𖹙": "𖹹",
+  "𖹚": "𖹺",
+  "𖹛": "𖹻",
+  "𖹜": "𖹼",
+  "𖹝": "𖹽",
+  "𖹞": "𖹾",
+  "𖹟": "𖹿",
+  "𞤀": "𞤢",
+  "𞤁": "𞤣",
+  "𞤂": "𞤤",
+  "𞤃": "𞤥",
+  "𞤄": "𞤦",
+  "𞤅": "𞤧",
+  "𞤆": "𞤨",
+  "𞤇": "𞤩",
+  "𞤈": "𞤪",
+  "𞤉": "𞤫",
+  "𞤊": "𞤬",
+  "𞤋": "𞤭",
+  "𞤌": "𞤮",
+  "𞤍": "𞤯",
+  "𞤎": "𞤰",
+  "𞤏": "𞤱",
+  "𞤐": "𞤲",
+  "𞤑": "𞤳",
+  "𞤒": "𞤴",
+  "𞤓": "𞤵",
+  "𞤔": "𞤶",
+  "𞤕": "𞤷",
+  "𞤖": "𞤸",
+  "𞤗": "𞤹",
+  "𞤘": "𞤺",
+  "𞤙": "𞤻",
+  "𞤚": "𞤼",
+  "𞤛": "𞤽",
+  "𞤜": "𞤾",
+  "𞤝": "𞤿",
+  "𞤞": "𞥀",
+  "𞤟": "𞥁",
+  "𞤠": "𞥂",
+  "𞤡": "𞥃"
+};
diff --git a/pkgs/markdown/lib/src/assets/html_entities.dart b/pkgs/markdown/lib/src/assets/html_entities.dart
new file mode 100644
index 0000000..2599762
--- /dev/null
+++ b/pkgs/markdown/lib/src/assets/html_entities.dart
@@ -0,0 +1,2133 @@
+// Generated file. do not edit.
+//
+// Source: tool/entities.json
+// Script: tool/update_entities.dart
+// ignore_for_file: prefer_single_quotes
+
+const htmlEntitiesMap = {
+  "&AElig;": "Æ",
+  "&AMP;": "&",
+  "&Aacute;": "Á",
+  "&Abreve;": "Ă",
+  "&Acirc;": "Â",
+  "&Acy;": "А",
+  "&Afr;": "𝔄",
+  "&Agrave;": "À",
+  "&Alpha;": "Α",
+  "&Amacr;": "Ā",
+  "&And;": "⩓",
+  "&Aogon;": "Ą",
+  "&Aopf;": "𝔸",
+  "&ApplyFunction;": "⁡",
+  "&Aring;": "Å",
+  "&Ascr;": "𝒜",
+  "&Assign;": "≔",
+  "&Atilde;": "Ã",
+  "&Auml;": "Ä",
+  "&Backslash;": "∖",
+  "&Barv;": "⫧",
+  "&Barwed;": "⌆",
+  "&Bcy;": "Б",
+  "&Because;": "∵",
+  "&Bernoullis;": "ℬ",
+  "&Beta;": "Β",
+  "&Bfr;": "𝔅",
+  "&Bopf;": "𝔹",
+  "&Breve;": "˘",
+  "&Bscr;": "ℬ",
+  "&Bumpeq;": "≎",
+  "&CHcy;": "Ч",
+  "&COPY;": "©",
+  "&Cacute;": "Ć",
+  "&Cap;": "⋒",
+  "&CapitalDifferentialD;": "ⅅ",
+  "&Cayleys;": "ℭ",
+  "&Ccaron;": "Č",
+  "&Ccedil;": "Ç",
+  "&Ccirc;": "Ĉ",
+  "&Cconint;": "∰",
+  "&Cdot;": "Ċ",
+  "&Cedilla;": "¸",
+  "&CenterDot;": "·",
+  "&Cfr;": "ℭ",
+  "&Chi;": "Χ",
+  "&CircleDot;": "⊙",
+  "&CircleMinus;": "⊖",
+  "&CirclePlus;": "⊕",
+  "&CircleTimes;": "⊗",
+  "&ClockwiseContourIntegral;": "∲",
+  "&CloseCurlyDoubleQuote;": "”",
+  "&CloseCurlyQuote;": "’",
+  "&Colon;": "∷",
+  "&Colone;": "⩴",
+  "&Congruent;": "≡",
+  "&Conint;": "∯",
+  "&ContourIntegral;": "∮",
+  "&Copf;": "ℂ",
+  "&Coproduct;": "∐",
+  "&CounterClockwiseContourIntegral;": "∳",
+  "&Cross;": "⨯",
+  "&Cscr;": "𝒞",
+  "&Cup;": "⋓",
+  "&CupCap;": "≍",
+  "&DD;": "ⅅ",
+  "&DDotrahd;": "⤑",
+  "&DJcy;": "Ђ",
+  "&DScy;": "Ѕ",
+  "&DZcy;": "Џ",
+  "&Dagger;": "‡",
+  "&Darr;": "↡",
+  "&Dashv;": "⫤",
+  "&Dcaron;": "Ď",
+  "&Dcy;": "Д",
+  "&Del;": "∇",
+  "&Delta;": "Δ",
+  "&Dfr;": "𝔇",
+  "&DiacriticalAcute;": "´",
+  "&DiacriticalDot;": "˙",
+  "&DiacriticalDoubleAcute;": "˝",
+  "&DiacriticalGrave;": "`",
+  "&DiacriticalTilde;": "˜",
+  "&Diamond;": "⋄",
+  "&DifferentialD;": "ⅆ",
+  "&Dopf;": "𝔻",
+  "&Dot;": "¨",
+  "&DotDot;": "⃜",
+  "&DotEqual;": "≐",
+  "&DoubleContourIntegral;": "∯",
+  "&DoubleDot;": "¨",
+  "&DoubleDownArrow;": "⇓",
+  "&DoubleLeftArrow;": "⇐",
+  "&DoubleLeftRightArrow;": "⇔",
+  "&DoubleLeftTee;": "⫤",
+  "&DoubleLongLeftArrow;": "⟸",
+  "&DoubleLongLeftRightArrow;": "⟺",
+  "&DoubleLongRightArrow;": "⟹",
+  "&DoubleRightArrow;": "⇒",
+  "&DoubleRightTee;": "⊨",
+  "&DoubleUpArrow;": "⇑",
+  "&DoubleUpDownArrow;": "⇕",
+  "&DoubleVerticalBar;": "∥",
+  "&DownArrow;": "↓",
+  "&DownArrowBar;": "⤓",
+  "&DownArrowUpArrow;": "⇵",
+  "&DownBreve;": "̑",
+  "&DownLeftRightVector;": "⥐",
+  "&DownLeftTeeVector;": "⥞",
+  "&DownLeftVector;": "↽",
+  "&DownLeftVectorBar;": "⥖",
+  "&DownRightTeeVector;": "⥟",
+  "&DownRightVector;": "⇁",
+  "&DownRightVectorBar;": "⥗",
+  "&DownTee;": "⊤",
+  "&DownTeeArrow;": "↧",
+  "&Downarrow;": "⇓",
+  "&Dscr;": "𝒟",
+  "&Dstrok;": "Đ",
+  "&ENG;": "Ŋ",
+  "&ETH;": "Ð",
+  "&Eacute;": "É",
+  "&Ecaron;": "Ě",
+  "&Ecirc;": "Ê",
+  "&Ecy;": "Э",
+  "&Edot;": "Ė",
+  "&Efr;": "𝔈",
+  "&Egrave;": "È",
+  "&Element;": "∈",
+  "&Emacr;": "Ē",
+  "&EmptySmallSquare;": "◻",
+  "&EmptyVerySmallSquare;": "▫",
+  "&Eogon;": "Ę",
+  "&Eopf;": "𝔼",
+  "&Epsilon;": "Ε",
+  "&Equal;": "⩵",
+  "&EqualTilde;": "≂",
+  "&Equilibrium;": "⇌",
+  "&Escr;": "ℰ",
+  "&Esim;": "⩳",
+  "&Eta;": "Η",
+  "&Euml;": "Ë",
+  "&Exists;": "∃",
+  "&ExponentialE;": "ⅇ",
+  "&Fcy;": "Ф",
+  "&Ffr;": "𝔉",
+  "&FilledSmallSquare;": "◼",
+  "&FilledVerySmallSquare;": "▪",
+  "&Fopf;": "𝔽",
+  "&ForAll;": "∀",
+  "&Fouriertrf;": "ℱ",
+  "&Fscr;": "ℱ",
+  "&GJcy;": "Ѓ",
+  "&GT;": ">",
+  "&Gamma;": "Γ",
+  "&Gammad;": "Ϝ",
+  "&Gbreve;": "Ğ",
+  "&Gcedil;": "Ģ",
+  "&Gcirc;": "Ĝ",
+  "&Gcy;": "Г",
+  "&Gdot;": "Ġ",
+  "&Gfr;": "𝔊",
+  "&Gg;": "⋙",
+  "&Gopf;": "𝔾",
+  "&GreaterEqual;": "≥",
+  "&GreaterEqualLess;": "⋛",
+  "&GreaterFullEqual;": "≧",
+  "&GreaterGreater;": "⪢",
+  "&GreaterLess;": "≷",
+  "&GreaterSlantEqual;": "⩾",
+  "&GreaterTilde;": "≳",
+  "&Gscr;": "𝒢",
+  "&Gt;": "≫",
+  "&HARDcy;": "Ъ",
+  "&Hacek;": "ˇ",
+  "&Hat;": "^",
+  "&Hcirc;": "Ĥ",
+  "&Hfr;": "ℌ",
+  "&HilbertSpace;": "ℋ",
+  "&Hopf;": "ℍ",
+  "&HorizontalLine;": "─",
+  "&Hscr;": "ℋ",
+  "&Hstrok;": "Ħ",
+  "&HumpDownHump;": "≎",
+  "&HumpEqual;": "≏",
+  "&IEcy;": "Е",
+  "&IJlig;": "IJ",
+  "&IOcy;": "Ё",
+  "&Iacute;": "Í",
+  "&Icirc;": "Î",
+  "&Icy;": "И",
+  "&Idot;": "İ",
+  "&Ifr;": "ℑ",
+  "&Igrave;": "Ì",
+  "&Im;": "ℑ",
+  "&Imacr;": "Ī",
+  "&ImaginaryI;": "ⅈ",
+  "&Implies;": "⇒",
+  "&Int;": "∬",
+  "&Integral;": "∫",
+  "&Intersection;": "⋂",
+  "&InvisibleComma;": "⁣",
+  "&InvisibleTimes;": "⁢",
+  "&Iogon;": "Į",
+  "&Iopf;": "𝕀",
+  "&Iota;": "Ι",
+  "&Iscr;": "ℐ",
+  "&Itilde;": "Ĩ",
+  "&Iukcy;": "І",
+  "&Iuml;": "Ï",
+  "&Jcirc;": "Ĵ",
+  "&Jcy;": "Й",
+  "&Jfr;": "𝔍",
+  "&Jopf;": "𝕁",
+  "&Jscr;": "𝒥",
+  "&Jsercy;": "Ј",
+  "&Jukcy;": "Є",
+  "&KHcy;": "Х",
+  "&KJcy;": "Ќ",
+  "&Kappa;": "Κ",
+  "&Kcedil;": "Ķ",
+  "&Kcy;": "К",
+  "&Kfr;": "𝔎",
+  "&Kopf;": "𝕂",
+  "&Kscr;": "𝒦",
+  "&LJcy;": "Љ",
+  "&LT;": "<",
+  "&Lacute;": "Ĺ",
+  "&Lambda;": "Λ",
+  "&Lang;": "⟪",
+  "&Laplacetrf;": "ℒ",
+  "&Larr;": "↞",
+  "&Lcaron;": "Ľ",
+  "&Lcedil;": "Ļ",
+  "&Lcy;": "Л",
+  "&LeftAngleBracket;": "⟨",
+  "&LeftArrow;": "←",
+  "&LeftArrowBar;": "⇤",
+  "&LeftArrowRightArrow;": "⇆",
+  "&LeftCeiling;": "⌈",
+  "&LeftDoubleBracket;": "⟦",
+  "&LeftDownTeeVector;": "⥡",
+  "&LeftDownVector;": "⇃",
+  "&LeftDownVectorBar;": "⥙",
+  "&LeftFloor;": "⌊",
+  "&LeftRightArrow;": "↔",
+  "&LeftRightVector;": "⥎",
+  "&LeftTee;": "⊣",
+  "&LeftTeeArrow;": "↤",
+  "&LeftTeeVector;": "⥚",
+  "&LeftTriangle;": "⊲",
+  "&LeftTriangleBar;": "⧏",
+  "&LeftTriangleEqual;": "⊴",
+  "&LeftUpDownVector;": "⥑",
+  "&LeftUpTeeVector;": "⥠",
+  "&LeftUpVector;": "↿",
+  "&LeftUpVectorBar;": "⥘",
+  "&LeftVector;": "↼",
+  "&LeftVectorBar;": "⥒",
+  "&Leftarrow;": "⇐",
+  "&Leftrightarrow;": "⇔",
+  "&LessEqualGreater;": "⋚",
+  "&LessFullEqual;": "≦",
+  "&LessGreater;": "≶",
+  "&LessLess;": "⪡",
+  "&LessSlantEqual;": "⩽",
+  "&LessTilde;": "≲",
+  "&Lfr;": "𝔏",
+  "&Ll;": "⋘",
+  "&Lleftarrow;": "⇚",
+  "&Lmidot;": "Ŀ",
+  "&LongLeftArrow;": "⟵",
+  "&LongLeftRightArrow;": "⟷",
+  "&LongRightArrow;": "⟶",
+  "&Longleftarrow;": "⟸",
+  "&Longleftrightarrow;": "⟺",
+  "&Longrightarrow;": "⟹",
+  "&Lopf;": "𝕃",
+  "&LowerLeftArrow;": "↙",
+  "&LowerRightArrow;": "↘",
+  "&Lscr;": "ℒ",
+  "&Lsh;": "↰",
+  "&Lstrok;": "Ł",
+  "&Lt;": "≪",
+  "&Map;": "⤅",
+  "&Mcy;": "М",
+  "&MediumSpace;": " ",
+  "&Mellintrf;": "ℳ",
+  "&Mfr;": "𝔐",
+  "&MinusPlus;": "∓",
+  "&Mopf;": "𝕄",
+  "&Mscr;": "ℳ",
+  "&Mu;": "Μ",
+  "&NJcy;": "Њ",
+  "&Nacute;": "Ń",
+  "&Ncaron;": "Ň",
+  "&Ncedil;": "Ņ",
+  "&Ncy;": "Н",
+  "&NegativeMediumSpace;": "​",
+  "&NegativeThickSpace;": "​",
+  "&NegativeThinSpace;": "​",
+  "&NegativeVeryThinSpace;": "​",
+  "&NestedGreaterGreater;": "≫",
+  "&NestedLessLess;": "≪",
+  "&NewLine;": "\n",
+  "&Nfr;": "𝔑",
+  "&NoBreak;": "⁠",
+  "&NonBreakingSpace;": " ",
+  "&Nopf;": "ℕ",
+  "&Not;": "⫬",
+  "&NotCongruent;": "≢",
+  "&NotCupCap;": "≭",
+  "&NotDoubleVerticalBar;": "∦",
+  "&NotElement;": "∉",
+  "&NotEqual;": "≠",
+  "&NotEqualTilde;": "≂̸",
+  "&NotExists;": "∄",
+  "&NotGreater;": "≯",
+  "&NotGreaterEqual;": "≱",
+  "&NotGreaterFullEqual;": "≧̸",
+  "&NotGreaterGreater;": "≫̸",
+  "&NotGreaterLess;": "≹",
+  "&NotGreaterSlantEqual;": "⩾̸",
+  "&NotGreaterTilde;": "≵",
+  "&NotHumpDownHump;": "≎̸",
+  "&NotHumpEqual;": "≏̸",
+  "&NotLeftTriangle;": "⋪",
+  "&NotLeftTriangleBar;": "⧏̸",
+  "&NotLeftTriangleEqual;": "⋬",
+  "&NotLess;": "≮",
+  "&NotLessEqual;": "≰",
+  "&NotLessGreater;": "≸",
+  "&NotLessLess;": "≪̸",
+  "&NotLessSlantEqual;": "⩽̸",
+  "&NotLessTilde;": "≴",
+  "&NotNestedGreaterGreater;": "⪢̸",
+  "&NotNestedLessLess;": "⪡̸",
+  "&NotPrecedes;": "⊀",
+  "&NotPrecedesEqual;": "⪯̸",
+  "&NotPrecedesSlantEqual;": "⋠",
+  "&NotReverseElement;": "∌",
+  "&NotRightTriangle;": "⋫",
+  "&NotRightTriangleBar;": "⧐̸",
+  "&NotRightTriangleEqual;": "⋭",
+  "&NotSquareSubset;": "⊏̸",
+  "&NotSquareSubsetEqual;": "⋢",
+  "&NotSquareSuperset;": "⊐̸",
+  "&NotSquareSupersetEqual;": "⋣",
+  "&NotSubset;": "⊂⃒",
+  "&NotSubsetEqual;": "⊈",
+  "&NotSucceeds;": "⊁",
+  "&NotSucceedsEqual;": "⪰̸",
+  "&NotSucceedsSlantEqual;": "⋡",
+  "&NotSucceedsTilde;": "≿̸",
+  "&NotSuperset;": "⊃⃒",
+  "&NotSupersetEqual;": "⊉",
+  "&NotTilde;": "≁",
+  "&NotTildeEqual;": "≄",
+  "&NotTildeFullEqual;": "≇",
+  "&NotTildeTilde;": "≉",
+  "&NotVerticalBar;": "∤",
+  "&Nscr;": "𝒩",
+  "&Ntilde;": "Ñ",
+  "&Nu;": "Ν",
+  "&OElig;": "Œ",
+  "&Oacute;": "Ó",
+  "&Ocirc;": "Ô",
+  "&Ocy;": "О",
+  "&Odblac;": "Ő",
+  "&Ofr;": "𝔒",
+  "&Ograve;": "Ò",
+  "&Omacr;": "Ō",
+  "&Omega;": "Ω",
+  "&Omicron;": "Ο",
+  "&Oopf;": "𝕆",
+  "&OpenCurlyDoubleQuote;": "“",
+  "&OpenCurlyQuote;": "‘",
+  "&Or;": "⩔",
+  "&Oscr;": "𝒪",
+  "&Oslash;": "Ø",
+  "&Otilde;": "Õ",
+  "&Otimes;": "⨷",
+  "&Ouml;": "Ö",
+  "&OverBar;": "‾",
+  "&OverBrace;": "⏞",
+  "&OverBracket;": "⎴",
+  "&OverParenthesis;": "⏜",
+  "&PartialD;": "∂",
+  "&Pcy;": "П",
+  "&Pfr;": "𝔓",
+  "&Phi;": "Φ",
+  "&Pi;": "Π",
+  "&PlusMinus;": "±",
+  "&Poincareplane;": "ℌ",
+  "&Popf;": "ℙ",
+  "&Pr;": "⪻",
+  "&Precedes;": "≺",
+  "&PrecedesEqual;": "⪯",
+  "&PrecedesSlantEqual;": "≼",
+  "&PrecedesTilde;": "≾",
+  "&Prime;": "″",
+  "&Product;": "∏",
+  "&Proportion;": "∷",
+  "&Proportional;": "∝",
+  "&Pscr;": "𝒫",
+  "&Psi;": "Ψ",
+  "&QUOT;": "\"",
+  "&Qfr;": "𝔔",
+  "&Qopf;": "ℚ",
+  "&Qscr;": "𝒬",
+  "&RBarr;": "⤐",
+  "&REG;": "®",
+  "&Racute;": "Ŕ",
+  "&Rang;": "⟫",
+  "&Rarr;": "↠",
+  "&Rarrtl;": "⤖",
+  "&Rcaron;": "Ř",
+  "&Rcedil;": "Ŗ",
+  "&Rcy;": "Р",
+  "&Re;": "ℜ",
+  "&ReverseElement;": "∋",
+  "&ReverseEquilibrium;": "⇋",
+  "&ReverseUpEquilibrium;": "⥯",
+  "&Rfr;": "ℜ",
+  "&Rho;": "Ρ",
+  "&RightAngleBracket;": "⟩",
+  "&RightArrow;": "→",
+  "&RightArrowBar;": "⇥",
+  "&RightArrowLeftArrow;": "⇄",
+  "&RightCeiling;": "⌉",
+  "&RightDoubleBracket;": "⟧",
+  "&RightDownTeeVector;": "⥝",
+  "&RightDownVector;": "⇂",
+  "&RightDownVectorBar;": "⥕",
+  "&RightFloor;": "⌋",
+  "&RightTee;": "⊢",
+  "&RightTeeArrow;": "↦",
+  "&RightTeeVector;": "⥛",
+  "&RightTriangle;": "⊳",
+  "&RightTriangleBar;": "⧐",
+  "&RightTriangleEqual;": "⊵",
+  "&RightUpDownVector;": "⥏",
+  "&RightUpTeeVector;": "⥜",
+  "&RightUpVector;": "↾",
+  "&RightUpVectorBar;": "⥔",
+  "&RightVector;": "⇀",
+  "&RightVectorBar;": "⥓",
+  "&Rightarrow;": "⇒",
+  "&Ropf;": "ℝ",
+  "&RoundImplies;": "⥰",
+  "&Rrightarrow;": "⇛",
+  "&Rscr;": "ℛ",
+  "&Rsh;": "↱",
+  "&RuleDelayed;": "⧴",
+  "&SHCHcy;": "Щ",
+  "&SHcy;": "Ш",
+  "&SOFTcy;": "Ь",
+  "&Sacute;": "Ś",
+  "&Sc;": "⪼",
+  "&Scaron;": "Š",
+  "&Scedil;": "Ş",
+  "&Scirc;": "Ŝ",
+  "&Scy;": "С",
+  "&Sfr;": "𝔖",
+  "&ShortDownArrow;": "↓",
+  "&ShortLeftArrow;": "←",
+  "&ShortRightArrow;": "→",
+  "&ShortUpArrow;": "↑",
+  "&Sigma;": "Σ",
+  "&SmallCircle;": "∘",
+  "&Sopf;": "𝕊",
+  "&Sqrt;": "√",
+  "&Square;": "□",
+  "&SquareIntersection;": "⊓",
+  "&SquareSubset;": "⊏",
+  "&SquareSubsetEqual;": "⊑",
+  "&SquareSuperset;": "⊐",
+  "&SquareSupersetEqual;": "⊒",
+  "&SquareUnion;": "⊔",
+  "&Sscr;": "𝒮",
+  "&Star;": "⋆",
+  "&Sub;": "⋐",
+  "&Subset;": "⋐",
+  "&SubsetEqual;": "⊆",
+  "&Succeeds;": "≻",
+  "&SucceedsEqual;": "⪰",
+  "&SucceedsSlantEqual;": "≽",
+  "&SucceedsTilde;": "≿",
+  "&SuchThat;": "∋",
+  "&Sum;": "∑",
+  "&Sup;": "⋑",
+  "&Superset;": "⊃",
+  "&SupersetEqual;": "⊇",
+  "&Supset;": "⋑",
+  "&THORN;": "Þ",
+  "&TRADE;": "™",
+  "&TSHcy;": "Ћ",
+  "&TScy;": "Ц",
+  "&Tab;": "\t",
+  "&Tau;": "Τ",
+  "&Tcaron;": "Ť",
+  "&Tcedil;": "Ţ",
+  "&Tcy;": "Т",
+  "&Tfr;": "𝔗",
+  "&Therefore;": "∴",
+  "&Theta;": "Θ",
+  "&ThickSpace;": "  ",
+  "&ThinSpace;": " ",
+  "&Tilde;": "∼",
+  "&TildeEqual;": "≃",
+  "&TildeFullEqual;": "≅",
+  "&TildeTilde;": "≈",
+  "&Topf;": "𝕋",
+  "&TripleDot;": "⃛",
+  "&Tscr;": "𝒯",
+  "&Tstrok;": "Ŧ",
+  "&Uacute;": "Ú",
+  "&Uarr;": "↟",
+  "&Uarrocir;": "⥉",
+  "&Ubrcy;": "Ў",
+  "&Ubreve;": "Ŭ",
+  "&Ucirc;": "Û",
+  "&Ucy;": "У",
+  "&Udblac;": "Ű",
+  "&Ufr;": "𝔘",
+  "&Ugrave;": "Ù",
+  "&Umacr;": "Ū",
+  "&UnderBar;": "_",
+  "&UnderBrace;": "⏟",
+  "&UnderBracket;": "⎵",
+  "&UnderParenthesis;": "⏝",
+  "&Union;": "⋃",
+  "&UnionPlus;": "⊎",
+  "&Uogon;": "Ų",
+  "&Uopf;": "𝕌",
+  "&UpArrow;": "↑",
+  "&UpArrowBar;": "⤒",
+  "&UpArrowDownArrow;": "⇅",
+  "&UpDownArrow;": "↕",
+  "&UpEquilibrium;": "⥮",
+  "&UpTee;": "⊥",
+  "&UpTeeArrow;": "↥",
+  "&Uparrow;": "⇑",
+  "&Updownarrow;": "⇕",
+  "&UpperLeftArrow;": "↖",
+  "&UpperRightArrow;": "↗",
+  "&Upsi;": "ϒ",
+  "&Upsilon;": "Υ",
+  "&Uring;": "Ů",
+  "&Uscr;": "𝒰",
+  "&Utilde;": "Ũ",
+  "&Uuml;": "Ü",
+  "&VDash;": "⊫",
+  "&Vbar;": "⫫",
+  "&Vcy;": "В",
+  "&Vdash;": "⊩",
+  "&Vdashl;": "⫦",
+  "&Vee;": "⋁",
+  "&Verbar;": "‖",
+  "&Vert;": "‖",
+  "&VerticalBar;": "∣",
+  "&VerticalLine;": "|",
+  "&VerticalSeparator;": "❘",
+  "&VerticalTilde;": "≀",
+  "&VeryThinSpace;": " ",
+  "&Vfr;": "𝔙",
+  "&Vopf;": "𝕍",
+  "&Vscr;": "𝒱",
+  "&Vvdash;": "⊪",
+  "&Wcirc;": "Ŵ",
+  "&Wedge;": "⋀",
+  "&Wfr;": "𝔚",
+  "&Wopf;": "𝕎",
+  "&Wscr;": "𝒲",
+  "&Xfr;": "𝔛",
+  "&Xi;": "Ξ",
+  "&Xopf;": "𝕏",
+  "&Xscr;": "𝒳",
+  "&YAcy;": "Я",
+  "&YIcy;": "Ї",
+  "&YUcy;": "Ю",
+  "&Yacute;": "Ý",
+  "&Ycirc;": "Ŷ",
+  "&Ycy;": "Ы",
+  "&Yfr;": "𝔜",
+  "&Yopf;": "𝕐",
+  "&Yscr;": "𝒴",
+  "&Yuml;": "Ÿ",
+  "&ZHcy;": "Ж",
+  "&Zacute;": "Ź",
+  "&Zcaron;": "Ž",
+  "&Zcy;": "З",
+  "&Zdot;": "Ż",
+  "&ZeroWidthSpace;": "​",
+  "&Zeta;": "Ζ",
+  "&Zfr;": "ℨ",
+  "&Zopf;": "ℤ",
+  "&Zscr;": "𝒵",
+  "&aacute;": "á",
+  "&abreve;": "ă",
+  "&ac;": "∾",
+  "&acE;": "∾̳",
+  "&acd;": "∿",
+  "&acirc;": "â",
+  "&acute;": "´",
+  "&acy;": "а",
+  "&aelig;": "æ",
+  "&af;": "⁡",
+  "&afr;": "𝔞",
+  "&agrave;": "à",
+  "&alefsym;": "ℵ",
+  "&aleph;": "ℵ",
+  "&alpha;": "α",
+  "&amacr;": "ā",
+  "&amalg;": "⨿",
+  "&amp;": "&",
+  "&and;": "∧",
+  "&andand;": "⩕",
+  "&andd;": "⩜",
+  "&andslope;": "⩘",
+  "&andv;": "⩚",
+  "&ang;": "∠",
+  "&ange;": "⦤",
+  "&angle;": "∠",
+  "&angmsd;": "∡",
+  "&angmsdaa;": "⦨",
+  "&angmsdab;": "⦩",
+  "&angmsdac;": "⦪",
+  "&angmsdad;": "⦫",
+  "&angmsdae;": "⦬",
+  "&angmsdaf;": "⦭",
+  "&angmsdag;": "⦮",
+  "&angmsdah;": "⦯",
+  "&angrt;": "∟",
+  "&angrtvb;": "⊾",
+  "&angrtvbd;": "⦝",
+  "&angsph;": "∢",
+  "&angst;": "Å",
+  "&angzarr;": "⍼",
+  "&aogon;": "ą",
+  "&aopf;": "𝕒",
+  "&ap;": "≈",
+  "&apE;": "⩰",
+  "&apacir;": "⩯",
+  "&ape;": "≊",
+  "&apid;": "≋",
+  "&apos;": "'",
+  "&approx;": "≈",
+  "&approxeq;": "≊",
+  "&aring;": "å",
+  "&ascr;": "𝒶",
+  "&ast;": "*",
+  "&asymp;": "≈",
+  "&asympeq;": "≍",
+  "&atilde;": "ã",
+  "&auml;": "ä",
+  "&awconint;": "∳",
+  "&awint;": "⨑",
+  "&bNot;": "⫭",
+  "&backcong;": "≌",
+  "&backepsilon;": "϶",
+  "&backprime;": "‵",
+  "&backsim;": "∽",
+  "&backsimeq;": "⋍",
+  "&barvee;": "⊽",
+  "&barwed;": "⌅",
+  "&barwedge;": "⌅",
+  "&bbrk;": "⎵",
+  "&bbrktbrk;": "⎶",
+  "&bcong;": "≌",
+  "&bcy;": "б",
+  "&bdquo;": "„",
+  "&becaus;": "∵",
+  "&because;": "∵",
+  "&bemptyv;": "⦰",
+  "&bepsi;": "϶",
+  "&bernou;": "ℬ",
+  "&beta;": "β",
+  "&beth;": "ℶ",
+  "&between;": "≬",
+  "&bfr;": "𝔟",
+  "&bigcap;": "⋂",
+  "&bigcirc;": "◯",
+  "&bigcup;": "⋃",
+  "&bigodot;": "⨀",
+  "&bigoplus;": "⨁",
+  "&bigotimes;": "⨂",
+  "&bigsqcup;": "⨆",
+  "&bigstar;": "★",
+  "&bigtriangledown;": "▽",
+  "&bigtriangleup;": "△",
+  "&biguplus;": "⨄",
+  "&bigvee;": "⋁",
+  "&bigwedge;": "⋀",
+  "&bkarow;": "⤍",
+  "&blacklozenge;": "⧫",
+  "&blacksquare;": "▪",
+  "&blacktriangle;": "▴",
+  "&blacktriangledown;": "▾",
+  "&blacktriangleleft;": "◂",
+  "&blacktriangleright;": "▸",
+  "&blank;": "␣",
+  "&blk12;": "▒",
+  "&blk14;": "░",
+  "&blk34;": "▓",
+  "&block;": "█",
+  "&bne;": "=⃥",
+  "&bnequiv;": "≡⃥",
+  "&bnot;": "⌐",
+  "&bopf;": "𝕓",
+  "&bot;": "⊥",
+  "&bottom;": "⊥",
+  "&bowtie;": "⋈",
+  "&boxDL;": "╗",
+  "&boxDR;": "╔",
+  "&boxDl;": "╖",
+  "&boxDr;": "╓",
+  "&boxH;": "═",
+  "&boxHD;": "╦",
+  "&boxHU;": "╩",
+  "&boxHd;": "╤",
+  "&boxHu;": "╧",
+  "&boxUL;": "╝",
+  "&boxUR;": "╚",
+  "&boxUl;": "╜",
+  "&boxUr;": "╙",
+  "&boxV;": "║",
+  "&boxVH;": "╬",
+  "&boxVL;": "╣",
+  "&boxVR;": "╠",
+  "&boxVh;": "╫",
+  "&boxVl;": "╢",
+  "&boxVr;": "╟",
+  "&boxbox;": "⧉",
+  "&boxdL;": "╕",
+  "&boxdR;": "╒",
+  "&boxdl;": "┐",
+  "&boxdr;": "┌",
+  "&boxh;": "─",
+  "&boxhD;": "╥",
+  "&boxhU;": "╨",
+  "&boxhd;": "┬",
+  "&boxhu;": "┴",
+  "&boxminus;": "⊟",
+  "&boxplus;": "⊞",
+  "&boxtimes;": "⊠",
+  "&boxuL;": "╛",
+  "&boxuR;": "╘",
+  "&boxul;": "┘",
+  "&boxur;": "└",
+  "&boxv;": "│",
+  "&boxvH;": "╪",
+  "&boxvL;": "╡",
+  "&boxvR;": "╞",
+  "&boxvh;": "┼",
+  "&boxvl;": "┤",
+  "&boxvr;": "├",
+  "&bprime;": "‵",
+  "&breve;": "˘",
+  "&brvbar;": "¦",
+  "&bscr;": "𝒷",
+  "&bsemi;": "⁏",
+  "&bsim;": "∽",
+  "&bsime;": "⋍",
+  "&bsol;": r"\",
+  "&bsolb;": "⧅",
+  "&bsolhsub;": "⟈",
+  "&bull;": "•",
+  "&bullet;": "•",
+  "&bump;": "≎",
+  "&bumpE;": "⪮",
+  "&bumpe;": "≏",
+  "&bumpeq;": "≏",
+  "&cacute;": "ć",
+  "&cap;": "∩",
+  "&capand;": "⩄",
+  "&capbrcup;": "⩉",
+  "&capcap;": "⩋",
+  "&capcup;": "⩇",
+  "&capdot;": "⩀",
+  "&caps;": "∩︀",
+  "&caret;": "⁁",
+  "&caron;": "ˇ",
+  "&ccaps;": "⩍",
+  "&ccaron;": "č",
+  "&ccedil;": "ç",
+  "&ccirc;": "ĉ",
+  "&ccups;": "⩌",
+  "&ccupssm;": "⩐",
+  "&cdot;": "ċ",
+  "&cedil;": "¸",
+  "&cemptyv;": "⦲",
+  "&cent;": "¢",
+  "&centerdot;": "·",
+  "&cfr;": "𝔠",
+  "&chcy;": "ч",
+  "&check;": "✓",
+  "&checkmark;": "✓",
+  "&chi;": "χ",
+  "&cir;": "○",
+  "&cirE;": "⧃",
+  "&circ;": "ˆ",
+  "&circeq;": "≗",
+  "&circlearrowleft;": "↺",
+  "&circlearrowright;": "↻",
+  "&circledR;": "®",
+  "&circledS;": "Ⓢ",
+  "&circledast;": "⊛",
+  "&circledcirc;": "⊚",
+  "&circleddash;": "⊝",
+  "&cire;": "≗",
+  "&cirfnint;": "⨐",
+  "&cirmid;": "⫯",
+  "&cirscir;": "⧂",
+  "&clubs;": "♣",
+  "&clubsuit;": "♣",
+  "&colon;": ":",
+  "&colone;": "≔",
+  "&coloneq;": "≔",
+  "&comma;": ",",
+  "&commat;": "@",
+  "&comp;": "∁",
+  "&compfn;": "∘",
+  "&complement;": "∁",
+  "&complexes;": "ℂ",
+  "&cong;": "≅",
+  "&congdot;": "⩭",
+  "&conint;": "∮",
+  "&copf;": "𝕔",
+  "&coprod;": "∐",
+  "&copy;": "©",
+  "&copysr;": "℗",
+  "&crarr;": "↵",
+  "&cross;": "✗",
+  "&cscr;": "𝒸",
+  "&csub;": "⫏",
+  "&csube;": "⫑",
+  "&csup;": "⫐",
+  "&csupe;": "⫒",
+  "&ctdot;": "⋯",
+  "&cudarrl;": "⤸",
+  "&cudarrr;": "⤵",
+  "&cuepr;": "⋞",
+  "&cuesc;": "⋟",
+  "&cularr;": "↶",
+  "&cularrp;": "⤽",
+  "&cup;": "∪",
+  "&cupbrcap;": "⩈",
+  "&cupcap;": "⩆",
+  "&cupcup;": "⩊",
+  "&cupdot;": "⊍",
+  "&cupor;": "⩅",
+  "&cups;": "∪︀",
+  "&curarr;": "↷",
+  "&curarrm;": "⤼",
+  "&curlyeqprec;": "⋞",
+  "&curlyeqsucc;": "⋟",
+  "&curlyvee;": "⋎",
+  "&curlywedge;": "⋏",
+  "&curren;": "¤",
+  "&curvearrowleft;": "↶",
+  "&curvearrowright;": "↷",
+  "&cuvee;": "⋎",
+  "&cuwed;": "⋏",
+  "&cwconint;": "∲",
+  "&cwint;": "∱",
+  "&cylcty;": "⌭",
+  "&dArr;": "⇓",
+  "&dHar;": "⥥",
+  "&dagger;": "†",
+  "&daleth;": "ℸ",
+  "&darr;": "↓",
+  "&dash;": "‐",
+  "&dashv;": "⊣",
+  "&dbkarow;": "⤏",
+  "&dblac;": "˝",
+  "&dcaron;": "ď",
+  "&dcy;": "д",
+  "&dd;": "ⅆ",
+  "&ddagger;": "‡",
+  "&ddarr;": "⇊",
+  "&ddotseq;": "⩷",
+  "&deg;": "°",
+  "&delta;": "δ",
+  "&demptyv;": "⦱",
+  "&dfisht;": "⥿",
+  "&dfr;": "𝔡",
+  "&dharl;": "⇃",
+  "&dharr;": "⇂",
+  "&diam;": "⋄",
+  "&diamond;": "⋄",
+  "&diamondsuit;": "♦",
+  "&diams;": "♦",
+  "&die;": "¨",
+  "&digamma;": "ϝ",
+  "&disin;": "⋲",
+  "&div;": "÷",
+  "&divide;": "÷",
+  "&divideontimes;": "⋇",
+  "&divonx;": "⋇",
+  "&djcy;": "ђ",
+  "&dlcorn;": "⌞",
+  "&dlcrop;": "⌍",
+  "&dollar;": r"$",
+  "&dopf;": "𝕕",
+  "&dot;": "˙",
+  "&doteq;": "≐",
+  "&doteqdot;": "≑",
+  "&dotminus;": "∸",
+  "&dotplus;": "∔",
+  "&dotsquare;": "⊡",
+  "&doublebarwedge;": "⌆",
+  "&downarrow;": "↓",
+  "&downdownarrows;": "⇊",
+  "&downharpoonleft;": "⇃",
+  "&downharpoonright;": "⇂",
+  "&drbkarow;": "⤐",
+  "&drcorn;": "⌟",
+  "&drcrop;": "⌌",
+  "&dscr;": "𝒹",
+  "&dscy;": "ѕ",
+  "&dsol;": "⧶",
+  "&dstrok;": "đ",
+  "&dtdot;": "⋱",
+  "&dtri;": "▿",
+  "&dtrif;": "▾",
+  "&duarr;": "⇵",
+  "&duhar;": "⥯",
+  "&dwangle;": "⦦",
+  "&dzcy;": "џ",
+  "&dzigrarr;": "⟿",
+  "&eDDot;": "⩷",
+  "&eDot;": "≑",
+  "&eacute;": "é",
+  "&easter;": "⩮",
+  "&ecaron;": "ě",
+  "&ecir;": "≖",
+  "&ecirc;": "ê",
+  "&ecolon;": "≕",
+  "&ecy;": "э",
+  "&edot;": "ė",
+  "&ee;": "ⅇ",
+  "&efDot;": "≒",
+  "&efr;": "𝔢",
+  "&eg;": "⪚",
+  "&egrave;": "è",
+  "&egs;": "⪖",
+  "&egsdot;": "⪘",
+  "&el;": "⪙",
+  "&elinters;": "⏧",
+  "&ell;": "ℓ",
+  "&els;": "⪕",
+  "&elsdot;": "⪗",
+  "&emacr;": "ē",
+  "&empty;": "∅",
+  "&emptyset;": "∅",
+  "&emptyv;": "∅",
+  "&emsp13;": " ",
+  "&emsp14;": " ",
+  "&emsp;": " ",
+  "&eng;": "ŋ",
+  "&ensp;": " ",
+  "&eogon;": "ę",
+  "&eopf;": "𝕖",
+  "&epar;": "⋕",
+  "&eparsl;": "⧣",
+  "&eplus;": "⩱",
+  "&epsi;": "ε",
+  "&epsilon;": "ε",
+  "&epsiv;": "ϵ",
+  "&eqcirc;": "≖",
+  "&eqcolon;": "≕",
+  "&eqsim;": "≂",
+  "&eqslantgtr;": "⪖",
+  "&eqslantless;": "⪕",
+  "&equals;": "=",
+  "&equest;": "≟",
+  "&equiv;": "≡",
+  "&equivDD;": "⩸",
+  "&eqvparsl;": "⧥",
+  "&erDot;": "≓",
+  "&erarr;": "⥱",
+  "&escr;": "ℯ",
+  "&esdot;": "≐",
+  "&esim;": "≂",
+  "&eta;": "η",
+  "&eth;": "ð",
+  "&euml;": "ë",
+  "&euro;": "€",
+  "&excl;": "!",
+  "&exist;": "∃",
+  "&expectation;": "ℰ",
+  "&exponentiale;": "ⅇ",
+  "&fallingdotseq;": "≒",
+  "&fcy;": "ф",
+  "&female;": "♀",
+  "&ffilig;": "ffi",
+  "&fflig;": "ff",
+  "&ffllig;": "ffl",
+  "&ffr;": "𝔣",
+  "&filig;": "fi",
+  "&fjlig;": "fj",
+  "&flat;": "♭",
+  "&fllig;": "fl",
+  "&fltns;": "▱",
+  "&fnof;": "ƒ",
+  "&fopf;": "𝕗",
+  "&forall;": "∀",
+  "&fork;": "⋔",
+  "&forkv;": "⫙",
+  "&fpartint;": "⨍",
+  "&frac12;": "½",
+  "&frac13;": "⅓",
+  "&frac14;": "¼",
+  "&frac15;": "⅕",
+  "&frac16;": "⅙",
+  "&frac18;": "⅛",
+  "&frac23;": "⅔",
+  "&frac25;": "⅖",
+  "&frac34;": "¾",
+  "&frac35;": "⅗",
+  "&frac38;": "⅜",
+  "&frac45;": "⅘",
+  "&frac56;": "⅚",
+  "&frac58;": "⅝",
+  "&frac78;": "⅞",
+  "&frasl;": "⁄",
+  "&frown;": "⌢",
+  "&fscr;": "𝒻",
+  "&gE;": "≧",
+  "&gEl;": "⪌",
+  "&gacute;": "ǵ",
+  "&gamma;": "γ",
+  "&gammad;": "ϝ",
+  "&gap;": "⪆",
+  "&gbreve;": "ğ",
+  "&gcirc;": "ĝ",
+  "&gcy;": "г",
+  "&gdot;": "ġ",
+  "&ge;": "≥",
+  "&gel;": "⋛",
+  "&geq;": "≥",
+  "&geqq;": "≧",
+  "&geqslant;": "⩾",
+  "&ges;": "⩾",
+  "&gescc;": "⪩",
+  "&gesdot;": "⪀",
+  "&gesdoto;": "⪂",
+  "&gesdotol;": "⪄",
+  "&gesl;": "⋛︀",
+  "&gesles;": "⪔",
+  "&gfr;": "𝔤",
+  "&gg;": "≫",
+  "&ggg;": "⋙",
+  "&gimel;": "ℷ",
+  "&gjcy;": "ѓ",
+  "&gl;": "≷",
+  "&glE;": "⪒",
+  "&gla;": "⪥",
+  "&glj;": "⪤",
+  "&gnE;": "≩",
+  "&gnap;": "⪊",
+  "&gnapprox;": "⪊",
+  "&gne;": "⪈",
+  "&gneq;": "⪈",
+  "&gneqq;": "≩",
+  "&gnsim;": "⋧",
+  "&gopf;": "𝕘",
+  "&grave;": "`",
+  "&gscr;": "ℊ",
+  "&gsim;": "≳",
+  "&gsime;": "⪎",
+  "&gsiml;": "⪐",
+  "&gt;": ">",
+  "&gtcc;": "⪧",
+  "&gtcir;": "⩺",
+  "&gtdot;": "⋗",
+  "&gtlPar;": "⦕",
+  "&gtquest;": "⩼",
+  "&gtrapprox;": "⪆",
+  "&gtrarr;": "⥸",
+  "&gtrdot;": "⋗",
+  "&gtreqless;": "⋛",
+  "&gtreqqless;": "⪌",
+  "&gtrless;": "≷",
+  "&gtrsim;": "≳",
+  "&gvertneqq;": "≩︀",
+  "&gvnE;": "≩︀",
+  "&hArr;": "⇔",
+  "&hairsp;": " ",
+  "&half;": "½",
+  "&hamilt;": "ℋ",
+  "&hardcy;": "ъ",
+  "&harr;": "↔",
+  "&harrcir;": "⥈",
+  "&harrw;": "↭",
+  "&hbar;": "ℏ",
+  "&hcirc;": "ĥ",
+  "&hearts;": "♥",
+  "&heartsuit;": "♥",
+  "&hellip;": "…",
+  "&hercon;": "⊹",
+  "&hfr;": "𝔥",
+  "&hksearow;": "⤥",
+  "&hkswarow;": "⤦",
+  "&hoarr;": "⇿",
+  "&homtht;": "∻",
+  "&hookleftarrow;": "↩",
+  "&hookrightarrow;": "↪",
+  "&hopf;": "𝕙",
+  "&horbar;": "―",
+  "&hscr;": "𝒽",
+  "&hslash;": "ℏ",
+  "&hstrok;": "ħ",
+  "&hybull;": "⁃",
+  "&hyphen;": "‐",
+  "&iacute;": "í",
+  "&ic;": "⁣",
+  "&icirc;": "î",
+  "&icy;": "и",
+  "&iecy;": "е",
+  "&iexcl;": "¡",
+  "&iff;": "⇔",
+  "&ifr;": "𝔦",
+  "&igrave;": "ì",
+  "&ii;": "ⅈ",
+  "&iiiint;": "⨌",
+  "&iiint;": "∭",
+  "&iinfin;": "⧜",
+  "&iiota;": "℩",
+  "&ijlig;": "ij",
+  "&imacr;": "ī",
+  "&image;": "ℑ",
+  "&imagline;": "ℐ",
+  "&imagpart;": "ℑ",
+  "&imath;": "ı",
+  "&imof;": "⊷",
+  "&imped;": "Ƶ",
+  "&in;": "∈",
+  "&incare;": "℅",
+  "&infin;": "∞",
+  "&infintie;": "⧝",
+  "&inodot;": "ı",
+  "&int;": "∫",
+  "&intcal;": "⊺",
+  "&integers;": "ℤ",
+  "&intercal;": "⊺",
+  "&intlarhk;": "⨗",
+  "&intprod;": "⨼",
+  "&iocy;": "ё",
+  "&iogon;": "į",
+  "&iopf;": "𝕚",
+  "&iota;": "ι",
+  "&iprod;": "⨼",
+  "&iquest;": "¿",
+  "&iscr;": "𝒾",
+  "&isin;": "∈",
+  "&isinE;": "⋹",
+  "&isindot;": "⋵",
+  "&isins;": "⋴",
+  "&isinsv;": "⋳",
+  "&isinv;": "∈",
+  "&it;": "⁢",
+  "&itilde;": "ĩ",
+  "&iukcy;": "і",
+  "&iuml;": "ï",
+  "&jcirc;": "ĵ",
+  "&jcy;": "й",
+  "&jfr;": "𝔧",
+  "&jmath;": "ȷ",
+  "&jopf;": "𝕛",
+  "&jscr;": "𝒿",
+  "&jsercy;": "ј",
+  "&jukcy;": "є",
+  "&kappa;": "κ",
+  "&kappav;": "ϰ",
+  "&kcedil;": "ķ",
+  "&kcy;": "к",
+  "&kfr;": "𝔨",
+  "&kgreen;": "ĸ",
+  "&khcy;": "х",
+  "&kjcy;": "ќ",
+  "&kopf;": "𝕜",
+  "&kscr;": "𝓀",
+  "&lAarr;": "⇚",
+  "&lArr;": "⇐",
+  "&lAtail;": "⤛",
+  "&lBarr;": "⤎",
+  "&lE;": "≦",
+  "&lEg;": "⪋",
+  "&lHar;": "⥢",
+  "&lacute;": "ĺ",
+  "&laemptyv;": "⦴",
+  "&lagran;": "ℒ",
+  "&lambda;": "λ",
+  "&lang;": "⟨",
+  "&langd;": "⦑",
+  "&langle;": "⟨",
+  "&lap;": "⪅",
+  "&laquo;": "«",
+  "&larr;": "←",
+  "&larrb;": "⇤",
+  "&larrbfs;": "⤟",
+  "&larrfs;": "⤝",
+  "&larrhk;": "↩",
+  "&larrlp;": "↫",
+  "&larrpl;": "⤹",
+  "&larrsim;": "⥳",
+  "&larrtl;": "↢",
+  "&lat;": "⪫",
+  "&latail;": "⤙",
+  "&late;": "⪭",
+  "&lates;": "⪭︀",
+  "&lbarr;": "⤌",
+  "&lbbrk;": "❲",
+  "&lbrace;": "{",
+  "&lbrack;": "[",
+  "&lbrke;": "⦋",
+  "&lbrksld;": "⦏",
+  "&lbrkslu;": "⦍",
+  "&lcaron;": "ľ",
+  "&lcedil;": "ļ",
+  "&lceil;": "⌈",
+  "&lcub;": "{",
+  "&lcy;": "л",
+  "&ldca;": "⤶",
+  "&ldquo;": "“",
+  "&ldquor;": "„",
+  "&ldrdhar;": "⥧",
+  "&ldrushar;": "⥋",
+  "&ldsh;": "↲",
+  "&le;": "≤",
+  "&leftarrow;": "←",
+  "&leftarrowtail;": "↢",
+  "&leftharpoondown;": "↽",
+  "&leftharpoonup;": "↼",
+  "&leftleftarrows;": "⇇",
+  "&leftrightarrow;": "↔",
+  "&leftrightarrows;": "⇆",
+  "&leftrightharpoons;": "⇋",
+  "&leftrightsquigarrow;": "↭",
+  "&leftthreetimes;": "⋋",
+  "&leg;": "⋚",
+  "&leq;": "≤",
+  "&leqq;": "≦",
+  "&leqslant;": "⩽",
+  "&les;": "⩽",
+  "&lescc;": "⪨",
+  "&lesdot;": "⩿",
+  "&lesdoto;": "⪁",
+  "&lesdotor;": "⪃",
+  "&lesg;": "⋚︀",
+  "&lesges;": "⪓",
+  "&lessapprox;": "⪅",
+  "&lessdot;": "⋖",
+  "&lesseqgtr;": "⋚",
+  "&lesseqqgtr;": "⪋",
+  "&lessgtr;": "≶",
+  "&lesssim;": "≲",
+  "&lfisht;": "⥼",
+  "&lfloor;": "⌊",
+  "&lfr;": "𝔩",
+  "&lg;": "≶",
+  "&lgE;": "⪑",
+  "&lhard;": "↽",
+  "&lharu;": "↼",
+  "&lharul;": "⥪",
+  "&lhblk;": "▄",
+  "&ljcy;": "љ",
+  "&ll;": "≪",
+  "&llarr;": "⇇",
+  "&llcorner;": "⌞",
+  "&llhard;": "⥫",
+  "&lltri;": "◺",
+  "&lmidot;": "ŀ",
+  "&lmoust;": "⎰",
+  "&lmoustache;": "⎰",
+  "&lnE;": "≨",
+  "&lnap;": "⪉",
+  "&lnapprox;": "⪉",
+  "&lne;": "⪇",
+  "&lneq;": "⪇",
+  "&lneqq;": "≨",
+  "&lnsim;": "⋦",
+  "&loang;": "⟬",
+  "&loarr;": "⇽",
+  "&lobrk;": "⟦",
+  "&longleftarrow;": "⟵",
+  "&longleftrightarrow;": "⟷",
+  "&longmapsto;": "⟼",
+  "&longrightarrow;": "⟶",
+  "&looparrowleft;": "↫",
+  "&looparrowright;": "↬",
+  "&lopar;": "⦅",
+  "&lopf;": "𝕝",
+  "&loplus;": "⨭",
+  "&lotimes;": "⨴",
+  "&lowast;": "∗",
+  "&lowbar;": "_",
+  "&loz;": "◊",
+  "&lozenge;": "◊",
+  "&lozf;": "⧫",
+  "&lpar;": "(",
+  "&lparlt;": "⦓",
+  "&lrarr;": "⇆",
+  "&lrcorner;": "⌟",
+  "&lrhar;": "⇋",
+  "&lrhard;": "⥭",
+  "&lrm;": "‎",
+  "&lrtri;": "⊿",
+  "&lsaquo;": "‹",
+  "&lscr;": "𝓁",
+  "&lsh;": "↰",
+  "&lsim;": "≲",
+  "&lsime;": "⪍",
+  "&lsimg;": "⪏",
+  "&lsqb;": "[",
+  "&lsquo;": "‘",
+  "&lsquor;": "‚",
+  "&lstrok;": "ł",
+  "&lt;": "<",
+  "&ltcc;": "⪦",
+  "&ltcir;": "⩹",
+  "&ltdot;": "⋖",
+  "&lthree;": "⋋",
+  "&ltimes;": "⋉",
+  "&ltlarr;": "⥶",
+  "&ltquest;": "⩻",
+  "&ltrPar;": "⦖",
+  "&ltri;": "◃",
+  "&ltrie;": "⊴",
+  "&ltrif;": "◂",
+  "&lurdshar;": "⥊",
+  "&luruhar;": "⥦",
+  "&lvertneqq;": "≨︀",
+  "&lvnE;": "≨︀",
+  "&mDDot;": "∺",
+  "&macr;": "¯",
+  "&male;": "♂",
+  "&malt;": "✠",
+  "&maltese;": "✠",
+  "&map;": "↦",
+  "&mapsto;": "↦",
+  "&mapstodown;": "↧",
+  "&mapstoleft;": "↤",
+  "&mapstoup;": "↥",
+  "&marker;": "▮",
+  "&mcomma;": "⨩",
+  "&mcy;": "м",
+  "&mdash;": "—",
+  "&measuredangle;": "∡",
+  "&mfr;": "𝔪",
+  "&mho;": "℧",
+  "&micro;": "µ",
+  "&mid;": "∣",
+  "&midast;": "*",
+  "&midcir;": "⫰",
+  "&middot;": "·",
+  "&minus;": "−",
+  "&minusb;": "⊟",
+  "&minusd;": "∸",
+  "&minusdu;": "⨪",
+  "&mlcp;": "⫛",
+  "&mldr;": "…",
+  "&mnplus;": "∓",
+  "&models;": "⊧",
+  "&mopf;": "𝕞",
+  "&mp;": "∓",
+  "&mscr;": "𝓂",
+  "&mstpos;": "∾",
+  "&mu;": "μ",
+  "&multimap;": "⊸",
+  "&mumap;": "⊸",
+  "&nGg;": "⋙̸",
+  "&nGt;": "≫⃒",
+  "&nGtv;": "≫̸",
+  "&nLeftarrow;": "⇍",
+  "&nLeftrightarrow;": "⇎",
+  "&nLl;": "⋘̸",
+  "&nLt;": "≪⃒",
+  "&nLtv;": "≪̸",
+  "&nRightarrow;": "⇏",
+  "&nVDash;": "⊯",
+  "&nVdash;": "⊮",
+  "&nabla;": "∇",
+  "&nacute;": "ń",
+  "&nang;": "∠⃒",
+  "&nap;": "≉",
+  "&napE;": "⩰̸",
+  "&napid;": "≋̸",
+  "&napos;": "ʼn",
+  "&napprox;": "≉",
+  "&natur;": "♮",
+  "&natural;": "♮",
+  "&naturals;": "ℕ",
+  "&nbsp;": " ",
+  "&nbump;": "≎̸",
+  "&nbumpe;": "≏̸",
+  "&ncap;": "⩃",
+  "&ncaron;": "ň",
+  "&ncedil;": "ņ",
+  "&ncong;": "≇",
+  "&ncongdot;": "⩭̸",
+  "&ncup;": "⩂",
+  "&ncy;": "н",
+  "&ndash;": "–",
+  "&ne;": "≠",
+  "&neArr;": "⇗",
+  "&nearhk;": "⤤",
+  "&nearr;": "↗",
+  "&nearrow;": "↗",
+  "&nedot;": "≐̸",
+  "&nequiv;": "≢",
+  "&nesear;": "⤨",
+  "&nesim;": "≂̸",
+  "&nexist;": "∄",
+  "&nexists;": "∄",
+  "&nfr;": "𝔫",
+  "&ngE;": "≧̸",
+  "&nge;": "≱",
+  "&ngeq;": "≱",
+  "&ngeqq;": "≧̸",
+  "&ngeqslant;": "⩾̸",
+  "&nges;": "⩾̸",
+  "&ngsim;": "≵",
+  "&ngt;": "≯",
+  "&ngtr;": "≯",
+  "&nhArr;": "⇎",
+  "&nharr;": "↮",
+  "&nhpar;": "⫲",
+  "&ni;": "∋",
+  "&nis;": "⋼",
+  "&nisd;": "⋺",
+  "&niv;": "∋",
+  "&njcy;": "њ",
+  "&nlArr;": "⇍",
+  "&nlE;": "≦̸",
+  "&nlarr;": "↚",
+  "&nldr;": "‥",
+  "&nle;": "≰",
+  "&nleftarrow;": "↚",
+  "&nleftrightarrow;": "↮",
+  "&nleq;": "≰",
+  "&nleqq;": "≦̸",
+  "&nleqslant;": "⩽̸",
+  "&nles;": "⩽̸",
+  "&nless;": "≮",
+  "&nlsim;": "≴",
+  "&nlt;": "≮",
+  "&nltri;": "⋪",
+  "&nltrie;": "⋬",
+  "&nmid;": "∤",
+  "&nopf;": "𝕟",
+  "&not;": "¬",
+  "&notin;": "∉",
+  "&notinE;": "⋹̸",
+  "&notindot;": "⋵̸",
+  "&notinva;": "∉",
+  "&notinvb;": "⋷",
+  "&notinvc;": "⋶",
+  "&notni;": "∌",
+  "&notniva;": "∌",
+  "&notnivb;": "⋾",
+  "&notnivc;": "⋽",
+  "&npar;": "∦",
+  "&nparallel;": "∦",
+  "&nparsl;": "⫽⃥",
+  "&npart;": "∂̸",
+  "&npolint;": "⨔",
+  "&npr;": "⊀",
+  "&nprcue;": "⋠",
+  "&npre;": "⪯̸",
+  "&nprec;": "⊀",
+  "&npreceq;": "⪯̸",
+  "&nrArr;": "⇏",
+  "&nrarr;": "↛",
+  "&nrarrc;": "⤳̸",
+  "&nrarrw;": "↝̸",
+  "&nrightarrow;": "↛",
+  "&nrtri;": "⋫",
+  "&nrtrie;": "⋭",
+  "&nsc;": "⊁",
+  "&nsccue;": "⋡",
+  "&nsce;": "⪰̸",
+  "&nscr;": "𝓃",
+  "&nshortmid;": "∤",
+  "&nshortparallel;": "∦",
+  "&nsim;": "≁",
+  "&nsime;": "≄",
+  "&nsimeq;": "≄",
+  "&nsmid;": "∤",
+  "&nspar;": "∦",
+  "&nsqsube;": "⋢",
+  "&nsqsupe;": "⋣",
+  "&nsub;": "⊄",
+  "&nsubE;": "⫅̸",
+  "&nsube;": "⊈",
+  "&nsubset;": "⊂⃒",
+  "&nsubseteq;": "⊈",
+  "&nsubseteqq;": "⫅̸",
+  "&nsucc;": "⊁",
+  "&nsucceq;": "⪰̸",
+  "&nsup;": "⊅",
+  "&nsupE;": "⫆̸",
+  "&nsupe;": "⊉",
+  "&nsupset;": "⊃⃒",
+  "&nsupseteq;": "⊉",
+  "&nsupseteqq;": "⫆̸",
+  "&ntgl;": "≹",
+  "&ntilde;": "ñ",
+  "&ntlg;": "≸",
+  "&ntriangleleft;": "⋪",
+  "&ntrianglelefteq;": "⋬",
+  "&ntriangleright;": "⋫",
+  "&ntrianglerighteq;": "⋭",
+  "&nu;": "ν",
+  "&num;": "#",
+  "&numero;": "№",
+  "&numsp;": " ",
+  "&nvDash;": "⊭",
+  "&nvHarr;": "⤄",
+  "&nvap;": "≍⃒",
+  "&nvdash;": "⊬",
+  "&nvge;": "≥⃒",
+  "&nvgt;": ">⃒",
+  "&nvinfin;": "⧞",
+  "&nvlArr;": "⤂",
+  "&nvle;": "≤⃒",
+  "&nvlt;": "<⃒",
+  "&nvltrie;": "⊴⃒",
+  "&nvrArr;": "⤃",
+  "&nvrtrie;": "⊵⃒",
+  "&nvsim;": "∼⃒",
+  "&nwArr;": "⇖",
+  "&nwarhk;": "⤣",
+  "&nwarr;": "↖",
+  "&nwarrow;": "↖",
+  "&nwnear;": "⤧",
+  "&oS;": "Ⓢ",
+  "&oacute;": "ó",
+  "&oast;": "⊛",
+  "&ocir;": "⊚",
+  "&ocirc;": "ô",
+  "&ocy;": "о",
+  "&odash;": "⊝",
+  "&odblac;": "ő",
+  "&odiv;": "⨸",
+  "&odot;": "⊙",
+  "&odsold;": "⦼",
+  "&oelig;": "œ",
+  "&ofcir;": "⦿",
+  "&ofr;": "𝔬",
+  "&ogon;": "˛",
+  "&ograve;": "ò",
+  "&ogt;": "⧁",
+  "&ohbar;": "⦵",
+  "&ohm;": "Ω",
+  "&oint;": "∮",
+  "&olarr;": "↺",
+  "&olcir;": "⦾",
+  "&olcross;": "⦻",
+  "&oline;": "‾",
+  "&olt;": "⧀",
+  "&omacr;": "ō",
+  "&omega;": "ω",
+  "&omicron;": "ο",
+  "&omid;": "⦶",
+  "&ominus;": "⊖",
+  "&oopf;": "𝕠",
+  "&opar;": "⦷",
+  "&operp;": "⦹",
+  "&oplus;": "⊕",
+  "&or;": "∨",
+  "&orarr;": "↻",
+  "&ord;": "⩝",
+  "&order;": "ℴ",
+  "&orderof;": "ℴ",
+  "&ordf;": "ª",
+  "&ordm;": "º",
+  "&origof;": "⊶",
+  "&oror;": "⩖",
+  "&orslope;": "⩗",
+  "&orv;": "⩛",
+  "&oscr;": "ℴ",
+  "&oslash;": "ø",
+  "&osol;": "⊘",
+  "&otilde;": "õ",
+  "&otimes;": "⊗",
+  "&otimesas;": "⨶",
+  "&ouml;": "ö",
+  "&ovbar;": "⌽",
+  "&par;": "∥",
+  "&para;": "¶",
+  "&parallel;": "∥",
+  "&parsim;": "⫳",
+  "&parsl;": "⫽",
+  "&part;": "∂",
+  "&pcy;": "п",
+  "&percnt;": "%",
+  "&period;": ".",
+  "&permil;": "‰",
+  "&perp;": "⊥",
+  "&pertenk;": "‱",
+  "&pfr;": "𝔭",
+  "&phi;": "φ",
+  "&phiv;": "ϕ",
+  "&phmmat;": "ℳ",
+  "&phone;": "☎",
+  "&pi;": "π",
+  "&pitchfork;": "⋔",
+  "&piv;": "ϖ",
+  "&planck;": "ℏ",
+  "&planckh;": "ℎ",
+  "&plankv;": "ℏ",
+  "&plus;": "+",
+  "&plusacir;": "⨣",
+  "&plusb;": "⊞",
+  "&pluscir;": "⨢",
+  "&plusdo;": "∔",
+  "&plusdu;": "⨥",
+  "&pluse;": "⩲",
+  "&plusmn;": "±",
+  "&plussim;": "⨦",
+  "&plustwo;": "⨧",
+  "&pm;": "±",
+  "&pointint;": "⨕",
+  "&popf;": "𝕡",
+  "&pound;": "£",
+  "&pr;": "≺",
+  "&prE;": "⪳",
+  "&prap;": "⪷",
+  "&prcue;": "≼",
+  "&pre;": "⪯",
+  "&prec;": "≺",
+  "&precapprox;": "⪷",
+  "&preccurlyeq;": "≼",
+  "&preceq;": "⪯",
+  "&precnapprox;": "⪹",
+  "&precneqq;": "⪵",
+  "&precnsim;": "⋨",
+  "&precsim;": "≾",
+  "&prime;": "′",
+  "&primes;": "ℙ",
+  "&prnE;": "⪵",
+  "&prnap;": "⪹",
+  "&prnsim;": "⋨",
+  "&prod;": "∏",
+  "&profalar;": "⌮",
+  "&profline;": "⌒",
+  "&profsurf;": "⌓",
+  "&prop;": "∝",
+  "&propto;": "∝",
+  "&prsim;": "≾",
+  "&prurel;": "⊰",
+  "&pscr;": "𝓅",
+  "&psi;": "ψ",
+  "&puncsp;": " ",
+  "&qfr;": "𝔮",
+  "&qint;": "⨌",
+  "&qopf;": "𝕢",
+  "&qprime;": "⁗",
+  "&qscr;": "𝓆",
+  "&quaternions;": "ℍ",
+  "&quatint;": "⨖",
+  "&quest;": "?",
+  "&questeq;": "≟",
+  "&quot;": "\"",
+  "&rAarr;": "⇛",
+  "&rArr;": "⇒",
+  "&rAtail;": "⤜",
+  "&rBarr;": "⤏",
+  "&rHar;": "⥤",
+  "&race;": "∽̱",
+  "&racute;": "ŕ",
+  "&radic;": "√",
+  "&raemptyv;": "⦳",
+  "&rang;": "⟩",
+  "&rangd;": "⦒",
+  "&range;": "⦥",
+  "&rangle;": "⟩",
+  "&raquo;": "»",
+  "&rarr;": "→",
+  "&rarrap;": "⥵",
+  "&rarrb;": "⇥",
+  "&rarrbfs;": "⤠",
+  "&rarrc;": "⤳",
+  "&rarrfs;": "⤞",
+  "&rarrhk;": "↪",
+  "&rarrlp;": "↬",
+  "&rarrpl;": "⥅",
+  "&rarrsim;": "⥴",
+  "&rarrtl;": "↣",
+  "&rarrw;": "↝",
+  "&ratail;": "⤚",
+  "&ratio;": "∶",
+  "&rationals;": "ℚ",
+  "&rbarr;": "⤍",
+  "&rbbrk;": "❳",
+  "&rbrace;": "}",
+  "&rbrack;": "]",
+  "&rbrke;": "⦌",
+  "&rbrksld;": "⦎",
+  "&rbrkslu;": "⦐",
+  "&rcaron;": "ř",
+  "&rcedil;": "ŗ",
+  "&rceil;": "⌉",
+  "&rcub;": "}",
+  "&rcy;": "р",
+  "&rdca;": "⤷",
+  "&rdldhar;": "⥩",
+  "&rdquo;": "”",
+  "&rdquor;": "”",
+  "&rdsh;": "↳",
+  "&real;": "ℜ",
+  "&realine;": "ℛ",
+  "&realpart;": "ℜ",
+  "&reals;": "ℝ",
+  "&rect;": "▭",
+  "&reg;": "®",
+  "&rfisht;": "⥽",
+  "&rfloor;": "⌋",
+  "&rfr;": "𝔯",
+  "&rhard;": "⇁",
+  "&rharu;": "⇀",
+  "&rharul;": "⥬",
+  "&rho;": "ρ",
+  "&rhov;": "ϱ",
+  "&rightarrow;": "→",
+  "&rightarrowtail;": "↣",
+  "&rightharpoondown;": "⇁",
+  "&rightharpoonup;": "⇀",
+  "&rightleftarrows;": "⇄",
+  "&rightleftharpoons;": "⇌",
+  "&rightrightarrows;": "⇉",
+  "&rightsquigarrow;": "↝",
+  "&rightthreetimes;": "⋌",
+  "&ring;": "˚",
+  "&risingdotseq;": "≓",
+  "&rlarr;": "⇄",
+  "&rlhar;": "⇌",
+  "&rlm;": "‏",
+  "&rmoust;": "⎱",
+  "&rmoustache;": "⎱",
+  "&rnmid;": "⫮",
+  "&roang;": "⟭",
+  "&roarr;": "⇾",
+  "&robrk;": "⟧",
+  "&ropar;": "⦆",
+  "&ropf;": "𝕣",
+  "&roplus;": "⨮",
+  "&rotimes;": "⨵",
+  "&rpar;": ")",
+  "&rpargt;": "⦔",
+  "&rppolint;": "⨒",
+  "&rrarr;": "⇉",
+  "&rsaquo;": "›",
+  "&rscr;": "𝓇",
+  "&rsh;": "↱",
+  "&rsqb;": "]",
+  "&rsquo;": "’",
+  "&rsquor;": "’",
+  "&rthree;": "⋌",
+  "&rtimes;": "⋊",
+  "&rtri;": "▹",
+  "&rtrie;": "⊵",
+  "&rtrif;": "▸",
+  "&rtriltri;": "⧎",
+  "&ruluhar;": "⥨",
+  "&rx;": "℞",
+  "&sacute;": "ś",
+  "&sbquo;": "‚",
+  "&sc;": "≻",
+  "&scE;": "⪴",
+  "&scap;": "⪸",
+  "&scaron;": "š",
+  "&sccue;": "≽",
+  "&sce;": "⪰",
+  "&scedil;": "ş",
+  "&scirc;": "ŝ",
+  "&scnE;": "⪶",
+  "&scnap;": "⪺",
+  "&scnsim;": "⋩",
+  "&scpolint;": "⨓",
+  "&scsim;": "≿",
+  "&scy;": "с",
+  "&sdot;": "⋅",
+  "&sdotb;": "⊡",
+  "&sdote;": "⩦",
+  "&seArr;": "⇘",
+  "&searhk;": "⤥",
+  "&searr;": "↘",
+  "&searrow;": "↘",
+  "&sect;": "§",
+  "&semi;": ";",
+  "&seswar;": "⤩",
+  "&setminus;": "∖",
+  "&setmn;": "∖",
+  "&sext;": "✶",
+  "&sfr;": "𝔰",
+  "&sfrown;": "⌢",
+  "&sharp;": "♯",
+  "&shchcy;": "щ",
+  "&shcy;": "ш",
+  "&shortmid;": "∣",
+  "&shortparallel;": "∥",
+  "&shy;": "­",
+  "&sigma;": "σ",
+  "&sigmaf;": "ς",
+  "&sigmav;": "ς",
+  "&sim;": "∼",
+  "&simdot;": "⩪",
+  "&sime;": "≃",
+  "&simeq;": "≃",
+  "&simg;": "⪞",
+  "&simgE;": "⪠",
+  "&siml;": "⪝",
+  "&simlE;": "⪟",
+  "&simne;": "≆",
+  "&simplus;": "⨤",
+  "&simrarr;": "⥲",
+  "&slarr;": "←",
+  "&smallsetminus;": "∖",
+  "&smashp;": "⨳",
+  "&smeparsl;": "⧤",
+  "&smid;": "∣",
+  "&smile;": "⌣",
+  "&smt;": "⪪",
+  "&smte;": "⪬",
+  "&smtes;": "⪬︀",
+  "&softcy;": "ь",
+  "&sol;": "/",
+  "&solb;": "⧄",
+  "&solbar;": "⌿",
+  "&sopf;": "𝕤",
+  "&spades;": "♠",
+  "&spadesuit;": "♠",
+  "&spar;": "∥",
+  "&sqcap;": "⊓",
+  "&sqcaps;": "⊓︀",
+  "&sqcup;": "⊔",
+  "&sqcups;": "⊔︀",
+  "&sqsub;": "⊏",
+  "&sqsube;": "⊑",
+  "&sqsubset;": "⊏",
+  "&sqsubseteq;": "⊑",
+  "&sqsup;": "⊐",
+  "&sqsupe;": "⊒",
+  "&sqsupset;": "⊐",
+  "&sqsupseteq;": "⊒",
+  "&squ;": "□",
+  "&square;": "□",
+  "&squarf;": "▪",
+  "&squf;": "▪",
+  "&srarr;": "→",
+  "&sscr;": "𝓈",
+  "&ssetmn;": "∖",
+  "&ssmile;": "⌣",
+  "&sstarf;": "⋆",
+  "&star;": "☆",
+  "&starf;": "★",
+  "&straightepsilon;": "ϵ",
+  "&straightphi;": "ϕ",
+  "&strns;": "¯",
+  "&sub;": "⊂",
+  "&subE;": "⫅",
+  "&subdot;": "⪽",
+  "&sube;": "⊆",
+  "&subedot;": "⫃",
+  "&submult;": "⫁",
+  "&subnE;": "⫋",
+  "&subne;": "⊊",
+  "&subplus;": "⪿",
+  "&subrarr;": "⥹",
+  "&subset;": "⊂",
+  "&subseteq;": "⊆",
+  "&subseteqq;": "⫅",
+  "&subsetneq;": "⊊",
+  "&subsetneqq;": "⫋",
+  "&subsim;": "⫇",
+  "&subsub;": "⫕",
+  "&subsup;": "⫓",
+  "&succ;": "≻",
+  "&succapprox;": "⪸",
+  "&succcurlyeq;": "≽",
+  "&succeq;": "⪰",
+  "&succnapprox;": "⪺",
+  "&succneqq;": "⪶",
+  "&succnsim;": "⋩",
+  "&succsim;": "≿",
+  "&sum;": "∑",
+  "&sung;": "♪",
+  "&sup1;": "¹",
+  "&sup2;": "²",
+  "&sup3;": "³",
+  "&sup;": "⊃",
+  "&supE;": "⫆",
+  "&supdot;": "⪾",
+  "&supdsub;": "⫘",
+  "&supe;": "⊇",
+  "&supedot;": "⫄",
+  "&suphsol;": "⟉",
+  "&suphsub;": "⫗",
+  "&suplarr;": "⥻",
+  "&supmult;": "⫂",
+  "&supnE;": "⫌",
+  "&supne;": "⊋",
+  "&supplus;": "⫀",
+  "&supset;": "⊃",
+  "&supseteq;": "⊇",
+  "&supseteqq;": "⫆",
+  "&supsetneq;": "⊋",
+  "&supsetneqq;": "⫌",
+  "&supsim;": "⫈",
+  "&supsub;": "⫔",
+  "&supsup;": "⫖",
+  "&swArr;": "⇙",
+  "&swarhk;": "⤦",
+  "&swarr;": "↙",
+  "&swarrow;": "↙",
+  "&swnwar;": "⤪",
+  "&szlig;": "ß",
+  "&target;": "⌖",
+  "&tau;": "τ",
+  "&tbrk;": "⎴",
+  "&tcaron;": "ť",
+  "&tcedil;": "ţ",
+  "&tcy;": "т",
+  "&tdot;": "⃛",
+  "&telrec;": "⌕",
+  "&tfr;": "𝔱",
+  "&there4;": "∴",
+  "&therefore;": "∴",
+  "&theta;": "θ",
+  "&thetasym;": "ϑ",
+  "&thetav;": "ϑ",
+  "&thickapprox;": "≈",
+  "&thicksim;": "∼",
+  "&thinsp;": " ",
+  "&thkap;": "≈",
+  "&thksim;": "∼",
+  "&thorn;": "þ",
+  "&tilde;": "˜",
+  "&times;": "×",
+  "&timesb;": "⊠",
+  "&timesbar;": "⨱",
+  "&timesd;": "⨰",
+  "&tint;": "∭",
+  "&toea;": "⤨",
+  "&top;": "⊤",
+  "&topbot;": "⌶",
+  "&topcir;": "⫱",
+  "&topf;": "𝕥",
+  "&topfork;": "⫚",
+  "&tosa;": "⤩",
+  "&tprime;": "‴",
+  "&trade;": "™",
+  "&triangle;": "▵",
+  "&triangledown;": "▿",
+  "&triangleleft;": "◃",
+  "&trianglelefteq;": "⊴",
+  "&triangleq;": "≜",
+  "&triangleright;": "▹",
+  "&trianglerighteq;": "⊵",
+  "&tridot;": "◬",
+  "&trie;": "≜",
+  "&triminus;": "⨺",
+  "&triplus;": "⨹",
+  "&trisb;": "⧍",
+  "&tritime;": "⨻",
+  "&trpezium;": "⏢",
+  "&tscr;": "𝓉",
+  "&tscy;": "ц",
+  "&tshcy;": "ћ",
+  "&tstrok;": "ŧ",
+  "&twixt;": "≬",
+  "&twoheadleftarrow;": "↞",
+  "&twoheadrightarrow;": "↠",
+  "&uArr;": "⇑",
+  "&uHar;": "⥣",
+  "&uacute;": "ú",
+  "&uarr;": "↑",
+  "&ubrcy;": "ў",
+  "&ubreve;": "ŭ",
+  "&ucirc;": "û",
+  "&ucy;": "у",
+  "&udarr;": "⇅",
+  "&udblac;": "ű",
+  "&udhar;": "⥮",
+  "&ufisht;": "⥾",
+  "&ufr;": "𝔲",
+  "&ugrave;": "ù",
+  "&uharl;": "↿",
+  "&uharr;": "↾",
+  "&uhblk;": "▀",
+  "&ulcorn;": "⌜",
+  "&ulcorner;": "⌜",
+  "&ulcrop;": "⌏",
+  "&ultri;": "◸",
+  "&umacr;": "ū",
+  "&uml;": "¨",
+  "&uogon;": "ų",
+  "&uopf;": "𝕦",
+  "&uparrow;": "↑",
+  "&updownarrow;": "↕",
+  "&upharpoonleft;": "↿",
+  "&upharpoonright;": "↾",
+  "&uplus;": "⊎",
+  "&upsi;": "υ",
+  "&upsih;": "ϒ",
+  "&upsilon;": "υ",
+  "&upuparrows;": "⇈",
+  "&urcorn;": "⌝",
+  "&urcorner;": "⌝",
+  "&urcrop;": "⌎",
+  "&uring;": "ů",
+  "&urtri;": "◹",
+  "&uscr;": "𝓊",
+  "&utdot;": "⋰",
+  "&utilde;": "ũ",
+  "&utri;": "▵",
+  "&utrif;": "▴",
+  "&uuarr;": "⇈",
+  "&uuml;": "ü",
+  "&uwangle;": "⦧",
+  "&vArr;": "⇕",
+  "&vBar;": "⫨",
+  "&vBarv;": "⫩",
+  "&vDash;": "⊨",
+  "&vangrt;": "⦜",
+  "&varepsilon;": "ϵ",
+  "&varkappa;": "ϰ",
+  "&varnothing;": "∅",
+  "&varphi;": "ϕ",
+  "&varpi;": "ϖ",
+  "&varpropto;": "∝",
+  "&varr;": "↕",
+  "&varrho;": "ϱ",
+  "&varsigma;": "ς",
+  "&varsubsetneq;": "⊊︀",
+  "&varsubsetneqq;": "⫋︀",
+  "&varsupsetneq;": "⊋︀",
+  "&varsupsetneqq;": "⫌︀",
+  "&vartheta;": "ϑ",
+  "&vartriangleleft;": "⊲",
+  "&vartriangleright;": "⊳",
+  "&vcy;": "в",
+  "&vdash;": "⊢",
+  "&vee;": "∨",
+  "&veebar;": "⊻",
+  "&veeeq;": "≚",
+  "&vellip;": "⋮",
+  "&verbar;": "|",
+  "&vert;": "|",
+  "&vfr;": "𝔳",
+  "&vltri;": "⊲",
+  "&vnsub;": "⊂⃒",
+  "&vnsup;": "⊃⃒",
+  "&vopf;": "𝕧",
+  "&vprop;": "∝",
+  "&vrtri;": "⊳",
+  "&vscr;": "𝓋",
+  "&vsubnE;": "⫋︀",
+  "&vsubne;": "⊊︀",
+  "&vsupnE;": "⫌︀",
+  "&vsupne;": "⊋︀",
+  "&vzigzag;": "⦚",
+  "&wcirc;": "ŵ",
+  "&wedbar;": "⩟",
+  "&wedge;": "∧",
+  "&wedgeq;": "≙",
+  "&weierp;": "℘",
+  "&wfr;": "𝔴",
+  "&wopf;": "𝕨",
+  "&wp;": "℘",
+  "&wr;": "≀",
+  "&wreath;": "≀",
+  "&wscr;": "𝓌",
+  "&xcap;": "⋂",
+  "&xcirc;": "◯",
+  "&xcup;": "⋃",
+  "&xdtri;": "▽",
+  "&xfr;": "𝔵",
+  "&xhArr;": "⟺",
+  "&xharr;": "⟷",
+  "&xi;": "ξ",
+  "&xlArr;": "⟸",
+  "&xlarr;": "⟵",
+  "&xmap;": "⟼",
+  "&xnis;": "⋻",
+  "&xodot;": "⨀",
+  "&xopf;": "𝕩",
+  "&xoplus;": "⨁",
+  "&xotime;": "⨂",
+  "&xrArr;": "⟹",
+  "&xrarr;": "⟶",
+  "&xscr;": "𝓍",
+  "&xsqcup;": "⨆",
+  "&xuplus;": "⨄",
+  "&xutri;": "△",
+  "&xvee;": "⋁",
+  "&xwedge;": "⋀",
+  "&yacute;": "ý",
+  "&yacy;": "я",
+  "&ycirc;": "ŷ",
+  "&ycy;": "ы",
+  "&yen;": "¥",
+  "&yfr;": "𝔶",
+  "&yicy;": "ї",
+  "&yopf;": "𝕪",
+  "&yscr;": "𝓎",
+  "&yucy;": "ю",
+  "&yuml;": "ÿ",
+  "&zacute;": "ź",
+  "&zcaron;": "ž",
+  "&zcy;": "з",
+  "&zdot;": "ż",
+  "&zeetrf;": "ℨ",
+  "&zeta;": "ζ",
+  "&zfr;": "𝔷",
+  "&zhcy;": "ж",
+  "&zigrarr;": "⇝",
+  "&zopf;": "𝕫",
+  "&zscr;": "𝓏",
+  "&zwj;": "‍",
+  "&zwnj;": "‌"
+};
diff --git a/pkgs/markdown/lib/src/ast.dart b/pkgs/markdown/lib/src/ast.dart
new file mode 100644
index 0000000..e5530cb
--- /dev/null
+++ b/pkgs/markdown/lib/src/ast.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+typedef Resolver = Node? Function(String name, [String? title]);
+
+/// Base class for any AST item.
+///
+/// Roughly corresponds to Node in the DOM. Will be either an Element or Text.
+abstract class Node {
+  void accept(NodeVisitor visitor);
+
+  String get textContent;
+}
+
+/// A named tag that can contain other nodes.
+class Element implements Node {
+  final String tag;
+  final List<Node>? children;
+  final Map<String, String> attributes;
+  String? generatedId;
+  String? footnoteLabel;
+
+  /// Instantiates a [tag] Element with [children].
+  Element(this.tag, this.children) : attributes = {};
+
+  /// Instantiates an empty, self-closing [tag] Element.
+  Element.empty(this.tag)
+      : children = null,
+        attributes = {};
+
+  /// Instantiates a [tag] Element with no [children].
+  Element.withTag(this.tag)
+      : children = const [],
+        attributes = {};
+
+  /// Instantiates a [tag] Element with a single Text child.
+  Element.text(this.tag, String text)
+      : children = [Text(text)],
+        attributes = {};
+
+  /// Whether this element is self-closing.
+  bool get isEmpty => children == null;
+
+  @override
+  void accept(NodeVisitor visitor) {
+    if (visitor.visitElementBefore(this)) {
+      if (children != null) {
+        for (final child in children!) {
+          child.accept(visitor);
+        }
+      }
+      visitor.visitElementAfter(this);
+    }
+  }
+
+  @override
+  String get textContent {
+    final children = this.children;
+    return children == null
+        ? ''
+        : children.map((child) => child.textContent).join();
+  }
+}
+
+/// A plain text element.
+class Text implements Node {
+  final String text;
+
+  Text(this.text);
+
+  @override
+  void accept(NodeVisitor visitor) => visitor.visitText(this);
+
+  @override
+  String get textContent => text;
+}
+
+/// Inline content that has not been parsed into inline nodes (strong, links,
+/// etc).
+///
+/// These placeholder nodes should only remain in place while the block nodes
+/// of a document are still being parsed, in order to gather all reference link
+/// definitions.
+class UnparsedContent implements Node {
+  @override
+  final String textContent;
+
+  UnparsedContent(this.textContent);
+
+  @override
+  void accept(NodeVisitor visitor) {}
+}
+
+/// Visitor pattern for the AST.
+///
+/// Renderers or other AST transformers should implement this.
+abstract class NodeVisitor {
+  /// Called when a Text node has been reached.
+  void visitText(Text text);
+
+  /// Called when an Element has been reached, before its children have been
+  /// visited.
+  ///
+  /// Returns `false` to skip its children.
+  bool visitElementBefore(Element element);
+
+  /// Called when an Element has been reached, after its children have been
+  /// visited.
+  ///
+  /// Will not be called if [visitElementBefore] returns `false`.
+  void visitElementAfter(Element element);
+}
diff --git a/pkgs/markdown/lib/src/block_parser.dart b/pkgs/markdown/lib/src/block_parser.dart
new file mode 100644
index 0000000..efe2352
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_parser.dart
@@ -0,0 +1,216 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'ast.dart';
+import 'block_syntaxes/block_syntax.dart';
+import 'block_syntaxes/blockquote_syntax.dart';
+import 'block_syntaxes/code_block_syntax.dart';
+import 'block_syntaxes/dummy_block_syntax.dart';
+import 'block_syntaxes/empty_block_syntax.dart';
+import 'block_syntaxes/header_syntax.dart';
+import 'block_syntaxes/horizontal_rule_syntax.dart';
+import 'block_syntaxes/html_block_syntax.dart';
+import 'block_syntaxes/link_reference_definition_syntax.dart';
+import 'block_syntaxes/ordered_list_syntax.dart';
+import 'block_syntaxes/paragraph_syntax.dart';
+import 'block_syntaxes/setext_header_syntax.dart';
+import 'block_syntaxes/unordered_list_syntax.dart';
+import 'document.dart';
+import 'line.dart';
+
+/// Maintains the internal state needed to parse a series of lines into blocks
+/// of Markdown suitable for further inline parsing.
+class BlockParser {
+  final List<Line> lines;
+
+  /// The Markdown document this parser is parsing.
+  final Document document;
+
+  /// The enabled block syntaxes.
+  ///
+  /// To turn a series of lines into blocks, each of these will be tried in
+  /// turn. Order matters here.
+  final List<BlockSyntax> blockSyntaxes = [];
+
+  /// Index of the current line.
+  int _pos = 0;
+
+  /// Starting line of the last unconsumed content.
+  int _start = 0;
+
+  /// The lines from [_start] to [_pos] (inclusive), it works as a buffer for
+  /// some blocks, for example:
+  /// When the [ParagraphSyntax] parsing process is interrupted by the
+  /// [SetextHeaderSyntax], so this structure is not a paragraph but a setext
+  /// heading, then the [ParagraphSyntax.parse] does not have to retreat the
+  /// reading position, it only needs to return `null`, the [SetextHeaderSyntax]
+  /// will pick up the lines in [linesToConsume].
+  List<Line> get linesToConsume => lines.getRange(_start, _pos + 1).toList();
+
+  /// Whether the parser has encountered a blank line between two block-level
+  /// elements.
+  bool encounteredBlankLine = false;
+
+  /// The collection of built-in block parsers.
+  final List<BlockSyntax> standardBlockSyntaxes = [
+    const EmptyBlockSyntax(),
+    const HtmlBlockSyntax(),
+    const SetextHeaderSyntax(),
+    const HeaderSyntax(),
+    const CodeBlockSyntax(),
+    const BlockquoteSyntax(),
+    const HorizontalRuleSyntax(),
+    const UnorderedListSyntax(),
+    const OrderedListSyntax(),
+    const LinkReferenceDefinitionSyntax(),
+    const ParagraphSyntax()
+  ];
+
+  BlockParser(this.lines, this.document) {
+    blockSyntaxes.addAll(document.blockSyntaxes);
+
+    if (document.withDefaultBlockSyntaxes) {
+      blockSyntaxes.addAll(standardBlockSyntaxes);
+    } else {
+      blockSyntaxes.add(const DummyBlockSyntax());
+    }
+  }
+
+  /// Gets the current line.
+  Line get current => lines[_pos];
+
+  /// Gets the line after the current one or `null` if there is none.
+  Line? get next {
+    // Don't read past the end.
+    if (_pos >= lines.length - 1) return null;
+    return lines[_pos + 1];
+  }
+
+  /// Gets the line that is [linesAhead] lines ahead of the current one, or
+  /// `null` if there is none.
+  ///
+  /// `peek(0)` is equivalent to [current].
+  ///
+  /// `peek(1)` is equivalent to [next].
+  Line? peek(int linesAhead) {
+    if (linesAhead < 0) {
+      throw ArgumentError('Invalid linesAhead: $linesAhead; must be >= 0.');
+    }
+    // Don't read past the end.
+    if (_pos >= lines.length - linesAhead) return null;
+    return lines[_pos + linesAhead];
+  }
+
+  /// Advances the reading position by one line.
+  void advance() {
+    _pos++;
+  }
+
+  /// Retreats the reading position by one line.
+  void retreat() {
+    _pos--;
+  }
+
+  /// Retreats the reading position by [count] lines.
+  void retreatBy(int count) {
+    _pos -= count;
+  }
+
+  bool get isDone => _pos >= lines.length;
+
+  /// Gets whether or not the current line matches the given pattern.
+  bool matches(RegExp regex) {
+    if (isDone) return false;
+    return regex.hasMatch(current.content);
+  }
+
+  /// Gets whether or not the next line matches the given pattern.
+  bool matchesNext(RegExp regex) {
+    if (next == null) return false;
+    return regex.hasMatch(next!.content);
+  }
+
+  /// The parent [BlockSyntax] when it is running inside a nested syntax.
+  BlockSyntax? get parentSyntax => _parentSyntax;
+  BlockSyntax? _parentSyntax;
+
+  /// Whether the [SetextHeadingSyntax] is disabled temporarily.
+  bool get setextHeadingDisabled => _setextHeadingDisabled;
+  bool _setextHeadingDisabled = false;
+
+  /// The [BlockSyntax] which is running now.
+  /// The value is `null` until we found the first matched [BlockSyntax].
+  BlockSyntax? get currentSyntax => _currentSyntax;
+  BlockSyntax? _currentSyntax;
+
+  /// The [BlockSyntax] which is running before the [currentSyntax].
+  BlockSyntax? get previousSyntax => _previousSyntax;
+  BlockSyntax? _previousSyntax;
+
+  List<Node> parseLines({
+    BlockSyntax? parentSyntax,
+    bool disabledSetextHeading = false,
+  }) {
+    _parentSyntax = parentSyntax;
+    _setextHeadingDisabled = disabledSetextHeading;
+
+    final blocks = <Node>[];
+
+    // If the `_pos` does not change before and after `parse()`, never try to
+    // parse the line at `_pos` with the same syntax again.
+    // For example the `TableSyntax` might not advance the `_pos` in `parse`
+    // method, beause of the header row does not match the delimiter row in the
+    // number of cells, which makes a table like structure not be recognized.
+    BlockSyntax? neverMatch;
+
+    var iterationsWithoutProgress = 0;
+    while (!isDone) {
+      final positionBefore = _pos;
+      for (final syntax in blockSyntaxes) {
+        if (neverMatch == syntax) {
+          continue;
+        }
+
+        if (syntax.canParse(this)) {
+          _previousSyntax = _currentSyntax;
+          _currentSyntax = syntax;
+          final block = syntax.parse(this);
+          if (block != null) {
+            blocks.add(block);
+          }
+          neverMatch = _pos != positionBefore ? null : syntax;
+
+          if (block != null ||
+              syntax is EmptyBlockSyntax ||
+              syntax is LinkReferenceDefinitionSyntax) {
+            _start = _pos;
+          }
+
+          break;
+        }
+      }
+      // Count the number of iterations without progress.
+      // This ensures that we don't have an infinite loop. And if we have an
+      // infinite loop, it's easier to gracefully recover from an error, than
+      // it is to discover an kill an isolate that's stuck in an infinite loop.
+      // Technically, it should be perfectly safe to remove this check
+      // But as it's possible to inject custom BlockSyntax implementations and
+      // combine existing ones, it is hard to promise that no combination can't
+      // trigger an infinite loop
+      if (positionBefore == _pos) {
+        iterationsWithoutProgress++;
+        if (iterationsWithoutProgress > 2) {
+          // If this happens we throw an error to avoid having the parser
+          // running in an infinite loop. An error is easier to handle.
+          // If you see this error in production please file a bug!
+          throw AssertionError('BlockParser.parseLines is not advancing');
+        }
+      } else {
+        iterationsWithoutProgress = 0;
+      }
+    }
+
+    return blocks;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/alert_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/alert_block_syntax.dart
new file mode 100644
index 0000000..0f4f5b1
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/alert_block_syntax.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+import 'code_block_syntax.dart';
+import 'paragraph_syntax.dart';
+
+/// Parses GitHub Alerts blocks.
+///
+/// See also: https://docs.github.com/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts
+class AlertBlockSyntax extends BlockSyntax {
+  const AlertBlockSyntax();
+
+  @override
+  RegExp get pattern => alertPattern;
+
+  @override
+  bool canParse(BlockParser parser) {
+    return alertPattern.hasMatch(parser.current.content);
+  }
+
+  /// Whether this alert ends with a lazy continuation line.
+  ///
+  /// The definition of lazy continuation lines:
+  /// https://spec.commonmark.org/0.30/#lazy-continuation-line
+  static bool _lazyContinuation = false;
+  static final _contentLineRegExp = RegExp(r'>?\s?(.*)*');
+
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    // Grab all of the lines that form the alert, stripping off the ">".
+    final childLines = <Line>[];
+    _lazyContinuation = false;
+
+    while (!parser.isDone) {
+      final lineContent = parser.current.content.trimLeft();
+      final strippedContent = lineContent.replaceFirst(RegExp(r'^>?\s*'), '');
+      final match = strippedContent.isEmpty && !lineContent.startsWith('>')
+          ? null
+          : _contentLineRegExp.firstMatch(strippedContent);
+      if (match != null) {
+        childLines.add(Line(strippedContent));
+        parser.advance();
+        _lazyContinuation = false;
+        continue;
+      }
+
+      final lastLine = childLines.isEmpty ? Line('') : childLines.last;
+
+      // A paragraph continuation is OK. This is content that cannot be parsed
+      // as any other syntax except Paragraph, and it doesn't match the bar in
+      // a Setext header.
+      // Because indented code blocks cannot interrupt paragraphs, a line
+      // matched CodeBlockSyntax is also paragraph continuation text.
+      final otherMatched =
+          parser.blockSyntaxes.firstWhere((s) => s.canParse(parser));
+      if ((otherMatched is ParagraphSyntax &&
+              !lastLine.isBlankLine &&
+              !codeFencePattern.hasMatch(lastLine.content)) ||
+          (otherMatched is CodeBlockSyntax &&
+              !indentPattern.hasMatch(lastLine.content))) {
+        childLines.add(parser.current);
+        _lazyContinuation = true;
+        parser.advance();
+      } else {
+        break;
+      }
+    }
+
+    return childLines;
+  }
+
+  @override
+  Node parse(BlockParser parser) {
+    // Parse the alert type from the first line.
+    final type =
+        pattern.firstMatch(parser.current.content)!.group(1)!.toLowerCase();
+    parser.advance();
+    final childLines = parseChildLines(parser);
+    // Recursively parse the contents of the alert.
+    final children = BlockParser(childLines, parser.document).parseLines(
+      // The setext heading underline cannot be a lazy continuation line in a
+      // block quote.
+      // https://spec.commonmark.org/0.30/#example-93
+      disabledSetextHeading: _lazyContinuation,
+      parentSyntax: this,
+    );
+
+    // Mapping the alert title text.
+    const typeTextMap = {
+      'note': 'Note',
+      'tip': 'Tip',
+      'important': 'Important',
+      'caution': 'Caution',
+      'warning': 'Warning',
+    };
+    final titleText = typeTextMap[type]!;
+    final titleElement = Element('p', [Text(titleText)])
+      ..attributes['class'] = 'markdown-alert-title';
+    final elementClass = 'markdown-alert markdown-alert-$type';
+    return Element('div', [titleElement, ...children])
+      ..attributes['class'] = elementClass;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/block_syntax.dart
new file mode 100644
index 0000000..947824a
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/block_syntax.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+
+abstract class BlockSyntax {
+  const BlockSyntax();
+
+  /// Gets the regex used to identify the beginning of this block, if any.
+  RegExp get pattern;
+
+  bool canEndBlock(BlockParser parser) => true;
+
+  bool canParse(BlockParser parser) {
+    return pattern.hasMatch(parser.current.content);
+  }
+
+  Node? parse(BlockParser parser);
+
+  List<Line?> parseChildLines(BlockParser parser) {
+    // Grab all of the lines that form the block element.
+    final childLines = <Line?>[];
+
+    while (!parser.isDone) {
+      final match = pattern.firstMatch(parser.current.content);
+      if (match == null) break;
+      childLines.add(parser.current);
+      parser.advance();
+    }
+
+    return childLines;
+  }
+
+  /// Returns the block which interrupts current syntax parsing if there is one,
+  /// otherwise returns `null`.
+  ///
+  /// Make sure to check if [parser] `isDone` is `false` first.
+  BlockSyntax? interruptedBy(BlockParser parser) {
+    for (final syntax in parser.blockSyntaxes) {
+      if (syntax.canParse(parser) && syntax.canEndBlock(parser)) {
+        return syntax;
+      }
+    }
+    return null;
+  }
+
+  /// Gets whether or not [parser]'s current line should end the previous block.
+  static bool isAtBlockEnd(BlockParser parser) {
+    if (parser.isDone) return true;
+    return parser.blockSyntaxes
+        .any((s) => s.canParse(parser) && s.canEndBlock(parser));
+  }
+
+  /// Generates a valid HTML anchor from the inner text of [element].
+  static String generateAnchorHash(Element element) =>
+      element.children!.first.textContent
+          .toLowerCase()
+          .trim()
+          .replaceAll(RegExp('[^a-z0-9 _-]'), '')
+          .replaceAll(RegExp(r'\s'), '-');
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/blockquote_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/blockquote_syntax.dart
new file mode 100644
index 0000000..afbe23a
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/blockquote_syntax.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../charcode.dart';
+import '../line.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'block_syntax.dart';
+import 'code_block_syntax.dart';
+import 'paragraph_syntax.dart';
+
+/// Parses email-style blockquotes: `> quote`.
+class BlockquoteSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => blockquotePattern;
+
+  const BlockquoteSyntax();
+
+  /// Whether this blockquote ends with a lazy continuation line.
+  // The definition of lazy continuation lines:
+  // https://spec.commonmark.org/0.30/#lazy-continuation-line
+  static var _lazyContinuation = false;
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    // Grab all of the lines that form the blockquote, stripping off the ">".
+    final childLines = <Line>[];
+    _lazyContinuation = false;
+
+    while (!parser.isDone) {
+      final currentLine = parser.current;
+      final match = pattern.firstMatch(parser.current.content);
+      if (match != null) {
+        // A block quote marker consists of a `>` together with an optional
+        // following space of indentation, see
+        // https://spec.commonmark.org/0.30/#block-quote-marker.
+        final markerStart = match.match.indexOf('>');
+        int markerEnd;
+        if (currentLine.content.length > 1) {
+          var hasSpace = false;
+          // Check if there is a following space if the marker is not at the end
+          // of this line.
+          if (markerStart < currentLine.content.length - 1) {
+            final nextChar = currentLine.content.codeUnitAt(markerStart + 1);
+            hasSpace = nextChar == $tab || nextChar == $space;
+          }
+          markerEnd = markerStart + (hasSpace ? 2 : 1);
+        } else {
+          markerEnd = markerStart + 1;
+        }
+        childLines.add(Line(currentLine.content.substring(markerEnd)));
+        parser.advance();
+        _lazyContinuation = false;
+        continue;
+      }
+
+      final lastLine = childLines.last;
+
+      // A paragraph continuation is OK. This is content that cannot be parsed
+      // as any other syntax except Paragraph, and it doesn't match the bar in
+      // a Setext header.
+      // Because indented code blocks cannot interrupt paragraphs, a line
+      // matched CodeBlockSyntax is also paragraph continuation text.
+      final otherMatched =
+          parser.blockSyntaxes.firstWhere((s) => s.canParse(parser));
+      if ((otherMatched is ParagraphSyntax &&
+              !lastLine.isBlankLine &&
+              !codeFencePattern.hasMatch(lastLine.content)) ||
+          (otherMatched is CodeBlockSyntax &&
+              !indentPattern.hasMatch(lastLine.content))) {
+        childLines.add(parser.current);
+        _lazyContinuation = true;
+        parser.advance();
+      } else {
+        break;
+      }
+    }
+
+    return childLines;
+  }
+
+  @override
+  Node parse(BlockParser parser) {
+    final childLines = parseChildLines(parser);
+
+    // Recursively parse the contents of the blockquote.
+    final children = BlockParser(childLines, parser.document).parseLines(
+      // The setext heading underline cannot be a lazy continuation line in a
+      // block quote.
+      // https://spec.commonmark.org/0.30/#example-93
+      disabledSetextHeading: _lazyContinuation,
+      parentSyntax: this,
+    );
+
+    return Element('blockquote', children);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/code_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/code_block_syntax.dart
new file mode 100644
index 0000000..1d30667
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/code_block_syntax.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'block_syntax.dart';
+
+/// Parses preformatted code blocks that are indented four spaces.
+class CodeBlockSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => indentPattern;
+
+  @override
+  bool canEndBlock(BlockParser parser) => false;
+
+  const CodeBlockSyntax();
+
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    final childLines = <Line>[];
+
+    while (!parser.isDone) {
+      final isBlankLine = parser.current.isBlankLine;
+      if (isBlankLine && _shouldEnd(parser)) {
+        break;
+      }
+
+      if (!isBlankLine &&
+          childLines.isNotEmpty &&
+          !pattern.hasMatch(parser.current.content)) {
+        break;
+      }
+
+      childLines.add(Line(
+        parser.current.content.dedent().text,
+        tabRemaining: parser.current.tabRemaining,
+      ));
+
+      parser.advance();
+    }
+
+    return childLines;
+  }
+
+  @override
+  Node parse(BlockParser parser) {
+    final childLines = parseChildLines(parser);
+
+    // The Markdown tests expect a trailing newline.
+    childLines.add(Line(''));
+
+    var content = childLines
+        .map((e) => e.content.prependSpace(e.tabRemaining ?? 0))
+        .join('\n');
+    if (parser.document.encodeHtml) {
+      content = escapeHtml(content, escapeApos: false);
+    }
+
+    return Element('pre', [Element.text('code', content)]);
+  }
+
+  bool _shouldEnd(BlockParser parser) {
+    var i = 1;
+    while (true) {
+      final nextLine = parser.peek(i);
+      // EOF
+      if (nextLine == null) {
+        return true;
+      }
+
+      // It does not matter how many blank lines between chunks:
+      // https://spec.commonmark.org/0.30/#example-111
+      if (nextLine.isBlankLine) {
+        i++;
+        continue;
+      }
+
+      return !pattern.hasMatch(nextLine.content);
+    }
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/dummy_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/dummy_block_syntax.dart
new file mode 100644
index 0000000..c08c8a8
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/dummy_block_syntax.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+/// Walks the parser forward through the lines does not match any [BlockSyntax].
+///
+/// Returns a [UnparsedContent] with the unmatched lines as `textContent`.
+class DummyBlockSyntax extends BlockSyntax {
+  const DummyBlockSyntax();
+
+  @override
+  RegExp get pattern => dummyPattern;
+
+  @override
+  bool canEndBlock(BlockParser parser) => false;
+
+  @override
+  bool canParse(BlockParser parser) => true;
+
+  @override
+  Node parse(BlockParser parser) {
+    final childLines = <String>[];
+
+    while (!BlockSyntax.isAtBlockEnd(parser)) {
+      childLines.add(parser.current.content);
+      parser.advance();
+    }
+
+    return UnparsedContent(childLines.join('\n'));
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/empty_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/empty_block_syntax.dart
new file mode 100644
index 0000000..54cc865
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/empty_block_syntax.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+class EmptyBlockSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => emptyPattern;
+
+  const EmptyBlockSyntax();
+
+  @override
+  Node? parse(BlockParser parser) {
+    parser.encounteredBlankLine = true;
+    parser.advance();
+
+    // Don't actually emit anything.
+    return null;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/fenced_blockquote_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/fenced_blockquote_syntax.dart
new file mode 100644
index 0000000..9e18d42
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/fenced_blockquote_syntax.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+/// Parses lines fenced by `>>>` to blockquotes
+class FencedBlockquoteSyntax extends BlockSyntax {
+  const FencedBlockquoteSyntax();
+
+  @override
+  RegExp get pattern => blockquoteFencePattern;
+
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    final childLines = <Line>[];
+    parser.advance();
+
+    while (!parser.isDone) {
+      final match = pattern.hasMatch(parser.current.content);
+      if (!match) {
+        childLines.add(parser.current);
+        parser.advance();
+      } else {
+        parser.advance();
+        break;
+      }
+    }
+
+    return childLines;
+  }
+
+  @override
+  Node? parse(BlockParser parser) {
+    final childLines = parseChildLines(parser);
+
+    // Recursively parse the contents of the blockquote.
+    final children = BlockParser(childLines, parser.document).parseLines();
+    return Element('blockquote', children);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart
new file mode 100644
index 0000000..cea1106
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/fenced_code_block_syntax.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'block_syntax.dart';
+
+/// Parses preformatted code blocks between two ~~~ or ``` sequences.
+///
+/// See the CommonMark spec:
+/// https://spec.commonmark.org/0.30/#fenced-code-blocks
+class FencedCodeBlockSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => codeFencePattern;
+
+  const FencedCodeBlockSyntax();
+
+  @override
+  Node parse(BlockParser parser) {
+    final openingFence = _FenceMatch.fromMatch(pattern.firstMatch(
+      escapePunctuation(parser.current.content),
+    )!);
+
+    var text = parseChildLines(
+      parser,
+      openingFence.marker,
+      openingFence.indent,
+    ).map((e) => e.content).join('\n');
+
+    if (parser.document.encodeHtml) {
+      text = escapeHtml(text, escapeApos: false);
+    }
+    if (text.isNotEmpty) {
+      text = '$text\n';
+    }
+
+    final code = Element.text('code', text);
+    if (openingFence.hasLanguage) {
+      var language = decodeHtmlCharacters(openingFence.language);
+      if (parser.document.encodeHtml) {
+        language = escapeHtmlAttribute(language);
+      }
+      code.attributes['class'] = 'language-$language';
+    }
+
+    return Element('pre', [code]);
+  }
+
+  String _removeIndentation(String content, int length) {
+    final text = content.replaceFirst(RegExp('^\\s{0,$length}'), '');
+    return content.substring(content.length - text.length);
+  }
+
+  @override
+  List<Line> parseChildLines(
+    BlockParser parser, [
+    String openingMarker = '',
+    int indent = 0,
+  ]) {
+    final childLines = <Line>[];
+
+    parser.advance();
+
+    _FenceMatch? closingFence;
+    while (!parser.isDone) {
+      final match = pattern.firstMatch(parser.current.content);
+      closingFence = match == null ? null : _FenceMatch.fromMatch(match);
+
+      // Closing code fences cannot have info strings:
+      // https://spec.commonmark.org/0.30/#example-147
+      if (closingFence == null ||
+          !closingFence.marker.startsWith(openingMarker) ||
+          closingFence.hasInfo) {
+        childLines.add(
+          Line(_removeIndentation(parser.current.content, indent)),
+        );
+        parser.advance();
+      } else {
+        parser.advance();
+        break;
+      }
+    }
+
+    // https://spec.commonmark.org/0.30/#example-127
+    // https://spec.commonmark.org/0.30/#example-128
+    if (closingFence == null &&
+        childLines.isNotEmpty &&
+        childLines.last.isBlankLine) {
+      childLines.removeLast();
+    }
+
+    return childLines;
+  }
+}
+
+class _FenceMatch {
+  _FenceMatch._({
+    required this.indent,
+    required this.marker,
+    required this.info,
+  });
+
+  factory _FenceMatch.fromMatch(RegExpMatch match) {
+    String marker;
+    String info;
+
+    if (match.namedGroup('backtick') != null) {
+      marker = match.namedGroup('backtick')!;
+      info = match.namedGroup('backtickInfo')!;
+    } else {
+      marker = match.namedGroup('tilde')!;
+      info = match.namedGroup('tildeInfo')!;
+    }
+
+    return _FenceMatch._(
+      indent: match[1]!.length,
+      marker: marker,
+      info: info.trim(),
+    );
+  }
+
+  final int indent;
+  final String marker;
+
+  // The info-string should be trimmed,
+  // https://spec.commonmark.org/0.30/#info-string.
+  final String info;
+
+  // The first word of the info string is typically used to specify the language
+  // of the code sample,
+  // https://spec.commonmark.org/0.30/#example-143.
+  String get language => info.split(' ').first;
+
+  bool get hasInfo => info.isNotEmpty;
+
+  bool get hasLanguage => language.isNotEmpty;
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/footnote_def_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/footnote_def_syntax.dart
new file mode 100644
index 0000000..3e59dcf
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/footnote_def_syntax.dart
@@ -0,0 +1,82 @@
+import '../ast.dart' show Element, Node;
+import '../block_parser.dart' show BlockParser;
+import '../line.dart';
+import '../patterns.dart' show dummyPattern, emptyPattern, footnotePattern;
+import 'block_syntax.dart' show BlockSyntax;
+
+/// The spec of GFM about footnotes is [missing](https://github.com/github/cmark-gfm/issues/283#issuecomment-1378868725).
+/// For online source code of cmark-gfm, see [master@c32ef78](https://github.com/github/cmark-gfm/blob/c32ef78/src/blocks.c#L1212).
+/// A Rust implementation is also [available](https://github.com/wooorm/markdown-rs/blob/2498e31eecead798efc649502bbf5f86feaa94be/src/construct/gfm_footnote_definition.rs).
+/// Footnote definition could contain multiple line-children and children could
+/// be separated by one empty line.
+/// Its first child-line would be the remaining part of the first line after
+/// taking definition leading, combining with other child lines parsed by
+/// [parseChildLines], is fed into [BlockParser].
+class FootnoteDefSyntax extends BlockSyntax {
+  const FootnoteDefSyntax();
+
+  @override
+  RegExp get pattern => footnotePattern;
+
+  @override
+  Node? parse(BlockParser parser) {
+    final current = parser.current.content;
+    final match = pattern.firstMatch(current)!;
+    final label = match[2]!;
+    final refs = parser.document.footnoteReferences;
+    refs[label] = 0;
+
+    final id = Uri.encodeComponent(label);
+    parser.advance();
+    final lines = [
+      Line(current.substring(match[0]!.length)),
+      ...parseChildLines(parser),
+    ];
+    final children = BlockParser(lines, parser.document).parseLines();
+    return Element('li', children)
+      ..attributes['id'] = 'fn-$id'
+      ..footnoteLabel = label;
+  }
+
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    final children = <String>[];
+    // As one empty line should not split footnote definition, use this flag.
+    var shouldBeBlock = false;
+    late final syntaxList = parser.blockSyntaxes
+        .where((s) => !_excludingPattern.contains(s.pattern));
+
+    // Every line is footnote's children util two blank lines or a block.
+    while (!parser.isDone) {
+      final line = parser.current.content;
+      if (line.trim().isEmpty) {
+        children.add(line);
+        parser.advance();
+        shouldBeBlock = true;
+        continue;
+      } else if (line.startsWith('    ')) {
+        children.add(line.substring(4));
+        parser.advance();
+        shouldBeBlock = false;
+      } else if (shouldBeBlock || _isBlock(syntaxList, line)) {
+        break;
+      } else {
+        children.add(line);
+        parser.advance();
+      }
+    }
+    return children.map(Line.new).toList(growable: false);
+  }
+
+  /// Patterns that would be used to decide if one line is a block.
+  static final _excludingPattern = {
+    emptyPattern,
+    dummyPattern,
+  };
+
+  /// Whether this line is any kind of block.
+  /// If `true`, the footnote block should end.
+  static bool _isBlock(Iterable<BlockSyntax> syntaxList, String line) {
+    return syntaxList.any((s) => s.pattern.hasMatch(line));
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/header_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/header_syntax.dart
new file mode 100644
index 0000000..197b417
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/header_syntax.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+/// Parses atx-style headers: `## Header ##`.
+class HeaderSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => headerPattern;
+
+  const HeaderSyntax();
+
+  @override
+  Node parse(BlockParser parser) {
+    final match = pattern.firstMatch(parser.current.content)!;
+    final matchedText = match[0]!;
+    final openMarker = match[1]!;
+    final closeMarker = match[2];
+    final level = openMarker.length;
+    final openMarkerStart = matchedText.indexOf(openMarker);
+    final openMarkerEnd = openMarkerStart + level;
+
+    String? content;
+    if (closeMarker == null) {
+      content = parser.current.content.substring(openMarkerEnd);
+    } else {
+      final closeMarkerStart = matchedText.lastIndexOf(closeMarker);
+      content = parser.current.content.substring(
+        openMarkerEnd,
+        closeMarkerStart,
+      );
+    }
+    content = content.trim();
+
+    // https://spec.commonmark.org/0.30/#example-79
+    if (closeMarker == null && RegExp(r'^#+$').hasMatch(content)) {
+      content = null;
+    }
+
+    parser.advance();
+    return Element('h$level', [if (content != null) UnparsedContent(content)]);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/header_with_id_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/header_with_id_syntax.dart
new file mode 100644
index 0000000..8e2c50b
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/header_with_id_syntax.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import 'block_syntax.dart';
+import 'header_syntax.dart';
+
+/// Parses atx-style headers, and adds generated IDs to the generated elements.
+class HeaderWithIdSyntax extends HeaderSyntax {
+  const HeaderWithIdSyntax();
+
+  @override
+  Node parse(BlockParser parser) {
+    final element = super.parse(parser) as Element;
+
+    if (element.children?.isNotEmpty ?? false) {
+      element.generatedId = BlockSyntax.generateAnchorHash(element);
+    }
+
+    return element;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/horizontal_rule_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/horizontal_rule_syntax.dart
new file mode 100644
index 0000000..12e7839
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/horizontal_rule_syntax.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+/// Parses horizontal rules like `---`, `_ _ _`, `*  *  *`, etc.
+class HorizontalRuleSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => hrPattern;
+
+  const HorizontalRuleSyntax();
+
+  @override
+  Node parse(BlockParser parser) {
+    parser.advance();
+    return Element.empty('hr');
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/html_block_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/html_block_syntax.dart
new file mode 100644
index 0000000..c1aa85c
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/html_block_syntax.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../line.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+import 'list_syntax.dart';
+
+/// Parse HTML blocks.
+// There are seven kinds of HTML block defined in the CommonMark spec:
+// https://spec.commonmark.org/0.30/#html-blocks.
+// These matching conditions and HTML block types mentioned in this syntax
+// correspond to these ones in the CommonMark spec.
+class HtmlBlockSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => htmlBlockPattern;
+
+  // All types of HTML blocks except type 7 may interrupt a paragraph, see the
+  // second paragraph after https://spec.commonmark.org/0.30/#example-148 for
+  // more detail.
+  @override
+  bool canEndBlock(BlockParser parser) =>
+      pattern.firstMatch(parser.current.content)!.namedGroup('condition_7') ==
+      null;
+
+  static final _endConditions = [
+    // For condition 1, it does not need to match the start tag, see
+    // https://spec.commonmark.org/0.30/#end-condition
+    RegExp('</(?:pre|script|style|textarea)>', caseSensitive: false),
+    RegExp('-->'),
+    RegExp(r'\?>'),
+    RegExp('>'),
+    RegExp(']]>'),
+    emptyPattern,
+    emptyPattern,
+  ];
+
+  const HtmlBlockSyntax();
+
+  @override
+  List<Line> parseChildLines(BlockParser parser) {
+    final lines = <Line>[];
+
+    final match = pattern.firstMatch(parser.current.content);
+    var matchedCondition = 0;
+    for (var i = 0; i < match!.groupCount; i++) {
+      if (match.group(i + 1) != null) {
+        matchedCondition = i;
+        break;
+      }
+    }
+
+    final endCondition = _endConditions[matchedCondition];
+    if (endCondition == emptyPattern) {
+      lines.add(parser.current);
+      parser.advance();
+
+      while (!parser.isDone && !endCondition.hasMatch(parser.current.content)) {
+        lines.add(parser.current);
+        parser.advance();
+      }
+    } else {
+      while (!parser.isDone) {
+        lines.add(parser.current);
+        if (endCondition.hasMatch(parser.current.content)) {
+          break;
+        }
+        parser.advance();
+      }
+      parser.advance();
+    }
+
+    // If the current line start an HTML block again, put them together with
+    // the previous HTML block.
+    if (!parser.isDone && pattern.hasMatch(parser.current.content)) {
+      lines.addAll(parseChildLines(parser));
+    }
+
+    return lines;
+  }
+
+  @override
+  Node parse(BlockParser parser) {
+    final childLines = parseChildLines(parser);
+
+    var text = childLines.map((e) => e.content).join('\n').trimRight();
+    if (parser.previousSyntax != null || parser.parentSyntax != null) {
+      text = '\n$text';
+      if (parser.parentSyntax is ListSyntax) {
+        text = '$text\n';
+      }
+    }
+
+    return Text(text);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/link_reference_definition_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/link_reference_definition_syntax.dart
new file mode 100644
index 0000000..5b2b1b5
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/link_reference_definition_syntax.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../document.dart';
+import '../line.dart';
+import '../link_parser.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'block_syntax.dart';
+
+class LinkReferenceDefinitionSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => linkReferenceDefinitionPattern;
+
+  @override
+  bool canEndBlock(BlockParser parser) => false;
+
+  const LinkReferenceDefinitionSyntax();
+
+  @override
+  Node? parse(BlockParser parser) {
+    final lines = <Line>[parser.current];
+    parser.advance();
+
+    while (!BlockSyntax.isAtBlockEnd(parser)) {
+      lines.add(parser.current);
+      parser.advance();
+    }
+
+    if (!_parseLinkReferenceDefinition(lines, parser)) {
+      parser.retreatBy(lines.length);
+    }
+
+    return null;
+  }
+
+  bool _parseLinkReferenceDefinition(List<Line> lines, BlockParser parser) {
+    final linkParser = LinkParser(lines.map((e) => e.content).join('\n'))
+      ..parseDefinition();
+
+    if (!linkParser.valid) {
+      return false;
+    }
+
+    // Retreat the parsing position back to where the link reference definition
+    // ends, so that the next syntax can continue parsing from there.
+    parser.retreatBy(linkParser.unconsumedLines);
+
+    final labelString = normalizeLinkLabel(linkParser.label!);
+
+    parser.document.linkReferences.putIfAbsent(
+      labelString,
+      () => LinkReference(
+        labelString,
+        linkParser.destination!,
+        linkParser.title,
+      ),
+    );
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/list_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/list_syntax.dart
new file mode 100644
index 0000000..534ca3e
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/list_syntax.dart
@@ -0,0 +1,353 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../charcode.dart';
+import '../line.dart';
+import '../patterns.dart';
+import '../text_parser.dart';
+import '../util.dart';
+import 'block_syntax.dart';
+import 'ordered_list_with_checkbox_syntax.dart';
+import 'unordered_list_with_checkbox_syntax.dart';
+
+class ListItem {
+  const ListItem(
+    this.lines, {
+    this.taskListItemState,
+  });
+
+  final List<Line> lines;
+  final TaskListItemState? taskListItemState;
+}
+
+enum TaskListItemState { checked, unchecked }
+
+/// Base class for both ordered and unordered lists.
+abstract class ListSyntax extends BlockSyntax {
+  @override
+  bool canParse(BlockParser parser) =>
+      pattern.hasMatch(parser.current.content) &&
+      !hrPattern.hasMatch(parser.current.content);
+
+  @override
+  bool canEndBlock(BlockParser parser) {
+    // An empty list cannot interrupt a paragraph. See
+    // https://spec.commonmark.org/0.30/#example-285.
+    // Ideally, [BlockSyntax.canEndBlock] should be changed to be a method
+    // which accepts a [BlockParser], but this would be a breaking change,
+    // so we're going with this temporarily.
+    final match = pattern.firstMatch(parser.current.content)!;
+
+    // Allow only lists starting with 1 to interrupt paragraphs, if it is an
+    // ordered list. See https://spec.commonmark.org/0.30/#example-304.
+    // But there should be an exception for nested ordered lists, for example:
+    // ```
+    // 1. one
+    // 2. two
+    //   3. three
+    //   4. four
+    // 5. five
+    // ```
+    if (parser.parentSyntax is! ListSyntax &&
+        match[1] != null &&
+        match[1] != '1') {
+      return false;
+    }
+
+    // An empty list item cannot interrupt a paragraph. See
+    // https://spec.commonmark.org/0.30/#example-285
+    return match[2]?.isNotEmpty ?? false;
+  }
+
+  const ListSyntax();
+
+  /// A list of patterns that can start a valid block within a list item.
+  static final blocksInList = [
+    blockquotePattern,
+    headerPattern,
+    hrPattern,
+    indentPattern,
+    listPattern,
+  ];
+
+  @override
+  Node parse(BlockParser parser) {
+    final match = pattern.firstMatch(parser.current.content);
+    final ordered = match![1] != null;
+
+    final taskListParserEnabled = this is UnorderedListWithCheckboxSyntax ||
+        this is OrderedListWithCheckboxSyntax;
+    final items = <ListItem>[];
+    var childLines = <Line>[];
+    TaskListItemState? taskListItemState;
+
+    void endItem() {
+      if (childLines.isNotEmpty) {
+        items.add(ListItem(childLines, taskListItemState: taskListItemState));
+        childLines = <Line>[];
+      }
+    }
+
+    String parseTaskListItem(String text) {
+      final pattern = RegExp(r'^ {0,3}\[([ xX])\][ \t]');
+
+      if (taskListParserEnabled && pattern.hasMatch(text)) {
+        return text.replaceFirstMapped(pattern, (match) {
+          taskListItemState = match[1] == ' '
+              ? TaskListItemState.unchecked
+              : TaskListItemState.checked;
+
+          return '';
+        });
+      } else {
+        taskListItemState = null;
+        return text;
+      }
+    }
+
+    late Match? possibleMatch;
+    bool tryMatch(RegExp pattern) {
+      possibleMatch = pattern.firstMatch(parser.current.content);
+      return possibleMatch != null;
+    }
+
+    String? listMarker;
+    int? indent;
+    // In case the first number in an ordered list is not 1, use it as the
+    // "start".
+    int? startNumber;
+
+    int? blankLines;
+
+    while (!parser.isDone) {
+      final currentIndent = parser.current.content.indentation() +
+          (parser.current.tabRemaining ?? 0);
+
+      if (parser.current.isBlankLine) {
+        childLines.add(parser.current);
+
+        if (blankLines != null) {
+          blankLines++;
+        }
+      } else if (indent != null && indent <= currentIndent) {
+        // A list item can begin with at most one blank line. See:
+        // https://spec.commonmark.org/0.30/#example-280
+        if (blankLines != null && blankLines > 1) {
+          break;
+        }
+
+        final indentedLine = parser.current.content.dedent(indent);
+
+        childLines.add(Line(
+          blankLines == null
+              ? indentedLine.text
+              : parseTaskListItem(indentedLine.text),
+          tabRemaining: indentedLine.tabRemaining,
+        ));
+      } else if (tryMatch(hrPattern)) {
+        // Horizontal rule takes precedence to a new list item.
+        break;
+      } else if (tryMatch(listPattern)) {
+        blankLines = null;
+        final match = possibleMatch!;
+        final textParser = TextParser(parser.current.content);
+        var precedingWhitespaces = textParser.moveThroughWhitespace();
+        final markerStart = textParser.pos;
+        final digits = match[1] ?? '';
+        if (digits.isNotEmpty) {
+          startNumber ??= int.parse(digits);
+          textParser.advanceBy(digits.length);
+        }
+        textParser.advance();
+
+        // See https://spec.commonmark.org/0.30/#ordered-list-marker
+        final marker = textParser.substring(
+          markerStart,
+          textParser.pos,
+        );
+
+        var isBlank = true;
+        var contentWhitespances = 0;
+        var containsTab = false;
+        int? contentBlockStart;
+
+        if (!textParser.isDone) {
+          containsTab = textParser.charAt() == $tab;
+          // Skip the first whitespace.
+          textParser.advance();
+          contentBlockStart = textParser.pos;
+          if (!textParser.isDone) {
+            contentWhitespances = textParser.moveThroughWhitespace();
+
+            if (!textParser.isDone) {
+              isBlank = false;
+            }
+          }
+        }
+
+        // Changing the bullet or ordered list delimiter starts a new list.
+        if (listMarker != null && listMarker.last() != marker.last()) {
+          break;
+        }
+
+        // End the current list item and start a new one.
+        endItem();
+
+        // Start a new list item, the last item will be ended up outside of the
+        // `while` loop.
+        listMarker = marker;
+        precedingWhitespaces += digits.length + 2;
+        if (isBlank) {
+          // See https://spec.commonmark.org/0.30/#example-278.
+          blankLines = 1;
+          indent = precedingWhitespaces;
+        } else if (contentWhitespances >= 4) {
+          // See https://spec.commonmark.org/0.30/#example-270.
+          //
+          // If the list item starts with indented code, we need to _not_ count
+          // any indentation past the required whitespace character.
+          indent = precedingWhitespaces;
+        } else {
+          indent = precedingWhitespaces + contentWhitespances;
+        }
+
+        taskListItemState = null;
+        var content = contentBlockStart != null && !isBlank
+            ? parseTaskListItem(textParser.substring(contentBlockStart))
+            : '';
+
+        if (content.isEmpty && containsTab) {
+          content = content.prependSpace(2);
+        }
+
+        childLines.add(Line(
+          content,
+          tabRemaining: containsTab ? 2 : null,
+        ));
+      } else if (BlockSyntax.isAtBlockEnd(parser)) {
+        // Done with the list.
+        break;
+      } else {
+        // If the previous item is a blank line, this means we're done with the
+        // list and are starting a new top-level paragraph.
+        if (childLines.isNotEmpty && childLines.last.isBlankLine) {
+          parser.encounteredBlankLine = true;
+          break;
+        }
+
+        // Anything else is paragraph continuation text.
+        childLines.add(parser.current);
+      }
+      parser.advance();
+    }
+
+    endItem();
+    final itemNodes = <Element>[];
+
+    items.forEach(_removeLeadingEmptyLine);
+    final anyEmptyLines = _removeTrailingEmptyLines(items);
+    var anyEmptyLinesBetweenBlocks = false;
+    var containsTaskList = false;
+    const taskListClass = 'task-list-item';
+
+    for (final item in items) {
+      Element? checkboxToInsert;
+      if (item.taskListItemState != null) {
+        containsTaskList = true;
+        checkboxToInsert = Element.withTag('input')
+          ..attributes['type'] = 'checkbox';
+        if (item.taskListItemState == TaskListItemState.checked) {
+          checkboxToInsert.attributes['checked'] = 'true';
+        }
+      }
+
+      final itemParser = BlockParser(item.lines, parser.document);
+      final children = itemParser.parseLines(parentSyntax: this);
+      final itemElement = checkboxToInsert == null
+          ? Element('li', children)
+          : (Element('li', _addCheckbox(children, checkboxToInsert))
+            ..attributes['class'] = taskListClass);
+
+      itemNodes.add(itemElement);
+      anyEmptyLinesBetweenBlocks =
+          anyEmptyLinesBetweenBlocks || itemParser.encounteredBlankLine;
+    }
+
+    // Must strip paragraph tags if the list is "tight".
+    // https://spec.commonmark.org/0.30/#lists
+    final listIsTight = !anyEmptyLines && !anyEmptyLinesBetweenBlocks;
+
+    if (listIsTight) {
+      // We must post-process the list items, converting any top-level paragraph
+      // elements to just text elements.
+      for (final item in itemNodes) {
+        final isTaskList = item.attributes['class'] == taskListClass;
+        final children = item.children;
+        if (children != null) {
+          Node? lastNode;
+          for (var i = 0; i < children.length; i++) {
+            final child = children[i];
+            if (child is Element && child.tag == 'p') {
+              final childContent = child.children!;
+              if (lastNode is Element && !isTaskList) {
+                childContent.insert(0, Text('\n'));
+              }
+
+              children
+                ..removeAt(i)
+                ..insertAll(i, childContent);
+            }
+
+            lastNode = child;
+          }
+        }
+      }
+    }
+
+    final listElement = Element(ordered ? 'ol' : 'ul', itemNodes);
+    if (ordered && startNumber != 1) {
+      listElement.attributes['start'] = '$startNumber';
+    }
+
+    if (containsTaskList) {
+      listElement.attributes['class'] = 'contains-task-list';
+    }
+    return listElement;
+  }
+
+  List<Node> _addCheckbox(List<Node> children, Element checkbox) {
+    if (children.isNotEmpty) {
+      final firstChild = children.first;
+      if (firstChild is Element && firstChild.tag == 'p') {
+        firstChild.children!.insert(0, checkbox);
+        return children;
+      }
+    }
+    return [checkbox, ...children];
+  }
+
+  void _removeLeadingEmptyLine(ListItem item) {
+    if (item.lines.isNotEmpty && item.lines.first.isBlankLine) {
+      item.lines.removeAt(0);
+    }
+  }
+
+  /// Removes any trailing empty lines and notes whether any items are separated
+  /// by such lines.
+  bool _removeTrailingEmptyLines(List<ListItem> items) {
+    var anyEmpty = false;
+    for (var i = 0; i < items.length; i++) {
+      if (items[i].lines.length == 1) continue;
+      while (items[i].lines.isNotEmpty && items[i].lines.last.isBlankLine) {
+        if (i < items.length - 1) {
+          anyEmpty = true;
+        }
+        items[i].lines.removeLast();
+      }
+    }
+    return anyEmpty;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/ordered_list_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/ordered_list_syntax.dart
new file mode 100644
index 0000000..53c4730
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/ordered_list_syntax.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../patterns.dart';
+import 'list_syntax.dart';
+
+/// Parses ordered lists.
+class OrderedListSyntax extends ListSyntax {
+  @override
+  RegExp get pattern => listPattern;
+
+  const OrderedListSyntax();
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/ordered_list_with_checkbox_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/ordered_list_with_checkbox_syntax.dart
new file mode 100644
index 0000000..8d865e8
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/ordered_list_with_checkbox_syntax.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'ordered_list_syntax.dart';
+
+/// Parses ordered lists with checkboxes.
+class OrderedListWithCheckboxSyntax extends OrderedListSyntax {
+  const OrderedListWithCheckboxSyntax();
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/paragraph_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/paragraph_syntax.dart
new file mode 100644
index 0000000..53d496d
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/paragraph_syntax.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+import 'setext_header_syntax.dart';
+
+/// Parses paragraphs of regular text.
+class ParagraphSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => dummyPattern;
+
+  @override
+  bool canEndBlock(BlockParser parser) => false;
+
+  const ParagraphSyntax();
+
+  @override
+  bool canParse(BlockParser parser) => true;
+
+  @override
+  Node? parse(BlockParser parser) {
+    final childLines = <String>[parser.current.content];
+
+    parser.advance();
+    var interruptedBySetextHeading = false;
+    // Eat until we hit something that ends a paragraph.
+    while (!parser.isDone) {
+      final syntax = interruptedBy(parser);
+      if (syntax != null) {
+        interruptedBySetextHeading = syntax is SetextHeaderSyntax;
+        break;
+      }
+      childLines.add(parser.current.content);
+      parser.advance();
+    }
+
+    // It is not a paragraph, but a setext heading.
+    if (interruptedBySetextHeading) {
+      return null;
+    }
+
+    final contents = UnparsedContent(childLines.join('\n').trimRight());
+    return Element('p', [contents]);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/setext_header_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/setext_header_syntax.dart
new file mode 100644
index 0000000..49f4eda
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/setext_header_syntax.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+import 'paragraph_syntax.dart';
+
+/// Parses setext-style headers.
+class SetextHeaderSyntax extends BlockSyntax {
+  @override
+  RegExp get pattern => setextPattern;
+
+  const SetextHeaderSyntax();
+
+  @override
+  bool canParse(BlockParser parser) {
+    final lastSyntax = parser.currentSyntax;
+    if (parser.setextHeadingDisabled || lastSyntax is! ParagraphSyntax) {
+      return false;
+    }
+    return pattern.hasMatch(parser.current.content);
+  }
+
+  @override
+  Node? parse(BlockParser parser) {
+    final lines = parser.linesToConsume;
+    if (lines.length < 2) {
+      return null;
+    }
+
+    // Remove the last line which is a marker.
+    lines.removeLast();
+
+    final marker = parser.current.content.trim();
+    final level = (marker[0] == '=') ? '1' : '2';
+    final content = lines.map((e) => e.content).join('\n').trimRight();
+
+    parser.advance();
+    return Element('h$level', [UnparsedContent(content)]);
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/setext_header_with_id_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/setext_header_with_id_syntax.dart
new file mode 100644
index 0000000..fffe992
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/setext_header_with_id_syntax.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import 'block_syntax.dart';
+import 'setext_header_syntax.dart';
+
+/// Parses setext-style headers, and adds generated IDs to the generated
+/// elements.
+class SetextHeaderWithIdSyntax extends SetextHeaderSyntax {
+  const SetextHeaderWithIdSyntax();
+
+  @override
+  Node parse(BlockParser parser) {
+    final element = super.parse(parser) as Element;
+    element.generatedId = BlockSyntax.generateAnchorHash(element);
+    return element;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/table_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/table_syntax.dart
new file mode 100644
index 0000000..89cbd90
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/table_syntax.dart
@@ -0,0 +1,225 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../block_parser.dart';
+import '../charcode.dart';
+import '../patterns.dart';
+import 'block_syntax.dart';
+
+/// Parses tables.
+class TableSyntax extends BlockSyntax {
+  @override
+  bool canEndBlock(BlockParser parser) => true;
+
+  @override
+  RegExp get pattern => dummyPattern;
+
+  const TableSyntax();
+
+  @override
+  bool canParse(BlockParser parser) {
+    // Note: matches *next* line, not the current one. We're looking for the
+    // bar separating the head row from the body rows.
+    return parser.matchesNext(tablePattern);
+  }
+
+  /// Parses a table into its three parts:
+  ///
+  /// * a head row of head cells (`<th>` cells)
+  /// * a divider of hyphens and pipes (not rendered)
+  /// * many body rows of body cells (`<td>` cells)
+  @override
+  Node? parse(BlockParser parser) {
+    final alignments = _parseAlignments(parser.next!.content);
+    final columnCount = alignments.length;
+    final headRow = _parseRow(parser, alignments, 'th');
+    if (headRow.children!.length != columnCount) {
+      parser.retreat();
+      return null;
+    }
+    final head = Element('thead', [headRow]);
+
+    // Advance past the divider of hyphens.
+    parser.advance();
+
+    final rows = <Element>[];
+    while (!parser.isDone && !BlockSyntax.isAtBlockEnd(parser)) {
+      final row = _parseRow(parser, alignments, 'td');
+      final children = row.children;
+      if (children != null) {
+        while (children.length < columnCount) {
+          // Insert synthetic empty cells.
+          children.add(Element('td', []));
+        }
+        while (children.length > columnCount) {
+          children.removeLast();
+        }
+      }
+      while (row.children!.length > columnCount) {
+        row.children!.removeLast();
+      }
+      rows.add(row);
+    }
+    if (rows.isEmpty) {
+      return Element('table', [head]);
+    } else {
+      final body = Element('tbody', rows);
+
+      return Element('table', [head, body]);
+    }
+  }
+
+  List<String?> _parseAlignments(String line) {
+    final columns = <String?>[];
+    // Set the value to `true` when hitting a non whitespace character other
+    // than the first pipe character.
+    var started = false;
+    var hitDash = false;
+    String? alignment;
+
+    for (var i = 0; i < line.length; i++) {
+      final char = line.codeUnitAt(i);
+      if (char == $space || char == $tab || (!started && char == $pipe)) {
+        continue;
+      }
+      started = true;
+
+      if (char == $colon) {
+        if (hitDash) {
+          alignment = alignment == 'left' ? 'center' : 'right';
+        } else {
+          alignment = 'left';
+        }
+      }
+
+      if (char == $pipe) {
+        columns.add(alignment);
+        hitDash = false;
+        alignment = null;
+      } else {
+        hitDash = true;
+      }
+    }
+
+    if (hitDash) {
+      columns.add(alignment);
+    }
+
+    return columns;
+  }
+
+  /// Parses a table row at the current line into a table row element, with
+  /// parsed table cells.
+  ///
+  /// [alignments] is used to annotate an alignment on each cell, and
+  /// [cellType] is used to declare either "td" or "th" cells.
+  Element _parseRow(
+    BlockParser parser,
+    List<String?> alignments,
+    String cellType,
+  ) {
+    final line = parser.current;
+    final cells = <String>[];
+    var index = _walkPastOpeningPipe(line.content);
+    final cellBuffer = StringBuffer();
+
+    while (true) {
+      if (index >= line.content.length) {
+        // This row ended without a trailing pipe, which is fine.
+        cells.add(cellBuffer.toString().trimRight());
+        cellBuffer.clear();
+        break;
+      }
+      final ch = line.content.codeUnitAt(index);
+      if (ch == $backslash) {
+        if (index == line.content.length - 1) {
+          // A table row ending in a backslash is not well-specified, but it
+          // looks like GitHub just allows the character as part of the text of
+          // the last cell.
+          cellBuffer.writeCharCode(ch);
+          cells.add(cellBuffer.toString().trimRight());
+          cellBuffer.clear();
+          break;
+        }
+        final escaped = line.content.codeUnitAt(index + 1);
+        if (escaped == $pipe) {
+          // GitHub Flavored Markdown has a strange bit here; the pipe is to be
+          // escaped before any other inline processing. One consequence, for
+          // example, is that "| `\|` |" should be parsed as a cell with a code
+          // element with text "|", rather than "\|". Most parsers are not
+          // compliant with this corner, but this is what is specified, and what
+          // GitHub does in practice.
+          cellBuffer.writeCharCode(escaped);
+        } else {
+          // The [InlineParser] will handle the escaping.
+          cellBuffer.writeCharCode(ch);
+          cellBuffer.writeCharCode(escaped);
+        }
+        index += 2;
+      } else if (ch == $pipe) {
+        cells.add(cellBuffer.toString().trimRight());
+        cellBuffer.clear();
+        // Walk forward past any whitespace which leads the next cell.
+        index++;
+        index = _walkPastWhitespace(line.content, index);
+        if (index >= line.content.length) {
+          // This row ended with a trailing pipe.
+          break;
+        }
+      } else {
+        cellBuffer.writeCharCode(ch);
+        index++;
+      }
+    }
+    parser.advance();
+    final row = [
+      for (final cell in cells) Element(cellType, [UnparsedContent(cell)])
+    ];
+
+    for (var i = 0; i < row.length && i < alignments.length; i++) {
+      if (alignments[i] == null) continue;
+      row[i].attributes['align'] = '${alignments[i]}';
+    }
+
+    return Element('tr', row);
+  }
+
+  /// Walks past whitespace in [line] starting at [index].
+  ///
+  /// Returns the index of the first non-whitespace character.
+  int _walkPastWhitespace(String line, int index) {
+    while (index < line.length) {
+      final ch = line.codeUnitAt(index);
+      if (ch != $space && ch != $tab) {
+        break;
+      }
+      index++;
+    }
+    return index;
+  }
+
+  /// Walks past the opening pipe (and any whitespace that surrounds it) in
+  /// [line].
+  ///
+  /// Returns the index of the first non-whitespace character after the pipe.
+  /// If no opening pipe is found, this just returns the index of the first
+  /// non-whitespace character.
+  int _walkPastOpeningPipe(String line) {
+    var index = 0;
+    while (index < line.length) {
+      final ch = line.codeUnitAt(index);
+      if (ch == $pipe) {
+        index++;
+        index = _walkPastWhitespace(line, index);
+      }
+      if (ch != $space && ch != $tab) {
+        // No leading pipe.
+        break;
+      }
+      index++;
+    }
+    return index;
+  }
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/unordered_list_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/unordered_list_syntax.dart
new file mode 100644
index 0000000..35dd670
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/unordered_list_syntax.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../block_parser.dart';
+import '../patterns.dart';
+import 'list_syntax.dart';
+
+/// Parses unordered lists.
+class UnorderedListSyntax extends ListSyntax {
+  @override
+  RegExp get pattern => listPattern;
+
+  @override
+  bool canParse(BlockParser parser) {
+    // Check if it matches `hrPattern`, otherwise it will produce an infinite
+    // loop if put `UnorderedListSyntax` or `UnorderedListWithCheckboxSyntax`
+    // bofore `HorizontalRuleSyntax` and parse:
+    // ```
+    // * * *
+    // ```
+    if (hrPattern.hasMatch(parser.current.content)) {
+      return false;
+    }
+
+    return pattern.hasMatch(parser.current.content);
+  }
+
+  const UnorderedListSyntax();
+}
diff --git a/pkgs/markdown/lib/src/block_syntaxes/unordered_list_with_checkbox_syntax.dart b/pkgs/markdown/lib/src/block_syntaxes/unordered_list_with_checkbox_syntax.dart
new file mode 100644
index 0000000..5f3ddf0
--- /dev/null
+++ b/pkgs/markdown/lib/src/block_syntaxes/unordered_list_with_checkbox_syntax.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'unordered_list_syntax.dart';
+
+/// Parses unordered lists with checkboxes.
+class UnorderedListWithCheckboxSyntax extends UnorderedListSyntax {
+  const UnorderedListWithCheckboxSyntax();
+}
diff --git a/pkgs/markdown/lib/src/charcode.dart b/pkgs/markdown/lib/src/charcode.dart
new file mode 100644
index 0000000..693fcc5
--- /dev/null
+++ b/pkgs/markdown/lib/src/charcode.dart
@@ -0,0 +1,123 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+/// "Horizontal Tab" control character, common name.
+const int $tab = 0x09;
+
+/// "Line feed" control character.
+const int $lf = 0x0A;
+
+/// "Vertical Tab" control character.
+const int $vt = 0x0B;
+
+/// "Form feed" control character.
+const int $ff = 0x0C;
+
+/// "Carriage return" control character.
+const int $cr = 0x0D;
+
+/// Space character.
+const int $space = 0x20;
+
+/// Character `!`.
+const int $exclamation = 0x21;
+
+/// Character `"`.
+const int $quote = 0x22;
+
+/// Character `"`.
+const int $double_quote = 0x22; // ignore: constant_identifier_names
+
+/// Character `#`.
+const int $hash = 0x23;
+
+/// Character `$`.
+const int $dollar = 0x24;
+
+/// Character `%`.
+const int $percent = 0x25;
+
+/// Character `&`.
+const int $ampersand = 0x26;
+
+/// Character `'`.
+const int $apostrophe = 0x27;
+
+/// Character `(`.
+const int $lparen = 0x28;
+
+/// Character `)`.
+const int $rparen = 0x29;
+
+/// Character `*`.
+const int $asterisk = 0x2A;
+
+/// Character `+`.
+const int $plus = 0x2B;
+
+/// Character `,`.
+const int $comma = 0x2C;
+
+/// Character `-`.
+const int $dash = 0x2D;
+
+/// Character `.`.
+const int $dot = 0x2E;
+
+/// Character `/`.
+const int $slash = 0x2F;
+
+/// Character `:`.
+const int $colon = 0x3A;
+
+/// Character `;`.
+const int $semicolon = 0x3B;
+
+/// Character `<`.
+const int $lt = 0x3C;
+
+/// Character `=`.
+const int $equal = 0x3D;
+
+/// Character `>`.
+const int $gt = 0x3E;
+
+/// Character `?`.
+const int $question = 0x3F;
+
+/// Character `@`.
+const int $at = 0x40;
+
+/// Character `[`.
+const int $lbracket = 0x5B;
+
+/// Character `\`.
+const int $backslash = 0x5C;
+
+/// Character `]`.
+const int $rbracket = 0x5D;
+
+/// Character `^`.
+const int $caret = 0x5E;
+
+/// Character `_`.
+const int $underscore = 0x5F;
+
+/// Character `` ` ``.
+const int $backquote = 0x60;
+
+/// Character `{`.
+const int $lbrace = 0x7B;
+
+/// Character `|`.
+const int $pipe = 0x7C;
+
+/// Character `|`.
+const int $bar = 0x7C;
+
+/// Character `}`.
+const int $rbrace = 0x7D;
+
+/// Character `~`.
+const int $tilde = 0x7E;
diff --git a/pkgs/markdown/lib/src/document.dart b/pkgs/markdown/lib/src/document.dart
new file mode 100644
index 0000000..f33ff33
--- /dev/null
+++ b/pkgs/markdown/lib/src/document.dart
@@ -0,0 +1,217 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'ast.dart';
+import 'block_parser.dart';
+import 'block_syntaxes/block_syntax.dart';
+import 'extension_set.dart';
+import 'inline_parser.dart';
+import 'inline_syntaxes/inline_syntax.dart';
+import 'line.dart';
+import 'util.dart';
+
+/// Maintains the context needed to parse a Markdown document.
+class Document {
+  final Map<String, LinkReference> linkReferences = {};
+
+  /// Footnote ref count, keys are case-sensitive and added by define syntax.
+  final footnoteReferences = <String, int>{};
+
+  /// Footnote labels by appearing order.
+  ///
+  /// They are case-insensitive and added by ref syntax.
+  final footnoteLabels = <String>[];
+  final Resolver? linkResolver;
+  final Resolver? imageLinkResolver;
+  final bool encodeHtml;
+
+  /// Whether to use default block syntaxes.
+  final bool withDefaultBlockSyntaxes;
+
+  /// Whether to use default inline syntaxes.
+  ///
+  /// Need to set both [withDefaultInlineSyntaxes] and [encodeHtml] to
+  /// `false` to disable all inline syntaxes including html encoding syntaxes.
+  final bool withDefaultInlineSyntaxes;
+
+  final _blockSyntaxes = <BlockSyntax>{};
+  final _inlineSyntaxes = <InlineSyntax>{};
+  final bool hasCustomInlineSyntaxes;
+
+  Iterable<BlockSyntax> get blockSyntaxes => _blockSyntaxes;
+
+  Iterable<InlineSyntax> get inlineSyntaxes => _inlineSyntaxes;
+
+  Document({
+    Iterable<BlockSyntax>? blockSyntaxes,
+    Iterable<InlineSyntax>? inlineSyntaxes,
+    ExtensionSet? extensionSet,
+    this.linkResolver,
+    this.imageLinkResolver,
+    this.encodeHtml = true,
+    this.withDefaultBlockSyntaxes = true,
+    this.withDefaultInlineSyntaxes = true,
+  }) : hasCustomInlineSyntaxes = (inlineSyntaxes?.isNotEmpty ?? false) ||
+            (extensionSet?.inlineSyntaxes.isNotEmpty ?? false) {
+    if (blockSyntaxes != null) {
+      _blockSyntaxes.addAll(blockSyntaxes);
+    }
+    if (inlineSyntaxes != null) {
+      _inlineSyntaxes.addAll(inlineSyntaxes);
+    }
+
+    if (extensionSet == null) {
+      if (withDefaultBlockSyntaxes) {
+        _blockSyntaxes.addAll(ExtensionSet.commonMark.blockSyntaxes);
+      }
+
+      if (withDefaultInlineSyntaxes) {
+        _inlineSyntaxes.addAll(ExtensionSet.commonMark.inlineSyntaxes);
+      }
+    } else {
+      _blockSyntaxes.addAll(extensionSet.blockSyntaxes);
+      _inlineSyntaxes.addAll(extensionSet.inlineSyntaxes);
+    }
+  }
+
+  /// Parses the given [lines] of Markdown to a series of AST nodes.
+  List<Node> parseLines(List<String> lines) =>
+      parseLineList(lines.map(Line.new).toList());
+
+  /// Parses the given [text] to a series of AST nodes.
+  List<Node> parse(String text) => parseLineList(text.toLines());
+
+  /// Parses the given [lines] of [Line] to a series of AST nodes.
+  List<Node> parseLineList(List<Line> lines) {
+    final nodes = BlockParser(lines, this).parseLines();
+    _parseInlineContent(nodes);
+    // Do filter after parsing inline as we need ref count.
+    return _filterFootnotes(nodes);
+  }
+
+  /// Parses the given inline Markdown [text] to a series of AST nodes.
+  List<Node> parseInline(String text) => InlineParser(text, this).parse();
+
+  void _parseInlineContent(List<Node> nodes) {
+    for (var i = 0; i < nodes.length; i++) {
+      final node = nodes[i];
+      if (node is UnparsedContent) {
+        final inlineNodes = parseInline(node.textContent);
+        nodes.removeAt(i);
+        nodes.insertAll(i, inlineNodes);
+        i += inlineNodes.length - 1;
+      } else if (node is Element && node.children != null) {
+        _parseInlineContent(node.children!);
+      }
+    }
+  }
+
+  /// Footnotes could be defined in arbitrary positions of a document, we need
+  /// to distinguish them and put them behind; and every footnote definition
+  /// may have multiple backrefs, we need to append backrefs for it.
+  List<Node> _filterFootnotes(List<Node> nodes) {
+    final footnotes = <Element>[];
+    final blocks = <Node>[];
+    for (final node in nodes) {
+      if (node is Element &&
+          node.tag == 'li' &&
+          footnoteReferences.containsKey(node.footnoteLabel)) {
+        final label = node.footnoteLabel;
+        var count = 0;
+        if (label != null && (count = footnoteReferences[label] ?? 0) > 0) {
+          footnotes.add(node);
+          final children = node.children;
+          if (children != null) {
+            _appendBackref(children, Uri.encodeComponent(label), count);
+          }
+        }
+      } else {
+        blocks.add(node);
+      }
+    }
+
+    if (footnotes.isNotEmpty) {
+      // Sort footnotes by appearing order.
+      final ordinal = {
+        for (var i = 0; i < footnoteLabels.length; i++)
+          'fn-${footnoteLabels[i]}': i,
+      };
+      footnotes.sort((l, r) {
+        final idl = l.attributes['id']?.toLowerCase() ?? '';
+        final idr = r.attributes['id']?.toLowerCase() ?? '';
+        return (ordinal[idl] ?? 0) - (ordinal[idr] ?? 0);
+      });
+      final list = Element('ol', footnotes);
+
+      // Ignore GFM attribute: <data-footnotes>.
+      final section = Element('section', [list])
+        ..attributes['class'] = 'footnotes';
+      blocks.add(section);
+    }
+    return blocks;
+  }
+
+  /// Generate backref nodes, append them to footnote definition's last child.
+  void _appendBackref(List<Node> children, String ref, int count) {
+    final refs = [
+      for (var i = 0; i < count; i++) ...[
+        Text(' '),
+        _ElementExt.footnoteAnchor(ref, i)
+      ]
+    ];
+    if (children.isEmpty) {
+      children.addAll(refs);
+    } else {
+      final last = children.last;
+      if (last is Element) {
+        last.children?.addAll(refs);
+      } else {
+        children.last = Element('p', [last, ...refs]);
+      }
+    }
+  }
+}
+
+extension _ElementExt on Element {
+  static Element footnoteAnchor(String ref, int i) {
+    final num = '${i + 1}';
+    final suffix = i > 0 ? '-$num' : '';
+    final e = Element.empty('tag');
+    e.match;
+    return Element('a', [
+      Text('\u21a9'),
+      if (i > 0)
+        Element('sup', [Text(num)])..attributes['class'] = 'footnote-ref',
+    ])
+      // Ignore GFM's attributes:
+      // <data-footnote-backref aria-label="Back to content">.
+      ..attributes['href'] = '#fnref-$ref$suffix'
+      ..attributes['class'] = 'footnote-backref';
+  }
+
+  String get match => tag;
+}
+
+/// A [link reference
+/// definition](https://spec.commonmark.org/0.30/#link-reference-definitions).
+class LinkReference {
+  /// The [link label](https://spec.commonmark.org/0.30/#link-label).
+  ///
+  /// Temporarily, this class is also being used to represent the link data for
+  /// an inline link (the destination and title), but this should change before
+  /// the package is released.
+  final String label;
+
+  /// The [link destination](https://spec.commonmark.org/0.30/#link-destination).
+  final String destination;
+
+  /// The [link title](https://spec.commonmark.org/0.30/#link-title).
+  final String? title;
+
+  /// Construct a new [LinkReference], with all necessary fields.
+  ///
+  /// If the parsed link reference definition does not include a title, use
+  /// `null` for the [title] parameter.
+  LinkReference(this.label, this.destination, this.title);
+}
diff --git a/pkgs/markdown/lib/src/emojis.dart b/pkgs/markdown/lib/src/emojis.dart
new file mode 100644
index 0000000..cca1a28
--- /dev/null
+++ b/pkgs/markdown/lib/src/emojis.dart
@@ -0,0 +1,1904 @@
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from GitHub's emoji API list endpoint:
+// https://api.github.com/emojis
+// at 2022-05-03 01:45:16.587812 by the script, tool/update_github_emojis.dart.
+
+const emojis = <String, String>{
+  '+1': '👍',
+  '-1': '👎',
+  '100': '💯',
+  '1234': '🔢',
+  '1st_place_medal': '🥇',
+  '2nd_place_medal': '🥈',
+  '3rd_place_medal': '🥉',
+  '8ball': '🎱',
+  'a': '🅰️',
+  'ab': '🆎',
+  'abacus': '🧮',
+  'abc': '🔤',
+  'abcd': '🔡',
+  'accept': '🉑',
+  'accordion': '🪗',
+  'adhesive_bandage': '🩹',
+  'adult': '🧑',
+  'aerial_tramway': '🚡',
+  'afghanistan': '🇦🇫',
+  'airplane': '✈️',
+  'aland_islands': '🇦🇽',
+  'alarm_clock': '⏰',
+  'albania': '🇦🇱',
+  'alembic': '⚗',
+  'algeria': '🇩🇿',
+  'alien': '👽',
+  'ambulance': '🚑',
+  'american_samoa': '🇦🇸',
+  'amphora': '🏺',
+  'anatomical_heart': '🫀',
+  'anchor': '⚓',
+  'andorra': '🇦🇩',
+  'angel': '👼',
+  'anger': '💢',
+  'angola': '🇦🇴',
+  'angry': '😠',
+  'anguilla': '🇦🇮',
+  'anguished': '😧',
+  'ant': '🐜',
+  'antarctica': '🇦🇶',
+  'antigua_barbuda': '🇦🇬',
+  'apple': '🍎',
+  'aquarius': '♒',
+  'argentina': '🇦🇷',
+  'aries': '♈',
+  'armenia': '🇦🇲',
+  'arrow_backward': '◀️',
+  'arrow_double_down': '⏬',
+  'arrow_double_up': '⏫',
+  'arrow_down': '⬇️',
+  'arrow_down_small': '🔽',
+  'arrow_forward': '▶️',
+  'arrow_heading_down': '⤵️',
+  'arrow_heading_up': '⤴️',
+  'arrow_left': '⬅️',
+  'arrow_lower_left': '↙️',
+  'arrow_lower_right': '↘️',
+  'arrow_right': '➡️',
+  'arrow_right_hook': '↪️',
+  'arrow_up': '⬆️',
+  'arrow_up_down': '↕️',
+  'arrow_up_small': '🔼',
+  'arrow_upper_left': '↖️',
+  'arrow_upper_right': '↗️',
+  'arrows_clockwise': '🔃',
+  'arrows_counterclockwise': '🔄',
+  'art': '🎨',
+  'articulated_lorry': '🚛',
+  'artificial_satellite': '🛰',
+  'artist': '🧑️‍🎨',
+  'aruba': '🇦🇼',
+  'ascension_island': '🇦️‍🇨',
+  'asterisk': '*⃣',
+  'astonished': '😲',
+  'astronaut': '🧑️‍🚀',
+  'athletic_shoe': '👟',
+  'atm': '🏧',
+  'atom_symbol': '⚛',
+  'australia': '🇦🇺',
+  'austria': '🇦🇹',
+  'auto_rickshaw': '🛺',
+  'avocado': '🥑',
+  'axe': '🪓',
+  'azerbaijan': '🇦🇿',
+  'b': '🅱️',
+  'baby': '👶',
+  'baby_bottle': '🍼',
+  'baby_chick': '🐤',
+  'baby_symbol': '🚼',
+  'back': '🔙',
+  'bacon': '🥓',
+  'badger': '🦡',
+  'badminton': '🏸',
+  'bagel': '🥯',
+  'baggage_claim': '🛄',
+  'baguette_bread': '🥖',
+  'bahamas': '🇧🇸',
+  'bahrain': '🇧🇭',
+  'balance_scale': '⚖',
+  'bald_man': '👨️‍🦲',
+  'bald_woman': '👩️‍🦲',
+  'ballet_shoes': '🩰',
+  'balloon': '🎈',
+  'ballot_box': '🗳',
+  'ballot_box_with_check': '☑️',
+  'bamboo': '🎍',
+  'banana': '🍌',
+  'bangbang': '‼️',
+  'bangladesh': '🇧🇩',
+  'banjo': '🪕',
+  'bank': '🏦',
+  'bar_chart': '📊',
+  'barbados': '🇧🇧',
+  'barber': '💈',
+  'baseball': '⚾',
+  'basket': '🧺',
+  'basketball': '🏀',
+  'basketball_man': '⛹',
+  'basketball_woman': '⛹️‍♀️',
+  'bat': '🦇',
+  'bath': '🛀',
+  'bathtub': '🛁',
+  'battery': '🔋',
+  'beach_umbrella': '🏖',
+  'bear': '🐻',
+  'bearded_person': '🧔',
+  'beaver': '🦫',
+  'bed': '🛏',
+  'bee': '🐝',
+  'beer': '🍺',
+  'beers': '🍻',
+  'beetle': '🪲',
+  'beginner': '🔰',
+  'belarus': '🇧🇾',
+  'belgium': '🇧🇪',
+  'belize': '🇧🇿',
+  'bell': '🔔',
+  'bell_pepper': '🫑',
+  'bellhop_bell': '🛎',
+  'benin': '🇧🇯',
+  'bento': '🍱',
+  'bermuda': '🇧🇲',
+  'beverage_box': '🧃',
+  'bhutan': '🇧🇹',
+  'bicyclist': '🚴',
+  'bike': '🚲',
+  'biking_man': '🚴',
+  'biking_woman': '🚴‍♀️',
+  'bikini': '👙',
+  'billed_cap': '🧢',
+  'billed_hat': '🧢',
+  'biohazard': '☣',
+  'bird': '🐦',
+  'birthday': '🎂',
+  'bison': '🦬',
+  'black_cat': '🐈️‍⬛',
+  'black_circle': '⚫',
+  'black_flag': '🏴',
+  'black_heart': '🖤',
+  'black_joker': '🃏',
+  'black_large_square': '⬛',
+  'black_medium_small_square': '◾',
+  'black_medium_square': '◼️',
+  'black_nib': '✒️',
+  'black_small_square': '▪️',
+  'black_square_button': '🔲',
+  'blond_haired_man': '👱️‍♂',
+  'blond_haired_person': '👱',
+  'blond_haired_woman': '👱️‍♀',
+  'blonde_man': '👱',
+  'blonde_woman': '👱‍♀️',
+  'blossom': '🌼',
+  'blowfish': '🐡',
+  'blue_book': '📘',
+  'blue_car': '🚙',
+  'blue_heart': '💙',
+  'blue_square': '🟦',
+  'blueberries': '🫐',
+  'blush': '😊',
+  'boar': '🐗',
+  'boat': '⛵',
+  'bolivia': '🇧🇴',
+  'bomb': '💣',
+  'bone': '🦴',
+  'book': '📖',
+  'bookmark': '🔖',
+  'bookmark_tabs': '📑',
+  'books': '📚',
+  'boom': '💥',
+  'boomerang': '🪃',
+  'boot': '👢',
+  'bosnia_herzegovina': '🇧🇦',
+  'botswana': '🇧🇼',
+  'bouncing_ball_man': '⛹️‍♂',
+  'bouncing_ball_person': '⛹',
+  'bouncing_ball_woman': '⛹️‍♀',
+  'bouquet': '💐',
+  'bouvet_island': '🇧️‍🇻',
+  'bow': '🙇',
+  'bow_and_arrow': '🏹',
+  'bowing_man': '🙇',
+  'bowing_woman': '🙇‍♀️',
+  'bowl_with_spoon': '🥣',
+  'bowling': '🎳',
+  'boxing_glove': '🥊',
+  'boy': '👦',
+  'brain': '🧠',
+  'brazil': '🇧🇷',
+  'bread': '🍞',
+  'breast_feeding': '🤱',
+  'breastfeeding': '🤱',
+  'brick': '🧱',
+  'bricks': '🧱',
+  'bride_with_veil': '👰',
+  'bridge_at_night': '🌉',
+  'briefcase': '💼',
+  'british_indian_ocean_territory': '🇮🇴',
+  'british_virgin_islands': '🇻🇬',
+  'broccoli': '🥦',
+  'broken_heart': '💔',
+  'broom': '🧹',
+  'brown_circle': '🟤',
+  'brown_heart': '🤎',
+  'brown_square': '🟫',
+  'brunei': '🇧🇳',
+  'bubble_tea': '🧋',
+  'bucket': '🪣',
+  'bug': '🐛',
+  'building_construction': '🏗',
+  'bulb': '💡',
+  'bulgaria': '🇧🇬',
+  'bullettrain_front': '🚅',
+  'bullettrain_side': '🚄',
+  'burkina_faso': '🇧🇫',
+  'burrito': '🌯',
+  'burundi': '🇧🇮',
+  'bus': '🚌',
+  'business_suit_levitating': '🕴',
+  'busstop': '🚏',
+  'bust_in_silhouette': '👤',
+  'busts_in_silhouette': '👥',
+  'butter': '🧈',
+  'butterfly': '🦋',
+  'cactus': '🌵',
+  'cake': '🍰',
+  'calendar': '📆',
+  'call_me_hand': '🤙',
+  'calling': '📲',
+  'cambodia': '🇰🇭',
+  'camel': '🐫',
+  'camera': '📷',
+  'camera_flash': '📸',
+  'cameroon': '🇨🇲',
+  'camping': '🏕',
+  'canada': '🇨🇦',
+  'canary_islands': '🇮🇨',
+  'cancer': '♋',
+  'candle': '🕯',
+  'candy': '🍬',
+  'canned_food': '🥫',
+  'canoe': '🛶',
+  'cape_verde': '🇨🇻',
+  'capital_abcd': '🔠',
+  'capricorn': '♑',
+  'car': '🚗',
+  'card_file_box': '🗃',
+  'card_index': '📇',
+  'card_index_dividers': '🗂',
+  'caribbean_netherlands': '🇧🇶',
+  'carousel_horse': '🎠',
+  'carpentry_saw': '🪚',
+  'carrot': '🥕',
+  'cartwheeling': '🤸',
+  'cat': '🐱',
+  'cat2': '🐈',
+  'cayman_islands': '🇰🇾',
+  'cd': '💿',
+  'central_african_republic': '🇨🇫',
+  'ceuta_melilla': '🇪️‍🇦',
+  'chad': '🇹🇩',
+  'chains': '⛓',
+  'chair': '🪑',
+  'champagne': '🍾',
+  'chart': '💹',
+  'chart_with_downwards_trend': '📉',
+  'chart_with_upwards_trend': '📈',
+  'checkered_flag': '🏁',
+  'cheese': '🧀',
+  'cherries': '🍒',
+  'cherry_blossom': '🌸',
+  'chess_pawn': '♟',
+  'chestnut': '🌰',
+  'chicken': '🐔',
+  'child': '🧒',
+  'children_crossing': '🚸',
+  'chile': '🇨🇱',
+  'chipmunk': '🐿',
+  'chocolate_bar': '🍫',
+  'chopsticks': '🥢',
+  'christmas_island': '🇨🇽',
+  'christmas_tree': '🎄',
+  'church': '⛪',
+  'cinema': '🎦',
+  'circus_tent': '🎪',
+  'city_sunrise': '🌇',
+  'city_sunset': '🌆',
+  'cityscape': '🏙',
+  'cl': '🆑',
+  'clamp': '🗜',
+  'clap': '👏',
+  'clapper': '🎬',
+  'classical_building': '🏛',
+  'climbing': '🧗',
+  'climbing_man': '🧗‍♂️',
+  'climbing_woman': '🧗‍♀️',
+  'clinking_glasses': '🥂',
+  'clipboard': '📋',
+  'clipperton_island': '🇨️‍🇵',
+  'clock1': '🕐',
+  'clock10': '🕙',
+  'clock1030': '🕥',
+  'clock11': '🕚',
+  'clock1130': '🕦',
+  'clock12': '🕛',
+  'clock1230': '🕧',
+  'clock130': '🕜',
+  'clock2': '🕑',
+  'clock230': '🕝',
+  'clock3': '🕒',
+  'clock330': '🕞',
+  'clock4': '🕓',
+  'clock430': '🕟',
+  'clock5': '🕔',
+  'clock530': '🕠',
+  'clock6': '🕕',
+  'clock630': '🕡',
+  'clock7': '🕖',
+  'clock730': '🕢',
+  'clock8': '🕗',
+  'clock830': '🕣',
+  'clock9': '🕘',
+  'clock930': '🕤',
+  'closed_book': '📕',
+  'closed_lock_with_key': '🔐',
+  'closed_umbrella': '🌂',
+  'cloud': '☁️',
+  'cloud_with_lightning': '🌩',
+  'cloud_with_lightning_and_rain': '⛈',
+  'cloud_with_rain': '🌧',
+  'cloud_with_snow': '🌨',
+  'clown_face': '🤡',
+  'clubs': '♣️',
+  'cn': '🇨🇳',
+  'coat': '🧥',
+  'cockroach': '🪳',
+  'cocktail': '🍸',
+  'coconut': '🥥',
+  'cocos_islands': '🇨🇨',
+  'coffee': '☕',
+  'coffin': '⚰',
+  'coin': '🪙',
+  'cold': '🥶',
+  'cold_face': '🥶',
+  'cold_sweat': '😰',
+  'collision': '💥',
+  'colombia': '🇨🇴',
+  'comet': '☄',
+  'comoros': '🇰🇲',
+  'compass': '🧭',
+  'computer': '💻',
+  'computer_mouse': '🖱',
+  'confetti_ball': '🎊',
+  'confounded': '😖',
+  'confused': '😕',
+  'congo_brazzaville': '🇨🇬',
+  'congo_kinshasa': '🇨🇩',
+  'congratulations': '㊗️',
+  'construction': '🚧',
+  'construction_worker': '👷',
+  'construction_worker_man': '👷',
+  'construction_worker_woman': '👷‍♀️',
+  'control_knobs': '🎛',
+  'convenience_store': '🏪',
+  'cook': '🧑️‍🍳',
+  'cook_islands': '🇨🇰',
+  'cookie': '🍪',
+  'cool': '🆒',
+  'cop': '👮',
+  'copyright': '©️',
+  'corn': '🌽',
+  'costa_rica': '🇨🇷',
+  'cote_divoire': '🇨🇮',
+  'couch_and_lamp': '🛋',
+  'couple': '👫',
+  'couple_with_heart': '💑',
+  'couple_with_heart_man_man': '👨‍❤️‍👨',
+  'couple_with_heart_woman_man': '💑',
+  'couple_with_heart_woman_woman': '👩‍❤️‍👩',
+  'couplekiss': '💏',
+  'couplekiss_man_man': '👨‍❤️‍💋‍👨',
+  'couplekiss_man_woman': '💏',
+  'couplekiss_woman_woman': '👩‍❤️‍💋‍👩',
+  'cow': '🐮',
+  'cow2': '🐄',
+  'cowboy_hat_face': '🤠',
+  'crab': '🦀',
+  'crayon': '🖍',
+  'credit_card': '💳',
+  'crescent_moon': '🌙',
+  'cricket': '🦗',
+  'cricket_game': '🏏',
+  'croatia': '🇭🇷',
+  'crocodile': '🐊',
+  'croissant': '🥐',
+  'crossed_fingers': '🤞',
+  'crossed_flags': '🎌',
+  'crossed_swords': '⚔',
+  'crown': '👑',
+  'cry': '😢',
+  'crying_cat_face': '😿',
+  'crystal_ball': '🔮',
+  'cuba': '🇨🇺',
+  'cucumber': '🥒',
+  'cup_with_straw': '🥤',
+  'cupcake': '🧁',
+  'cupid': '💘',
+  'curacao': '🇨🇼',
+  'curling_stone': '🥌',
+  'curly_haired_man': '👨️‍🦱',
+  'curly_haired_woman': '👩️‍🦱',
+  'curly_loop': '➰',
+  'currency_exchange': '💱',
+  'curry': '🍛',
+  'cursing_face': '🤬',
+  'custard': '🍮',
+  'customs': '🛃',
+  'cut_of_meat': '🥩',
+  'cyclone': '🌀',
+  'cyprus': '🇨🇾',
+  'czech_republic': '🇨🇿',
+  'dagger': '🗡',
+  'dancer': '💃',
+  'dancers': '👯',
+  'dancing_men': '👯‍♂️',
+  'dancing_women': '👯',
+  'dango': '🍡',
+  'dark_sunglasses': '🕶',
+  'dart': '🎯',
+  'dash': '💨',
+  'date': '📅',
+  'de': '🇩🇪',
+  'deaf_man': '🧏️‍♂',
+  'deaf_person': '🧏',
+  'deaf_woman': '🧏️‍♀',
+  'deciduous_tree': '🌳',
+  'deer': '🦌',
+  'denmark': '🇩🇰',
+  'department_store': '🏬',
+  'derelict_house': '🏚',
+  'desert': '🏜',
+  'desert_island': '🏝',
+  'desktop_computer': '🖥',
+  'detective': '🕵',
+  'diamond_shape_with_a_dot_inside': '💠',
+  'diamonds': '♦️',
+  'diego_garcia': '🇩️‍🇬',
+  'disappointed': '😞',
+  'disappointed_relieved': '😥',
+  'disguised_face': '🥸',
+  'diving_mask': '🤿',
+  'diya_lamp': '🪔',
+  'dizzy': '💫',
+  'dizzy_face': '😵',
+  'djibouti': '🇩🇯',
+  'dna': '🧬',
+  'do_not_litter': '🚯',
+  'dodo': '🦤',
+  'dog': '🐶',
+  'dog2': '🐕',
+  'dollar': '💵',
+  'dolls': '🎎',
+  'dolphin': '🐬',
+  'dominica': '🇩🇲',
+  'dominican_republic': '🇩🇴',
+  'door': '🚪',
+  'doughnut': '🍩',
+  'dove': '🕊',
+  'dragon': '🐉',
+  'dragon_face': '🐲',
+  'dress': '👗',
+  'dromedary_camel': '🐪',
+  'drooling_face': '🤤',
+  'drop_of_blood': '🩸',
+  'droplet': '💧',
+  'drum': '🥁',
+  'duck': '🦆',
+  'dumpling': '🥟',
+  'dvd': '📀',
+  'e-mail': '📧',
+  'eagle': '🦅',
+  'ear': '👂',
+  'ear_of_rice': '🌾',
+  'ear_with_hearing_aid': '🦻',
+  'earth_africa': '🌍',
+  'earth_americas': '🌎',
+  'earth_asia': '🌏',
+  'ecuador': '🇪🇨',
+  'egg': '🥚',
+  'eggplant': '🍆',
+  'egypt': '🇪🇬',
+  'eight': '8️⃣',
+  'eight_pointed_black_star': '✴️',
+  'eight_spoked_asterisk': '✳️',
+  'eject_button': '⏏️',
+  'el_salvador': '🇸🇻',
+  'electric_plug': '🔌',
+  'elephant': '🐘',
+  'elevator': '🛗',
+  'elf': '🧝',
+  'elf_man': '🧝️‍♂',
+  'elf_woman': '🧝️‍♀',
+  'email': '✉️',
+  'end': '🔚',
+  'england': '🏴󠁧󠁢󠁥󠁮󠁧󠁿',
+  'envelope': '✉',
+  'envelope_with_arrow': '📩',
+  'equatorial_guinea': '🇬🇶',
+  'eritrea': '🇪🇷',
+  'es': '🇪🇸',
+  'estonia': '🇪🇪',
+  'ethiopia': '🇪🇹',
+  'eu': '🇪🇺',
+  'euro': '💶',
+  'european_castle': '🏰',
+  'european_post_office': '🏤',
+  'european_union': '🇪️‍🇺',
+  'evergreen_tree': '🌲',
+  'exclamation': '❗',
+  'exploding_head': '🤯',
+  'expressionless': '😑',
+  'eye': '👁',
+  'eye_speech_bubble': '👁️‍🗨',
+  'eyeglasses': '👓',
+  'eyes': '👀',
+  'face_exhaling': '😮️‍💨',
+  'face_in_clouds': '😶️‍🌫',
+  'face_with_head_bandage': '🤕',
+  'face_with_spiral_eyes': '😵️‍💫',
+  'face_with_thermometer': '🤒',
+  'facepalm': '🤦',
+  'facepunch': '👊',
+  'factory': '🏭',
+  'factory_worker': '🧑️‍🏭',
+  'fairy': '🧚',
+  'fairy_man': '🧚️‍♂',
+  'fairy_woman': '🧚️‍♀',
+  'falafel': '🧆',
+  'falkland_islands': '🇫🇰',
+  'fallen_leaf': '🍂',
+  'family': '👪',
+  'family_man_boy': '👨‍👦',
+  'family_man_boy_boy': '👨‍👦‍👦',
+  'family_man_girl': '👨‍👧',
+  'family_man_girl_boy': '👨‍👧‍👦',
+  'family_man_girl_girl': '👨‍👧‍👧',
+  'family_man_man_boy': '👨‍👨‍👦',
+  'family_man_man_boy_boy': '👨‍👨‍👦‍👦',
+  'family_man_man_girl': '👨‍👨‍👧',
+  'family_man_man_girl_boy': '👨‍👨‍👧‍👦',
+  'family_man_man_girl_girl': '👨‍👨‍👧‍👧',
+  'family_man_woman_boy': '👪',
+  'family_man_woman_boy_boy': '👨‍👩‍👦‍👦',
+  'family_man_woman_girl': '👨‍👩‍👧',
+  'family_man_woman_girl_boy': '👨‍👩‍👧‍👦',
+  'family_man_woman_girl_girl': '👨‍👩‍👧‍👧',
+  'family_woman_boy': '👩‍👦',
+  'family_woman_boy_boy': '👩‍👦‍👦',
+  'family_woman_girl': '👩‍👧',
+  'family_woman_girl_boy': '👩‍👧‍👦',
+  'family_woman_girl_girl': '👩‍👧‍👧',
+  'family_woman_woman_boy': '👩‍👩‍👦',
+  'family_woman_woman_boy_boy': '👩‍👩‍👦‍👦',
+  'family_woman_woman_girl': '👩‍👩‍👧',
+  'family_woman_woman_girl_boy': '👩‍👩‍👧‍👦',
+  'family_woman_woman_girl_girl': '👩‍👩‍👧‍👧',
+  'farmer': '🧑️‍🌾',
+  'faroe_islands': '🇫🇴',
+  'fast_forward': '⏩',
+  'fax': '📠',
+  'fearful': '😨',
+  'feather': '🪶',
+  'feet': '🐾',
+  'female_detective': '🕵️‍♀️',
+  'female_sign': '♀',
+  'ferris_wheel': '🎡',
+  'ferry': '⛴',
+  'field_hockey': '🏑',
+  'fiji': '🇫🇯',
+  'file_cabinet': '🗄',
+  'file_folder': '📁',
+  'film_projector': '📽',
+  'film_strip': '🎞',
+  'finland': '🇫🇮',
+  'fire': '🔥',
+  'fire_engine': '🚒',
+  'fire_extinguisher': '🧯',
+  'firecracker': '🧨',
+  'firefighter': '🧑️‍🚒',
+  'fireworks': '🎆',
+  'first_quarter_moon': '🌓',
+  'first_quarter_moon_with_face': '🌛',
+  'fish': '🐟',
+  'fish_cake': '🍥',
+  'fishing_pole_and_fish': '🎣',
+  'fist': '✊',
+  'fist_left': '🤛',
+  'fist_oncoming': '👊',
+  'fist_raised': '✊',
+  'fist_right': '🤜',
+  'five': '5️⃣',
+  'flags': '🎏',
+  'flamingo': '🦩',
+  'flashlight': '🔦',
+  'flat_shoe': '🥿',
+  'flatbread': '🫓',
+  'fleur_de_lis': '⚜',
+  'flight_arrival': '🛬',
+  'flight_departure': '🛫',
+  'flipper': '🐬',
+  'floppy_disk': '💾',
+  'flower_playing_cards': '🎴',
+  'flushed': '😳',
+  'fly': '🪰',
+  'flying_disc': '🥏',
+  'flying_saucer': '🛸',
+  'fog': '🌫',
+  'foggy': '🌁',
+  'fondue': '🫕',
+  'foot': '🦶',
+  'football': '🏈',
+  'footprints': '👣',
+  'fork_and_knife': '🍴',
+  'fortune_cookie': '🥠',
+  'fountain': '⛲',
+  'fountain_pen': '🖋',
+  'four': '4️⃣',
+  'four_leaf_clover': '🍀',
+  'fox_face': '🦊',
+  'fr': '🇫🇷',
+  'framed_picture': '🖼',
+  'free': '🆓',
+  'french_guiana': '🇬🇫',
+  'french_polynesia': '🇵🇫',
+  'french_southern_territories': '🇹🇫',
+  'fried_egg': '🍳',
+  'fried_shrimp': '🍤',
+  'fries': '🍟',
+  'frog': '🐸',
+  'frowning': '😦',
+  'frowning_face': '☹',
+  'frowning_man': '🙍‍♂️',
+  'frowning_person': '🙍',
+  'frowning_woman': '🙍',
+  'fu': '🖕',
+  'fuelpump': '⛽',
+  'full_moon': '🌕',
+  'full_moon_with_face': '🌝',
+  'funeral_urn': '⚱',
+  'gabon': '🇬🇦',
+  'gambia': '🇬🇲',
+  'game_die': '🎲',
+  'garlic': '🧄',
+  'gb': '🇬️‍🇧',
+  'gear': '⚙',
+  'gem': '💎',
+  'gemini': '♊',
+  'genie': '🧞',
+  'genie_man': '🧞️‍♂',
+  'genie_woman': '🧞️‍♀',
+  'georgia': '🇬🇪',
+  'ghana': '🇬🇭',
+  'ghost': '👻',
+  'gibraltar': '🇬🇮',
+  'gift': '🎁',
+  'gift_heart': '💝',
+  'giraffe': '🦒',
+  'girl': '👧',
+  'globe_with_meridians': '🌐',
+  'gloves': '🧤',
+  'goal_net': '🥅',
+  'goat': '🐐',
+  'goggles': '🥽',
+  'golf': '⛳',
+  'golfing': '🏌',
+  'golfing_man': '🏌',
+  'golfing_woman': '🏌️‍♀️',
+  'gorilla': '🦍',
+  'grapes': '🍇',
+  'grasshopper': '🦗',
+  'greece': '🇬🇷',
+  'green_apple': '🍏',
+  'green_book': '📗',
+  'green_circle': '🟢',
+  'green_heart': '💚',
+  'green_salad': '🥗',
+  'green_square': '🟩',
+  'greenland': '🇬🇱',
+  'grenada': '🇬🇩',
+  'grey_exclamation': '❕',
+  'grey_question': '❔',
+  'grimacing': '😬',
+  'grin': '😁',
+  'grinning': '😀',
+  'guadeloupe': '🇬🇵',
+  'guam': '🇬🇺',
+  'guard': '💂',
+  'guardsman': '💂',
+  'guardswoman': '💂‍♀️',
+  'guatemala': '🇬🇹',
+  'guernsey': '🇬🇬',
+  'guide_dog': '🦮',
+  'guinea': '🇬🇳',
+  'guinea_bissau': '🇬🇼',
+  'guitar': '🎸',
+  'gun': '🔫',
+  'guyana': '🇬🇾',
+  'haircut': '💇',
+  'haircut_man': '💇‍♂️',
+  'haircut_woman': '💇',
+  'haiti': '🇭🇹',
+  'hamburger': '🍔',
+  'hammer': '🔨',
+  'hammer_and_pick': '⚒',
+  'hammer_and_wrench': '🛠',
+  'hamster': '🐹',
+  'hand': '✋',
+  'hand_over_mouth': '🤭',
+  'handbag': '👜',
+  'handball_person': '🤾',
+  'handshake': '🤝',
+  'hankey': '💩',
+  'hash': '#️⃣',
+  'hatched_chick': '🐥',
+  'hatching_chick': '🐣',
+  'headphones': '🎧',
+  'headstone': '🪦',
+  'health_worker': '🧑️‍⚕',
+  'hear_no_evil': '🙉',
+  'heard_mcdonald_islands': '🇭️‍🇲',
+  'heart': '❤️',
+  'heart_decoration': '💟',
+  'heart_eyes': '😍',
+  'heart_eyes_cat': '😻',
+  'heart_on_fire': '❤️‍🔥',
+  'heartbeat': '💓',
+  'heartpulse': '💗',
+  'hearts': '♥️',
+  'heavy_check_mark': '✔️',
+  'heavy_division_sign': '➗',
+  'heavy_dollar_sign': '💲',
+  'heavy_exclamation_mark': '❗',
+  'heavy_heart_exclamation': '❣',
+  'heavy_minus_sign': '➖',
+  'heavy_multiplication_x': '✖️',
+  'heavy_plus_sign': '➕',
+  'hedgehog': '🦔',
+  'helicopter': '🚁',
+  'herb': '🌿',
+  'hibiscus': '🌺',
+  'high_brightness': '🔆',
+  'high_heel': '👠',
+  'hiking_boot': '🥾',
+  'hindu_temple': '🛕',
+  'hippopotamus': '🦛',
+  'hocho': '🔪',
+  'hole': '🕳',
+  'honduras': '🇭🇳',
+  'honey_pot': '🍯',
+  'honeybee': '🐝',
+  'hong_kong': '🇭🇰',
+  'hook': '🪝',
+  'horse': '🐴',
+  'horse_racing': '🏇',
+  'hospital': '🏥',
+  'hot': '🥵',
+  'hot_face': '🥵',
+  'hot_pepper': '🌶',
+  'hotdog': '🌭',
+  'hotel': '🏨',
+  'hotsprings': '♨️',
+  'hourglass': '⌛',
+  'hourglass_flowing_sand': '⏳',
+  'house': '🏠',
+  'house_with_garden': '🏡',
+  'houses': '🏘',
+  'hugs': '🤗',
+  'hungary': '🇭🇺',
+  'hushed': '😯',
+  'hut': '🛖',
+  'ice_cream': '🍨',
+  'ice_cube': '🧊',
+  'ice_hockey': '🏒',
+  'ice_skate': '⛸',
+  'icecream': '🍦',
+  'iceland': '🇮🇸',
+  'id': '🆔',
+  'ideograph_advantage': '🉐',
+  'imp': '👿',
+  'inbox_tray': '📥',
+  'incoming_envelope': '📨',
+  'india': '🇮🇳',
+  'indonesia': '🇮🇩',
+  'infinity': '♾',
+  'information_desk_person': '💁',
+  'information_source': 'ℹ️',
+  'innocent': '😇',
+  'interrobang': '⁉️',
+  'iphone': '📱',
+  'iran': '🇮🇷',
+  'iraq': '🇮🇶',
+  'ireland': '🇮🇪',
+  'isle_of_man': '🇮🇲',
+  'israel': '🇮🇱',
+  'it': '🇮🇹',
+  'izakaya_lantern': '🏮',
+  'jack_o_lantern': '🎃',
+  'jamaica': '🇯🇲',
+  'japan': '🗾',
+  'japanese_castle': '🏯',
+  'japanese_goblin': '👺',
+  'japanese_ogre': '👹',
+  'jeans': '👖',
+  'jersey': '🇯🇪',
+  'jigsaw': '🧩',
+  'jordan': '🇯🇴',
+  'joy': '😂',
+  'joy_cat': '😹',
+  'joystick': '🕹',
+  'jp': '🇯🇵',
+  'judge': '🧑️‍⚖',
+  'juggling_person': '🤹',
+  'kaaba': '🕋',
+  'kangaroo': '🦘',
+  'kazakhstan': '🇰🇿',
+  'kenya': '🇰🇪',
+  'key': '🔑',
+  'keyboard': '⌨',
+  'keycap_ten': '🔟',
+  'kick_scooter': '🛴',
+  'kimono': '👘',
+  'kiribati': '🇰🇮',
+  'kiss': '💋',
+  'kissing': '😗',
+  'kissing_cat': '😽',
+  'kissing_closed_eyes': '😚',
+  'kissing_heart': '😘',
+  'kissing_smiling_eyes': '😙',
+  'kite': '🪁',
+  'kiwi_fruit': '🥝',
+  'kneeling_man': '🧎️‍♂',
+  'kneeling_person': '🧎',
+  'kneeling_woman': '🧎️‍♀',
+  'knife': '🔪',
+  'knot': '🪢',
+  'koala': '🐨',
+  'koko': '🈁',
+  'kosovo': '🇽🇰',
+  'kr': '🇰🇷',
+  'kuwait': '🇰🇼',
+  'kyrgyzstan': '🇰🇬',
+  'lab_coat': '🥼',
+  'labcoat': '🥼',
+  'label': '🏷',
+  'lacrosse': '🥍',
+  'ladder': '🪜',
+  'lady_beetle': '🐞',
+  'lantern': '🏮',
+  'laos': '🇱🇦',
+  'large_blue_circle': '🔵',
+  'large_blue_diamond': '🔷',
+  'large_orange_diamond': '🔶',
+  'last_quarter_moon': '🌗',
+  'last_quarter_moon_with_face': '🌜',
+  'latin_cross': '✝',
+  'latvia': '🇱🇻',
+  'laughing': '😆',
+  'leafy_green': '🥬',
+  'leafy_greens': '🥬',
+  'leaves': '🍃',
+  'lebanon': '🇱🇧',
+  'ledger': '📒',
+  'left_luggage': '🛅',
+  'left_right_arrow': '↔️',
+  'left_speech_bubble': '🗨',
+  'leftwards_arrow_with_hook': '↩️',
+  'leg': '🦵',
+  'lemon': '🍋',
+  'leo': '♌',
+  'leopard': '🐆',
+  'lesotho': '🇱🇸',
+  'level_slider': '🎚',
+  'liberia': '🇱🇷',
+  'libra': '♎',
+  'libya': '🇱🇾',
+  'liechtenstein': '🇱🇮',
+  'light_rail': '🚈',
+  'link': '🔗',
+  'lion': '🦁',
+  'lips': '👄',
+  'lipstick': '💄',
+  'lithuania': '🇱🇹',
+  'lizard': '🦎',
+  'llama': '🦙',
+  'lobster': '🦞',
+  'lock': '🔒',
+  'lock_with_ink_pen': '🔏',
+  'lollipop': '🍭',
+  'long_drum': '🪘',
+  'loop': '➿',
+  'lotion_bottle': '🧴',
+  'lotus_position': '🧘',
+  'lotus_position_man': '🧘️‍♂',
+  'lotus_position_woman': '🧘️‍♀',
+  'loud_sound': '🔊',
+  'loudspeaker': '📢',
+  'love_hotel': '🏩',
+  'love_letter': '💌',
+  'love_you': '🤟',
+  'love_you_gesture': '🤟',
+  'low_brightness': '🔅',
+  'luggage': '🧳',
+  'lungs': '🫁',
+  'luxembourg': '🇱🇺',
+  'lying_face': '🤥',
+  'm': 'Ⓜ️',
+  'macau': '🇲🇴',
+  'macedonia': '🇲🇰',
+  'madagascar': '🇲🇬',
+  'mag': '🔍',
+  'mag_right': '🔎',
+  'mage': '🧙',
+  'mage_man': '🧙️‍♂',
+  'mage_woman': '🧙️‍♀',
+  'magic_wand': '🪄',
+  'magnet': '🧲',
+  'mahjong': '🀄',
+  'mailbox': '📫',
+  'mailbox_closed': '📪',
+  'mailbox_with_mail': '📬',
+  'mailbox_with_no_mail': '📭',
+  'malawi': '🇲🇼',
+  'malaysia': '🇲🇾',
+  'maldives': '🇲🇻',
+  'male_detective': '🕵',
+  'male_sign': '♂',
+  'mali': '🇲🇱',
+  'malta': '🇲🇹',
+  'mammoth': '🦣',
+  'man': '👨',
+  'man_artist': '👨‍🎨',
+  'man_astronaut': '👨‍🚀',
+  'man_beard': '🧔️‍♂',
+  'man_cartwheeling': '🤸‍♂️',
+  'man_cook': '👨‍🍳',
+  'man_dancing': '🕺',
+  'man_elf': '🧝‍♂️',
+  'man_facepalming': '🤦‍♂️',
+  'man_factory_worker': '👨‍🏭',
+  'man_fairy': '🧚‍♂️',
+  'man_farmer': '👨‍🌾',
+  'man_feeding_baby': '👨️‍🍼',
+  'man_firefighter': '👨‍🚒',
+  'man_genie': '🧞‍♂️',
+  'man_health_worker': '👨‍⚕️',
+  'man_in_lotus_position': '🧘‍♂️',
+  'man_in_manual_wheelchair': '👨️‍🦽',
+  'man_in_motorized_wheelchair': '👨️‍🦼',
+  'man_in_steamy_room': '🧖‍♂️',
+  'man_in_tuxedo': '🤵',
+  'man_judge': '👨‍⚖️',
+  'man_juggling': '🤹‍♂️',
+  'man_mechanic': '👨‍🔧',
+  'man_office_worker': '👨‍💼',
+  'man_pilot': '👨‍✈️',
+  'man_playing_handball': '🤾‍♂️',
+  'man_playing_water_polo': '🤽‍♂️',
+  'man_scientist': '👨‍🔬',
+  'man_shrugging': '🤷‍♂️',
+  'man_singer': '👨‍🎤',
+  'man_student': '👨‍🎓',
+  'man_superhero': '🦸‍♂️',
+  'man_supervillain': '🦹‍♂️',
+  'man_teacher': '👨‍🏫',
+  'man_technologist': '👨‍💻',
+  'man_vampire': '🧛‍♂️',
+  'man_with_gua_pi_mao': '👲',
+  'man_with_probing_cane': '👨️‍🦯',
+  'man_with_turban': '👳',
+  'man_with_veil': '👰️‍♂',
+  'man_zombie': '🧟‍♂️',
+  'mandarin': '🍊',
+  'mango': '🥭',
+  'mans_shoe': '👞',
+  'mantelpiece_clock': '🕰',
+  'manual_wheelchair': '🦽',
+  'maple_leaf': '🍁',
+  'marshall_islands': '🇲🇭',
+  'martial_arts_uniform': '🥋',
+  'martinique': '🇲🇶',
+  'mask': '😷',
+  'massage': '💆',
+  'massage_man': '💆‍♂️',
+  'massage_woman': '💆',
+  'mate': '🧉',
+  'mauritania': '🇲🇷',
+  'mauritius': '🇲🇺',
+  'mayotte': '🇾🇹',
+  'meat_on_bone': '🍖',
+  'mechanic': '🧑️‍🔧',
+  'mechanical_arm': '🦾',
+  'mechanical_leg': '🦿',
+  'medal_military': '🎖',
+  'medal_sports': '🏅',
+  'medical_symbol': '⚕',
+  'mega': '📣',
+  'melon': '🍈',
+  'memo': '📝',
+  'men_wrestling': '🤼‍♂️',
+  'mending_heart': '❤️‍🩹',
+  'menorah': '🕎',
+  'mens': '🚹',
+  'mermaid': '🧜‍♀️',
+  'merman': '🧜‍♂️',
+  'merperson': '🧜',
+  'metal': '🤘',
+  'metro': '🚇',
+  'mexico': '🇲🇽',
+  'microbe': '🦠',
+  'micronesia': '🇫🇲',
+  'microphone': '🎤',
+  'microscope': '🔬',
+  'middle_finger': '🖕',
+  'military_helmet': '🪖',
+  'milk_glass': '🥛',
+  'milky_way': '🌌',
+  'minibus': '🚐',
+  'minidisc': '💽',
+  'mirror': '🪞',
+  'mobile_phone_off': '📴',
+  'moldova': '🇲🇩',
+  'monaco': '🇲🇨',
+  'money_mouth_face': '🤑',
+  'money_with_wings': '💸',
+  'moneybag': '💰',
+  'mongolia': '🇲🇳',
+  'monkey': '🐒',
+  'monkey_face': '🐵',
+  'monocle': '🧐',
+  'monocle_face': '🧐',
+  'monorail': '🚝',
+  'montenegro': '🇲🇪',
+  'montserrat': '🇲🇸',
+  'moon': '🌔',
+  'moon_cake': '🥮',
+  'morocco': '🇲🇦',
+  'mortar_board': '🎓',
+  'mosque': '🕌',
+  'mosquito': '🦟',
+  'motor_boat': '🛥',
+  'motor_scooter': '🛵',
+  'motorcycle': '🏍',
+  'motorized_wheelchair': '🦼',
+  'motorway': '🛣',
+  'mount_fuji': '🗻',
+  'mountain': '⛰',
+  'mountain_bicyclist': '🚵',
+  'mountain_biking_man': '🚵',
+  'mountain_biking_woman': '🚵‍♀️',
+  'mountain_cableway': '🚠',
+  'mountain_railway': '🚞',
+  'mountain_snow': '🏔',
+  'mouse': '🐭',
+  'mouse2': '🐁',
+  'mouse_trap': '🪤',
+  'movie_camera': '🎥',
+  'moyai': '🗿',
+  'mozambique': '🇲🇿',
+  'mrs_claus': '🤶',
+  'muscle': '💪',
+  'mushroom': '🍄',
+  'musical_keyboard': '🎹',
+  'musical_note': '🎵',
+  'musical_score': '🎼',
+  'mute': '🔇',
+  'mx_claus': '🧑️‍🎄',
+  'myanmar': '🇲🇲',
+  'nail_care': '💅',
+  'name_badge': '📛',
+  'namibia': '🇳🇦',
+  'national_park': '🏞',
+  'nauru': '🇳🇷',
+  'nauseated_face': '🤢',
+  'nazar_amulet': '🧿',
+  'necktie': '👔',
+  'negative_squared_cross_mark': '❎',
+  'nepal': '🇳🇵',
+  'nerd_face': '🤓',
+  'nesting_dolls': '🪆',
+  'netherlands': '🇳🇱',
+  'neutral_face': '😐',
+  'new': '🆕',
+  'new_caledonia': '🇳🇨',
+  'new_moon': '🌑',
+  'new_moon_with_face': '🌚',
+  'new_zealand': '🇳🇿',
+  'newspaper': '📰',
+  'newspaper_roll': '🗞',
+  'next_track_button': '⏭',
+  'ng': '🆖',
+  'ng_man': '🙅️‍♂',
+  'ng_woman': '🙅️‍♀',
+  'nicaragua': '🇳🇮',
+  'niger': '🇳🇪',
+  'nigeria': '🇳🇬',
+  'night_with_stars': '🌃',
+  'nine': '9️⃣',
+  'ninja': '🥷',
+  'niue': '🇳🇺',
+  'no_bell': '🔕',
+  'no_bicycles': '🚳',
+  'no_entry': '⛔',
+  'no_entry_sign': '🚫',
+  'no_good': '🙅',
+  'no_good_man': '🙅‍♂️',
+  'no_good_woman': '🙅',
+  'no_mobile_phones': '📵',
+  'no_mouth': '😶',
+  'no_pedestrians': '🚷',
+  'no_smoking': '🚭',
+  'non-potable_water': '🚱',
+  'norfolk_island': '🇳🇫',
+  'north_korea': '🇰🇵',
+  'northern_mariana_islands': '🇲🇵',
+  'norway': '🇳🇴',
+  'nose': '👃',
+  'notebook': '📓',
+  'notebook_with_decorative_cover': '📔',
+  'notes': '🎶',
+  'nut_and_bolt': '🔩',
+  'o': '⭕',
+  'o2': '🅾️',
+  'ocean': '🌊',
+  'octopus': '🐙',
+  'oden': '🍢',
+  'office': '🏢',
+  'office_worker': '🧑️‍💼',
+  'oil_drum': '🛢',
+  'ok': '🆗',
+  'ok_hand': '👌',
+  'ok_man': '🙆‍♂️',
+  'ok_person': '🙆',
+  'ok_woman': '🙆',
+  'old_key': '🗝',
+  'older_adult': '🧓',
+  'older_man': '👴',
+  'older_woman': '👵',
+  'olive': '🫒',
+  'om': '🕉',
+  'oman': '🇴🇲',
+  'on': '🔛',
+  'oncoming_automobile': '🚘',
+  'oncoming_bus': '🚍',
+  'oncoming_police_car': '🚔',
+  'oncoming_taxi': '🚖',
+  'one': '1️⃣',
+  'one_piece_swimsuit': '🩱',
+  'onion': '🧅',
+  'open_book': '📖',
+  'open_file_folder': '📂',
+  'open_hands': '👐',
+  'open_mouth': '😮',
+  'open_umbrella': '☂',
+  'ophiuchus': '⛎',
+  'orange': '🍊',
+  'orange_book': '📙',
+  'orange_circle': '🟠',
+  'orange_heart': '🧡',
+  'orange_square': '🟧',
+  'orangutan': '🦧',
+  'orthodox_cross': '☦',
+  'otter': '🦦',
+  'outbox_tray': '📤',
+  'owl': '🦉',
+  'ox': '🐂',
+  'oyster': '🦪',
+  'package': '📦',
+  'page_facing_up': '📄',
+  'page_with_curl': '📃',
+  'pager': '📟',
+  'paintbrush': '🖌',
+  'pakistan': '🇵🇰',
+  'palau': '🇵🇼',
+  'palestinian_territories': '🇵🇸',
+  'palm_tree': '🌴',
+  'palms_up': '🤲',
+  'palms_up_together': '🤲',
+  'panama': '🇵🇦',
+  'pancakes': '🥞',
+  'panda_face': '🐼',
+  'paperclip': '📎',
+  'paperclips': '🖇',
+  'papua_new_guinea': '🇵🇬',
+  'parachute': '🪂',
+  'paraguay': '🇵🇾',
+  'parasol_on_ground': '⛱',
+  'parking': '🅿️',
+  'parrot': '🦜',
+  'part_alternation_mark': '〽️',
+  'partly_sunny': '⛅',
+  'partying': '🥳',
+  'partying_face': '🥳',
+  'passenger_ship': '🛳',
+  'passport_control': '🛂',
+  'pause_button': '⏸',
+  'paw_prints': '🐾',
+  'peace_symbol': '☮',
+  'peach': '🍑',
+  'peacock': '🦚',
+  'peanuts': '🥜',
+  'pear': '🍐',
+  'pen': '🖊',
+  'pencil': '📝',
+  'pencil2': '✏️',
+  'penguin': '🐧',
+  'pensive': '😔',
+  'people_holding_hands': '🧑️‍🤝️‍🧑',
+  'people_hugging': '🫂',
+  'performing_arts': '🎭',
+  'persevere': '😣',
+  'person_bald': '🧑️‍🦲',
+  'person_curly_hair': '🧑️‍🦱',
+  'person_feeding_baby': '🧑️‍🍼',
+  'person_fencing': '🤺',
+  'person_in_manual_wheelchair': '🧑️‍🦽',
+  'person_in_motorized_wheelchair': '🧑️‍🦼',
+  'person_in_tuxedo': '🤵',
+  'person_red_hair': '🧑️‍🦰',
+  'person_white_hair': '🧑️‍🦳',
+  'person_with_probing_cane': '🧑️‍🦯',
+  'person_with_turban': '👳',
+  'person_with_veil': '👰',
+  'peru': '🇵🇪',
+  'petri_dish': '🧫',
+  'philippines': '🇵🇭',
+  'phone': '☎️',
+  'pick': '⛏',
+  'pickup_truck': '🛻',
+  'pie': '🥧',
+  'pig': '🐷',
+  'pig2': '🐖',
+  'pig_nose': '🐽',
+  'pill': '💊',
+  'pilot': '🧑️‍✈',
+  'pinata': '🪅',
+  'pinched_fingers': '🤌',
+  'pinching_hand': '🤏',
+  'pineapple': '🍍',
+  'ping_pong': '🏓',
+  'pirate_flag': '🏴‍☠️',
+  'pisces': '♓',
+  'pitcairn_islands': '🇵🇳',
+  'pizza': '🍕',
+  'placard': '🪧',
+  'place_of_worship': '🛐',
+  'plate_with_cutlery': '🍽',
+  'play_or_pause_button': '⏯',
+  'pleading': '🥺',
+  'pleading_face': '🥺',
+  'plunger': '🪠',
+  'point_down': '👇',
+  'point_left': '👈',
+  'point_right': '👉',
+  'point_up': '☝',
+  'point_up_2': '👆',
+  'poland': '🇵🇱',
+  'polar_bear': '🐻️‍❄',
+  'police_car': '🚓',
+  'police_officer': '👮',
+  'policeman': '👮',
+  'policewoman': '👮‍♀️',
+  'poodle': '🐩',
+  'poop': '💩',
+  'popcorn': '🍿',
+  'portugal': '🇵🇹',
+  'post_office': '🏣',
+  'postal_horn': '📯',
+  'postbox': '📮',
+  'potable_water': '🚰',
+  'potato': '🥔',
+  'potted_plant': '🪴',
+  'pouch': '👝',
+  'poultry_leg': '🍗',
+  'pound': '💷',
+  'pout': '😡',
+  'pouting_cat': '😾',
+  'pouting_face': '🙎',
+  'pouting_man': '🙎‍♂️',
+  'pouting_woman': '🙎',
+  'pray': '🙏',
+  'prayer_beads': '📿',
+  'pregnant_woman': '🤰',
+  'pretzel': '🥨',
+  'previous_track_button': '⏮',
+  'prince': '🤴',
+  'princess': '👸',
+  'printer': '🖨',
+  'probing_cane': '🦯',
+  'puerto_rico': '🇵🇷',
+  'punch': '👊',
+  'purple_circle': '🟣',
+  'purple_heart': '💜',
+  'purple_square': '🟪',
+  'purse': '👛',
+  'pushpin': '📌',
+  'put_litter_in_its_place': '🚮',
+  'qatar': '🇶🇦',
+  'question': '❓',
+  'rabbit': '🐰',
+  'rabbit2': '🐇',
+  'raccoon': '🦝',
+  'racehorse': '🐎',
+  'racing_car': '🏎',
+  'radio': '📻',
+  'radio_button': '🔘',
+  'radioactive': '☢',
+  'rage': '😡',
+  'railway_car': '🚃',
+  'railway_track': '🛤',
+  'rainbow': '🌈',
+  'rainbow_flag': '🏳️‍🌈',
+  'raised_back_of_hand': '🤚',
+  'raised_eyebrow': '🤨',
+  'raised_hand': '✋',
+  'raised_hand_with_fingers_splayed': '🖐',
+  'raised_hands': '🙌',
+  'raising_hand': '🙋',
+  'raising_hand_man': '🙋‍♂️',
+  'raising_hand_woman': '🙋',
+  'ram': '🐏',
+  'ramen': '🍜',
+  'rat': '🐀',
+  'razor': '🪒',
+  'receipt': '🧾',
+  'record_button': '⏺',
+  'recycle': '♻️',
+  'red_car': '🚗',
+  'red_circle': '🔴',
+  'red_envelope': '🧧',
+  'red_haired_man': '👨️‍🦰',
+  'red_haired_woman': '👩️‍🦰',
+  'red_square': '🟥',
+  'registered': '®️',
+  'relaxed': '☺️',
+  'relieved': '😌',
+  'reminder_ribbon': '🎗',
+  'repeat': '🔁',
+  'repeat_one': '🔂',
+  'rescue_worker_helmet': '⛑',
+  'restroom': '🚻',
+  'reunion': '🇷🇪',
+  'revolving_hearts': '💞',
+  'rewind': '⏪',
+  'rhinoceros': '🦏',
+  'ribbon': '🎀',
+  'rice': '🍚',
+  'rice_ball': '🍙',
+  'rice_cracker': '🍘',
+  'rice_scene': '🎑',
+  'right_anger_bubble': '🗯',
+  'ring': '💍',
+  'ringed_planet': '🪐',
+  'robot': '🤖',
+  'rock': '🪨',
+  'rocket': '🚀',
+  'rofl': '🤣',
+  'roll_eyes': '🙄',
+  'roll_of_paper': '🧻',
+  'roller_coaster': '🎢',
+  'roller_skate': '🛼',
+  'romania': '🇷🇴',
+  'rooster': '🐓',
+  'rose': '🌹',
+  'rosette': '🏵',
+  'rotating_light': '🚨',
+  'round_pushpin': '📍',
+  'rowboat': '🚣',
+  'rowing_man': '🚣',
+  'rowing_woman': '🚣‍♀️',
+  'ru': '🇷🇺',
+  'rugby_football': '🏉',
+  'runner': '🏃',
+  'running': '🏃',
+  'running_man': '🏃',
+  'running_shirt_with_sash': '🎽',
+  'running_woman': '🏃‍♀️',
+  'rwanda': '🇷🇼',
+  'sa': '🈂️',
+  'safety_pin': '🧷',
+  'safety_vest': '🦺',
+  'sagittarius': '♐',
+  'sailboat': '⛵',
+  'sake': '🍶',
+  'salt': '🧂',
+  'samoa': '🇼🇸',
+  'san_marino': '🇸🇲',
+  'sandal': '👡',
+  'sandwich': '🥪',
+  'santa': '🎅',
+  'sao_tome_principe': '🇸🇹',
+  'sari': '🥻',
+  'sassy_man': '💁️‍♂',
+  'sassy_woman': '💁️‍♀',
+  'satellite': '📡',
+  'satisfied': '😆',
+  'saudi_arabia': '🇸🇦',
+  'sauna_man': '🧖️‍♂',
+  'sauna_person': '🧖',
+  'sauna_woman': '🧖️‍♀',
+  'sauropod': '🦕',
+  'saxophone': '🎷',
+  'scarf': '🧣',
+  'school': '🏫',
+  'school_satchel': '🎒',
+  'scientist': '🧑️‍🔬',
+  'scissors': '✂️',
+  'scorpion': '🦂',
+  'scorpius': '♏',
+  'scotland': '🏴󠁧󠁢󠁳󠁣󠁴󠁿',
+  'scream': '😱',
+  'scream_cat': '🙀',
+  'screwdriver': '🪛',
+  'scroll': '📜',
+  'seal': '🦭',
+  'seat': '💺',
+  'secret': '㊙️',
+  'see_no_evil': '🙈',
+  'seedling': '🌱',
+  'selfie': '🤳',
+  'senegal': '🇸🇳',
+  'serbia': '🇷🇸',
+  'service_dog': '🐕️‍🦺',
+  'seven': '7️⃣',
+  'sewing_needle': '🪡',
+  'seychelles': '🇸🇨',
+  'shallow_pan_of_food': '🥘',
+  'shamrock': '☘',
+  'shark': '🦈',
+  'shaved_ice': '🍧',
+  'sheep': '🐑',
+  'shell': '🐚',
+  'shield': '🛡',
+  'shinto_shrine': '⛩',
+  'ship': '🚢',
+  'shirt': '👕',
+  'shit': '💩',
+  'shoe': '👞',
+  'shopping': '🛍',
+  'shopping_cart': '🛒',
+  'shorts': '🩳',
+  'shower': '🚿',
+  'shrimp': '🦐',
+  'shrug': '🤷',
+  'shushing': '🤫',
+  'shushing_face': '🤫',
+  'sierra_leone': '🇸🇱',
+  'signal_strength': '📶',
+  'singapore': '🇸🇬',
+  'singer': '🧑️‍🎤',
+  'sint_maarten': '🇸🇽',
+  'six': '6️⃣',
+  'six_pointed_star': '🔯',
+  'skateboard': '🛹',
+  'ski': '🎿',
+  'skier': '⛷',
+  'skull': '💀',
+  'skull_and_crossbones': '☠',
+  'skunk': '🦨',
+  'sled': '🛷',
+  'sleeping': '😴',
+  'sleeping_bed': '🛌',
+  'sleepy': '😪',
+  'slightly_frowning_face': '🙁',
+  'slightly_smiling_face': '🙂',
+  'slot_machine': '🎰',
+  'sloth': '🦥',
+  'slovakia': '🇸🇰',
+  'slovenia': '🇸🇮',
+  'small_airplane': '🛩',
+  'small_blue_diamond': '🔹',
+  'small_orange_diamond': '🔸',
+  'small_red_triangle': '🔺',
+  'small_red_triangle_down': '🔻',
+  'smile': '😄',
+  'smile_cat': '😸',
+  'smiley': '😃',
+  'smiley_cat': '😺',
+  'smiling_face_with_tear': '🥲',
+  'smiling_face_with_three_hearts': '🥰',
+  'smiling_imp': '😈',
+  'smirk': '😏',
+  'smirk_cat': '😼',
+  'smoking': '🚬',
+  'snail': '🐌',
+  'snake': '🐍',
+  'sneezing_face': '🤧',
+  'snowboarder': '🏂',
+  'snowflake': '❄️',
+  'snowman': '⛄',
+  'snowman_with_snow': '☃',
+  'soap': '🧼',
+  'sob': '😭',
+  'soccer': '⚽',
+  'socks': '🧦',
+  'softball': '🥎',
+  'solomon_islands': '🇸🇧',
+  'somalia': '🇸🇴',
+  'soon': '🔜',
+  'sorceress': '🧙‍♀️',
+  'sos': '🆘',
+  'sound': '🔉',
+  'south_africa': '🇿🇦',
+  'south_georgia_south_sandwich_islands': '🇬🇸',
+  'south_sudan': '🇸🇸',
+  'space_invader': '👾',
+  'spades': '♠️',
+  'spaghetti': '🍝',
+  'sparkle': '❇️',
+  'sparkler': '🎇',
+  'sparkles': '✨',
+  'sparkling_heart': '💖',
+  'speak_no_evil': '🙊',
+  'speaker': '🔈',
+  'speaking_head': '🗣',
+  'speech_balloon': '💬',
+  'speedboat': '🚤',
+  'spider': '🕷',
+  'spider_web': '🕸',
+  'spiral_calendar': '🗓',
+  'spiral_notepad': '🗒',
+  'sponge': '🧽',
+  'spoon': '🥄',
+  'squid': '🦑',
+  'sri_lanka': '🇱🇰',
+  'st_barthelemy': '🇧🇱',
+  'st_helena': '🇸🇭',
+  'st_kitts_nevis': '🇰🇳',
+  'st_lucia': '🇱🇨',
+  'st_martin': '🇲️‍🇫',
+  'st_pierre_miquelon': '🇵🇲',
+  'st_vincent_grenadines': '🇻🇨',
+  'stadium': '🏟',
+  'standing_man': '🧍️‍♂',
+  'standing_person': '🧍',
+  'standing_woman': '🧍️‍♀',
+  'star': '⭐',
+  'star2': '🌟',
+  'star_and_crescent': '☪',
+  'star_of_david': '✡',
+  'star_struck': '🤩',
+  'stars': '🌠',
+  'station': '🚉',
+  'statue_of_liberty': '🗽',
+  'steak': '🥩',
+  'steam_locomotive': '🚂',
+  'stethoscope': '🩺',
+  'stew': '🍲',
+  'stop_button': '⏹',
+  'stop_sign': '🛑',
+  'stopwatch': '⏱',
+  'straight_ruler': '📏',
+  'strawberry': '🍓',
+  'stuck_out_tongue': '😛',
+  'stuck_out_tongue_closed_eyes': '😝',
+  'stuck_out_tongue_winking_eye': '😜',
+  'student': '🧑️‍🎓',
+  'studio_microphone': '🎙',
+  'stuffed_flatbread': '🥙',
+  'sudan': '🇸🇩',
+  'sun_behind_large_cloud': '🌥',
+  'sun_behind_rain_cloud': '🌦',
+  'sun_behind_small_cloud': '🌤',
+  'sun_with_face': '🌞',
+  'sunflower': '🌻',
+  'sunglasses': '😎',
+  'sunny': '☀️',
+  'sunrise': '🌅',
+  'sunrise_over_mountains': '🌄',
+  'superhero': '🦸',
+  'superhero_man': '🦸️‍♂',
+  'superhero_woman': '🦸️‍♀',
+  'supervillain': '🦹',
+  'supervillain_man': '🦹️‍♂',
+  'supervillain_woman': '🦹️‍♀',
+  'surfer': '🏄',
+  'surfing_man': '🏄',
+  'surfing_woman': '🏄‍♀️',
+  'suriname': '🇸🇷',
+  'sushi': '🍣',
+  'suspension_railway': '🚟',
+  'svalbard_jan_mayen': '🇸️‍🇯',
+  'swan': '🦢',
+  'swaziland': '🇸🇿',
+  'sweat': '😓',
+  'sweat_drops': '💦',
+  'sweat_smile': '😅',
+  'sweden': '🇸🇪',
+  'sweet_potato': '🍠',
+  'swim_brief': '🩲',
+  'swimmer': '🏊',
+  'swimming_man': '🏊',
+  'swimming_woman': '🏊‍♀️',
+  'switzerland': '🇨🇭',
+  'symbols': '🔣',
+  'symbols_over_mouth': '🤬',
+  'synagogue': '🕍',
+  'syria': '🇸🇾',
+  'syringe': '💉',
+  't-rex': '🦖',
+  'taco': '🌮',
+  'tada': '🎉',
+  'taiwan': '🇹🇼',
+  'tajikistan': '🇹🇯',
+  'takeout_box': '🥡',
+  'tamale': '🫔',
+  'tanabata_tree': '🎋',
+  'tangerine': '🍊',
+  'tanzania': '🇹🇿',
+  'taurus': '♉',
+  'taxi': '🚕',
+  'tea': '🍵',
+  'teacher': '🧑️‍🏫',
+  'teapot': '🫖',
+  'technologist': '🧑️‍💻',
+  'teddy_bear': '🧸',
+  'telephone': '☎️',
+  'telephone_receiver': '📞',
+  'telescope': '🔭',
+  'tennis': '🎾',
+  'tent': '⛺',
+  'test_tube': '🧪',
+  'thailand': '🇹🇭',
+  'thermometer': '🌡',
+  'thinking': '🤔',
+  'thong_sandal': '🩴',
+  'thought_balloon': '💭',
+  'thread': '🧵',
+  'three': '3️⃣',
+  'thumbsdown': '👎',
+  'thumbsup': '👍',
+  'ticket': '🎫',
+  'tickets': '🎟',
+  'tiger': '🐯',
+  'tiger2': '🐅',
+  'timer_clock': '⏲',
+  'timor_leste': '🇹🇱',
+  'tipping_hand_man': '💁‍♂️',
+  'tipping_hand_person': '💁',
+  'tipping_hand_woman': '💁',
+  'tired_face': '😫',
+  'tm': '™️',
+  'togo': '🇹🇬',
+  'toilet': '🚽',
+  'toilet_paper': '🧻',
+  'tokelau': '🇹🇰',
+  'tokyo_tower': '🗼',
+  'tomato': '🍅',
+  'tonga': '🇹🇴',
+  'tongue': '👅',
+  'toolbox': '🧰',
+  'tooth': '🦷',
+  'toothbrush': '🪥',
+  'top': '🔝',
+  'tophat': '🎩',
+  'tornado': '🌪',
+  'tr': '🇹🇷',
+  'trackball': '🖲',
+  'tractor': '🚜',
+  'traffic_light': '🚥',
+  'train': '🚋',
+  'train2': '🚆',
+  'tram': '🚊',
+  'transgender_flag': '🏳️‍⚧',
+  'transgender_symbol': '⚧',
+  'triangular_flag_on_post': '🚩',
+  'triangular_ruler': '📐',
+  'trident': '🔱',
+  'trinidad_tobago': '🇹🇹',
+  'tristan_da_cunha': '🇹️‍🇦',
+  'triumph': '😤',
+  'trolleybus': '🚎',
+  'trophy': '🏆',
+  'tropical_drink': '🍹',
+  'tropical_fish': '🐠',
+  'truck': '🚚',
+  'trumpet': '🎺',
+  'tshirt': '👕',
+  'tulip': '🌷',
+  'tumbler_glass': '🥃',
+  'tunisia': '🇹🇳',
+  'turkey': '🦃',
+  'turkmenistan': '🇹🇲',
+  'turks_caicos_islands': '🇹🇨',
+  'turtle': '🐢',
+  'tuvalu': '🇹🇻',
+  'tv': '📺',
+  'twisted_rightwards_arrows': '🔀',
+  'two': '2️⃣',
+  'two_hearts': '💕',
+  'two_men_holding_hands': '👬',
+  'two_women_holding_hands': '👭',
+  'u5272': '🈹',
+  'u5408': '🈴',
+  'u55b6': '🈺',
+  'u6307': '🈯',
+  'u6708': '🈷️',
+  'u6709': '🈶',
+  'u6e80': '🈵',
+  'u7121': '🈚',
+  'u7533': '🈸',
+  'u7981': '🈲',
+  'u7a7a': '🈳',
+  'uganda': '🇺🇬',
+  'uk': '🇬🇧',
+  'ukraine': '🇺🇦',
+  'umbrella': '☔',
+  'unamused': '😒',
+  'underage': '🔞',
+  'unicorn': '🦄',
+  'united_arab_emirates': '🇦🇪',
+  'united_nations': '🇺🇳',
+  'unlock': '🔓',
+  'up': '🆙',
+  'upside_down_face': '🙃',
+  'uruguay': '🇺🇾',
+  'us': '🇺🇸',
+  'us_outlying_islands': '🇺️‍🇲',
+  'us_virgin_islands': '🇻🇮',
+  'uzbekistan': '🇺🇿',
+  'v': '✌',
+  'vampire': '🧛',
+  'vampire_man': '🧛️‍♂',
+  'vampire_woman': '🧛️‍♀',
+  'vanuatu': '🇻🇺',
+  'vatican_city': '🇻🇦',
+  'venezuela': '🇻🇪',
+  'vertical_traffic_light': '🚦',
+  'vhs': '📼',
+  'vibration_mode': '📳',
+  'video_camera': '📹',
+  'video_game': '🎮',
+  'vietnam': '🇻🇳',
+  'violin': '🎻',
+  'virgo': '♍',
+  'volcano': '🌋',
+  'volleyball': '🏐',
+  'vomiting': '🤮',
+  'vomiting_face': '🤮',
+  'vs': '🆚',
+  'vulcan_salute': '🖖',
+  'waffle': '🧇',
+  'wales': '🏴󠁧󠁢󠁷󠁬󠁳󠁿',
+  'walking': '🚶',
+  'walking_man': '🚶',
+  'walking_woman': '🚶‍♀️',
+  'wallis_futuna': '🇼🇫',
+  'waning_crescent_moon': '🌘',
+  'waning_gibbous_moon': '🌖',
+  'warning': '⚠️',
+  'wastebasket': '🗑',
+  'watch': '⌚',
+  'water_buffalo': '🐃',
+  'water_polo': '🤽',
+  'watermelon': '🍉',
+  'wave': '👋',
+  'wavy_dash': '〰️',
+  'waxing_crescent_moon': '🌒',
+  'waxing_gibbous_moon': '🌔',
+  'wc': '🚾',
+  'weary': '😩',
+  'wedding': '💒',
+  'weight_lifting': '🏋',
+  'weight_lifting_man': '🏋',
+  'weight_lifting_woman': '🏋️‍♀️',
+  'western_sahara': '🇪🇭',
+  'whale': '🐳',
+  'whale2': '🐋',
+  'wheel_of_dharma': '☸',
+  'wheelchair': '♿',
+  'white_check_mark': '✅',
+  'white_circle': '⚪',
+  'white_flag': '🏳',
+  'white_flower': '💮',
+  'white_haired_man': '👨️‍🦳',
+  'white_haired_woman': '👩️‍🦳',
+  'white_heart': '🤍',
+  'white_large_square': '⬜',
+  'white_medium_small_square': '◽',
+  'white_medium_square': '◻️',
+  'white_small_square': '▫️',
+  'white_square_button': '🔳',
+  'wilted_flower': '🥀',
+  'wind_chime': '🎐',
+  'wind_face': '🌬',
+  'window': '🪟',
+  'wine_glass': '🍷',
+  'wink': '😉',
+  'wizard': '🧙‍♂️',
+  'wolf': '🐺',
+  'woman': '👩',
+  'woman_artist': '👩‍🎨',
+  'woman_astronaut': '👩‍🚀',
+  'woman_beard': '🧔️‍♀',
+  'woman_cartwheeling': '🤸‍♀️',
+  'woman_cook': '👩‍🍳',
+  'woman_dancing': '💃',
+  'woman_elf': '🧝‍♀️',
+  'woman_facepalming': '🤦‍♀️',
+  'woman_factory_worker': '👩‍🏭',
+  'woman_fairy': '🧚‍♀️',
+  'woman_farmer': '👩‍🌾',
+  'woman_feeding_baby': '👩️‍🍼',
+  'woman_firefighter': '👩‍🚒',
+  'woman_genie': '🧞‍♀️',
+  'woman_health_worker': '👩‍⚕️',
+  'woman_in_lotus_position': '🧘‍♀️',
+  'woman_in_manual_wheelchair': '👩️‍🦽',
+  'woman_in_motorized_wheelchair': '👩️‍🦼',
+  'woman_in_steamy_room': '🧖‍♀️',
+  'woman_in_tuxedo': '🤵️‍♀',
+  'woman_judge': '👩‍⚖️',
+  'woman_juggling': '🤹‍♀️',
+  'woman_mechanic': '👩‍🔧',
+  'woman_office_worker': '👩‍💼',
+  'woman_pilot': '👩‍✈️',
+  'woman_playing_handball': '🤾‍♀️',
+  'woman_playing_water_polo': '🤽‍♀️',
+  'woman_scientist': '👩‍🔬',
+  'woman_shrugging': '🤷',
+  'woman_singer': '👩‍🎤',
+  'woman_student': '👩‍🎓',
+  'woman_superhero': '🦸‍♀️',
+  'woman_supervillain': '🦹‍♀️',
+  'woman_teacher': '👩‍🏫',
+  'woman_technologist': '👩‍💻',
+  'woman_vampire': '🧛‍♀️',
+  'woman_with_headscarf': '🧕',
+  'woman_with_probing_cane': '👩️‍🦯',
+  'woman_with_turban': '👳‍♀️',
+  'woman_with_veil': '👰️‍♀',
+  'woman_zombie': '🧟‍♀️',
+  'womans_clothes': '👚',
+  'womans_hat': '👒',
+  'women_wrestling': '🤼‍♀️',
+  'womens': '🚺',
+  'wood': '🪵',
+  'woozy': '🥴',
+  'woozy_face': '🥴',
+  'world_map': '🗺',
+  'worm': '🪱',
+  'worried': '😟',
+  'wrench': '🔧',
+  'wrestling': '🤼',
+  'writing_hand': '✍',
+  'x': '❌',
+  'yarn': '🧶',
+  'yawning_face': '🥱',
+  'yellow_circle': '🟡',
+  'yellow_heart': '💛',
+  'yellow_square': '🟨',
+  'yemen': '🇾🇪',
+  'yen': '💴',
+  'yin_yang': '☯',
+  'yo_yo': '🪀',
+  'yum': '😋',
+  'zambia': '🇿🇲',
+  'zany': '🤪',
+  'zany_face': '🤪',
+  'zap': '⚡',
+  'zebra': '🦓',
+  'zero': '0️⃣',
+  'zimbabwe': '🇿🇼',
+  'zipper_mouth_face': '🤐',
+  'zombie': '🧟',
+  'zombie_man': '🧟️‍♂',
+  'zombie_woman': '🧟️‍♀',
+  'zzz': '💤',
+};
diff --git a/pkgs/markdown/lib/src/extension_set.dart b/pkgs/markdown/lib/src/extension_set.dart
new file mode 100644
index 0000000..58a25d8
--- /dev/null
+++ b/pkgs/markdown/lib/src/extension_set.dart
@@ -0,0 +1,103 @@
+import 'block_syntaxes/alert_block_syntax.dart';
+import 'block_syntaxes/block_syntax.dart';
+import 'block_syntaxes/fenced_code_block_syntax.dart';
+import 'block_syntaxes/footnote_def_syntax.dart';
+import 'block_syntaxes/header_with_id_syntax.dart';
+import 'block_syntaxes/ordered_list_with_checkbox_syntax.dart';
+import 'block_syntaxes/setext_header_with_id_syntax.dart';
+import 'block_syntaxes/table_syntax.dart';
+import 'block_syntaxes/unordered_list_with_checkbox_syntax.dart';
+import 'inline_syntaxes/autolink_extension_syntax.dart';
+import 'inline_syntaxes/color_swatch_syntax.dart';
+import 'inline_syntaxes/emoji_syntax.dart';
+import 'inline_syntaxes/inline_html_syntax.dart';
+import 'inline_syntaxes/inline_syntax.dart';
+import 'inline_syntaxes/strikethrough_syntax.dart';
+
+/// ExtensionSets provide a simple grouping mechanism for common Markdown
+/// flavors.
+///
+/// For example, the [gitHubFlavored] set of syntax extensions allows users to
+/// output HTML from their Markdown in a similar fashion to GitHub's parsing.
+class ExtensionSet {
+  /// The [ExtensionSet.none] extension set renders Markdown similar to
+  /// [Markdown.pl].
+  ///
+  /// However, this set does not render _exactly_ the same as Markdown.pl;
+  /// rather it is more-or-less the CommonMark standard of Markdown, without
+  /// fenced code blocks, or inline HTML.
+  ///
+  /// [Markdown.pl]: http://daringfireball.net/projects/markdown/syntax
+  static final ExtensionSet none = ExtensionSet(const [], const []);
+
+  /// The [commonMark] extension set is close to compliance with [CommonMark].
+  ///
+  /// [CommonMark]: http://commonmark.org/
+  static final ExtensionSet commonMark = ExtensionSet(
+    List<BlockSyntax>.unmodifiable(
+      <BlockSyntax>[const FencedCodeBlockSyntax()],
+    ),
+    List<InlineSyntax>.unmodifiable(
+      <InlineSyntax>[InlineHtmlSyntax()],
+    ),
+  );
+
+  /// The [gitHubWeb] extension set renders Markdown similarly to GitHub.
+  ///
+  /// This is different from the [gitHubFlavored] extension set in that GitHub
+  /// actually renders HTML different from straight [GitHub flavored Markdown].
+  ///
+  /// (The only difference currently is that [gitHubWeb] renders headers with
+  /// linkable IDs.)
+  ///
+  /// [GitHub flavored Markdown]: https://github.github.com/gfm/
+  static final ExtensionSet gitHubWeb = ExtensionSet(
+    List<BlockSyntax>.unmodifiable(
+      <BlockSyntax>[
+        const FencedCodeBlockSyntax(),
+        const HeaderWithIdSyntax(),
+        const SetextHeaderWithIdSyntax(),
+        const TableSyntax(),
+        const UnorderedListWithCheckboxSyntax(),
+        const OrderedListWithCheckboxSyntax(),
+        const FootnoteDefSyntax(),
+        const AlertBlockSyntax(),
+      ],
+    ),
+    List<InlineSyntax>.unmodifiable(
+      <InlineSyntax>[
+        InlineHtmlSyntax(),
+        StrikethroughSyntax(),
+        EmojiSyntax(),
+        ColorSwatchSyntax(),
+        AutolinkExtensionSyntax()
+      ],
+    ),
+  );
+
+  /// The [gitHubFlavored] extension set is close to compliance with the
+  /// [GitHub flavored Markdown spec](https://github.github.com/gfm/).
+  static final ExtensionSet gitHubFlavored = ExtensionSet(
+    List<BlockSyntax>.unmodifiable(
+      <BlockSyntax>[
+        const FencedCodeBlockSyntax(),
+        const TableSyntax(),
+        const UnorderedListWithCheckboxSyntax(),
+        const OrderedListWithCheckboxSyntax(),
+        const FootnoteDefSyntax(),
+      ],
+    ),
+    List<InlineSyntax>.unmodifiable(
+      <InlineSyntax>[
+        InlineHtmlSyntax(),
+        StrikethroughSyntax(),
+        AutolinkExtensionSyntax()
+      ],
+    ),
+  );
+
+  final List<BlockSyntax> blockSyntaxes;
+  final List<InlineSyntax> inlineSyntaxes;
+
+  ExtensionSet(this.blockSyntaxes, this.inlineSyntaxes);
+}
diff --git a/pkgs/markdown/lib/src/html_renderer.dart b/pkgs/markdown/lib/src/html_renderer.dart
new file mode 100644
index 0000000..404d870
--- /dev/null
+++ b/pkgs/markdown/lib/src/html_renderer.dart
@@ -0,0 +1,218 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+
+import 'ast.dart';
+import 'block_syntaxes/block_syntax.dart';
+import 'document.dart';
+import 'extension_set.dart';
+import 'inline_syntaxes/inline_syntax.dart';
+
+/// Converts the given string of Markdown to HTML.
+String markdownToHtml(
+  String markdown, {
+  Iterable<BlockSyntax> blockSyntaxes = const [],
+  Iterable<InlineSyntax> inlineSyntaxes = const [],
+  ExtensionSet? extensionSet,
+  Resolver? linkResolver,
+  Resolver? imageLinkResolver,
+  bool inlineOnly = false,
+  bool encodeHtml = true,
+  bool enableTagfilter = false,
+  bool withDefaultBlockSyntaxes = true,
+  bool withDefaultInlineSyntaxes = true,
+}) {
+  final document = Document(
+    blockSyntaxes: blockSyntaxes,
+    inlineSyntaxes: inlineSyntaxes,
+    extensionSet: extensionSet,
+    linkResolver: linkResolver,
+    imageLinkResolver: imageLinkResolver,
+    encodeHtml: encodeHtml,
+    withDefaultBlockSyntaxes: withDefaultBlockSyntaxes,
+    withDefaultInlineSyntaxes: withDefaultInlineSyntaxes,
+  );
+
+  if (inlineOnly) return renderToHtml(document.parseInline(markdown));
+
+  final nodes = document.parse(markdown);
+
+  return '${renderToHtml(nodes, enableTagfilter: enableTagfilter)}\n';
+}
+
+/// Renders [nodes] to HTML.
+String renderToHtml(List<Node> nodes, {bool enableTagfilter = false}) =>
+    HtmlRenderer(
+      enableTagfilter: enableTagfilter,
+    ).render(nodes);
+
+const _blockTags = [
+  'blockquote',
+  'h1',
+  'h2',
+  'h3',
+  'h4',
+  'h5',
+  'h6',
+  'hr',
+  'li',
+  'ol',
+  'p',
+  'pre',
+  'ul',
+  'address',
+  'article',
+  'aside',
+  'details',
+  'dd',
+  'div',
+  'dl',
+  'dt',
+  'figcaption',
+  'figure',
+  'footer',
+  'header',
+  'hgroup',
+  'main',
+  'nav',
+  'section',
+  'table',
+  'thead',
+  'tbody',
+  'th',
+  'tr',
+  'td',
+];
+
+/// Translates a parsed AST to HTML.
+class HtmlRenderer implements NodeVisitor {
+  late StringBuffer buffer;
+  late Set<String> uniqueIds;
+
+  final _elementStack = <Element>[];
+  String? _lastVisitedTag;
+  final bool _tagfilterEnabled;
+
+  HtmlRenderer({
+    bool enableTagfilter = false,
+  }) : _tagfilterEnabled = enableTagfilter;
+
+  String render(List<Node> nodes) {
+    buffer = StringBuffer();
+    uniqueIds = <String>{};
+
+    for (final node in nodes) {
+      node.accept(this);
+    }
+
+    return buffer.toString();
+  }
+
+  @override
+  void visitText(Text text) {
+    var content = text.textContent;
+
+    if (_tagfilterEnabled) {
+      content = _filterTags(content);
+    }
+    if (const ['br', 'p', 'li'].contains(_lastVisitedTag)) {
+      final lines = LineSplitter.split(content);
+      content = content.contains('<pre>')
+          ? lines.join('\n')
+          : lines.map((line) => line.trimLeft()).join('\n');
+      if (text.textContent.endsWith('\n')) {
+        content = '$content\n';
+      }
+    }
+    buffer.write(content);
+
+    _lastVisitedTag = null;
+  }
+
+  @override
+  bool visitElementBefore(Element element) {
+    // Hackish. Separate block-level elements with newlines.
+    if (buffer.isNotEmpty && _blockTags.contains(element.tag)) {
+      buffer.writeln();
+    }
+
+    buffer.write('<${element.tag}');
+
+    for (final entry in element.attributes.entries) {
+      buffer.write(' ${entry.key}="${entry.value}"');
+    }
+
+    final generatedId = element.generatedId;
+
+    // attach header anchor ids generated from text
+    if (generatedId != null) {
+      buffer.write(' id="${uniquifyId(generatedId)}"');
+    }
+
+    _lastVisitedTag = element.tag;
+
+    if (element.isEmpty) {
+      // Empty element like <hr/>.
+      buffer.write(' />');
+
+      if (element.tag == 'br') {
+        buffer.write('\n');
+      }
+
+      return false;
+    } else {
+      _elementStack.add(element);
+      buffer.write('>');
+      return true;
+    }
+  }
+
+  @override
+  void visitElementAfter(Element element) {
+    assert(identical(_elementStack.last, element));
+
+    if (element.children != null &&
+        element.children!.isNotEmpty &&
+        _blockTags.contains(_lastVisitedTag) &&
+        _blockTags.contains(element.tag)) {
+      buffer.writeln();
+    } else if (element.tag == 'blockquote') {
+      buffer.writeln();
+    }
+    buffer.write('</${element.tag}>');
+
+    _lastVisitedTag = _elementStack.removeLast().tag;
+  }
+
+  /// Uniquifies an id generated from text.
+  String uniquifyId(String id) {
+    if (!uniqueIds.contains(id)) {
+      uniqueIds.add(id);
+      return id;
+    }
+
+    var suffix = 2;
+    var suffixedId = '$id-$suffix';
+    while (uniqueIds.contains(suffixedId)) {
+      suffixedId = '$id-${suffix++}';
+    }
+    uniqueIds.add(suffixedId);
+    return suffixedId;
+  }
+
+  /// Filters some particular tags, see:
+  /// https://github.github.com/gfm/#disallowed-raw-html-extension-
+  // As said in the specification, this process should happen when rendering
+  // HTML output, so there should not be a dedicated syntax for this extension.
+  String _filterTags(String content) => content.replaceAll(
+      RegExp(
+        '<(?=(?:'
+        'title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext'
+        ')>)',
+        caseSensitive: false,
+        multiLine: true,
+      ),
+      '&lt;');
+}
diff --git a/pkgs/markdown/lib/src/inline_parser.dart b/pkgs/markdown/lib/src/inline_parser.dart
new file mode 100644
index 0000000..e700ecf
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_parser.dart
@@ -0,0 +1,355 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'ast.dart';
+import 'charcode.dart';
+import 'document.dart';
+import 'inline_syntaxes/autolink_syntax.dart';
+import 'inline_syntaxes/code_syntax.dart';
+import 'inline_syntaxes/decode_html_syntax.dart';
+import 'inline_syntaxes/delimiter_syntax.dart';
+import 'inline_syntaxes/email_autolink_syntax.dart';
+import 'inline_syntaxes/emphasis_syntax.dart';
+import 'inline_syntaxes/escape_html_syntax.dart';
+import 'inline_syntaxes/escape_syntax.dart';
+import 'inline_syntaxes/image_syntax.dart';
+import 'inline_syntaxes/inline_syntax.dart';
+import 'inline_syntaxes/line_break_syntax.dart';
+import 'inline_syntaxes/link_syntax.dart';
+import 'inline_syntaxes/soft_line_break_syntax.dart';
+import 'inline_syntaxes/text_syntax.dart';
+
+/// Maintains the internal state needed to parse inline span elements in
+/// Markdown.
+class InlineParser {
+  static final List<InlineSyntax> _defaultSyntaxes =
+      List<InlineSyntax>.unmodifiable(<InlineSyntax>[
+    EmailAutolinkSyntax(),
+    AutolinkSyntax(),
+    LineBreakSyntax(),
+    // Parse "**strong**" and "*emphasis*" tags.
+    EmphasisSyntax.asterisk(),
+    // Parse "__strong__" and "_emphasis_" tags.
+    EmphasisSyntax.underscore(),
+    CodeSyntax(),
+    SoftLineBreakSyntax(),
+    // We will add the LinkSyntax once we know about the specific link resolver.
+  ]);
+
+  /// The string of Markdown being parsed.
+  final String source;
+
+  /// The Markdown document this parser is parsing.
+  final Document document;
+
+  final syntaxes = <InlineSyntax>[];
+
+  /// The current read position.
+  int pos = 0;
+
+  /// Starting position of the last unconsumed text.
+  int start = 0;
+
+  /// The delimiter stack tracking possible opening delimiters and closing
+  /// delimiters for [DelimiterSyntax] nodes.
+  final _delimiterStack = <Delimiter>[];
+
+  /// The tree of parsed HTML nodes.
+  final _tree = <Node>[];
+
+  InlineParser(this.source, this.document) {
+    // User specified syntaxes are the first syntaxes to be evaluated.
+    syntaxes.addAll(document.inlineSyntaxes);
+
+    // This first RegExp matches plain text to accelerate parsing. It's written
+    // so that it does not match any prefix of any following syntaxes. Most
+    // Markdown is plain text, so it's faster to match one RegExp per 'word'
+    // rather than fail to match all the following RegExps at each non-syntax
+    // character position.
+    if (document.hasCustomInlineSyntaxes) {
+      // We should be less aggressive in blowing past "words".
+      syntaxes.add(TextSyntax(r'[A-Za-z0-9]+(?=\s)'));
+    } else {
+      syntaxes.add(TextSyntax(r'[ \tA-Za-z0-9]*[A-Za-z0-9](?=\s)'));
+    }
+
+    if (document.withDefaultInlineSyntaxes) {
+      // Custom link resolvers go after the generic text syntax.
+      syntaxes.addAll([
+        EscapeSyntax(),
+        DecodeHtmlSyntax(),
+        LinkSyntax(linkResolver: document.linkResolver),
+        ImageSyntax(linkResolver: document.imageLinkResolver)
+      ]);
+
+      syntaxes.addAll(_defaultSyntaxes);
+    }
+
+    if (encodeHtml) {
+      syntaxes.addAll([
+        EscapeHtmlSyntax(),
+        // Leave already-encoded HTML entities alone. Ensures we don't turn
+        // "&amp;" into "&amp;amp;"
+        TextSyntax('&[#a-zA-Z0-9]*;', startCharacter: $ampersand),
+      ]);
+    }
+  }
+
+  List<Node> parse() {
+    while (!isDone) {
+      // A right bracket (']') is special. Hitting this character triggers the
+      // "look for link or image" procedure.
+      // See https://spec.commonmark.org/0.30/#an-algorithm-for-parsing-nested-emphasis-and-links.
+      if (charAt(pos) == $rbracket) {
+        writeText();
+        _linkOrImage();
+        continue;
+      }
+
+      // See if the current text matches any defined Markdown syntax.
+      if (syntaxes.any((syntax) => syntax.tryMatch(this))) continue;
+
+      // If we got here, it's just text.
+      advanceBy(1);
+    }
+
+    // Write any trailing text content to a Text node.
+    writeText();
+    _processDelimiterRun(-1);
+    _combineAdjacentText(_tree);
+    return _tree;
+  }
+
+  /// Look back through the delimiter stack to see if we've found a link or
+  /// image.
+  ///
+  /// This is the "look for link or image" routine from the CommonMark spec:
+  /// https://spec.commonmark.org/0.30/#look-for-link-or-image.
+  void _linkOrImage() {
+    final index = _delimiterStack
+        .lastIndexWhere((d) => d.char == $lbracket || d.char == $exclamation);
+    if (index == -1) {
+      // Never found a possible open bracket. This is just a literal "]".
+      addNode(Text(']'));
+      advanceBy(1);
+      start = pos;
+      return;
+    }
+    final delimiter = _delimiterStack[index] as SimpleDelimiter;
+    if (!delimiter.isActive) {
+      _delimiterStack.removeAt(index);
+      addNode(Text(']'));
+      advanceBy(1);
+      start = pos;
+      return;
+    }
+    final syntax = delimiter.syntax;
+    if (syntax is LinkSyntax && syntaxes.any((e) => e is LinkSyntax)) {
+      final nodeIndex = _tree.lastIndexWhere((n) => n == delimiter.node);
+      final linkNodes = syntax.close(this, delimiter, null, getChildren: () {
+        _processDelimiterRun(index);
+        // All of the nodes which lie past [index] are children of this
+        // link/image.
+        final children = _tree.sublist(nodeIndex + 1, _tree.length);
+        _tree.removeRange(nodeIndex + 1, _tree.length);
+        return children;
+      });
+      if (linkNodes != null) {
+        _delimiterStack.removeAt(index);
+        if (delimiter.char == $lbracket) {
+          for (final d in _delimiterStack.sublist(0, index)) {
+            if (d.char == $lbracket) d.isActive = false;
+          }
+        }
+        _tree.replaceRange(nodeIndex, _tree.length, linkNodes);
+        advanceBy(1);
+        start = pos;
+      } else {
+        _delimiterStack.removeAt(index);
+        pos = start;
+        advanceBy(1);
+      }
+    } else {
+      throw StateError('Non-link syntax delimiter found with character '
+          '"${delimiter.char}"');
+    }
+  }
+
+  /// Rules 9 and 10.
+  bool _canFormEmphasis(Delimiter opener, Delimiter closer) {
+    if ((opener.canOpen && opener.canClose) ||
+        (closer.canOpen && closer.canClose)) {
+      return (opener.length + closer.length) % 3 != 0 ||
+          (opener.length % 3 == 0 && closer.length % 3 == 0);
+    } else {
+      return true;
+    }
+  }
+
+  /// Processes [DelimiterRun] type delimiters from [bottomIndex] and up.
+  ///
+  /// This is the same strategy as "process emphasis" routine according to the
+  /// CommonMark spec: https://spec.commonmark.org/0.30/#phase-2-inline-structure.
+  void _processDelimiterRun(int bottomIndex) {
+    var currentIndex = bottomIndex + 1;
+    // Track the lowest index where we might find an open delimiter given a
+    // closing delimiter length modulo 3.
+    // Each key in this map is an open delimiter character. Each value is a
+    // 3-element list. Each value in the list is the lowest index for the given
+    // delimiter length modulo 3 (0, 1, 2).
+    final openersBottom = <int, List<int>>{};
+    while (currentIndex < _delimiterStack.length) {
+      final closer = _delimiterStack[currentIndex];
+      if (!closer.canClose || closer is! DelimiterRun) {
+        currentIndex++;
+        continue;
+      }
+      openersBottom.putIfAbsent(closer.char, () => List.filled(3, bottomIndex));
+      final openersBottomPerCloserLength = openersBottom[closer.char]!;
+      final openerBottom = openersBottomPerCloserLength[closer.length % 3];
+      final openerIndex = _delimiterStack.lastIndexWhere(
+          (d) =>
+              d.char == closer.char && d.canOpen && _canFormEmphasis(d, closer),
+          currentIndex - 1);
+      if (openerIndex > bottomIndex && openerIndex > openerBottom) {
+        // Found an opener for [closer].
+        final opener = _delimiterStack[openerIndex];
+        if (opener is! DelimiterRun) {
+          currentIndex++;
+          continue;
+        }
+        final matchedTagIndex = opener.tags.lastIndexWhere((e) =>
+            opener.length >= e.indicatorLength &&
+            closer.length >= e.indicatorLength);
+        if (matchedTagIndex == -1) {
+          currentIndex++;
+          continue;
+        }
+        final matchedTag = opener.tags[matchedTagIndex];
+        final indicatorLength = matchedTag.indicatorLength;
+        final openerTextNode = opener.node;
+        final openerTextNodeIndex = _tree.indexOf(openerTextNode);
+        final closerTextNode = closer.node;
+        var closerTextNodeIndex = _tree.indexOf(closerTextNode);
+        final nodes = opener.syntax.close(
+          this,
+          opener,
+          closer,
+          tag: matchedTag.tag,
+          getChildren: () => _tree.sublist(
+            openerTextNodeIndex + 1,
+            closerTextNodeIndex,
+          ),
+        );
+        // Replace all of the nodes between the opener and the closer (which
+        // are now the new emphasis node's children) with the emphasis node.
+        _tree.replaceRange(
+          openerTextNodeIndex + 1,
+          closerTextNodeIndex,
+          nodes!,
+        );
+        // Slide [closerTextNodeIndex] back accordingly.
+        closerTextNodeIndex = openerTextNodeIndex + 2;
+
+        _delimiterStack.removeRange(openerIndex + 1, currentIndex);
+        // Slide [currentIndex] back accordingly.
+        currentIndex = openerIndex + 1;
+
+        // Remove delimiter characters, possibly removing nodes from the tree
+        // and Delimiters from the delimiter stack.
+        if (opener.length == indicatorLength) {
+          _tree.removeAt(openerTextNodeIndex);
+          _delimiterStack.removeAt(openerIndex);
+          // Slide [currentIndex] and [closerTextNodeIndex] back accordingly.
+          currentIndex--;
+          closerTextNodeIndex--;
+        } else {
+          final newOpenerTextNode =
+              Text(openerTextNode.text.substring(indicatorLength));
+          _tree[openerTextNodeIndex] = newOpenerTextNode;
+          opener.node = newOpenerTextNode;
+        }
+
+        if (closer.length == indicatorLength) {
+          _tree.removeAt(closerTextNodeIndex);
+          _delimiterStack.removeAt(currentIndex);
+          // [currentIndex] has just moved to point at the next delimiter;
+          // leave it.
+        } else {
+          final newCloserTextNode =
+              Text(closerTextNode.text.substring(indicatorLength));
+          _tree[closerTextNodeIndex] = newCloserTextNode;
+          closer.node = newCloserTextNode;
+          // [currentIndex] needs to be considered again; leave it.
+        }
+      } else {
+        // No opener is found.
+        openersBottomPerCloserLength[closer.length % 3] = currentIndex - 1;
+        if (!closer.canOpen) {
+          _delimiterStack.removeAt(currentIndex);
+          // This advances [currentIndex] to the next delimiter.
+        } else {
+          currentIndex++;
+        }
+      }
+    }
+
+    _delimiterStack.removeRange(bottomIndex + 1, _delimiterStack.length);
+  }
+
+  // Combine any remaining adjacent Text nodes. This is important to produce
+  // correct output across newlines, where whitespace is sometimes compressed.
+  void _combineAdjacentText(List<Node> nodes) {
+    for (var i = 0; i < nodes.length - 1; i++) {
+      final node = nodes[i];
+      if (node is Element && node.children != null) {
+        _combineAdjacentText(node.children!);
+        continue;
+      }
+      if (node is Text && nodes[i + 1] is Text) {
+        final buffer =
+            StringBuffer('${node.textContent}${nodes[i + 1].textContent}');
+        var j = i + 2;
+        while (j < nodes.length && nodes[j] is Text) {
+          buffer.write(nodes[j].textContent);
+          j++;
+        }
+        nodes[i] = Text(buffer.toString());
+        nodes.removeRange(i + 1, j);
+      }
+    }
+  }
+
+  int charAt(int index) => source.codeUnitAt(index);
+
+  void writeText() {
+    if (pos == start) {
+      return;
+    }
+    final text = source.substring(start, pos);
+    _tree.add(Text(text));
+    start = pos;
+  }
+
+  /// Add [node] to the current tree.
+  void addNode(Node node) {
+    _tree.add(node);
+  }
+
+  /// Push [delimiter] onto the stack of [Delimiter]s.
+  void pushDelimiter(Delimiter delimiter) => _delimiterStack.add(delimiter);
+
+  bool get isDone => pos == source.length;
+
+  void advanceBy(int length) {
+    pos += length;
+  }
+
+  void consume(int length) {
+    pos += length;
+    start = pos;
+  }
+
+  bool get encodeHtml => document.encodeHtml;
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/autolink_extension_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/autolink_extension_syntax.dart
new file mode 100644
index 0000000..0333abb
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/autolink_extension_syntax.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches autolinks like `http://foo.com` and `foo@bar.com`.
+class AutolinkExtensionSyntax extends InlineSyntax {
+  static const _linkPattern =
+      // Autolinks can only come at the beginning of a line, after whitespace,
+      // or any of the delimiting characters *, _, ~, and (.
+      // Note: Disable this piece for now, as Safari does not support
+      // lookarounds. Consider re-enabling later.
+      // r'(?<=^|[\s*_~(>])'
+
+      // An extended url autolink will be recognised when one of the schemes
+      // http://, or https://, followed by a valid domain. See
+      // https://github.github.com/gfm/#extended-url-autolink.
+      r'(?:(?:https?|ftp):\/\/|www\.)'
+
+      // A valid domain consists of segments of alphanumeric characters,
+      // underscores (_) and hyphens (-) separated by periods (.). There must
+      // be at least one period, and no underscores may be present in the last
+      // two segments of the domain. See
+      // https://github.github.com/gfm/#valid-domain.
+      r'(?:[-_a-z0-9]+\.)*(?:[-a-z0-9]+\.[-a-z0-9]+)'
+
+      // After a valid domain, zero or more non-space non-< characters may
+      // follow.
+      r'[^\s<]*'
+
+      // Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will
+      // not be considered part of the autolink, though they may be included in
+      // the interior of the link. See
+      // https://github.github.com/gfm/#extended-autolink-path-validation.
+      // Note: Do not use negative lookbehind, as Safari does not support it.
+      // '(?<![?!.,:*_~])'
+      r'[^\s<?!.,:*_~]';
+
+  // An extended email autolink, see
+  // https://github.github.com/gfm/#extended-email-autolink.
+  static const _emailPattern =
+      r'[-_.+a-z0-9]+@(?:[-_a-z0-9]+\.)+[-_a-z0-9]*[a-z0-9]';
+
+  AutolinkExtensionSyntax()
+      : super(
+          '($_linkPattern)|($_emailPattern)',
+          caseSensitive: false,
+        );
+
+  @override
+  bool tryMatch(InlineParser parser, [int? startMatchPos]) {
+    startMatchPos ??= parser.pos;
+    final startMatch = pattern.matchAsPrefix(parser.source, startMatchPos);
+    if (startMatch == null) {
+      return false;
+    }
+
+    // When it is a link and it is not at the beginning of a line, or preceded
+    // by whitespace, `*`, `_`, `~`, `(`, or `>`, it is invalid. See
+    // https://github.github.com/gfm/#autolinks-extension-.
+    if (startMatch[1] != null && parser.pos > 0) {
+      final precededBy = String.fromCharCode(parser.charAt(parser.pos - 1));
+      const validPrecedingChars = {'\n', ' ', '*', '_', '~', '(', '>'};
+      if (!validPrecedingChars.contains(precededBy)) {
+        return false;
+      }
+    }
+
+    // When it is an email link and followed by `_` or `-`, it is invalid. See
+    // https://github.github.com/gfm/#example-633
+    if (startMatch[2] != null && parser.source.length > startMatch.end) {
+      final followedBy = String.fromCharCode(parser.charAt(startMatch.end));
+      const invalidFollowingChars = {'_', '-'};
+      if (invalidFollowingChars.contains(followedBy)) {
+        return false;
+      }
+    }
+
+    parser.writeText();
+    return onMatch(parser, startMatch);
+  }
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    int consumeLength;
+
+    final isEmailLink = match[2] != null;
+    if (isEmailLink) {
+      consumeLength = match.match.length;
+    } else {
+      consumeLength = _getConsumeLength(match.match);
+    }
+
+    var text = match.match.substring(0, consumeLength);
+    text = parser.encodeHtml ? escapeHtml(text) : text;
+
+    var destination = text;
+    if (isEmailLink) {
+      destination = 'mailto:$destination';
+    } else if (destination[0] == 'w') {
+      // When there is no scheme specified, insert the scheme `http`.
+      destination = 'http://$destination';
+    }
+
+    final anchor = Element.text('a', text)
+      ..attributes['href'] = Uri.encodeFull(destination);
+
+    parser
+      ..addNode(anchor)
+      ..consume(consumeLength);
+
+    return true;
+  }
+
+  int _getConsumeLength(String text) {
+    var excludedLength = 0;
+
+    // When an autolink ends in `)`, see
+    // https://github.github.com/gfm/#example-625.
+    if (text.endsWith(')')) {
+      final match = RegExp(r'(\(.*)?(\)+)$').firstMatch(text)!;
+
+      if (match[1] == null) {
+        excludedLength = match[2]!.length;
+      } else {
+        var parenCount = 0;
+        for (var i = 0; i < text.length; i++) {
+          final char = text.codeUnitAt(i);
+          if (char == $lparen) {
+            parenCount++;
+          } else if (char == $rparen) {
+            parenCount--;
+          }
+        }
+        if (parenCount < 0) {
+          excludedLength = parenCount.abs();
+        }
+      }
+    }
+    // If an autolink ends in a semicolon `;`, see
+    // https://github.github.com/gfm/#example-627
+    else if (text.endsWith(';')) {
+      final match = RegExp(r'&[0-9a-z]+;$').firstMatch(text);
+      if (match != null) {
+        excludedLength = match.match.length;
+      }
+    }
+
+    return text.length - excludedLength;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart
new file mode 100644
index 0000000..073c1cc
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/autolink_syntax.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches autolinks like `<http://foo.com>`.
+class AutolinkSyntax extends InlineSyntax {
+  AutolinkSyntax() : super(r'<(([a-zA-Z][a-zA-Z\-\+\.]+):(?://)?[^\s>]*)>');
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final url = match[1]!;
+    final text = parser.encodeHtml ? escapeHtml(url) : url;
+    final anchor = Element.text('a', text);
+
+    final destination = normalizeLinkDestination(url);
+    anchor.attributes['href'] =
+        parser.encodeHtml ? escapeHtml(destination) : destination;
+    parser.addNode(anchor);
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart
new file mode 100644
index 0000000..35783d3
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/code_syntax.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches backtick-enclosed inline code blocks.
+class CodeSyntax extends InlineSyntax {
+  // This pattern matches:
+  //
+  // * a string of backticks (not followed by any more), followed by
+  // * a non-greedy string of anything, including newlines, ending with anything
+  //   except a backtick, followed by
+  // * a string of backticks the same length as the first, not followed by any
+  //   more.
+  //
+  // This conforms to the delimiters of inline code, both in Markdown.pl, and
+  // CommonMark.
+  static const _pattern = r'(`+(?!`))((?:.|\n)*?[^`])\1(?!`)';
+
+  CodeSyntax() : super(_pattern);
+
+  @override
+  bool tryMatch(InlineParser parser, [int? startMatchPos]) {
+    if (parser.pos > 0 && parser.charAt(parser.pos - 1) == $backquote) {
+      // Not really a match! We can't just sneak past one backtick to try the
+      // next character. An example of this situation would be:
+      //
+      //     before ``` and `` after.
+      //             ^--parser.pos
+      return false;
+    }
+
+    final match = pattern.matchAsPrefix(parser.source, parser.pos);
+    if (match == null) {
+      return false;
+    }
+    parser.writeText();
+    if (onMatch(parser, match)) parser.consume(match.match.length);
+    return true;
+  }
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final markerLength = match[1]!.length;
+    final contentLength = match.match.length - markerLength * 2;
+    final contentStart = parser.pos + markerLength;
+    final contentEnd = contentStart + contentLength;
+
+    var code = parser.source.substring(contentStart, contentEnd);
+    if (_shouldStrip(code)) {
+      code = code.substring(1, code.length - 1);
+    }
+    code = code.replaceAll('\n', ' ');
+
+    if (parser.encodeHtml) {
+      code = escapeHtml(code, escapeApos: false);
+    }
+
+    parser.addNode(Element.text('code', code));
+    return true;
+  }
+
+  bool _shouldStrip(String code) {
+    // No stripping occurs if the code span contains only spaces:
+    // https://spec.commonmark.org/0.30/#example-334.
+    if (code.trim().isEmpty) {
+      return false;
+    }
+
+    // Only spaces, and not unicode whitespace in general, are stripped in this
+    // way, see https://spec.commonmark.org/0.30/#example-333.
+    final startsWithSpace = code.startsWith(' ') || code.startsWith('\n');
+    final endsWithSpace = code.endsWith(' ') || code.endsWith('\n');
+
+    // The stripping only happens if the space is on both sides of the string:
+    // https://spec.commonmark.org/0.30/#example-332.
+    if (!startsWithSpace || !endsWithSpace) {
+      return false;
+    }
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart
new file mode 100644
index 0000000..e44fdbf
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/color_swatch_syntax.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches code blocks containing a subset of CSS color syntax.
+class ColorSwatchSyntax extends InlineSyntax {
+  /// This pattern matches:
+  /// * GitHub Flavored Markup supports fewer of these options, GitLab Flavored
+  ///   Markup supports all of these. Presumably GitHub will be more complete at
+  ///   some point.
+  /// * CSS style '#' prefixed color hex codes in 3,4,6 or 8 digits in length.
+  /// * CSS style RGB()/RgbA()/Hsl()/HSLA() style color declarations, of any
+  ///   capitalization.
+  /// EXAMPLES:
+  /// * `#f00`
+  /// * `#BA`        (2 digit hex, regex will not match)
+  /// * `#F00a`
+  /// * `#F0BAD`     (5 digit hex, regex will not match)
+  /// * `#FF0000`
+  /// * `#F000BAD`   (7 digit hex, regex will not match)
+  /// * `#FF0000aA`    (GitHub supports only this style)
+  /// * `RGB(0,255,0)`
+  /// * `rgb(0,255,0)`
+  /// * `RGB(0%,100%,0%)`
+  /// * `rgb(0%,100%,0%)`
+  /// * `RGBA(0,255,0,0.3)`
+  /// * `rgba(0,255,0,0.3)`
+  /// * `HSL(540,70%,50%)`
+  /// * `hsl(540,70%,50%)`
+  /// * `HSLA(540,70%,50%,0.3)`
+  /// * `Hsla(540,70%,50%,0.3)`
+  static const _pattern =
+      '`((#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8}))|'
+      r'([Rr][Gg][Bb][Aa]?\((\d+[%]?),(\d+[%]?),(\d+[%]?),?(\d+\.?\d+[%]?)?\))|'
+      r'([Hh][Ss][Ll][Aa]?\((\d+[%]?),(\d+[%]?),(\d+[%]?),?(\d+\.?\d+[%]?)?\)))`';
+
+  ColorSwatchSyntax() : super(_pattern);
+
+  @override
+  bool tryMatch(InlineParser parser, [int? startMatchPos]) {
+    if (parser.pos > 0 && parser.charAt(parser.pos - 1) == $backquote) {
+      // Not really a match! We can't just sneak past one backtick to try the
+      // next character. An example of this situation would be:
+      //
+      //     before ``` and `` after.
+      //             ^--parser.pos
+      return false;
+    }
+
+    final match = pattern.matchAsPrefix(parser.source, parser.pos);
+    if (match == null) {
+      return false;
+    }
+    parser.writeText();
+    if (onMatch(parser, match)) parser.consume(match.match.length);
+    return true;
+  }
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    var code = match[1]!.trim().replaceAll('\n', ' ');
+
+    if (parser.encodeHtml) code = escapeHtml(code);
+
+    parser.addNode(Element('code', [
+      Text(code),
+      Element.withTag('span')..attributes['style'] = 'background-color:$code;',
+    ])
+      ..attributes['class'] = 'gfm-color_chip');
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/decode_html_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/decode_html_syntax.dart
new file mode 100644
index 0000000..1af15d5
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/decode_html_syntax.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../assets/html_entities.dart';
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Decodes numeric character references, for example decode `&#35;` to `#`.
+// https://spec.commonmark.org/0.30/#entity-and-numeric-character-references
+class DecodeHtmlSyntax extends InlineSyntax {
+  DecodeHtmlSyntax()
+      : super(htmlCharactersPattern.pattern,
+            caseSensitive: false, startCharacter: $ampersand);
+
+  @override
+  bool tryMatch(InlineParser parser, [int? startMatchPos]) {
+    if (parser.pos > 0 && parser.charAt(parser.pos - 1) == $backquote) {
+      return false;
+    }
+
+    final match = pattern.matchAsPrefix(parser.source, parser.pos);
+    if (match == null) {
+      return false;
+    }
+
+    if (match[1] != null && htmlEntitiesMap[match.match] == null) {
+      return false;
+    }
+
+    parser.writeText();
+    if (onMatch(parser, match)) parser.consume(match.match.length);
+    return true;
+  }
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    var decodedText = decodeHtmlCharacterFromMatch(match);
+
+    if (parser.encodeHtml) {
+      decodedText = escapeHtml(decodedText);
+    }
+
+    parser.addNode(Text(decodedText));
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/delimiter_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/delimiter_syntax.dart
new file mode 100644
index 0000000..f26bdc9
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/delimiter_syntax.dart
@@ -0,0 +1,337 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../inline_parser.dart';
+import '../patterns.dart';
+import 'inline_syntax.dart';
+
+/// Matches syntax that has a pair of tags and becomes an element, like `*` for
+/// `<em>`. Allows nested tags.
+class DelimiterSyntax extends InlineSyntax {
+  /// Whether this is parsed according to the same nesting rules as [emphasis
+  /// delimiters][].
+  ///
+  /// [emphasis delimiters]: https://spec.commonmark.org/0.30/#can-open-emphasis
+  final bool requiresDelimiterRun;
+
+  /// Whether to allow intra-word delimiter runs. CommonMark emphasis and
+  /// strong emphasis does not allow this, but GitHub-Flavored Markdown allows
+  /// it on strikethrough.
+  final bool allowIntraWord;
+
+  final List<DelimiterTag>? tags;
+
+  /// Creates a new [DelimiterSyntax] which matches text on [pattern].
+  ///
+  /// The [pattern] is used to find the matching text. If [requiresDelimiterRun]
+  /// is passed, this syntax parses according to the same nesting rules as
+  /// emphasis delimiters.  If [startCharacter] is passed, it is used as a
+  /// pre-matching check which is faster than matching against [pattern].
+  DelimiterSyntax(
+    super.pattern, {
+    this.requiresDelimiterRun = false,
+    super.startCharacter,
+    this.allowIntraWord = false,
+    this.tags,
+  });
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final runLength = match.group(0)!.length;
+    final matchStart = parser.pos;
+    final matchEnd = parser.pos + runLength;
+    final text = Text(parser.source.substring(matchStart, matchEnd));
+    if (!requiresDelimiterRun) {
+      parser.pushDelimiter(SimpleDelimiter(
+        node: text,
+        length: runLength,
+        char: parser.source.codeUnitAt(matchStart),
+        canOpen: true,
+        canClose: false,
+        syntax: this,
+        endPos: matchEnd,
+      ));
+      parser.addNode(text);
+      return true;
+    }
+
+    final delimiterRun = DelimiterRun.tryParse(
+      parser,
+      matchStart,
+      matchEnd,
+      syntax: this,
+      node: text,
+      allowIntraWord: allowIntraWord,
+      tags: tags ?? const [],
+    );
+    if (delimiterRun != null) {
+      parser.pushDelimiter(delimiterRun);
+      parser.addNode(text);
+      return true;
+    } else {
+      parser.advanceBy(runLength);
+      return false;
+    }
+  }
+
+  /// Attempts to close this tag at the current position.
+  ///
+  /// If a tag cannot be closed at the current position (for example, if a link
+  /// reference cannot be found for a link tag's label), then `null` is
+  /// returned.
+  ///
+  /// If a tag can be closed at the current position, then this method calls
+  /// [getChildren], in which [parser] parses any nested text into child nodes.
+  /// The returned [Iterable] includes these children nodes.
+  Iterable<Node>? close(
+    InlineParser parser,
+    Delimiter opener,
+    Delimiter closer, {
+    required String tag,
+    required List<Node> Function() getChildren,
+  }) {
+    return [Element(tag, getChildren())];
+  }
+}
+
+class DelimiterTag {
+  DelimiterTag(this.tag, this.indicatorLength);
+
+  // Tag name of the HTML element.
+  final String tag;
+
+  final int indicatorLength;
+}
+
+/// A delimiter indicating the possible "open" or possible "close" of a tag for
+/// a [DelimiterSyntax].
+abstract class Delimiter {
+  /// The [Text] node representing the plain text representing this delimiter.
+  abstract Text node;
+
+  /// The type of delimiter.
+  ///
+  /// For the two-character image delimiter, `![`, this is `!`.
+  int get char;
+
+  /// The number of delimiters.
+  int get length;
+
+  /// Whether the delimiter is active.
+  ///
+  /// Links cannot be nested, so we must "deactivate" any pending ones. For
+  /// example, take the following text:
+  ///
+  ///     Text [link and [more](links)](links).
+  ///
+  /// Once we have parsed `Text [`, there is one (pending) link in the state
+  /// stack.  It is, by default, active. Once we parse the next possible link,
+  /// `[more](links)`, as a real link, we must deactive the pending links (just
+  /// the one, in this case).
+  abstract bool isActive;
+
+  /// Whether this delimiter can open emphasis or strong emphasis.
+  bool get canOpen;
+
+  /// Whether this delimiter can close emphasis or strong emphasis.
+  bool get canClose;
+
+  /// The syntax which uses this delimiter to parse a tag.
+  DelimiterSyntax get syntax;
+}
+
+/// A simple delimiter implements the [Delimiter] interface with basic fields,
+/// and does not have the concept of "left-flanking" or "right-flanking".
+class SimpleDelimiter implements Delimiter {
+  @override
+  Text node;
+
+  @override
+  final int char;
+
+  @override
+  final int length;
+
+  @override
+  bool isActive;
+
+  @override
+  final bool canOpen;
+
+  @override
+  final bool canClose;
+
+  @override
+  final DelimiterSyntax syntax;
+
+  final int endPos;
+
+  SimpleDelimiter({
+    required this.node,
+    required this.char,
+    required this.length,
+    required this.canOpen,
+    required this.canClose,
+    required this.syntax,
+    required this.endPos,
+  }) : isActive = true;
+}
+
+/// An implementation of [Delimiter] which uses concepts of "left-flanking" and
+/// "right-flanking" to determine the values of [canOpen] and [canClose].
+///
+/// This is primarily used when parsing emphasis and strong emphasis, but can
+/// also be used by other extensions of [DelimiterSyntax].
+class DelimiterRun implements Delimiter {
+  /// According to
+  /// [CommonMark](https://spec.commonmark.org/0.30/#unicode-punctuation-character):
+  ///
+  /// > A punctuation character is an ASCII punctuation character or anything in
+  /// > the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or
+  /// > `Ps`.
+  // This RegExp is inspired by
+  // https://github.com/commonmark/commonmark.js/blob/1f7d09099c20d7861a674674a5a88733f55ff729/lib/inlines.js#L39.
+  // I don't know if there is any way to simplify it or maintain it.
+  static final unicodePunctuationPattern = RegExp('['
+      '$asciiPunctuationEscaped'
+      r'\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE'
+      r'\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E'
+      r'\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E'
+      r'\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14'
+      r'\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB'
+      r'\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736'
+      r'\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F'
+      r'\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E'
+      r'\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051'
+      r'\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A'
+      r'\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC'
+      r'\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42'
+      r'\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE'
+      r'\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF'
+      r'\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF'
+      r'\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19'
+      r'\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03'
+      r'\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F'
+      r'\uFF5B\uFF5D\uFF5F-\uFF65'
+      ']');
+
+  /// Unicode whitespace.
+  // See https://spec.commonmark.org/0.30/#unicode-whitespace-character.
+  // Unicode Zs: https://www.compart.com/en/unicode/category.
+  static const unicodeWhitespace = '\u0020\u0009\u000A\u000C\u000D'
+      '\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008'
+      '\u2009\u200A\u202F\u205F\u3000';
+
+  @override
+  Text node;
+
+  @override
+  final int char;
+
+  @override
+  int get length => node.text.length;
+
+  @override
+  bool isActive;
+
+  @override
+  final DelimiterSyntax syntax;
+
+  final bool allowIntraWord;
+
+  @override
+  final bool canOpen;
+
+  @override
+  final bool canClose;
+
+  final List<DelimiterTag> tags;
+
+  DelimiterRun._({
+    required this.node,
+    required this.char,
+    required this.syntax,
+    required this.tags,
+    required bool isLeftFlanking,
+    required bool isRightFlanking,
+    required bool isPrecededByPunctuation,
+    required bool isFollowedByPunctuation,
+    required this.allowIntraWord,
+  })  : canOpen = isLeftFlanking &&
+            (!isRightFlanking || allowIntraWord || isPrecededByPunctuation),
+        canClose = isRightFlanking &&
+            (!isLeftFlanking || allowIntraWord || isFollowedByPunctuation),
+        isActive = true;
+
+  /// Tries to parse a delimiter run from [runStart] (inclusive) to [runEnd]
+  /// (exclusive).
+  static DelimiterRun? tryParse(
+    InlineParser parser,
+    int runStart,
+    int runEnd, {
+    required DelimiterSyntax syntax,
+    required List<DelimiterTag> tags,
+    required Text node,
+    bool allowIntraWord = false,
+  }) {
+    bool precededByWhitespace;
+    bool followedByWhitespace;
+    bool precededByPunctuation;
+    bool followedByPunctuation;
+
+    if (runStart == 0) {
+      precededByWhitespace = true;
+      precededByPunctuation = false;
+    } else {
+      final preceding = parser.source.substring(runStart - 1, runStart);
+      precededByWhitespace = unicodeWhitespace.contains(preceding);
+      precededByPunctuation = !precededByWhitespace &&
+          unicodePunctuationPattern.hasMatch(preceding);
+    }
+
+    if (runEnd == parser.source.length) {
+      followedByWhitespace = true;
+      followedByPunctuation = false;
+    } else {
+      final following = parser.source.substring(runEnd, runEnd + 1);
+      followedByWhitespace = unicodeWhitespace.contains(following);
+      followedByPunctuation = !followedByWhitespace &&
+          unicodePunctuationPattern.hasMatch(following);
+    }
+
+    // If it is a left-flanking delimiter run, see
+    // https://spec.commonmark.org/0.30/#left-flanking-delimiter-run.
+    final isLeftFlanking = !followedByWhitespace &&
+        (!followedByPunctuation ||
+            precededByWhitespace ||
+            precededByPunctuation);
+
+    // If it is a right-flanking delimiter run, see
+    // https://spec.commonmark.org/0.30/#right-flanking-delimiter-run.
+    final isRightFlanking = !precededByWhitespace &&
+        (!precededByPunctuation ||
+            followedByWhitespace ||
+            followedByPunctuation);
+
+    // Make sure the shorter delimiter takes precedence.
+    tags.sort((a, b) => a.indicatorLength.compareTo(b.indicatorLength));
+
+    return DelimiterRun._(
+      node: node,
+      char: parser.charAt(runStart),
+      syntax: syntax,
+      tags: tags,
+      isLeftFlanking: isLeftFlanking,
+      isRightFlanking: isRightFlanking,
+      isPrecededByPunctuation: precededByPunctuation,
+      isFollowedByPunctuation: followedByPunctuation,
+      allowIntraWord: allowIntraWord,
+    );
+  }
+
+  @override
+  String toString() => '<char: $char, length: $length, canOpen: $canOpen, '
+      'canClose: $canClose>';
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/email_autolink_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/email_autolink_syntax.dart
new file mode 100644
index 0000000..212f1a4
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/email_autolink_syntax.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches autolinks like `<foo@bar.example.com>`.
+///
+/// See <https://spec.commonmark.org/0.30/#email-address>.
+class EmailAutolinkSyntax extends InlineSyntax {
+  static const _email =
+      r'''[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}'''
+      r'''[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*''';
+
+  EmailAutolinkSyntax() : super('<($_email)>', startCharacter: $lt);
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final url = match[1]!;
+    final text = parser.encodeHtml ? escapeHtml(url) : url;
+    final anchor = Element.text('a', text);
+    anchor.attributes['href'] = Uri.encodeFull('mailto:$url');
+    parser.addNode(anchor);
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart
new file mode 100644
index 0000000..a068c6b
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/emoji_syntax.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../emojis.dart';
+import '../inline_parser.dart';
+import 'inline_syntax.dart';
+
+/// Matches GitHub Markdown emoji syntax like `:smile:`.
+///
+/// There is no formal specification of GitHub's support for this colon-based
+/// emoji support, so this syntax is based on the results of Markdown-enabled
+/// text fields at github.com.
+class EmojiSyntax extends InlineSyntax {
+  // Emoji "aliases" are mostly limited to lower-case letters, numbers, and
+  // underscores, but GitHub also supports `:+1:` and `:-1:`.
+  EmojiSyntax() : super(':([a-z0-9_+-]+):');
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final alias = match[1]!;
+    final emoji = emojis[alias];
+    if (emoji == null) {
+      parser.advanceBy(1);
+      return false;
+    }
+    parser.addNode(Text(emoji));
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/emphasis_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/emphasis_syntax.dart
new file mode 100644
index 0000000..58f2e70
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/emphasis_syntax.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../charcode.dart';
+import 'delimiter_syntax.dart';
+
+class EmphasisSyntax extends DelimiterSyntax {
+  /// Parses `__strong__` and `_emphasis_`.
+  EmphasisSyntax.underscore()
+      : super(
+          '_+',
+          requiresDelimiterRun: true,
+          tags: _tags,
+          startCharacter: $underscore,
+        );
+
+  /// Parses `**strong**` and `*emphasis*`.
+  EmphasisSyntax.asterisk()
+      : super(
+          r'\*+',
+          requiresDelimiterRun: true,
+          allowIntraWord: true,
+          tags: _tags,
+          startCharacter: $asterisk,
+        );
+
+  static final _tags = [DelimiterTag('em', 1), DelimiterTag('strong', 2)];
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/escape_html_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/escape_html_syntax.dart
new file mode 100644
index 0000000..565f870
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/escape_html_syntax.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Encodes (`"`), (`<`), (`>`) and (`&`).
+class EscapeHtmlSyntax extends InlineSyntax {
+  EscapeHtmlSyntax() : super('["<>&]');
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final text = escapeHtml(match[0]!);
+    parser.addNode(Text(text));
+
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/escape_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/escape_syntax.dart
new file mode 100644
index 0000000..c112d93
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/escape_syntax.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../inline_parser.dart';
+import '../patterns.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Escape ASCII punctuation preceded by a backslash.
+///
+/// Backslashes before other characters are treated as literal backslashes.
+// See https://spec.commonmark.org/0.30/#backslash-escapes.
+class EscapeSyntax extends InlineSyntax {
+  EscapeSyntax()
+      : super('\\\\([$asciiPunctuationEscaped])', startCharacter: $backslash);
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    final chars = match.match;
+
+    String text;
+    if ('&"<>'.contains(match[1]!) && parser.encodeHtml) {
+      text = escapeHtml(match[1]!);
+    } else {
+      text = chars[1];
+    }
+
+    parser.addNode(Text(text));
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/footnote_ref_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/footnote_ref_syntax.dart
new file mode 100644
index 0000000..155fd74
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/footnote_ref_syntax.dart
@@ -0,0 +1,72 @@
+import '../ast.dart' show Element, Node, Text;
+import '../charcode.dart';
+import 'link_syntax.dart' show LinkContext;
+
+/// The spec of GFM about footnotes is
+/// [missing](https://github.com/github/cmark-gfm/issues/283#issuecomment-1378868725).
+/// For source code of cmark-gfm, see the `noMatch` label of the
+/// `handle_close_bracket` function in [master@c32ef78](https://github.com/github/cmark-gfm/blob/c32ef78/src/inlines.c#L1236).
+/// A Rust implementation is also [available](https://github.com/wooorm/markdown-rs/blob/2498e31eecead798efc649502bbf5f86feaa94be/src/construct/gfm_label_start_footnote.rs).
+/// Footnotes shares the same syntax with [LinkSyntax],
+/// but have a different branch of handling the close bracket.
+class FootnoteRefSyntax {
+  static String? _footnoteLabel(String key) {
+    if (key.isEmpty || key.codeUnitAt(0) != $caret) {
+      return null;
+    }
+    key = key.substring(1).trim().toLowerCase();
+    if (key.isEmpty) {
+      return null;
+    }
+    return key;
+  }
+
+  static Iterable<Node>? tryCreateFootnoteLink(
+    LinkContext context,
+    String text, {
+    bool? secondary,
+  }) {
+    secondary ??= false;
+    final parser = context.parser;
+    final key = _footnoteLabel(text);
+    final refs = parser.document.footnoteReferences;
+    // `label` is what footnoteReferences stored, it is case sensitive.
+    final label =
+        refs.keys.firstWhere((k) => k.toLowerCase() == key, orElse: () => '');
+    // `count != null` means footnote was valid.
+    var count = refs[label];
+    // And then check if footnote was matched.
+    if (key == null || count == null) {
+      return null;
+    }
+    final result = <Node>[];
+    // There are 4 cases here: ![^...], [^...], ![...][^...], [...][^...]
+    if (context.opener.char == $exclamation) {
+      result.add(Text('!'));
+    }
+    refs[label] = ++count;
+    final labels = parser.document.footnoteLabels;
+    var pos = labels.indexOf(key);
+    if (pos < 0) {
+      pos = labels.length;
+      labels.add(key);
+    }
+
+    // `children` are text segments after '[^' before ']'.
+    final children = context.getChildren();
+    if (secondary) {
+      result.add(Text('['));
+      result.addAll(children);
+      result.add(Text(']'));
+    }
+    final id = Uri.encodeComponent(label);
+    final suffix = count > 1 ? '-$count' : '';
+    final link = Element('a', [Text('${pos + 1}')])
+      // Ignore GitHub's attribute: <data-footnote-ref>.
+      ..attributes['href'] = '#fn-$id'
+      ..attributes['id'] = 'fnref-$id$suffix';
+    final sup = Element('sup', [link])..attributes['class'] = 'footnote-ref';
+    result.add(sup);
+    return result;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/image_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/image_syntax.dart
new file mode 100644
index 0000000..a8b2c35
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/image_syntax.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../util.dart';
+import 'link_syntax.dart';
+
+/// Matches images like `![alternate text](url "optional title")` and
+/// `![alternate text][label]`.
+class ImageSyntax extends LinkSyntax {
+  ImageSyntax({super.linkResolver})
+      : super(
+          pattern: r'!\[',
+          startCharacter: $exclamation,
+        );
+
+  @override
+  Element createNode(
+    String destination,
+    String? title, {
+    required List<Node> Function() getChildren,
+  }) {
+    final element = Element.empty('img');
+    final children = getChildren();
+    element.attributes['src'] = normalizeLinkDestination(
+      escapePunctuation(destination),
+    );
+    element.attributes['alt'] = children.map((node) {
+      // See https://spec.commonmark.org/0.30/#image-description.
+      // An image description may contain links. Fetch text from the alt
+      // attribute if this nested link is an image.
+      if (node is Element && node.tag == 'img') {
+        return node.attributes['alt'];
+      }
+      return node.textContent;
+    }).join();
+    if (title != null && title.isNotEmpty) {
+      element.attributes['title'] = normalizeLinkTitle(title);
+    }
+    return element;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/inline_html_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/inline_html_syntax.dart
new file mode 100644
index 0000000..3a7ce77
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/inline_html_syntax.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../../markdown.dart';
+import '../charcode.dart';
+import '../patterns.dart';
+
+/// Leave inline HTML tags alone, from
+/// [CommonMark 0.30](https://spec.commonmark.org/0.30/#raw-html).
+///
+/// This is not actually a good definition (nor CommonMark's) of an HTML tag,
+/// but it is fast. It will leave text like `<a href='hi">` alone, which is
+/// incorrect.
+///
+/// TODO(srawlins): improve accuracy while ensuring performance, once
+/// Markdown benchmarking is more mature.
+class InlineHtmlSyntax extends TextSyntax {
+  static const _pattern = '(?:$namedTagDefinition)'
+      // Or
+      '|'
+
+      // HTML comment, see
+      // https://spec.commonmark.org/0.30/#html-comment.
+      '<!--(?:(?:[^-<>]+-[^-<>]+)+|[^-<>]+)-->'
+      '|'
+
+      // Processing-instruction, see
+      // https://spec.commonmark.org/0.30/#processing-instruction
+      r'<\?.*?\?>'
+      '|'
+
+      // Declaration, see
+      // https://spec.commonmark.org/0.30/#declaration.
+      '(<![a-z]+.*?>)'
+      '|'
+
+      // CDATA section, see
+      // https://spec.commonmark.org/0.30/#cdata-section.
+      r'(<!\[CDATA\[.*?]]>)';
+
+  InlineHtmlSyntax()
+      : super(_pattern, startCharacter: $lt, caseSensitive: false);
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/inline_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/inline_syntax.dart
new file mode 100644
index 0000000..997d03a
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/inline_syntax.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../inline_parser.dart';
+import '../util.dart';
+
+/// Represents one kind of Markdown tag that can be parsed.
+abstract class InlineSyntax {
+  final RegExp pattern;
+
+  /// The first character of [pattern], to be used as an efficient first check
+  /// that this syntax matches the current parser position.
+  final int? _startCharacter;
+
+  /// Create a new [InlineSyntax] which matches text on [pattern].
+  ///
+  /// If [startCharacter] is passed, it is used as a pre-matching check which
+  /// is faster than matching against [pattern].
+  ///
+  /// If [caseSensitive] is disabled, then case is ignored when matching
+  /// the [pattern].
+  InlineSyntax(String pattern, {int? startCharacter, bool caseSensitive = true})
+      : pattern =
+            RegExp(pattern, multiLine: true, caseSensitive: caseSensitive),
+        _startCharacter = startCharacter;
+
+  /// Tries to match at the parser's current position.
+  ///
+  /// The parser's position can be overriden with [startMatchPos].
+  /// Returns whether or not the pattern successfully matched.
+  bool tryMatch(InlineParser parser, [int? startMatchPos]) {
+    startMatchPos ??= parser.pos;
+
+    // Before matching with the regular expression [pattern], which can be
+    // expensive on some platforms, check if even the first character matches
+    // this syntax.
+    if (_startCharacter != null &&
+        parser.source.codeUnitAt(startMatchPos) != _startCharacter) {
+      return false;
+    }
+
+    final startMatch = pattern.matchAsPrefix(parser.source, startMatchPos);
+    if (startMatch == null) return false;
+
+    // Write any existing plain text up to this point.
+    parser.writeText();
+
+    if (onMatch(parser, startMatch)) parser.consume(startMatch.match.length);
+    return true;
+  }
+
+  /// Processes [match], adding nodes to [parser] and possibly advancing
+  /// [parser].
+  ///
+  /// Returns whether the caller should advance [parser] by `match[0].length`.
+  bool onMatch(InlineParser parser, Match match);
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/line_break_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/line_break_syntax.dart
new file mode 100644
index 0000000..0a5fb01
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/line_break_syntax.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../inline_parser.dart';
+import 'inline_syntax.dart';
+
+/// Represents a hard line break.
+class LineBreakSyntax extends InlineSyntax {
+  LineBreakSyntax() : super(r'(?:\\|  +)\n');
+
+  /// Create a void <br> element.
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    parser.addNode(Element.empty('br'));
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart
new file mode 100644
index 0000000..bca3efb
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/link_syntax.dart
@@ -0,0 +1,479 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../charcode.dart';
+import '../document.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'delimiter_syntax.dart';
+import 'footnote_ref_syntax.dart';
+
+/// A helper class holds params of link context.
+/// Footnote creation needs other info in [_tryCreateReferenceLink].
+class LinkContext {
+  final InlineParser parser;
+  final SimpleDelimiter opener;
+  final List<Node> Function() getChildren;
+
+  const LinkContext(this.parser, this.opener, this.getChildren);
+}
+
+/// Matches links like `[blah][label]` and `[blah](url)`.
+class LinkSyntax extends DelimiterSyntax {
+  static final _entirelyWhitespacePattern = RegExp(r'^\s*$');
+
+  final Resolver linkResolver;
+
+  LinkSyntax({
+    Resolver? linkResolver,
+    String pattern = r'\[',
+    int startCharacter = $lbracket,
+  })  : linkResolver = (linkResolver ?? ((String _, [String? __]) => null)),
+        super(pattern, startCharacter: startCharacter);
+
+  @override
+  Iterable<Node>? close(
+    InlineParser parser,
+    covariant SimpleDelimiter opener,
+    Delimiter? closer, {
+    String? tag,
+    required List<Node> Function() getChildren,
+  }) {
+    final context = LinkContext(parser, opener, getChildren);
+    final text = parser.source.substring(opener.endPos, parser.pos);
+    // The current character is the `]` that closed the link text. Examine the
+    // next character, to determine what type of link we might have (a '('
+    // means a possible inline link; otherwise a possible reference link).
+    if (parser.pos + 1 >= parser.source.length) {
+      // The `]` is at the end of the document, but this may still be a valid
+      // shortcut reference link.
+      return _tryCreateReferenceLink(context, text);
+    }
+
+    // Peek at the next character; don't advance, so as to avoid later stepping
+    // backward.
+    final char = parser.charAt(parser.pos + 1);
+
+    if (char == $lparen) {
+      // Maybe an inline link, like `[text](destination)`.
+      parser.advanceBy(1);
+      final leftParenIndex = parser.pos;
+      final inlineLink = _parseInlineLink(parser);
+      if (inlineLink != null) {
+        return [
+          _tryCreateInlineLink(
+            parser,
+            inlineLink,
+            getChildren: getChildren,
+          ),
+        ];
+      }
+      // At this point, we've matched `[...](`, but that `(` did not pan out to
+      // be an inline link. We must now check if `[...]` is simply a shortcut
+      // reference link.
+
+      // Reset the parser position.
+      parser.pos = leftParenIndex;
+      parser.advanceBy(-1);
+      return _tryCreateReferenceLink(context, text);
+    }
+
+    if (char == $lbracket) {
+      parser.advanceBy(1);
+      // At this point, we've matched `[...][`. Maybe a *full* reference link,
+      // like `[foo][bar]` or a *collapsed* reference link, like `[foo][]`.
+      if (parser.pos + 1 < parser.source.length &&
+          parser.charAt(parser.pos + 1) == $rbracket) {
+        // That opening `[` is not actually part of the link. Maybe a
+        // *shortcut* reference link (followed by a `[`).
+        parser.advanceBy(1);
+        return _tryCreateReferenceLink(context, text);
+      }
+      final label = _parseReferenceLinkLabel(parser);
+      if (label != null) {
+        return _tryCreateReferenceLink(context, label, secondary: true);
+      }
+      return null;
+    }
+
+    // The link text (inside `[...]`) was not followed with a opening `(` nor
+    // an opening `[`. Perhaps just a simple shortcut reference link (`[...]`).
+    return _tryCreateReferenceLink(context, text);
+  }
+
+  /// Resolve a possible reference link.
+  ///
+  /// Uses [linkReferences], [linkResolver], and [createNode] to try to
+  /// resolve [label] into a [Node]. If [label] is defined in
+  /// [linkReferences] or can be resolved by [linkResolver], returns a [Node]
+  /// that links to the resolved URL.
+  ///
+  /// Otherwise, returns `null`.
+  ///
+  /// [label] does not need to be normalized.
+  Node? _resolveReferenceLink(
+    String label,
+    Map<String, LinkReference> linkReferences, {
+    required List<Node> Function() getChildren,
+  }) {
+    final linkReference = linkReferences[normalizeLinkLabel(label)];
+    if (linkReference != null) {
+      return createNode(
+        linkReference.destination,
+        linkReference.title,
+        getChildren: getChildren,
+      );
+    } else {
+      // This link has no reference definition. But we allow users of the
+      // library to specify a custom resolver function ([linkResolver]) that
+      // may choose to handle this. Otherwise, it's just treated as plain
+      // text.
+
+      // Normally, label text does not get parsed as inline Markdown. However,
+      // for the benefit of the link resolver, we need to at least escape
+      // brackets, so that, e.g. a link resolver can receive `[\[\]]` as `[]`.
+      final resolved = linkResolver(label
+          .replaceAll(r'\\', r'\')
+          .replaceAll(r'\[', '[')
+          .replaceAll(r'\]', ']'));
+      if (resolved != null) {
+        getChildren();
+      }
+      return resolved;
+    }
+  }
+
+  /// Create the node represented by a Markdown link.
+  Node createNode(
+    String destination,
+    String? title, {
+    required List<Node> Function() getChildren,
+  }) {
+    final children = getChildren();
+    final element = Element('a', children);
+    element.attributes['href'] = normalizeLinkDestination(
+      escapePunctuation(destination),
+    );
+    if (title != null && title.isNotEmpty) {
+      element.attributes['title'] = normalizeLinkTitle(
+        escapePunctuation(title),
+      );
+    }
+    return element;
+  }
+
+  /// Tries to create a reference link node.
+  ///
+  /// Returns the nodes if it was successfully created, `null` otherwise.
+  Iterable<Node>? _tryCreateReferenceLink(
+    LinkContext context,
+    String label, {
+    bool? secondary,
+  }) {
+    final parser = context.parser;
+    final getChildren = context.getChildren;
+    final link = _resolveReferenceLink(
+      label,
+      parser.document.linkReferences,
+      getChildren: getChildren,
+    );
+    if (link != null) {
+      return [link];
+    }
+    return FootnoteRefSyntax.tryCreateFootnoteLink(
+      context,
+      label,
+      secondary: secondary,
+    );
+  }
+
+  // Tries to create an inline link node.
+  //
+  /// Returns the link if it was successfully created, `null` otherwise.
+  Node _tryCreateInlineLink(
+    InlineParser parser,
+    InlineLink link, {
+    required List<Node> Function() getChildren,
+  }) {
+    return createNode(link.destination, link.title, getChildren: getChildren);
+  }
+
+  /// Parse a reference link label at the current position.
+  ///
+  /// Specifically, [parser.pos] is expected to be pointing at the `[` which
+  /// opens the link label.
+  ///
+  /// Returns the label if it could be parsed, or `null` if not.
+  String? _parseReferenceLinkLabel(InlineParser parser) {
+    // Walk past the opening `[`.
+    parser.advanceBy(1);
+    if (parser.isDone) return null;
+
+    final buffer = StringBuffer();
+    while (true) {
+      final char = parser.charAt(parser.pos);
+      if (char == $backslash) {
+        parser.advanceBy(1);
+        if (parser.isDone) return null;
+        final next = parser.charAt(parser.pos);
+        if (next != $backslash && next != $rbracket) {
+          buffer.writeCharCode(char);
+        }
+        buffer.writeCharCode(next);
+      } else if (char == $lbracket) {
+        return null;
+      } else if (char == $rbracket) {
+        break;
+      } else {
+        buffer.writeCharCode(char);
+      }
+      parser.advanceBy(1);
+      if (parser.isDone) return null;
+      // TODO(srawlins): only check 999 characters, for performance reasons?
+    }
+
+    final label = buffer.toString();
+
+    // A link label must contain at least one non-whitespace character.
+    if (_entirelyWhitespacePattern.hasMatch(label)) return null;
+
+    return label;
+  }
+
+  /// Parse an inline [InlineLink] at the current position.
+  ///
+  /// At this point, we have parsed a link's (or image's) opening `[`, and then
+  /// a matching closing `]`, and [parser.pos] is pointing at an opening `(`.
+  /// This method will then attempt to parse a link destination wrapped in `<>`,
+  /// such as `(<http://url>)`, or a bare link destination, such as
+  /// `(http://url)`, or a link destination with a title, such as
+  /// `(http://url "title")`.
+  ///
+  /// Returns the [InlineLink] if one was parsed, or `null` if not.
+  InlineLink? _parseInlineLink(InlineParser parser) {
+    // Start walking to the character just after the opening `(`.
+    parser.advanceBy(1);
+
+    _moveThroughWhitespace(parser);
+    if (parser.isDone) return null; // EOF. Not a link.
+
+    if (parser.charAt(parser.pos) == $lt) {
+      // Maybe a `<...>`-enclosed link destination.
+      return _parseInlineBracketedLink(parser);
+    } else {
+      return _parseInlineBareDestinationLink(parser);
+    }
+  }
+
+  /// Parse an inline link with a bracketed destination (a destination wrapped
+  /// in `<...>`). The current position of the parser must be the first
+  /// character of the destination.
+  ///
+  /// Returns the link if it was successfully created, `null` otherwise.
+  InlineLink? _parseInlineBracketedLink(InlineParser parser) {
+    parser.advanceBy(1);
+    if (parser.isDone) return null;
+
+    final buffer = StringBuffer();
+    while (true) {
+      final char = parser.charAt(parser.pos);
+      if (char == $backslash) {
+        parser.advanceBy(1);
+        if (parser.isDone) return null;
+        final next = parser.charAt(parser.pos);
+        // TODO: Follow the backslash spec better here.
+        // https://spec.commonmark.org/0.30/#backslash-escapes
+        if (next != $backslash && next != $gt) {
+          buffer.writeCharCode(char);
+        }
+        buffer.writeCharCode(next);
+      } else if (char == $lf || char == $cr || char == $ff) {
+        // Not a link (no line breaks allowed within `<...>`).
+        return null;
+      } else if (char == $space) {
+        buffer.write('%20');
+      } else if (char == $gt) {
+        break;
+      } else {
+        buffer.writeCharCode(char);
+      }
+      parser.advanceBy(1);
+      if (parser.isDone) return null;
+    }
+    final destination = buffer.toString();
+
+    parser.advanceBy(1);
+    if (parser.isDone) return null;
+    final char = parser.charAt(parser.pos);
+    if (char == $space || char == $lf || char == $cr || char == $ff) {
+      final title = _parseTitle(parser);
+      if (title == null &&
+          (parser.isDone || parser.charAt(parser.pos) != $rparen)) {
+        // This looked like an inline link, until we found this $space
+        // followed by mystery characters; no longer a link.
+        return null;
+      }
+      return InlineLink(destination, title: title);
+    } else if (char == $rparen) {
+      return InlineLink(destination);
+    } else {
+      // We parsed something like `[foo](<url>X`. Not a link.
+      return null;
+    }
+  }
+
+  /// Parse an inline link with a "bare" destination (a destination _not_
+  /// wrapped in `<...>`). The current position of the parser must be the first
+  /// character of the destination.
+  ///
+  /// Returns the link if it was successfully created, `null` otherwise.
+  InlineLink? _parseInlineBareDestinationLink(InlineParser parser) {
+    // According to
+    // [CommonMark](https://spec.commonmark.org/0.30/#link-destination):
+    //
+    // > A link destination consists of [...] a nonempty sequence of
+    // > characters [...], and includes parentheses only if (a) they are
+    // > backslash-escaped or (b) they are part of a balanced pair of
+    // > unescaped parentheses.
+    //
+    // We need to count the open parens. We start with 1 for the paren that
+    // opened the destination.
+    var parenCount = 1;
+    final buffer = StringBuffer();
+
+    while (true) {
+      final char = parser.charAt(parser.pos);
+      switch (char) {
+        case $backslash:
+          parser.advanceBy(1);
+          if (parser.isDone) return null; // EOF. Not a link.
+          final next = parser.charAt(parser.pos);
+          // Parentheses may be escaped.
+          //
+          // https://spec.commonmark.org/0.30/#example-494
+          if (next != $backslash && next != $lparen && next != $rparen) {
+            buffer.writeCharCode(char);
+          }
+          buffer.writeCharCode(next);
+          break;
+
+        case $space:
+        case $lf:
+        case $cr:
+        case $ff:
+          final destination = buffer.toString();
+          final title = _parseTitle(parser);
+          if (title == null &&
+              (parser.isDone || parser.charAt(parser.pos) != $rparen)) {
+            // This looked like an inline link, until we found this $space
+            // followed by mystery characters; no longer a link.
+            return null;
+          }
+          // [_parseTitle] made sure the title was follwed by a closing `)`
+          // (but it's up to the code here to examine the balance of
+          // parentheses).
+          parenCount--;
+          if (parenCount == 0) {
+            return InlineLink(destination, title: title);
+          }
+          break;
+
+        case $lparen:
+          parenCount++;
+          buffer.writeCharCode(char);
+          break;
+
+        case $rparen:
+          parenCount--;
+          if (parenCount == 0) {
+            final destination = buffer.toString();
+            return InlineLink(destination);
+          }
+          buffer.writeCharCode(char);
+          break;
+
+        default:
+          buffer.writeCharCode(char);
+      }
+      parser.advanceBy(1);
+      if (parser.isDone) return null; // EOF. Not a link.
+    }
+  }
+
+  // Walk the parser forward through any whitespace.
+  void _moveThroughWhitespace(InlineParser parser) {
+    while (!parser.isDone) {
+      final char = parser.charAt(parser.pos);
+      if (char != $space &&
+          char != $tab &&
+          char != $lf &&
+          char != $vt &&
+          char != $cr &&
+          char != $ff) {
+        return;
+      }
+      parser.advanceBy(1);
+    }
+  }
+
+  /// Parses a link title in [parser] at it's current position. The parser's
+  /// current position should be a whitespace character that followed a link
+  /// destination.
+  ///
+  /// Returns the title if it was successfully parsed, `null` otherwise.
+  String? _parseTitle(InlineParser parser) {
+    _moveThroughWhitespace(parser);
+    if (parser.isDone) return null;
+
+    // The whitespace should be followed by a title delimiter.
+    final delimiter = parser.charAt(parser.pos);
+    if (delimiter != $apostrophe &&
+        delimiter != $quote &&
+        delimiter != $lparen) {
+      return null;
+    }
+
+    final closeDelimiter = delimiter == $lparen ? $rparen : delimiter;
+    parser.advanceBy(1);
+    if (parser.isDone) return null;
+
+    // Now we look for an un-escaped closing delimiter.
+    final buffer = StringBuffer();
+    while (true) {
+      final char = parser.charAt(parser.pos);
+      if (char == $backslash) {
+        parser.advanceBy(1);
+        if (parser.isDone) return null;
+        final next = parser.charAt(parser.pos);
+        if (next != $backslash && next != closeDelimiter) {
+          buffer.writeCharCode(char);
+        }
+        buffer.writeCharCode(next);
+      } else if (char == closeDelimiter) {
+        break;
+      } else {
+        buffer.writeCharCode(char);
+      }
+      parser.advanceBy(1);
+      if (parser.isDone) return null;
+    }
+    final title = buffer.toString();
+
+    // Advance past the closing delimiter.
+    parser.advanceBy(1);
+    if (parser.isDone) return null;
+    _moveThroughWhitespace(parser);
+    if (parser.isDone) return null;
+    if (parser.charAt(parser.pos) != $rparen) return null;
+    return title;
+  }
+}
+
+class InlineLink {
+  final String destination;
+  final String? title;
+
+  InlineLink(this.destination, {this.title});
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/soft_line_break_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/soft_line_break_syntax.dart
new file mode 100644
index 0000000..c8395d5
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/soft_line_break_syntax.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../charcode.dart';
+import '../inline_parser.dart';
+import 'inline_syntax.dart';
+
+/// Removes the single space before the line ending.
+// https://spec.commonmark.org/0.30/#soft-line-breaks.
+// If there are more than one spaces before the line ending, it may hit the hard
+// break syntax.
+class SoftLineBreakSyntax extends InlineSyntax {
+  SoftLineBreakSyntax() : super(' \n', startCharacter: $space);
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    parser.consume(1);
+    return false;
+  }
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/strikethrough_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/strikethrough_syntax.dart
new file mode 100644
index 0000000..ebe5e1a
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/strikethrough_syntax.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../charcode.dart';
+import 'delimiter_syntax.dart';
+
+/// Matches strikethrough syntax according to the GFM spec.
+class StrikethroughSyntax extends DelimiterSyntax {
+  StrikethroughSyntax()
+      : super(
+          '~+',
+          requiresDelimiterRun: true,
+          allowIntraWord: true,
+          startCharacter: $tilde,
+          tags: [DelimiterTag('del', 1), DelimiterTag('del', 2)],
+        );
+}
diff --git a/pkgs/markdown/lib/src/inline_syntaxes/text_syntax.dart b/pkgs/markdown/lib/src/inline_syntaxes/text_syntax.dart
new file mode 100644
index 0000000..b73d09d
--- /dev/null
+++ b/pkgs/markdown/lib/src/inline_syntaxes/text_syntax.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import '../ast.dart';
+import '../inline_parser.dart';
+import '../util.dart';
+import 'inline_syntax.dart';
+
+/// Matches stuff that should just be passed through as straight text.
+class TextSyntax extends InlineSyntax {
+  final String substitute;
+
+  /// Create a new [TextSyntax] which matches text on [pattern].
+  ///
+  /// If [sub] is passed, it is used as a simple replacement for [pattern]. If
+  /// [startCharacter] is passed, it is used as a pre-matching check which is
+  /// faster than matching against [pattern].
+  TextSyntax(
+    super.pattern, {
+    String sub = '',
+    super.startCharacter,
+    super.caseSensitive,
+  }) : substitute = sub;
+
+  /// Adds a [Text] node to [parser] and returns `true` if there is a
+  /// [substitute], as long as the preceding character (if any) is not a `/`.
+  ///
+  /// Otherwise, the parser is advanced by the length of [match] and `false` is
+  /// returned.
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    if (substitute.isEmpty ||
+        (match.start > 0 &&
+            match.input.substring(match.start - 1, match.start) == '/')) {
+      // Just use the original matched text.
+      parser.advanceBy(match.match.length);
+      return false;
+    }
+
+    // Insert the substitution.
+    parser.addNode(Text(substitute));
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/legacy_emojis.dart b/pkgs/markdown/lib/src/legacy_emojis.dart
new file mode 100644
index 0000000..d608841
--- /dev/null
+++ b/pkgs/markdown/lib/src/legacy_emojis.dart
@@ -0,0 +1,1578 @@
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from emojilib's emoji data file:
+// https://raw.githubusercontent.com/muan/emojilib/v2.4.0/emojis.json
+// at 2022-05-02 10:18:54.685294 by the script, tool/update_emojis.dart.
+
+const emojis = <String, String>{
+  '+1': '👍',
+  '-1': '👎',
+  '100': '💯',
+  '1234': '🔢',
+  '1st_place_medal': '🥇',
+  '2nd_place_medal': '🥈',
+  '3rd_place_medal': '🥉',
+  '8ball': '🎱',
+  'a': '🅰️',
+  'ab': '🆎',
+  'abacus': '🧮',
+  'abc': '🔤',
+  'abcd': '🔡',
+  'accept': '🉑',
+  'adult': '🧑',
+  'aerial_tramway': '🚡',
+  'afghanistan': '🇦🇫',
+  'airplane': '✈️',
+  'aland_islands': '🇦🇽',
+  'alarm_clock': '⏰',
+  'albania': '🇦🇱',
+  'alembic': '⚗',
+  'algeria': '🇩🇿',
+  'alien': '👽',
+  'ambulance': '🚑',
+  'american_samoa': '🇦🇸',
+  'amphora': '🏺',
+  'anchor': '⚓',
+  'andorra': '🇦🇩',
+  'angel': '👼',
+  'anger': '💢',
+  'angola': '🇦🇴',
+  'angry': '😠',
+  'anguilla': '🇦🇮',
+  'anguished': '😧',
+  'ant': '🐜',
+  'antarctica': '🇦🇶',
+  'antigua_barbuda': '🇦🇬',
+  'apple': '🍎',
+  'aquarius': '♒',
+  'argentina': '🇦🇷',
+  'aries': '♈',
+  'armenia': '🇦🇲',
+  'arrow_backward': '◀️',
+  'arrow_double_down': '⏬',
+  'arrow_double_up': '⏫',
+  'arrow_down': '⬇️',
+  'arrow_down_small': '🔽',
+  'arrow_forward': '▶️',
+  'arrow_heading_down': '⤵️',
+  'arrow_heading_up': '⤴️',
+  'arrow_left': '⬅️',
+  'arrow_lower_left': '↙️',
+  'arrow_lower_right': '↘️',
+  'arrow_right': '➡️',
+  'arrow_right_hook': '↪️',
+  'arrow_up': '⬆️',
+  'arrow_up_down': '↕️',
+  'arrow_up_small': '🔼',
+  'arrow_upper_left': '↖️',
+  'arrow_upper_right': '↗️',
+  'arrows_clockwise': '🔃',
+  'arrows_counterclockwise': '🔄',
+  'art': '🎨',
+  'articulated_lorry': '🚛',
+  'artificial_satellite': '🛰',
+  'aruba': '🇦🇼',
+  'asterisk': '*⃣',
+  'astonished': '😲',
+  'athletic_shoe': '👟',
+  'atm': '🏧',
+  'atom_symbol': '⚛',
+  'australia': '🇦🇺',
+  'austria': '🇦🇹',
+  'avocado': '🥑',
+  'azerbaijan': '🇦🇿',
+  'b': '🅱️',
+  'baby': '👶',
+  'baby_bottle': '🍼',
+  'baby_chick': '🐤',
+  'baby_symbol': '🚼',
+  'back': '🔙',
+  'bacon': '🥓',
+  'badger': '🦡',
+  'badminton': '🏸',
+  'bagel': '🥯',
+  'baggage_claim': '🛄',
+  'baguette_bread': '🥖',
+  'bahamas': '🇧🇸',
+  'bahrain': '🇧🇭',
+  'balance_scale': '⚖',
+  'balloon': '🎈',
+  'ballot_box': '🗳',
+  'ballot_box_with_check': '☑️',
+  'bamboo': '🎍',
+  'banana': '🍌',
+  'bangbang': '‼️',
+  'bangladesh': '🇧🇩',
+  'bank': '🏦',
+  'bar_chart': '📊',
+  'barbados': '🇧🇧',
+  'barber': '💈',
+  'baseball': '⚾',
+  'basket': '🧺',
+  'basketball': '🏀',
+  'basketball_man': '⛹',
+  'basketball_woman': '⛹️‍♀️',
+  'bat': '🦇',
+  'bath': '🛀',
+  'bathtub': '🛁',
+  'battery': '🔋',
+  'beach_umbrella': '🏖',
+  'bear': '🐻',
+  'bearded_person': '🧔',
+  'bed': '🛏',
+  'beer': '🍺',
+  'beers': '🍻',
+  'beetle': '🐞',
+  'beginner': '🔰',
+  'belarus': '🇧🇾',
+  'belgium': '🇧🇪',
+  'belize': '🇧🇿',
+  'bell': '🔔',
+  'bellhop_bell': '🛎',
+  'benin': '🇧🇯',
+  'bento': '🍱',
+  'bermuda': '🇧🇲',
+  'bhutan': '🇧🇹',
+  'bike': '🚲',
+  'biking_man': '🚴',
+  'biking_woman': '🚴‍♀️',
+  'bikini': '👙',
+  'billed_hat': '🧢',
+  'biohazard': '☣',
+  'bird': '🐦',
+  'birthday': '🎂',
+  'black_circle': '⚫',
+  'black_flag': '🏴',
+  'black_heart': '🖤',
+  'black_joker': '🃏',
+  'black_large_square': '⬛',
+  'black_medium_small_square': '◾',
+  'black_medium_square': '◼️',
+  'black_nib': '✒️',
+  'black_small_square': '▪️',
+  'black_square_button': '🔲',
+  'blonde_man': '👱',
+  'blonde_woman': '👱‍♀️',
+  'blossom': '🌼',
+  'blowfish': '🐡',
+  'blue_book': '📘',
+  'blue_car': '🚙',
+  'blue_heart': '💙',
+  'blush': '😊',
+  'boar': '🐗',
+  'bolivia': '🇧🇴',
+  'bomb': '💣',
+  'bone': '🦴',
+  'bookmark': '🔖',
+  'bookmark_tabs': '📑',
+  'books': '📚',
+  'boom': '💥',
+  'boot': '👢',
+  'bosnia_herzegovina': '🇧🇦',
+  'botswana': '🇧🇼',
+  'bouquet': '💐',
+  'bow_and_arrow': '🏹',
+  'bowing_man': '🙇',
+  'bowing_woman': '🙇‍♀️',
+  'bowl_with_spoon': '🥣',
+  'bowling': '🎳',
+  'boxing_glove': '🥊',
+  'boy': '👦',
+  'brain': '🧠',
+  'brazil': '🇧🇷',
+  'bread': '🍞',
+  'breastfeeding': '🤱',
+  'brick': '🧱',
+  'bride_with_veil': '👰',
+  'bridge_at_night': '🌉',
+  'briefcase': '💼',
+  'british_indian_ocean_territory': '🇮🇴',
+  'british_virgin_islands': '🇻🇬',
+  'broccoli': '🥦',
+  'broken_heart': '💔',
+  'broom': '🧹',
+  'brunei': '🇧🇳',
+  'bug': '🐛',
+  'building_construction': '🏗',
+  'bulb': '💡',
+  'bulgaria': '🇧🇬',
+  'bullettrain_front': '🚅',
+  'bullettrain_side': '🚄',
+  'burkina_faso': '🇧🇫',
+  'burrito': '🌯',
+  'burundi': '🇧🇮',
+  'bus': '🚌',
+  'business_suit_levitating': '🕴',
+  'busstop': '🚏',
+  'bust_in_silhouette': '👤',
+  'busts_in_silhouette': '👥',
+  'butterfly': '🦋',
+  'cactus': '🌵',
+  'cake': '🍰',
+  'calendar': '📆',
+  'call_me_hand': '🤙',
+  'calling': '📲',
+  'cambodia': '🇰🇭',
+  'camel': '🐫',
+  'camera': '📷',
+  'camera_flash': '📸',
+  'cameroon': '🇨🇲',
+  'camping': '🏕',
+  'canada': '🇨🇦',
+  'canary_islands': '🇮🇨',
+  'cancer': '♋',
+  'candle': '🕯',
+  'candy': '🍬',
+  'canned_food': '🥫',
+  'canoe': '🛶',
+  'cape_verde': '🇨🇻',
+  'capital_abcd': '🔠',
+  'capricorn': '♑',
+  'card_file_box': '🗃',
+  'card_index': '📇',
+  'card_index_dividers': '🗂',
+  'caribbean_netherlands': '🇧🇶',
+  'carousel_horse': '🎠',
+  'carrot': '🥕',
+  'cat': '🐱',
+  'cat2': '🐈',
+  'cayman_islands': '🇰🇾',
+  'cd': '💿',
+  'central_african_republic': '🇨🇫',
+  'chad': '🇹🇩',
+  'chains': '⛓',
+  'champagne': '🍾',
+  'chart': '💹',
+  'chart_with_downwards_trend': '📉',
+  'chart_with_upwards_trend': '📈',
+  'checkered_flag': '🏁',
+  'cheese': '🧀',
+  'cherries': '🍒',
+  'cherry_blossom': '🌸',
+  'chess_pawn': '♟',
+  'chestnut': '🌰',
+  'chicken': '🐔',
+  'child': '🧒',
+  'children_crossing': '🚸',
+  'chile': '🇨🇱',
+  'chipmunk': '🐿',
+  'chocolate_bar': '🍫',
+  'chopsticks': '🥢',
+  'christmas_island': '🇨🇽',
+  'christmas_tree': '🎄',
+  'church': '⛪',
+  'cinema': '🎦',
+  'circus_tent': '🎪',
+  'city_sunrise': '🌇',
+  'city_sunset': '🌆',
+  'cityscape': '🏙',
+  'cl': '🆑',
+  'clamp': '🗜',
+  'clap': '👏',
+  'clapper': '🎬',
+  'classical_building': '🏛',
+  'climbing_man': '🧗‍♂️',
+  'climbing_woman': '🧗‍♀️',
+  'clinking_glasses': '🥂',
+  'clipboard': '📋',
+  'clock1': '🕐',
+  'clock10': '🕙',
+  'clock1030': '🕥',
+  'clock11': '🕚',
+  'clock1130': '🕦',
+  'clock12': '🕛',
+  'clock1230': '🕧',
+  'clock130': '🕜',
+  'clock2': '🕑',
+  'clock230': '🕝',
+  'clock3': '🕒',
+  'clock330': '🕞',
+  'clock4': '🕓',
+  'clock430': '🕟',
+  'clock5': '🕔',
+  'clock530': '🕠',
+  'clock6': '🕕',
+  'clock630': '🕡',
+  'clock7': '🕖',
+  'clock730': '🕢',
+  'clock8': '🕗',
+  'clock830': '🕣',
+  'clock9': '🕘',
+  'clock930': '🕤',
+  'closed_book': '📕',
+  'closed_lock_with_key': '🔐',
+  'closed_umbrella': '🌂',
+  'cloud': '☁️',
+  'cloud_with_lightning': '🌩',
+  'cloud_with_lightning_and_rain': '⛈',
+  'cloud_with_rain': '🌧',
+  'cloud_with_snow': '🌨',
+  'clown_face': '🤡',
+  'clubs': '♣️',
+  'cn': '🇨🇳',
+  'coat': '🧥',
+  'cocktail': '🍸',
+  'coconut': '🥥',
+  'cocos_islands': '🇨🇨',
+  'coffee': '☕',
+  'coffin': '⚰',
+  'cold': '🥶',
+  'cold_sweat': '😰',
+  'colombia': '🇨🇴',
+  'comet': '☄',
+  'comoros': '🇰🇲',
+  'compass': '🧭',
+  'computer': '💻',
+  'computer_mouse': '🖱',
+  'confetti_ball': '🎊',
+  'confounded': '😖',
+  'confused': '😕',
+  'congo_brazzaville': '🇨🇬',
+  'congo_kinshasa': '🇨🇩',
+  'congratulations': '㊗️',
+  'construction': '🚧',
+  'construction_worker_man': '👷',
+  'construction_worker_woman': '👷‍♀️',
+  'control_knobs': '🎛',
+  'convenience_store': '🏪',
+  'cook_islands': '🇨🇰',
+  'cookie': '🍪',
+  'cool': '🆒',
+  'copyright': '©️',
+  'corn': '🌽',
+  'costa_rica': '🇨🇷',
+  'cote_divoire': '🇨🇮',
+  'couch_and_lamp': '🛋',
+  'couple': '👫',
+  'couple_with_heart_man_man': '👨‍❤️‍👨',
+  'couple_with_heart_woman_man': '💑',
+  'couple_with_heart_woman_woman': '👩‍❤️‍👩',
+  'couplekiss_man_man': '👨‍❤️‍💋‍👨',
+  'couplekiss_man_woman': '💏',
+  'couplekiss_woman_woman': '👩‍❤️‍💋‍👩',
+  'cow': '🐮',
+  'cow2': '🐄',
+  'cowboy_hat_face': '🤠',
+  'crab': '🦀',
+  'crayon': '🖍',
+  'credit_card': '💳',
+  'crescent_moon': '🌙',
+  'cricket': '🏏',
+  'croatia': '🇭🇷',
+  'crocodile': '🐊',
+  'croissant': '🥐',
+  'crossed_fingers': '🤞',
+  'crossed_flags': '🎌',
+  'crossed_swords': '⚔',
+  'crown': '👑',
+  'cry': '😢',
+  'crying_cat_face': '😿',
+  'crystal_ball': '🔮',
+  'cuba': '🇨🇺',
+  'cucumber': '🥒',
+  'cup_with_straw': '🥤',
+  'cupcake': '🧁',
+  'cupid': '💘',
+  'curacao': '🇨🇼',
+  'curling_stone': '🥌',
+  'curly_loop': '➰',
+  'currency_exchange': '💱',
+  'curry': '🍛',
+  'custard': '🍮',
+  'customs': '🛃',
+  'cyclone': '🌀',
+  'cyprus': '🇨🇾',
+  'czech_republic': '🇨🇿',
+  'dagger': '🗡',
+  'dancer': '💃',
+  'dancing_men': '👯‍♂️',
+  'dancing_women': '👯',
+  'dango': '🍡',
+  'dark_sunglasses': '🕶',
+  'dart': '🎯',
+  'dash': '💨',
+  'date': '📅',
+  'de': '🇩🇪',
+  'deciduous_tree': '🌳',
+  'deer': '🦌',
+  'denmark': '🇩🇰',
+  'department_store': '🏬',
+  'derelict_house': '🏚',
+  'desert': '🏜',
+  'desert_island': '🏝',
+  'desktop_computer': '🖥',
+  'diamond_shape_with_a_dot_inside': '💠',
+  'diamonds': '♦️',
+  'disappointed': '😞',
+  'disappointed_relieved': '😥',
+  'dizzy': '💫',
+  'dizzy_face': '😵',
+  'djibouti': '🇩🇯',
+  'dna': '🧬',
+  'do_not_litter': '🚯',
+  'dog': '🐶',
+  'dog2': '🐕',
+  'dollar': '💵',
+  'dolls': '🎎',
+  'dolphin': '🐬',
+  'dominica': '🇩🇲',
+  'dominican_republic': '🇩🇴',
+  'door': '🚪',
+  'doughnut': '🍩',
+  'dove': '🕊',
+  'dragon': '🐉',
+  'dragon_face': '🐲',
+  'dress': '👗',
+  'dromedary_camel': '🐪',
+  'drooling_face': '🤤',
+  'droplet': '💧',
+  'drum': '🥁',
+  'duck': '🦆',
+  'dumpling': '🥟',
+  'dvd': '📀',
+  'e-mail': '📧',
+  'eagle': '🦅',
+  'ear': '👂',
+  'ear_of_rice': '🌾',
+  'earth_africa': '🌍',
+  'earth_americas': '🌎',
+  'earth_asia': '🌏',
+  'ecuador': '🇪🇨',
+  'egg': '🥚',
+  'eggplant': '🍆',
+  'egypt': '🇪🇬',
+  'eight': '8️⃣',
+  'eight_pointed_black_star': '✴️',
+  'eight_spoked_asterisk': '✳️',
+  'eject_button': '⏏️',
+  'el_salvador': '🇸🇻',
+  'electric_plug': '🔌',
+  'elephant': '🐘',
+  'email': '✉️',
+  'end': '🔚',
+  'england': '🏴󠁧󠁢󠁥󠁮󠁧󠁿',
+  'envelope_with_arrow': '📩',
+  'equatorial_guinea': '🇬🇶',
+  'eritrea': '🇪🇷',
+  'es': '🇪🇸',
+  'estonia': '🇪🇪',
+  'ethiopia': '🇪🇹',
+  'eu': '🇪🇺',
+  'euro': '💶',
+  'european_castle': '🏰',
+  'european_post_office': '🏤',
+  'evergreen_tree': '🌲',
+  'exclamation': '❗',
+  'exploding_head': '🤯',
+  'expressionless': '😑',
+  'eye': '👁',
+  'eyeglasses': '👓',
+  'eyes': '👀',
+  'face_with_head_bandage': '🤕',
+  'face_with_thermometer': '🤒',
+  'facepunch': '👊',
+  'factory': '🏭',
+  'falkland_islands': '🇫🇰',
+  'fallen_leaf': '🍂',
+  'family_man_boy': '👨‍👦',
+  'family_man_boy_boy': '👨‍👦‍👦',
+  'family_man_girl': '👨‍👧',
+  'family_man_girl_boy': '👨‍👧‍👦',
+  'family_man_girl_girl': '👨‍👧‍👧',
+  'family_man_man_boy': '👨‍👨‍👦',
+  'family_man_man_boy_boy': '👨‍👨‍👦‍👦',
+  'family_man_man_girl': '👨‍👨‍👧',
+  'family_man_man_girl_boy': '👨‍👨‍👧‍👦',
+  'family_man_man_girl_girl': '👨‍👨‍👧‍👧',
+  'family_man_woman_boy': '👪',
+  'family_man_woman_boy_boy': '👨‍👩‍👦‍👦',
+  'family_man_woman_girl': '👨‍👩‍👧',
+  'family_man_woman_girl_boy': '👨‍👩‍👧‍👦',
+  'family_man_woman_girl_girl': '👨‍👩‍👧‍👧',
+  'family_woman_boy': '👩‍👦',
+  'family_woman_boy_boy': '👩‍👦‍👦',
+  'family_woman_girl': '👩‍👧',
+  'family_woman_girl_boy': '👩‍👧‍👦',
+  'family_woman_girl_girl': '👩‍👧‍👧',
+  'family_woman_woman_boy': '👩‍👩‍👦',
+  'family_woman_woman_boy_boy': '👩‍👩‍👦‍👦',
+  'family_woman_woman_girl': '👩‍👩‍👧',
+  'family_woman_woman_girl_boy': '👩‍👩‍👧‍👦',
+  'family_woman_woman_girl_girl': '👩‍👩‍👧‍👧',
+  'faroe_islands': '🇫🇴',
+  'fast_forward': '⏩',
+  'fax': '📠',
+  'fearful': '😨',
+  'female_detective': '🕵️‍♀️',
+  'ferris_wheel': '🎡',
+  'ferry': '⛴',
+  'field_hockey': '🏑',
+  'fiji': '🇫🇯',
+  'file_cabinet': '🗄',
+  'file_folder': '📁',
+  'film_projector': '📽',
+  'film_strip': '🎞',
+  'finland': '🇫🇮',
+  'fire': '🔥',
+  'fire_engine': '🚒',
+  'fire_extinguisher': '🧯',
+  'firecracker': '🧨',
+  'fireworks': '🎆',
+  'first_quarter_moon': '🌓',
+  'first_quarter_moon_with_face': '🌛',
+  'fish': '🐟',
+  'fish_cake': '🍥',
+  'fishing_pole_and_fish': '🎣',
+  'fist': '✊',
+  'fist_left': '🤛',
+  'fist_right': '🤜',
+  'five': '5️⃣',
+  'flags': '🎏',
+  'flashlight': '🔦',
+  'flat_shoe': '🥿',
+  'fleur_de_lis': '⚜',
+  'flight_arrival': '🛬',
+  'flight_departure': '🛫',
+  'floppy_disk': '💾',
+  'flower_playing_cards': '🎴',
+  'flushed': '😳',
+  'flying_disc': '🥏',
+  'flying_saucer': '🛸',
+  'fog': '🌫',
+  'foggy': '🌁',
+  'foot': '🦶',
+  'football': '🏈',
+  'footprints': '👣',
+  'fork_and_knife': '🍴',
+  'fortune_cookie': '🥠',
+  'fountain': '⛲',
+  'fountain_pen': '🖋',
+  'four': '4️⃣',
+  'four_leaf_clover': '🍀',
+  'fox_face': '🦊',
+  'fr': '🇫🇷',
+  'framed_picture': '🖼',
+  'free': '🆓',
+  'french_guiana': '🇬🇫',
+  'french_polynesia': '🇵🇫',
+  'french_southern_territories': '🇹🇫',
+  'fried_egg': '🍳',
+  'fried_shrimp': '🍤',
+  'fries': '🍟',
+  'frog': '🐸',
+  'frowning': '😦',
+  'frowning_face': '☹',
+  'frowning_man': '🙍‍♂️',
+  'frowning_woman': '🙍',
+  'fu': '🖕',
+  'fuelpump': '⛽',
+  'full_moon': '🌕',
+  'full_moon_with_face': '🌝',
+  'funeral_urn': '⚱',
+  'gabon': '🇬🇦',
+  'gambia': '🇬🇲',
+  'game_die': '🎲',
+  'gear': '⚙',
+  'gem': '💎',
+  'gemini': '♊',
+  'georgia': '🇬🇪',
+  'ghana': '🇬🇭',
+  'ghost': '👻',
+  'gibraltar': '🇬🇮',
+  'gift': '🎁',
+  'gift_heart': '💝',
+  'giraffe': '🦒',
+  'girl': '👧',
+  'globe_with_meridians': '🌐',
+  'gloves': '🧤',
+  'goal_net': '🥅',
+  'goat': '🐐',
+  'goggles': '🥽',
+  'golf': '⛳',
+  'golfing_man': '🏌',
+  'golfing_woman': '🏌️‍♀️',
+  'gorilla': '🦍',
+  'grapes': '🍇',
+  'grasshopper': '🦗',
+  'greece': '🇬🇷',
+  'green_apple': '🍏',
+  'green_book': '📗',
+  'green_heart': '💚',
+  'green_salad': '🥗',
+  'greenland': '🇬🇱',
+  'grenada': '🇬🇩',
+  'grey_exclamation': '❕',
+  'grey_question': '❔',
+  'grimacing': '😬',
+  'grin': '😁',
+  'grinning': '😀',
+  'guadeloupe': '🇬🇵',
+  'guam': '🇬🇺',
+  'guardsman': '💂',
+  'guardswoman': '💂‍♀️',
+  'guatemala': '🇬🇹',
+  'guernsey': '🇬🇬',
+  'guinea': '🇬🇳',
+  'guinea_bissau': '🇬🇼',
+  'guitar': '🎸',
+  'gun': '🔫',
+  'guyana': '🇬🇾',
+  'haircut_man': '💇‍♂️',
+  'haircut_woman': '💇',
+  'haiti': '🇭🇹',
+  'hamburger': '🍔',
+  'hammer': '🔨',
+  'hammer_and_pick': '⚒',
+  'hammer_and_wrench': '🛠',
+  'hamster': '🐹',
+  'hand_over_mouth': '🤭',
+  'handbag': '👜',
+  'handshake': '🤝',
+  'hash': '#️⃣',
+  'hatched_chick': '🐥',
+  'hatching_chick': '🐣',
+  'headphones': '🎧',
+  'hear_no_evil': '🙉',
+  'heart': '❤️',
+  'heart_decoration': '💟',
+  'heart_eyes': '😍',
+  'heart_eyes_cat': '😻',
+  'heartbeat': '💓',
+  'heartpulse': '💗',
+  'hearts': '♥️',
+  'heavy_check_mark': '✔️',
+  'heavy_division_sign': '➗',
+  'heavy_dollar_sign': '💲',
+  'heavy_heart_exclamation': '❣',
+  'heavy_minus_sign': '➖',
+  'heavy_multiplication_x': '✖️',
+  'heavy_plus_sign': '➕',
+  'hedgehog': '🦔',
+  'helicopter': '🚁',
+  'herb': '🌿',
+  'hibiscus': '🌺',
+  'high_brightness': '🔆',
+  'high_heel': '👠',
+  'hiking_boot': '🥾',
+  'hippopotamus': '🦛',
+  'hocho': '🔪',
+  'hole': '🕳',
+  'honduras': '🇭🇳',
+  'honey_pot': '🍯',
+  'honeybee': '🐝',
+  'hong_kong': '🇭🇰',
+  'horse': '🐴',
+  'horse_racing': '🏇',
+  'hospital': '🏥',
+  'hot': '🥵',
+  'hot_pepper': '🌶',
+  'hotdog': '🌭',
+  'hotel': '🏨',
+  'hotsprings': '♨️',
+  'hourglass': '⌛',
+  'hourglass_flowing_sand': '⏳',
+  'house': '🏠',
+  'house_with_garden': '🏡',
+  'houses': '🏘',
+  'hugs': '🤗',
+  'hungary': '🇭🇺',
+  'hushed': '😯',
+  'ice_cream': '🍨',
+  'ice_hockey': '🏒',
+  'ice_skate': '⛸',
+  'icecream': '🍦',
+  'iceland': '🇮🇸',
+  'id': '🆔',
+  'ideograph_advantage': '🉐',
+  'imp': '👿',
+  'inbox_tray': '📥',
+  'incoming_envelope': '📨',
+  'india': '🇮🇳',
+  'indonesia': '🇮🇩',
+  'infinity': '♾',
+  'information_source': 'ℹ️',
+  'innocent': '😇',
+  'interrobang': '⁉️',
+  'iphone': '📱',
+  'iran': '🇮🇷',
+  'iraq': '🇮🇶',
+  'ireland': '🇮🇪',
+  'isle_of_man': '🇮🇲',
+  'israel': '🇮🇱',
+  'it': '🇮🇹',
+  'izakaya_lantern': '🏮',
+  'jack_o_lantern': '🎃',
+  'jamaica': '🇯🇲',
+  'japan': '🗾',
+  'japanese_castle': '🏯',
+  'japanese_goblin': '👺',
+  'japanese_ogre': '👹',
+  'jeans': '👖',
+  'jersey': '🇯🇪',
+  'jigsaw': '🧩',
+  'jordan': '🇯🇴',
+  'joy': '😂',
+  'joy_cat': '😹',
+  'joystick': '🕹',
+  'jp': '🇯🇵',
+  'kaaba': '🕋',
+  'kangaroo': '🦘',
+  'kazakhstan': '🇰🇿',
+  'kenya': '🇰🇪',
+  'key': '🔑',
+  'keyboard': '⌨',
+  'keycap_ten': '🔟',
+  'kick_scooter': '🛴',
+  'kimono': '👘',
+  'kiribati': '🇰🇮',
+  'kiss': '💋',
+  'kissing': '😗',
+  'kissing_cat': '😽',
+  'kissing_closed_eyes': '😚',
+  'kissing_heart': '😘',
+  'kissing_smiling_eyes': '😙',
+  'kiwi_fruit': '🥝',
+  'koala': '🐨',
+  'koko': '🈁',
+  'kosovo': '🇽🇰',
+  'kr': '🇰🇷',
+  'kuwait': '🇰🇼',
+  'kyrgyzstan': '🇰🇬',
+  'labcoat': '🥼',
+  'label': '🏷',
+  'lacrosse': '🥍',
+  'laos': '🇱🇦',
+  'large_blue_circle': '🔵',
+  'large_blue_diamond': '🔷',
+  'large_orange_diamond': '🔶',
+  'last_quarter_moon': '🌗',
+  'last_quarter_moon_with_face': '🌜',
+  'latin_cross': '✝',
+  'latvia': '🇱🇻',
+  'laughing': '😆',
+  'leafy_greens': '🥬',
+  'leaves': '🍃',
+  'lebanon': '🇱🇧',
+  'ledger': '📒',
+  'left_luggage': '🛅',
+  'left_right_arrow': '↔️',
+  'left_speech_bubble': '🗨',
+  'leftwards_arrow_with_hook': '↩️',
+  'leg': '🦵',
+  'lemon': '🍋',
+  'leo': '♌',
+  'leopard': '🐆',
+  'lesotho': '🇱🇸',
+  'level_slider': '🎚',
+  'liberia': '🇱🇷',
+  'libra': '♎',
+  'libya': '🇱🇾',
+  'liechtenstein': '🇱🇮',
+  'light_rail': '🚈',
+  'link': '🔗',
+  'lion': '🦁',
+  'lips': '👄',
+  'lipstick': '💄',
+  'lithuania': '🇱🇹',
+  'lizard': '🦎',
+  'llama': '🦙',
+  'lobster': '🦞',
+  'lock': '🔒',
+  'lock_with_ink_pen': '🔏',
+  'lollipop': '🍭',
+  'loop': '➿',
+  'lotion_bottle': '🧴',
+  'loud_sound': '🔊',
+  'loudspeaker': '📢',
+  'love_hotel': '🏩',
+  'love_letter': '💌',
+  'love_you': '🤟',
+  'low_brightness': '🔅',
+  'luggage': '🧳',
+  'luxembourg': '🇱🇺',
+  'lying_face': '🤥',
+  'm': 'Ⓜ️',
+  'macau': '🇲🇴',
+  'macedonia': '🇲🇰',
+  'madagascar': '🇲🇬',
+  'mag': '🔍',
+  'mag_right': '🔎',
+  'magnet': '🧲',
+  'mahjong': '🀄',
+  'mailbox': '📫',
+  'mailbox_closed': '📪',
+  'mailbox_with_mail': '📬',
+  'mailbox_with_no_mail': '📭',
+  'malawi': '🇲🇼',
+  'malaysia': '🇲🇾',
+  'maldives': '🇲🇻',
+  'male_detective': '🕵',
+  'mali': '🇲🇱',
+  'malta': '🇲🇹',
+  'man': '👨',
+  'man_artist': '👨‍🎨',
+  'man_astronaut': '👨‍🚀',
+  'man_cartwheeling': '🤸‍♂️',
+  'man_cook': '👨‍🍳',
+  'man_dancing': '🕺',
+  'man_elf': '🧝‍♂️',
+  'man_facepalming': '🤦‍♂️',
+  'man_factory_worker': '👨‍🏭',
+  'man_fairy': '🧚‍♂️',
+  'man_farmer': '👨‍🌾',
+  'man_firefighter': '👨‍🚒',
+  'man_genie': '🧞‍♂️',
+  'man_health_worker': '👨‍⚕️',
+  'man_in_lotus_position': '🧘‍♂️',
+  'man_in_steamy_room': '🧖‍♂️',
+  'man_in_tuxedo': '🤵',
+  'man_judge': '👨‍⚖️',
+  'man_juggling': '🤹‍♂️',
+  'man_mechanic': '👨‍🔧',
+  'man_office_worker': '👨‍💼',
+  'man_pilot': '👨‍✈️',
+  'man_playing_handball': '🤾‍♂️',
+  'man_playing_water_polo': '🤽‍♂️',
+  'man_scientist': '👨‍🔬',
+  'man_shrugging': '🤷‍♂️',
+  'man_singer': '👨‍🎤',
+  'man_student': '👨‍🎓',
+  'man_superhero': '🦸‍♂️',
+  'man_supervillain': '🦹‍♂️',
+  'man_teacher': '👨‍🏫',
+  'man_technologist': '👨‍💻',
+  'man_vampire': '🧛‍♂️',
+  'man_with_gua_pi_mao': '👲',
+  'man_with_turban': '👳',
+  'man_zombie': '🧟‍♂️',
+  'mango': '🥭',
+  'mans_shoe': '👞',
+  'mantelpiece_clock': '🕰',
+  'maple_leaf': '🍁',
+  'marshall_islands': '🇲🇭',
+  'martial_arts_uniform': '🥋',
+  'martinique': '🇲🇶',
+  'mask': '😷',
+  'massage_man': '💆‍♂️',
+  'massage_woman': '💆',
+  'mauritania': '🇲🇷',
+  'mauritius': '🇲🇺',
+  'mayotte': '🇾🇹',
+  'meat_on_bone': '🍖',
+  'medal_military': '🎖',
+  'medal_sports': '🏅',
+  'mega': '📣',
+  'melon': '🍈',
+  'memo': '📝',
+  'men_wrestling': '🤼‍♂️',
+  'menorah': '🕎',
+  'mens': '🚹',
+  'mermaid': '🧜‍♀️',
+  'merman': '🧜‍♂️',
+  'metal': '🤘',
+  'metro': '🚇',
+  'mexico': '🇲🇽',
+  'microbe': '🦠',
+  'micronesia': '🇫🇲',
+  'microphone': '🎤',
+  'microscope': '🔬',
+  'milk_glass': '🥛',
+  'milky_way': '🌌',
+  'minibus': '🚐',
+  'minidisc': '💽',
+  'mobile_phone_off': '📴',
+  'moldova': '🇲🇩',
+  'monaco': '🇲🇨',
+  'money_mouth_face': '🤑',
+  'money_with_wings': '💸',
+  'moneybag': '💰',
+  'mongolia': '🇲🇳',
+  'monkey': '🐒',
+  'monkey_face': '🐵',
+  'monocle': '🧐',
+  'monorail': '🚝',
+  'montenegro': '🇲🇪',
+  'montserrat': '🇲🇸',
+  'moon_cake': '🥮',
+  'morocco': '🇲🇦',
+  'mortar_board': '🎓',
+  'mosque': '🕌',
+  'mosquito': '🦟',
+  'motor_boat': '🛥',
+  'motor_scooter': '🛵',
+  'motorcycle': '🏍',
+  'motorway': '🛣',
+  'mount_fuji': '🗻',
+  'mountain': '⛰',
+  'mountain_biking_man': '🚵',
+  'mountain_biking_woman': '🚵‍♀️',
+  'mountain_cableway': '🚠',
+  'mountain_railway': '🚞',
+  'mountain_snow': '🏔',
+  'mouse': '🐭',
+  'mouse2': '🐁',
+  'movie_camera': '🎥',
+  'moyai': '🗿',
+  'mozambique': '🇲🇿',
+  'mrs_claus': '🤶',
+  'muscle': '💪',
+  'mushroom': '🍄',
+  'musical_keyboard': '🎹',
+  'musical_note': '🎵',
+  'musical_score': '🎼',
+  'mute': '🔇',
+  'myanmar': '🇲🇲',
+  'nail_care': '💅',
+  'name_badge': '📛',
+  'namibia': '🇳🇦',
+  'national_park': '🏞',
+  'nauru': '🇳🇷',
+  'nauseated_face': '🤢',
+  'nazar_amulet': '🧿',
+  'necktie': '👔',
+  'negative_squared_cross_mark': '❎',
+  'nepal': '🇳🇵',
+  'nerd_face': '🤓',
+  'netherlands': '🇳🇱',
+  'neutral_face': '😐',
+  'new': '🆕',
+  'new_caledonia': '🇳🇨',
+  'new_moon': '🌑',
+  'new_moon_with_face': '🌚',
+  'new_zealand': '🇳🇿',
+  'newspaper': '📰',
+  'newspaper_roll': '🗞',
+  'next_track_button': '⏭',
+  'ng': '🆖',
+  'nicaragua': '🇳🇮',
+  'niger': '🇳🇪',
+  'nigeria': '🇳🇬',
+  'night_with_stars': '🌃',
+  'nine': '9️⃣',
+  'niue': '🇳🇺',
+  'no_bell': '🔕',
+  'no_bicycles': '🚳',
+  'no_entry': '⛔',
+  'no_entry_sign': '🚫',
+  'no_good_man': '🙅‍♂️',
+  'no_good_woman': '🙅',
+  'no_mobile_phones': '📵',
+  'no_mouth': '😶',
+  'no_pedestrians': '🚷',
+  'no_smoking': '🚭',
+  'non-potable_water': '🚱',
+  'norfolk_island': '🇳🇫',
+  'north_korea': '🇰🇵',
+  'northern_mariana_islands': '🇲🇵',
+  'norway': '🇳🇴',
+  'nose': '👃',
+  'notebook': '📓',
+  'notebook_with_decorative_cover': '📔',
+  'notes': '🎶',
+  'nut_and_bolt': '🔩',
+  'o': '⭕',
+  'o2': '🅾️',
+  'ocean': '🌊',
+  'octopus': '🐙',
+  'oden': '🍢',
+  'office': '🏢',
+  'oil_drum': '🛢',
+  'ok': '🆗',
+  'ok_hand': '👌',
+  'ok_man': '🙆‍♂️',
+  'ok_woman': '🙆',
+  'old_key': '🗝',
+  'older_adult': '🧓',
+  'older_man': '👴',
+  'older_woman': '👵',
+  'om': '🕉',
+  'oman': '🇴🇲',
+  'on': '🔛',
+  'oncoming_automobile': '🚘',
+  'oncoming_bus': '🚍',
+  'oncoming_police_car': '🚔',
+  'oncoming_taxi': '🚖',
+  'one': '1️⃣',
+  'open_book': '📖',
+  'open_file_folder': '📂',
+  'open_hands': '👐',
+  'open_mouth': '😮',
+  'open_umbrella': '☂',
+  'ophiuchus': '⛎',
+  'orange_book': '📙',
+  'orange_heart': '🧡',
+  'orthodox_cross': '☦',
+  'outbox_tray': '📤',
+  'owl': '🦉',
+  'ox': '🐂',
+  'package': '📦',
+  'page_facing_up': '📄',
+  'page_with_curl': '📃',
+  'pager': '📟',
+  'paintbrush': '🖌',
+  'pakistan': '🇵🇰',
+  'palau': '🇵🇼',
+  'palestinian_territories': '🇵🇸',
+  'palm_tree': '🌴',
+  'palms_up': '🤲',
+  'panama': '🇵🇦',
+  'pancakes': '🥞',
+  'panda_face': '🐼',
+  'paperclip': '📎',
+  'paperclips': '🖇',
+  'papua_new_guinea': '🇵🇬',
+  'paraguay': '🇵🇾',
+  'parasol_on_ground': '⛱',
+  'parking': '🅿️',
+  'parrot': '🦜',
+  'part_alternation_mark': '〽️',
+  'partly_sunny': '⛅',
+  'partying': '🥳',
+  'passenger_ship': '🛳',
+  'passport_control': '🛂',
+  'pause_button': '⏸',
+  'paw_prints': '🐾',
+  'peace_symbol': '☮',
+  'peach': '🍑',
+  'peacock': '🦚',
+  'peanuts': '🥜',
+  'pear': '🍐',
+  'pen': '🖊',
+  'pencil2': '✏️',
+  'penguin': '🐧',
+  'pensive': '😔',
+  'performing_arts': '🎭',
+  'persevere': '😣',
+  'person_fencing': '🤺',
+  'peru': '🇵🇪',
+  'petri_dish': '🧫',
+  'philippines': '🇵🇭',
+  'phone': '☎️',
+  'pick': '⛏',
+  'pie': '🥧',
+  'pig': '🐷',
+  'pig2': '🐖',
+  'pig_nose': '🐽',
+  'pill': '💊',
+  'pineapple': '🍍',
+  'ping_pong': '🏓',
+  'pirate_flag': '🏴‍☠️',
+  'pisces': '♓',
+  'pitcairn_islands': '🇵🇳',
+  'pizza': '🍕',
+  'place_of_worship': '🛐',
+  'plate_with_cutlery': '🍽',
+  'play_or_pause_button': '⏯',
+  'pleading': '🥺',
+  'point_down': '👇',
+  'point_left': '👈',
+  'point_right': '👉',
+  'point_up': '☝',
+  'point_up_2': '👆',
+  'poland': '🇵🇱',
+  'police_car': '🚓',
+  'policeman': '👮',
+  'policewoman': '👮‍♀️',
+  'poodle': '🐩',
+  'poop': '💩',
+  'popcorn': '🍿',
+  'portugal': '🇵🇹',
+  'post_office': '🏣',
+  'postal_horn': '📯',
+  'postbox': '📮',
+  'potable_water': '🚰',
+  'potato': '🥔',
+  'pouch': '👝',
+  'poultry_leg': '🍗',
+  'pound': '💷',
+  'pouting_cat': '😾',
+  'pouting_man': '🙎‍♂️',
+  'pouting_woman': '🙎',
+  'pray': '🙏',
+  'prayer_beads': '📿',
+  'pregnant_woman': '🤰',
+  'pretzel': '🥨',
+  'previous_track_button': '⏮',
+  'prince': '🤴',
+  'princess': '👸',
+  'printer': '🖨',
+  'puerto_rico': '🇵🇷',
+  'purple_heart': '💜',
+  'purse': '👛',
+  'pushpin': '📌',
+  'put_litter_in_its_place': '🚮',
+  'qatar': '🇶🇦',
+  'question': '❓',
+  'rabbit': '🐰',
+  'rabbit2': '🐇',
+  'raccoon': '🦝',
+  'racehorse': '🐎',
+  'racing_car': '🏎',
+  'radio': '📻',
+  'radio_button': '🔘',
+  'radioactive': '☢',
+  'rage': '😡',
+  'railway_car': '🚃',
+  'railway_track': '🛤',
+  'rainbow': '🌈',
+  'rainbow_flag': '🏳️‍🌈',
+  'raised_back_of_hand': '🤚',
+  'raised_eyebrow': '🤨',
+  'raised_hand': '✋',
+  'raised_hand_with_fingers_splayed': '🖐',
+  'raised_hands': '🙌',
+  'raising_hand_man': '🙋‍♂️',
+  'raising_hand_woman': '🙋',
+  'ram': '🐏',
+  'ramen': '🍜',
+  'rat': '🐀',
+  'receipt': '🧾',
+  'record_button': '⏺',
+  'recycle': '♻️',
+  'red_car': '🚗',
+  'red_circle': '🔴',
+  'red_envelope': '🧧',
+  'registered': '®️',
+  'relaxed': '☺️',
+  'relieved': '😌',
+  'reminder_ribbon': '🎗',
+  'repeat': '🔁',
+  'repeat_one': '🔂',
+  'rescue_worker_helmet': '⛑',
+  'restroom': '🚻',
+  'reunion': '🇷🇪',
+  'revolving_hearts': '💞',
+  'rewind': '⏪',
+  'rhinoceros': '🦏',
+  'ribbon': '🎀',
+  'rice': '🍚',
+  'rice_ball': '🍙',
+  'rice_cracker': '🍘',
+  'rice_scene': '🎑',
+  'right_anger_bubble': '🗯',
+  'ring': '💍',
+  'robot': '🤖',
+  'rocket': '🚀',
+  'rofl': '🤣',
+  'roll_eyes': '🙄',
+  'roller_coaster': '🎢',
+  'romania': '🇷🇴',
+  'rooster': '🐓',
+  'rose': '🌹',
+  'rosette': '🏵',
+  'rotating_light': '🚨',
+  'round_pushpin': '📍',
+  'rowing_man': '🚣',
+  'rowing_woman': '🚣‍♀️',
+  'ru': '🇷🇺',
+  'rugby_football': '🏉',
+  'running_man': '🏃',
+  'running_shirt_with_sash': '🎽',
+  'running_woman': '🏃‍♀️',
+  'rwanda': '🇷🇼',
+  'sa': '🈂️',
+  'safety_pin': '🧷',
+  'sagittarius': '♐',
+  'sailboat': '⛵',
+  'sake': '🍶',
+  'salt': '🧂',
+  'samoa': '🇼🇸',
+  'san_marino': '🇸🇲',
+  'sandal': '👡',
+  'sandwich': '🥪',
+  'santa': '🎅',
+  'sao_tome_principe': '🇸🇹',
+  'satellite': '📡',
+  'saudi_arabia': '🇸🇦',
+  'sauropod': '🦕',
+  'saxophone': '🎷',
+  'scarf': '🧣',
+  'school': '🏫',
+  'school_satchel': '🎒',
+  'scissors': '✂️',
+  'scorpion': '🦂',
+  'scorpius': '♏',
+  'scotland': '🏴󠁧󠁢󠁳󠁣󠁴󠁿',
+  'scream': '😱',
+  'scream_cat': '🙀',
+  'scroll': '📜',
+  'seat': '💺',
+  'secret': '㊙️',
+  'see_no_evil': '🙈',
+  'seedling': '🌱',
+  'selfie': '🤳',
+  'senegal': '🇸🇳',
+  'serbia': '🇷🇸',
+  'seven': '7️⃣',
+  'seychelles': '🇸🇨',
+  'shallow_pan_of_food': '🥘',
+  'shamrock': '☘',
+  'shark': '🦈',
+  'shaved_ice': '🍧',
+  'sheep': '🐑',
+  'shell': '🐚',
+  'shield': '🛡',
+  'shinto_shrine': '⛩',
+  'ship': '🚢',
+  'shopping': '🛍',
+  'shopping_cart': '🛒',
+  'shower': '🚿',
+  'shrimp': '🦐',
+  'shushing': '🤫',
+  'sierra_leone': '🇸🇱',
+  'signal_strength': '📶',
+  'singapore': '🇸🇬',
+  'sint_maarten': '🇸🇽',
+  'six': '6️⃣',
+  'six_pointed_star': '🔯',
+  'skateboard': '🛹',
+  'ski': '🎿',
+  'skier': '⛷',
+  'skull': '💀',
+  'skull_and_crossbones': '☠',
+  'sled': '🛷',
+  'sleeping': '😴',
+  'sleeping_bed': '🛌',
+  'sleepy': '😪',
+  'slightly_frowning_face': '🙁',
+  'slightly_smiling_face': '🙂',
+  'slot_machine': '🎰',
+  'slovakia': '🇸🇰',
+  'slovenia': '🇸🇮',
+  'small_airplane': '🛩',
+  'small_blue_diamond': '🔹',
+  'small_orange_diamond': '🔸',
+  'small_red_triangle': '🔺',
+  'small_red_triangle_down': '🔻',
+  'smile': '😄',
+  'smile_cat': '😸',
+  'smiley': '😃',
+  'smiley_cat': '😺',
+  'smiling_face_with_three_hearts': '🥰',
+  'smiling_imp': '😈',
+  'smirk': '😏',
+  'smirk_cat': '😼',
+  'smoking': '🚬',
+  'snail': '🐌',
+  'snake': '🐍',
+  'sneezing_face': '🤧',
+  'snowboarder': '🏂',
+  'snowflake': '❄️',
+  'snowman': '⛄',
+  'snowman_with_snow': '☃',
+  'soap': '🧼',
+  'sob': '😭',
+  'soccer': '⚽',
+  'socks': '🧦',
+  'softball': '🥎',
+  'solomon_islands': '🇸🇧',
+  'somalia': '🇸🇴',
+  'soon': '🔜',
+  'sorceress': '🧙‍♀️',
+  'sos': '🆘',
+  'sound': '🔉',
+  'south_africa': '🇿🇦',
+  'south_georgia_south_sandwich_islands': '🇬🇸',
+  'south_sudan': '🇸🇸',
+  'space_invader': '👾',
+  'spades': '♠️',
+  'spaghetti': '🍝',
+  'sparkle': '❇️',
+  'sparkler': '🎇',
+  'sparkles': '✨',
+  'sparkling_heart': '💖',
+  'speak_no_evil': '🙊',
+  'speaker': '🔈',
+  'speaking_head': '🗣',
+  'speech_balloon': '💬',
+  'speedboat': '🚤',
+  'spider': '🕷',
+  'spider_web': '🕸',
+  'spiral_calendar': '🗓',
+  'spiral_notepad': '🗒',
+  'sponge': '🧽',
+  'spoon': '🥄',
+  'squid': '🦑',
+  'sri_lanka': '🇱🇰',
+  'st_barthelemy': '🇧🇱',
+  'st_helena': '🇸🇭',
+  'st_kitts_nevis': '🇰🇳',
+  'st_lucia': '🇱🇨',
+  'st_pierre_miquelon': '🇵🇲',
+  'st_vincent_grenadines': '🇻🇨',
+  'stadium': '🏟',
+  'star': '⭐',
+  'star2': '🌟',
+  'star_and_crescent': '☪',
+  'star_of_david': '✡',
+  'star_struck': '🤩',
+  'stars': '🌠',
+  'station': '🚉',
+  'statue_of_liberty': '🗽',
+  'steak': '🥩',
+  'steam_locomotive': '🚂',
+  'stew': '🍲',
+  'stop_button': '⏹',
+  'stop_sign': '🛑',
+  'stopwatch': '⏱',
+  'straight_ruler': '📏',
+  'strawberry': '🍓',
+  'stuck_out_tongue': '😛',
+  'stuck_out_tongue_closed_eyes': '😝',
+  'stuck_out_tongue_winking_eye': '😜',
+  'studio_microphone': '🎙',
+  'stuffed_flatbread': '🥙',
+  'sudan': '🇸🇩',
+  'sun_behind_large_cloud': '🌥',
+  'sun_behind_rain_cloud': '🌦',
+  'sun_behind_small_cloud': '🌤',
+  'sun_with_face': '🌞',
+  'sunflower': '🌻',
+  'sunglasses': '😎',
+  'sunny': '☀️',
+  'sunrise': '🌅',
+  'sunrise_over_mountains': '🌄',
+  'surfing_man': '🏄',
+  'surfing_woman': '🏄‍♀️',
+  'suriname': '🇸🇷',
+  'sushi': '🍣',
+  'suspension_railway': '🚟',
+  'swan': '🦢',
+  'swaziland': '🇸🇿',
+  'sweat': '😓',
+  'sweat_drops': '💦',
+  'sweat_smile': '😅',
+  'sweden': '🇸🇪',
+  'sweet_potato': '🍠',
+  'swimming_man': '🏊',
+  'swimming_woman': '🏊‍♀️',
+  'switzerland': '🇨🇭',
+  'symbols': '🔣',
+  'symbols_over_mouth': '🤬',
+  'synagogue': '🕍',
+  'syria': '🇸🇾',
+  'syringe': '💉',
+  't-rex': '🦖',
+  'taco': '🌮',
+  'tada': '🎉',
+  'taiwan': '🇹🇼',
+  'tajikistan': '🇹🇯',
+  'takeout_box': '🥡',
+  'tanabata_tree': '🎋',
+  'tangerine': '🍊',
+  'tanzania': '🇹🇿',
+  'taurus': '♉',
+  'taxi': '🚕',
+  'tea': '🍵',
+  'teddy_bear': '🧸',
+  'telephone_receiver': '📞',
+  'telescope': '🔭',
+  'tennis': '🎾',
+  'tent': '⛺',
+  'test_tube': '🧪',
+  'thailand': '🇹🇭',
+  'thermometer': '🌡',
+  'thinking': '🤔',
+  'thought_balloon': '💭',
+  'thread': '🧵',
+  'three': '3️⃣',
+  'ticket': '🎫',
+  'tickets': '🎟',
+  'tiger': '🐯',
+  'tiger2': '🐅',
+  'timer_clock': '⏲',
+  'timor_leste': '🇹🇱',
+  'tipping_hand_man': '💁‍♂️',
+  'tipping_hand_woman': '💁',
+  'tired_face': '😫',
+  'tm': '™️',
+  'togo': '🇹🇬',
+  'toilet': '🚽',
+  'toilet_paper': '🧻',
+  'tokelau': '🇹🇰',
+  'tokyo_tower': '🗼',
+  'tomato': '🍅',
+  'tonga': '🇹🇴',
+  'tongue': '👅',
+  'toolbox': '🧰',
+  'tooth': '🦷',
+  'top': '🔝',
+  'tophat': '🎩',
+  'tornado': '🌪',
+  'tr': '🇹🇷',
+  'trackball': '🖲',
+  'tractor': '🚜',
+  'traffic_light': '🚥',
+  'train': '🚋',
+  'train2': '🚆',
+  'tram': '🚊',
+  'triangular_flag_on_post': '🚩',
+  'triangular_ruler': '📐',
+  'trident': '🔱',
+  'trinidad_tobago': '🇹🇹',
+  'triumph': '😤',
+  'trolleybus': '🚎',
+  'trophy': '🏆',
+  'tropical_drink': '🍹',
+  'tropical_fish': '🐠',
+  'truck': '🚚',
+  'trumpet': '🎺',
+  'tshirt': '👕',
+  'tulip': '🌷',
+  'tumbler_glass': '🥃',
+  'tunisia': '🇹🇳',
+  'turkey': '🦃',
+  'turkmenistan': '🇹🇲',
+  'turks_caicos_islands': '🇹🇨',
+  'turtle': '🐢',
+  'tuvalu': '🇹🇻',
+  'tv': '📺',
+  'twisted_rightwards_arrows': '🔀',
+  'two': '2️⃣',
+  'two_hearts': '💕',
+  'two_men_holding_hands': '👬',
+  'two_women_holding_hands': '👭',
+  'u5272': '🈹',
+  'u5408': '🈴',
+  'u55b6': '🈺',
+  'u6307': '🈯',
+  'u6708': '🈷️',
+  'u6709': '🈶',
+  'u6e80': '🈵',
+  'u7121': '🈚',
+  'u7533': '🈸',
+  'u7981': '🈲',
+  'u7a7a': '🈳',
+  'uganda': '🇺🇬',
+  'uk': '🇬🇧',
+  'ukraine': '🇺🇦',
+  'umbrella': '☔',
+  'unamused': '😒',
+  'underage': '🔞',
+  'unicorn': '🦄',
+  'united_arab_emirates': '🇦🇪',
+  'united_nations': '🇺🇳',
+  'unlock': '🔓',
+  'up': '🆙',
+  'upside_down_face': '🙃',
+  'uruguay': '🇺🇾',
+  'us': '🇺🇸',
+  'us_virgin_islands': '🇻🇮',
+  'uzbekistan': '🇺🇿',
+  'v': '✌',
+  'vanuatu': '🇻🇺',
+  'vatican_city': '🇻🇦',
+  'venezuela': '🇻🇪',
+  'vertical_traffic_light': '🚦',
+  'vhs': '📼',
+  'vibration_mode': '📳',
+  'video_camera': '📹',
+  'video_game': '🎮',
+  'vietnam': '🇻🇳',
+  'violin': '🎻',
+  'virgo': '♍',
+  'volcano': '🌋',
+  'volleyball': '🏐',
+  'vomiting': '🤮',
+  'vs': '🆚',
+  'vulcan_salute': '🖖',
+  'wales': '🏴󠁧󠁢󠁷󠁬󠁳󠁿',
+  'walking_man': '🚶',
+  'walking_woman': '🚶‍♀️',
+  'wallis_futuna': '🇼🇫',
+  'waning_crescent_moon': '🌘',
+  'waning_gibbous_moon': '🌖',
+  'warning': '⚠️',
+  'wastebasket': '🗑',
+  'watch': '⌚',
+  'water_buffalo': '🐃',
+  'watermelon': '🍉',
+  'wave': '👋',
+  'wavy_dash': '〰️',
+  'waxing_crescent_moon': '🌒',
+  'waxing_gibbous_moon': '🌔',
+  'wc': '🚾',
+  'weary': '😩',
+  'wedding': '💒',
+  'weight_lifting_man': '🏋',
+  'weight_lifting_woman': '🏋️‍♀️',
+  'western_sahara': '🇪🇭',
+  'whale': '🐳',
+  'whale2': '🐋',
+  'wheel_of_dharma': '☸',
+  'wheelchair': '♿',
+  'white_check_mark': '✅',
+  'white_circle': '⚪',
+  'white_flag': '🏳',
+  'white_flower': '💮',
+  'white_large_square': '⬜',
+  'white_medium_small_square': '◽',
+  'white_medium_square': '◻️',
+  'white_small_square': '▫️',
+  'white_square_button': '🔳',
+  'wilted_flower': '🥀',
+  'wind_chime': '🎐',
+  'wind_face': '🌬',
+  'wine_glass': '🍷',
+  'wink': '😉',
+  'wizard': '🧙‍♂️',
+  'wolf': '🐺',
+  'woman': '👩',
+  'woman_artist': '👩‍🎨',
+  'woman_astronaut': '👩‍🚀',
+  'woman_cartwheeling': '🤸‍♀️',
+  'woman_cook': '👩‍🍳',
+  'woman_elf': '🧝‍♀️',
+  'woman_facepalming': '🤦‍♀️',
+  'woman_factory_worker': '👩‍🏭',
+  'woman_fairy': '🧚‍♀️',
+  'woman_farmer': '👩‍🌾',
+  'woman_firefighter': '👩‍🚒',
+  'woman_genie': '🧞‍♀️',
+  'woman_health_worker': '👩‍⚕️',
+  'woman_in_lotus_position': '🧘‍♀️',
+  'woman_in_steamy_room': '🧖‍♀️',
+  'woman_judge': '👩‍⚖️',
+  'woman_juggling': '🤹‍♀️',
+  'woman_mechanic': '👩‍🔧',
+  'woman_office_worker': '👩‍💼',
+  'woman_pilot': '👩‍✈️',
+  'woman_playing_handball': '🤾‍♀️',
+  'woman_playing_water_polo': '🤽‍♀️',
+  'woman_scientist': '👩‍🔬',
+  'woman_shrugging': '🤷',
+  'woman_singer': '👩‍🎤',
+  'woman_student': '👩‍🎓',
+  'woman_superhero': '🦸‍♀️',
+  'woman_supervillain': '🦹‍♀️',
+  'woman_teacher': '👩‍🏫',
+  'woman_technologist': '👩‍💻',
+  'woman_vampire': '🧛‍♀️',
+  'woman_with_headscarf': '🧕',
+  'woman_with_turban': '👳‍♀️',
+  'woman_zombie': '🧟‍♀️',
+  'womans_clothes': '👚',
+  'womans_hat': '👒',
+  'women_wrestling': '🤼‍♀️',
+  'womens': '🚺',
+  'woozy': '🥴',
+  'world_map': '🗺',
+  'worried': '😟',
+  'wrench': '🔧',
+  'writing_hand': '✍',
+  'x': '❌',
+  'yarn': '🧶',
+  'yellow_heart': '💛',
+  'yemen': '🇾🇪',
+  'yen': '💴',
+  'yin_yang': '☯',
+  'yum': '😋',
+  'zambia': '🇿🇲',
+  'zany': '🤪',
+  'zap': '⚡',
+  'zebra': '🦓',
+  'zero': '0️⃣',
+  'zimbabwe': '🇿🇼',
+  'zipper_mouth_face': '🤐',
+  'zzz': '💤',
+};
diff --git a/pkgs/markdown/lib/src/line.dart b/pkgs/markdown/lib/src/line.dart
new file mode 100644
index 0000000..1ccd5da
--- /dev/null
+++ b/pkgs/markdown/lib/src/line.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'patterns.dart';
+
+/// A [Line] is a sequence of zero or more characters other than line feed
+/// (`U+000A`) or carriage return (`U+000D`), followed by a line ending or by
+/// the end of file.
+// See https://spec.commonmark.org/0.30/#line.
+class Line {
+  /// A sequence of zero or more characters other than the line ending.
+  final String content;
+
+  /// How many spaces of a tab that remains after part of it has been consumed.
+  // See: https://spec.commonmark.org/0.30/#example-6
+  // We cannot simply expand the `tabRemaining` to spaces, for example
+  //
+  // `>\t\tfoo`
+  //
+  // If we expand the 2 space width `tabRemaining` from blockquote block into 2
+  // spaces, so the string segment for the indented code block is:
+  //
+  // `  \tfoo`,
+  //
+  // then the output will be:
+  // ```html
+  // <pre><code>foo
+  // </code></pre>
+  // ```
+  // instead of the expected:
+  // ```html
+  // <pre><code>  foo
+  // </code></pre>
+  // ```
+  final int? tabRemaining;
+
+  // A line containing no characters, or a line containing only spaces
+  // (`U+0020`) or tabs (`U+0009`), is called a blank line.
+  // https://spec.commonmark.org/0.30/#blank-line
+  final bool isBlankLine;
+
+  Line(
+    this.content, {
+    this.tabRemaining,
+  }) : isBlankLine = emptyPattern.hasMatch(content);
+}
diff --git a/pkgs/markdown/lib/src/link_parser.dart b/pkgs/markdown/lib/src/link_parser.dart
new file mode 100644
index 0000000..4db22ad
--- /dev/null
+++ b/pkgs/markdown/lib/src/link_parser.dart
@@ -0,0 +1,270 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'charcode.dart';
+import 'text_parser.dart';
+import 'util.dart';
+
+class LinkParser extends TextParser {
+  /// If there is a valid link formed.
+  bool get valid => _valid;
+  bool _valid = false;
+
+  /// Link label.
+  String? get label => _label;
+  String? _label;
+
+  /// Link destination.
+  String? get destination => _destination;
+  String? _destination;
+
+  /// Link title.
+  String? get title => _title;
+  String? _title;
+
+  LinkParser(super.source);
+
+  /// How many lines of the [source] have been consumed by link reference
+  /// definition.
+  int get unconsumedLines => _unconsumedLines;
+  int _unconsumedLines = 0;
+
+  /// Parses [source] to a link reference definition.
+  void parseDefinition() {
+    if (!parseLabel() || isDone || charAt() != $colon) {
+      return;
+    }
+
+    // Advance to the next character after the colon.
+    advance();
+    if (!_parseDestination()) {
+      return;
+    }
+
+    var precedingWhitespaces = moveThroughWhitespace();
+    if (isDone) {
+      _valid = true;
+      return;
+    }
+
+    final multiline = charAt() == $lf;
+    precedingWhitespaces += moveThroughWhitespace(multiLine: true);
+
+    // The title must be preceded by whitespaces.
+    if (precedingWhitespaces == 0 || isDone) {
+      _valid = isDone;
+      return;
+    }
+
+    final hasValidTitle = _parseTitle();
+    // For example: `[foo]: <bar> "baz` is a invalid definition, but this one is
+    // valid:
+    // ```
+    // [foo]: <bar>
+    // "baz
+    // ```
+    if (!hasValidTitle && !multiline) {
+      return;
+    }
+
+    if (hasValidTitle) {
+      moveThroughWhitespace();
+      if (!isDone && charAt() != $lf) {
+        // It is not a valid definition if the title is followed by
+        // non-whitespace characters, for example: `[foo]: <bar> "baz" hello`.
+        // See https://spec.commonmark.org/0.30/#example-209.
+        if (!multiline) {
+          return;
+        }
+        // But it is a valid link reference definition if this definition is
+        // multiline, see https://spec.commonmark.org/0.30/#example-210.
+        _title = null;
+      }
+    }
+
+    final linesUnconsumed = source.substring(pos).split('\n');
+    if (linesUnconsumed.isNotEmpty && linesUnconsumed.first.isBlank) {
+      linesUnconsumed.removeAt(0);
+    }
+    _unconsumedLines = linesUnconsumed.length;
+
+    _valid = true;
+  }
+
+  /// Parses the link label, returns `true` if there is a valid link label.
+  bool parseLabel() {
+    moveThroughWhitespace(multiLine: true);
+
+    if (length - pos < 2) {
+      return false;
+    }
+
+    if (charAt() != $lbracket) {
+      return false;
+    }
+
+    // Advance past the opening `[`.
+    advance();
+    final start = pos;
+
+    // A link label can have at most 999 characters inside the square brackets.
+    // See https://spec.commonmark.org/0.30/#link-label.
+    var maxLoop = 999;
+    while (true) {
+      if (maxLoop-- < 0) {
+        return false;
+      }
+      final char = charAt(pos);
+      if (char == $backslash) {
+        advance();
+      } else if (char == $lbracket) {
+        return false;
+      } else if (char == $rbracket) {
+        break;
+      }
+      advance();
+      if (isDone) {
+        return false;
+      }
+    }
+
+    final text = substring(start, pos);
+    if (text.isBlank) {
+      return false;
+    }
+
+    // Advance past the closing `]`.
+    advance();
+    _label = text;
+    return true;
+  }
+
+  /// Parses the link destination, returns `true` there is a valid link
+  /// destination.
+  bool _parseDestination() {
+    moveThroughWhitespace(multiLine: true);
+    if (isDone) {
+      return false;
+    }
+
+    final isValidDestination = charAt() == $lt
+        ? _parseBracketedDestination()
+        : _parseBareDestination();
+
+    return isValidDestination;
+  }
+
+  /// Parses bracketed destinations (destinations wrapped in `<...>`). The
+  /// current position of the parser must be the first character of the
+  /// destination.
+  ///
+  /// Returns `true` if there is a valid link destination.
+  bool _parseBracketedDestination() {
+    // Walk past the opening `<`.
+    advance();
+
+    final start = pos;
+    while (true) {
+      final char = charAt();
+      if (char == $backslash) {
+        advance();
+      } else if (char == $lf || char == $cr || char == $ff) {
+        return false;
+      } else if (char == $gt) {
+        break;
+      }
+      advance();
+      if (isDone) {
+        return false;
+      }
+    }
+
+    _destination = substring(start, pos);
+
+    // Advance past the closing `>`.
+    advance();
+    return true;
+  }
+
+  /// Parse "bare" destinations (destinations _not_ wrapped in `<...>`). The
+  /// current position of the parser must be the first character of the
+  /// destination.
+  ///
+  /// Returns `true` if there is a valid link destination.
+  bool _parseBareDestination() {
+    var parenCount = 0;
+    final start = pos;
+
+    while (true) {
+      final char = charAt();
+      if (char == $backslash) {
+        advance();
+      } else if (char == $space || char == $lf || char == $cr || char == $ff) {
+        break;
+      } else if (char == $lparen) {
+        parenCount++;
+      } else if (char == $rparen) {
+        parenCount--;
+        if (parenCount == 0) {
+          advance();
+          break;
+        }
+      }
+      advance();
+
+      // There is no ending delimiter, so `isDone` also means it is at the end
+      // of a link destination.
+      if (isDone) {
+        break;
+      }
+    }
+
+    _destination = substring(start, pos);
+    return true;
+  }
+
+  /// Parses the **optional** link title, returns `true` if there is a valid
+  /// link title.
+  bool _parseTitle() {
+    // See: https://spec.commonmark.org/0.30/#link-title
+    // The whitespace should be followed by a title delimiter.
+    final delimiter = charAt();
+    if (delimiter != $apostrophe &&
+        delimiter != $quote &&
+        delimiter != $lparen) {
+      return false;
+    }
+
+    final closeDelimiter = delimiter == $lparen ? $rparen : delimiter;
+    advance();
+    if (isDone) {
+      return false;
+    }
+    final start = pos;
+
+    // Looking for an un-escaped closing delimiter.
+    while (true) {
+      final char = charAt();
+      if (char == $backslash) {
+        advance();
+      } else if (char == closeDelimiter) {
+        break;
+      }
+      advance();
+      if (isDone) {
+        return false;
+      }
+    }
+
+    if (isDone) {
+      return false;
+    }
+
+    _title = substring(start, pos);
+
+    // Advance past the closing delimiter.
+    advance();
+    return true;
+  }
+}
diff --git a/pkgs/markdown/lib/src/patterns.dart b/pkgs/markdown/lib/src/patterns.dart
new file mode 100644
index 0000000..2690419
--- /dev/null
+++ b/pkgs/markdown/lib/src/patterns.dart
@@ -0,0 +1,162 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+/// The line contains only whitespace or is empty.
+final emptyPattern = RegExp(r'^(?:[ \t]*)$');
+
+/// A series of `=` or `-` (on the next line) define setext-style headers.
+final setextPattern = RegExp(r'^[ ]{0,3}(=+|-+)\s*$');
+
+/// Leading (and trailing) `#` define atx-style headers.
+///
+/// Starts with 1-6 unescaped `#` characters which must not be followed by a
+/// non-space character. Line may end with any number of `#` characters,.
+final headerPattern =
+    RegExp(r'^ {0,3}(#{1,6})(?:[ \x09\x0b\x0c].*?)?(?:\s(#*)\s*)?$');
+
+/// The line starts with `>` with one optional space after.
+final blockquotePattern = RegExp(r'^[ ]{0,3}>[ \t]?.*$');
+
+/// A line indented four spaces. Used for code blocks and lists.
+final indentPattern = RegExp(r'^(?:    | {0,3}\t)(.*)$');
+
+/// Fenced code block.
+final codeFencePattern = RegExp(
+  '^([ ]{0,3})(?:(?<backtick>`{3,})(?<backtickInfo>[^`]*)|'
+  r'(?<tilde>~{3,})(?<tildeInfo>.*))$',
+);
+
+/// Fenced blockquotes.
+final blockquoteFencePattern = RegExp(r'^>{3}\s*$');
+
+/// 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,
+/// SETEXT should win.
+final hrPattern = RegExp(r'^ {0,3}([-*_])[ \t]*\1[ \t]*\1(?:\1|[ \t])*$');
+
+/// **Unordered list**
+/// A line starting with one of these markers: `-`, `*`, `+`. May have up to
+/// three leading spaces before the marker and any number of spaces or tabs
+/// after.
+///
+/// **Ordered list**
+///
+/// A line starting with a number like `123.`. May have up to three leading
+/// spaces before the marker and any number of spaces or tabs after.
+final listPattern =
+    RegExp(r'^[ ]{0,3}(?:(\d{1,9})[\.)]|[*+-])(?:[ \t]+(.*))?$');
+
+/// A line of hyphens separated by at least one pipe.
+final tablePattern = RegExp(
+    r'^[ ]{0,3}\|?([ \t]*:?\-+:?[ \t]*\|[ \t]*)+([ \t]|[ \t]*:?\-+:?[ \t]*)?$');
+
+/// A line starting with `[^` and contains with `]:`, but without special chars
+/// (`\] \r\n\x00\t`) between. Same as [GFM](cmark-gfm/src/scanners.re:318).
+final footnotePattern = RegExp(r'(^[ ]{0,3})\[\^([^\] \r\n\x00\t]+)\]:[ \t]*');
+
+/// A pattern which should never be used. It just satisfies non-nullability of
+/// pattern fields.
+final dummyPattern = RegExp('');
+
+/// A [String] pattern to match a named tag like `<table>` or `</table>`.
+const namedTagDefinition =
+    // Opening tag begins.
+    '<'
+
+    // Tag name.
+    '[a-z][a-z0-9-]*'
+
+    // Attribute begins, see
+    // https://spec.commonmark.org/0.30/#attribute.
+    r'(?:\s+'
+
+    // Attribute name, see
+    // https://spec.commonmark.org/0.30/#attribute-name.
+    '[a-z_:][a-z0-9._:-]*'
+
+    //
+    '(?:'
+    // Attribute value specification, see
+    // https://spec.commonmark.org/0.30/#attribute-value-specification.
+    r'\s*=\s*'
+
+    // Attribute value, see
+    // https://spec.commonmark.org/0.30/#unquoted-attribute-value.
+    r'''(?:[^\s"'=<>`]+?|'[^']*?'|"[^"]*?")'''
+
+    // Attribute ends.
+    ')?)*'
+
+    // Opening tag ends.
+    r'\s*/?>'
+
+    // Or
+    '|'
+
+    // Closing tag, see
+    // https://spec.commonmark.org/0.30/#closing-tag.
+    r'</[a-z][a-z0-9-]*\s*>';
+
+/// A pattern to match the start of an HTML block.
+///
+/// The 7 conditions here correspond to the 7 start conditions in the Commonmark
+/// specification one by one: https://spec.commonmark.org/0.30/#html-block.
+final htmlBlockPattern = RegExp(
+  '^ {0,3}(?:'
+  '<(?<condition_1>pre|script|style|textarea)'
+  r'(?:\s|>|$)'
+  '|'
+  '(?<condition_2><!--)'
+  '|'
+  r'(?<condition_3><\?)'
+  '|'
+  '(?<condition_4><![a-z])'
+  '|'
+  r'(?<condition_5><!\[CDATA\[)'
+  '|'
+  '</?(?<condition_6>address|article|aside|base|basefont|blockquote|body|'
+  'caption|center|col|colgroup|dd|details|dialog|dir|DIV|dl|dt|fieldset|'
+  'figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|'
+  'header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|'
+  'optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|'
+  'thead|title|tr|track|ul)'
+  r'(?:\s|>|/>|$)'
+  '|'
+
+  // Here we are more restrictive than the Commonmark definition (Rule #7).
+  // Otherwise some raw HTML test cases will fail, for example:
+  // https://spec.commonmark.org/0.30/#example-618.
+  // Because if a line is treated as an HTML block, it will output as a
+  // Text node directly, and the RawHtmlSyntax will not have a chance to
+  // validate if this HTML tag is legal or not.
+  '(?<condition_7>(?:$namedTagDefinition)\\s*\$))',
+  caseSensitive: false,
+);
+
+/// ASCII punctuation characters.
+// See https://spec.commonmark.org/0.30/#unicode-whitespace-character.
+const asciiPunctuationCharacters = r'''!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~''';
+
+/// ASCII punctuation characters with some characters escaped, in order to be
+// used in the RegExp character set.
+const asciiPunctuationEscaped = r'''!"#$%&'()*+,\-./:;<=>?@\[\\\]^_`{|}~''';
+
+/// A pattern to match HTML entity references and numeric character references.
+// https://spec.commonmark.org/0.30/#entity-and-numeric-character-references
+final htmlCharactersPattern = RegExp(
+  '&(?:([a-z0-9]+)|#([0-9]{1,7})|#x([a-f0-9]{1,6}));',
+  caseSensitive: false,
+);
+
+/// A line starts with `[`.
+final linkReferenceDefinitionPattern = RegExp(r'^[ ]{0,3}\[');
+
+/// Alert type patterns.
+///
+/// A alert block is similar to a blockquote, starts with `> [!TYPE]`, and only
+/// 5 types are supported (case-insensitive).
+final alertPattern = RegExp(
+  r'^\s{0,3}>\s{0,3}\\?\[!(note|tip|important|caution|warning)\\?\]\s*$',
+  caseSensitive: false,
+);
diff --git a/pkgs/markdown/lib/src/text_parser.dart b/pkgs/markdown/lib/src/text_parser.dart
new file mode 100644
index 0000000..2f696de
--- /dev/null
+++ b/pkgs/markdown/lib/src/text_parser.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+import 'charcode.dart';
+
+/// A parser to parse a segment of source text.
+class TextParser {
+  final String source;
+
+  TextParser(this.source);
+
+  /// The current read position.
+  var _position = 0;
+  int get pos => _position;
+
+  /// Whether the read position has reached the end of [source].
+  bool get isDone => _position == length;
+
+  /// The length of [source].
+  int get length => source.length;
+
+  /// Walk the parser forward through any whitespace.
+  ///
+  /// Set [multiLine] `true` to support multiline, otherwise it will stop before
+  /// the line feed [$lf].
+  int moveThroughWhitespace({bool multiLine = false}) {
+    var i = 0;
+    while (!isDone) {
+      final char = charAt();
+      if (char != $space &&
+          char != $tab &&
+          char != $vt &&
+          char != $cr &&
+          char != $ff &&
+          !(multiLine && char == $lf)) {
+        return i;
+      }
+
+      i++;
+      advance();
+    }
+    return i;
+  }
+
+  int charAt([int? position]) => source.codeUnitAt(position ?? _position);
+
+  /// Moves the read position one character ahead.
+  void advance() => advanceBy(1);
+
+  /// Moves the read position for [length] characters. [length] can be negative.
+  void advanceBy(int length) {
+    _position += length;
+  }
+
+  /// Substrings the [source] and returns a [String].
+  String substring(int start, [int? end]) => source.substring(start, end);
+}
diff --git a/pkgs/markdown/lib/src/util.dart b/pkgs/markdown/lib/src/util.dart
new file mode 100644
index 0000000..93ea1e6
--- /dev/null
+++ b/pkgs/markdown/lib/src/util.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+
+import 'assets/case_folding.dart';
+import 'assets/html_entities.dart';
+import 'charcode.dart';
+import 'line.dart';
+import 'patterns.dart';
+
+/// One or more whitespace, for compressing.
+final _oneOrMoreWhitespacePattern = RegExp('[ \n\r\t]+');
+
+/// Escapes (`"`), (`<`), (`>`) and (`&`) characters.
+/// Escapes (`'`) if [escapeApos] is `true`.
+String escapeHtml(String html, {bool escapeApos = true}) =>
+    HtmlEscape(HtmlEscapeMode(
+      escapeApos: escapeApos,
+      escapeLtGt: true,
+      escapeQuot: true,
+    )).convert(html);
+
+/// Escapes (`"`), (`<`) and (`>`) characters.
+String escapeHtmlAttribute(String text) =>
+    const HtmlEscape(HtmlEscapeMode.attribute).convert(text);
+
+/// "Normalizes" a link label, according to the [CommonMark spec].
+///
+/// [CommonMark spec] https://spec.commonmark.org/0.30/#link-label
+String normalizeLinkLabel(String label) {
+  var text = label.trim().replaceAll(_oneOrMoreWhitespacePattern, ' ');
+  for (var i = 0; i < text.length; i++) {
+    final mapped = caseFoldingMap[text[i]];
+    if (mapped != null) {
+      text = text.replaceRange(i, i + 1, mapped);
+    }
+  }
+  return text;
+}
+
+/// Normalizes a link destination, including the process of HTML characters
+/// decoding and percent encoding.
+// See the description of these examples:
+// https://spec.commonmark.org/0.30/#example-501
+// https://spec.commonmark.org/0.30/#example-502
+String normalizeLinkDestination(String destination) {
+  // Split by url escaping characters
+  // Concatenate them with unmodified URL-escaping.
+  // URL-escaping should be left alone inside the destination
+  // Refer: https://spec.commonmark.org/0.30/#example-502.
+
+  final regex = RegExp('%[0-9A-Fa-f]{2}');
+
+  return destination.splitMapJoin(
+    regex,
+    onMatch: (m) => m.match,
+    onNonMatch: (e) {
+      try {
+        e = Uri.decodeFull(e);
+      } catch (_) {}
+      return Uri.encodeFull(decodeHtmlCharacters(e));
+    },
+  );
+}
+
+/// Normalizes a link title, including the process of HTML characters decoding
+/// and HTML characters escaping.
+// See the description of these examples:
+// https://spec.commonmark.org/0.30/#example-505
+// https://spec.commonmark.org/0.30/#example-506
+// https://spec.commonmark.org/0.30/#example-507
+// https://spec.commonmark.org/0.30/#example-508
+String normalizeLinkTitle(String title) =>
+    escapeHtmlAttribute(decodeHtmlCharacters(title));
+
+///  Decodes HTML entity and numeric character references, for example decode
+/// `&#35` to `#`.
+String decodeHtmlCharacters(String input) =>
+    input.replaceAllMapped(htmlCharactersPattern, decodeHtmlCharacterFromMatch);
+
+/// Decodes HTML entity and numeric character references from the given [match].
+String decodeHtmlCharacterFromMatch(Match match) {
+  final text = match.match;
+  final entity = match[1];
+  final decimalNumber = match[2];
+  final hexadecimalNumber = match[3];
+
+  // Entity references, see
+  // https://spec.commonmark.org/0.30/#entity-references.
+  if (entity != null) {
+    return htmlEntitiesMap[text] ?? text;
+  }
+
+  // Decimal numeric character references, see
+  // https://spec.commonmark.org/0.30/#decimal-numeric-character-references.
+  else if (decimalNumber != null) {
+    final decimalValue = int.parse(decimalNumber);
+    int hexValue;
+    if (decimalValue < 1114112 && decimalValue > 1) {
+      hexValue = int.parse(decimalValue.toRadixString(16), radix: 16);
+    } else {
+      hexValue = 0xFFFd;
+    }
+
+    return String.fromCharCode(hexValue);
+  }
+
+  // Hexadecimal numeric character references, see
+  // https://spec.commonmark.org/0.30/#hexadecimal-numeric-character-references.
+  else if (hexadecimalNumber != null) {
+    var hexValue = int.parse(hexadecimalNumber, radix: 16);
+    if (hexValue > 0x10ffff || hexValue == 0) {
+      hexValue = 0xFFFd;
+    }
+    return String.fromCharCode(hexValue);
+  }
+
+  return text;
+}
+
+extension MatchExtensions on Match {
+  /// Returns the whole match String
+  String get match => this[0]!;
+}
+
+/// Escapes the ASCII punctuation characters after backslash(`\`).
+String escapePunctuation(String input) {
+  final buffer = StringBuffer();
+
+  for (var i = 0; i < input.length; i++) {
+    if (input.codeUnitAt(i) == $backslash) {
+      final next = i + 1 < input.length ? input[i + 1] : null;
+      if (next != null && asciiPunctuationCharacters.contains(next)) {
+        i++;
+      }
+    }
+    buffer.write(input[i]);
+  }
+
+  return buffer.toString();
+}
+
+extension StringExtensions on String {
+  /// Calculates the length of indentation a `String` has.
+  ///
+  // The behavior of tabs: https://spec.commonmark.org/0.30/#tabs
+  int indentation() {
+    var length = 0;
+    for (final char in codeUnits) {
+      if (char != $space && char != $tab) {
+        break;
+      }
+      length += char == $tab ? 4 - (length % 4) : 1;
+    }
+    return length;
+  }
+
+  /// Removes up to [length] characters of leading whitespace.
+  // The way of handling tabs: https://spec.commonmark.org/0.30/#tabs
+  DedentedText dedent([int length = 4]) {
+    final whitespaceMatch = RegExp('^[ \t]{0,$length}').firstMatch(this);
+    const tabSize = 4;
+
+    int? tabRemaining;
+    var start = 0;
+    final whitespaces = whitespaceMatch?[0];
+    if (whitespaces != null) {
+      var indentLength = 0;
+      for (; start < whitespaces.length; start++) {
+        final isTab = whitespaces[start] == '\t';
+        if (isTab) {
+          indentLength += tabSize;
+          tabRemaining = 4;
+        } else {
+          indentLength += 1;
+        }
+        if (indentLength >= length) {
+          if (tabRemaining != null) {
+            tabRemaining = indentLength - length;
+          }
+          if (indentLength == length || isTab) {
+            start += 1;
+          }
+          break;
+        }
+        if (tabRemaining != null) {
+          tabRemaining = 0;
+        }
+      }
+    }
+    return DedentedText(substring(start), tabRemaining);
+  }
+
+  /// Adds [width] of spaces to the beginning of this string.
+  String prependSpace(int width) => '${" " * width}$this';
+
+  /// Whether this string contains only whitespaces.
+  bool get isBlank => trim().isEmpty;
+
+  /// Converts this string to a list of [Line].
+  List<Line> toLines() => LineSplitter.split(this).map(Line.new).toList();
+
+  /// Returns the last character.
+  String last([int n = 1]) => substring(length - n);
+}
+
+/// A class that describes a dedented text.
+class DedentedText {
+  /// The dedented text.
+  final String text;
+
+  /// How many spaces of a tab that remains after part of it has been consumed.
+  ///
+  /// `null` means we did not read a `tab`.
+  final int? tabRemaining;
+
+  DedentedText(this.text, this.tabRemaining);
+}
diff --git a/pkgs/markdown/lib/src/version.dart b/pkgs/markdown/lib/src/version.dart
new file mode 100644
index 0000000..1e5327e
--- /dev/null
+++ b/pkgs/markdown/lib/src/version.dart
@@ -0,0 +1,2 @@
+// Generated code. Do not modify.
+const packageVersion = '7.3.0';
diff --git a/pkgs/markdown/pubspec.yaml b/pkgs/markdown/pubspec.yaml
new file mode 100644
index 0000000..fadd44f
--- /dev/null
+++ b/pkgs/markdown/pubspec.yaml
@@ -0,0 +1,34 @@
+name: markdown
+version: 7.3.0
+description: >-
+  A portable Markdown library written in Dart that can parse Markdown into HTML.
+repository: https://github.com/dart-lang/tools/tree/main/pkgs/markdown
+
+topics:
+ - markdown
+
+executables:
+  markdown:
+
+environment:
+  sdk: ^3.2.0
+
+dependencies:
+  args: ^2.0.0
+  meta: ^1.3.0
+
+dev_dependencies:
+  build_runner: ^2.0.5
+  build_version: ^2.0.3
+  build_web_compilers: ^4.0.0
+  collection: ^1.15.0
+  dart_flutter_team_lints: ^3.0.0
+  html: ^0.15.0
+  http: ^1.0.0
+  io: ^1.0.0
+  path: ^1.8.0
+  pool: ^1.5.1
+  tar: ^1.0.3
+  test: ^1.16.0
+  web: '>=0.4.2 <2.0.0'
+  yaml: ^3.0.0
diff --git a/pkgs/markdown/test/blns.dart b/pkgs/markdown/test/blns.dart
new file mode 100644
index 0000000..4f06115
--- /dev/null
+++ b/pkgs/markdown/test/blns.dart
@@ -0,0 +1,526 @@
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from big-list-of-naughty-strings's JSON file:
+// https://github.com/minimaxir/big-list-of-naughty-strings/raw/master/blns.json
+// at 2023-08-26 16:34:37.127975 by the script, tool/update_blns.dart.
+
+// ignore_for_file: text_direction_code_point_in_literal, use_raw_strings
+// ignore_for_file: lines_longer_than_80_chars
+
+const blns = <String>[
+  '',
+  'undefined',
+  'undef',
+  'null',
+  'NULL',
+  '(null)',
+  'nil',
+  'NIL',
+  'true',
+  'false',
+  'True',
+  'False',
+  'TRUE',
+  'FALSE',
+  'None',
+  'hasOwnProperty',
+  'then',
+  '\\',
+  '\\\\',
+  '0',
+  '1',
+  '1.00',
+  '\$1.00',
+  '1/2',
+  '1E2',
+  '1E02',
+  '1E+02',
+  '-1',
+  '-1.00',
+  '-\$1.00',
+  '-1/2',
+  '-1E2',
+  '-1E02',
+  '-1E+02',
+  '1/0',
+  '0/0',
+  '-2147483648/-1',
+  '-9223372036854775808/-1',
+  '-0',
+  '-0.0',
+  '+0',
+  '+0.0',
+  '0.00',
+  '0..0',
+  '.',
+  '0.0.0',
+  '0,00',
+  '0,,0',
+  ',',
+  '0,0,0',
+  '0.0/0',
+  '1.0/0.0',
+  '0.0/0.0',
+  '1,0/0,0',
+  '0,0/0,0',
+  '--1',
+  '-',
+  '-.',
+  '-,',
+  '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999',
+  'NaN',
+  'Infinity',
+  '-Infinity',
+  'INF',
+  '1#INF',
+  '-1#IND',
+  '1#QNAN',
+  '1#SNAN',
+  '1#IND',
+  '0x0',
+  '0xffffffff',
+  '0xffffffffffffffff',
+  '0xabad1dea',
+  '123456789012345678901234567890123456789',
+  '1,000.00',
+  '1 000.00',
+  '1\'000.00',
+  '1,000,000.00',
+  '1 000 000.00',
+  '1\'000\'000.00',
+  '1.000,00',
+  '1 000,00',
+  '1\'000,00',
+  '1.000.000,00',
+  '1 000 000,00',
+  '1\'000\'000,00',
+  '01000',
+  '08',
+  '09',
+  '2.2250738585072011e-308',
+  ',./;\'[]\\-=',
+  '<>?:"{}|_+',
+  '!@#\$%^&*()`~',
+  '',
+  '€‚ƒ„†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ',
+  '	 …             ​

   ',
+  '­؀؁؂؃؄؅؜۝܏᠎​‌‍‎‏‪‫‬‭‮⁠⁡⁢⁣⁤⁦⁧⁨⁩𑂽𛲠𛲡𛲢𛲣𝅳𝅴𝅵𝅶𝅷𝅸𝅹𝅺󠀁󠀠󠀡󠀢󠀣󠀤󠀥󠀦󠀧󠀨󠀩󠀪󠀫󠀬󠀭󠀮󠀯󠀰󠀱󠀲󠀳󠀴󠀵󠀶󠀷󠀸󠀹󠀺󠀻󠀼󠀽󠀾󠀿󠁀󠁁󠁂󠁃󠁄󠁅󠁆󠁇󠁈󠁉󠁊󠁋󠁌󠁍󠁎󠁏󠁐󠁑󠁒󠁓󠁔󠁕󠁖󠁗󠁘󠁙󠁚󠁛󠁜󠁝󠁞󠁟󠁠󠁡󠁢󠁣󠁤󠁥󠁦󠁧󠁨󠁩󠁪󠁫󠁬󠁭󠁮󠁯󠁰󠁱󠁲󠁳󠁴󠁵󠁶󠁷󠁸󠁹󠁺󠁻󠁼󠁽󠁾󠁿',
+  '',
+  '￾',
+  'Ω≈ç√∫˜µ≤≥÷',
+  'åß∂ƒ©˙∆˚¬…æ',
+  'œ∑´®†¥¨ˆøπ“‘',
+  '¡™£¢∞§¶•ªº–≠',
+  '¸˛Ç◊ı˜Â¯˘¿',
+  'ÅÍÎÏ˝ÓÔÒÚÆ☃',
+  'Œ„´‰ˇÁ¨ˆØ∏”’',
+  '`⁄€‹›fifl‡°·‚—±',
+  '⅛⅜⅝⅞',
+  'ЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя',
+  '٠١٢٣٤٥٦٧٨٩',
+  '⁰⁴⁵',
+  '₀₁₂',
+  '⁰⁴⁵₀₁₂',
+  'ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็ ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็ ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็',
+  '\'',
+  '"',
+  '\'\'',
+  '""',
+  '\'"\'',
+  '"\'\'\'\'"\'"',
+  '"\'"\'"\'\'\'\'"',
+  '<foo val=“bar” />',
+  '<foo val=“bar” />',
+  '<foo val=”bar“ />',
+  '<foo val=`bar\' />',
+  '田中さんにあげて下さい',
+  'パーティーへ行かないか',
+  '和製漢語',
+  '部落格',
+  '사회과학원 어학연구소',
+  '찦차를 타고 온 펲시맨과 쑛다리 똠방각하',
+  '社會科學院語學研究所',
+  '울란바토르',
+  '𠜎𠜱𠝹𠱓𠱸𠲖𠳏',
+  '𐐜 𐐔𐐇𐐝𐐀𐐡𐐇𐐓 𐐙𐐊𐐡𐐝𐐓/𐐝𐐇𐐗𐐊𐐤𐐔 𐐒𐐋𐐗 𐐒𐐌 𐐜 𐐡𐐀𐐖𐐇𐐤𐐓𐐝 𐐱𐑂 𐑄 𐐔𐐇𐐝𐐀𐐡𐐇𐐓 𐐏𐐆𐐅𐐤𐐆𐐚𐐊𐐡𐐝𐐆𐐓𐐆',
+  '表ポあA鷗ŒéB逍Üߪąñ丂㐀𠀀',
+  'Ⱥ',
+  'Ⱦ',
+  'ヽ༼ຈل͜ຈ༽ノ ヽ༼ຈل͜ຈ༽ノ',
+  '(。◕ ∀ ◕。)',
+  '`ィ(´∀`∩',
+  '__ロ(,_,*)',
+  '・( ̄∀ ̄)・:*:',
+  '゚・✿ヾ╲(。◕‿◕。)╱✿・゚',
+  ',。・:*:・゜’( ☻ ω ☻ )。・:*:・゜’',
+  '(╯°□°)╯︵ ┻━┻)',
+  '(ノಥ益ಥ)ノ ┻━┻',
+  '┬─┬ノ( º _ ºノ)',
+  '( ͡° ͜ʖ ͡°)',
+  '¯\\_(ツ)_/¯',
+  '😍',
+  '👩🏽',
+  '👨‍🦰 👨🏿‍🦰 👨‍🦱 👨🏿‍🦱 🦹🏿‍♂️',
+  '👾 🙇 💁 🙅 🙆 🙋 🙎 🙍',
+  '🐵 🙈 🙉 🙊',
+  '❤️ 💔 💌 💕 💞 💓 💗 💖 💘 💝 💟 💜 💛 💚 💙',
+  '✋🏿 💪🏿 👐🏿 🙌🏿 👏🏿 🙏🏿',
+  '👨‍👩‍👦 👨‍👩‍👧‍👦 👨‍👨‍👦 👩‍👩‍👧 👨‍👦 👨‍👧‍👦 👩‍👦 👩‍👧‍👦',
+  '🚾 🆒 🆓 🆕 🆖 🆗 🆙 🏧',
+  '0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟',
+  '🇺🇸🇷🇺🇸 🇦🇫🇦🇲🇸',
+  '🇺🇸🇷🇺🇸🇦🇫🇦🇲',
+  '🇺🇸🇷🇺🇸🇦',
+  '123',
+  '١٢٣',
+  'ثم نفس سقطت وبالتحديد،, جزيرتي باستخدام أن دنو. إذ هنا؟ الستار وتنصيب كان. أهّل ايطاليا، بريطانيا-فرنسا قد أخذ. سليمان، إتفاقية بين ما, يذكر الحدود أي بعد, معاملة بولندا، الإطلاق عل إيو.',
+  'בְּרֵאשִׁית, בָּרָא אֱלֹהִים, אֵת הַשָּׁמַיִם, וְאֵת הָאָרֶץ',
+  'הָיְתָהtestالصفحات التّحول',
+  '﷽',
+  'ﷺ',
+  'مُنَاقَشَةُ سُبُلِ اِسْتِخْدَامِ اللُّغَةِ فِي النُّظُمِ الْقَائِمَةِ وَفِيم يَخُصَّ التَّطْبِيقَاتُ الْحاسُوبِيَّةُ، ',
+  '᚛ᚄᚓᚐᚋᚒᚄ ᚑᚄᚂᚑᚏᚅ᚜‪‪‪',
+  '‪‪᚛                 ᚜‪',
+  '‪‪test‪',
+  '‫test‫',
+  '
test
',
+  'test⁠test‫',
+  '⁦test⁧',
+  'Ṱ̺̺̕o͞ ̷i̲̬͇̪͙n̝̗͕v̟̜̘̦͟o̶̙̰̠kè͚̮̺̪̹̱̤ ̖t̝͕̳̣̻̪͞h̼͓̲̦̳̘̲e͇̣̰̦̬͎ ̢̼̻̱̘h͚͎͙̜̣̲ͅi̦̲̣̰̤v̻͍e̺̭̳̪̰-m̢iͅn̖̺̞̲̯̰d̵̼̟͙̩̼̘̳ ̞̥̱̳̭r̛̗̘e͙p͠r̼̞̻̭̗e̺̠̣͟s̘͇̳͍̝͉e͉̥̯̞̲͚̬͜ǹ̬͎͎̟̖͇̤t͍̬̤͓̼̭͘ͅi̪̱n͠g̴͉ ͏͉ͅc̬̟h͡a̫̻̯͘o̫̟̖͍̙̝͉s̗̦̲.̨̹͈̣',
+  '̡͓̞ͅI̗̘̦͝n͇͇͙v̮̫ok̲̫̙͈i̖͙̭̹̠̞n̡̻̮̣̺g̲͈͙̭͙̬͎ ̰t͔̦h̞̲e̢̤ ͍̬̲͖f̴̘͕̣è͖ẹ̥̩l͖͔͚i͓͚̦͠n͖͍̗͓̳̮g͍ ̨o͚̪͡f̘̣̬ ̖̘͖̟͙̮c҉͔̫͖͓͇͖ͅh̵̤̣͚͔á̗̼͕ͅo̼̣̥s̱͈̺̖̦̻͢.̛̖̞̠̫̰',
+  '̗̺͖̹̯͓Ṯ̤͍̥͇͈h̲́e͏͓̼̗̙̼̣͔ ͇̜̱̠͓͍ͅN͕͠e̗̱z̘̝̜̺͙p̤̺̹͍̯͚e̠̻̠͜r̨̤͍̺̖͔̖̖d̠̟̭̬̝͟i̦͖̩͓͔̤a̠̗̬͉̙n͚͜ ̻̞̰͚ͅh̵͉i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟',
+  '̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕',
+  'Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮',
+  '˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs \'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ \'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥',
+  '00˙Ɩ\$-',
+  'The quick brown fox jumps over the lazy dog',
+  '𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠',
+  '𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌',
+  '𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈',
+  '𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰',
+  '𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘',
+  '𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐',
+  '⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢',
+  '<script>alert(123)</script>',
+  '&lt;script&gt;alert(&#39;123&#39;);&lt;/script&gt;',
+  '<img src=x onerror=alert(123) />',
+  '<svg><script>123<1>alert(123)</script>',
+  '"><script>alert(123)</script>',
+  '\'><script>alert(123)</script>',
+  '><script>alert(123)</script>',
+  '</script><script>alert(123)</script>',
+  '< / script >< script >alert(123)< / script >',
+  ' onfocus=JaVaSCript:alert(123) autofocus',
+  '" onfocus=JaVaSCript:alert(123) autofocus',
+  '\' onfocus=JaVaSCript:alert(123) autofocus',
+  '<script>alert(123)</script>',
+  '<sc<script>ript>alert(123)</sc</script>ript>',
+  '--><script>alert(123)</script>',
+  '";alert(123);t="',
+  '\';alert(123);t=\'',
+  'JavaSCript:alert(123)',
+  ';alert(123);',
+  'src=JaVaSCript:prompt(132)',
+  '"><script>alert(123);</script x="',
+  '\'><script>alert(123);</script x=\'',
+  '><script>alert(123);</script x=',
+  '" autofocus onkeyup="javascript:alert(123)',
+  '\' autofocus onkeyup=\'javascript:alert(123)',
+  '<script\\x20type="text/javascript">javascript:alert(1);</script>',
+  '<script\\x3Etype="text/javascript">javascript:alert(1);</script>',
+  '<script\\x0Dtype="text/javascript">javascript:alert(1);</script>',
+  '<script\\x09type="text/javascript">javascript:alert(1);</script>',
+  '<script\\x0Ctype="text/javascript">javascript:alert(1);</script>',
+  '<script\\x2Ftype="text/javascript">javascript:alert(1);</script>',
+  '<script\\x0Atype="text/javascript">javascript:alert(1);</script>',
+  '\'`"><\\x3Cscript>javascript:alert(1)</script>',
+  '\'`"><\\x00script>javascript:alert(1)</script>',
+  'ABC<div style="x\\x3Aexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:expression\\x5C(javascript:alert(1)">DEF',
+  'ABC<div style="x:expression\\x00(javascript:alert(1)">DEF',
+  'ABC<div style="x:exp\\x00ression(javascript:alert(1)">DEF',
+  'ABC<div style="x:exp\\x5Cression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x0Aexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x09expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE3\\x80\\x80expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x84expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xC2\\xA0expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x80expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x0Dexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x0Cexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x87expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x20expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x88expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x00expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x86expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x85expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x82expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\x0Bexpression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x81expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x83expression(javascript:alert(1)">DEF',
+  'ABC<div style="x:\\xE2\\x80\\x89expression(javascript:alert(1)">DEF',
+  '<a href="\\x0Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x0Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xC2\\xA0javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x05javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x18javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x11javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x88javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x89javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x17javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x03javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x0Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x00javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x10javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x82javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x20javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x13javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x09javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x8Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x14javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x19javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\xAFjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x81javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x87javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x07javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE1\\x9A\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x83javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x04javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x01javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x08javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x84javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x86javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE3\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x12javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x0Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x0Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x0Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x15javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\xA8javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x16javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x02javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x06javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\xA9javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x80\\x85javascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\xE2\\x81\\x9Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="\\x1Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="javascript\\x00:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="javascript\\x3A:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="javascript\\x09:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="javascript\\x0D:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '<a href="javascript\\x0A:javascript:alert(1)" id="fuzzelement1">test</a>',
+  '`"\'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x22onerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x0Donerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x09onerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x0Conerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x00onerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x27onerror=javascript:alert(1)>',
+  '`"\'><img src=xxx:x \\x20onerror=javascript:alert(1)>',
+  '"`\'><script>\\x3Bjavascript:alert(1)</script>',
+  '"`\'><script>\\x0Djavascript:alert(1)</script>',
+  '"`\'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x81javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x84javascript:alert(1)</script>',
+  '"`\'><script>\\xE3\\x80\\x80javascript:alert(1)</script>',
+  '"`\'><script>\\x09javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x89javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x85javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x88javascript:alert(1)</script>',
+  '"`\'><script>\\x00javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>',
+  '"`\'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>',
+  '"`\'><script>\\x0Cjavascript:alert(1)</script>',
+  '"`\'><script>\\x2Bjavascript:alert(1)</script>',
+  '"`\'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>',
+  '"`\'><script>-javascript:alert(1)</script>',
+  '"`\'><script>\\x0Ajavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>',
+  '"`\'><script>\\x7Ejavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x87javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>',
+  '"`\'><script>\\xC2\\x85javascript:alert(1)</script>',
+  '"`\'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x83javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>',
+  '"`\'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x80javascript:alert(1)</script>',
+  '"`\'><script>\\x21javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x82javascript:alert(1)</script>',
+  '"`\'><script>\\xE2\\x80\\x86javascript:alert(1)</script>',
+  '"`\'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>',
+  '"`\'><script>\\x0Bjavascript:alert(1)</script>',
+  '"`\'><script>\\x20javascript:alert(1)</script>',
+  '"`\'><script>\\xC2\\xA0javascript:alert(1)</script>',
+  '<img \\x00src=x onerror="alert(1)">',
+  '<img \\x47src=x onerror="javascript:alert(1)">',
+  '<img \\x11src=x onerror="javascript:alert(1)">',
+  '<img \\x12src=x onerror="javascript:alert(1)">',
+  '<img\\x47src=x onerror="javascript:alert(1)">',
+  '<img\\x10src=x onerror="javascript:alert(1)">',
+  '<img\\x13src=x onerror="javascript:alert(1)">',
+  '<img\\x32src=x onerror="javascript:alert(1)">',
+  '<img\\x47src=x onerror="javascript:alert(1)">',
+  '<img\\x11src=x onerror="javascript:alert(1)">',
+  '<img \\x47src=x onerror="javascript:alert(1)">',
+  '<img \\x34src=x onerror="javascript:alert(1)">',
+  '<img \\x39src=x onerror="javascript:alert(1)">',
+  '<img \\x00src=x onerror="javascript:alert(1)">',
+  '<img src\\x09=x onerror="javascript:alert(1)">',
+  '<img src\\x10=x onerror="javascript:alert(1)">',
+  '<img src\\x13=x onerror="javascript:alert(1)">',
+  '<img src\\x32=x onerror="javascript:alert(1)">',
+  '<img src\\x12=x onerror="javascript:alert(1)">',
+  '<img src\\x11=x onerror="javascript:alert(1)">',
+  '<img src\\x00=x onerror="javascript:alert(1)">',
+  '<img src\\x47=x onerror="javascript:alert(1)">',
+  '<img src=x\\x09onerror="javascript:alert(1)">',
+  '<img src=x\\x10onerror="javascript:alert(1)">',
+  '<img src=x\\x11onerror="javascript:alert(1)">',
+  '<img src=x\\x12onerror="javascript:alert(1)">',
+  '<img src=x\\x13onerror="javascript:alert(1)">',
+  '<img[a][b][c]src[d]=x[e]onerror=[f]"alert(1)">',
+  '<img src=x onerror=\\x09"javascript:alert(1)">',
+  '<img src=x onerror=\\x10"javascript:alert(1)">',
+  '<img src=x onerror=\\x11"javascript:alert(1)">',
+  '<img src=x onerror=\\x12"javascript:alert(1)">',
+  '<img src=x onerror=\\x32"javascript:alert(1)">',
+  '<img src=x onerror=\\x00"javascript:alert(1)">',
+  '<a href=java&#1&#2&#3&#4&#5&#6&#7&#8&#11&#12script:javascript:alert(1)>XXX</a>',
+  '<img src="x` `<script>javascript:alert(1)</script>"` `>',
+  '<img src onerror /" \'"= alt=javascript:alert(1)//">',
+  '<title onpropertychange=javascript:alert(1)></title><title title=>',
+  '<a href=http://foo.bar/#x=`y></a><img alt="`><img src=x:x onerror=javascript:alert(1)></a>">',
+  '<!--[if]><script>javascript:alert(1)</script -->',
+  '<!--[if<img src=x onerror=javascript:alert(1)//]> -->',
+  '<script src="/\\%(jscript)s"></script>',
+  '<script src="\\\\%(jscript)s"></script>',
+  '<IMG """><SCRIPT>alert("XSS")</SCRIPT>">',
+  '<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>',
+  '<IMG SRC=# onmouseover="alert(\'xxs\')">',
+  '<IMG SRC= onmouseover="alert(\'xxs\')">',
+  '<IMG onmouseover="alert(\'xxs\')">',
+  '<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>',
+  '<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>',
+  '<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>',
+  '<IMG SRC="jav   ascript:alert(\'XSS\');">',
+  '<IMG SRC="jav&#x09;ascript:alert(\'XSS\');">',
+  '<IMG SRC="jav&#x0A;ascript:alert(\'XSS\');">',
+  '<IMG SRC="jav&#x0D;ascript:alert(\'XSS\');">',
+  'perl -e \'print "<IMG SRC=java\\0script:alert(\\"XSS\\")>";\' > out',
+  '<IMG SRC=" &#14;  javascript:alert(\'XSS\');">',
+  '<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+  '<BODY onload!#\$%&()*~+-_.,:;?@[/|\\]^`=alert("XSS")>',
+  '<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+  '<<SCRIPT>alert("XSS");//<</SCRIPT>',
+  '<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >',
+  '<SCRIPT SRC=//ha.ckers.org/.j>',
+  '<IMG SRC="javascript:alert(\'XSS\')"',
+  '<iframe src=http://ha.ckers.org/scriptlet.html <',
+  '\\";alert(\'XSS\');//',
+  '<u oncopy=alert()> Copy me</u>',
+  '<i onwheel=alert(1)> Scroll over me </i>',
+  '<plaintext>',
+  'http://a/%%30%30',
+  '</textarea><script>alert(123)</script>',
+  '1;DROP TABLE users',
+  '1\'; DROP TABLE users-- 1',
+  '\' OR 1=1 -- 1',
+  '\' OR \'1\'=\'1',
+  '\'; EXEC sp_MSForEachTable \'DROP TABLE ?\'; --',
+  ' ',
+  '%',
+  '_',
+  '-',
+  '--',
+  '--version',
+  '--help',
+  '\$USER',
+  '/dev/null; touch /tmp/blns.fail ; echo',
+  '`touch /tmp/blns.fail`',
+  '\$(touch /tmp/blns.fail)',
+  '@{[system "touch /tmp/blns.fail"]}',
+  'eval("puts \'hello world\'")',
+  'System("ls -al /")',
+  '`ls -al /`',
+  'Kernel.exec("ls -al /")',
+  'Kernel.exit(1)',
+  '%x(\'ls -al /\')',
+  '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>',
+  '\$HOME',
+  '\$ENV{\'HOME\'}',
+  '%d',
+  '%s%s%s%s%s',
+  '{0}',
+  '%*.*s',
+  '%@',
+  '%n',
+  'File:///',
+  '../../../../../../../../../../../etc/passwd%00',
+  '../../../../../../../../../../../etc/hosts',
+  '() { 0; }; touch /tmp/blns.shellshock1.fail;',
+  '() { _; } >_[\$(\$())] { touch /tmp/blns.shellshock2.fail; }',
+  '<<< %s(un=\'%s\') = %u',
+  '+++ATH0',
+  'CON',
+  'PRN',
+  'AUX',
+  'CLOCK\$',
+  'NUL',
+  'A:',
+  'ZZ:',
+  'COM1',
+  'LPT1',
+  'LPT2',
+  'LPT3',
+  'COM2',
+  'COM3',
+  'COM4',
+  'DCC SEND STARTKEYLOGGER 0 0 0',
+  'Scunthorpe General Hospital',
+  'Penistone Community Church',
+  'Lightwater Country Park',
+  'Jimmy Clitheroe',
+  'Horniman Museum',
+  'shitake mushrooms',
+  'RomansInSussex.co.uk',
+  'http://www.cum.qc.ca/',
+  'Craig Cockburn, Software Specialist',
+  'Linda Callahan',
+  'Dr. Herman I. Libshitz',
+  'magna cum laude',
+  'Super Bowl XXX',
+  'medieval erection of parapets',
+  'evaluate',
+  'mocha',
+  'expression',
+  'Arsenal canal',
+  'classic',
+  'Tyson Gay',
+  'Dick Van Dyke',
+  'basement',
+  'If you\'re reading this, you\'ve been in a coma for almost 20 years now. We\'re trying a new technique. We don\'t know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.',
+  'Roses are red, violets are blue. Hope you enjoy terminal hue',
+  'But now...for my greatest trick...',
+  'The quick brown fox... [Beeeep]',
+  'Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗',
+  '🏳0🌈️',
+  'జ్ఞ‌ా',
+  'گچپژ',
+  '{% print \'x\' * 64 * 1024**3 %}',
+  '{{ "".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read() }}',
+];
diff --git a/pkgs/markdown/test/blns_test.dart b/pkgs/markdown/test/blns_test.dart
new file mode 100644
index 0000000..69790ef
--- /dev/null
+++ b/pkgs/markdown/test/blns_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'package:markdown/markdown.dart';
+import 'package:test/test.dart';
+
+import 'blns.dart';
+
+// The BLNS tests merely test that `markdownToHtml` does not throw or hang while
+// processing "naughty string" inputs. While there are examples of multi-byte
+// characters, non-visible characters, etc., these tests should not be _relied
+// upon_ for testing multi-byte character support, etc.
+void main() {
+  test('parsing blns', () {
+    // This is more a test of update_blns.dart: we're testing that the strings
+    // were encoded half-decently, and nothing got globbed up into a big
+    // multiline string.
+    expect(blns, hasLength(515));
+  });
+
+  var index = 0;
+  for (final str in blns) {
+    test('blns string $index', () {
+      final result = markdownToHtml(str);
+      expect(result, const TypeMatcher<String>());
+    });
+    index++;
+  }
+
+  index = 0;
+  for (final str in blns) {
+    test('blns string $index w/ gitHubWeb', () {
+      final result = markdownToHtml(str, extensionSet: ExtensionSet.gitHubWeb);
+      expect(result, const TypeMatcher<String>());
+    });
+    index++;
+  }
+}
diff --git a/pkgs/markdown/test/common_mark/atx_headings.unit b/pkgs/markdown/test/common_mark/atx_headings.unit
new file mode 100644
index 0000000..1cb7e98
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/atx_headings.unit
@@ -0,0 +1,112 @@
+>>> ATX headings - 62
+# foo
+## foo
+### foo
+#### foo
+##### foo
+###### foo
+<<<
+<h1>foo</h1>
+<h2>foo</h2>
+<h3>foo</h3>
+<h4>foo</h4>
+<h5>foo</h5>
+<h6>foo</h6>
+>>> ATX headings - 63
+####### foo
+<<<
+<p>####### foo</p>
+>>> ATX headings - 64
+#5 bolt
+
+#hashtag
+<<<
+<p>#5 bolt</p>
+<p>#hashtag</p>
+>>> ATX headings - 65
+\## foo
+<<<
+<p>## foo</p>
+>>> ATX headings - 66
+# foo *bar* \*baz\*
+<<<
+<h1>foo <em>bar</em> *baz*</h1>
+>>> ATX headings - 67
+#                  foo                     
+<<<
+<h1>foo</h1>
+>>> ATX headings - 68
+ ### foo
+  ## foo
+   # foo
+<<<
+<h3>foo</h3>
+<h2>foo</h2>
+<h1>foo</h1>
+>>> ATX headings - 69
+    # foo
+<<<
+<pre><code># foo
+</code></pre>
+>>> ATX headings - 70
+foo
+    # bar
+<<<
+<p>foo
+# bar</p>
+>>> ATX headings - 71
+## foo ##
+  ###   bar    ###
+<<<
+<h2>foo</h2>
+<h3>bar</h3>
+>>> ATX headings - 72
+# foo ##################################
+##### foo ##
+<<<
+<h1>foo</h1>
+<h5>foo</h5>
+>>> ATX headings - 73
+### foo ###     
+<<<
+<h3>foo</h3>
+>>> ATX headings - 74
+### foo ### b
+<<<
+<h3>foo ### b</h3>
+>>> ATX headings - 75
+# foo#
+<<<
+<h1>foo#</h1>
+>>> ATX headings - 76
+### foo \###
+## foo #\##
+# foo \#
+<<<
+<h3>foo ###</h3>
+<h2>foo ###</h2>
+<h1>foo #</h1>
+>>> ATX headings - 77
+****
+## foo
+****
+<<<
+<hr />
+<h2>foo</h2>
+<hr />
+>>> ATX headings - 78
+Foo bar
+# baz
+Bar foo
+<<<
+<p>Foo bar</p>
+<h1>baz</h1>
+<p>Bar foo</p>
+>>> ATX headings - 79
+## 
+#
+### ###
+<<<
+<h2></h2>
+<h1></h1>
+<h3></h3>
diff --git a/pkgs/markdown/test/common_mark/autolinks.unit b/pkgs/markdown/test/common_mark/autolinks.unit
new file mode 100644
index 0000000..0bb319c
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/autolinks.unit
@@ -0,0 +1,76 @@
+>>> Autolinks - 594
+<http://foo.bar.baz>
+<<<
+<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
+>>> Autolinks - 595
+<https://foo.bar.baz/test?q=hello&id=22&boolean>
+<<<
+<p><a href="https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
+>>> Autolinks - 596
+<irc://foo.bar:2233/baz>
+<<<
+<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
+>>> Autolinks - 597
+<MAILTO:FOO@BAR.BAZ>
+<<<
+<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
+>>> Autolinks - 598
+<a+b+c:d>
+<<<
+<p><a href="a+b+c:d">a+b+c:d</a></p>
+>>> Autolinks - 599
+<made-up-scheme://foo,bar>
+<<<
+<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
+>>> Autolinks - 600
+<https://../>
+<<<
+<p><a href="https://../">https://../</a></p>
+>>> Autolinks - 601
+<localhost:5001/foo>
+<<<
+<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
+>>> Autolinks - 602
+<https://foo.bar/baz bim>
+<<<
+<p>&lt;https://foo.bar/baz bim&gt;</p>
+>>> Autolinks - 603
+<https://example.com/\[\>
+<<<
+<p><a href="https://example.com/%5C%5B%5C">https://example.com/\[\</a></p>
+>>> Autolinks - 604
+<foo@bar.example.com>
+<<<
+<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
+>>> Autolinks - 605
+<foo+special@Bar.baz-bar0.com>
+<<<
+<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
+>>> Autolinks - 606
+<foo\+@bar.example.com>
+<<<
+<p>&lt;foo+@bar.example.com&gt;</p>
+>>> Autolinks - 607
+<>
+<<<
+<p>&lt;&gt;</p>
+>>> Autolinks - 608
+< https://foo.bar >
+<<<
+<p>&lt; https://foo.bar &gt;</p>
+>>> Autolinks - 609
+<m:abc>
+<<<
+<p>&lt;m:abc&gt;</p>
+>>> Autolinks - 610
+<foo.bar.baz>
+<<<
+<p>&lt;foo.bar.baz&gt;</p>
+>>> Autolinks - 611
+https://example.com
+<<<
+<p>https://example.com</p>
+>>> Autolinks - 612
+foo@bar.example.com
+<<<
+<p>foo@bar.example.com</p>
diff --git a/pkgs/markdown/test/common_mark/backslash_escapes.unit b/pkgs/markdown/test/common_mark/backslash_escapes.unit
new file mode 100644
index 0000000..54766e4
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/backslash_escapes.unit
@@ -0,0 +1,79 @@
+>>> Backslash escapes - 12
+\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+<<<
+<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
+>>> Backslash escapes - 13
+\	\A\a\ \3\φ\«
+<<<
+<p>\	\A\a\ \3\φ\«</p>
+>>> Backslash escapes - 14
+\*not emphasized*
+\<br/> not a tag
+\[not a link](/foo)
+\`not code`
+1\. not a list
+\* not a list
+\# not a heading
+\[foo]: /url "not a reference"
+\&ouml; not a character entity
+<<<
+<p>*not emphasized*
+&lt;br/&gt; not a tag
+[not a link](/foo)
+`not code`
+1. not a list
+* not a list
+# not a heading
+[foo]: /url &quot;not a reference&quot;
+&amp;ouml; not a character entity</p>
+>>> Backslash escapes - 15
+\\*emphasis*
+<<<
+<p>\<em>emphasis</em></p>
+>>> Backslash escapes - 16
+foo\
+bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Backslash escapes - 17
+`` \[\` ``
+<<<
+<p><code>\[\`</code></p>
+>>> Backslash escapes - 18
+    \[\]
+<<<
+<pre><code>\[\]
+</code></pre>
+>>> Backslash escapes - 19
+~~~
+\[\]
+~~~
+<<<
+<pre><code>\[\]
+</code></pre>
+>>> Backslash escapes - 20
+<https://example.com?find=\*>
+<<<
+<p><a href="https://example.com?find=%5C*">https://example.com?find=\*</a></p>
+>>> Backslash escapes - 21
+<a href="/bar\/)">
+<<<
+<a href="/bar\/)">
+>>> Backslash escapes - 22
+[foo](/bar\* "ti\*tle")
+<<<
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+>>> Backslash escapes - 23
+[foo]
+
+[foo]: /bar\* "ti\*tle"
+<<<
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+>>> Backslash escapes - 24
+``` foo\+bar
+foo
+```
+<<<
+<pre><code class="language-foo+bar">foo
+</code></pre>
diff --git a/pkgs/markdown/test/common_mark/blank_lines.unit b/pkgs/markdown/test/common_mark/blank_lines.unit
new file mode 100644
index 0000000..86977bd
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/blank_lines.unit
@@ -0,0 +1,12 @@
+>>> Blank lines - 227
+  
+
+aaa
+  
+
+# aaa
+
+  
+<<<
+<p>aaa</p>
+<h1>aaa</h1>
diff --git a/pkgs/markdown/test/common_mark/block_quotes.unit b/pkgs/markdown/test/common_mark/block_quotes.unit
new file mode 100644
index 0000000..9931044
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/block_quotes.unit
@@ -0,0 +1,239 @@
+>>> Block quotes - 228
+> # Foo
+> bar
+> baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 229
+># Foo
+>bar
+> baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 230
+   > # Foo
+   > bar
+ > baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 231
+    > # Foo
+    > bar
+    > baz
+<<<
+<pre><code>&gt; # Foo
+&gt; bar
+&gt; baz
+</code></pre>
+>>> Block quotes - 232
+> # Foo
+> bar
+baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 233
+> bar
+baz
+> foo
+<<<
+<blockquote>
+<p>bar
+baz
+foo</p>
+</blockquote>
+>>> Block quotes - 234
+> foo
+---
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+>>> Block quotes - 235
+> - foo
+- bar
+<<<
+<blockquote>
+<ul>
+<li>foo</li>
+</ul>
+</blockquote>
+<ul>
+<li>bar</li>
+</ul>
+>>> Block quotes - 236
+>     foo
+    bar
+<<<
+<blockquote>
+<pre><code>foo
+</code></pre>
+</blockquote>
+<pre><code>bar
+</code></pre>
+>>> Block quotes - 237
+> ```
+foo
+```
+<<<
+<blockquote>
+<pre><code></code></pre>
+</blockquote>
+<p>foo</p>
+<pre><code></code></pre>
+>>> Block quotes - 238
+> foo
+    - bar
+<<<
+<blockquote>
+<p>foo
+- bar</p>
+</blockquote>
+>>> Block quotes - 239
+>
+<<<
+<blockquote>
+</blockquote>
+>>> Block quotes - 240
+>
+>  
+> 
+<<<
+<blockquote>
+</blockquote>
+>>> Block quotes - 241
+>
+> foo
+>  
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+>>> Block quotes - 242
+> foo
+
+> bar
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 243
+> foo
+> bar
+<<<
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+>>> Block quotes - 244
+> foo
+>
+> bar
+<<<
+<blockquote>
+<p>foo</p>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 245
+foo
+> bar
+<<<
+<p>foo</p>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 246
+> aaa
+***
+> bbb
+<<<
+<blockquote>
+<p>aaa</p>
+</blockquote>
+<hr />
+<blockquote>
+<p>bbb</p>
+</blockquote>
+>>> Block quotes - 247
+> bar
+baz
+<<<
+<blockquote>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 248
+> bar
+
+baz
+<<<
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+>>> Block quotes - 249
+> bar
+>
+baz
+<<<
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+>>> Block quotes - 250
+> > > foo
+bar
+<<<
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+</blockquote>
+</blockquote>
+>>> Block quotes - 251
+>>> foo
+> bar
+>>baz
+<<<
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar
+baz</p>
+</blockquote>
+</blockquote>
+</blockquote>
+>>> Block quotes - 252
+>     code
+
+>    not code
+<<<
+<blockquote>
+<pre><code>code
+</code></pre>
+</blockquote>
+<blockquote>
+<p>not code</p>
+</blockquote>
diff --git a/pkgs/markdown/test/common_mark/code_spans.unit b/pkgs/markdown/test/common_mark/code_spans.unit
new file mode 100644
index 0000000..5ff95dd
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/code_spans.unit
@@ -0,0 +1,97 @@
+>>> Code spans - 328
+`foo`
+<<<
+<p><code>foo</code></p>
+>>> Code spans - 329
+`` foo ` bar ``
+<<<
+<p><code>foo ` bar</code></p>
+>>> Code spans - 330
+` `` `
+<<<
+<p><code>``</code></p>
+>>> Code spans - 331
+`  ``  `
+<<<
+<p><code> `` </code></p>
+>>> Code spans - 332
+` a`
+<<<
+<p><code> a</code></p>
+>>> Code spans - 333
+` b `
+<<<
+<p><code> b </code></p>
+>>> Code spans - 334
+` `
+`  `
+<<<
+<p><code> </code>
+<code>  </code></p>
+>>> Code spans - 335
+``
+foo
+bar  
+baz
+``
+<<<
+<p><code>foo bar   baz</code></p>
+>>> Code spans - 336
+``
+foo 
+``
+<<<
+<p><code>foo </code></p>
+>>> Code spans - 337
+`foo   bar 
+baz`
+<<<
+<p><code>foo   bar  baz</code></p>
+>>> Code spans - 338
+`foo\`bar`
+<<<
+<p><code>foo\</code>bar`</p>
+>>> Code spans - 339
+``foo`bar``
+<<<
+<p><code>foo`bar</code></p>
+>>> Code spans - 340
+` foo `` bar `
+<<<
+<p><code>foo `` bar</code></p>
+>>> Code spans - 341
+*foo`*`
+<<<
+<p>*foo<code>*</code></p>
+>>> Code spans - 342
+[not a `link](/foo`)
+<<<
+<p>[not a <code>link](/foo</code>)</p>
+>>> Code spans - 343
+`<a href="`">`
+<<<
+<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
+>>> Code spans - 344
+<a href="`">`
+<<<
+<p><a href="`">`</p>
+>>> Code spans - 345
+`<https://foo.bar.`baz>`
+<<<
+<p><code>&lt;https://foo.bar.</code>baz&gt;`</p>
+>>> Code spans - 346
+<https://foo.bar.`baz>`
+<<<
+<p><a href="https://foo.bar.%60baz">https://foo.bar.`baz</a>`</p>
+>>> Code spans - 347
+```foo``
+<<<
+<p>```foo``</p>
+>>> Code spans - 348
+`foo
+<<<
+<p>`foo</p>
+>>> Code spans - 349
+`foo``bar``
+<<<
+<p>`foo<code>bar</code></p>
diff --git a/pkgs/markdown/test/common_mark/emphasis_and_strong_emphasis.unit b/pkgs/markdown/test/common_mark/emphasis_and_strong_emphasis.unit
new file mode 100644
index 0000000..6c8181d
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/emphasis_and_strong_emphasis.unit
@@ -0,0 +1,546 @@
+>>> Emphasis and strong emphasis - 350
+*foo bar*
+<<<
+<p><em>foo bar</em></p>
+>>> Emphasis and strong emphasis - 351
+a * foo bar*
+<<<
+<p>a * foo bar*</p>
+>>> Emphasis and strong emphasis - 352
+a*"foo"*
+<<<
+<p>a*&quot;foo&quot;*</p>
+>>> Emphasis and strong emphasis - 353
+* a *
+<<<
+<p>* a *</p>
+>>> Emphasis and strong emphasis - 354
+*$*alpha.
+
+*£*bravo.
+
+*€*charlie.
+<<<
+<p>*$*alpha.</p>
+<p><em>£</em>bravo.</p>
+<p><em>€</em>charlie.</p>
+>>> Emphasis and strong emphasis - 355
+foo*bar*
+<<<
+<p>foo<em>bar</em></p>
+>>> Emphasis and strong emphasis - 356
+5*6*78
+<<<
+<p>5<em>6</em>78</p>
+>>> Emphasis and strong emphasis - 357
+_foo bar_
+<<<
+<p><em>foo bar</em></p>
+>>> Emphasis and strong emphasis - 358
+_ foo bar_
+<<<
+<p>_ foo bar_</p>
+>>> Emphasis and strong emphasis - 359
+a_"foo"_
+<<<
+<p>a_&quot;foo&quot;_</p>
+>>> Emphasis and strong emphasis - 360
+foo_bar_
+<<<
+<p>foo_bar_</p>
+>>> Emphasis and strong emphasis - 361
+5_6_78
+<<<
+<p>5_6_78</p>
+>>> Emphasis and strong emphasis - 362
+пристаням_стремятся_
+<<<
+<p>пристаням_стремятся_</p>
+>>> Emphasis and strong emphasis - 363
+aa_"bb"_cc
+<<<
+<p>aa_&quot;bb&quot;_cc</p>
+>>> Emphasis and strong emphasis - 364
+foo-_(bar)_
+<<<
+<p>foo-<em>(bar)</em></p>
+>>> Emphasis and strong emphasis - 365
+_foo*
+<<<
+<p>_foo*</p>
+>>> Emphasis and strong emphasis - 366
+*foo bar *
+<<<
+<p>*foo bar *</p>
+>>> Emphasis and strong emphasis - 367
+*foo bar
+*
+<<<
+<p>*foo bar
+*</p>
+>>> Emphasis and strong emphasis - 368
+*(*foo)
+<<<
+<p>*(*foo)</p>
+>>> Emphasis and strong emphasis - 369
+*(*foo*)*
+<<<
+<p><em>(<em>foo</em>)</em></p>
+>>> Emphasis and strong emphasis - 370
+*foo*bar
+<<<
+<p><em>foo</em>bar</p>
+>>> Emphasis and strong emphasis - 371
+_foo bar _
+<<<
+<p>_foo bar _</p>
+>>> Emphasis and strong emphasis - 372
+_(_foo)
+<<<
+<p>_(_foo)</p>
+>>> Emphasis and strong emphasis - 373
+_(_foo_)_
+<<<
+<p><em>(<em>foo</em>)</em></p>
+>>> Emphasis and strong emphasis - 374
+_foo_bar
+<<<
+<p>_foo_bar</p>
+>>> Emphasis and strong emphasis - 375
+_пристаням_стремятся
+<<<
+<p>_пристаням_стремятся</p>
+>>> Emphasis and strong emphasis - 376
+_foo_bar_baz_
+<<<
+<p><em>foo_bar_baz</em></p>
+>>> Emphasis and strong emphasis - 377
+_(bar)_.
+<<<
+<p><em>(bar)</em>.</p>
+>>> Emphasis and strong emphasis - 378
+**foo bar**
+<<<
+<p><strong>foo bar</strong></p>
+>>> Emphasis and strong emphasis - 379
+** foo bar**
+<<<
+<p>** foo bar**</p>
+>>> Emphasis and strong emphasis - 380
+a**"foo"**
+<<<
+<p>a**&quot;foo&quot;**</p>
+>>> Emphasis and strong emphasis - 381
+foo**bar**
+<<<
+<p>foo<strong>bar</strong></p>
+>>> Emphasis and strong emphasis - 382
+__foo bar__
+<<<
+<p><strong>foo bar</strong></p>
+>>> Emphasis and strong emphasis - 383
+__ foo bar__
+<<<
+<p>__ foo bar__</p>
+>>> Emphasis and strong emphasis - 384
+__
+foo bar__
+<<<
+<p>__
+foo bar__</p>
+>>> Emphasis and strong emphasis - 385
+a__"foo"__
+<<<
+<p>a__&quot;foo&quot;__</p>
+>>> Emphasis and strong emphasis - 386
+foo__bar__
+<<<
+<p>foo__bar__</p>
+>>> Emphasis and strong emphasis - 387
+5__6__78
+<<<
+<p>5__6__78</p>
+>>> Emphasis and strong emphasis - 388
+пристаням__стремятся__
+<<<
+<p>пристаням__стремятся__</p>
+>>> Emphasis and strong emphasis - 389
+__foo, __bar__, baz__
+<<<
+<p><strong>foo, <strong>bar</strong>, baz</strong></p>
+>>> Emphasis and strong emphasis - 390
+foo-__(bar)__
+<<<
+<p>foo-<strong>(bar)</strong></p>
+>>> Emphasis and strong emphasis - 391
+**foo bar **
+<<<
+<p>**foo bar **</p>
+>>> Emphasis and strong emphasis - 392
+**(**foo)
+<<<
+<p>**(**foo)</p>
+>>> Emphasis and strong emphasis - 393
+*(**foo**)*
+<<<
+<p><em>(<strong>foo</strong>)</em></p>
+>>> Emphasis and strong emphasis - 394
+**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
+*Asclepias physocarpa*)**
+<<<
+<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
+<em>Asclepias physocarpa</em>)</strong></p>
+>>> Emphasis and strong emphasis - 395
+**foo "*bar*" foo**
+<<<
+<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
+>>> Emphasis and strong emphasis - 396
+**foo**bar
+<<<
+<p><strong>foo</strong>bar</p>
+>>> Emphasis and strong emphasis - 397
+__foo bar __
+<<<
+<p>__foo bar __</p>
+>>> Emphasis and strong emphasis - 398
+__(__foo)
+<<<
+<p>__(__foo)</p>
+>>> Emphasis and strong emphasis - 399
+_(__foo__)_
+<<<
+<p><em>(<strong>foo</strong>)</em></p>
+>>> Emphasis and strong emphasis - 400
+__foo__bar
+<<<
+<p>__foo__bar</p>
+>>> Emphasis and strong emphasis - 401
+__пристаням__стремятся
+<<<
+<p>__пристаням__стремятся</p>
+>>> Emphasis and strong emphasis - 402
+__foo__bar__baz__
+<<<
+<p><strong>foo__bar__baz</strong></p>
+>>> Emphasis and strong emphasis - 403
+__(bar)__.
+<<<
+<p><strong>(bar)</strong>.</p>
+>>> Emphasis and strong emphasis - 404
+*foo [bar](/url)*
+<<<
+<p><em>foo <a href="/url">bar</a></em></p>
+>>> Emphasis and strong emphasis - 405
+*foo
+bar*
+<<<
+<p><em>foo
+bar</em></p>
+>>> Emphasis and strong emphasis - 406
+_foo __bar__ baz_
+<<<
+<p><em>foo <strong>bar</strong> baz</em></p>
+>>> Emphasis and strong emphasis - 407
+_foo _bar_ baz_
+<<<
+<p><em>foo <em>bar</em> baz</em></p>
+>>> Emphasis and strong emphasis - 408
+__foo_ bar_
+<<<
+<p><em><em>foo</em> bar</em></p>
+>>> Emphasis and strong emphasis - 409
+*foo *bar**
+<<<
+<p><em>foo <em>bar</em></em></p>
+>>> Emphasis and strong emphasis - 410
+*foo **bar** baz*
+<<<
+<p><em>foo <strong>bar</strong> baz</em></p>
+>>> Emphasis and strong emphasis - 411
+*foo**bar**baz*
+<<<
+<p><em>foo<strong>bar</strong>baz</em></p>
+>>> Emphasis and strong emphasis - 412
+*foo**bar*
+<<<
+<p><em>foo**bar</em></p>
+>>> Emphasis and strong emphasis - 413
+***foo** bar*
+<<<
+<p><em><strong>foo</strong> bar</em></p>
+>>> Emphasis and strong emphasis - 414
+*foo **bar***
+<<<
+<p><em>foo <strong>bar</strong></em></p>
+>>> Emphasis and strong emphasis - 415
+*foo**bar***
+<<<
+<p><em>foo<strong>bar</strong></em></p>
+>>> Emphasis and strong emphasis - 416
+foo***bar***baz
+<<<
+<p>foo<em><strong>bar</strong></em>baz</p>
+>>> Emphasis and strong emphasis - 417
+foo******bar*********baz
+<<<
+<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
+>>> Emphasis and strong emphasis - 418
+*foo **bar *baz* bim** bop*
+<<<
+<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
+>>> Emphasis and strong emphasis - 419
+*foo [*bar*](/url)*
+<<<
+<p><em>foo <a href="/url"><em>bar</em></a></em></p>
+>>> Emphasis and strong emphasis - 420
+** is not an empty emphasis
+<<<
+<p>** is not an empty emphasis</p>
+>>> Emphasis and strong emphasis - 421
+**** is not an empty strong emphasis
+<<<
+<p>**** is not an empty strong emphasis</p>
+>>> Emphasis and strong emphasis - 422
+**foo [bar](/url)**
+<<<
+<p><strong>foo <a href="/url">bar</a></strong></p>
+>>> Emphasis and strong emphasis - 423
+**foo
+bar**
+<<<
+<p><strong>foo
+bar</strong></p>
+>>> Emphasis and strong emphasis - 424
+__foo _bar_ baz__
+<<<
+<p><strong>foo <em>bar</em> baz</strong></p>
+>>> Emphasis and strong emphasis - 425
+__foo __bar__ baz__
+<<<
+<p><strong>foo <strong>bar</strong> baz</strong></p>
+>>> Emphasis and strong emphasis - 426
+____foo__ bar__
+<<<
+<p><strong><strong>foo</strong> bar</strong></p>
+>>> Emphasis and strong emphasis - 427
+**foo **bar****
+<<<
+<p><strong>foo <strong>bar</strong></strong></p>
+>>> Emphasis and strong emphasis - 428
+**foo *bar* baz**
+<<<
+<p><strong>foo <em>bar</em> baz</strong></p>
+>>> Emphasis and strong emphasis - 429
+**foo*bar*baz**
+<<<
+<p><strong>foo<em>bar</em>baz</strong></p>
+>>> Emphasis and strong emphasis - 430
+***foo* bar**
+<<<
+<p><strong><em>foo</em> bar</strong></p>
+>>> Emphasis and strong emphasis - 431
+**foo *bar***
+<<<
+<p><strong>foo <em>bar</em></strong></p>
+>>> Emphasis and strong emphasis - 432
+**foo *bar **baz**
+bim* bop**
+<<<
+<p><strong>foo <em>bar <strong>baz</strong>
+bim</em> bop</strong></p>
+>>> Emphasis and strong emphasis - 433
+**foo [*bar*](/url)**
+<<<
+<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
+>>> Emphasis and strong emphasis - 434
+__ is not an empty emphasis
+<<<
+<p>__ is not an empty emphasis</p>
+>>> Emphasis and strong emphasis - 435
+____ is not an empty strong emphasis
+<<<
+<p>____ is not an empty strong emphasis</p>
+>>> Emphasis and strong emphasis - 436
+foo ***
+<<<
+<p>foo ***</p>
+>>> Emphasis and strong emphasis - 437
+foo *\**
+<<<
+<p>foo <em>*</em></p>
+>>> Emphasis and strong emphasis - 438
+foo *_*
+<<<
+<p>foo <em>_</em></p>
+>>> Emphasis and strong emphasis - 439
+foo *****
+<<<
+<p>foo *****</p>
+>>> Emphasis and strong emphasis - 440
+foo **\***
+<<<
+<p>foo <strong>*</strong></p>
+>>> Emphasis and strong emphasis - 441
+foo **_**
+<<<
+<p>foo <strong>_</strong></p>
+>>> Emphasis and strong emphasis - 442
+**foo*
+<<<
+<p>*<em>foo</em></p>
+>>> Emphasis and strong emphasis - 443
+*foo**
+<<<
+<p><em>foo</em>*</p>
+>>> Emphasis and strong emphasis - 444
+***foo**
+<<<
+<p>*<strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 445
+****foo*
+<<<
+<p>***<em>foo</em></p>
+>>> Emphasis and strong emphasis - 446
+**foo***
+<<<
+<p><strong>foo</strong>*</p>
+>>> Emphasis and strong emphasis - 447
+*foo****
+<<<
+<p><em>foo</em>***</p>
+>>> Emphasis and strong emphasis - 448
+foo ___
+<<<
+<p>foo ___</p>
+>>> Emphasis and strong emphasis - 449
+foo _\__
+<<<
+<p>foo <em>_</em></p>
+>>> Emphasis and strong emphasis - 450
+foo _*_
+<<<
+<p>foo <em>*</em></p>
+>>> Emphasis and strong emphasis - 451
+foo _____
+<<<
+<p>foo _____</p>
+>>> Emphasis and strong emphasis - 452
+foo __\___
+<<<
+<p>foo <strong>_</strong></p>
+>>> Emphasis and strong emphasis - 453
+foo __*__
+<<<
+<p>foo <strong>*</strong></p>
+>>> Emphasis and strong emphasis - 454
+__foo_
+<<<
+<p>_<em>foo</em></p>
+>>> Emphasis and strong emphasis - 455
+_foo__
+<<<
+<p><em>foo</em>_</p>
+>>> Emphasis and strong emphasis - 456
+___foo__
+<<<
+<p>_<strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 457
+____foo_
+<<<
+<p>___<em>foo</em></p>
+>>> Emphasis and strong emphasis - 458
+__foo___
+<<<
+<p><strong>foo</strong>_</p>
+>>> Emphasis and strong emphasis - 459
+_foo____
+<<<
+<p><em>foo</em>___</p>
+>>> Emphasis and strong emphasis - 460
+**foo**
+<<<
+<p><strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 461
+*_foo_*
+<<<
+<p><em><em>foo</em></em></p>
+>>> Emphasis and strong emphasis - 462
+__foo__
+<<<
+<p><strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 463
+_*foo*_
+<<<
+<p><em><em>foo</em></em></p>
+>>> Emphasis and strong emphasis - 464
+****foo****
+<<<
+<p><strong><strong>foo</strong></strong></p>
+>>> Emphasis and strong emphasis - 465
+____foo____
+<<<
+<p><strong><strong>foo</strong></strong></p>
+>>> Emphasis and strong emphasis - 466
+******foo******
+<<<
+<p><strong><strong><strong>foo</strong></strong></strong></p>
+>>> Emphasis and strong emphasis - 467
+***foo***
+<<<
+<p><em><strong>foo</strong></em></p>
+>>> Emphasis and strong emphasis - 468
+_____foo_____
+<<<
+<p><em><strong><strong>foo</strong></strong></em></p>
+>>> Emphasis and strong emphasis - 469
+*foo _bar* baz_
+<<<
+<p><em>foo _bar</em> baz_</p>
+>>> Emphasis and strong emphasis - 470
+*foo __bar *baz bim__ bam*
+<<<
+<p><em>foo <strong>bar *baz bim</strong> bam</em></p>
+>>> Emphasis and strong emphasis - 471
+**foo **bar baz**
+<<<
+<p>**foo <strong>bar baz</strong></p>
+>>> Emphasis and strong emphasis - 472
+*foo *bar baz*
+<<<
+<p>*foo <em>bar baz</em></p>
+>>> Emphasis and strong emphasis - 473
+*[bar*](/url)
+<<<
+<p>*<a href="/url">bar*</a></p>
+>>> Emphasis and strong emphasis - 474
+_foo [bar_](/url)
+<<<
+<p>_foo <a href="/url">bar_</a></p>
+>>> Emphasis and strong emphasis - 475
+*<img src="foo" title="*"/>
+<<<
+<p>*<img src="foo" title="*"/></p>
+>>> Emphasis and strong emphasis - 476
+**<a href="**">
+<<<
+<p>**<a href="**"></p>
+>>> Emphasis and strong emphasis - 477
+__<a href="__">
+<<<
+<p>__<a href="__"></p>
+>>> Emphasis and strong emphasis - 478
+*a `*`*
+<<<
+<p><em>a <code>*</code></em></p>
+>>> Emphasis and strong emphasis - 479
+_a `_`_
+<<<
+<p><em>a <code>_</code></em></p>
+>>> Emphasis and strong emphasis - 480
+**a<https://foo.bar/?q=**>
+<<<
+<p>**a<a href="https://foo.bar/?q=**">https://foo.bar/?q=**</a></p>
+>>> Emphasis and strong emphasis - 481
+__a<https://foo.bar/?q=__>
+<<<
+<p>__a<a href="https://foo.bar/?q=__">https://foo.bar/?q=__</a></p>
diff --git a/pkgs/markdown/test/common_mark/entity_and_numeric_character_references.unit b/pkgs/markdown/test/common_mark/entity_and_numeric_character_references.unit
new file mode 100644
index 0000000..2859435
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/entity_and_numeric_character_references.unit
@@ -0,0 +1,93 @@
+>>> Entity and numeric character references - 25
+&nbsp; &amp; &copy; &AElig; &Dcaron;
+&frac34; &HilbertSpace; &DifferentialD;
+&ClockwiseContourIntegral; &ngE;
+<<<
+<p>&amp; © Æ Ď
+¾ ℋ ⅆ
+∲ ≧̸</p>
+>>> Entity and numeric character references - 26
+&#35; &#1234; &#992; &#0;
+<<<
+<p># Ӓ Ϡ �</p>
+>>> Entity and numeric character references - 27
+&#X22; &#XD06; &#xcab;
+<<<
+<p>&quot; ആ ಫ</p>
+>>> Entity and numeric character references - 28
+&nbsp &x; &#; &#x;
+&#87654321;
+&#abcdef0;
+&ThisIsNotDefined; &hi?;
+<<<
+<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
+&amp;#87654321;
+&amp;#abcdef0;
+&amp;ThisIsNotDefined; &amp;hi?;</p>
+>>> Entity and numeric character references - 29
+&copy
+<<<
+<p>&amp;copy</p>
+>>> Entity and numeric character references - 30
+&MadeUpEntity;
+<<<
+<p>&amp;MadeUpEntity;</p>
+>>> Entity and numeric character references - 31
+<a href="&ouml;&ouml;.html">
+<<<
+<a href="&ouml;&ouml;.html">
+>>> Entity and numeric character references - 32
+[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
+<<<
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+>>> Entity and numeric character references - 33
+[foo]
+
+[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
+<<<
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+>>> Entity and numeric character references - 34
+``` f&ouml;&ouml;
+foo
+```
+<<<
+<pre><code class="language-föö">foo
+</code></pre>
+>>> Entity and numeric character references - 35
+`f&ouml;&ouml;`
+<<<
+<p><code>f&amp;ouml;&amp;ouml;</code></p>
+>>> Entity and numeric character references - 36
+    f&ouml;f&ouml;
+<<<
+<pre><code>f&amp;ouml;f&amp;ouml;
+</code></pre>
+>>> Entity and numeric character references - 37
+&#42;foo&#42;
+*foo*
+<<<
+<p>*foo*
+<em>foo</em></p>
+>>> Entity and numeric character references - 38
+&#42; foo
+
+* foo
+<<<
+<p>* foo</p>
+<ul>
+<li>foo</li>
+</ul>
+>>> Entity and numeric character references - 39
+foo&#10;&#10;bar
+<<<
+<p>foo
+
+bar</p>
+>>> Entity and numeric character references - 40
+&#9;foo
+<<<
+<p>foo</p>
+>>> Entity and numeric character references - 41
+[a](url &quot;tit&quot;)
+<<<
+<p>[a](url &quot;tit&quot;)</p>
diff --git a/pkgs/markdown/test/common_mark/fenced_code_blocks.unit b/pkgs/markdown/test/common_mark/fenced_code_blocks.unit
new file mode 100644
index 0000000..06dec58
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/fenced_code_blocks.unit
@@ -0,0 +1,245 @@
+>>> Fenced code blocks - 119
+```
+<
+ >
+```
+<<<
+<pre><code>&lt;
+ &gt;
+</code></pre>
+>>> Fenced code blocks - 120
+~~~
+<
+ >
+~~~
+<<<
+<pre><code>&lt;
+ &gt;
+</code></pre>
+>>> Fenced code blocks - 121
+``
+foo
+``
+<<<
+<p><code>foo</code></p>
+>>> Fenced code blocks - 122
+```
+aaa
+~~~
+```
+<<<
+<pre><code>aaa
+~~~
+</code></pre>
+>>> Fenced code blocks - 123
+~~~
+aaa
+```
+~~~
+<<<
+<pre><code>aaa
+```
+</code></pre>
+>>> Fenced code blocks - 124
+````
+aaa
+```
+``````
+<<<
+<pre><code>aaa
+```
+</code></pre>
+>>> Fenced code blocks - 125
+~~~~
+aaa
+~~~
+~~~~
+<<<
+<pre><code>aaa
+~~~
+</code></pre>
+>>> Fenced code blocks - 126
+```
+<<<
+<pre><code></code></pre>
+>>> Fenced code blocks - 127
+`````
+
+```
+aaa
+<<<
+<pre><code>
+```
+aaa
+</code></pre>
+>>> Fenced code blocks - 128
+> ```
+> aaa
+
+bbb
+<<<
+<blockquote>
+<pre><code>aaa
+</code></pre>
+</blockquote>
+<p>bbb</p>
+>>> Fenced code blocks - 129
+```
+
+  
+```
+<<<
+<pre><code>
+  
+</code></pre>
+>>> Fenced code blocks - 130
+```
+```
+<<<
+<pre><code></code></pre>
+>>> Fenced code blocks - 131
+ ```
+ aaa
+aaa
+```
+<<<
+<pre><code>aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 132
+  ```
+aaa
+  aaa
+aaa
+  ```
+<<<
+<pre><code>aaa
+aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 133
+   ```
+   aaa
+    aaa
+  aaa
+   ```
+<<<
+<pre><code>aaa
+ aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 134
+    ```
+    aaa
+    ```
+<<<
+<pre><code>```
+aaa
+```
+</code></pre>
+>>> Fenced code blocks - 135
+```
+aaa
+  ```
+<<<
+<pre><code>aaa
+</code></pre>
+>>> Fenced code blocks - 136
+   ```
+aaa
+  ```
+<<<
+<pre><code>aaa
+</code></pre>
+>>> Fenced code blocks - 137
+```
+aaa
+    ```
+<<<
+<pre><code>aaa
+    ```
+</code></pre>
+>>> Fenced code blocks - 138
+``` ```
+aaa
+<<<
+<p><code> </code>
+aaa</p>
+>>> Fenced code blocks - 139
+~~~~~~
+aaa
+~~~ ~~
+<<<
+<pre><code>aaa
+~~~ ~~
+</code></pre>
+>>> Fenced code blocks - 140
+foo
+```
+bar
+```
+baz
+<<<
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+>>> Fenced code blocks - 141
+foo
+---
+~~~
+bar
+~~~
+# baz
+<<<
+<h2>foo</h2>
+<pre><code>bar
+</code></pre>
+<h1>baz</h1>
+>>> Fenced code blocks - 142
+```ruby
+def foo(x)
+  return 3
+end
+```
+<<<
+<pre><code class="language-ruby">def foo(x)
+  return 3
+end
+</code></pre>
+>>> Fenced code blocks - 143
+~~~~    ruby startline=3 $%@#$
+def foo(x)
+  return 3
+end
+~~~~~~~
+<<<
+<pre><code class="language-ruby">def foo(x)
+  return 3
+end
+</code></pre>
+>>> Fenced code blocks - 144
+````;
+````
+<<<
+<pre><code class="language-;"></code></pre>
+>>> Fenced code blocks - 145
+``` aa ```
+foo
+<<<
+<p><code>aa</code>
+foo</p>
+>>> Fenced code blocks - 146
+~~~ aa ``` ~~~
+foo
+~~~
+<<<
+<pre><code class="language-aa">foo
+</code></pre>
+>>> Fenced code blocks - 147
+```
+``` aaa
+```
+<<<
+<pre><code>``` aaa
+</code></pre>
diff --git a/pkgs/markdown/test/common_mark/hard_line_breaks.unit b/pkgs/markdown/test/common_mark/hard_line_breaks.unit
new file mode 100644
index 0000000..8a3f0be
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/hard_line_breaks.unit
@@ -0,0 +1,80 @@
+>>> Hard line breaks - 633
+foo  
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 634
+foo\
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 635
+foo       
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 636
+foo  
+     bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Hard line breaks - 637
+foo\
+     bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Hard line breaks - 638
+*foo  
+bar*
+<<<
+<p><em>foo<br />
+bar</em></p>
+>>> Hard line breaks - 639
+*foo\
+bar*
+<<<
+<p><em>foo<br />
+bar</em></p>
+>>> Hard line breaks - 640
+`code  
+span`
+<<<
+<p><code>code   span</code></p>
+>>> Hard line breaks - 641
+`code\
+span`
+<<<
+<p><code>code\ span</code></p>
+>>> Hard line breaks - 642
+<a href="foo  
+bar">
+<<<
+<p><a href="foo  
+bar"></p>
+>>> Hard line breaks - 643
+<a href="foo\
+bar">
+<<<
+<p><a href="foo\
+bar"></p>
+>>> Hard line breaks - 644
+foo\
+<<<
+<p>foo\</p>
+>>> Hard line breaks - 645
+foo  
+<<<
+<p>foo</p>
+>>> Hard line breaks - 646
+### foo\
+<<<
+<h3>foo\</h3>
+>>> Hard line breaks - 647
+### foo  
+<<<
+<h3>foo</h3>
diff --git a/pkgs/markdown/test/common_mark/html_blocks.unit b/pkgs/markdown/test/common_mark/html_blocks.unit
new file mode 100644
index 0000000..3a01cd0
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/html_blocks.unit
@@ -0,0 +1,449 @@
+>>> HTML blocks - 148
+<table><tr><td>
+<pre>
+**Hello**,
+
+_world_.
+</pre>
+</td></tr></table>
+<<<
+<table><tr><td>
+<pre>
+**Hello**,
+<p><em>world</em>.
+</pre></p>
+</td></tr></table>
+>>> HTML blocks - 149
+<table>
+  <tr>
+    <td>
+           hi
+    </td>
+  </tr>
+</table>
+
+okay.
+<<<
+<table>
+  <tr>
+    <td>
+           hi
+    </td>
+  </tr>
+</table>
+<p>okay.</p>
+>>> HTML blocks - 150
+ <div>
+  *hello*
+         <foo><a>
+<<<
+ <div>
+  *hello*
+         <foo><a>
+>>> HTML blocks - 151
+</div>
+*foo*
+<<<
+</div>
+*foo*
+>>> HTML blocks - 152
+<DIV CLASS="foo">
+
+*Markdown*
+
+</DIV>
+<<<
+<DIV CLASS="foo">
+<p><em>Markdown</em></p>
+</DIV>
+>>> HTML blocks - 153
+<div id="foo"
+  class="bar">
+</div>
+<<<
+<div id="foo"
+  class="bar">
+</div>
+>>> HTML blocks - 154
+<div id="foo" class="bar
+  baz">
+</div>
+<<<
+<div id="foo" class="bar
+  baz">
+</div>
+>>> HTML blocks - 155
+<div>
+*foo*
+
+*bar*
+<<<
+<div>
+*foo*
+<p><em>bar</em></p>
+>>> HTML blocks - 156
+<div id="foo"
+*hi*
+<<<
+<div id="foo"
+*hi*
+>>> HTML blocks - 157
+<div class
+foo
+<<<
+<div class
+foo
+>>> HTML blocks - 158
+<div *???-&&&-<---
+*foo*
+<<<
+<div *???-&&&-<---
+*foo*
+>>> HTML blocks - 159
+<div><a href="bar">*foo*</a></div>
+<<<
+<div><a href="bar">*foo*</a></div>
+>>> HTML blocks - 160
+<table><tr><td>
+foo
+</td></tr></table>
+<<<
+<table><tr><td>
+foo
+</td></tr></table>
+>>> HTML blocks - 161
+<div></div>
+``` c
+int x = 33;
+```
+<<<
+<div></div>
+``` c
+int x = 33;
+```
+>>> HTML blocks - 162
+<a href="foo">
+*bar*
+</a>
+<<<
+<a href="foo">
+*bar*
+</a>
+>>> HTML blocks - 163
+<Warning>
+*bar*
+</Warning>
+<<<
+<Warning>
+*bar*
+</Warning>
+>>> HTML blocks - 164
+<i class="foo">
+*bar*
+</i>
+<<<
+<i class="foo">
+*bar*
+</i>
+>>> HTML blocks - 165
+</ins>
+*bar*
+<<<
+</ins>
+*bar*
+>>> HTML blocks - 166
+<del>
+*foo*
+</del>
+<<<
+<del>
+*foo*
+</del>
+>>> HTML blocks - 167
+<del>
+
+*foo*
+
+</del>
+<<<
+<del>
+<p><em>foo</em></p>
+</del>
+>>> HTML blocks - 168
+<del>*foo*</del>
+<<<
+<p><del><em>foo</em></del></p>
+>>> HTML blocks - 169
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+okay
+<<<
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+<p>okay</p>
+>>> HTML blocks - 170
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+okay
+<<<
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+<p>okay</p>
+>>> HTML blocks - 171
+<textarea>
+
+*foo*
+
+_bar_
+
+</textarea>
+<<<
+<textarea>
+
+*foo*
+
+_bar_
+
+</textarea>
+>>> HTML blocks - 172
+<style
+  type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+okay
+<<<
+<style
+  type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+<p>okay</p>
+>>> HTML blocks - 173
+<style
+  type="text/css">
+
+foo
+<<<
+<style
+  type="text/css">
+
+foo
+>>> HTML blocks - 174
+> <div>
+> foo
+
+bar
+<<<
+<blockquote>
+<div>
+foo
+</blockquote>
+<p>bar</p>
+>>> HTML blocks - 175
+- <div>
+- foo
+<<<
+<ul>
+<li>
+<div>
+</li>
+<li>foo</li>
+</ul>
+>>> HTML blocks - 176
+<style>p{color:red;}</style>
+*foo*
+<<<
+<style>p{color:red;}</style>
+<p><em>foo</em></p>
+>>> HTML blocks - 177
+<!-- foo -->*bar*
+*baz*
+<<<
+<!-- foo -->*bar*
+<p><em>baz</em></p>
+>>> HTML blocks - 178
+<script>
+foo
+</script>1. *bar*
+<<<
+<script>
+foo
+</script>1. *bar*
+>>> HTML blocks - 179
+<!-- Foo
+
+bar
+   baz -->
+okay
+<<<
+<!-- Foo
+
+bar
+   baz -->
+<p>okay</p>
+>>> HTML blocks - 180
+<?php
+
+  echo '>';
+
+?>
+okay
+<<<
+<?php
+
+  echo '>';
+
+?>
+<p>okay</p>
+>>> HTML blocks - 181
+<!DOCTYPE html>
+<<<
+<!DOCTYPE html>
+>>> HTML blocks - 182
+<![CDATA[
+function matchwo(a,b)
+{
+  if (a < b && a < 0) then {
+    return 1;
+
+  } else {
+
+    return 0;
+  }
+}
+]]>
+okay
+<<<
+<![CDATA[
+function matchwo(a,b)
+{
+  if (a < b && a < 0) then {
+    return 1;
+
+  } else {
+
+    return 0;
+  }
+}
+]]>
+<p>okay</p>
+>>> HTML blocks - 183
+  <!-- foo -->
+
+    <!-- foo -->
+<<<
+  <!-- foo -->
+<pre><code>&lt;!-- foo --&gt;
+</code></pre>
+>>> HTML blocks - 184
+  <div>
+
+    <div>
+<<<
+  <div>
+<pre><code>&lt;div&gt;
+</code></pre>
+>>> HTML blocks - 185
+Foo
+<div>
+bar
+</div>
+<<<
+<p>Foo</p>
+<div>
+bar
+</div>
+>>> HTML blocks - 186
+<div>
+bar
+</div>
+*foo*
+<<<
+<div>
+bar
+</div>
+*foo*
+>>> HTML blocks - 187
+Foo
+<a href="bar">
+baz
+<<<
+<p>Foo
+<a href="bar">
+baz</p>
+>>> HTML blocks - 188
+<div>
+
+*Emphasized* text.
+
+</div>
+<<<
+<div>
+<p><em>Emphasized</em> text.</p>
+</div>
+>>> HTML blocks - 189
+<div>
+*Emphasized* text.
+</div>
+<<<
+<div>
+*Emphasized* text.
+</div>
+>>> HTML blocks - 190
+<table>
+
+<tr>
+
+<td>
+Hi
+</td>
+
+</tr>
+
+</table>
+<<<
+<table>
+<tr>
+<td>
+Hi
+</td>
+</tr>
+</table>
+>>> HTML blocks - 191
+<table>
+
+  <tr>
+
+    <td>
+      Hi
+    </td>
+
+  </tr>
+
+</table>
+<<<
+<table>
+  <tr>
+<pre><code>&lt;td&gt;
+  Hi
+&lt;/td&gt;
+</code></pre>
+  </tr>
+</table>
diff --git a/pkgs/markdown/test/common_mark/images.unit b/pkgs/markdown/test/common_mark/images.unit
new file mode 100644
index 0000000..ae42aa2
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/images.unit
@@ -0,0 +1,121 @@
+>>> Images - 572
+![foo](/url "title")
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 573
+![foo *bar*]
+
+[foo *bar*]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 574
+![foo ![bar](/url)](/url2)
+<<<
+<p><img src="/url2" alt="foo bar" /></p>
+>>> Images - 575
+![foo [bar](/url)](/url2)
+<<<
+<p><img src="/url2" alt="foo bar" /></p>
+>>> Images - 576
+![foo *bar*][]
+
+[foo *bar*]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 577
+![foo *bar*][foobar]
+
+[FOOBAR]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 578
+![foo](train.jpg)
+<<<
+<p><img src="train.jpg" alt="foo" /></p>
+>>> Images - 579
+My ![foo bar](/path/to/train.jpg  "title"   )
+<<<
+<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
+>>> Images - 580
+![foo](<url>)
+<<<
+<p><img src="url" alt="foo" /></p>
+>>> Images - 581
+![](/url)
+<<<
+<p><img src="/url" alt="" /></p>
+>>> Images - 582
+![foo][bar]
+
+[bar]: /url
+<<<
+<p><img src="/url" alt="foo" /></p>
+>>> Images - 583
+![foo][bar]
+
+[BAR]: /url
+<<<
+<p><img src="/url" alt="foo" /></p>
+>>> Images - 584
+![foo][]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 585
+![*foo* bar][]
+
+[*foo* bar]: /url "title"
+<<<
+<p><img src="/url" alt="foo bar" title="title" /></p>
+>>> Images - 586
+![Foo][]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="Foo" title="title" /></p>
+>>> Images - 587
+![foo] 
+[]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" />
+[]</p>
+>>> Images - 588
+![foo]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 589
+![*foo* bar]
+
+[*foo* bar]: /url "title"
+<<<
+<p><img src="/url" alt="foo bar" title="title" /></p>
+>>> Images - 590
+![[foo]]
+
+[[foo]]: /url "title"
+<<<
+<p>![[foo]]</p>
+<p>[[foo]]: /url &quot;title&quot;</p>
+>>> Images - 591
+![Foo]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="Foo" title="title" /></p>
+>>> Images - 592
+!\[foo]
+
+[foo]: /url "title"
+<<<
+<p>![foo]</p>
+>>> Images - 593
+\![foo]
+
+[foo]: /url "title"
+<<<
+<p>!<a href="/url" title="title">foo</a></p>
diff --git a/pkgs/markdown/test/common_mark/indented_code_blocks.unit b/pkgs/markdown/test/common_mark/indented_code_blocks.unit
new file mode 100644
index 0000000..ce142fe
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/indented_code_blocks.unit
@@ -0,0 +1,118 @@
+>>> Indented code blocks - 107
+    a simple
+      indented code block
+<<<
+<pre><code>a simple
+  indented code block
+</code></pre>
+>>> Indented code blocks - 108
+  - foo
+
+    bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> Indented code blocks - 109
+1.  foo
+
+    - bar
+<<<
+<ol>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+>>> Indented code blocks - 110
+    <a/>
+    *hi*
+
+    - one
+<<<
+<pre><code>&lt;a/&gt;
+*hi*
+
+- one
+</code></pre>
+>>> Indented code blocks - 111
+    chunk1
+
+    chunk2
+  
+ 
+ 
+    chunk3
+<<<
+<pre><code>chunk1
+
+chunk2
+
+
+
+chunk3
+</code></pre>
+>>> Indented code blocks - 112
+    chunk1
+      
+      chunk2
+<<<
+<pre><code>chunk1
+  
+  chunk2
+</code></pre>
+>>> Indented code blocks - 113
+Foo
+    bar
+
+<<<
+<p>Foo
+bar</p>
+>>> Indented code blocks - 114
+    foo
+bar
+<<<
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+>>> Indented code blocks - 115
+# Heading
+    foo
+Heading
+------
+    foo
+----
+<<<
+<h1>Heading</h1>
+<pre><code>foo
+</code></pre>
+<h2>Heading</h2>
+<pre><code>foo
+</code></pre>
+<hr />
+>>> Indented code blocks - 116
+        foo
+    bar
+<<<
+<pre><code>    foo
+bar
+</code></pre>
+>>> Indented code blocks - 117
+
+    
+    foo
+    
+
+<<<
+<pre><code>foo
+</code></pre>
+>>> Indented code blocks - 118
+    foo  
+<<<
+<pre><code>foo  
+</code></pre>
diff --git a/pkgs/markdown/test/common_mark/inlines.unit b/pkgs/markdown/test/common_mark/inlines.unit
new file mode 100644
index 0000000..3d2eebe
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/inlines.unit
@@ -0,0 +1,4 @@
+>>> Inlines - 327
+`hi`lo`
+<<<
+<p><code>hi</code>lo`</p>
diff --git a/pkgs/markdown/test/common_mark/link_reference_definitions.unit b/pkgs/markdown/test/common_mark/link_reference_definitions.unit
new file mode 100644
index 0000000..0677259
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/link_reference_definitions.unit
@@ -0,0 +1,202 @@
+>>> Link reference definitions - 192
+[foo]: /url "title"
+
+[foo]
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Link reference definitions - 193
+   [foo]: 
+      /url  
+           'the title'  
+
+[foo]
+<<<
+<p><a href="/url" title="the title">foo</a></p>
+>>> Link reference definitions - 194
+[Foo*bar\]]:my_(url) 'title (with parens)'
+
+[Foo*bar\]]
+<<<
+<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
+>>> Link reference definitions - 195
+[Foo bar]:
+<my url>
+'title'
+
+[Foo bar]
+<<<
+<p><a href="my%20url" title="title">Foo bar</a></p>
+>>> Link reference definitions - 196
+[foo]: /url '
+title
+line1
+line2
+'
+
+[foo]
+<<<
+<p><a href="/url" title="
+title
+line1
+line2
+">foo</a></p>
+>>> Link reference definitions - 197
+[foo]: /url 'title
+
+with blank line'
+
+[foo]
+<<<
+<p>[foo]: /url 'title</p>
+<p>with blank line'</p>
+<p>[foo]</p>
+>>> Link reference definitions - 198
+[foo]:
+/url
+
+[foo]
+<<<
+<p><a href="/url">foo</a></p>
+>>> Link reference definitions - 199
+[foo]:
+
+[foo]
+<<<
+<p>[foo]:</p>
+<p>[foo]</p>
+>>> Link reference definitions - 200
+[foo]: <>
+
+[foo]
+<<<
+<p><a href="">foo</a></p>
+>>> Link reference definitions - 201
+[foo]: <bar>(baz)
+
+[foo]
+<<<
+<p>[foo]: <bar>(baz)</p>
+<p>[foo]</p>
+>>> Link reference definitions - 202
+[foo]: /url\bar\*baz "foo\"bar\baz"
+
+[foo]
+<<<
+<p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
+>>> Link reference definitions - 203
+[foo]
+
+[foo]: url
+<<<
+<p><a href="url">foo</a></p>
+>>> Link reference definitions - 204
+[foo]
+
+[foo]: first
+[foo]: second
+<<<
+<p><a href="first">foo</a></p>
+>>> Link reference definitions - 205
+[FOO]: /url
+
+[Foo]
+<<<
+<p><a href="/url">Foo</a></p>
+>>> Link reference definitions - 206
+[ΑΓΩ]: /φου
+
+[αγω]
+<<<
+<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
+>>> Link reference definitions - 207
+[foo]: /url
+<<<
+
+>>> Link reference definitions - 208
+[
+foo
+]: /url
+bar
+<<<
+<p>bar</p>
+>>> Link reference definitions - 209
+[foo]: /url "title" ok
+<<<
+<p>[foo]: /url &quot;title&quot; ok</p>
+>>> Link reference definitions - 210
+[foo]: /url
+"title" ok
+<<<
+<p>&quot;title&quot; ok</p>
+>>> Link reference definitions - 211
+    [foo]: /url "title"
+
+[foo]
+<<<
+<pre><code>[foo]: /url &quot;title&quot;
+</code></pre>
+<p>[foo]</p>
+>>> Link reference definitions - 212
+```
+[foo]: /url
+```
+
+[foo]
+<<<
+<pre><code>[foo]: /url
+</code></pre>
+<p>[foo]</p>
+>>> Link reference definitions - 213
+Foo
+[bar]: /baz
+
+[bar]
+<<<
+<p>Foo
+[bar]: /baz</p>
+<p>[bar]</p>
+>>> Link reference definitions - 214
+# [Foo]
+[foo]: /url
+> bar
+<<<
+<h1><a href="/url">Foo</a></h1>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Link reference definitions - 215
+[foo]: /url
+bar
+===
+[foo]
+<<<
+<h1>bar</h1>
+<p><a href="/url">foo</a></p>
+>>> Link reference definitions - 216
+[foo]: /url
+===
+[foo]
+<<<
+<p>===
+<a href="/url">foo</a></p>
+>>> Link reference definitions - 217
+[foo]: /foo-url "foo"
+[bar]: /bar-url
+  "bar"
+[baz]: /baz-url
+
+[foo],
+[bar],
+[baz]
+<<<
+<p><a href="/foo-url" title="foo">foo</a>,
+<a href="/bar-url" title="bar">bar</a>,
+<a href="/baz-url">baz</a></p>
+>>> Link reference definitions - 218
+[foo]
+
+> [foo]: /url
+<<<
+<p><a href="/url">foo</a></p>
+<blockquote>
+</blockquote>
diff --git a/pkgs/markdown/test/common_mark/links.unit b/pkgs/markdown/test/common_mark/links.unit
new file mode 100644
index 0000000..ab399f5
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/links.unit
@@ -0,0 +1,488 @@
+>>> Links - 482
+[link](/uri "title")
+<<<
+<p><a href="/uri" title="title">link</a></p>
+>>> Links - 483
+[link](/uri)
+<<<
+<p><a href="/uri">link</a></p>
+>>> Links - 484
+[](./target.md)
+<<<
+<p><a href="./target.md"></a></p>
+>>> Links - 485
+[link]()
+<<<
+<p><a href="">link</a></p>
+>>> Links - 486
+[link](<>)
+<<<
+<p><a href="">link</a></p>
+>>> Links - 487
+[]()
+<<<
+<p><a href=""></a></p>
+>>> Links - 488
+[link](/my uri)
+<<<
+<p>[link](/my uri)</p>
+>>> Links - 489
+[link](</my uri>)
+<<<
+<p><a href="/my%20uri">link</a></p>
+>>> Links - 490
+[link](foo
+bar)
+<<<
+<p>[link](foo
+bar)</p>
+>>> Links - 491
+[link](<foo
+bar>)
+<<<
+<p>[link](<foo
+bar>)</p>
+>>> Links - 492
+[a](<b)c>)
+<<<
+<p><a href="b)c">a</a></p>
+>>> Links - 493
+[link](<foo\>)
+<<<
+<p>[link](&lt;foo&gt;)</p>
+>>> Links - 494
+[a](<b)c
+[a](<b)c>
+[a](<b>c)
+<<<
+<p>[a](&lt;b)c
+[a](&lt;b)c&gt;
+[a](<b>c)</p>
+>>> Links - 495
+[link](\(foo\))
+<<<
+<p><a href="(foo)">link</a></p>
+>>> Links - 496
+[link](foo(and(bar)))
+<<<
+<p><a href="foo(and(bar))">link</a></p>
+>>> Links - 497
+[link](foo(and(bar))
+<<<
+<p>[link](foo(and(bar))</p>
+>>> Links - 498
+[link](foo\(and\(bar\))
+<<<
+<p><a href="foo(and(bar)">link</a></p>
+>>> Links - 499
+[link](<foo(and(bar)>)
+<<<
+<p><a href="foo(and(bar)">link</a></p>
+>>> Links - 500
+[link](foo\)\:)
+<<<
+<p><a href="foo):">link</a></p>
+>>> Links - 501
+[link](#fragment)
+
+[link](https://example.com#fragment)
+
+[link](https://example.com?foo=3#frag)
+<<<
+<p><a href="#fragment">link</a></p>
+<p><a href="https://example.com#fragment">link</a></p>
+<p><a href="https://example.com?foo=3#frag">link</a></p>
+>>> Links - 502
+[link](foo\bar)
+<<<
+<p><a href="foo%5Cbar">link</a></p>
+>>> Links - 503
+[link](foo%20b&auml;)
+<<<
+<p><a href="foo%20b%C3%A4">link</a></p>
+>>> Links - 504
+[link]("title")
+<<<
+<p><a href="%22title%22">link</a></p>
+>>> Links - 505
+[link](/url "title")
+[link](/url 'title')
+[link](/url (title))
+<<<
+<p><a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a></p>
+>>> Links - 506
+[link](/url "title \"&quot;")
+<<<
+<p><a href="/url" title="title &quot;&quot;">link</a></p>
+>>> Links - 507
+[link](/url "title")
+<<<
+<p><a href="/url%C2%A0%22title%22">link</a></p>
+>>> Links - 508
+[link](/url "title "and" title")
+<<<
+<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
+>>> Links - 509
+[link](/url 'title "and" title')
+<<<
+<p><a href="/url" title="title &quot;and&quot; title">link</a></p>
+>>> Links - 510
+[link](   /uri
+  "title"  )
+<<<
+<p><a href="/uri" title="title">link</a></p>
+>>> Links - 511
+[link] (/uri)
+<<<
+<p>[link] (/uri)</p>
+>>> Links - 512
+[link [foo [bar]]](/uri)
+<<<
+<p><a href="/uri">link [foo [bar]]</a></p>
+>>> Links - 513
+[link] bar](/uri)
+<<<
+<p>[link] bar](/uri)</p>
+>>> Links - 514
+[link [bar](/uri)
+<<<
+<p>[link <a href="/uri">bar</a></p>
+>>> Links - 515
+[link \[bar](/uri)
+<<<
+<p><a href="/uri">link [bar</a></p>
+>>> Links - 516
+[link *foo **bar** `#`*](/uri)
+<<<
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+>>> Links - 517
+[![moon](moon.jpg)](/uri)
+<<<
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+>>> Links - 518
+[foo [bar](/uri)](/uri)
+<<<
+<p>[foo <a href="/uri">bar</a>](/uri)</p>
+>>> Links - 519
+[foo *[bar [baz](/uri)](/uri)*](/uri)
+<<<
+<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
+>>> Links - 520
+![[[foo](uri1)](uri2)](uri3)
+<<<
+<p><img src="uri3" alt="[foo](uri2)" /></p>
+>>> Links - 521
+*[foo*](/uri)
+<<<
+<p>*<a href="/uri">foo*</a></p>
+>>> Links - 522
+[foo *bar](baz*)
+<<<
+<p><a href="baz*">foo *bar</a></p>
+>>> Links - 523
+*foo [bar* baz]
+<<<
+<p><em>foo [bar</em> baz]</p>
+>>> Links - 524
+[foo <bar attr="](baz)">
+<<<
+<p>[foo <bar attr="](baz)"></p>
+>>> Links - 525
+[foo`](/uri)`
+<<<
+<p>[foo<code>](/uri)</code></p>
+>>> Links - 526
+[foo<https://example.com/?search=](uri)>
+<<<
+<p>[foo<a href="https://example.com/?search=%5D(uri)">https://example.com/?search=](uri)</a></p>
+>>> Links - 527
+[foo][bar]
+
+[bar]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 528
+[link [foo [bar]]][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link [foo [bar]]</a></p>
+>>> Links - 529
+[link \[bar][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link [bar</a></p>
+>>> Links - 530
+[link *foo **bar** `#`*][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+>>> Links - 531
+[![moon](moon.jpg)][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+>>> Links - 532
+[foo [bar](/uri)][ref]
+
+[ref]: /uri
+<<<
+<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
+>>> Links - 533
+[foo *bar [baz][ref]*][ref]
+
+[ref]: /uri
+<<<
+<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
+>>> Links - 534
+*[foo*][ref]
+
+[ref]: /uri
+<<<
+<p>*<a href="/uri">foo*</a></p>
+>>> Links - 535
+[foo *bar][ref]*
+
+[ref]: /uri
+<<<
+<p><a href="/uri">foo *bar</a>*</p>
+>>> Links - 536
+[foo <bar attr="][ref]">
+
+[ref]: /uri
+<<<
+<p>[foo <bar attr="][ref]"></p>
+>>> Links - 537
+[foo`][ref]`
+
+[ref]: /uri
+<<<
+<p>[foo<code>][ref]</code></p>
+>>> Links - 538
+[foo<https://example.com/?search=][ref]>
+
+[ref]: /uri
+<<<
+<p>[foo<a href="https://example.com/?search=%5D%5Bref%5D">https://example.com/?search=][ref]</a></p>
+>>> Links - 539
+[foo][BaR]
+
+[bar]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 540
+[ẞ]
+
+[SS]: /url
+<<<
+<p><a href="/url">ẞ</a></p>
+>>> Links - 541
+[Foo
+  bar]: /url
+
+[Baz][Foo bar]
+<<<
+<p><a href="/url">Baz</a></p>
+>>> Links - 542
+[foo] [bar]
+
+[bar]: /url "title"
+<<<
+<p>[foo] <a href="/url" title="title">bar</a></p>
+>>> Links - 543
+[foo]
+[bar]
+
+[bar]: /url "title"
+<<<
+<p>[foo]
+<a href="/url" title="title">bar</a></p>
+>>> Links - 544
+[foo]: /url1
+
+[foo]: /url2
+
+[bar][foo]
+<<<
+<p><a href="/url1">bar</a></p>
+>>> Links - 545
+[bar][foo\!]
+
+[foo!]: /url
+<<<
+<p>[bar][foo!]</p>
+>>> Links - 546
+[foo][ref[]
+
+[ref[]: /uri
+<<<
+<p>[foo][ref[]</p>
+<p>[ref[]: /uri</p>
+>>> Links - 547
+[foo][ref[bar]]
+
+[ref[bar]]: /uri
+<<<
+<p>[foo][ref[bar]]</p>
+<p>[ref[bar]]: /uri</p>
+>>> Links - 548
+[[[foo]]]
+
+[[[foo]]]: /url
+<<<
+<p>[[[foo]]]</p>
+<p>[[[foo]]]: /url</p>
+>>> Links - 549
+[foo][ref\[]
+
+[ref\[]: /uri
+<<<
+<p><a href="/uri">foo</a></p>
+>>> Links - 550
+[bar\\]: /uri
+
+[bar\\]
+<<<
+<p><a href="/uri">bar\</a></p>
+>>> Links - 551
+[]
+
+[]: /uri
+<<<
+<p>[]</p>
+<p>[]: /uri</p>
+>>> Links - 552
+[
+ ]
+
+[
+ ]: /uri
+<<<
+<p>[
+]</p>
+<p>[
+]: /uri</p>
+>>> Links - 553
+[foo][]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 554
+[*foo* bar][]
+
+[*foo* bar]: /url "title"
+<<<
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+>>> Links - 555
+[Foo][]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">Foo</a></p>
+>>> Links - 556
+[foo] 
+[]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a>
+[]</p>
+>>> Links - 557
+[foo]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 558
+[*foo* bar]
+
+[*foo* bar]: /url "title"
+<<<
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+>>> Links - 559
+[[*foo* bar]]
+
+[*foo* bar]: /url "title"
+<<<
+<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
+>>> Links - 560
+[[bar [foo]
+
+[foo]: /url
+<<<
+<p>[[bar <a href="/url">foo</a></p>
+>>> Links - 561
+[Foo]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">Foo</a></p>
+>>> Links - 562
+[foo] bar
+
+[foo]: /url
+<<<
+<p><a href="/url">foo</a> bar</p>
+>>> Links - 563
+\[foo]
+
+[foo]: /url "title"
+<<<
+<p>[foo]</p>
+>>> Links - 564
+[foo*]: /url
+
+*[foo*]
+<<<
+<p>*<a href="/url">foo*</a></p>
+>>> Links - 565
+[foo][bar]
+
+[foo]: /url1
+[bar]: /url2
+<<<
+<p><a href="/url2">foo</a></p>
+>>> Links - 566
+[foo][]
+
+[foo]: /url1
+<<<
+<p><a href="/url1">foo</a></p>
+>>> Links - 567
+[foo]()
+
+[foo]: /url1
+<<<
+<p><a href="">foo</a></p>
+>>> Links - 568
+[foo](not a link)
+
+[foo]: /url1
+<<<
+<p><a href="/url1">foo</a>(not a link)</p>
+>>> Links - 569
+[foo][bar][baz]
+
+[baz]: /url
+<<<
+<p>[foo]<a href="/url">bar</a></p>
+>>> Links - 570
+[foo][bar][baz]
+
+[baz]: /url1
+[bar]: /url2
+<<<
+<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
+>>> Links - 571
+[foo][bar][baz]
+
+[baz]: /url1
+[foo]: /url2
+<<<
+<p>[foo]<a href="/url1">bar</a></p>
diff --git a/pkgs/markdown/test/common_mark/list_items.unit b/pkgs/markdown/test/common_mark/list_items.unit
new file mode 100644
index 0000000..46162a9
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/list_items.unit
@@ -0,0 +1,586 @@
+>>> List items - 253
+A paragraph
+with two lines.
+
+    indented code
+
+> A block quote.
+<<<
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+>>> List items - 254
+1.  A paragraph
+    with two lines.
+
+        indented code
+
+    > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 255
+- one
+
+ two
+<<<
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+>>> List items - 256
+- one
+
+  two
+<<<
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+>>> List items - 257
+ -    one
+
+     two
+<<<
+<ul>
+<li>one</li>
+</ul>
+<pre><code> two
+</code></pre>
+>>> List items - 258
+ -    one
+
+      two
+<<<
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+>>> List items - 259
+   > > 1.  one
+>>
+>>     two
+<<<
+<blockquote>
+<blockquote>
+<ol>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ol>
+</blockquote>
+</blockquote>
+>>> List items - 260
+>>- one
+>>
+  >  > two
+<<<
+<blockquote>
+<blockquote>
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+</blockquote>
+</blockquote>
+>>> List items - 261
+-one
+
+2.two
+<<<
+<p>-one</p>
+<p>2.two</p>
+>>> List items - 262
+- foo
+
+
+  bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> List items - 263
+1.  foo
+
+    ```
+    bar
+    ```
+
+    baz
+
+    > bam
+<<<
+<ol>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+<blockquote>
+<p>bam</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 264
+- Foo
+
+      bar
+
+
+      baz
+<<<
+<ul>
+<li>
+<p>Foo</p>
+<pre><code>bar
+
+
+baz
+</code></pre>
+</li>
+</ul>
+>>> List items - 265
+123456789. ok
+<<<
+<ol start="123456789">
+<li>ok</li>
+</ol>
+>>> List items - 266
+1234567890. not ok
+<<<
+<p>1234567890. not ok</p>
+>>> List items - 267
+0. ok
+<<<
+<ol start="0">
+<li>ok</li>
+</ol>
+>>> List items - 268
+003. ok
+<<<
+<ol start="3">
+<li>ok</li>
+</ol>
+>>> List items - 269
+-1. not ok
+<<<
+<p>-1. not ok</p>
+>>> List items - 270
+- foo
+
+      bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ul>
+>>> List items - 271
+  10.  foo
+
+           bar
+<<<
+<ol start="10">
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ol>
+>>> List items - 272
+    indented code
+
+paragraph
+
+    more code
+<<<
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+>>> List items - 273
+1.     indented code
+
+   paragraph
+
+       more code
+<<<
+<ol>
+<li>
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+>>> List items - 274
+1.      indented code
+
+   paragraph
+
+       more code
+<<<
+<ol>
+<li>
+<pre><code> indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+>>> List items - 275
+   foo
+
+bar
+<<<
+<p>foo</p>
+<p>bar</p>
+>>> List items - 276
+-    foo
+
+  bar
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<p>bar</p>
+>>> List items - 277
+-  foo
+
+   bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> List items - 278
+-
+  foo
+-
+  ```
+  bar
+  ```
+-
+      baz
+<<<
+<ul>
+<li>foo</li>
+<li>
+<pre><code>bar
+</code></pre>
+</li>
+<li>
+<pre><code>baz
+</code></pre>
+</li>
+</ul>
+>>> List items - 279
+-   
+  foo
+<<<
+<ul>
+<li>foo</li>
+</ul>
+>>> List items - 280
+-
+
+  foo
+<<<
+<ul>
+<li></li>
+</ul>
+<p>foo</p>
+>>> List items - 281
+- foo
+-
+- bar
+<<<
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+>>> List items - 282
+- foo
+-   
+- bar
+<<<
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+>>> List items - 283
+1. foo
+2.
+3. bar
+<<<
+<ol>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ol>
+>>> List items - 284
+*
+<<<
+<ul>
+<li></li>
+</ul>
+>>> List items - 285
+foo
+*
+
+foo
+1.
+<<<
+<p>foo
+*</p>
+<p>foo
+1.</p>
+>>> List items - 286
+ 1.  A paragraph
+     with two lines.
+
+         indented code
+
+     > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 287
+  1.  A paragraph
+      with two lines.
+
+          indented code
+
+      > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 288
+   1.  A paragraph
+       with two lines.
+
+           indented code
+
+       > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 289
+    1.  A paragraph
+        with two lines.
+
+            indented code
+
+        > A block quote.
+<<<
+<pre><code>1.  A paragraph
+    with two lines.
+
+        indented code
+
+    &gt; A block quote.
+</code></pre>
+>>> List items - 290
+  1.  A paragraph
+with two lines.
+
+          indented code
+
+      > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 291
+  1.  A paragraph
+    with two lines.
+<<<
+<ol>
+<li>A paragraph
+with two lines.</li>
+</ol>
+>>> List items - 292
+> 1. > Blockquote
+continued here.
+<<<
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+>>> List items - 293
+> 1. > Blockquote
+> continued here.
+<<<
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+>>> List items - 294
+- foo
+  - bar
+    - baz
+      - boo
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz
+<ul>
+<li>boo</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> List items - 295
+- foo
+ - bar
+  - baz
+   - boo
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+<li>baz</li>
+<li>boo</li>
+</ul>
+>>> List items - 296
+10) foo
+    - bar
+<<<
+<ol start="10">
+<li>foo
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+>>> List items - 297
+10) foo
+   - bar
+<<<
+<ol start="10">
+<li>foo</li>
+</ol>
+<ul>
+<li>bar</li>
+</ul>
+>>> List items - 298
+- - foo
+<<<
+<ul>
+<li>
+<ul>
+<li>foo</li>
+</ul>
+</li>
+</ul>
+>>> List items - 299
+1. - 2. foo
+<<<
+<ol>
+<li>
+<ul>
+<li>
+<ol start="2">
+<li>foo</li>
+</ol>
+</li>
+</ul>
+</li>
+</ol>
+>>> List items - 300
+- # Foo
+- Bar
+  ---
+  baz
+<<<
+<ul>
+<li>
+<h1>Foo</h1>
+</li>
+<li>
+<h2>Bar</h2>
+baz</li>
+</ul>
diff --git a/pkgs/markdown/test/common_mark/lists.unit b/pkgs/markdown/test/common_mark/lists.unit
new file mode 100644
index 0000000..fce59fe
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/lists.unit
@@ -0,0 +1,406 @@
+>>> Lists - 301
+- foo
+- bar
++ baz
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<ul>
+<li>baz</li>
+</ul>
+>>> Lists - 302
+1. foo
+2. bar
+3) baz
+<<<
+<ol>
+<li>foo</li>
+<li>bar</li>
+</ol>
+<ol start="3">
+<li>baz</li>
+</ol>
+>>> Lists - 303
+Foo
+- bar
+- baz
+<<<
+<p>Foo</p>
+<ul>
+<li>bar</li>
+<li>baz</li>
+</ul>
+>>> Lists - 304
+The number of windows in my house is
+14.  The number of doors is 6.
+<<<
+<p>The number of windows in my house is
+14.  The number of doors is 6.</p>
+>>> Lists - 305
+The number of windows in my house is
+1.  The number of doors is 6.
+<<<
+<p>The number of windows in my house is</p>
+<ol>
+<li>The number of doors is 6.</li>
+</ol>
+>>> Lists - 306
+- foo
+
+- bar
+
+
+- baz
+<<<
+<ul>
+<li>
+<p>foo</p>
+</li>
+<li>
+<p>bar</p>
+</li>
+<li>
+<p>baz</p>
+</li>
+</ul>
+>>> Lists - 307
+- foo
+  - bar
+    - baz
+
+
+      bim
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>
+<p>baz</p>
+<p>bim</p>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> Lists - 308
+- foo
+- bar
+
+<!-- -->
+
+- baz
+- bim
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<!-- -->
+<ul>
+<li>baz</li>
+<li>bim</li>
+</ul>
+>>> Lists - 309
+-   foo
+
+    notcode
+
+-   foo
+
+<!-- -->
+
+    code
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>notcode</p>
+</li>
+<li>
+<p>foo</p>
+</li>
+</ul>
+<!-- -->
+<pre><code>code
+</code></pre>
+>>> Lists - 310
+- a
+ - b
+  - c
+   - d
+  - e
+ - f
+- g
+<<<
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d</li>
+<li>e</li>
+<li>f</li>
+<li>g</li>
+</ul>
+>>> Lists - 311
+1. a
+
+  2. b
+
+   3. c
+<<<
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ol>
+>>> Lists - 312
+- a
+ - b
+  - c
+   - d
+    - e
+<<<
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d
+- e</li>
+</ul>
+>>> Lists - 313
+1. a
+
+  2. b
+
+    3. c
+<<<
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+</ol>
+<pre><code>3. c
+</code></pre>
+>>> Lists - 314
+- a
+- b
+
+- c
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ul>
+>>> Lists - 315
+* a
+*
+
+* c
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li></li>
+<li>
+<p>c</p>
+</li>
+</ul>
+>>> Lists - 316
+- a
+- b
+
+  c
+- d
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+>>> Lists - 317
+- a
+- b
+
+  [ref]: /url
+- d
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+>>> Lists - 318
+- a
+- ```
+  b
+
+
+  ```
+- c
+<<<
+<ul>
+<li>a</li>
+<li>
+<pre><code>b
+
+
+</code></pre>
+</li>
+<li>c</li>
+</ul>
+>>> Lists - 319
+- a
+  - b
+
+    c
+- d
+<<<
+<ul>
+<li>a
+<ul>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+</ul>
+</li>
+<li>d</li>
+</ul>
+>>> Lists - 320
+* a
+  > b
+  >
+* c
+<<<
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+</li>
+<li>c</li>
+</ul>
+>>> Lists - 321
+- a
+  > b
+  ```
+  c
+  ```
+- d
+<<<
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+<pre><code>c
+</code></pre>
+</li>
+<li>d</li>
+</ul>
+>>> Lists - 322
+- a
+<<<
+<ul>
+<li>a</li>
+</ul>
+>>> Lists - 323
+- a
+  - b
+<<<
+<ul>
+<li>a
+<ul>
+<li>b</li>
+</ul>
+</li>
+</ul>
+>>> Lists - 324
+1. ```
+   foo
+   ```
+
+   bar
+<<<
+<ol>
+<li>
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+</li>
+</ol>
+>>> Lists - 325
+* foo
+  * bar
+
+  baz
+<<<
+<ul>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+<p>baz</p>
+</li>
+</ul>
+>>> Lists - 326
+- a
+  - b
+  - c
+
+- d
+  - e
+  - f
+<<<
+<ul>
+<li>
+<p>a</p>
+<ul>
+<li>b</li>
+<li>c</li>
+</ul>
+</li>
+<li>
+<p>d</p>
+<ul>
+<li>e</li>
+<li>f</li>
+</ul>
+</li>
+</ul>
diff --git a/pkgs/markdown/test/common_mark/paragraphs.unit b/pkgs/markdown/test/common_mark/paragraphs.unit
new file mode 100644
index 0000000..a03f4a1
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/paragraphs.unit
@@ -0,0 +1,59 @@
+>>> Paragraphs - 219
+aaa
+
+bbb
+<<<
+<p>aaa</p>
+<p>bbb</p>
+>>> Paragraphs - 220
+aaa
+bbb
+
+ccc
+ddd
+<<<
+<p>aaa
+bbb</p>
+<p>ccc
+ddd</p>
+>>> Paragraphs - 221
+aaa
+
+
+bbb
+<<<
+<p>aaa</p>
+<p>bbb</p>
+>>> Paragraphs - 222
+  aaa
+ bbb
+<<<
+<p>aaa
+bbb</p>
+>>> Paragraphs - 223
+aaa
+             bbb
+                                       ccc
+<<<
+<p>aaa
+bbb
+ccc</p>
+>>> Paragraphs - 224
+   aaa
+bbb
+<<<
+<p>aaa
+bbb</p>
+>>> Paragraphs - 225
+    aaa
+bbb
+<<<
+<pre><code>aaa
+</code></pre>
+<p>bbb</p>
+>>> Paragraphs - 226
+aaa     
+bbb     
+<<<
+<p>aaa<br />
+bbb</p>
diff --git a/pkgs/markdown/test/common_mark/precedence.unit b/pkgs/markdown/test/common_mark/precedence.unit
new file mode 100644
index 0000000..4359ce9
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/precedence.unit
@@ -0,0 +1,8 @@
+>>> Precedence - 42
+- `one
+- two`
+<<<
+<ul>
+<li>`one</li>
+<li>two`</li>
+</ul>
diff --git a/pkgs/markdown/test/common_mark/raw_html.unit b/pkgs/markdown/test/common_mark/raw_html.unit
new file mode 100644
index 0000000..329f96a
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/raw_html.unit
@@ -0,0 +1,95 @@
+>>> Raw HTML - 613
+<a><bab><c2c>
+<<<
+<p><a><bab><c2c></p>
+>>> Raw HTML - 614
+<a/><b2/>
+<<<
+<p><a/><b2/></p>
+>>> Raw HTML - 615
+<a  /><b2
+data="foo" >
+<<<
+<p><a  /><b2
+data="foo" ></p>
+>>> Raw HTML - 616
+<a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 />
+<<<
+<p><a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 /></p>
+>>> Raw HTML - 617
+Foo <responsive-image src="foo.jpg" />
+<<<
+<p>Foo <responsive-image src="foo.jpg" /></p>
+>>> Raw HTML - 618
+<33> <__>
+<<<
+<p>&lt;33&gt; &lt;__&gt;</p>
+>>> Raw HTML - 619
+<a h*#ref="hi">
+<<<
+<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
+>>> Raw HTML - 620
+<a href="hi'> <a href=hi'>
+<<<
+<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
+>>> Raw HTML - 621
+< a><
+foo><bar/ >
+<foo bar=baz
+bim!bop />
+<<<
+<p>&lt; a&gt;&lt;
+foo&gt;&lt;bar/ &gt;
+&lt;foo bar=baz
+bim!bop /&gt;</p>
+>>> Raw HTML - 622
+<a href='bar'title=title>
+<<<
+<p>&lt;a href='bar'title=title&gt;</p>
+>>> Raw HTML - 623
+</a></foo >
+<<<
+<p></a></foo ></p>
+>>> Raw HTML - 624
+</a href="foo">
+<<<
+<p>&lt;/a href=&quot;foo&quot;&gt;</p>
+>>> Raw HTML - 625
+foo <!-- this is a --
+comment - with hyphens -->
+<<<
+<p>foo &lt;!-- this is a --
+comment - with hyphens --&gt;</p>
+>>> Raw HTML - 626
+foo <!--> foo -->
+
+foo <!---> foo -->
+<<<
+<p>foo &lt;!--&gt; foo --&gt;</p>
+<p>foo &lt;!---&gt; foo --&gt;</p>
+>>> Raw HTML - 627
+foo <?php echo $a; ?>
+<<<
+<p>foo <?php echo $a; ?></p>
+>>> Raw HTML - 628
+foo <!ELEMENT br EMPTY>
+<<<
+<p>foo <!ELEMENT br EMPTY></p>
+>>> Raw HTML - 629
+foo <![CDATA[>&<]]>
+<<<
+<p>foo <![CDATA[>&<]]></p>
+>>> Raw HTML - 630
+foo <a href="&ouml;">
+<<<
+<p>foo <a href="&ouml;"></p>
+>>> Raw HTML - 631
+foo <a href="\*">
+<<<
+<p>foo <a href="\*"></p>
+>>> Raw HTML - 632
+<a href="\"">
+<<<
+<p>&lt;a href=&quot;&quot;&quot;&gt;</p>
diff --git a/pkgs/markdown/test/common_mark/setext_headings.unit b/pkgs/markdown/test/common_mark/setext_headings.unit
new file mode 100644
index 0000000..702c72c
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/setext_headings.unit
@@ -0,0 +1,229 @@
+>>> Setext headings - 80
+Foo *bar*
+=========
+
+Foo *bar*
+---------
+<<<
+<h1>Foo <em>bar</em></h1>
+<h2>Foo <em>bar</em></h2>
+>>> Setext headings - 81
+Foo *bar
+baz*
+====
+<<<
+<h1>Foo <em>bar
+baz</em></h1>
+>>> Setext headings - 82
+  Foo *bar
+baz*	
+====
+<<<
+<h1>  Foo <em>bar
+baz</em></h1>
+>>> Setext headings - 83
+Foo
+-------------------------
+
+Foo
+=
+<<<
+<h2>Foo</h2>
+<h1>Foo</h1>
+>>> Setext headings - 84
+   Foo
+---
+
+  Foo
+-----
+
+  Foo
+  ===
+<<<
+<h2>   Foo</h2>
+<h2>  Foo</h2>
+<h1>  Foo</h1>
+>>> Setext headings - 85
+    Foo
+    ---
+
+    Foo
+---
+<<<
+<pre><code>Foo
+---
+
+Foo
+</code></pre>
+<hr />
+>>> Setext headings - 86
+Foo
+   ----      
+<<<
+<h2>Foo</h2>
+>>> Setext headings - 87
+Foo
+    ---
+<<<
+<p>Foo
+---</p>
+>>> Setext headings - 88
+Foo
+= =
+
+Foo
+--- -
+<<<
+<p>Foo
+= =</p>
+<p>Foo</p>
+<hr />
+>>> Setext headings - 89
+Foo  
+-----
+<<<
+<h2>Foo</h2>
+>>> Setext headings - 90
+Foo\
+----
+<<<
+<h2>Foo\</h2>
+>>> Setext headings - 91
+`Foo
+----
+`
+
+<a title="a lot
+---
+of dashes"/>
+<<<
+<h2>`Foo</h2>
+<p>`</p>
+<h2>&lt;a title=&quot;a lot</h2>
+<p>of dashes&quot;/&gt;</p>
+>>> Setext headings - 92
+> Foo
+---
+<<<
+<blockquote>
+<p>Foo</p>
+</blockquote>
+<hr />
+>>> Setext headings - 93
+> foo
+bar
+===
+<<<
+<blockquote>
+<p>foo
+bar
+===</p>
+</blockquote>
+>>> Setext headings - 94
+- Foo
+---
+<<<
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+>>> Setext headings - 95
+Foo
+Bar
+---
+<<<
+<h2>Foo
+Bar</h2>
+>>> Setext headings - 96
+---
+Foo
+---
+Bar
+---
+Baz
+<<<
+<hr />
+<h2>Foo</h2>
+<h2>Bar</h2>
+<p>Baz</p>
+>>> Setext headings - 97
+
+====
+<<<
+<p>====</p>
+>>> Setext headings - 98
+---
+---
+<<<
+<hr />
+<hr />
+>>> Setext headings - 99
+- foo
+-----
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+>>> Setext headings - 100
+    foo
+---
+<<<
+<pre><code>foo
+</code></pre>
+<hr />
+>>> Setext headings - 101
+> foo
+-----
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+>>> Setext headings - 102
+\> foo
+------
+<<<
+<h2>&gt; foo</h2>
+>>> Setext headings - 103
+Foo
+
+bar
+---
+baz
+<<<
+<p>Foo</p>
+<h2>bar</h2>
+<p>baz</p>
+>>> Setext headings - 104
+Foo
+bar
+
+---
+
+baz
+<<<
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+>>> Setext headings - 105
+Foo
+bar
+* * *
+baz
+<<<
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+>>> Setext headings - 106
+Foo
+bar
+\---
+baz
+<<<
+<p>Foo
+bar
+---
+baz</p>
diff --git a/pkgs/markdown/test/common_mark/soft_line_breaks.unit b/pkgs/markdown/test/common_mark/soft_line_breaks.unit
new file mode 100644
index 0000000..88e82f2
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/soft_line_breaks.unit
@@ -0,0 +1,12 @@
+>>> Soft line breaks - 648
+foo
+baz
+<<<
+<p>foo
+baz</p>
+>>> Soft line breaks - 649
+foo 
+ baz
+<<<
+<p>foo
+baz</p>
diff --git a/pkgs/markdown/test/common_mark/tabs.unit b/pkgs/markdown/test/common_mark/tabs.unit
new file mode 100644
index 0000000..1239481
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/tabs.unit
@@ -0,0 +1,87 @@
+>>> Tabs - 1
+	foo	baz		bim
+<<<
+<pre><code>foo	baz		bim
+</code></pre>
+>>> Tabs - 2
+  	foo	baz		bim
+<<<
+<pre><code>foo	baz		bim
+</code></pre>
+>>> Tabs - 3
+    a	a
+    ὐ	a
+<<<
+<pre><code>a	a
+ὐ	a
+</code></pre>
+>>> Tabs - 4
+  - foo
+
+	bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> Tabs - 5
+- foo
+
+		bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<pre><code>  bar
+</code></pre>
+</li>
+</ul>
+>>> Tabs - 6
+>		foo
+<<<
+<blockquote>
+<pre><code>foo
+</code></pre>
+</blockquote>
+>>> Tabs - 7
+-		foo
+<<<
+<ul>
+<li>
+<pre><code>  foo
+</code></pre>
+</li>
+</ul>
+>>> Tabs - 8
+    foo
+	bar
+<<<
+<pre><code>foo
+bar
+</code></pre>
+>>> Tabs - 9
+ - foo
+   - bar
+	 - baz
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> Tabs - 10
+#	Foo
+<<<
+<h1>Foo</h1>
+>>> Tabs - 11
+*	*	*	
+<<<
+<hr />
diff --git a/pkgs/markdown/test/common_mark/textual_content.unit b/pkgs/markdown/test/common_mark/textual_content.unit
new file mode 100644
index 0000000..0069e0f
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/textual_content.unit
@@ -0,0 +1,12 @@
+>>> Textual content - 650
+hello $.;'there
+<<<
+<p>hello $.;'there</p>
+>>> Textual content - 651
+Foo χρῆν
+<<<
+<p>Foo χρῆν</p>
+>>> Textual content - 652
+Multiple     spaces
+<<<
+<p>Multiple     spaces</p>
diff --git a/pkgs/markdown/test/common_mark/thematic_breaks.unit b/pkgs/markdown/test/common_mark/thematic_breaks.unit
new file mode 100644
index 0000000..b4d490f
--- /dev/null
+++ b/pkgs/markdown/test/common_mark/thematic_breaks.unit
@@ -0,0 +1,126 @@
+>>> Thematic breaks - 43
+***
+---
+___
+<<<
+<hr />
+<hr />
+<hr />
+>>> Thematic breaks - 44
++++
+<<<
+<p>+++</p>
+>>> Thematic breaks - 45
+===
+<<<
+<p>===</p>
+>>> Thematic breaks - 46
+--
+**
+__
+<<<
+<p>--
+**
+__</p>
+>>> Thematic breaks - 47
+ ***
+  ***
+   ***
+<<<
+<hr />
+<hr />
+<hr />
+>>> Thematic breaks - 48
+    ***
+<<<
+<pre><code>***
+</code></pre>
+>>> Thematic breaks - 49
+Foo
+    ***
+<<<
+<p>Foo
+***</p>
+>>> Thematic breaks - 50
+_____________________________________
+<<<
+<hr />
+>>> Thematic breaks - 51
+ - - -
+<<<
+<hr />
+>>> Thematic breaks - 52
+ **  * ** * ** * **
+<<<
+<hr />
+>>> Thematic breaks - 53
+-     -      -      -
+<<<
+<hr />
+>>> Thematic breaks - 54
+- - - -    
+<<<
+<hr />
+>>> Thematic breaks - 55
+_ _ _ _ a
+
+a------
+
+---a---
+<<<
+<p>_ _ _ _ a</p>
+<p>a------</p>
+<p>---a---</p>
+>>> Thematic breaks - 56
+ *-*
+<<<
+<p><em>-</em></p>
+>>> Thematic breaks - 57
+- foo
+***
+- bar
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+<ul>
+<li>bar</li>
+</ul>
+>>> Thematic breaks - 58
+Foo
+***
+bar
+<<<
+<p>Foo</p>
+<hr />
+<p>bar</p>
+>>> Thematic breaks - 59
+Foo
+---
+bar
+<<<
+<h2>Foo</h2>
+<p>bar</p>
+>>> Thematic breaks - 60
+* Foo
+* * *
+* Bar
+<<<
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+<ul>
+<li>Bar</li>
+</ul>
+>>> Thematic breaks - 61
+- Foo
+- * * *
+<<<
+<ul>
+<li>Foo</li>
+<li>
+<hr />
+</li>
+</ul>
diff --git a/pkgs/markdown/test/crash_test.dart b/pkgs/markdown/test/crash_test.dart
new file mode 100644
index 0000000..a6f427d
--- /dev/null
+++ b/pkgs/markdown/test/crash_test.dart
@@ -0,0 +1,226 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:http/http.dart' as http;
+import 'package:http/retry.dart' as http;
+import 'package:markdown/markdown.dart';
+import 'package:pool/pool.dart';
+import 'package:tar/tar.dart';
+import 'package:test/test.dart';
+
+// ignore_for_file: avoid_dynamic_calls
+
+const extensions = [
+  '.md',
+  '.mkd',
+  '.mdwn',
+  '.mdown',
+  '.mdtxt',
+  '.mdtext',
+  '.markdown',
+  'README',
+  'CHANGELOG',
+];
+
+void main() async {
+  // This test is a really dumb and very slow crash-test.
+  // It downloads the latest package version for each package on pub.dev
+  // and tries to parse all `*.md` files in the package, counting the number
+  // of times where the parser throws.
+  //
+  // Needless to say, this test is very slow and running it eats a lot of CPU.
+  // But it's a fairly good way to try a lot of real-world markdown text to see
+  // if any of the poorly formatted markdown causes the parser to crash.
+  test(
+    'crash test',
+    () async {
+      final started = DateTime.now();
+      var lastStatus = DateTime(0);
+      void status(String Function() message) {
+        if (DateTime.now().difference(lastStatus) >
+            const Duration(seconds: 30)) {
+          lastStatus = DateTime.now();
+          print(message());
+        }
+      }
+
+      final c = http.RetryClient(http.Client());
+      Future<dynamic> getJson(String url) async {
+        final u = Uri.tryParse(url);
+        if (u == null) {
+          return null;
+        }
+        try {
+          final data = await c.read(u);
+          try {
+            return jsonDecode(data);
+          } on FormatException {
+            return null;
+          }
+        } on http.ClientException {
+          return null;
+        } on IOException {
+          return null;
+        }
+      }
+
+      final packages =
+          ((await getJson('https://pub.dev/api/package-names'))['packages']
+                  as List)
+              .cast<String>();
+      //.take(3).toList(); // useful when testing
+      print('## Found ${packages.length} packages to scan');
+
+      var count = 0;
+      final pool = Pool(50);
+      final packageVersions = <PackageVersion>[];
+      await Future.wait(packages.map((package) async {
+        await pool.withResource(() async {
+          final response = await getJson(
+            'https://pub.dev/api/packages/$package',
+          );
+          final entry = response['latest'] as Map?;
+          if (entry != null) {
+            packageVersions.add(PackageVersion(
+              package: package,
+              version: entry['version'] as String,
+              archiveUrl: entry['archive_url'] as String,
+            ));
+          }
+          count++;
+          status(
+            () => 'Listed versions for $count / ${packages.length} packages',
+          );
+        });
+      }));
+
+      print('## Found ${packageVersions.length} package versions to scan');
+
+      count = 0;
+      final errors = <String>[];
+      var skipped = 0;
+      await Future.wait(packageVersions.map((pv) async {
+        await pool.withResource(() async {
+          final archiveUrl = Uri.tryParse(pv.archiveUrl);
+          if (archiveUrl == null) {
+            skipped++;
+            return;
+          }
+          late List<int> archive;
+          try {
+            archive = await c.readBytes(archiveUrl);
+          } on http.ClientException {
+            skipped++;
+            return;
+          } on IOException {
+            skipped++;
+            return;
+          }
+
+          final result = await _findMarkdownIssues(
+            pv.package,
+            pv.version,
+            archive,
+          );
+
+          // If tar decoding fails.
+          if (result == null) {
+            skipped++;
+            return;
+          }
+
+          errors.addAll(result);
+          result.forEach(print);
+        });
+        count++;
+        status(() =>
+            'Scanned $count / ${packageVersions.length} (skipped $skipped),'
+            ' found ${errors.length} issues');
+      }));
+
+      await pool.close();
+      c.close();
+
+      print('## Finished scanning');
+      print('Scanned ${packageVersions.length} package versions in '
+          '${DateTime.now().difference(started)}');
+
+      if (errors.isNotEmpty) {
+        print('Found issues:');
+        errors.forEach(print);
+        fail('Found ${errors.length} cases where markdownToHtml threw!');
+      }
+    },
+    timeout: const Timeout(Duration(hours: 5)),
+    tags: 'crash_test', // skipped by default, see: dart_test.yaml
+  );
+}
+
+class PackageVersion {
+  final String package;
+  final String version;
+  final String archiveUrl;
+
+  PackageVersion({
+    required this.package,
+    required this.version,
+    required this.archiveUrl,
+  });
+}
+
+/// Scans [gzippedArchive] for markdown files and tries to parse them all.
+///
+/// Creates a list of issues that arose when parsing markdown files. The
+/// [package] and [version] strings are used to construct nice issues.
+/// An issue string may be multi-line, but should be printable.
+///
+/// Returns a list of issues, or `null` if decoding and parsing [gzippedArchive]
+/// failed.
+Future<List<String>?> _findMarkdownIssues(
+  String package,
+  String version,
+  List<int> gzippedArchive,
+) async {
+  return Isolate.run<List<String>?>(() async {
+    try {
+      final archive = gzip.decode(gzippedArchive);
+      final issues = <String>[];
+      await TarReader.forEach(Stream.value(archive), (entry) async {
+        if (extensions.any((ext) => entry.name.endsWith(ext))) {
+          late String contents;
+          try {
+            final bytes = await http.ByteStream(entry.contents).toBytes();
+            contents = utf8.decode(bytes);
+          } on FormatException {
+            return; // ignore invalid utf8
+          }
+          final start = DateTime.now();
+          try {
+            markdownToHtml(
+              contents,
+              extensionSet: ExtensionSet.gitHubWeb,
+            );
+          } catch (err, st) {
+            issues.add(
+                'package:$package-$version/${entry.name}, throws: $err\n$st');
+          }
+          final time = DateTime.now().difference(start);
+          if (time.inSeconds > 30) {
+            issues.add(
+                'package:$package-$version/${entry.name} took $time to process');
+          }
+        }
+      });
+      return issues;
+    } on FormatException {
+      return null;
+    }
+  }).timeout(const Duration(minutes: 2), onTimeout: () {
+    return ['package:$package-$version failed to be processed in 2 minutes'];
+  });
+}
diff --git a/pkgs/markdown/test/document_test.dart b/pkgs/markdown/test/document_test.dart
new file mode 100644
index 0000000..3e30697
--- /dev/null
+++ b/pkgs/markdown/test/document_test.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'package:markdown/markdown.dart';
+import 'package:markdown/src/util.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('Document', () {
+    test('encodeHtml prevents less than and ampersand escaping', () {
+      final document = Document(encodeHtml: false);
+      final result = document.parseInline('< &');
+      expect(result, hasLength(1));
+      expect(
+        result[0],
+        const TypeMatcher<Text>().having((e) => e.text, 'text', equals('< &')),
+      );
+    });
+
+    group('with encodeHtml enabled', () {
+      final document = Document();
+
+      test('encodes HTML in an inline code snippet', () {
+        final result =
+            document.parseInline('``<p>Hello <em>Markdown</em></p>``');
+        final codeSnippet = result.single as Element;
+        expect(
+          codeSnippet.textContent,
+          equals('&lt;p&gt;Hello &lt;em&gt;Markdown&lt;/em&gt;&lt;/p&gt;'),
+        );
+      });
+
+      test('encodes HTML in a fenced code block', () {
+        final lines = '```\n<p>Hello <em>Markdown</em></p>\n```\n'.toLines();
+        final result = document.parseLineList(lines);
+        final codeBlock = result.single as Element;
+        expect(
+          codeBlock.textContent,
+          equals('&lt;p&gt;Hello &lt;em&gt;Markdown&lt;/em&gt;&lt;/p&gt;\n'),
+        );
+      });
+
+      test('encodes HTML in an indented code block', () {
+        final lines = '    <p>Hello <em>Markdown</em></p>\n'.toLines();
+        final result = document.parseLineList(lines);
+        final codeBlock = result.single as Element;
+        expect(
+          codeBlock.textContent,
+          equals('&lt;p&gt;Hello &lt;em&gt;Markdown&lt;/em&gt;&lt;/p&gt;\n'),
+        );
+      });
+
+      test('encodeHtml spaces are preserved in text', () {
+        // Example to get a <p> tag rendered before a text node.
+        const contents = 'Sample\n\n<pre>\n A\n B\n</pre>';
+        final document = Document();
+        final nodes = BlockParser(contents.toLines(), document).parseLines();
+        final result = HtmlRenderer().render(nodes);
+        expect(result, '<p>\n</p>\n<pre>\n A\n B\n</pre>');
+      });
+
+      test('encode double quotes, greater than, and less than when escaped',
+          () {
+        const contents = r'\>\"\< Hello';
+        final document = Document();
+        final nodes = document.parseInline(contents);
+        expect(nodes, hasLength(1));
+        expect(
+          nodes.single,
+          const TypeMatcher<Text>().having(
+            (e) => e.text,
+            'text',
+            '&gt;&quot;&lt; Hello',
+          ),
+        );
+      });
+    });
+
+    group('with encodeHtml disabled', () {
+      final document = Document(encodeHtml: false);
+
+      test('leaves HTML alone, in a code snippet', () {
+        final result =
+            document.parseInline('```<p>Hello <em>Markdown</em></p>```');
+        final codeSnippet = result.single as Element;
+        expect(
+          codeSnippet.textContent,
+          equals('<p>Hello <em>Markdown</em></p>'),
+        );
+      });
+
+      test('leaves HTML alone, in a fenced code block', () {
+        final lines = '```\n<p>Hello <em>Markdown</em></p>\n```\n'.toLines();
+        final result = document.parseLineList(lines);
+        final codeBlock = result.single as Element;
+        expect(
+          codeBlock.textContent,
+          equals('<p>Hello <em>Markdown</em></p>\n'),
+        );
+      });
+
+      test('leaves HTML alone, in an indented code block', () {
+        final lines = '    <p>Hello <em>Markdown</em></p>\n'.toLines();
+        final result = document.parseLineList(lines);
+        final codeBlock = result.single as Element;
+        expect(
+          codeBlock.textContent,
+          equals('<p>Hello <em>Markdown</em></p>\n'),
+        );
+      });
+
+      test('leave double quotes, greater than, and less than when escaped', () {
+        const contents = r'\>\"\< Hello';
+        final document = Document(encodeHtml: false);
+        final nodes = document.parseInline(contents);
+        expect(nodes, hasLength(1));
+        expect(
+          nodes.single,
+          const TypeMatcher<Text>().having((e) => e.text, 'text', '>"< Hello'),
+        );
+      });
+    });
+  });
+}
diff --git a/pkgs/markdown/test/extensions/alert_extension.unit b/pkgs/markdown/test/extensions/alert_extension.unit
new file mode 100644
index 0000000..9a21f18
--- /dev/null
+++ b/pkgs/markdown/test/extensions/alert_extension.unit
@@ -0,0 +1,162 @@
+>>> type note
+> [!NoTe]
+> Test note alert.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>Test note alert.</p>
+</div>
+>>> type tip
+> [!TiP]
+> Test tip alert.
+<<<
+<div class="markdown-alert markdown-alert-tip">
+<p class="markdown-alert-title">Tip</p>
+<p>Test tip alert.</p>
+</div>
+>>> type important
+> [!ImpoRtanT]
+> Test important alert.
+<<<
+<div class="markdown-alert markdown-alert-important">
+<p class="markdown-alert-title">Important</p>
+<p>Test important alert.</p>
+</div>
+>>> type warning
+> [!WarNinG]
+> Test warning alert.
+<<<
+<div class="markdown-alert markdown-alert-warning">
+<p class="markdown-alert-title">Warning</p>
+<p>Test warning alert.</p>
+</div>
+>>> type caution
+> [!CauTioN]
+> Test caution alert.
+<<<
+<div class="markdown-alert markdown-alert-caution">
+<p class="markdown-alert-title">Caution</p>
+<p>Test caution alert.</p>
+</div>
+>>> invalid type
+> [!foo]
+> Test foo alert.
+<<<
+<blockquote>
+<p>[!foo]
+Test foo alert.</p>
+</blockquote>
+>>> contents can both contain/not contain starting quote
+> [!NOTE]
+Test note alert.
+>Test note alert x2.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>Test note alert.
+Test note alert x2.</p>
+</div>
+>>> spaces everywhere
+ >  [!NOTE]
+>   Test note alert.
+  > Test note alert x2.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>Test note alert.
+Test note alert x2.</p>
+</div>
+>>> title has 3 more spaces then fallback to blockquote
+>    [!NOTE]
+>   Test blockquote.
+<<<
+<blockquote>
+<p>[!NOTE]
+Test blockquote.</p>
+</blockquote>
+>>> nested blockquote
+> [!NOTE]
+>> Test nested blockquote.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<blockquote>
+<p>Test nested blockquote.</p>
+</blockquote>
+</div>
+>>> escape brackets
+> \[!note\]
+> Test escape brackets.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>Test escape brackets.</p>
+</div>
+>>> terminates properly
+> [!note]
+> A sample note.
+
+Additional markdown text.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>A sample note.</p>
+</div>
+<p>Additional markdown text.</p>
+>>> supports multiple quoted lines
+> [!note]
+> A sample note
+> with two lines.
+
+Additional markdown text.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>A sample note
+with two lines.</p>
+</div>
+<p>Additional markdown text.</p>
+>>> supports multiple lines
+> [!note]
+> A sample note
+  with two lines.
+
+Additional markdown text.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>A sample note
+with two lines.</p>
+</div>
+<p>Additional markdown text.</p>
+>>> supports continuation lines
+> [!note]
+> A sample note
+with two lines.
+
+Additional markdown text.
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>A sample note
+with two lines.</p>
+</div>
+<p>Additional markdown text.</p>
+>>> crash repro #584.1
+> [!Warning]
+>
+> Some extensions won't work on dynamic types.
+<<<
+<div class="markdown-alert markdown-alert-warning">
+<p class="markdown-alert-title">Warning</p>
+<p>Some extensions won't work on dynamic types.</p>
+</div>
+>>> crash repro #584.2
+> [!NOTE]
+> 
+> if you receive the following error:
+<<<
+<div class="markdown-alert markdown-alert-note">
+<p class="markdown-alert-title">Note</p>
+<p>if you receive the following error:</p>
+</div>
diff --git a/pkgs/markdown/test/extensions/autolink_extension.unit b/pkgs/markdown/test/extensions/autolink_extension.unit
new file mode 100644
index 0000000..4a07fdc
--- /dev/null
+++ b/pkgs/markdown/test/extensions/autolink_extension.unit
@@ -0,0 +1,10 @@
+>>> not a link 
+mhttp://www.foo.com
+<<<
+<p>mhttp://www.foo.com</p>
+>>> following a newline
+m
+http://www.foo.com
+<<<
+<p>m
+<a href="http://www.foo.com">http://www.foo.com</a></p>
\ No newline at end of file
diff --git a/pkgs/markdown/test/extensions/emojis.unit b/pkgs/markdown/test/extensions/emojis.unit
new file mode 100644
index 0000000..00197e5
--- /dev/null
+++ b/pkgs/markdown/test/extensions/emojis.unit
@@ -0,0 +1,42 @@
+>>> within a paragraph
+I love to :smile:.
+
+<<<
+<p>I love to 😄.</p>
+>>> within other inline syntax
+I *love to :smile:*
+<<<
+<p>I <em>love to 😄</em></p>
+>>> within blockquote
+> I love to :smile:.
+<<<
+<blockquote>
+<p>I love to 😄.</p>
+</blockquote>
+>>> within code block
+    I love to :smile:
+<<<
+<pre><code>I love to :smile:
+</code></pre>
+>>> within a link
+I love [to :smile:](http://www.google.com).
+<<<
+<p>I love <a href="http://www.google.com">to 😄</a>.</p>
+>>> within a reference link
+I love [to :smile:][].
+
+[to :smile:]: http://www.google.com
+<<<
+<p>I love <a href="http://www.google.com">to 😄</a>.</p>
+>>> within inline code
+I love to `:smile:`.
+<<<
+<p>I love to <code>:smile:</code>.</p>
+>>> with multiple code points
+Yay :australia:
+<<<
+<p>Yay 🇦🇺</p>
+>>> leaves unknown emojis alone
+I love :smiles:.
+<<<
+<p>I love :smiles:.</p>
diff --git a/pkgs/markdown/test/extensions/fenced_blockquotes.unit b/pkgs/markdown/test/extensions/fenced_blockquotes.unit
new file mode 100644
index 0000000..8124ad4
--- /dev/null
+++ b/pkgs/markdown/test/extensions/fenced_blockquotes.unit
@@ -0,0 +1,70 @@
+>>> simple block quote
+>>>
+# Foo
+bar
+baz
+>>>
+
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> has blank lines
+>>>
+
+foo
+
+
+
+
+bar
+
+
+>>>
+
+<<<
+<blockquote>
+<p>foo</p>
+<p>bar</p>
+</blockquote>
+>>> with nested block quote
+>>>
+foo
+> bar
+>>>
+
+<<<
+<blockquote>
+<p>foo</p>
+<blockquote>
+<p>bar</p>
+</blockquote>
+</blockquote>
+>>> with nested indented clode block
+>>>
+    foo
+    bar
+>>>
+
+<<<
+<blockquote>
+<pre><code>foo
+bar
+</code></pre>
+</blockquote>
+>>> with nested fenced clode block
+>>>
+```
+foo
+bar
+```
+>>>
+
+<<<
+<blockquote>
+<pre><code>foo
+bar
+</code></pre>
+</blockquote>
\ No newline at end of file
diff --git a/pkgs/markdown/test/extensions/fenced_code_blocks.unit b/pkgs/markdown/test/extensions/fenced_code_blocks.unit
new file mode 100644
index 0000000..596f49a
--- /dev/null
+++ b/pkgs/markdown/test/extensions/fenced_code_blocks.unit
@@ -0,0 +1,52 @@
+>>> without an optional language identifier
+```
+code
+```
+
+<<<
+<pre><code>code
+</code></pre>
+>>> with an optional language identifier
+```dart
+code
+```
+
+<<<
+<pre><code class="language-dart">code
+</code></pre>
+>>> escape HTML characters
+```
+<&>
+```
+
+<<<
+<pre><code>&lt;&amp;&gt;
+</code></pre>
+>>> Pandoc style without language identifier
+~~~~~
+code
+~~~~~
+
+<<<
+<pre><code>code
+</code></pre>
+>>> Pandoc style with language identifier
+~~~~~dart
+code
+~~~~~
+
+<<<
+<pre><code class="language-dart">code
+</code></pre>
+>>> Pandoc style with inner tildes row
+~~~~~
+~~~
+code
+~~~
+~~~~~
+
+<<<
+<pre><code>~~~
+code
+~~~
+</code></pre>
diff --git a/pkgs/markdown/test/extensions/footnote_block.unit b/pkgs/markdown/test/extensions/footnote_block.unit
new file mode 100644
index 0000000..ae730bf
--- /dev/null
+++ b/pkgs/markdown/test/extensions/footnote_block.unit
@@ -0,0 +1,288 @@
+>>> footnote reference in footnote definition
+
+Footnote 1 link[^first].
+
+[^first]: footnote reference in footnote definition[^first]
+
+<<<
+<p>Footnote 1 link<sup class="footnote-ref"><a href="#fn-first" id="fnref-first">1</a></sup>.</p>
+<section class="footnotes">
+<ol>
+<li id="fn-first">
+<p>footnote reference in footnote definition<sup class="footnote-ref"><a href="#fn-first" id="fnref-first-2">1</a></sup> <a href="#fnref-first" class="footnote-backref">↩</a> <a href="#fnref-first-2" class="footnote-backref">↩<sup class="footnote-ref">2</sup></a></p>
+</li>
+</ol>
+</section>
+>>> footnote reference cases
+[^fifth]: ending with another ']' and different order
+
+Footnote 1 link[^first].
+
+Footnote 2 link[^きゃくちゅう脚注].
+
+Footnote 3 link[^p1 p2].
+
+Footnote 4 link![^forth].
+
+Footnote 5 link![^fifth]].
+
+Footnote 6 link![^ sixth ].
+
+Footnote 7 link[^きゃくちゅう脚注].
+
+[^first]: Here is the footnote definition
+
+[^きゃくちゅう脚注]: unicode label and duplicated reference.
+
+[^p1 p2]: p1 p2
+
+[^ForTh]: start with '[' and with upper case
+
+[^sixth]: label-start-with-blank
+<<<
+<p>Footnote 1 link<sup class="footnote-ref"><a href="#fn-first" id="fnref-first">1</a></sup>.</p>
+<p>Footnote 2 link<sup class="footnote-ref"><a href="#fn-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8" id="fnref-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8">2</a></sup>.</p>
+<p>Footnote 3 link[^p1 p2].</p>
+<p>Footnote 4 link!<sup class="footnote-ref"><a href="#fn-ForTh" id="fnref-ForTh">3</a></sup>.</p>
+<p>Footnote 5 link!<sup class="footnote-ref"><a href="#fn-fifth" id="fnref-fifth">4</a></sup>].</p>
+<p>Footnote 6 link!<sup class="footnote-ref"><a href="#fn-sixth" id="fnref-sixth">5</a></sup>.</p>
+<p>Footnote 7 link<sup class="footnote-ref"><a href="#fn-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8" id="fnref-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8-2">2</a></sup>.</p>
+<p>[^p1 p2]: p1 p2</p>
+<section class="footnotes">
+<ol>
+<li id="fn-first">
+<p>Here is the footnote definition <a href="#fnref-first" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8">
+<p>unicode label and duplicated reference. <a href="#fnref-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8" class="footnote-backref">↩</a> <a href="#fnref-%E3%81%8D%E3%82%83%E3%81%8F%E3%81%A1%E3%82%85%E3%81%86%E8%84%9A%E6%B3%A8-2" class="footnote-backref">↩<sup class="footnote-ref">2</sup></a></p>
+</li>
+<li id="fn-ForTh">
+<p>start with '[' and with upper case <a href="#fnref-ForTh" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-fifth">
+<p>ending with another ']' and different order <a href="#fnref-fifth" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-sixth">
+<p>label-start-with-blank <a href="#fnref-sixth" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> footnote labels with special chars
+empty label[^] and blank label[^ ]
+
+some[^-] strange[^^] but[^\[] labels[^\[\]]
+
+[^]:
+[^ ]:
+
+[^-]: valid1
+
+[^^]:valid2
+
+[^\[]: valid3
+
+[^\[\]]: this-is-link-not-footnote
+<<<
+<p>empty label[^] and blank label[^ ]</p>
+<p>some<sup class="footnote-ref"><a href="#fn--" id="fnref--">1</a></sup> strange<sup class="footnote-ref"><a href="#fn-%5E" id="fnref-%5E">2</a></sup> but<sup class="footnote-ref"><a href="#fn-%5C%5B" id="fnref-%5C%5B">3</a></sup> labels<a href="this-is-link-not-footnote">^[]</a></p>
+<p>[^]:
+[^ ]:</p>
+<section class="footnotes">
+<ol>
+<li id="fn--">
+<p>valid1 <a href="#fnref--" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-%5E">
+<p>valid2 <a href="#fnref-%5E" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-%5C%5B">
+<p>valid3 <a href="#fnref-%5C%5B" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> footnote with paragraph
+test footnote[^first].
+
+[^first]: Footnote **can have markup**
+
+    and multiple paragraphs.
+
+"Smartypants, double quotes" and 'single quotes'
+<<<
+<p>test footnote<sup class="footnote-ref"><a href="#fn-first" id="fnref-first">1</a></sup>.</p>
+<p>&quot;Smartypants, double quotes&quot; and 'single quotes'</p>
+<section class="footnotes">
+<ol>
+<li id="fn-first">
+<p>Footnote <strong>can have markup</strong></p>
+<p>and multiple paragraphs. <a href="#fnref-first" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> footnote adjacent paragraph
+Here is a footnote reference,[^1]
+[^1]: Here is the footnote.
+    Subsequent paragraphs
+<<<
+<p>Here is a footnote reference,<sup class="footnote-ref"><a href="#fn-1" id="fnref-1">1</a></sup></p>
+<section class="footnotes">
+<ol>
+<li id="fn-1">
+<p>Here is the footnote.
+Subsequent paragraphs <a href="#fnref-1" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> footnote without ref
+Here is a footnote reference
+[^1]: Here is the footnote.
+<<<
+<p>Here is a footnote reference</p>
+>>> footnote example from github
+Here is a simple footnote[^1].
+
+A footnote can also have multiple lines[^2].
+
+You can also use words, to fit your writing style more closely[^note].
+
+[^1]: My reference.
+[^2]: Every new line should be prefixed with 2 spaces.
+  This allows you to have a footnote with multiple lines.
+[^note]:
+    Named footnotes will still render with numbers instead of the text but allow easier identification and linking.
+    This footnote also has been made with a different syntax using 4 spaces for new lines.
+<<<
+<p>Here is a simple footnote<sup class="footnote-ref"><a href="#fn-1" id="fnref-1">1</a></sup>.</p>
+<p>A footnote can also have multiple lines<sup class="footnote-ref"><a href="#fn-2" id="fnref-2">2</a></sup>.</p>
+<p>You can also use words, to fit your writing style more closely<sup class="footnote-ref"><a href="#fn-note" id="fnref-note">3</a></sup>.</p>
+<section class="footnotes">
+<ol>
+<li id="fn-1">
+<p>My reference. <a href="#fnref-1" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-2">
+<p>Every new line should be prefixed with 2 spaces.
+This allows you to have a footnote with multiple lines. <a href="#fnref-2" class="footnote-backref">↩</a></p>
+</li>
+<li id="fn-note">
+<p>Named footnotes will still render with numbers instead of the text but allow easier identification and linking.
+This footnote also has been made with a different syntax using 4 spaces for new lines. <a href="#fnref-note" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> ![^  **image**] without definition should be formatted: unlike github
+![^  **image**]
+<<<
+<p>![^  <strong>image</strong>]</p>
+>>> ![^  **image**] with definition should be image: unlike github
+![^  **image**]
+
+[^  **image**]: valid-link
+<<<
+<p><img src="valid-link" alt="^  image" /></p>
+>>> ![^  **image**] with definition should be plain html: unlike github
+![^  **image**]
+
+[^  **image**]: invalid link
+<<<
+<p>![^  <strong>image</strong>]</p>
+<p>[^  <strong>image</strong>]: invalid link</p>
+>>> ![ ^**image**] without definition should be formatted
+![ ^**image**]
+<<<
+<p>![ ^<strong>image</strong>]</p>
+>>> ![^ ^**image**] without definition should be formatted: unlike github
+![^ ^**image**]
+<<<
+<p>![^ ^<strong>image</strong>]</p>
+>>> ![^ ^**image**] with definition should be image: unlike github
+![^ ^**image**]
+
+[^ ^**image**]: valid-link
+<<<
+<p><img src="valid-link" alt="^ ^image" /></p>
+>>> [^  **label**] without definition should be formatted: unlike github
+[^  **label**]
+<<<
+<p>[^  <strong>label</strong>]</p>
+>>> [adc][^**link**] without definition should be formatted: unlike github
+[adc][^**link**]
+<<<
+<p>[adc][^<strong>link</strong>]</p>
+>>> [adc][^**link**] with definition should be footnotes:
+[adc][^**link**]
+
+[^**link**]: valid-link
+<<<
+<p>[adc]<sup class="footnote-ref"><a href="#fn-**link**" id="fnref-**link**">1</a></sup></p>
+<section class="footnotes">
+<ol>
+<li id="fn-**link**">
+<p>valid-link <a href="#fnref-**link**" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> \[^good] should be text
+\[^good]
+
+[^good]: good
+<<<
+<p>[^good]</p>
+>>>[^ nice] should be link
+[^ nice]
+
+[^ nice ]: good
+<<<
+<p><a href="good">^ nice</a></p>
+>>>[^ nice ] should be text
+[^ nice ]
+
+[^nice ]: good
+<<<
+<p>[^ nice ]</p>
+>>> [^\]] with definition should be link
+[^\]]
+
+[^\]]: good
+<<<
+<p><a href="good">^]</a></p>
+>>> [^a-\nb] with definition should be paragraph
+[^a-
+b]
+
+[^a-
+b]: good
+<<<
+<p><a href="good">^a-
+b</a></p>
+>>> [^a] with error definition should be text
+[^a]
+
+[^a\]: good
+<<<
+<p>[^a]</p>
+>>> [^a] with double definition contain '\]' should be text
+[^a]
+
+[^a\]:]: definition contain '\]'
+<<<
+<p>[^a]</p>
+>>> [^a] with double definition trailing should be footnote
+[^a]
+
+[^a]:]: good
+<<<
+<p><sup class="footnote-ref"><a href="#fn-a" id="fnref-a">1</a></sup></p>
+<section class="footnotes">
+<ol>
+<li id="fn-a">
+<p>]: good <a href="#fnref-a" class="footnote-backref">↩</a></p>
+</li>
+</ol>
+</section>
+>>> complete image link with definition would be image: unlike github
+![^image](example.png)
+
+[^image]: image footnote
+<<<
+<p><img src="example.png" alt="^image" /></p>
diff --git a/pkgs/markdown/test/extensions/headers_with_ids.unit b/pkgs/markdown/test/extensions/headers_with_ids.unit
new file mode 100644
index 0000000..7bad75c
--- /dev/null
+++ b/pkgs/markdown/test/extensions/headers_with_ids.unit
@@ -0,0 +1,41 @@
+>>> simple header
+# header
+
+<<<
+<h1 id="header">header</h1>
+>>> header that starts with garbage
+## 2. header again
+
+<<<
+<h2 id="2-header-again">2. header again</h2>
+>>> header with inline syntaxes
+### headers **rock** `etc.`
+
+<<<
+<h3 id="headers-rock-etc">headers <strong>rock</strong> <code>etc.</code></h3>
+>>> non-unique headers
+# header
+
+## header
+
+<<<
+<h1 id="header">header</h1>
+<h2 id="header-2">header</h2>
+>>> header starts with inline syntax
+# *headers* etc.
+<<<
+<h1 id="headers-etc"><em>headers</em> etc.</h1>
+>>> numbers-only headers (like a changelog)
+# 1.2.34
+
+## 1.23.4
+
+## 1.2.3+4
+<<<
+<h1 id="1234">1.2.34</h1>
+<h2 id="1234-2">1.23.4</h2>
+<h2 id="1234-3">1.2.3+4</h2>
+>>> no id
+# #
+<<<
+<h1></h1>
diff --git a/pkgs/markdown/test/extensions/inline_html.unit b/pkgs/markdown/test/extensions/inline_html.unit
new file mode 100644
index 0000000..1540118
--- /dev/null
+++ b/pkgs/markdown/test/extensions/inline_html.unit
@@ -0,0 +1,17 @@
+>>> within a paragraph
+Within a <em class="x">paragraph</EM>.
+
+<<<
+<p>Within a <em class="x">paragraph</EM>.</p>
+>>> not HTML
+Obviously, 3 < 5 and 7 > 2.
+Not HTML: <3>, <_a>, <>
+
+<<<
+<p>Obviously, 3 &lt; 5 and 7 &gt; 2.
+Not HTML: &lt;3&gt;, &lt;_a&gt;, &lt;&gt;</p>
+>>> "markdown" within a tag is not parsed
+Text <a href="_foo_">And "_foo_"</a>.
+
+<<<
+<p>Text <a href="_foo_">And &quot;<em>foo</em>&quot;</a>.</p>
diff --git a/pkgs/markdown/test/extensions/ordered_list_with_checkboxes.unit b/pkgs/markdown/test/extensions/ordered_list_with_checkboxes.unit
new file mode 100644
index 0000000..8503e56
--- /dev/null
+++ b/pkgs/markdown/test/extensions/ordered_list_with_checkboxes.unit
@@ -0,0 +1,79 @@
+>>> checkbox with space
+1. [ ] one
+2. [ ] two
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li class="task-list-item"><input type="checkbox"></input>two</li>
+</ol>
+>>> empty checkbox
+1. [] one
+2. [] two
+<<<
+<ol>
+<li>[] one</li>
+<li>[] two</li>
+</ol>
+>>> checkbox with x
+1. [x] one
+2. [x] two
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox" checked="true"></input>one</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>two</li>
+</ol>
+>>> checkbox with X
+1. [X] one
+2. [X] two
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox" checked="true"></input>one</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>two</li>
+</ol>
+>>> mixed checkboxes
+1. [ ] one
+2. [] two
+3. [x] three
+4. [X] four
+5. five
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li>[] two</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>three</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>four</li>
+<li>five</li>
+</ol>
+>>> mixed leading spaces
+1. [ ] zero
+2.  [ ] one
+3.   [ ] two
+4.    [ ] three
+5.     [ ] four
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>zero</li>
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li class="task-list-item"><input type="checkbox"></input>two</li>
+<li class="task-list-item"><input type="checkbox"></input>three</li>
+<li>
+<pre><code>[ ] four
+</code></pre>
+</li>
+</ol>
+>>> checkbox with empty content
+1. [ ] one
+2.
+3. 
+4. four
+5. [ ] five
+6.
+<<<
+<ol class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li></li>
+<li></li>
+<li>four</li>
+<li class="task-list-item"><input type="checkbox"></input>five</li>
+<li></li>
+</ol>
\ No newline at end of file
diff --git a/pkgs/markdown/test/extensions/setext_headers_with_ids.unit b/pkgs/markdown/test/extensions/setext_headers_with_ids.unit
new file mode 100644
index 0000000..b8ef022
--- /dev/null
+++ b/pkgs/markdown/test/extensions/setext_headers_with_ids.unit
@@ -0,0 +1,18 @@
+>>> h1
+text
+===
+
+<<<
+<h1 id="text">text</h1>
+>>> h2
+text
+---
+
+<<<
+<h2 id="text">text</h2>
+>>> header with inline syntax
+header *emphasised*
+===
+
+<<<
+<h1 id="header-emphasised">header <em>emphasised</em></h1>
diff --git a/pkgs/markdown/test/extensions/strikethrough.unit b/pkgs/markdown/test/extensions/strikethrough.unit
new file mode 100644
index 0000000..5222d91
--- /dev/null
+++ b/pkgs/markdown/test/extensions/strikethrough.unit
@@ -0,0 +1,24 @@
+>>> Missing leading whitespace
+word pas~~t~~ word
+<<<
+<p>word pas<del>t</del> word</p>
+>>> Missing trailing whitespace
+word ~~p~~ast word
+<<<
+<p>word <del>p</del>ast word</p>
+>>> Middle of word
+word p~~as~~t word
+<<<
+<p>word p<del>as</del>t word</p>
+>>> Whitespace after opening
+word~~ past~~ word
+<<<
+<p>word~~ past~~ word</p>
+>>> Whitespace before closing
+word ~~past ~~word
+<<<
+<p>word ~~past ~~word</p>
+>>> mixed with emphasis and order changes
+**~~first~~** ~~**second**~~
+<<<
+<p><strong><del>first</del></strong> <del><strong>second</strong></del></p>
diff --git a/pkgs/markdown/test/extensions/tables.unit b/pkgs/markdown/test/extensions/tables.unit
new file mode 100644
index 0000000..c7a8cae
--- /dev/null
+++ b/pkgs/markdown/test/extensions/tables.unit
@@ -0,0 +1,378 @@
+>>> basic table
+head | cells
+-----|------
+body | cells
+
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>cells</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td>cells</td>
+</tr>
+</tbody>
+</table>
+>>> multiple rows
+head | cells
+-----|------
+body | cells
+more | cells
+
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>cells</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td>cells</td>
+</tr>
+<tr>
+<td>more</td>
+<td>cells</td>
+</tr>
+</tbody>
+</table>
+>>> rows wrapped in pipes
+| head | cells |
+|------|-------|
+| body | cells |
+
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>cells</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td>cells</td>
+</tr>
+</tbody>
+</table>
+>>> rows wrapped in pipes, whitespace alignment row
+| head | cells |
+|  --  |  ---  |
+| body | cells |
+
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>cells</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td>cells</td>
+</tr>
+</tbody>
+</table>
+>>> rows wrapped in pipes, tabs in whitespace
+|	head	|	cells	|
+|	--	|	---	|
+|	body	|	cells	|
+
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>cells</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td>cells</td>
+</tr>
+</tbody>
+</table>
+>>> cells with inline syntax
+head `code` | _cells_
+------------|--------
+*text*      | <span>text</span>
+<<<
+<table>
+<thead>
+<tr>
+<th>head <code>code</code></th>
+<th><em>cells</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td><em>text</em></td>
+<td><span>text</span></td>
+</tr>
+</tbody>
+</table>
+>>> cells are parsed before inline syntax
+header | _foo | bar_
+-------|------------|---
+text   | text
+<<<
+<table>
+<thead>
+<tr>
+<th>header</th>
+<th>_foo</th>
+<th>bar_</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>text</td>
+<td>text</td>
+<td></td>
+</tr>
+</tbody>
+</table>
+>>> cells contain reference links
+header | header
+-------|--------
+text   | [link][here]
+
+[here]: http://url
+<<<
+<table>
+<thead>
+<tr>
+<th>header</th>
+<th>header</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>text</td>
+<td><a href="http://url">link</a></td>
+</tr>
+</tbody>
+</table>
+>>> one column tables
+head
+-----|
+body
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+</tr>
+</tbody>
+</table>
+>>> varying cells per row
+head | foo | bar
+-----|-----|-----
+body
+row with | two cells
+<<<
+<table>
+<thead>
+<tr>
+<th>head</th>
+<th>foo</th>
+<th>bar</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>body</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>row with</td>
+<td>two cells</td>
+<td></td>
+</tr>
+</tbody>
+</table>
+>>> left, center, and right alignment
+head | cells | here
+:----|:-----:|----:
+body | cells | here
+too | many | cells | here
+
+<<<
+<table>
+<thead>
+<tr>
+<th align="left">head</th>
+<th align="center">cells</th>
+<th align="right">here</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left">body</td>
+<td align="center">cells</td>
+<td align="right">here</td>
+</tr>
+<tr>
+<td align="left">too</td>
+<td align="center">many</td>
+<td align="right">cells</td>
+</tr>
+</tbody>
+</table>
+>>> left, center, and right alignment, with whitespace
+head | cells | here
+ :-- | :---: | ---:
+body | cells | here
+too | many | cells | here
+
+<<<
+<table>
+<thead>
+<tr>
+<th align="left">head</th>
+<th align="center">cells</th>
+<th align="right">here</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left">body</td>
+<td align="center">cells</td>
+<td align="right">here</td>
+</tr>
+<tr>
+<td align="left">too</td>
+<td align="center">many</td>
+<td align="right">cells</td>
+</tr>
+</tbody>
+</table>
+>>> escape pipe
+| Name     | Character |
+| ---      | ---       |
+| Backtick | `         |
+| Pipe     | \|        |
+
+<<<
+<table>
+<thead>
+<tr>
+<th>Name</th>
+<th>Character</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>Backtick</td>
+<td>`</td>
+</tr>
+<tr>
+<td>Pipe</td>
+<td>|</td>
+</tr>
+</tbody>
+</table>
+>>> escape pipe, preserve trailing whitespace
+| Name     | Character |
+| ---      | ---       |
+| Pipe     | \| abcdef |
+
+<<<
+<table>
+<thead>
+<tr>
+<th>Name</th>
+<th>Character</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>Pipe</td>
+<td>| abcdef</td>
+</tr>
+</tbody>
+</table>
+>>> trailing whitespace after final pipe
+| Name     | Character | 
+| ---      | ---       |	
+| Pipe     | abcdef    |
+<<<
+<table>
+<thead>
+<tr>
+<th>Name</th>
+<th>Character</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>Pipe</td>
+<td>abcdef</td>
+</tr>
+</tbody>
+</table>
+>>> issue #531
+| A | [B](url) | C |
+|---|---|
+|  a | b | c |
+<<<
+<p>| A | <a href="url">B</a> | C |
+|---|---|
+|  a | b | c |</p>
+>>> trailing whitespace after delimiter row
+| Name    | Value |
+| ---     | ---   |     
+| Foo     | bar   |
+<<<
+<table>
+<thead>
+<tr>
+<th>Name</th>
+<th>Value</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>Foo</td>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
+>>> can interrupt a paragraph
+paragraph
+foo | bar
+--- | ---
+baz | bim
+<<<
+<p>paragraph</p>
+<table>
+<thead>
+<tr>
+<th>foo</th>
+<th>bar</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>baz</td>
+<td>bim</td>
+</tr>
+</tbody>
+</table>
diff --git a/pkgs/markdown/test/extensions/unordered_list_with_checkboxes.unit b/pkgs/markdown/test/extensions/unordered_list_with_checkboxes.unit
new file mode 100644
index 0000000..f33161e
--- /dev/null
+++ b/pkgs/markdown/test/extensions/unordered_list_with_checkboxes.unit
@@ -0,0 +1,83 @@
+>>> checkbox with space
+* [ ] one
+* [ ] two
+<<<
+<ul class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li class="task-list-item"><input type="checkbox"></input>two</li>
+</ul>
+>>> empty checkbox
+* [] one
+* [] two
+<<<
+<ul>
+<li>[] one</li>
+<li>[] two</li>
+</ul>
+>>> checkbox with x
+* [x] one
+* [x] two
+<<<
+<ul class="contains-task-list">
+<li class="task-list-item"><input type="checkbox" checked="true"></input>one</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>two</li>
+</ul>
+>>> checkbox with X
+* [X] one
+* [X] two
+<<<
+<ul class="contains-task-list">
+<li class="task-list-item"><input type="checkbox" checked="true"></input>one</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>two</li>
+</ul>
+>>> mixed checkboxes
+* [ ] one
+* [] two
+* [x] three
+* [X] four
+* five
+<<<
+<ul class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li>[] two</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>three</li>
+<li class="task-list-item"><input type="checkbox" checked="true"></input>four</li>
+<li>five</li>
+</ul>
+>>> mixed leading spaces
+*[ ] zero
+* [ ] one
+*  [ ] two
+*   [ ] three
+*    [ ] four
+*     [ ] five
+<<<
+<p>*[ ] zero</p>
+<ul class="contains-task-list">
+<li class="task-list-item"><input type="checkbox"></input>one</li>
+<li class="task-list-item"><input type="checkbox"></input>two</li>
+<li class="task-list-item"><input type="checkbox"></input>three</li>
+<li class="task-list-item"><input type="checkbox"></input>four</li>
+<li>
+<pre><code>[ ] five
+</code></pre>
+</li>
+</ul>
+>>> checkbox list separated with blank lines
+- [ ] A
+
+- [ ] B
+
+- [ ]
+<<<
+<ul class="contains-task-list">
+<li class="task-list-item">
+<p><input type="checkbox"></input>A</p>
+</li>
+<li class="task-list-item">
+<p><input type="checkbox"></input>B</p>
+</li>
+<li>
+<p>[ ]</p>
+</li>
+</ul>
\ No newline at end of file
diff --git a/pkgs/markdown/test/gfm/atx_headings.unit b/pkgs/markdown/test/gfm/atx_headings.unit
new file mode 100644
index 0000000..5a60cf4
--- /dev/null
+++ b/pkgs/markdown/test/gfm/atx_headings.unit
@@ -0,0 +1,112 @@
+>>> ATX headings - 32
+# foo
+## foo
+### foo
+#### foo
+##### foo
+###### foo
+<<<
+<h1>foo</h1>
+<h2>foo</h2>
+<h3>foo</h3>
+<h4>foo</h4>
+<h5>foo</h5>
+<h6>foo</h6>
+>>> ATX headings - 33
+####### foo
+<<<
+<p>####### foo</p>
+>>> ATX headings - 34
+#5 bolt
+
+#hashtag
+<<<
+<p>#5 bolt</p>
+<p>#hashtag</p>
+>>> ATX headings - 35
+\## foo
+<<<
+<p>## foo</p>
+>>> ATX headings - 36
+# foo *bar* \*baz\*
+<<<
+<h1>foo <em>bar</em> *baz*</h1>
+>>> ATX headings - 37
+#                  foo                     
+<<<
+<h1>foo</h1>
+>>> ATX headings - 38
+ ### foo
+  ## foo
+   # foo
+<<<
+<h3>foo</h3>
+<h2>foo</h2>
+<h1>foo</h1>
+>>> ATX headings - 39
+    # foo
+<<<
+<pre><code># foo
+</code></pre>
+>>> ATX headings - 40
+foo
+    # bar
+<<<
+<p>foo
+# bar</p>
+>>> ATX headings - 41
+## foo ##
+  ###   bar    ###
+<<<
+<h2>foo</h2>
+<h3>bar</h3>
+>>> ATX headings - 42
+# foo ##################################
+##### foo ##
+<<<
+<h1>foo</h1>
+<h5>foo</h5>
+>>> ATX headings - 43
+### foo ###     
+<<<
+<h3>foo</h3>
+>>> ATX headings - 44
+### foo ### b
+<<<
+<h3>foo ### b</h3>
+>>> ATX headings - 45
+# foo#
+<<<
+<h1>foo#</h1>
+>>> ATX headings - 46
+### foo \###
+## foo #\##
+# foo \#
+<<<
+<h3>foo ###</h3>
+<h2>foo ###</h2>
+<h1>foo #</h1>
+>>> ATX headings - 47
+****
+## foo
+****
+<<<
+<hr />
+<h2>foo</h2>
+<hr />
+>>> ATX headings - 48
+Foo bar
+# baz
+Bar foo
+<<<
+<p>Foo bar</p>
+<h1>baz</h1>
+<p>Bar foo</p>
+>>> ATX headings - 49
+## 
+#
+### ###
+<<<
+<h2></h2>
+<h1></h1>
+<h3></h3>
diff --git a/pkgs/markdown/test/gfm/autolinks.unit b/pkgs/markdown/test/gfm/autolinks.unit
new file mode 100644
index 0000000..6df5296
--- /dev/null
+++ b/pkgs/markdown/test/gfm/autolinks.unit
@@ -0,0 +1,76 @@
+>>> Autolinks - 602
+<http://foo.bar.baz>
+<<<
+<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
+>>> Autolinks - 603
+<http://foo.bar.baz/test?q=hello&id=22&boolean>
+<<<
+<p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
+>>> Autolinks - 604
+<irc://foo.bar:2233/baz>
+<<<
+<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
+>>> Autolinks - 605
+<MAILTO:FOO@BAR.BAZ>
+<<<
+<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
+>>> Autolinks - 606
+<a+b+c:d>
+<<<
+<p><a href="a+b+c:d">a+b+c:d</a></p>
+>>> Autolinks - 607
+<made-up-scheme://foo,bar>
+<<<
+<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
+>>> Autolinks - 608
+<http://../>
+<<<
+<p><a href="http://../">http://../</a></p>
+>>> Autolinks - 609
+<localhost:5001/foo>
+<<<
+<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
+>>> Autolinks - 610
+<http://foo.bar/baz bim>
+<<<
+<p>&lt;http://foo.bar/baz bim&gt;</p>
+>>> Autolinks - 611
+<http://example.com/\[\>
+<<<
+<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
+>>> Autolinks - 612
+<foo@bar.example.com>
+<<<
+<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
+>>> Autolinks - 613
+<foo+special@Bar.baz-bar0.com>
+<<<
+<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
+>>> Autolinks - 614
+<foo\+@bar.example.com>
+<<<
+<p>&lt;foo+@bar.example.com&gt;</p>
+>>> Autolinks - 615
+<>
+<<<
+<p>&lt;&gt;</p>
+>>> Autolinks - 616
+< http://foo.bar >
+<<<
+<p>&lt; http://foo.bar &gt;</p>
+>>> Autolinks - 617
+<m:abc>
+<<<
+<p>&lt;m:abc&gt;</p>
+>>> Autolinks - 618
+<foo.bar.baz>
+<<<
+<p>&lt;foo.bar.baz&gt;</p>
+>>> Autolinks - 619
+http://example.com
+<<<
+<p>http://example.com</p>
+>>> Autolinks - 620
+foo@bar.example.com
+<<<
+<p>foo@bar.example.com</p>
diff --git a/pkgs/markdown/test/gfm/autolinks_extension.unit b/pkgs/markdown/test/gfm/autolinks_extension.unit
new file mode 100644
index 0000000..ff69a53
--- /dev/null
+++ b/pkgs/markdown/test/gfm/autolinks_extension.unit
@@ -0,0 +1,74 @@
+>>> Autolinks (extension) - 621
+www.commonmark.org
+<<<
+<p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
+>>> Autolinks (extension) - 622
+Visit www.commonmark.org/help for more information.
+<<<
+<p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
+>>> Autolinks (extension) - 623
+Visit www.commonmark.org.
+
+Visit www.commonmark.org/a.b.
+<<<
+<p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
+<p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
+>>> Autolinks (extension) - 624
+www.google.com/search?q=Markup+(business)
+
+www.google.com/search?q=Markup+(business)))
+
+(www.google.com/search?q=Markup+(business))
+
+(www.google.com/search?q=Markup+(business)
+<<<
+<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
+<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
+<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+>>> Autolinks (extension) - 625
+www.google.com/search?q=(business))+ok
+<<<
+<p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
+>>> Autolinks (extension) - 626
+www.google.com/search?q=commonmark&hl=en
+
+www.google.com/search?q=commonmark&hl;
+<<<
+<p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
+<p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
+>>> Autolinks (extension) - 627
+www.commonmark.org/he<lp
+<<<
+<p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
+>>> Autolinks (extension) - 628
+http://commonmark.org
+
+(Visit https://encrypted.google.com/search?q=Markup+(business))
+
+Anonymous FTP is available at ftp://foo.bar.baz.
+<<<
+<p><a href="http://commonmark.org">http://commonmark.org</a></p>
+<p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
+<p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
+>>> Autolinks (extension) - 629
+foo@bar.baz
+<<<
+<p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
+>>> Autolinks (extension) - 630
+hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
+<<<
+<p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
+>>> Autolinks (extension) - 631
+a.b-c_d@a.b
+
+a.b-c_d@a.b.
+
+a.b-c_d@a.b-
+
+a.b-c_d@a.b_
+<<<
+<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
+<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
+<p>a.b-c_d@a.b-</p>
+<p>a.b-c_d@a.b_</p>
diff --git a/pkgs/markdown/test/gfm/backslash_escapes.unit b/pkgs/markdown/test/gfm/backslash_escapes.unit
new file mode 100644
index 0000000..0e9074a
--- /dev/null
+++ b/pkgs/markdown/test/gfm/backslash_escapes.unit
@@ -0,0 +1,79 @@
+>>> Backslash escapes - 308
+\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+<<<
+<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
+>>> Backslash escapes - 309
+\	\A\a\ \3\φ\«
+<<<
+<p>\	\A\a\ \3\φ\«</p>
+>>> Backslash escapes - 310
+\*not emphasized*
+\<br/> not a tag
+\[not a link](/foo)
+\`not code`
+1\. not a list
+\* not a list
+\# not a heading
+\[foo]: /url "not a reference"
+\&ouml; not a character entity
+<<<
+<p>*not emphasized*
+&lt;br/&gt; not a tag
+[not a link](/foo)
+`not code`
+1. not a list
+* not a list
+# not a heading
+[foo]: /url &quot;not a reference&quot;
+&amp;ouml; not a character entity</p>
+>>> Backslash escapes - 311
+\\*emphasis*
+<<<
+<p>\<em>emphasis</em></p>
+>>> Backslash escapes - 312
+foo\
+bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Backslash escapes - 313
+`` \[\` ``
+<<<
+<p><code>\[\`</code></p>
+>>> Backslash escapes - 314
+    \[\]
+<<<
+<pre><code>\[\]
+</code></pre>
+>>> Backslash escapes - 315
+~~~
+\[\]
+~~~
+<<<
+<pre><code>\[\]
+</code></pre>
+>>> Backslash escapes - 316
+<http://example.com?find=\*>
+<<<
+<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
+>>> Backslash escapes - 317
+<a href="/bar\/)">
+<<<
+<a href="/bar\/)">
+>>> Backslash escapes - 318
+[foo](/bar\* "ti\*tle")
+<<<
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+>>> Backslash escapes - 319
+[foo]
+
+[foo]: /bar\* "ti\*tle"
+<<<
+<p><a href="/bar*" title="ti*tle">foo</a></p>
+>>> Backslash escapes - 320
+``` foo\+bar
+foo
+```
+<<<
+<pre><code class="language-foo+bar">foo
+</code></pre>
diff --git a/pkgs/markdown/test/gfm/blank_lines.unit b/pkgs/markdown/test/gfm/blank_lines.unit
new file mode 100644
index 0000000..be24ab7
--- /dev/null
+++ b/pkgs/markdown/test/gfm/blank_lines.unit
@@ -0,0 +1,12 @@
+>>> Blank lines - 197
+  
+
+aaa
+  
+
+# aaa
+
+  
+<<<
+<p>aaa</p>
+<h1>aaa</h1>
diff --git a/pkgs/markdown/test/gfm/block_quotes.unit b/pkgs/markdown/test/gfm/block_quotes.unit
new file mode 100644
index 0000000..50d8757
--- /dev/null
+++ b/pkgs/markdown/test/gfm/block_quotes.unit
@@ -0,0 +1,239 @@
+>>> Block quotes - 206
+> # Foo
+> bar
+> baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 207
+># Foo
+>bar
+> baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 208
+   > # Foo
+   > bar
+ > baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 209
+    > # Foo
+    > bar
+    > baz
+<<<
+<pre><code>&gt; # Foo
+&gt; bar
+&gt; baz
+</code></pre>
+>>> Block quotes - 210
+> # Foo
+> bar
+baz
+<<<
+<blockquote>
+<h1>Foo</h1>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 211
+> bar
+baz
+> foo
+<<<
+<blockquote>
+<p>bar
+baz
+foo</p>
+</blockquote>
+>>> Block quotes - 212
+> foo
+---
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+>>> Block quotes - 213
+> - foo
+- bar
+<<<
+<blockquote>
+<ul>
+<li>foo</li>
+</ul>
+</blockquote>
+<ul>
+<li>bar</li>
+</ul>
+>>> Block quotes - 214
+>     foo
+    bar
+<<<
+<blockquote>
+<pre><code>foo
+</code></pre>
+</blockquote>
+<pre><code>bar
+</code></pre>
+>>> Block quotes - 215
+> ```
+foo
+```
+<<<
+<blockquote>
+<pre><code></code></pre>
+</blockquote>
+<p>foo</p>
+<pre><code></code></pre>
+>>> Block quotes - 216
+> foo
+    - bar
+<<<
+<blockquote>
+<p>foo
+- bar</p>
+</blockquote>
+>>> Block quotes - 217
+>
+<<<
+<blockquote>
+</blockquote>
+>>> Block quotes - 218
+>
+>  
+> 
+<<<
+<blockquote>
+</blockquote>
+>>> Block quotes - 219
+>
+> foo
+>  
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+>>> Block quotes - 220
+> foo
+
+> bar
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 221
+> foo
+> bar
+<<<
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+>>> Block quotes - 222
+> foo
+>
+> bar
+<<<
+<blockquote>
+<p>foo</p>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 223
+foo
+> bar
+<<<
+<p>foo</p>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Block quotes - 224
+> aaa
+***
+> bbb
+<<<
+<blockquote>
+<p>aaa</p>
+</blockquote>
+<hr />
+<blockquote>
+<p>bbb</p>
+</blockquote>
+>>> Block quotes - 225
+> bar
+baz
+<<<
+<blockquote>
+<p>bar
+baz</p>
+</blockquote>
+>>> Block quotes - 226
+> bar
+
+baz
+<<<
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+>>> Block quotes - 227
+> bar
+>
+baz
+<<<
+<blockquote>
+<p>bar</p>
+</blockquote>
+<p>baz</p>
+>>> Block quotes - 228
+> > > foo
+bar
+<<<
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar</p>
+</blockquote>
+</blockquote>
+</blockquote>
+>>> Block quotes - 229
+>>> foo
+> bar
+>>baz
+<<<
+<blockquote>
+<blockquote>
+<blockquote>
+<p>foo
+bar
+baz</p>
+</blockquote>
+</blockquote>
+</blockquote>
+>>> Block quotes - 230
+>     code
+
+>    not code
+<<<
+<blockquote>
+<pre><code>code
+</code></pre>
+</blockquote>
+<blockquote>
+<p>not code</p>
+</blockquote>
diff --git a/pkgs/markdown/test/gfm/code_spans.unit b/pkgs/markdown/test/gfm/code_spans.unit
new file mode 100644
index 0000000..68a4b3a
--- /dev/null
+++ b/pkgs/markdown/test/gfm/code_spans.unit
@@ -0,0 +1,97 @@
+>>> Code spans - 338
+`foo`
+<<<
+<p><code>foo</code></p>
+>>> Code spans - 339
+`` foo ` bar ``
+<<<
+<p><code>foo ` bar</code></p>
+>>> Code spans - 340
+` `` `
+<<<
+<p><code>``</code></p>
+>>> Code spans - 341
+`  ``  `
+<<<
+<p><code> `` </code></p>
+>>> Code spans - 342
+` a`
+<<<
+<p><code> a</code></p>
+>>> Code spans - 343
+` b `
+<<<
+<p><code> b </code></p>
+>>> Code spans - 344
+` `
+`  `
+<<<
+<p><code> </code>
+<code>  </code></p>
+>>> Code spans - 345
+``
+foo
+bar  
+baz
+``
+<<<
+<p><code>foo bar   baz</code></p>
+>>> Code spans - 346
+``
+foo 
+``
+<<<
+<p><code>foo </code></p>
+>>> Code spans - 347
+`foo   bar 
+baz`
+<<<
+<p><code>foo   bar  baz</code></p>
+>>> Code spans - 348
+`foo\`bar`
+<<<
+<p><code>foo\</code>bar`</p>
+>>> Code spans - 349
+``foo`bar``
+<<<
+<p><code>foo`bar</code></p>
+>>> Code spans - 350
+` foo `` bar `
+<<<
+<p><code>foo `` bar</code></p>
+>>> Code spans - 351
+*foo`*`
+<<<
+<p>*foo<code>*</code></p>
+>>> Code spans - 352
+[not a `link](/foo`)
+<<<
+<p>[not a <code>link](/foo</code>)</p>
+>>> Code spans - 353
+`<a href="`">`
+<<<
+<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
+>>> Code spans - 354
+<a href="`">`
+<<<
+<p><a href="`">`</p>
+>>> Code spans - 355
+`<http://foo.bar.`baz>`
+<<<
+<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
+>>> Code spans - 356
+<http://foo.bar.`baz>`
+<<<
+<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
+>>> Code spans - 357
+```foo``
+<<<
+<p>```foo``</p>
+>>> Code spans - 358
+`foo
+<<<
+<p>`foo</p>
+>>> Code spans - 359
+`foo``bar``
+<<<
+<p>`foo<code>bar</code></p>
diff --git a/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit b/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit
new file mode 100644
index 0000000..34cc396
--- /dev/null
+++ b/pkgs/markdown/test/gfm/disallowed_raw_html_extension.unit
@@ -0,0 +1,11 @@
+>>> Disallowed Raw HTML (extension) - 652
+<strong> <title> <style> <em>
+
+<blockquote>
+  <xmp> is disallowed.  <XMP> is also disallowed.
+</blockquote>
+<<<
+<p><strong> &lt;title> &lt;style> <em></p>
+<blockquote>
+&lt;xmp> is disallowed.  &lt;XMP> is also disallowed.
+</blockquote>
diff --git a/pkgs/markdown/test/gfm/emphasis_and_strong_emphasis.unit b/pkgs/markdown/test/gfm/emphasis_and_strong_emphasis.unit
new file mode 100644
index 0000000..b6e8155
--- /dev/null
+++ b/pkgs/markdown/test/gfm/emphasis_and_strong_emphasis.unit
@@ -0,0 +1,536 @@
+>>> Emphasis and strong emphasis - 360
+*foo bar*
+<<<
+<p><em>foo bar</em></p>
+>>> Emphasis and strong emphasis - 361
+a * foo bar*
+<<<
+<p>a * foo bar*</p>
+>>> Emphasis and strong emphasis - 362
+a*"foo"*
+<<<
+<p>a*&quot;foo&quot;*</p>
+>>> Emphasis and strong emphasis - 363
+* a *
+<<<
+<p>* a *</p>
+>>> Emphasis and strong emphasis - 364
+foo*bar*
+<<<
+<p>foo<em>bar</em></p>
+>>> Emphasis and strong emphasis - 365
+5*6*78
+<<<
+<p>5<em>6</em>78</p>
+>>> Emphasis and strong emphasis - 366
+_foo bar_
+<<<
+<p><em>foo bar</em></p>
+>>> Emphasis and strong emphasis - 367
+_ foo bar_
+<<<
+<p>_ foo bar_</p>
+>>> Emphasis and strong emphasis - 368
+a_"foo"_
+<<<
+<p>a_&quot;foo&quot;_</p>
+>>> Emphasis and strong emphasis - 369
+foo_bar_
+<<<
+<p>foo_bar_</p>
+>>> Emphasis and strong emphasis - 370
+5_6_78
+<<<
+<p>5_6_78</p>
+>>> Emphasis and strong emphasis - 371
+пристаням_стремятся_
+<<<
+<p>пристаням_стремятся_</p>
+>>> Emphasis and strong emphasis - 372
+aa_"bb"_cc
+<<<
+<p>aa_&quot;bb&quot;_cc</p>
+>>> Emphasis and strong emphasis - 373
+foo-_(bar)_
+<<<
+<p>foo-<em>(bar)</em></p>
+>>> Emphasis and strong emphasis - 374
+_foo*
+<<<
+<p>_foo*</p>
+>>> Emphasis and strong emphasis - 375
+*foo bar *
+<<<
+<p>*foo bar *</p>
+>>> Emphasis and strong emphasis - 376
+*foo bar
+*
+<<<
+<p>*foo bar
+*</p>
+>>> Emphasis and strong emphasis - 377
+*(*foo)
+<<<
+<p>*(*foo)</p>
+>>> Emphasis and strong emphasis - 378
+*(*foo*)*
+<<<
+<p><em>(<em>foo</em>)</em></p>
+>>> Emphasis and strong emphasis - 379
+*foo*bar
+<<<
+<p><em>foo</em>bar</p>
+>>> Emphasis and strong emphasis - 380
+_foo bar _
+<<<
+<p>_foo bar _</p>
+>>> Emphasis and strong emphasis - 381
+_(_foo)
+<<<
+<p>_(_foo)</p>
+>>> Emphasis and strong emphasis - 382
+_(_foo_)_
+<<<
+<p><em>(<em>foo</em>)</em></p>
+>>> Emphasis and strong emphasis - 383
+_foo_bar
+<<<
+<p>_foo_bar</p>
+>>> Emphasis and strong emphasis - 384
+_пристаням_стремятся
+<<<
+<p>_пристаням_стремятся</p>
+>>> Emphasis and strong emphasis - 385
+_foo_bar_baz_
+<<<
+<p><em>foo_bar_baz</em></p>
+>>> Emphasis and strong emphasis - 386
+_(bar)_.
+<<<
+<p><em>(bar)</em>.</p>
+>>> Emphasis and strong emphasis - 387
+**foo bar**
+<<<
+<p><strong>foo bar</strong></p>
+>>> Emphasis and strong emphasis - 388
+** foo bar**
+<<<
+<p>** foo bar**</p>
+>>> Emphasis and strong emphasis - 389
+a**"foo"**
+<<<
+<p>a**&quot;foo&quot;**</p>
+>>> Emphasis and strong emphasis - 390
+foo**bar**
+<<<
+<p>foo<strong>bar</strong></p>
+>>> Emphasis and strong emphasis - 391
+__foo bar__
+<<<
+<p><strong>foo bar</strong></p>
+>>> Emphasis and strong emphasis - 392
+__ foo bar__
+<<<
+<p>__ foo bar__</p>
+>>> Emphasis and strong emphasis - 393
+__
+foo bar__
+<<<
+<p>__
+foo bar__</p>
+>>> Emphasis and strong emphasis - 394
+a__"foo"__
+<<<
+<p>a__&quot;foo&quot;__</p>
+>>> Emphasis and strong emphasis - 395
+foo__bar__
+<<<
+<p>foo__bar__</p>
+>>> Emphasis and strong emphasis - 396
+5__6__78
+<<<
+<p>5__6__78</p>
+>>> Emphasis and strong emphasis - 397
+пристаням__стремятся__
+<<<
+<p>пристаням__стремятся__</p>
+>>> Emphasis and strong emphasis - 398
+__foo, __bar__, baz__
+<<<
+<p><strong>foo, <strong>bar</strong>, baz</strong></p>
+>>> Emphasis and strong emphasis - 399
+foo-__(bar)__
+<<<
+<p>foo-<strong>(bar)</strong></p>
+>>> Emphasis and strong emphasis - 400
+**foo bar **
+<<<
+<p>**foo bar **</p>
+>>> Emphasis and strong emphasis - 401
+**(**foo)
+<<<
+<p>**(**foo)</p>
+>>> Emphasis and strong emphasis - 402
+*(**foo**)*
+<<<
+<p><em>(<strong>foo</strong>)</em></p>
+>>> Emphasis and strong emphasis - 403
+**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
+*Asclepias physocarpa*)**
+<<<
+<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
+<em>Asclepias physocarpa</em>)</strong></p>
+>>> Emphasis and strong emphasis - 404
+**foo "*bar*" foo**
+<<<
+<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
+>>> Emphasis and strong emphasis - 405
+**foo**bar
+<<<
+<p><strong>foo</strong>bar</p>
+>>> Emphasis and strong emphasis - 406
+__foo bar __
+<<<
+<p>__foo bar __</p>
+>>> Emphasis and strong emphasis - 407
+__(__foo)
+<<<
+<p>__(__foo)</p>
+>>> Emphasis and strong emphasis - 408
+_(__foo__)_
+<<<
+<p><em>(<strong>foo</strong>)</em></p>
+>>> Emphasis and strong emphasis - 409
+__foo__bar
+<<<
+<p>__foo__bar</p>
+>>> Emphasis and strong emphasis - 410
+__пристаням__стремятся
+<<<
+<p>__пристаням__стремятся</p>
+>>> Emphasis and strong emphasis - 411
+__foo__bar__baz__
+<<<
+<p><strong>foo__bar__baz</strong></p>
+>>> Emphasis and strong emphasis - 412
+__(bar)__.
+<<<
+<p><strong>(bar)</strong>.</p>
+>>> Emphasis and strong emphasis - 413
+*foo [bar](/url)*
+<<<
+<p><em>foo <a href="/url">bar</a></em></p>
+>>> Emphasis and strong emphasis - 414
+*foo
+bar*
+<<<
+<p><em>foo
+bar</em></p>
+>>> Emphasis and strong emphasis - 415
+_foo __bar__ baz_
+<<<
+<p><em>foo <strong>bar</strong> baz</em></p>
+>>> Emphasis and strong emphasis - 416
+_foo _bar_ baz_
+<<<
+<p><em>foo <em>bar</em> baz</em></p>
+>>> Emphasis and strong emphasis - 417
+__foo_ bar_
+<<<
+<p><em><em>foo</em> bar</em></p>
+>>> Emphasis and strong emphasis - 418
+*foo *bar**
+<<<
+<p><em>foo <em>bar</em></em></p>
+>>> Emphasis and strong emphasis - 419
+*foo **bar** baz*
+<<<
+<p><em>foo <strong>bar</strong> baz</em></p>
+>>> Emphasis and strong emphasis - 420
+*foo**bar**baz*
+<<<
+<p><em>foo<strong>bar</strong>baz</em></p>
+>>> Emphasis and strong emphasis - 421
+*foo**bar*
+<<<
+<p><em>foo**bar</em></p>
+>>> Emphasis and strong emphasis - 422
+***foo** bar*
+<<<
+<p><em><strong>foo</strong> bar</em></p>
+>>> Emphasis and strong emphasis - 423
+*foo **bar***
+<<<
+<p><em>foo <strong>bar</strong></em></p>
+>>> Emphasis and strong emphasis - 424
+*foo**bar***
+<<<
+<p><em>foo<strong>bar</strong></em></p>
+>>> Emphasis and strong emphasis - 425
+foo***bar***baz
+<<<
+<p>foo<em><strong>bar</strong></em>baz</p>
+>>> Emphasis and strong emphasis - 426
+foo******bar*********baz
+<<<
+<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
+>>> Emphasis and strong emphasis - 427
+*foo **bar *baz* bim** bop*
+<<<
+<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
+>>> Emphasis and strong emphasis - 428
+*foo [*bar*](/url)*
+<<<
+<p><em>foo <a href="/url"><em>bar</em></a></em></p>
+>>> Emphasis and strong emphasis - 429
+** is not an empty emphasis
+<<<
+<p>** is not an empty emphasis</p>
+>>> Emphasis and strong emphasis - 430
+**** is not an empty strong emphasis
+<<<
+<p>**** is not an empty strong emphasis</p>
+>>> Emphasis and strong emphasis - 431
+**foo [bar](/url)**
+<<<
+<p><strong>foo <a href="/url">bar</a></strong></p>
+>>> Emphasis and strong emphasis - 432
+**foo
+bar**
+<<<
+<p><strong>foo
+bar</strong></p>
+>>> Emphasis and strong emphasis - 433
+__foo _bar_ baz__
+<<<
+<p><strong>foo <em>bar</em> baz</strong></p>
+>>> Emphasis and strong emphasis - 434
+__foo __bar__ baz__
+<<<
+<p><strong>foo <strong>bar</strong> baz</strong></p>
+>>> Emphasis and strong emphasis - 435
+____foo__ bar__
+<<<
+<p><strong><strong>foo</strong> bar</strong></p>
+>>> Emphasis and strong emphasis - 436
+**foo **bar****
+<<<
+<p><strong>foo <strong>bar</strong></strong></p>
+>>> Emphasis and strong emphasis - 437
+**foo *bar* baz**
+<<<
+<p><strong>foo <em>bar</em> baz</strong></p>
+>>> Emphasis and strong emphasis - 438
+**foo*bar*baz**
+<<<
+<p><strong>foo<em>bar</em>baz</strong></p>
+>>> Emphasis and strong emphasis - 439
+***foo* bar**
+<<<
+<p><strong><em>foo</em> bar</strong></p>
+>>> Emphasis and strong emphasis - 440
+**foo *bar***
+<<<
+<p><strong>foo <em>bar</em></strong></p>
+>>> Emphasis and strong emphasis - 441
+**foo *bar **baz**
+bim* bop**
+<<<
+<p><strong>foo <em>bar <strong>baz</strong>
+bim</em> bop</strong></p>
+>>> Emphasis and strong emphasis - 442
+**foo [*bar*](/url)**
+<<<
+<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
+>>> Emphasis and strong emphasis - 443
+__ is not an empty emphasis
+<<<
+<p>__ is not an empty emphasis</p>
+>>> Emphasis and strong emphasis - 444
+____ is not an empty strong emphasis
+<<<
+<p>____ is not an empty strong emphasis</p>
+>>> Emphasis and strong emphasis - 445
+foo ***
+<<<
+<p>foo ***</p>
+>>> Emphasis and strong emphasis - 446
+foo *\**
+<<<
+<p>foo <em>*</em></p>
+>>> Emphasis and strong emphasis - 447
+foo *_*
+<<<
+<p>foo <em>_</em></p>
+>>> Emphasis and strong emphasis - 448
+foo *****
+<<<
+<p>foo *****</p>
+>>> Emphasis and strong emphasis - 449
+foo **\***
+<<<
+<p>foo <strong>*</strong></p>
+>>> Emphasis and strong emphasis - 450
+foo **_**
+<<<
+<p>foo <strong>_</strong></p>
+>>> Emphasis and strong emphasis - 451
+**foo*
+<<<
+<p>*<em>foo</em></p>
+>>> Emphasis and strong emphasis - 452
+*foo**
+<<<
+<p><em>foo</em>*</p>
+>>> Emphasis and strong emphasis - 453
+***foo**
+<<<
+<p>*<strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 454
+****foo*
+<<<
+<p>***<em>foo</em></p>
+>>> Emphasis and strong emphasis - 455
+**foo***
+<<<
+<p><strong>foo</strong>*</p>
+>>> Emphasis and strong emphasis - 456
+*foo****
+<<<
+<p><em>foo</em>***</p>
+>>> Emphasis and strong emphasis - 457
+foo ___
+<<<
+<p>foo ___</p>
+>>> Emphasis and strong emphasis - 458
+foo _\__
+<<<
+<p>foo <em>_</em></p>
+>>> Emphasis and strong emphasis - 459
+foo _*_
+<<<
+<p>foo <em>*</em></p>
+>>> Emphasis and strong emphasis - 460
+foo _____
+<<<
+<p>foo _____</p>
+>>> Emphasis and strong emphasis - 461
+foo __\___
+<<<
+<p>foo <strong>_</strong></p>
+>>> Emphasis and strong emphasis - 462
+foo __*__
+<<<
+<p>foo <strong>*</strong></p>
+>>> Emphasis and strong emphasis - 463
+__foo_
+<<<
+<p>_<em>foo</em></p>
+>>> Emphasis and strong emphasis - 464
+_foo__
+<<<
+<p><em>foo</em>_</p>
+>>> Emphasis and strong emphasis - 465
+___foo__
+<<<
+<p>_<strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 466
+____foo_
+<<<
+<p>___<em>foo</em></p>
+>>> Emphasis and strong emphasis - 467
+__foo___
+<<<
+<p><strong>foo</strong>_</p>
+>>> Emphasis and strong emphasis - 468
+_foo____
+<<<
+<p><em>foo</em>___</p>
+>>> Emphasis and strong emphasis - 469
+**foo**
+<<<
+<p><strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 470
+*_foo_*
+<<<
+<p><em><em>foo</em></em></p>
+>>> Emphasis and strong emphasis - 471
+__foo__
+<<<
+<p><strong>foo</strong></p>
+>>> Emphasis and strong emphasis - 472
+_*foo*_
+<<<
+<p><em><em>foo</em></em></p>
+>>> Emphasis and strong emphasis - 473
+****foo****
+<<<
+<p><strong><strong>foo</strong></strong></p>
+>>> Emphasis and strong emphasis - 474
+____foo____
+<<<
+<p><strong><strong>foo</strong></strong></p>
+>>> Emphasis and strong emphasis - 475
+******foo******
+<<<
+<p><strong><strong><strong>foo</strong></strong></strong></p>
+>>> Emphasis and strong emphasis - 476
+***foo***
+<<<
+<p><em><strong>foo</strong></em></p>
+>>> Emphasis and strong emphasis - 477
+_____foo_____
+<<<
+<p><em><strong><strong>foo</strong></strong></em></p>
+>>> Emphasis and strong emphasis - 478
+*foo _bar* baz_
+<<<
+<p><em>foo _bar</em> baz_</p>
+>>> Emphasis and strong emphasis - 479
+*foo __bar *baz bim__ bam*
+<<<
+<p><em>foo <strong>bar *baz bim</strong> bam</em></p>
+>>> Emphasis and strong emphasis - 480
+**foo **bar baz**
+<<<
+<p>**foo <strong>bar baz</strong></p>
+>>> Emphasis and strong emphasis - 481
+*foo *bar baz*
+<<<
+<p>*foo <em>bar baz</em></p>
+>>> Emphasis and strong emphasis - 482
+*[bar*](/url)
+<<<
+<p>*<a href="/url">bar*</a></p>
+>>> Emphasis and strong emphasis - 483
+_foo [bar_](/url)
+<<<
+<p>_foo <a href="/url">bar_</a></p>
+>>> Emphasis and strong emphasis - 484
+*<img src="foo" title="*"/>
+<<<
+<p>*<img src="foo" title="*"/></p>
+>>> Emphasis and strong emphasis - 485
+**<a href="**">
+<<<
+<p>**<a href="**"></p>
+>>> Emphasis and strong emphasis - 486
+__<a href="__">
+<<<
+<p>__<a href="__"></p>
+>>> Emphasis and strong emphasis - 487
+*a `*`*
+<<<
+<p><em>a <code>*</code></em></p>
+>>> Emphasis and strong emphasis - 488
+_a `_`_
+<<<
+<p><em>a <code>_</code></em></p>
+>>> Emphasis and strong emphasis - 489
+**a<http://foo.bar/?q=**>
+<<<
+<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
+>>> Emphasis and strong emphasis - 490
+__a<http://foo.bar/?q=__>
+<<<
+<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
diff --git a/pkgs/markdown/test/gfm/entity_and_numeric_character_references.unit b/pkgs/markdown/test/gfm/entity_and_numeric_character_references.unit
new file mode 100644
index 0000000..2a6248e
--- /dev/null
+++ b/pkgs/markdown/test/gfm/entity_and_numeric_character_references.unit
@@ -0,0 +1,93 @@
+>>> Entity and numeric character references - 321
+&nbsp; &amp; &copy; &AElig; &Dcaron;
+&frac34; &HilbertSpace; &DifferentialD;
+&ClockwiseContourIntegral; &ngE;
+<<<
+<p>&amp; © Æ Ď
+¾ ℋ ⅆ
+∲ ≧̸</p>
+>>> Entity and numeric character references - 322
+&#35; &#1234; &#992; &#0;
+<<<
+<p># Ӓ Ϡ �</p>
+>>> Entity and numeric character references - 323
+&#X22; &#XD06; &#xcab;
+<<<
+<p>&quot; ആ ಫ</p>
+>>> Entity and numeric character references - 324
+&nbsp &x; &#; &#x;
+&#987654321;
+&#abcdef0;
+&ThisIsNotDefined; &hi?;
+<<<
+<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
+&amp;#987654321;
+&amp;#abcdef0;
+&amp;ThisIsNotDefined; &amp;hi?;</p>
+>>> Entity and numeric character references - 325
+&copy
+<<<
+<p>&amp;copy</p>
+>>> Entity and numeric character references - 326
+&MadeUpEntity;
+<<<
+<p>&amp;MadeUpEntity;</p>
+>>> Entity and numeric character references - 327
+<a href="&ouml;&ouml;.html">
+<<<
+<a href="&ouml;&ouml;.html">
+>>> Entity and numeric character references - 328
+[foo](/f&ouml;&ouml; "f&ouml;&ouml;")
+<<<
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+>>> Entity and numeric character references - 329
+[foo]
+
+[foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
+<<<
+<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+>>> Entity and numeric character references - 330
+``` f&ouml;&ouml;
+foo
+```
+<<<
+<pre><code class="language-föö">foo
+</code></pre>
+>>> Entity and numeric character references - 331
+`f&ouml;&ouml;`
+<<<
+<p><code>f&amp;ouml;&amp;ouml;</code></p>
+>>> Entity and numeric character references - 332
+    f&ouml;f&ouml;
+<<<
+<pre><code>f&amp;ouml;f&amp;ouml;
+</code></pre>
+>>> Entity and numeric character references - 333
+&#42;foo&#42;
+*foo*
+<<<
+<p>*foo*
+<em>foo</em></p>
+>>> Entity and numeric character references - 334
+&#42; foo
+
+* foo
+<<<
+<p>* foo</p>
+<ul>
+<li>foo</li>
+</ul>
+>>> Entity and numeric character references - 335
+foo&#10;&#10;bar
+<<<
+<p>foo
+
+bar</p>
+>>> Entity and numeric character references - 336
+&#9;foo
+<<<
+<p>foo</p>
+>>> Entity and numeric character references - 337
+[a](url &quot;tit&quot;)
+<<<
+<p>[a](url &quot;tit&quot;)</p>
diff --git a/pkgs/markdown/test/gfm/fenced_code_blocks.unit b/pkgs/markdown/test/gfm/fenced_code_blocks.unit
new file mode 100644
index 0000000..f6fa843
--- /dev/null
+++ b/pkgs/markdown/test/gfm/fenced_code_blocks.unit
@@ -0,0 +1,245 @@
+>>> Fenced code blocks - 89
+```
+<
+ >
+```
+<<<
+<pre><code>&lt;
+ &gt;
+</code></pre>
+>>> Fenced code blocks - 90
+~~~
+<
+ >
+~~~
+<<<
+<pre><code>&lt;
+ &gt;
+</code></pre>
+>>> Fenced code blocks - 91
+``
+foo
+``
+<<<
+<p><code>foo</code></p>
+>>> Fenced code blocks - 92
+```
+aaa
+~~~
+```
+<<<
+<pre><code>aaa
+~~~
+</code></pre>
+>>> Fenced code blocks - 93
+~~~
+aaa
+```
+~~~
+<<<
+<pre><code>aaa
+```
+</code></pre>
+>>> Fenced code blocks - 94
+````
+aaa
+```
+``````
+<<<
+<pre><code>aaa
+```
+</code></pre>
+>>> Fenced code blocks - 95
+~~~~
+aaa
+~~~
+~~~~
+<<<
+<pre><code>aaa
+~~~
+</code></pre>
+>>> Fenced code blocks - 96
+```
+<<<
+<pre><code></code></pre>
+>>> Fenced code blocks - 97
+`````
+
+```
+aaa
+<<<
+<pre><code>
+```
+aaa
+</code></pre>
+>>> Fenced code blocks - 98
+> ```
+> aaa
+
+bbb
+<<<
+<blockquote>
+<pre><code>aaa
+</code></pre>
+</blockquote>
+<p>bbb</p>
+>>> Fenced code blocks - 99
+```
+
+  
+```
+<<<
+<pre><code>
+  
+</code></pre>
+>>> Fenced code blocks - 100
+```
+```
+<<<
+<pre><code></code></pre>
+>>> Fenced code blocks - 101
+ ```
+ aaa
+aaa
+```
+<<<
+<pre><code>aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 102
+  ```
+aaa
+  aaa
+aaa
+  ```
+<<<
+<pre><code>aaa
+aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 103
+   ```
+   aaa
+    aaa
+  aaa
+   ```
+<<<
+<pre><code>aaa
+ aaa
+aaa
+</code></pre>
+>>> Fenced code blocks - 104
+    ```
+    aaa
+    ```
+<<<
+<pre><code>```
+aaa
+```
+</code></pre>
+>>> Fenced code blocks - 105
+```
+aaa
+  ```
+<<<
+<pre><code>aaa
+</code></pre>
+>>> Fenced code blocks - 106
+   ```
+aaa
+  ```
+<<<
+<pre><code>aaa
+</code></pre>
+>>> Fenced code blocks - 107
+```
+aaa
+    ```
+<<<
+<pre><code>aaa
+    ```
+</code></pre>
+>>> Fenced code blocks - 108
+``` ```
+aaa
+<<<
+<p><code> </code>
+aaa</p>
+>>> Fenced code blocks - 109
+~~~~~~
+aaa
+~~~ ~~
+<<<
+<pre><code>aaa
+~~~ ~~
+</code></pre>
+>>> Fenced code blocks - 110
+foo
+```
+bar
+```
+baz
+<<<
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+>>> Fenced code blocks - 111
+foo
+---
+~~~
+bar
+~~~
+# baz
+<<<
+<h2>foo</h2>
+<pre><code>bar
+</code></pre>
+<h1>baz</h1>
+>>> Fenced code blocks - 112
+```ruby
+def foo(x)
+  return 3
+end
+```
+<<<
+<pre><code class="language-ruby">def foo(x)
+  return 3
+end
+</code></pre>
+>>> Fenced code blocks - 113
+~~~~    ruby startline=3 $%@#$
+def foo(x)
+  return 3
+end
+~~~~~~~
+<<<
+<pre><code class="language-ruby">def foo(x)
+  return 3
+end
+</code></pre>
+>>> Fenced code blocks - 114
+````;
+````
+<<<
+<pre><code class="language-;"></code></pre>
+>>> Fenced code blocks - 115
+``` aa ```
+foo
+<<<
+<p><code>aa</code>
+foo</p>
+>>> Fenced code blocks - 116
+~~~ aa ``` ~~~
+foo
+~~~
+<<<
+<pre><code class="language-aa">foo
+</code></pre>
+>>> Fenced code blocks - 117
+```
+``` aaa
+```
+<<<
+<pre><code>``` aaa
+</code></pre>
diff --git a/pkgs/markdown/test/gfm/hard_line_breaks.unit b/pkgs/markdown/test/gfm/hard_line_breaks.unit
new file mode 100644
index 0000000..e8aa5c0
--- /dev/null
+++ b/pkgs/markdown/test/gfm/hard_line_breaks.unit
@@ -0,0 +1,80 @@
+>>> Hard line breaks - 653
+foo  
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 654
+foo\
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 655
+foo       
+baz
+<<<
+<p>foo<br />
+baz</p>
+>>> Hard line breaks - 656
+foo  
+     bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Hard line breaks - 657
+foo\
+     bar
+<<<
+<p>foo<br />
+bar</p>
+>>> Hard line breaks - 658
+*foo  
+bar*
+<<<
+<p><em>foo<br />
+bar</em></p>
+>>> Hard line breaks - 659
+*foo\
+bar*
+<<<
+<p><em>foo<br />
+bar</em></p>
+>>> Hard line breaks - 660
+`code  
+span`
+<<<
+<p><code>code   span</code></p>
+>>> Hard line breaks - 661
+`code\
+span`
+<<<
+<p><code>code\ span</code></p>
+>>> Hard line breaks - 662
+<a href="foo  
+bar">
+<<<
+<p><a href="foo  
+bar"></p>
+>>> Hard line breaks - 663
+<a href="foo\
+bar">
+<<<
+<p><a href="foo\
+bar"></p>
+>>> Hard line breaks - 664
+foo\
+<<<
+<p>foo\</p>
+>>> Hard line breaks - 665
+foo  
+<<<
+<p>foo</p>
+>>> Hard line breaks - 666
+### foo\
+<<<
+<h3>foo\</h3>
+>>> Hard line breaks - 667
+### foo  
+<<<
+<h3>foo</h3>
diff --git a/pkgs/markdown/test/gfm/html_blocks.unit b/pkgs/markdown/test/gfm/html_blocks.unit
new file mode 100644
index 0000000..1af6420
--- /dev/null
+++ b/pkgs/markdown/test/gfm/html_blocks.unit
@@ -0,0 +1,433 @@
+>>> HTML blocks - 118
+<table><tr><td>
+<pre>
+**Hello**,
+
+_world_.
+</pre>
+</td></tr></table>
+<<<
+<table><tr><td>
+<pre>
+**Hello**,
+<p><em>world</em>.
+</pre></p>
+</td></tr></table>
+>>> HTML blocks - 119
+<table>
+  <tr>
+    <td>
+           hi
+    </td>
+  </tr>
+</table>
+
+okay.
+<<<
+<table>
+  <tr>
+    <td>
+           hi
+    </td>
+  </tr>
+</table>
+<p>okay.</p>
+>>> HTML blocks - 120
+ <div>
+  *hello*
+         <foo><a>
+<<<
+ <div>
+  *hello*
+         <foo><a>
+>>> HTML blocks - 121
+</div>
+*foo*
+<<<
+</div>
+*foo*
+>>> HTML blocks - 122
+<DIV CLASS="foo">
+
+*Markdown*
+
+</DIV>
+<<<
+<DIV CLASS="foo">
+<p><em>Markdown</em></p>
+</DIV>
+>>> HTML blocks - 123
+<div id="foo"
+  class="bar">
+</div>
+<<<
+<div id="foo"
+  class="bar">
+</div>
+>>> HTML blocks - 124
+<div id="foo" class="bar
+  baz">
+</div>
+<<<
+<div id="foo" class="bar
+  baz">
+</div>
+>>> HTML blocks - 125
+<div>
+*foo*
+
+*bar*
+<<<
+<div>
+*foo*
+<p><em>bar</em></p>
+>>> HTML blocks - 126
+<div id="foo"
+*hi*
+<<<
+<div id="foo"
+*hi*
+>>> HTML blocks - 127
+<div class
+foo
+<<<
+<div class
+foo
+>>> HTML blocks - 128
+<div *???-&&&-<---
+*foo*
+<<<
+<div *???-&&&-<---
+*foo*
+>>> HTML blocks - 129
+<div><a href="bar">*foo*</a></div>
+<<<
+<div><a href="bar">*foo*</a></div>
+>>> HTML blocks - 130
+<table><tr><td>
+foo
+</td></tr></table>
+<<<
+<table><tr><td>
+foo
+</td></tr></table>
+>>> HTML blocks - 131
+<div></div>
+``` c
+int x = 33;
+```
+<<<
+<div></div>
+``` c
+int x = 33;
+```
+>>> HTML blocks - 132
+<a href="foo">
+*bar*
+</a>
+<<<
+<a href="foo">
+*bar*
+</a>
+>>> HTML blocks - 133
+<Warning>
+*bar*
+</Warning>
+<<<
+<Warning>
+*bar*
+</Warning>
+>>> HTML blocks - 134
+<i class="foo">
+*bar*
+</i>
+<<<
+<i class="foo">
+*bar*
+</i>
+>>> HTML blocks - 135
+</ins>
+*bar*
+<<<
+</ins>
+*bar*
+>>> HTML blocks - 136
+<del>
+*foo*
+</del>
+<<<
+<del>
+*foo*
+</del>
+>>> HTML blocks - 137
+<del>
+
+*foo*
+
+</del>
+<<<
+<del>
+<p><em>foo</em></p>
+</del>
+>>> HTML blocks - 138
+<del>*foo*</del>
+<<<
+<p><del><em>foo</em></del></p>
+>>> HTML blocks - 139
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+okay
+<<<
+<pre language="haskell"><code>
+import Text.HTML.TagSoup
+
+main :: IO ()
+main = print $ parseTags tags
+</code></pre>
+<p>okay</p>
+>>> HTML blocks - 140
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+okay
+<<<
+<script type="text/javascript">
+// JavaScript example
+
+document.getElementById("demo").innerHTML = "Hello JavaScript!";
+</script>
+<p>okay</p>
+>>> HTML blocks - 141
+<style
+  type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+okay
+<<<
+<style
+  type="text/css">
+h1 {color:red;}
+
+p {color:blue;}
+</style>
+<p>okay</p>
+>>> HTML blocks - 142
+<style
+  type="text/css">
+
+foo
+<<<
+<style
+  type="text/css">
+
+foo
+>>> HTML blocks - 143
+> <div>
+> foo
+
+bar
+<<<
+<blockquote>
+<div>
+foo
+</blockquote>
+<p>bar</p>
+>>> HTML blocks - 144
+- <div>
+- foo
+<<<
+<ul>
+<li>
+<div>
+</li>
+<li>foo</li>
+</ul>
+>>> HTML blocks - 145
+<style>p{color:red;}</style>
+*foo*
+<<<
+<style>p{color:red;}</style>
+<p><em>foo</em></p>
+>>> HTML blocks - 146
+<!-- foo -->*bar*
+*baz*
+<<<
+<!-- foo -->*bar*
+<p><em>baz</em></p>
+>>> HTML blocks - 147
+<script>
+foo
+</script>1. *bar*
+<<<
+<script>
+foo
+</script>1. *bar*
+>>> HTML blocks - 148
+<!-- Foo
+
+bar
+   baz -->
+okay
+<<<
+<!-- Foo
+
+bar
+   baz -->
+<p>okay</p>
+>>> HTML blocks - 149
+<?php
+
+  echo '>';
+
+?>
+okay
+<<<
+<?php
+
+  echo '>';
+
+?>
+<p>okay</p>
+>>> HTML blocks - 150
+<!DOCTYPE html>
+<<<
+<!DOCTYPE html>
+>>> HTML blocks - 151
+<![CDATA[
+function matchwo(a,b)
+{
+  if (a < b && a < 0) then {
+    return 1;
+
+  } else {
+
+    return 0;
+  }
+}
+]]>
+okay
+<<<
+<![CDATA[
+function matchwo(a,b)
+{
+  if (a < b && a < 0) then {
+    return 1;
+
+  } else {
+
+    return 0;
+  }
+}
+]]>
+<p>okay</p>
+>>> HTML blocks - 152
+  <!-- foo -->
+
+    <!-- foo -->
+<<<
+  <!-- foo -->
+<pre><code>&lt;!-- foo --&gt;
+</code></pre>
+>>> HTML blocks - 153
+  <div>
+
+    <div>
+<<<
+  <div>
+<pre><code>&lt;div&gt;
+</code></pre>
+>>> HTML blocks - 154
+Foo
+<div>
+bar
+</div>
+<<<
+<p>Foo</p>
+<div>
+bar
+</div>
+>>> HTML blocks - 155
+<div>
+bar
+</div>
+*foo*
+<<<
+<div>
+bar
+</div>
+*foo*
+>>> HTML blocks - 156
+Foo
+<a href="bar">
+baz
+<<<
+<p>Foo
+<a href="bar">
+baz</p>
+>>> HTML blocks - 157
+<div>
+
+*Emphasized* text.
+
+</div>
+<<<
+<div>
+<p><em>Emphasized</em> text.</p>
+</div>
+>>> HTML blocks - 158
+<div>
+*Emphasized* text.
+</div>
+<<<
+<div>
+*Emphasized* text.
+</div>
+>>> HTML blocks - 159
+<table>
+
+<tr>
+
+<td>
+Hi
+</td>
+
+</tr>
+
+</table>
+<<<
+<table>
+<tr>
+<td>
+Hi
+</td>
+</tr>
+</table>
+>>> HTML blocks - 160
+<table>
+
+  <tr>
+
+    <td>
+      Hi
+    </td>
+
+  </tr>
+
+</table>
+<<<
+<table>
+  <tr>
+<pre><code>&lt;td&gt;
+  Hi
+&lt;/td&gt;
+</code></pre>
+  </tr>
+</table>
diff --git a/pkgs/markdown/test/gfm/images.unit b/pkgs/markdown/test/gfm/images.unit
new file mode 100644
index 0000000..106e1a2
--- /dev/null
+++ b/pkgs/markdown/test/gfm/images.unit
@@ -0,0 +1,121 @@
+>>> Images - 580
+![foo](/url "title")
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 581
+![foo *bar*]
+
+[foo *bar*]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 582
+![foo ![bar](/url)](/url2)
+<<<
+<p><img src="/url2" alt="foo bar" /></p>
+>>> Images - 583
+![foo [bar](/url)](/url2)
+<<<
+<p><img src="/url2" alt="foo bar" /></p>
+>>> Images - 584
+![foo *bar*][]
+
+[foo *bar*]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 585
+![foo *bar*][foobar]
+
+[FOOBAR]: train.jpg "train & tracks"
+<<<
+<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
+>>> Images - 586
+![foo](train.jpg)
+<<<
+<p><img src="train.jpg" alt="foo" /></p>
+>>> Images - 587
+My ![foo bar](/path/to/train.jpg  "title"   )
+<<<
+<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
+>>> Images - 588
+![foo](<url>)
+<<<
+<p><img src="url" alt="foo" /></p>
+>>> Images - 589
+![](/url)
+<<<
+<p><img src="/url" alt="" /></p>
+>>> Images - 590
+![foo][bar]
+
+[bar]: /url
+<<<
+<p><img src="/url" alt="foo" /></p>
+>>> Images - 591
+![foo][bar]
+
+[BAR]: /url
+<<<
+<p><img src="/url" alt="foo" /></p>
+>>> Images - 592
+![foo][]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 593
+![*foo* bar][]
+
+[*foo* bar]: /url "title"
+<<<
+<p><img src="/url" alt="foo bar" title="title" /></p>
+>>> Images - 594
+![Foo][]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="Foo" title="title" /></p>
+>>> Images - 595
+![foo] 
+[]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" />
+[]</p>
+>>> Images - 596
+![foo]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="foo" title="title" /></p>
+>>> Images - 597
+![*foo* bar]
+
+[*foo* bar]: /url "title"
+<<<
+<p><img src="/url" alt="foo bar" title="title" /></p>
+>>> Images - 598
+![[foo]]
+
+[[foo]]: /url "title"
+<<<
+<p>![[foo]]</p>
+<p>[[foo]]: /url &quot;title&quot;</p>
+>>> Images - 599
+![Foo]
+
+[foo]: /url "title"
+<<<
+<p><img src="/url" alt="Foo" title="title" /></p>
+>>> Images - 600
+!\[foo]
+
+[foo]: /url "title"
+<<<
+<p>![foo]</p>
+>>> Images - 601
+\![foo]
+
+[foo]: /url "title"
+<<<
+<p>!<a href="/url" title="title">foo</a></p>
diff --git a/pkgs/markdown/test/gfm/indented_code_blocks.unit b/pkgs/markdown/test/gfm/indented_code_blocks.unit
new file mode 100644
index 0000000..68fc6d1
--- /dev/null
+++ b/pkgs/markdown/test/gfm/indented_code_blocks.unit
@@ -0,0 +1,118 @@
+>>> Indented code blocks - 77
+    a simple
+      indented code block
+<<<
+<pre><code>a simple
+  indented code block
+</code></pre>
+>>> Indented code blocks - 78
+  - foo
+
+    bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> Indented code blocks - 79
+1.  foo
+
+    - bar
+<<<
+<ol>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+>>> Indented code blocks - 80
+    <a/>
+    *hi*
+
+    - one
+<<<
+<pre><code>&lt;a/&gt;
+*hi*
+
+- one
+</code></pre>
+>>> Indented code blocks - 81
+    chunk1
+
+    chunk2
+  
+ 
+ 
+    chunk3
+<<<
+<pre><code>chunk1
+
+chunk2
+
+
+
+chunk3
+</code></pre>
+>>> Indented code blocks - 82
+    chunk1
+      
+      chunk2
+<<<
+<pre><code>chunk1
+  
+  chunk2
+</code></pre>
+>>> Indented code blocks - 83
+Foo
+    bar
+
+<<<
+<p>Foo
+bar</p>
+>>> Indented code blocks - 84
+    foo
+bar
+<<<
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+>>> Indented code blocks - 85
+# Heading
+    foo
+Heading
+------
+    foo
+----
+<<<
+<h1>Heading</h1>
+<pre><code>foo
+</code></pre>
+<h2>Heading</h2>
+<pre><code>foo
+</code></pre>
+<hr />
+>>> Indented code blocks - 86
+        foo
+    bar
+<<<
+<pre><code>    foo
+bar
+</code></pre>
+>>> Indented code blocks - 87
+
+    
+    foo
+    
+
+<<<
+<pre><code>foo
+</code></pre>
+>>> Indented code blocks - 88
+    foo  
+<<<
+<pre><code>foo  
+</code></pre>
diff --git a/pkgs/markdown/test/gfm/inlines.unit b/pkgs/markdown/test/gfm/inlines.unit
new file mode 100644
index 0000000..9e19a33
--- /dev/null
+++ b/pkgs/markdown/test/gfm/inlines.unit
@@ -0,0 +1,4 @@
+>>> Inlines - 307
+`hi`lo`
+<<<
+<p><code>hi</code>lo`</p>
diff --git a/pkgs/markdown/test/gfm/link_reference_definitions.unit b/pkgs/markdown/test/gfm/link_reference_definitions.unit
new file mode 100644
index 0000000..b09236f
--- /dev/null
+++ b/pkgs/markdown/test/gfm/link_reference_definitions.unit
@@ -0,0 +1,206 @@
+>>> Link reference definitions - 161
+[foo]: /url "title"
+
+[foo]
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Link reference definitions - 162
+   [foo]: 
+      /url  
+           'the title'  
+
+[foo]
+<<<
+<p><a href="/url" title="the title">foo</a></p>
+>>> Link reference definitions - 163
+[Foo*bar\]]:my_(url) 'title (with parens)'
+
+[Foo*bar\]]
+<<<
+<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
+>>> Link reference definitions - 164
+[Foo bar]:
+<my url>
+'title'
+
+[Foo bar]
+<<<
+<p><a href="my%20url" title="title">Foo bar</a></p>
+>>> Link reference definitions - 165
+[foo]: /url '
+title
+line1
+line2
+'
+
+[foo]
+<<<
+<p><a href="/url" title="
+title
+line1
+line2
+">foo</a></p>
+>>> Link reference definitions - 166
+[foo]: /url 'title
+
+with blank line'
+
+[foo]
+<<<
+<p>[foo]: /url 'title</p>
+<p>with blank line'</p>
+<p>[foo]</p>
+>>> Link reference definitions - 167
+[foo]:
+/url
+
+[foo]
+<<<
+<p><a href="/url">foo</a></p>
+>>> Link reference definitions - 168
+[foo]:
+
+[foo]
+<<<
+<p>[foo]:</p>
+<p>[foo]</p>
+>>> Link reference definitions - 169
+[foo]: <>
+
+[foo]
+<<<
+<p><a href="">foo</a></p>
+>>> Link reference definitions - 170
+[foo]: <bar>(baz)
+
+[foo]
+<<<
+<p>[foo]: <bar>(baz)</p>
+<p>[foo]</p>
+>>> Link reference definitions - 171
+[foo]: /url\bar\*baz "foo\"bar\baz"
+
+[foo]
+<<<
+<p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
+>>> Link reference definitions - 172
+[foo]
+
+[foo]: url
+<<<
+<p><a href="url">foo</a></p>
+>>> Link reference definitions - 173
+[foo]
+
+[foo]: first
+[foo]: second
+<<<
+<p><a href="first">foo</a></p>
+>>> Link reference definitions - 174
+[FOO]: /url
+
+[Foo]
+<<<
+<p><a href="/url">Foo</a></p>
+>>> Link reference definitions - 175
+[ΑΓΩ]: /φου
+
+[αγω]
+<<<
+<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
+>>> Link reference definitions - 176
+[foo]: /url
+<<<
+
+>>> Link reference definitions - 177
+[
+foo
+]: /url
+bar
+<<<
+<p>bar</p>
+>>> Link reference definitions - 178
+[foo]: /url "title" ok
+<<<
+<p>[foo]: /url &quot;title&quot; ok</p>
+>>> Link reference definitions - 179
+[foo]: /url
+"title" ok
+<<<
+<p>&quot;title&quot; ok</p>
+>>> Link reference definitions - 180
+    [foo]: /url "title"
+
+[foo]
+<<<
+<pre><code>[foo]: /url &quot;title&quot;
+</code></pre>
+<p>[foo]</p>
+>>> Link reference definitions - 181
+```
+[foo]: /url
+```
+
+[foo]
+<<<
+<pre><code>[foo]: /url
+</code></pre>
+<p>[foo]</p>
+>>> Link reference definitions - 182
+Foo
+[bar]: /baz
+
+[bar]
+<<<
+<p>Foo
+[bar]: /baz</p>
+<p>[bar]</p>
+>>> Link reference definitions - 183
+# [Foo]
+[foo]: /url
+> bar
+<<<
+<h1><a href="/url">Foo</a></h1>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Link reference definitions - 184
+[foo]: /url
+bar
+===
+[foo]
+<<<
+<h1>bar</h1>
+<p><a href="/url">foo</a></p>
+>>> Link reference definitions - 185
+[foo]: /url
+===
+[foo]
+<<<
+<p>===
+<a href="/url">foo</a></p>
+>>> Link reference definitions - 186
+[foo]: /foo-url "foo"
+[bar]: /bar-url
+  "bar"
+[baz]: /baz-url
+
+[foo],
+[bar],
+[baz]
+<<<
+<p><a href="/foo-url" title="foo">foo</a>,
+<a href="/bar-url" title="bar">bar</a>,
+<a href="/baz-url">baz</a></p>
+>>> Link reference definitions - 187
+[foo]
+
+> [foo]: /url
+<<<
+<p><a href="/url">foo</a></p>
+<blockquote>
+</blockquote>
+>>> Link reference definitions - 188
+[foo]: /url
+<<<
+
diff --git a/pkgs/markdown/test/gfm/links.unit b/pkgs/markdown/test/gfm/links.unit
new file mode 100644
index 0000000..7288c79
--- /dev/null
+++ b/pkgs/markdown/test/gfm/links.unit
@@ -0,0 +1,476 @@
+>>> Links - 493
+[link](/uri "title")
+<<<
+<p><a href="/uri" title="title">link</a></p>
+>>> Links - 494
+[link](/uri)
+<<<
+<p><a href="/uri">link</a></p>
+>>> Links - 495
+[link]()
+<<<
+<p><a href="">link</a></p>
+>>> Links - 496
+[link](<>)
+<<<
+<p><a href="">link</a></p>
+>>> Links - 497
+[link](/my uri)
+<<<
+<p>[link](/my uri)</p>
+>>> Links - 498
+[link](</my uri>)
+<<<
+<p><a href="/my%20uri">link</a></p>
+>>> Links - 499
+[link](foo
+bar)
+<<<
+<p>[link](foo
+bar)</p>
+>>> Links - 500
+[link](<foo
+bar>)
+<<<
+<p>[link](<foo
+bar>)</p>
+>>> Links - 501
+[a](<b)c>)
+<<<
+<p><a href="b)c">a</a></p>
+>>> Links - 502
+[link](<foo\>)
+<<<
+<p>[link](&lt;foo&gt;)</p>
+>>> Links - 503
+[a](<b)c
+[a](<b)c>
+[a](<b>c)
+<<<
+<p>[a](&lt;b)c
+[a](&lt;b)c&gt;
+[a](<b>c)</p>
+>>> Links - 504
+[link](\(foo\))
+<<<
+<p><a href="(foo)">link</a></p>
+>>> Links - 505
+[link](foo(and(bar)))
+<<<
+<p><a href="foo(and(bar))">link</a></p>
+>>> Links - 506
+[link](foo\(and\(bar\))
+<<<
+<p><a href="foo(and(bar)">link</a></p>
+>>> Links - 507
+[link](<foo(and(bar)>)
+<<<
+<p><a href="foo(and(bar)">link</a></p>
+>>> Links - 508
+[link](foo\)\:)
+<<<
+<p><a href="foo):">link</a></p>
+>>> Links - 509
+[link](#fragment)
+
+[link](http://example.com#fragment)
+
+[link](http://example.com?foo=3#frag)
+<<<
+<p><a href="#fragment">link</a></p>
+<p><a href="http://example.com#fragment">link</a></p>
+<p><a href="http://example.com?foo=3#frag">link</a></p>
+>>> Links - 510
+[link](foo\bar)
+<<<
+<p><a href="foo%5Cbar">link</a></p>
+>>> Links - 511
+[link](foo%20b&auml;)
+<<<
+<p><a href="foo%20b%C3%A4">link</a></p>
+>>> Links - 512
+[link]("title")
+<<<
+<p><a href="%22title%22">link</a></p>
+>>> Links - 513
+[link](/url "title")
+[link](/url 'title')
+[link](/url (title))
+<<<
+<p><a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a>
+<a href="/url" title="title">link</a></p>
+>>> Links - 514
+[link](/url "title \"&quot;")
+<<<
+<p><a href="/url" title="title &quot;&quot;">link</a></p>
+>>> Links - 515
+[link](/url "title")
+<<<
+<p><a href="/url%C2%A0%22title%22">link</a></p>
+>>> Links - 516
+[link](/url "title "and" title")
+<<<
+<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
+>>> Links - 517
+[link](/url 'title "and" title')
+<<<
+<p><a href="/url" title="title &quot;and&quot; title">link</a></p>
+>>> Links - 518
+[link](   /uri
+  "title"  )
+<<<
+<p><a href="/uri" title="title">link</a></p>
+>>> Links - 519
+[link] (/uri)
+<<<
+<p>[link] (/uri)</p>
+>>> Links - 520
+[link [foo [bar]]](/uri)
+<<<
+<p><a href="/uri">link [foo [bar]]</a></p>
+>>> Links - 521
+[link] bar](/uri)
+<<<
+<p>[link] bar](/uri)</p>
+>>> Links - 522
+[link [bar](/uri)
+<<<
+<p>[link <a href="/uri">bar</a></p>
+>>> Links - 523
+[link \[bar](/uri)
+<<<
+<p><a href="/uri">link [bar</a></p>
+>>> Links - 524
+[link *foo **bar** `#`*](/uri)
+<<<
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+>>> Links - 525
+[![moon](moon.jpg)](/uri)
+<<<
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+>>> Links - 526
+[foo [bar](/uri)](/uri)
+<<<
+<p>[foo <a href="/uri">bar</a>](/uri)</p>
+>>> Links - 527
+[foo *[bar [baz](/uri)](/uri)*](/uri)
+<<<
+<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
+>>> Links - 528
+![[[foo](uri1)](uri2)](uri3)
+<<<
+<p><img src="uri3" alt="[foo](uri2)" /></p>
+>>> Links - 529
+*[foo*](/uri)
+<<<
+<p>*<a href="/uri">foo*</a></p>
+>>> Links - 530
+[foo *bar](baz*)
+<<<
+<p><a href="baz*">foo *bar</a></p>
+>>> Links - 531
+*foo [bar* baz]
+<<<
+<p><em>foo [bar</em> baz]</p>
+>>> Links - 532
+[foo <bar attr="](baz)">
+<<<
+<p>[foo <bar attr="](baz)"></p>
+>>> Links - 533
+[foo`](/uri)`
+<<<
+<p>[foo<code>](/uri)</code></p>
+>>> Links - 534
+[foo<http://example.com/?search=](uri)>
+<<<
+<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
+>>> Links - 535
+[foo][bar]
+
+[bar]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 536
+[link [foo [bar]]][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link [foo [bar]]</a></p>
+>>> Links - 537
+[link \[bar][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link [bar</a></p>
+>>> Links - 538
+[link *foo **bar** `#`*][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
+>>> Links - 539
+[![moon](moon.jpg)][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
+>>> Links - 540
+[foo [bar](/uri)][ref]
+
+[ref]: /uri
+<<<
+<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
+>>> Links - 541
+[foo *bar [baz][ref]*][ref]
+
+[ref]: /uri
+<<<
+<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
+>>> Links - 542
+*[foo*][ref]
+
+[ref]: /uri
+<<<
+<p>*<a href="/uri">foo*</a></p>
+>>> Links - 543
+[foo *bar][ref]
+
+[ref]: /uri
+<<<
+<p><a href="/uri">foo *bar</a></p>
+>>> Links - 544
+[foo <bar attr="][ref]">
+
+[ref]: /uri
+<<<
+<p>[foo <bar attr="][ref]"></p>
+>>> Links - 545
+[foo`][ref]`
+
+[ref]: /uri
+<<<
+<p>[foo<code>][ref]</code></p>
+>>> Links - 546
+[foo<http://example.com/?search=][ref]>
+
+[ref]: /uri
+<<<
+<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
+>>> Links - 547
+[foo][BaR]
+
+[bar]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 548
+[Толпой][Толпой] is a Russian word.
+
+[ТОЛПОЙ]: /url
+<<<
+<p><a href="/url">Толпой</a> is a Russian word.</p>
+>>> Links - 549
+[Foo
+  bar]: /url
+
+[Baz][Foo bar]
+<<<
+<p><a href="/url">Baz</a></p>
+>>> Links - 550
+[foo] [bar]
+
+[bar]: /url "title"
+<<<
+<p>[foo] <a href="/url" title="title">bar</a></p>
+>>> Links - 551
+[foo]
+[bar]
+
+[bar]: /url "title"
+<<<
+<p>[foo]
+<a href="/url" title="title">bar</a></p>
+>>> Links - 552
+[foo]: /url1
+
+[foo]: /url2
+
+[bar][foo]
+<<<
+<p><a href="/url1">bar</a></p>
+>>> Links - 553
+[bar][foo\!]
+
+[foo!]: /url
+<<<
+<p>[bar][foo!]</p>
+>>> Links - 554
+[foo][ref[]
+
+[ref[]: /uri
+<<<
+<p>[foo][ref[]</p>
+<p>[ref[]: /uri</p>
+>>> Links - 555
+[foo][ref[bar]]
+
+[ref[bar]]: /uri
+<<<
+<p>[foo][ref[bar]]</p>
+<p>[ref[bar]]: /uri</p>
+>>> Links - 556
+[[[foo]]]
+
+[[[foo]]]: /url
+<<<
+<p>[[[foo]]]</p>
+<p>[[[foo]]]: /url</p>
+>>> Links - 557
+[foo][ref\[]
+
+[ref\[]: /uri
+<<<
+<p><a href="/uri">foo</a></p>
+>>> Links - 558
+[bar\\]: /uri
+
+[bar\\]
+<<<
+<p><a href="/uri">bar\</a></p>
+>>> Links - 559
+[]
+
+[]: /uri
+<<<
+<p>[]</p>
+<p>[]: /uri</p>
+>>> Links - 560
+[
+ ]
+
+[
+ ]: /uri
+<<<
+<p>[
+]</p>
+<p>[
+]: /uri</p>
+>>> Links - 561
+[foo][]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 562
+[*foo* bar][]
+
+[*foo* bar]: /url "title"
+<<<
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+>>> Links - 563
+[Foo][]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">Foo</a></p>
+>>> Links - 564
+[foo] 
+[]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a>
+[]</p>
+>>> Links - 565
+[foo]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">foo</a></p>
+>>> Links - 566
+[*foo* bar]
+
+[*foo* bar]: /url "title"
+<<<
+<p><a href="/url" title="title"><em>foo</em> bar</a></p>
+>>> Links - 567
+[[*foo* bar]]
+
+[*foo* bar]: /url "title"
+<<<
+<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
+>>> Links - 568
+[[bar [foo]
+
+[foo]: /url
+<<<
+<p>[[bar <a href="/url">foo</a></p>
+>>> Links - 569
+[Foo]
+
+[foo]: /url "title"
+<<<
+<p><a href="/url" title="title">Foo</a></p>
+>>> Links - 570
+[foo] bar
+
+[foo]: /url
+<<<
+<p><a href="/url">foo</a> bar</p>
+>>> Links - 571
+\[foo]
+
+[foo]: /url "title"
+<<<
+<p>[foo]</p>
+>>> Links - 572
+[foo*]: /url
+
+*[foo*]
+<<<
+<p>*<a href="/url">foo*</a></p>
+>>> Links - 573
+[foo][bar]
+
+[foo]: /url1
+[bar]: /url2
+<<<
+<p><a href="/url2">foo</a></p>
+>>> Links - 574
+[foo][]
+
+[foo]: /url1
+<<<
+<p><a href="/url1">foo</a></p>
+>>> Links - 575
+[foo]()
+
+[foo]: /url1
+<<<
+<p><a href="">foo</a></p>
+>>> Links - 576
+[foo](not a link)
+
+[foo]: /url1
+<<<
+<p><a href="/url1">foo</a>(not a link)</p>
+>>> Links - 577
+[foo][bar][baz]
+
+[baz]: /url
+<<<
+<p>[foo]<a href="/url">bar</a></p>
+>>> Links - 578
+[foo][bar][baz]
+
+[baz]: /url1
+[bar]: /url2
+<<<
+<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
+>>> Links - 579
+[foo][bar][baz]
+
+[baz]: /url1
+[foo]: /url2
+<<<
+<p>[foo]<a href="/url1">bar</a></p>
diff --git a/pkgs/markdown/test/gfm/list_items.unit b/pkgs/markdown/test/gfm/list_items.unit
new file mode 100644
index 0000000..3954af8
--- /dev/null
+++ b/pkgs/markdown/test/gfm/list_items.unit
@@ -0,0 +1,586 @@
+>>> List items - 231
+A paragraph
+with two lines.
+
+    indented code
+
+> A block quote.
+<<<
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+>>> List items - 232
+1.  A paragraph
+    with two lines.
+
+        indented code
+
+    > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 233
+- one
+
+ two
+<<<
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+>>> List items - 234
+- one
+
+  two
+<<<
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+>>> List items - 235
+ -    one
+
+     two
+<<<
+<ul>
+<li>one</li>
+</ul>
+<pre><code> two
+</code></pre>
+>>> List items - 236
+ -    one
+
+      two
+<<<
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ul>
+>>> List items - 237
+   > > 1.  one
+>>
+>>     two
+<<<
+<blockquote>
+<blockquote>
+<ol>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+</ol>
+</blockquote>
+</blockquote>
+>>> List items - 238
+>>- one
+>>
+  >  > two
+<<<
+<blockquote>
+<blockquote>
+<ul>
+<li>one</li>
+</ul>
+<p>two</p>
+</blockquote>
+</blockquote>
+>>> List items - 239
+-one
+
+2.two
+<<<
+<p>-one</p>
+<p>2.two</p>
+>>> List items - 240
+- foo
+
+
+  bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> List items - 241
+1.  foo
+
+    ```
+    bar
+    ```
+
+    baz
+
+    > bam
+<<<
+<ol>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+<p>baz</p>
+<blockquote>
+<p>bam</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 242
+- Foo
+
+      bar
+
+
+      baz
+<<<
+<ul>
+<li>
+<p>Foo</p>
+<pre><code>bar
+
+
+baz
+</code></pre>
+</li>
+</ul>
+>>> List items - 243
+123456789. ok
+<<<
+<ol start="123456789">
+<li>ok</li>
+</ol>
+>>> List items - 244
+1234567890. not ok
+<<<
+<p>1234567890. not ok</p>
+>>> List items - 245
+0. ok
+<<<
+<ol start="0">
+<li>ok</li>
+</ol>
+>>> List items - 246
+003. ok
+<<<
+<ol start="3">
+<li>ok</li>
+</ol>
+>>> List items - 247
+-1. not ok
+<<<
+<p>-1. not ok</p>
+>>> List items - 248
+- foo
+
+      bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ul>
+>>> List items - 249
+  10.  foo
+
+           bar
+<<<
+<ol start="10">
+<li>
+<p>foo</p>
+<pre><code>bar
+</code></pre>
+</li>
+</ol>
+>>> List items - 250
+    indented code
+
+paragraph
+
+    more code
+<<<
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+>>> List items - 251
+1.     indented code
+
+   paragraph
+
+       more code
+<<<
+<ol>
+<li>
+<pre><code>indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+>>> List items - 252
+1.      indented code
+
+   paragraph
+
+       more code
+<<<
+<ol>
+<li>
+<pre><code> indented code
+</code></pre>
+<p>paragraph</p>
+<pre><code>more code
+</code></pre>
+</li>
+</ol>
+>>> List items - 253
+   foo
+
+bar
+<<<
+<p>foo</p>
+<p>bar</p>
+>>> List items - 254
+-    foo
+
+  bar
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<p>bar</p>
+>>> List items - 255
+-  foo
+
+   bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> List items - 256
+-
+  foo
+-
+  ```
+  bar
+  ```
+-
+      baz
+<<<
+<ul>
+<li>foo</li>
+<li>
+<pre><code>bar
+</code></pre>
+</li>
+<li>
+<pre><code>baz
+</code></pre>
+</li>
+</ul>
+>>> List items - 257
+-   
+  foo
+<<<
+<ul>
+<li>foo</li>
+</ul>
+>>> List items - 258
+-
+
+  foo
+<<<
+<ul>
+<li></li>
+</ul>
+<p>foo</p>
+>>> List items - 259
+- foo
+-
+- bar
+<<<
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+>>> List items - 260
+- foo
+-   
+- bar
+<<<
+<ul>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ul>
+>>> List items - 261
+1. foo
+2.
+3. bar
+<<<
+<ol>
+<li>foo</li>
+<li></li>
+<li>bar</li>
+</ol>
+>>> List items - 262
+*
+<<<
+<ul>
+<li></li>
+</ul>
+>>> List items - 263
+foo
+*
+
+foo
+1.
+<<<
+<p>foo
+*</p>
+<p>foo
+1.</p>
+>>> List items - 264
+ 1.  A paragraph
+     with two lines.
+
+         indented code
+
+     > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 265
+  1.  A paragraph
+      with two lines.
+
+          indented code
+
+      > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 266
+   1.  A paragraph
+       with two lines.
+
+           indented code
+
+       > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 267
+    1.  A paragraph
+        with two lines.
+
+            indented code
+
+        > A block quote.
+<<<
+<pre><code>1.  A paragraph
+    with two lines.
+
+        indented code
+
+    &gt; A block quote.
+</code></pre>
+>>> List items - 268
+  1.  A paragraph
+with two lines.
+
+          indented code
+
+      > A block quote.
+<<<
+<ol>
+<li>
+<p>A paragraph
+with two lines.</p>
+<pre><code>indented code
+</code></pre>
+<blockquote>
+<p>A block quote.</p>
+</blockquote>
+</li>
+</ol>
+>>> List items - 269
+  1.  A paragraph
+    with two lines.
+<<<
+<ol>
+<li>A paragraph
+with two lines.</li>
+</ol>
+>>> List items - 270
+> 1. > Blockquote
+continued here.
+<<<
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+>>> List items - 271
+> 1. > Blockquote
+> continued here.
+<<<
+<blockquote>
+<ol>
+<li>
+<blockquote>
+<p>Blockquote
+continued here.</p>
+</blockquote>
+</li>
+</ol>
+</blockquote>
+>>> List items - 272
+- foo
+  - bar
+    - baz
+      - boo
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz
+<ul>
+<li>boo</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> List items - 273
+- foo
+ - bar
+  - baz
+   - boo
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+<li>baz</li>
+<li>boo</li>
+</ul>
+>>> List items - 274
+10) foo
+    - bar
+<<<
+<ol start="10">
+<li>foo
+<ul>
+<li>bar</li>
+</ul>
+</li>
+</ol>
+>>> List items - 275
+10) foo
+   - bar
+<<<
+<ol start="10">
+<li>foo</li>
+</ol>
+<ul>
+<li>bar</li>
+</ul>
+>>> List items - 276
+- - foo
+<<<
+<ul>
+<li>
+<ul>
+<li>foo</li>
+</ul>
+</li>
+</ul>
+>>> List items - 277
+1. - 2. foo
+<<<
+<ol>
+<li>
+<ul>
+<li>
+<ol start="2">
+<li>foo</li>
+</ol>
+</li>
+</ul>
+</li>
+</ol>
+>>> List items - 278
+- # Foo
+- Bar
+  ---
+  baz
+<<<
+<ul>
+<li>
+<h1>Foo</h1>
+</li>
+<li>
+<h2>Bar</h2>
+baz</li>
+</ul>
diff --git a/pkgs/markdown/test/gfm/lists.unit b/pkgs/markdown/test/gfm/lists.unit
new file mode 100644
index 0000000..e5802db
--- /dev/null
+++ b/pkgs/markdown/test/gfm/lists.unit
@@ -0,0 +1,406 @@
+>>> Lists - 281
+- foo
+- bar
++ baz
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<ul>
+<li>baz</li>
+</ul>
+>>> Lists - 282
+1. foo
+2. bar
+3) baz
+<<<
+<ol>
+<li>foo</li>
+<li>bar</li>
+</ol>
+<ol start="3">
+<li>baz</li>
+</ol>
+>>> Lists - 283
+Foo
+- bar
+- baz
+<<<
+<p>Foo</p>
+<ul>
+<li>bar</li>
+<li>baz</li>
+</ul>
+>>> Lists - 284
+The number of windows in my house is
+14.  The number of doors is 6.
+<<<
+<p>The number of windows in my house is
+14.  The number of doors is 6.</p>
+>>> Lists - 285
+The number of windows in my house is
+1.  The number of doors is 6.
+<<<
+<p>The number of windows in my house is</p>
+<ol>
+<li>The number of doors is 6.</li>
+</ol>
+>>> Lists - 286
+- foo
+
+- bar
+
+
+- baz
+<<<
+<ul>
+<li>
+<p>foo</p>
+</li>
+<li>
+<p>bar</p>
+</li>
+<li>
+<p>baz</p>
+</li>
+</ul>
+>>> Lists - 287
+- foo
+  - bar
+    - baz
+
+
+      bim
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>
+<p>baz</p>
+<p>bim</p>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> Lists - 288
+- foo
+- bar
+
+<!-- -->
+
+- baz
+- bim
+<<<
+<ul>
+<li>foo</li>
+<li>bar</li>
+</ul>
+<!-- -->
+<ul>
+<li>baz</li>
+<li>bim</li>
+</ul>
+>>> Lists - 289
+-   foo
+
+    notcode
+
+-   foo
+
+<!-- -->
+
+    code
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>notcode</p>
+</li>
+<li>
+<p>foo</p>
+</li>
+</ul>
+<!-- -->
+<pre><code>code
+</code></pre>
+>>> Lists - 290
+- a
+ - b
+  - c
+   - d
+  - e
+ - f
+- g
+<<<
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d</li>
+<li>e</li>
+<li>f</li>
+<li>g</li>
+</ul>
+>>> Lists - 291
+1. a
+
+  2. b
+
+   3. c
+<<<
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ol>
+>>> Lists - 292
+- a
+ - b
+  - c
+   - d
+    - e
+<<<
+<ul>
+<li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d
+- e</li>
+</ul>
+>>> Lists - 293
+1. a
+
+  2. b
+
+    3. c
+<<<
+<ol>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+</ol>
+<pre><code>3. c
+</code></pre>
+>>> Lists - 294
+- a
+- b
+
+- c
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>c</p>
+</li>
+</ul>
+>>> Lists - 295
+* a
+*
+
+* c
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li></li>
+<li>
+<p>c</p>
+</li>
+</ul>
+>>> Lists - 296
+- a
+- b
+
+  c
+- d
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+>>> Lists - 297
+- a
+- b
+
+  [ref]: /url
+- d
+<<<
+<ul>
+<li>
+<p>a</p>
+</li>
+<li>
+<p>b</p>
+</li>
+<li>
+<p>d</p>
+</li>
+</ul>
+>>> Lists - 298
+- a
+- ```
+  b
+
+
+  ```
+- c
+<<<
+<ul>
+<li>a</li>
+<li>
+<pre><code>b
+
+
+</code></pre>
+</li>
+<li>c</li>
+</ul>
+>>> Lists - 299
+- a
+  - b
+
+    c
+- d
+<<<
+<ul>
+<li>a
+<ul>
+<li>
+<p>b</p>
+<p>c</p>
+</li>
+</ul>
+</li>
+<li>d</li>
+</ul>
+>>> Lists - 300
+* a
+  > b
+  >
+* c
+<<<
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+</li>
+<li>c</li>
+</ul>
+>>> Lists - 301
+- a
+  > b
+  ```
+  c
+  ```
+- d
+<<<
+<ul>
+<li>a
+<blockquote>
+<p>b</p>
+</blockquote>
+<pre><code>c
+</code></pre>
+</li>
+<li>d</li>
+</ul>
+>>> Lists - 302
+- a
+<<<
+<ul>
+<li>a</li>
+</ul>
+>>> Lists - 303
+- a
+  - b
+<<<
+<ul>
+<li>a
+<ul>
+<li>b</li>
+</ul>
+</li>
+</ul>
+>>> Lists - 304
+1. ```
+   foo
+   ```
+
+   bar
+<<<
+<ol>
+<li>
+<pre><code>foo
+</code></pre>
+<p>bar</p>
+</li>
+</ol>
+>>> Lists - 305
+* foo
+  * bar
+
+  baz
+<<<
+<ul>
+<li>
+<p>foo</p>
+<ul>
+<li>bar</li>
+</ul>
+<p>baz</p>
+</li>
+</ul>
+>>> Lists - 306
+- a
+  - b
+  - c
+
+- d
+  - e
+  - f
+<<<
+<ul>
+<li>
+<p>a</p>
+<ul>
+<li>b</li>
+<li>c</li>
+</ul>
+</li>
+<li>
+<p>d</p>
+<ul>
+<li>e</li>
+<li>f</li>
+</ul>
+</li>
+</ul>
diff --git a/pkgs/markdown/test/gfm/paragraphs.unit b/pkgs/markdown/test/gfm/paragraphs.unit
new file mode 100644
index 0000000..a6fc2b1
--- /dev/null
+++ b/pkgs/markdown/test/gfm/paragraphs.unit
@@ -0,0 +1,59 @@
+>>> Paragraphs - 189
+aaa
+
+bbb
+<<<
+<p>aaa</p>
+<p>bbb</p>
+>>> Paragraphs - 190
+aaa
+bbb
+
+ccc
+ddd
+<<<
+<p>aaa
+bbb</p>
+<p>ccc
+ddd</p>
+>>> Paragraphs - 191
+aaa
+
+
+bbb
+<<<
+<p>aaa</p>
+<p>bbb</p>
+>>> Paragraphs - 192
+  aaa
+ bbb
+<<<
+<p>aaa
+bbb</p>
+>>> Paragraphs - 193
+aaa
+             bbb
+                                       ccc
+<<<
+<p>aaa
+bbb
+ccc</p>
+>>> Paragraphs - 194
+   aaa
+bbb
+<<<
+<p>aaa
+bbb</p>
+>>> Paragraphs - 195
+    aaa
+bbb
+<<<
+<pre><code>aaa
+</code></pre>
+<p>bbb</p>
+>>> Paragraphs - 196
+aaa     
+bbb     
+<<<
+<p>aaa<br />
+bbb</p>
diff --git a/pkgs/markdown/test/gfm/precedence.unit b/pkgs/markdown/test/gfm/precedence.unit
new file mode 100644
index 0000000..793a094
--- /dev/null
+++ b/pkgs/markdown/test/gfm/precedence.unit
@@ -0,0 +1,8 @@
+>>> Precedence - 12
+- `one
+- two`
+<<<
+<ul>
+<li>`one</li>
+<li>two`</li>
+</ul>
diff --git a/pkgs/markdown/test/gfm/raw_html.unit b/pkgs/markdown/test/gfm/raw_html.unit
new file mode 100644
index 0000000..b408353
--- /dev/null
+++ b/pkgs/markdown/test/gfm/raw_html.unit
@@ -0,0 +1,95 @@
+>>> Raw HTML - 632
+<a><bab><c2c>
+<<<
+<p><a><bab><c2c></p>
+>>> Raw HTML - 633
+<a/><b2/>
+<<<
+<p><a/><b2/></p>
+>>> Raw HTML - 634
+<a  /><b2
+data="foo" >
+<<<
+<p><a  /><b2
+data="foo" ></p>
+>>> Raw HTML - 635
+<a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 />
+<<<
+<p><a foo="bar" bam = 'baz <em>"</em>'
+_boolean zoop:33=zoop:33 /></p>
+>>> Raw HTML - 636
+Foo <responsive-image src="foo.jpg" />
+<<<
+<p>Foo <responsive-image src="foo.jpg" /></p>
+>>> Raw HTML - 637
+<33> <__>
+<<<
+<p>&lt;33&gt; &lt;__&gt;</p>
+>>> Raw HTML - 638
+<a h*#ref="hi">
+<<<
+<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
+>>> Raw HTML - 639
+<a href="hi'> <a href=hi'>
+<<<
+<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
+>>> Raw HTML - 640
+< a><
+foo><bar/ >
+<foo bar=baz
+bim!bop />
+<<<
+<p>&lt; a&gt;&lt;
+foo&gt;&lt;bar/ &gt;
+&lt;foo bar=baz
+bim!bop /&gt;</p>
+>>> Raw HTML - 641
+<a href='bar'title=title>
+<<<
+<p>&lt;a href='bar'title=title&gt;</p>
+>>> Raw HTML - 642
+</a></foo >
+<<<
+<p></a></foo ></p>
+>>> Raw HTML - 643
+</a href="foo">
+<<<
+<p>&lt;/a href=&quot;foo&quot;&gt;</p>
+>>> Raw HTML - 644
+foo <!-- this is a --
+comment - with hyphens -->
+<<<
+<p>foo &lt;!-- this is a --
+comment - with hyphens --&gt;</p>
+>>> Raw HTML - 645
+foo <!--> foo -->
+
+foo <!---> foo -->
+<<<
+<p>foo &lt;!--&gt; foo --&gt;</p>
+<p>foo &lt;!---&gt; foo --&gt;</p>
+>>> Raw HTML - 646
+foo <?php echo $a; ?>
+<<<
+<p>foo <?php echo $a; ?></p>
+>>> Raw HTML - 647
+foo <!ELEMENT br EMPTY>
+<<<
+<p>foo <!ELEMENT br EMPTY></p>
+>>> Raw HTML - 648
+foo <![CDATA[>&<]]>
+<<<
+<p>foo <![CDATA[>&<]]></p>
+>>> Raw HTML - 649
+foo <a href="&ouml;">
+<<<
+<p>foo <a href="&ouml;"></p>
+>>> Raw HTML - 650
+foo <a href="\*">
+<<<
+<p>foo <a href="\*"></p>
+>>> Raw HTML - 651
+<a href="\"">
+<<<
+<p>&lt;a href=&quot;&quot;&quot;&gt;</p>
diff --git a/pkgs/markdown/test/gfm/setext_headings.unit b/pkgs/markdown/test/gfm/setext_headings.unit
new file mode 100644
index 0000000..725a175
--- /dev/null
+++ b/pkgs/markdown/test/gfm/setext_headings.unit
@@ -0,0 +1,229 @@
+>>> Setext headings - 50
+Foo *bar*
+=========
+
+Foo *bar*
+---------
+<<<
+<h1>Foo <em>bar</em></h1>
+<h2>Foo <em>bar</em></h2>
+>>> Setext headings - 51
+Foo *bar
+baz*
+====
+<<<
+<h1>Foo <em>bar
+baz</em></h1>
+>>> Setext headings - 52
+  Foo *bar
+baz*	
+====
+<<<
+<h1>  Foo <em>bar
+baz</em></h1>
+>>> Setext headings - 53
+Foo
+-------------------------
+
+Foo
+=
+<<<
+<h2>Foo</h2>
+<h1>Foo</h1>
+>>> Setext headings - 54
+   Foo
+---
+
+  Foo
+-----
+
+  Foo
+  ===
+<<<
+<h2>   Foo</h2>
+<h2>  Foo</h2>
+<h1>  Foo</h1>
+>>> Setext headings - 55
+    Foo
+    ---
+
+    Foo
+---
+<<<
+<pre><code>Foo
+---
+
+Foo
+</code></pre>
+<hr />
+>>> Setext headings - 56
+Foo
+   ----      
+<<<
+<h2>Foo</h2>
+>>> Setext headings - 57
+Foo
+    ---
+<<<
+<p>Foo
+---</p>
+>>> Setext headings - 58
+Foo
+= =
+
+Foo
+--- -
+<<<
+<p>Foo
+= =</p>
+<p>Foo</p>
+<hr />
+>>> Setext headings - 59
+Foo  
+-----
+<<<
+<h2>Foo</h2>
+>>> Setext headings - 60
+Foo\
+----
+<<<
+<h2>Foo\</h2>
+>>> Setext headings - 61
+`Foo
+----
+`
+
+<a title="a lot
+---
+of dashes"/>
+<<<
+<h2>`Foo</h2>
+<p>`</p>
+<h2>&lt;a title=&quot;a lot</h2>
+<p>of dashes&quot;/&gt;</p>
+>>> Setext headings - 62
+> Foo
+---
+<<<
+<blockquote>
+<p>Foo</p>
+</blockquote>
+<hr />
+>>> Setext headings - 63
+> foo
+bar
+===
+<<<
+<blockquote>
+<p>foo
+bar
+===</p>
+</blockquote>
+>>> Setext headings - 64
+- Foo
+---
+<<<
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+>>> Setext headings - 65
+Foo
+Bar
+---
+<<<
+<h2>Foo
+Bar</h2>
+>>> Setext headings - 66
+---
+Foo
+---
+Bar
+---
+Baz
+<<<
+<hr />
+<h2>Foo</h2>
+<h2>Bar</h2>
+<p>Baz</p>
+>>> Setext headings - 67
+
+====
+<<<
+<p>====</p>
+>>> Setext headings - 68
+---
+---
+<<<
+<hr />
+<hr />
+>>> Setext headings - 69
+- foo
+-----
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+>>> Setext headings - 70
+    foo
+---
+<<<
+<pre><code>foo
+</code></pre>
+<hr />
+>>> Setext headings - 71
+> foo
+-----
+<<<
+<blockquote>
+<p>foo</p>
+</blockquote>
+<hr />
+>>> Setext headings - 72
+\> foo
+------
+<<<
+<h2>&gt; foo</h2>
+>>> Setext headings - 73
+Foo
+
+bar
+---
+baz
+<<<
+<p>Foo</p>
+<h2>bar</h2>
+<p>baz</p>
+>>> Setext headings - 74
+Foo
+bar
+
+---
+
+baz
+<<<
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+>>> Setext headings - 75
+Foo
+bar
+* * *
+baz
+<<<
+<p>Foo
+bar</p>
+<hr />
+<p>baz</p>
+>>> Setext headings - 76
+Foo
+bar
+\---
+baz
+<<<
+<p>Foo
+bar
+---
+baz</p>
diff --git a/pkgs/markdown/test/gfm/soft_line_breaks.unit b/pkgs/markdown/test/gfm/soft_line_breaks.unit
new file mode 100644
index 0000000..2186b00
--- /dev/null
+++ b/pkgs/markdown/test/gfm/soft_line_breaks.unit
@@ -0,0 +1,12 @@
+>>> Soft line breaks - 668
+foo
+baz
+<<<
+<p>foo
+baz</p>
+>>> Soft line breaks - 669
+foo 
+ baz
+<<<
+<p>foo
+baz</p>
diff --git a/pkgs/markdown/test/gfm/strikethrough_extension.unit b/pkgs/markdown/test/gfm/strikethrough_extension.unit
new file mode 100644
index 0000000..0d6f75f
--- /dev/null
+++ b/pkgs/markdown/test/gfm/strikethrough_extension.unit
@@ -0,0 +1,19 @@
+>>> Strikethrough (extension) - 491
+~~Hi~~ Hello, world!
+<<<
+<p><del>Hi</del> Hello, world!</p>
+>>> Strikethrough (extension) - 492
+This ~~has a
+
+new paragraph~~.
+<<<
+<p>This ~~has a</p>
+<p>new paragraph~~.</p>
+>>> single tilde
+~Hi~ there.
+<<<
+<p><del>Hi</del> there.</p>
+>>> single tilde with double tilde
+~Hi~~ there.
+<<<
+<p><del>Hi</del>~ there.</p>
diff --git a/pkgs/markdown/test/gfm/tables_extension.unit b/pkgs/markdown/test/gfm/tables_extension.unit
new file mode 100644
index 0000000..625fca8
--- /dev/null
+++ b/pkgs/markdown/test/gfm/tables_extension.unit
@@ -0,0 +1,153 @@
+>>> Tables (extension) - 198
+| foo | bar |
+| --- | --- |
+| baz | bim |
+<<<
+<table>
+<thead>
+<tr>
+<th>foo</th>
+<th>bar</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>baz</td>
+<td>bim</td>
+</tr>
+</tbody>
+</table>
+>>> Tables (extension) - 199
+| abc | defghi |
+:-: | -----------:
+bar | baz
+<<<
+<table>
+<thead>
+<tr>
+<th align="center">abc</th>
+<th align="right">defghi</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">bar</td>
+<td align="right">baz</td>
+</tr>
+</tbody>
+</table>
+>>> Tables (extension) - 200
+| f\|oo  |
+| ------ |
+| b `\|` az |
+| b **\|** im |
+<<<
+<table>
+<thead>
+<tr>
+<th>f|oo</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>b <code>|</code> az</td>
+</tr>
+<tr>
+<td>b <strong>|</strong> im</td>
+</tr>
+</tbody>
+</table>
+>>> Tables (extension) - 201
+| abc | def |
+| --- | --- |
+| bar | baz |
+> bar
+<<<
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+</tbody>
+</table>
+<blockquote>
+<p>bar</p>
+</blockquote>
+>>> Tables (extension) - 202
+| abc | def |
+| --- | --- |
+| bar | baz |
+bar
+
+bar
+<<<
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+<tr>
+<td>bar</td>
+<td></td>
+</tr>
+</tbody>
+</table>
+<p>bar</p>
+>>> Tables (extension) - 203
+| abc | def |
+| --- |
+| bar |
+<<<
+<p>| abc | def |
+| --- |
+| bar |</p>
+>>> Tables (extension) - 204
+| abc | def |
+| --- | --- |
+| bar |
+| bar | baz | boo |
+<<<
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>bar</td>
+<td></td>
+</tr>
+<tr>
+<td>bar</td>
+<td>baz</td>
+</tr>
+</tbody>
+</table>
+>>> Tables (extension) - 205
+| abc | def |
+| --- | --- |
+<<<
+<table>
+<thead>
+<tr>
+<th>abc</th>
+<th>def</th>
+</tr>
+</thead>
+</table>
diff --git a/pkgs/markdown/test/gfm/tabs.unit b/pkgs/markdown/test/gfm/tabs.unit
new file mode 100644
index 0000000..1239481
--- /dev/null
+++ b/pkgs/markdown/test/gfm/tabs.unit
@@ -0,0 +1,87 @@
+>>> Tabs - 1
+	foo	baz		bim
+<<<
+<pre><code>foo	baz		bim
+</code></pre>
+>>> Tabs - 2
+  	foo	baz		bim
+<<<
+<pre><code>foo	baz		bim
+</code></pre>
+>>> Tabs - 3
+    a	a
+    ὐ	a
+<<<
+<pre><code>a	a
+ὐ	a
+</code></pre>
+>>> Tabs - 4
+  - foo
+
+	bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<p>bar</p>
+</li>
+</ul>
+>>> Tabs - 5
+- foo
+
+		bar
+<<<
+<ul>
+<li>
+<p>foo</p>
+<pre><code>  bar
+</code></pre>
+</li>
+</ul>
+>>> Tabs - 6
+>		foo
+<<<
+<blockquote>
+<pre><code>foo
+</code></pre>
+</blockquote>
+>>> Tabs - 7
+-		foo
+<<<
+<ul>
+<li>
+<pre><code>  foo
+</code></pre>
+</li>
+</ul>
+>>> Tabs - 8
+    foo
+	bar
+<<<
+<pre><code>foo
+bar
+</code></pre>
+>>> Tabs - 9
+ - foo
+   - bar
+	 - baz
+<<<
+<ul>
+<li>foo
+<ul>
+<li>bar
+<ul>
+<li>baz</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+>>> Tabs - 10
+#	Foo
+<<<
+<h1>Foo</h1>
+>>> Tabs - 11
+*	*	*	
+<<<
+<hr />
diff --git a/pkgs/markdown/test/gfm/textual_content.unit b/pkgs/markdown/test/gfm/textual_content.unit
new file mode 100644
index 0000000..7a1b02c
--- /dev/null
+++ b/pkgs/markdown/test/gfm/textual_content.unit
@@ -0,0 +1,12 @@
+>>> Textual content - 670
+hello $.;'there
+<<<
+<p>hello $.;'there</p>
+>>> Textual content - 671
+Foo χρῆν
+<<<
+<p>Foo χρῆν</p>
+>>> Textual content - 672
+Multiple     spaces
+<<<
+<p>Multiple     spaces</p>
diff --git a/pkgs/markdown/test/gfm/thematic_breaks.unit b/pkgs/markdown/test/gfm/thematic_breaks.unit
new file mode 100644
index 0000000..85206c8
--- /dev/null
+++ b/pkgs/markdown/test/gfm/thematic_breaks.unit
@@ -0,0 +1,126 @@
+>>> Thematic breaks - 13
+***
+---
+___
+<<<
+<hr />
+<hr />
+<hr />
+>>> Thematic breaks - 14
++++
+<<<
+<p>+++</p>
+>>> Thematic breaks - 15
+===
+<<<
+<p>===</p>
+>>> Thematic breaks - 16
+--
+**
+__
+<<<
+<p>--
+**
+__</p>
+>>> Thematic breaks - 17
+ ***
+  ***
+   ***
+<<<
+<hr />
+<hr />
+<hr />
+>>> Thematic breaks - 18
+    ***
+<<<
+<pre><code>***
+</code></pre>
+>>> Thematic breaks - 19
+Foo
+    ***
+<<<
+<p>Foo
+***</p>
+>>> Thematic breaks - 20
+_____________________________________
+<<<
+<hr />
+>>> Thematic breaks - 21
+ - - -
+<<<
+<hr />
+>>> Thematic breaks - 22
+ **  * ** * ** * **
+<<<
+<hr />
+>>> Thematic breaks - 23
+-     -      -      -
+<<<
+<hr />
+>>> Thematic breaks - 24
+- - - -    
+<<<
+<hr />
+>>> Thematic breaks - 25
+_ _ _ _ a
+
+a------
+
+---a---
+<<<
+<p>_ _ _ _ a</p>
+<p>a------</p>
+<p>---a---</p>
+>>> Thematic breaks - 26
+ *-*
+<<<
+<p><em>-</em></p>
+>>> Thematic breaks - 27
+- foo
+***
+- bar
+<<<
+<ul>
+<li>foo</li>
+</ul>
+<hr />
+<ul>
+<li>bar</li>
+</ul>
+>>> Thematic breaks - 28
+Foo
+***
+bar
+<<<
+<p>Foo</p>
+<hr />
+<p>bar</p>
+>>> Thematic breaks - 29
+Foo
+---
+bar
+<<<
+<h2>Foo</h2>
+<p>bar</p>
+>>> Thematic breaks - 30
+* Foo
+* * *
+* Bar
+<<<
+<ul>
+<li>Foo</li>
+</ul>
+<hr />
+<ul>
+<li>Bar</li>
+</ul>
+>>> Thematic breaks - 31
+- Foo
+- * * *
+<<<
+<ul>
+<li>Foo</li>
+<li>
+<hr />
+</li>
+</ul>
diff --git a/pkgs/markdown/test/html_renderer_test.dart b/pkgs/markdown/test/html_renderer_test.dart
new file mode 100644
index 0000000..77c33d3
--- /dev/null
+++ b/pkgs/markdown/test/html_renderer_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'package:markdown/markdown.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('markdownToHtml', () {
+    const text = '# Hello **Markdown<em>!</em>**\n***';
+
+    test('with no syntaxes', () {
+      final result = markdownToHtml(
+        text,
+        withDefaultBlockSyntaxes: false,
+        withDefaultInlineSyntaxes: false,
+        encodeHtml: false,
+      );
+      expect(result, equals('# Hello **Markdown<em>!</em>**\n***\n'));
+    });
+
+    test('with no default syntaxes but with custom syntaxes', () {
+      final result = markdownToHtml(
+        text,
+        withDefaultBlockSyntaxes: false,
+        withDefaultInlineSyntaxes: false,
+        encodeHtml: false,
+        blockSyntaxes: [const HorizontalRuleSyntax()],
+        inlineSyntaxes: [
+          EmphasisSyntax.asterisk(),
+        ],
+      );
+
+      expect(
+        result,
+        equals('# Hello <strong>Markdown<em>!</em></strong>\n<hr />\n'),
+      );
+    });
+
+    test('with only default block syntaxes', () {
+      final result = markdownToHtml(
+        text,
+        withDefaultInlineSyntaxes: false,
+        encodeHtml: false,
+      );
+
+      expect(
+        result,
+        equals('<h1>Hello **Markdown<em>!</em>**</h1>\n<hr />\n'),
+      );
+    });
+
+    test('with only default inline syntaxes', () {
+      final result = markdownToHtml(
+        text,
+        withDefaultBlockSyntaxes: false,
+        encodeHtml: false,
+      );
+
+      expect(
+        result,
+        equals('# Hello <strong>Markdown<em>!</em></strong>\n***\n'),
+      );
+    });
+
+    test('with no default syntaxes but with encodeHtml enabled', () {
+      final result = markdownToHtml(
+        text,
+        withDefaultBlockSyntaxes: false,
+        withDefaultInlineSyntaxes: false,
+      );
+
+      expect(
+        result,
+        equals('# Hello **Markdown&lt;em&gt;!&lt;/em&gt;**\n***\n'),
+      );
+    });
+  });
+
+  group('test InlineSyntax caseSensitive parameter', () {
+    const text = 'one BREAK two';
+
+    test('with caseSensitive enabled', () {
+      final result = markdownToHtml(
+        text,
+        inlineOnly: true,
+        inlineSyntaxes: [_BreakSyntax(true)],
+      );
+
+      expect(result, equals('one BREAK two'));
+    });
+
+    test('with caseSensitive disabled', () {
+      final result = markdownToHtml(
+        text,
+        inlineOnly: true,
+        inlineSyntaxes: [_BreakSyntax(false)],
+      );
+
+      expect(result, equals('one <break /> two'));
+    });
+  });
+}
+
+class _BreakSyntax extends InlineSyntax {
+  _BreakSyntax(bool caseSensitive)
+      : super('break', caseSensitive: caseSensitive);
+
+  @override
+  bool onMatch(InlineParser parser, Match match) {
+    parser.addNode(Element.empty('break'));
+    return true;
+  }
+}
diff --git a/pkgs/markdown/test/markdown_test.dart b/pkgs/markdown/test/markdown_test.dart
new file mode 100644
index 0000000..feb2d77
--- /dev/null
+++ b/pkgs/markdown/test/markdown_test.dart
@@ -0,0 +1,306 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+@TestOn('vm')
+library;
+
+import 'package:markdown/markdown.dart';
+import 'package:test/test.dart';
+
+import 'util.dart';
+
+void main() async {
+  testDirectory('original');
+
+  // Block syntax extensions.
+  testFile(
+    'extensions/fenced_blockquotes.unit',
+    blockSyntaxes: [const FencedBlockquoteSyntax()],
+  );
+  testFile(
+    'extensions/fenced_code_blocks.unit',
+    blockSyntaxes: [const FencedCodeBlockSyntax()],
+  );
+  testFile(
+    'extensions/headers_with_ids.unit',
+    blockSyntaxes: [const HeaderWithIdSyntax()],
+  );
+  testFile(
+    'extensions/ordered_list_with_checkboxes.unit',
+    blockSyntaxes: [const OrderedListWithCheckboxSyntax()],
+  );
+  testFile(
+    'extensions/setext_headers_with_ids.unit',
+    blockSyntaxes: [const SetextHeaderWithIdSyntax()],
+  );
+  testFile(
+    'extensions/tables.unit',
+    blockSyntaxes: [const TableSyntax()],
+  );
+  testFile(
+    'extensions/unordered_list_with_checkboxes.unit',
+    blockSyntaxes: [const UnorderedListWithCheckboxSyntax()],
+  );
+  testFile(
+    'extensions/alert_extension.unit',
+    blockSyntaxes: [const AlertBlockSyntax()],
+  );
+
+  // Inline syntax extensions
+  testFile(
+    'extensions/autolink_extension.unit',
+    inlineSyntaxes: [AutolinkExtensionSyntax()],
+  );
+
+  testFile(
+    'extensions/emojis.unit',
+    inlineSyntaxes: [EmojiSyntax()],
+  );
+  testFile(
+    'extensions/inline_html.unit',
+    inlineSyntaxes: [InlineHtmlSyntax()],
+  );
+  testFile(
+    'extensions/strikethrough.unit',
+    inlineSyntaxes: [StrikethroughSyntax()],
+  );
+  testFile(
+    'extensions/footnote_block.unit',
+    blockSyntaxes: [const FootnoteDefSyntax()],
+  );
+
+  testDirectory('common_mark');
+  testDirectory('gfm');
+
+  group('Corner cases', () {
+    validateCore('Incorrect Links', '''
+5 Ethernet ([Music](
+''', '''
+<p>5 Ethernet ([Music](</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 1 - Bracketed link 1', '''
+[](<
+''', '''
+<p>[](&lt;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 2 - Bracketed link 2', '''
+[](<>
+''', '''
+<p>[](&lt;&gt;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 3 - Bracketed link 3', r'''
+[](<\
+''', r'''
+<p>[](&lt;\</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 4 - Link title 1', '''
+[](www.example.com "
+''', '''
+<p>[](www.example.com &quot;</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 5 - Link title 2', r'''
+[](www.example.com "\
+''', r'''
+<p>[](www.example.com &quot;\</p>
+''');
+
+    validateCore('Incorrect Links - Issue #623 - 6 - Reference link label', r'''
+[][\
+''', r'''
+<p>[][\</p>
+''');
+
+    validateCore('Escaping code block language', '''
+```"/><a/href="url">arbitrary_html</a>
+```
+''', '''
+<pre><code class="language-&quot;/&gt;&lt;a/href=&quot;url&quot;&gt;arbitrary_html&lt;/a&gt;"></code></pre>
+''');
+
+    validateCore('Unicode ellipsis as punctuation', '''
+"Connecting dot **A** to **B.**…"
+''', '''
+<p>&quot;Connecting dot <strong>A</strong> to <strong>B.</strong>…&quot;</p>
+''');
+  });
+
+  group('Resolver', () {
+    Node? nyanResolver(String text, [_]) =>
+        text.isEmpty ? null : Text('~=[,,_${text}_,,]:3');
+    validateCore(
+        'simple link resolver',
+        '''
+resolve [this] thing
+''',
+        '''
+<p>resolve ~=[,,_this_,,]:3 thing</p>
+''',
+        linkResolver: nyanResolver);
+
+    validateCore(
+        'simple image resolver',
+        '''
+resolve ![this] thing
+''',
+        '''
+<p>resolve ~=[,,_this_,,]:3 thing</p>
+''',
+        imageLinkResolver: nyanResolver);
+
+    validateCore(
+        'can resolve link containing inline tags',
+        '''
+resolve [*star* _underline_] thing
+''',
+        '''
+<p>resolve ~=[,,_*star* _underline__,,]:3 thing</p>
+''',
+        linkResolver: nyanResolver);
+
+    validateCore(
+        'link resolver uses un-normalized link label',
+        '''
+resolve [TH  IS] thing
+''',
+        '''
+<p>resolve ~=[,,_TH  IS_,,]:3 thing</p>
+''',
+        linkResolver: nyanResolver);
+
+    validateCore(
+        'can resolve escaped brackets',
+        r'''
+resolve [\[\]] thing
+''',
+        '''
+<p>resolve ~=[,,_[]_,,]:3 thing</p>
+''',
+        linkResolver: nyanResolver);
+
+    validateCore(
+        'can choose to _not_ resolve something, like an empty link',
+        '''
+resolve [[]] thing
+''',
+        '''
+<p>resolve ~=[,,_[]_,,]:3 thing</p>
+''',
+        linkResolver: nyanResolver);
+  });
+
+  group('Custom inline syntax', () {
+    final nyanSyntax = <InlineSyntax>[TextSyntax('nyan', sub: '~=[,,_,,]:3')];
+    validateCore(
+        'simple inline syntax',
+        '''
+nyan''',
+        '''<p>~=[,,_,,]:3</p>
+''',
+        inlineSyntaxes: nyanSyntax);
+
+    validateCore(
+      'dart custom links',
+      'links [are<foo>] awesome',
+      '<p>links <a>are&lt;foo></a> awesome</p>\n',
+      linkResolver: (String text, [String? _]) => Element.text(
+        'a',
+        text.replaceAll('<', '&lt;'),
+      ),
+    );
+
+    // TODO(amouravski): need more tests here for custom syntaxes, as some
+    // things are not quite working properly. The regexps are sometime a little
+    // too greedy, I think.
+  });
+
+  group('Inline only', () {
+    validateCore(
+        'simple line',
+        '''
+        This would normally create a paragraph.
+        ''',
+        '''
+        This would normally create a paragraph.
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'strong and em',
+        '''
+        This would _normally_ create a **paragraph**.
+        ''',
+        '''
+        This would <em>normally</em> create a <strong>paragraph</strong>.
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'link',
+        '''
+        This [link](http://www.example.com/) will work normally.
+        ''',
+        '''
+        This <a href="http://www.example.com/">link</a> will work normally.
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'references do not work',
+        '''
+        [This][] shouldn't work, though.
+        ''',
+        '''
+        [This][] shouldn't work, though.
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'less than and ampersand are escaped',
+        '''
+        < &
+        ''',
+        '''
+        &lt; &amp;
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'keeps newlines',
+        '''
+        This paragraph
+        continues after a newline.
+        ''',
+        '''
+        This paragraph
+        continues after a newline.
+        ''',
+        inlineOnly: true);
+    validateCore(
+        'ignores block-level markdown syntax',
+        '''
+        1. This will not be an <ol>.
+        ''',
+        '''
+        1. This will not be an <ol>.
+        ''',
+        inlineOnly: true);
+  });
+
+  group('ExtensionSet', () {
+    test(
+      '3 asterisks separated with spaces horizontal rule while it is '
+      'gitHubFlavored',
+      () {
+        // Because `gitHubFlavored` will put `UnorderedListWithCheckboxSyntax`
+        // before `HorizontalRuleSyntax`, the `* * *` will be parsed into an
+        // empty unordered list if `ListSyntax` does not skip the horizontal
+        // rule structure.
+        expect(
+          markdownToHtml('* * *', extensionSet: ExtensionSet.gitHubFlavored),
+          '<hr />\n',
+        );
+      },
+    );
+  });
+}
diff --git a/pkgs/markdown/test/original/autolinks.unit b/pkgs/markdown/test/original/autolinks.unit
new file mode 100644
index 0000000..d3658e8
--- /dev/null
+++ b/pkgs/markdown/test/original/autolinks.unit
@@ -0,0 +1,10 @@
+>>> basic link
+before <http://foo.com/> after
+
+<<<
+<p>before <a href="http://foo.com/">http://foo.com/</a> after</p>
+>>> handles ampersand in url
+<http://foo.com/?a=1&b=2>
+
+<<<
+<p><a href="http://foo.com/?a=1&amp;b=2">http://foo.com/?a=1&amp;b=2</a></p>
diff --git a/pkgs/markdown/test/original/backslash_escapes.unit b/pkgs/markdown/test/original/backslash_escapes.unit
new file mode 100644
index 0000000..e3446f3
--- /dev/null
+++ b/pkgs/markdown/test/original/backslash_escapes.unit
@@ -0,0 +1,38 @@
+>>> Escaped punctuation is indeed escaped.
+Punctuations like \! and \" and \# and \$ and \% and \& and \' and \( and \)
+and \* and \+ and \, and \- and \. and \/ and \: and \; and \< and \= and \>
+and \? and \@ and \[ and \\ and \] and \^ and \_ and \` and \{ and \| and \}
+and \~.
+
+<<<
+<p>Punctuations like ! and &quot; and # and $ and % and &amp; and ' and ( and )
+and * and + and , and - and . and / and : and ; and &lt; and = and &gt;
+and ? and @ and [ and \ and ] and ^ and _ and ` and { and | and }
+and ~.</p>
+>>> Inline code blocks can be escaped.
+Not \`code`.
+
+<<<
+<p>Not `code`.</p>
+>>> Emphasis can be escaped.
+\*Both* \_kinds_.
+
+<<<
+<p>*Both* _kinds_.</p>
+>>> Links can be escaped.
+Escaped brackets: \[foo](bar), and parens: [foo]\(bar).
+
+<<<
+<p>Escaped brackets: [foo](bar), and parens: [foo](bar).</p>
+>>> Reference links can be escaped.
+Front: \[foo][bar] and back: [foo]\[bar].
+
+<<<
+<p>Front: [foo][bar] and back: [foo][bar].</p>
+>>> Images can be escaped.
+Escapes the bang: \![img](img.png),
+and escapes the image: !\[img](img.png).
+
+<<<
+<p>Escapes the bang: !<a href="img.png">img</a>,
+and escapes the image: ![img](img.png).</p>
diff --git a/pkgs/markdown/test/original/block_level_html.unit b/pkgs/markdown/test/original/block_level_html.unit
new file mode 100644
index 0000000..ce40760
--- /dev/null
+++ b/pkgs/markdown/test/original/block_level_html.unit
@@ -0,0 +1,38 @@
+>>> single line
+<table></table>
+
+<<<
+<table></table>
+>>> multi-line
+<table>
+    blah
+</table>
+
+<<<
+<table>
+    blah
+</table>
+>>> blank line ends block
+<table>
+    blah
+</table>
+
+para
+
+<<<
+<table>
+    blah
+</table>
+<p>para</p>
+>>> HTML can be bogus
+<bogus>
+blah
+</weird>
+
+para
+
+<<<
+<bogus>
+blah
+</weird>
+<p>para</p>
diff --git a/pkgs/markdown/test/original/block_quotes.unit b/pkgs/markdown/test/original/block_quotes.unit
new file mode 100644
index 0000000..548bc1a
--- /dev/null
+++ b/pkgs/markdown/test/original/block_quotes.unit
@@ -0,0 +1,54 @@
+>>> single line
+> blah
+
+<<<
+<blockquote>
+<p>blah</p>
+</blockquote>
+>>> with two paragraphs
+> first
+>
+> second
+
+<<<
+<blockquote>
+<p>first</p>
+<p>second</p>
+</blockquote>
+>>> nested
+> one
+>> two
+> > > three
+
+<<<
+<blockquote>
+<p>one</p>
+<blockquote>
+<p>two</p>
+<blockquote>
+<p>three</p>
+</blockquote>
+</blockquote>
+</blockquote>
+>>> qoute with lazy continuation
+> quote
+text
+<<<
+<blockquote>
+<p>quote
+text</p>
+</blockquote>
+>>> quote turns what might be an h2 into an hr
+> quote
+---
+
+<<<
+<blockquote>
+<p>quote</p>
+</blockquote>
+<hr />
+>>> issue #495
+  >
+<<<
+<blockquote>
+</blockquote>
diff --git a/pkgs/markdown/test/original/code_blocks.unit b/pkgs/markdown/test/original/code_blocks.unit
new file mode 100644
index 0000000..330a90f
--- /dev/null
+++ b/pkgs/markdown/test/original/code_blocks.unit
@@ -0,0 +1,65 @@
+>>> single line
+    code
+
+<<<
+<pre><code>code
+</code></pre>
+>>> include leading whitespace after indentation
+    zero
+     one
+      two
+       three
+
+<<<
+<pre><code>zero
+ one
+  two
+   three
+</code></pre>
+>>> code blocks separated by newlines form one block
+    zero
+    one
+
+    two
+
+    three
+
+<<<
+<pre><code>zero
+one
+
+two
+
+three
+</code></pre>
+>>> code blocks separated by two newlines form multiple blocks
+    zero
+    one
+
+
+    two
+
+
+    three
+
+<<<
+<pre><code>zero
+one
+
+
+two
+
+
+three
+</code></pre>
+>>> escape HTML characters
+    <&>
+
+<<<
+<pre><code>&lt;&amp;&gt;
+</code></pre>
+>>> issue #497
+    'foo'
+<<<
+<pre><code>'foo'
+</code></pre>
diff --git a/pkgs/markdown/test/original/emphasis_and_strong.unit b/pkgs/markdown/test/original/emphasis_and_strong.unit
new file mode 100644
index 0000000..13a6dd2
--- /dev/null
+++ b/pkgs/markdown/test/original/emphasis_and_strong.unit
@@ -0,0 +1,83 @@
+>>> single asterisks
+before *em* after
+
+<<<
+<p>before <em>em</em> after</p>
+>>> single underscores
+before _em_ after
+
+<<<
+<p>before <em>em</em> after</p>
+>>> double asterisks
+before **strong** after
+
+<<<
+<p>before <strong>strong</strong> after</p>
+>>> double underscores
+before __strong__ after
+
+<<<
+<p>before <strong>strong</strong> after</p>
+>>> unmatched asterisk
+before *after
+
+<<<
+<p>before *after</p>
+>>> unmatched underscore
+before _after
+
+<<<
+<p>before _after</p>
+>>> multiple spans in one text
+a *one* b _two_ c
+
+<<<
+<p>a <em>one</em> b <em>two</em> c</p>
+>>> multi-line
+before *first
+second* after
+
+<<<
+<p>before <em>first
+second</em> after</p>
+>>> not processed when surrounded by spaces
+a * b * c _ d _ e
+
+<<<
+<p>a * b * c _ d _ e</p>
+>>> strong then emphasis
+**strong***em*
+
+<<<
+<p><strong>strong</strong><em>em</em></p>
+>>> emphasis then strong
+*em***strong**
+
+<<<
+<p><em>em</em><strong>strong</strong></p>
+>>> emphasis inside strong
+**strong *em***
+
+<<<
+<p><strong>strong <em>em</em></strong></p>
+>>> mismatched in nested
+*a _b* c_
+
+<<<
+<p><em>a _b</em> c_</p>
+>>> in the middle of a word
+a_b_c a__b__c a*b*c a**b**c
+<<<
+<p>a_b_c a__b__c a<em>b</em>c a<strong>b</strong>c</p>
+>>> prefixing a word
+_a_b __a__b *a*b **a**b
+<<<
+<p>_a_b __a__b <em>a</em>b <strong>a</strong>b</p>
+>>> suffixing a word
+a_b_ a__b__ a*b* a**b**
+<<<
+<p>a_b_ a__b__ a<em>b</em> a<strong>b</strong></p>
+>>> spanning words
+_a_b c_d_ __a__b c__d__ *a*b c*d* **a**b c**d**
+<<<
+<p><em>a_b c_d</em> <strong>a__b c__d</strong> <em>a</em>b c<em>d</em> <strong>a</strong>b c<strong>d</strong></p>
diff --git a/pkgs/markdown/test/original/fenced_code_block.unit b/pkgs/markdown/test/original/fenced_code_block.unit
new file mode 100644
index 0000000..779e747
--- /dev/null
+++ b/pkgs/markdown/test/original/fenced_code_block.unit
@@ -0,0 +1,7 @@
+>>> issue #497
+```
+'foo'
+```
+<<<
+<pre><code>'foo'
+</code></pre>
diff --git a/pkgs/markdown/test/original/hard_line_breaks.unit b/pkgs/markdown/test/original/hard_line_breaks.unit
new file mode 100644
index 0000000..c8d1626
--- /dev/null
+++ b/pkgs/markdown/test/original/hard_line_breaks.unit
@@ -0,0 +1,40 @@
+>>> hard line break in a paragraph, using backslash
+First line.\
+Second line.
+
+<<<
+<p>First line.<br />
+Second line.</p>
+>>> within emphasis, using backslash
+*Emphasised\
+text.*
+
+<<<
+<p><em>Emphasised<br />
+text.</em></p>
+>>> no escape within code, using backslash
+`Some\
+code`.
+
+<<<
+<p><code>Some\ code</code>.</p>
+>>> hard line break in a paragraph, using trailing spaces
+First line.
+Second line.
+
+<<<
+<p>First line.
+Second line.</p>
+>>> within emphasis, using trailing spaces
+*Emphasised
+text.*
+
+<<<
+<p><em>Emphasised
+text.</em></p>
+>>> no escape within code, using trailing spaces
+`Some
+code`.
+
+<<<
+<p><code>Some code</code>.</p>
diff --git a/pkgs/markdown/test/original/headers.unit b/pkgs/markdown/test/original/headers.unit
new file mode 100644
index 0000000..928da8b
--- /dev/null
+++ b/pkgs/markdown/test/original/headers.unit
@@ -0,0 +1,35 @@
+>>> h1
+# header
+
+<<<
+<h1>header</h1>
+>>> h2
+## header
+
+<<<
+<h2>header</h2>
+>>> h3
+### header
+
+<<<
+<h3>header</h3>
+>>> h4
+#### header
+
+<<<
+<h4>header</h4>
+>>> h5
+##### header
+
+<<<
+<h5>header</h5>
+>>> h6
+###### header
+
+<<<
+<h6>header</h6>
+>>> trailing "#" are removed
+# header ######
+
+<<<
+<h1>header</h1>
diff --git a/pkgs/markdown/test/original/horizontal_rules.unit b/pkgs/markdown/test/original/horizontal_rules.unit
new file mode 100644
index 0000000..36642e9
--- /dev/null
+++ b/pkgs/markdown/test/original/horizontal_rules.unit
@@ -0,0 +1,20 @@
+>>> from dashes
+---
+
+<<<
+<hr />
+>>> from asterisks
+***
+
+<<<
+<hr />
+>>> from underscores
+___
+
+<<<
+<hr />
+>>> can include up to two spaces
+_ _  _
+
+<<<
+<hr />
diff --git a/pkgs/markdown/test/original/html_block.unit b/pkgs/markdown/test/original/html_block.unit
new file mode 100644
index 0000000..f6b9216
--- /dev/null
+++ b/pkgs/markdown/test/original/html_block.unit
@@ -0,0 +1,11 @@
+>>> issue https://github.com/dart-lang/markdown/issues/547
+<?code-excerpt ?>
+```xml
+<q>
+</q>
+```
+<<<
+<?code-excerpt ?>
+<pre><code class="language-xml">&lt;q&gt;
+&lt;/q&gt;
+</code></pre>
\ No newline at end of file
diff --git a/pkgs/markdown/test/original/html_encoding.unit b/pkgs/markdown/test/original/html_encoding.unit
new file mode 100644
index 0000000..dab9043
--- /dev/null
+++ b/pkgs/markdown/test/original/html_encoding.unit
@@ -0,0 +1,15 @@
+>>> less than and ampersand are escaped
+< &
+
+<<<
+<p>&lt; &amp;</p>
+>>> greater than is escaped
+not you >
+
+<<<
+<p>not you &gt;</p>
+>>> existing entities are untouched
+&amp;
+
+<<<
+<p>&amp;</p>
diff --git a/pkgs/markdown/test/original/inline_code.unit b/pkgs/markdown/test/original/inline_code.unit
new file mode 100644
index 0000000..7315931
--- /dev/null
+++ b/pkgs/markdown/test/original/inline_code.unit
@@ -0,0 +1,87 @@
+>>> simple case
+before `source` after
+
+<<<
+<p>before <code>source</code> after</p>
+>>> single characters
+before `x` and `_` after
+
+<<<
+<p>before <code>x</code> and <code>_</code> after</p>
+>>> unmatched backtick
+before ` after
+
+<<<
+<p>before ` after</p>
+>>> multiple spans in one text
+a `one` b `two` c
+
+<<<
+<p>a <code>one</code> b <code>two</code> c</p>
+>>> multi-line
+before `first
+second` after
+
+<<<
+<p>before <code>first second</code> after</p>
+>>> simple double backticks
+before ``source`` after
+
+<<<
+<p>before <code>source</code> after</p>
+>>> even more backticks
+before ````source with ``` and```` after
+
+<<<
+<p>before <code>source with ``` and</code> after</p>
+>>> double backticks
+before ``can `contain` backticks`` after
+
+<<<
+<p>before <code>can `contain` backticks</code> after</p>
+>>> double backticks with spaces
+before `` `tick` `` after
+
+<<<
+<p>before <code>`tick`</code> after</p>
+>>> multiline single backticks with spaces
+before `in tick
+another` after
+
+<<<
+<p>before <code>in tick another</code> after</p>
+>>> multiline double backticks with spaces
+before ``in `tick`
+another`` after
+
+<<<
+<p>before <code>in `tick` another</code> after</p>
+>>> ignore markup inside code
+before `*b* _c_` after
+
+<<<
+<p>before <code>*b* _c_</code> after</p>
+>>> escape HTML characters
+`<&>`
+
+<<<
+<p><code>&lt;&amp;&gt;</code></p>
+>>> escape HTML tags
+'*' `<em>`
+
+<<<
+<p>'*' <code>&lt;em&gt;</code></p>
+>>> leave unmatched backticks when first are too long
+before ``` tick `` after
+
+<<<
+<p>before ``` tick `` after</p>
+>>> leave unmatched backticks when first are too short
+before `` tick ``` after
+
+<<<
+<p>before `` tick ``` after</p>
+>>> issue #497
+`'foo'`
+<<<
+<p><code>'foo'</code></p>
diff --git a/pkgs/markdown/test/original/inline_images.unit b/pkgs/markdown/test/original/inline_images.unit
new file mode 100644
index 0000000..c8180ce
--- /dev/null
+++ b/pkgs/markdown/test/original/inline_images.unit
@@ -0,0 +1,29 @@
+>>> image
+![](http://foo.com/foo.png)
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="" /></p>
+>>> alternate text
+![alternate text](http://foo.com/foo.png)
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="alternate text" /></p>
+>>> title
+![](http://foo.com/foo.png "optional title")
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="" title="optional title" /></p>
+>>> invalid alt text
+![`alt`](http://foo.com/foo.png)
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="alt" /></p>
+>>> XSS
+![Uh oh...]("onerror="alert('XSS'))
+
+<<<
+<p><img src="%22onerror=%22alert('XSS')" alt="Uh oh..." /></p>
+>>> URL-escaping should be left alone inside the destination
+![](https://example/foo%2Fvar)
+<<<
+<p><img src="https://example/foo%2Fvar" alt="" /></p>
\ No newline at end of file
diff --git a/pkgs/markdown/test/original/inline_links.unit b/pkgs/markdown/test/original/inline_links.unit
new file mode 100644
index 0000000..0a40407
--- /dev/null
+++ b/pkgs/markdown/test/original/inline_links.unit
@@ -0,0 +1,87 @@
+>>> double quotes for title
+links [are](http://foo.com "woo") awesome
+
+<<<
+<p>links <a href="http://foo.com" title="woo">are</a> awesome</p>
+>>> no title
+links [are](http://foo.com) awesome
+
+<<<
+<p>links <a href="http://foo.com">are</a> awesome</p>
+>>> can style link contents
+links [*are*](http://foo.com) awesome
+
+<<<
+<p>links <a href="http://foo.com"><em>are</em></a> awesome</p>
+>>> image inside link
+links [![](/are.png)](http://foo.com) awesome
+
+<<<
+<p>links <a href="http://foo.com"><img src="/are.png" alt="" /></a> awesome</p>
+>>> image with alt inside link
+links [![my alt](/are.png)](http://foo.com) awesome
+
+<<<
+<p>links <a href="http://foo.com"><img src="/are.png" alt="my alt" /></a> awesome</p>
+>>> image with title inside link
+links [![](/are.png "my title")](http://foo.com) awesome
+
+<<<
+<p>links <a href="http://foo.com"><img src="/are.png" alt="" title="my title" /></a> awesome</p>
+>>> no URL
+links [are]() awesome
+
+<<<
+<p>links <a href="">are</a> awesome</p>
+>>> URL wrapped in angle brackets
+links [are](<http://example.com>) awesome
+
+<<<
+<p>links <a href="http://example.com">are</a> awesome</p>
+>>> URL wrapped in angle brackets with a title; https://github.com/commonmark/CommonMark/issues/521
+links [are](<http://example.com> "title") awesome
+
+<<<
+<p>links <a href="http://example.com" title="title">are</a> awesome</p>
+>>> multi-line link
+links [are
+awesome](<http://example.com>).
+
+<<<
+<p>links <a href="http://example.com">are
+awesome</a>.</p>
+>>> multi-line link with a title
+links [are](http://foo.com
+"woo") awesome
+
+<<<
+<p>links <a href="http://foo.com" title="woo">are</a> awesome</p>
+>>> not a real link
+links [are] (http://foo.com) awesome
+
+<<<
+<p>links [are] (http://foo.com) awesome</p>
+>>> resolver link without a resolver
+links [are *awesome*]
+
+<<<
+<p>links [are <em>awesome</em>]</p>
+>>> links with escaped parens
+[a](\(yes-a-link)
+[a](\(yes-a-link\))
+[a](\\(not-a-link\))
+[a](\\(yes-a-link\)))
+<<<
+<p><a href="(yes-a-link">a</a>
+<a href="(yes-a-link)">a</a>
+[a](\(not-a-link))
+<a href="(yes-a-link))">a</a></p>
+>>> links with unbalanced parentheses
+[foo](link(1.png) (what?)
+<<<
+<p>[foo](link(1.png) (what?)</p>
+>>> not an inline link: the title's ending quote is escaped
+links [are](<http://example.com> "title\") awesome
+
+<<<
+<p>links [are](<a href="http://example.com">http://example.com</a> &quot;title&quot;) awesome</p>
\ No newline at end of file
diff --git a/pkgs/markdown/test/original/ordered_lists.unit b/pkgs/markdown/test/original/ordered_lists.unit
new file mode 100644
index 0000000..8156889
--- /dev/null
+++ b/pkgs/markdown/test/original/ordered_lists.unit
@@ -0,0 +1,49 @@
+>>> ordered list with multiple items
+1.  one
+2.  two
+10. ten
+<<<
+<ol>
+<li>one</li>
+<li>two</li>
+<li>ten</li>
+</ol>
+>>> ordered list with almost nested item
+1.  one
+45.  two
+   12345. three
+
+<<<
+<ol>
+<li>one</li>
+<li>two</li>
+<li>three</li>
+</ol>
+>>> nested ordered lists
+1. one
+2. two
+   3. three
+   4. four
+5. five
+<<<
+<ol>
+<li>one</li>
+<li>two
+<ol start="3">
+<li>three</li>
+<li>four</li>
+</ol>
+</li>
+<li>five</li>
+</ol>
+>>> new list markers start new lists
+1. a
+* b
+
+<<<
+<ol>
+<li>a</li>
+</ol>
+<ul>
+<li>b</li>
+</ul>
diff --git a/pkgs/markdown/test/original/paragraphs.unit b/pkgs/markdown/test/original/paragraphs.unit
new file mode 100644
index 0000000..a20a556
--- /dev/null
+++ b/pkgs/markdown/test/original/paragraphs.unit
@@ -0,0 +1,55 @@
+>>> consecutive lines form a single paragraph
+This is the first line.
+This is the second line.
+
+<<<
+<p>This is the first line.
+This is the second line.</p>
+>>> are terminated by a header
+para
+# header
+
+<<<
+<p>para</p>
+<h1>header</h1>
+>>> are terminated by a hr
+para
+___
+
+<<<
+<p>para</p>
+<hr />
+>>> are terminated by an unordered list
+para
+* list
+
+<<<
+<p>para</p>
+<ul>
+<li>list</li>
+</ul>
+>>> are terminated by an ordered list
+para
+1. list
+
+<<<
+<p>para</p>
+<ol>
+<li>list</li>
+</ol>
+>>> take account of windows line endings
+line1
+
+line2
+
+
+<<<
+<p>line1</p>
+<p>line2</p>
+>>> cannot be terminated by indented code blocks
+para
+    not code
+
+<<<
+<p>para
+not code</p>
diff --git a/pkgs/markdown/test/original/reference_images.unit b/pkgs/markdown/test/original/reference_images.unit
new file mode 100644
index 0000000..b098d24
--- /dev/null
+++ b/pkgs/markdown/test/original/reference_images.unit
@@ -0,0 +1,34 @@
+>>> image
+![][foo]
+
+[foo]: http://foo.com/foo.png
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="" /></p>
+>>> alternate text
+![alternate text][foo]
+
+[foo]: http://foo.com/foo.png
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="alternate text" /></p>
+>>> title
+![][foo]
+
+[foo]: http://foo.com/foo.png "optional title"
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="" title="optional title" /></p>
+>>> invalid alt text
+![`alt`][foo]
+
+[foo]: http://foo.com/foo.png "optional title"
+
+<<<
+<p><img src="http://foo.com/foo.png" alt="alt" title="optional title" /></p>
+>>> shortcut reference image
+![foo]
+
+[foo]: http://foo.com/foo.png
+<<<
+<p><img src="http://foo.com/foo.png" alt="foo" /></p>
diff --git a/pkgs/markdown/test/original/reference_links.unit b/pkgs/markdown/test/original/reference_links.unit
new file mode 100644
index 0000000..bc3e336
--- /dev/null
+++ b/pkgs/markdown/test/original/reference_links.unit
@@ -0,0 +1,100 @@
+>>> double quotes for title
+links [are][a] awesome
+
+[a]: http://foo.com "woo"
+
+<<<
+<p>links <a href="http://foo.com" title="woo">are</a> awesome</p>
+>>> single quoted title
+links [are][a] awesome
+
+[a]: http://foo.com 'woo'
+
+<<<
+<p>links <a href="http://foo.com" title="woo">are</a> awesome</p>
+>>> parentheses for title
+links [are][a] awesome
+
+[a]: http://foo.com (woo)
+
+<<<
+<p>links <a href="http://foo.com" title="woo">are</a> awesome</p>
+>>> no title
+links [are][a] awesome
+
+[a]: http://foo.com
+
+<<<
+<p>links <a href="http://foo.com">are</a> awesome</p>
+>>> unknown link becomes plaintext
+[not] [known]
+
+<<<
+<p>[not] [known]</p>
+>>> can style link contents
+links [*are*][a] awesome
+
+[a]: http://foo.com
+
+<<<
+<p>links <a href="http://foo.com"><em>are</em></a> awesome</p>
+>>> inline styles after a bad link are processed
+[bad] `code`
+
+<<<
+<p>[bad] <code>code</code></p>
+>>> empty reference uses text from link
+links [are][] awesome
+
+[are]: http://foo.com
+
+<<<
+<p>links <a href="http://foo.com">are</a> awesome</p>
+>>> references are case-insensitive
+links [ARE][] awesome
+
+[are]: http://foo.com
+
+<<<
+<p>links <a href="http://foo.com">ARE</a> awesome</p>
+>>> shortcut reference links
+links [are] awesome
+
+[are]: http://foo.com
+<<<
+<p>links <a href="http://foo.com">are</a> awesome</p>
+>>> reference definitions can span lines
+links [are] [awesome]
+
+[are]:
+http://foo.com
+[awesome]:
+http://bar.com
+"Long
+Title"
+<<<
+<p>links <a href="http://foo.com">are</a> <a href="http://bar.com" title="Long
+Title">awesome</a></p>
+>>> references can be defined in blocks
+> links [are] awesome
+>
+> [are]: http://foo.com
+<<<
+<blockquote>
+<p>links <a href="http://foo.com">are</a> awesome</p>
+</blockquote>
+>>> reference link regression for github.com/dart-lang/markdown/issues/176
+[![Coverage Status][coverage_status]][coverage_page]
+
+[coverage_page]:https://coveralls.io/github/yeradis/stay_points.dart?branch=master
+[coverage_status]: https://coveralls.io/repos/github/yeradis/stay_points.dart/badge.svg?branch=master
+<<<
+<p><a href="https://coveralls.io/github/yeradis/stay_points.dart?branch=master"><img src="https://coveralls.io/repos/github/yeradis/stay_points.dart/badge.svg?branch=master" alt="Coverage Status" /></a></p>
+>>> compressed reference link label is normalized
+Text [foo
+bar][].
+
+[foo bar]: http://bar.com
+<<<
+<p>Text <a href="http://bar.com">foo
+bar</a>.</p>
diff --git a/pkgs/markdown/test/original/setext_headers.unit b/pkgs/markdown/test/original/setext_headers.unit
new file mode 100644
index 0000000..f094801
--- /dev/null
+++ b/pkgs/markdown/test/original/setext_headers.unit
@@ -0,0 +1,32 @@
+>>> h1
+text
+===
+
+<<<
+<h1>text</h1>
+>>> h2
+text
+---
+
+<<<
+<h2>text</h2>
+>>> h1 bar on first line becomes text
+===
+
+<<<
+<p>===</p>
+>>> h2 bar on first line becomes list
+-
+
+<<<
+<ul>
+<li></li>
+</ul>
+>>> can be multiline
+header
+on two lines
+==
+
+<<<
+<h1>header
+on two lines</h1>
diff --git a/pkgs/markdown/test/original/strong.unit b/pkgs/markdown/test/original/strong.unit
new file mode 100644
index 0000000..e558424
--- /dev/null
+++ b/pkgs/markdown/test/original/strong.unit
@@ -0,0 +1,32 @@
+>>> using asterisks
+before **strong** after
+
+<<<
+<p>before <strong>strong</strong> after</p>
+>>> using underscores
+before __strong__ after
+
+<<<
+<p>before <strong>strong</strong> after</p>
+>>> unmatched asterisks
+before ** after
+
+<<<
+<p>before ** after</p>
+>>> unmatched underscores
+before __ after
+
+<<<
+<p>before __ after</p>
+>>> multiple spans in one text
+a **one** b __two__ c
+
+<<<
+<p>a <strong>one</strong> b <strong>two</strong> c</p>
+>>> multi-line
+before **first
+second** after
+
+<<<
+<p>before <strong>first
+second</strong> after</p>
diff --git a/pkgs/markdown/test/original/unordered_lists.unit b/pkgs/markdown/test/original/unordered_lists.unit
new file mode 100644
index 0000000..6017775
--- /dev/null
+++ b/pkgs/markdown/test/original/unordered_lists.unit
@@ -0,0 +1,151 @@
+>>> asterisk, plus and hyphen
+* star
+- dash
++ plus
+
+<<<
+<ul>
+<li>star</li>
+</ul>
+<ul>
+<li>dash</li>
+</ul>
+<ul>
+<li>plus</li>
+</ul>
+>>> new markers begin new lists
+* a
+1. b
+
+<<<
+<ul>
+<li>a</li>
+</ul>
+<ol>
+<li>b</li>
+</ol>
+>>> allow a tab after the marker
+*	a
+1.	b
+
+<<<
+<ul>
+<li>a</li>
+</ul>
+<ol>
+<li>b</li>
+</ol>
+>>> wrap items in paragraphs if blank lines separate
+* one
+
+* two
+
+<<<
+<ul>
+<li>
+<p>one</p>
+</li>
+<li>
+<p>two</p>
+</li>
+</ul>
+>>> force paragraph on item before and after blank lines
+* one
+* two
+
+* three
+
+<<<
+<ul>
+<li>
+<p>one</p>
+</li>
+<li>
+<p>two</p>
+</li>
+<li>
+<p>three</p>
+</li>
+</ul>
+>>> do not force paragraph if item is already block
+* > quote
+
+* # header
+
+<<<
+<ul>
+<li>
+<blockquote>
+<p>quote</p>
+</blockquote>
+</li>
+<li>
+<h1>header</h1>
+</li>
+</ul>
+>>> can contain multiple paragraphs
+* one
+
+  two
+
+* three
+
+<<<
+<ul>
+<li>
+<p>one</p>
+<p>two</p>
+</li>
+<li>
+<p>three</p>
+</li>
+</ul>
+>>> can span newlines
+* one
+  two
+* three
+
+<<<
+<ul>
+<li>one
+two</li>
+<li>three</li>
+</ul>
+>>> can nest lists
+* one
+  * nested one
+  * nested two
+
+* two
+
+<<<
+<ul>
+<li>
+<p>one</p>
+<ul>
+<li>nested one</li>
+<li>nested two</li>
+</ul>
+</li>
+<li>
+<p>two</p>
+</li>
+</ul>
+>>> list item allows lazy continuations
+- list
+item
+
+<<<
+<ul>
+<li>list
+item</li>
+</ul>
+>>> list item turns what might be an h2 into nothing
+- list
+---
+
+<<<
+<ul>
+<li>list</li>
+</ul>
+<hr />
diff --git a/pkgs/markdown/test/util.dart b/pkgs/markdown/test/util.dart
new file mode 100644
index 0000000..3d7dc6a
--- /dev/null
+++ b/pkgs/markdown/test/util.dart
@@ -0,0 +1,124 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'package:io/ansi.dart' as ansi;
+import 'package:markdown/markdown.dart';
+import 'package:path/path.dart' as p;
+import 'package:test/test.dart';
+
+import '../tool/expected_output.dart';
+
+/// Runs tests defined in "*.unit" files inside directory [name].
+void testDirectory(String name, {ExtensionSet? extensionSet}) {
+  for (final dataCase in dataCasesUnder(testDirectory: name)) {
+    final description =
+        '${dataCase.directory}/${dataCase.file}.unit ${dataCase.description}';
+
+    final inlineSyntaxes = <InlineSyntax>[];
+    final blockSyntaxes = <BlockSyntax>[];
+    var enableTagfilter = false;
+
+    if (dataCase.file.endsWith('_extension')) {
+      final extension = dataCase.file.substring(
+        0,
+        dataCase.file.lastIndexOf('_extension'),
+      );
+      switch (extension) {
+        case 'autolinks':
+          inlineSyntaxes.add(AutolinkExtensionSyntax());
+          break;
+        case 'strikethrough':
+          inlineSyntaxes.add(StrikethroughSyntax());
+          break;
+        case 'tables':
+          blockSyntaxes.add(const TableSyntax());
+          break;
+        case 'disallowed_raw_html':
+          enableTagfilter = true;
+          break;
+        default:
+          throw UnimplementedError('Unimplemented extension "$extension"');
+      }
+    }
+
+    validateCore(
+      description,
+      dataCase.input,
+      dataCase.expectedOutput,
+      extensionSet: extensionSet,
+      inlineSyntaxes: inlineSyntaxes,
+      blockSyntaxes: blockSyntaxes,
+      enableTagfilter: enableTagfilter,
+    );
+  }
+}
+
+void testFile(
+  String file, {
+  Iterable<BlockSyntax> blockSyntaxes = const [],
+  Iterable<InlineSyntax> inlineSyntaxes = const [],
+}) {
+  for (final dataCase
+      in dataCasesInFile(path: p.join(p.current, 'test', file))) {
+    final description =
+        '${dataCase.directory}/${dataCase.file}.unit ${dataCase.description}';
+    validateCore(
+      description,
+      dataCase.input,
+      dataCase.expectedOutput,
+      blockSyntaxes: blockSyntaxes,
+      inlineSyntaxes: inlineSyntaxes,
+    );
+  }
+}
+
+void validateCore(
+  String description,
+  String markdown,
+  String html, {
+  Iterable<BlockSyntax> blockSyntaxes = const [],
+  Iterable<InlineSyntax> inlineSyntaxes = const [],
+  ExtensionSet? extensionSet,
+  Resolver? linkResolver,
+  Resolver? imageLinkResolver,
+  bool inlineOnly = false,
+  bool enableTagfilter = false,
+}) {
+  test(description, () {
+    final result = markdownToHtml(
+      markdown,
+      blockSyntaxes: blockSyntaxes,
+      inlineSyntaxes: inlineSyntaxes,
+      extensionSet: extensionSet,
+      linkResolver: linkResolver,
+      imageLinkResolver: imageLinkResolver,
+      inlineOnly: inlineOnly,
+      enableTagfilter: enableTagfilter,
+    );
+
+    markdownPrintOnFailure(markdown, html, result);
+
+    expect(result, html);
+  });
+}
+
+String whitespaceColor(String input) => input
+    .replaceAll(' ', ansi.lightBlue.wrap('·')!)
+    .replaceAll('\t', ansi.backgroundDarkGray.wrap('\t')!);
+
+void markdownPrintOnFailure(String markdown, String expected, String actual) {
+  printOnFailure("""
+INPUT:
+'''r
+${whitespaceColor(markdown)}'''
+           
+EXPECTED:
+'''r
+${whitespaceColor(expected)}'''
+
+GOT:
+'''r
+${whitespaceColor(actual)}'''
+""");
+}
diff --git a/pkgs/markdown/test/util_test.dart b/pkgs/markdown/test/util_test.dart
new file mode 100644
index 0000000..5a2108a
--- /dev/null
+++ b/pkgs/markdown/test/util_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'package:markdown/markdown.dart';
+import 'package:markdown/src/util.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('String.toLines()', () {
+    test('a single line without a line ending', () {
+      const text = 'Foo';
+      final lines = text.toLines();
+
+      expect(lines.map((e) => e.toMap()), [
+        {
+          'content': 'Foo',
+          'isBlankLine': false,
+        }
+      ]);
+    });
+
+    test('a single line with a line ending', () {
+      const text = 'Foo\n';
+      final lines = text.toLines();
+
+      expect(lines.map((e) => e.toMap()), [
+        {
+          'content': 'Foo',
+          'isBlankLine': false,
+        },
+      ]);
+    });
+
+    test('multiple lines with a blank line in between', () {
+      const text = 'Foo\r\n\nBar';
+      final lines = text.toLines();
+
+      expect(lines.map((e) => e.toMap()), [
+        {
+          'content': 'Foo',
+          'isBlankLine': false,
+        },
+        {
+          'content': '',
+          'isBlankLine': true,
+        },
+        {
+          'content': 'Bar',
+          'isBlankLine': false,
+        }
+      ]);
+    });
+  });
+
+  group('String.indentation()', () {
+    test('only spaces', () {
+      expect('   '.indentation(), 3);
+      expect('    '.indentation(), 4);
+      expect('     '.indentation(), 5);
+    });
+
+    test('spaces and tabs', () {
+      expect('\t  '.indentation(), 6);
+      expect(' \t '.indentation(), 5);
+      expect('  \t'.indentation(), 4);
+      expect('\t\t  '.indentation(), 10);
+      expect(' \t\t '.indentation(), 9);
+      expect('  \t\t'.indentation(), 8);
+    });
+
+    test('spaces, tabs and non whitespace characters', () {
+      expect('\t  foo'.indentation(), 6);
+      expect(' \t foo'.indentation(), 5);
+      expect('  \tfoo'.indentation(), 4);
+    });
+  });
+}
+
+extension on Line {
+  Map<String, dynamic> toMap() => {
+        'content': content,
+        'isBlankLine': isBlankLine,
+        if (tabRemaining != null) 'tabRemaining': tabRemaining,
+      };
+}
diff --git a/pkgs/markdown/test/version_test.dart b/pkgs/markdown/test/version_test.dart
new file mode 100644
index 0000000..93fedcb
--- /dev/null
+++ b/pkgs/markdown/test/version_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+@TestOn('vm')
+library;
+
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart';
+
+void main() {
+  test('check versions', () async {
+    final binary = p.join(p.current, 'bin', 'markdown.dart');
+    final dartBin = Platform.executable;
+    final result = Process.runSync(dartBin, [binary, '--version']);
+    expect(
+      result.exitCode,
+      0,
+      reason: 'Exit code expected: 0; actual: ${result.exitCode}\n\n'
+          'stdout: ${result.stdout}\n\n'
+          'stderr: ${result.stderr}',
+    );
+
+    final binVersion = (result.stdout as String).trim();
+
+    final pubspecFile = p.join(p.current, 'pubspec.yaml');
+
+    final pubspecContent =
+        loadYaml(File(pubspecFile).readAsStringSync()) as YamlMap;
+
+    expect(
+      binVersion,
+      pubspecContent['version'],
+      reason: 'The version reported by bin/markdown.dart should match the '
+          'version in pubspec. Run `dart run build_runner build` to update.',
+    );
+  });
+}
diff --git a/pkgs/markdown/tool/README.md b/pkgs/markdown/tool/README.md
new file mode 100644
index 0000000..ff2f749
--- /dev/null
+++ b/pkgs/markdown/tool/README.md
@@ -0,0 +1,48 @@
+# Developer Tools
+
+This directory contains tools for developers of the Dart markdown package.
+
+## dartdoc_compare.dart
+
+When you make a change to the package that might have subtle consequences on
+how Markdown is parsed, it would be really great to see how your output compares
+to the previous output, on a large collection of Markdown.
+
+One such collection is the Dartdoc comments of any Dart package, which [dartdoc]
+translates into HTML, with the help of this markdown package. You can use the
+`dartdoc_compare.dart` script to compare what changes your code will make to
+dartdoc's output. Here's how it works:
+
+1. Clone the [dartdoc git repository].
+2. Get a copy of some Dart code that you would like to use for the comparison.
+3. Run the `dartdoc_compare.dart` script like so:
+
+   ```
+   $ dart tool/dartdoc_compare.dart \
+         --dartdoc-dir=<dartdoc repo> \
+         --before=<git SHA of "previous" code> \
+         <directory of dart code for comparison>
+   ```
+
+4. The tool will then walk through the following steps:
+
+   1. cd into the dartdoc directory, change `pubspec.yaml` to depend on your
+      "before" version of markdown, and run `pub get`.
+   2. cd into the directory of dart code, and run `pub get`.
+   3. Run dartdoc.
+   4. cd back into the dartdoc directory, change `pubspec.yaml` to depend on
+      your "after" version of markdown (defaults to HEAD), and run `pub get`.
+   5. Repeat steps 2 and 3.
+   6. Diff the output of steps 3 and 5, and show you how to diff it yourself.
+
+[dartdoc]: https://pub.dev/packages/dartdoc
+[dartdoc git repository]: https://github.com/dart-lang/dartdoc
+
+## stats.dart
+
+In an effort to make this package CommonMark-compliant, we have a script that
+runs the package through the CommonMark specs. To see help:
+
+```bash
+$ dart tool/stats.dart --help
+```
diff --git a/pkgs/markdown/tool/case_folding.txt b/pkgs/markdown/tool/case_folding.txt
new file mode 100644
index 0000000..932ace2
--- /dev/null
+++ b/pkgs/markdown/tool/case_folding.txt
@@ -0,0 +1,1624 @@
+# CaseFolding-14.0.0.txt
+# Date: 2021-03-08, 19:35:41 GMT
+# © 2021 Unicode®, Inc.
+# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Unicode Character Database
+#   For documentation, see http://www.unicode.org/reports/tr44/
+#
+# Case Folding Properties
+#
+# This file is a supplement to the UnicodeData file.
+# It provides a case folding mapping generated from the Unicode Character Database.
+# If all characters are mapped according to the full mapping below, then
+# case differences (according to UnicodeData.txt and SpecialCasing.txt)
+# are eliminated.
+#
+# The data supports both implementations that require simple case foldings
+# (where string lengths don't change), and implementations that allow full case folding
+# (where string lengths may grow). Note that where they can be supported, the
+# full case foldings are superior: for example, they allow "MASSE" and "Maße" to match.
+#
+# All code points not listed in this file map to themselves.
+#
+# NOTE: case folding does not preserve normalization formats!
+#
+# For information on case folding, including how to have case folding
+# preserve normalization formats, see Section 3.13 Default Case Algorithms in
+# The Unicode Standard.
+#
+# ================================================================================
+# Format
+# ================================================================================
+# The entries in this file are in the following machine-readable format:
+#
+# <code>; <status>; <mapping>; # <name>
+#
+# The status field is:
+# C: common case folding, common mappings shared by both simple and full mappings.
+# F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces.
+# S: simple case folding, mappings to single characters where different from F.
+# T: special case for uppercase I and dotted uppercase I
+#    - For non-Turkic languages, this mapping is normally not used.
+#    - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters.
+#      Note that the Turkic mappings do not maintain canonical equivalence without additional processing.
+#      See the discussions of case mapping in the Unicode Standard for more information.
+#
+# Usage:
+#  A. To do a simple case folding, use the mappings with status C + S.
+#  B. To do a full case folding, use the mappings with status C + F.
+#
+#    The mappings with status T can be used or omitted depending on the desired case-folding
+#    behavior. (The default option is to exclude them.)
+#
+# =================================================================
+
+# Property: Case_Folding
+
+#  All code points not explicitly listed for Case_Folding
+#  have the value C for the status field, and the code point itself for the mapping field.
+
+# =================================================================
+0041; C; 0061; # LATIN CAPITAL LETTER A
+0042; C; 0062; # LATIN CAPITAL LETTER B
+0043; C; 0063; # LATIN CAPITAL LETTER C
+0044; C; 0064; # LATIN CAPITAL LETTER D
+0045; C; 0065; # LATIN CAPITAL LETTER E
+0046; C; 0066; # LATIN CAPITAL LETTER F
+0047; C; 0067; # LATIN CAPITAL LETTER G
+0048; C; 0068; # LATIN CAPITAL LETTER H
+0049; C; 0069; # LATIN CAPITAL LETTER I
+0049; T; 0131; # LATIN CAPITAL LETTER I
+004A; C; 006A; # LATIN CAPITAL LETTER J
+004B; C; 006B; # LATIN CAPITAL LETTER K
+004C; C; 006C; # LATIN CAPITAL LETTER L
+004D; C; 006D; # LATIN CAPITAL LETTER M
+004E; C; 006E; # LATIN CAPITAL LETTER N
+004F; C; 006F; # LATIN CAPITAL LETTER O
+0050; C; 0070; # LATIN CAPITAL LETTER P
+0051; C; 0071; # LATIN CAPITAL LETTER Q
+0052; C; 0072; # LATIN CAPITAL LETTER R
+0053; C; 0073; # LATIN CAPITAL LETTER S
+0054; C; 0074; # LATIN CAPITAL LETTER T
+0055; C; 0075; # LATIN CAPITAL LETTER U
+0056; C; 0076; # LATIN CAPITAL LETTER V
+0057; C; 0077; # LATIN CAPITAL LETTER W
+0058; C; 0078; # LATIN CAPITAL LETTER X
+0059; C; 0079; # LATIN CAPITAL LETTER Y
+005A; C; 007A; # LATIN CAPITAL LETTER Z
+00B5; C; 03BC; # MICRO SIGN
+00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE
+00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE
+00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE
+00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS
+00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE
+00C6; C; 00E6; # LATIN CAPITAL LETTER AE
+00C7; C; 00E7; # LATIN CAPITAL LETTER C WITH CEDILLA
+00C8; C; 00E8; # LATIN CAPITAL LETTER E WITH GRAVE
+00C9; C; 00E9; # LATIN CAPITAL LETTER E WITH ACUTE
+00CA; C; 00EA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+00CB; C; 00EB; # LATIN CAPITAL LETTER E WITH DIAERESIS
+00CC; C; 00EC; # LATIN CAPITAL LETTER I WITH GRAVE
+00CD; C; 00ED; # LATIN CAPITAL LETTER I WITH ACUTE
+00CE; C; 00EE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+00CF; C; 00EF; # LATIN CAPITAL LETTER I WITH DIAERESIS
+00D0; C; 00F0; # LATIN CAPITAL LETTER ETH
+00D1; C; 00F1; # LATIN CAPITAL LETTER N WITH TILDE
+00D2; C; 00F2; # LATIN CAPITAL LETTER O WITH GRAVE
+00D3; C; 00F3; # LATIN CAPITAL LETTER O WITH ACUTE
+00D4; C; 00F4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+00D5; C; 00F5; # LATIN CAPITAL LETTER O WITH TILDE
+00D6; C; 00F6; # LATIN CAPITAL LETTER O WITH DIAERESIS
+00D8; C; 00F8; # LATIN CAPITAL LETTER O WITH STROKE
+00D9; C; 00F9; # LATIN CAPITAL LETTER U WITH GRAVE
+00DA; C; 00FA; # LATIN CAPITAL LETTER U WITH ACUTE
+00DB; C; 00FB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+00DC; C; 00FC; # LATIN CAPITAL LETTER U WITH DIAERESIS
+00DD; C; 00FD; # LATIN CAPITAL LETTER Y WITH ACUTE
+00DE; C; 00FE; # LATIN CAPITAL LETTER THORN
+00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S
+0100; C; 0101; # LATIN CAPITAL LETTER A WITH MACRON
+0102; C; 0103; # LATIN CAPITAL LETTER A WITH BREVE
+0104; C; 0105; # LATIN CAPITAL LETTER A WITH OGONEK
+0106; C; 0107; # LATIN CAPITAL LETTER C WITH ACUTE
+0108; C; 0109; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+010A; C; 010B; # LATIN CAPITAL LETTER C WITH DOT ABOVE
+010C; C; 010D; # LATIN CAPITAL LETTER C WITH CARON
+010E; C; 010F; # LATIN CAPITAL LETTER D WITH CARON
+0110; C; 0111; # LATIN CAPITAL LETTER D WITH STROKE
+0112; C; 0113; # LATIN CAPITAL LETTER E WITH MACRON
+0114; C; 0115; # LATIN CAPITAL LETTER E WITH BREVE
+0116; C; 0117; # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0118; C; 0119; # LATIN CAPITAL LETTER E WITH OGONEK
+011A; C; 011B; # LATIN CAPITAL LETTER E WITH CARON
+011C; C; 011D; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+011E; C; 011F; # LATIN CAPITAL LETTER G WITH BREVE
+0120; C; 0121; # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0122; C; 0123; # LATIN CAPITAL LETTER G WITH CEDILLA
+0124; C; 0125; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0126; C; 0127; # LATIN CAPITAL LETTER H WITH STROKE
+0128; C; 0129; # LATIN CAPITAL LETTER I WITH TILDE
+012A; C; 012B; # LATIN CAPITAL LETTER I WITH MACRON
+012C; C; 012D; # LATIN CAPITAL LETTER I WITH BREVE
+012E; C; 012F; # LATIN CAPITAL LETTER I WITH OGONEK
+0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0132; C; 0133; # LATIN CAPITAL LIGATURE IJ
+0134; C; 0135; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0136; C; 0137; # LATIN CAPITAL LETTER K WITH CEDILLA
+0139; C; 013A; # LATIN CAPITAL LETTER L WITH ACUTE
+013B; C; 013C; # LATIN CAPITAL LETTER L WITH CEDILLA
+013D; C; 013E; # LATIN CAPITAL LETTER L WITH CARON
+013F; C; 0140; # LATIN CAPITAL LETTER L WITH MIDDLE DOT
+0141; C; 0142; # LATIN CAPITAL LETTER L WITH STROKE
+0143; C; 0144; # LATIN CAPITAL LETTER N WITH ACUTE
+0145; C; 0146; # LATIN CAPITAL LETTER N WITH CEDILLA
+0147; C; 0148; # LATIN CAPITAL LETTER N WITH CARON
+0149; F; 02BC 006E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+014A; C; 014B; # LATIN CAPITAL LETTER ENG
+014C; C; 014D; # LATIN CAPITAL LETTER O WITH MACRON
+014E; C; 014F; # LATIN CAPITAL LETTER O WITH BREVE
+0150; C; 0151; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0152; C; 0153; # LATIN CAPITAL LIGATURE OE
+0154; C; 0155; # LATIN CAPITAL LETTER R WITH ACUTE
+0156; C; 0157; # LATIN CAPITAL LETTER R WITH CEDILLA
+0158; C; 0159; # LATIN CAPITAL LETTER R WITH CARON
+015A; C; 015B; # LATIN CAPITAL LETTER S WITH ACUTE
+015C; C; 015D; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+015E; C; 015F; # LATIN CAPITAL LETTER S WITH CEDILLA
+0160; C; 0161; # LATIN CAPITAL LETTER S WITH CARON
+0162; C; 0163; # LATIN CAPITAL LETTER T WITH CEDILLA
+0164; C; 0165; # LATIN CAPITAL LETTER T WITH CARON
+0166; C; 0167; # LATIN CAPITAL LETTER T WITH STROKE
+0168; C; 0169; # LATIN CAPITAL LETTER U WITH TILDE
+016A; C; 016B; # LATIN CAPITAL LETTER U WITH MACRON
+016C; C; 016D; # LATIN CAPITAL LETTER U WITH BREVE
+016E; C; 016F; # LATIN CAPITAL LETTER U WITH RING ABOVE
+0170; C; 0171; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0172; C; 0173; # LATIN CAPITAL LETTER U WITH OGONEK
+0174; C; 0175; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0176; C; 0177; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0178; C; 00FF; # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0179; C; 017A; # LATIN CAPITAL LETTER Z WITH ACUTE
+017B; C; 017C; # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+017D; C; 017E; # LATIN CAPITAL LETTER Z WITH CARON
+017F; C; 0073; # LATIN SMALL LETTER LONG S
+0181; C; 0253; # LATIN CAPITAL LETTER B WITH HOOK
+0182; C; 0183; # LATIN CAPITAL LETTER B WITH TOPBAR
+0184; C; 0185; # LATIN CAPITAL LETTER TONE SIX
+0186; C; 0254; # LATIN CAPITAL LETTER OPEN O
+0187; C; 0188; # LATIN CAPITAL LETTER C WITH HOOK
+0189; C; 0256; # LATIN CAPITAL LETTER AFRICAN D
+018A; C; 0257; # LATIN CAPITAL LETTER D WITH HOOK
+018B; C; 018C; # LATIN CAPITAL LETTER D WITH TOPBAR
+018E; C; 01DD; # LATIN CAPITAL LETTER REVERSED E
+018F; C; 0259; # LATIN CAPITAL LETTER SCHWA
+0190; C; 025B; # LATIN CAPITAL LETTER OPEN E
+0191; C; 0192; # LATIN CAPITAL LETTER F WITH HOOK
+0193; C; 0260; # LATIN CAPITAL LETTER G WITH HOOK
+0194; C; 0263; # LATIN CAPITAL LETTER GAMMA
+0196; C; 0269; # LATIN CAPITAL LETTER IOTA
+0197; C; 0268; # LATIN CAPITAL LETTER I WITH STROKE
+0198; C; 0199; # LATIN CAPITAL LETTER K WITH HOOK
+019C; C; 026F; # LATIN CAPITAL LETTER TURNED M
+019D; C; 0272; # LATIN CAPITAL LETTER N WITH LEFT HOOK
+019F; C; 0275; # LATIN CAPITAL LETTER O WITH MIDDLE TILDE
+01A0; C; 01A1; # LATIN CAPITAL LETTER O WITH HORN
+01A2; C; 01A3; # LATIN CAPITAL LETTER OI
+01A4; C; 01A5; # LATIN CAPITAL LETTER P WITH HOOK
+01A6; C; 0280; # LATIN LETTER YR
+01A7; C; 01A8; # LATIN CAPITAL LETTER TONE TWO
+01A9; C; 0283; # LATIN CAPITAL LETTER ESH
+01AC; C; 01AD; # LATIN CAPITAL LETTER T WITH HOOK
+01AE; C; 0288; # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
+01AF; C; 01B0; # LATIN CAPITAL LETTER U WITH HORN
+01B1; C; 028A; # LATIN CAPITAL LETTER UPSILON
+01B2; C; 028B; # LATIN CAPITAL LETTER V WITH HOOK
+01B3; C; 01B4; # LATIN CAPITAL LETTER Y WITH HOOK
+01B5; C; 01B6; # LATIN CAPITAL LETTER Z WITH STROKE
+01B7; C; 0292; # LATIN CAPITAL LETTER EZH
+01B8; C; 01B9; # LATIN CAPITAL LETTER EZH REVERSED
+01BC; C; 01BD; # LATIN CAPITAL LETTER TONE FIVE
+01C4; C; 01C6; # LATIN CAPITAL LETTER DZ WITH CARON
+01C5; C; 01C6; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+01C7; C; 01C9; # LATIN CAPITAL LETTER LJ
+01C8; C; 01C9; # LATIN CAPITAL LETTER L WITH SMALL LETTER J
+01CA; C; 01CC; # LATIN CAPITAL LETTER NJ
+01CB; C; 01CC; # LATIN CAPITAL LETTER N WITH SMALL LETTER J
+01CD; C; 01CE; # LATIN CAPITAL LETTER A WITH CARON
+01CF; C; 01D0; # LATIN CAPITAL LETTER I WITH CARON
+01D1; C; 01D2; # LATIN CAPITAL LETTER O WITH CARON
+01D3; C; 01D4; # LATIN CAPITAL LETTER U WITH CARON
+01D5; C; 01D6; # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+01D7; C; 01D8; # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+01D9; C; 01DA; # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+01DB; C; 01DC; # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+01DE; C; 01DF; # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+01E0; C; 01E1; # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+01E2; C; 01E3; # LATIN CAPITAL LETTER AE WITH MACRON
+01E4; C; 01E5; # LATIN CAPITAL LETTER G WITH STROKE
+01E6; C; 01E7; # LATIN CAPITAL LETTER G WITH CARON
+01E8; C; 01E9; # LATIN CAPITAL LETTER K WITH CARON
+01EA; C; 01EB; # LATIN CAPITAL LETTER O WITH OGONEK
+01EC; C; 01ED; # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+01EE; C; 01EF; # LATIN CAPITAL LETTER EZH WITH CARON
+01F0; F; 006A 030C; # LATIN SMALL LETTER J WITH CARON
+01F1; C; 01F3; # LATIN CAPITAL LETTER DZ
+01F2; C; 01F3; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+01F4; C; 01F5; # LATIN CAPITAL LETTER G WITH ACUTE
+01F6; C; 0195; # LATIN CAPITAL LETTER HWAIR
+01F7; C; 01BF; # LATIN CAPITAL LETTER WYNN
+01F8; C; 01F9; # LATIN CAPITAL LETTER N WITH GRAVE
+01FA; C; 01FB; # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+01FC; C; 01FD; # LATIN CAPITAL LETTER AE WITH ACUTE
+01FE; C; 01FF; # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+0200; C; 0201; # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+0202; C; 0203; # LATIN CAPITAL LETTER A WITH INVERTED BREVE
+0204; C; 0205; # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+0206; C; 0207; # LATIN CAPITAL LETTER E WITH INVERTED BREVE
+0208; C; 0209; # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+020A; C; 020B; # LATIN CAPITAL LETTER I WITH INVERTED BREVE
+020C; C; 020D; # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+020E; C; 020F; # LATIN CAPITAL LETTER O WITH INVERTED BREVE
+0210; C; 0211; # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+0212; C; 0213; # LATIN CAPITAL LETTER R WITH INVERTED BREVE
+0214; C; 0215; # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+0216; C; 0217; # LATIN CAPITAL LETTER U WITH INVERTED BREVE
+0218; C; 0219; # LATIN CAPITAL LETTER S WITH COMMA BELOW
+021A; C; 021B; # LATIN CAPITAL LETTER T WITH COMMA BELOW
+021C; C; 021D; # LATIN CAPITAL LETTER YOGH
+021E; C; 021F; # LATIN CAPITAL LETTER H WITH CARON
+0220; C; 019E; # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
+0222; C; 0223; # LATIN CAPITAL LETTER OU
+0224; C; 0225; # LATIN CAPITAL LETTER Z WITH HOOK
+0226; C; 0227; # LATIN CAPITAL LETTER A WITH DOT ABOVE
+0228; C; 0229; # LATIN CAPITAL LETTER E WITH CEDILLA
+022A; C; 022B; # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+022C; C; 022D; # LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE
+0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON
+023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE
+023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE
+023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR
+023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
+0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP
+0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE
+0244; C; 0289; # LATIN CAPITAL LETTER U BAR
+0245; C; 028C; # LATIN CAPITAL LETTER TURNED V
+0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE
+0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE
+024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
+024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE
+024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE
+0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI
+0370; C; 0371; # GREEK CAPITAL LETTER HETA
+0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI
+0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
+037F; C; 03F3; # GREEK CAPITAL LETTER YOT
+0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS
+0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS
+0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS
+038A; C; 03AF; # GREEK CAPITAL LETTER IOTA WITH TONOS
+038C; C; 03CC; # GREEK CAPITAL LETTER OMICRON WITH TONOS
+038E; C; 03CD; # GREEK CAPITAL LETTER UPSILON WITH TONOS
+038F; C; 03CE; # GREEK CAPITAL LETTER OMEGA WITH TONOS
+0390; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0391; C; 03B1; # GREEK CAPITAL LETTER ALPHA
+0392; C; 03B2; # GREEK CAPITAL LETTER BETA
+0393; C; 03B3; # GREEK CAPITAL LETTER GAMMA
+0394; C; 03B4; # GREEK CAPITAL LETTER DELTA
+0395; C; 03B5; # GREEK CAPITAL LETTER EPSILON
+0396; C; 03B6; # GREEK CAPITAL LETTER ZETA
+0397; C; 03B7; # GREEK CAPITAL LETTER ETA
+0398; C; 03B8; # GREEK CAPITAL LETTER THETA
+0399; C; 03B9; # GREEK CAPITAL LETTER IOTA
+039A; C; 03BA; # GREEK CAPITAL LETTER KAPPA
+039B; C; 03BB; # GREEK CAPITAL LETTER LAMDA
+039C; C; 03BC; # GREEK CAPITAL LETTER MU
+039D; C; 03BD; # GREEK CAPITAL LETTER NU
+039E; C; 03BE; # GREEK CAPITAL LETTER XI
+039F; C; 03BF; # GREEK CAPITAL LETTER OMICRON
+03A0; C; 03C0; # GREEK CAPITAL LETTER PI
+03A1; C; 03C1; # GREEK CAPITAL LETTER RHO
+03A3; C; 03C3; # GREEK CAPITAL LETTER SIGMA
+03A4; C; 03C4; # GREEK CAPITAL LETTER TAU
+03A5; C; 03C5; # GREEK CAPITAL LETTER UPSILON
+03A6; C; 03C6; # GREEK CAPITAL LETTER PHI
+03A7; C; 03C7; # GREEK CAPITAL LETTER CHI
+03A8; C; 03C8; # GREEK CAPITAL LETTER PSI
+03A9; C; 03C9; # GREEK CAPITAL LETTER OMEGA
+03AA; C; 03CA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA
+03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL
+03D0; C; 03B2; # GREEK BETA SYMBOL
+03D1; C; 03B8; # GREEK THETA SYMBOL
+03D5; C; 03C6; # GREEK PHI SYMBOL
+03D6; C; 03C0; # GREEK PI SYMBOL
+03D8; C; 03D9; # GREEK LETTER ARCHAIC KOPPA
+03DA; C; 03DB; # GREEK LETTER STIGMA
+03DC; C; 03DD; # GREEK LETTER DIGAMMA
+03DE; C; 03DF; # GREEK LETTER KOPPA
+03E0; C; 03E1; # GREEK LETTER SAMPI
+03E2; C; 03E3; # COPTIC CAPITAL LETTER SHEI
+03E4; C; 03E5; # COPTIC CAPITAL LETTER FEI
+03E6; C; 03E7; # COPTIC CAPITAL LETTER KHEI
+03E8; C; 03E9; # COPTIC CAPITAL LETTER HORI
+03EA; C; 03EB; # COPTIC CAPITAL LETTER GANGIA
+03EC; C; 03ED; # COPTIC CAPITAL LETTER SHIMA
+03EE; C; 03EF; # COPTIC CAPITAL LETTER DEI
+03F0; C; 03BA; # GREEK KAPPA SYMBOL
+03F1; C; 03C1; # GREEK RHO SYMBOL
+03F4; C; 03B8; # GREEK CAPITAL THETA SYMBOL
+03F5; C; 03B5; # GREEK LUNATE EPSILON SYMBOL
+03F7; C; 03F8; # GREEK CAPITAL LETTER SHO
+03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL
+03FA; C; 03FB; # GREEK CAPITAL LETTER SAN
+03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL
+03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL
+03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
+0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE
+0401; C; 0451; # CYRILLIC CAPITAL LETTER IO
+0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE
+0403; C; 0453; # CYRILLIC CAPITAL LETTER GJE
+0404; C; 0454; # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0405; C; 0455; # CYRILLIC CAPITAL LETTER DZE
+0406; C; 0456; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0407; C; 0457; # CYRILLIC CAPITAL LETTER YI
+0408; C; 0458; # CYRILLIC CAPITAL LETTER JE
+0409; C; 0459; # CYRILLIC CAPITAL LETTER LJE
+040A; C; 045A; # CYRILLIC CAPITAL LETTER NJE
+040B; C; 045B; # CYRILLIC CAPITAL LETTER TSHE
+040C; C; 045C; # CYRILLIC CAPITAL LETTER KJE
+040D; C; 045D; # CYRILLIC CAPITAL LETTER I WITH GRAVE
+040E; C; 045E; # CYRILLIC CAPITAL LETTER SHORT U
+040F; C; 045F; # CYRILLIC CAPITAL LETTER DZHE
+0410; C; 0430; # CYRILLIC CAPITAL LETTER A
+0411; C; 0431; # CYRILLIC CAPITAL LETTER BE
+0412; C; 0432; # CYRILLIC CAPITAL LETTER VE
+0413; C; 0433; # CYRILLIC CAPITAL LETTER GHE
+0414; C; 0434; # CYRILLIC CAPITAL LETTER DE
+0415; C; 0435; # CYRILLIC CAPITAL LETTER IE
+0416; C; 0436; # CYRILLIC CAPITAL LETTER ZHE
+0417; C; 0437; # CYRILLIC CAPITAL LETTER ZE
+0418; C; 0438; # CYRILLIC CAPITAL LETTER I
+0419; C; 0439; # CYRILLIC CAPITAL LETTER SHORT I
+041A; C; 043A; # CYRILLIC CAPITAL LETTER KA
+041B; C; 043B; # CYRILLIC CAPITAL LETTER EL
+041C; C; 043C; # CYRILLIC CAPITAL LETTER EM
+041D; C; 043D; # CYRILLIC CAPITAL LETTER EN
+041E; C; 043E; # CYRILLIC CAPITAL LETTER O
+041F; C; 043F; # CYRILLIC CAPITAL LETTER PE
+0420; C; 0440; # CYRILLIC CAPITAL LETTER ER
+0421; C; 0441; # CYRILLIC CAPITAL LETTER ES
+0422; C; 0442; # CYRILLIC CAPITAL LETTER TE
+0423; C; 0443; # CYRILLIC CAPITAL LETTER U
+0424; C; 0444; # CYRILLIC CAPITAL LETTER EF
+0425; C; 0445; # CYRILLIC CAPITAL LETTER HA
+0426; C; 0446; # CYRILLIC CAPITAL LETTER TSE
+0427; C; 0447; # CYRILLIC CAPITAL LETTER CHE
+0428; C; 0448; # CYRILLIC CAPITAL LETTER SHA
+0429; C; 0449; # CYRILLIC CAPITAL LETTER SHCHA
+042A; C; 044A; # CYRILLIC CAPITAL LETTER HARD SIGN
+042B; C; 044B; # CYRILLIC CAPITAL LETTER YERU
+042C; C; 044C; # CYRILLIC CAPITAL LETTER SOFT SIGN
+042D; C; 044D; # CYRILLIC CAPITAL LETTER E
+042E; C; 044E; # CYRILLIC CAPITAL LETTER YU
+042F; C; 044F; # CYRILLIC CAPITAL LETTER YA
+0460; C; 0461; # CYRILLIC CAPITAL LETTER OMEGA
+0462; C; 0463; # CYRILLIC CAPITAL LETTER YAT
+0464; C; 0465; # CYRILLIC CAPITAL LETTER IOTIFIED E
+0466; C; 0467; # CYRILLIC CAPITAL LETTER LITTLE YUS
+0468; C; 0469; # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+046A; C; 046B; # CYRILLIC CAPITAL LETTER BIG YUS
+046C; C; 046D; # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+046E; C; 046F; # CYRILLIC CAPITAL LETTER KSI
+0470; C; 0471; # CYRILLIC CAPITAL LETTER PSI
+0472; C; 0473; # CYRILLIC CAPITAL LETTER FITA
+0474; C; 0475; # CYRILLIC CAPITAL LETTER IZHITSA
+0476; C; 0477; # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0478; C; 0479; # CYRILLIC CAPITAL LETTER UK
+047A; C; 047B; # CYRILLIC CAPITAL LETTER ROUND OMEGA
+047C; C; 047D; # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+047E; C; 047F; # CYRILLIC CAPITAL LETTER OT
+0480; C; 0481; # CYRILLIC CAPITAL LETTER KOPPA
+048A; C; 048B; # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
+048C; C; 048D; # CYRILLIC CAPITAL LETTER SEMISOFT SIGN
+048E; C; 048F; # CYRILLIC CAPITAL LETTER ER WITH TICK
+0490; C; 0491; # CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0492; C; 0493; # CYRILLIC CAPITAL LETTER GHE WITH STROKE
+0494; C; 0495; # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+0496; C; 0497; # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+0498; C; 0499; # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+049A; C; 049B; # CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+049C; C; 049D; # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+049E; C; 049F; # CYRILLIC CAPITAL LETTER KA WITH STROKE
+04A0; C; 04A1; # CYRILLIC CAPITAL LETTER BASHKIR KA
+04A2; C; 04A3; # CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+04A4; C; 04A5; # CYRILLIC CAPITAL LIGATURE EN GHE
+04A6; C; 04A7; # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+04A8; C; 04A9; # CYRILLIC CAPITAL LETTER ABKHASIAN HA
+04AA; C; 04AB; # CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+04AC; C; 04AD; # CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+04AE; C; 04AF; # CYRILLIC CAPITAL LETTER STRAIGHT U
+04B0; C; 04B1; # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+04B2; C; 04B3; # CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+04B4; C; 04B5; # CYRILLIC CAPITAL LIGATURE TE TSE
+04B6; C; 04B7; # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+04B8; C; 04B9; # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA
+04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA
+04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK
+04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL
+04C7; C; 04C8; # CYRILLIC CAPITAL LETTER EN WITH HOOK
+04C9; C; 04CA; # CYRILLIC CAPITAL LETTER EN WITH TAIL
+04CB; C; 04CC; # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+04CD; C; 04CE; # CYRILLIC CAPITAL LETTER EM WITH TAIL
+04D0; C; 04D1; # CYRILLIC CAPITAL LETTER A WITH BREVE
+04D2; C; 04D3; # CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+04D4; C; 04D5; # CYRILLIC CAPITAL LIGATURE A IE
+04D6; C; 04D7; # CYRILLIC CAPITAL LETTER IE WITH BREVE
+04D8; C; 04D9; # CYRILLIC CAPITAL LETTER SCHWA
+04DA; C; 04DB; # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04DC; C; 04DD; # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+04DE; C; 04DF; # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+04E0; C; 04E1; # CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+04E2; C; 04E3; # CYRILLIC CAPITAL LETTER I WITH MACRON
+04E4; C; 04E5; # CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+04E6; C; 04E7; # CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+04E8; C; 04E9; # CYRILLIC CAPITAL LETTER BARRED O
+04EA; C; 04EB; # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+04EC; C; 04ED; # CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+04EE; C; 04EF; # CYRILLIC CAPITAL LETTER U WITH MACRON
+04F0; C; 04F1; # CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+04F2; C; 04F3; # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
+04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
+04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK
+04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE
+0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE
+0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE
+0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE
+0506; C; 0507; # CYRILLIC CAPITAL LETTER KOMI DZJE
+0508; C; 0509; # CYRILLIC CAPITAL LETTER KOMI LJE
+050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE
+050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE
+050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE
+0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE
+0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK
+0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA
+0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA
+0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE
+051A; C; 051B; # CYRILLIC CAPITAL LETTER QA
+051C; C; 051D; # CYRILLIC CAPITAL LETTER WE
+051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA
+0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
+0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
+0524; C; 0525; # CYRILLIC CAPITAL LETTER PE WITH DESCENDER
+0526; C; 0527; # CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
+0528; C; 0529; # CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK
+052A; C; 052B; # CYRILLIC CAPITAL LETTER DZZHE
+052C; C; 052D; # CYRILLIC CAPITAL LETTER DCHE
+052E; C; 052F; # CYRILLIC CAPITAL LETTER EL WITH DESCENDER
+0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB
+0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN
+0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM
+0534; C; 0564; # ARMENIAN CAPITAL LETTER DA
+0535; C; 0565; # ARMENIAN CAPITAL LETTER ECH
+0536; C; 0566; # ARMENIAN CAPITAL LETTER ZA
+0537; C; 0567; # ARMENIAN CAPITAL LETTER EH
+0538; C; 0568; # ARMENIAN CAPITAL LETTER ET
+0539; C; 0569; # ARMENIAN CAPITAL LETTER TO
+053A; C; 056A; # ARMENIAN CAPITAL LETTER ZHE
+053B; C; 056B; # ARMENIAN CAPITAL LETTER INI
+053C; C; 056C; # ARMENIAN CAPITAL LETTER LIWN
+053D; C; 056D; # ARMENIAN CAPITAL LETTER XEH
+053E; C; 056E; # ARMENIAN CAPITAL LETTER CA
+053F; C; 056F; # ARMENIAN CAPITAL LETTER KEN
+0540; C; 0570; # ARMENIAN CAPITAL LETTER HO
+0541; C; 0571; # ARMENIAN CAPITAL LETTER JA
+0542; C; 0572; # ARMENIAN CAPITAL LETTER GHAD
+0543; C; 0573; # ARMENIAN CAPITAL LETTER CHEH
+0544; C; 0574; # ARMENIAN CAPITAL LETTER MEN
+0545; C; 0575; # ARMENIAN CAPITAL LETTER YI
+0546; C; 0576; # ARMENIAN CAPITAL LETTER NOW
+0547; C; 0577; # ARMENIAN CAPITAL LETTER SHA
+0548; C; 0578; # ARMENIAN CAPITAL LETTER VO
+0549; C; 0579; # ARMENIAN CAPITAL LETTER CHA
+054A; C; 057A; # ARMENIAN CAPITAL LETTER PEH
+054B; C; 057B; # ARMENIAN CAPITAL LETTER JHEH
+054C; C; 057C; # ARMENIAN CAPITAL LETTER RA
+054D; C; 057D; # ARMENIAN CAPITAL LETTER SEH
+054E; C; 057E; # ARMENIAN CAPITAL LETTER VEW
+054F; C; 057F; # ARMENIAN CAPITAL LETTER TIWN
+0550; C; 0580; # ARMENIAN CAPITAL LETTER REH
+0551; C; 0581; # ARMENIAN CAPITAL LETTER CO
+0552; C; 0582; # ARMENIAN CAPITAL LETTER YIWN
+0553; C; 0583; # ARMENIAN CAPITAL LETTER PIWR
+0554; C; 0584; # ARMENIAN CAPITAL LETTER KEH
+0555; C; 0585; # ARMENIAN CAPITAL LETTER OH
+0556; C; 0586; # ARMENIAN CAPITAL LETTER FEH
+0587; F; 0565 0582; # ARMENIAN SMALL LIGATURE ECH YIWN
+10A0; C; 2D00; # GEORGIAN CAPITAL LETTER AN
+10A1; C; 2D01; # GEORGIAN CAPITAL LETTER BAN
+10A2; C; 2D02; # GEORGIAN CAPITAL LETTER GAN
+10A3; C; 2D03; # GEORGIAN CAPITAL LETTER DON
+10A4; C; 2D04; # GEORGIAN CAPITAL LETTER EN
+10A5; C; 2D05; # GEORGIAN CAPITAL LETTER VIN
+10A6; C; 2D06; # GEORGIAN CAPITAL LETTER ZEN
+10A7; C; 2D07; # GEORGIAN CAPITAL LETTER TAN
+10A8; C; 2D08; # GEORGIAN CAPITAL LETTER IN
+10A9; C; 2D09; # GEORGIAN CAPITAL LETTER KAN
+10AA; C; 2D0A; # GEORGIAN CAPITAL LETTER LAS
+10AB; C; 2D0B; # GEORGIAN CAPITAL LETTER MAN
+10AC; C; 2D0C; # GEORGIAN CAPITAL LETTER NAR
+10AD; C; 2D0D; # GEORGIAN CAPITAL LETTER ON
+10AE; C; 2D0E; # GEORGIAN CAPITAL LETTER PAR
+10AF; C; 2D0F; # GEORGIAN CAPITAL LETTER ZHAR
+10B0; C; 2D10; # GEORGIAN CAPITAL LETTER RAE
+10B1; C; 2D11; # GEORGIAN CAPITAL LETTER SAN
+10B2; C; 2D12; # GEORGIAN CAPITAL LETTER TAR
+10B3; C; 2D13; # GEORGIAN CAPITAL LETTER UN
+10B4; C; 2D14; # GEORGIAN CAPITAL LETTER PHAR
+10B5; C; 2D15; # GEORGIAN CAPITAL LETTER KHAR
+10B6; C; 2D16; # GEORGIAN CAPITAL LETTER GHAN
+10B7; C; 2D17; # GEORGIAN CAPITAL LETTER QAR
+10B8; C; 2D18; # GEORGIAN CAPITAL LETTER SHIN
+10B9; C; 2D19; # GEORGIAN CAPITAL LETTER CHIN
+10BA; C; 2D1A; # GEORGIAN CAPITAL LETTER CAN
+10BB; C; 2D1B; # GEORGIAN CAPITAL LETTER JIL
+10BC; C; 2D1C; # GEORGIAN CAPITAL LETTER CIL
+10BD; C; 2D1D; # GEORGIAN CAPITAL LETTER CHAR
+10BE; C; 2D1E; # GEORGIAN CAPITAL LETTER XAN
+10BF; C; 2D1F; # GEORGIAN CAPITAL LETTER JHAN
+10C0; C; 2D20; # GEORGIAN CAPITAL LETTER HAE
+10C1; C; 2D21; # GEORGIAN CAPITAL LETTER HE
+10C2; C; 2D22; # GEORGIAN CAPITAL LETTER HIE
+10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE
+10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR
+10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE
+10C7; C; 2D27; # GEORGIAN CAPITAL LETTER YN
+10CD; C; 2D2D; # GEORGIAN CAPITAL LETTER AEN
+13F8; C; 13F0; # CHEROKEE SMALL LETTER YE
+13F9; C; 13F1; # CHEROKEE SMALL LETTER YI
+13FA; C; 13F2; # CHEROKEE SMALL LETTER YO
+13FB; C; 13F3; # CHEROKEE SMALL LETTER YU
+13FC; C; 13F4; # CHEROKEE SMALL LETTER YV
+13FD; C; 13F5; # CHEROKEE SMALL LETTER MV
+1C80; C; 0432; # CYRILLIC SMALL LETTER ROUNDED VE
+1C81; C; 0434; # CYRILLIC SMALL LETTER LONG-LEGGED DE
+1C82; C; 043E; # CYRILLIC SMALL LETTER NARROW O
+1C83; C; 0441; # CYRILLIC SMALL LETTER WIDE ES
+1C84; C; 0442; # CYRILLIC SMALL LETTER TALL TE
+1C85; C; 0442; # CYRILLIC SMALL LETTER THREE-LEGGED TE
+1C86; C; 044A; # CYRILLIC SMALL LETTER TALL HARD SIGN
+1C87; C; 0463; # CYRILLIC SMALL LETTER TALL YAT
+1C88; C; A64B; # CYRILLIC SMALL LETTER UNBLENDED UK
+1C90; C; 10D0; # GEORGIAN MTAVRULI CAPITAL LETTER AN
+1C91; C; 10D1; # GEORGIAN MTAVRULI CAPITAL LETTER BAN
+1C92; C; 10D2; # GEORGIAN MTAVRULI CAPITAL LETTER GAN
+1C93; C; 10D3; # GEORGIAN MTAVRULI CAPITAL LETTER DON
+1C94; C; 10D4; # GEORGIAN MTAVRULI CAPITAL LETTER EN
+1C95; C; 10D5; # GEORGIAN MTAVRULI CAPITAL LETTER VIN
+1C96; C; 10D6; # GEORGIAN MTAVRULI CAPITAL LETTER ZEN
+1C97; C; 10D7; # GEORGIAN MTAVRULI CAPITAL LETTER TAN
+1C98; C; 10D8; # GEORGIAN MTAVRULI CAPITAL LETTER IN
+1C99; C; 10D9; # GEORGIAN MTAVRULI CAPITAL LETTER KAN
+1C9A; C; 10DA; # GEORGIAN MTAVRULI CAPITAL LETTER LAS
+1C9B; C; 10DB; # GEORGIAN MTAVRULI CAPITAL LETTER MAN
+1C9C; C; 10DC; # GEORGIAN MTAVRULI CAPITAL LETTER NAR
+1C9D; C; 10DD; # GEORGIAN MTAVRULI CAPITAL LETTER ON
+1C9E; C; 10DE; # GEORGIAN MTAVRULI CAPITAL LETTER PAR
+1C9F; C; 10DF; # GEORGIAN MTAVRULI CAPITAL LETTER ZHAR
+1CA0; C; 10E0; # GEORGIAN MTAVRULI CAPITAL LETTER RAE
+1CA1; C; 10E1; # GEORGIAN MTAVRULI CAPITAL LETTER SAN
+1CA2; C; 10E2; # GEORGIAN MTAVRULI CAPITAL LETTER TAR
+1CA3; C; 10E3; # GEORGIAN MTAVRULI CAPITAL LETTER UN
+1CA4; C; 10E4; # GEORGIAN MTAVRULI CAPITAL LETTER PHAR
+1CA5; C; 10E5; # GEORGIAN MTAVRULI CAPITAL LETTER KHAR
+1CA6; C; 10E6; # GEORGIAN MTAVRULI CAPITAL LETTER GHAN
+1CA7; C; 10E7; # GEORGIAN MTAVRULI CAPITAL LETTER QAR
+1CA8; C; 10E8; # GEORGIAN MTAVRULI CAPITAL LETTER SHIN
+1CA9; C; 10E9; # GEORGIAN MTAVRULI CAPITAL LETTER CHIN
+1CAA; C; 10EA; # GEORGIAN MTAVRULI CAPITAL LETTER CAN
+1CAB; C; 10EB; # GEORGIAN MTAVRULI CAPITAL LETTER JIL
+1CAC; C; 10EC; # GEORGIAN MTAVRULI CAPITAL LETTER CIL
+1CAD; C; 10ED; # GEORGIAN MTAVRULI CAPITAL LETTER CHAR
+1CAE; C; 10EE; # GEORGIAN MTAVRULI CAPITAL LETTER XAN
+1CAF; C; 10EF; # GEORGIAN MTAVRULI CAPITAL LETTER JHAN
+1CB0; C; 10F0; # GEORGIAN MTAVRULI CAPITAL LETTER HAE
+1CB1; C; 10F1; # GEORGIAN MTAVRULI CAPITAL LETTER HE
+1CB2; C; 10F2; # GEORGIAN MTAVRULI CAPITAL LETTER HIE
+1CB3; C; 10F3; # GEORGIAN MTAVRULI CAPITAL LETTER WE
+1CB4; C; 10F4; # GEORGIAN MTAVRULI CAPITAL LETTER HAR
+1CB5; C; 10F5; # GEORGIAN MTAVRULI CAPITAL LETTER HOE
+1CB6; C; 10F6; # GEORGIAN MTAVRULI CAPITAL LETTER FI
+1CB7; C; 10F7; # GEORGIAN MTAVRULI CAPITAL LETTER YN
+1CB8; C; 10F8; # GEORGIAN MTAVRULI CAPITAL LETTER ELIFI
+1CB9; C; 10F9; # GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN
+1CBA; C; 10FA; # GEORGIAN MTAVRULI CAPITAL LETTER AIN
+1CBD; C; 10FD; # GEORGIAN MTAVRULI CAPITAL LETTER AEN
+1CBE; C; 10FE; # GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN
+1CBF; C; 10FF; # GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
+1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW
+1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE
+1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW
+1E06; C; 1E07; # LATIN CAPITAL LETTER B WITH LINE BELOW
+1E08; C; 1E09; # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
+1E0A; C; 1E0B; # LATIN CAPITAL LETTER D WITH DOT ABOVE
+1E0C; C; 1E0D; # LATIN CAPITAL LETTER D WITH DOT BELOW
+1E0E; C; 1E0F; # LATIN CAPITAL LETTER D WITH LINE BELOW
+1E10; C; 1E11; # LATIN CAPITAL LETTER D WITH CEDILLA
+1E12; C; 1E13; # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
+1E14; C; 1E15; # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
+1E16; C; 1E17; # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
+1E18; C; 1E19; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
+1E1A; C; 1E1B; # LATIN CAPITAL LETTER E WITH TILDE BELOW
+1E1C; C; 1E1D; # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
+1E1E; C; 1E1F; # LATIN CAPITAL LETTER F WITH DOT ABOVE
+1E20; C; 1E21; # LATIN CAPITAL LETTER G WITH MACRON
+1E22; C; 1E23; # LATIN CAPITAL LETTER H WITH DOT ABOVE
+1E24; C; 1E25; # LATIN CAPITAL LETTER H WITH DOT BELOW
+1E26; C; 1E27; # LATIN CAPITAL LETTER H WITH DIAERESIS
+1E28; C; 1E29; # LATIN CAPITAL LETTER H WITH CEDILLA
+1E2A; C; 1E2B; # LATIN CAPITAL LETTER H WITH BREVE BELOW
+1E2C; C; 1E2D; # LATIN CAPITAL LETTER I WITH TILDE BELOW
+1E2E; C; 1E2F; # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
+1E30; C; 1E31; # LATIN CAPITAL LETTER K WITH ACUTE
+1E32; C; 1E33; # LATIN CAPITAL LETTER K WITH DOT BELOW
+1E34; C; 1E35; # LATIN CAPITAL LETTER K WITH LINE BELOW
+1E36; C; 1E37; # LATIN CAPITAL LETTER L WITH DOT BELOW
+1E38; C; 1E39; # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
+1E3A; C; 1E3B; # LATIN CAPITAL LETTER L WITH LINE BELOW
+1E3C; C; 1E3D; # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
+1E3E; C; 1E3F; # LATIN CAPITAL LETTER M WITH ACUTE
+1E40; C; 1E41; # LATIN CAPITAL LETTER M WITH DOT ABOVE
+1E42; C; 1E43; # LATIN CAPITAL LETTER M WITH DOT BELOW
+1E44; C; 1E45; # LATIN CAPITAL LETTER N WITH DOT ABOVE
+1E46; C; 1E47; # LATIN CAPITAL LETTER N WITH DOT BELOW
+1E48; C; 1E49; # LATIN CAPITAL LETTER N WITH LINE BELOW
+1E4A; C; 1E4B; # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
+1E4C; C; 1E4D; # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
+1E4E; C; 1E4F; # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
+1E50; C; 1E51; # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
+1E52; C; 1E53; # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
+1E54; C; 1E55; # LATIN CAPITAL LETTER P WITH ACUTE
+1E56; C; 1E57; # LATIN CAPITAL LETTER P WITH DOT ABOVE
+1E58; C; 1E59; # LATIN CAPITAL LETTER R WITH DOT ABOVE
+1E5A; C; 1E5B; # LATIN CAPITAL LETTER R WITH DOT BELOW
+1E5C; C; 1E5D; # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
+1E5E; C; 1E5F; # LATIN CAPITAL LETTER R WITH LINE BELOW
+1E60; C; 1E61; # LATIN CAPITAL LETTER S WITH DOT ABOVE
+1E62; C; 1E63; # LATIN CAPITAL LETTER S WITH DOT BELOW
+1E64; C; 1E65; # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
+1E66; C; 1E67; # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
+1E68; C; 1E69; # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E6A; C; 1E6B; # LATIN CAPITAL LETTER T WITH DOT ABOVE
+1E6C; C; 1E6D; # LATIN CAPITAL LETTER T WITH DOT BELOW
+1E6E; C; 1E6F; # LATIN CAPITAL LETTER T WITH LINE BELOW
+1E70; C; 1E71; # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
+1E72; C; 1E73; # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
+1E74; C; 1E75; # LATIN CAPITAL LETTER U WITH TILDE BELOW
+1E76; C; 1E77; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
+1E78; C; 1E79; # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
+1E7A; C; 1E7B; # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
+1E7C; C; 1E7D; # LATIN CAPITAL LETTER V WITH TILDE
+1E7E; C; 1E7F; # LATIN CAPITAL LETTER V WITH DOT BELOW
+1E80; C; 1E81; # LATIN CAPITAL LETTER W WITH GRAVE
+1E82; C; 1E83; # LATIN CAPITAL LETTER W WITH ACUTE
+1E84; C; 1E85; # LATIN CAPITAL LETTER W WITH DIAERESIS
+1E86; C; 1E87; # LATIN CAPITAL LETTER W WITH DOT ABOVE
+1E88; C; 1E89; # LATIN CAPITAL LETTER W WITH DOT BELOW
+1E8A; C; 1E8B; # LATIN CAPITAL LETTER X WITH DOT ABOVE
+1E8C; C; 1E8D; # LATIN CAPITAL LETTER X WITH DIAERESIS
+1E8E; C; 1E8F; # LATIN CAPITAL LETTER Y WITH DOT ABOVE
+1E90; C; 1E91; # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
+1E92; C; 1E93; # LATIN CAPITAL LETTER Z WITH DOT BELOW
+1E94; C; 1E95; # LATIN CAPITAL LETTER Z WITH LINE BELOW
+1E96; F; 0068 0331; # LATIN SMALL LETTER H WITH LINE BELOW
+1E97; F; 0074 0308; # LATIN SMALL LETTER T WITH DIAERESIS
+1E98; F; 0077 030A; # LATIN SMALL LETTER W WITH RING ABOVE
+1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE
+1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING
+1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE
+1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S
+1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S
+1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW
+1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE
+1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA6; C; 1EA7; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA8; C; 1EA9; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EAA; C; 1EAB; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAC; C; 1EAD; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAE; C; 1EAF; # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+1EB0; C; 1EB1; # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+1EB2; C; 1EB3; # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+1EB4; C; 1EB5; # LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+1EB6; C; 1EB7; # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+1EB8; C; 1EB9; # LATIN CAPITAL LETTER E WITH DOT BELOW
+1EBA; C; 1EBB; # LATIN CAPITAL LETTER E WITH HOOK ABOVE
+1EBC; C; 1EBD; # LATIN CAPITAL LETTER E WITH TILDE
+1EBE; C; 1EBF; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EC0; C; 1EC1; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC2; C; 1EC3; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC4; C; 1EC5; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC6; C; 1EC7; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC8; C; 1EC9; # LATIN CAPITAL LETTER I WITH HOOK ABOVE
+1ECA; C; 1ECB; # LATIN CAPITAL LETTER I WITH DOT BELOW
+1ECC; C; 1ECD; # LATIN CAPITAL LETTER O WITH DOT BELOW
+1ECE; C; 1ECF; # LATIN CAPITAL LETTER O WITH HOOK ABOVE
+1ED0; C; 1ED1; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED2; C; 1ED3; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED4; C; 1ED5; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED6; C; 1ED7; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED8; C; 1ED9; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1EDA; C; 1EDB; # LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+1EDC; C; 1EDD; # LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+1EDE; C; 1EDF; # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+1EE0; C; 1EE1; # LATIN CAPITAL LETTER O WITH HORN AND TILDE
+1EE2; C; 1EE3; # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+1EE4; C; 1EE5; # LATIN CAPITAL LETTER U WITH DOT BELOW
+1EE6; C; 1EE7; # LATIN CAPITAL LETTER U WITH HOOK ABOVE
+1EE8; C; 1EE9; # LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+1EEA; C; 1EEB; # LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+1EEC; C; 1EED; # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+1EEE; C; 1EEF; # LATIN CAPITAL LETTER U WITH HORN AND TILDE
+1EF0; C; 1EF1; # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+1EF2; C; 1EF3; # LATIN CAPITAL LETTER Y WITH GRAVE
+1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW
+1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE
+1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL
+1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V
+1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP
+1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI
+1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA
+1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
+1F0B; C; 1F03; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
+1F0C; C; 1F04; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
+1F0D; C; 1F05; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
+1F0E; C; 1F06; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
+1F0F; C; 1F07; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F18; C; 1F10; # GREEK CAPITAL LETTER EPSILON WITH PSILI
+1F19; C; 1F11; # GREEK CAPITAL LETTER EPSILON WITH DASIA
+1F1A; C; 1F12; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
+1F1B; C; 1F13; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
+1F1C; C; 1F14; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
+1F1D; C; 1F15; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F28; C; 1F20; # GREEK CAPITAL LETTER ETA WITH PSILI
+1F29; C; 1F21; # GREEK CAPITAL LETTER ETA WITH DASIA
+1F2A; C; 1F22; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
+1F2B; C; 1F23; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
+1F2C; C; 1F24; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
+1F2D; C; 1F25; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
+1F2E; C; 1F26; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
+1F2F; C; 1F27; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+1F38; C; 1F30; # GREEK CAPITAL LETTER IOTA WITH PSILI
+1F39; C; 1F31; # GREEK CAPITAL LETTER IOTA WITH DASIA
+1F3A; C; 1F32; # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
+1F3B; C; 1F33; # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
+1F3C; C; 1F34; # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
+1F3D; C; 1F35; # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
+1F3E; C; 1F36; # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
+1F3F; C; 1F37; # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F48; C; 1F40; # GREEK CAPITAL LETTER OMICRON WITH PSILI
+1F49; C; 1F41; # GREEK CAPITAL LETTER OMICRON WITH DASIA
+1F4A; C; 1F42; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
+1F4B; C; 1F43; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
+1F4C; C; 1F44; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
+1F4D; C; 1F45; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F50; F; 03C5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI
+1F52; F; 03C5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA
+1F54; F; 03C5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA
+1F56; F; 03C5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI
+1F59; C; 1F51; # GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5B; C; 1F53; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5D; C; 1F55; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5F; C; 1F57; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F68; C; 1F60; # GREEK CAPITAL LETTER OMEGA WITH PSILI
+1F69; C; 1F61; # GREEK CAPITAL LETTER OMEGA WITH DASIA
+1F6A; C; 1F62; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
+1F6B; C; 1F63; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
+1F6C; C; 1F64; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
+1F6D; C; 1F65; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
+1F6E; C; 1F66; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
+1F6F; C; 1F67; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F80; F; 1F00 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
+1F81; F; 1F01 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
+1F82; F; 1F02 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F83; F; 1F03 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F84; F; 1F04 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F85; F; 1F05 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F86; F; 1F06 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F87; F; 1F07 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F88; F; 1F00 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+1F88; S; 1F80; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+1F89; F; 1F01 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+1F89; S; 1F81; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+1F8A; F; 1F02 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F8A; S; 1F82; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F8B; F; 1F03 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F8B; S; 1F83; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F8C; F; 1F04 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F8C; S; 1F84; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F8D; F; 1F05 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F8D; S; 1F85; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F8E; F; 1F06 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F8E; S; 1F86; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F8F; F; 1F07 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1F8F; S; 1F87; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1F90; F; 1F20 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
+1F91; F; 1F21 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
+1F92; F; 1F22 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F93; F; 1F23 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F94; F; 1F24 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F95; F; 1F25 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F96; F; 1F26 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F97; F; 1F27 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F98; F; 1F20 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+1F98; S; 1F90; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+1F99; F; 1F21 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+1F99; S; 1F91; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+1F9A; F; 1F22 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F9A; S; 1F92; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F9B; F; 1F23 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F9B; S; 1F93; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F9C; F; 1F24 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F9C; S; 1F94; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F9D; F; 1F25 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F9D; S; 1F95; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F9E; F; 1F26 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F9E; S; 1F96; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F9F; F; 1F27 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1F9F; S; 1F97; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FA0; F; 1F60 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
+1FA1; F; 1F61 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
+1FA2; F; 1F62 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1FA3; F; 1F63 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1FA4; F; 1F64 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1FA5; F; 1F65 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1FA6; F; 1F66 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1FA7; F; 1F67 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1FA8; F; 1F60 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+1FA8; S; 1FA0; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+1FA9; F; 1F61 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+1FA9; S; 1FA1; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+1FAA; F; 1F62 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1FAA; S; 1FA2; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1FAB; F; 1F63 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1FAB; S; 1FA3; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1FAC; F; 1F64 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1FAC; S; 1FA4; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1FAD; F; 1F65 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1FAD; S; 1FA5; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1FAE; F; 1F66 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1FAE; S; 1FA6; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1FAF; F; 1F67 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FAF; S; 1FA7; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FB2; F; 1F70 03B9; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
+1FB3; F; 03B1 03B9; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
+1FB4; F; 03AC 03B9; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB6; F; 03B1 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+1FB7; F; 03B1 0342 03B9; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FB8; C; 1FB0; # GREEK CAPITAL LETTER ALPHA WITH VRACHY
+1FB9; C; 1FB1; # GREEK CAPITAL LETTER ALPHA WITH MACRON
+1FBA; C; 1F70; # GREEK CAPITAL LETTER ALPHA WITH VARIA
+1FBB; C; 1F71; # GREEK CAPITAL LETTER ALPHA WITH OXIA
+1FBC; F; 03B1 03B9; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBC; S; 1FB3; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBE; C; 03B9; # GREEK PROSGEGRAMMENI
+1FC2; F; 1F74 03B9; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
+1FC3; F; 03B7 03B9; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
+1FC4; F; 03AE 03B9; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC6; F; 03B7 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI
+1FC7; F; 03B7 0342 03B9; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FC8; C; 1F72; # GREEK CAPITAL LETTER EPSILON WITH VARIA
+1FC9; C; 1F73; # GREEK CAPITAL LETTER EPSILON WITH OXIA
+1FCA; C; 1F74; # GREEK CAPITAL LETTER ETA WITH VARIA
+1FCB; C; 1F75; # GREEK CAPITAL LETTER ETA WITH OXIA
+1FCC; F; 03B7 03B9; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI
+1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY
+1FD9; C; 1FD1; # GREEK CAPITAL LETTER IOTA WITH MACRON
+1FDA; C; 1F76; # GREEK CAPITAL LETTER IOTA WITH VARIA
+1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA
+1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI
+1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI
+1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+1FE8; C; 1FE0; # GREEK CAPITAL LETTER UPSILON WITH VRACHY
+1FE9; C; 1FE1; # GREEK CAPITAL LETTER UPSILON WITH MACRON
+1FEA; C; 1F7A; # GREEK CAPITAL LETTER UPSILON WITH VARIA
+1FEB; C; 1F7B; # GREEK CAPITAL LETTER UPSILON WITH OXIA
+1FEC; C; 1FE5; # GREEK CAPITAL LETTER RHO WITH DASIA
+1FF2; F; 1F7C 03B9; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
+1FF3; F; 03C9 03B9; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
+1FF4; F; 03CE 03B9; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF6; F; 03C9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+1FF7; F; 03C9 0342 03B9; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FF8; C; 1F78; # GREEK CAPITAL LETTER OMICRON WITH VARIA
+1FF9; C; 1F79; # GREEK CAPITAL LETTER OMICRON WITH OXIA
+1FFA; C; 1F7C; # GREEK CAPITAL LETTER OMEGA WITH VARIA
+1FFB; C; 1F7D; # GREEK CAPITAL LETTER OMEGA WITH OXIA
+1FFC; F; 03C9 03B9; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+1FFC; S; 1FF3; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+2126; C; 03C9; # OHM SIGN
+212A; C; 006B; # KELVIN SIGN
+212B; C; 00E5; # ANGSTROM SIGN
+2132; C; 214E; # TURNED CAPITAL F
+2160; C; 2170; # ROMAN NUMERAL ONE
+2161; C; 2171; # ROMAN NUMERAL TWO
+2162; C; 2172; # ROMAN NUMERAL THREE
+2163; C; 2173; # ROMAN NUMERAL FOUR
+2164; C; 2174; # ROMAN NUMERAL FIVE
+2165; C; 2175; # ROMAN NUMERAL SIX
+2166; C; 2176; # ROMAN NUMERAL SEVEN
+2167; C; 2177; # ROMAN NUMERAL EIGHT
+2168; C; 2178; # ROMAN NUMERAL NINE
+2169; C; 2179; # ROMAN NUMERAL TEN
+216A; C; 217A; # ROMAN NUMERAL ELEVEN
+216B; C; 217B; # ROMAN NUMERAL TWELVE
+216C; C; 217C; # ROMAN NUMERAL FIFTY
+216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED
+216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED
+216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND
+2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED
+24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A
+24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B
+24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C
+24B9; C; 24D3; # CIRCLED LATIN CAPITAL LETTER D
+24BA; C; 24D4; # CIRCLED LATIN CAPITAL LETTER E
+24BB; C; 24D5; # CIRCLED LATIN CAPITAL LETTER F
+24BC; C; 24D6; # CIRCLED LATIN CAPITAL LETTER G
+24BD; C; 24D7; # CIRCLED LATIN CAPITAL LETTER H
+24BE; C; 24D8; # CIRCLED LATIN CAPITAL LETTER I
+24BF; C; 24D9; # CIRCLED LATIN CAPITAL LETTER J
+24C0; C; 24DA; # CIRCLED LATIN CAPITAL LETTER K
+24C1; C; 24DB; # CIRCLED LATIN CAPITAL LETTER L
+24C2; C; 24DC; # CIRCLED LATIN CAPITAL LETTER M
+24C3; C; 24DD; # CIRCLED LATIN CAPITAL LETTER N
+24C4; C; 24DE; # CIRCLED LATIN CAPITAL LETTER O
+24C5; C; 24DF; # CIRCLED LATIN CAPITAL LETTER P
+24C6; C; 24E0; # CIRCLED LATIN CAPITAL LETTER Q
+24C7; C; 24E1; # CIRCLED LATIN CAPITAL LETTER R
+24C8; C; 24E2; # CIRCLED LATIN CAPITAL LETTER S
+24C9; C; 24E3; # CIRCLED LATIN CAPITAL LETTER T
+24CA; C; 24E4; # CIRCLED LATIN CAPITAL LETTER U
+24CB; C; 24E5; # CIRCLED LATIN CAPITAL LETTER V
+24CC; C; 24E6; # CIRCLED LATIN CAPITAL LETTER W
+24CD; C; 24E7; # CIRCLED LATIN CAPITAL LETTER X
+24CE; C; 24E8; # CIRCLED LATIN CAPITAL LETTER Y
+24CF; C; 24E9; # CIRCLED LATIN CAPITAL LETTER Z
+2C00; C; 2C30; # GLAGOLITIC CAPITAL LETTER AZU
+2C01; C; 2C31; # GLAGOLITIC CAPITAL LETTER BUKY
+2C02; C; 2C32; # GLAGOLITIC CAPITAL LETTER VEDE
+2C03; C; 2C33; # GLAGOLITIC CAPITAL LETTER GLAGOLI
+2C04; C; 2C34; # GLAGOLITIC CAPITAL LETTER DOBRO
+2C05; C; 2C35; # GLAGOLITIC CAPITAL LETTER YESTU
+2C06; C; 2C36; # GLAGOLITIC CAPITAL LETTER ZHIVETE
+2C07; C; 2C37; # GLAGOLITIC CAPITAL LETTER DZELO
+2C08; C; 2C38; # GLAGOLITIC CAPITAL LETTER ZEMLJA
+2C09; C; 2C39; # GLAGOLITIC CAPITAL LETTER IZHE
+2C0A; C; 2C3A; # GLAGOLITIC CAPITAL LETTER INITIAL IZHE
+2C0B; C; 2C3B; # GLAGOLITIC CAPITAL LETTER I
+2C0C; C; 2C3C; # GLAGOLITIC CAPITAL LETTER DJERVI
+2C0D; C; 2C3D; # GLAGOLITIC CAPITAL LETTER KAKO
+2C0E; C; 2C3E; # GLAGOLITIC CAPITAL LETTER LJUDIJE
+2C0F; C; 2C3F; # GLAGOLITIC CAPITAL LETTER MYSLITE
+2C10; C; 2C40; # GLAGOLITIC CAPITAL LETTER NASHI
+2C11; C; 2C41; # GLAGOLITIC CAPITAL LETTER ONU
+2C12; C; 2C42; # GLAGOLITIC CAPITAL LETTER POKOJI
+2C13; C; 2C43; # GLAGOLITIC CAPITAL LETTER RITSI
+2C14; C; 2C44; # GLAGOLITIC CAPITAL LETTER SLOVO
+2C15; C; 2C45; # GLAGOLITIC CAPITAL LETTER TVRIDO
+2C16; C; 2C46; # GLAGOLITIC CAPITAL LETTER UKU
+2C17; C; 2C47; # GLAGOLITIC CAPITAL LETTER FRITU
+2C18; C; 2C48; # GLAGOLITIC CAPITAL LETTER HERU
+2C19; C; 2C49; # GLAGOLITIC CAPITAL LETTER OTU
+2C1A; C; 2C4A; # GLAGOLITIC CAPITAL LETTER PE
+2C1B; C; 2C4B; # GLAGOLITIC CAPITAL LETTER SHTA
+2C1C; C; 2C4C; # GLAGOLITIC CAPITAL LETTER TSI
+2C1D; C; 2C4D; # GLAGOLITIC CAPITAL LETTER CHRIVI
+2C1E; C; 2C4E; # GLAGOLITIC CAPITAL LETTER SHA
+2C1F; C; 2C4F; # GLAGOLITIC CAPITAL LETTER YERU
+2C20; C; 2C50; # GLAGOLITIC CAPITAL LETTER YERI
+2C21; C; 2C51; # GLAGOLITIC CAPITAL LETTER YATI
+2C22; C; 2C52; # GLAGOLITIC CAPITAL LETTER SPIDERY HA
+2C23; C; 2C53; # GLAGOLITIC CAPITAL LETTER YU
+2C24; C; 2C54; # GLAGOLITIC CAPITAL LETTER SMALL YUS
+2C25; C; 2C55; # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL
+2C26; C; 2C56; # GLAGOLITIC CAPITAL LETTER YO
+2C27; C; 2C57; # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS
+2C28; C; 2C58; # GLAGOLITIC CAPITAL LETTER BIG YUS
+2C29; C; 2C59; # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS
+2C2A; C; 2C5A; # GLAGOLITIC CAPITAL LETTER FITA
+2C2B; C; 2C5B; # GLAGOLITIC CAPITAL LETTER IZHITSA
+2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC
+2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A
+2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
+2C2F; C; 2C5F; # GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI
+2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR
+2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE
+2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE
+2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL
+2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER
+2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER
+2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER
+2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA
+2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK
+2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A
+2C70; C; 0252; # LATIN CAPITAL LETTER TURNED ALPHA
+2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK
+2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H
+2C7E; C; 023F; # LATIN CAPITAL LETTER S WITH SWASH TAIL
+2C7F; C; 0240; # LATIN CAPITAL LETTER Z WITH SWASH TAIL
+2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA
+2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA
+2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA
+2C86; C; 2C87; # COPTIC CAPITAL LETTER DALDA
+2C88; C; 2C89; # COPTIC CAPITAL LETTER EIE
+2C8A; C; 2C8B; # COPTIC CAPITAL LETTER SOU
+2C8C; C; 2C8D; # COPTIC CAPITAL LETTER ZATA
+2C8E; C; 2C8F; # COPTIC CAPITAL LETTER HATE
+2C90; C; 2C91; # COPTIC CAPITAL LETTER THETHE
+2C92; C; 2C93; # COPTIC CAPITAL LETTER IAUDA
+2C94; C; 2C95; # COPTIC CAPITAL LETTER KAPA
+2C96; C; 2C97; # COPTIC CAPITAL LETTER LAULA
+2C98; C; 2C99; # COPTIC CAPITAL LETTER MI
+2C9A; C; 2C9B; # COPTIC CAPITAL LETTER NI
+2C9C; C; 2C9D; # COPTIC CAPITAL LETTER KSI
+2C9E; C; 2C9F; # COPTIC CAPITAL LETTER O
+2CA0; C; 2CA1; # COPTIC CAPITAL LETTER PI
+2CA2; C; 2CA3; # COPTIC CAPITAL LETTER RO
+2CA4; C; 2CA5; # COPTIC CAPITAL LETTER SIMA
+2CA6; C; 2CA7; # COPTIC CAPITAL LETTER TAU
+2CA8; C; 2CA9; # COPTIC CAPITAL LETTER UA
+2CAA; C; 2CAB; # COPTIC CAPITAL LETTER FI
+2CAC; C; 2CAD; # COPTIC CAPITAL LETTER KHI
+2CAE; C; 2CAF; # COPTIC CAPITAL LETTER PSI
+2CB0; C; 2CB1; # COPTIC CAPITAL LETTER OOU
+2CB2; C; 2CB3; # COPTIC CAPITAL LETTER DIALECT-P ALEF
+2CB4; C; 2CB5; # COPTIC CAPITAL LETTER OLD COPTIC AIN
+2CB6; C; 2CB7; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
+2CB8; C; 2CB9; # COPTIC CAPITAL LETTER DIALECT-P KAPA
+2CBA; C; 2CBB; # COPTIC CAPITAL LETTER DIALECT-P NI
+2CBC; C; 2CBD; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
+2CBE; C; 2CBF; # COPTIC CAPITAL LETTER OLD COPTIC OOU
+2CC0; C; 2CC1; # COPTIC CAPITAL LETTER SAMPI
+2CC2; C; 2CC3; # COPTIC CAPITAL LETTER CROSSED SHEI
+2CC4; C; 2CC5; # COPTIC CAPITAL LETTER OLD COPTIC SHEI
+2CC6; C; 2CC7; # COPTIC CAPITAL LETTER OLD COPTIC ESH
+2CC8; C; 2CC9; # COPTIC CAPITAL LETTER AKHMIMIC KHEI
+2CCA; C; 2CCB; # COPTIC CAPITAL LETTER DIALECT-P HORI
+2CCC; C; 2CCD; # COPTIC CAPITAL LETTER OLD COPTIC HORI
+2CCE; C; 2CCF; # COPTIC CAPITAL LETTER OLD COPTIC HA
+2CD0; C; 2CD1; # COPTIC CAPITAL LETTER L-SHAPED HA
+2CD2; C; 2CD3; # COPTIC CAPITAL LETTER OLD COPTIC HEI
+2CD4; C; 2CD5; # COPTIC CAPITAL LETTER OLD COPTIC HAT
+2CD6; C; 2CD7; # COPTIC CAPITAL LETTER OLD COPTIC GANGIA
+2CD8; C; 2CD9; # COPTIC CAPITAL LETTER OLD COPTIC DJA
+2CDA; C; 2CDB; # COPTIC CAPITAL LETTER OLD COPTIC SHIMA
+2CDC; C; 2CDD; # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
+2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI
+2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI
+2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU
+2CEB; C; 2CEC; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
+2CED; C; 2CEE; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
+2CF2; C; 2CF3; # COPTIC CAPITAL LETTER BOHAIRIC KHEI
+A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA
+A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO
+A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE
+A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA
+A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV
+A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK
+A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA
+A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER
+A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER
+A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT
+A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU
+A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A
+A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
+A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS
+A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
+A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN
+A660; C; A661; # CYRILLIC CAPITAL LETTER REVERSED TSE
+A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE
+A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL
+A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM
+A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O
+A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O
+A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
+A680; C; A681; # CYRILLIC CAPITAL LETTER DWE
+A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE
+A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE
+A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE
+A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE
+A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
+A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE
+A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE
+A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE
+A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE
+A694; C; A695; # CYRILLIC CAPITAL LETTER HWE
+A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE
+A698; C; A699; # CYRILLIC CAPITAL LETTER DOUBLE O
+A69A; C; A69B; # CYRILLIC CAPITAL LETTER CROSSED O
+A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
+A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
+A726; C; A727; # LATIN CAPITAL LETTER HENG
+A728; C; A729; # LATIN CAPITAL LETTER TZ
+A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO
+A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO
+A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA
+A732; C; A733; # LATIN CAPITAL LETTER AA
+A734; C; A735; # LATIN CAPITAL LETTER AO
+A736; C; A737; # LATIN CAPITAL LETTER AU
+A738; C; A739; # LATIN CAPITAL LETTER AV
+A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
+A73C; C; A73D; # LATIN CAPITAL LETTER AY
+A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT
+A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE
+A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
+A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
+A746; C; A747; # LATIN CAPITAL LETTER BROKEN L
+A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE
+A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
+A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP
+A74E; C; A74F; # LATIN CAPITAL LETTER OO
+A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
+A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH
+A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
+A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
+A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
+A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA
+A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA
+A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
+A760; C; A761; # LATIN CAPITAL LETTER VY
+A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z
+A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE
+A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
+A768; C; A769; # LATIN CAPITAL LETTER VEND
+A76A; C; A76B; # LATIN CAPITAL LETTER ET
+A76C; C; A76D; # LATIN CAPITAL LETTER IS
+A76E; C; A76F; # LATIN CAPITAL LETTER CON
+A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D
+A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F
+A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G
+A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G
+A780; C; A781; # LATIN CAPITAL LETTER TURNED L
+A782; C; A783; # LATIN CAPITAL LETTER INSULAR R
+A784; C; A785; # LATIN CAPITAL LETTER INSULAR S
+A786; C; A787; # LATIN CAPITAL LETTER INSULAR T
+A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO
+A78D; C; 0265; # LATIN CAPITAL LETTER TURNED H
+A790; C; A791; # LATIN CAPITAL LETTER N WITH DESCENDER
+A792; C; A793; # LATIN CAPITAL LETTER C WITH BAR
+A796; C; A797; # LATIN CAPITAL LETTER B WITH FLOURISH
+A798; C; A799; # LATIN CAPITAL LETTER F WITH STROKE
+A79A; C; A79B; # LATIN CAPITAL LETTER VOLAPUK AE
+A79C; C; A79D; # LATIN CAPITAL LETTER VOLAPUK OE
+A79E; C; A79F; # LATIN CAPITAL LETTER VOLAPUK UE
+A7A0; C; A7A1; # LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
+A7A2; C; A7A3; # LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
+A7A4; C; A7A5; # LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
+A7A6; C; A7A7; # LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
+A7A8; C; A7A9; # LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
+A7AA; C; 0266; # LATIN CAPITAL LETTER H WITH HOOK
+A7AB; C; 025C; # LATIN CAPITAL LETTER REVERSED OPEN E
+A7AC; C; 0261; # LATIN CAPITAL LETTER SCRIPT G
+A7AD; C; 026C; # LATIN CAPITAL LETTER L WITH BELT
+A7AE; C; 026A; # LATIN CAPITAL LETTER SMALL CAPITAL I
+A7B0; C; 029E; # LATIN CAPITAL LETTER TURNED K
+A7B1; C; 0287; # LATIN CAPITAL LETTER TURNED T
+A7B2; C; 029D; # LATIN CAPITAL LETTER J WITH CROSSED-TAIL
+A7B3; C; AB53; # LATIN CAPITAL LETTER CHI
+A7B4; C; A7B5; # LATIN CAPITAL LETTER BETA
+A7B6; C; A7B7; # LATIN CAPITAL LETTER OMEGA
+A7B8; C; A7B9; # LATIN CAPITAL LETTER U WITH STROKE
+A7BA; C; A7BB; # LATIN CAPITAL LETTER GLOTTAL A
+A7BC; C; A7BD; # LATIN CAPITAL LETTER GLOTTAL I
+A7BE; C; A7BF; # LATIN CAPITAL LETTER GLOTTAL U
+A7C0; C; A7C1; # LATIN CAPITAL LETTER OLD POLISH O
+A7C2; C; A7C3; # LATIN CAPITAL LETTER ANGLICANA W
+A7C4; C; A794; # LATIN CAPITAL LETTER C WITH PALATAL HOOK
+A7C5; C; 0282; # LATIN CAPITAL LETTER S WITH HOOK
+A7C6; C; 1D8E; # LATIN CAPITAL LETTER Z WITH PALATAL HOOK
+A7C7; C; A7C8; # LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY
+A7C9; C; A7CA; # LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY
+A7D0; C; A7D1; # LATIN CAPITAL LETTER CLOSED INSULAR G
+A7D6; C; A7D7; # LATIN CAPITAL LETTER MIDDLE SCOTS S
+A7D8; C; A7D9; # LATIN CAPITAL LETTER SIGMOID S
+A7F5; C; A7F6; # LATIN CAPITAL LETTER REVERSED HALF H
+AB70; C; 13A0; # CHEROKEE SMALL LETTER A
+AB71; C; 13A1; # CHEROKEE SMALL LETTER E
+AB72; C; 13A2; # CHEROKEE SMALL LETTER I
+AB73; C; 13A3; # CHEROKEE SMALL LETTER O
+AB74; C; 13A4; # CHEROKEE SMALL LETTER U
+AB75; C; 13A5; # CHEROKEE SMALL LETTER V
+AB76; C; 13A6; # CHEROKEE SMALL LETTER GA
+AB77; C; 13A7; # CHEROKEE SMALL LETTER KA
+AB78; C; 13A8; # CHEROKEE SMALL LETTER GE
+AB79; C; 13A9; # CHEROKEE SMALL LETTER GI
+AB7A; C; 13AA; # CHEROKEE SMALL LETTER GO
+AB7B; C; 13AB; # CHEROKEE SMALL LETTER GU
+AB7C; C; 13AC; # CHEROKEE SMALL LETTER GV
+AB7D; C; 13AD; # CHEROKEE SMALL LETTER HA
+AB7E; C; 13AE; # CHEROKEE SMALL LETTER HE
+AB7F; C; 13AF; # CHEROKEE SMALL LETTER HI
+AB80; C; 13B0; # CHEROKEE SMALL LETTER HO
+AB81; C; 13B1; # CHEROKEE SMALL LETTER HU
+AB82; C; 13B2; # CHEROKEE SMALL LETTER HV
+AB83; C; 13B3; # CHEROKEE SMALL LETTER LA
+AB84; C; 13B4; # CHEROKEE SMALL LETTER LE
+AB85; C; 13B5; # CHEROKEE SMALL LETTER LI
+AB86; C; 13B6; # CHEROKEE SMALL LETTER LO
+AB87; C; 13B7; # CHEROKEE SMALL LETTER LU
+AB88; C; 13B8; # CHEROKEE SMALL LETTER LV
+AB89; C; 13B9; # CHEROKEE SMALL LETTER MA
+AB8A; C; 13BA; # CHEROKEE SMALL LETTER ME
+AB8B; C; 13BB; # CHEROKEE SMALL LETTER MI
+AB8C; C; 13BC; # CHEROKEE SMALL LETTER MO
+AB8D; C; 13BD; # CHEROKEE SMALL LETTER MU
+AB8E; C; 13BE; # CHEROKEE SMALL LETTER NA
+AB8F; C; 13BF; # CHEROKEE SMALL LETTER HNA
+AB90; C; 13C0; # CHEROKEE SMALL LETTER NAH
+AB91; C; 13C1; # CHEROKEE SMALL LETTER NE
+AB92; C; 13C2; # CHEROKEE SMALL LETTER NI
+AB93; C; 13C3; # CHEROKEE SMALL LETTER NO
+AB94; C; 13C4; # CHEROKEE SMALL LETTER NU
+AB95; C; 13C5; # CHEROKEE SMALL LETTER NV
+AB96; C; 13C6; # CHEROKEE SMALL LETTER QUA
+AB97; C; 13C7; # CHEROKEE SMALL LETTER QUE
+AB98; C; 13C8; # CHEROKEE SMALL LETTER QUI
+AB99; C; 13C9; # CHEROKEE SMALL LETTER QUO
+AB9A; C; 13CA; # CHEROKEE SMALL LETTER QUU
+AB9B; C; 13CB; # CHEROKEE SMALL LETTER QUV
+AB9C; C; 13CC; # CHEROKEE SMALL LETTER SA
+AB9D; C; 13CD; # CHEROKEE SMALL LETTER S
+AB9E; C; 13CE; # CHEROKEE SMALL LETTER SE
+AB9F; C; 13CF; # CHEROKEE SMALL LETTER SI
+ABA0; C; 13D0; # CHEROKEE SMALL LETTER SO
+ABA1; C; 13D1; # CHEROKEE SMALL LETTER SU
+ABA2; C; 13D2; # CHEROKEE SMALL LETTER SV
+ABA3; C; 13D3; # CHEROKEE SMALL LETTER DA
+ABA4; C; 13D4; # CHEROKEE SMALL LETTER TA
+ABA5; C; 13D5; # CHEROKEE SMALL LETTER DE
+ABA6; C; 13D6; # CHEROKEE SMALL LETTER TE
+ABA7; C; 13D7; # CHEROKEE SMALL LETTER DI
+ABA8; C; 13D8; # CHEROKEE SMALL LETTER TI
+ABA9; C; 13D9; # CHEROKEE SMALL LETTER DO
+ABAA; C; 13DA; # CHEROKEE SMALL LETTER DU
+ABAB; C; 13DB; # CHEROKEE SMALL LETTER DV
+ABAC; C; 13DC; # CHEROKEE SMALL LETTER DLA
+ABAD; C; 13DD; # CHEROKEE SMALL LETTER TLA
+ABAE; C; 13DE; # CHEROKEE SMALL LETTER TLE
+ABAF; C; 13DF; # CHEROKEE SMALL LETTER TLI
+ABB0; C; 13E0; # CHEROKEE SMALL LETTER TLO
+ABB1; C; 13E1; # CHEROKEE SMALL LETTER TLU
+ABB2; C; 13E2; # CHEROKEE SMALL LETTER TLV
+ABB3; C; 13E3; # CHEROKEE SMALL LETTER TSA
+ABB4; C; 13E4; # CHEROKEE SMALL LETTER TSE
+ABB5; C; 13E5; # CHEROKEE SMALL LETTER TSI
+ABB6; C; 13E6; # CHEROKEE SMALL LETTER TSO
+ABB7; C; 13E7; # CHEROKEE SMALL LETTER TSU
+ABB8; C; 13E8; # CHEROKEE SMALL LETTER TSV
+ABB9; C; 13E9; # CHEROKEE SMALL LETTER WA
+ABBA; C; 13EA; # CHEROKEE SMALL LETTER WE
+ABBB; C; 13EB; # CHEROKEE SMALL LETTER WI
+ABBC; C; 13EC; # CHEROKEE SMALL LETTER WO
+ABBD; C; 13ED; # CHEROKEE SMALL LETTER WU
+ABBE; C; 13EE; # CHEROKEE SMALL LETTER WV
+ABBF; C; 13EF; # CHEROKEE SMALL LETTER YA
+FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF
+FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI
+FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL
+FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI
+FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL
+FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T
+FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST
+FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW
+FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH
+FB15; F; 0574 056B; # ARMENIAN SMALL LIGATURE MEN INI
+FB16; F; 057E 0576; # ARMENIAN SMALL LIGATURE VEW NOW
+FB17; F; 0574 056D; # ARMENIAN SMALL LIGATURE MEN XEH
+FF21; C; FF41; # FULLWIDTH LATIN CAPITAL LETTER A
+FF22; C; FF42; # FULLWIDTH LATIN CAPITAL LETTER B
+FF23; C; FF43; # FULLWIDTH LATIN CAPITAL LETTER C
+FF24; C; FF44; # FULLWIDTH LATIN CAPITAL LETTER D
+FF25; C; FF45; # FULLWIDTH LATIN CAPITAL LETTER E
+FF26; C; FF46; # FULLWIDTH LATIN CAPITAL LETTER F
+FF27; C; FF47; # FULLWIDTH LATIN CAPITAL LETTER G
+FF28; C; FF48; # FULLWIDTH LATIN CAPITAL LETTER H
+FF29; C; FF49; # FULLWIDTH LATIN CAPITAL LETTER I
+FF2A; C; FF4A; # FULLWIDTH LATIN CAPITAL LETTER J
+FF2B; C; FF4B; # FULLWIDTH LATIN CAPITAL LETTER K
+FF2C; C; FF4C; # FULLWIDTH LATIN CAPITAL LETTER L
+FF2D; C; FF4D; # FULLWIDTH LATIN CAPITAL LETTER M
+FF2E; C; FF4E; # FULLWIDTH LATIN CAPITAL LETTER N
+FF2F; C; FF4F; # FULLWIDTH LATIN CAPITAL LETTER O
+FF30; C; FF50; # FULLWIDTH LATIN CAPITAL LETTER P
+FF31; C; FF51; # FULLWIDTH LATIN CAPITAL LETTER Q
+FF32; C; FF52; # FULLWIDTH LATIN CAPITAL LETTER R
+FF33; C; FF53; # FULLWIDTH LATIN CAPITAL LETTER S
+FF34; C; FF54; # FULLWIDTH LATIN CAPITAL LETTER T
+FF35; C; FF55; # FULLWIDTH LATIN CAPITAL LETTER U
+FF36; C; FF56; # FULLWIDTH LATIN CAPITAL LETTER V
+FF37; C; FF57; # FULLWIDTH LATIN CAPITAL LETTER W
+FF38; C; FF58; # FULLWIDTH LATIN CAPITAL LETTER X
+FF39; C; FF59; # FULLWIDTH LATIN CAPITAL LETTER Y
+FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z
+10400; C; 10428; # DESERET CAPITAL LETTER LONG I
+10401; C; 10429; # DESERET CAPITAL LETTER LONG E
+10402; C; 1042A; # DESERET CAPITAL LETTER LONG A
+10403; C; 1042B; # DESERET CAPITAL LETTER LONG AH
+10404; C; 1042C; # DESERET CAPITAL LETTER LONG O
+10405; C; 1042D; # DESERET CAPITAL LETTER LONG OO
+10406; C; 1042E; # DESERET CAPITAL LETTER SHORT I
+10407; C; 1042F; # DESERET CAPITAL LETTER SHORT E
+10408; C; 10430; # DESERET CAPITAL LETTER SHORT A
+10409; C; 10431; # DESERET CAPITAL LETTER SHORT AH
+1040A; C; 10432; # DESERET CAPITAL LETTER SHORT O
+1040B; C; 10433; # DESERET CAPITAL LETTER SHORT OO
+1040C; C; 10434; # DESERET CAPITAL LETTER AY
+1040D; C; 10435; # DESERET CAPITAL LETTER OW
+1040E; C; 10436; # DESERET CAPITAL LETTER WU
+1040F; C; 10437; # DESERET CAPITAL LETTER YEE
+10410; C; 10438; # DESERET CAPITAL LETTER H
+10411; C; 10439; # DESERET CAPITAL LETTER PEE
+10412; C; 1043A; # DESERET CAPITAL LETTER BEE
+10413; C; 1043B; # DESERET CAPITAL LETTER TEE
+10414; C; 1043C; # DESERET CAPITAL LETTER DEE
+10415; C; 1043D; # DESERET CAPITAL LETTER CHEE
+10416; C; 1043E; # DESERET CAPITAL LETTER JEE
+10417; C; 1043F; # DESERET CAPITAL LETTER KAY
+10418; C; 10440; # DESERET CAPITAL LETTER GAY
+10419; C; 10441; # DESERET CAPITAL LETTER EF
+1041A; C; 10442; # DESERET CAPITAL LETTER VEE
+1041B; C; 10443; # DESERET CAPITAL LETTER ETH
+1041C; C; 10444; # DESERET CAPITAL LETTER THEE
+1041D; C; 10445; # DESERET CAPITAL LETTER ES
+1041E; C; 10446; # DESERET CAPITAL LETTER ZEE
+1041F; C; 10447; # DESERET CAPITAL LETTER ESH
+10420; C; 10448; # DESERET CAPITAL LETTER ZHEE
+10421; C; 10449; # DESERET CAPITAL LETTER ER
+10422; C; 1044A; # DESERET CAPITAL LETTER EL
+10423; C; 1044B; # DESERET CAPITAL LETTER EM
+10424; C; 1044C; # DESERET CAPITAL LETTER EN
+10425; C; 1044D; # DESERET CAPITAL LETTER ENG
+10426; C; 1044E; # DESERET CAPITAL LETTER OI
+10427; C; 1044F; # DESERET CAPITAL LETTER EW
+104B0; C; 104D8; # OSAGE CAPITAL LETTER A
+104B1; C; 104D9; # OSAGE CAPITAL LETTER AI
+104B2; C; 104DA; # OSAGE CAPITAL LETTER AIN
+104B3; C; 104DB; # OSAGE CAPITAL LETTER AH
+104B4; C; 104DC; # OSAGE CAPITAL LETTER BRA
+104B5; C; 104DD; # OSAGE CAPITAL LETTER CHA
+104B6; C; 104DE; # OSAGE CAPITAL LETTER EHCHA
+104B7; C; 104DF; # OSAGE CAPITAL LETTER E
+104B8; C; 104E0; # OSAGE CAPITAL LETTER EIN
+104B9; C; 104E1; # OSAGE CAPITAL LETTER HA
+104BA; C; 104E2; # OSAGE CAPITAL LETTER HYA
+104BB; C; 104E3; # OSAGE CAPITAL LETTER I
+104BC; C; 104E4; # OSAGE CAPITAL LETTER KA
+104BD; C; 104E5; # OSAGE CAPITAL LETTER EHKA
+104BE; C; 104E6; # OSAGE CAPITAL LETTER KYA
+104BF; C; 104E7; # OSAGE CAPITAL LETTER LA
+104C0; C; 104E8; # OSAGE CAPITAL LETTER MA
+104C1; C; 104E9; # OSAGE CAPITAL LETTER NA
+104C2; C; 104EA; # OSAGE CAPITAL LETTER O
+104C3; C; 104EB; # OSAGE CAPITAL LETTER OIN
+104C4; C; 104EC; # OSAGE CAPITAL LETTER PA
+104C5; C; 104ED; # OSAGE CAPITAL LETTER EHPA
+104C6; C; 104EE; # OSAGE CAPITAL LETTER SA
+104C7; C; 104EF; # OSAGE CAPITAL LETTER SHA
+104C8; C; 104F0; # OSAGE CAPITAL LETTER TA
+104C9; C; 104F1; # OSAGE CAPITAL LETTER EHTA
+104CA; C; 104F2; # OSAGE CAPITAL LETTER TSA
+104CB; C; 104F3; # OSAGE CAPITAL LETTER EHTSA
+104CC; C; 104F4; # OSAGE CAPITAL LETTER TSHA
+104CD; C; 104F5; # OSAGE CAPITAL LETTER DHA
+104CE; C; 104F6; # OSAGE CAPITAL LETTER U
+104CF; C; 104F7; # OSAGE CAPITAL LETTER WA
+104D0; C; 104F8; # OSAGE CAPITAL LETTER KHA
+104D1; C; 104F9; # OSAGE CAPITAL LETTER GHA
+104D2; C; 104FA; # OSAGE CAPITAL LETTER ZA
+104D3; C; 104FB; # OSAGE CAPITAL LETTER ZHA
+10570; C; 10597; # VITHKUQI CAPITAL LETTER A
+10571; C; 10598; # VITHKUQI CAPITAL LETTER BBE
+10572; C; 10599; # VITHKUQI CAPITAL LETTER BE
+10573; C; 1059A; # VITHKUQI CAPITAL LETTER CE
+10574; C; 1059B; # VITHKUQI CAPITAL LETTER CHE
+10575; C; 1059C; # VITHKUQI CAPITAL LETTER DE
+10576; C; 1059D; # VITHKUQI CAPITAL LETTER DHE
+10577; C; 1059E; # VITHKUQI CAPITAL LETTER EI
+10578; C; 1059F; # VITHKUQI CAPITAL LETTER E
+10579; C; 105A0; # VITHKUQI CAPITAL LETTER FE
+1057A; C; 105A1; # VITHKUQI CAPITAL LETTER GA
+1057C; C; 105A3; # VITHKUQI CAPITAL LETTER HA
+1057D; C; 105A4; # VITHKUQI CAPITAL LETTER HHA
+1057E; C; 105A5; # VITHKUQI CAPITAL LETTER I
+1057F; C; 105A6; # VITHKUQI CAPITAL LETTER IJE
+10580; C; 105A7; # VITHKUQI CAPITAL LETTER JE
+10581; C; 105A8; # VITHKUQI CAPITAL LETTER KA
+10582; C; 105A9; # VITHKUQI CAPITAL LETTER LA
+10583; C; 105AA; # VITHKUQI CAPITAL LETTER LLA
+10584; C; 105AB; # VITHKUQI CAPITAL LETTER ME
+10585; C; 105AC; # VITHKUQI CAPITAL LETTER NE
+10586; C; 105AD; # VITHKUQI CAPITAL LETTER NJE
+10587; C; 105AE; # VITHKUQI CAPITAL LETTER O
+10588; C; 105AF; # VITHKUQI CAPITAL LETTER PE
+10589; C; 105B0; # VITHKUQI CAPITAL LETTER QA
+1058A; C; 105B1; # VITHKUQI CAPITAL LETTER RE
+1058C; C; 105B3; # VITHKUQI CAPITAL LETTER SE
+1058D; C; 105B4; # VITHKUQI CAPITAL LETTER SHE
+1058E; C; 105B5; # VITHKUQI CAPITAL LETTER TE
+1058F; C; 105B6; # VITHKUQI CAPITAL LETTER THE
+10590; C; 105B7; # VITHKUQI CAPITAL LETTER U
+10591; C; 105B8; # VITHKUQI CAPITAL LETTER VE
+10592; C; 105B9; # VITHKUQI CAPITAL LETTER XE
+10594; C; 105BB; # VITHKUQI CAPITAL LETTER Y
+10595; C; 105BC; # VITHKUQI CAPITAL LETTER ZE
+10C80; C; 10CC0; # OLD HUNGARIAN CAPITAL LETTER A
+10C81; C; 10CC1; # OLD HUNGARIAN CAPITAL LETTER AA
+10C82; C; 10CC2; # OLD HUNGARIAN CAPITAL LETTER EB
+10C83; C; 10CC3; # OLD HUNGARIAN CAPITAL LETTER AMB
+10C84; C; 10CC4; # OLD HUNGARIAN CAPITAL LETTER EC
+10C85; C; 10CC5; # OLD HUNGARIAN CAPITAL LETTER ENC
+10C86; C; 10CC6; # OLD HUNGARIAN CAPITAL LETTER ECS
+10C87; C; 10CC7; # OLD HUNGARIAN CAPITAL LETTER ED
+10C88; C; 10CC8; # OLD HUNGARIAN CAPITAL LETTER AND
+10C89; C; 10CC9; # OLD HUNGARIAN CAPITAL LETTER E
+10C8A; C; 10CCA; # OLD HUNGARIAN CAPITAL LETTER CLOSE E
+10C8B; C; 10CCB; # OLD HUNGARIAN CAPITAL LETTER EE
+10C8C; C; 10CCC; # OLD HUNGARIAN CAPITAL LETTER EF
+10C8D; C; 10CCD; # OLD HUNGARIAN CAPITAL LETTER EG
+10C8E; C; 10CCE; # OLD HUNGARIAN CAPITAL LETTER EGY
+10C8F; C; 10CCF; # OLD HUNGARIAN CAPITAL LETTER EH
+10C90; C; 10CD0; # OLD HUNGARIAN CAPITAL LETTER I
+10C91; C; 10CD1; # OLD HUNGARIAN CAPITAL LETTER II
+10C92; C; 10CD2; # OLD HUNGARIAN CAPITAL LETTER EJ
+10C93; C; 10CD3; # OLD HUNGARIAN CAPITAL LETTER EK
+10C94; C; 10CD4; # OLD HUNGARIAN CAPITAL LETTER AK
+10C95; C; 10CD5; # OLD HUNGARIAN CAPITAL LETTER UNK
+10C96; C; 10CD6; # OLD HUNGARIAN CAPITAL LETTER EL
+10C97; C; 10CD7; # OLD HUNGARIAN CAPITAL LETTER ELY
+10C98; C; 10CD8; # OLD HUNGARIAN CAPITAL LETTER EM
+10C99; C; 10CD9; # OLD HUNGARIAN CAPITAL LETTER EN
+10C9A; C; 10CDA; # OLD HUNGARIAN CAPITAL LETTER ENY
+10C9B; C; 10CDB; # OLD HUNGARIAN CAPITAL LETTER O
+10C9C; C; 10CDC; # OLD HUNGARIAN CAPITAL LETTER OO
+10C9D; C; 10CDD; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE
+10C9E; C; 10CDE; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE
+10C9F; C; 10CDF; # OLD HUNGARIAN CAPITAL LETTER OEE
+10CA0; C; 10CE0; # OLD HUNGARIAN CAPITAL LETTER EP
+10CA1; C; 10CE1; # OLD HUNGARIAN CAPITAL LETTER EMP
+10CA2; C; 10CE2; # OLD HUNGARIAN CAPITAL LETTER ER
+10CA3; C; 10CE3; # OLD HUNGARIAN CAPITAL LETTER SHORT ER
+10CA4; C; 10CE4; # OLD HUNGARIAN CAPITAL LETTER ES
+10CA5; C; 10CE5; # OLD HUNGARIAN CAPITAL LETTER ESZ
+10CA6; C; 10CE6; # OLD HUNGARIAN CAPITAL LETTER ET
+10CA7; C; 10CE7; # OLD HUNGARIAN CAPITAL LETTER ENT
+10CA8; C; 10CE8; # OLD HUNGARIAN CAPITAL LETTER ETY
+10CA9; C; 10CE9; # OLD HUNGARIAN CAPITAL LETTER ECH
+10CAA; C; 10CEA; # OLD HUNGARIAN CAPITAL LETTER U
+10CAB; C; 10CEB; # OLD HUNGARIAN CAPITAL LETTER UU
+10CAC; C; 10CEC; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE
+10CAD; C; 10CED; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE
+10CAE; C; 10CEE; # OLD HUNGARIAN CAPITAL LETTER EV
+10CAF; C; 10CEF; # OLD HUNGARIAN CAPITAL LETTER EZ
+10CB0; C; 10CF0; # OLD HUNGARIAN CAPITAL LETTER EZS
+10CB1; C; 10CF1; # OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN
+10CB2; C; 10CF2; # OLD HUNGARIAN CAPITAL LETTER US
+118A0; C; 118C0; # WARANG CITI CAPITAL LETTER NGAA
+118A1; C; 118C1; # WARANG CITI CAPITAL LETTER A
+118A2; C; 118C2; # WARANG CITI CAPITAL LETTER WI
+118A3; C; 118C3; # WARANG CITI CAPITAL LETTER YU
+118A4; C; 118C4; # WARANG CITI CAPITAL LETTER YA
+118A5; C; 118C5; # WARANG CITI CAPITAL LETTER YO
+118A6; C; 118C6; # WARANG CITI CAPITAL LETTER II
+118A7; C; 118C7; # WARANG CITI CAPITAL LETTER UU
+118A8; C; 118C8; # WARANG CITI CAPITAL LETTER E
+118A9; C; 118C9; # WARANG CITI CAPITAL LETTER O
+118AA; C; 118CA; # WARANG CITI CAPITAL LETTER ANG
+118AB; C; 118CB; # WARANG CITI CAPITAL LETTER GA
+118AC; C; 118CC; # WARANG CITI CAPITAL LETTER KO
+118AD; C; 118CD; # WARANG CITI CAPITAL LETTER ENY
+118AE; C; 118CE; # WARANG CITI CAPITAL LETTER YUJ
+118AF; C; 118CF; # WARANG CITI CAPITAL LETTER UC
+118B0; C; 118D0; # WARANG CITI CAPITAL LETTER ENN
+118B1; C; 118D1; # WARANG CITI CAPITAL LETTER ODD
+118B2; C; 118D2; # WARANG CITI CAPITAL LETTER TTE
+118B3; C; 118D3; # WARANG CITI CAPITAL LETTER NUNG
+118B4; C; 118D4; # WARANG CITI CAPITAL LETTER DA
+118B5; C; 118D5; # WARANG CITI CAPITAL LETTER AT
+118B6; C; 118D6; # WARANG CITI CAPITAL LETTER AM
+118B7; C; 118D7; # WARANG CITI CAPITAL LETTER BU
+118B8; C; 118D8; # WARANG CITI CAPITAL LETTER PU
+118B9; C; 118D9; # WARANG CITI CAPITAL LETTER HIYO
+118BA; C; 118DA; # WARANG CITI CAPITAL LETTER HOLO
+118BB; C; 118DB; # WARANG CITI CAPITAL LETTER HORR
+118BC; C; 118DC; # WARANG CITI CAPITAL LETTER HAR
+118BD; C; 118DD; # WARANG CITI CAPITAL LETTER SSUU
+118BE; C; 118DE; # WARANG CITI CAPITAL LETTER SII
+118BF; C; 118DF; # WARANG CITI CAPITAL LETTER VIYO
+16E40; C; 16E60; # MEDEFAIDRIN CAPITAL LETTER M
+16E41; C; 16E61; # MEDEFAIDRIN CAPITAL LETTER S
+16E42; C; 16E62; # MEDEFAIDRIN CAPITAL LETTER V
+16E43; C; 16E63; # MEDEFAIDRIN CAPITAL LETTER W
+16E44; C; 16E64; # MEDEFAIDRIN CAPITAL LETTER ATIU
+16E45; C; 16E65; # MEDEFAIDRIN CAPITAL LETTER Z
+16E46; C; 16E66; # MEDEFAIDRIN CAPITAL LETTER KP
+16E47; C; 16E67; # MEDEFAIDRIN CAPITAL LETTER P
+16E48; C; 16E68; # MEDEFAIDRIN CAPITAL LETTER T
+16E49; C; 16E69; # MEDEFAIDRIN CAPITAL LETTER G
+16E4A; C; 16E6A; # MEDEFAIDRIN CAPITAL LETTER F
+16E4B; C; 16E6B; # MEDEFAIDRIN CAPITAL LETTER I
+16E4C; C; 16E6C; # MEDEFAIDRIN CAPITAL LETTER K
+16E4D; C; 16E6D; # MEDEFAIDRIN CAPITAL LETTER A
+16E4E; C; 16E6E; # MEDEFAIDRIN CAPITAL LETTER J
+16E4F; C; 16E6F; # MEDEFAIDRIN CAPITAL LETTER E
+16E50; C; 16E70; # MEDEFAIDRIN CAPITAL LETTER B
+16E51; C; 16E71; # MEDEFAIDRIN CAPITAL LETTER C
+16E52; C; 16E72; # MEDEFAIDRIN CAPITAL LETTER U
+16E53; C; 16E73; # MEDEFAIDRIN CAPITAL LETTER YU
+16E54; C; 16E74; # MEDEFAIDRIN CAPITAL LETTER L
+16E55; C; 16E75; # MEDEFAIDRIN CAPITAL LETTER Q
+16E56; C; 16E76; # MEDEFAIDRIN CAPITAL LETTER HP
+16E57; C; 16E77; # MEDEFAIDRIN CAPITAL LETTER NY
+16E58; C; 16E78; # MEDEFAIDRIN CAPITAL LETTER X
+16E59; C; 16E79; # MEDEFAIDRIN CAPITAL LETTER D
+16E5A; C; 16E7A; # MEDEFAIDRIN CAPITAL LETTER OE
+16E5B; C; 16E7B; # MEDEFAIDRIN CAPITAL LETTER N
+16E5C; C; 16E7C; # MEDEFAIDRIN CAPITAL LETTER R
+16E5D; C; 16E7D; # MEDEFAIDRIN CAPITAL LETTER O
+16E5E; C; 16E7E; # MEDEFAIDRIN CAPITAL LETTER AI
+16E5F; C; 16E7F; # MEDEFAIDRIN CAPITAL LETTER Y
+1E900; C; 1E922; # ADLAM CAPITAL LETTER ALIF
+1E901; C; 1E923; # ADLAM CAPITAL LETTER DAALI
+1E902; C; 1E924; # ADLAM CAPITAL LETTER LAAM
+1E903; C; 1E925; # ADLAM CAPITAL LETTER MIIM
+1E904; C; 1E926; # ADLAM CAPITAL LETTER BA
+1E905; C; 1E927; # ADLAM CAPITAL LETTER SINNYIIYHE
+1E906; C; 1E928; # ADLAM CAPITAL LETTER PE
+1E907; C; 1E929; # ADLAM CAPITAL LETTER BHE
+1E908; C; 1E92A; # ADLAM CAPITAL LETTER RA
+1E909; C; 1E92B; # ADLAM CAPITAL LETTER E
+1E90A; C; 1E92C; # ADLAM CAPITAL LETTER FA
+1E90B; C; 1E92D; # ADLAM CAPITAL LETTER I
+1E90C; C; 1E92E; # ADLAM CAPITAL LETTER O
+1E90D; C; 1E92F; # ADLAM CAPITAL LETTER DHA
+1E90E; C; 1E930; # ADLAM CAPITAL LETTER YHE
+1E90F; C; 1E931; # ADLAM CAPITAL LETTER WAW
+1E910; C; 1E932; # ADLAM CAPITAL LETTER NUN
+1E911; C; 1E933; # ADLAM CAPITAL LETTER KAF
+1E912; C; 1E934; # ADLAM CAPITAL LETTER YA
+1E913; C; 1E935; # ADLAM CAPITAL LETTER U
+1E914; C; 1E936; # ADLAM CAPITAL LETTER JIIM
+1E915; C; 1E937; # ADLAM CAPITAL LETTER CHI
+1E916; C; 1E938; # ADLAM CAPITAL LETTER HA
+1E917; C; 1E939; # ADLAM CAPITAL LETTER QAAF
+1E918; C; 1E93A; # ADLAM CAPITAL LETTER GA
+1E919; C; 1E93B; # ADLAM CAPITAL LETTER NYA
+1E91A; C; 1E93C; # ADLAM CAPITAL LETTER TU
+1E91B; C; 1E93D; # ADLAM CAPITAL LETTER NHA
+1E91C; C; 1E93E; # ADLAM CAPITAL LETTER VA
+1E91D; C; 1E93F; # ADLAM CAPITAL LETTER KHA
+1E91E; C; 1E940; # ADLAM CAPITAL LETTER GBE
+1E91F; C; 1E941; # ADLAM CAPITAL LETTER ZAL
+1E920; C; 1E942; # ADLAM CAPITAL LETTER KPO
+1E921; C; 1E943; # ADLAM CAPITAL LETTER SHA
+#
+# EOF
diff --git a/pkgs/markdown/tool/common_mark_stats.json b/pkgs/markdown/tool/common_mark_stats.json
new file mode 100644
index 0000000..2e0ba8f
--- /dev/null
+++ b/pkgs/markdown/tool/common_mark_stats.json
@@ -0,0 +1,706 @@
+{
+ "ATX headings": {
+  "62": "strict",
+  "63": "strict",
+  "64": "strict",
+  "65": "strict",
+  "66": "strict",
+  "67": "strict",
+  "68": "strict",
+  "69": "strict",
+  "70": "strict",
+  "71": "strict",
+  "72": "strict",
+  "73": "strict",
+  "74": "strict",
+  "75": "strict",
+  "76": "strict",
+  "77": "strict",
+  "78": "strict",
+  "79": "strict"
+ },
+ "Autolinks": {
+  "594": "strict",
+  "595": "strict",
+  "596": "strict",
+  "597": "strict",
+  "598": "strict",
+  "599": "strict",
+  "600": "strict",
+  "601": "strict",
+  "602": "strict",
+  "603": "strict",
+  "604": "strict",
+  "605": "strict",
+  "606": "strict",
+  "607": "strict",
+  "608": "strict",
+  "609": "strict",
+  "610": "strict",
+  "611": "strict",
+  "612": "strict"
+ },
+ "Backslash escapes": {
+  "12": "strict",
+  "13": "strict",
+  "14": "strict",
+  "15": "strict",
+  "16": "strict",
+  "17": "strict",
+  "18": "strict",
+  "19": "strict",
+  "20": "strict",
+  "21": "strict",
+  "22": "strict",
+  "23": "strict",
+  "24": "strict"
+ },
+ "Blank lines": {
+  "227": "strict"
+ },
+ "Block quotes": {
+  "228": "strict",
+  "229": "strict",
+  "230": "strict",
+  "231": "strict",
+  "232": "strict",
+  "233": "strict",
+  "234": "strict",
+  "235": "strict",
+  "236": "strict",
+  "237": "strict",
+  "238": "strict",
+  "239": "strict",
+  "240": "strict",
+  "241": "strict",
+  "242": "strict",
+  "243": "strict",
+  "244": "strict",
+  "245": "strict",
+  "246": "strict",
+  "247": "strict",
+  "248": "strict",
+  "249": "strict",
+  "250": "strict",
+  "251": "strict",
+  "252": "strict"
+ },
+ "Code spans": {
+  "328": "strict",
+  "329": "strict",
+  "330": "strict",
+  "331": "strict",
+  "332": "strict",
+  "333": "strict",
+  "334": "strict",
+  "335": "strict",
+  "336": "strict",
+  "337": "strict",
+  "338": "strict",
+  "339": "strict",
+  "340": "strict",
+  "341": "strict",
+  "342": "strict",
+  "343": "strict",
+  "344": "strict",
+  "345": "strict",
+  "346": "strict",
+  "347": "strict",
+  "348": "strict",
+  "349": "strict"
+ },
+ "Emphasis and strong emphasis": {
+  "350": "strict",
+  "351": "strict",
+  "352": "strict",
+  "353": "strict",
+  "354": "fail",
+  "355": "strict",
+  "356": "strict",
+  "357": "strict",
+  "358": "strict",
+  "359": "strict",
+  "360": "strict",
+  "361": "strict",
+  "362": "strict",
+  "363": "strict",
+  "364": "strict",
+  "365": "strict",
+  "366": "strict",
+  "367": "strict",
+  "368": "strict",
+  "369": "strict",
+  "370": "strict",
+  "371": "strict",
+  "372": "strict",
+  "373": "strict",
+  "374": "strict",
+  "375": "strict",
+  "376": "strict",
+  "377": "strict",
+  "378": "strict",
+  "379": "strict",
+  "380": "strict",
+  "381": "strict",
+  "382": "strict",
+  "383": "strict",
+  "384": "strict",
+  "385": "strict",
+  "386": "strict",
+  "387": "strict",
+  "388": "strict",
+  "389": "strict",
+  "390": "strict",
+  "391": "strict",
+  "392": "strict",
+  "393": "strict",
+  "394": "strict",
+  "395": "strict",
+  "396": "strict",
+  "397": "strict",
+  "398": "strict",
+  "399": "strict",
+  "400": "strict",
+  "401": "strict",
+  "402": "strict",
+  "403": "strict",
+  "404": "strict",
+  "405": "strict",
+  "406": "strict",
+  "407": "strict",
+  "408": "strict",
+  "409": "strict",
+  "410": "strict",
+  "411": "strict",
+  "412": "strict",
+  "413": "strict",
+  "414": "strict",
+  "415": "strict",
+  "416": "strict",
+  "417": "strict",
+  "418": "strict",
+  "419": "strict",
+  "420": "strict",
+  "421": "strict",
+  "422": "strict",
+  "423": "strict",
+  "424": "strict",
+  "425": "strict",
+  "426": "strict",
+  "427": "strict",
+  "428": "strict",
+  "429": "strict",
+  "430": "strict",
+  "431": "strict",
+  "432": "strict",
+  "433": "strict",
+  "434": "strict",
+  "435": "strict",
+  "436": "strict",
+  "437": "strict",
+  "438": "strict",
+  "439": "strict",
+  "440": "strict",
+  "441": "strict",
+  "442": "strict",
+  "443": "strict",
+  "444": "strict",
+  "445": "strict",
+  "446": "strict",
+  "447": "strict",
+  "448": "strict",
+  "449": "strict",
+  "450": "strict",
+  "451": "strict",
+  "452": "strict",
+  "453": "strict",
+  "454": "strict",
+  "455": "strict",
+  "456": "strict",
+  "457": "strict",
+  "458": "strict",
+  "459": "strict",
+  "460": "strict",
+  "461": "strict",
+  "462": "strict",
+  "463": "strict",
+  "464": "strict",
+  "465": "strict",
+  "466": "strict",
+  "467": "strict",
+  "468": "strict",
+  "469": "strict",
+  "470": "strict",
+  "471": "strict",
+  "472": "strict",
+  "473": "strict",
+  "474": "strict",
+  "475": "strict",
+  "476": "strict",
+  "477": "strict",
+  "478": "strict",
+  "479": "strict",
+  "480": "strict",
+  "481": "strict"
+ },
+ "Entity and numeric character references": {
+  "25": "loose",
+  "26": "strict",
+  "27": "strict",
+  "28": "strict",
+  "29": "strict",
+  "30": "strict",
+  "31": "strict",
+  "32": "strict",
+  "33": "strict",
+  "34": "strict",
+  "35": "strict",
+  "36": "strict",
+  "37": "strict",
+  "38": "strict",
+  "39": "strict",
+  "40": "loose",
+  "41": "strict"
+ },
+ "Fenced code blocks": {
+  "119": "strict",
+  "120": "strict",
+  "121": "strict",
+  "122": "strict",
+  "123": "strict",
+  "124": "strict",
+  "125": "strict",
+  "126": "strict",
+  "127": "strict",
+  "128": "strict",
+  "129": "strict",
+  "130": "strict",
+  "131": "strict",
+  "132": "strict",
+  "133": "strict",
+  "134": "strict",
+  "135": "strict",
+  "136": "strict",
+  "137": "strict",
+  "138": "strict",
+  "139": "strict",
+  "140": "strict",
+  "141": "strict",
+  "142": "strict",
+  "143": "strict",
+  "144": "strict",
+  "145": "strict",
+  "146": "strict",
+  "147": "strict"
+ },
+ "Hard line breaks": {
+  "633": "strict",
+  "634": "strict",
+  "635": "strict",
+  "636": "strict",
+  "637": "strict",
+  "638": "strict",
+  "639": "strict",
+  "640": "strict",
+  "641": "strict",
+  "642": "strict",
+  "643": "strict",
+  "644": "strict",
+  "645": "strict",
+  "646": "strict",
+  "647": "strict"
+ },
+ "HTML blocks": {
+  "148": "strict",
+  "149": "strict",
+  "150": "strict",
+  "151": "strict",
+  "152": "strict",
+  "153": "strict",
+  "154": "strict",
+  "155": "strict",
+  "156": "strict",
+  "157": "strict",
+  "158": "strict",
+  "159": "strict",
+  "160": "strict",
+  "161": "strict",
+  "162": "strict",
+  "163": "strict",
+  "164": "strict",
+  "165": "strict",
+  "166": "strict",
+  "167": "strict",
+  "168": "strict",
+  "169": "strict",
+  "170": "strict",
+  "171": "strict",
+  "172": "strict",
+  "173": "strict",
+  "174": "strict",
+  "175": "strict",
+  "176": "strict",
+  "177": "strict",
+  "178": "strict",
+  "179": "strict",
+  "180": "strict",
+  "181": "strict",
+  "182": "strict",
+  "183": "strict",
+  "184": "strict",
+  "185": "strict",
+  "186": "strict",
+  "187": "strict",
+  "188": "strict",
+  "189": "strict",
+  "190": "strict",
+  "191": "strict"
+ },
+ "Images": {
+  "572": "strict",
+  "573": "strict",
+  "574": "strict",
+  "575": "strict",
+  "576": "strict",
+  "577": "strict",
+  "578": "strict",
+  "579": "strict",
+  "580": "strict",
+  "581": "strict",
+  "582": "strict",
+  "583": "strict",
+  "584": "strict",
+  "585": "strict",
+  "586": "strict",
+  "587": "strict",
+  "588": "strict",
+  "589": "strict",
+  "590": "strict",
+  "591": "strict",
+  "592": "strict",
+  "593": "strict"
+ },
+ "Indented code blocks": {
+  "107": "strict",
+  "108": "strict",
+  "109": "strict",
+  "110": "strict",
+  "111": "strict",
+  "112": "strict",
+  "113": "strict",
+  "114": "strict",
+  "115": "strict",
+  "116": "strict",
+  "117": "strict",
+  "118": "strict"
+ },
+ "Inlines": {
+  "327": "strict"
+ },
+ "Link reference definitions": {
+  "192": "strict",
+  "193": "strict",
+  "194": "strict",
+  "195": "strict",
+  "196": "strict",
+  "197": "strict",
+  "198": "strict",
+  "199": "strict",
+  "200": "strict",
+  "201": "strict",
+  "202": "strict",
+  "203": "strict",
+  "204": "strict",
+  "205": "strict",
+  "206": "strict",
+  "207": "loose",
+  "208": "strict",
+  "209": "strict",
+  "210": "strict",
+  "211": "strict",
+  "212": "strict",
+  "213": "strict",
+  "214": "strict",
+  "215": "strict",
+  "216": "strict",
+  "217": "strict",
+  "218": "strict"
+ },
+ "Links": {
+  "482": "strict",
+  "483": "strict",
+  "484": "strict",
+  "485": "strict",
+  "486": "strict",
+  "487": "strict",
+  "488": "strict",
+  "489": "strict",
+  "490": "strict",
+  "491": "strict",
+  "492": "strict",
+  "493": "strict",
+  "494": "strict",
+  "495": "strict",
+  "496": "strict",
+  "497": "strict",
+  "498": "strict",
+  "499": "strict",
+  "500": "strict",
+  "501": "strict",
+  "502": "strict",
+  "503": "strict",
+  "504": "strict",
+  "505": "strict",
+  "506": "strict",
+  "507": "strict",
+  "508": "strict",
+  "509": "strict",
+  "510": "strict",
+  "511": "strict",
+  "512": "strict",
+  "513": "strict",
+  "514": "strict",
+  "515": "strict",
+  "516": "strict",
+  "517": "strict",
+  "518": "strict",
+  "519": "strict",
+  "520": "strict",
+  "521": "strict",
+  "522": "strict",
+  "523": "strict",
+  "524": "strict",
+  "525": "strict",
+  "526": "strict",
+  "527": "strict",
+  "528": "strict",
+  "529": "strict",
+  "530": "strict",
+  "531": "strict",
+  "532": "strict",
+  "533": "strict",
+  "534": "strict",
+  "535": "strict",
+  "536": "strict",
+  "537": "strict",
+  "538": "strict",
+  "539": "strict",
+  "540": "strict",
+  "541": "strict",
+  "542": "strict",
+  "543": "strict",
+  "544": "strict",
+  "545": "strict",
+  "546": "strict",
+  "547": "strict",
+  "548": "strict",
+  "549": "strict",
+  "550": "strict",
+  "551": "strict",
+  "552": "strict",
+  "553": "strict",
+  "554": "strict",
+  "555": "strict",
+  "556": "strict",
+  "557": "strict",
+  "558": "strict",
+  "559": "strict",
+  "560": "strict",
+  "561": "strict",
+  "562": "strict",
+  "563": "strict",
+  "564": "strict",
+  "565": "strict",
+  "566": "strict",
+  "567": "strict",
+  "568": "strict",
+  "569": "strict",
+  "570": "strict",
+  "571": "strict"
+ },
+ "List items": {
+  "253": "strict",
+  "254": "strict",
+  "255": "strict",
+  "256": "strict",
+  "257": "strict",
+  "258": "strict",
+  "259": "strict",
+  "260": "strict",
+  "261": "strict",
+  "262": "strict",
+  "263": "strict",
+  "264": "strict",
+  "265": "strict",
+  "266": "strict",
+  "267": "strict",
+  "268": "strict",
+  "269": "strict",
+  "270": "strict",
+  "271": "strict",
+  "272": "strict",
+  "273": "strict",
+  "274": "strict",
+  "275": "strict",
+  "276": "strict",
+  "277": "strict",
+  "278": "strict",
+  "279": "strict",
+  "280": "strict",
+  "281": "strict",
+  "282": "strict",
+  "283": "strict",
+  "284": "strict",
+  "285": "strict",
+  "286": "strict",
+  "287": "strict",
+  "288": "strict",
+  "289": "strict",
+  "290": "strict",
+  "291": "strict",
+  "292": "strict",
+  "293": "strict",
+  "294": "strict",
+  "295": "strict",
+  "296": "strict",
+  "297": "strict",
+  "298": "strict",
+  "299": "strict",
+  "300": "strict"
+ },
+ "Lists": {
+  "301": "strict",
+  "302": "strict",
+  "303": "strict",
+  "304": "strict",
+  "305": "strict",
+  "306": "strict",
+  "307": "strict",
+  "308": "strict",
+  "309": "strict",
+  "310": "strict",
+  "311": "strict",
+  "312": "strict",
+  "313": "strict",
+  "314": "strict",
+  "315": "strict",
+  "316": "strict",
+  "317": "strict",
+  "318": "strict",
+  "319": "strict",
+  "320": "strict",
+  "321": "strict",
+  "322": "strict",
+  "323": "strict",
+  "324": "strict",
+  "325": "strict",
+  "326": "strict"
+ },
+ "Paragraphs": {
+  "219": "strict",
+  "220": "strict",
+  "221": "strict",
+  "222": "strict",
+  "223": "strict",
+  "224": "strict",
+  "225": "strict",
+  "226": "strict"
+ },
+ "Precedence": {
+  "42": "strict"
+ },
+ "Raw HTML": {
+  "613": "strict",
+  "614": "strict",
+  "615": "strict",
+  "616": "strict",
+  "617": "strict",
+  "618": "strict",
+  "619": "strict",
+  "620": "strict",
+  "621": "strict",
+  "622": "strict",
+  "623": "strict",
+  "624": "strict",
+  "625": "loose",
+  "626": "loose",
+  "627": "strict",
+  "628": "strict",
+  "629": "strict",
+  "630": "strict",
+  "631": "strict",
+  "632": "strict"
+ },
+ "Setext headings": {
+  "80": "strict",
+  "81": "strict",
+  "82": "loose",
+  "83": "strict",
+  "84": "loose",
+  "85": "strict",
+  "86": "strict",
+  "87": "strict",
+  "88": "strict",
+  "89": "strict",
+  "90": "strict",
+  "91": "strict",
+  "92": "strict",
+  "93": "strict",
+  "94": "strict",
+  "95": "strict",
+  "96": "strict",
+  "97": "strict",
+  "98": "strict",
+  "99": "strict",
+  "100": "strict",
+  "101": "strict",
+  "102": "strict",
+  "103": "strict",
+  "104": "strict",
+  "105": "strict",
+  "106": "strict"
+ },
+ "Soft line breaks": {
+  "648": "strict",
+  "649": "strict"
+ },
+ "Tabs": {
+  "1": "strict",
+  "2": "strict",
+  "3": "strict",
+  "4": "strict",
+  "5": "strict",
+  "6": "loose",
+  "7": "strict",
+  "8": "strict",
+  "9": "strict",
+  "10": "strict",
+  "11": "strict"
+ },
+ "Textual content": {
+  "650": "strict",
+  "651": "strict",
+  "652": "strict"
+ },
+ "Thematic breaks": {
+  "43": "strict",
+  "44": "strict",
+  "45": "strict",
+  "46": "strict",
+  "47": "strict",
+  "48": "strict",
+  "49": "strict",
+  "50": "strict",
+  "51": "strict",
+  "52": "strict",
+  "53": "strict",
+  "54": "strict",
+  "55": "strict",
+  "56": "strict",
+  "57": "strict",
+  "58": "strict",
+  "59": "strict",
+  "60": "strict",
+  "61": "strict"
+ }
+}
diff --git a/pkgs/markdown/tool/common_mark_stats.txt b/pkgs/markdown/tool/common_mark_stats.txt
new file mode 100644
index 0000000..db3b891
--- /dev/null
+++ b/pkgs/markdown/tool/common_mark_stats.txt
@@ -0,0 +1,28 @@
+  18 of   18 – 100.0%  ATX headings
+  19 of   19 – 100.0%  Autolinks
+  13 of   13 – 100.0%  Backslash escapes
+   1 of    1 – 100.0%  Blank lines
+  25 of   25 – 100.0%  Block quotes
+  22 of   22 – 100.0%  Code spans
+ 131 of  132 –  99.2%  Emphasis and strong emphasis
+  17 of   17 – 100.0%  Entity and numeric character references
+  29 of   29 – 100.0%  Fenced code blocks
+  15 of   15 – 100.0%  Hard line breaks
+  44 of   44 – 100.0%  HTML blocks
+  22 of   22 – 100.0%  Images
+  12 of   12 – 100.0%  Indented code blocks
+   1 of    1 – 100.0%  Inlines
+  27 of   27 – 100.0%  Link reference definitions
+  90 of   90 – 100.0%  Links
+  48 of   48 – 100.0%  List items
+  26 of   26 – 100.0%  Lists
+   8 of    8 – 100.0%  Paragraphs
+   1 of    1 – 100.0%  Precedence
+  20 of   20 – 100.0%  Raw HTML
+  27 of   27 – 100.0%  Setext headings
+   2 of    2 – 100.0%  Soft line breaks
+  11 of   11 – 100.0%  Tabs
+   3 of    3 – 100.0%  Textual content
+  19 of   19 – 100.0%  Thematic breaks
+ 651 of  652 –  99.8%  TOTAL
+ 643 of  651 –  98.8%  TOTAL Strict
diff --git a/pkgs/markdown/tool/common_mark_tests.json b/pkgs/markdown/tool/common_mark_tests.json
new file mode 100644
index 0000000..1f89e66
--- /dev/null
+++ b/pkgs/markdown/tool/common_mark_tests.json
@@ -0,0 +1,5218 @@
+[
+  {
+    "markdown": "\tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 1,
+    "start_line": 355,
+    "end_line": 360,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "  \tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 2,
+    "start_line": 362,
+    "end_line": 367,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "    a\ta\n    ὐ\ta\n",
+    "html": "<pre><code>a\ta\nὐ\ta\n</code></pre>\n",
+    "example": 3,
+    "start_line": 369,
+    "end_line": 376,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "  - foo\n\n\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 4,
+    "start_line": 382,
+    "end_line": 393,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "- foo\n\n\t\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>  bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 5,
+    "start_line": 395,
+    "end_line": 407,
+    "section": "Tabs"
+  },
+  {
+    "markdown": ">\t\tfoo\n",
+    "html": "<blockquote>\n<pre><code>  foo\n</code></pre>\n</blockquote>\n",
+    "example": 6,
+    "start_line": 418,
+    "end_line": 425,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "-\t\tfoo\n",
+    "html": "<ul>\n<li>\n<pre><code>  foo\n</code></pre>\n</li>\n</ul>\n",
+    "example": 7,
+    "start_line": 427,
+    "end_line": 436,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "    foo\n\tbar\n",
+    "html": "<pre><code>foo\nbar\n</code></pre>\n",
+    "example": 8,
+    "start_line": 439,
+    "end_line": 446,
+    "section": "Tabs"
+  },
+  {
+    "markdown": " - foo\n   - bar\n\t - baz\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 9,
+    "start_line": 448,
+    "end_line": 464,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "#\tFoo\n",
+    "html": "<h1>Foo</h1>\n",
+    "example": 10,
+    "start_line": 466,
+    "end_line": 470,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "*\t*\t*\t\n",
+    "html": "<hr />\n",
+    "example": 11,
+    "start_line": 472,
+    "end_line": 476,
+    "section": "Tabs"
+  },
+  {
+    "markdown": "\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n",
+    "html": "<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~</p>\n",
+    "example": 12,
+    "start_line": 489,
+    "end_line": 493,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "\\\t\\A\\a\\ \\3\\φ\\«\n",
+    "html": "<p>\\\t\\A\\a\\ \\3\\φ\\«</p>\n",
+    "example": 13,
+    "start_line": 499,
+    "end_line": 503,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "\\*not emphasized*\n\\<br/> not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url \"not a reference\"\n\\&ouml; not a character entity\n",
+    "html": "<p>*not emphasized*\n&lt;br/&gt; not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url &quot;not a reference&quot;\n&amp;ouml; not a character entity</p>\n",
+    "example": 14,
+    "start_line": 509,
+    "end_line": 529,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "\\\\*emphasis*\n",
+    "html": "<p>\\<em>emphasis</em></p>\n",
+    "example": 15,
+    "start_line": 534,
+    "end_line": 538,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "foo\\\nbar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 16,
+    "start_line": 543,
+    "end_line": 549,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "`` \\[\\` ``\n",
+    "html": "<p><code>\\[\\`</code></p>\n",
+    "example": 17,
+    "start_line": 555,
+    "end_line": 559,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "    \\[\\]\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 18,
+    "start_line": 562,
+    "end_line": 567,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "~~~\n\\[\\]\n~~~\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 19,
+    "start_line": 570,
+    "end_line": 577,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "<https://example.com?find=\\*>\n",
+    "html": "<p><a href=\"https://example.com?find=%5C*\">https://example.com?find=\\*</a></p>\n",
+    "example": 20,
+    "start_line": 580,
+    "end_line": 584,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "<a href=\"/bar\\/)\">\n",
+    "html": "<a href=\"/bar\\/)\">\n",
+    "example": 21,
+    "start_line": 587,
+    "end_line": 591,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "[foo](/bar\\* \"ti\\*tle\")\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 22,
+    "start_line": 597,
+    "end_line": 601,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /bar\\* \"ti\\*tle\"\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 23,
+    "start_line": 604,
+    "end_line": 610,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "``` foo\\+bar\nfoo\n```\n",
+    "html": "<pre><code class=\"language-foo+bar\">foo\n</code></pre>\n",
+    "example": 24,
+    "start_line": 613,
+    "end_line": 620,
+    "section": "Backslash escapes"
+  },
+  {
+    "markdown": "&nbsp; &amp; &copy; &AElig; &Dcaron;\n&frac34; &HilbertSpace; &DifferentialD;\n&ClockwiseContourIntegral; &ngE;\n",
+    "html": "<p>  &amp; © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸</p>\n",
+    "example": 25,
+    "start_line": 649,
+    "end_line": 657,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&#35; &#1234; &#992; &#0;\n",
+    "html": "<p># Ӓ Ϡ �</p>\n",
+    "example": 26,
+    "start_line": 668,
+    "end_line": 672,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&#X22; &#XD06; &#xcab;\n",
+    "html": "<p>&quot; ആ ಫ</p>\n",
+    "example": 27,
+    "start_line": 681,
+    "end_line": 685,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&nbsp &x; &#; &#x;\n&#87654321;\n&#abcdef0;\n&ThisIsNotDefined; &hi?;\n",
+    "html": "<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;\n&amp;#87654321;\n&amp;#abcdef0;\n&amp;ThisIsNotDefined; &amp;hi?;</p>\n",
+    "example": 28,
+    "start_line": 690,
+    "end_line": 700,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&copy\n",
+    "html": "<p>&amp;copy</p>\n",
+    "example": 29,
+    "start_line": 707,
+    "end_line": 711,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&MadeUpEntity;\n",
+    "html": "<p>&amp;MadeUpEntity;</p>\n",
+    "example": 30,
+    "start_line": 717,
+    "end_line": 721,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "<a href=\"&ouml;&ouml;.html\">\n",
+    "html": "<a href=\"&ouml;&ouml;.html\">\n",
+    "example": 31,
+    "start_line": 728,
+    "end_line": 732,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "[foo](/f&ouml;&ouml; \"f&ouml;&ouml;\")\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"föö\">foo</a></p>\n",
+    "example": 32,
+    "start_line": 735,
+    "end_line": 739,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /f&ouml;&ouml; \"f&ouml;&ouml;\"\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"föö\">foo</a></p>\n",
+    "example": 33,
+    "start_line": 742,
+    "end_line": 748,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "``` f&ouml;&ouml;\nfoo\n```\n",
+    "html": "<pre><code class=\"language-föö\">foo\n</code></pre>\n",
+    "example": 34,
+    "start_line": 751,
+    "end_line": 758,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "`f&ouml;&ouml;`\n",
+    "html": "<p><code>f&amp;ouml;&amp;ouml;</code></p>\n",
+    "example": 35,
+    "start_line": 764,
+    "end_line": 768,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "    f&ouml;f&ouml;\n",
+    "html": "<pre><code>f&amp;ouml;f&amp;ouml;\n</code></pre>\n",
+    "example": 36,
+    "start_line": 771,
+    "end_line": 776,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&#42;foo&#42;\n*foo*\n",
+    "html": "<p>*foo*\n<em>foo</em></p>\n",
+    "example": 37,
+    "start_line": 783,
+    "end_line": 789,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&#42; foo\n\n* foo\n",
+    "html": "<p>* foo</p>\n<ul>\n<li>foo</li>\n</ul>\n",
+    "example": 38,
+    "start_line": 791,
+    "end_line": 800,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "foo&#10;&#10;bar\n",
+    "html": "<p>foo\n\nbar</p>\n",
+    "example": 39,
+    "start_line": 802,
+    "end_line": 808,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "&#9;foo\n",
+    "html": "<p>\tfoo</p>\n",
+    "example": 40,
+    "start_line": 810,
+    "end_line": 814,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "[a](url &quot;tit&quot;)\n",
+    "html": "<p>[a](url &quot;tit&quot;)</p>\n",
+    "example": 41,
+    "start_line": 817,
+    "end_line": 821,
+    "section": "Entity and numeric character references"
+  },
+  {
+    "markdown": "- `one\n- two`\n",
+    "html": "<ul>\n<li>`one</li>\n<li>two`</li>\n</ul>\n",
+    "example": 42,
+    "start_line": 840,
+    "end_line": 848,
+    "section": "Precedence"
+  },
+  {
+    "markdown": "***\n---\n___\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 43,
+    "start_line": 879,
+    "end_line": 887,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "+++\n",
+    "html": "<p>+++</p>\n",
+    "example": 44,
+    "start_line": 892,
+    "end_line": 896,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "===\n",
+    "html": "<p>===</p>\n",
+    "example": 45,
+    "start_line": 899,
+    "end_line": 903,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "--\n**\n__\n",
+    "html": "<p>--\n**\n__</p>\n",
+    "example": 46,
+    "start_line": 908,
+    "end_line": 916,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": " ***\n  ***\n   ***\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 47,
+    "start_line": 921,
+    "end_line": 929,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "    ***\n",
+    "html": "<pre><code>***\n</code></pre>\n",
+    "example": 48,
+    "start_line": 934,
+    "end_line": 939,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "Foo\n    ***\n",
+    "html": "<p>Foo\n***</p>\n",
+    "example": 49,
+    "start_line": 942,
+    "end_line": 948,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "_____________________________________\n",
+    "html": "<hr />\n",
+    "example": 50,
+    "start_line": 953,
+    "end_line": 957,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": " - - -\n",
+    "html": "<hr />\n",
+    "example": 51,
+    "start_line": 962,
+    "end_line": 966,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": " **  * ** * ** * **\n",
+    "html": "<hr />\n",
+    "example": 52,
+    "start_line": 969,
+    "end_line": 973,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "-     -      -      -\n",
+    "html": "<hr />\n",
+    "example": 53,
+    "start_line": 976,
+    "end_line": 980,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "- - - -    \n",
+    "html": "<hr />\n",
+    "example": 54,
+    "start_line": 985,
+    "end_line": 989,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "_ _ _ _ a\n\na------\n\n---a---\n",
+    "html": "<p>_ _ _ _ a</p>\n<p>a------</p>\n<p>---a---</p>\n",
+    "example": 55,
+    "start_line": 994,
+    "end_line": 1004,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": " *-*\n",
+    "html": "<p><em>-</em></p>\n",
+    "example": 56,
+    "start_line": 1010,
+    "end_line": 1014,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "- foo\n***\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 57,
+    "start_line": 1019,
+    "end_line": 1031,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "Foo\n***\nbar\n",
+    "html": "<p>Foo</p>\n<hr />\n<p>bar</p>\n",
+    "example": 58,
+    "start_line": 1036,
+    "end_line": 1044,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "Foo\n---\nbar\n",
+    "html": "<h2>Foo</h2>\n<p>bar</p>\n",
+    "example": 59,
+    "start_line": 1053,
+    "end_line": 1060,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "* Foo\n* * *\n* Bar\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n<ul>\n<li>Bar</li>\n</ul>\n",
+    "example": 60,
+    "start_line": 1066,
+    "end_line": 1078,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "- Foo\n- * * *\n",
+    "html": "<ul>\n<li>Foo</li>\n<li>\n<hr />\n</li>\n</ul>\n",
+    "example": 61,
+    "start_line": 1083,
+    "end_line": 1093,
+    "section": "Thematic breaks"
+  },
+  {
+    "markdown": "# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n",
+    "html": "<h1>foo</h1>\n<h2>foo</h2>\n<h3>foo</h3>\n<h4>foo</h4>\n<h5>foo</h5>\n<h6>foo</h6>\n",
+    "example": 62,
+    "start_line": 1112,
+    "end_line": 1126,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "####### foo\n",
+    "html": "<p>####### foo</p>\n",
+    "example": 63,
+    "start_line": 1131,
+    "end_line": 1135,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "#5 bolt\n\n#hashtag\n",
+    "html": "<p>#5 bolt</p>\n<p>#hashtag</p>\n",
+    "example": 64,
+    "start_line": 1146,
+    "end_line": 1153,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "\\## foo\n",
+    "html": "<p>## foo</p>\n",
+    "example": 65,
+    "start_line": 1158,
+    "end_line": 1162,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "# foo *bar* \\*baz\\*\n",
+    "html": "<h1>foo <em>bar</em> *baz*</h1>\n",
+    "example": 66,
+    "start_line": 1167,
+    "end_line": 1171,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "#                  foo                     \n",
+    "html": "<h1>foo</h1>\n",
+    "example": 67,
+    "start_line": 1176,
+    "end_line": 1180,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": " ### foo\n  ## foo\n   # foo\n",
+    "html": "<h3>foo</h3>\n<h2>foo</h2>\n<h1>foo</h1>\n",
+    "example": 68,
+    "start_line": 1185,
+    "end_line": 1193,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "    # foo\n",
+    "html": "<pre><code># foo\n</code></pre>\n",
+    "example": 69,
+    "start_line": 1198,
+    "end_line": 1203,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "foo\n    # bar\n",
+    "html": "<p>foo\n# bar</p>\n",
+    "example": 70,
+    "start_line": 1206,
+    "end_line": 1212,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "## foo ##\n  ###   bar    ###\n",
+    "html": "<h2>foo</h2>\n<h3>bar</h3>\n",
+    "example": 71,
+    "start_line": 1217,
+    "end_line": 1223,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "# foo ##################################\n##### foo ##\n",
+    "html": "<h1>foo</h1>\n<h5>foo</h5>\n",
+    "example": 72,
+    "start_line": 1228,
+    "end_line": 1234,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "### foo ###     \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 73,
+    "start_line": 1239,
+    "end_line": 1243,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "### foo ### b\n",
+    "html": "<h3>foo ### b</h3>\n",
+    "example": 74,
+    "start_line": 1250,
+    "end_line": 1254,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "# foo#\n",
+    "html": "<h1>foo#</h1>\n",
+    "example": 75,
+    "start_line": 1259,
+    "end_line": 1263,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "### foo \\###\n## foo #\\##\n# foo \\#\n",
+    "html": "<h3>foo ###</h3>\n<h2>foo ###</h2>\n<h1>foo #</h1>\n",
+    "example": 76,
+    "start_line": 1269,
+    "end_line": 1277,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "****\n## foo\n****\n",
+    "html": "<hr />\n<h2>foo</h2>\n<hr />\n",
+    "example": 77,
+    "start_line": 1283,
+    "end_line": 1291,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "Foo bar\n# baz\nBar foo\n",
+    "html": "<p>Foo bar</p>\n<h1>baz</h1>\n<p>Bar foo</p>\n",
+    "example": 78,
+    "start_line": 1294,
+    "end_line": 1302,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "## \n#\n### ###\n",
+    "html": "<h2></h2>\n<h1></h1>\n<h3></h3>\n",
+    "example": 79,
+    "start_line": 1307,
+    "end_line": 1315,
+    "section": "ATX headings"
+  },
+  {
+    "markdown": "Foo *bar*\n=========\n\nFoo *bar*\n---------\n",
+    "html": "<h1>Foo <em>bar</em></h1>\n<h2>Foo <em>bar</em></h2>\n",
+    "example": 80,
+    "start_line": 1347,
+    "end_line": 1356,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo *bar\nbaz*\n====\n",
+    "html": "<h1>Foo <em>bar\nbaz</em></h1>\n",
+    "example": 81,
+    "start_line": 1361,
+    "end_line": 1368,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "  Foo *bar\nbaz*\t\n====\n",
+    "html": "<h1>Foo <em>bar\nbaz</em></h1>\n",
+    "example": 82,
+    "start_line": 1375,
+    "end_line": 1382,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\n-------------------------\n\nFoo\n=\n",
+    "html": "<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 83,
+    "start_line": 1387,
+    "end_line": 1396,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "   Foo\n---\n\n  Foo\n-----\n\n  Foo\n  ===\n",
+    "html": "<h2>Foo</h2>\n<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 84,
+    "start_line": 1402,
+    "end_line": 1415,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "    Foo\n    ---\n\n    Foo\n---\n",
+    "html": "<pre><code>Foo\n---\n\nFoo\n</code></pre>\n<hr />\n",
+    "example": 85,
+    "start_line": 1420,
+    "end_line": 1433,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\n   ----      \n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 86,
+    "start_line": 1439,
+    "end_line": 1444,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\n    ---\n",
+    "html": "<p>Foo\n---</p>\n",
+    "example": 87,
+    "start_line": 1449,
+    "end_line": 1455,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\n= =\n\nFoo\n--- -\n",
+    "html": "<p>Foo\n= =</p>\n<p>Foo</p>\n<hr />\n",
+    "example": 88,
+    "start_line": 1460,
+    "end_line": 1471,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo  \n-----\n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 89,
+    "start_line": 1476,
+    "end_line": 1481,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\\\n----\n",
+    "html": "<h2>Foo\\</h2>\n",
+    "example": 90,
+    "start_line": 1486,
+    "end_line": 1491,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "`Foo\n----\n`\n\n<a title=\"a lot\n---\nof dashes\"/>\n",
+    "html": "<h2>`Foo</h2>\n<p>`</p>\n<h2>&lt;a title=&quot;a lot</h2>\n<p>of dashes&quot;/&gt;</p>\n",
+    "example": 91,
+    "start_line": 1497,
+    "end_line": 1510,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "> Foo\n---\n",
+    "html": "<blockquote>\n<p>Foo</p>\n</blockquote>\n<hr />\n",
+    "example": 92,
+    "start_line": 1516,
+    "end_line": 1524,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "> foo\nbar\n===\n",
+    "html": "<blockquote>\n<p>foo\nbar\n===</p>\n</blockquote>\n",
+    "example": 93,
+    "start_line": 1527,
+    "end_line": 1537,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "- Foo\n---\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n",
+    "example": 94,
+    "start_line": 1540,
+    "end_line": 1548,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\nBar\n---\n",
+    "html": "<h2>Foo\nBar</h2>\n",
+    "example": 95,
+    "start_line": 1555,
+    "end_line": 1562,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "---\nFoo\n---\nBar\n---\nBaz\n",
+    "html": "<hr />\n<h2>Foo</h2>\n<h2>Bar</h2>\n<p>Baz</p>\n",
+    "example": 96,
+    "start_line": 1568,
+    "end_line": 1580,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "\n====\n",
+    "html": "<p>====</p>\n",
+    "example": 97,
+    "start_line": 1585,
+    "end_line": 1590,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "---\n---\n",
+    "html": "<hr />\n<hr />\n",
+    "example": 98,
+    "start_line": 1597,
+    "end_line": 1603,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "- foo\n-----\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n",
+    "example": 99,
+    "start_line": 1606,
+    "end_line": 1614,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "    foo\n---\n",
+    "html": "<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 100,
+    "start_line": 1617,
+    "end_line": 1624,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "> foo\n-----\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 101,
+    "start_line": 1627,
+    "end_line": 1635,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "\\> foo\n------\n",
+    "html": "<h2>&gt; foo</h2>\n",
+    "example": 102,
+    "start_line": 1641,
+    "end_line": 1646,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\n\nbar\n---\nbaz\n",
+    "html": "<p>Foo</p>\n<h2>bar</h2>\n<p>baz</p>\n",
+    "example": 103,
+    "start_line": 1672,
+    "end_line": 1682,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\nbar\n\n---\n\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 104,
+    "start_line": 1688,
+    "end_line": 1700,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\nbar\n* * *\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 105,
+    "start_line": 1706,
+    "end_line": 1716,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "Foo\nbar\n\\---\nbaz\n",
+    "html": "<p>Foo\nbar\n---\nbaz</p>\n",
+    "example": 106,
+    "start_line": 1721,
+    "end_line": 1731,
+    "section": "Setext headings"
+  },
+  {
+    "markdown": "    a simple\n      indented code block\n",
+    "html": "<pre><code>a simple\n  indented code block\n</code></pre>\n",
+    "example": 107,
+    "start_line": 1749,
+    "end_line": 1756,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "  - foo\n\n    bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 108,
+    "start_line": 1763,
+    "end_line": 1774,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "1.  foo\n\n    - bar\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 109,
+    "start_line": 1777,
+    "end_line": 1790,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "    <a/>\n    *hi*\n\n    - one\n",
+    "html": "<pre><code>&lt;a/&gt;\n*hi*\n\n- one\n</code></pre>\n",
+    "example": 110,
+    "start_line": 1797,
+    "end_line": 1808,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "    chunk1\n\n    chunk2\n  \n \n \n    chunk3\n",
+    "html": "<pre><code>chunk1\n\nchunk2\n\n\n\nchunk3\n</code></pre>\n",
+    "example": 111,
+    "start_line": 1813,
+    "end_line": 1830,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "    chunk1\n      \n      chunk2\n",
+    "html": "<pre><code>chunk1\n  \n  chunk2\n</code></pre>\n",
+    "example": 112,
+    "start_line": 1836,
+    "end_line": 1845,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "Foo\n    bar\n\n",
+    "html": "<p>Foo\nbar</p>\n",
+    "example": 113,
+    "start_line": 1851,
+    "end_line": 1858,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "    foo\nbar\n",
+    "html": "<pre><code>foo\n</code></pre>\n<p>bar</p>\n",
+    "example": 114,
+    "start_line": 1865,
+    "end_line": 1872,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "# Heading\n    foo\nHeading\n------\n    foo\n----\n",
+    "html": "<h1>Heading</h1>\n<pre><code>foo\n</code></pre>\n<h2>Heading</h2>\n<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 115,
+    "start_line": 1878,
+    "end_line": 1893,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "        foo\n    bar\n",
+    "html": "<pre><code>    foo\nbar\n</code></pre>\n",
+    "example": 116,
+    "start_line": 1898,
+    "end_line": 1905,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "\n    \n    foo\n    \n\n",
+    "html": "<pre><code>foo\n</code></pre>\n",
+    "example": 117,
+    "start_line": 1911,
+    "end_line": 1920,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "    foo  \n",
+    "html": "<pre><code>foo  \n</code></pre>\n",
+    "example": 118,
+    "start_line": 1925,
+    "end_line": 1930,
+    "section": "Indented code blocks"
+  },
+  {
+    "markdown": "```\n<\n >\n```\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 119,
+    "start_line": 1980,
+    "end_line": 1989,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~\n<\n >\n~~~\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 120,
+    "start_line": 1994,
+    "end_line": 2003,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "``\nfoo\n``\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 121,
+    "start_line": 2007,
+    "end_line": 2013,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\naaa\n~~~\n```\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 122,
+    "start_line": 2018,
+    "end_line": 2027,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~\naaa\n```\n~~~\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 123,
+    "start_line": 2030,
+    "end_line": 2039,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "````\naaa\n```\n``````\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 124,
+    "start_line": 2044,
+    "end_line": 2053,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~~\naaa\n~~~\n~~~~\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 125,
+    "start_line": 2056,
+    "end_line": 2065,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 126,
+    "start_line": 2071,
+    "end_line": 2075,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "`````\n\n```\naaa\n",
+    "html": "<pre><code>\n```\naaa\n</code></pre>\n",
+    "example": 127,
+    "start_line": 2078,
+    "end_line": 2088,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "> ```\n> aaa\n\nbbb\n",
+    "html": "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>\n",
+    "example": 128,
+    "start_line": 2091,
+    "end_line": 2102,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\n\n  \n```\n",
+    "html": "<pre><code>\n  \n</code></pre>\n",
+    "example": 129,
+    "start_line": 2107,
+    "end_line": 2116,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\n```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 130,
+    "start_line": 2121,
+    "end_line": 2126,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": " ```\n aaa\naaa\n```\n",
+    "html": "<pre><code>aaa\naaa\n</code></pre>\n",
+    "example": 131,
+    "start_line": 2133,
+    "end_line": 2142,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "  ```\naaa\n  aaa\naaa\n  ```\n",
+    "html": "<pre><code>aaa\naaa\naaa\n</code></pre>\n",
+    "example": 132,
+    "start_line": 2145,
+    "end_line": 2156,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "   ```\n   aaa\n    aaa\n  aaa\n   ```\n",
+    "html": "<pre><code>aaa\n aaa\naaa\n</code></pre>\n",
+    "example": 133,
+    "start_line": 2159,
+    "end_line": 2170,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "    ```\n    aaa\n    ```\n",
+    "html": "<pre><code>```\naaa\n```\n</code></pre>\n",
+    "example": 134,
+    "start_line": 2175,
+    "end_line": 2184,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 135,
+    "start_line": 2190,
+    "end_line": 2197,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "   ```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 136,
+    "start_line": 2200,
+    "end_line": 2207,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\naaa\n    ```\n",
+    "html": "<pre><code>aaa\n    ```\n</code></pre>\n",
+    "example": 137,
+    "start_line": 2212,
+    "end_line": 2220,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "``` ```\naaa\n",
+    "html": "<p><code> </code>\naaa</p>\n",
+    "example": 138,
+    "start_line": 2226,
+    "end_line": 2232,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~~~~\naaa\n~~~ ~~\n",
+    "html": "<pre><code>aaa\n~~~ ~~\n</code></pre>\n",
+    "example": 139,
+    "start_line": 2235,
+    "end_line": 2243,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "foo\n```\nbar\n```\nbaz\n",
+    "html": "<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n",
+    "example": 140,
+    "start_line": 2249,
+    "end_line": 2260,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "foo\n---\n~~~\nbar\n~~~\n# baz\n",
+    "html": "<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>\n",
+    "example": 141,
+    "start_line": 2266,
+    "end_line": 2278,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```ruby\ndef foo(x)\n  return 3\nend\n```\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 142,
+    "start_line": 2288,
+    "end_line": 2299,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~~    ruby startline=3 $%@#$\ndef foo(x)\n  return 3\nend\n~~~~~~~\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 143,
+    "start_line": 2302,
+    "end_line": 2313,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "````;\n````\n",
+    "html": "<pre><code class=\"language-;\"></code></pre>\n",
+    "example": 144,
+    "start_line": 2316,
+    "end_line": 2321,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "``` aa ```\nfoo\n",
+    "html": "<p><code>aa</code>\nfoo</p>\n",
+    "example": 145,
+    "start_line": 2326,
+    "end_line": 2332,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "~~~ aa ``` ~~~\nfoo\n~~~\n",
+    "html": "<pre><code class=\"language-aa\">foo\n</code></pre>\n",
+    "example": 146,
+    "start_line": 2337,
+    "end_line": 2344,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "```\n``` aaa\n```\n",
+    "html": "<pre><code>``` aaa\n</code></pre>\n",
+    "example": 147,
+    "start_line": 2349,
+    "end_line": 2356,
+    "section": "Fenced code blocks"
+  },
+  {
+    "markdown": "<table><tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr></table>\n",
+    "html": "<table><tr><td>\n<pre>\n**Hello**,\n<p><em>world</em>.\n</pre></p>\n</td></tr></table>\n",
+    "example": 148,
+    "start_line": 2428,
+    "end_line": 2443,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n\nokay.\n",
+    "html": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n<p>okay.</p>\n",
+    "example": 149,
+    "start_line": 2457,
+    "end_line": 2476,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": " <div>\n  *hello*\n         <foo><a>\n",
+    "html": " <div>\n  *hello*\n         <foo><a>\n",
+    "example": 150,
+    "start_line": 2479,
+    "end_line": 2487,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "</div>\n*foo*\n",
+    "html": "</div>\n*foo*\n",
+    "example": 151,
+    "start_line": 2492,
+    "end_line": 2498,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<DIV CLASS=\"foo\">\n\n*Markdown*\n\n</DIV>\n",
+    "html": "<DIV CLASS=\"foo\">\n<p><em>Markdown</em></p>\n</DIV>\n",
+    "example": 152,
+    "start_line": 2503,
+    "end_line": 2513,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "html": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "example": 153,
+    "start_line": 2519,
+    "end_line": 2527,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "html": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "example": 154,
+    "start_line": 2530,
+    "end_line": 2538,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div>\n*foo*\n\n*bar*\n",
+    "html": "<div>\n*foo*\n<p><em>bar</em></p>\n",
+    "example": 155,
+    "start_line": 2542,
+    "end_line": 2551,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div id=\"foo\"\n*hi*\n",
+    "html": "<div id=\"foo\"\n*hi*\n",
+    "example": 156,
+    "start_line": 2558,
+    "end_line": 2564,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div class\nfoo\n",
+    "html": "<div class\nfoo\n",
+    "example": 157,
+    "start_line": 2567,
+    "end_line": 2573,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div *???-&&&-<---\n*foo*\n",
+    "html": "<div *???-&&&-<---\n*foo*\n",
+    "example": 158,
+    "start_line": 2579,
+    "end_line": 2585,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "html": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "example": 159,
+    "start_line": 2591,
+    "end_line": 2595,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "html": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "example": 160,
+    "start_line": 2598,
+    "end_line": 2606,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "html": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "example": 161,
+    "start_line": 2615,
+    "end_line": 2625,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "html": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "example": 162,
+    "start_line": 2632,
+    "end_line": 2640,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<Warning>\n*bar*\n</Warning>\n",
+    "html": "<Warning>\n*bar*\n</Warning>\n",
+    "example": 163,
+    "start_line": 2645,
+    "end_line": 2653,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "html": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "example": 164,
+    "start_line": 2656,
+    "end_line": 2664,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "</ins>\n*bar*\n",
+    "html": "</ins>\n*bar*\n",
+    "example": 165,
+    "start_line": 2667,
+    "end_line": 2673,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<del>\n*foo*\n</del>\n",
+    "html": "<del>\n*foo*\n</del>\n",
+    "example": 166,
+    "start_line": 2682,
+    "end_line": 2690,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<del>\n\n*foo*\n\n</del>\n",
+    "html": "<del>\n<p><em>foo</em></p>\n</del>\n",
+    "example": 167,
+    "start_line": 2697,
+    "end_line": 2707,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<del>*foo*</del>\n",
+    "html": "<p><del><em>foo</em></del></p>\n",
+    "example": 168,
+    "start_line": 2715,
+    "end_line": 2719,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay\n",
+    "html": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>\n",
+    "example": 169,
+    "start_line": 2731,
+    "end_line": 2747,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\nokay\n",
+    "html": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\n<p>okay</p>\n",
+    "example": 170,
+    "start_line": 2752,
+    "end_line": 2766,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<textarea>\n\n*foo*\n\n_bar_\n\n</textarea>\n",
+    "html": "<textarea>\n\n*foo*\n\n_bar_\n\n</textarea>\n",
+    "example": 171,
+    "start_line": 2771,
+    "end_line": 2787,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay\n",
+    "html": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>\n",
+    "example": 172,
+    "start_line": 2791,
+    "end_line": 2807,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "html": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "example": 173,
+    "start_line": 2814,
+    "end_line": 2824,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "> <div>\n> foo\n\nbar\n",
+    "html": "<blockquote>\n<div>\nfoo\n</blockquote>\n<p>bar</p>\n",
+    "example": 174,
+    "start_line": 2827,
+    "end_line": 2838,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "- <div>\n- foo\n",
+    "html": "<ul>\n<li>\n<div>\n</li>\n<li>foo</li>\n</ul>\n",
+    "example": 175,
+    "start_line": 2841,
+    "end_line": 2851,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<style>p{color:red;}</style>\n*foo*\n",
+    "html": "<style>p{color:red;}</style>\n<p><em>foo</em></p>\n",
+    "example": 176,
+    "start_line": 2856,
+    "end_line": 2862,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<!-- foo -->*bar*\n*baz*\n",
+    "html": "<!-- foo -->*bar*\n<p><em>baz</em></p>\n",
+    "example": 177,
+    "start_line": 2865,
+    "end_line": 2871,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<script>\nfoo\n</script>1. *bar*\n",
+    "html": "<script>\nfoo\n</script>1. *bar*\n",
+    "example": 178,
+    "start_line": 2877,
+    "end_line": 2885,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<!-- Foo\n\nbar\n   baz -->\nokay\n",
+    "html": "<!-- Foo\n\nbar\n   baz -->\n<p>okay</p>\n",
+    "example": 179,
+    "start_line": 2890,
+    "end_line": 2902,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<?php\n\n  echo '>';\n\n?>\nokay\n",
+    "html": "<?php\n\n  echo '>';\n\n?>\n<p>okay</p>\n",
+    "example": 180,
+    "start_line": 2908,
+    "end_line": 2922,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<!DOCTYPE html>\n",
+    "html": "<!DOCTYPE html>\n",
+    "example": 181,
+    "start_line": 2927,
+    "end_line": 2931,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\nokay\n",
+    "html": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\n<p>okay</p>\n",
+    "example": 182,
+    "start_line": 2936,
+    "end_line": 2964,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "  <!-- foo -->\n\n    <!-- foo -->\n",
+    "html": "  <!-- foo -->\n<pre><code>&lt;!-- foo --&gt;\n</code></pre>\n",
+    "example": 183,
+    "start_line": 2970,
+    "end_line": 2978,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "  <div>\n\n    <div>\n",
+    "html": "  <div>\n<pre><code>&lt;div&gt;\n</code></pre>\n",
+    "example": 184,
+    "start_line": 2981,
+    "end_line": 2989,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "Foo\n<div>\nbar\n</div>\n",
+    "html": "<p>Foo</p>\n<div>\nbar\n</div>\n",
+    "example": 185,
+    "start_line": 2995,
+    "end_line": 3005,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div>\nbar\n</div>\n*foo*\n",
+    "html": "<div>\nbar\n</div>\n*foo*\n",
+    "example": 186,
+    "start_line": 3012,
+    "end_line": 3022,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "Foo\n<a href=\"bar\">\nbaz\n",
+    "html": "<p>Foo\n<a href=\"bar\">\nbaz</p>\n",
+    "example": 187,
+    "start_line": 3027,
+    "end_line": 3035,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div>\n\n*Emphasized* text.\n\n</div>\n",
+    "html": "<div>\n<p><em>Emphasized</em> text.</p>\n</div>\n",
+    "example": 188,
+    "start_line": 3068,
+    "end_line": 3078,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<div>\n*Emphasized* text.\n</div>\n",
+    "html": "<div>\n*Emphasized* text.\n</div>\n",
+    "example": 189,
+    "start_line": 3081,
+    "end_line": 3089,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<table>\n\n<tr>\n\n<td>\nHi\n</td>\n\n</tr>\n\n</table>\n",
+    "html": "<table>\n<tr>\n<td>\nHi\n</td>\n</tr>\n</table>\n",
+    "example": 190,
+    "start_line": 3103,
+    "end_line": 3123,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "<table>\n\n  <tr>\n\n    <td>\n      Hi\n    </td>\n\n  </tr>\n\n</table>\n",
+    "html": "<table>\n  <tr>\n<pre><code>&lt;td&gt;\n  Hi\n&lt;/td&gt;\n</code></pre>\n  </tr>\n</table>\n",
+    "example": 191,
+    "start_line": 3130,
+    "end_line": 3151,
+    "section": "HTML blocks"
+  },
+  {
+    "markdown": "[foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 192,
+    "start_line": 3179,
+    "end_line": 3185,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "   [foo]: \n      /url  \n           'the title'  \n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"the title\">foo</a></p>\n",
+    "example": 193,
+    "start_line": 3188,
+    "end_line": 3196,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]\n",
+    "html": "<p><a href=\"my_(url)\" title=\"title (with parens)\">Foo*bar]</a></p>\n",
+    "example": 194,
+    "start_line": 3199,
+    "end_line": 3205,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[Foo bar]:\n<my url>\n'title'\n\n[Foo bar]\n",
+    "html": "<p><a href=\"my%20url\" title=\"title\">Foo bar</a></p>\n",
+    "example": 195,
+    "start_line": 3208,
+    "end_line": 3216,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"\ntitle\nline1\nline2\n\">foo</a></p>\n",
+    "example": 196,
+    "start_line": 3221,
+    "end_line": 3235,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url 'title\n\nwith blank line'\n\n[foo]\n",
+    "html": "<p>[foo]: /url 'title</p>\n<p>with blank line'</p>\n<p>[foo]</p>\n",
+    "example": 197,
+    "start_line": 3240,
+    "end_line": 3250,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]:\n/url\n\n[foo]\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n",
+    "example": 198,
+    "start_line": 3255,
+    "end_line": 3262,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]:\n\n[foo]\n",
+    "html": "<p>[foo]:</p>\n<p>[foo]</p>\n",
+    "example": 199,
+    "start_line": 3267,
+    "end_line": 3274,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: <>\n\n[foo]\n",
+    "html": "<p><a href=\"\">foo</a></p>\n",
+    "example": 200,
+    "start_line": 3279,
+    "end_line": 3285,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: <bar>(baz)\n\n[foo]\n",
+    "html": "<p>[foo]: <bar>(baz)</p>\n<p>[foo]</p>\n",
+    "example": 201,
+    "start_line": 3290,
+    "end_line": 3297,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url%5Cbar*baz\" title=\"foo&quot;bar\\baz\">foo</a></p>\n",
+    "example": 202,
+    "start_line": 3303,
+    "end_line": 3309,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: url\n",
+    "html": "<p><a href=\"url\">foo</a></p>\n",
+    "example": 203,
+    "start_line": 3314,
+    "end_line": 3320,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: first\n[foo]: second\n",
+    "html": "<p><a href=\"first\">foo</a></p>\n",
+    "example": 204,
+    "start_line": 3326,
+    "end_line": 3333,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[FOO]: /url\n\n[Foo]\n",
+    "html": "<p><a href=\"/url\">Foo</a></p>\n",
+    "example": 205,
+    "start_line": 3339,
+    "end_line": 3345,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[ΑΓΩ]: /φου\n\n[αγω]\n",
+    "html": "<p><a href=\"/%CF%86%CE%BF%CF%85\">αγω</a></p>\n",
+    "example": 206,
+    "start_line": 3348,
+    "end_line": 3354,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url\n",
+    "html": "",
+    "example": 207,
+    "start_line": 3363,
+    "end_line": 3366,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[\nfoo\n]: /url\nbar\n",
+    "html": "<p>bar</p>\n",
+    "example": 208,
+    "start_line": 3371,
+    "end_line": 3378,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url \"title\" ok\n",
+    "html": "<p>[foo]: /url &quot;title&quot; ok</p>\n",
+    "example": 209,
+    "start_line": 3384,
+    "end_line": 3388,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url\n\"title\" ok\n",
+    "html": "<p>&quot;title&quot; ok</p>\n",
+    "example": 210,
+    "start_line": 3393,
+    "end_line": 3398,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "    [foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url &quot;title&quot;\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 211,
+    "start_line": 3404,
+    "end_line": 3412,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "```\n[foo]: /url\n```\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 212,
+    "start_line": 3418,
+    "end_line": 3428,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "Foo\n[bar]: /baz\n\n[bar]\n",
+    "html": "<p>Foo\n[bar]: /baz</p>\n<p>[bar]</p>\n",
+    "example": 213,
+    "start_line": 3433,
+    "end_line": 3442,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "# [Foo]\n[foo]: /url\n> bar\n",
+    "html": "<h1><a href=\"/url\">Foo</a></h1>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 214,
+    "start_line": 3448,
+    "end_line": 3457,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url\nbar\n===\n[foo]\n",
+    "html": "<h1>bar</h1>\n<p><a href=\"/url\">foo</a></p>\n",
+    "example": 215,
+    "start_line": 3459,
+    "end_line": 3467,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /url\n===\n[foo]\n",
+    "html": "<p>===\n<a href=\"/url\">foo</a></p>\n",
+    "example": 216,
+    "start_line": 3469,
+    "end_line": 3476,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n  \"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]\n",
+    "html": "<p><a href=\"/foo-url\" title=\"foo\">foo</a>,\n<a href=\"/bar-url\" title=\"bar\">bar</a>,\n<a href=\"/baz-url\">baz</a></p>\n",
+    "example": 217,
+    "start_line": 3482,
+    "end_line": 3495,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "[foo]\n\n> [foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n<blockquote>\n</blockquote>\n",
+    "example": 218,
+    "start_line": 3503,
+    "end_line": 3511,
+    "section": "Link reference definitions"
+  },
+  {
+    "markdown": "aaa\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 219,
+    "start_line": 3525,
+    "end_line": 3532,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "aaa\nbbb\n\nccc\nddd\n",
+    "html": "<p>aaa\nbbb</p>\n<p>ccc\nddd</p>\n",
+    "example": 220,
+    "start_line": 3537,
+    "end_line": 3548,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "aaa\n\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 221,
+    "start_line": 3553,
+    "end_line": 3561,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "  aaa\n bbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 222,
+    "start_line": 3566,
+    "end_line": 3572,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "aaa\n             bbb\n                                       ccc\n",
+    "html": "<p>aaa\nbbb\nccc</p>\n",
+    "example": 223,
+    "start_line": 3578,
+    "end_line": 3586,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "   aaa\nbbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 224,
+    "start_line": 3592,
+    "end_line": 3598,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "    aaa\nbbb\n",
+    "html": "<pre><code>aaa\n</code></pre>\n<p>bbb</p>\n",
+    "example": 225,
+    "start_line": 3601,
+    "end_line": 3608,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "aaa     \nbbb     \n",
+    "html": "<p>aaa<br />\nbbb</p>\n",
+    "example": 226,
+    "start_line": 3615,
+    "end_line": 3621,
+    "section": "Paragraphs"
+  },
+  {
+    "markdown": "  \n\naaa\n  \n\n# aaa\n\n  \n",
+    "html": "<p>aaa</p>\n<h1>aaa</h1>\n",
+    "example": 227,
+    "start_line": 3632,
+    "end_line": 3644,
+    "section": "Blank lines"
+  },
+  {
+    "markdown": "> # Foo\n> bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 228,
+    "start_line": 3700,
+    "end_line": 3710,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "># Foo\n>bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 229,
+    "start_line": 3715,
+    "end_line": 3725,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "   > # Foo\n   > bar\n > baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 230,
+    "start_line": 3730,
+    "end_line": 3740,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "    > # Foo\n    > bar\n    > baz\n",
+    "html": "<pre><code>&gt; # Foo\n&gt; bar\n&gt; baz\n</code></pre>\n",
+    "example": 231,
+    "start_line": 3745,
+    "end_line": 3754,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> # Foo\n> bar\nbaz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 232,
+    "start_line": 3760,
+    "end_line": 3770,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> bar\nbaz\n> foo\n",
+    "html": "<blockquote>\n<p>bar\nbaz\nfoo</p>\n</blockquote>\n",
+    "example": 233,
+    "start_line": 3776,
+    "end_line": 3786,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> foo\n---\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 234,
+    "start_line": 3800,
+    "end_line": 3808,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> - foo\n- bar\n",
+    "html": "<blockquote>\n<ul>\n<li>foo</li>\n</ul>\n</blockquote>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 235,
+    "start_line": 3820,
+    "end_line": 3832,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">     foo\n    bar\n",
+    "html": "<blockquote>\n<pre><code>foo\n</code></pre>\n</blockquote>\n<pre><code>bar\n</code></pre>\n",
+    "example": 236,
+    "start_line": 3838,
+    "end_line": 3848,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> ```\nfoo\n```\n",
+    "html": "<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>\n",
+    "example": 237,
+    "start_line": 3851,
+    "end_line": 3861,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> foo\n    - bar\n",
+    "html": "<blockquote>\n<p>foo\n- bar</p>\n</blockquote>\n",
+    "example": 238,
+    "start_line": 3867,
+    "end_line": 3875,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">\n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 239,
+    "start_line": 3891,
+    "end_line": 3896,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">\n>  \n> \n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 240,
+    "start_line": 3899,
+    "end_line": 3906,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">\n> foo\n>  \n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n",
+    "example": 241,
+    "start_line": 3911,
+    "end_line": 3919,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> foo\n\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 242,
+    "start_line": 3924,
+    "end_line": 3935,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> foo\n> bar\n",
+    "html": "<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n",
+    "example": 243,
+    "start_line": 3946,
+    "end_line": 3954,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> foo\n>\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>\n",
+    "example": 244,
+    "start_line": 3959,
+    "end_line": 3968,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "foo\n> bar\n",
+    "html": "<p>foo</p>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 245,
+    "start_line": 3973,
+    "end_line": 3981,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> aaa\n***\n> bbb\n",
+    "html": "<blockquote>\n<p>aaa</p>\n</blockquote>\n<hr />\n<blockquote>\n<p>bbb</p>\n</blockquote>\n",
+    "example": 246,
+    "start_line": 3987,
+    "end_line": 3999,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> bar\nbaz\n",
+    "html": "<blockquote>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 247,
+    "start_line": 4005,
+    "end_line": 4013,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> bar\n\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 248,
+    "start_line": 4016,
+    "end_line": 4025,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> bar\n>\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 249,
+    "start_line": 4028,
+    "end_line": 4037,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "> > > foo\nbar\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 250,
+    "start_line": 4044,
+    "end_line": 4056,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">>> foo\n> bar\n>>baz\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar\nbaz</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 251,
+    "start_line": 4059,
+    "end_line": 4073,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": ">     code\n\n>    not code\n",
+    "html": "<blockquote>\n<pre><code>code\n</code></pre>\n</blockquote>\n<blockquote>\n<p>not code</p>\n</blockquote>\n",
+    "example": 252,
+    "start_line": 4081,
+    "end_line": 4093,
+    "section": "Block quotes"
+  },
+  {
+    "markdown": "A paragraph\nwith two lines.\n\n    indented code\n\n> A block quote.\n",
+    "html": "<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n",
+    "example": 253,
+    "start_line": 4135,
+    "end_line": 4150,
+    "section": "List items"
+  },
+  {
+    "markdown": "1.  A paragraph\n    with two lines.\n\n        indented code\n\n    > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 254,
+    "start_line": 4157,
+    "end_line": 4176,
+    "section": "List items"
+  },
+  {
+    "markdown": "- one\n\n two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n",
+    "example": 255,
+    "start_line": 4190,
+    "end_line": 4199,
+    "section": "List items"
+  },
+  {
+    "markdown": "- one\n\n  two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 256,
+    "start_line": 4202,
+    "end_line": 4213,
+    "section": "List items"
+  },
+  {
+    "markdown": " -    one\n\n     two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<pre><code> two\n</code></pre>\n",
+    "example": 257,
+    "start_line": 4216,
+    "end_line": 4226,
+    "section": "List items"
+  },
+  {
+    "markdown": " -    one\n\n      two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 258,
+    "start_line": 4229,
+    "end_line": 4240,
+    "section": "List items"
+  },
+  {
+    "markdown": "   > > 1.  one\n>>\n>>     two\n",
+    "html": "<blockquote>\n<blockquote>\n<ol>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ol>\n</blockquote>\n</blockquote>\n",
+    "example": 259,
+    "start_line": 4251,
+    "end_line": 4266,
+    "section": "List items"
+  },
+  {
+    "markdown": ">>- one\n>>\n  >  > two\n",
+    "html": "<blockquote>\n<blockquote>\n<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n</blockquote>\n</blockquote>\n",
+    "example": 260,
+    "start_line": 4278,
+    "end_line": 4291,
+    "section": "List items"
+  },
+  {
+    "markdown": "-one\n\n2.two\n",
+    "html": "<p>-one</p>\n<p>2.two</p>\n",
+    "example": 261,
+    "start_line": 4297,
+    "end_line": 4304,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n\n\n  bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 262,
+    "start_line": 4310,
+    "end_line": 4322,
+    "section": "List items"
+  },
+  {
+    "markdown": "1.  foo\n\n    ```\n    bar\n    ```\n\n    baz\n\n    > bam\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n<blockquote>\n<p>bam</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 263,
+    "start_line": 4327,
+    "end_line": 4349,
+    "section": "List items"
+  },
+  {
+    "markdown": "- Foo\n\n      bar\n\n\n      baz\n",
+    "html": "<ul>\n<li>\n<p>Foo</p>\n<pre><code>bar\n\n\nbaz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 264,
+    "start_line": 4355,
+    "end_line": 4373,
+    "section": "List items"
+  },
+  {
+    "markdown": "123456789. ok\n",
+    "html": "<ol start=\"123456789\">\n<li>ok</li>\n</ol>\n",
+    "example": 265,
+    "start_line": 4377,
+    "end_line": 4383,
+    "section": "List items"
+  },
+  {
+    "markdown": "1234567890. not ok\n",
+    "html": "<p>1234567890. not ok</p>\n",
+    "example": 266,
+    "start_line": 4386,
+    "end_line": 4390,
+    "section": "List items"
+  },
+  {
+    "markdown": "0. ok\n",
+    "html": "<ol start=\"0\">\n<li>ok</li>\n</ol>\n",
+    "example": 267,
+    "start_line": 4395,
+    "end_line": 4401,
+    "section": "List items"
+  },
+  {
+    "markdown": "003. ok\n",
+    "html": "<ol start=\"3\">\n<li>ok</li>\n</ol>\n",
+    "example": 268,
+    "start_line": 4404,
+    "end_line": 4410,
+    "section": "List items"
+  },
+  {
+    "markdown": "-1. not ok\n",
+    "html": "<p>-1. not ok</p>\n",
+    "example": 269,
+    "start_line": 4415,
+    "end_line": 4419,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n\n      bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 270,
+    "start_line": 4438,
+    "end_line": 4450,
+    "section": "List items"
+  },
+  {
+    "markdown": "  10.  foo\n\n           bar\n",
+    "html": "<ol start=\"10\">\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ol>\n",
+    "example": 271,
+    "start_line": 4455,
+    "end_line": 4467,
+    "section": "List items"
+  },
+  {
+    "markdown": "    indented code\n\nparagraph\n\n    more code\n",
+    "html": "<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n",
+    "example": 272,
+    "start_line": 4474,
+    "end_line": 4486,
+    "section": "List items"
+  },
+  {
+    "markdown": "1.     indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 273,
+    "start_line": 4489,
+    "end_line": 4505,
+    "section": "List items"
+  },
+  {
+    "markdown": "1.      indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code> indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 274,
+    "start_line": 4511,
+    "end_line": 4527,
+    "section": "List items"
+  },
+  {
+    "markdown": "   foo\n\nbar\n",
+    "html": "<p>foo</p>\n<p>bar</p>\n",
+    "example": 275,
+    "start_line": 4538,
+    "end_line": 4545,
+    "section": "List items"
+  },
+  {
+    "markdown": "-    foo\n\n  bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<p>bar</p>\n",
+    "example": 276,
+    "start_line": 4548,
+    "end_line": 4557,
+    "section": "List items"
+  },
+  {
+    "markdown": "-  foo\n\n   bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 277,
+    "start_line": 4565,
+    "end_line": 4576,
+    "section": "List items"
+  },
+  {
+    "markdown": "-\n  foo\n-\n  ```\n  bar\n  ```\n-\n      baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>\n<pre><code>bar\n</code></pre>\n</li>\n<li>\n<pre><code>baz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 278,
+    "start_line": 4592,
+    "end_line": 4613,
+    "section": "List items"
+  },
+  {
+    "markdown": "-   \n  foo\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n",
+    "example": 279,
+    "start_line": 4618,
+    "end_line": 4625,
+    "section": "List items"
+  },
+  {
+    "markdown": "-\n\n  foo\n",
+    "html": "<ul>\n<li></li>\n</ul>\n<p>foo</p>\n",
+    "example": 280,
+    "start_line": 4632,
+    "end_line": 4641,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n-\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 281,
+    "start_line": 4646,
+    "end_line": 4656,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n-   \n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 282,
+    "start_line": 4661,
+    "end_line": 4671,
+    "section": "List items"
+  },
+  {
+    "markdown": "1. foo\n2.\n3. bar\n",
+    "html": "<ol>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ol>\n",
+    "example": 283,
+    "start_line": 4676,
+    "end_line": 4686,
+    "section": "List items"
+  },
+  {
+    "markdown": "*\n",
+    "html": "<ul>\n<li></li>\n</ul>\n",
+    "example": 284,
+    "start_line": 4691,
+    "end_line": 4697,
+    "section": "List items"
+  },
+  {
+    "markdown": "foo\n*\n\nfoo\n1.\n",
+    "html": "<p>foo\n*</p>\n<p>foo\n1.</p>\n",
+    "example": 285,
+    "start_line": 4701,
+    "end_line": 4712,
+    "section": "List items"
+  },
+  {
+    "markdown": " 1.  A paragraph\n     with two lines.\n\n         indented code\n\n     > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 286,
+    "start_line": 4723,
+    "end_line": 4742,
+    "section": "List items"
+  },
+  {
+    "markdown": "  1.  A paragraph\n      with two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 287,
+    "start_line": 4747,
+    "end_line": 4766,
+    "section": "List items"
+  },
+  {
+    "markdown": "   1.  A paragraph\n       with two lines.\n\n           indented code\n\n       > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 288,
+    "start_line": 4771,
+    "end_line": 4790,
+    "section": "List items"
+  },
+  {
+    "markdown": "    1.  A paragraph\n        with two lines.\n\n            indented code\n\n        > A block quote.\n",
+    "html": "<pre><code>1.  A paragraph\n    with two lines.\n\n        indented code\n\n    &gt; A block quote.\n</code></pre>\n",
+    "example": 289,
+    "start_line": 4795,
+    "end_line": 4810,
+    "section": "List items"
+  },
+  {
+    "markdown": "  1.  A paragraph\nwith two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 290,
+    "start_line": 4825,
+    "end_line": 4844,
+    "section": "List items"
+  },
+  {
+    "markdown": "  1.  A paragraph\n    with two lines.\n",
+    "html": "<ol>\n<li>A paragraph\nwith two lines.</li>\n</ol>\n",
+    "example": 291,
+    "start_line": 4849,
+    "end_line": 4857,
+    "section": "List items"
+  },
+  {
+    "markdown": "> 1. > Blockquote\ncontinued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 292,
+    "start_line": 4862,
+    "end_line": 4876,
+    "section": "List items"
+  },
+  {
+    "markdown": "> 1. > Blockquote\n> continued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 293,
+    "start_line": 4879,
+    "end_line": 4893,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n      - boo\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 294,
+    "start_line": 4907,
+    "end_line": 4928,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n - bar\n  - baz\n   - boo\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>\n",
+    "example": 295,
+    "start_line": 4933,
+    "end_line": 4945,
+    "section": "List items"
+  },
+  {
+    "markdown": "10) foo\n    - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 296,
+    "start_line": 4950,
+    "end_line": 4961,
+    "section": "List items"
+  },
+  {
+    "markdown": "10) foo\n   - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo</li>\n</ol>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 297,
+    "start_line": 4966,
+    "end_line": 4976,
+    "section": "List items"
+  },
+  {
+    "markdown": "- - foo\n",
+    "html": "<ul>\n<li>\n<ul>\n<li>foo</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 298,
+    "start_line": 4981,
+    "end_line": 4991,
+    "section": "List items"
+  },
+  {
+    "markdown": "1. - 2. foo\n",
+    "html": "<ol>\n<li>\n<ul>\n<li>\n<ol start=\"2\">\n<li>foo</li>\n</ol>\n</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 299,
+    "start_line": 4994,
+    "end_line": 5008,
+    "section": "List items"
+  },
+  {
+    "markdown": "- # Foo\n- Bar\n  ---\n  baz\n",
+    "html": "<ul>\n<li>\n<h1>Foo</h1>\n</li>\n<li>\n<h2>Bar</h2>\nbaz</li>\n</ul>\n",
+    "example": 300,
+    "start_line": 5013,
+    "end_line": 5027,
+    "section": "List items"
+  },
+  {
+    "markdown": "- foo\n- bar\n+ baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<ul>\n<li>baz</li>\n</ul>\n",
+    "example": 301,
+    "start_line": 5249,
+    "end_line": 5261,
+    "section": "Lists"
+  },
+  {
+    "markdown": "1. foo\n2. bar\n3) baz\n",
+    "html": "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>\n<ol start=\"3\">\n<li>baz</li>\n</ol>\n",
+    "example": 302,
+    "start_line": 5264,
+    "end_line": 5276,
+    "section": "Lists"
+  },
+  {
+    "markdown": "Foo\n- bar\n- baz\n",
+    "html": "<p>Foo</p>\n<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n",
+    "example": 303,
+    "start_line": 5283,
+    "end_line": 5293,
+    "section": "Lists"
+  },
+  {
+    "markdown": "The number of windows in my house is\n14.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is\n14.  The number of doors is 6.</p>\n",
+    "example": 304,
+    "start_line": 5360,
+    "end_line": 5366,
+    "section": "Lists"
+  },
+  {
+    "markdown": "The number of windows in my house is\n1.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is</p>\n<ol>\n<li>The number of doors is 6.</li>\n</ol>\n",
+    "example": 305,
+    "start_line": 5370,
+    "end_line": 5378,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- foo\n\n- bar\n\n\n- baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n</li>\n<li>\n<p>bar</p>\n</li>\n<li>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 306,
+    "start_line": 5384,
+    "end_line": 5403,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n\n\n      bim\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>\n<p>baz</p>\n<p>bim</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 307,
+    "start_line": 5405,
+    "end_line": 5427,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>\n",
+    "example": 308,
+    "start_line": 5435,
+    "end_line": 5453,
+    "section": "Lists"
+  },
+  {
+    "markdown": "-   foo\n\n    notcode\n\n-   foo\n\n<!-- -->\n\n    code\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>\n",
+    "example": 309,
+    "start_line": 5456,
+    "end_line": 5479,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n - b\n  - c\n   - d\n  - e\n - f\n- g\n",
+    "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n<li>e</li>\n<li>f</li>\n<li>g</li>\n</ul>\n",
+    "example": 310,
+    "start_line": 5487,
+    "end_line": 5505,
+    "section": "Lists"
+  },
+  {
+    "markdown": "1. a\n\n  2. b\n\n   3. c\n",
+    "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ol>\n",
+    "example": 311,
+    "start_line": 5508,
+    "end_line": 5526,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n - b\n  - c\n   - d\n    - e\n",
+    "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d\n- e</li>\n</ul>\n",
+    "example": 312,
+    "start_line": 5532,
+    "end_line": 5546,
+    "section": "Lists"
+  },
+  {
+    "markdown": "1. a\n\n  2. b\n\n    3. c\n",
+    "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n</ol>\n<pre><code>3. c\n</code></pre>\n",
+    "example": 313,
+    "start_line": 5552,
+    "end_line": 5569,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n- b\n\n- c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 314,
+    "start_line": 5575,
+    "end_line": 5592,
+    "section": "Lists"
+  },
+  {
+    "markdown": "* a\n*\n\n* c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 315,
+    "start_line": 5597,
+    "end_line": 5612,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n- b\n\n  c\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 316,
+    "start_line": 5619,
+    "end_line": 5638,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n- b\n\n  [ref]: /url\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 317,
+    "start_line": 5641,
+    "end_line": 5659,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n- ```\n  b\n\n\n  ```\n- c\n",
+    "html": "<ul>\n<li>a</li>\n<li>\n<pre><code>b\n\n\n</code></pre>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 318,
+    "start_line": 5664,
+    "end_line": 5683,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n  - b\n\n    c\n- d\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 319,
+    "start_line": 5690,
+    "end_line": 5708,
+    "section": "Lists"
+  },
+  {
+    "markdown": "* a\n  > b\n  >\n* c\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 320,
+    "start_line": 5714,
+    "end_line": 5728,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n  > b\n  ```\n  c\n  ```\n- d\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n<pre><code>c\n</code></pre>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 321,
+    "start_line": 5734,
+    "end_line": 5752,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n",
+    "html": "<ul>\n<li>a</li>\n</ul>\n",
+    "example": 322,
+    "start_line": 5757,
+    "end_line": 5763,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n  - b\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>b</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 323,
+    "start_line": 5766,
+    "end_line": 5777,
+    "section": "Lists"
+  },
+  {
+    "markdown": "1. ```\n   foo\n   ```\n\n   bar\n",
+    "html": "<ol>\n<li>\n<pre><code>foo\n</code></pre>\n<p>bar</p>\n</li>\n</ol>\n",
+    "example": 324,
+    "start_line": 5783,
+    "end_line": 5797,
+    "section": "Lists"
+  },
+  {
+    "markdown": "* foo\n  * bar\n\n  baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 325,
+    "start_line": 5802,
+    "end_line": 5817,
+    "section": "Lists"
+  },
+  {
+    "markdown": "- a\n  - b\n  - c\n\n- d\n  - e\n  - f\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n<ul>\n<li>b</li>\n<li>c</li>\n</ul>\n</li>\n<li>\n<p>d</p>\n<ul>\n<li>e</li>\n<li>f</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 326,
+    "start_line": 5820,
+    "end_line": 5845,
+    "section": "Lists"
+  },
+  {
+    "markdown": "`hi`lo`\n",
+    "html": "<p><code>hi</code>lo`</p>\n",
+    "example": 327,
+    "start_line": 5854,
+    "end_line": 5858,
+    "section": "Inlines"
+  },
+  {
+    "markdown": "`foo`\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 328,
+    "start_line": 5886,
+    "end_line": 5890,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`` foo ` bar ``\n",
+    "html": "<p><code>foo ` bar</code></p>\n",
+    "example": 329,
+    "start_line": 5897,
+    "end_line": 5901,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "` `` `\n",
+    "html": "<p><code>``</code></p>\n",
+    "example": 330,
+    "start_line": 5907,
+    "end_line": 5911,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`  ``  `\n",
+    "html": "<p><code> `` </code></p>\n",
+    "example": 331,
+    "start_line": 5915,
+    "end_line": 5919,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "` a`\n",
+    "html": "<p><code> a</code></p>\n",
+    "example": 332,
+    "start_line": 5924,
+    "end_line": 5928,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "` b `\n",
+    "html": "<p><code> b </code></p>\n",
+    "example": 333,
+    "start_line": 5933,
+    "end_line": 5937,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "` `\n`  `\n",
+    "html": "<p><code> </code>\n<code>  </code></p>\n",
+    "example": 334,
+    "start_line": 5941,
+    "end_line": 5947,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "``\nfoo\nbar  \nbaz\n``\n",
+    "html": "<p><code>foo bar   baz</code></p>\n",
+    "example": 335,
+    "start_line": 5952,
+    "end_line": 5960,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "``\nfoo \n``\n",
+    "html": "<p><code>foo </code></p>\n",
+    "example": 336,
+    "start_line": 5962,
+    "end_line": 5968,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`foo   bar \nbaz`\n",
+    "html": "<p><code>foo   bar  baz</code></p>\n",
+    "example": 337,
+    "start_line": 5973,
+    "end_line": 5978,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`foo\\`bar`\n",
+    "html": "<p><code>foo\\</code>bar`</p>\n",
+    "example": 338,
+    "start_line": 5990,
+    "end_line": 5994,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "``foo`bar``\n",
+    "html": "<p><code>foo`bar</code></p>\n",
+    "example": 339,
+    "start_line": 6001,
+    "end_line": 6005,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "` foo `` bar `\n",
+    "html": "<p><code>foo `` bar</code></p>\n",
+    "example": 340,
+    "start_line": 6007,
+    "end_line": 6011,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "*foo`*`\n",
+    "html": "<p>*foo<code>*</code></p>\n",
+    "example": 341,
+    "start_line": 6019,
+    "end_line": 6023,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "[not a `link](/foo`)\n",
+    "html": "<p>[not a <code>link](/foo</code>)</p>\n",
+    "example": 342,
+    "start_line": 6028,
+    "end_line": 6032,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`<a href=\"`\">`\n",
+    "html": "<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>\n",
+    "example": 343,
+    "start_line": 6038,
+    "end_line": 6042,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "<a href=\"`\">`\n",
+    "html": "<p><a href=\"`\">`</p>\n",
+    "example": 344,
+    "start_line": 6047,
+    "end_line": 6051,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`<https://foo.bar.`baz>`\n",
+    "html": "<p><code>&lt;https://foo.bar.</code>baz&gt;`</p>\n",
+    "example": 345,
+    "start_line": 6056,
+    "end_line": 6060,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "<https://foo.bar.`baz>`\n",
+    "html": "<p><a href=\"https://foo.bar.%60baz\">https://foo.bar.`baz</a>`</p>\n",
+    "example": 346,
+    "start_line": 6065,
+    "end_line": 6069,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "```foo``\n",
+    "html": "<p>```foo``</p>\n",
+    "example": 347,
+    "start_line": 6075,
+    "end_line": 6079,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`foo\n",
+    "html": "<p>`foo</p>\n",
+    "example": 348,
+    "start_line": 6082,
+    "end_line": 6086,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "`foo``bar``\n",
+    "html": "<p>`foo<code>bar</code></p>\n",
+    "example": 349,
+    "start_line": 6091,
+    "end_line": 6095,
+    "section": "Code spans"
+  },
+  {
+    "markdown": "*foo bar*\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 350,
+    "start_line": 6308,
+    "end_line": 6312,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "a * foo bar*\n",
+    "html": "<p>a * foo bar*</p>\n",
+    "example": 351,
+    "start_line": 6318,
+    "end_line": 6322,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "a*\"foo\"*\n",
+    "html": "<p>a*&quot;foo&quot;*</p>\n",
+    "example": 352,
+    "start_line": 6329,
+    "end_line": 6333,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "* a *\n",
+    "html": "<p>* a *</p>\n",
+    "example": 353,
+    "start_line": 6338,
+    "end_line": 6342,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*$*alpha.\n\n*£*bravo.\n\n*€*charlie.\n",
+    "html": "<p>*$*alpha.</p>\n<p>*£*bravo.</p>\n<p>*€*charlie.</p>\n",
+    "example": 354,
+    "start_line": 6347,
+    "end_line": 6357,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo*bar*\n",
+    "html": "<p>foo<em>bar</em></p>\n",
+    "example": 355,
+    "start_line": 6362,
+    "end_line": 6366,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "5*6*78\n",
+    "html": "<p>5<em>6</em>78</p>\n",
+    "example": 356,
+    "start_line": 6369,
+    "end_line": 6373,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo bar_\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 357,
+    "start_line": 6378,
+    "end_line": 6382,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_ foo bar_\n",
+    "html": "<p>_ foo bar_</p>\n",
+    "example": 358,
+    "start_line": 6388,
+    "end_line": 6392,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "a_\"foo\"_\n",
+    "html": "<p>a_&quot;foo&quot;_</p>\n",
+    "example": 359,
+    "start_line": 6398,
+    "end_line": 6402,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo_bar_\n",
+    "html": "<p>foo_bar_</p>\n",
+    "example": 360,
+    "start_line": 6407,
+    "end_line": 6411,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "5_6_78\n",
+    "html": "<p>5_6_78</p>\n",
+    "example": 361,
+    "start_line": 6414,
+    "end_line": 6418,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "пристаням_стремятся_\n",
+    "html": "<p>пристаням_стремятся_</p>\n",
+    "example": 362,
+    "start_line": 6421,
+    "end_line": 6425,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "aa_\"bb\"_cc\n",
+    "html": "<p>aa_&quot;bb&quot;_cc</p>\n",
+    "example": 363,
+    "start_line": 6431,
+    "end_line": 6435,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo-_(bar)_\n",
+    "html": "<p>foo-<em>(bar)</em></p>\n",
+    "example": 364,
+    "start_line": 6442,
+    "end_line": 6446,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo*\n",
+    "html": "<p>_foo*</p>\n",
+    "example": 365,
+    "start_line": 6454,
+    "end_line": 6458,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo bar *\n",
+    "html": "<p>*foo bar *</p>\n",
+    "example": 366,
+    "start_line": 6464,
+    "end_line": 6468,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo bar\n*\n",
+    "html": "<p>*foo bar\n*</p>\n",
+    "example": 367,
+    "start_line": 6473,
+    "end_line": 6479,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*(*foo)\n",
+    "html": "<p>*(*foo)</p>\n",
+    "example": 368,
+    "start_line": 6486,
+    "end_line": 6490,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*(*foo*)*\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 369,
+    "start_line": 6496,
+    "end_line": 6500,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo*bar\n",
+    "html": "<p><em>foo</em>bar</p>\n",
+    "example": 370,
+    "start_line": 6505,
+    "end_line": 6509,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo bar _\n",
+    "html": "<p>_foo bar _</p>\n",
+    "example": 371,
+    "start_line": 6518,
+    "end_line": 6522,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_(_foo)\n",
+    "html": "<p>_(_foo)</p>\n",
+    "example": 372,
+    "start_line": 6528,
+    "end_line": 6532,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_(_foo_)_\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 373,
+    "start_line": 6537,
+    "end_line": 6541,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo_bar\n",
+    "html": "<p>_foo_bar</p>\n",
+    "example": 374,
+    "start_line": 6546,
+    "end_line": 6550,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_пристаням_стремятся\n",
+    "html": "<p>_пристаням_стремятся</p>\n",
+    "example": 375,
+    "start_line": 6553,
+    "end_line": 6557,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo_bar_baz_\n",
+    "html": "<p><em>foo_bar_baz</em></p>\n",
+    "example": 376,
+    "start_line": 6560,
+    "end_line": 6564,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_(bar)_.\n",
+    "html": "<p><em>(bar)</em>.</p>\n",
+    "example": 377,
+    "start_line": 6571,
+    "end_line": 6575,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo bar**\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 378,
+    "start_line": 6580,
+    "end_line": 6584,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "** foo bar**\n",
+    "html": "<p>** foo bar**</p>\n",
+    "example": 379,
+    "start_line": 6590,
+    "end_line": 6594,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "a**\"foo\"**\n",
+    "html": "<p>a**&quot;foo&quot;**</p>\n",
+    "example": 380,
+    "start_line": 6601,
+    "end_line": 6605,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo**bar**\n",
+    "html": "<p>foo<strong>bar</strong></p>\n",
+    "example": 381,
+    "start_line": 6610,
+    "end_line": 6614,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo bar__\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 382,
+    "start_line": 6619,
+    "end_line": 6623,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__ foo bar__\n",
+    "html": "<p>__ foo bar__</p>\n",
+    "example": 383,
+    "start_line": 6629,
+    "end_line": 6633,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__\nfoo bar__\n",
+    "html": "<p>__\nfoo bar__</p>\n",
+    "example": 384,
+    "start_line": 6637,
+    "end_line": 6643,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "a__\"foo\"__\n",
+    "html": "<p>a__&quot;foo&quot;__</p>\n",
+    "example": 385,
+    "start_line": 6649,
+    "end_line": 6653,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo__bar__\n",
+    "html": "<p>foo__bar__</p>\n",
+    "example": 386,
+    "start_line": 6658,
+    "end_line": 6662,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "5__6__78\n",
+    "html": "<p>5__6__78</p>\n",
+    "example": 387,
+    "start_line": 6665,
+    "end_line": 6669,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "пристаням__стремятся__\n",
+    "html": "<p>пристаням__стремятся__</p>\n",
+    "example": 388,
+    "start_line": 6672,
+    "end_line": 6676,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo, __bar__, baz__\n",
+    "html": "<p><strong>foo, <strong>bar</strong>, baz</strong></p>\n",
+    "example": 389,
+    "start_line": 6679,
+    "end_line": 6683,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo-__(bar)__\n",
+    "html": "<p>foo-<strong>(bar)</strong></p>\n",
+    "example": 390,
+    "start_line": 6690,
+    "end_line": 6694,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo bar **\n",
+    "html": "<p>**foo bar **</p>\n",
+    "example": 391,
+    "start_line": 6703,
+    "end_line": 6707,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**(**foo)\n",
+    "html": "<p>**(**foo)</p>\n",
+    "example": 392,
+    "start_line": 6716,
+    "end_line": 6720,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*(**foo**)*\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 393,
+    "start_line": 6726,
+    "end_line": 6730,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**\n",
+    "html": "<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.\n<em>Asclepias physocarpa</em>)</strong></p>\n",
+    "example": 394,
+    "start_line": 6733,
+    "end_line": 6739,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo \"*bar*\" foo**\n",
+    "html": "<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>\n",
+    "example": 395,
+    "start_line": 6742,
+    "end_line": 6746,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo**bar\n",
+    "html": "<p><strong>foo</strong>bar</p>\n",
+    "example": 396,
+    "start_line": 6751,
+    "end_line": 6755,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo bar __\n",
+    "html": "<p>__foo bar __</p>\n",
+    "example": 397,
+    "start_line": 6763,
+    "end_line": 6767,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__(__foo)\n",
+    "html": "<p>__(__foo)</p>\n",
+    "example": 398,
+    "start_line": 6773,
+    "end_line": 6777,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_(__foo__)_\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 399,
+    "start_line": 6783,
+    "end_line": 6787,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo__bar\n",
+    "html": "<p>__foo__bar</p>\n",
+    "example": 400,
+    "start_line": 6792,
+    "end_line": 6796,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__пристаням__стремятся\n",
+    "html": "<p>__пристаням__стремятся</p>\n",
+    "example": 401,
+    "start_line": 6799,
+    "end_line": 6803,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo__bar__baz__\n",
+    "html": "<p><strong>foo__bar__baz</strong></p>\n",
+    "example": 402,
+    "start_line": 6806,
+    "end_line": 6810,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__(bar)__.\n",
+    "html": "<p><strong>(bar)</strong>.</p>\n",
+    "example": 403,
+    "start_line": 6817,
+    "end_line": 6821,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo [bar](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\">bar</a></em></p>\n",
+    "example": 404,
+    "start_line": 6829,
+    "end_line": 6833,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo\nbar*\n",
+    "html": "<p><em>foo\nbar</em></p>\n",
+    "example": 405,
+    "start_line": 6836,
+    "end_line": 6842,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo __bar__ baz_\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 406,
+    "start_line": 6848,
+    "end_line": 6852,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo _bar_ baz_\n",
+    "html": "<p><em>foo <em>bar</em> baz</em></p>\n",
+    "example": 407,
+    "start_line": 6855,
+    "end_line": 6859,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo_ bar_\n",
+    "html": "<p><em><em>foo</em> bar</em></p>\n",
+    "example": 408,
+    "start_line": 6862,
+    "end_line": 6866,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo *bar**\n",
+    "html": "<p><em>foo <em>bar</em></em></p>\n",
+    "example": 409,
+    "start_line": 6869,
+    "end_line": 6873,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo **bar** baz*\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 410,
+    "start_line": 6876,
+    "end_line": 6880,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo**bar**baz*\n",
+    "html": "<p><em>foo<strong>bar</strong>baz</em></p>\n",
+    "example": 411,
+    "start_line": 6882,
+    "end_line": 6886,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo**bar*\n",
+    "html": "<p><em>foo**bar</em></p>\n",
+    "example": 412,
+    "start_line": 6906,
+    "end_line": 6910,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "***foo** bar*\n",
+    "html": "<p><em><strong>foo</strong> bar</em></p>\n",
+    "example": 413,
+    "start_line": 6919,
+    "end_line": 6923,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo **bar***\n",
+    "html": "<p><em>foo <strong>bar</strong></em></p>\n",
+    "example": 414,
+    "start_line": 6926,
+    "end_line": 6930,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo**bar***\n",
+    "html": "<p><em>foo<strong>bar</strong></em></p>\n",
+    "example": 415,
+    "start_line": 6933,
+    "end_line": 6937,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo***bar***baz\n",
+    "html": "<p>foo<em><strong>bar</strong></em>baz</p>\n",
+    "example": 416,
+    "start_line": 6944,
+    "end_line": 6948,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo******bar*********baz\n",
+    "html": "<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>\n",
+    "example": 417,
+    "start_line": 6950,
+    "end_line": 6954,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo **bar *baz* bim** bop*\n",
+    "html": "<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>\n",
+    "example": 418,
+    "start_line": 6959,
+    "end_line": 6963,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo [*bar*](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\"><em>bar</em></a></em></p>\n",
+    "example": 419,
+    "start_line": 6966,
+    "end_line": 6970,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "** is not an empty emphasis\n",
+    "html": "<p>** is not an empty emphasis</p>\n",
+    "example": 420,
+    "start_line": 6975,
+    "end_line": 6979,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**** is not an empty strong emphasis\n",
+    "html": "<p>**** is not an empty strong emphasis</p>\n",
+    "example": 421,
+    "start_line": 6982,
+    "end_line": 6986,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo [bar](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\">bar</a></strong></p>\n",
+    "example": 422,
+    "start_line": 6995,
+    "end_line": 6999,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo\nbar**\n",
+    "html": "<p><strong>foo\nbar</strong></p>\n",
+    "example": 423,
+    "start_line": 7002,
+    "end_line": 7008,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo _bar_ baz__\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 424,
+    "start_line": 7014,
+    "end_line": 7018,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo __bar__ baz__\n",
+    "html": "<p><strong>foo <strong>bar</strong> baz</strong></p>\n",
+    "example": 425,
+    "start_line": 7021,
+    "end_line": 7025,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "____foo__ bar__\n",
+    "html": "<p><strong><strong>foo</strong> bar</strong></p>\n",
+    "example": 426,
+    "start_line": 7028,
+    "end_line": 7032,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo **bar****\n",
+    "html": "<p><strong>foo <strong>bar</strong></strong></p>\n",
+    "example": 427,
+    "start_line": 7035,
+    "end_line": 7039,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo *bar* baz**\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 428,
+    "start_line": 7042,
+    "end_line": 7046,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo*bar*baz**\n",
+    "html": "<p><strong>foo<em>bar</em>baz</strong></p>\n",
+    "example": 429,
+    "start_line": 7049,
+    "end_line": 7053,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "***foo* bar**\n",
+    "html": "<p><strong><em>foo</em> bar</strong></p>\n",
+    "example": 430,
+    "start_line": 7056,
+    "end_line": 7060,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo *bar***\n",
+    "html": "<p><strong>foo <em>bar</em></strong></p>\n",
+    "example": 431,
+    "start_line": 7063,
+    "end_line": 7067,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo *bar **baz**\nbim* bop**\n",
+    "html": "<p><strong>foo <em>bar <strong>baz</strong>\nbim</em> bop</strong></p>\n",
+    "example": 432,
+    "start_line": 7072,
+    "end_line": 7078,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo [*bar*](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\"><em>bar</em></a></strong></p>\n",
+    "example": 433,
+    "start_line": 7081,
+    "end_line": 7085,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__ is not an empty emphasis\n",
+    "html": "<p>__ is not an empty emphasis</p>\n",
+    "example": 434,
+    "start_line": 7090,
+    "end_line": 7094,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "____ is not an empty strong emphasis\n",
+    "html": "<p>____ is not an empty strong emphasis</p>\n",
+    "example": 435,
+    "start_line": 7097,
+    "end_line": 7101,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo ***\n",
+    "html": "<p>foo ***</p>\n",
+    "example": 436,
+    "start_line": 7107,
+    "end_line": 7111,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo *\\**\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 437,
+    "start_line": 7114,
+    "end_line": 7118,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo *_*\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 438,
+    "start_line": 7121,
+    "end_line": 7125,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo *****\n",
+    "html": "<p>foo *****</p>\n",
+    "example": 439,
+    "start_line": 7128,
+    "end_line": 7132,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo **\\***\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 440,
+    "start_line": 7135,
+    "end_line": 7139,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo **_**\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 441,
+    "start_line": 7142,
+    "end_line": 7146,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo*\n",
+    "html": "<p>*<em>foo</em></p>\n",
+    "example": 442,
+    "start_line": 7153,
+    "end_line": 7157,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo**\n",
+    "html": "<p><em>foo</em>*</p>\n",
+    "example": 443,
+    "start_line": 7160,
+    "end_line": 7164,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "***foo**\n",
+    "html": "<p>*<strong>foo</strong></p>\n",
+    "example": 444,
+    "start_line": 7167,
+    "end_line": 7171,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "****foo*\n",
+    "html": "<p>***<em>foo</em></p>\n",
+    "example": 445,
+    "start_line": 7174,
+    "end_line": 7178,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo***\n",
+    "html": "<p><strong>foo</strong>*</p>\n",
+    "example": 446,
+    "start_line": 7181,
+    "end_line": 7185,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo****\n",
+    "html": "<p><em>foo</em>***</p>\n",
+    "example": 447,
+    "start_line": 7188,
+    "end_line": 7192,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo ___\n",
+    "html": "<p>foo ___</p>\n",
+    "example": 448,
+    "start_line": 7198,
+    "end_line": 7202,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo _\\__\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 449,
+    "start_line": 7205,
+    "end_line": 7209,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo _*_\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 450,
+    "start_line": 7212,
+    "end_line": 7216,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo _____\n",
+    "html": "<p>foo _____</p>\n",
+    "example": 451,
+    "start_line": 7219,
+    "end_line": 7223,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo __\\___\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 452,
+    "start_line": 7226,
+    "end_line": 7230,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "foo __*__\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 453,
+    "start_line": 7233,
+    "end_line": 7237,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo_\n",
+    "html": "<p>_<em>foo</em></p>\n",
+    "example": 454,
+    "start_line": 7240,
+    "end_line": 7244,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo__\n",
+    "html": "<p><em>foo</em>_</p>\n",
+    "example": 455,
+    "start_line": 7251,
+    "end_line": 7255,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "___foo__\n",
+    "html": "<p>_<strong>foo</strong></p>\n",
+    "example": 456,
+    "start_line": 7258,
+    "end_line": 7262,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "____foo_\n",
+    "html": "<p>___<em>foo</em></p>\n",
+    "example": 457,
+    "start_line": 7265,
+    "end_line": 7269,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo___\n",
+    "html": "<p><strong>foo</strong>_</p>\n",
+    "example": 458,
+    "start_line": 7272,
+    "end_line": 7276,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo____\n",
+    "html": "<p><em>foo</em>___</p>\n",
+    "example": 459,
+    "start_line": 7279,
+    "end_line": 7283,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo**\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 460,
+    "start_line": 7289,
+    "end_line": 7293,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*_foo_*\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 461,
+    "start_line": 7296,
+    "end_line": 7300,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__foo__\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 462,
+    "start_line": 7303,
+    "end_line": 7307,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_*foo*_\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 463,
+    "start_line": 7310,
+    "end_line": 7314,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "****foo****\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 464,
+    "start_line": 7320,
+    "end_line": 7324,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "____foo____\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 465,
+    "start_line": 7327,
+    "end_line": 7331,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "******foo******\n",
+    "html": "<p><strong><strong><strong>foo</strong></strong></strong></p>\n",
+    "example": 466,
+    "start_line": 7338,
+    "end_line": 7342,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "***foo***\n",
+    "html": "<p><em><strong>foo</strong></em></p>\n",
+    "example": 467,
+    "start_line": 7347,
+    "end_line": 7351,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_____foo_____\n",
+    "html": "<p><em><strong><strong>foo</strong></strong></em></p>\n",
+    "example": 468,
+    "start_line": 7354,
+    "end_line": 7358,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo _bar* baz_\n",
+    "html": "<p><em>foo _bar</em> baz_</p>\n",
+    "example": 469,
+    "start_line": 7363,
+    "end_line": 7367,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo __bar *baz bim__ bam*\n",
+    "html": "<p><em>foo <strong>bar *baz bim</strong> bam</em></p>\n",
+    "example": 470,
+    "start_line": 7370,
+    "end_line": 7374,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**foo **bar baz**\n",
+    "html": "<p>**foo <strong>bar baz</strong></p>\n",
+    "example": 471,
+    "start_line": 7379,
+    "end_line": 7383,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*foo *bar baz*\n",
+    "html": "<p>*foo <em>bar baz</em></p>\n",
+    "example": 472,
+    "start_line": 7386,
+    "end_line": 7390,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*[bar*](/url)\n",
+    "html": "<p>*<a href=\"/url\">bar*</a></p>\n",
+    "example": 473,
+    "start_line": 7395,
+    "end_line": 7399,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_foo [bar_](/url)\n",
+    "html": "<p>_foo <a href=\"/url\">bar_</a></p>\n",
+    "example": 474,
+    "start_line": 7402,
+    "end_line": 7406,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*<img src=\"foo\" title=\"*\"/>\n",
+    "html": "<p>*<img src=\"foo\" title=\"*\"/></p>\n",
+    "example": 475,
+    "start_line": 7409,
+    "end_line": 7413,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**<a href=\"**\">\n",
+    "html": "<p>**<a href=\"**\"></p>\n",
+    "example": 476,
+    "start_line": 7416,
+    "end_line": 7420,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__<a href=\"__\">\n",
+    "html": "<p>__<a href=\"__\"></p>\n",
+    "example": 477,
+    "start_line": 7423,
+    "end_line": 7427,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "*a `*`*\n",
+    "html": "<p><em>a <code>*</code></em></p>\n",
+    "example": 478,
+    "start_line": 7430,
+    "end_line": 7434,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "_a `_`_\n",
+    "html": "<p><em>a <code>_</code></em></p>\n",
+    "example": 479,
+    "start_line": 7437,
+    "end_line": 7441,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "**a<https://foo.bar/?q=**>\n",
+    "html": "<p>**a<a href=\"https://foo.bar/?q=**\">https://foo.bar/?q=**</a></p>\n",
+    "example": 480,
+    "start_line": 7444,
+    "end_line": 7448,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "__a<https://foo.bar/?q=__>\n",
+    "html": "<p>__a<a href=\"https://foo.bar/?q=__\">https://foo.bar/?q=__</a></p>\n",
+    "example": 481,
+    "start_line": 7451,
+    "end_line": 7455,
+    "section": "Emphasis and strong emphasis"
+  },
+  {
+    "markdown": "[link](/uri \"title\")\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 482,
+    "start_line": 7539,
+    "end_line": 7543,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/uri)\n",
+    "html": "<p><a href=\"/uri\">link</a></p>\n",
+    "example": 483,
+    "start_line": 7549,
+    "end_line": 7553,
+    "section": "Links"
+  },
+  {
+    "markdown": "[](./target.md)\n",
+    "html": "<p><a href=\"./target.md\"></a></p>\n",
+    "example": 484,
+    "start_line": 7555,
+    "end_line": 7559,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link]()\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 485,
+    "start_line": 7562,
+    "end_line": 7566,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](<>)\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 486,
+    "start_line": 7569,
+    "end_line": 7573,
+    "section": "Links"
+  },
+  {
+    "markdown": "[]()\n",
+    "html": "<p><a href=\"\"></a></p>\n",
+    "example": 487,
+    "start_line": 7576,
+    "end_line": 7580,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/my uri)\n",
+    "html": "<p>[link](/my uri)</p>\n",
+    "example": 488,
+    "start_line": 7585,
+    "end_line": 7589,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](</my uri>)\n",
+    "html": "<p><a href=\"/my%20uri\">link</a></p>\n",
+    "example": 489,
+    "start_line": 7591,
+    "end_line": 7595,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo\nbar)\n",
+    "html": "<p>[link](foo\nbar)</p>\n",
+    "example": 490,
+    "start_line": 7600,
+    "end_line": 7606,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](<foo\nbar>)\n",
+    "html": "<p>[link](<foo\nbar>)</p>\n",
+    "example": 491,
+    "start_line": 7608,
+    "end_line": 7614,
+    "section": "Links"
+  },
+  {
+    "markdown": "[a](<b)c>)\n",
+    "html": "<p><a href=\"b)c\">a</a></p>\n",
+    "example": 492,
+    "start_line": 7619,
+    "end_line": 7623,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](<foo\\>)\n",
+    "html": "<p>[link](&lt;foo&gt;)</p>\n",
+    "example": 493,
+    "start_line": 7627,
+    "end_line": 7631,
+    "section": "Links"
+  },
+  {
+    "markdown": "[a](<b)c\n[a](<b)c>\n[a](<b>c)\n",
+    "html": "<p>[a](&lt;b)c\n[a](&lt;b)c&gt;\n[a](<b>c)</p>\n",
+    "example": 494,
+    "start_line": 7636,
+    "end_line": 7644,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](\\(foo\\))\n",
+    "html": "<p><a href=\"(foo)\">link</a></p>\n",
+    "example": 495,
+    "start_line": 7648,
+    "end_line": 7652,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo(and(bar)))\n",
+    "html": "<p><a href=\"foo(and(bar))\">link</a></p>\n",
+    "example": 496,
+    "start_line": 7657,
+    "end_line": 7661,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo(and(bar))\n",
+    "html": "<p>[link](foo(and(bar))</p>\n",
+    "example": 497,
+    "start_line": 7666,
+    "end_line": 7670,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo\\(and\\(bar\\))\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 498,
+    "start_line": 7673,
+    "end_line": 7677,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](<foo(and(bar)>)\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 499,
+    "start_line": 7680,
+    "end_line": 7684,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo\\)\\:)\n",
+    "html": "<p><a href=\"foo):\">link</a></p>\n",
+    "example": 500,
+    "start_line": 7690,
+    "end_line": 7694,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](#fragment)\n\n[link](https://example.com#fragment)\n\n[link](https://example.com?foo=3#frag)\n",
+    "html": "<p><a href=\"#fragment\">link</a></p>\n<p><a href=\"https://example.com#fragment\">link</a></p>\n<p><a href=\"https://example.com?foo=3#frag\">link</a></p>\n",
+    "example": 501,
+    "start_line": 7699,
+    "end_line": 7709,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo\\bar)\n",
+    "html": "<p><a href=\"foo%5Cbar\">link</a></p>\n",
+    "example": 502,
+    "start_line": 7715,
+    "end_line": 7719,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](foo%20b&auml;)\n",
+    "html": "<p><a href=\"foo%20b%C3%A4\">link</a></p>\n",
+    "example": 503,
+    "start_line": 7731,
+    "end_line": 7735,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](\"title\")\n",
+    "html": "<p><a href=\"%22title%22\">link</a></p>\n",
+    "example": 504,
+    "start_line": 7742,
+    "end_line": 7746,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/url \"title\")\n[link](/url 'title')\n[link](/url (title))\n",
+    "html": "<p><a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a></p>\n",
+    "example": 505,
+    "start_line": 7751,
+    "end_line": 7759,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/url \"title \\\"&quot;\")\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;&quot;\">link</a></p>\n",
+    "example": 506,
+    "start_line": 7765,
+    "end_line": 7769,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/url \"title\")\n",
+    "html": "<p><a href=\"/url%C2%A0%22title%22\">link</a></p>\n",
+    "example": 507,
+    "start_line": 7776,
+    "end_line": 7780,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/url \"title \"and\" title\")\n",
+    "html": "<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>\n",
+    "example": 508,
+    "start_line": 7785,
+    "end_line": 7789,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](/url 'title \"and\" title')\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;and&quot; title\">link</a></p>\n",
+    "example": 509,
+    "start_line": 7794,
+    "end_line": 7798,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link](   /uri\n  \"title\"  )\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 510,
+    "start_line": 7819,
+    "end_line": 7824,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link] (/uri)\n",
+    "html": "<p>[link] (/uri)</p>\n",
+    "example": 511,
+    "start_line": 7830,
+    "end_line": 7834,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link [foo [bar]]](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 512,
+    "start_line": 7840,
+    "end_line": 7844,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link] bar](/uri)\n",
+    "html": "<p>[link] bar](/uri)</p>\n",
+    "example": 513,
+    "start_line": 7847,
+    "end_line": 7851,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link [bar](/uri)\n",
+    "html": "<p>[link <a href=\"/uri\">bar</a></p>\n",
+    "example": 514,
+    "start_line": 7854,
+    "end_line": 7858,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link \\[bar](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 515,
+    "start_line": 7861,
+    "end_line": 7865,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*](/uri)\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 516,
+    "start_line": 7870,
+    "end_line": 7874,
+    "section": "Links"
+  },
+  {
+    "markdown": "[![moon](moon.jpg)](/uri)\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 517,
+    "start_line": 7877,
+    "end_line": 7881,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo [bar](/uri)](/uri)\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>](/uri)</p>\n",
+    "example": 518,
+    "start_line": 7886,
+    "end_line": 7890,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo *[bar [baz](/uri)](/uri)*](/uri)\n",
+    "html": "<p>[foo <em>[bar <a href=\"/uri\">baz</a>](/uri)</em>](/uri)</p>\n",
+    "example": 519,
+    "start_line": 7893,
+    "end_line": 7897,
+    "section": "Links"
+  },
+  {
+    "markdown": "![[[foo](uri1)](uri2)](uri3)\n",
+    "html": "<p><img src=\"uri3\" alt=\"[foo](uri2)\" /></p>\n",
+    "example": 520,
+    "start_line": 7900,
+    "end_line": 7904,
+    "section": "Links"
+  },
+  {
+    "markdown": "*[foo*](/uri)\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 521,
+    "start_line": 7910,
+    "end_line": 7914,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo *bar](baz*)\n",
+    "html": "<p><a href=\"baz*\">foo *bar</a></p>\n",
+    "example": 522,
+    "start_line": 7917,
+    "end_line": 7921,
+    "section": "Links"
+  },
+  {
+    "markdown": "*foo [bar* baz]\n",
+    "html": "<p><em>foo [bar</em> baz]</p>\n",
+    "example": 523,
+    "start_line": 7927,
+    "end_line": 7931,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo <bar attr=\"](baz)\">\n",
+    "html": "<p>[foo <bar attr=\"](baz)\"></p>\n",
+    "example": 524,
+    "start_line": 7937,
+    "end_line": 7941,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo`](/uri)`\n",
+    "html": "<p>[foo<code>](/uri)</code></p>\n",
+    "example": 525,
+    "start_line": 7944,
+    "end_line": 7948,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo<https://example.com/?search=](uri)>\n",
+    "html": "<p>[foo<a href=\"https://example.com/?search=%5D(uri)\">https://example.com/?search=](uri)</a></p>\n",
+    "example": 526,
+    "start_line": 7951,
+    "end_line": 7955,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 527,
+    "start_line": 7989,
+    "end_line": 7995,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link [foo [bar]]][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 528,
+    "start_line": 8004,
+    "end_line": 8010,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link \\[bar][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 529,
+    "start_line": 8013,
+    "end_line": 8019,
+    "section": "Links"
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 530,
+    "start_line": 8024,
+    "end_line": 8030,
+    "section": "Links"
+  },
+  {
+    "markdown": "[![moon](moon.jpg)][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 531,
+    "start_line": 8033,
+    "end_line": 8039,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo [bar](/uri)][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 532,
+    "start_line": 8044,
+    "end_line": 8050,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <em>bar <a href=\"/uri\">baz</a></em>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 533,
+    "start_line": 8053,
+    "end_line": 8059,
+    "section": "Links"
+  },
+  {
+    "markdown": "*[foo*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 534,
+    "start_line": 8068,
+    "end_line": 8074,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo *bar][ref]*\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo *bar</a>*</p>\n",
+    "example": 535,
+    "start_line": 8077,
+    "end_line": 8083,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo <bar attr=\"][ref]\">\n\n[ref]: /uri\n",
+    "html": "<p>[foo <bar attr=\"][ref]\"></p>\n",
+    "example": 536,
+    "start_line": 8089,
+    "end_line": 8095,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo`][ref]`\n\n[ref]: /uri\n",
+    "html": "<p>[foo<code>][ref]</code></p>\n",
+    "example": 537,
+    "start_line": 8098,
+    "end_line": 8104,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo<https://example.com/?search=][ref]>\n\n[ref]: /uri\n",
+    "html": "<p>[foo<a href=\"https://example.com/?search=%5D%5Bref%5D\">https://example.com/?search=][ref]</a></p>\n",
+    "example": 538,
+    "start_line": 8107,
+    "end_line": 8113,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][BaR]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 539,
+    "start_line": 8118,
+    "end_line": 8124,
+    "section": "Links"
+  },
+  {
+    "markdown": "[ẞ]\n\n[SS]: /url\n",
+    "html": "<p><a href=\"/url\">ẞ</a></p>\n",
+    "example": 540,
+    "start_line": 8129,
+    "end_line": 8135,
+    "section": "Links"
+  },
+  {
+    "markdown": "[Foo\n  bar]: /url\n\n[Baz][Foo bar]\n",
+    "html": "<p><a href=\"/url\">Baz</a></p>\n",
+    "example": 541,
+    "start_line": 8141,
+    "end_line": 8148,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo] [bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo] <a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 542,
+    "start_line": 8154,
+    "end_line": 8160,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo]\n[bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo]\n<a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 543,
+    "start_line": 8163,
+    "end_line": 8171,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]\n",
+    "html": "<p><a href=\"/url1\">bar</a></p>\n",
+    "example": 544,
+    "start_line": 8204,
+    "end_line": 8212,
+    "section": "Links"
+  },
+  {
+    "markdown": "[bar][foo\\!]\n\n[foo!]: /url\n",
+    "html": "<p>[bar][foo!]</p>\n",
+    "example": 545,
+    "start_line": 8219,
+    "end_line": 8225,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][ref[]\n\n[ref[]: /uri\n",
+    "html": "<p>[foo][ref[]</p>\n<p>[ref[]: /uri</p>\n",
+    "example": 546,
+    "start_line": 8231,
+    "end_line": 8238,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][ref[bar]]\n\n[ref[bar]]: /uri\n",
+    "html": "<p>[foo][ref[bar]]</p>\n<p>[ref[bar]]: /uri</p>\n",
+    "example": 547,
+    "start_line": 8241,
+    "end_line": 8248,
+    "section": "Links"
+  },
+  {
+    "markdown": "[[[foo]]]\n\n[[[foo]]]: /url\n",
+    "html": "<p>[[[foo]]]</p>\n<p>[[[foo]]]: /url</p>\n",
+    "example": 548,
+    "start_line": 8251,
+    "end_line": 8258,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][ref\\[]\n\n[ref\\[]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo</a></p>\n",
+    "example": 549,
+    "start_line": 8261,
+    "end_line": 8267,
+    "section": "Links"
+  },
+  {
+    "markdown": "[bar\\\\]: /uri\n\n[bar\\\\]\n",
+    "html": "<p><a href=\"/uri\">bar\\</a></p>\n",
+    "example": 550,
+    "start_line": 8272,
+    "end_line": 8278,
+    "section": "Links"
+  },
+  {
+    "markdown": "[]\n\n[]: /uri\n",
+    "html": "<p>[]</p>\n<p>[]: /uri</p>\n",
+    "example": 551,
+    "start_line": 8284,
+    "end_line": 8291,
+    "section": "Links"
+  },
+  {
+    "markdown": "[\n ]\n\n[\n ]: /uri\n",
+    "html": "<p>[\n]</p>\n<p>[\n]: /uri</p>\n",
+    "example": 552,
+    "start_line": 8294,
+    "end_line": 8305,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 553,
+    "start_line": 8317,
+    "end_line": 8323,
+    "section": "Links"
+  },
+  {
+    "markdown": "[*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 554,
+    "start_line": 8326,
+    "end_line": 8332,
+    "section": "Links"
+  },
+  {
+    "markdown": "[Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 555,
+    "start_line": 8337,
+    "end_line": 8343,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a>\n[]</p>\n",
+    "example": 556,
+    "start_line": 8350,
+    "end_line": 8358,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 557,
+    "start_line": 8370,
+    "end_line": 8376,
+    "section": "Links"
+  },
+  {
+    "markdown": "[*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 558,
+    "start_line": 8379,
+    "end_line": 8385,
+    "section": "Links"
+  },
+  {
+    "markdown": "[[*foo* bar]]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p>[<a href=\"/url\" title=\"title\"><em>foo</em> bar</a>]</p>\n",
+    "example": 559,
+    "start_line": 8388,
+    "end_line": 8394,
+    "section": "Links"
+  },
+  {
+    "markdown": "[[bar [foo]\n\n[foo]: /url\n",
+    "html": "<p>[[bar <a href=\"/url\">foo</a></p>\n",
+    "example": 560,
+    "start_line": 8397,
+    "end_line": 8403,
+    "section": "Links"
+  },
+  {
+    "markdown": "[Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 561,
+    "start_line": 8408,
+    "end_line": 8414,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo] bar\n\n[foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a> bar</p>\n",
+    "example": 562,
+    "start_line": 8419,
+    "end_line": 8425,
+    "section": "Links"
+  },
+  {
+    "markdown": "\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>[foo]</p>\n",
+    "example": 563,
+    "start_line": 8431,
+    "end_line": 8437,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo*]: /url\n\n*[foo*]\n",
+    "html": "<p>*<a href=\"/url\">foo*</a></p>\n",
+    "example": 564,
+    "start_line": 8443,
+    "end_line": 8449,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][bar]\n\n[foo]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a></p>\n",
+    "example": 565,
+    "start_line": 8455,
+    "end_line": 8462,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a></p>\n",
+    "example": 566,
+    "start_line": 8464,
+    "end_line": 8470,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo]()\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"\">foo</a></p>\n",
+    "example": 567,
+    "start_line": 8474,
+    "end_line": 8480,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo](not a link)\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a>(not a link)</p>\n",
+    "example": 568,
+    "start_line": 8482,
+    "end_line": 8488,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url\n",
+    "html": "<p>[foo]<a href=\"/url\">bar</a></p>\n",
+    "example": 569,
+    "start_line": 8493,
+    "end_line": 8499,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a><a href=\"/url1\">baz</a></p>\n",
+    "example": 570,
+    "start_line": 8505,
+    "end_line": 8512,
+    "section": "Links"
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2\n",
+    "html": "<p>[foo]<a href=\"/url1\">bar</a></p>\n",
+    "example": 571,
+    "start_line": 8518,
+    "end_line": 8525,
+    "section": "Links"
+  },
+  {
+    "markdown": "![foo](/url \"title\")\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 572,
+    "start_line": 8541,
+    "end_line": 8545,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo *bar*]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 573,
+    "start_line": 8548,
+    "end_line": 8554,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo ![bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 574,
+    "start_line": 8557,
+    "end_line": 8561,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo [bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 575,
+    "start_line": 8564,
+    "end_line": 8568,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo *bar*][]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 576,
+    "start_line": 8578,
+    "end_line": 8584,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 577,
+    "start_line": 8587,
+    "end_line": 8593,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo](train.jpg)\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo\" /></p>\n",
+    "example": 578,
+    "start_line": 8596,
+    "end_line": 8600,
+    "section": "Images"
+  },
+  {
+    "markdown": "My ![foo bar](/path/to/train.jpg  \"title\"   )\n",
+    "html": "<p>My <img src=\"/path/to/train.jpg\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 579,
+    "start_line": 8603,
+    "end_line": 8607,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo](<url>)\n",
+    "html": "<p><img src=\"url\" alt=\"foo\" /></p>\n",
+    "example": 580,
+    "start_line": 8610,
+    "end_line": 8614,
+    "section": "Images"
+  },
+  {
+    "markdown": "![](/url)\n",
+    "html": "<p><img src=\"/url\" alt=\"\" /></p>\n",
+    "example": 581,
+    "start_line": 8617,
+    "end_line": 8621,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo][bar]\n\n[bar]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 582,
+    "start_line": 8626,
+    "end_line": 8632,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo][bar]\n\n[BAR]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 583,
+    "start_line": 8635,
+    "end_line": 8641,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 584,
+    "start_line": 8646,
+    "end_line": 8652,
+    "section": "Images"
+  },
+  {
+    "markdown": "![*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 585,
+    "start_line": 8655,
+    "end_line": 8661,
+    "section": "Images"
+  },
+  {
+    "markdown": "![Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 586,
+    "start_line": 8666,
+    "end_line": 8672,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" />\n[]</p>\n",
+    "example": 587,
+    "start_line": 8678,
+    "end_line": 8686,
+    "section": "Images"
+  },
+  {
+    "markdown": "![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 588,
+    "start_line": 8691,
+    "end_line": 8697,
+    "section": "Images"
+  },
+  {
+    "markdown": "![*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 589,
+    "start_line": 8700,
+    "end_line": 8706,
+    "section": "Images"
+  },
+  {
+    "markdown": "![[foo]]\n\n[[foo]]: /url \"title\"\n",
+    "html": "<p>![[foo]]</p>\n<p>[[foo]]: /url &quot;title&quot;</p>\n",
+    "example": 590,
+    "start_line": 8711,
+    "end_line": 8718,
+    "section": "Images"
+  },
+  {
+    "markdown": "![Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 591,
+    "start_line": 8723,
+    "end_line": 8729,
+    "section": "Images"
+  },
+  {
+    "markdown": "!\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>![foo]</p>\n",
+    "example": 592,
+    "start_line": 8735,
+    "end_line": 8741,
+    "section": "Images"
+  },
+  {
+    "markdown": "\\![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>!<a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 593,
+    "start_line": 8747,
+    "end_line": 8753,
+    "section": "Images"
+  },
+  {
+    "markdown": "<http://foo.bar.baz>\n",
+    "html": "<p><a href=\"http://foo.bar.baz\">http://foo.bar.baz</a></p>\n",
+    "example": 594,
+    "start_line": 8780,
+    "end_line": 8784,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<https://foo.bar.baz/test?q=hello&id=22&boolean>\n",
+    "html": "<p><a href=\"https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean\">https://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>\n",
+    "example": 595,
+    "start_line": 8787,
+    "end_line": 8791,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<irc://foo.bar:2233/baz>\n",
+    "html": "<p><a href=\"irc://foo.bar:2233/baz\">irc://foo.bar:2233/baz</a></p>\n",
+    "example": 596,
+    "start_line": 8794,
+    "end_line": 8798,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<MAILTO:FOO@BAR.BAZ>\n",
+    "html": "<p><a href=\"MAILTO:FOO@BAR.BAZ\">MAILTO:FOO@BAR.BAZ</a></p>\n",
+    "example": 597,
+    "start_line": 8803,
+    "end_line": 8807,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<a+b+c:d>\n",
+    "html": "<p><a href=\"a+b+c:d\">a+b+c:d</a></p>\n",
+    "example": 598,
+    "start_line": 8815,
+    "end_line": 8819,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<made-up-scheme://foo,bar>\n",
+    "html": "<p><a href=\"made-up-scheme://foo,bar\">made-up-scheme://foo,bar</a></p>\n",
+    "example": 599,
+    "start_line": 8822,
+    "end_line": 8826,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<https://../>\n",
+    "html": "<p><a href=\"https://../\">https://../</a></p>\n",
+    "example": 600,
+    "start_line": 8829,
+    "end_line": 8833,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<localhost:5001/foo>\n",
+    "html": "<p><a href=\"localhost:5001/foo\">localhost:5001/foo</a></p>\n",
+    "example": 601,
+    "start_line": 8836,
+    "end_line": 8840,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<https://foo.bar/baz bim>\n",
+    "html": "<p>&lt;https://foo.bar/baz bim&gt;</p>\n",
+    "example": 602,
+    "start_line": 8845,
+    "end_line": 8849,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<https://example.com/\\[\\>\n",
+    "html": "<p><a href=\"https://example.com/%5C%5B%5C\">https://example.com/\\[\\</a></p>\n",
+    "example": 603,
+    "start_line": 8854,
+    "end_line": 8858,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<foo@bar.example.com>\n",
+    "html": "<p><a href=\"mailto:foo@bar.example.com\">foo@bar.example.com</a></p>\n",
+    "example": 604,
+    "start_line": 8876,
+    "end_line": 8880,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<foo+special@Bar.baz-bar0.com>\n",
+    "html": "<p><a href=\"mailto:foo+special@Bar.baz-bar0.com\">foo+special@Bar.baz-bar0.com</a></p>\n",
+    "example": 605,
+    "start_line": 8883,
+    "end_line": 8887,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<foo\\+@bar.example.com>\n",
+    "html": "<p>&lt;foo+@bar.example.com&gt;</p>\n",
+    "example": 606,
+    "start_line": 8892,
+    "end_line": 8896,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<>\n",
+    "html": "<p>&lt;&gt;</p>\n",
+    "example": 607,
+    "start_line": 8901,
+    "end_line": 8905,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "< https://foo.bar >\n",
+    "html": "<p>&lt; https://foo.bar &gt;</p>\n",
+    "example": 608,
+    "start_line": 8908,
+    "end_line": 8912,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<m:abc>\n",
+    "html": "<p>&lt;m:abc&gt;</p>\n",
+    "example": 609,
+    "start_line": 8915,
+    "end_line": 8919,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<foo.bar.baz>\n",
+    "html": "<p>&lt;foo.bar.baz&gt;</p>\n",
+    "example": 610,
+    "start_line": 8922,
+    "end_line": 8926,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "https://example.com\n",
+    "html": "<p>https://example.com</p>\n",
+    "example": 611,
+    "start_line": 8929,
+    "end_line": 8933,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "foo@bar.example.com\n",
+    "html": "<p>foo@bar.example.com</p>\n",
+    "example": 612,
+    "start_line": 8936,
+    "end_line": 8940,
+    "section": "Autolinks"
+  },
+  {
+    "markdown": "<a><bab><c2c>\n",
+    "html": "<p><a><bab><c2c></p>\n",
+    "example": 613,
+    "start_line": 9016,
+    "end_line": 9020,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a/><b2/>\n",
+    "html": "<p><a/><b2/></p>\n",
+    "example": 614,
+    "start_line": 9025,
+    "end_line": 9029,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a  /><b2\ndata=\"foo\" >\n",
+    "html": "<p><a  /><b2\ndata=\"foo\" ></p>\n",
+    "example": 615,
+    "start_line": 9034,
+    "end_line": 9040,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 />\n",
+    "html": "<p><a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 /></p>\n",
+    "example": 616,
+    "start_line": 9045,
+    "end_line": 9051,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "Foo <responsive-image src=\"foo.jpg\" />\n",
+    "html": "<p>Foo <responsive-image src=\"foo.jpg\" /></p>\n",
+    "example": 617,
+    "start_line": 9056,
+    "end_line": 9060,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<33> <__>\n",
+    "html": "<p>&lt;33&gt; &lt;__&gt;</p>\n",
+    "example": 618,
+    "start_line": 9065,
+    "end_line": 9069,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a h*#ref=\"hi\">\n",
+    "html": "<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>\n",
+    "example": 619,
+    "start_line": 9074,
+    "end_line": 9078,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a href=\"hi'> <a href=hi'>\n",
+    "html": "<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>\n",
+    "example": 620,
+    "start_line": 9083,
+    "end_line": 9087,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "< a><\nfoo><bar/ >\n<foo bar=baz\nbim!bop />\n",
+    "html": "<p>&lt; a&gt;&lt;\nfoo&gt;&lt;bar/ &gt;\n&lt;foo bar=baz\nbim!bop /&gt;</p>\n",
+    "example": 621,
+    "start_line": 9092,
+    "end_line": 9102,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a href='bar'title=title>\n",
+    "html": "<p>&lt;a href='bar'title=title&gt;</p>\n",
+    "example": 622,
+    "start_line": 9107,
+    "end_line": 9111,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "</a></foo >\n",
+    "html": "<p></a></foo ></p>\n",
+    "example": 623,
+    "start_line": 9116,
+    "end_line": 9120,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "</a href=\"foo\">\n",
+    "html": "<p>&lt;/a href=&quot;foo&quot;&gt;</p>\n",
+    "example": 624,
+    "start_line": 9125,
+    "end_line": 9129,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <!-- this is a --\ncomment - with hyphens -->\n",
+    "html": "<p>foo <!-- this is a --\ncomment - with hyphens --></p>\n",
+    "example": 625,
+    "start_line": 9134,
+    "end_line": 9140,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <!--> foo -->\n\nfoo <!---> foo -->\n",
+    "html": "<p>foo <!--> foo --&gt;</p>\n<p>foo <!---> foo --&gt;</p>\n",
+    "example": 626,
+    "start_line": 9142,
+    "end_line": 9149,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <?php echo $a; ?>\n",
+    "html": "<p>foo <?php echo $a; ?></p>\n",
+    "example": 627,
+    "start_line": 9154,
+    "end_line": 9158,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <!ELEMENT br EMPTY>\n",
+    "html": "<p>foo <!ELEMENT br EMPTY></p>\n",
+    "example": 628,
+    "start_line": 9163,
+    "end_line": 9167,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <![CDATA[>&<]]>\n",
+    "html": "<p>foo <![CDATA[>&<]]></p>\n",
+    "example": 629,
+    "start_line": 9172,
+    "end_line": 9176,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <a href=\"&ouml;\">\n",
+    "html": "<p>foo <a href=\"&ouml;\"></p>\n",
+    "example": 630,
+    "start_line": 9182,
+    "end_line": 9186,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo <a href=\"\\*\">\n",
+    "html": "<p>foo <a href=\"\\*\"></p>\n",
+    "example": 631,
+    "start_line": 9191,
+    "end_line": 9195,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "<a href=\"\\\"\">\n",
+    "html": "<p>&lt;a href=&quot;&quot;&quot;&gt;</p>\n",
+    "example": 632,
+    "start_line": 9198,
+    "end_line": 9202,
+    "section": "Raw HTML"
+  },
+  {
+    "markdown": "foo  \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 633,
+    "start_line": 9212,
+    "end_line": 9218,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo\\\nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 634,
+    "start_line": 9224,
+    "end_line": 9230,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo       \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 635,
+    "start_line": 9235,
+    "end_line": 9241,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo  \n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 636,
+    "start_line": 9246,
+    "end_line": 9252,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo\\\n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 637,
+    "start_line": 9255,
+    "end_line": 9261,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "*foo  \nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 638,
+    "start_line": 9267,
+    "end_line": 9273,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "*foo\\\nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 639,
+    "start_line": 9276,
+    "end_line": 9282,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "`code  \nspan`\n",
+    "html": "<p><code>code   span</code></p>\n",
+    "example": 640,
+    "start_line": 9287,
+    "end_line": 9292,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "`code\\\nspan`\n",
+    "html": "<p><code>code\\ span</code></p>\n",
+    "example": 641,
+    "start_line": 9295,
+    "end_line": 9300,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "<a href=\"foo  \nbar\">\n",
+    "html": "<p><a href=\"foo  \nbar\"></p>\n",
+    "example": 642,
+    "start_line": 9305,
+    "end_line": 9311,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "<a href=\"foo\\\nbar\">\n",
+    "html": "<p><a href=\"foo\\\nbar\"></p>\n",
+    "example": 643,
+    "start_line": 9314,
+    "end_line": 9320,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo\\\n",
+    "html": "<p>foo\\</p>\n",
+    "example": 644,
+    "start_line": 9327,
+    "end_line": 9331,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo  \n",
+    "html": "<p>foo</p>\n",
+    "example": 645,
+    "start_line": 9334,
+    "end_line": 9338,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "### foo\\\n",
+    "html": "<h3>foo\\</h3>\n",
+    "example": 646,
+    "start_line": 9341,
+    "end_line": 9345,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "### foo  \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 647,
+    "start_line": 9348,
+    "end_line": 9352,
+    "section": "Hard line breaks"
+  },
+  {
+    "markdown": "foo\nbaz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 648,
+    "start_line": 9363,
+    "end_line": 9369,
+    "section": "Soft line breaks"
+  },
+  {
+    "markdown": "foo \n baz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 649,
+    "start_line": 9375,
+    "end_line": 9381,
+    "section": "Soft line breaks"
+  },
+  {
+    "markdown": "hello $.;'there\n",
+    "html": "<p>hello $.;'there</p>\n",
+    "example": 650,
+    "start_line": 9395,
+    "end_line": 9399,
+    "section": "Textual content"
+  },
+  {
+    "markdown": "Foo χρῆν\n",
+    "html": "<p>Foo χρῆν</p>\n",
+    "example": 651,
+    "start_line": 9402,
+    "end_line": 9406,
+    "section": "Textual content"
+  },
+  {
+    "markdown": "Multiple     spaces\n",
+    "html": "<p>Multiple     spaces</p>\n",
+    "example": 652,
+    "start_line": 9411,
+    "end_line": 9415,
+    "section": "Textual content"
+  }
+]
\ No newline at end of file
diff --git a/pkgs/markdown/tool/dartdoc_compare.dart b/pkgs/markdown/tool/dartdoc_compare.dart
new file mode 100644
index 0000000..e6100ee
--- /dev/null
+++ b/pkgs/markdown/tool/dartdoc_compare.dart
@@ -0,0 +1,189 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:io' show Directory, File, Platform, Process, exitCode;
+
+import 'package:args/args.dart' show ArgParser;
+import 'package:path/path.dart' show absolute;
+import 'package:yaml/yaml.dart' show loadYaml;
+
+const _dartdocDir = 'dartdoc-dir';
+const _markdownBefore = 'before';
+const _markdownAfter = 'after';
+const _sdk = 'sdk';
+const _help = 'help';
+
+void main(List<String> arguments) {
+  final parser = ArgParser()
+    ..addSeparator('Usage: dartdoc-compare.dart [OPTIONS] <dart-package>')
+    ..addOption(_dartdocDir, help: 'Directory of the dartdoc package')
+    ..addOption(_markdownBefore, help: "Markdown package 'before' ref")
+    ..addOption(
+      _markdownAfter,
+      defaultsTo: 'HEAD',
+      help: "Markdown package 'after' ref (or 'local')",
+    )
+    ..addFlag(
+      _sdk,
+      negatable: false,
+      help: 'Is the package the SDK?',
+    )
+    ..addFlag(_help, abbr: 'h', hide: true);
+
+  final options = parser.parse(arguments);
+  if (options[_help] as bool) {
+    print(parser.usage);
+    exitCode = 0;
+    return;
+  }
+  if (options[_dartdocDir] == null || options[_markdownBefore] == null) {
+    print(
+      'Invalid arguments: Options --$_dartdocDir and --$_markdownBefore '
+      'must be specified',
+    );
+    print(parser.usage);
+    exitCode = 1;
+    return;
+  }
+  final comparer = DartdocCompare(
+    options[_dartdocDir] as String,
+    options[_markdownBefore] as String,
+    options[_markdownAfter] as String,
+    absolute(options[_dartdocDir] as String, 'bin/dartdoc.dart'),
+    absolute(options[_dartdocDir] as String, 'pubspec.yaml'),
+    options[_sdk] as bool,
+  );
+
+  String? path;
+  if (comparer.sdk) {
+    if (options.rest.isNotEmpty) {
+      path = options.rest.single;
+    }
+  } else {
+    path = options.rest.single;
+  }
+
+  if (comparer.compare(path)) {
+    exitCode = 0;
+  } else {
+    exitCode = 1;
+  }
+}
+
+class DartdocCompare {
+  final String dartdocDir;
+  final String markdownBefore;
+  final String markdownAfter;
+  final String dartdocBin;
+  final String dartdocPubspecPath;
+  final bool sdk;
+  final String markdownPath = File(Platform.script.path).parent.parent.path;
+
+  DartdocCompare(
+    this.dartdocDir,
+    this.markdownBefore,
+    this.markdownAfter,
+    this.dartdocBin,
+    this.dartdocPubspecPath,
+    this.sdk,
+  );
+
+  bool compare(String? package) {
+    // Generate docs with Markdown "Before".
+    final outBefore = _runDartdoc(markdownBefore, package);
+
+    // Generate docs with Markdown "After".
+    final outAfter = _runDartdoc(markdownAfter, package);
+
+    // Compare outputs
+    final diffOptions = ['-r', '-B', outBefore, outAfter];
+    final result = Process.runSync('diff', diffOptions, runInShell: true);
+    final nlines = '\n'.allMatches(result.stdout as String).length;
+    print('Diff lines: $nlines');
+    print('diff ${diffOptions.join(" ")}');
+    return result.exitCode == 0;
+  }
+
+  String _runDartdoc(String markdownRef, String? path) {
+    print('==========================================================');
+    print('Running dartdoc for $markdownRef...');
+    print('==========================================================');
+    _doInPath(dartdocDir, () {
+      final returnCode = _updateDartdocPubspec(markdownRef);
+      if (returnCode != 0) {
+        throw Exception("Could not update dartdoc's pubspec!");
+      }
+    });
+    return _doInPath(path, () {
+      if (!sdk) {
+        _system('pub', ['upgrade']);
+      }
+      final out = Directory.systemTemp
+          .createTempSync('dartdoc-compare-${markdownRef}__');
+      const cmd = 'dart';
+      final args = [dartdocBin, '--output=${out.path}'];
+
+      if (sdk) {
+        args.add('--sdk-docs');
+      }
+
+      print('Command: $cmd ${args.join(' ')}');
+      final startTime = DateTime.now();
+      _system(cmd, args);
+      final endTime = DateTime.now();
+      final duration = endTime.difference(startTime).inSeconds;
+      print('dartdoc generation for $markdownRef took $duration seconds.');
+      print('');
+
+      return out.path;
+    });
+  }
+
+  int _updateDartdocPubspec(String markdownRef) {
+    var dartdocPubspec =
+        loadYaml(File(dartdocPubspecPath).readAsStringSync()) as Map;
+    // make modifiable copy
+    dartdocPubspec = jsonDecode(jsonEncode(dartdocPubspec)) as Map;
+
+    final dependencies = dartdocPubspec['dependencies'] as Map;
+
+    if (markdownRef == 'local') {
+      dependencies['markdown'] = {
+        'path': markdownPath,
+      };
+    } else {
+      dependencies['markdown'] = {
+        'git': {
+          'url': 'git://github.com/dart-lang/markdown.git',
+          'ref': markdownRef
+        }
+      };
+    }
+
+    File(dartdocPubspecPath).writeAsStringSync(jsonEncode(dartdocPubspec));
+    return _system('pub', ['upgrade']);
+  }
+}
+
+int _system(String cmd, List<String> args) {
+  final result = Process.runSync(cmd, args);
+  print(result.stdout);
+  print(result.stderr);
+  return result.exitCode;
+}
+
+T _doInPath<T>(String? path, T Function() f) {
+  if (path == null) {
+    return f();
+  }
+
+  final former = Directory.current.path;
+  Directory.current = path;
+  try {
+    return f();
+  } finally {
+    Directory.current = former;
+  }
+}
diff --git a/pkgs/markdown/tool/entities.json b/pkgs/markdown/tool/entities.json
new file mode 100644
index 0000000..557170b
--- /dev/null
+++ b/pkgs/markdown/tool/entities.json
@@ -0,0 +1,2233 @@
+{
+  "&AElig": { "codepoints": [198], "characters": "\u00C6" },
+  "&AElig;": { "codepoints": [198], "characters": "\u00C6" },
+  "&AMP": { "codepoints": [38], "characters": "\u0026" },
+  "&AMP;": { "codepoints": [38], "characters": "\u0026" },
+  "&Aacute": { "codepoints": [193], "characters": "\u00C1" },
+  "&Aacute;": { "codepoints": [193], "characters": "\u00C1" },
+  "&Abreve;": { "codepoints": [258], "characters": "\u0102" },
+  "&Acirc": { "codepoints": [194], "characters": "\u00C2" },
+  "&Acirc;": { "codepoints": [194], "characters": "\u00C2" },
+  "&Acy;": { "codepoints": [1040], "characters": "\u0410" },
+  "&Afr;": { "codepoints": [120068], "characters": "\uD835\uDD04" },
+  "&Agrave": { "codepoints": [192], "characters": "\u00C0" },
+  "&Agrave;": { "codepoints": [192], "characters": "\u00C0" },
+  "&Alpha;": { "codepoints": [913], "characters": "\u0391" },
+  "&Amacr;": { "codepoints": [256], "characters": "\u0100" },
+  "&And;": { "codepoints": [10835], "characters": "\u2A53" },
+  "&Aogon;": { "codepoints": [260], "characters": "\u0104" },
+  "&Aopf;": { "codepoints": [120120], "characters": "\uD835\uDD38" },
+  "&ApplyFunction;": { "codepoints": [8289], "characters": "\u2061" },
+  "&Aring": { "codepoints": [197], "characters": "\u00C5" },
+  "&Aring;": { "codepoints": [197], "characters": "\u00C5" },
+  "&Ascr;": { "codepoints": [119964], "characters": "\uD835\uDC9C" },
+  "&Assign;": { "codepoints": [8788], "characters": "\u2254" },
+  "&Atilde": { "codepoints": [195], "characters": "\u00C3" },
+  "&Atilde;": { "codepoints": [195], "characters": "\u00C3" },
+  "&Auml": { "codepoints": [196], "characters": "\u00C4" },
+  "&Auml;": { "codepoints": [196], "characters": "\u00C4" },
+  "&Backslash;": { "codepoints": [8726], "characters": "\u2216" },
+  "&Barv;": { "codepoints": [10983], "characters": "\u2AE7" },
+  "&Barwed;": { "codepoints": [8966], "characters": "\u2306" },
+  "&Bcy;": { "codepoints": [1041], "characters": "\u0411" },
+  "&Because;": { "codepoints": [8757], "characters": "\u2235" },
+  "&Bernoullis;": { "codepoints": [8492], "characters": "\u212C" },
+  "&Beta;": { "codepoints": [914], "characters": "\u0392" },
+  "&Bfr;": { "codepoints": [120069], "characters": "\uD835\uDD05" },
+  "&Bopf;": { "codepoints": [120121], "characters": "\uD835\uDD39" },
+  "&Breve;": { "codepoints": [728], "characters": "\u02D8" },
+  "&Bscr;": { "codepoints": [8492], "characters": "\u212C" },
+  "&Bumpeq;": { "codepoints": [8782], "characters": "\u224E" },
+  "&CHcy;": { "codepoints": [1063], "characters": "\u0427" },
+  "&COPY": { "codepoints": [169], "characters": "\u00A9" },
+  "&COPY;": { "codepoints": [169], "characters": "\u00A9" },
+  "&Cacute;": { "codepoints": [262], "characters": "\u0106" },
+  "&Cap;": { "codepoints": [8914], "characters": "\u22D2" },
+  "&CapitalDifferentialD;": { "codepoints": [8517], "characters": "\u2145" },
+  "&Cayleys;": { "codepoints": [8493], "characters": "\u212D" },
+  "&Ccaron;": { "codepoints": [268], "characters": "\u010C" },
+  "&Ccedil": { "codepoints": [199], "characters": "\u00C7" },
+  "&Ccedil;": { "codepoints": [199], "characters": "\u00C7" },
+  "&Ccirc;": { "codepoints": [264], "characters": "\u0108" },
+  "&Cconint;": { "codepoints": [8752], "characters": "\u2230" },
+  "&Cdot;": { "codepoints": [266], "characters": "\u010A" },
+  "&Cedilla;": { "codepoints": [184], "characters": "\u00B8" },
+  "&CenterDot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&Cfr;": { "codepoints": [8493], "characters": "\u212D" },
+  "&Chi;": { "codepoints": [935], "characters": "\u03A7" },
+  "&CircleDot;": { "codepoints": [8857], "characters": "\u2299" },
+  "&CircleMinus;": { "codepoints": [8854], "characters": "\u2296" },
+  "&CirclePlus;": { "codepoints": [8853], "characters": "\u2295" },
+  "&CircleTimes;": { "codepoints": [8855], "characters": "\u2297" },
+  "&ClockwiseContourIntegral;": { "codepoints": [8754], "characters": "\u2232" },
+  "&CloseCurlyDoubleQuote;": { "codepoints": [8221], "characters": "\u201D" },
+  "&CloseCurlyQuote;": { "codepoints": [8217], "characters": "\u2019" },
+  "&Colon;": { "codepoints": [8759], "characters": "\u2237" },
+  "&Colone;": { "codepoints": [10868], "characters": "\u2A74" },
+  "&Congruent;": { "codepoints": [8801], "characters": "\u2261" },
+  "&Conint;": { "codepoints": [8751], "characters": "\u222F" },
+  "&ContourIntegral;": { "codepoints": [8750], "characters": "\u222E" },
+  "&Copf;": { "codepoints": [8450], "characters": "\u2102" },
+  "&Coproduct;": { "codepoints": [8720], "characters": "\u2210" },
+  "&CounterClockwiseContourIntegral;": { "codepoints": [8755], "characters": "\u2233" },
+  "&Cross;": { "codepoints": [10799], "characters": "\u2A2F" },
+  "&Cscr;": { "codepoints": [119966], "characters": "\uD835\uDC9E" },
+  "&Cup;": { "codepoints": [8915], "characters": "\u22D3" },
+  "&CupCap;": { "codepoints": [8781], "characters": "\u224D" },
+  "&DD;": { "codepoints": [8517], "characters": "\u2145" },
+  "&DDotrahd;": { "codepoints": [10513], "characters": "\u2911" },
+  "&DJcy;": { "codepoints": [1026], "characters": "\u0402" },
+  "&DScy;": { "codepoints": [1029], "characters": "\u0405" },
+  "&DZcy;": { "codepoints": [1039], "characters": "\u040F" },
+  "&Dagger;": { "codepoints": [8225], "characters": "\u2021" },
+  "&Darr;": { "codepoints": [8609], "characters": "\u21A1" },
+  "&Dashv;": { "codepoints": [10980], "characters": "\u2AE4" },
+  "&Dcaron;": { "codepoints": [270], "characters": "\u010E" },
+  "&Dcy;": { "codepoints": [1044], "characters": "\u0414" },
+  "&Del;": { "codepoints": [8711], "characters": "\u2207" },
+  "&Delta;": { "codepoints": [916], "characters": "\u0394" },
+  "&Dfr;": { "codepoints": [120071], "characters": "\uD835\uDD07" },
+  "&DiacriticalAcute;": { "codepoints": [180], "characters": "\u00B4" },
+  "&DiacriticalDot;": { "codepoints": [729], "characters": "\u02D9" },
+  "&DiacriticalDoubleAcute;": { "codepoints": [733], "characters": "\u02DD" },
+  "&DiacriticalGrave;": { "codepoints": [96], "characters": "\u0060" },
+  "&DiacriticalTilde;": { "codepoints": [732], "characters": "\u02DC" },
+  "&Diamond;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&DifferentialD;": { "codepoints": [8518], "characters": "\u2146" },
+  "&Dopf;": { "codepoints": [120123], "characters": "\uD835\uDD3B" },
+  "&Dot;": { "codepoints": [168], "characters": "\u00A8" },
+  "&DotDot;": { "codepoints": [8412], "characters": "\u20DC" },
+  "&DotEqual;": { "codepoints": [8784], "characters": "\u2250" },
+  "&DoubleContourIntegral;": { "codepoints": [8751], "characters": "\u222F" },
+  "&DoubleDot;": { "codepoints": [168], "characters": "\u00A8" },
+  "&DoubleDownArrow;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&DoubleLeftArrow;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&DoubleLeftRightArrow;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&DoubleLeftTee;": { "codepoints": [10980], "characters": "\u2AE4" },
+  "&DoubleLongLeftArrow;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&DoubleLongLeftRightArrow;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&DoubleLongRightArrow;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&DoubleRightArrow;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&DoubleRightTee;": { "codepoints": [8872], "characters": "\u22A8" },
+  "&DoubleUpArrow;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&DoubleUpDownArrow;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&DoubleVerticalBar;": { "codepoints": [8741], "characters": "\u2225" },
+  "&DownArrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&DownArrowBar;": { "codepoints": [10515], "characters": "\u2913" },
+  "&DownArrowUpArrow;": { "codepoints": [8693], "characters": "\u21F5" },
+  "&DownBreve;": { "codepoints": [785], "characters": "\u0311" },
+  "&DownLeftRightVector;": { "codepoints": [10576], "characters": "\u2950" },
+  "&DownLeftTeeVector;": { "codepoints": [10590], "characters": "\u295E" },
+  "&DownLeftVector;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&DownLeftVectorBar;": { "codepoints": [10582], "characters": "\u2956" },
+  "&DownRightTeeVector;": { "codepoints": [10591], "characters": "\u295F" },
+  "&DownRightVector;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&DownRightVectorBar;": { "codepoints": [10583], "characters": "\u2957" },
+  "&DownTee;": { "codepoints": [8868], "characters": "\u22A4" },
+  "&DownTeeArrow;": { "codepoints": [8615], "characters": "\u21A7" },
+  "&Downarrow;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&Dscr;": { "codepoints": [119967], "characters": "\uD835\uDC9F" },
+  "&Dstrok;": { "codepoints": [272], "characters": "\u0110" },
+  "&ENG;": { "codepoints": [330], "characters": "\u014A" },
+  "&ETH": { "codepoints": [208], "characters": "\u00D0" },
+  "&ETH;": { "codepoints": [208], "characters": "\u00D0" },
+  "&Eacute": { "codepoints": [201], "characters": "\u00C9" },
+  "&Eacute;": { "codepoints": [201], "characters": "\u00C9" },
+  "&Ecaron;": { "codepoints": [282], "characters": "\u011A" },
+  "&Ecirc": { "codepoints": [202], "characters": "\u00CA" },
+  "&Ecirc;": { "codepoints": [202], "characters": "\u00CA" },
+  "&Ecy;": { "codepoints": [1069], "characters": "\u042D" },
+  "&Edot;": { "codepoints": [278], "characters": "\u0116" },
+  "&Efr;": { "codepoints": [120072], "characters": "\uD835\uDD08" },
+  "&Egrave": { "codepoints": [200], "characters": "\u00C8" },
+  "&Egrave;": { "codepoints": [200], "characters": "\u00C8" },
+  "&Element;": { "codepoints": [8712], "characters": "\u2208" },
+  "&Emacr;": { "codepoints": [274], "characters": "\u0112" },
+  "&EmptySmallSquare;": { "codepoints": [9723], "characters": "\u25FB" },
+  "&EmptyVerySmallSquare;": { "codepoints": [9643], "characters": "\u25AB" },
+  "&Eogon;": { "codepoints": [280], "characters": "\u0118" },
+  "&Eopf;": { "codepoints": [120124], "characters": "\uD835\uDD3C" },
+  "&Epsilon;": { "codepoints": [917], "characters": "\u0395" },
+  "&Equal;": { "codepoints": [10869], "characters": "\u2A75" },
+  "&EqualTilde;": { "codepoints": [8770], "characters": "\u2242" },
+  "&Equilibrium;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&Escr;": { "codepoints": [8496], "characters": "\u2130" },
+  "&Esim;": { "codepoints": [10867], "characters": "\u2A73" },
+  "&Eta;": { "codepoints": [919], "characters": "\u0397" },
+  "&Euml": { "codepoints": [203], "characters": "\u00CB" },
+  "&Euml;": { "codepoints": [203], "characters": "\u00CB" },
+  "&Exists;": { "codepoints": [8707], "characters": "\u2203" },
+  "&ExponentialE;": { "codepoints": [8519], "characters": "\u2147" },
+  "&Fcy;": { "codepoints": [1060], "characters": "\u0424" },
+  "&Ffr;": { "codepoints": [120073], "characters": "\uD835\uDD09" },
+  "&FilledSmallSquare;": { "codepoints": [9724], "characters": "\u25FC" },
+  "&FilledVerySmallSquare;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&Fopf;": { "codepoints": [120125], "characters": "\uD835\uDD3D" },
+  "&ForAll;": { "codepoints": [8704], "characters": "\u2200" },
+  "&Fouriertrf;": { "codepoints": [8497], "characters": "\u2131" },
+  "&Fscr;": { "codepoints": [8497], "characters": "\u2131" },
+  "&GJcy;": { "codepoints": [1027], "characters": "\u0403" },
+  "&GT": { "codepoints": [62], "characters": "\u003E" },
+  "&GT;": { "codepoints": [62], "characters": "\u003E" },
+  "&Gamma;": { "codepoints": [915], "characters": "\u0393" },
+  "&Gammad;": { "codepoints": [988], "characters": "\u03DC" },
+  "&Gbreve;": { "codepoints": [286], "characters": "\u011E" },
+  "&Gcedil;": { "codepoints": [290], "characters": "\u0122" },
+  "&Gcirc;": { "codepoints": [284], "characters": "\u011C" },
+  "&Gcy;": { "codepoints": [1043], "characters": "\u0413" },
+  "&Gdot;": { "codepoints": [288], "characters": "\u0120" },
+  "&Gfr;": { "codepoints": [120074], "characters": "\uD835\uDD0A" },
+  "&Gg;": { "codepoints": [8921], "characters": "\u22D9" },
+  "&Gopf;": { "codepoints": [120126], "characters": "\uD835\uDD3E" },
+  "&GreaterEqual;": { "codepoints": [8805], "characters": "\u2265" },
+  "&GreaterEqualLess;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&GreaterFullEqual;": { "codepoints": [8807], "characters": "\u2267" },
+  "&GreaterGreater;": { "codepoints": [10914], "characters": "\u2AA2" },
+  "&GreaterLess;": { "codepoints": [8823], "characters": "\u2277" },
+  "&GreaterSlantEqual;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&GreaterTilde;": { "codepoints": [8819], "characters": "\u2273" },
+  "&Gscr;": { "codepoints": [119970], "characters": "\uD835\uDCA2" },
+  "&Gt;": { "codepoints": [8811], "characters": "\u226B" },
+  "&HARDcy;": { "codepoints": [1066], "characters": "\u042A" },
+  "&Hacek;": { "codepoints": [711], "characters": "\u02C7" },
+  "&Hat;": { "codepoints": [94], "characters": "\u005E" },
+  "&Hcirc;": { "codepoints": [292], "characters": "\u0124" },
+  "&Hfr;": { "codepoints": [8460], "characters": "\u210C" },
+  "&HilbertSpace;": { "codepoints": [8459], "characters": "\u210B" },
+  "&Hopf;": { "codepoints": [8461], "characters": "\u210D" },
+  "&HorizontalLine;": { "codepoints": [9472], "characters": "\u2500" },
+  "&Hscr;": { "codepoints": [8459], "characters": "\u210B" },
+  "&Hstrok;": { "codepoints": [294], "characters": "\u0126" },
+  "&HumpDownHump;": { "codepoints": [8782], "characters": "\u224E" },
+  "&HumpEqual;": { "codepoints": [8783], "characters": "\u224F" },
+  "&IEcy;": { "codepoints": [1045], "characters": "\u0415" },
+  "&IJlig;": { "codepoints": [306], "characters": "\u0132" },
+  "&IOcy;": { "codepoints": [1025], "characters": "\u0401" },
+  "&Iacute": { "codepoints": [205], "characters": "\u00CD" },
+  "&Iacute;": { "codepoints": [205], "characters": "\u00CD" },
+  "&Icirc": { "codepoints": [206], "characters": "\u00CE" },
+  "&Icirc;": { "codepoints": [206], "characters": "\u00CE" },
+  "&Icy;": { "codepoints": [1048], "characters": "\u0418" },
+  "&Idot;": { "codepoints": [304], "characters": "\u0130" },
+  "&Ifr;": { "codepoints": [8465], "characters": "\u2111" },
+  "&Igrave": { "codepoints": [204], "characters": "\u00CC" },
+  "&Igrave;": { "codepoints": [204], "characters": "\u00CC" },
+  "&Im;": { "codepoints": [8465], "characters": "\u2111" },
+  "&Imacr;": { "codepoints": [298], "characters": "\u012A" },
+  "&ImaginaryI;": { "codepoints": [8520], "characters": "\u2148" },
+  "&Implies;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&Int;": { "codepoints": [8748], "characters": "\u222C" },
+  "&Integral;": { "codepoints": [8747], "characters": "\u222B" },
+  "&Intersection;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&InvisibleComma;": { "codepoints": [8291], "characters": "\u2063" },
+  "&InvisibleTimes;": { "codepoints": [8290], "characters": "\u2062" },
+  "&Iogon;": { "codepoints": [302], "characters": "\u012E" },
+  "&Iopf;": { "codepoints": [120128], "characters": "\uD835\uDD40" },
+  "&Iota;": { "codepoints": [921], "characters": "\u0399" },
+  "&Iscr;": { "codepoints": [8464], "characters": "\u2110" },
+  "&Itilde;": { "codepoints": [296], "characters": "\u0128" },
+  "&Iukcy;": { "codepoints": [1030], "characters": "\u0406" },
+  "&Iuml": { "codepoints": [207], "characters": "\u00CF" },
+  "&Iuml;": { "codepoints": [207], "characters": "\u00CF" },
+  "&Jcirc;": { "codepoints": [308], "characters": "\u0134" },
+  "&Jcy;": { "codepoints": [1049], "characters": "\u0419" },
+  "&Jfr;": { "codepoints": [120077], "characters": "\uD835\uDD0D" },
+  "&Jopf;": { "codepoints": [120129], "characters": "\uD835\uDD41" },
+  "&Jscr;": { "codepoints": [119973], "characters": "\uD835\uDCA5" },
+  "&Jsercy;": { "codepoints": [1032], "characters": "\u0408" },
+  "&Jukcy;": { "codepoints": [1028], "characters": "\u0404" },
+  "&KHcy;": { "codepoints": [1061], "characters": "\u0425" },
+  "&KJcy;": { "codepoints": [1036], "characters": "\u040C" },
+  "&Kappa;": { "codepoints": [922], "characters": "\u039A" },
+  "&Kcedil;": { "codepoints": [310], "characters": "\u0136" },
+  "&Kcy;": { "codepoints": [1050], "characters": "\u041A" },
+  "&Kfr;": { "codepoints": [120078], "characters": "\uD835\uDD0E" },
+  "&Kopf;": { "codepoints": [120130], "characters": "\uD835\uDD42" },
+  "&Kscr;": { "codepoints": [119974], "characters": "\uD835\uDCA6" },
+  "&LJcy;": { "codepoints": [1033], "characters": "\u0409" },
+  "&LT": { "codepoints": [60], "characters": "\u003C" },
+  "&LT;": { "codepoints": [60], "characters": "\u003C" },
+  "&Lacute;": { "codepoints": [313], "characters": "\u0139" },
+  "&Lambda;": { "codepoints": [923], "characters": "\u039B" },
+  "&Lang;": { "codepoints": [10218], "characters": "\u27EA" },
+  "&Laplacetrf;": { "codepoints": [8466], "characters": "\u2112" },
+  "&Larr;": { "codepoints": [8606], "characters": "\u219E" },
+  "&Lcaron;": { "codepoints": [317], "characters": "\u013D" },
+  "&Lcedil;": { "codepoints": [315], "characters": "\u013B" },
+  "&Lcy;": { "codepoints": [1051], "characters": "\u041B" },
+  "&LeftAngleBracket;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&LeftArrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&LeftArrowBar;": { "codepoints": [8676], "characters": "\u21E4" },
+  "&LeftArrowRightArrow;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&LeftCeiling;": { "codepoints": [8968], "characters": "\u2308" },
+  "&LeftDoubleBracket;": { "codepoints": [10214], "characters": "\u27E6" },
+  "&LeftDownTeeVector;": { "codepoints": [10593], "characters": "\u2961" },
+  "&LeftDownVector;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&LeftDownVectorBar;": { "codepoints": [10585], "characters": "\u2959" },
+  "&LeftFloor;": { "codepoints": [8970], "characters": "\u230A" },
+  "&LeftRightArrow;": { "codepoints": [8596], "characters": "\u2194" },
+  "&LeftRightVector;": { "codepoints": [10574], "characters": "\u294E" },
+  "&LeftTee;": { "codepoints": [8867], "characters": "\u22A3" },
+  "&LeftTeeArrow;": { "codepoints": [8612], "characters": "\u21A4" },
+  "&LeftTeeVector;": { "codepoints": [10586], "characters": "\u295A" },
+  "&LeftTriangle;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&LeftTriangleBar;": { "codepoints": [10703], "characters": "\u29CF" },
+  "&LeftTriangleEqual;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&LeftUpDownVector;": { "codepoints": [10577], "characters": "\u2951" },
+  "&LeftUpTeeVector;": { "codepoints": [10592], "characters": "\u2960" },
+  "&LeftUpVector;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&LeftUpVectorBar;": { "codepoints": [10584], "characters": "\u2958" },
+  "&LeftVector;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&LeftVectorBar;": { "codepoints": [10578], "characters": "\u2952" },
+  "&Leftarrow;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&Leftrightarrow;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&LessEqualGreater;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&LessFullEqual;": { "codepoints": [8806], "characters": "\u2266" },
+  "&LessGreater;": { "codepoints": [8822], "characters": "\u2276" },
+  "&LessLess;": { "codepoints": [10913], "characters": "\u2AA1" },
+  "&LessSlantEqual;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&LessTilde;": { "codepoints": [8818], "characters": "\u2272" },
+  "&Lfr;": { "codepoints": [120079], "characters": "\uD835\uDD0F" },
+  "&Ll;": { "codepoints": [8920], "characters": "\u22D8" },
+  "&Lleftarrow;": { "codepoints": [8666], "characters": "\u21DA" },
+  "&Lmidot;": { "codepoints": [319], "characters": "\u013F" },
+  "&LongLeftArrow;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&LongLeftRightArrow;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&LongRightArrow;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&Longleftarrow;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&Longleftrightarrow;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&Longrightarrow;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&Lopf;": { "codepoints": [120131], "characters": "\uD835\uDD43" },
+  "&LowerLeftArrow;": { "codepoints": [8601], "characters": "\u2199" },
+  "&LowerRightArrow;": { "codepoints": [8600], "characters": "\u2198" },
+  "&Lscr;": { "codepoints": [8466], "characters": "\u2112" },
+  "&Lsh;": { "codepoints": [8624], "characters": "\u21B0" },
+  "&Lstrok;": { "codepoints": [321], "characters": "\u0141" },
+  "&Lt;": { "codepoints": [8810], "characters": "\u226A" },
+  "&Map;": { "codepoints": [10501], "characters": "\u2905" },
+  "&Mcy;": { "codepoints": [1052], "characters": "\u041C" },
+  "&MediumSpace;": { "codepoints": [8287], "characters": "\u205F" },
+  "&Mellintrf;": { "codepoints": [8499], "characters": "\u2133" },
+  "&Mfr;": { "codepoints": [120080], "characters": "\uD835\uDD10" },
+  "&MinusPlus;": { "codepoints": [8723], "characters": "\u2213" },
+  "&Mopf;": { "codepoints": [120132], "characters": "\uD835\uDD44" },
+  "&Mscr;": { "codepoints": [8499], "characters": "\u2133" },
+  "&Mu;": { "codepoints": [924], "characters": "\u039C" },
+  "&NJcy;": { "codepoints": [1034], "characters": "\u040A" },
+  "&Nacute;": { "codepoints": [323], "characters": "\u0143" },
+  "&Ncaron;": { "codepoints": [327], "characters": "\u0147" },
+  "&Ncedil;": { "codepoints": [325], "characters": "\u0145" },
+  "&Ncy;": { "codepoints": [1053], "characters": "\u041D" },
+  "&NegativeMediumSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeThickSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeThinSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NegativeVeryThinSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&NestedGreaterGreater;": { "codepoints": [8811], "characters": "\u226B" },
+  "&NestedLessLess;": { "codepoints": [8810], "characters": "\u226A" },
+  "&NewLine;": { "codepoints": [10], "characters": "\u000A" },
+  "&Nfr;": { "codepoints": [120081], "characters": "\uD835\uDD11" },
+  "&NoBreak;": { "codepoints": [8288], "characters": "\u2060" },
+  "&NonBreakingSpace;": { "codepoints": [160], "characters": "\u00A0" },
+  "&Nopf;": { "codepoints": [8469], "characters": "\u2115" },
+  "&Not;": { "codepoints": [10988], "characters": "\u2AEC" },
+  "&NotCongruent;": { "codepoints": [8802], "characters": "\u2262" },
+  "&NotCupCap;": { "codepoints": [8813], "characters": "\u226D" },
+  "&NotDoubleVerticalBar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&NotElement;": { "codepoints": [8713], "characters": "\u2209" },
+  "&NotEqual;": { "codepoints": [8800], "characters": "\u2260" },
+  "&NotEqualTilde;": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+  "&NotExists;": { "codepoints": [8708], "characters": "\u2204" },
+  "&NotGreater;": { "codepoints": [8815], "characters": "\u226F" },
+  "&NotGreaterEqual;": { "codepoints": [8817], "characters": "\u2271" },
+  "&NotGreaterFullEqual;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&NotGreaterGreater;": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+  "&NotGreaterLess;": { "codepoints": [8825], "characters": "\u2279" },
+  "&NotGreaterSlantEqual;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&NotGreaterTilde;": { "codepoints": [8821], "characters": "\u2275" },
+  "&NotHumpDownHump;": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+  "&NotHumpEqual;": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+  "&NotLeftTriangle;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&NotLeftTriangleBar;": { "codepoints": [10703, 824], "characters": "\u29CF\u0338" },
+  "&NotLeftTriangleEqual;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&NotLess;": { "codepoints": [8814], "characters": "\u226E" },
+  "&NotLessEqual;": { "codepoints": [8816], "characters": "\u2270" },
+  "&NotLessGreater;": { "codepoints": [8824], "characters": "\u2278" },
+  "&NotLessLess;": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+  "&NotLessSlantEqual;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&NotLessTilde;": { "codepoints": [8820], "characters": "\u2274" },
+  "&NotNestedGreaterGreater;": { "codepoints": [10914, 824], "characters": "\u2AA2\u0338" },
+  "&NotNestedLessLess;": { "codepoints": [10913, 824], "characters": "\u2AA1\u0338" },
+  "&NotPrecedes;": { "codepoints": [8832], "characters": "\u2280" },
+  "&NotPrecedesEqual;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&NotPrecedesSlantEqual;": { "codepoints": [8928], "characters": "\u22E0" },
+  "&NotReverseElement;": { "codepoints": [8716], "characters": "\u220C" },
+  "&NotRightTriangle;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&NotRightTriangleBar;": { "codepoints": [10704, 824], "characters": "\u29D0\u0338" },
+  "&NotRightTriangleEqual;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&NotSquareSubset;": { "codepoints": [8847, 824], "characters": "\u228F\u0338" },
+  "&NotSquareSubsetEqual;": { "codepoints": [8930], "characters": "\u22E2" },
+  "&NotSquareSuperset;": { "codepoints": [8848, 824], "characters": "\u2290\u0338" },
+  "&NotSquareSupersetEqual;": { "codepoints": [8931], "characters": "\u22E3" },
+  "&NotSubset;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&NotSubsetEqual;": { "codepoints": [8840], "characters": "\u2288" },
+  "&NotSucceeds;": { "codepoints": [8833], "characters": "\u2281" },
+  "&NotSucceedsEqual;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&NotSucceedsSlantEqual;": { "codepoints": [8929], "characters": "\u22E1" },
+  "&NotSucceedsTilde;": { "codepoints": [8831, 824], "characters": "\u227F\u0338" },
+  "&NotSuperset;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&NotSupersetEqual;": { "codepoints": [8841], "characters": "\u2289" },
+  "&NotTilde;": { "codepoints": [8769], "characters": "\u2241" },
+  "&NotTildeEqual;": { "codepoints": [8772], "characters": "\u2244" },
+  "&NotTildeFullEqual;": { "codepoints": [8775], "characters": "\u2247" },
+  "&NotTildeTilde;": { "codepoints": [8777], "characters": "\u2249" },
+  "&NotVerticalBar;": { "codepoints": [8740], "characters": "\u2224" },
+  "&Nscr;": { "codepoints": [119977], "characters": "\uD835\uDCA9" },
+  "&Ntilde": { "codepoints": [209], "characters": "\u00D1" },
+  "&Ntilde;": { "codepoints": [209], "characters": "\u00D1" },
+  "&Nu;": { "codepoints": [925], "characters": "\u039D" },
+  "&OElig;": { "codepoints": [338], "characters": "\u0152" },
+  "&Oacute": { "codepoints": [211], "characters": "\u00D3" },
+  "&Oacute;": { "codepoints": [211], "characters": "\u00D3" },
+  "&Ocirc": { "codepoints": [212], "characters": "\u00D4" },
+  "&Ocirc;": { "codepoints": [212], "characters": "\u00D4" },
+  "&Ocy;": { "codepoints": [1054], "characters": "\u041E" },
+  "&Odblac;": { "codepoints": [336], "characters": "\u0150" },
+  "&Ofr;": { "codepoints": [120082], "characters": "\uD835\uDD12" },
+  "&Ograve": { "codepoints": [210], "characters": "\u00D2" },
+  "&Ograve;": { "codepoints": [210], "characters": "\u00D2" },
+  "&Omacr;": { "codepoints": [332], "characters": "\u014C" },
+  "&Omega;": { "codepoints": [937], "characters": "\u03A9" },
+  "&Omicron;": { "codepoints": [927], "characters": "\u039F" },
+  "&Oopf;": { "codepoints": [120134], "characters": "\uD835\uDD46" },
+  "&OpenCurlyDoubleQuote;": { "codepoints": [8220], "characters": "\u201C" },
+  "&OpenCurlyQuote;": { "codepoints": [8216], "characters": "\u2018" },
+  "&Or;": { "codepoints": [10836], "characters": "\u2A54" },
+  "&Oscr;": { "codepoints": [119978], "characters": "\uD835\uDCAA" },
+  "&Oslash": { "codepoints": [216], "characters": "\u00D8" },
+  "&Oslash;": { "codepoints": [216], "characters": "\u00D8" },
+  "&Otilde": { "codepoints": [213], "characters": "\u00D5" },
+  "&Otilde;": { "codepoints": [213], "characters": "\u00D5" },
+  "&Otimes;": { "codepoints": [10807], "characters": "\u2A37" },
+  "&Ouml": { "codepoints": [214], "characters": "\u00D6" },
+  "&Ouml;": { "codepoints": [214], "characters": "\u00D6" },
+  "&OverBar;": { "codepoints": [8254], "characters": "\u203E" },
+  "&OverBrace;": { "codepoints": [9182], "characters": "\u23DE" },
+  "&OverBracket;": { "codepoints": [9140], "characters": "\u23B4" },
+  "&OverParenthesis;": { "codepoints": [9180], "characters": "\u23DC" },
+  "&PartialD;": { "codepoints": [8706], "characters": "\u2202" },
+  "&Pcy;": { "codepoints": [1055], "characters": "\u041F" },
+  "&Pfr;": { "codepoints": [120083], "characters": "\uD835\uDD13" },
+  "&Phi;": { "codepoints": [934], "characters": "\u03A6" },
+  "&Pi;": { "codepoints": [928], "characters": "\u03A0" },
+  "&PlusMinus;": { "codepoints": [177], "characters": "\u00B1" },
+  "&Poincareplane;": { "codepoints": [8460], "characters": "\u210C" },
+  "&Popf;": { "codepoints": [8473], "characters": "\u2119" },
+  "&Pr;": { "codepoints": [10939], "characters": "\u2ABB" },
+  "&Precedes;": { "codepoints": [8826], "characters": "\u227A" },
+  "&PrecedesEqual;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&PrecedesSlantEqual;": { "codepoints": [8828], "characters": "\u227C" },
+  "&PrecedesTilde;": { "codepoints": [8830], "characters": "\u227E" },
+  "&Prime;": { "codepoints": [8243], "characters": "\u2033" },
+  "&Product;": { "codepoints": [8719], "characters": "\u220F" },
+  "&Proportion;": { "codepoints": [8759], "characters": "\u2237" },
+  "&Proportional;": { "codepoints": [8733], "characters": "\u221D" },
+  "&Pscr;": { "codepoints": [119979], "characters": "\uD835\uDCAB" },
+  "&Psi;": { "codepoints": [936], "characters": "\u03A8" },
+  "&QUOT": { "codepoints": [34], "characters": "\u0022" },
+  "&QUOT;": { "codepoints": [34], "characters": "\u0022" },
+  "&Qfr;": { "codepoints": [120084], "characters": "\uD835\uDD14" },
+  "&Qopf;": { "codepoints": [8474], "characters": "\u211A" },
+  "&Qscr;": { "codepoints": [119980], "characters": "\uD835\uDCAC" },
+  "&RBarr;": { "codepoints": [10512], "characters": "\u2910" },
+  "&REG": { "codepoints": [174], "characters": "\u00AE" },
+  "&REG;": { "codepoints": [174], "characters": "\u00AE" },
+  "&Racute;": { "codepoints": [340], "characters": "\u0154" },
+  "&Rang;": { "codepoints": [10219], "characters": "\u27EB" },
+  "&Rarr;": { "codepoints": [8608], "characters": "\u21A0" },
+  "&Rarrtl;": { "codepoints": [10518], "characters": "\u2916" },
+  "&Rcaron;": { "codepoints": [344], "characters": "\u0158" },
+  "&Rcedil;": { "codepoints": [342], "characters": "\u0156" },
+  "&Rcy;": { "codepoints": [1056], "characters": "\u0420" },
+  "&Re;": { "codepoints": [8476], "characters": "\u211C" },
+  "&ReverseElement;": { "codepoints": [8715], "characters": "\u220B" },
+  "&ReverseEquilibrium;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&ReverseUpEquilibrium;": { "codepoints": [10607], "characters": "\u296F" },
+  "&Rfr;": { "codepoints": [8476], "characters": "\u211C" },
+  "&Rho;": { "codepoints": [929], "characters": "\u03A1" },
+  "&RightAngleBracket;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&RightArrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&RightArrowBar;": { "codepoints": [8677], "characters": "\u21E5" },
+  "&RightArrowLeftArrow;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&RightCeiling;": { "codepoints": [8969], "characters": "\u2309" },
+  "&RightDoubleBracket;": { "codepoints": [10215], "characters": "\u27E7" },
+  "&RightDownTeeVector;": { "codepoints": [10589], "characters": "\u295D" },
+  "&RightDownVector;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&RightDownVectorBar;": { "codepoints": [10581], "characters": "\u2955" },
+  "&RightFloor;": { "codepoints": [8971], "characters": "\u230B" },
+  "&RightTee;": { "codepoints": [8866], "characters": "\u22A2" },
+  "&RightTeeArrow;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&RightTeeVector;": { "codepoints": [10587], "characters": "\u295B" },
+  "&RightTriangle;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&RightTriangleBar;": { "codepoints": [10704], "characters": "\u29D0" },
+  "&RightTriangleEqual;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&RightUpDownVector;": { "codepoints": [10575], "characters": "\u294F" },
+  "&RightUpTeeVector;": { "codepoints": [10588], "characters": "\u295C" },
+  "&RightUpVector;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&RightUpVectorBar;": { "codepoints": [10580], "characters": "\u2954" },
+  "&RightVector;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&RightVectorBar;": { "codepoints": [10579], "characters": "\u2953" },
+  "&Rightarrow;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&Ropf;": { "codepoints": [8477], "characters": "\u211D" },
+  "&RoundImplies;": { "codepoints": [10608], "characters": "\u2970" },
+  "&Rrightarrow;": { "codepoints": [8667], "characters": "\u21DB" },
+  "&Rscr;": { "codepoints": [8475], "characters": "\u211B" },
+  "&Rsh;": { "codepoints": [8625], "characters": "\u21B1" },
+  "&RuleDelayed;": { "codepoints": [10740], "characters": "\u29F4" },
+  "&SHCHcy;": { "codepoints": [1065], "characters": "\u0429" },
+  "&SHcy;": { "codepoints": [1064], "characters": "\u0428" },
+  "&SOFTcy;": { "codepoints": [1068], "characters": "\u042C" },
+  "&Sacute;": { "codepoints": [346], "characters": "\u015A" },
+  "&Sc;": { "codepoints": [10940], "characters": "\u2ABC" },
+  "&Scaron;": { "codepoints": [352], "characters": "\u0160" },
+  "&Scedil;": { "codepoints": [350], "characters": "\u015E" },
+  "&Scirc;": { "codepoints": [348], "characters": "\u015C" },
+  "&Scy;": { "codepoints": [1057], "characters": "\u0421" },
+  "&Sfr;": { "codepoints": [120086], "characters": "\uD835\uDD16" },
+  "&ShortDownArrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&ShortLeftArrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&ShortRightArrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&ShortUpArrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&Sigma;": { "codepoints": [931], "characters": "\u03A3" },
+  "&SmallCircle;": { "codepoints": [8728], "characters": "\u2218" },
+  "&Sopf;": { "codepoints": [120138], "characters": "\uD835\uDD4A" },
+  "&Sqrt;": { "codepoints": [8730], "characters": "\u221A" },
+  "&Square;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&SquareIntersection;": { "codepoints": [8851], "characters": "\u2293" },
+  "&SquareSubset;": { "codepoints": [8847], "characters": "\u228F" },
+  "&SquareSubsetEqual;": { "codepoints": [8849], "characters": "\u2291" },
+  "&SquareSuperset;": { "codepoints": [8848], "characters": "\u2290" },
+  "&SquareSupersetEqual;": { "codepoints": [8850], "characters": "\u2292" },
+  "&SquareUnion;": { "codepoints": [8852], "characters": "\u2294" },
+  "&Sscr;": { "codepoints": [119982], "characters": "\uD835\uDCAE" },
+  "&Star;": { "codepoints": [8902], "characters": "\u22C6" },
+  "&Sub;": { "codepoints": [8912], "characters": "\u22D0" },
+  "&Subset;": { "codepoints": [8912], "characters": "\u22D0" },
+  "&SubsetEqual;": { "codepoints": [8838], "characters": "\u2286" },
+  "&Succeeds;": { "codepoints": [8827], "characters": "\u227B" },
+  "&SucceedsEqual;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&SucceedsSlantEqual;": { "codepoints": [8829], "characters": "\u227D" },
+  "&SucceedsTilde;": { "codepoints": [8831], "characters": "\u227F" },
+  "&SuchThat;": { "codepoints": [8715], "characters": "\u220B" },
+  "&Sum;": { "codepoints": [8721], "characters": "\u2211" },
+  "&Sup;": { "codepoints": [8913], "characters": "\u22D1" },
+  "&Superset;": { "codepoints": [8835], "characters": "\u2283" },
+  "&SupersetEqual;": { "codepoints": [8839], "characters": "\u2287" },
+  "&Supset;": { "codepoints": [8913], "characters": "\u22D1" },
+  "&THORN": { "codepoints": [222], "characters": "\u00DE" },
+  "&THORN;": { "codepoints": [222], "characters": "\u00DE" },
+  "&TRADE;": { "codepoints": [8482], "characters": "\u2122" },
+  "&TSHcy;": { "codepoints": [1035], "characters": "\u040B" },
+  "&TScy;": { "codepoints": [1062], "characters": "\u0426" },
+  "&Tab;": { "codepoints": [9], "characters": "\u0009" },
+  "&Tau;": { "codepoints": [932], "characters": "\u03A4" },
+  "&Tcaron;": { "codepoints": [356], "characters": "\u0164" },
+  "&Tcedil;": { "codepoints": [354], "characters": "\u0162" },
+  "&Tcy;": { "codepoints": [1058], "characters": "\u0422" },
+  "&Tfr;": { "codepoints": [120087], "characters": "\uD835\uDD17" },
+  "&Therefore;": { "codepoints": [8756], "characters": "\u2234" },
+  "&Theta;": { "codepoints": [920], "characters": "\u0398" },
+  "&ThickSpace;": { "codepoints": [8287, 8202], "characters": "\u205F\u200A" },
+  "&ThinSpace;": { "codepoints": [8201], "characters": "\u2009" },
+  "&Tilde;": { "codepoints": [8764], "characters": "\u223C" },
+  "&TildeEqual;": { "codepoints": [8771], "characters": "\u2243" },
+  "&TildeFullEqual;": { "codepoints": [8773], "characters": "\u2245" },
+  "&TildeTilde;": { "codepoints": [8776], "characters": "\u2248" },
+  "&Topf;": { "codepoints": [120139], "characters": "\uD835\uDD4B" },
+  "&TripleDot;": { "codepoints": [8411], "characters": "\u20DB" },
+  "&Tscr;": { "codepoints": [119983], "characters": "\uD835\uDCAF" },
+  "&Tstrok;": { "codepoints": [358], "characters": "\u0166" },
+  "&Uacute": { "codepoints": [218], "characters": "\u00DA" },
+  "&Uacute;": { "codepoints": [218], "characters": "\u00DA" },
+  "&Uarr;": { "codepoints": [8607], "characters": "\u219F" },
+  "&Uarrocir;": { "codepoints": [10569], "characters": "\u2949" },
+  "&Ubrcy;": { "codepoints": [1038], "characters": "\u040E" },
+  "&Ubreve;": { "codepoints": [364], "characters": "\u016C" },
+  "&Ucirc": { "codepoints": [219], "characters": "\u00DB" },
+  "&Ucirc;": { "codepoints": [219], "characters": "\u00DB" },
+  "&Ucy;": { "codepoints": [1059], "characters": "\u0423" },
+  "&Udblac;": { "codepoints": [368], "characters": "\u0170" },
+  "&Ufr;": { "codepoints": [120088], "characters": "\uD835\uDD18" },
+  "&Ugrave": { "codepoints": [217], "characters": "\u00D9" },
+  "&Ugrave;": { "codepoints": [217], "characters": "\u00D9" },
+  "&Umacr;": { "codepoints": [362], "characters": "\u016A" },
+  "&UnderBar;": { "codepoints": [95], "characters": "\u005F" },
+  "&UnderBrace;": { "codepoints": [9183], "characters": "\u23DF" },
+  "&UnderBracket;": { "codepoints": [9141], "characters": "\u23B5" },
+  "&UnderParenthesis;": { "codepoints": [9181], "characters": "\u23DD" },
+  "&Union;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&UnionPlus;": { "codepoints": [8846], "characters": "\u228E" },
+  "&Uogon;": { "codepoints": [370], "characters": "\u0172" },
+  "&Uopf;": { "codepoints": [120140], "characters": "\uD835\uDD4C" },
+  "&UpArrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&UpArrowBar;": { "codepoints": [10514], "characters": "\u2912" },
+  "&UpArrowDownArrow;": { "codepoints": [8645], "characters": "\u21C5" },
+  "&UpDownArrow;": { "codepoints": [8597], "characters": "\u2195" },
+  "&UpEquilibrium;": { "codepoints": [10606], "characters": "\u296E" },
+  "&UpTee;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&UpTeeArrow;": { "codepoints": [8613], "characters": "\u21A5" },
+  "&Uparrow;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&Updownarrow;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&UpperLeftArrow;": { "codepoints": [8598], "characters": "\u2196" },
+  "&UpperRightArrow;": { "codepoints": [8599], "characters": "\u2197" },
+  "&Upsi;": { "codepoints": [978], "characters": "\u03D2" },
+  "&Upsilon;": { "codepoints": [933], "characters": "\u03A5" },
+  "&Uring;": { "codepoints": [366], "characters": "\u016E" },
+  "&Uscr;": { "codepoints": [119984], "characters": "\uD835\uDCB0" },
+  "&Utilde;": { "codepoints": [360], "characters": "\u0168" },
+  "&Uuml": { "codepoints": [220], "characters": "\u00DC" },
+  "&Uuml;": { "codepoints": [220], "characters": "\u00DC" },
+  "&VDash;": { "codepoints": [8875], "characters": "\u22AB" },
+  "&Vbar;": { "codepoints": [10987], "characters": "\u2AEB" },
+  "&Vcy;": { "codepoints": [1042], "characters": "\u0412" },
+  "&Vdash;": { "codepoints": [8873], "characters": "\u22A9" },
+  "&Vdashl;": { "codepoints": [10982], "characters": "\u2AE6" },
+  "&Vee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&Verbar;": { "codepoints": [8214], "characters": "\u2016" },
+  "&Vert;": { "codepoints": [8214], "characters": "\u2016" },
+  "&VerticalBar;": { "codepoints": [8739], "characters": "\u2223" },
+  "&VerticalLine;": { "codepoints": [124], "characters": "\u007C" },
+  "&VerticalSeparator;": { "codepoints": [10072], "characters": "\u2758" },
+  "&VerticalTilde;": { "codepoints": [8768], "characters": "\u2240" },
+  "&VeryThinSpace;": { "codepoints": [8202], "characters": "\u200A" },
+  "&Vfr;": { "codepoints": [120089], "characters": "\uD835\uDD19" },
+  "&Vopf;": { "codepoints": [120141], "characters": "\uD835\uDD4D" },
+  "&Vscr;": { "codepoints": [119985], "characters": "\uD835\uDCB1" },
+  "&Vvdash;": { "codepoints": [8874], "characters": "\u22AA" },
+  "&Wcirc;": { "codepoints": [372], "characters": "\u0174" },
+  "&Wedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&Wfr;": { "codepoints": [120090], "characters": "\uD835\uDD1A" },
+  "&Wopf;": { "codepoints": [120142], "characters": "\uD835\uDD4E" },
+  "&Wscr;": { "codepoints": [119986], "characters": "\uD835\uDCB2" },
+  "&Xfr;": { "codepoints": [120091], "characters": "\uD835\uDD1B" },
+  "&Xi;": { "codepoints": [926], "characters": "\u039E" },
+  "&Xopf;": { "codepoints": [120143], "characters": "\uD835\uDD4F" },
+  "&Xscr;": { "codepoints": [119987], "characters": "\uD835\uDCB3" },
+  "&YAcy;": { "codepoints": [1071], "characters": "\u042F" },
+  "&YIcy;": { "codepoints": [1031], "characters": "\u0407" },
+  "&YUcy;": { "codepoints": [1070], "characters": "\u042E" },
+  "&Yacute": { "codepoints": [221], "characters": "\u00DD" },
+  "&Yacute;": { "codepoints": [221], "characters": "\u00DD" },
+  "&Ycirc;": { "codepoints": [374], "characters": "\u0176" },
+  "&Ycy;": { "codepoints": [1067], "characters": "\u042B" },
+  "&Yfr;": { "codepoints": [120092], "characters": "\uD835\uDD1C" },
+  "&Yopf;": { "codepoints": [120144], "characters": "\uD835\uDD50" },
+  "&Yscr;": { "codepoints": [119988], "characters": "\uD835\uDCB4" },
+  "&Yuml;": { "codepoints": [376], "characters": "\u0178" },
+  "&ZHcy;": { "codepoints": [1046], "characters": "\u0416" },
+  "&Zacute;": { "codepoints": [377], "characters": "\u0179" },
+  "&Zcaron;": { "codepoints": [381], "characters": "\u017D" },
+  "&Zcy;": { "codepoints": [1047], "characters": "\u0417" },
+  "&Zdot;": { "codepoints": [379], "characters": "\u017B" },
+  "&ZeroWidthSpace;": { "codepoints": [8203], "characters": "\u200B" },
+  "&Zeta;": { "codepoints": [918], "characters": "\u0396" },
+  "&Zfr;": { "codepoints": [8488], "characters": "\u2128" },
+  "&Zopf;": { "codepoints": [8484], "characters": "\u2124" },
+  "&Zscr;": { "codepoints": [119989], "characters": "\uD835\uDCB5" },
+  "&aacute": { "codepoints": [225], "characters": "\u00E1" },
+  "&aacute;": { "codepoints": [225], "characters": "\u00E1" },
+  "&abreve;": { "codepoints": [259], "characters": "\u0103" },
+  "&ac;": { "codepoints": [8766], "characters": "\u223E" },
+  "&acE;": { "codepoints": [8766, 819], "characters": "\u223E\u0333" },
+  "&acd;": { "codepoints": [8767], "characters": "\u223F" },
+  "&acirc": { "codepoints": [226], "characters": "\u00E2" },
+  "&acirc;": { "codepoints": [226], "characters": "\u00E2" },
+  "&acute": { "codepoints": [180], "characters": "\u00B4" },
+  "&acute;": { "codepoints": [180], "characters": "\u00B4" },
+  "&acy;": { "codepoints": [1072], "characters": "\u0430" },
+  "&aelig": { "codepoints": [230], "characters": "\u00E6" },
+  "&aelig;": { "codepoints": [230], "characters": "\u00E6" },
+  "&af;": { "codepoints": [8289], "characters": "\u2061" },
+  "&afr;": { "codepoints": [120094], "characters": "\uD835\uDD1E" },
+  "&agrave": { "codepoints": [224], "characters": "\u00E0" },
+  "&agrave;": { "codepoints": [224], "characters": "\u00E0" },
+  "&alefsym;": { "codepoints": [8501], "characters": "\u2135" },
+  "&aleph;": { "codepoints": [8501], "characters": "\u2135" },
+  "&alpha;": { "codepoints": [945], "characters": "\u03B1" },
+  "&amacr;": { "codepoints": [257], "characters": "\u0101" },
+  "&amalg;": { "codepoints": [10815], "characters": "\u2A3F" },
+  "&amp": { "codepoints": [38], "characters": "\u0026" },
+  "&amp;": { "codepoints": [38], "characters": "\u0026" },
+  "&and;": { "codepoints": [8743], "characters": "\u2227" },
+  "&andand;": { "codepoints": [10837], "characters": "\u2A55" },
+  "&andd;": { "codepoints": [10844], "characters": "\u2A5C" },
+  "&andslope;": { "codepoints": [10840], "characters": "\u2A58" },
+  "&andv;": { "codepoints": [10842], "characters": "\u2A5A" },
+  "&ang;": { "codepoints": [8736], "characters": "\u2220" },
+  "&ange;": { "codepoints": [10660], "characters": "\u29A4" },
+  "&angle;": { "codepoints": [8736], "characters": "\u2220" },
+  "&angmsd;": { "codepoints": [8737], "characters": "\u2221" },
+  "&angmsdaa;": { "codepoints": [10664], "characters": "\u29A8" },
+  "&angmsdab;": { "codepoints": [10665], "characters": "\u29A9" },
+  "&angmsdac;": { "codepoints": [10666], "characters": "\u29AA" },
+  "&angmsdad;": { "codepoints": [10667], "characters": "\u29AB" },
+  "&angmsdae;": { "codepoints": [10668], "characters": "\u29AC" },
+  "&angmsdaf;": { "codepoints": [10669], "characters": "\u29AD" },
+  "&angmsdag;": { "codepoints": [10670], "characters": "\u29AE" },
+  "&angmsdah;": { "codepoints": [10671], "characters": "\u29AF" },
+  "&angrt;": { "codepoints": [8735], "characters": "\u221F" },
+  "&angrtvb;": { "codepoints": [8894], "characters": "\u22BE" },
+  "&angrtvbd;": { "codepoints": [10653], "characters": "\u299D" },
+  "&angsph;": { "codepoints": [8738], "characters": "\u2222" },
+  "&angst;": { "codepoints": [197], "characters": "\u00C5" },
+  "&angzarr;": { "codepoints": [9084], "characters": "\u237C" },
+  "&aogon;": { "codepoints": [261], "characters": "\u0105" },
+  "&aopf;": { "codepoints": [120146], "characters": "\uD835\uDD52" },
+  "&ap;": { "codepoints": [8776], "characters": "\u2248" },
+  "&apE;": { "codepoints": [10864], "characters": "\u2A70" },
+  "&apacir;": { "codepoints": [10863], "characters": "\u2A6F" },
+  "&ape;": { "codepoints": [8778], "characters": "\u224A" },
+  "&apid;": { "codepoints": [8779], "characters": "\u224B" },
+  "&apos;": { "codepoints": [39], "characters": "\u0027" },
+  "&approx;": { "codepoints": [8776], "characters": "\u2248" },
+  "&approxeq;": { "codepoints": [8778], "characters": "\u224A" },
+  "&aring": { "codepoints": [229], "characters": "\u00E5" },
+  "&aring;": { "codepoints": [229], "characters": "\u00E5" },
+  "&ascr;": { "codepoints": [119990], "characters": "\uD835\uDCB6" },
+  "&ast;": { "codepoints": [42], "characters": "\u002A" },
+  "&asymp;": { "codepoints": [8776], "characters": "\u2248" },
+  "&asympeq;": { "codepoints": [8781], "characters": "\u224D" },
+  "&atilde": { "codepoints": [227], "characters": "\u00E3" },
+  "&atilde;": { "codepoints": [227], "characters": "\u00E3" },
+  "&auml": { "codepoints": [228], "characters": "\u00E4" },
+  "&auml;": { "codepoints": [228], "characters": "\u00E4" },
+  "&awconint;": { "codepoints": [8755], "characters": "\u2233" },
+  "&awint;": { "codepoints": [10769], "characters": "\u2A11" },
+  "&bNot;": { "codepoints": [10989], "characters": "\u2AED" },
+  "&backcong;": { "codepoints": [8780], "characters": "\u224C" },
+  "&backepsilon;": { "codepoints": [1014], "characters": "\u03F6" },
+  "&backprime;": { "codepoints": [8245], "characters": "\u2035" },
+  "&backsim;": { "codepoints": [8765], "characters": "\u223D" },
+  "&backsimeq;": { "codepoints": [8909], "characters": "\u22CD" },
+  "&barvee;": { "codepoints": [8893], "characters": "\u22BD" },
+  "&barwed;": { "codepoints": [8965], "characters": "\u2305" },
+  "&barwedge;": { "codepoints": [8965], "characters": "\u2305" },
+  "&bbrk;": { "codepoints": [9141], "characters": "\u23B5" },
+  "&bbrktbrk;": { "codepoints": [9142], "characters": "\u23B6" },
+  "&bcong;": { "codepoints": [8780], "characters": "\u224C" },
+  "&bcy;": { "codepoints": [1073], "characters": "\u0431" },
+  "&bdquo;": { "codepoints": [8222], "characters": "\u201E" },
+  "&becaus;": { "codepoints": [8757], "characters": "\u2235" },
+  "&because;": { "codepoints": [8757], "characters": "\u2235" },
+  "&bemptyv;": { "codepoints": [10672], "characters": "\u29B0" },
+  "&bepsi;": { "codepoints": [1014], "characters": "\u03F6" },
+  "&bernou;": { "codepoints": [8492], "characters": "\u212C" },
+  "&beta;": { "codepoints": [946], "characters": "\u03B2" },
+  "&beth;": { "codepoints": [8502], "characters": "\u2136" },
+  "&between;": { "codepoints": [8812], "characters": "\u226C" },
+  "&bfr;": { "codepoints": [120095], "characters": "\uD835\uDD1F" },
+  "&bigcap;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&bigcirc;": { "codepoints": [9711], "characters": "\u25EF" },
+  "&bigcup;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&bigodot;": { "codepoints": [10752], "characters": "\u2A00" },
+  "&bigoplus;": { "codepoints": [10753], "characters": "\u2A01" },
+  "&bigotimes;": { "codepoints": [10754], "characters": "\u2A02" },
+  "&bigsqcup;": { "codepoints": [10758], "characters": "\u2A06" },
+  "&bigstar;": { "codepoints": [9733], "characters": "\u2605" },
+  "&bigtriangledown;": { "codepoints": [9661], "characters": "\u25BD" },
+  "&bigtriangleup;": { "codepoints": [9651], "characters": "\u25B3" },
+  "&biguplus;": { "codepoints": [10756], "characters": "\u2A04" },
+  "&bigvee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&bigwedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&bkarow;": { "codepoints": [10509], "characters": "\u290D" },
+  "&blacklozenge;": { "codepoints": [10731], "characters": "\u29EB" },
+  "&blacksquare;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&blacktriangle;": { "codepoints": [9652], "characters": "\u25B4" },
+  "&blacktriangledown;": { "codepoints": [9662], "characters": "\u25BE" },
+  "&blacktriangleleft;": { "codepoints": [9666], "characters": "\u25C2" },
+  "&blacktriangleright;": { "codepoints": [9656], "characters": "\u25B8" },
+  "&blank;": { "codepoints": [9251], "characters": "\u2423" },
+  "&blk12;": { "codepoints": [9618], "characters": "\u2592" },
+  "&blk14;": { "codepoints": [9617], "characters": "\u2591" },
+  "&blk34;": { "codepoints": [9619], "characters": "\u2593" },
+  "&block;": { "codepoints": [9608], "characters": "\u2588" },
+  "&bne;": { "codepoints": [61, 8421], "characters": "\u003D\u20E5" },
+  "&bnequiv;": { "codepoints": [8801, 8421], "characters": "\u2261\u20E5" },
+  "&bnot;": { "codepoints": [8976], "characters": "\u2310" },
+  "&bopf;": { "codepoints": [120147], "characters": "\uD835\uDD53" },
+  "&bot;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&bottom;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&bowtie;": { "codepoints": [8904], "characters": "\u22C8" },
+  "&boxDL;": { "codepoints": [9559], "characters": "\u2557" },
+  "&boxDR;": { "codepoints": [9556], "characters": "\u2554" },
+  "&boxDl;": { "codepoints": [9558], "characters": "\u2556" },
+  "&boxDr;": { "codepoints": [9555], "characters": "\u2553" },
+  "&boxH;": { "codepoints": [9552], "characters": "\u2550" },
+  "&boxHD;": { "codepoints": [9574], "characters": "\u2566" },
+  "&boxHU;": { "codepoints": [9577], "characters": "\u2569" },
+  "&boxHd;": { "codepoints": [9572], "characters": "\u2564" },
+  "&boxHu;": { "codepoints": [9575], "characters": "\u2567" },
+  "&boxUL;": { "codepoints": [9565], "characters": "\u255D" },
+  "&boxUR;": { "codepoints": [9562], "characters": "\u255A" },
+  "&boxUl;": { "codepoints": [9564], "characters": "\u255C" },
+  "&boxUr;": { "codepoints": [9561], "characters": "\u2559" },
+  "&boxV;": { "codepoints": [9553], "characters": "\u2551" },
+  "&boxVH;": { "codepoints": [9580], "characters": "\u256C" },
+  "&boxVL;": { "codepoints": [9571], "characters": "\u2563" },
+  "&boxVR;": { "codepoints": [9568], "characters": "\u2560" },
+  "&boxVh;": { "codepoints": [9579], "characters": "\u256B" },
+  "&boxVl;": { "codepoints": [9570], "characters": "\u2562" },
+  "&boxVr;": { "codepoints": [9567], "characters": "\u255F" },
+  "&boxbox;": { "codepoints": [10697], "characters": "\u29C9" },
+  "&boxdL;": { "codepoints": [9557], "characters": "\u2555" },
+  "&boxdR;": { "codepoints": [9554], "characters": "\u2552" },
+  "&boxdl;": { "codepoints": [9488], "characters": "\u2510" },
+  "&boxdr;": { "codepoints": [9484], "characters": "\u250C" },
+  "&boxh;": { "codepoints": [9472], "characters": "\u2500" },
+  "&boxhD;": { "codepoints": [9573], "characters": "\u2565" },
+  "&boxhU;": { "codepoints": [9576], "characters": "\u2568" },
+  "&boxhd;": { "codepoints": [9516], "characters": "\u252C" },
+  "&boxhu;": { "codepoints": [9524], "characters": "\u2534" },
+  "&boxminus;": { "codepoints": [8863], "characters": "\u229F" },
+  "&boxplus;": { "codepoints": [8862], "characters": "\u229E" },
+  "&boxtimes;": { "codepoints": [8864], "characters": "\u22A0" },
+  "&boxuL;": { "codepoints": [9563], "characters": "\u255B" },
+  "&boxuR;": { "codepoints": [9560], "characters": "\u2558" },
+  "&boxul;": { "codepoints": [9496], "characters": "\u2518" },
+  "&boxur;": { "codepoints": [9492], "characters": "\u2514" },
+  "&boxv;": { "codepoints": [9474], "characters": "\u2502" },
+  "&boxvH;": { "codepoints": [9578], "characters": "\u256A" },
+  "&boxvL;": { "codepoints": [9569], "characters": "\u2561" },
+  "&boxvR;": { "codepoints": [9566], "characters": "\u255E" },
+  "&boxvh;": { "codepoints": [9532], "characters": "\u253C" },
+  "&boxvl;": { "codepoints": [9508], "characters": "\u2524" },
+  "&boxvr;": { "codepoints": [9500], "characters": "\u251C" },
+  "&bprime;": { "codepoints": [8245], "characters": "\u2035" },
+  "&breve;": { "codepoints": [728], "characters": "\u02D8" },
+  "&brvbar": { "codepoints": [166], "characters": "\u00A6" },
+  "&brvbar;": { "codepoints": [166], "characters": "\u00A6" },
+  "&bscr;": { "codepoints": [119991], "characters": "\uD835\uDCB7" },
+  "&bsemi;": { "codepoints": [8271], "characters": "\u204F" },
+  "&bsim;": { "codepoints": [8765], "characters": "\u223D" },
+  "&bsime;": { "codepoints": [8909], "characters": "\u22CD" },
+  "&bsol;": { "codepoints": [92], "characters": "\u005C" },
+  "&bsolb;": { "codepoints": [10693], "characters": "\u29C5" },
+  "&bsolhsub;": { "codepoints": [10184], "characters": "\u27C8" },
+  "&bull;": { "codepoints": [8226], "characters": "\u2022" },
+  "&bullet;": { "codepoints": [8226], "characters": "\u2022" },
+  "&bump;": { "codepoints": [8782], "characters": "\u224E" },
+  "&bumpE;": { "codepoints": [10926], "characters": "\u2AAE" },
+  "&bumpe;": { "codepoints": [8783], "characters": "\u224F" },
+  "&bumpeq;": { "codepoints": [8783], "characters": "\u224F" },
+  "&cacute;": { "codepoints": [263], "characters": "\u0107" },
+  "&cap;": { "codepoints": [8745], "characters": "\u2229" },
+  "&capand;": { "codepoints": [10820], "characters": "\u2A44" },
+  "&capbrcup;": { "codepoints": [10825], "characters": "\u2A49" },
+  "&capcap;": { "codepoints": [10827], "characters": "\u2A4B" },
+  "&capcup;": { "codepoints": [10823], "characters": "\u2A47" },
+  "&capdot;": { "codepoints": [10816], "characters": "\u2A40" },
+  "&caps;": { "codepoints": [8745, 65024], "characters": "\u2229\uFE00" },
+  "&caret;": { "codepoints": [8257], "characters": "\u2041" },
+  "&caron;": { "codepoints": [711], "characters": "\u02C7" },
+  "&ccaps;": { "codepoints": [10829], "characters": "\u2A4D" },
+  "&ccaron;": { "codepoints": [269], "characters": "\u010D" },
+  "&ccedil": { "codepoints": [231], "characters": "\u00E7" },
+  "&ccedil;": { "codepoints": [231], "characters": "\u00E7" },
+  "&ccirc;": { "codepoints": [265], "characters": "\u0109" },
+  "&ccups;": { "codepoints": [10828], "characters": "\u2A4C" },
+  "&ccupssm;": { "codepoints": [10832], "characters": "\u2A50" },
+  "&cdot;": { "codepoints": [267], "characters": "\u010B" },
+  "&cedil": { "codepoints": [184], "characters": "\u00B8" },
+  "&cedil;": { "codepoints": [184], "characters": "\u00B8" },
+  "&cemptyv;": { "codepoints": [10674], "characters": "\u29B2" },
+  "&cent": { "codepoints": [162], "characters": "\u00A2" },
+  "&cent;": { "codepoints": [162], "characters": "\u00A2" },
+  "&centerdot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&cfr;": { "codepoints": [120096], "characters": "\uD835\uDD20" },
+  "&chcy;": { "codepoints": [1095], "characters": "\u0447" },
+  "&check;": { "codepoints": [10003], "characters": "\u2713" },
+  "&checkmark;": { "codepoints": [10003], "characters": "\u2713" },
+  "&chi;": { "codepoints": [967], "characters": "\u03C7" },
+  "&cir;": { "codepoints": [9675], "characters": "\u25CB" },
+  "&cirE;": { "codepoints": [10691], "characters": "\u29C3" },
+  "&circ;": { "codepoints": [710], "characters": "\u02C6" },
+  "&circeq;": { "codepoints": [8791], "characters": "\u2257" },
+  "&circlearrowleft;": { "codepoints": [8634], "characters": "\u21BA" },
+  "&circlearrowright;": { "codepoints": [8635], "characters": "\u21BB" },
+  "&circledR;": { "codepoints": [174], "characters": "\u00AE" },
+  "&circledS;": { "codepoints": [9416], "characters": "\u24C8" },
+  "&circledast;": { "codepoints": [8859], "characters": "\u229B" },
+  "&circledcirc;": { "codepoints": [8858], "characters": "\u229A" },
+  "&circleddash;": { "codepoints": [8861], "characters": "\u229D" },
+  "&cire;": { "codepoints": [8791], "characters": "\u2257" },
+  "&cirfnint;": { "codepoints": [10768], "characters": "\u2A10" },
+  "&cirmid;": { "codepoints": [10991], "characters": "\u2AEF" },
+  "&cirscir;": { "codepoints": [10690], "characters": "\u29C2" },
+  "&clubs;": { "codepoints": [9827], "characters": "\u2663" },
+  "&clubsuit;": { "codepoints": [9827], "characters": "\u2663" },
+  "&colon;": { "codepoints": [58], "characters": "\u003A" },
+  "&colone;": { "codepoints": [8788], "characters": "\u2254" },
+  "&coloneq;": { "codepoints": [8788], "characters": "\u2254" },
+  "&comma;": { "codepoints": [44], "characters": "\u002C" },
+  "&commat;": { "codepoints": [64], "characters": "\u0040" },
+  "&comp;": { "codepoints": [8705], "characters": "\u2201" },
+  "&compfn;": { "codepoints": [8728], "characters": "\u2218" },
+  "&complement;": { "codepoints": [8705], "characters": "\u2201" },
+  "&complexes;": { "codepoints": [8450], "characters": "\u2102" },
+  "&cong;": { "codepoints": [8773], "characters": "\u2245" },
+  "&congdot;": { "codepoints": [10861], "characters": "\u2A6D" },
+  "&conint;": { "codepoints": [8750], "characters": "\u222E" },
+  "&copf;": { "codepoints": [120148], "characters": "\uD835\uDD54" },
+  "&coprod;": { "codepoints": [8720], "characters": "\u2210" },
+  "&copy": { "codepoints": [169], "characters": "\u00A9" },
+  "&copy;": { "codepoints": [169], "characters": "\u00A9" },
+  "&copysr;": { "codepoints": [8471], "characters": "\u2117" },
+  "&crarr;": { "codepoints": [8629], "characters": "\u21B5" },
+  "&cross;": { "codepoints": [10007], "characters": "\u2717" },
+  "&cscr;": { "codepoints": [119992], "characters": "\uD835\uDCB8" },
+  "&csub;": { "codepoints": [10959], "characters": "\u2ACF" },
+  "&csube;": { "codepoints": [10961], "characters": "\u2AD1" },
+  "&csup;": { "codepoints": [10960], "characters": "\u2AD0" },
+  "&csupe;": { "codepoints": [10962], "characters": "\u2AD2" },
+  "&ctdot;": { "codepoints": [8943], "characters": "\u22EF" },
+  "&cudarrl;": { "codepoints": [10552], "characters": "\u2938" },
+  "&cudarrr;": { "codepoints": [10549], "characters": "\u2935" },
+  "&cuepr;": { "codepoints": [8926], "characters": "\u22DE" },
+  "&cuesc;": { "codepoints": [8927], "characters": "\u22DF" },
+  "&cularr;": { "codepoints": [8630], "characters": "\u21B6" },
+  "&cularrp;": { "codepoints": [10557], "characters": "\u293D" },
+  "&cup;": { "codepoints": [8746], "characters": "\u222A" },
+  "&cupbrcap;": { "codepoints": [10824], "characters": "\u2A48" },
+  "&cupcap;": { "codepoints": [10822], "characters": "\u2A46" },
+  "&cupcup;": { "codepoints": [10826], "characters": "\u2A4A" },
+  "&cupdot;": { "codepoints": [8845], "characters": "\u228D" },
+  "&cupor;": { "codepoints": [10821], "characters": "\u2A45" },
+  "&cups;": { "codepoints": [8746, 65024], "characters": "\u222A\uFE00" },
+  "&curarr;": { "codepoints": [8631], "characters": "\u21B7" },
+  "&curarrm;": { "codepoints": [10556], "characters": "\u293C" },
+  "&curlyeqprec;": { "codepoints": [8926], "characters": "\u22DE" },
+  "&curlyeqsucc;": { "codepoints": [8927], "characters": "\u22DF" },
+  "&curlyvee;": { "codepoints": [8910], "characters": "\u22CE" },
+  "&curlywedge;": { "codepoints": [8911], "characters": "\u22CF" },
+  "&curren": { "codepoints": [164], "characters": "\u00A4" },
+  "&curren;": { "codepoints": [164], "characters": "\u00A4" },
+  "&curvearrowleft;": { "codepoints": [8630], "characters": "\u21B6" },
+  "&curvearrowright;": { "codepoints": [8631], "characters": "\u21B7" },
+  "&cuvee;": { "codepoints": [8910], "characters": "\u22CE" },
+  "&cuwed;": { "codepoints": [8911], "characters": "\u22CF" },
+  "&cwconint;": { "codepoints": [8754], "characters": "\u2232" },
+  "&cwint;": { "codepoints": [8753], "characters": "\u2231" },
+  "&cylcty;": { "codepoints": [9005], "characters": "\u232D" },
+  "&dArr;": { "codepoints": [8659], "characters": "\u21D3" },
+  "&dHar;": { "codepoints": [10597], "characters": "\u2965" },
+  "&dagger;": { "codepoints": [8224], "characters": "\u2020" },
+  "&daleth;": { "codepoints": [8504], "characters": "\u2138" },
+  "&darr;": { "codepoints": [8595], "characters": "\u2193" },
+  "&dash;": { "codepoints": [8208], "characters": "\u2010" },
+  "&dashv;": { "codepoints": [8867], "characters": "\u22A3" },
+  "&dbkarow;": { "codepoints": [10511], "characters": "\u290F" },
+  "&dblac;": { "codepoints": [733], "characters": "\u02DD" },
+  "&dcaron;": { "codepoints": [271], "characters": "\u010F" },
+  "&dcy;": { "codepoints": [1076], "characters": "\u0434" },
+  "&dd;": { "codepoints": [8518], "characters": "\u2146" },
+  "&ddagger;": { "codepoints": [8225], "characters": "\u2021" },
+  "&ddarr;": { "codepoints": [8650], "characters": "\u21CA" },
+  "&ddotseq;": { "codepoints": [10871], "characters": "\u2A77" },
+  "&deg": { "codepoints": [176], "characters": "\u00B0" },
+  "&deg;": { "codepoints": [176], "characters": "\u00B0" },
+  "&delta;": { "codepoints": [948], "characters": "\u03B4" },
+  "&demptyv;": { "codepoints": [10673], "characters": "\u29B1" },
+  "&dfisht;": { "codepoints": [10623], "characters": "\u297F" },
+  "&dfr;": { "codepoints": [120097], "characters": "\uD835\uDD21" },
+  "&dharl;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&dharr;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&diam;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&diamond;": { "codepoints": [8900], "characters": "\u22C4" },
+  "&diamondsuit;": { "codepoints": [9830], "characters": "\u2666" },
+  "&diams;": { "codepoints": [9830], "characters": "\u2666" },
+  "&die;": { "codepoints": [168], "characters": "\u00A8" },
+  "&digamma;": { "codepoints": [989], "characters": "\u03DD" },
+  "&disin;": { "codepoints": [8946], "characters": "\u22F2" },
+  "&div;": { "codepoints": [247], "characters": "\u00F7" },
+  "&divide": { "codepoints": [247], "characters": "\u00F7" },
+  "&divide;": { "codepoints": [247], "characters": "\u00F7" },
+  "&divideontimes;": { "codepoints": [8903], "characters": "\u22C7" },
+  "&divonx;": { "codepoints": [8903], "characters": "\u22C7" },
+  "&djcy;": { "codepoints": [1106], "characters": "\u0452" },
+  "&dlcorn;": { "codepoints": [8990], "characters": "\u231E" },
+  "&dlcrop;": { "codepoints": [8973], "characters": "\u230D" },
+  "&dollar;": { "codepoints": [36], "characters": "\u0024" },
+  "&dopf;": { "codepoints": [120149], "characters": "\uD835\uDD55" },
+  "&dot;": { "codepoints": [729], "characters": "\u02D9" },
+  "&doteq;": { "codepoints": [8784], "characters": "\u2250" },
+  "&doteqdot;": { "codepoints": [8785], "characters": "\u2251" },
+  "&dotminus;": { "codepoints": [8760], "characters": "\u2238" },
+  "&dotplus;": { "codepoints": [8724], "characters": "\u2214" },
+  "&dotsquare;": { "codepoints": [8865], "characters": "\u22A1" },
+  "&doublebarwedge;": { "codepoints": [8966], "characters": "\u2306" },
+  "&downarrow;": { "codepoints": [8595], "characters": "\u2193" },
+  "&downdownarrows;": { "codepoints": [8650], "characters": "\u21CA" },
+  "&downharpoonleft;": { "codepoints": [8643], "characters": "\u21C3" },
+  "&downharpoonright;": { "codepoints": [8642], "characters": "\u21C2" },
+  "&drbkarow;": { "codepoints": [10512], "characters": "\u2910" },
+  "&drcorn;": { "codepoints": [8991], "characters": "\u231F" },
+  "&drcrop;": { "codepoints": [8972], "characters": "\u230C" },
+  "&dscr;": { "codepoints": [119993], "characters": "\uD835\uDCB9" },
+  "&dscy;": { "codepoints": [1109], "characters": "\u0455" },
+  "&dsol;": { "codepoints": [10742], "characters": "\u29F6" },
+  "&dstrok;": { "codepoints": [273], "characters": "\u0111" },
+  "&dtdot;": { "codepoints": [8945], "characters": "\u22F1" },
+  "&dtri;": { "codepoints": [9663], "characters": "\u25BF" },
+  "&dtrif;": { "codepoints": [9662], "characters": "\u25BE" },
+  "&duarr;": { "codepoints": [8693], "characters": "\u21F5" },
+  "&duhar;": { "codepoints": [10607], "characters": "\u296F" },
+  "&dwangle;": { "codepoints": [10662], "characters": "\u29A6" },
+  "&dzcy;": { "codepoints": [1119], "characters": "\u045F" },
+  "&dzigrarr;": { "codepoints": [10239], "characters": "\u27FF" },
+  "&eDDot;": { "codepoints": [10871], "characters": "\u2A77" },
+  "&eDot;": { "codepoints": [8785], "characters": "\u2251" },
+  "&eacute": { "codepoints": [233], "characters": "\u00E9" },
+  "&eacute;": { "codepoints": [233], "characters": "\u00E9" },
+  "&easter;": { "codepoints": [10862], "characters": "\u2A6E" },
+  "&ecaron;": { "codepoints": [283], "characters": "\u011B" },
+  "&ecir;": { "codepoints": [8790], "characters": "\u2256" },
+  "&ecirc": { "codepoints": [234], "characters": "\u00EA" },
+  "&ecirc;": { "codepoints": [234], "characters": "\u00EA" },
+  "&ecolon;": { "codepoints": [8789], "characters": "\u2255" },
+  "&ecy;": { "codepoints": [1101], "characters": "\u044D" },
+  "&edot;": { "codepoints": [279], "characters": "\u0117" },
+  "&ee;": { "codepoints": [8519], "characters": "\u2147" },
+  "&efDot;": { "codepoints": [8786], "characters": "\u2252" },
+  "&efr;": { "codepoints": [120098], "characters": "\uD835\uDD22" },
+  "&eg;": { "codepoints": [10906], "characters": "\u2A9A" },
+  "&egrave": { "codepoints": [232], "characters": "\u00E8" },
+  "&egrave;": { "codepoints": [232], "characters": "\u00E8" },
+  "&egs;": { "codepoints": [10902], "characters": "\u2A96" },
+  "&egsdot;": { "codepoints": [10904], "characters": "\u2A98" },
+  "&el;": { "codepoints": [10905], "characters": "\u2A99" },
+  "&elinters;": { "codepoints": [9191], "characters": "\u23E7" },
+  "&ell;": { "codepoints": [8467], "characters": "\u2113" },
+  "&els;": { "codepoints": [10901], "characters": "\u2A95" },
+  "&elsdot;": { "codepoints": [10903], "characters": "\u2A97" },
+  "&emacr;": { "codepoints": [275], "characters": "\u0113" },
+  "&empty;": { "codepoints": [8709], "characters": "\u2205" },
+  "&emptyset;": { "codepoints": [8709], "characters": "\u2205" },
+  "&emptyv;": { "codepoints": [8709], "characters": "\u2205" },
+  "&emsp13;": { "codepoints": [8196], "characters": "\u2004" },
+  "&emsp14;": { "codepoints": [8197], "characters": "\u2005" },
+  "&emsp;": { "codepoints": [8195], "characters": "\u2003" },
+  "&eng;": { "codepoints": [331], "characters": "\u014B" },
+  "&ensp;": { "codepoints": [8194], "characters": "\u2002" },
+  "&eogon;": { "codepoints": [281], "characters": "\u0119" },
+  "&eopf;": { "codepoints": [120150], "characters": "\uD835\uDD56" },
+  "&epar;": { "codepoints": [8917], "characters": "\u22D5" },
+  "&eparsl;": { "codepoints": [10723], "characters": "\u29E3" },
+  "&eplus;": { "codepoints": [10865], "characters": "\u2A71" },
+  "&epsi;": { "codepoints": [949], "characters": "\u03B5" },
+  "&epsilon;": { "codepoints": [949], "characters": "\u03B5" },
+  "&epsiv;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&eqcirc;": { "codepoints": [8790], "characters": "\u2256" },
+  "&eqcolon;": { "codepoints": [8789], "characters": "\u2255" },
+  "&eqsim;": { "codepoints": [8770], "characters": "\u2242" },
+  "&eqslantgtr;": { "codepoints": [10902], "characters": "\u2A96" },
+  "&eqslantless;": { "codepoints": [10901], "characters": "\u2A95" },
+  "&equals;": { "codepoints": [61], "characters": "\u003D" },
+  "&equest;": { "codepoints": [8799], "characters": "\u225F" },
+  "&equiv;": { "codepoints": [8801], "characters": "\u2261" },
+  "&equivDD;": { "codepoints": [10872], "characters": "\u2A78" },
+  "&eqvparsl;": { "codepoints": [10725], "characters": "\u29E5" },
+  "&erDot;": { "codepoints": [8787], "characters": "\u2253" },
+  "&erarr;": { "codepoints": [10609], "characters": "\u2971" },
+  "&escr;": { "codepoints": [8495], "characters": "\u212F" },
+  "&esdot;": { "codepoints": [8784], "characters": "\u2250" },
+  "&esim;": { "codepoints": [8770], "characters": "\u2242" },
+  "&eta;": { "codepoints": [951], "characters": "\u03B7" },
+  "&eth": { "codepoints": [240], "characters": "\u00F0" },
+  "&eth;": { "codepoints": [240], "characters": "\u00F0" },
+  "&euml": { "codepoints": [235], "characters": "\u00EB" },
+  "&euml;": { "codepoints": [235], "characters": "\u00EB" },
+  "&euro;": { "codepoints": [8364], "characters": "\u20AC" },
+  "&excl;": { "codepoints": [33], "characters": "\u0021" },
+  "&exist;": { "codepoints": [8707], "characters": "\u2203" },
+  "&expectation;": { "codepoints": [8496], "characters": "\u2130" },
+  "&exponentiale;": { "codepoints": [8519], "characters": "\u2147" },
+  "&fallingdotseq;": { "codepoints": [8786], "characters": "\u2252" },
+  "&fcy;": { "codepoints": [1092], "characters": "\u0444" },
+  "&female;": { "codepoints": [9792], "characters": "\u2640" },
+  "&ffilig;": { "codepoints": [64259], "characters": "\uFB03" },
+  "&fflig;": { "codepoints": [64256], "characters": "\uFB00" },
+  "&ffllig;": { "codepoints": [64260], "characters": "\uFB04" },
+  "&ffr;": { "codepoints": [120099], "characters": "\uD835\uDD23" },
+  "&filig;": { "codepoints": [64257], "characters": "\uFB01" },
+  "&fjlig;": { "codepoints": [102, 106], "characters": "\u0066\u006A" },
+  "&flat;": { "codepoints": [9837], "characters": "\u266D" },
+  "&fllig;": { "codepoints": [64258], "characters": "\uFB02" },
+  "&fltns;": { "codepoints": [9649], "characters": "\u25B1" },
+  "&fnof;": { "codepoints": [402], "characters": "\u0192" },
+  "&fopf;": { "codepoints": [120151], "characters": "\uD835\uDD57" },
+  "&forall;": { "codepoints": [8704], "characters": "\u2200" },
+  "&fork;": { "codepoints": [8916], "characters": "\u22D4" },
+  "&forkv;": { "codepoints": [10969], "characters": "\u2AD9" },
+  "&fpartint;": { "codepoints": [10765], "characters": "\u2A0D" },
+  "&frac12": { "codepoints": [189], "characters": "\u00BD" },
+  "&frac12;": { "codepoints": [189], "characters": "\u00BD" },
+  "&frac13;": { "codepoints": [8531], "characters": "\u2153" },
+  "&frac14": { "codepoints": [188], "characters": "\u00BC" },
+  "&frac14;": { "codepoints": [188], "characters": "\u00BC" },
+  "&frac15;": { "codepoints": [8533], "characters": "\u2155" },
+  "&frac16;": { "codepoints": [8537], "characters": "\u2159" },
+  "&frac18;": { "codepoints": [8539], "characters": "\u215B" },
+  "&frac23;": { "codepoints": [8532], "characters": "\u2154" },
+  "&frac25;": { "codepoints": [8534], "characters": "\u2156" },
+  "&frac34": { "codepoints": [190], "characters": "\u00BE" },
+  "&frac34;": { "codepoints": [190], "characters": "\u00BE" },
+  "&frac35;": { "codepoints": [8535], "characters": "\u2157" },
+  "&frac38;": { "codepoints": [8540], "characters": "\u215C" },
+  "&frac45;": { "codepoints": [8536], "characters": "\u2158" },
+  "&frac56;": { "codepoints": [8538], "characters": "\u215A" },
+  "&frac58;": { "codepoints": [8541], "characters": "\u215D" },
+  "&frac78;": { "codepoints": [8542], "characters": "\u215E" },
+  "&frasl;": { "codepoints": [8260], "characters": "\u2044" },
+  "&frown;": { "codepoints": [8994], "characters": "\u2322" },
+  "&fscr;": { "codepoints": [119995], "characters": "\uD835\uDCBB" },
+  "&gE;": { "codepoints": [8807], "characters": "\u2267" },
+  "&gEl;": { "codepoints": [10892], "characters": "\u2A8C" },
+  "&gacute;": { "codepoints": [501], "characters": "\u01F5" },
+  "&gamma;": { "codepoints": [947], "characters": "\u03B3" },
+  "&gammad;": { "codepoints": [989], "characters": "\u03DD" },
+  "&gap;": { "codepoints": [10886], "characters": "\u2A86" },
+  "&gbreve;": { "codepoints": [287], "characters": "\u011F" },
+  "&gcirc;": { "codepoints": [285], "characters": "\u011D" },
+  "&gcy;": { "codepoints": [1075], "characters": "\u0433" },
+  "&gdot;": { "codepoints": [289], "characters": "\u0121" },
+  "&ge;": { "codepoints": [8805], "characters": "\u2265" },
+  "&gel;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&geq;": { "codepoints": [8805], "characters": "\u2265" },
+  "&geqq;": { "codepoints": [8807], "characters": "\u2267" },
+  "&geqslant;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&ges;": { "codepoints": [10878], "characters": "\u2A7E" },
+  "&gescc;": { "codepoints": [10921], "characters": "\u2AA9" },
+  "&gesdot;": { "codepoints": [10880], "characters": "\u2A80" },
+  "&gesdoto;": { "codepoints": [10882], "characters": "\u2A82" },
+  "&gesdotol;": { "codepoints": [10884], "characters": "\u2A84" },
+  "&gesl;": { "codepoints": [8923, 65024], "characters": "\u22DB\uFE00" },
+  "&gesles;": { "codepoints": [10900], "characters": "\u2A94" },
+  "&gfr;": { "codepoints": [120100], "characters": "\uD835\uDD24" },
+  "&gg;": { "codepoints": [8811], "characters": "\u226B" },
+  "&ggg;": { "codepoints": [8921], "characters": "\u22D9" },
+  "&gimel;": { "codepoints": [8503], "characters": "\u2137" },
+  "&gjcy;": { "codepoints": [1107], "characters": "\u0453" },
+  "&gl;": { "codepoints": [8823], "characters": "\u2277" },
+  "&glE;": { "codepoints": [10898], "characters": "\u2A92" },
+  "&gla;": { "codepoints": [10917], "characters": "\u2AA5" },
+  "&glj;": { "codepoints": [10916], "characters": "\u2AA4" },
+  "&gnE;": { "codepoints": [8809], "characters": "\u2269" },
+  "&gnap;": { "codepoints": [10890], "characters": "\u2A8A" },
+  "&gnapprox;": { "codepoints": [10890], "characters": "\u2A8A" },
+  "&gne;": { "codepoints": [10888], "characters": "\u2A88" },
+  "&gneq;": { "codepoints": [10888], "characters": "\u2A88" },
+  "&gneqq;": { "codepoints": [8809], "characters": "\u2269" },
+  "&gnsim;": { "codepoints": [8935], "characters": "\u22E7" },
+  "&gopf;": { "codepoints": [120152], "characters": "\uD835\uDD58" },
+  "&grave;": { "codepoints": [96], "characters": "\u0060" },
+  "&gscr;": { "codepoints": [8458], "characters": "\u210A" },
+  "&gsim;": { "codepoints": [8819], "characters": "\u2273" },
+  "&gsime;": { "codepoints": [10894], "characters": "\u2A8E" },
+  "&gsiml;": { "codepoints": [10896], "characters": "\u2A90" },
+  "&gt": { "codepoints": [62], "characters": "\u003E" },
+  "&gt;": { "codepoints": [62], "characters": "\u003E" },
+  "&gtcc;": { "codepoints": [10919], "characters": "\u2AA7" },
+  "&gtcir;": { "codepoints": [10874], "characters": "\u2A7A" },
+  "&gtdot;": { "codepoints": [8919], "characters": "\u22D7" },
+  "&gtlPar;": { "codepoints": [10645], "characters": "\u2995" },
+  "&gtquest;": { "codepoints": [10876], "characters": "\u2A7C" },
+  "&gtrapprox;": { "codepoints": [10886], "characters": "\u2A86" },
+  "&gtrarr;": { "codepoints": [10616], "characters": "\u2978" },
+  "&gtrdot;": { "codepoints": [8919], "characters": "\u22D7" },
+  "&gtreqless;": { "codepoints": [8923], "characters": "\u22DB" },
+  "&gtreqqless;": { "codepoints": [10892], "characters": "\u2A8C" },
+  "&gtrless;": { "codepoints": [8823], "characters": "\u2277" },
+  "&gtrsim;": { "codepoints": [8819], "characters": "\u2273" },
+  "&gvertneqq;": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+  "&gvnE;": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+  "&hArr;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&hairsp;": { "codepoints": [8202], "characters": "\u200A" },
+  "&half;": { "codepoints": [189], "characters": "\u00BD" },
+  "&hamilt;": { "codepoints": [8459], "characters": "\u210B" },
+  "&hardcy;": { "codepoints": [1098], "characters": "\u044A" },
+  "&harr;": { "codepoints": [8596], "characters": "\u2194" },
+  "&harrcir;": { "codepoints": [10568], "characters": "\u2948" },
+  "&harrw;": { "codepoints": [8621], "characters": "\u21AD" },
+  "&hbar;": { "codepoints": [8463], "characters": "\u210F" },
+  "&hcirc;": { "codepoints": [293], "characters": "\u0125" },
+  "&hearts;": { "codepoints": [9829], "characters": "\u2665" },
+  "&heartsuit;": { "codepoints": [9829], "characters": "\u2665" },
+  "&hellip;": { "codepoints": [8230], "characters": "\u2026" },
+  "&hercon;": { "codepoints": [8889], "characters": "\u22B9" },
+  "&hfr;": { "codepoints": [120101], "characters": "\uD835\uDD25" },
+  "&hksearow;": { "codepoints": [10533], "characters": "\u2925" },
+  "&hkswarow;": { "codepoints": [10534], "characters": "\u2926" },
+  "&hoarr;": { "codepoints": [8703], "characters": "\u21FF" },
+  "&homtht;": { "codepoints": [8763], "characters": "\u223B" },
+  "&hookleftarrow;": { "codepoints": [8617], "characters": "\u21A9" },
+  "&hookrightarrow;": { "codepoints": [8618], "characters": "\u21AA" },
+  "&hopf;": { "codepoints": [120153], "characters": "\uD835\uDD59" },
+  "&horbar;": { "codepoints": [8213], "characters": "\u2015" },
+  "&hscr;": { "codepoints": [119997], "characters": "\uD835\uDCBD" },
+  "&hslash;": { "codepoints": [8463], "characters": "\u210F" },
+  "&hstrok;": { "codepoints": [295], "characters": "\u0127" },
+  "&hybull;": { "codepoints": [8259], "characters": "\u2043" },
+  "&hyphen;": { "codepoints": [8208], "characters": "\u2010" },
+  "&iacute": { "codepoints": [237], "characters": "\u00ED" },
+  "&iacute;": { "codepoints": [237], "characters": "\u00ED" },
+  "&ic;": { "codepoints": [8291], "characters": "\u2063" },
+  "&icirc": { "codepoints": [238], "characters": "\u00EE" },
+  "&icirc;": { "codepoints": [238], "characters": "\u00EE" },
+  "&icy;": { "codepoints": [1080], "characters": "\u0438" },
+  "&iecy;": { "codepoints": [1077], "characters": "\u0435" },
+  "&iexcl": { "codepoints": [161], "characters": "\u00A1" },
+  "&iexcl;": { "codepoints": [161], "characters": "\u00A1" },
+  "&iff;": { "codepoints": [8660], "characters": "\u21D4" },
+  "&ifr;": { "codepoints": [120102], "characters": "\uD835\uDD26" },
+  "&igrave": { "codepoints": [236], "characters": "\u00EC" },
+  "&igrave;": { "codepoints": [236], "characters": "\u00EC" },
+  "&ii;": { "codepoints": [8520], "characters": "\u2148" },
+  "&iiiint;": { "codepoints": [10764], "characters": "\u2A0C" },
+  "&iiint;": { "codepoints": [8749], "characters": "\u222D" },
+  "&iinfin;": { "codepoints": [10716], "characters": "\u29DC" },
+  "&iiota;": { "codepoints": [8489], "characters": "\u2129" },
+  "&ijlig;": { "codepoints": [307], "characters": "\u0133" },
+  "&imacr;": { "codepoints": [299], "characters": "\u012B" },
+  "&image;": { "codepoints": [8465], "characters": "\u2111" },
+  "&imagline;": { "codepoints": [8464], "characters": "\u2110" },
+  "&imagpart;": { "codepoints": [8465], "characters": "\u2111" },
+  "&imath;": { "codepoints": [305], "characters": "\u0131" },
+  "&imof;": { "codepoints": [8887], "characters": "\u22B7" },
+  "&imped;": { "codepoints": [437], "characters": "\u01B5" },
+  "&in;": { "codepoints": [8712], "characters": "\u2208" },
+  "&incare;": { "codepoints": [8453], "characters": "\u2105" },
+  "&infin;": { "codepoints": [8734], "characters": "\u221E" },
+  "&infintie;": { "codepoints": [10717], "characters": "\u29DD" },
+  "&inodot;": { "codepoints": [305], "characters": "\u0131" },
+  "&int;": { "codepoints": [8747], "characters": "\u222B" },
+  "&intcal;": { "codepoints": [8890], "characters": "\u22BA" },
+  "&integers;": { "codepoints": [8484], "characters": "\u2124" },
+  "&intercal;": { "codepoints": [8890], "characters": "\u22BA" },
+  "&intlarhk;": { "codepoints": [10775], "characters": "\u2A17" },
+  "&intprod;": { "codepoints": [10812], "characters": "\u2A3C" },
+  "&iocy;": { "codepoints": [1105], "characters": "\u0451" },
+  "&iogon;": { "codepoints": [303], "characters": "\u012F" },
+  "&iopf;": { "codepoints": [120154], "characters": "\uD835\uDD5A" },
+  "&iota;": { "codepoints": [953], "characters": "\u03B9" },
+  "&iprod;": { "codepoints": [10812], "characters": "\u2A3C" },
+  "&iquest": { "codepoints": [191], "characters": "\u00BF" },
+  "&iquest;": { "codepoints": [191], "characters": "\u00BF" },
+  "&iscr;": { "codepoints": [119998], "characters": "\uD835\uDCBE" },
+  "&isin;": { "codepoints": [8712], "characters": "\u2208" },
+  "&isinE;": { "codepoints": [8953], "characters": "\u22F9" },
+  "&isindot;": { "codepoints": [8949], "characters": "\u22F5" },
+  "&isins;": { "codepoints": [8948], "characters": "\u22F4" },
+  "&isinsv;": { "codepoints": [8947], "characters": "\u22F3" },
+  "&isinv;": { "codepoints": [8712], "characters": "\u2208" },
+  "&it;": { "codepoints": [8290], "characters": "\u2062" },
+  "&itilde;": { "codepoints": [297], "characters": "\u0129" },
+  "&iukcy;": { "codepoints": [1110], "characters": "\u0456" },
+  "&iuml": { "codepoints": [239], "characters": "\u00EF" },
+  "&iuml;": { "codepoints": [239], "characters": "\u00EF" },
+  "&jcirc;": { "codepoints": [309], "characters": "\u0135" },
+  "&jcy;": { "codepoints": [1081], "characters": "\u0439" },
+  "&jfr;": { "codepoints": [120103], "characters": "\uD835\uDD27" },
+  "&jmath;": { "codepoints": [567], "characters": "\u0237" },
+  "&jopf;": { "codepoints": [120155], "characters": "\uD835\uDD5B" },
+  "&jscr;": { "codepoints": [119999], "characters": "\uD835\uDCBF" },
+  "&jsercy;": { "codepoints": [1112], "characters": "\u0458" },
+  "&jukcy;": { "codepoints": [1108], "characters": "\u0454" },
+  "&kappa;": { "codepoints": [954], "characters": "\u03BA" },
+  "&kappav;": { "codepoints": [1008], "characters": "\u03F0" },
+  "&kcedil;": { "codepoints": [311], "characters": "\u0137" },
+  "&kcy;": { "codepoints": [1082], "characters": "\u043A" },
+  "&kfr;": { "codepoints": [120104], "characters": "\uD835\uDD28" },
+  "&kgreen;": { "codepoints": [312], "characters": "\u0138" },
+  "&khcy;": { "codepoints": [1093], "characters": "\u0445" },
+  "&kjcy;": { "codepoints": [1116], "characters": "\u045C" },
+  "&kopf;": { "codepoints": [120156], "characters": "\uD835\uDD5C" },
+  "&kscr;": { "codepoints": [120000], "characters": "\uD835\uDCC0" },
+  "&lAarr;": { "codepoints": [8666], "characters": "\u21DA" },
+  "&lArr;": { "codepoints": [8656], "characters": "\u21D0" },
+  "&lAtail;": { "codepoints": [10523], "characters": "\u291B" },
+  "&lBarr;": { "codepoints": [10510], "characters": "\u290E" },
+  "&lE;": { "codepoints": [8806], "characters": "\u2266" },
+  "&lEg;": { "codepoints": [10891], "characters": "\u2A8B" },
+  "&lHar;": { "codepoints": [10594], "characters": "\u2962" },
+  "&lacute;": { "codepoints": [314], "characters": "\u013A" },
+  "&laemptyv;": { "codepoints": [10676], "characters": "\u29B4" },
+  "&lagran;": { "codepoints": [8466], "characters": "\u2112" },
+  "&lambda;": { "codepoints": [955], "characters": "\u03BB" },
+  "&lang;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&langd;": { "codepoints": [10641], "characters": "\u2991" },
+  "&langle;": { "codepoints": [10216], "characters": "\u27E8" },
+  "&lap;": { "codepoints": [10885], "characters": "\u2A85" },
+  "&laquo": { "codepoints": [171], "characters": "\u00AB" },
+  "&laquo;": { "codepoints": [171], "characters": "\u00AB" },
+  "&larr;": { "codepoints": [8592], "characters": "\u2190" },
+  "&larrb;": { "codepoints": [8676], "characters": "\u21E4" },
+  "&larrbfs;": { "codepoints": [10527], "characters": "\u291F" },
+  "&larrfs;": { "codepoints": [10525], "characters": "\u291D" },
+  "&larrhk;": { "codepoints": [8617], "characters": "\u21A9" },
+  "&larrlp;": { "codepoints": [8619], "characters": "\u21AB" },
+  "&larrpl;": { "codepoints": [10553], "characters": "\u2939" },
+  "&larrsim;": { "codepoints": [10611], "characters": "\u2973" },
+  "&larrtl;": { "codepoints": [8610], "characters": "\u21A2" },
+  "&lat;": { "codepoints": [10923], "characters": "\u2AAB" },
+  "&latail;": { "codepoints": [10521], "characters": "\u2919" },
+  "&late;": { "codepoints": [10925], "characters": "\u2AAD" },
+  "&lates;": { "codepoints": [10925, 65024], "characters": "\u2AAD\uFE00" },
+  "&lbarr;": { "codepoints": [10508], "characters": "\u290C" },
+  "&lbbrk;": { "codepoints": [10098], "characters": "\u2772" },
+  "&lbrace;": { "codepoints": [123], "characters": "\u007B" },
+  "&lbrack;": { "codepoints": [91], "characters": "\u005B" },
+  "&lbrke;": { "codepoints": [10635], "characters": "\u298B" },
+  "&lbrksld;": { "codepoints": [10639], "characters": "\u298F" },
+  "&lbrkslu;": { "codepoints": [10637], "characters": "\u298D" },
+  "&lcaron;": { "codepoints": [318], "characters": "\u013E" },
+  "&lcedil;": { "codepoints": [316], "characters": "\u013C" },
+  "&lceil;": { "codepoints": [8968], "characters": "\u2308" },
+  "&lcub;": { "codepoints": [123], "characters": "\u007B" },
+  "&lcy;": { "codepoints": [1083], "characters": "\u043B" },
+  "&ldca;": { "codepoints": [10550], "characters": "\u2936" },
+  "&ldquo;": { "codepoints": [8220], "characters": "\u201C" },
+  "&ldquor;": { "codepoints": [8222], "characters": "\u201E" },
+  "&ldrdhar;": { "codepoints": [10599], "characters": "\u2967" },
+  "&ldrushar;": { "codepoints": [10571], "characters": "\u294B" },
+  "&ldsh;": { "codepoints": [8626], "characters": "\u21B2" },
+  "&le;": { "codepoints": [8804], "characters": "\u2264" },
+  "&leftarrow;": { "codepoints": [8592], "characters": "\u2190" },
+  "&leftarrowtail;": { "codepoints": [8610], "characters": "\u21A2" },
+  "&leftharpoondown;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&leftharpoonup;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&leftleftarrows;": { "codepoints": [8647], "characters": "\u21C7" },
+  "&leftrightarrow;": { "codepoints": [8596], "characters": "\u2194" },
+  "&leftrightarrows;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&leftrightharpoons;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&leftrightsquigarrow;": { "codepoints": [8621], "characters": "\u21AD" },
+  "&leftthreetimes;": { "codepoints": [8907], "characters": "\u22CB" },
+  "&leg;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&leq;": { "codepoints": [8804], "characters": "\u2264" },
+  "&leqq;": { "codepoints": [8806], "characters": "\u2266" },
+  "&leqslant;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&les;": { "codepoints": [10877], "characters": "\u2A7D" },
+  "&lescc;": { "codepoints": [10920], "characters": "\u2AA8" },
+  "&lesdot;": { "codepoints": [10879], "characters": "\u2A7F" },
+  "&lesdoto;": { "codepoints": [10881], "characters": "\u2A81" },
+  "&lesdotor;": { "codepoints": [10883], "characters": "\u2A83" },
+  "&lesg;": { "codepoints": [8922, 65024], "characters": "\u22DA\uFE00" },
+  "&lesges;": { "codepoints": [10899], "characters": "\u2A93" },
+  "&lessapprox;": { "codepoints": [10885], "characters": "\u2A85" },
+  "&lessdot;": { "codepoints": [8918], "characters": "\u22D6" },
+  "&lesseqgtr;": { "codepoints": [8922], "characters": "\u22DA" },
+  "&lesseqqgtr;": { "codepoints": [10891], "characters": "\u2A8B" },
+  "&lessgtr;": { "codepoints": [8822], "characters": "\u2276" },
+  "&lesssim;": { "codepoints": [8818], "characters": "\u2272" },
+  "&lfisht;": { "codepoints": [10620], "characters": "\u297C" },
+  "&lfloor;": { "codepoints": [8970], "characters": "\u230A" },
+  "&lfr;": { "codepoints": [120105], "characters": "\uD835\uDD29" },
+  "&lg;": { "codepoints": [8822], "characters": "\u2276" },
+  "&lgE;": { "codepoints": [10897], "characters": "\u2A91" },
+  "&lhard;": { "codepoints": [8637], "characters": "\u21BD" },
+  "&lharu;": { "codepoints": [8636], "characters": "\u21BC" },
+  "&lharul;": { "codepoints": [10602], "characters": "\u296A" },
+  "&lhblk;": { "codepoints": [9604], "characters": "\u2584" },
+  "&ljcy;": { "codepoints": [1113], "characters": "\u0459" },
+  "&ll;": { "codepoints": [8810], "characters": "\u226A" },
+  "&llarr;": { "codepoints": [8647], "characters": "\u21C7" },
+  "&llcorner;": { "codepoints": [8990], "characters": "\u231E" },
+  "&llhard;": { "codepoints": [10603], "characters": "\u296B" },
+  "&lltri;": { "codepoints": [9722], "characters": "\u25FA" },
+  "&lmidot;": { "codepoints": [320], "characters": "\u0140" },
+  "&lmoust;": { "codepoints": [9136], "characters": "\u23B0" },
+  "&lmoustache;": { "codepoints": [9136], "characters": "\u23B0" },
+  "&lnE;": { "codepoints": [8808], "characters": "\u2268" },
+  "&lnap;": { "codepoints": [10889], "characters": "\u2A89" },
+  "&lnapprox;": { "codepoints": [10889], "characters": "\u2A89" },
+  "&lne;": { "codepoints": [10887], "characters": "\u2A87" },
+  "&lneq;": { "codepoints": [10887], "characters": "\u2A87" },
+  "&lneqq;": { "codepoints": [8808], "characters": "\u2268" },
+  "&lnsim;": { "codepoints": [8934], "characters": "\u22E6" },
+  "&loang;": { "codepoints": [10220], "characters": "\u27EC" },
+  "&loarr;": { "codepoints": [8701], "characters": "\u21FD" },
+  "&lobrk;": { "codepoints": [10214], "characters": "\u27E6" },
+  "&longleftarrow;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&longleftrightarrow;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&longmapsto;": { "codepoints": [10236], "characters": "\u27FC" },
+  "&longrightarrow;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&looparrowleft;": { "codepoints": [8619], "characters": "\u21AB" },
+  "&looparrowright;": { "codepoints": [8620], "characters": "\u21AC" },
+  "&lopar;": { "codepoints": [10629], "characters": "\u2985" },
+  "&lopf;": { "codepoints": [120157], "characters": "\uD835\uDD5D" },
+  "&loplus;": { "codepoints": [10797], "characters": "\u2A2D" },
+  "&lotimes;": { "codepoints": [10804], "characters": "\u2A34" },
+  "&lowast;": { "codepoints": [8727], "characters": "\u2217" },
+  "&lowbar;": { "codepoints": [95], "characters": "\u005F" },
+  "&loz;": { "codepoints": [9674], "characters": "\u25CA" },
+  "&lozenge;": { "codepoints": [9674], "characters": "\u25CA" },
+  "&lozf;": { "codepoints": [10731], "characters": "\u29EB" },
+  "&lpar;": { "codepoints": [40], "characters": "\u0028" },
+  "&lparlt;": { "codepoints": [10643], "characters": "\u2993" },
+  "&lrarr;": { "codepoints": [8646], "characters": "\u21C6" },
+  "&lrcorner;": { "codepoints": [8991], "characters": "\u231F" },
+  "&lrhar;": { "codepoints": [8651], "characters": "\u21CB" },
+  "&lrhard;": { "codepoints": [10605], "characters": "\u296D" },
+  "&lrm;": { "codepoints": [8206], "characters": "\u200E" },
+  "&lrtri;": { "codepoints": [8895], "characters": "\u22BF" },
+  "&lsaquo;": { "codepoints": [8249], "characters": "\u2039" },
+  "&lscr;": { "codepoints": [120001], "characters": "\uD835\uDCC1" },
+  "&lsh;": { "codepoints": [8624], "characters": "\u21B0" },
+  "&lsim;": { "codepoints": [8818], "characters": "\u2272" },
+  "&lsime;": { "codepoints": [10893], "characters": "\u2A8D" },
+  "&lsimg;": { "codepoints": [10895], "characters": "\u2A8F" },
+  "&lsqb;": { "codepoints": [91], "characters": "\u005B" },
+  "&lsquo;": { "codepoints": [8216], "characters": "\u2018" },
+  "&lsquor;": { "codepoints": [8218], "characters": "\u201A" },
+  "&lstrok;": { "codepoints": [322], "characters": "\u0142" },
+  "&lt": { "codepoints": [60], "characters": "\u003C" },
+  "&lt;": { "codepoints": [60], "characters": "\u003C" },
+  "&ltcc;": { "codepoints": [10918], "characters": "\u2AA6" },
+  "&ltcir;": { "codepoints": [10873], "characters": "\u2A79" },
+  "&ltdot;": { "codepoints": [8918], "characters": "\u22D6" },
+  "&lthree;": { "codepoints": [8907], "characters": "\u22CB" },
+  "&ltimes;": { "codepoints": [8905], "characters": "\u22C9" },
+  "&ltlarr;": { "codepoints": [10614], "characters": "\u2976" },
+  "&ltquest;": { "codepoints": [10875], "characters": "\u2A7B" },
+  "&ltrPar;": { "codepoints": [10646], "characters": "\u2996" },
+  "&ltri;": { "codepoints": [9667], "characters": "\u25C3" },
+  "&ltrie;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&ltrif;": { "codepoints": [9666], "characters": "\u25C2" },
+  "&lurdshar;": { "codepoints": [10570], "characters": "\u294A" },
+  "&luruhar;": { "codepoints": [10598], "characters": "\u2966" },
+  "&lvertneqq;": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+  "&lvnE;": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+  "&mDDot;": { "codepoints": [8762], "characters": "\u223A" },
+  "&macr": { "codepoints": [175], "characters": "\u00AF" },
+  "&macr;": { "codepoints": [175], "characters": "\u00AF" },
+  "&male;": { "codepoints": [9794], "characters": "\u2642" },
+  "&malt;": { "codepoints": [10016], "characters": "\u2720" },
+  "&maltese;": { "codepoints": [10016], "characters": "\u2720" },
+  "&map;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&mapsto;": { "codepoints": [8614], "characters": "\u21A6" },
+  "&mapstodown;": { "codepoints": [8615], "characters": "\u21A7" },
+  "&mapstoleft;": { "codepoints": [8612], "characters": "\u21A4" },
+  "&mapstoup;": { "codepoints": [8613], "characters": "\u21A5" },
+  "&marker;": { "codepoints": [9646], "characters": "\u25AE" },
+  "&mcomma;": { "codepoints": [10793], "characters": "\u2A29" },
+  "&mcy;": { "codepoints": [1084], "characters": "\u043C" },
+  "&mdash;": { "codepoints": [8212], "characters": "\u2014" },
+  "&measuredangle;": { "codepoints": [8737], "characters": "\u2221" },
+  "&mfr;": { "codepoints": [120106], "characters": "\uD835\uDD2A" },
+  "&mho;": { "codepoints": [8487], "characters": "\u2127" },
+  "&micro": { "codepoints": [181], "characters": "\u00B5" },
+  "&micro;": { "codepoints": [181], "characters": "\u00B5" },
+  "&mid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&midast;": { "codepoints": [42], "characters": "\u002A" },
+  "&midcir;": { "codepoints": [10992], "characters": "\u2AF0" },
+  "&middot": { "codepoints": [183], "characters": "\u00B7" },
+  "&middot;": { "codepoints": [183], "characters": "\u00B7" },
+  "&minus;": { "codepoints": [8722], "characters": "\u2212" },
+  "&minusb;": { "codepoints": [8863], "characters": "\u229F" },
+  "&minusd;": { "codepoints": [8760], "characters": "\u2238" },
+  "&minusdu;": { "codepoints": [10794], "characters": "\u2A2A" },
+  "&mlcp;": { "codepoints": [10971], "characters": "\u2ADB" },
+  "&mldr;": { "codepoints": [8230], "characters": "\u2026" },
+  "&mnplus;": { "codepoints": [8723], "characters": "\u2213" },
+  "&models;": { "codepoints": [8871], "characters": "\u22A7" },
+  "&mopf;": { "codepoints": [120158], "characters": "\uD835\uDD5E" },
+  "&mp;": { "codepoints": [8723], "characters": "\u2213" },
+  "&mscr;": { "codepoints": [120002], "characters": "\uD835\uDCC2" },
+  "&mstpos;": { "codepoints": [8766], "characters": "\u223E" },
+  "&mu;": { "codepoints": [956], "characters": "\u03BC" },
+  "&multimap;": { "codepoints": [8888], "characters": "\u22B8" },
+  "&mumap;": { "codepoints": [8888], "characters": "\u22B8" },
+  "&nGg;": { "codepoints": [8921, 824], "characters": "\u22D9\u0338" },
+  "&nGt;": { "codepoints": [8811, 8402], "characters": "\u226B\u20D2" },
+  "&nGtv;": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+  "&nLeftarrow;": { "codepoints": [8653], "characters": "\u21CD" },
+  "&nLeftrightarrow;": { "codepoints": [8654], "characters": "\u21CE" },
+  "&nLl;": { "codepoints": [8920, 824], "characters": "\u22D8\u0338" },
+  "&nLt;": { "codepoints": [8810, 8402], "characters": "\u226A\u20D2" },
+  "&nLtv;": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+  "&nRightarrow;": { "codepoints": [8655], "characters": "\u21CF" },
+  "&nVDash;": { "codepoints": [8879], "characters": "\u22AF" },
+  "&nVdash;": { "codepoints": [8878], "characters": "\u22AE" },
+  "&nabla;": { "codepoints": [8711], "characters": "\u2207" },
+  "&nacute;": { "codepoints": [324], "characters": "\u0144" },
+  "&nang;": { "codepoints": [8736, 8402], "characters": "\u2220\u20D2" },
+  "&nap;": { "codepoints": [8777], "characters": "\u2249" },
+  "&napE;": { "codepoints": [10864, 824], "characters": "\u2A70\u0338" },
+  "&napid;": { "codepoints": [8779, 824], "characters": "\u224B\u0338" },
+  "&napos;": { "codepoints": [329], "characters": "\u0149" },
+  "&napprox;": { "codepoints": [8777], "characters": "\u2249" },
+  "&natur;": { "codepoints": [9838], "characters": "\u266E" },
+  "&natural;": { "codepoints": [9838], "characters": "\u266E" },
+  "&naturals;": { "codepoints": [8469], "characters": "\u2115" },
+  "&nbsp": { "codepoints": [160], "characters": "\u00A0" },
+  "&nbsp;": { "codepoints": [160], "characters": "\u00A0" },
+  "&nbump;": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+  "&nbumpe;": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+  "&ncap;": { "codepoints": [10819], "characters": "\u2A43" },
+  "&ncaron;": { "codepoints": [328], "characters": "\u0148" },
+  "&ncedil;": { "codepoints": [326], "characters": "\u0146" },
+  "&ncong;": { "codepoints": [8775], "characters": "\u2247" },
+  "&ncongdot;": { "codepoints": [10861, 824], "characters": "\u2A6D\u0338" },
+  "&ncup;": { "codepoints": [10818], "characters": "\u2A42" },
+  "&ncy;": { "codepoints": [1085], "characters": "\u043D" },
+  "&ndash;": { "codepoints": [8211], "characters": "\u2013" },
+  "&ne;": { "codepoints": [8800], "characters": "\u2260" },
+  "&neArr;": { "codepoints": [8663], "characters": "\u21D7" },
+  "&nearhk;": { "codepoints": [10532], "characters": "\u2924" },
+  "&nearr;": { "codepoints": [8599], "characters": "\u2197" },
+  "&nearrow;": { "codepoints": [8599], "characters": "\u2197" },
+  "&nedot;": { "codepoints": [8784, 824], "characters": "\u2250\u0338" },
+  "&nequiv;": { "codepoints": [8802], "characters": "\u2262" },
+  "&nesear;": { "codepoints": [10536], "characters": "\u2928" },
+  "&nesim;": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+  "&nexist;": { "codepoints": [8708], "characters": "\u2204" },
+  "&nexists;": { "codepoints": [8708], "characters": "\u2204" },
+  "&nfr;": { "codepoints": [120107], "characters": "\uD835\uDD2B" },
+  "&ngE;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&nge;": { "codepoints": [8817], "characters": "\u2271" },
+  "&ngeq;": { "codepoints": [8817], "characters": "\u2271" },
+  "&ngeqq;": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+  "&ngeqslant;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&nges;": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+  "&ngsim;": { "codepoints": [8821], "characters": "\u2275" },
+  "&ngt;": { "codepoints": [8815], "characters": "\u226F" },
+  "&ngtr;": { "codepoints": [8815], "characters": "\u226F" },
+  "&nhArr;": { "codepoints": [8654], "characters": "\u21CE" },
+  "&nharr;": { "codepoints": [8622], "characters": "\u21AE" },
+  "&nhpar;": { "codepoints": [10994], "characters": "\u2AF2" },
+  "&ni;": { "codepoints": [8715], "characters": "\u220B" },
+  "&nis;": { "codepoints": [8956], "characters": "\u22FC" },
+  "&nisd;": { "codepoints": [8954], "characters": "\u22FA" },
+  "&niv;": { "codepoints": [8715], "characters": "\u220B" },
+  "&njcy;": { "codepoints": [1114], "characters": "\u045A" },
+  "&nlArr;": { "codepoints": [8653], "characters": "\u21CD" },
+  "&nlE;": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+  "&nlarr;": { "codepoints": [8602], "characters": "\u219A" },
+  "&nldr;": { "codepoints": [8229], "characters": "\u2025" },
+  "&nle;": { "codepoints": [8816], "characters": "\u2270" },
+  "&nleftarrow;": { "codepoints": [8602], "characters": "\u219A" },
+  "&nleftrightarrow;": { "codepoints": [8622], "characters": "\u21AE" },
+  "&nleq;": { "codepoints": [8816], "characters": "\u2270" },
+  "&nleqq;": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+  "&nleqslant;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&nles;": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+  "&nless;": { "codepoints": [8814], "characters": "\u226E" },
+  "&nlsim;": { "codepoints": [8820], "characters": "\u2274" },
+  "&nlt;": { "codepoints": [8814], "characters": "\u226E" },
+  "&nltri;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&nltrie;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&nmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nopf;": { "codepoints": [120159], "characters": "\uD835\uDD5F" },
+  "&not": { "codepoints": [172], "characters": "\u00AC" },
+  "&not;": { "codepoints": [172], "characters": "\u00AC" },
+  "&notin;": { "codepoints": [8713], "characters": "\u2209" },
+  "&notinE;": { "codepoints": [8953, 824], "characters": "\u22F9\u0338" },
+  "&notindot;": { "codepoints": [8949, 824], "characters": "\u22F5\u0338" },
+  "&notinva;": { "codepoints": [8713], "characters": "\u2209" },
+  "&notinvb;": { "codepoints": [8951], "characters": "\u22F7" },
+  "&notinvc;": { "codepoints": [8950], "characters": "\u22F6" },
+  "&notni;": { "codepoints": [8716], "characters": "\u220C" },
+  "&notniva;": { "codepoints": [8716], "characters": "\u220C" },
+  "&notnivb;": { "codepoints": [8958], "characters": "\u22FE" },
+  "&notnivc;": { "codepoints": [8957], "characters": "\u22FD" },
+  "&npar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nparallel;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nparsl;": { "codepoints": [11005, 8421], "characters": "\u2AFD\u20E5" },
+  "&npart;": { "codepoints": [8706, 824], "characters": "\u2202\u0338" },
+  "&npolint;": { "codepoints": [10772], "characters": "\u2A14" },
+  "&npr;": { "codepoints": [8832], "characters": "\u2280" },
+  "&nprcue;": { "codepoints": [8928], "characters": "\u22E0" },
+  "&npre;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&nprec;": { "codepoints": [8832], "characters": "\u2280" },
+  "&npreceq;": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+  "&nrArr;": { "codepoints": [8655], "characters": "\u21CF" },
+  "&nrarr;": { "codepoints": [8603], "characters": "\u219B" },
+  "&nrarrc;": { "codepoints": [10547, 824], "characters": "\u2933\u0338" },
+  "&nrarrw;": { "codepoints": [8605, 824], "characters": "\u219D\u0338" },
+  "&nrightarrow;": { "codepoints": [8603], "characters": "\u219B" },
+  "&nrtri;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&nrtrie;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&nsc;": { "codepoints": [8833], "characters": "\u2281" },
+  "&nsccue;": { "codepoints": [8929], "characters": "\u22E1" },
+  "&nsce;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&nscr;": { "codepoints": [120003], "characters": "\uD835\uDCC3" },
+  "&nshortmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nshortparallel;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nsim;": { "codepoints": [8769], "characters": "\u2241" },
+  "&nsime;": { "codepoints": [8772], "characters": "\u2244" },
+  "&nsimeq;": { "codepoints": [8772], "characters": "\u2244" },
+  "&nsmid;": { "codepoints": [8740], "characters": "\u2224" },
+  "&nspar;": { "codepoints": [8742], "characters": "\u2226" },
+  "&nsqsube;": { "codepoints": [8930], "characters": "\u22E2" },
+  "&nsqsupe;": { "codepoints": [8931], "characters": "\u22E3" },
+  "&nsub;": { "codepoints": [8836], "characters": "\u2284" },
+  "&nsubE;": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+  "&nsube;": { "codepoints": [8840], "characters": "\u2288" },
+  "&nsubset;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&nsubseteq;": { "codepoints": [8840], "characters": "\u2288" },
+  "&nsubseteqq;": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+  "&nsucc;": { "codepoints": [8833], "characters": "\u2281" },
+  "&nsucceq;": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+  "&nsup;": { "codepoints": [8837], "characters": "\u2285" },
+  "&nsupE;": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+  "&nsupe;": { "codepoints": [8841], "characters": "\u2289" },
+  "&nsupset;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&nsupseteq;": { "codepoints": [8841], "characters": "\u2289" },
+  "&nsupseteqq;": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+  "&ntgl;": { "codepoints": [8825], "characters": "\u2279" },
+  "&ntilde": { "codepoints": [241], "characters": "\u00F1" },
+  "&ntilde;": { "codepoints": [241], "characters": "\u00F1" },
+  "&ntlg;": { "codepoints": [8824], "characters": "\u2278" },
+  "&ntriangleleft;": { "codepoints": [8938], "characters": "\u22EA" },
+  "&ntrianglelefteq;": { "codepoints": [8940], "characters": "\u22EC" },
+  "&ntriangleright;": { "codepoints": [8939], "characters": "\u22EB" },
+  "&ntrianglerighteq;": { "codepoints": [8941], "characters": "\u22ED" },
+  "&nu;": { "codepoints": [957], "characters": "\u03BD" },
+  "&num;": { "codepoints": [35], "characters": "\u0023" },
+  "&numero;": { "codepoints": [8470], "characters": "\u2116" },
+  "&numsp;": { "codepoints": [8199], "characters": "\u2007" },
+  "&nvDash;": { "codepoints": [8877], "characters": "\u22AD" },
+  "&nvHarr;": { "codepoints": [10500], "characters": "\u2904" },
+  "&nvap;": { "codepoints": [8781, 8402], "characters": "\u224D\u20D2" },
+  "&nvdash;": { "codepoints": [8876], "characters": "\u22AC" },
+  "&nvge;": { "codepoints": [8805, 8402], "characters": "\u2265\u20D2" },
+  "&nvgt;": { "codepoints": [62, 8402], "characters": "\u003E\u20D2" },
+  "&nvinfin;": { "codepoints": [10718], "characters": "\u29DE" },
+  "&nvlArr;": { "codepoints": [10498], "characters": "\u2902" },
+  "&nvle;": { "codepoints": [8804, 8402], "characters": "\u2264\u20D2" },
+  "&nvlt;": { "codepoints": [60, 8402], "characters": "\u003C\u20D2" },
+  "&nvltrie;": { "codepoints": [8884, 8402], "characters": "\u22B4\u20D2" },
+  "&nvrArr;": { "codepoints": [10499], "characters": "\u2903" },
+  "&nvrtrie;": { "codepoints": [8885, 8402], "characters": "\u22B5\u20D2" },
+  "&nvsim;": { "codepoints": [8764, 8402], "characters": "\u223C\u20D2" },
+  "&nwArr;": { "codepoints": [8662], "characters": "\u21D6" },
+  "&nwarhk;": { "codepoints": [10531], "characters": "\u2923" },
+  "&nwarr;": { "codepoints": [8598], "characters": "\u2196" },
+  "&nwarrow;": { "codepoints": [8598], "characters": "\u2196" },
+  "&nwnear;": { "codepoints": [10535], "characters": "\u2927" },
+  "&oS;": { "codepoints": [9416], "characters": "\u24C8" },
+  "&oacute": { "codepoints": [243], "characters": "\u00F3" },
+  "&oacute;": { "codepoints": [243], "characters": "\u00F3" },
+  "&oast;": { "codepoints": [8859], "characters": "\u229B" },
+  "&ocir;": { "codepoints": [8858], "characters": "\u229A" },
+  "&ocirc": { "codepoints": [244], "characters": "\u00F4" },
+  "&ocirc;": { "codepoints": [244], "characters": "\u00F4" },
+  "&ocy;": { "codepoints": [1086], "characters": "\u043E" },
+  "&odash;": { "codepoints": [8861], "characters": "\u229D" },
+  "&odblac;": { "codepoints": [337], "characters": "\u0151" },
+  "&odiv;": { "codepoints": [10808], "characters": "\u2A38" },
+  "&odot;": { "codepoints": [8857], "characters": "\u2299" },
+  "&odsold;": { "codepoints": [10684], "characters": "\u29BC" },
+  "&oelig;": { "codepoints": [339], "characters": "\u0153" },
+  "&ofcir;": { "codepoints": [10687], "characters": "\u29BF" },
+  "&ofr;": { "codepoints": [120108], "characters": "\uD835\uDD2C" },
+  "&ogon;": { "codepoints": [731], "characters": "\u02DB" },
+  "&ograve": { "codepoints": [242], "characters": "\u00F2" },
+  "&ograve;": { "codepoints": [242], "characters": "\u00F2" },
+  "&ogt;": { "codepoints": [10689], "characters": "\u29C1" },
+  "&ohbar;": { "codepoints": [10677], "characters": "\u29B5" },
+  "&ohm;": { "codepoints": [937], "characters": "\u03A9" },
+  "&oint;": { "codepoints": [8750], "characters": "\u222E" },
+  "&olarr;": { "codepoints": [8634], "characters": "\u21BA" },
+  "&olcir;": { "codepoints": [10686], "characters": "\u29BE" },
+  "&olcross;": { "codepoints": [10683], "characters": "\u29BB" },
+  "&oline;": { "codepoints": [8254], "characters": "\u203E" },
+  "&olt;": { "codepoints": [10688], "characters": "\u29C0" },
+  "&omacr;": { "codepoints": [333], "characters": "\u014D" },
+  "&omega;": { "codepoints": [969], "characters": "\u03C9" },
+  "&omicron;": { "codepoints": [959], "characters": "\u03BF" },
+  "&omid;": { "codepoints": [10678], "characters": "\u29B6" },
+  "&ominus;": { "codepoints": [8854], "characters": "\u2296" },
+  "&oopf;": { "codepoints": [120160], "characters": "\uD835\uDD60" },
+  "&opar;": { "codepoints": [10679], "characters": "\u29B7" },
+  "&operp;": { "codepoints": [10681], "characters": "\u29B9" },
+  "&oplus;": { "codepoints": [8853], "characters": "\u2295" },
+  "&or;": { "codepoints": [8744], "characters": "\u2228" },
+  "&orarr;": { "codepoints": [8635], "characters": "\u21BB" },
+  "&ord;": { "codepoints": [10845], "characters": "\u2A5D" },
+  "&order;": { "codepoints": [8500], "characters": "\u2134" },
+  "&orderof;": { "codepoints": [8500], "characters": "\u2134" },
+  "&ordf": { "codepoints": [170], "characters": "\u00AA" },
+  "&ordf;": { "codepoints": [170], "characters": "\u00AA" },
+  "&ordm": { "codepoints": [186], "characters": "\u00BA" },
+  "&ordm;": { "codepoints": [186], "characters": "\u00BA" },
+  "&origof;": { "codepoints": [8886], "characters": "\u22B6" },
+  "&oror;": { "codepoints": [10838], "characters": "\u2A56" },
+  "&orslope;": { "codepoints": [10839], "characters": "\u2A57" },
+  "&orv;": { "codepoints": [10843], "characters": "\u2A5B" },
+  "&oscr;": { "codepoints": [8500], "characters": "\u2134" },
+  "&oslash": { "codepoints": [248], "characters": "\u00F8" },
+  "&oslash;": { "codepoints": [248], "characters": "\u00F8" },
+  "&osol;": { "codepoints": [8856], "characters": "\u2298" },
+  "&otilde": { "codepoints": [245], "characters": "\u00F5" },
+  "&otilde;": { "codepoints": [245], "characters": "\u00F5" },
+  "&otimes;": { "codepoints": [8855], "characters": "\u2297" },
+  "&otimesas;": { "codepoints": [10806], "characters": "\u2A36" },
+  "&ouml": { "codepoints": [246], "characters": "\u00F6" },
+  "&ouml;": { "codepoints": [246], "characters": "\u00F6" },
+  "&ovbar;": { "codepoints": [9021], "characters": "\u233D" },
+  "&par;": { "codepoints": [8741], "characters": "\u2225" },
+  "&para": { "codepoints": [182], "characters": "\u00B6" },
+  "&para;": { "codepoints": [182], "characters": "\u00B6" },
+  "&parallel;": { "codepoints": [8741], "characters": "\u2225" },
+  "&parsim;": { "codepoints": [10995], "characters": "\u2AF3" },
+  "&parsl;": { "codepoints": [11005], "characters": "\u2AFD" },
+  "&part;": { "codepoints": [8706], "characters": "\u2202" },
+  "&pcy;": { "codepoints": [1087], "characters": "\u043F" },
+  "&percnt;": { "codepoints": [37], "characters": "\u0025" },
+  "&period;": { "codepoints": [46], "characters": "\u002E" },
+  "&permil;": { "codepoints": [8240], "characters": "\u2030" },
+  "&perp;": { "codepoints": [8869], "characters": "\u22A5" },
+  "&pertenk;": { "codepoints": [8241], "characters": "\u2031" },
+  "&pfr;": { "codepoints": [120109], "characters": "\uD835\uDD2D" },
+  "&phi;": { "codepoints": [966], "characters": "\u03C6" },
+  "&phiv;": { "codepoints": [981], "characters": "\u03D5" },
+  "&phmmat;": { "codepoints": [8499], "characters": "\u2133" },
+  "&phone;": { "codepoints": [9742], "characters": "\u260E" },
+  "&pi;": { "codepoints": [960], "characters": "\u03C0" },
+  "&pitchfork;": { "codepoints": [8916], "characters": "\u22D4" },
+  "&piv;": { "codepoints": [982], "characters": "\u03D6" },
+  "&planck;": { "codepoints": [8463], "characters": "\u210F" },
+  "&planckh;": { "codepoints": [8462], "characters": "\u210E" },
+  "&plankv;": { "codepoints": [8463], "characters": "\u210F" },
+  "&plus;": { "codepoints": [43], "characters": "\u002B" },
+  "&plusacir;": { "codepoints": [10787], "characters": "\u2A23" },
+  "&plusb;": { "codepoints": [8862], "characters": "\u229E" },
+  "&pluscir;": { "codepoints": [10786], "characters": "\u2A22" },
+  "&plusdo;": { "codepoints": [8724], "characters": "\u2214" },
+  "&plusdu;": { "codepoints": [10789], "characters": "\u2A25" },
+  "&pluse;": { "codepoints": [10866], "characters": "\u2A72" },
+  "&plusmn": { "codepoints": [177], "characters": "\u00B1" },
+  "&plusmn;": { "codepoints": [177], "characters": "\u00B1" },
+  "&plussim;": { "codepoints": [10790], "characters": "\u2A26" },
+  "&plustwo;": { "codepoints": [10791], "characters": "\u2A27" },
+  "&pm;": { "codepoints": [177], "characters": "\u00B1" },
+  "&pointint;": { "codepoints": [10773], "characters": "\u2A15" },
+  "&popf;": { "codepoints": [120161], "characters": "\uD835\uDD61" },
+  "&pound": { "codepoints": [163], "characters": "\u00A3" },
+  "&pound;": { "codepoints": [163], "characters": "\u00A3" },
+  "&pr;": { "codepoints": [8826], "characters": "\u227A" },
+  "&prE;": { "codepoints": [10931], "characters": "\u2AB3" },
+  "&prap;": { "codepoints": [10935], "characters": "\u2AB7" },
+  "&prcue;": { "codepoints": [8828], "characters": "\u227C" },
+  "&pre;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&prec;": { "codepoints": [8826], "characters": "\u227A" },
+  "&precapprox;": { "codepoints": [10935], "characters": "\u2AB7" },
+  "&preccurlyeq;": { "codepoints": [8828], "characters": "\u227C" },
+  "&preceq;": { "codepoints": [10927], "characters": "\u2AAF" },
+  "&precnapprox;": { "codepoints": [10937], "characters": "\u2AB9" },
+  "&precneqq;": { "codepoints": [10933], "characters": "\u2AB5" },
+  "&precnsim;": { "codepoints": [8936], "characters": "\u22E8" },
+  "&precsim;": { "codepoints": [8830], "characters": "\u227E" },
+  "&prime;": { "codepoints": [8242], "characters": "\u2032" },
+  "&primes;": { "codepoints": [8473], "characters": "\u2119" },
+  "&prnE;": { "codepoints": [10933], "characters": "\u2AB5" },
+  "&prnap;": { "codepoints": [10937], "characters": "\u2AB9" },
+  "&prnsim;": { "codepoints": [8936], "characters": "\u22E8" },
+  "&prod;": { "codepoints": [8719], "characters": "\u220F" },
+  "&profalar;": { "codepoints": [9006], "characters": "\u232E" },
+  "&profline;": { "codepoints": [8978], "characters": "\u2312" },
+  "&profsurf;": { "codepoints": [8979], "characters": "\u2313" },
+  "&prop;": { "codepoints": [8733], "characters": "\u221D" },
+  "&propto;": { "codepoints": [8733], "characters": "\u221D" },
+  "&prsim;": { "codepoints": [8830], "characters": "\u227E" },
+  "&prurel;": { "codepoints": [8880], "characters": "\u22B0" },
+  "&pscr;": { "codepoints": [120005], "characters": "\uD835\uDCC5" },
+  "&psi;": { "codepoints": [968], "characters": "\u03C8" },
+  "&puncsp;": { "codepoints": [8200], "characters": "\u2008" },
+  "&qfr;": { "codepoints": [120110], "characters": "\uD835\uDD2E" },
+  "&qint;": { "codepoints": [10764], "characters": "\u2A0C" },
+  "&qopf;": { "codepoints": [120162], "characters": "\uD835\uDD62" },
+  "&qprime;": { "codepoints": [8279], "characters": "\u2057" },
+  "&qscr;": { "codepoints": [120006], "characters": "\uD835\uDCC6" },
+  "&quaternions;": { "codepoints": [8461], "characters": "\u210D" },
+  "&quatint;": { "codepoints": [10774], "characters": "\u2A16" },
+  "&quest;": { "codepoints": [63], "characters": "\u003F" },
+  "&questeq;": { "codepoints": [8799], "characters": "\u225F" },
+  "&quot": { "codepoints": [34], "characters": "\u0022" },
+  "&quot;": { "codepoints": [34], "characters": "\u0022" },
+  "&rAarr;": { "codepoints": [8667], "characters": "\u21DB" },
+  "&rArr;": { "codepoints": [8658], "characters": "\u21D2" },
+  "&rAtail;": { "codepoints": [10524], "characters": "\u291C" },
+  "&rBarr;": { "codepoints": [10511], "characters": "\u290F" },
+  "&rHar;": { "codepoints": [10596], "characters": "\u2964" },
+  "&race;": { "codepoints": [8765, 817], "characters": "\u223D\u0331" },
+  "&racute;": { "codepoints": [341], "characters": "\u0155" },
+  "&radic;": { "codepoints": [8730], "characters": "\u221A" },
+  "&raemptyv;": { "codepoints": [10675], "characters": "\u29B3" },
+  "&rang;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&rangd;": { "codepoints": [10642], "characters": "\u2992" },
+  "&range;": { "codepoints": [10661], "characters": "\u29A5" },
+  "&rangle;": { "codepoints": [10217], "characters": "\u27E9" },
+  "&raquo": { "codepoints": [187], "characters": "\u00BB" },
+  "&raquo;": { "codepoints": [187], "characters": "\u00BB" },
+  "&rarr;": { "codepoints": [8594], "characters": "\u2192" },
+  "&rarrap;": { "codepoints": [10613], "characters": "\u2975" },
+  "&rarrb;": { "codepoints": [8677], "characters": "\u21E5" },
+  "&rarrbfs;": { "codepoints": [10528], "characters": "\u2920" },
+  "&rarrc;": { "codepoints": [10547], "characters": "\u2933" },
+  "&rarrfs;": { "codepoints": [10526], "characters": "\u291E" },
+  "&rarrhk;": { "codepoints": [8618], "characters": "\u21AA" },
+  "&rarrlp;": { "codepoints": [8620], "characters": "\u21AC" },
+  "&rarrpl;": { "codepoints": [10565], "characters": "\u2945" },
+  "&rarrsim;": { "codepoints": [10612], "characters": "\u2974" },
+  "&rarrtl;": { "codepoints": [8611], "characters": "\u21A3" },
+  "&rarrw;": { "codepoints": [8605], "characters": "\u219D" },
+  "&ratail;": { "codepoints": [10522], "characters": "\u291A" },
+  "&ratio;": { "codepoints": [8758], "characters": "\u2236" },
+  "&rationals;": { "codepoints": [8474], "characters": "\u211A" },
+  "&rbarr;": { "codepoints": [10509], "characters": "\u290D" },
+  "&rbbrk;": { "codepoints": [10099], "characters": "\u2773" },
+  "&rbrace;": { "codepoints": [125], "characters": "\u007D" },
+  "&rbrack;": { "codepoints": [93], "characters": "\u005D" },
+  "&rbrke;": { "codepoints": [10636], "characters": "\u298C" },
+  "&rbrksld;": { "codepoints": [10638], "characters": "\u298E" },
+  "&rbrkslu;": { "codepoints": [10640], "characters": "\u2990" },
+  "&rcaron;": { "codepoints": [345], "characters": "\u0159" },
+  "&rcedil;": { "codepoints": [343], "characters": "\u0157" },
+  "&rceil;": { "codepoints": [8969], "characters": "\u2309" },
+  "&rcub;": { "codepoints": [125], "characters": "\u007D" },
+  "&rcy;": { "codepoints": [1088], "characters": "\u0440" },
+  "&rdca;": { "codepoints": [10551], "characters": "\u2937" },
+  "&rdldhar;": { "codepoints": [10601], "characters": "\u2969" },
+  "&rdquo;": { "codepoints": [8221], "characters": "\u201D" },
+  "&rdquor;": { "codepoints": [8221], "characters": "\u201D" },
+  "&rdsh;": { "codepoints": [8627], "characters": "\u21B3" },
+  "&real;": { "codepoints": [8476], "characters": "\u211C" },
+  "&realine;": { "codepoints": [8475], "characters": "\u211B" },
+  "&realpart;": { "codepoints": [8476], "characters": "\u211C" },
+  "&reals;": { "codepoints": [8477], "characters": "\u211D" },
+  "&rect;": { "codepoints": [9645], "characters": "\u25AD" },
+  "&reg": { "codepoints": [174], "characters": "\u00AE" },
+  "&reg;": { "codepoints": [174], "characters": "\u00AE" },
+  "&rfisht;": { "codepoints": [10621], "characters": "\u297D" },
+  "&rfloor;": { "codepoints": [8971], "characters": "\u230B" },
+  "&rfr;": { "codepoints": [120111], "characters": "\uD835\uDD2F" },
+  "&rhard;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&rharu;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&rharul;": { "codepoints": [10604], "characters": "\u296C" },
+  "&rho;": { "codepoints": [961], "characters": "\u03C1" },
+  "&rhov;": { "codepoints": [1009], "characters": "\u03F1" },
+  "&rightarrow;": { "codepoints": [8594], "characters": "\u2192" },
+  "&rightarrowtail;": { "codepoints": [8611], "characters": "\u21A3" },
+  "&rightharpoondown;": { "codepoints": [8641], "characters": "\u21C1" },
+  "&rightharpoonup;": { "codepoints": [8640], "characters": "\u21C0" },
+  "&rightleftarrows;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&rightleftharpoons;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&rightrightarrows;": { "codepoints": [8649], "characters": "\u21C9" },
+  "&rightsquigarrow;": { "codepoints": [8605], "characters": "\u219D" },
+  "&rightthreetimes;": { "codepoints": [8908], "characters": "\u22CC" },
+  "&ring;": { "codepoints": [730], "characters": "\u02DA" },
+  "&risingdotseq;": { "codepoints": [8787], "characters": "\u2253" },
+  "&rlarr;": { "codepoints": [8644], "characters": "\u21C4" },
+  "&rlhar;": { "codepoints": [8652], "characters": "\u21CC" },
+  "&rlm;": { "codepoints": [8207], "characters": "\u200F" },
+  "&rmoust;": { "codepoints": [9137], "characters": "\u23B1" },
+  "&rmoustache;": { "codepoints": [9137], "characters": "\u23B1" },
+  "&rnmid;": { "codepoints": [10990], "characters": "\u2AEE" },
+  "&roang;": { "codepoints": [10221], "characters": "\u27ED" },
+  "&roarr;": { "codepoints": [8702], "characters": "\u21FE" },
+  "&robrk;": { "codepoints": [10215], "characters": "\u27E7" },
+  "&ropar;": { "codepoints": [10630], "characters": "\u2986" },
+  "&ropf;": { "codepoints": [120163], "characters": "\uD835\uDD63" },
+  "&roplus;": { "codepoints": [10798], "characters": "\u2A2E" },
+  "&rotimes;": { "codepoints": [10805], "characters": "\u2A35" },
+  "&rpar;": { "codepoints": [41], "characters": "\u0029" },
+  "&rpargt;": { "codepoints": [10644], "characters": "\u2994" },
+  "&rppolint;": { "codepoints": [10770], "characters": "\u2A12" },
+  "&rrarr;": { "codepoints": [8649], "characters": "\u21C9" },
+  "&rsaquo;": { "codepoints": [8250], "characters": "\u203A" },
+  "&rscr;": { "codepoints": [120007], "characters": "\uD835\uDCC7" },
+  "&rsh;": { "codepoints": [8625], "characters": "\u21B1" },
+  "&rsqb;": { "codepoints": [93], "characters": "\u005D" },
+  "&rsquo;": { "codepoints": [8217], "characters": "\u2019" },
+  "&rsquor;": { "codepoints": [8217], "characters": "\u2019" },
+  "&rthree;": { "codepoints": [8908], "characters": "\u22CC" },
+  "&rtimes;": { "codepoints": [8906], "characters": "\u22CA" },
+  "&rtri;": { "codepoints": [9657], "characters": "\u25B9" },
+  "&rtrie;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&rtrif;": { "codepoints": [9656], "characters": "\u25B8" },
+  "&rtriltri;": { "codepoints": [10702], "characters": "\u29CE" },
+  "&ruluhar;": { "codepoints": [10600], "characters": "\u2968" },
+  "&rx;": { "codepoints": [8478], "characters": "\u211E" },
+  "&sacute;": { "codepoints": [347], "characters": "\u015B" },
+  "&sbquo;": { "codepoints": [8218], "characters": "\u201A" },
+  "&sc;": { "codepoints": [8827], "characters": "\u227B" },
+  "&scE;": { "codepoints": [10932], "characters": "\u2AB4" },
+  "&scap;": { "codepoints": [10936], "characters": "\u2AB8" },
+  "&scaron;": { "codepoints": [353], "characters": "\u0161" },
+  "&sccue;": { "codepoints": [8829], "characters": "\u227D" },
+  "&sce;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&scedil;": { "codepoints": [351], "characters": "\u015F" },
+  "&scirc;": { "codepoints": [349], "characters": "\u015D" },
+  "&scnE;": { "codepoints": [10934], "characters": "\u2AB6" },
+  "&scnap;": { "codepoints": [10938], "characters": "\u2ABA" },
+  "&scnsim;": { "codepoints": [8937], "characters": "\u22E9" },
+  "&scpolint;": { "codepoints": [10771], "characters": "\u2A13" },
+  "&scsim;": { "codepoints": [8831], "characters": "\u227F" },
+  "&scy;": { "codepoints": [1089], "characters": "\u0441" },
+  "&sdot;": { "codepoints": [8901], "characters": "\u22C5" },
+  "&sdotb;": { "codepoints": [8865], "characters": "\u22A1" },
+  "&sdote;": { "codepoints": [10854], "characters": "\u2A66" },
+  "&seArr;": { "codepoints": [8664], "characters": "\u21D8" },
+  "&searhk;": { "codepoints": [10533], "characters": "\u2925" },
+  "&searr;": { "codepoints": [8600], "characters": "\u2198" },
+  "&searrow;": { "codepoints": [8600], "characters": "\u2198" },
+  "&sect": { "codepoints": [167], "characters": "\u00A7" },
+  "&sect;": { "codepoints": [167], "characters": "\u00A7" },
+  "&semi;": { "codepoints": [59], "characters": "\u003B" },
+  "&seswar;": { "codepoints": [10537], "characters": "\u2929" },
+  "&setminus;": { "codepoints": [8726], "characters": "\u2216" },
+  "&setmn;": { "codepoints": [8726], "characters": "\u2216" },
+  "&sext;": { "codepoints": [10038], "characters": "\u2736" },
+  "&sfr;": { "codepoints": [120112], "characters": "\uD835\uDD30" },
+  "&sfrown;": { "codepoints": [8994], "characters": "\u2322" },
+  "&sharp;": { "codepoints": [9839], "characters": "\u266F" },
+  "&shchcy;": { "codepoints": [1097], "characters": "\u0449" },
+  "&shcy;": { "codepoints": [1096], "characters": "\u0448" },
+  "&shortmid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&shortparallel;": { "codepoints": [8741], "characters": "\u2225" },
+  "&shy": { "codepoints": [173], "characters": "\u00AD" },
+  "&shy;": { "codepoints": [173], "characters": "\u00AD" },
+  "&sigma;": { "codepoints": [963], "characters": "\u03C3" },
+  "&sigmaf;": { "codepoints": [962], "characters": "\u03C2" },
+  "&sigmav;": { "codepoints": [962], "characters": "\u03C2" },
+  "&sim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&simdot;": { "codepoints": [10858], "characters": "\u2A6A" },
+  "&sime;": { "codepoints": [8771], "characters": "\u2243" },
+  "&simeq;": { "codepoints": [8771], "characters": "\u2243" },
+  "&simg;": { "codepoints": [10910], "characters": "\u2A9E" },
+  "&simgE;": { "codepoints": [10912], "characters": "\u2AA0" },
+  "&siml;": { "codepoints": [10909], "characters": "\u2A9D" },
+  "&simlE;": { "codepoints": [10911], "characters": "\u2A9F" },
+  "&simne;": { "codepoints": [8774], "characters": "\u2246" },
+  "&simplus;": { "codepoints": [10788], "characters": "\u2A24" },
+  "&simrarr;": { "codepoints": [10610], "characters": "\u2972" },
+  "&slarr;": { "codepoints": [8592], "characters": "\u2190" },
+  "&smallsetminus;": { "codepoints": [8726], "characters": "\u2216" },
+  "&smashp;": { "codepoints": [10803], "characters": "\u2A33" },
+  "&smeparsl;": { "codepoints": [10724], "characters": "\u29E4" },
+  "&smid;": { "codepoints": [8739], "characters": "\u2223" },
+  "&smile;": { "codepoints": [8995], "characters": "\u2323" },
+  "&smt;": { "codepoints": [10922], "characters": "\u2AAA" },
+  "&smte;": { "codepoints": [10924], "characters": "\u2AAC" },
+  "&smtes;": { "codepoints": [10924, 65024], "characters": "\u2AAC\uFE00" },
+  "&softcy;": { "codepoints": [1100], "characters": "\u044C" },
+  "&sol;": { "codepoints": [47], "characters": "\u002F" },
+  "&solb;": { "codepoints": [10692], "characters": "\u29C4" },
+  "&solbar;": { "codepoints": [9023], "characters": "\u233F" },
+  "&sopf;": { "codepoints": [120164], "characters": "\uD835\uDD64" },
+  "&spades;": { "codepoints": [9824], "characters": "\u2660" },
+  "&spadesuit;": { "codepoints": [9824], "characters": "\u2660" },
+  "&spar;": { "codepoints": [8741], "characters": "\u2225" },
+  "&sqcap;": { "codepoints": [8851], "characters": "\u2293" },
+  "&sqcaps;": { "codepoints": [8851, 65024], "characters": "\u2293\uFE00" },
+  "&sqcup;": { "codepoints": [8852], "characters": "\u2294" },
+  "&sqcups;": { "codepoints": [8852, 65024], "characters": "\u2294\uFE00" },
+  "&sqsub;": { "codepoints": [8847], "characters": "\u228F" },
+  "&sqsube;": { "codepoints": [8849], "characters": "\u2291" },
+  "&sqsubset;": { "codepoints": [8847], "characters": "\u228F" },
+  "&sqsubseteq;": { "codepoints": [8849], "characters": "\u2291" },
+  "&sqsup;": { "codepoints": [8848], "characters": "\u2290" },
+  "&sqsupe;": { "codepoints": [8850], "characters": "\u2292" },
+  "&sqsupset;": { "codepoints": [8848], "characters": "\u2290" },
+  "&sqsupseteq;": { "codepoints": [8850], "characters": "\u2292" },
+  "&squ;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&square;": { "codepoints": [9633], "characters": "\u25A1" },
+  "&squarf;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&squf;": { "codepoints": [9642], "characters": "\u25AA" },
+  "&srarr;": { "codepoints": [8594], "characters": "\u2192" },
+  "&sscr;": { "codepoints": [120008], "characters": "\uD835\uDCC8" },
+  "&ssetmn;": { "codepoints": [8726], "characters": "\u2216" },
+  "&ssmile;": { "codepoints": [8995], "characters": "\u2323" },
+  "&sstarf;": { "codepoints": [8902], "characters": "\u22C6" },
+  "&star;": { "codepoints": [9734], "characters": "\u2606" },
+  "&starf;": { "codepoints": [9733], "characters": "\u2605" },
+  "&straightepsilon;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&straightphi;": { "codepoints": [981], "characters": "\u03D5" },
+  "&strns;": { "codepoints": [175], "characters": "\u00AF" },
+  "&sub;": { "codepoints": [8834], "characters": "\u2282" },
+  "&subE;": { "codepoints": [10949], "characters": "\u2AC5" },
+  "&subdot;": { "codepoints": [10941], "characters": "\u2ABD" },
+  "&sube;": { "codepoints": [8838], "characters": "\u2286" },
+  "&subedot;": { "codepoints": [10947], "characters": "\u2AC3" },
+  "&submult;": { "codepoints": [10945], "characters": "\u2AC1" },
+  "&subnE;": { "codepoints": [10955], "characters": "\u2ACB" },
+  "&subne;": { "codepoints": [8842], "characters": "\u228A" },
+  "&subplus;": { "codepoints": [10943], "characters": "\u2ABF" },
+  "&subrarr;": { "codepoints": [10617], "characters": "\u2979" },
+  "&subset;": { "codepoints": [8834], "characters": "\u2282" },
+  "&subseteq;": { "codepoints": [8838], "characters": "\u2286" },
+  "&subseteqq;": { "codepoints": [10949], "characters": "\u2AC5" },
+  "&subsetneq;": { "codepoints": [8842], "characters": "\u228A" },
+  "&subsetneqq;": { "codepoints": [10955], "characters": "\u2ACB" },
+  "&subsim;": { "codepoints": [10951], "characters": "\u2AC7" },
+  "&subsub;": { "codepoints": [10965], "characters": "\u2AD5" },
+  "&subsup;": { "codepoints": [10963], "characters": "\u2AD3" },
+  "&succ;": { "codepoints": [8827], "characters": "\u227B" },
+  "&succapprox;": { "codepoints": [10936], "characters": "\u2AB8" },
+  "&succcurlyeq;": { "codepoints": [8829], "characters": "\u227D" },
+  "&succeq;": { "codepoints": [10928], "characters": "\u2AB0" },
+  "&succnapprox;": { "codepoints": [10938], "characters": "\u2ABA" },
+  "&succneqq;": { "codepoints": [10934], "characters": "\u2AB6" },
+  "&succnsim;": { "codepoints": [8937], "characters": "\u22E9" },
+  "&succsim;": { "codepoints": [8831], "characters": "\u227F" },
+  "&sum;": { "codepoints": [8721], "characters": "\u2211" },
+  "&sung;": { "codepoints": [9834], "characters": "\u266A" },
+  "&sup1": { "codepoints": [185], "characters": "\u00B9" },
+  "&sup1;": { "codepoints": [185], "characters": "\u00B9" },
+  "&sup2": { "codepoints": [178], "characters": "\u00B2" },
+  "&sup2;": { "codepoints": [178], "characters": "\u00B2" },
+  "&sup3": { "codepoints": [179], "characters": "\u00B3" },
+  "&sup3;": { "codepoints": [179], "characters": "\u00B3" },
+  "&sup;": { "codepoints": [8835], "characters": "\u2283" },
+  "&supE;": { "codepoints": [10950], "characters": "\u2AC6" },
+  "&supdot;": { "codepoints": [10942], "characters": "\u2ABE" },
+  "&supdsub;": { "codepoints": [10968], "characters": "\u2AD8" },
+  "&supe;": { "codepoints": [8839], "characters": "\u2287" },
+  "&supedot;": { "codepoints": [10948], "characters": "\u2AC4" },
+  "&suphsol;": { "codepoints": [10185], "characters": "\u27C9" },
+  "&suphsub;": { "codepoints": [10967], "characters": "\u2AD7" },
+  "&suplarr;": { "codepoints": [10619], "characters": "\u297B" },
+  "&supmult;": { "codepoints": [10946], "characters": "\u2AC2" },
+  "&supnE;": { "codepoints": [10956], "characters": "\u2ACC" },
+  "&supne;": { "codepoints": [8843], "characters": "\u228B" },
+  "&supplus;": { "codepoints": [10944], "characters": "\u2AC0" },
+  "&supset;": { "codepoints": [8835], "characters": "\u2283" },
+  "&supseteq;": { "codepoints": [8839], "characters": "\u2287" },
+  "&supseteqq;": { "codepoints": [10950], "characters": "\u2AC6" },
+  "&supsetneq;": { "codepoints": [8843], "characters": "\u228B" },
+  "&supsetneqq;": { "codepoints": [10956], "characters": "\u2ACC" },
+  "&supsim;": { "codepoints": [10952], "characters": "\u2AC8" },
+  "&supsub;": { "codepoints": [10964], "characters": "\u2AD4" },
+  "&supsup;": { "codepoints": [10966], "characters": "\u2AD6" },
+  "&swArr;": { "codepoints": [8665], "characters": "\u21D9" },
+  "&swarhk;": { "codepoints": [10534], "characters": "\u2926" },
+  "&swarr;": { "codepoints": [8601], "characters": "\u2199" },
+  "&swarrow;": { "codepoints": [8601], "characters": "\u2199" },
+  "&swnwar;": { "codepoints": [10538], "characters": "\u292A" },
+  "&szlig": { "codepoints": [223], "characters": "\u00DF" },
+  "&szlig;": { "codepoints": [223], "characters": "\u00DF" },
+  "&target;": { "codepoints": [8982], "characters": "\u2316" },
+  "&tau;": { "codepoints": [964], "characters": "\u03C4" },
+  "&tbrk;": { "codepoints": [9140], "characters": "\u23B4" },
+  "&tcaron;": { "codepoints": [357], "characters": "\u0165" },
+  "&tcedil;": { "codepoints": [355], "characters": "\u0163" },
+  "&tcy;": { "codepoints": [1090], "characters": "\u0442" },
+  "&tdot;": { "codepoints": [8411], "characters": "\u20DB" },
+  "&telrec;": { "codepoints": [8981], "characters": "\u2315" },
+  "&tfr;": { "codepoints": [120113], "characters": "\uD835\uDD31" },
+  "&there4;": { "codepoints": [8756], "characters": "\u2234" },
+  "&therefore;": { "codepoints": [8756], "characters": "\u2234" },
+  "&theta;": { "codepoints": [952], "characters": "\u03B8" },
+  "&thetasym;": { "codepoints": [977], "characters": "\u03D1" },
+  "&thetav;": { "codepoints": [977], "characters": "\u03D1" },
+  "&thickapprox;": { "codepoints": [8776], "characters": "\u2248" },
+  "&thicksim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&thinsp;": { "codepoints": [8201], "characters": "\u2009" },
+  "&thkap;": { "codepoints": [8776], "characters": "\u2248" },
+  "&thksim;": { "codepoints": [8764], "characters": "\u223C" },
+  "&thorn": { "codepoints": [254], "characters": "\u00FE" },
+  "&thorn;": { "codepoints": [254], "characters": "\u00FE" },
+  "&tilde;": { "codepoints": [732], "characters": "\u02DC" },
+  "&times": { "codepoints": [215], "characters": "\u00D7" },
+  "&times;": { "codepoints": [215], "characters": "\u00D7" },
+  "&timesb;": { "codepoints": [8864], "characters": "\u22A0" },
+  "&timesbar;": { "codepoints": [10801], "characters": "\u2A31" },
+  "&timesd;": { "codepoints": [10800], "characters": "\u2A30" },
+  "&tint;": { "codepoints": [8749], "characters": "\u222D" },
+  "&toea;": { "codepoints": [10536], "characters": "\u2928" },
+  "&top;": { "codepoints": [8868], "characters": "\u22A4" },
+  "&topbot;": { "codepoints": [9014], "characters": "\u2336" },
+  "&topcir;": { "codepoints": [10993], "characters": "\u2AF1" },
+  "&topf;": { "codepoints": [120165], "characters": "\uD835\uDD65" },
+  "&topfork;": { "codepoints": [10970], "characters": "\u2ADA" },
+  "&tosa;": { "codepoints": [10537], "characters": "\u2929" },
+  "&tprime;": { "codepoints": [8244], "characters": "\u2034" },
+  "&trade;": { "codepoints": [8482], "characters": "\u2122" },
+  "&triangle;": { "codepoints": [9653], "characters": "\u25B5" },
+  "&triangledown;": { "codepoints": [9663], "characters": "\u25BF" },
+  "&triangleleft;": { "codepoints": [9667], "characters": "\u25C3" },
+  "&trianglelefteq;": { "codepoints": [8884], "characters": "\u22B4" },
+  "&triangleq;": { "codepoints": [8796], "characters": "\u225C" },
+  "&triangleright;": { "codepoints": [9657], "characters": "\u25B9" },
+  "&trianglerighteq;": { "codepoints": [8885], "characters": "\u22B5" },
+  "&tridot;": { "codepoints": [9708], "characters": "\u25EC" },
+  "&trie;": { "codepoints": [8796], "characters": "\u225C" },
+  "&triminus;": { "codepoints": [10810], "characters": "\u2A3A" },
+  "&triplus;": { "codepoints": [10809], "characters": "\u2A39" },
+  "&trisb;": { "codepoints": [10701], "characters": "\u29CD" },
+  "&tritime;": { "codepoints": [10811], "characters": "\u2A3B" },
+  "&trpezium;": { "codepoints": [9186], "characters": "\u23E2" },
+  "&tscr;": { "codepoints": [120009], "characters": "\uD835\uDCC9" },
+  "&tscy;": { "codepoints": [1094], "characters": "\u0446" },
+  "&tshcy;": { "codepoints": [1115], "characters": "\u045B" },
+  "&tstrok;": { "codepoints": [359], "characters": "\u0167" },
+  "&twixt;": { "codepoints": [8812], "characters": "\u226C" },
+  "&twoheadleftarrow;": { "codepoints": [8606], "characters": "\u219E" },
+  "&twoheadrightarrow;": { "codepoints": [8608], "characters": "\u21A0" },
+  "&uArr;": { "codepoints": [8657], "characters": "\u21D1" },
+  "&uHar;": { "codepoints": [10595], "characters": "\u2963" },
+  "&uacute": { "codepoints": [250], "characters": "\u00FA" },
+  "&uacute;": { "codepoints": [250], "characters": "\u00FA" },
+  "&uarr;": { "codepoints": [8593], "characters": "\u2191" },
+  "&ubrcy;": { "codepoints": [1118], "characters": "\u045E" },
+  "&ubreve;": { "codepoints": [365], "characters": "\u016D" },
+  "&ucirc": { "codepoints": [251], "characters": "\u00FB" },
+  "&ucirc;": { "codepoints": [251], "characters": "\u00FB" },
+  "&ucy;": { "codepoints": [1091], "characters": "\u0443" },
+  "&udarr;": { "codepoints": [8645], "characters": "\u21C5" },
+  "&udblac;": { "codepoints": [369], "characters": "\u0171" },
+  "&udhar;": { "codepoints": [10606], "characters": "\u296E" },
+  "&ufisht;": { "codepoints": [10622], "characters": "\u297E" },
+  "&ufr;": { "codepoints": [120114], "characters": "\uD835\uDD32" },
+  "&ugrave": { "codepoints": [249], "characters": "\u00F9" },
+  "&ugrave;": { "codepoints": [249], "characters": "\u00F9" },
+  "&uharl;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&uharr;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&uhblk;": { "codepoints": [9600], "characters": "\u2580" },
+  "&ulcorn;": { "codepoints": [8988], "characters": "\u231C" },
+  "&ulcorner;": { "codepoints": [8988], "characters": "\u231C" },
+  "&ulcrop;": { "codepoints": [8975], "characters": "\u230F" },
+  "&ultri;": { "codepoints": [9720], "characters": "\u25F8" },
+  "&umacr;": { "codepoints": [363], "characters": "\u016B" },
+  "&uml": { "codepoints": [168], "characters": "\u00A8" },
+  "&uml;": { "codepoints": [168], "characters": "\u00A8" },
+  "&uogon;": { "codepoints": [371], "characters": "\u0173" },
+  "&uopf;": { "codepoints": [120166], "characters": "\uD835\uDD66" },
+  "&uparrow;": { "codepoints": [8593], "characters": "\u2191" },
+  "&updownarrow;": { "codepoints": [8597], "characters": "\u2195" },
+  "&upharpoonleft;": { "codepoints": [8639], "characters": "\u21BF" },
+  "&upharpoonright;": { "codepoints": [8638], "characters": "\u21BE" },
+  "&uplus;": { "codepoints": [8846], "characters": "\u228E" },
+  "&upsi;": { "codepoints": [965], "characters": "\u03C5" },
+  "&upsih;": { "codepoints": [978], "characters": "\u03D2" },
+  "&upsilon;": { "codepoints": [965], "characters": "\u03C5" },
+  "&upuparrows;": { "codepoints": [8648], "characters": "\u21C8" },
+  "&urcorn;": { "codepoints": [8989], "characters": "\u231D" },
+  "&urcorner;": { "codepoints": [8989], "characters": "\u231D" },
+  "&urcrop;": { "codepoints": [8974], "characters": "\u230E" },
+  "&uring;": { "codepoints": [367], "characters": "\u016F" },
+  "&urtri;": { "codepoints": [9721], "characters": "\u25F9" },
+  "&uscr;": { "codepoints": [120010], "characters": "\uD835\uDCCA" },
+  "&utdot;": { "codepoints": [8944], "characters": "\u22F0" },
+  "&utilde;": { "codepoints": [361], "characters": "\u0169" },
+  "&utri;": { "codepoints": [9653], "characters": "\u25B5" },
+  "&utrif;": { "codepoints": [9652], "characters": "\u25B4" },
+  "&uuarr;": { "codepoints": [8648], "characters": "\u21C8" },
+  "&uuml": { "codepoints": [252], "characters": "\u00FC" },
+  "&uuml;": { "codepoints": [252], "characters": "\u00FC" },
+  "&uwangle;": { "codepoints": [10663], "characters": "\u29A7" },
+  "&vArr;": { "codepoints": [8661], "characters": "\u21D5" },
+  "&vBar;": { "codepoints": [10984], "characters": "\u2AE8" },
+  "&vBarv;": { "codepoints": [10985], "characters": "\u2AE9" },
+  "&vDash;": { "codepoints": [8872], "characters": "\u22A8" },
+  "&vangrt;": { "codepoints": [10652], "characters": "\u299C" },
+  "&varepsilon;": { "codepoints": [1013], "characters": "\u03F5" },
+  "&varkappa;": { "codepoints": [1008], "characters": "\u03F0" },
+  "&varnothing;": { "codepoints": [8709], "characters": "\u2205" },
+  "&varphi;": { "codepoints": [981], "characters": "\u03D5" },
+  "&varpi;": { "codepoints": [982], "characters": "\u03D6" },
+  "&varpropto;": { "codepoints": [8733], "characters": "\u221D" },
+  "&varr;": { "codepoints": [8597], "characters": "\u2195" },
+  "&varrho;": { "codepoints": [1009], "characters": "\u03F1" },
+  "&varsigma;": { "codepoints": [962], "characters": "\u03C2" },
+  "&varsubsetneq;": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+  "&varsubsetneqq;": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+  "&varsupsetneq;": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+  "&varsupsetneqq;": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+  "&vartheta;": { "codepoints": [977], "characters": "\u03D1" },
+  "&vartriangleleft;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&vartriangleright;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&vcy;": { "codepoints": [1074], "characters": "\u0432" },
+  "&vdash;": { "codepoints": [8866], "characters": "\u22A2" },
+  "&vee;": { "codepoints": [8744], "characters": "\u2228" },
+  "&veebar;": { "codepoints": [8891], "characters": "\u22BB" },
+  "&veeeq;": { "codepoints": [8794], "characters": "\u225A" },
+  "&vellip;": { "codepoints": [8942], "characters": "\u22EE" },
+  "&verbar;": { "codepoints": [124], "characters": "\u007C" },
+  "&vert;": { "codepoints": [124], "characters": "\u007C" },
+  "&vfr;": { "codepoints": [120115], "characters": "\uD835\uDD33" },
+  "&vltri;": { "codepoints": [8882], "characters": "\u22B2" },
+  "&vnsub;": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+  "&vnsup;": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+  "&vopf;": { "codepoints": [120167], "characters": "\uD835\uDD67" },
+  "&vprop;": { "codepoints": [8733], "characters": "\u221D" },
+  "&vrtri;": { "codepoints": [8883], "characters": "\u22B3" },
+  "&vscr;": { "codepoints": [120011], "characters": "\uD835\uDCCB" },
+  "&vsubnE;": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+  "&vsubne;": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+  "&vsupnE;": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+  "&vsupne;": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+  "&vzigzag;": { "codepoints": [10650], "characters": "\u299A" },
+  "&wcirc;": { "codepoints": [373], "characters": "\u0175" },
+  "&wedbar;": { "codepoints": [10847], "characters": "\u2A5F" },
+  "&wedge;": { "codepoints": [8743], "characters": "\u2227" },
+  "&wedgeq;": { "codepoints": [8793], "characters": "\u2259" },
+  "&weierp;": { "codepoints": [8472], "characters": "\u2118" },
+  "&wfr;": { "codepoints": [120116], "characters": "\uD835\uDD34" },
+  "&wopf;": { "codepoints": [120168], "characters": "\uD835\uDD68" },
+  "&wp;": { "codepoints": [8472], "characters": "\u2118" },
+  "&wr;": { "codepoints": [8768], "characters": "\u2240" },
+  "&wreath;": { "codepoints": [8768], "characters": "\u2240" },
+  "&wscr;": { "codepoints": [120012], "characters": "\uD835\uDCCC" },
+  "&xcap;": { "codepoints": [8898], "characters": "\u22C2" },
+  "&xcirc;": { "codepoints": [9711], "characters": "\u25EF" },
+  "&xcup;": { "codepoints": [8899], "characters": "\u22C3" },
+  "&xdtri;": { "codepoints": [9661], "characters": "\u25BD" },
+  "&xfr;": { "codepoints": [120117], "characters": "\uD835\uDD35" },
+  "&xhArr;": { "codepoints": [10234], "characters": "\u27FA" },
+  "&xharr;": { "codepoints": [10231], "characters": "\u27F7" },
+  "&xi;": { "codepoints": [958], "characters": "\u03BE" },
+  "&xlArr;": { "codepoints": [10232], "characters": "\u27F8" },
+  "&xlarr;": { "codepoints": [10229], "characters": "\u27F5" },
+  "&xmap;": { "codepoints": [10236], "characters": "\u27FC" },
+  "&xnis;": { "codepoints": [8955], "characters": "\u22FB" },
+  "&xodot;": { "codepoints": [10752], "characters": "\u2A00" },
+  "&xopf;": { "codepoints": [120169], "characters": "\uD835\uDD69" },
+  "&xoplus;": { "codepoints": [10753], "characters": "\u2A01" },
+  "&xotime;": { "codepoints": [10754], "characters": "\u2A02" },
+  "&xrArr;": { "codepoints": [10233], "characters": "\u27F9" },
+  "&xrarr;": { "codepoints": [10230], "characters": "\u27F6" },
+  "&xscr;": { "codepoints": [120013], "characters": "\uD835\uDCCD" },
+  "&xsqcup;": { "codepoints": [10758], "characters": "\u2A06" },
+  "&xuplus;": { "codepoints": [10756], "characters": "\u2A04" },
+  "&xutri;": { "codepoints": [9651], "characters": "\u25B3" },
+  "&xvee;": { "codepoints": [8897], "characters": "\u22C1" },
+  "&xwedge;": { "codepoints": [8896], "characters": "\u22C0" },
+  "&yacute": { "codepoints": [253], "characters": "\u00FD" },
+  "&yacute;": { "codepoints": [253], "characters": "\u00FD" },
+  "&yacy;": { "codepoints": [1103], "characters": "\u044F" },
+  "&ycirc;": { "codepoints": [375], "characters": "\u0177" },
+  "&ycy;": { "codepoints": [1099], "characters": "\u044B" },
+  "&yen": { "codepoints": [165], "characters": "\u00A5" },
+  "&yen;": { "codepoints": [165], "characters": "\u00A5" },
+  "&yfr;": { "codepoints": [120118], "characters": "\uD835\uDD36" },
+  "&yicy;": { "codepoints": [1111], "characters": "\u0457" },
+  "&yopf;": { "codepoints": [120170], "characters": "\uD835\uDD6A" },
+  "&yscr;": { "codepoints": [120014], "characters": "\uD835\uDCCE" },
+  "&yucy;": { "codepoints": [1102], "characters": "\u044E" },
+  "&yuml": { "codepoints": [255], "characters": "\u00FF" },
+  "&yuml;": { "codepoints": [255], "characters": "\u00FF" },
+  "&zacute;": { "codepoints": [378], "characters": "\u017A" },
+  "&zcaron;": { "codepoints": [382], "characters": "\u017E" },
+  "&zcy;": { "codepoints": [1079], "characters": "\u0437" },
+  "&zdot;": { "codepoints": [380], "characters": "\u017C" },
+  "&zeetrf;": { "codepoints": [8488], "characters": "\u2128" },
+  "&zeta;": { "codepoints": [950], "characters": "\u03B6" },
+  "&zfr;": { "codepoints": [120119], "characters": "\uD835\uDD37" },
+  "&zhcy;": { "codepoints": [1078], "characters": "\u0436" },
+  "&zigrarr;": { "codepoints": [8669], "characters": "\u21DD" },
+  "&zopf;": { "codepoints": [120171], "characters": "\uD835\uDD6B" },
+  "&zscr;": { "codepoints": [120015], "characters": "\uD835\uDCCF" },
+  "&zwj;": { "codepoints": [8205], "characters": "\u200D" },
+  "&zwnj;": { "codepoints": [8204], "characters": "\u200C" }
+}
diff --git a/pkgs/markdown/tool/expected_output.dart b/pkgs/markdown/tool/expected_output.dart
new file mode 100644
index 0000000..aa7bab3
--- /dev/null
+++ b/pkgs/markdown/tool/expected_output.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+
+/// Parse and yield data cases (each a [DataCase]) from [path].
+Iterable<DataCase> dataCasesInFile({
+  required String path,
+  String? baseDir,
+}) sync* {
+  final file = p.basename(path).replaceFirst(RegExp(r'\..+$'), '');
+  baseDir ??= p.relative(p.dirname(path), from: p.dirname(p.dirname(path)));
+
+  // Explicitly create a File, in case the entry is a Link.
+  final lines = File(path).readAsLinesSync();
+
+  final frontMatter = StringBuffer();
+
+  var i = 0;
+
+  while (!lines[i].startsWith('>>>')) {
+    frontMatter.write('${lines[i++]}\n');
+  }
+
+  while (i < lines.length) {
+    var description = lines[i++].replaceFirst(RegExp(r'>>>\s*'), '').trim();
+    final skip = description.startsWith('skip:');
+    if (description == '') {
+      description = 'line ${i + 1}';
+    } else {
+      description = 'line ${i + 1}: $description';
+    }
+
+    final input = StringBuffer();
+    while (!lines[i].startsWith('<<<')) {
+      input.writeln(lines[i++]);
+    }
+
+    final expectedOutput = StringBuffer();
+    while (++i < lines.length && !lines[i].startsWith('>>>')) {
+      expectedOutput.writeln(lines[i]);
+    }
+
+    final dataCase = DataCase(
+      directory: baseDir,
+      file: file,
+      front_matter: frontMatter.toString(),
+      description: description,
+      skip: skip,
+      input: input.toString(),
+      expectedOutput: expectedOutput.toString(),
+    );
+    yield dataCase;
+  }
+}
+
+/// Parse and return data cases (each a [DataCase]) from [directory].
+///
+/// By default, only read data cases from files with a `.unit` extension. Data
+/// cases are read from files located immediately in [directory], or
+/// recursively, according to [recursive].
+Iterable<DataCase> _dataCases({
+  required String directory,
+  String extension = 'unit',
+  bool recursive = true,
+}) {
+  final entries =
+      Directory(directory).listSync(recursive: recursive, followLinks: false);
+  final results = <DataCase>[];
+  for (final entry in entries) {
+    if (!entry.path.endsWith(extension)) {
+      continue;
+    }
+
+    final relativeDir =
+        p.relative(p.dirname(entry.path), from: p.dirname(directory));
+
+    results.addAll(dataCasesInFile(path: entry.path, baseDir: relativeDir));
+  }
+
+  // The API makes no guarantees on order. This is just here for stability in
+  // tests.
+  results.sort((a, b) {
+    final compare = a.directory.compareTo(b.directory);
+    if (compare != 0) return compare;
+
+    return a.file.compareTo(b.file);
+  });
+  return results;
+}
+
+/// Parse and yield data cases (each a [DataCase]) from [testDirectory].
+///
+/// By default, only read data cases from files with a `.unit` extension. Data
+/// cases are read from files located immediately in [testDirectory], or
+/// recursively, according to [recursive].
+///
+/// The typical use case of this method is to declare a library at the top of a
+/// Dart test file, then reference the symbol with a pound sign. Example:
+///
+/// ```dart
+/// library my_package.test.this_test;
+///
+/// import 'package:expected_output/expected_output.dart';
+/// import 'package:test/test.dart';
+///
+/// void main() {
+///   for (final dataCase
+///       in dataCasesUnder(library: #my_package.test.this_test)) {
+///     // ...
+///   }
+/// }
+/// ```
+Iterable<DataCase> dataCasesUnder({
+  required String testDirectory,
+  String extension = 'unit',
+  bool recursive = true,
+}) sync* {
+  final directory = p.join(p.current, 'test', testDirectory);
+  for (final dataCase in _dataCases(
+    directory: directory,
+    extension: extension,
+    recursive: recursive,
+  )) {
+    yield dataCase;
+  }
+}
+
+/// All of the data pertaining to a particular test case, namely the [input] and
+/// [expectedOutput].
+class DataCase {
+  final String directory;
+  final String file;
+
+  // ignore: non_constant_identifier_names
+  final String front_matter;
+  final String description;
+  final bool skip;
+  final String input;
+  final String expectedOutput;
+
+  DataCase({
+    this.directory = '',
+    this.file = '',
+    // ignore: non_constant_identifier_names
+    this.front_matter = '',
+    this.description = '',
+    this.skip = false,
+    required this.input,
+    required this.expectedOutput,
+  });
+
+  /// A good standard description for `test()`, derived from the data directory,
+  /// the particular data file, and the test case description.
+  String get testDescription => [directory, file, description].join(' ');
+}
diff --git a/pkgs/markdown/tool/gfm_stats.json b/pkgs/markdown/tool/gfm_stats.json
new file mode 100644
index 0000000..93c0cab
--- /dev/null
+++ b/pkgs/markdown/tool/gfm_stats.json
@@ -0,0 +1,732 @@
+{
+ "ATX headings": {
+  "32": "strict",
+  "33": "strict",
+  "34": "strict",
+  "35": "strict",
+  "36": "strict",
+  "37": "strict",
+  "38": "strict",
+  "39": "strict",
+  "40": "strict",
+  "41": "strict",
+  "42": "strict",
+  "43": "strict",
+  "44": "strict",
+  "45": "strict",
+  "46": "strict",
+  "47": "strict",
+  "48": "strict",
+  "49": "strict"
+ },
+ "Autolinks": {
+  "602": "strict",
+  "603": "strict",
+  "604": "strict",
+  "605": "strict",
+  "606": "strict",
+  "607": "strict",
+  "608": "strict",
+  "609": "strict",
+  "610": "strict",
+  "611": "strict",
+  "612": "strict",
+  "613": "strict",
+  "614": "strict",
+  "615": "strict",
+  "616": "strict",
+  "617": "strict",
+  "618": "strict",
+  "619": "strict",
+  "620": "strict"
+ },
+ "Autolinks (extension)": {
+  "621": "strict",
+  "622": "strict",
+  "623": "strict",
+  "624": "strict",
+  "625": "strict",
+  "626": "strict",
+  "627": "strict",
+  "628": "strict",
+  "629": "strict",
+  "630": "strict",
+  "631": "strict"
+ },
+ "Backslash escapes": {
+  "308": "strict",
+  "309": "strict",
+  "310": "strict",
+  "311": "strict",
+  "312": "strict",
+  "313": "strict",
+  "314": "strict",
+  "315": "strict",
+  "316": "strict",
+  "317": "strict",
+  "318": "strict",
+  "319": "strict",
+  "320": "strict"
+ },
+ "Blank lines": {
+  "197": "strict"
+ },
+ "Block quotes": {
+  "206": "strict",
+  "207": "strict",
+  "208": "strict",
+  "209": "strict",
+  "210": "strict",
+  "211": "strict",
+  "212": "strict",
+  "213": "strict",
+  "214": "strict",
+  "215": "strict",
+  "216": "strict",
+  "217": "strict",
+  "218": "strict",
+  "219": "strict",
+  "220": "strict",
+  "221": "strict",
+  "222": "strict",
+  "223": "strict",
+  "224": "strict",
+  "225": "strict",
+  "226": "strict",
+  "227": "strict",
+  "228": "strict",
+  "229": "strict",
+  "230": "strict"
+ },
+ "Code spans": {
+  "338": "strict",
+  "339": "strict",
+  "340": "strict",
+  "341": "strict",
+  "342": "strict",
+  "343": "strict",
+  "344": "strict",
+  "345": "strict",
+  "346": "strict",
+  "347": "strict",
+  "348": "strict",
+  "349": "strict",
+  "350": "strict",
+  "351": "strict",
+  "352": "strict",
+  "353": "strict",
+  "354": "strict",
+  "355": "strict",
+  "356": "strict",
+  "357": "strict",
+  "358": "strict",
+  "359": "strict"
+ },
+ "Disallowed Raw HTML (extension)": {
+  "652": "loose"
+ },
+ "Emphasis and strong emphasis": {
+  "360": "strict",
+  "361": "strict",
+  "362": "strict",
+  "363": "strict",
+  "364": "strict",
+  "365": "strict",
+  "366": "strict",
+  "367": "strict",
+  "368": "strict",
+  "369": "strict",
+  "370": "strict",
+  "371": "strict",
+  "372": "strict",
+  "373": "strict",
+  "374": "strict",
+  "375": "strict",
+  "376": "strict",
+  "377": "strict",
+  "378": "strict",
+  "379": "strict",
+  "380": "strict",
+  "381": "strict",
+  "382": "strict",
+  "383": "strict",
+  "384": "strict",
+  "385": "strict",
+  "386": "strict",
+  "387": "strict",
+  "388": "strict",
+  "389": "strict",
+  "390": "strict",
+  "391": "strict",
+  "392": "strict",
+  "393": "strict",
+  "394": "strict",
+  "395": "strict",
+  "396": "strict",
+  "397": "strict",
+  "398": "strict",
+  "399": "strict",
+  "400": "strict",
+  "401": "strict",
+  "402": "strict",
+  "403": "strict",
+  "404": "strict",
+  "405": "strict",
+  "406": "strict",
+  "407": "strict",
+  "408": "strict",
+  "409": "strict",
+  "410": "strict",
+  "411": "strict",
+  "412": "strict",
+  "413": "strict",
+  "414": "strict",
+  "415": "strict",
+  "416": "strict",
+  "417": "strict",
+  "418": "strict",
+  "419": "strict",
+  "420": "strict",
+  "421": "strict",
+  "422": "strict",
+  "423": "strict",
+  "424": "strict",
+  "425": "strict",
+  "426": "strict",
+  "427": "strict",
+  "428": "strict",
+  "429": "strict",
+  "430": "strict",
+  "431": "strict",
+  "432": "strict",
+  "433": "strict",
+  "434": "strict",
+  "435": "strict",
+  "436": "strict",
+  "437": "strict",
+  "438": "strict",
+  "439": "strict",
+  "440": "strict",
+  "441": "strict",
+  "442": "strict",
+  "443": "strict",
+  "444": "strict",
+  "445": "strict",
+  "446": "strict",
+  "447": "strict",
+  "448": "strict",
+  "449": "strict",
+  "450": "strict",
+  "451": "strict",
+  "452": "strict",
+  "453": "strict",
+  "454": "strict",
+  "455": "strict",
+  "456": "strict",
+  "457": "strict",
+  "458": "strict",
+  "459": "strict",
+  "460": "strict",
+  "461": "strict",
+  "462": "strict",
+  "463": "strict",
+  "464": "strict",
+  "465": "strict",
+  "466": "strict",
+  "467": "strict",
+  "468": "strict",
+  "469": "strict",
+  "470": "strict",
+  "471": "strict",
+  "472": "strict",
+  "473": "strict",
+  "474": "strict",
+  "475": "strict",
+  "476": "strict",
+  "477": "strict",
+  "478": "strict",
+  "479": "strict",
+  "480": "strict",
+  "481": "strict",
+  "482": "strict",
+  "483": "strict",
+  "484": "strict",
+  "485": "strict",
+  "486": "strict",
+  "487": "strict",
+  "488": "strict",
+  "489": "strict",
+  "490": "strict"
+ },
+ "Entity and numeric character references": {
+  "321": "loose",
+  "322": "strict",
+  "323": "strict",
+  "324": "strict",
+  "325": "strict",
+  "326": "strict",
+  "327": "strict",
+  "328": "strict",
+  "329": "strict",
+  "330": "strict",
+  "331": "strict",
+  "332": "strict",
+  "333": "strict",
+  "334": "strict",
+  "335": "strict",
+  "336": "loose",
+  "337": "strict"
+ },
+ "Fenced code blocks": {
+  "89": "strict",
+  "90": "strict",
+  "91": "strict",
+  "92": "strict",
+  "93": "strict",
+  "94": "strict",
+  "95": "strict",
+  "96": "strict",
+  "97": "strict",
+  "98": "strict",
+  "99": "strict",
+  "100": "strict",
+  "101": "strict",
+  "102": "strict",
+  "103": "strict",
+  "104": "strict",
+  "105": "strict",
+  "106": "strict",
+  "107": "strict",
+  "108": "strict",
+  "109": "strict",
+  "110": "strict",
+  "111": "strict",
+  "112": "strict",
+  "113": "strict",
+  "114": "strict",
+  "115": "strict",
+  "116": "strict",
+  "117": "strict"
+ },
+ "Hard line breaks": {
+  "653": "strict",
+  "654": "strict",
+  "655": "strict",
+  "656": "strict",
+  "657": "strict",
+  "658": "strict",
+  "659": "strict",
+  "660": "strict",
+  "661": "strict",
+  "662": "strict",
+  "663": "strict",
+  "664": "strict",
+  "665": "strict",
+  "666": "strict",
+  "667": "strict"
+ },
+ "HTML blocks": {
+  "118": "strict",
+  "119": "strict",
+  "120": "strict",
+  "121": "strict",
+  "122": "strict",
+  "123": "strict",
+  "124": "strict",
+  "125": "strict",
+  "126": "strict",
+  "127": "strict",
+  "128": "strict",
+  "129": "strict",
+  "130": "strict",
+  "131": "strict",
+  "132": "strict",
+  "133": "strict",
+  "134": "strict",
+  "135": "strict",
+  "136": "strict",
+  "137": "strict",
+  "138": "strict",
+  "139": "strict",
+  "140": "strict",
+  "141": "strict",
+  "142": "strict",
+  "143": "strict",
+  "144": "strict",
+  "145": "strict",
+  "146": "strict",
+  "147": "strict",
+  "148": "strict",
+  "149": "strict",
+  "150": "strict",
+  "151": "strict",
+  "152": "strict",
+  "153": "strict",
+  "154": "strict",
+  "155": "strict",
+  "156": "strict",
+  "157": "strict",
+  "158": "strict",
+  "159": "strict",
+  "160": "strict"
+ },
+ "Images": {
+  "580": "strict",
+  "581": "strict",
+  "582": "strict",
+  "583": "strict",
+  "584": "strict",
+  "585": "strict",
+  "586": "strict",
+  "587": "strict",
+  "588": "strict",
+  "589": "strict",
+  "590": "strict",
+  "591": "strict",
+  "592": "strict",
+  "593": "strict",
+  "594": "strict",
+  "595": "strict",
+  "596": "strict",
+  "597": "strict",
+  "598": "strict",
+  "599": "strict",
+  "600": "strict",
+  "601": "strict"
+ },
+ "Indented code blocks": {
+  "77": "strict",
+  "78": "strict",
+  "79": "strict",
+  "80": "strict",
+  "81": "strict",
+  "82": "strict",
+  "83": "strict",
+  "84": "strict",
+  "85": "strict",
+  "86": "strict",
+  "87": "strict",
+  "88": "strict"
+ },
+ "Inlines": {
+  "307": "strict"
+ },
+ "Link reference definitions": {
+  "161": "strict",
+  "162": "strict",
+  "163": "strict",
+  "164": "strict",
+  "165": "strict",
+  "166": "strict",
+  "167": "strict",
+  "168": "strict",
+  "169": "strict",
+  "170": "strict",
+  "171": "strict",
+  "172": "strict",
+  "173": "strict",
+  "174": "strict",
+  "175": "strict",
+  "176": "loose",
+  "177": "strict",
+  "178": "strict",
+  "179": "strict",
+  "180": "strict",
+  "181": "strict",
+  "182": "strict",
+  "183": "strict",
+  "184": "strict",
+  "185": "strict",
+  "186": "strict",
+  "187": "strict",
+  "188": "loose"
+ },
+ "Links": {
+  "493": "strict",
+  "494": "strict",
+  "495": "strict",
+  "496": "strict",
+  "497": "strict",
+  "498": "strict",
+  "499": "strict",
+  "500": "strict",
+  "501": "strict",
+  "502": "strict",
+  "503": "strict",
+  "504": "strict",
+  "505": "strict",
+  "506": "strict",
+  "507": "strict",
+  "508": "strict",
+  "509": "strict",
+  "510": "strict",
+  "511": "strict",
+  "512": "strict",
+  "513": "strict",
+  "514": "strict",
+  "515": "strict",
+  "516": "strict",
+  "517": "strict",
+  "518": "strict",
+  "519": "strict",
+  "520": "strict",
+  "521": "strict",
+  "522": "strict",
+  "523": "strict",
+  "524": "strict",
+  "525": "strict",
+  "526": "strict",
+  "527": "strict",
+  "528": "strict",
+  "529": "strict",
+  "530": "strict",
+  "531": "strict",
+  "532": "strict",
+  "533": "strict",
+  "534": "strict",
+  "535": "strict",
+  "536": "strict",
+  "537": "strict",
+  "538": "strict",
+  "539": "strict",
+  "540": "strict",
+  "541": "strict",
+  "542": "strict",
+  "543": "strict",
+  "544": "strict",
+  "545": "strict",
+  "546": "strict",
+  "547": "strict",
+  "548": "strict",
+  "549": "strict",
+  "550": "strict",
+  "551": "strict",
+  "552": "strict",
+  "553": "strict",
+  "554": "strict",
+  "555": "strict",
+  "556": "strict",
+  "557": "strict",
+  "558": "strict",
+  "559": "strict",
+  "560": "strict",
+  "561": "strict",
+  "562": "strict",
+  "563": "strict",
+  "564": "strict",
+  "565": "strict",
+  "566": "strict",
+  "567": "strict",
+  "568": "strict",
+  "569": "strict",
+  "570": "strict",
+  "571": "strict",
+  "572": "strict",
+  "573": "strict",
+  "574": "strict",
+  "575": "strict",
+  "576": "strict",
+  "577": "strict",
+  "578": "strict",
+  "579": "strict"
+ },
+ "List items": {
+  "231": "strict",
+  "232": "strict",
+  "233": "strict",
+  "234": "strict",
+  "235": "strict",
+  "236": "strict",
+  "237": "strict",
+  "238": "strict",
+  "239": "strict",
+  "240": "strict",
+  "241": "strict",
+  "242": "strict",
+  "243": "strict",
+  "244": "strict",
+  "245": "strict",
+  "246": "strict",
+  "247": "strict",
+  "248": "strict",
+  "249": "strict",
+  "250": "strict",
+  "251": "strict",
+  "252": "strict",
+  "253": "strict",
+  "254": "strict",
+  "255": "strict",
+  "256": "strict",
+  "257": "strict",
+  "258": "strict",
+  "259": "strict",
+  "260": "strict",
+  "261": "strict",
+  "262": "strict",
+  "263": "strict",
+  "264": "strict",
+  "265": "strict",
+  "266": "strict",
+  "267": "strict",
+  "268": "strict",
+  "269": "strict",
+  "270": "strict",
+  "271": "strict",
+  "272": "strict",
+  "273": "strict",
+  "274": "strict",
+  "275": "strict",
+  "276": "strict",
+  "277": "strict",
+  "278": "strict"
+ },
+ "Lists": {
+  "281": "strict",
+  "282": "strict",
+  "283": "strict",
+  "284": "strict",
+  "285": "strict",
+  "286": "strict",
+  "287": "strict",
+  "288": "strict",
+  "289": "strict",
+  "290": "strict",
+  "291": "strict",
+  "292": "strict",
+  "293": "strict",
+  "294": "strict",
+  "295": "strict",
+  "296": "strict",
+  "297": "strict",
+  "298": "strict",
+  "299": "strict",
+  "300": "strict",
+  "301": "strict",
+  "302": "strict",
+  "303": "strict",
+  "304": "strict",
+  "305": "strict",
+  "306": "strict"
+ },
+ "Paragraphs": {
+  "189": "strict",
+  "190": "strict",
+  "191": "strict",
+  "192": "strict",
+  "193": "strict",
+  "194": "strict",
+  "195": "strict",
+  "196": "strict"
+ },
+ "Precedence": {
+  "12": "strict"
+ },
+ "Raw HTML": {
+  "632": "strict",
+  "633": "strict",
+  "634": "strict",
+  "635": "strict",
+  "636": "strict",
+  "637": "strict",
+  "638": "strict",
+  "639": "strict",
+  "640": "strict",
+  "641": "strict",
+  "642": "strict",
+  "643": "strict",
+  "644": "loose",
+  "645": "loose",
+  "646": "strict",
+  "647": "strict",
+  "648": "strict",
+  "649": "strict",
+  "650": "strict",
+  "651": "strict"
+ },
+ "Setext headings": {
+  "50": "strict",
+  "51": "strict",
+  "52": "loose",
+  "53": "strict",
+  "54": "loose",
+  "55": "strict",
+  "56": "strict",
+  "57": "strict",
+  "58": "strict",
+  "59": "strict",
+  "60": "strict",
+  "61": "strict",
+  "62": "strict",
+  "63": "strict",
+  "64": "strict",
+  "65": "strict",
+  "66": "strict",
+  "67": "strict",
+  "68": "strict",
+  "69": "strict",
+  "70": "strict",
+  "71": "strict",
+  "72": "strict",
+  "73": "strict",
+  "74": "strict",
+  "75": "strict",
+  "76": "strict"
+ },
+ "Soft line breaks": {
+  "668": "strict",
+  "669": "strict"
+ },
+ "Strikethrough (extension)": {
+  "491": "strict",
+  "492": "strict"
+ },
+ "Tables (extension)": {
+  "198": "strict",
+  "199": "strict",
+  "200": "strict",
+  "201": "strict",
+  "202": "strict",
+  "203": "strict",
+  "204": "strict",
+  "205": "strict"
+ },
+ "Tabs": {
+  "1": "strict",
+  "2": "strict",
+  "3": "strict",
+  "4": "strict",
+  "5": "strict",
+  "6": "loose",
+  "7": "strict",
+  "8": "strict",
+  "9": "strict",
+  "10": "strict",
+  "11": "strict"
+ },
+ "Textual content": {
+  "670": "strict",
+  "671": "strict",
+  "672": "strict"
+ },
+ "Thematic breaks": {
+  "13": "strict",
+  "14": "strict",
+  "15": "strict",
+  "16": "strict",
+  "17": "strict",
+  "18": "strict",
+  "19": "strict",
+  "20": "strict",
+  "21": "strict",
+  "22": "strict",
+  "23": "strict",
+  "24": "strict",
+  "25": "strict",
+  "26": "strict",
+  "27": "strict",
+  "28": "strict",
+  "29": "strict",
+  "30": "strict",
+  "31": "strict"
+ }
+}
diff --git a/pkgs/markdown/tool/gfm_stats.txt b/pkgs/markdown/tool/gfm_stats.txt
new file mode 100644
index 0000000..06e240b
--- /dev/null
+++ b/pkgs/markdown/tool/gfm_stats.txt
@@ -0,0 +1,32 @@
+  18 of   18 – 100.0%  ATX headings
+  19 of   19 – 100.0%  Autolinks
+  11 of   11 – 100.0%  Autolinks (extension)
+  13 of   13 – 100.0%  Backslash escapes
+   1 of    1 – 100.0%  Blank lines
+  25 of   25 – 100.0%  Block quotes
+  22 of   22 – 100.0%  Code spans
+   1 of    1 – 100.0%  Disallowed Raw HTML (extension)
+ 131 of  131 – 100.0%  Emphasis and strong emphasis
+  17 of   17 – 100.0%  Entity and numeric character references
+  29 of   29 – 100.0%  Fenced code blocks
+  15 of   15 – 100.0%  Hard line breaks
+  43 of   43 – 100.0%  HTML blocks
+  22 of   22 – 100.0%  Images
+  12 of   12 – 100.0%  Indented code blocks
+   1 of    1 – 100.0%  Inlines
+  28 of   28 – 100.0%  Link reference definitions
+  87 of   87 – 100.0%  Links
+  48 of   48 – 100.0%  List items
+  26 of   26 – 100.0%  Lists
+   8 of    8 – 100.0%  Paragraphs
+   1 of    1 – 100.0%  Precedence
+  20 of   20 – 100.0%  Raw HTML
+  27 of   27 – 100.0%  Setext headings
+   2 of    2 – 100.0%  Soft line breaks
+   2 of    2 – 100.0%  Strikethrough (extension)
+   8 of    8 – 100.0%  Tables (extension)
+  11 of   11 – 100.0%  Tabs
+   3 of    3 – 100.0%  Textual content
+  19 of   19 – 100.0%  Thematic breaks
+ 670 of  670 – 100.0%  TOTAL
+ 660 of  670 –  98.5%  TOTAL Strict
diff --git a/pkgs/markdown/tool/gfm_tests.json b/pkgs/markdown/tool/gfm_tests.json
new file mode 100644
index 0000000..e5e849c
--- /dev/null
+++ b/pkgs/markdown/tool/gfm_tests.json
@@ -0,0 +1,6076 @@
+[
+  {
+    "markdown": "\tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 1,
+    "start_line": 368,
+    "end_line": 373,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "  \tfoo\tbaz\t\tbim\n",
+    "html": "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n",
+    "example": 2,
+    "start_line": 375,
+    "end_line": 380,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "    a\ta\n    \u1f50\ta\n",
+    "html": "<pre><code>a\ta\n\u1f50\ta\n</code></pre>\n",
+    "example": 3,
+    "start_line": 382,
+    "end_line": 389,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "  - foo\n\n\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 4,
+    "start_line": 395,
+    "end_line": 406,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n\t\tbar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>  bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 5,
+    "start_line": 408,
+    "end_line": 420,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": ">\t\tfoo\n",
+    "html": "<blockquote>\n<pre><code>  foo\n</code></pre>\n</blockquote>\n",
+    "example": 6,
+    "start_line": 431,
+    "end_line": 438,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "-\t\tfoo\n",
+    "html": "<ul>\n<li>\n<pre><code>  foo\n</code></pre>\n</li>\n</ul>\n",
+    "example": 7,
+    "start_line": 440,
+    "end_line": 449,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\n\tbar\n",
+    "html": "<pre><code>foo\nbar\n</code></pre>\n",
+    "example": 8,
+    "start_line": 452,
+    "end_line": 459,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": " - foo\n   - bar\n\t - baz\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 9,
+    "start_line": 461,
+    "end_line": 477,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "#\tFoo\n",
+    "html": "<h1>Foo</h1>\n",
+    "example": 10,
+    "start_line": 479,
+    "end_line": 483,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "*\t*\t*\t\n",
+    "html": "<hr />\n",
+    "example": 11,
+    "start_line": 485,
+    "end_line": 489,
+    "section": "Tabs",
+    "extensions": []
+  },
+  {
+    "markdown": "- `one\n- two`\n",
+    "html": "<ul>\n<li>`one</li>\n<li>two`</li>\n</ul>\n",
+    "example": 12,
+    "start_line": 512,
+    "end_line": 520,
+    "section": "Precedence",
+    "extensions": []
+  },
+  {
+    "markdown": "***\n---\n___\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 13,
+    "start_line": 551,
+    "end_line": 559,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "+++\n",
+    "html": "<p>+++</p>\n",
+    "example": 14,
+    "start_line": 564,
+    "end_line": 568,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "===\n",
+    "html": "<p>===</p>\n",
+    "example": 15,
+    "start_line": 571,
+    "end_line": 575,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "--\n**\n__\n",
+    "html": "<p>--\n**\n__</p>\n",
+    "example": 16,
+    "start_line": 580,
+    "end_line": 588,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " ***\n  ***\n   ***\n",
+    "html": "<hr />\n<hr />\n<hr />\n",
+    "example": 17,
+    "start_line": 593,
+    "end_line": 601,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "    ***\n",
+    "html": "<pre><code>***\n</code></pre>\n",
+    "example": 18,
+    "start_line": 606,
+    "end_line": 611,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    ***\n",
+    "html": "<p>Foo\n***</p>\n",
+    "example": 19,
+    "start_line": 614,
+    "end_line": 620,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "_____________________________________\n",
+    "html": "<hr />\n",
+    "example": 20,
+    "start_line": 625,
+    "end_line": 629,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " - - -\n",
+    "html": "<hr />\n",
+    "example": 21,
+    "start_line": 634,
+    "end_line": 638,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " **  * ** * ** * **\n",
+    "html": "<hr />\n",
+    "example": 22,
+    "start_line": 641,
+    "end_line": 645,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "-     -      -      -\n",
+    "html": "<hr />\n",
+    "example": 23,
+    "start_line": 648,
+    "end_line": 652,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- - - -    \n",
+    "html": "<hr />\n",
+    "example": 24,
+    "start_line": 657,
+    "end_line": 661,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "_ _ _ _ a\n\na------\n\n---a---\n",
+    "html": "<p>_ _ _ _ a</p>\n<p>a------</p>\n<p>---a---</p>\n",
+    "example": 25,
+    "start_line": 666,
+    "end_line": 676,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": " *-*\n",
+    "html": "<p><em>-</em></p>\n",
+    "example": 26,
+    "start_line": 682,
+    "end_line": 686,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n***\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 27,
+    "start_line": 691,
+    "end_line": 703,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n***\nbar\n",
+    "html": "<p>Foo</p>\n<hr />\n<p>bar</p>\n",
+    "example": 28,
+    "start_line": 708,
+    "end_line": 716,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n---\nbar\n",
+    "html": "<h2>Foo</h2>\n<p>bar</p>\n",
+    "example": 29,
+    "start_line": 725,
+    "end_line": 732,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "* Foo\n* * *\n* Bar\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n<ul>\n<li>Bar</li>\n</ul>\n",
+    "example": 30,
+    "start_line": 738,
+    "end_line": 750,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n- * * *\n",
+    "html": "<ul>\n<li>Foo</li>\n<li>\n<hr />\n</li>\n</ul>\n",
+    "example": 31,
+    "start_line": 755,
+    "end_line": 765,
+    "section": "Thematic breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo\n## foo\n### foo\n#### foo\n##### foo\n###### foo\n",
+    "html": "<h1>foo</h1>\n<h2>foo</h2>\n<h3>foo</h3>\n<h4>foo</h4>\n<h5>foo</h5>\n<h6>foo</h6>\n",
+    "example": 32,
+    "start_line": 784,
+    "end_line": 798,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "####### foo\n",
+    "html": "<p>####### foo</p>\n",
+    "example": 33,
+    "start_line": 803,
+    "end_line": 807,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "#5 bolt\n\n#hashtag\n",
+    "html": "<p>#5 bolt</p>\n<p>#hashtag</p>\n",
+    "example": 34,
+    "start_line": 818,
+    "end_line": 825,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\\## foo\n",
+    "html": "<p>## foo</p>\n",
+    "example": 35,
+    "start_line": 830,
+    "end_line": 834,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo *bar* \\*baz\\*\n",
+    "html": "<h1>foo <em>bar</em> *baz*</h1>\n",
+    "example": 36,
+    "start_line": 839,
+    "end_line": 843,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "#                  foo                     \n",
+    "html": "<h1>foo</h1>\n",
+    "example": 37,
+    "start_line": 848,
+    "end_line": 852,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": " ### foo\n  ## foo\n   # foo\n",
+    "html": "<h3>foo</h3>\n<h2>foo</h2>\n<h1>foo</h1>\n",
+    "example": 38,
+    "start_line": 857,
+    "end_line": 865,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    # foo\n",
+    "html": "<pre><code># foo\n</code></pre>\n",
+    "example": 39,
+    "start_line": 870,
+    "end_line": 875,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n    # bar\n",
+    "html": "<p>foo\n# bar</p>\n",
+    "example": 40,
+    "start_line": 878,
+    "end_line": 884,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "## foo ##\n  ###   bar    ###\n",
+    "html": "<h2>foo</h2>\n<h3>bar</h3>\n",
+    "example": 41,
+    "start_line": 889,
+    "end_line": 895,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo ##################################\n##### foo ##\n",
+    "html": "<h1>foo</h1>\n<h5>foo</h5>\n",
+    "example": 42,
+    "start_line": 900,
+    "end_line": 906,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo ###     \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 43,
+    "start_line": 911,
+    "end_line": 915,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo ### b\n",
+    "html": "<h3>foo ### b</h3>\n",
+    "example": 44,
+    "start_line": 922,
+    "end_line": 926,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "# foo#\n",
+    "html": "<h1>foo#</h1>\n",
+    "example": 45,
+    "start_line": 931,
+    "end_line": 935,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo \\###\n## foo #\\##\n# foo \\#\n",
+    "html": "<h3>foo ###</h3>\n<h2>foo ###</h2>\n<h1>foo #</h1>\n",
+    "example": 46,
+    "start_line": 941,
+    "end_line": 949,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "****\n## foo\n****\n",
+    "html": "<hr />\n<h2>foo</h2>\n<hr />\n",
+    "example": 47,
+    "start_line": 955,
+    "end_line": 963,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo bar\n# baz\nBar foo\n",
+    "html": "<p>Foo bar</p>\n<h1>baz</h1>\n<p>Bar foo</p>\n",
+    "example": 48,
+    "start_line": 966,
+    "end_line": 974,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "## \n#\n### ###\n",
+    "html": "<h2></h2>\n<h1></h1>\n<h3></h3>\n",
+    "example": 49,
+    "start_line": 979,
+    "end_line": 987,
+    "section": "ATX headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo *bar*\n=========\n\nFoo *bar*\n---------\n",
+    "html": "<h1>Foo <em>bar</em></h1>\n<h2>Foo <em>bar</em></h2>\n",
+    "example": 50,
+    "start_line": 1019,
+    "end_line": 1028,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo *bar\nbaz*\n====\n",
+    "html": "<h1>Foo <em>bar\nbaz</em></h1>\n",
+    "example": 51,
+    "start_line": 1033,
+    "end_line": 1040,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "  Foo *bar\nbaz*\t\n====\n",
+    "html": "<h1>Foo <em>bar\nbaz</em></h1>\n",
+    "example": 52,
+    "start_line": 1047,
+    "end_line": 1054,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n-------------------------\n\nFoo\n=\n",
+    "html": "<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 53,
+    "start_line": 1059,
+    "end_line": 1068,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "   Foo\n---\n\n  Foo\n-----\n\n  Foo\n  ===\n",
+    "html": "<h2>Foo</h2>\n<h2>Foo</h2>\n<h1>Foo</h1>\n",
+    "example": 54,
+    "start_line": 1074,
+    "end_line": 1087,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    Foo\n    ---\n\n    Foo\n---\n",
+    "html": "<pre><code>Foo\n---\n\nFoo\n</code></pre>\n<hr />\n",
+    "example": 55,
+    "start_line": 1092,
+    "end_line": 1105,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n   ----      \n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 56,
+    "start_line": 1111,
+    "end_line": 1116,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    ---\n",
+    "html": "<p>Foo\n---</p>\n",
+    "example": 57,
+    "start_line": 1121,
+    "end_line": 1127,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n= =\n\nFoo\n--- -\n",
+    "html": "<p>Foo\n= =</p>\n<p>Foo</p>\n<hr />\n",
+    "example": 58,
+    "start_line": 1132,
+    "end_line": 1143,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo  \n-----\n",
+    "html": "<h2>Foo</h2>\n",
+    "example": 59,
+    "start_line": 1148,
+    "end_line": 1153,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\\\n----\n",
+    "html": "<h2>Foo\\</h2>\n",
+    "example": 60,
+    "start_line": 1158,
+    "end_line": 1163,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "`Foo\n----\n`\n\n<a title=\"a lot\n---\nof dashes\"/>\n",
+    "html": "<h2>`Foo</h2>\n<p>`</p>\n<h2>&lt;a title=&quot;a lot</h2>\n<p>of dashes&quot;/&gt;</p>\n",
+    "example": 61,
+    "start_line": 1169,
+    "end_line": 1182,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> Foo\n---\n",
+    "html": "<blockquote>\n<p>Foo</p>\n</blockquote>\n<hr />\n",
+    "example": 62,
+    "start_line": 1188,
+    "end_line": 1196,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\nbar\n===\n",
+    "html": "<blockquote>\n<p>foo\nbar\n===</p>\n</blockquote>\n",
+    "example": 63,
+    "start_line": 1199,
+    "end_line": 1209,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n---\n",
+    "html": "<ul>\n<li>Foo</li>\n</ul>\n<hr />\n",
+    "example": 64,
+    "start_line": 1212,
+    "end_line": 1220,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nBar\n---\n",
+    "html": "<h2>Foo\nBar</h2>\n",
+    "example": 65,
+    "start_line": 1227,
+    "end_line": 1234,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "---\nFoo\n---\nBar\n---\nBaz\n",
+    "html": "<hr />\n<h2>Foo</h2>\n<h2>Bar</h2>\n<p>Baz</p>\n",
+    "example": 66,
+    "start_line": 1240,
+    "end_line": 1252,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\n====\n",
+    "html": "<p>====</p>\n",
+    "example": 67,
+    "start_line": 1257,
+    "end_line": 1262,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "---\n---\n",
+    "html": "<hr />\n<hr />\n",
+    "example": 68,
+    "start_line": 1269,
+    "end_line": 1275,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-----\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<hr />\n",
+    "example": 69,
+    "start_line": 1278,
+    "end_line": 1286,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\n---\n",
+    "html": "<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 70,
+    "start_line": 1289,
+    "end_line": 1296,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n-----\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 71,
+    "start_line": 1299,
+    "end_line": 1307,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "\\> foo\n------\n",
+    "html": "<h2>&gt; foo</h2>\n",
+    "example": 72,
+    "start_line": 1313,
+    "end_line": 1318,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n\nbar\n---\nbaz\n",
+    "html": "<p>Foo</p>\n<h2>bar</h2>\n<p>baz</p>\n",
+    "example": 73,
+    "start_line": 1344,
+    "end_line": 1354,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n\n---\n\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 74,
+    "start_line": 1360,
+    "end_line": 1372,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n* * *\nbaz\n",
+    "html": "<p>Foo\nbar</p>\n<hr />\n<p>baz</p>\n",
+    "example": 75,
+    "start_line": 1378,
+    "end_line": 1388,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\nbar\n\\---\nbaz\n",
+    "html": "<p>Foo\nbar\n---\nbaz</p>\n",
+    "example": 76,
+    "start_line": 1393,
+    "end_line": 1403,
+    "section": "Setext headings",
+    "extensions": []
+  },
+  {
+    "markdown": "    a simple\n      indented code block\n",
+    "html": "<pre><code>a simple\n  indented code block\n</code></pre>\n",
+    "example": 77,
+    "start_line": 1421,
+    "end_line": 1428,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  - foo\n\n    bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 78,
+    "start_line": 1435,
+    "end_line": 1446,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  foo\n\n    - bar\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 79,
+    "start_line": 1449,
+    "end_line": 1462,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    <a/>\n    *hi*\n\n    - one\n",
+    "html": "<pre><code>&lt;a/&gt;\n*hi*\n\n- one\n</code></pre>\n",
+    "example": 80,
+    "start_line": 1469,
+    "end_line": 1480,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    chunk1\n\n    chunk2\n  \n \n \n    chunk3\n",
+    "html": "<pre><code>chunk1\n\nchunk2\n\n\n\nchunk3\n</code></pre>\n",
+    "example": 81,
+    "start_line": 1485,
+    "end_line": 1502,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    chunk1\n      \n      chunk2\n",
+    "html": "<pre><code>chunk1\n  \n  chunk2\n</code></pre>\n",
+    "example": 82,
+    "start_line": 1508,
+    "end_line": 1517,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n    bar\n\n",
+    "html": "<p>Foo\nbar</p>\n",
+    "example": 83,
+    "start_line": 1523,
+    "end_line": 1530,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo\nbar\n",
+    "html": "<pre><code>foo\n</code></pre>\n<p>bar</p>\n",
+    "example": 84,
+    "start_line": 1537,
+    "end_line": 1544,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "# Heading\n    foo\nHeading\n------\n    foo\n----\n",
+    "html": "<h1>Heading</h1>\n<pre><code>foo\n</code></pre>\n<h2>Heading</h2>\n<pre><code>foo\n</code></pre>\n<hr />\n",
+    "example": 85,
+    "start_line": 1550,
+    "end_line": 1565,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "        foo\n    bar\n",
+    "html": "<pre><code>    foo\nbar\n</code></pre>\n",
+    "example": 86,
+    "start_line": 1570,
+    "end_line": 1577,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "\n    \n    foo\n    \n\n",
+    "html": "<pre><code>foo\n</code></pre>\n",
+    "example": 87,
+    "start_line": 1583,
+    "end_line": 1592,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    foo  \n",
+    "html": "<pre><code>foo  \n</code></pre>\n",
+    "example": 88,
+    "start_line": 1597,
+    "end_line": 1602,
+    "section": "Indented code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n<\n >\n```\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 89,
+    "start_line": 1652,
+    "end_line": 1661,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\n<\n >\n~~~\n",
+    "html": "<pre><code>&lt;\n &gt;\n</code></pre>\n",
+    "example": 90,
+    "start_line": 1666,
+    "end_line": 1675,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "``\nfoo\n``\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 91,
+    "start_line": 1679,
+    "end_line": 1685,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n~~~\n```\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 92,
+    "start_line": 1690,
+    "end_line": 1699,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\naaa\n```\n~~~\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 93,
+    "start_line": 1702,
+    "end_line": 1711,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "````\naaa\n```\n``````\n",
+    "html": "<pre><code>aaa\n```\n</code></pre>\n",
+    "example": 94,
+    "start_line": 1716,
+    "end_line": 1725,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~\naaa\n~~~\n~~~~\n",
+    "html": "<pre><code>aaa\n~~~\n</code></pre>\n",
+    "example": 95,
+    "start_line": 1728,
+    "end_line": 1737,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 96,
+    "start_line": 1743,
+    "end_line": 1747,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "`````\n\n```\naaa\n",
+    "html": "<pre><code>\n```\naaa\n</code></pre>\n",
+    "example": 97,
+    "start_line": 1750,
+    "end_line": 1760,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "> ```\n> aaa\n\nbbb\n",
+    "html": "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>\n",
+    "example": 98,
+    "start_line": 1763,
+    "end_line": 1774,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n\n  \n```\n",
+    "html": "<pre><code>\n  \n</code></pre>\n",
+    "example": 99,
+    "start_line": 1779,
+    "end_line": 1788,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n```\n",
+    "html": "<pre><code></code></pre>\n",
+    "example": 100,
+    "start_line": 1793,
+    "end_line": 1798,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": " ```\n aaa\naaa\n```\n",
+    "html": "<pre><code>aaa\naaa\n</code></pre>\n",
+    "example": 101,
+    "start_line": 1805,
+    "end_line": 1814,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  ```\naaa\n  aaa\naaa\n  ```\n",
+    "html": "<pre><code>aaa\naaa\naaa\n</code></pre>\n",
+    "example": 102,
+    "start_line": 1817,
+    "end_line": 1828,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "   ```\n   aaa\n    aaa\n  aaa\n   ```\n",
+    "html": "<pre><code>aaa\n aaa\naaa\n</code></pre>\n",
+    "example": 103,
+    "start_line": 1831,
+    "end_line": 1842,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "    ```\n    aaa\n    ```\n",
+    "html": "<pre><code>```\naaa\n```\n</code></pre>\n",
+    "example": 104,
+    "start_line": 1847,
+    "end_line": 1856,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 105,
+    "start_line": 1862,
+    "end_line": 1869,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "   ```\naaa\n  ```\n",
+    "html": "<pre><code>aaa\n</code></pre>\n",
+    "example": 106,
+    "start_line": 1872,
+    "end_line": 1879,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\naaa\n    ```\n",
+    "html": "<pre><code>aaa\n    ```\n</code></pre>\n",
+    "example": 107,
+    "start_line": 1884,
+    "end_line": 1892,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "``` ```\naaa\n",
+    "html": "<p><code> </code>\naaa</p>\n",
+    "example": 108,
+    "start_line": 1898,
+    "end_line": 1904,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~~~\naaa\n~~~ ~~\n",
+    "html": "<pre><code>aaa\n~~~ ~~\n</code></pre>\n",
+    "example": 109,
+    "start_line": 1907,
+    "end_line": 1915,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n```\nbar\n```\nbaz\n",
+    "html": "<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n",
+    "example": 110,
+    "start_line": 1921,
+    "end_line": 1932,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n---\n~~~\nbar\n~~~\n# baz\n",
+    "html": "<h2>foo</h2>\n<pre><code>bar\n</code></pre>\n<h1>baz</h1>\n",
+    "example": 111,
+    "start_line": 1938,
+    "end_line": 1950,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```ruby\ndef foo(x)\n  return 3\nend\n```\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 112,
+    "start_line": 1960,
+    "end_line": 1971,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~~    ruby startline=3 $%@#$\ndef foo(x)\n  return 3\nend\n~~~~~~~\n",
+    "html": "<pre><code class=\"language-ruby\">def foo(x)\n  return 3\nend\n</code></pre>\n",
+    "example": 113,
+    "start_line": 1974,
+    "end_line": 1985,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "````;\n````\n",
+    "html": "<pre><code class=\"language-;\"></code></pre>\n",
+    "example": 114,
+    "start_line": 1988,
+    "end_line": 1993,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "``` aa ```\nfoo\n",
+    "html": "<p><code>aa</code>\nfoo</p>\n",
+    "example": 115,
+    "start_line": 1998,
+    "end_line": 2004,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~ aa ``` ~~~\nfoo\n~~~\n",
+    "html": "<pre><code class=\"language-aa\">foo\n</code></pre>\n",
+    "example": 116,
+    "start_line": 2009,
+    "end_line": 2016,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n``` aaa\n```\n",
+    "html": "<pre><code>``` aaa\n</code></pre>\n",
+    "example": 117,
+    "start_line": 2021,
+    "end_line": 2028,
+    "section": "Fenced code blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table><tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr></table>\n",
+    "html": "<table><tr><td>\n<pre>\n**Hello**,\n<p><em>world</em>.\n</pre></p>\n</td></tr></table>\n",
+    "example": 118,
+    "start_line": 2100,
+    "end_line": 2115,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n\nokay.\n",
+    "html": "<table>\n  <tr>\n    <td>\n           hi\n    </td>\n  </tr>\n</table>\n<p>okay.</p>\n",
+    "example": 119,
+    "start_line": 2129,
+    "end_line": 2148,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": " <div>\n  *hello*\n         <foo><a>\n",
+    "html": " <div>\n  *hello*\n         <foo><a>\n",
+    "example": 120,
+    "start_line": 2151,
+    "end_line": 2159,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "</div>\n*foo*\n",
+    "html": "</div>\n*foo*\n",
+    "example": 121,
+    "start_line": 2164,
+    "end_line": 2170,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<DIV CLASS=\"foo\">\n\n*Markdown*\n\n</DIV>\n",
+    "html": "<DIV CLASS=\"foo\">\n<p><em>Markdown</em></p>\n</DIV>\n",
+    "example": 122,
+    "start_line": 2175,
+    "end_line": 2185,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "html": "<div id=\"foo\"\n  class=\"bar\">\n</div>\n",
+    "example": 123,
+    "start_line": 2191,
+    "end_line": 2199,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "html": "<div id=\"foo\" class=\"bar\n  baz\">\n</div>\n",
+    "example": 124,
+    "start_line": 2202,
+    "end_line": 2210,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n*foo*\n\n*bar*\n",
+    "html": "<div>\n*foo*\n<p><em>bar</em></p>\n",
+    "example": 125,
+    "start_line": 2214,
+    "end_line": 2223,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div id=\"foo\"\n*hi*\n",
+    "html": "<div id=\"foo\"\n*hi*\n",
+    "example": 126,
+    "start_line": 2230,
+    "end_line": 2236,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div class\nfoo\n",
+    "html": "<div class\nfoo\n",
+    "example": 127,
+    "start_line": 2239,
+    "end_line": 2245,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div *???-&&&-<---\n*foo*\n",
+    "html": "<div *???-&&&-<---\n*foo*\n",
+    "example": 128,
+    "start_line": 2251,
+    "end_line": 2257,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "html": "<div><a href=\"bar\">*foo*</a></div>\n",
+    "example": 129,
+    "start_line": 2263,
+    "end_line": 2267,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "html": "<table><tr><td>\nfoo\n</td></tr></table>\n",
+    "example": 130,
+    "start_line": 2270,
+    "end_line": 2278,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "html": "<div></div>\n``` c\nint x = 33;\n```\n",
+    "example": 131,
+    "start_line": 2287,
+    "end_line": 2297,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "html": "<a href=\"foo\">\n*bar*\n</a>\n",
+    "example": 132,
+    "start_line": 2304,
+    "end_line": 2312,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<Warning>\n*bar*\n</Warning>\n",
+    "html": "<Warning>\n*bar*\n</Warning>\n",
+    "example": 133,
+    "start_line": 2317,
+    "end_line": 2325,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "html": "<i class=\"foo\">\n*bar*\n</i>\n",
+    "example": 134,
+    "start_line": 2328,
+    "end_line": 2336,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "</ins>\n*bar*\n",
+    "html": "</ins>\n*bar*\n",
+    "example": 135,
+    "start_line": 2339,
+    "end_line": 2345,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>\n*foo*\n</del>\n",
+    "html": "<del>\n*foo*\n</del>\n",
+    "example": 136,
+    "start_line": 2354,
+    "end_line": 2362,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>\n\n*foo*\n\n</del>\n",
+    "html": "<del>\n<p><em>foo</em></p>\n</del>\n",
+    "example": 137,
+    "start_line": 2369,
+    "end_line": 2379,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<del>*foo*</del>\n",
+    "html": "<p><del><em>foo</em></del></p>\n",
+    "example": 138,
+    "start_line": 2387,
+    "end_line": 2391,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay\n",
+    "html": "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>\n",
+    "example": 139,
+    "start_line": 2403,
+    "end_line": 2419,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\nokay\n",
+    "html": "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\n<p>okay</p>\n",
+    "example": 140,
+    "start_line": 2424,
+    "end_line": 2438,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay\n",
+    "html": "<style\n  type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>\n",
+    "example": 141,
+    "start_line": 2443,
+    "end_line": 2459,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "html": "<style\n  type=\"text/css\">\n\nfoo\n",
+    "example": 142,
+    "start_line": 2466,
+    "end_line": 2476,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "> <div>\n> foo\n\nbar\n",
+    "html": "<blockquote>\n<div>\nfoo\n</blockquote>\n<p>bar</p>\n",
+    "example": 143,
+    "start_line": 2479,
+    "end_line": 2490,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "- <div>\n- foo\n",
+    "html": "<ul>\n<li>\n<div>\n</li>\n<li>foo</li>\n</ul>\n",
+    "example": 144,
+    "start_line": 2493,
+    "end_line": 2503,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<style>p{color:red;}</style>\n*foo*\n",
+    "html": "<style>p{color:red;}</style>\n<p><em>foo</em></p>\n",
+    "example": 145,
+    "start_line": 2508,
+    "end_line": 2514,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!-- foo -->*bar*\n*baz*\n",
+    "html": "<!-- foo -->*bar*\n<p><em>baz</em></p>\n",
+    "example": 146,
+    "start_line": 2517,
+    "end_line": 2523,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<script>\nfoo\n</script>1. *bar*\n",
+    "html": "<script>\nfoo\n</script>1. *bar*\n",
+    "example": 147,
+    "start_line": 2529,
+    "end_line": 2537,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!-- Foo\n\nbar\n   baz -->\nokay\n",
+    "html": "<!-- Foo\n\nbar\n   baz -->\n<p>okay</p>\n",
+    "example": 148,
+    "start_line": 2542,
+    "end_line": 2554,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<?php\n\n  echo '>';\n\n?>\nokay\n",
+    "html": "<?php\n\n  echo '>';\n\n?>\n<p>okay</p>\n",
+    "example": 149,
+    "start_line": 2560,
+    "end_line": 2574,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<!DOCTYPE html>\n",
+    "html": "<!DOCTYPE html>\n",
+    "example": 150,
+    "start_line": 2579,
+    "end_line": 2583,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\nokay\n",
+    "html": "<![CDATA[\nfunction matchwo(a,b)\n{\n  if (a < b && a < 0) then {\n    return 1;\n\n  } else {\n\n    return 0;\n  }\n}\n]]>\n<p>okay</p>\n",
+    "example": 151,
+    "start_line": 2588,
+    "end_line": 2616,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  <!-- foo -->\n\n    <!-- foo -->\n",
+    "html": "  <!-- foo -->\n<pre><code>&lt;!-- foo --&gt;\n</code></pre>\n",
+    "example": 152,
+    "start_line": 2621,
+    "end_line": 2629,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "  <div>\n\n    <div>\n",
+    "html": "  <div>\n<pre><code>&lt;div&gt;\n</code></pre>\n",
+    "example": 153,
+    "start_line": 2632,
+    "end_line": 2640,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n<div>\nbar\n</div>\n",
+    "html": "<p>Foo</p>\n<div>\nbar\n</div>\n",
+    "example": 154,
+    "start_line": 2646,
+    "end_line": 2656,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\nbar\n</div>\n*foo*\n",
+    "html": "<div>\nbar\n</div>\n*foo*\n",
+    "example": 155,
+    "start_line": 2663,
+    "end_line": 2673,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n<a href=\"bar\">\nbaz\n",
+    "html": "<p>Foo\n<a href=\"bar\">\nbaz</p>\n",
+    "example": 156,
+    "start_line": 2678,
+    "end_line": 2686,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n\n*Emphasized* text.\n\n</div>\n",
+    "html": "<div>\n<p><em>Emphasized</em> text.</p>\n</div>\n",
+    "example": 157,
+    "start_line": 2719,
+    "end_line": 2729,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<div>\n*Emphasized* text.\n</div>\n",
+    "html": "<div>\n*Emphasized* text.\n</div>\n",
+    "example": 158,
+    "start_line": 2732,
+    "end_line": 2740,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n\n<tr>\n\n<td>\nHi\n</td>\n\n</tr>\n\n</table>\n",
+    "html": "<table>\n<tr>\n<td>\nHi\n</td>\n</tr>\n</table>\n",
+    "example": 159,
+    "start_line": 2754,
+    "end_line": 2774,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "<table>\n\n  <tr>\n\n    <td>\n      Hi\n    </td>\n\n  </tr>\n\n</table>\n",
+    "html": "<table>\n  <tr>\n<pre><code>&lt;td&gt;\n  Hi\n&lt;/td&gt;\n</code></pre>\n  </tr>\n</table>\n",
+    "example": 160,
+    "start_line": 2781,
+    "end_line": 2802,
+    "section": "HTML blocks",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 161,
+    "start_line": 2829,
+    "end_line": 2835,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "   [foo]: \n      /url  \n           'the title'  \n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"the title\">foo</a></p>\n",
+    "example": 162,
+    "start_line": 2838,
+    "end_line": 2846,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]\n",
+    "html": "<p><a href=\"my_(url)\" title=\"title (with parens)\">Foo*bar]</a></p>\n",
+    "example": 163,
+    "start_line": 2849,
+    "end_line": 2855,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo bar]:\n<my url>\n'title'\n\n[Foo bar]\n",
+    "html": "<p><a href=\"my%20url\" title=\"title\">Foo bar</a></p>\n",
+    "example": 164,
+    "start_line": 2858,
+    "end_line": 2866,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]\n",
+    "html": "<p><a href=\"/url\" title=\"\ntitle\nline1\nline2\n\">foo</a></p>\n",
+    "example": 165,
+    "start_line": 2871,
+    "end_line": 2885,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url 'title\n\nwith blank line'\n\n[foo]\n",
+    "html": "<p>[foo]: /url 'title</p>\n<p>with blank line'</p>\n<p>[foo]</p>\n",
+    "example": 166,
+    "start_line": 2890,
+    "end_line": 2900,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]:\n/url\n\n[foo]\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n",
+    "example": 167,
+    "start_line": 2905,
+    "end_line": 2912,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]:\n\n[foo]\n",
+    "html": "<p>[foo]:</p>\n<p>[foo]</p>\n",
+    "example": 168,
+    "start_line": 2917,
+    "end_line": 2924,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: <>\n\n[foo]\n",
+    "html": "<p><a href=\"\">foo</a></p>\n",
+    "example": 169,
+    "start_line": 2929,
+    "end_line": 2935,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: <bar>(baz)\n\n[foo]\n",
+    "html": "<p>[foo]: <bar>(baz)</p>\n<p>[foo]</p>\n",
+    "example": 170,
+    "start_line": 2940,
+    "end_line": 2947,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]\n",
+    "html": "<p><a href=\"/url%5Cbar*baz\" title=\"foo&quot;bar\\baz\">foo</a></p>\n",
+    "example": 171,
+    "start_line": 2953,
+    "end_line": 2959,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: url\n",
+    "html": "<p><a href=\"url\">foo</a></p>\n",
+    "example": 172,
+    "start_line": 2964,
+    "end_line": 2970,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: first\n[foo]: second\n",
+    "html": "<p><a href=\"first\">foo</a></p>\n",
+    "example": 173,
+    "start_line": 2976,
+    "end_line": 2983,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[FOO]: /url\n\n[Foo]\n",
+    "html": "<p><a href=\"/url\">Foo</a></p>\n",
+    "example": 174,
+    "start_line": 2989,
+    "end_line": 2995,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[\u0391\u0393\u03a9]: /\u03c6\u03bf\u03c5\n\n[\u03b1\u03b3\u03c9]\n",
+    "html": "<p><a href=\"/%CF%86%CE%BF%CF%85\">\u03b1\u03b3\u03c9</a></p>\n",
+    "example": 175,
+    "start_line": 2998,
+    "end_line": 3004,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n",
+    "html": "",
+    "example": 176,
+    "start_line": 3010,
+    "end_line": 3013,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[\nfoo\n]: /url\nbar\n",
+    "html": "<p>bar</p>\n",
+    "example": 177,
+    "start_line": 3018,
+    "end_line": 3025,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url \"title\" ok\n",
+    "html": "<p>[foo]: /url &quot;title&quot; ok</p>\n",
+    "example": 178,
+    "start_line": 3031,
+    "end_line": 3035,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n\"title\" ok\n",
+    "html": "<p>&quot;title&quot; ok</p>\n",
+    "example": 179,
+    "start_line": 3040,
+    "end_line": 3045,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "    [foo]: /url \"title\"\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url &quot;title&quot;\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 180,
+    "start_line": 3051,
+    "end_line": 3059,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "```\n[foo]: /url\n```\n\n[foo]\n",
+    "html": "<pre><code>[foo]: /url\n</code></pre>\n<p>[foo]</p>\n",
+    "example": 181,
+    "start_line": 3065,
+    "end_line": 3075,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n[bar]: /baz\n\n[bar]\n",
+    "html": "<p>Foo\n[bar]: /baz</p>\n<p>[bar]</p>\n",
+    "example": 182,
+    "start_line": 3080,
+    "end_line": 3089,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "# [Foo]\n[foo]: /url\n> bar\n",
+    "html": "<h1><a href=\"/url\">Foo</a></h1>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 183,
+    "start_line": 3095,
+    "end_line": 3104,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\nbar\n===\n[foo]\n",
+    "html": "<h1>bar</h1>\n<p><a href=\"/url\">foo</a></p>\n",
+    "example": 184,
+    "start_line": 3106,
+    "end_line": 3114,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n===\n[foo]\n",
+    "html": "<p>===\n<a href=\"/url\">foo</a></p>\n",
+    "example": 185,
+    "start_line": 3116,
+    "end_line": 3123,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n  \"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]\n",
+    "html": "<p><a href=\"/foo-url\" title=\"foo\">foo</a>,\n<a href=\"/bar-url\" title=\"bar\">bar</a>,\n<a href=\"/baz-url\">baz</a></p>\n",
+    "example": 186,
+    "start_line": 3129,
+    "end_line": 3142,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n> [foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a></p>\n<blockquote>\n</blockquote>\n",
+    "example": 187,
+    "start_line": 3150,
+    "end_line": 3158,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url\n",
+    "html": "",
+    "example": 188,
+    "start_line": 3167,
+    "end_line": 3170,
+    "section": "Link reference definitions",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 189,
+    "start_line": 3184,
+    "end_line": 3191,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\nbbb\n\nccc\nddd\n",
+    "html": "<p>aaa\nbbb</p>\n<p>ccc\nddd</p>\n",
+    "example": 190,
+    "start_line": 3196,
+    "end_line": 3207,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n\n\nbbb\n",
+    "html": "<p>aaa</p>\n<p>bbb</p>\n",
+    "example": 191,
+    "start_line": 3212,
+    "end_line": 3220,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "  aaa\n bbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 192,
+    "start_line": 3225,
+    "end_line": 3231,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa\n             bbb\n                                       ccc\n",
+    "html": "<p>aaa\nbbb\nccc</p>\n",
+    "example": 193,
+    "start_line": 3237,
+    "end_line": 3245,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "   aaa\nbbb\n",
+    "html": "<p>aaa\nbbb</p>\n",
+    "example": 194,
+    "start_line": 3251,
+    "end_line": 3257,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "    aaa\nbbb\n",
+    "html": "<pre><code>aaa\n</code></pre>\n<p>bbb</p>\n",
+    "example": 195,
+    "start_line": 3260,
+    "end_line": 3267,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "aaa     \nbbb     \n",
+    "html": "<p>aaa<br />\nbbb</p>\n",
+    "example": 196,
+    "start_line": 3274,
+    "end_line": 3280,
+    "section": "Paragraphs",
+    "extensions": []
+  },
+  {
+    "markdown": "  \n\naaa\n  \n\n# aaa\n\n  \n",
+    "html": "<p>aaa</p>\n<h1>aaa</h1>\n",
+    "example": 197,
+    "start_line": 3291,
+    "end_line": 3303,
+    "section": "Blank lines",
+    "extensions": []
+  },
+  {
+    "markdown": "| foo | bar |\n| --- | --- |\n| baz | bim |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>foo</th>\n<th>bar</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>baz</td>\n<td>bim</td>\n</tr>\n</tbody>\n</table>\n",
+    "example": 198,
+    "start_line": 3326,
+    "end_line": 3345,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | defghi |\n:-: | -----------:\nbar | baz\n",
+    "html": "<table>\n<thead>\n<tr>\n<th align=\"center\">abc</th>\n<th align=\"right\">defghi</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\">bar</td>\n<td align=\"right\">baz</td>\n</tr>\n</tbody>\n</table>\n",
+    "example": 199,
+    "start_line": 3350,
+    "end_line": 3369,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| f\\|oo  |\n| ------ |\n| b `\\|` az |\n| b **\\|** im |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>f|oo</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b <code>|</code> az</td>\n</tr>\n<tr>\n<td>b <strong>|</strong> im</td>\n</tr>\n</tbody>\n</table>\n",
+    "example": 200,
+    "start_line": 3374,
+    "end_line": 3395,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\n> bar\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n</tbody>\n</table>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 201,
+    "start_line": 3400,
+    "end_line": 3423,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\nbar\n\nbar\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n<tr>\n<td>bar</td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>bar</p>\n",
+    "example": 202,
+    "start_line": 3425,
+    "end_line": 3452,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- |\n| bar |\n",
+    "html": "<p>| abc | def |\n| --- |\n| bar |</p>\n",
+    "example": 203,
+    "start_line": 3457,
+    "end_line": 3465,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n| bar |\n| bar | baz | boo |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>bar</td>\n<td></td>\n</tr>\n<tr>\n<td>bar</td>\n<td>baz</td>\n</tr>\n</tbody>\n</table>\n",
+    "example": 204,
+    "start_line": 3471,
+    "end_line": 3495,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "| abc | def |\n| --- | --- |\n",
+    "html": "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n</table>\n",
+    "example": 205,
+    "start_line": 3499,
+    "end_line": 3511,
+    "section": "Tables (extension)",
+    "extensions": [
+      "table"
+    ]
+  },
+  {
+    "markdown": "> # Foo\n> bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 206,
+    "start_line": 3565,
+    "end_line": 3575,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "># Foo\n>bar\n> baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 207,
+    "start_line": 3580,
+    "end_line": 3590,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "   > # Foo\n   > bar\n > baz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 208,
+    "start_line": 3595,
+    "end_line": 3605,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "    > # Foo\n    > bar\n    > baz\n",
+    "html": "<pre><code>&gt; # Foo\n&gt; bar\n&gt; baz\n</code></pre>\n",
+    "example": 209,
+    "start_line": 3610,
+    "end_line": 3619,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> # Foo\n> bar\nbaz\n",
+    "html": "<blockquote>\n<h1>Foo</h1>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 210,
+    "start_line": 3625,
+    "end_line": 3635,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\nbaz\n> foo\n",
+    "html": "<blockquote>\n<p>bar\nbaz\nfoo</p>\n</blockquote>\n",
+    "example": 211,
+    "start_line": 3641,
+    "end_line": 3651,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n---\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<hr />\n",
+    "example": 212,
+    "start_line": 3665,
+    "end_line": 3673,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> - foo\n- bar\n",
+    "html": "<blockquote>\n<ul>\n<li>foo</li>\n</ul>\n</blockquote>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 213,
+    "start_line": 3685,
+    "end_line": 3697,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">     foo\n    bar\n",
+    "html": "<blockquote>\n<pre><code>foo\n</code></pre>\n</blockquote>\n<pre><code>bar\n</code></pre>\n",
+    "example": 214,
+    "start_line": 3703,
+    "end_line": 3713,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> ```\nfoo\n```\n",
+    "html": "<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>\n",
+    "example": 215,
+    "start_line": 3716,
+    "end_line": 3726,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n    - bar\n",
+    "html": "<blockquote>\n<p>foo\n- bar</p>\n</blockquote>\n",
+    "example": 216,
+    "start_line": 3732,
+    "end_line": 3740,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 217,
+    "start_line": 3756,
+    "end_line": 3761,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n>  \n> \n",
+    "html": "<blockquote>\n</blockquote>\n",
+    "example": 218,
+    "start_line": 3764,
+    "end_line": 3771,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">\n> foo\n>  \n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n",
+    "example": 219,
+    "start_line": 3776,
+    "end_line": 3784,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n</blockquote>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 220,
+    "start_line": 3789,
+    "end_line": 3800,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n> bar\n",
+    "html": "<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n",
+    "example": 221,
+    "start_line": 3811,
+    "end_line": 3819,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> foo\n>\n> bar\n",
+    "html": "<blockquote>\n<p>foo</p>\n<p>bar</p>\n</blockquote>\n",
+    "example": 222,
+    "start_line": 3824,
+    "end_line": 3833,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n> bar\n",
+    "html": "<p>foo</p>\n<blockquote>\n<p>bar</p>\n</blockquote>\n",
+    "example": 223,
+    "start_line": 3838,
+    "end_line": 3846,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> aaa\n***\n> bbb\n",
+    "html": "<blockquote>\n<p>aaa</p>\n</blockquote>\n<hr />\n<blockquote>\n<p>bbb</p>\n</blockquote>\n",
+    "example": 224,
+    "start_line": 3852,
+    "end_line": 3864,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\nbaz\n",
+    "html": "<blockquote>\n<p>bar\nbaz</p>\n</blockquote>\n",
+    "example": 225,
+    "start_line": 3870,
+    "end_line": 3878,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\n\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 226,
+    "start_line": 3881,
+    "end_line": 3890,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> bar\n>\nbaz\n",
+    "html": "<blockquote>\n<p>bar</p>\n</blockquote>\n<p>baz</p>\n",
+    "example": 227,
+    "start_line": 3893,
+    "end_line": 3902,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "> > > foo\nbar\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 228,
+    "start_line": 3909,
+    "end_line": 3921,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">>> foo\n> bar\n>>baz\n",
+    "html": "<blockquote>\n<blockquote>\n<blockquote>\n<p>foo\nbar\nbaz</p>\n</blockquote>\n</blockquote>\n</blockquote>\n",
+    "example": 229,
+    "start_line": 3924,
+    "end_line": 3938,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": ">     code\n\n>    not code\n",
+    "html": "<blockquote>\n<pre><code>code\n</code></pre>\n</blockquote>\n<blockquote>\n<p>not code</p>\n</blockquote>\n",
+    "example": 230,
+    "start_line": 3946,
+    "end_line": 3958,
+    "section": "Block quotes",
+    "extensions": []
+  },
+  {
+    "markdown": "A paragraph\nwith two lines.\n\n    indented code\n\n> A block quote.\n",
+    "html": "<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n",
+    "example": 231,
+    "start_line": 4000,
+    "end_line": 4015,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  A paragraph\n    with two lines.\n\n        indented code\n\n    > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 232,
+    "start_line": 4022,
+    "end_line": 4041,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- one\n\n two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n",
+    "example": 233,
+    "start_line": 4055,
+    "end_line": 4064,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- one\n\n  two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 234,
+    "start_line": 4067,
+    "end_line": 4078,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " -    one\n\n     two\n",
+    "html": "<ul>\n<li>one</li>\n</ul>\n<pre><code> two\n</code></pre>\n",
+    "example": 235,
+    "start_line": 4081,
+    "end_line": 4091,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " -    one\n\n      two\n",
+    "html": "<ul>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ul>\n",
+    "example": 236,
+    "start_line": 4094,
+    "end_line": 4105,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   > > 1.  one\n>>\n>>     two\n",
+    "html": "<blockquote>\n<blockquote>\n<ol>\n<li>\n<p>one</p>\n<p>two</p>\n</li>\n</ol>\n</blockquote>\n</blockquote>\n",
+    "example": 237,
+    "start_line": 4116,
+    "end_line": 4131,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": ">>- one\n>>\n  >  > two\n",
+    "html": "<blockquote>\n<blockquote>\n<ul>\n<li>one</li>\n</ul>\n<p>two</p>\n</blockquote>\n</blockquote>\n",
+    "example": 238,
+    "start_line": 4143,
+    "end_line": 4156,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-one\n\n2.two\n",
+    "html": "<p>-one</p>\n<p>2.two</p>\n",
+    "example": 239,
+    "start_line": 4162,
+    "end_line": 4169,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n\n  bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 240,
+    "start_line": 4175,
+    "end_line": 4187,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.  foo\n\n    ```\n    bar\n    ```\n\n    baz\n\n    > bam\n",
+    "html": "<ol>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n<p>baz</p>\n<blockquote>\n<p>bam</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 241,
+    "start_line": 4192,
+    "end_line": 4214,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- Foo\n\n      bar\n\n\n      baz\n",
+    "html": "<ul>\n<li>\n<p>Foo</p>\n<pre><code>bar\n\n\nbaz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 242,
+    "start_line": 4220,
+    "end_line": 4238,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "123456789. ok\n",
+    "html": "<ol start=\"123456789\">\n<li>ok</li>\n</ol>\n",
+    "example": 243,
+    "start_line": 4242,
+    "end_line": 4248,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1234567890. not ok\n",
+    "html": "<p>1234567890. not ok</p>\n",
+    "example": 244,
+    "start_line": 4251,
+    "end_line": 4255,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "0. ok\n",
+    "html": "<ol start=\"0\">\n<li>ok</li>\n</ol>\n",
+    "example": 245,
+    "start_line": 4260,
+    "end_line": 4266,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "003. ok\n",
+    "html": "<ol start=\"3\">\n<li>ok</li>\n</ol>\n",
+    "example": 246,
+    "start_line": 4269,
+    "end_line": 4275,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-1. not ok\n",
+    "html": "<p>-1. not ok</p>\n",
+    "example": 247,
+    "start_line": 4280,
+    "end_line": 4284,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n      bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ul>\n",
+    "example": 248,
+    "start_line": 4303,
+    "end_line": 4315,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  10.  foo\n\n           bar\n",
+    "html": "<ol start=\"10\">\n<li>\n<p>foo</p>\n<pre><code>bar\n</code></pre>\n</li>\n</ol>\n",
+    "example": 249,
+    "start_line": 4320,
+    "end_line": 4332,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "    indented code\n\nparagraph\n\n    more code\n",
+    "html": "<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n",
+    "example": 250,
+    "start_line": 4339,
+    "end_line": 4351,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.     indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code>indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 251,
+    "start_line": 4354,
+    "end_line": 4370,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1.      indented code\n\n   paragraph\n\n       more code\n",
+    "html": "<ol>\n<li>\n<pre><code> indented code\n</code></pre>\n<p>paragraph</p>\n<pre><code>more code\n</code></pre>\n</li>\n</ol>\n",
+    "example": 252,
+    "start_line": 4376,
+    "end_line": 4392,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   foo\n\nbar\n",
+    "html": "<p>foo</p>\n<p>bar</p>\n",
+    "example": 253,
+    "start_line": 4403,
+    "end_line": 4410,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-    foo\n\n  bar\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n<p>bar</p>\n",
+    "example": 254,
+    "start_line": 4413,
+    "end_line": 4422,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-  foo\n\n   bar\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>bar</p>\n</li>\n</ul>\n",
+    "example": 255,
+    "start_line": 4430,
+    "end_line": 4441,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-\n  foo\n-\n  ```\n  bar\n  ```\n-\n      baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>\n<pre><code>bar\n</code></pre>\n</li>\n<li>\n<pre><code>baz\n</code></pre>\n</li>\n</ul>\n",
+    "example": 256,
+    "start_line": 4458,
+    "end_line": 4479,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-   \n  foo\n",
+    "html": "<ul>\n<li>foo</li>\n</ul>\n",
+    "example": 257,
+    "start_line": 4484,
+    "end_line": 4491,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "-\n\n  foo\n",
+    "html": "<ul>\n<li></li>\n</ul>\n<p>foo</p>\n",
+    "example": 258,
+    "start_line": 4498,
+    "end_line": 4507,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-\n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 259,
+    "start_line": 4512,
+    "end_line": 4522,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n-   \n- bar\n",
+    "html": "<ul>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ul>\n",
+    "example": 260,
+    "start_line": 4527,
+    "end_line": 4537,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1. foo\n2.\n3. bar\n",
+    "html": "<ol>\n<li>foo</li>\n<li></li>\n<li>bar</li>\n</ol>\n",
+    "example": 261,
+    "start_line": 4542,
+    "end_line": 4552,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "*\n",
+    "html": "<ul>\n<li></li>\n</ul>\n",
+    "example": 262,
+    "start_line": 4557,
+    "end_line": 4563,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\n*\n\nfoo\n1.\n",
+    "html": "<p>foo\n*</p>\n<p>foo\n1.</p>\n",
+    "example": 263,
+    "start_line": 4567,
+    "end_line": 4578,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": " 1.  A paragraph\n     with two lines.\n\n         indented code\n\n     > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 264,
+    "start_line": 4589,
+    "end_line": 4608,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\n      with two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 265,
+    "start_line": 4613,
+    "end_line": 4632,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "   1.  A paragraph\n       with two lines.\n\n           indented code\n\n       > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 266,
+    "start_line": 4637,
+    "end_line": 4656,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "    1.  A paragraph\n        with two lines.\n\n            indented code\n\n        > A block quote.\n",
+    "html": "<pre><code>1.  A paragraph\n    with two lines.\n\n        indented code\n\n    &gt; A block quote.\n</code></pre>\n",
+    "example": 267,
+    "start_line": 4661,
+    "end_line": 4676,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\nwith two lines.\n\n          indented code\n\n      > A block quote.\n",
+    "html": "<ol>\n<li>\n<p>A paragraph\nwith two lines.</p>\n<pre><code>indented code\n</code></pre>\n<blockquote>\n<p>A block quote.</p>\n</blockquote>\n</li>\n</ol>\n",
+    "example": 268,
+    "start_line": 4691,
+    "end_line": 4710,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "  1.  A paragraph\n    with two lines.\n",
+    "html": "<ol>\n<li>A paragraph\nwith two lines.</li>\n</ol>\n",
+    "example": 269,
+    "start_line": 4715,
+    "end_line": 4723,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "> 1. > Blockquote\ncontinued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 270,
+    "start_line": 4728,
+    "end_line": 4742,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "> 1. > Blockquote\n> continued here.\n",
+    "html": "<blockquote>\n<ol>\n<li>\n<blockquote>\n<p>Blockquote\ncontinued here.</p>\n</blockquote>\n</li>\n</ol>\n</blockquote>\n",
+    "example": 271,
+    "start_line": 4745,
+    "end_line": 4759,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n      - boo\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 272,
+    "start_line": 4773,
+    "end_line": 4794,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n - bar\n  - baz\n   - boo\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>\n",
+    "example": 273,
+    "start_line": 4799,
+    "end_line": 4811,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "10) foo\n    - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo\n<ul>\n<li>bar</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 274,
+    "start_line": 4816,
+    "end_line": 4827,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "10) foo\n   - bar\n",
+    "html": "<ol start=\"10\">\n<li>foo</li>\n</ol>\n<ul>\n<li>bar</li>\n</ul>\n",
+    "example": 275,
+    "start_line": 4832,
+    "end_line": 4842,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- - foo\n",
+    "html": "<ul>\n<li>\n<ul>\n<li>foo</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 276,
+    "start_line": 4847,
+    "end_line": 4857,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "1. - 2. foo\n",
+    "html": "<ol>\n<li>\n<ul>\n<li>\n<ol start=\"2\">\n<li>foo</li>\n</ol>\n</li>\n</ul>\n</li>\n</ol>\n",
+    "example": 277,
+    "start_line": 4860,
+    "end_line": 4874,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- # Foo\n- Bar\n  ---\n  baz\n",
+    "html": "<ul>\n<li>\n<h1>Foo</h1>\n</li>\n<li>\n<h2>Bar</h2>\nbaz</li>\n</ul>\n",
+    "example": 278,
+    "start_line": 4879,
+    "end_line": 4893,
+    "section": "List items",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n- bar\n+ baz\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<ul>\n<li>baz</li>\n</ul>\n",
+    "example": 281,
+    "start_line": 5172,
+    "end_line": 5184,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. foo\n2. bar\n3) baz\n",
+    "html": "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>\n<ol start=\"3\">\n<li>baz</li>\n</ol>\n",
+    "example": 282,
+    "start_line": 5187,
+    "end_line": 5199,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo\n- bar\n- baz\n",
+    "html": "<p>Foo</p>\n<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n",
+    "example": 283,
+    "start_line": 5206,
+    "end_line": 5216,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "The number of windows in my house is\n14.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is\n14.  The number of doors is 6.</p>\n",
+    "example": 284,
+    "start_line": 5283,
+    "end_line": 5289,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "The number of windows in my house is\n1.  The number of doors is 6.\n",
+    "html": "<p>The number of windows in my house is</p>\n<ol>\n<li>The number of doors is 6.</li>\n</ol>\n",
+    "example": 285,
+    "start_line": 5293,
+    "end_line": 5301,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n\n- bar\n\n\n- baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n</li>\n<li>\n<p>bar</p>\n</li>\n<li>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 286,
+    "start_line": 5307,
+    "end_line": 5326,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n  - bar\n    - baz\n\n\n      bim\n",
+    "html": "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>\n<p>baz</p>\n<p>bim</p>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 287,
+    "start_line": 5328,
+    "end_line": 5350,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim\n",
+    "html": "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>\n",
+    "example": 288,
+    "start_line": 5358,
+    "end_line": 5376,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "-   foo\n\n    notcode\n\n-   foo\n\n<!-- -->\n\n    code\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>\n",
+    "example": 289,
+    "start_line": 5379,
+    "end_line": 5402,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n - b\n  - c\n   - d\n  - e\n - f\n- g\n",
+    "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d</li>\n<li>e</li>\n<li>f</li>\n<li>g</li>\n</ul>\n",
+    "example": 290,
+    "start_line": 5410,
+    "end_line": 5428,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. a\n\n  2. b\n\n   3. c\n",
+    "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ol>\n",
+    "example": 291,
+    "start_line": 5431,
+    "end_line": 5449,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n - b\n  - c\n   - d\n    - e\n",
+    "html": "<ul>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n<li>d\n- e</li>\n</ul>\n",
+    "example": 292,
+    "start_line": 5455,
+    "end_line": 5469,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. a\n\n  2. b\n\n    3. c\n",
+    "html": "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n</ol>\n<pre><code>3. c\n</code></pre>\n",
+    "example": 293,
+    "start_line": 5475,
+    "end_line": 5492,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n- c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 294,
+    "start_line": 5498,
+    "end_line": 5515,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* a\n*\n\n* c\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>\n",
+    "example": 295,
+    "start_line": 5520,
+    "end_line": 5535,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n  c\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 296,
+    "start_line": 5542,
+    "end_line": 5561,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- b\n\n  [ref]: /url\n- d\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n<li>\n<p>d</p>\n</li>\n</ul>\n",
+    "example": 297,
+    "start_line": 5564,
+    "end_line": 5582,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n- ```\n  b\n\n\n  ```\n- c\n",
+    "html": "<ul>\n<li>a</li>\n<li>\n<pre><code>b\n\n\n</code></pre>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 298,
+    "start_line": 5587,
+    "end_line": 5606,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n\n    c\n- d\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 299,
+    "start_line": 5613,
+    "end_line": 5631,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* a\n  > b\n  >\n* c\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n</li>\n<li>c</li>\n</ul>\n",
+    "example": 300,
+    "start_line": 5637,
+    "end_line": 5651,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  > b\n  ```\n  c\n  ```\n- d\n",
+    "html": "<ul>\n<li>a\n<blockquote>\n<p>b</p>\n</blockquote>\n<pre><code>c\n</code></pre>\n</li>\n<li>d</li>\n</ul>\n",
+    "example": 301,
+    "start_line": 5657,
+    "end_line": 5675,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n",
+    "html": "<ul>\n<li>a</li>\n</ul>\n",
+    "example": 302,
+    "start_line": 5680,
+    "end_line": 5686,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n",
+    "html": "<ul>\n<li>a\n<ul>\n<li>b</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 303,
+    "start_line": 5689,
+    "end_line": 5700,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "1. ```\n   foo\n   ```\n\n   bar\n",
+    "html": "<ol>\n<li>\n<pre><code>foo\n</code></pre>\n<p>bar</p>\n</li>\n</ol>\n",
+    "example": 304,
+    "start_line": 5706,
+    "end_line": 5720,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "* foo\n  * bar\n\n  baz\n",
+    "html": "<ul>\n<li>\n<p>foo</p>\n<ul>\n<li>bar</li>\n</ul>\n<p>baz</p>\n</li>\n</ul>\n",
+    "example": 305,
+    "start_line": 5725,
+    "end_line": 5740,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "- a\n  - b\n  - c\n\n- d\n  - e\n  - f\n",
+    "html": "<ul>\n<li>\n<p>a</p>\n<ul>\n<li>b</li>\n<li>c</li>\n</ul>\n</li>\n<li>\n<p>d</p>\n<ul>\n<li>e</li>\n<li>f</li>\n</ul>\n</li>\n</ul>\n",
+    "example": 306,
+    "start_line": 5743,
+    "end_line": 5768,
+    "section": "Lists",
+    "extensions": []
+  },
+  {
+    "markdown": "`hi`lo`\n",
+    "html": "<p><code>hi</code>lo`</p>\n",
+    "example": 307,
+    "start_line": 5777,
+    "end_line": 5781,
+    "section": "Inlines",
+    "extensions": []
+  },
+  {
+    "markdown": "\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n",
+    "html": "<p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~</p>\n",
+    "example": 308,
+    "start_line": 5791,
+    "end_line": 5795,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\\t\\A\\a\\ \\3\\\u03c6\\\u00ab\n",
+    "html": "<p>\\\t\\A\\a\\ \\3\\\u03c6\\\u00ab</p>\n",
+    "example": 309,
+    "start_line": 5801,
+    "end_line": 5805,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\*not emphasized*\n\\<br/> not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url \"not a reference\"\n\\&ouml; not a character entity\n",
+    "html": "<p>*not emphasized*\n&lt;br/&gt; not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url &quot;not a reference&quot;\n&amp;ouml; not a character entity</p>\n",
+    "example": 310,
+    "start_line": 5811,
+    "end_line": 5831,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "\\\\*emphasis*\n",
+    "html": "<p>\\<em>emphasis</em></p>\n",
+    "example": 311,
+    "start_line": 5836,
+    "end_line": 5840,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\nbar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 312,
+    "start_line": 5845,
+    "end_line": 5851,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "`` \\[\\` ``\n",
+    "html": "<p><code>\\[\\`</code></p>\n",
+    "example": 313,
+    "start_line": 5857,
+    "end_line": 5861,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "    \\[\\]\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 314,
+    "start_line": 5864,
+    "end_line": 5869,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "~~~\n\\[\\]\n~~~\n",
+    "html": "<pre><code>\\[\\]\n</code></pre>\n",
+    "example": 315,
+    "start_line": 5872,
+    "end_line": 5879,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://example.com?find=\\*>\n",
+    "html": "<p><a href=\"http://example.com?find=%5C*\">http://example.com?find=\\*</a></p>\n",
+    "example": 316,
+    "start_line": 5882,
+    "end_line": 5886,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"/bar\\/)\">\n",
+    "html": "<a href=\"/bar\\/)\">\n",
+    "example": 317,
+    "start_line": 5889,
+    "end_line": 5893,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](/bar\\* \"ti\\*tle\")\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 318,
+    "start_line": 5899,
+    "end_line": 5903,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /bar\\* \"ti\\*tle\"\n",
+    "html": "<p><a href=\"/bar*\" title=\"ti*tle\">foo</a></p>\n",
+    "example": 319,
+    "start_line": 5906,
+    "end_line": 5912,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "``` foo\\+bar\nfoo\n```\n",
+    "html": "<pre><code class=\"language-foo+bar\">foo\n</code></pre>\n",
+    "example": 320,
+    "start_line": 5915,
+    "end_line": 5922,
+    "section": "Backslash escapes",
+    "extensions": []
+  },
+  {
+    "markdown": "&nbsp; &amp; &copy; &AElig; &Dcaron;\n&frac34; &HilbertSpace; &DifferentialD;\n&ClockwiseContourIntegral; &ngE;\n",
+    "html": "<p>\u00a0 &amp; \u00a9 \u00c6 \u010e\n\u00be \u210b \u2146\n\u2232 \u2267\u0338</p>\n",
+    "example": 321,
+    "start_line": 5952,
+    "end_line": 5960,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#35; &#1234; &#992; &#0;\n",
+    "html": "<p># \u04d2 \u03e0 \ufffd</p>\n",
+    "example": 322,
+    "start_line": 5971,
+    "end_line": 5975,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#X22; &#XD06; &#xcab;\n",
+    "html": "<p>&quot; \u0d06 \u0cab</p>\n",
+    "example": 323,
+    "start_line": 5984,
+    "end_line": 5988,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&nbsp &x; &#; &#x;\n&#987654321;\n&#abcdef0;\n&ThisIsNotDefined; &hi?;\n",
+    "html": "<p>&amp;nbsp &amp;x; &amp;#; &amp;#x;\n&amp;#987654321;\n&amp;#abcdef0;\n&amp;ThisIsNotDefined; &amp;hi?;</p>\n",
+    "example": 324,
+    "start_line": 5993,
+    "end_line": 6003,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&copy\n",
+    "html": "<p>&amp;copy</p>\n",
+    "example": 325,
+    "start_line": 6010,
+    "end_line": 6014,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&MadeUpEntity;\n",
+    "html": "<p>&amp;MadeUpEntity;</p>\n",
+    "example": 326,
+    "start_line": 6020,
+    "end_line": 6024,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"&ouml;&ouml;.html\">\n",
+    "html": "<a href=\"&ouml;&ouml;.html\">\n",
+    "example": 327,
+    "start_line": 6031,
+    "end_line": 6035,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](/f&ouml;&ouml; \"f&ouml;&ouml;\")\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"f\u00f6\u00f6\">foo</a></p>\n",
+    "example": 328,
+    "start_line": 6038,
+    "end_line": 6042,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /f&ouml;&ouml; \"f&ouml;&ouml;\"\n",
+    "html": "<p><a href=\"/f%C3%B6%C3%B6\" title=\"f\u00f6\u00f6\">foo</a></p>\n",
+    "example": 329,
+    "start_line": 6045,
+    "end_line": 6051,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "``` f&ouml;&ouml;\nfoo\n```\n",
+    "html": "<pre><code class=\"language-f\u00f6\u00f6\">foo\n</code></pre>\n",
+    "example": 330,
+    "start_line": 6054,
+    "end_line": 6061,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "`f&ouml;&ouml;`\n",
+    "html": "<p><code>f&amp;ouml;&amp;ouml;</code></p>\n",
+    "example": 331,
+    "start_line": 6067,
+    "end_line": 6071,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "    f&ouml;f&ouml;\n",
+    "html": "<pre><code>f&amp;ouml;f&amp;ouml;\n</code></pre>\n",
+    "example": 332,
+    "start_line": 6074,
+    "end_line": 6079,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#42;foo&#42;\n*foo*\n",
+    "html": "<p>*foo*\n<em>foo</em></p>\n",
+    "example": 333,
+    "start_line": 6086,
+    "end_line": 6092,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#42; foo\n\n* foo\n",
+    "html": "<p>* foo</p>\n<ul>\n<li>foo</li>\n</ul>\n",
+    "example": 334,
+    "start_line": 6094,
+    "end_line": 6103,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "foo&#10;&#10;bar\n",
+    "html": "<p>foo\n\nbar</p>\n",
+    "example": 335,
+    "start_line": 6105,
+    "end_line": 6111,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "&#9;foo\n",
+    "html": "<p>\tfoo</p>\n",
+    "example": 336,
+    "start_line": 6113,
+    "end_line": 6117,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "[a](url &quot;tit&quot;)\n",
+    "html": "<p>[a](url &quot;tit&quot;)</p>\n",
+    "example": 337,
+    "start_line": 6120,
+    "end_line": 6124,
+    "section": "Entity and numeric character references",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo`\n",
+    "html": "<p><code>foo</code></p>\n",
+    "example": 338,
+    "start_line": 6148,
+    "end_line": 6152,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`` foo ` bar ``\n",
+    "html": "<p><code>foo ` bar</code></p>\n",
+    "example": 339,
+    "start_line": 6159,
+    "end_line": 6163,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "` `` `\n",
+    "html": "<p><code>``</code></p>\n",
+    "example": 340,
+    "start_line": 6169,
+    "end_line": 6173,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`  ``  `\n",
+    "html": "<p><code> `` </code></p>\n",
+    "example": 341,
+    "start_line": 6177,
+    "end_line": 6181,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "` a`\n",
+    "html": "<p><code> a</code></p>\n",
+    "example": 342,
+    "start_line": 6186,
+    "end_line": 6190,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`\u00a0b\u00a0`\n",
+    "html": "<p><code>\u00a0b\u00a0</code></p>\n",
+    "example": 343,
+    "start_line": 6195,
+    "end_line": 6199,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`\u00a0`\n`  `\n",
+    "html": "<p><code>\u00a0</code>\n<code>  </code></p>\n",
+    "example": 344,
+    "start_line": 6203,
+    "end_line": 6209,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "``\nfoo\nbar  \nbaz\n``\n",
+    "html": "<p><code>foo bar   baz</code></p>\n",
+    "example": 345,
+    "start_line": 6214,
+    "end_line": 6222,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "``\nfoo \n``\n",
+    "html": "<p><code>foo </code></p>\n",
+    "example": 346,
+    "start_line": 6224,
+    "end_line": 6230,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo   bar \nbaz`\n",
+    "html": "<p><code>foo   bar  baz</code></p>\n",
+    "example": 347,
+    "start_line": 6235,
+    "end_line": 6240,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo\\`bar`\n",
+    "html": "<p><code>foo\\</code>bar`</p>\n",
+    "example": 348,
+    "start_line": 6252,
+    "end_line": 6256,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "``foo`bar``\n",
+    "html": "<p><code>foo`bar</code></p>\n",
+    "example": 349,
+    "start_line": 6263,
+    "end_line": 6267,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "` foo `` bar `\n",
+    "html": "<p><code>foo `` bar</code></p>\n",
+    "example": 350,
+    "start_line": 6269,
+    "end_line": 6273,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo`*`\n",
+    "html": "<p>*foo<code>*</code></p>\n",
+    "example": 351,
+    "start_line": 6281,
+    "end_line": 6285,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "[not a `link](/foo`)\n",
+    "html": "<p>[not a <code>link](/foo</code>)</p>\n",
+    "example": 352,
+    "start_line": 6290,
+    "end_line": 6294,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`<a href=\"`\">`\n",
+    "html": "<p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>\n",
+    "example": 353,
+    "start_line": 6300,
+    "end_line": 6304,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"`\">`\n",
+    "html": "<p><a href=\"`\">`</p>\n",
+    "example": 354,
+    "start_line": 6309,
+    "end_line": 6313,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`<http://foo.bar.`baz>`\n",
+    "html": "<p><code>&lt;http://foo.bar.</code>baz&gt;`</p>\n",
+    "example": 355,
+    "start_line": 6318,
+    "end_line": 6322,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.`baz>`\n",
+    "html": "<p><a href=\"http://foo.bar.%60baz\">http://foo.bar.`baz</a>`</p>\n",
+    "example": 356,
+    "start_line": 6327,
+    "end_line": 6331,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "```foo``\n",
+    "html": "<p>```foo``</p>\n",
+    "example": 357,
+    "start_line": 6337,
+    "end_line": 6341,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo\n",
+    "html": "<p>`foo</p>\n",
+    "example": 358,
+    "start_line": 6344,
+    "end_line": 6348,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "`foo``bar``\n",
+    "html": "<p>`foo<code>bar</code></p>\n",
+    "example": 359,
+    "start_line": 6353,
+    "end_line": 6357,
+    "section": "Code spans",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar*\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 360,
+    "start_line": 6570,
+    "end_line": 6574,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a * foo bar*\n",
+    "html": "<p>a * foo bar*</p>\n",
+    "example": 361,
+    "start_line": 6580,
+    "end_line": 6584,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a*\"foo\"*\n",
+    "html": "<p>a*&quot;foo&quot;*</p>\n",
+    "example": 362,
+    "start_line": 6591,
+    "end_line": 6595,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*\u00a0a\u00a0*\n",
+    "html": "<p>*\u00a0a\u00a0*</p>\n",
+    "example": 363,
+    "start_line": 6600,
+    "end_line": 6604,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo*bar*\n",
+    "html": "<p>foo<em>bar</em></p>\n",
+    "example": 364,
+    "start_line": 6609,
+    "end_line": 6613,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5*6*78\n",
+    "html": "<p>5<em>6</em>78</p>\n",
+    "example": 365,
+    "start_line": 6616,
+    "end_line": 6620,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo bar_\n",
+    "html": "<p><em>foo bar</em></p>\n",
+    "example": 366,
+    "start_line": 6625,
+    "end_line": 6629,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_ foo bar_\n",
+    "html": "<p>_ foo bar_</p>\n",
+    "example": 367,
+    "start_line": 6635,
+    "end_line": 6639,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a_\"foo\"_\n",
+    "html": "<p>a_&quot;foo&quot;_</p>\n",
+    "example": 368,
+    "start_line": 6645,
+    "end_line": 6649,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo_bar_\n",
+    "html": "<p>foo_bar_</p>\n",
+    "example": 369,
+    "start_line": 6654,
+    "end_line": 6658,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5_6_78\n",
+    "html": "<p>5_6_78</p>\n",
+    "example": 370,
+    "start_line": 6661,
+    "end_line": 6665,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f_\n",
+    "html": "<p>\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f_</p>\n",
+    "example": 371,
+    "start_line": 6668,
+    "end_line": 6672,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "aa_\"bb\"_cc\n",
+    "html": "<p>aa_&quot;bb&quot;_cc</p>\n",
+    "example": 372,
+    "start_line": 6678,
+    "end_line": 6682,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo-_(bar)_\n",
+    "html": "<p>foo-<em>(bar)</em></p>\n",
+    "example": 373,
+    "start_line": 6689,
+    "end_line": 6693,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo*\n",
+    "html": "<p>_foo*</p>\n",
+    "example": 374,
+    "start_line": 6701,
+    "end_line": 6705,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar *\n",
+    "html": "<p>*foo bar *</p>\n",
+    "example": 375,
+    "start_line": 6711,
+    "end_line": 6715,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo bar\n*\n",
+    "html": "<p>*foo bar\n*</p>\n",
+    "example": 376,
+    "start_line": 6720,
+    "end_line": 6726,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(*foo)\n",
+    "html": "<p>*(*foo)</p>\n",
+    "example": 377,
+    "start_line": 6733,
+    "end_line": 6737,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(*foo*)*\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 378,
+    "start_line": 6743,
+    "end_line": 6747,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo*bar\n",
+    "html": "<p><em>foo</em>bar</p>\n",
+    "example": 379,
+    "start_line": 6752,
+    "end_line": 6756,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo bar _\n",
+    "html": "<p>_foo bar _</p>\n",
+    "example": 380,
+    "start_line": 6765,
+    "end_line": 6769,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(_foo)\n",
+    "html": "<p>_(_foo)</p>\n",
+    "example": 381,
+    "start_line": 6775,
+    "end_line": 6779,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(_foo_)_\n",
+    "html": "<p><em>(<em>foo</em>)</em></p>\n",
+    "example": 382,
+    "start_line": 6784,
+    "end_line": 6788,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo_bar\n",
+    "html": "<p>_foo_bar</p>\n",
+    "example": 383,
+    "start_line": 6793,
+    "end_line": 6797,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f\n",
+    "html": "<p>_\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c_\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f</p>\n",
+    "example": 384,
+    "start_line": 6800,
+    "end_line": 6804,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo_bar_baz_\n",
+    "html": "<p><em>foo_bar_baz</em></p>\n",
+    "example": 385,
+    "start_line": 6807,
+    "end_line": 6811,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(bar)_.\n",
+    "html": "<p><em>(bar)</em>.</p>\n",
+    "example": 386,
+    "start_line": 6818,
+    "end_line": 6822,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo bar**\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 387,
+    "start_line": 6827,
+    "end_line": 6831,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "** foo bar**\n",
+    "html": "<p>** foo bar**</p>\n",
+    "example": 388,
+    "start_line": 6837,
+    "end_line": 6841,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a**\"foo\"**\n",
+    "html": "<p>a**&quot;foo&quot;**</p>\n",
+    "example": 389,
+    "start_line": 6848,
+    "end_line": 6852,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo**bar**\n",
+    "html": "<p>foo<strong>bar</strong></p>\n",
+    "example": 390,
+    "start_line": 6857,
+    "end_line": 6861,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo bar__\n",
+    "html": "<p><strong>foo bar</strong></p>\n",
+    "example": 391,
+    "start_line": 6866,
+    "end_line": 6870,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__ foo bar__\n",
+    "html": "<p>__ foo bar__</p>\n",
+    "example": 392,
+    "start_line": 6876,
+    "end_line": 6880,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__\nfoo bar__\n",
+    "html": "<p>__\nfoo bar__</p>\n",
+    "example": 393,
+    "start_line": 6884,
+    "end_line": 6890,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "a__\"foo\"__\n",
+    "html": "<p>a__&quot;foo&quot;__</p>\n",
+    "example": 394,
+    "start_line": 6896,
+    "end_line": 6900,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo__bar__\n",
+    "html": "<p>foo__bar__</p>\n",
+    "example": 395,
+    "start_line": 6905,
+    "end_line": 6909,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "5__6__78\n",
+    "html": "<p>5__6__78</p>\n",
+    "example": 396,
+    "start_line": 6912,
+    "end_line": 6916,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f__\n",
+    "html": "<p>\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f__</p>\n",
+    "example": 397,
+    "start_line": 6919,
+    "end_line": 6923,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo, __bar__, baz__\n",
+    "html": "<p><strong>foo, <strong>bar</strong>, baz</strong></p>\n",
+    "example": 398,
+    "start_line": 6926,
+    "end_line": 6930,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo-__(bar)__\n",
+    "html": "<p>foo-<strong>(bar)</strong></p>\n",
+    "example": 399,
+    "start_line": 6937,
+    "end_line": 6941,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo bar **\n",
+    "html": "<p>**foo bar **</p>\n",
+    "example": 400,
+    "start_line": 6950,
+    "end_line": 6954,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**(**foo)\n",
+    "html": "<p>**(**foo)</p>\n",
+    "example": 401,
+    "start_line": 6963,
+    "end_line": 6967,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*(**foo**)*\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 402,
+    "start_line": 6973,
+    "end_line": 6977,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**\n",
+    "html": "<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.\n<em>Asclepias physocarpa</em>)</strong></p>\n",
+    "example": 403,
+    "start_line": 6980,
+    "end_line": 6986,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo \"*bar*\" foo**\n",
+    "html": "<p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>\n",
+    "example": 404,
+    "start_line": 6989,
+    "end_line": 6993,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo**bar\n",
+    "html": "<p><strong>foo</strong>bar</p>\n",
+    "example": 405,
+    "start_line": 6998,
+    "end_line": 7002,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo bar __\n",
+    "html": "<p>__foo bar __</p>\n",
+    "example": 406,
+    "start_line": 7010,
+    "end_line": 7014,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__(__foo)\n",
+    "html": "<p>__(__foo)</p>\n",
+    "example": 407,
+    "start_line": 7020,
+    "end_line": 7024,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_(__foo__)_\n",
+    "html": "<p><em>(<strong>foo</strong>)</em></p>\n",
+    "example": 408,
+    "start_line": 7030,
+    "end_line": 7034,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__bar\n",
+    "html": "<p>__foo__bar</p>\n",
+    "example": 409,
+    "start_line": 7039,
+    "end_line": 7043,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f\n",
+    "html": "<p>__\u043f\u0440\u0438\u0441\u0442\u0430\u043d\u044f\u043c__\u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f</p>\n",
+    "example": 410,
+    "start_line": 7046,
+    "end_line": 7050,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__bar__baz__\n",
+    "html": "<p><strong>foo__bar__baz</strong></p>\n",
+    "example": 411,
+    "start_line": 7053,
+    "end_line": 7057,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__(bar)__.\n",
+    "html": "<p><strong>(bar)</strong>.</p>\n",
+    "example": 412,
+    "start_line": 7064,
+    "end_line": 7068,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [bar](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\">bar</a></em></p>\n",
+    "example": 413,
+    "start_line": 7076,
+    "end_line": 7080,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo\nbar*\n",
+    "html": "<p><em>foo\nbar</em></p>\n",
+    "example": 414,
+    "start_line": 7083,
+    "end_line": 7089,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo __bar__ baz_\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 415,
+    "start_line": 7095,
+    "end_line": 7099,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo _bar_ baz_\n",
+    "html": "<p><em>foo <em>bar</em> baz</em></p>\n",
+    "example": 416,
+    "start_line": 7102,
+    "end_line": 7106,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo_ bar_\n",
+    "html": "<p><em><em>foo</em> bar</em></p>\n",
+    "example": 417,
+    "start_line": 7109,
+    "end_line": 7113,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo *bar**\n",
+    "html": "<p><em>foo <em>bar</em></em></p>\n",
+    "example": 418,
+    "start_line": 7116,
+    "end_line": 7120,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar** baz*\n",
+    "html": "<p><em>foo <strong>bar</strong> baz</em></p>\n",
+    "example": 419,
+    "start_line": 7123,
+    "end_line": 7127,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**bar**baz*\n",
+    "html": "<p><em>foo<strong>bar</strong>baz</em></p>\n",
+    "example": 420,
+    "start_line": 7129,
+    "end_line": 7133,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**bar*\n",
+    "html": "<p><em>foo**bar</em></p>\n",
+    "example": 421,
+    "start_line": 7153,
+    "end_line": 7157,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo** bar*\n",
+    "html": "<p><em><strong>foo</strong> bar</em></p>\n",
+    "example": 422,
+    "start_line": 7166,
+    "end_line": 7170,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar***\n",
+    "html": "<p><em>foo <strong>bar</strong></em></p>\n",
+    "example": 423,
+    "start_line": 7173,
+    "end_line": 7177,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**bar***\n",
+    "html": "<p><em>foo<strong>bar</strong></em></p>\n",
+    "example": 424,
+    "start_line": 7180,
+    "end_line": 7184,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo***bar***baz\n",
+    "html": "<p>foo<em><strong>bar</strong></em>baz</p>\n",
+    "example": 425,
+    "start_line": 7191,
+    "end_line": 7195,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo******bar*********baz\n",
+    "html": "<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>\n",
+    "example": 426,
+    "start_line": 7197,
+    "end_line": 7201,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo **bar *baz* bim** bop*\n",
+    "html": "<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>\n",
+    "example": 427,
+    "start_line": 7206,
+    "end_line": 7210,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [*bar*](/url)*\n",
+    "html": "<p><em>foo <a href=\"/url\"><em>bar</em></a></em></p>\n",
+    "example": 428,
+    "start_line": 7213,
+    "end_line": 7217,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "** is not an empty emphasis\n",
+    "html": "<p>** is not an empty emphasis</p>\n",
+    "example": 429,
+    "start_line": 7222,
+    "end_line": 7226,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**** is not an empty strong emphasis\n",
+    "html": "<p>**** is not an empty strong emphasis</p>\n",
+    "example": 430,
+    "start_line": 7229,
+    "end_line": 7233,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo [bar](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\">bar</a></strong></p>\n",
+    "example": 431,
+    "start_line": 7242,
+    "end_line": 7246,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo\nbar**\n",
+    "html": "<p><strong>foo\nbar</strong></p>\n",
+    "example": 432,
+    "start_line": 7249,
+    "end_line": 7255,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo _bar_ baz__\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 433,
+    "start_line": 7261,
+    "end_line": 7265,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo __bar__ baz__\n",
+    "html": "<p><strong>foo <strong>bar</strong> baz</strong></p>\n",
+    "example": 434,
+    "start_line": 7268,
+    "end_line": 7272,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo__ bar__\n",
+    "html": "<p><strong><strong>foo</strong> bar</strong></p>\n",
+    "example": 435,
+    "start_line": 7275,
+    "end_line": 7279,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo **bar****\n",
+    "html": "<p><strong>foo <strong>bar</strong></strong></p>\n",
+    "example": 436,
+    "start_line": 7282,
+    "end_line": 7286,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar* baz**\n",
+    "html": "<p><strong>foo <em>bar</em> baz</strong></p>\n",
+    "example": 437,
+    "start_line": 7289,
+    "end_line": 7293,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo*bar*baz**\n",
+    "html": "<p><strong>foo<em>bar</em>baz</strong></p>\n",
+    "example": 438,
+    "start_line": 7296,
+    "end_line": 7300,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo* bar**\n",
+    "html": "<p><strong><em>foo</em> bar</strong></p>\n",
+    "example": 439,
+    "start_line": 7303,
+    "end_line": 7307,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar***\n",
+    "html": "<p><strong>foo <em>bar</em></strong></p>\n",
+    "example": 440,
+    "start_line": 7310,
+    "end_line": 7314,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo *bar **baz**\nbim* bop**\n",
+    "html": "<p><strong>foo <em>bar <strong>baz</strong>\nbim</em> bop</strong></p>\n",
+    "example": 441,
+    "start_line": 7319,
+    "end_line": 7325,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo [*bar*](/url)**\n",
+    "html": "<p><strong>foo <a href=\"/url\"><em>bar</em></a></strong></p>\n",
+    "example": 442,
+    "start_line": 7328,
+    "end_line": 7332,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__ is not an empty emphasis\n",
+    "html": "<p>__ is not an empty emphasis</p>\n",
+    "example": 443,
+    "start_line": 7337,
+    "end_line": 7341,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____ is not an empty strong emphasis\n",
+    "html": "<p>____ is not an empty strong emphasis</p>\n",
+    "example": 444,
+    "start_line": 7344,
+    "end_line": 7348,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo ***\n",
+    "html": "<p>foo ***</p>\n",
+    "example": 445,
+    "start_line": 7354,
+    "end_line": 7358,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *\\**\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 446,
+    "start_line": 7361,
+    "end_line": 7365,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *_*\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 447,
+    "start_line": 7368,
+    "end_line": 7372,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo *****\n",
+    "html": "<p>foo *****</p>\n",
+    "example": 448,
+    "start_line": 7375,
+    "end_line": 7379,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo **\\***\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 449,
+    "start_line": 7382,
+    "end_line": 7386,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo **_**\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 450,
+    "start_line": 7389,
+    "end_line": 7393,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo*\n",
+    "html": "<p>*<em>foo</em></p>\n",
+    "example": 451,
+    "start_line": 7400,
+    "end_line": 7404,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo**\n",
+    "html": "<p><em>foo</em>*</p>\n",
+    "example": 452,
+    "start_line": 7407,
+    "end_line": 7411,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo**\n",
+    "html": "<p>*<strong>foo</strong></p>\n",
+    "example": 453,
+    "start_line": 7414,
+    "end_line": 7418,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "****foo*\n",
+    "html": "<p>***<em>foo</em></p>\n",
+    "example": 454,
+    "start_line": 7421,
+    "end_line": 7425,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo***\n",
+    "html": "<p><strong>foo</strong>*</p>\n",
+    "example": 455,
+    "start_line": 7428,
+    "end_line": 7432,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo****\n",
+    "html": "<p><em>foo</em>***</p>\n",
+    "example": 456,
+    "start_line": 7435,
+    "end_line": 7439,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo ___\n",
+    "html": "<p>foo ___</p>\n",
+    "example": 457,
+    "start_line": 7445,
+    "end_line": 7449,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _\\__\n",
+    "html": "<p>foo <em>_</em></p>\n",
+    "example": 458,
+    "start_line": 7452,
+    "end_line": 7456,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _*_\n",
+    "html": "<p>foo <em>*</em></p>\n",
+    "example": 459,
+    "start_line": 7459,
+    "end_line": 7463,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo _____\n",
+    "html": "<p>foo _____</p>\n",
+    "example": 460,
+    "start_line": 7466,
+    "end_line": 7470,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo __\\___\n",
+    "html": "<p>foo <strong>_</strong></p>\n",
+    "example": 461,
+    "start_line": 7473,
+    "end_line": 7477,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "foo __*__\n",
+    "html": "<p>foo <strong>*</strong></p>\n",
+    "example": 462,
+    "start_line": 7480,
+    "end_line": 7484,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo_\n",
+    "html": "<p>_<em>foo</em></p>\n",
+    "example": 463,
+    "start_line": 7487,
+    "end_line": 7491,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo__\n",
+    "html": "<p><em>foo</em>_</p>\n",
+    "example": 464,
+    "start_line": 7498,
+    "end_line": 7502,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "___foo__\n",
+    "html": "<p>_<strong>foo</strong></p>\n",
+    "example": 465,
+    "start_line": 7505,
+    "end_line": 7509,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo_\n",
+    "html": "<p>___<em>foo</em></p>\n",
+    "example": 466,
+    "start_line": 7512,
+    "end_line": 7516,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo___\n",
+    "html": "<p><strong>foo</strong>_</p>\n",
+    "example": 467,
+    "start_line": 7519,
+    "end_line": 7523,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo____\n",
+    "html": "<p><em>foo</em>___</p>\n",
+    "example": 468,
+    "start_line": 7526,
+    "end_line": 7530,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo**\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 469,
+    "start_line": 7536,
+    "end_line": 7540,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*_foo_*\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 470,
+    "start_line": 7543,
+    "end_line": 7547,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__foo__\n",
+    "html": "<p><strong>foo</strong></p>\n",
+    "example": 471,
+    "start_line": 7550,
+    "end_line": 7554,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_*foo*_\n",
+    "html": "<p><em><em>foo</em></em></p>\n",
+    "example": 472,
+    "start_line": 7557,
+    "end_line": 7561,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "****foo****\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 473,
+    "start_line": 7567,
+    "end_line": 7571,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "____foo____\n",
+    "html": "<p><strong><strong>foo</strong></strong></p>\n",
+    "example": 474,
+    "start_line": 7574,
+    "end_line": 7578,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "******foo******\n",
+    "html": "<p><strong><strong><strong>foo</strong></strong></strong></p>\n",
+    "example": 475,
+    "start_line": 7585,
+    "end_line": 7589,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "***foo***\n",
+    "html": "<p><em><strong>foo</strong></em></p>\n",
+    "example": 476,
+    "start_line": 7594,
+    "end_line": 7598,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_____foo_____\n",
+    "html": "<p><em><strong><strong>foo</strong></strong></em></p>\n",
+    "example": 477,
+    "start_line": 7601,
+    "end_line": 7605,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo _bar* baz_\n",
+    "html": "<p><em>foo _bar</em> baz_</p>\n",
+    "example": 478,
+    "start_line": 7610,
+    "end_line": 7614,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo __bar *baz bim__ bam*\n",
+    "html": "<p><em>foo <strong>bar *baz bim</strong> bam</em></p>\n",
+    "example": 479,
+    "start_line": 7617,
+    "end_line": 7621,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**foo **bar baz**\n",
+    "html": "<p>**foo <strong>bar baz</strong></p>\n",
+    "example": 480,
+    "start_line": 7626,
+    "end_line": 7630,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo *bar baz*\n",
+    "html": "<p>*foo <em>bar baz</em></p>\n",
+    "example": 481,
+    "start_line": 7633,
+    "end_line": 7637,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*[bar*](/url)\n",
+    "html": "<p>*<a href=\"/url\">bar*</a></p>\n",
+    "example": 482,
+    "start_line": 7642,
+    "end_line": 7646,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_foo [bar_](/url)\n",
+    "html": "<p>_foo <a href=\"/url\">bar_</a></p>\n",
+    "example": 483,
+    "start_line": 7649,
+    "end_line": 7653,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*<img src=\"foo\" title=\"*\"/>\n",
+    "html": "<p>*<img src=\"foo\" title=\"*\"/></p>\n",
+    "example": 484,
+    "start_line": 7656,
+    "end_line": 7660,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**<a href=\"**\">\n",
+    "html": "<p>**<a href=\"**\"></p>\n",
+    "example": 485,
+    "start_line": 7663,
+    "end_line": 7667,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__<a href=\"__\">\n",
+    "html": "<p>__<a href=\"__\"></p>\n",
+    "example": 486,
+    "start_line": 7670,
+    "end_line": 7674,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "*a `*`*\n",
+    "html": "<p><em>a <code>*</code></em></p>\n",
+    "example": 487,
+    "start_line": 7677,
+    "end_line": 7681,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "_a `_`_\n",
+    "html": "<p><em>a <code>_</code></em></p>\n",
+    "example": 488,
+    "start_line": 7684,
+    "end_line": 7688,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "**a<http://foo.bar/?q=**>\n",
+    "html": "<p>**a<a href=\"http://foo.bar/?q=**\">http://foo.bar/?q=**</a></p>\n",
+    "example": 489,
+    "start_line": 7691,
+    "end_line": 7695,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "__a<http://foo.bar/?q=__>\n",
+    "html": "<p>__a<a href=\"http://foo.bar/?q=__\">http://foo.bar/?q=__</a></p>\n",
+    "example": 490,
+    "start_line": 7698,
+    "end_line": 7702,
+    "section": "Emphasis and strong emphasis",
+    "extensions": []
+  },
+  {
+    "markdown": "~~Hi~~ Hello, world!\n",
+    "html": "<p><del>Hi</del> Hello, world!</p>\n",
+    "example": 491,
+    "start_line": 7714,
+    "end_line": 7718,
+    "section": "Strikethrough (extension)",
+    "extensions": [
+      "strikethrough"
+    ]
+  },
+  {
+    "markdown": "This ~~has a\n\nnew paragraph~~.\n",
+    "html": "<p>This ~~has a</p>\n<p>new paragraph~~.</p>\n",
+    "example": 492,
+    "start_line": 7723,
+    "end_line": 7730,
+    "section": "Strikethrough (extension)",
+    "extensions": [
+      "strikethrough"
+    ]
+  },
+  {
+    "markdown": "[link](/uri \"title\")\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 493,
+    "start_line": 7809,
+    "end_line": 7813,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/uri)\n",
+    "html": "<p><a href=\"/uri\">link</a></p>\n",
+    "example": 494,
+    "start_line": 7818,
+    "end_line": 7822,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link]()\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 495,
+    "start_line": 7827,
+    "end_line": 7831,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<>)\n",
+    "html": "<p><a href=\"\">link</a></p>\n",
+    "example": 496,
+    "start_line": 7834,
+    "end_line": 7838,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/my uri)\n",
+    "html": "<p>[link](/my uri)</p>\n",
+    "example": 497,
+    "start_line": 7843,
+    "end_line": 7847,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](</my uri>)\n",
+    "html": "<p><a href=\"/my%20uri\">link</a></p>\n",
+    "example": 498,
+    "start_line": 7849,
+    "end_line": 7853,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\nbar)\n",
+    "html": "<p>[link](foo\nbar)</p>\n",
+    "example": 499,
+    "start_line": 7858,
+    "end_line": 7864,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<foo\nbar>)\n",
+    "html": "<p>[link](<foo\nbar>)</p>\n",
+    "example": 500,
+    "start_line": 7866,
+    "end_line": 7872,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[a](<b)c>)\n",
+    "html": "<p><a href=\"b)c\">a</a></p>\n",
+    "example": 501,
+    "start_line": 7877,
+    "end_line": 7881,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<foo\\>)\n",
+    "html": "<p>[link](&lt;foo&gt;)</p>\n",
+    "example": 502,
+    "start_line": 7885,
+    "end_line": 7889,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[a](<b)c\n[a](<b)c>\n[a](<b>c)\n",
+    "html": "<p>[a](&lt;b)c\n[a](&lt;b)c&gt;\n[a](<b>c)</p>\n",
+    "example": 503,
+    "start_line": 7894,
+    "end_line": 7902,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](\\(foo\\))\n",
+    "html": "<p><a href=\"(foo)\">link</a></p>\n",
+    "example": 504,
+    "start_line": 7906,
+    "end_line": 7910,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo(and(bar)))\n",
+    "html": "<p><a href=\"foo(and(bar))\">link</a></p>\n",
+    "example": 505,
+    "start_line": 7915,
+    "end_line": 7919,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\(and\\(bar\\))\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 506,
+    "start_line": 7924,
+    "end_line": 7928,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](<foo(and(bar)>)\n",
+    "html": "<p><a href=\"foo(and(bar)\">link</a></p>\n",
+    "example": 507,
+    "start_line": 7931,
+    "end_line": 7935,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\)\\:)\n",
+    "html": "<p><a href=\"foo):\">link</a></p>\n",
+    "example": 508,
+    "start_line": 7941,
+    "end_line": 7945,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](#fragment)\n\n[link](http://example.com#fragment)\n\n[link](http://example.com?foo=3#frag)\n",
+    "html": "<p><a href=\"#fragment\">link</a></p>\n<p><a href=\"http://example.com#fragment\">link</a></p>\n<p><a href=\"http://example.com?foo=3#frag\">link</a></p>\n",
+    "example": 509,
+    "start_line": 7950,
+    "end_line": 7960,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo\\bar)\n",
+    "html": "<p><a href=\"foo%5Cbar\">link</a></p>\n",
+    "example": 510,
+    "start_line": 7966,
+    "end_line": 7970,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](foo%20b&auml;)\n",
+    "html": "<p><a href=\"foo%20b%C3%A4\">link</a></p>\n",
+    "example": 511,
+    "start_line": 7982,
+    "end_line": 7986,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](\"title\")\n",
+    "html": "<p><a href=\"%22title%22\">link</a></p>\n",
+    "example": 512,
+    "start_line": 7993,
+    "end_line": 7997,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title\")\n[link](/url 'title')\n[link](/url (title))\n",
+    "html": "<p><a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a>\n<a href=\"/url\" title=\"title\">link</a></p>\n",
+    "example": 513,
+    "start_line": 8002,
+    "end_line": 8010,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title \\\"&quot;\")\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;&quot;\">link</a></p>\n",
+    "example": 514,
+    "start_line": 8016,
+    "end_line": 8020,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url\u00a0\"title\")\n",
+    "html": "<p><a href=\"/url%C2%A0%22title%22\">link</a></p>\n",
+    "example": 515,
+    "start_line": 8026,
+    "end_line": 8030,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url \"title \"and\" title\")\n",
+    "html": "<p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>\n",
+    "example": 516,
+    "start_line": 8035,
+    "end_line": 8039,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](/url 'title \"and\" title')\n",
+    "html": "<p><a href=\"/url\" title=\"title &quot;and&quot; title\">link</a></p>\n",
+    "example": 517,
+    "start_line": 8044,
+    "end_line": 8048,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link](   /uri\n  \"title\"  )\n",
+    "html": "<p><a href=\"/uri\" title=\"title\">link</a></p>\n",
+    "example": 518,
+    "start_line": 8068,
+    "end_line": 8073,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link] (/uri)\n",
+    "html": "<p>[link] (/uri)</p>\n",
+    "example": 519,
+    "start_line": 8079,
+    "end_line": 8083,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [foo [bar]]](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 520,
+    "start_line": 8089,
+    "end_line": 8093,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link] bar](/uri)\n",
+    "html": "<p>[link] bar](/uri)</p>\n",
+    "example": 521,
+    "start_line": 8096,
+    "end_line": 8100,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [bar](/uri)\n",
+    "html": "<p>[link <a href=\"/uri\">bar</a></p>\n",
+    "example": 522,
+    "start_line": 8103,
+    "end_line": 8107,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link \\[bar](/uri)\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 523,
+    "start_line": 8110,
+    "end_line": 8114,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*](/uri)\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 524,
+    "start_line": 8119,
+    "end_line": 8123,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[![moon](moon.jpg)](/uri)\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 525,
+    "start_line": 8126,
+    "end_line": 8130,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo [bar](/uri)](/uri)\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>](/uri)</p>\n",
+    "example": 526,
+    "start_line": 8135,
+    "end_line": 8139,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *[bar [baz](/uri)](/uri)*](/uri)\n",
+    "html": "<p>[foo <em>[bar <a href=\"/uri\">baz</a>](/uri)</em>](/uri)</p>\n",
+    "example": 527,
+    "start_line": 8142,
+    "end_line": 8146,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "![[[foo](uri1)](uri2)](uri3)\n",
+    "html": "<p><img src=\"uri3\" alt=\"[foo](uri2)\" /></p>\n",
+    "example": 528,
+    "start_line": 8149,
+    "end_line": 8153,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*[foo*](/uri)\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 529,
+    "start_line": 8159,
+    "end_line": 8163,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar](baz*)\n",
+    "html": "<p><a href=\"baz*\">foo *bar</a></p>\n",
+    "example": 530,
+    "start_line": 8166,
+    "end_line": 8170,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo [bar* baz]\n",
+    "html": "<p><em>foo [bar</em> baz]</p>\n",
+    "example": 531,
+    "start_line": 8176,
+    "end_line": 8180,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo <bar attr=\"](baz)\">\n",
+    "html": "<p>[foo <bar attr=\"](baz)\"></p>\n",
+    "example": 532,
+    "start_line": 8186,
+    "end_line": 8190,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo`](/uri)`\n",
+    "html": "<p>[foo<code>](/uri)</code></p>\n",
+    "example": 533,
+    "start_line": 8193,
+    "end_line": 8197,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo<http://example.com/?search=](uri)>\n",
+    "html": "<p>[foo<a href=\"http://example.com/?search=%5D(uri)\">http://example.com/?search=](uri)</a></p>\n",
+    "example": 534,
+    "start_line": 8200,
+    "end_line": 8204,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 535,
+    "start_line": 8238,
+    "end_line": 8244,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link [foo [bar]]][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [foo [bar]]</a></p>\n",
+    "example": 536,
+    "start_line": 8253,
+    "end_line": 8259,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link \\[bar][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link [bar</a></p>\n",
+    "example": 537,
+    "start_line": 8262,
+    "end_line": 8268,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[link *foo **bar** `#`*][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>\n",
+    "example": 538,
+    "start_line": 8273,
+    "end_line": 8279,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[![moon](moon.jpg)][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\"><img src=\"moon.jpg\" alt=\"moon\" /></a></p>\n",
+    "example": 539,
+    "start_line": 8282,
+    "end_line": 8288,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo [bar](/uri)][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <a href=\"/uri\">bar</a>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 540,
+    "start_line": 8293,
+    "end_line": 8299,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>[foo <em>bar <a href=\"/uri\">baz</a></em>]<a href=\"/uri\">ref</a></p>\n",
+    "example": 541,
+    "start_line": 8302,
+    "end_line": 8308,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "*[foo*][ref]\n\n[ref]: /uri\n",
+    "html": "<p>*<a href=\"/uri\">foo*</a></p>\n",
+    "example": 542,
+    "start_line": 8317,
+    "end_line": 8323,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo *bar][ref]\n\n[ref]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo *bar</a></p>\n",
+    "example": 543,
+    "start_line": 8326,
+    "end_line": 8332,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo <bar attr=\"][ref]\">\n\n[ref]: /uri\n",
+    "html": "<p>[foo <bar attr=\"][ref]\"></p>\n",
+    "example": 544,
+    "start_line": 8338,
+    "end_line": 8344,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo`][ref]`\n\n[ref]: /uri\n",
+    "html": "<p>[foo<code>][ref]</code></p>\n",
+    "example": 545,
+    "start_line": 8347,
+    "end_line": 8353,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo<http://example.com/?search=][ref]>\n\n[ref]: /uri\n",
+    "html": "<p>[foo<a href=\"http://example.com/?search=%5D%5Bref%5D\">http://example.com/?search=][ref]</a></p>\n",
+    "example": 546,
+    "start_line": 8356,
+    "end_line": 8362,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][BaR]\n\n[bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 547,
+    "start_line": 8367,
+    "end_line": 8373,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[\u0422\u043e\u043b\u043f\u043e\u0439][\u0422\u043e\u043b\u043f\u043e\u0439] is a Russian word.\n\n[\u0422\u041e\u041b\u041f\u041e\u0419]: /url\n",
+    "html": "<p><a href=\"/url\">\u0422\u043e\u043b\u043f\u043e\u0439</a> is a Russian word.</p>\n",
+    "example": 548,
+    "start_line": 8378,
+    "end_line": 8384,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo\n  bar]: /url\n\n[Baz][Foo bar]\n",
+    "html": "<p><a href=\"/url\">Baz</a></p>\n",
+    "example": 549,
+    "start_line": 8390,
+    "end_line": 8397,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] [bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo] <a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 550,
+    "start_line": 8403,
+    "end_line": 8409,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n[bar]\n\n[bar]: /url \"title\"\n",
+    "html": "<p>[foo]\n<a href=\"/url\" title=\"title\">bar</a></p>\n",
+    "example": 551,
+    "start_line": 8412,
+    "end_line": 8420,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]\n",
+    "html": "<p><a href=\"/url1\">bar</a></p>\n",
+    "example": 552,
+    "start_line": 8453,
+    "end_line": 8461,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[bar][foo\\!]\n\n[foo!]: /url\n",
+    "html": "<p>[bar][foo!]</p>\n",
+    "example": 553,
+    "start_line": 8468,
+    "end_line": 8474,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref[]\n\n[ref[]: /uri\n",
+    "html": "<p>[foo][ref[]</p>\n<p>[ref[]: /uri</p>\n",
+    "example": 554,
+    "start_line": 8480,
+    "end_line": 8487,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref[bar]]\n\n[ref[bar]]: /uri\n",
+    "html": "<p>[foo][ref[bar]]</p>\n<p>[ref[bar]]: /uri</p>\n",
+    "example": 555,
+    "start_line": 8490,
+    "end_line": 8497,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[[foo]]]\n\n[[[foo]]]: /url\n",
+    "html": "<p>[[[foo]]]</p>\n<p>[[[foo]]]: /url</p>\n",
+    "example": 556,
+    "start_line": 8500,
+    "end_line": 8507,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][ref\\[]\n\n[ref\\[]: /uri\n",
+    "html": "<p><a href=\"/uri\">foo</a></p>\n",
+    "example": 557,
+    "start_line": 8510,
+    "end_line": 8516,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[bar\\\\]: /uri\n\n[bar\\\\]\n",
+    "html": "<p><a href=\"/uri\">bar\\</a></p>\n",
+    "example": 558,
+    "start_line": 8521,
+    "end_line": 8527,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[]\n\n[]: /uri\n",
+    "html": "<p>[]</p>\n<p>[]: /uri</p>\n",
+    "example": 559,
+    "start_line": 8532,
+    "end_line": 8539,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[\n ]\n\n[\n ]: /uri\n",
+    "html": "<p>[\n]</p>\n<p>[\n]: /uri</p>\n",
+    "example": 560,
+    "start_line": 8542,
+    "end_line": 8553,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 561,
+    "start_line": 8565,
+    "end_line": 8571,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 562,
+    "start_line": 8574,
+    "end_line": 8580,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 563,
+    "start_line": 8585,
+    "end_line": 8591,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a>\n[]</p>\n",
+    "example": 564,
+    "start_line": 8598,
+    "end_line": 8606,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 565,
+    "start_line": 8618,
+    "end_line": 8624,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\"><em>foo</em> bar</a></p>\n",
+    "example": 566,
+    "start_line": 8627,
+    "end_line": 8633,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[*foo* bar]]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p>[<a href=\"/url\" title=\"title\"><em>foo</em> bar</a>]</p>\n",
+    "example": 567,
+    "start_line": 8636,
+    "end_line": 8642,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[[bar [foo]\n\n[foo]: /url\n",
+    "html": "<p>[[bar <a href=\"/url\">foo</a></p>\n",
+    "example": 568,
+    "start_line": 8645,
+    "end_line": 8651,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><a href=\"/url\" title=\"title\">Foo</a></p>\n",
+    "example": 569,
+    "start_line": 8656,
+    "end_line": 8662,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo] bar\n\n[foo]: /url\n",
+    "html": "<p><a href=\"/url\">foo</a> bar</p>\n",
+    "example": 570,
+    "start_line": 8667,
+    "end_line": 8673,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>[foo]</p>\n",
+    "example": 571,
+    "start_line": 8679,
+    "end_line": 8685,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo*]: /url\n\n*[foo*]\n",
+    "html": "<p>*<a href=\"/url\">foo*</a></p>\n",
+    "example": 572,
+    "start_line": 8691,
+    "end_line": 8697,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar]\n\n[foo]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a></p>\n",
+    "example": 573,
+    "start_line": 8703,
+    "end_line": 8710,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][]\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a></p>\n",
+    "example": 574,
+    "start_line": 8712,
+    "end_line": 8718,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo]()\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"\">foo</a></p>\n",
+    "example": 575,
+    "start_line": 8722,
+    "end_line": 8728,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo](not a link)\n\n[foo]: /url1\n",
+    "html": "<p><a href=\"/url1\">foo</a>(not a link)</p>\n",
+    "example": 576,
+    "start_line": 8730,
+    "end_line": 8736,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url\n",
+    "html": "<p>[foo]<a href=\"/url\">bar</a></p>\n",
+    "example": 577,
+    "start_line": 8741,
+    "end_line": 8747,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2\n",
+    "html": "<p><a href=\"/url2\">foo</a><a href=\"/url1\">baz</a></p>\n",
+    "example": 578,
+    "start_line": 8753,
+    "end_line": 8760,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2\n",
+    "html": "<p>[foo]<a href=\"/url1\">bar</a></p>\n",
+    "example": 579,
+    "start_line": 8766,
+    "end_line": 8773,
+    "section": "Links",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](/url \"title\")\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 580,
+    "start_line": 8789,
+    "end_line": 8793,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 581,
+    "start_line": 8796,
+    "end_line": 8802,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo ![bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 582,
+    "start_line": 8805,
+    "end_line": 8809,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo [bar](/url)](/url2)\n",
+    "html": "<p><img src=\"/url2\" alt=\"foo bar\" /></p>\n",
+    "example": 583,
+    "start_line": 8812,
+    "end_line": 8816,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*][]\n\n[foo *bar*]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 584,
+    "start_line": 8826,
+    "end_line": 8832,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg \"train & tracks\"\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>\n",
+    "example": 585,
+    "start_line": 8835,
+    "end_line": 8841,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](train.jpg)\n",
+    "html": "<p><img src=\"train.jpg\" alt=\"foo\" /></p>\n",
+    "example": 586,
+    "start_line": 8844,
+    "end_line": 8848,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "My ![foo bar](/path/to/train.jpg  \"title\"   )\n",
+    "html": "<p>My <img src=\"/path/to/train.jpg\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 587,
+    "start_line": 8851,
+    "end_line": 8855,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo](<url>)\n",
+    "html": "<p><img src=\"url\" alt=\"foo\" /></p>\n",
+    "example": 588,
+    "start_line": 8858,
+    "end_line": 8862,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![](/url)\n",
+    "html": "<p><img src=\"/url\" alt=\"\" /></p>\n",
+    "example": 589,
+    "start_line": 8865,
+    "end_line": 8869,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][bar]\n\n[bar]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 590,
+    "start_line": 8874,
+    "end_line": 8880,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][bar]\n\n[BAR]: /url\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" /></p>\n",
+    "example": 591,
+    "start_line": 8883,
+    "end_line": 8889,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 592,
+    "start_line": 8894,
+    "end_line": 8900,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![*foo* bar][]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 593,
+    "start_line": 8903,
+    "end_line": 8909,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![Foo][]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 594,
+    "start_line": 8914,
+    "end_line": 8920,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo] \n[]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" />\n[]</p>\n",
+    "example": 595,
+    "start_line": 8926,
+    "end_line": 8934,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>\n",
+    "example": 596,
+    "start_line": 8939,
+    "end_line": 8945,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![*foo* bar]\n\n[*foo* bar]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>\n",
+    "example": 597,
+    "start_line": 8948,
+    "end_line": 8954,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![[foo]]\n\n[[foo]]: /url \"title\"\n",
+    "html": "<p>![[foo]]</p>\n<p>[[foo]]: /url &quot;title&quot;</p>\n",
+    "example": 598,
+    "start_line": 8959,
+    "end_line": 8966,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "![Foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>\n",
+    "example": 599,
+    "start_line": 8971,
+    "end_line": 8977,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "!\\[foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>![foo]</p>\n",
+    "example": 600,
+    "start_line": 8983,
+    "end_line": 8989,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "\\![foo]\n\n[foo]: /url \"title\"\n",
+    "html": "<p>!<a href=\"/url\" title=\"title\">foo</a></p>\n",
+    "example": 601,
+    "start_line": 8995,
+    "end_line": 9001,
+    "section": "Images",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.baz>\n",
+    "html": "<p><a href=\"http://foo.bar.baz\">http://foo.bar.baz</a></p>\n",
+    "example": 602,
+    "start_line": 9028,
+    "end_line": 9032,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar.baz/test?q=hello&id=22&boolean>\n",
+    "html": "<p><a href=\"http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean\">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>\n",
+    "example": 603,
+    "start_line": 9035,
+    "end_line": 9039,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<irc://foo.bar:2233/baz>\n",
+    "html": "<p><a href=\"irc://foo.bar:2233/baz\">irc://foo.bar:2233/baz</a></p>\n",
+    "example": 604,
+    "start_line": 9042,
+    "end_line": 9046,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<MAILTO:FOO@BAR.BAZ>\n",
+    "html": "<p><a href=\"MAILTO:FOO@BAR.BAZ\">MAILTO:FOO@BAR.BAZ</a></p>\n",
+    "example": 605,
+    "start_line": 9051,
+    "end_line": 9055,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a+b+c:d>\n",
+    "html": "<p><a href=\"a+b+c:d\">a+b+c:d</a></p>\n",
+    "example": 606,
+    "start_line": 9063,
+    "end_line": 9067,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<made-up-scheme://foo,bar>\n",
+    "html": "<p><a href=\"made-up-scheme://foo,bar\">made-up-scheme://foo,bar</a></p>\n",
+    "example": 607,
+    "start_line": 9070,
+    "end_line": 9074,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://../>\n",
+    "html": "<p><a href=\"http://../\">http://../</a></p>\n",
+    "example": 608,
+    "start_line": 9077,
+    "end_line": 9081,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<localhost:5001/foo>\n",
+    "html": "<p><a href=\"localhost:5001/foo\">localhost:5001/foo</a></p>\n",
+    "example": 609,
+    "start_line": 9084,
+    "end_line": 9088,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://foo.bar/baz bim>\n",
+    "html": "<p>&lt;http://foo.bar/baz bim&gt;</p>\n",
+    "example": 610,
+    "start_line": 9093,
+    "end_line": 9097,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<http://example.com/\\[\\>\n",
+    "html": "<p><a href=\"http://example.com/%5C%5B%5C\">http://example.com/\\[\\</a></p>\n",
+    "example": 611,
+    "start_line": 9102,
+    "end_line": 9106,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo@bar.example.com>\n",
+    "html": "<p><a href=\"mailto:foo@bar.example.com\">foo@bar.example.com</a></p>\n",
+    "example": 612,
+    "start_line": 9124,
+    "end_line": 9128,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo+special@Bar.baz-bar0.com>\n",
+    "html": "<p><a href=\"mailto:foo+special@Bar.baz-bar0.com\">foo+special@Bar.baz-bar0.com</a></p>\n",
+    "example": 613,
+    "start_line": 9131,
+    "end_line": 9135,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo\\+@bar.example.com>\n",
+    "html": "<p>&lt;foo+@bar.example.com&gt;</p>\n",
+    "example": 614,
+    "start_line": 9140,
+    "end_line": 9144,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<>\n",
+    "html": "<p>&lt;&gt;</p>\n",
+    "example": 615,
+    "start_line": 9149,
+    "end_line": 9153,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "< http://foo.bar >\n",
+    "html": "<p>&lt; http://foo.bar &gt;</p>\n",
+    "example": 616,
+    "start_line": 9156,
+    "end_line": 9160,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<m:abc>\n",
+    "html": "<p>&lt;m:abc&gt;</p>\n",
+    "example": 617,
+    "start_line": 9163,
+    "end_line": 9167,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "<foo.bar.baz>\n",
+    "html": "<p>&lt;foo.bar.baz&gt;</p>\n",
+    "example": 618,
+    "start_line": 9170,
+    "end_line": 9174,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "http://example.com\n",
+    "html": "<p>http://example.com</p>\n",
+    "example": 619,
+    "start_line": 9177,
+    "end_line": 9181,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo@bar.example.com\n",
+    "html": "<p>foo@bar.example.com</p>\n",
+    "example": 620,
+    "start_line": 9184,
+    "end_line": 9188,
+    "section": "Autolinks",
+    "extensions": []
+  },
+  {
+    "markdown": "www.commonmark.org\n",
+    "html": "<p><a href=\"http://www.commonmark.org\">www.commonmark.org</a></p>\n",
+    "example": 621,
+    "start_line": 9213,
+    "end_line": 9217,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "Visit www.commonmark.org/help for more information.\n",
+    "html": "<p>Visit <a href=\"http://www.commonmark.org/help\">www.commonmark.org/help</a> for more information.</p>\n",
+    "example": 622,
+    "start_line": 9221,
+    "end_line": 9225,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "Visit www.commonmark.org.\n\nVisit www.commonmark.org/a.b.\n",
+    "html": "<p>Visit <a href=\"http://www.commonmark.org\">www.commonmark.org</a>.</p>\n<p>Visit <a href=\"http://www.commonmark.org/a.b\">www.commonmark.org/a.b</a>.</p>\n",
+    "example": 623,
+    "start_line": 9233,
+    "end_line": 9240,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=Markup+(business)\n\nwww.google.com/search?q=Markup+(business)))\n\n(www.google.com/search?q=Markup+(business))\n\n(www.google.com/search?q=Markup+(business)\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a></p>\n<p><a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a>))</p>\n<p>(<a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a>)</p>\n<p>(<a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a></p>\n",
+    "example": 624,
+    "start_line": 9247,
+    "end_line": 9260,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=(business))+ok\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=(business))+ok\">www.google.com/search?q=(business))+ok</a></p>\n",
+    "example": 625,
+    "start_line": 9266,
+    "end_line": 9270,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.google.com/search?q=commonmark&hl=en\n\nwww.google.com/search?q=commonmark&hl;\n",
+    "html": "<p><a href=\"http://www.google.com/search?q=commonmark&amp;hl=en\">www.google.com/search?q=commonmark&amp;hl=en</a></p>\n<p><a href=\"http://www.google.com/search?q=commonmark\">www.google.com/search?q=commonmark</a>&amp;hl;</p>\n",
+    "example": 626,
+    "start_line": 9277,
+    "end_line": 9284,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "www.commonmark.org/he<lp\n",
+    "html": "<p><a href=\"http://www.commonmark.org/he\">www.commonmark.org/he</a>&lt;lp</p>\n",
+    "example": 627,
+    "start_line": 9288,
+    "end_line": 9292,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "http://commonmark.org\n\n(Visit https://encrypted.google.com/search?q=Markup+(business))\n\nAnonymous FTP is available at ftp://foo.bar.baz.\n",
+    "html": "<p><a href=\"http://commonmark.org\">http://commonmark.org</a></p>\n<p>(Visit <a href=\"https://encrypted.google.com/search?q=Markup+(business)\">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>\n<p>Anonymous FTP is available at <a href=\"ftp://foo.bar.baz\">ftp://foo.bar.baz</a>.</p>\n",
+    "example": 628,
+    "start_line": 9299,
+    "end_line": 9309,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "foo@bar.baz\n",
+    "html": "<p><a href=\"mailto:foo@bar.baz\">foo@bar.baz</a></p>\n",
+    "example": 629,
+    "start_line": 9325,
+    "end_line": 9329,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.\n",
+    "html": "<p>hello@mail+xyz.example isn't valid, but <a href=\"mailto:hello+xyz@mail.example\">hello+xyz@mail.example</a> is.</p>\n",
+    "example": 630,
+    "start_line": 9333,
+    "end_line": 9337,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "a.b-c_d@a.b\n\na.b-c_d@a.b.\n\na.b-c_d@a.b-\n\na.b-c_d@a.b_\n",
+    "html": "<p><a href=\"mailto:a.b-c_d@a.b\">a.b-c_d@a.b</a></p>\n<p><a href=\"mailto:a.b-c_d@a.b\">a.b-c_d@a.b</a>.</p>\n<p>a.b-c_d@a.b-</p>\n<p>a.b-c_d@a.b_</p>\n",
+    "example": 631,
+    "start_line": 9343,
+    "end_line": 9356,
+    "section": "Autolinks (extension)",
+    "extensions": [
+      "autolink"
+    ]
+  },
+  {
+    "markdown": "<a><bab><c2c>\n",
+    "html": "<p><a><bab><c2c></p>\n",
+    "example": 632,
+    "start_line": 9434,
+    "end_line": 9438,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a/><b2/>\n",
+    "html": "<p><a/><b2/></p>\n",
+    "example": 633,
+    "start_line": 9443,
+    "end_line": 9447,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a  /><b2\ndata=\"foo\" >\n",
+    "html": "<p><a  /><b2\ndata=\"foo\" ></p>\n",
+    "example": 634,
+    "start_line": 9452,
+    "end_line": 9458,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 />\n",
+    "html": "<p><a foo=\"bar\" bam = 'baz <em>\"</em>'\n_boolean zoop:33=zoop:33 /></p>\n",
+    "example": 635,
+    "start_line": 9463,
+    "end_line": 9469,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo <responsive-image src=\"foo.jpg\" />\n",
+    "html": "<p>Foo <responsive-image src=\"foo.jpg\" /></p>\n",
+    "example": 636,
+    "start_line": 9474,
+    "end_line": 9478,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<33> <__>\n",
+    "html": "<p>&lt;33&gt; &lt;__&gt;</p>\n",
+    "example": 637,
+    "start_line": 9483,
+    "end_line": 9487,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a h*#ref=\"hi\">\n",
+    "html": "<p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>\n",
+    "example": 638,
+    "start_line": 9492,
+    "end_line": 9496,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"hi'> <a href=hi'>\n",
+    "html": "<p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>\n",
+    "example": 639,
+    "start_line": 9501,
+    "end_line": 9505,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "< a><\nfoo><bar/ >\n<foo bar=baz\nbim!bop />\n",
+    "html": "<p>&lt; a&gt;&lt;\nfoo&gt;&lt;bar/ &gt;\n&lt;foo bar=baz\nbim!bop /&gt;</p>\n",
+    "example": 640,
+    "start_line": 9510,
+    "end_line": 9520,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href='bar'title=title>\n",
+    "html": "<p>&lt;a href='bar'title=title&gt;</p>\n",
+    "example": 641,
+    "start_line": 9525,
+    "end_line": 9529,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "</a></foo >\n",
+    "html": "<p></a></foo ></p>\n",
+    "example": 642,
+    "start_line": 9534,
+    "end_line": 9538,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "</a href=\"foo\">\n",
+    "html": "<p>&lt;/a href=&quot;foo&quot;&gt;</p>\n",
+    "example": 643,
+    "start_line": 9543,
+    "end_line": 9547,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!-- this is a --\ncomment - with hyphens -->\n",
+    "html": "<p>foo <!-- this is a --\ncomment - with hyphens --></p>\n",
+    "example": 644,
+    "start_line": 9552,
+    "end_line": 9558,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!--> foo -->\n\nfoo <!---> foo -->\n",
+    "html": "<p>foo <!--> foo --&gt;</p>\n<p>foo <!---> foo --&gt;</p>\n",
+    "example": 645,
+    "start_line": 9560,
+    "end_line": 9567,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <?php echo $a; ?>\n",
+    "html": "<p>foo <?php echo $a; ?></p>\n",
+    "example": 646,
+    "start_line": 9572,
+    "end_line": 9576,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <!ELEMENT br EMPTY>\n",
+    "html": "<p>foo <!ELEMENT br EMPTY></p>\n",
+    "example": 647,
+    "start_line": 9581,
+    "end_line": 9585,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <![CDATA[>&<]]>\n",
+    "html": "<p>foo <![CDATA[>&<]]></p>\n",
+    "example": 648,
+    "start_line": 9590,
+    "end_line": 9594,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <a href=\"&ouml;\">\n",
+    "html": "<p>foo <a href=\"&ouml;\"></p>\n",
+    "example": 649,
+    "start_line": 9600,
+    "end_line": 9604,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "foo <a href=\"\\*\">\n",
+    "html": "<p>foo <a href=\"\\*\"></p>\n",
+    "example": 650,
+    "start_line": 9609,
+    "end_line": 9613,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"\\\"\">\n",
+    "html": "<p>&lt;a href=&quot;&quot;&quot;&gt;</p>\n",
+    "example": 651,
+    "start_line": 9616,
+    "end_line": 9620,
+    "section": "Raw HTML",
+    "extensions": []
+  },
+  {
+    "markdown": "<strong> <title> <style> <em>\n\n<blockquote>\n  <xmp> is disallowed.  <XMP> is also disallowed.\n</blockquote>\n",
+    "html": "<p><strong> &lt;title> &lt;style> <em></p>\n<blockquote>\n  &lt;xmp> is disallowed.  &lt;XMP> is also disallowed.\n</blockquote>\n",
+    "example": 652,
+    "start_line": 9647,
+    "end_line": 9658,
+    "section": "Disallowed Raw HTML (extension)",
+    "extensions": [
+      "tagfilter"
+    ]
+  },
+  {
+    "markdown": "foo  \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 653,
+    "start_line": 9669,
+    "end_line": 9675,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 654,
+    "start_line": 9681,
+    "end_line": 9687,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo       \nbaz\n",
+    "html": "<p>foo<br />\nbaz</p>\n",
+    "example": 655,
+    "start_line": 9692,
+    "end_line": 9698,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo  \n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 656,
+    "start_line": 9703,
+    "end_line": 9709,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\n     bar\n",
+    "html": "<p>foo<br />\nbar</p>\n",
+    "example": 657,
+    "start_line": 9712,
+    "end_line": 9718,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo  \nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 658,
+    "start_line": 9724,
+    "end_line": 9730,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "*foo\\\nbar*\n",
+    "html": "<p><em>foo<br />\nbar</em></p>\n",
+    "example": 659,
+    "start_line": 9733,
+    "end_line": 9739,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "`code  \nspan`\n",
+    "html": "<p><code>code   span</code></p>\n",
+    "example": 660,
+    "start_line": 9744,
+    "end_line": 9749,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "`code\\\nspan`\n",
+    "html": "<p><code>code\\ span</code></p>\n",
+    "example": 661,
+    "start_line": 9752,
+    "end_line": 9757,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo  \nbar\">\n",
+    "html": "<p><a href=\"foo  \nbar\"></p>\n",
+    "example": 662,
+    "start_line": 9762,
+    "end_line": 9768,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "<a href=\"foo\\\nbar\">\n",
+    "html": "<p><a href=\"foo\\\nbar\"></p>\n",
+    "example": 663,
+    "start_line": 9771,
+    "end_line": 9777,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\\\n",
+    "html": "<p>foo\\</p>\n",
+    "example": 664,
+    "start_line": 9784,
+    "end_line": 9788,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo  \n",
+    "html": "<p>foo</p>\n",
+    "example": 665,
+    "start_line": 9791,
+    "end_line": 9795,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo\\\n",
+    "html": "<h3>foo\\</h3>\n",
+    "example": 666,
+    "start_line": 9798,
+    "end_line": 9802,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "### foo  \n",
+    "html": "<h3>foo</h3>\n",
+    "example": 667,
+    "start_line": 9805,
+    "end_line": 9809,
+    "section": "Hard line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo\nbaz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 668,
+    "start_line": 9820,
+    "end_line": 9826,
+    "section": "Soft line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "foo \n baz\n",
+    "html": "<p>foo\nbaz</p>\n",
+    "example": 669,
+    "start_line": 9832,
+    "end_line": 9838,
+    "section": "Soft line breaks",
+    "extensions": []
+  },
+  {
+    "markdown": "hello $.;'there\n",
+    "html": "<p>hello $.;'there</p>\n",
+    "example": 670,
+    "start_line": 9852,
+    "end_line": 9856,
+    "section": "Textual content",
+    "extensions": []
+  },
+  {
+    "markdown": "Foo \u03c7\u03c1\u1fc6\u03bd\n",
+    "html": "<p>Foo \u03c7\u03c1\u1fc6\u03bd</p>\n",
+    "example": 671,
+    "start_line": 9859,
+    "end_line": 9863,
+    "section": "Textual content",
+    "extensions": []
+  },
+  {
+    "markdown": "Multiple     spaces\n",
+    "html": "<p>Multiple     spaces</p>\n",
+    "example": 672,
+    "start_line": 9868,
+    "end_line": 9872,
+    "section": "Textual content",
+    "extensions": []
+  }
+]
\ No newline at end of file
diff --git a/pkgs/markdown/tool/stats.dart b/pkgs/markdown/tool/stats.dart
new file mode 100644
index 0000000..67b1d39
--- /dev/null
+++ b/pkgs/markdown/tool/stats.dart
@@ -0,0 +1,266 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:collection/collection.dart';
+import 'package:path/path.dart' as p;
+
+import '../tool/expected_output.dart';
+import 'stats_lib.dart';
+
+final _configs = List<Config>.unmodifiable([
+  Config.commonMarkConfig,
+  Config.gfmConfig,
+]);
+
+Future<void> main(List<String> args) async {
+  final parser = ArgParser()
+    ..addOption(
+      'section',
+      help: 'Restrict tests to one section, provided after the option.',
+    )
+    ..addFlag(
+      'raw',
+      help: 'raw JSON format',
+      negatable: false,
+    )
+    ..addFlag(
+      'update-files',
+      help: 'Update stats files in $toolDir',
+      negatable: false,
+    )
+    ..addFlag(
+      'verbose',
+      help: 'Print details for failures and errors.',
+      negatable: false,
+    )
+    ..addFlag(
+      'verbose-loose',
+      help: 'Print details for "loose" matches.',
+      negatable: false,
+    )
+    ..addOption('flavor', allowed: _configs.map((c) => c.prefix))
+    ..addFlag('help', negatable: false);
+
+  ArgResults options;
+
+  try {
+    options = parser.parse(args);
+  } on FormatException catch (e) {
+    stderr.writeln(e);
+    print(parser.usage);
+    exitCode = 64; // unix standard improper usage
+    return;
+  }
+
+  if (options['help'] as bool) {
+    print(parser.usage);
+    return;
+  }
+
+  final specifiedSection = options['section'] as String?;
+  final raw = options['raw'] as bool;
+  final verbose = options['verbose'] as bool;
+  final verboseLooseMatch = options['verbose-loose'] as bool;
+  final updateFiles = options['update-files'] as bool;
+
+  if (updateFiles && (raw || verbose || (specifiedSection != null))) {
+    stderr.writeln('The `update-files` flag must be used by itself');
+    print(parser.usage);
+    exitCode = 64; // unix standard improper usage
+    return;
+  }
+
+  var testPrefix = options['flavor'] as String?;
+  if (!updateFiles) {
+    testPrefix = _configs.first.prefix;
+  }
+
+  final testPrefixes =
+      testPrefix == null ? _configs.map((c) => c.prefix) : <String>[testPrefix];
+
+  for (final testPrefix in testPrefixes) {
+    await _processConfig(
+      testPrefix,
+      raw,
+      updateFiles,
+      verbose,
+      specifiedSection,
+      verboseLooseMatch,
+    );
+  }
+}
+
+final _sectionNameReplace = RegExp(r'[ \)\(]+');
+
+String _unitOutput(Iterable<DataCase> cases) => cases.map((dataCase) => '''
+>>> ${dataCase.front_matter}
+${dataCase.input}<<<
+${dataCase.expectedOutput}''').join();
+
+/// Set this to `true` and rerun `--update-files` to ease finding easy strict
+/// fixes.
+const _improveStrict = false;
+
+Future<void> _processConfig(
+  String testPrefix,
+  bool raw,
+  bool updateFiles,
+  bool verbose,
+  String? specifiedSection,
+  bool verboseLooseMatch,
+) async {
+  final config = _configs.singleWhere((c) => c.prefix == testPrefix);
+
+  final sections = loadCommonMarkSections(testPrefix);
+
+  final scores = SplayTreeMap<String, SplayTreeMap<int, CompareLevel>>(
+      compareAsciiLowerCaseNatural);
+
+  for (final entry in sections.entries) {
+    if (specifiedSection != null && entry.key != specifiedSection) {
+      continue;
+    }
+
+    final units = <DataCase>[];
+
+    for (final e in entry.value) {
+      final result = compareResult(
+        config,
+        e,
+        verboseFail: verbose,
+        verboseLooseMatch: verboseLooseMatch,
+        extensions: e.extensions,
+      );
+
+      units.add(DataCase(
+        front_matter: result.testCase.toString(),
+        input: result.testCase.markdown,
+        expectedOutput:
+            (_improveStrict && result.compareLevel == CompareLevel.loose)
+                ? result.testCase.html
+                : result.result!,
+      ));
+
+      final nestedMap = scores.putIfAbsent(
+        entry.key,
+        SplayTreeMap<int, CompareLevel>.new,
+      );
+      nestedMap[e.example] = result.compareLevel;
+    }
+
+    if (updateFiles && units.isNotEmpty) {
+      var fileName =
+          entry.key.toLowerCase().replaceAll(_sectionNameReplace, '_');
+      while (fileName.endsWith('_')) {
+        fileName = fileName.substring(0, fileName.length - 1);
+      }
+      fileName = '$fileName.unit';
+      File(p.join('test', testPrefix, fileName))
+        ..createSync(recursive: true)
+        ..writeAsStringSync(_unitOutput(units));
+    }
+  }
+
+  if (raw || updateFiles) {
+    await _printRaw(testPrefix, scores, updateFiles);
+  }
+
+  if (!raw || updateFiles) {
+    await _printFriendly(testPrefix, scores, updateFiles);
+  }
+}
+
+Object? _convert(Object? obj) {
+  if (obj is CompareLevel) {
+    return obj.name;
+  }
+  if (obj is Map) {
+    return obj
+        .map<String, Object?>((key, value) => MapEntry(key.toString(), value));
+  }
+  return obj;
+}
+
+Future<void> _printRaw(
+  String testPrefix,
+  Map<String, Map<int, CompareLevel>> scores,
+  bool updateFiles,
+) async {
+  IOSink sink;
+  if (updateFiles) {
+    final file = getStatsFile(testPrefix);
+    print('Updating ${file.path}');
+    sink = file.openWrite();
+  } else {
+    sink = stdout;
+  }
+
+  const encoder = JsonEncoder.withIndent(' ', _convert);
+  try {
+    sink.writeln(encoder.convert(scores));
+    // ignore: avoid_catching_errors
+  } on JsonUnsupportedObjectError catch (e) {
+    stderr.writeln(e.cause);
+    stderr.writeln(e.unsupportedObject.runtimeType);
+    rethrow;
+  }
+
+  await sink.flush();
+  await sink.close();
+}
+
+String _pct(int value, int total, String section) =>
+    '${value.toString().padLeft(4)} '
+    'of ${total.toString().padLeft(4)} '
+    '– ${(100 * value / total).toStringAsFixed(1).padLeft(5)}%  $section';
+
+Future<void> _printFriendly(
+  String testPrefix,
+  SplayTreeMap<String, SplayTreeMap<int, CompareLevel>> scores,
+  bool updateFiles,
+) async {
+  var totalValid = 0;
+  var totalStrict = 0;
+  var totalExamples = 0;
+
+  IOSink sink;
+  if (updateFiles) {
+    final path = p.join(toolDir, '${testPrefix}_stats.txt');
+    print('Updating $path');
+    final file = File(path);
+    sink = file.openWrite();
+  } else {
+    sink = stdout;
+  }
+
+  scores.forEach((section, Map<int, CompareLevel> map) {
+    final total = map.values.length;
+    totalExamples += total;
+
+    final sectionStrictCount =
+        map.values.where((val) => val == CompareLevel.strict).length;
+
+    final sectionLooseCount =
+        map.values.where((val) => val == CompareLevel.loose).length;
+
+    final sectionValidCount = sectionStrictCount + sectionLooseCount;
+
+    totalStrict += sectionStrictCount;
+    totalValid += sectionValidCount;
+
+    sink.writeln(_pct(sectionValidCount, total, section));
+  });
+
+  sink.writeln(_pct(totalValid, totalExamples, 'TOTAL'));
+  sink.writeln(_pct(totalStrict, totalValid, 'TOTAL Strict'));
+
+  await sink.flush();
+  await sink.close();
+}
diff --git a/pkgs/markdown/tool/stats_lib.dart b/pkgs/markdown/tool/stats_lib.dart
new file mode 100644
index 0000000..5ff6321
--- /dev/null
+++ b/pkgs/markdown/tool/stats_lib.dart
@@ -0,0 +1,276 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+import 'dart:mirrors';
+
+import 'package:html/dom.dart' show Element;
+import 'package:html/parser.dart' show parseFragment;
+import 'package:markdown/markdown.dart'
+    show
+        AutolinkExtensionSyntax,
+        BlockSyntax,
+        InlineSyntax,
+        StrikethroughSyntax,
+        TableSyntax,
+        markdownToHtml;
+import 'package:path/path.dart' as p;
+
+import '../test/util.dart';
+
+// Locate the "tool" directory. Use mirrors so that this works with the test
+// package, which loads this suite into an isolate.
+String get toolDir {
+  final path = (reflect(loadCommonMarkSections) as ClosureMirror)
+      .function
+      .location!
+      .sourceUri
+      .path;
+
+  return p.dirname(path);
+}
+
+File getStatsFile(String prefix) =>
+    File(p.join(toolDir, '${prefix}_stats.json'));
+
+Map<String, List<CommonMarkTestCase>> loadCommonMarkSections(
+    String testPrefix) {
+  final testFile = File(p.join(toolDir, '${testPrefix}_tests.json'));
+  final testsJson = testFile.readAsStringSync();
+
+  final testArray = jsonDecode(testsJson) as List;
+
+  final sections = <String, List<CommonMarkTestCase>>{};
+
+  for (final exampleMap in testArray) {
+    final exampleTest =
+        CommonMarkTestCase.fromJson(exampleMap as Map<String, dynamic>);
+
+    final sectionList =
+        sections.putIfAbsent(exampleTest.section, () => <CommonMarkTestCase>[]);
+
+    sectionList.add(exampleTest);
+  }
+
+  return sections;
+}
+
+class Config {
+  static final Config commonMarkConfig = Config._(
+    'common_mark',
+    'https://spec.commonmark.org/0.30/',
+  );
+  static final Config gfmConfig = Config._(
+    'gfm',
+    'https://github.github.com/gfm/',
+  );
+
+  final String prefix;
+  final String baseUrl;
+
+  Config._(this.prefix, this.baseUrl);
+}
+
+class CommonMarkTestCase {
+  final String markdown;
+  final String section;
+  final int example;
+  final String html;
+  final int startLine;
+  final int endLine;
+  final Set<String> extensions;
+
+  CommonMarkTestCase(
+    this.example,
+    this.section,
+    this.startLine,
+    this.endLine,
+    this.markdown,
+    this.html,
+    this.extensions,
+  );
+
+  factory CommonMarkTestCase.fromJson(Map<String, dynamic> json) {
+    return CommonMarkTestCase(
+      json['example'] as int,
+      json['section'] as String /*!*/,
+      json['start_line'] as int,
+      json['end_line'] as int,
+      json['markdown'] as String /*!*/,
+      json['html'] as String,
+      json['extensions'] == null
+          ? const {}
+          : Set.from(json['extensions'] as List),
+    );
+  }
+
+  @override
+  String toString() => '$section - $example';
+}
+
+enum CompareLevel { strict, loose, fail, error }
+
+class CompareResult {
+  final CompareLevel compareLevel;
+  final CommonMarkTestCase testCase;
+  final String? result;
+
+  CompareResult(this.testCase, this.result, this.compareLevel);
+}
+
+CompareResult compareResult(
+  Config config,
+  CommonMarkTestCase testCase, {
+  bool throwOnError = false,
+  bool verboseFail = false,
+  bool verboseLooseMatch = false,
+  Set<String> extensions = const {},
+}) {
+  var enabletagfilter = false;
+
+  String output;
+  final inlineSyntaxes = <InlineSyntax>[];
+  final blockSyntaxes = <BlockSyntax>[];
+
+  for (final extension in extensions) {
+    switch (extension) {
+      case 'autolink':
+        inlineSyntaxes.add(AutolinkExtensionSyntax());
+        break;
+      case 'strikethrough':
+        inlineSyntaxes.add(StrikethroughSyntax());
+        break;
+      case 'table':
+        blockSyntaxes.add(const TableSyntax());
+        break;
+      case 'tagfilter':
+        enabletagfilter = true;
+        break;
+      default:
+        throw UnimplementedError('Unimplemented extension "$extension"');
+    }
+  }
+
+  try {
+    output = markdownToHtml(
+      testCase.markdown,
+      inlineSyntaxes: inlineSyntaxes,
+      blockSyntaxes: blockSyntaxes,
+      enableTagfilter: enabletagfilter,
+    );
+  } catch (err, stackTrace) {
+    if (throwOnError) {
+      rethrow;
+    }
+    if (verboseFail) {
+      _printVerboseFailure(
+        config.baseUrl,
+        'ERROR',
+        testCase,
+        'Thrown: $err\n$stackTrace',
+      );
+    }
+
+    return CompareResult(testCase, null, CompareLevel.error);
+  }
+
+  if (testCase.html == output) {
+    return CompareResult(testCase, output, CompareLevel.strict);
+  }
+
+  final expectedParsed = parseFragment(testCase.html);
+  final actual = parseFragment(output);
+
+  final looseMatch = _compareHtml(expectedParsed.children, actual.children);
+
+  if (!looseMatch && verboseFail) {
+    _printVerboseFailure(config.baseUrl, 'FAIL', testCase, output);
+  }
+
+  if (looseMatch && verboseLooseMatch) {
+    _printVerboseFailure(config.baseUrl, 'LOOSE', testCase, output);
+  }
+
+  return CompareResult(
+    testCase,
+    output,
+    looseMatch ? CompareLevel.loose : CompareLevel.fail,
+  );
+}
+
+String _indent(String s) =>
+    s.splitMapJoin('\n', onNonMatch: (n) => '    ${whitespaceColor(n)}');
+
+void _printVerboseFailure(
+  String baseUrl,
+  String message,
+  CommonMarkTestCase testCase,
+  String actual,
+) {
+  print('$message: $baseUrl#example-${testCase.example} '
+      '@ ${testCase.section}');
+  print('input:');
+  print(_indent(testCase.markdown));
+  print('expected:');
+  print(_indent(testCase.html));
+  print('actual:');
+  print(_indent(actual));
+  print('-----------------------');
+}
+
+/// Compare two DOM trees for equality.
+bool _compareHtml(
+  List<Element> expectedElements,
+  List<Element> actualElements,
+) {
+  if (expectedElements.length != actualElements.length) {
+    return false;
+  }
+
+  for (var childNum = 0; childNum < expectedElements.length; childNum++) {
+    final expected = expectedElements[childNum];
+    final actual = actualElements[childNum];
+
+    if (expected.runtimeType != actual.runtimeType) {
+      return false;
+    }
+
+    if (expected.localName != actual.localName) {
+      return false;
+    }
+
+    if (expected.attributes.length != actual.attributes.length) {
+      return false;
+    }
+
+    final expectedAttrKeys = expected.attributes.keys.toList();
+    expectedAttrKeys.sort();
+
+    final actualAttrKeys = actual.attributes.keys.toList();
+    actualAttrKeys.sort();
+
+    for (var attrNum = 0; attrNum < actualAttrKeys.length; attrNum++) {
+      final expectedAttrKey = expectedAttrKeys[attrNum];
+      final actualAttrKey = actualAttrKeys[attrNum];
+
+      if (expectedAttrKey != actualAttrKey) {
+        return false;
+      }
+
+      if (expected.attributes[expectedAttrKey] !=
+          actual.attributes[actualAttrKey]) {
+        return false;
+      }
+    }
+
+    final childrenEqual = _compareHtml(expected.children, actual.children);
+
+    if (!childrenEqual) {
+      return false;
+    }
+  }
+
+  return true;
+}
diff --git a/pkgs/markdown/tool/update-gh-pages.sh b/pkgs/markdown/tool/update-gh-pages.sh
new file mode 100755
index 0000000..97762ad
--- /dev/null
+++ b/pkgs/markdown/tool/update-gh-pages.sh
@@ -0,0 +1,13 @@
+# Echo every command being run.
+set +x
+
+# Fail fast if a command fails.
+set -e
+
+dart pub global activate peanut
+
+peanut -d example
+
+echo Now push updated gh-pages branch with:
+echo
+echo '    git push origin --set-upstream gh-pages'
diff --git a/pkgs/markdown/tool/update_blns.dart b/pkgs/markdown/tool/update_blns.dart
new file mode 100644
index 0000000..fbdabca
--- /dev/null
+++ b/pkgs/markdown/tool/update_blns.dart
@@ -0,0 +1,33 @@
+import 'dart:async';
+import 'dart:io';
+
+import 'update_shared.dart';
+
+const _blnsJsonRawUrl =
+    'https://github.com/minimaxir/big-list-of-naughty-strings/raw/master/blns.json';
+const _blnsFilePath = 'test/blns.dart';
+
+Future<void> main() async {
+  final json = (await downloadJson(_blnsJsonRawUrl) as List).cast<String>();
+  final blnsContent = StringBuffer('''
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from big-list-of-naughty-strings's JSON file:
+// $_blnsJsonRawUrl
+// at ${DateTime.now()} by the script, tool/update_blns.dart.
+
+// ignore_for_file: text_direction_code_point_in_literal, use_raw_strings
+// ignore_for_file: lines_longer_than_80_chars
+
+''');
+  blnsContent.writeln('const blns = <String>[');
+  for (final str in json) {
+    final escaped = str
+        .replaceAll(r'\', r'\\')
+        .replaceAll("'", r"\'")
+        .replaceAll(r'$', r'\$');
+    blnsContent.writeln("  '$escaped',");
+  }
+  blnsContent.writeln('];');
+  File(_blnsFilePath).writeAsStringSync(blnsContent.toString());
+}
diff --git a/pkgs/markdown/tool/update_case_folding.dart b/pkgs/markdown/tool/update_case_folding.dart
new file mode 100644
index 0000000..e53f70b
--- /dev/null
+++ b/pkgs/markdown/tool/update_case_folding.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+
+// Generates and updates unicode case folding map.
+// Here only extract status C + F capital letters.
+void main() {
+  // Downloaded from http://www.unicode.org/Public/14.0.0/ucd/CaseFolding.txt
+  final file = File('${p.current}/tool/case_folding.txt');
+
+  final result = <String, String>{};
+
+  for (final line in file.readAsLinesSync()) {
+    if (line.startsWith('#') ||
+        line.trim().isEmpty ||
+        !line.contains('CAPITAL LETTER')) {
+      continue;
+    }
+
+    final content = line.substring(0, line.indexOf('#'));
+    final match =
+        RegExp(r'([0-9A-F]{1,6});\s+[CF];\s+(.+);').firstMatch(content);
+    if (match == null) {
+      continue;
+    }
+
+    final key = String.fromCharCode(int.parse(match[1]!, radix: 16));
+    final value = match[2]!.split(RegExp('[ ]+')).map((e) {
+      return String.fromCharCode(int.parse(e, radix: 16));
+    }).join();
+    result[key] = value;
+  }
+
+  final outputPath = '${p.current}/lib/src/assets/case_folding.dart';
+  final stringMap = const JsonEncoder.withIndent('  ').convert(result);
+  final output = '''
+// Generated file. do not edit.
+//
+// Source: tool/case_folding.txt
+// Script: tool/update_case_folding.dart
+// ignore_for_file: prefer_single_quotes
+
+const caseFoldingMap = $stringMap;
+''';
+  File(outputPath).writeAsStringSync(output);
+}
diff --git a/pkgs/markdown/tool/update_emojis.dart b/pkgs/markdown/tool/update_emojis.dart
new file mode 100644
index 0000000..0b2b8a9
--- /dev/null
+++ b/pkgs/markdown/tool/update_emojis.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'update_shared.dart';
+
+// update_github_emojis.dart now generates the emoji list using the GitHub API
+// to retrieve the emoji list.  It uses this emoji source as a source to keep
+// binary compatibility with the Unicode sequences for each emoji found here.
+const _emojisJsonRawUrl =
+    'https://raw.githubusercontent.com/muan/emojilib/v2.4.0/emojis.json';
+const _emojisFilePath = 'lib/src/legacy_emojis.dart';
+
+Future<void> main() async {
+  final json =
+      (await downloadJson(_emojisJsonRawUrl) as Map<String, dynamic>).map(
+    (String alias, dynamic info) =>
+        MapEntry(alias, info as Map<String, dynamic>),
+  );
+  final emojisContent = StringBuffer('''
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from emojilib's emoji data file:
+// $_emojisJsonRawUrl
+// at ${DateTime.now()} by the script, tool/update_emojis.dart.
+
+''');
+  emojisContent.writeln('const emojis = <String, String>{');
+  var emojiCount = 0;
+  final ignored = <String>[];
+  // Dump in sorted order now to facilitate comparison with new GitHub emoji.
+  final sortedKeys = json.keys.toList()..sort();
+  for (final alias in sortedKeys) {
+    final info = json[alias] as Map<String, dynamic>;
+    if (info['char'] != null) {
+      emojisContent.writeln("  '$alias': '${info['char']}',");
+      emojiCount++;
+    } else {
+      ignored.add(alias);
+    }
+  }
+  emojisContent.writeln('};');
+  File(_emojisFilePath).writeAsStringSync(emojisContent.toString());
+  print(
+    'WARNING: This updates only the LEGACY emoji - to update the active '
+    'emoji recognized by the markdown package, '
+    'execute `update_github_emojis.dart`.',
+  );
+  print(
+    'Wrote data to $_emojisFilePath for $emojiCount emoji, '
+    'ignoring ${ignored.length}: ${ignored.join(', ')}.',
+  );
+}
diff --git a/pkgs/markdown/tool/update_entities.dart b/pkgs/markdown/tool/update_entities.dart
new file mode 100644
index 0000000..2d114bd
--- /dev/null
+++ b/pkgs/markdown/tool/update_entities.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+import 'package:path/path.dart' as p;
+
+/// Generates and updates HTML entities.
+void main() {
+  // Original file: https://html.spec.whatwg.org/entities.json
+  final file = File('${p.current}/tool/entities.json');
+  final json = file.readAsStringSync();
+  final map = Map<String, Map<String, dynamic>>.from(jsonDecode(json) as Map);
+
+  final result = <String, String>{};
+  for (final name in map.keys) {
+    if (name.endsWith(';')) {
+      final value = map[name]!['characters'] as String;
+      result[name] = value;
+    }
+  }
+
+  final outputPath = '${p.current}/lib/src/assets/html_entities.dart';
+  final stringMap = const JsonEncoder.withIndent('  ')
+      .convert(result)
+      .replaceAll(r'"$"', r'r"$"')
+      .replaceAll(r'"\\"', r'r"\"');
+  final output = '''
+// Generated file. do not edit.
+//
+// Source: tool/entities.json
+// Script: tool/update_entities.dart
+// ignore_for_file: prefer_single_quotes
+
+const htmlEntitiesMap = $stringMap;
+''';
+  File(outputPath).writeAsStringSync(output);
+}
diff --git a/pkgs/markdown/tool/update_github_emojis.dart b/pkgs/markdown/tool/update_github_emojis.dart
new file mode 100644
index 0000000..fb07ac5
--- /dev/null
+++ b/pkgs/markdown/tool/update_github_emojis.dart
@@ -0,0 +1,348 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:markdown/src/legacy_emojis.dart' as legacy;
+
+import 'update_shared.dart';
+
+/// Regular expression to parse unicode from GitHub emoji API output filenames.
+RegExp gitHubEmojiUnicodeFromFilenamePattern =
+    RegExp(r'.*unicode\/([A-Fa-f0-9\-]+)\.png');
+
+/// URL for GitHub's emoji API.  We reconcile with our legacy emoji so that
+/// we don't change or break anything.
+/// There are essentially only TWO (2) emoji that change and the
+/// legacy emoji is still available with an alternate name.
+/// The 'beetle' emoji changes from `🐞` to `🪲`,
+/// legacy available as 'lady_beetle'.
+/// The 'cricket' emoji changes from `🏏` to `🦗`,
+/// legacy available as 'cricket_game'.
+/// (if the -g flag us used to force using the GitHub Unicode sequences for the
+/// emoji then additionally the 'email' emoji changes from '✉️' to '📧').
+const _emojisJsonRawUrl = 'https://api.github.com/emojis';
+const _emojisFilePath = 'lib/src/emojis.dart';
+
+/// Reference to emoji map within legacy_emojis.dart
+const legacyEmojis = legacy.emojis;
+
+/// AUTO GENERATED by `reconcile_emojis.dart` - this only needed to be done ONCE
+/// during the reconciliation process with the legacy emoji.
+/// This array is ONLY USED when the --useGitHubUnicodes option is used to
+/// minimize the visual differences in the output emoji.
+const legacyEmojisUsedVariationModifier = {
+  '263a',
+  '2600',
+  '2601',
+  '2744',
+  '2708',
+  '260e',
+  '2702',
+  '2712',
+  '270f',
+  '2764',
+  'd83c-de37',
+  '2734',
+  '3299',
+  '3297',
+  'd83c-dd70',
+  'd83c-dd71',
+  'd83c-dd7e',
+  '2668',
+  '203c',
+  '2049',
+  '303d',
+  '26a0',
+  '267b',
+  '2747',
+  '2733',
+  '24c2',
+  'd83c-de02',
+  'd83c-dd7f',
+  '23cf',
+  '25b6',
+  '25c0',
+  '27a1',
+  '2b05',
+  '2b06',
+  '2b07',
+  '2197',
+  '2198',
+  '2199',
+  '2196',
+  '2195',
+  '2194',
+  '21aa',
+  '21a9',
+  '2934',
+  '2935',
+  '2139',
+  '3030',
+  '2714',
+  '2716',
+  '00a9',
+  '00ae',
+  '2122',
+  '2611',
+  '25aa',
+  '25ab',
+  '25fc',
+  '25fb',
+  '2660',
+  '2663',
+  '2665',
+  '2666',
+};
+
+/// Special replacement character '�'
+const errorSpecialReplacement = '\u{FFFD}';
+
+const useOfGitHubUnicodeSequencesWarning = '''
+IMPORTANT NOTE: The use of the --useGitHubUnicodes switch will force using
+GitHub Unicode sequences.
+This option is essentially here only for completeness, not for
+release use.
+The slight visual differences of some emoji might also be another
+reason using --useGitHubUnicodes should be considered a *Breaking Change*.
+
+Some test will fail because of the different Unicode sequences
+and the emojis.unit file would need to be updated to contain the new
+expected GitHub versions of the Unicode sequences of the emoji in order
+for the tests to pass.
+''';
+
+/// The GitHub API URL will return a JSON map of all emoji in the form of
+/// `{ 'shortcode':'emojifilename' ... }`.
+/// The filenames are simply a list of all of the hex string of the
+/// *essential* Unicode codepoints representing the emoji.
+/// These sequences exclude the Unicode join zero width (0x200D) and
+/// variation select (0xFE0F) modifiers. (We will need to add these in to
+/// build our actually Unicode strings representing the emoji).
+/// Multiple Unicode codepoints are separated by '-'.
+/// Examples filenames (single and double code point examples):
+///  - "https://github.githubassets.com/images/icons/emoji/unicode/1f643.png?v8"
+///  - "https://github.githubassets.com/images/icons/emoji/unicode/1f1fa-1f1fe.png?v8"
+///  - "https://github.githubassets.com/images/icons/emoji/unicode/1f469-1f469-1f467-1f466.png?v8"
+/// NOTE: Some filenames will be GitHub 'custom' emoji that have
+/// no Unicode equivalent and these will not have hex codepoints,
+/// only the GitHub custom name.
+/// We will ignore these (there are only a 19 and they are mostly pixel art
+/// from the old Doom game).
+/// Example GitHub custom emoji filename:
+///  - "https://github.githubassets.com/images/icons/emoji/godmode.png?v8",
+String parseGitHubFilenameIntoUnicodeString(String emojiFilename) {
+  const variationSelector = 0xFE0F;
+  const zeroWidthJoiner = 0x200D;
+
+  try {
+    final rawHexList = gitHubEmojiUnicodeFromFilenamePattern
+        .firstMatch(emojiFilename)
+        ?.group(1);
+    if (rawHexList == null) {
+      // This is a GitHub custom emoji and it is represented by a PNG image only
+      // and there is no equivalent Unicode. We have to ignore.
+      return '';
+    }
+    var legacyUsedVariationCode = false;
+    if (legacyEmojisUsedVariationModifier.contains(rawHexList)) {
+      legacyUsedVariationCode = true;
+    }
+    final rawCodePointsHex = rawHexList
+        .split('-')
+        .map((hexstr) => int.parse(hexstr, radix: 16))
+        .toList();
+    final codePointsHex = <int>[];
+
+    if (legacyUsedVariationCode) {
+      // Just add single variation selector.
+      codePointsHex.addAll(rawCodePointsHex);
+      codePointsHex.add(variationSelector);
+    } else {
+      // Now insert the join zero width and
+      // variation select modifying Unicode chars.
+      for (var i = 0; i < rawCodePointsHex.length; i++) {
+        final codePointAtIndex = rawCodePointsHex[i];
+        codePointsHex.add(codePointAtIndex);
+        if (i < (rawCodePointsHex.length - 1)) {
+          codePointsHex.add(variationSelector);
+          // # and 0-9 don't use Zero Width Joiner.
+          if (codePointAtIndex == 0x23 ||
+              (codePointAtIndex >= 0x30 && codePointAtIndex <= 0x39)) {
+            // Don't add Zero Width Joiner.
+          } else {
+            codePointsHex.add(zeroWidthJoiner);
+          }
+        }
+      }
+    }
+    return String.fromCharCodes(codePointsHex);
+  } catch (e) {
+    print(
+        'Invalid/Non-Conformant emoji filename encountered "$emojiFilename"!');
+    return errorSpecialReplacement;
+  }
+}
+
+Future<void> main(List<String> args) async {
+  final parser = ArgParser()
+    ..addFlag('help',
+        abbr: 'h', negatable: false, help: 'Print help text and exit.')
+    ..addFlag('useGitHubUnicodes',
+        abbr: 'g',
+        negatable: false,
+        help: 'Use the GitHub Unicode sequences instead of legacy sequences.')
+    ..addFlag('visualizeDifferentUnicodes',
+        abbr: 'v',
+        negatable: false,
+        help: 'Visualize any Unicode sequence differences.')
+    ..addOption('dumpMarkdownShortCodes',
+        abbr: 's',
+        defaultsTo: 'missing',
+        allowed: ['plain', 'tooltip'],
+        allowedHelp: {
+          'plain': 'just shortcode',
+          'tooltip':
+              '(shortcode with a link to provide emoji name in tooltips)',
+        },
+        help: 'Outputs all emoji shortcodes to stdout which can be used '
+            'in markdown to show and tests all emoji.');
+  late final ArgResults results;
+
+  try {
+    results = parser.parse(args);
+  } catch (e) {
+    print(e);
+    printUsage(parser);
+    return;
+  }
+
+  if (results['help'] as bool) {
+    printUsage(parser);
+    return;
+  }
+
+  var totalEmojiWithDifferentUnicodeSequences = 0;
+  final useLegacyUnicodeSequences = !(results['useGitHubUnicodes'] as bool);
+  final visualizeUnicodeDiffs = results['visualizeDifferentUnicodes'] as bool;
+
+  final shortCodes =
+      (results['dumpMarkdownShortCodes'] as String).toLowerCase();
+  final dumpMarkdownShortCodes = shortCodes == 'plain';
+  final dumpMarkdownToolTipShortCodes = shortCodes == 'tooltip';
+
+  if (!useLegacyUnicodeSequences) {
+    // Issue warning of the implications of using
+    // full GitHub emoji Unicode sequences.
+    print(useOfGitHubUnicodeSequencesWarning);
+  }
+  if (visualizeUnicodeDiffs) {
+    print(
+      'The following emoji have different Unicode sequences '
+      'from those of legacy versions:',
+    );
+  }
+  final shortcodeToEmoji =
+      (await downloadJson(_emojisJsonRawUrl) as Map<String, dynamic>).map(
+    (String alias, dynamic filename) => MapEntry(
+      alias,
+      parseGitHubFilenameIntoUnicodeString(filename as String),
+    ),
+  );
+
+  // Now before we proceed we need to 'mix in' any legacy emoji alias shortcodes
+  // that are missing from the GitHub emoji list.
+  legacyEmojis.forEach((String shortCodeAlias, String emojiUnicode) {
+    if (!shortcodeToEmoji.containsKey(shortCodeAlias)) {
+      shortcodeToEmoji[shortCodeAlias] = emojiUnicode;
+    }
+  });
+
+  final emojisContent = StringBuffer('''
+// GENERATED FILE. DO NOT EDIT.
+//
+// This file was generated from GitHub's emoji API list endpoint:
+// $_emojisJsonRawUrl
+// at ${DateTime.now()} by the script, tool/update_github_emojis.dart.
+
+''');
+  emojisContent.writeln('const emojis = <String, String>{');
+  var emojiCount = 0;
+  final ignored = <String>[];
+  final errored = <String>[];
+  // Dump in sorted order now to facilitate comparison with new GitHub emoji.
+  final sortedKeys = shortcodeToEmoji.keys.toList()..sort();
+  for (final shortCodeAlias in sortedKeys) {
+    var emojiUnicode = shortcodeToEmoji[shortCodeAlias]!;
+    if (useLegacyUnicodeSequences &&
+        legacyEmojis.containsKey(shortCodeAlias) &&
+        shortCodeAlias != 'cricket' &&
+        shortCodeAlias != 'beetle') {
+      emojiUnicode = legacyEmojis[
+          shortCodeAlias]!; // Use legacy Unicode string if available.
+    }
+    if (legacyEmojis.containsKey(shortCodeAlias) &&
+        emojiUnicode != legacyEmojis[shortCodeAlias]) {
+      totalEmojiWithDifferentUnicodeSequences++;
+      if (visualizeUnicodeDiffs) {
+        print(
+          '$emojiUnicode was ${legacyEmojis[shortCodeAlias]} '
+          ':$shortCodeAlias:',
+        );
+      }
+    }
+    if (emojiUnicode != errorSpecialReplacement && emojiUnicode.isNotEmpty) {
+      emojisContent.writeln("  '$shortCodeAlias': '$emojiUnicode',");
+      if (dumpMarkdownShortCodes) {
+        print(':$shortCodeAlias:');
+      } else if (dumpMarkdownToolTipShortCodes) {
+        print('[:$shortCodeAlias:](## "&colon;$shortCodeAlias&colon; emoji")');
+      }
+      emojiCount++;
+    } else {
+      if (emojiUnicode == errorSpecialReplacement) {
+        errored.add(shortCodeAlias);
+      } else {
+        ignored.add(shortCodeAlias);
+      }
+    }
+  }
+  emojisContent.writeln('};');
+  File(_emojisFilePath).writeAsStringSync(emojisContent.toString());
+
+  if (dumpMarkdownShortCodes) {
+    // We are outputing the markdown to stdout, and presumably it
+    // is being captured, so we exit now to exclude the summary
+    // report from being included in the emoji markdown we have
+    // been outputing.
+    return;
+  }
+
+  print('''Wrote data to $_emojisFilePath for $emojiCount emoji,
+$totalEmojiWithDifferentUnicodeSequences emoji's Unicode sequences differ from legacy versions${!visualizeUnicodeDiffs ? " (run with -v flag to visualize)" : ""},
+ignoring ${ignored.length}: ${ignored.join(', ')},
+errored: ${errored.length} ${errored.join(', ')}.''');
+}
+
+void printUsage(ArgParser parser) {
+  print('''Usage: update_emojis.dart [--useGitHubUnicodes | -l]
+
+By default, the legacy Unicode sequences are used (for
+maximum visual compatability with the legacy emoji).
+The --useGitHubUnicodes flag can be used so that the 
+Unicode sequences from GitHub are used for emoji's that
+existed within the legacy set.  This will result in very slight visual
+differences for some emoji, but it will result in many more
+binary differences when comparing legacy_emoji.dart to emoji.dart.
+$useOfGitHubUnicodeSequencesWarning
+
+The --visualizeDifferentUnicodes flag can be used to visually
+verify that any different Unicode sequences produce the same
+emoji.
+
+${parser.usage}
+''');
+}
diff --git a/pkgs/markdown/tool/update_shared.dart b/pkgs/markdown/tool/update_shared.dart
new file mode 100644
index 0000000..6992cd5
--- /dev/null
+++ b/pkgs/markdown/tool/update_shared.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+
+Future<Object?> downloadJson(String uri) async {
+  final client = HttpClient();
+  try {
+    final request = await client.getUrl(Uri.parse(uri));
+    final response = await request.close();
+
+    return response
+        .transform(utf8.decoder)
+        .transform(const JsonDecoder())
+        .single;
+  } finally {
+    client.close();
+  }
+}