Rework Markdown parsing (#719)
authorginnyTheCat <ginnythecat@lelux.net>
Sun, 21 Aug 2022 14:04:09 +0000 (16:04 +0200)
committerGitHub <noreply@github.com>
Sun, 21 Aug 2022 14:04:09 +0000 (19:34 +0530)
* Switch markdown parser

* Add inline maths

* Basic plain text rendering

* Add display math support

* Remove unnecessary <p> tag

* Fixed spoiler not working

* Add spoiler reason input support

* Make paragraphs display with newline in between

* Handle single newlines

* Fix typo when allowing start attribute

* Cleanup for merge

* Remove unused import

package-lock.json
package.json
src/app/molecules/message/Message.scss
src/client/state/RoomsInput.js
src/util/markdown.js
src/util/sanitize.js

index 6994fe8a7b06bcf7810e0709bcc0d7cc240e3070..5c2db9d38e24a6d51bf712cd41c168c01ebfd5ac 100644 (file)
@@ -11,6 +11,7 @@
       "dependencies": {
         "@fontsource/inter": "^4.5.12",
         "@fontsource/roboto": "^4.5.8",
+        "@khanacademy/simple-markdown": "^0.8.3",
         "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
         "@tippyjs/react": "^4.2.6",
         "babel-polyfill": "^6.26.0",
         "linkify-html": "^4.0.0-beta.5",
         "linkifyjs": "^4.0.0-beta.5",
         "matrix-js-sdk": "^19.2.0",
-        "micromark": "^3.0.10",
-        "micromark-extension-gfm": "^2.0.1",
-        "micromark-extension-math": "^2.0.2",
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-symbol": "^1.0.1",
         "prop-types": "^15.8.1",
         "react": "^17.0.2",
         "react-autosize-textarea": "^7.1.0",
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "node_modules/@khanacademy/simple-markdown": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/@khanacademy/simple-markdown/-/simple-markdown-0.8.3.tgz",
+      "integrity": "sha512-mPK4PkGHDoue+pVA5HPIPyZa3iB8TwdAKEcoQWWQQueyWMsetaVM1L0QeFeuvYMqV+YdTAdUxTlLtibYhkwZig==",
+      "dependencies": {
+        "@types/react": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "react": "16.14.0",
+        "react-dom": "16.14.0"
+      }
+    },
     "node_modules/@leichtgewicht/ip-codec": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz",
         "@types/node": "*"
       }
     },
-    "node_modules/@types/debug": {
-      "version": "4.1.7",
-      "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
-      "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==",
-      "dependencies": {
-        "@types/ms": "*"
-      }
-    },
     "node_modules/@types/eslint": {
       "version": "8.4.1",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz",
       "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
       "dev": true
     },
-    "node_modules/@types/katex": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz",
-      "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg=="
-    },
     "node_modules/@types/mime": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
       "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
       "dev": true
     },
-    "node_modules/@types/ms": {
-      "version": "0.7.31",
-      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
-      "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
-    },
     "node_modules/@types/node": {
       "version": "16.11.6",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
       "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==",
       "devOptional": true
     },
+    "node_modules/@types/prop-types": {
+      "version": "15.7.5",
+      "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+      "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+    },
     "node_modules/@types/qs": {
       "version": "6.9.7",
       "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
       "dev": true
     },
+    "node_modules/@types/react": {
+      "version": "18.0.15",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
+      "integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
+      "dependencies": {
+        "@types/prop-types": "*",
+        "@types/scheduler": "*",
+        "csstype": "^3.0.2"
+      }
+    },
     "node_modules/@types/retry": {
       "version": "0.12.1",
       "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
       "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g=="
     },
+    "node_modules/@types/scheduler": {
+      "version": "0.16.2",
+      "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
+    },
     "node_modules/@types/serve-index": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
       "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.1",
         "json-schema-traverse": "^1.0.0",
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
       "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/ajv-keywords": {
       "version": "3.5.2",
         "node": ">=4"
       }
     },
-    "node_modules/character-entities": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.0.tgz",
-      "integrity": "sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
-    "node_modules/character-entities-legacy": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-2.0.0.tgz",
-      "integrity": "sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
-    "node_modules/character-reference-invalid": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
-      "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/chokidar": {
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
         "node": ">=8.0.0"
       }
     },
+    "node_modules/csstype": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+    },
     "node_modules/damerau-levenshtein": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
       "version": "4.3.2",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
       "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "dev": true,
       "dependencies": {
         "ms": "2.1.2"
       },
         }
       }
     },
-    "node_modules/decode-named-character-reference": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.1.tgz",
-      "integrity": "sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==",
-      "dependencies": {
-        "character-entities": "^2.0.0"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/decompress-response": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
         "node": ">= 0.6"
       }
     },
-    "node_modules/dequal": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
-      "integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==",
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/des.js": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
       "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
       "dev": true
     },
-    "node_modules/diff": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
-      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
-      "engines": {
-        "node": ">=0.3.1"
-      }
-    },
     "node_modules/diffie-hellman": {
       "version": "5.0.3",
       "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
         "node": "*"
       }
     },
-    "node_modules/is-alphabetical": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.0.tgz",
-      "integrity": "sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
-    "node_modules/is-alphanumerical": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz",
-      "integrity": "sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ==",
-      "dependencies": {
-        "is-alphabetical": "^2.0.0",
-        "is-decimal": "^2.0.0"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/is-arguments": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/is-decimal": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.0.tgz",
-      "integrity": "sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/is-docker": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
         "node": ">=0.10.0"
       }
     },
-    "node_modules/is-hexadecimal": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz",
-      "integrity": "sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug==",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/is-nan": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
         "node": ">=0.10.0"
       }
     },
-    "node_modules/kleur": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
-      "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==",
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/klona": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz",
     "node_modules/media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/memfs": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
-      "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
-      "dev": true,
-      "dependencies": {
-        "fs-monkey": "1.0.3"
-      },
-      "engines": {
-        "node": ">= 4.0.0"
-      }
-    },
-    "node_modules/merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
-      "dev": true
-    },
-    "node_modules/merge-stream": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
-      "dev": true
-    },
-    "node_modules/merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/micromark": {
-      "version": "3.0.10",
-      "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.0.10.tgz",
-      "integrity": "sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "@types/debug": "^4.0.0",
-        "debug": "^4.0.0",
-        "decode-named-character-reference": "^1.0.0",
-        "micromark-core-commonmark": "^1.0.1",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-combine-extensions": "^1.0.0",
-        "micromark-util-decode-numeric-character-reference": "^1.0.0",
-        "micromark-util-encode": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-subtokenize": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.1",
-        "uvu": "^0.5.0"
-      }
-    },
-    "node_modules/micromark-core-commonmark": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.4.tgz",
-      "integrity": "sha512-HAtoZisp1M/sQFuw2zoUKGo1pMKod7GSvdM6B2oBU0U2CEN5/C6Tmydmi1rmvEieEhGQsjMyiiSoYgxISNxGFA==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-factory-destination": "^1.0.0",
-        "micromark-factory-label": "^1.0.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-factory-title": "^1.0.0",
-        "micromark-factory-whitespace": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-classify-character": "^1.0.0",
-        "micromark-util-html-tag-name": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-subtokenize": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.1",
-        "parse-entities": "^3.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "node_modules/micromark-extension-gfm": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz",
-      "integrity": "sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==",
-      "dependencies": {
-        "micromark-extension-gfm-autolink-literal": "^1.0.0",
-        "micromark-extension-gfm-footnote": "^1.0.0",
-        "micromark-extension-gfm-strikethrough": "^1.0.0",
-        "micromark-extension-gfm-table": "^1.0.0",
-        "micromark-extension-gfm-tagfilter": "^1.0.0",
-        "micromark-extension-gfm-task-list-item": "^1.0.0",
-        "micromark-util-combine-extensions": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-autolink-literal": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.2.tgz",
-      "integrity": "sha512-z2Asd0v4iV/QoI1l23J1qB6G8IqVWTKmwdlP45YQfdGW47ZzpddyzSxZ78YmlucOLqIbS5H98ekKf9GunFfnLA==",
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-footnote": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.3.tgz",
-      "integrity": "sha512-bn62pC5y39rIo2g1RqZk1NhF7T7cJLuJlbevunQz41U0iPVCdVOFASe5/L1kke+DFKSgfCRhv24+o42cZ1+ADw==",
-      "dependencies": {
-        "micromark-core-commonmark": "^1.0.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-strikethrough": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.3.tgz",
-      "integrity": "sha512-PJKhBNyrNIo694ZQCE/FBBQOQSb6YC0Wi5Sv0OCah5XunnNaYbtak9CSv9/eq4YeFMMyd1jX84IRwUSE+7ioLA==",
-      "dependencies": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-classify-character": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-table": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.3.tgz",
-      "integrity": "sha512-JIfE1DGi64zzOx39/pGg6cZbiaUAF/MXbBLZnVl4aFz6Mja7GYMZjksfTGm9NzbgZkiZvbD77NLPuwGIRcFMjg==",
-      "dependencies": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-tagfilter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.0.tgz",
-      "integrity": "sha512-GGUZhzQrOdHR8RHU2ru6K+4LMlj+pBdNuXRtw5prOflDOk2hHqDB0xEgej1AHJ2VETeycX7tzQh2EmaTUOmSKg==",
-      "dependencies": {
-        "micromark-util-types": "^1.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-gfm-task-list-item": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.2.tgz",
-      "integrity": "sha512-8AZib9xxPtppTKig/d00i9uKi96kVgoqin7+TRtGprDb8uTUrN1ZfJ38ga8yUdmu7EDQxr2xH8ltZdbCcmdshg==",
-      "dependencies": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-math": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.0.2.tgz",
-      "integrity": "sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/katex": "^0.11.0",
-        "katex": "^0.13.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/unified"
-      }
-    },
-    "node_modules/micromark-extension-math/node_modules/katex": {
-      "version": "0.13.24",
-      "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.24.tgz",
-      "integrity": "sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==",
-      "funding": [
-        "https://opencollective.com/katex",
-        "https://github.com/sponsors/katex"
-      ],
-      "dependencies": {
-        "commander": "^8.0.0"
-      },
-      "bin": {
-        "katex": "cli.js"
-      }
-    },
-    "node_modules/micromark-factory-destination": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz",
-      "integrity": "sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-factory-label": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz",
-      "integrity": "sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "node_modules/micromark-factory-space": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz",
-      "integrity": "sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-factory-title": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz",
-      "integrity": "sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "node_modules/micromark-factory-whitespace": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz",
-      "integrity": "sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-character": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz",
-      "integrity": "sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-chunked": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz",
-      "integrity": "sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-classify-character": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz",
-      "integrity": "sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-combine-extensions": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz",
-      "integrity": "sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-decode-numeric-character-reference": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz",
-      "integrity": "sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-encode": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.0.tgz",
-      "integrity": "sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ]
-    },
-    "node_modules/micromark-util-html-tag-name": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz",
-      "integrity": "sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ]
-    },
-    "node_modules/micromark-util-normalize-identifier": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz",
-      "integrity": "sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-resolve-all": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz",
-      "integrity": "sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-sanitize-uri": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz",
-      "integrity": "sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "dependencies": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-encode": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "node_modules/micromark-util-subtokenize": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz",
-      "integrity": "sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/memfs": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
+      "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
+      "dev": true,
       "dependencies": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
+        "fs-monkey": "1.0.3"
+      },
+      "engines": {
+        "node": ">= 4.0.0"
       }
     },
-    "node_modules/micromark-util-symbol": {
+    "node_modules/merge-descriptors": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz",
-      "integrity": "sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ],
-      "license": "MIT"
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+      "dev": true
     },
-    "node_modules/micromark-util-types": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.1.tgz",
-      "integrity": "sha512-UT0ylWEEy80RFYzK9pEaugTqaxoD/j0Y9WhHpSyitxd99zjoQz7JJ+iKuhPAgOW2MiPSUAx+c09dcqokeyaROA==",
-      "funding": [
-        {
-          "type": "GitHub Sponsors",
-          "url": "https://github.com/sponsors/unifiedjs"
-        },
-        {
-          "type": "OpenCollective",
-          "url": "https://opencollective.com/unified"
-        }
-      ]
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
     },
     "node_modules/micromatch": {
       "version": "4.0.4",
       "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
       "dev": true
     },
-    "node_modules/mri": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
-      "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
     },
     "node_modules/multicast-dns": {
       "version": "7.2.4",
         "xml2js": "^0.4.5"
       }
     },
-    "node_modules/parse-entities": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-3.0.0.tgz",
-      "integrity": "sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ==",
-      "dependencies": {
-        "character-entities": "^2.0.0",
-        "character-entities-legacy": "^2.0.0",
-        "character-reference-invalid": "^2.0.0",
-        "is-alphanumerical": "^2.0.0",
-        "is-decimal": "^2.0.0",
-        "is-hexadecimal": "^2.0.0"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/parse-headers": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz",
         "queue-microtask": "^1.2.2"
       }
     },
-    "node_modules/sade": {
-      "version": "1.7.4",
-      "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz",
-      "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==",
-      "dependencies": {
-        "mri": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
     "node_modules/safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
         "node": ">=0.6"
       }
     },
-    "node_modules/totalist": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/totalist/-/totalist-2.0.0.tgz",
-      "integrity": "sha512-+Y17F0YzxfACxTyjfhnJQEe7afPA0GSpYlFkl2VFMxYP7jshQf9gXV7cH47EfToBumFThfKBvfAcoUn6fdNeRQ==",
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/tough-cookie": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
         "uuid": "bin/uuid"
       }
     },
-    "node_modules/uvu": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.2.tgz",
-      "integrity": "sha512-m2hLe7I2eROhh+tm3WE5cTo/Cv3WQA7Oc9f7JB6uWv+/zVKvfAm53bMyOoGOSZeQ7Ov2Fu9pLhFr7p07bnT20w==",
-      "dependencies": {
-        "dequal": "^2.0.0",
-        "diff": "^5.0.0",
-        "kleur": "^4.0.3",
-        "sade": "^1.7.3",
-        "totalist": "^2.0.0"
-      },
-      "bin": {
-        "uvu": "bin.js"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/v8-compile-cache": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
         "@jridgewell/sourcemap-codec": "^1.4.10"
       }
     },
+    "@khanacademy/simple-markdown": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/@khanacademy/simple-markdown/-/simple-markdown-0.8.3.tgz",
+      "integrity": "sha512-mPK4PkGHDoue+pVA5HPIPyZa3iB8TwdAKEcoQWWQQueyWMsetaVM1L0QeFeuvYMqV+YdTAdUxTlLtibYhkwZig==",
+      "requires": {
+        "@types/react": ">=16.0.0"
+      }
+    },
     "@leichtgewicht/ip-codec": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz",
         "@types/node": "*"
       }
     },
-    "@types/debug": {
-      "version": "4.1.7",
-      "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
-      "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==",
-      "requires": {
-        "@types/ms": "*"
-      }
-    },
     "@types/eslint": {
       "version": "8.4.1",
       "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz",
       "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
       "dev": true
     },
-    "@types/katex": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.11.1.tgz",
-      "integrity": "sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg=="
-    },
     "@types/mime": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
       "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
       "dev": true
     },
-    "@types/ms": {
-      "version": "0.7.31",
-      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
-      "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
-    },
     "@types/node": {
       "version": "16.11.6",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
       "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==",
       "devOptional": true
     },
+    "@types/prop-types": {
+      "version": "15.7.5",
+      "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+      "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+    },
     "@types/qs": {
       "version": "6.9.7",
       "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
       "dev": true
     },
+    "@types/react": {
+      "version": "18.0.15",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
+      "integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
+      "requires": {
+        "@types/prop-types": "*",
+        "@types/scheduler": "*",
+        "csstype": "^3.0.2"
+      }
+    },
     "@types/retry": {
       "version": "0.12.1",
       "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
       "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g=="
     },
+    "@types/scheduler": {
+      "version": "0.16.2",
+      "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
+    },
     "@types/serve-index": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
       "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
       "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
       "dev": true,
-      "requires": {
-        "ajv": "^8.0.0"
-      },
+      "requires": {},
       "dependencies": {
         "ajv": {
-          "version": "8.9.0",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
+          "version": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
           "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
           "dev": true,
+          "optional": true,
+          "peer": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
             "json-schema-traverse": "^1.0.0",
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
           "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-          "dev": true
+          "dev": true,
+          "optional": true,
+          "peer": true
         }
       }
     },
         "supports-color": "^5.3.0"
       }
     },
-    "character-entities": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.0.tgz",
-      "integrity": "sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA=="
-    },
-    "character-entities-legacy": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-2.0.0.tgz",
-      "integrity": "sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA=="
-    },
-    "character-reference-invalid": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
-      "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="
-    },
     "chokidar": {
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
         "css-tree": "^1.1.2"
       }
     },
+    "csstype": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+    },
     "damerau-levenshtein": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
       "version": "4.3.2",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
       "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "dev": true,
       "requires": {
         "ms": "2.1.2"
       }
     },
-    "decode-named-character-reference": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.1.tgz",
-      "integrity": "sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==",
-      "requires": {
-        "character-entities": "^2.0.0"
-      }
-    },
     "decompress-response": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
       "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
       "dev": true
     },
-    "dequal": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
-      "integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug=="
-    },
     "des.js": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
       "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
       "dev": true
     },
-    "diff": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
-      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w=="
-    },
     "diffie-hellman": {
       "version": "5.0.3",
       "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
       "integrity": "sha1-OzSixI81mXLzUEKEkZOucmS2NWI=",
       "dev": true
     },
-    "is-alphabetical": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.0.tgz",
-      "integrity": "sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w=="
-    },
-    "is-alphanumerical": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz",
-      "integrity": "sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ==",
-      "requires": {
-        "is-alphabetical": "^2.0.0",
-        "is-decimal": "^2.0.0"
-      }
-    },
     "is-arguments": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
         "has-tostringtag": "^1.0.0"
       }
     },
-    "is-decimal": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.0.tgz",
-      "integrity": "sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw=="
-    },
     "is-docker": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
         "is-extglob": "^2.1.1"
       }
     },
-    "is-hexadecimal": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz",
-      "integrity": "sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug=="
-    },
     "is-nan": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
       "dev": true
     },
-    "kleur": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
-      "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA=="
-    },
     "klona": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz",
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
       "dev": true
     },
-    "micromark": {
-      "version": "3.0.10",
-      "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.0.10.tgz",
-      "integrity": "sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==",
-      "requires": {
-        "@types/debug": "^4.0.0",
-        "debug": "^4.0.0",
-        "decode-named-character-reference": "^1.0.0",
-        "micromark-core-commonmark": "^1.0.1",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-combine-extensions": "^1.0.0",
-        "micromark-util-decode-numeric-character-reference": "^1.0.0",
-        "micromark-util-encode": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-subtokenize": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.1",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-core-commonmark": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.4.tgz",
-      "integrity": "sha512-HAtoZisp1M/sQFuw2zoUKGo1pMKod7GSvdM6B2oBU0U2CEN5/C6Tmydmi1rmvEieEhGQsjMyiiSoYgxISNxGFA==",
-      "requires": {
-        "micromark-factory-destination": "^1.0.0",
-        "micromark-factory-label": "^1.0.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-factory-title": "^1.0.0",
-        "micromark-factory-whitespace": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-classify-character": "^1.0.0",
-        "micromark-util-html-tag-name": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-subtokenize": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.1",
-        "parse-entities": "^3.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-gfm": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz",
-      "integrity": "sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==",
-      "requires": {
-        "micromark-extension-gfm-autolink-literal": "^1.0.0",
-        "micromark-extension-gfm-footnote": "^1.0.0",
-        "micromark-extension-gfm-strikethrough": "^1.0.0",
-        "micromark-extension-gfm-table": "^1.0.0",
-        "micromark-extension-gfm-tagfilter": "^1.0.0",
-        "micromark-extension-gfm-task-list-item": "^1.0.0",
-        "micromark-util-combine-extensions": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-extension-gfm-autolink-literal": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.2.tgz",
-      "integrity": "sha512-z2Asd0v4iV/QoI1l23J1qB6G8IqVWTKmwdlP45YQfdGW47ZzpddyzSxZ78YmlucOLqIbS5H98ekKf9GunFfnLA==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-gfm-footnote": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.3.tgz",
-      "integrity": "sha512-bn62pC5y39rIo2g1RqZk1NhF7T7cJLuJlbevunQz41U0iPVCdVOFASe5/L1kke+DFKSgfCRhv24+o42cZ1+ADw==",
-      "requires": {
-        "micromark-core-commonmark": "^1.0.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-normalize-identifier": "^1.0.0",
-        "micromark-util-sanitize-uri": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-gfm-strikethrough": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.3.tgz",
-      "integrity": "sha512-PJKhBNyrNIo694ZQCE/FBBQOQSb6YC0Wi5Sv0OCah5XunnNaYbtak9CSv9/eq4YeFMMyd1jX84IRwUSE+7ioLA==",
-      "requires": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-classify-character": "^1.0.0",
-        "micromark-util-resolve-all": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-gfm-table": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.3.tgz",
-      "integrity": "sha512-JIfE1DGi64zzOx39/pGg6cZbiaUAF/MXbBLZnVl4aFz6Mja7GYMZjksfTGm9NzbgZkiZvbD77NLPuwGIRcFMjg==",
-      "requires": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-gfm-tagfilter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.0.tgz",
-      "integrity": "sha512-GGUZhzQrOdHR8RHU2ru6K+4LMlj+pBdNuXRtw5prOflDOk2hHqDB0xEgej1AHJ2VETeycX7tzQh2EmaTUOmSKg==",
-      "requires": {
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-extension-gfm-task-list-item": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.2.tgz",
-      "integrity": "sha512-8AZib9xxPtppTKig/d00i9uKi96kVgoqin7+TRtGprDb8uTUrN1ZfJ38ga8yUdmu7EDQxr2xH8ltZdbCcmdshg==",
-      "requires": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-extension-math": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.0.2.tgz",
-      "integrity": "sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA==",
-      "requires": {
-        "@types/katex": "^0.11.0",
-        "katex": "^0.13.0",
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      },
-      "dependencies": {
-        "katex": {
-          "version": "0.13.24",
-          "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.24.tgz",
-          "integrity": "sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==",
-          "requires": {
-            "commander": "^8.0.0"
-          }
-        }
-      }
-    },
-    "micromark-factory-destination": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz",
-      "integrity": "sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-factory-label": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz",
-      "integrity": "sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-factory-space": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz",
-      "integrity": "sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-factory-title": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz",
-      "integrity": "sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==",
-      "requires": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-factory-whitespace": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz",
-      "integrity": "sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==",
-      "requires": {
-        "micromark-factory-space": "^1.0.0",
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-util-character": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz",
-      "integrity": "sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==",
-      "requires": {
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-util-chunked": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz",
-      "integrity": "sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==",
-      "requires": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "micromark-util-classify-character": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz",
-      "integrity": "sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-util-combine-extensions": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz",
-      "integrity": "sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==",
-      "requires": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-util-decode-numeric-character-reference": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz",
-      "integrity": "sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==",
-      "requires": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "micromark-util-encode": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.0.tgz",
-      "integrity": "sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg=="
-    },
-    "micromark-util-html-tag-name": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz",
-      "integrity": "sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g=="
-    },
-    "micromark-util-normalize-identifier": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz",
-      "integrity": "sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==",
-      "requires": {
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "micromark-util-resolve-all": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz",
-      "integrity": "sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==",
-      "requires": {
-        "micromark-util-types": "^1.0.0"
-      }
-    },
-    "micromark-util-sanitize-uri": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz",
-      "integrity": "sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==",
-      "requires": {
-        "micromark-util-character": "^1.0.0",
-        "micromark-util-encode": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0"
-      }
-    },
-    "micromark-util-subtokenize": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz",
-      "integrity": "sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==",
-      "requires": {
-        "micromark-util-chunked": "^1.0.0",
-        "micromark-util-symbol": "^1.0.0",
-        "micromark-util-types": "^1.0.0",
-        "uvu": "^0.5.0"
-      }
-    },
-    "micromark-util-symbol": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz",
-      "integrity": "sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ=="
-    },
-    "micromark-util-types": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.1.tgz",
-      "integrity": "sha512-UT0ylWEEy80RFYzK9pEaugTqaxoD/j0Y9WhHpSyitxd99zjoQz7JJ+iKuhPAgOW2MiPSUAx+c09dcqokeyaROA=="
-    },
     "micromatch": {
       "version": "4.0.4",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
       "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
       "dev": true
     },
-    "mri": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
-      "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
-    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
     },
     "multicast-dns": {
       "version": "7.2.4",
         "xml2js": "^0.4.5"
       }
     },
-    "parse-entities": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-3.0.0.tgz",
-      "integrity": "sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ==",
-      "requires": {
-        "character-entities": "^2.0.0",
-        "character-entities-legacy": "^2.0.0",
-        "character-reference-invalid": "^2.0.0",
-        "is-alphanumerical": "^2.0.0",
-        "is-decimal": "^2.0.0",
-        "is-hexadecimal": "^2.0.0"
-      }
-    },
     "parse-headers": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz",
         "queue-microtask": "^1.2.2"
       }
     },
-    "sade": {
-      "version": "1.7.4",
-      "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz",
-      "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==",
-      "requires": {
-        "mri": "^1.1.0"
-      }
-    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
       "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
       "dev": true
     },
-    "totalist": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/totalist/-/totalist-2.0.0.tgz",
-      "integrity": "sha512-+Y17F0YzxfACxTyjfhnJQEe7afPA0GSpYlFkl2VFMxYP7jshQf9gXV7cH47EfToBumFThfKBvfAcoUn6fdNeRQ=="
-    },
     "tough-cookie": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
     },
-    "uvu": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.2.tgz",
-      "integrity": "sha512-m2hLe7I2eROhh+tm3WE5cTo/Cv3WQA7Oc9f7JB6uWv+/zVKvfAm53bMyOoGOSZeQ7Ov2Fu9pLhFr7p07bnT20w==",
-      "requires": {
-        "dequal": "^2.0.0",
-        "diff": "^5.0.0",
-        "kleur": "^4.0.3",
-        "sade": "^1.7.3",
-        "totalist": "^2.0.0"
-      }
-    },
     "v8-compile-cache": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
index 1d30d928b5b3e01ae8d63383db6a1989d4171e07..63e46a64b6eb1d02304359d50e9aec7e0797366a 100644 (file)
@@ -17,6 +17,7 @@
   "dependencies": {
     "@fontsource/inter": "^4.5.12",
     "@fontsource/roboto": "^4.5.8",
+    "@khanacademy/simple-markdown": "^0.8.3",
     "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
     "@tippyjs/react": "^4.2.6",
     "babel-polyfill": "^6.26.0",
     "linkify-html": "^4.0.0-beta.5",
     "linkifyjs": "^4.0.0-beta.5",
     "matrix-js-sdk": "^19.2.0",
-    "micromark": "^3.0.10",
-    "micromark-extension-gfm": "^2.0.1",
-    "micromark-extension-math": "^2.0.2",
-    "micromark-util-chunked": "^1.0.0",
-    "micromark-util-resolve-all": "^1.0.0",
-    "micromark-util-symbol": "^1.0.1",
     "prop-types": "^15.8.1",
     "react": "^17.0.2",
     "react-autosize-textarea": "^7.1.0",
index 155126412e26f5d1b36724217462e0a0e3eb0388..47338d2b0c88eeb6a36d8165c575bb48a8bb7265 100644 (file)
@@ -15,7 +15,7 @@
       display: flex;
     }
   }
-  
+
   &__avatar-container {
     padding-top: 6px;
     @include dir.side(margin, 0, var(--sp-tight));
   }
 }
 
-
 .message__header {
   display: flex;
   align-items: baseline;
       @extend .cp-txt__ellipsis;
       color: inherit;
     }
-    & > span:last-child { display: none; }
+    & > span:last-child {
+      display: none;
+    }
     &:hover {
-      & > span:first-child { display: none; }
-      & > span:last-child { display: block; }
+      & > span:first-child {
+        display: none;
+      }
+      & > span:last-child {
+        display: block;
+      }
     }
   }
 
   & > .text > a {
     white-space: initial !important;
   }
-  
+
+  & p:not(:last-child) {
+    margin-bottom: var(--sp-normal);
+  }
+
   & span[data-mx-pill] {
     background-color: hsla(0, 0%, 64%, 0.15);
     padding: 0 2px;
   & span[data-mx-spoiler] {
     border-radius: 4px;
     background-color: rgba(124, 124, 124, 0.5);
-    color:transparent;
+    color: transparent;
     cursor: pointer;
     -webkit-touch-callout: none;
     -webkit-user-select: none;
   }
   &-count {
     margin: 0 var(--sp-ultra-tight);
-    color: var(--tc-surface-normal)
+    color: var(--tc-surface-normal);
   }
-  &-tooltip .react-emoji  {
+  &-tooltip .react-emoji {
     width: 16px;
     height: 16px;
     margin: 0 var(--sp-ultra-tight);
     }
   }
   &:active {
-    background-color: var(--bg-surface-active)
+    background-color: var(--bg-surface-active);
   }
 
   &--active {
     background-color: var(--bg-caution-active);
-    
+
     @media (hover: hover) {
       &:hover {
         background-color: var(--bg-caution-hover);
       }
     }
     &:active {
-      background-color: var(--bg-caution-active)
+      background-color: var(--bg-caution-active);
     }
   }
 }
 
 // markdown formating
 .message__body {
-  & h1, h2, h3, h4, h5, h6 {
+  & h1,
+  h2,
+  h3,
+  h4,
+  h5,
+  h6 {
     margin: 0;
     margin-bottom: var(--sp-ultra-tight);
     font-weight: var(--fw-medium);
     @include scrollbar.scroll__h;
     @include scrollbar.scroll--auto-hide;
 
-    & td, & th {
+    & td,
+    & th {
       padding: var(--sp-extra-tight);
       border: 1px solid var(--bg-surface-border);
       border-width: 0 1px 1px 0;
       &:last-child {
         border-width: 0;
         border-bottom-width: 1px;
-        [dir=rtl] & {
+        [dir='rtl'] & {
           border-width: 0 1px 1px 0;
         }
       }
-      [dir=rtl] &:first-child {
+      [dir='rtl'] &:first-child {
         border-width: 0;
         border-bottom-width: 1px;
       }
index 9b6628804a693e804293161f4c3cf40edac069fb..03dd074515f8a5e3244f3b2d4eff73e5e3a7acf1 100644 (file)
@@ -1,15 +1,12 @@
 import EventEmitter from 'events';
-import { micromark } from 'micromark';
-import { gfm, gfmHtml } from 'micromark-extension-gfm';
 import encrypt from 'browser-encrypt-attachment';
-import { math } from 'micromark-extension-math';
 import { encode } from 'blurhash';
 import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
-import { mathExtensionHtml, spoilerExtension, spoilerExtensionHtml } from '../../util/markdown';
 import { getBlobSafeMimeType } from '../../util/mimetypes';
 import { sanitizeText } from '../../util/sanitize';
 import cons from './cons';
 import settings from './settings';
+import { htmlOutput, parser } from '../../util/markdown';
 
 const blurhashField = 'xyz.amorgan.blurhash';
 const MXID_REGEX = /\B@\S+:\S+\.\S+[^.,:;?!\s]/g;
@@ -104,14 +101,11 @@ function getVideoThumbnail(video, width, height, mimeType) {
 }
 
 function getFormattedBody(markdown) {
-  const result = micromark(markdown, {
-    extensions: [gfm(), spoilerExtension(), math()],
-    htmlExtensions: [gfmHtml(), spoilerExtensionHtml, mathExtensionHtml],
-  });
-  const bodyParts = result.match(/^(<p>)(.*)(<\/p>)$/);
-  if (bodyParts === null) return result;
-  if (bodyParts[2].indexOf('</p>') >= 0) return result;
-  return bodyParts[2];
+  let content = parser(markdown);
+  if (content.length === 1 && content[0].type === 'paragraph') {
+    content = content[0].content;
+  }
+  return htmlOutput(content);
 }
 
 function getReplyFormattedBody(roomId, reply) {
index 2ce613b0443dde058c57e020ccff99762f1bc535..2e4f53d000976703dfec582d577d688f6a127edc 100644 (file)
-/* eslint-disable no-param-reassign */
-/* eslint-disable no-plusplus */
-/* eslint-disable no-continue */
+import SimpleMarkdown from '@khanacademy/simple-markdown';
 
-import { codes } from 'micromark-util-symbol/codes';
-import { types } from 'micromark-util-symbol/types';
-import { resolveAll } from 'micromark-util-resolve-all';
-import { splice } from 'micromark-util-chunked';
+const {
+  defaultRules, parserFor, outputFor, anyScopeRegex, blockRegex, inlineRegex, htmlTag, sanitizeText,
+} = SimpleMarkdown;
 
-function inlineExtension(marker, len, key) {
-  const keySeq = `${key}Sequence`;
-  const keySeqTmp = `${keySeq}Temporary`;
-
-  return () => {
-    function tokenize(effects, ok, nok) {
-      const { previous, events } = this;
-
-      let size = 0;
-
-      function more(code) {
-        // consume more markers if the maximum length hasn't been reached yet
-        if (code === marker && size < len) {
-          effects.consume(code);
-          size += 1;
-          return more;
-        }
-
-        // check for minimum length
-        if (size < len) return nok(code);
-
-        effects.exit(keySeqTmp);
-        return ok(code);
-      }
-
-      function start(code) {
-        // ignore code if it's not a marker
-        if (code !== marker) return nok(code);
-
-        if (previous === marker
-            && events[events.length - 1][1].type !== types.characterEscape) return nok(code);
-
-        effects.enter(keySeqTmp);
-        return more(code);
-      }
-
-      return start;
-    }
-
-    function resolve(events, context) {
-      let i = -1;
-
-      while (++i < events.length) {
-        if (events[i][0] !== 'enter' || events[i][1].type !== keySeqTmp) continue;
-
-        let open = i;
-        while (open--) {
-          if (events[open][0] !== 'exit' || events[open][1].type !== keySeqTmp) continue;
-
-          events[i][1].type = keySeq;
-          events[open][1].type = keySeq;
-
-          const border = {
-            type: key,
-            start: { ...events[open][1].start },
-            end: { ...events[i][1].end },
-          };
-
-          const text = {
-            type: `${key}Text`,
-            start: { ...events[open][1].end },
-            end: { ...events[i][1].start },
-          };
-
-          const nextEvents = [
-            ['enter', border, context],
-            ['enter', events[open][1], context],
-            ['exit', events[open][1], context],
-            ['enter', text, context],
-          ];
-
-          splice(
-            nextEvents,
-            nextEvents.length,
-            0,
-            resolveAll(
-              context.parser.constructs.insideSpan.null,
-              events.slice(open + 1, i),
-              context,
-            ),
-          );
-
-          splice(nextEvents, nextEvents.length, 0, [
-            ['exit', text, context],
-            ['enter', events[i][1], context],
-            ['exit', events[i][1], context],
-            ['exit', border, context],
-          ]);
-
-          splice(events, open - 1, i - open + 3, nextEvents);
-
-          i = open + nextEvents.length - 2;
-          break;
-        }
-      }
-
-      events.forEach((event) => {
-        if (event[1].type === keySeqTmp) {
-          event[1].type = types.data;
-        }
-      });
-
-      return events;
-    }
-
-    const tokenizer = {
-      tokenize,
-      resolveAll: resolve,
-    };
-
-    return {
-      text: { [marker]: tokenizer },
-      insideSpan: { null: [tokenizer] },
-      attentionMarkers: { null: [marker] },
-    };
-  };
+function mathHtml(wrap, node) {
+  return htmlTag(wrap, htmlTag('code', sanitizeText(node.content)), { 'data-mx-maths': node.content });
 }
 
-const spoilerExtension = inlineExtension(codes.verticalBar, 2, 'spoiler');
-
-const spoilerExtensionHtml = {
-  enter: {
-    spoiler() {
-      this.tag('<span data-mx-spoiler>');
-    },
+const rules = {
+  ...defaultRules,
+  Array: {
+    ...defaultRules.Array,
+    plain: (arr, output, state) => arr.map((node) => output(node, state)).join(''),
   },
-  exit: {
-    spoiler() {
-      this.tag('</span>');
-    },
+  displayMath: {
+    order: defaultRules.list.order + 0.5,
+    match: blockRegex(/^\$\$\n*([\s\S]+?)\n*\$\$/),
+    parse: (capture) => ({ content: capture[1] }),
+    plain: (node) => `$$\n${node.content}\n$$`,
+    html: (node) => mathHtml('div', node),
   },
-};
-
-const mathExtensionHtml = {
-  enter: {
-    mathFlow() {
-      this.lineEndingIfNeeded();
-    },
-    mathFlowFenceMeta() {
-      this.buffer();
-    },
-    mathText() {
-      this.buffer();
-    },
+  newline: {
+    ...defaultRules.newline,
+    plain: () => '\n',
+  },
+  paragraph: {
+    ...defaultRules.paragraph,
+    plain: (node, output, state) => `${output(node.content, state)}\n\n`,
+    html: (node, output, state) => htmlTag('p', output(node.content, state)),
+  },
+  escape: {
+    ...defaultRules.escape,
+    plain: (node, output, state) => `\\${output(node.content, state)}`,
   },
-  exit: {
-    mathFlow() {
-      const value = this.encode(this.resume().replace(/(?:\r?\n|\r)$/, ''));
-      this.tag('<div data-mx-maths="');
-      this.tag(value);
-      this.tag('"><code>');
-      this.raw(value);
-      this.tag('</code></div>');
-      this.setData('mathFlowOpen');
-      this.setData('slurpOneLineEnding');
-    },
-    mathFlowFence() {
-      // After the first fence.
-      if (!this.getData('mathFlowOpen')) {
-        this.setData('mathFlowOpen', true);
-        this.setData('slurpOneLineEnding', true);
-        this.buffer();
-      }
-    },
-    mathFlowFenceMeta() {
-      this.resume();
-    },
-    mathFlowValue(token) {
-      this.raw(this.sliceSerialize(token));
-    },
-    mathText() {
-      const value = this.encode(this.resume());
-      this.tag('<span data-mx-maths="');
-      this.tag(value);
-      this.tag('"><code>');
-      this.raw(value);
-      this.tag('</code></span>');
-    },
-    mathTextData(token) {
-      this.raw(this.sliceSerialize(token));
-    },
+  em: {
+    ...defaultRules.em,
+    plain: (node, output, state) => `_${output(node.content, state)}_`,
+  },
+  strong: {
+    ...defaultRules.strong,
+    plain: (node, output, state) => `**${output(node.content, state)}**`,
+  },
+  u: {
+    ...defaultRules.u,
+    plain: (node, output, state) => `__${output(node.content, state)}__`,
+  },
+  del: {
+    ...defaultRules.del,
+    plain: (node, output, state) => `~~${output(node.content, state)}~~`,
+  },
+  spoiler: {
+    order: defaultRules.em.order - 0.5,
+    match: inlineRegex(/^\|\|([\s\S]+?)\|\|(?:\(([\s\S]+?)\))?/),
+    parse: (capture, parse, state) => ({
+      content: parse(capture[1], state),
+      reason: capture[2],
+    }),
+    plain: (node) => `[spoiler${node.reason ? `: ${node.reason}` : ''}](mxc://somewhere)`,
+    html: (node, output, state) => `<span data-mx-spoiler${node.reason ? `="${sanitizeText(node.reason)}"` : ''}>${output(node.content, state)}</span>`,
+  },
+  inlineMath: {
+    order: defaultRules.del.order + 0.5,
+    match: inlineRegex(/^\$(\S[\s\S]+?\S|\S)\$(?!\d)/),
+    parse: (capture) => ({ content: capture[1] }),
+    plain: (node) => `$${node.content}$`,
+    html: (node) => mathHtml('span', node),
+  },
+  br: {
+    ...defaultRules.br,
+    match: anyScopeRegex(/^ *\n/),
+    plain: () => '\n',
+  },
+  text: {
+    ...defaultRules.text,
+    match: anyScopeRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]| *\n|\w+:\S|$)/),
+    plain: (node) => node.content,
   },
 };
 
+const parser = parserFor(rules);
+
+const plainOutput = outputFor(rules, 'plain');
+const htmlOutput = outputFor(rules, 'html');
+
 export {
-  inlineExtension,
-  spoilerExtension, spoilerExtensionHtml,
-  mathExtensionHtml,
+  parser, plainOutput, htmlOutput,
 };
index 0f88c62b3e46746da1180413391ad9f101a25822..79cc0418383c7c411d334df263408da47a16323c 100644 (file)
@@ -19,7 +19,7 @@ const permittedTagToAttributes = {
   div: ['data-mx-maths'],
   a: ['name', 'target', 'href', 'rel'],
   img: ['width', 'height', 'alt', 'title', 'src', 'data-mx-emoticon'],
-  o: ['start'],
+  ol: ['start'],
   code: ['class'],
 };