{"id":23193956,"url":"https://github.com/evitanrelta/htmlarkdown","last_synced_at":"2025-08-18T20:33:56.438Z","repository":{"id":50490933,"uuid":"519252699","full_name":"EvitanRelta/htmlarkdown","owner":"EvitanRelta","description":"HTML-to-Markdown converter that adaptively preserves HTML when needed (eg. when center-aligning, or resizing images)","archived":false,"fork":false,"pushed_at":"2023-02-19T12:04:26.000Z","size":2104,"stargazers_count":61,"open_issues_count":20,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-08T15:37:46.184Z","etag":null,"topics":["commonmark","converter","gfm","html-converter","html-to-markdown","javascript","node","node-js","nodejs","typescript"],"latest_commit_sha":null,"homepage":"https://evitanrelta.github.io/htmlarkdown","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EvitanRelta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-07-29T14:53:56.000Z","updated_at":"2024-11-01T18:28:12.000Z","dependencies_parsed_at":"2024-01-14T04:40:03.242Z","dependency_job_id":"9dd0f51c-bb22-4676-bdc1-b22c088f2318","html_url":"https://github.com/EvitanRelta/htmlarkdown","commit_stats":{"total_commits":278,"total_committers":1,"mean_commits":278.0,"dds":0.0,"last_synced_commit":"5f06be0fdf11b55ba59e8fb8470a2fa9002a06c1"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvitanRelta%2Fhtmlarkdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvitanRelta%2Fhtmlarkdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvitanRelta%2Fhtmlarkdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvitanRelta%2Fhtmlarkdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EvitanRelta","download_url":"https://codeload.github.com/EvitanRelta/htmlarkdown/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230276333,"owners_count":18201092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonmark","converter","gfm","html-converter","html-to-markdown","javascript","node","node-js","nodejs","typescript"],"created_at":"2024-12-18T13:12:54.705Z","updated_at":"2024-12-18T13:12:55.381Z","avatar_url":"https://github.com/EvitanRelta.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/title_dark.webp\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"./assets/title_light.webp\"\u003e\n    \u003cimg alt=\"HTMLarkdown Title\" src=\"./assets/title_light.webp\" width=\"700\"\u003e\n  \u003c/picture\u003e\n\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Coverage][coverage-badge]][coverage-link]\n[![Version][version-badge]][version-link]\n[![License][license-badge]][license-link]\n\n\u003c/div\u003e\n\n[coverage-badge]: https://badgen.net/codecov/c/github/EvitanRelta/htmlarkdown?color=009900\n[coverage-link]: https://codecov.io/gh/EvitanRelta/htmlarkdown\n[version-badge]: https://badgen.net/github/release/EvitanRelta/htmlarkdown\n[version-link]: https://github.com/EvitanRelta/htmlarkdown/releases/latest\n[license-badge]: https://badgen.net/github/license/EvitanRelta/htmlarkdown\n[license-link]: https://badgen.net/github/license/EvitanRelta/htmlarkdown\n\n\u003cbr\u003e\n\nHTMLarkdown is a **\u003cins\u003eHTML-to-Markdown converter\u003c/ins\u003e** that's able to output HTML-syntax when required.  \nLike when center-aligning, or resizing images:\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/html_switching_dark.gif\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"./assets/html_switching_light.gif\"\u003e\n    \u003cimg alt=\"Switching to HTML showcase\" src=\"./assets/html_switching_light.gif\" width=\"95%\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n- Written completely in \u003cimg height=\"15\" src=\"https://upload.wikimedia.org/wikipedia/commons/4/4c/Typescript_logo_2020.svg\"\u003e **\u003cins\u003eTypeScript\u003c/ins\u003e**.  \n- Has many Jest [tests](./tests), covering many edge-case conversions.\n  \u003e _[Leave a issue/PR](#new-conversions-ideas-features-tests) if you can think of more!_\n- [For now](#other-markdown-specs), is designed for [GFM].\n- Try it out at the demo site below!  \n  https://evitanrelta.github.io/htmlarkdown\n\n[GFM]: https://github.github.com/gfm/\n\n\u003cbr\u003e\n\n# How is this different?\n\n## Switching to HTML-syntax\n\nWhenever elements **\u003cins\u003ecannot be represented\u003c/ins\u003e** in markdown-syntax, HTMLarkdown will **\u003cins\u003eswitch to HTML-syntax\u003c/ins\u003e**:\n\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth width=500\u003eInput HTML\u003c/th\u003e\n            \u003cth width=500\u003eOutput Markdown\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\u0026lt;h1\u003eNormal-heading is \u0026lt;strong\u003eboring\u0026lt;/strong\u003e\u0026lt;/h1\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;h1 align=\"center\"\u003e\n  Centered-heading is \u0026lt;strong\u003eda wae\u0026lt;/strong\u003e\n\u0026lt;/h1\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;p\u003e\u0026lt;img src=\"https://image.src\" /\u003e\u0026lt;/p\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;p\u003e\u0026lt;img width=\"80%\" src=\"https://image.src\" /\u003e\u0026lt;/p\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e# Normal-heading is **boring**\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;h1 align=\"center\"\u003e\n  Centered-heading is \u0026lt;b\u003eda wae\u0026lt;/b\u003e\n\u0026lt;/h1\u003e\n\u003c!-- BLANK_LINE --\u003e\n![](https://image.src)\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;img width=\"80%\" src=\"https://image.src\" /\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003e _**Note:** The HTML-switching is controlled by the rules' `Rule.toUseHtmlPredicate`._\n\n\u003cbr\u003e\n\nBut HTMLarkdown tries to use as **\u003cins\u003elittle HTML-syntax\u003c/ins\u003e** as possible. **\u003cins\u003eMixing markdown and HTML\u003c/ins\u003e** if needed:\n\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth width=500\u003eInput HTML\u003c/th\u003e\n            \u003cth width=500\u003eOutput Markdown\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\u0026lt;blockquote\u003e\n  \u0026lt;p align=\"center\"\u003e\n    Centered-paragraph\n  \u0026lt;/p\u003e\n  \u0026lt;p\u003eBelow is a horizontal-rule in blockquote:\u0026lt;/p\u003e\n  \u0026lt;hr\u003e\n\u0026lt;/blockquote\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\u003e \u0026lt;p align=\"center\"\u003e\n\u003e   Centered-paragraph\n\u003e \u0026lt;/p\u003e\n\u003e Below is a horizontal-rule in blockquote:\n\u003e \n\u003e \u0026lt;hr\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003cbr\u003e\n\nDepending on the situation, HTMLarkdown will switch between markdown's **\u003cins\u003ebackslash-escaping\u003c/ins\u003e** or **\u003cins\u003eHTML-escaping\u003c/ins\u003e**:\n\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth width=500\u003eInput HTML\u003c/th\u003e\n            \u003cth width=500\u003eOutput Markdown\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\u0026lt;!-- In markdown --\u003e\n\u0026lt;p\u003e\u0026amp;lt;TAG\u0026amp;gt;, **NOT BOLD**\u0026lt;/p\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;!-- In in-line HTML --\u003e\n\u0026lt;p\u003e\n  \u0026lt;sup\u003e\u0026amp;lt;TAG\u0026amp;gt;, **NOT BOLD**\u0026lt;/sup\u003e\n\u0026lt;/p\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;!-- In block HTML --\u003e\n\u0026lt;p align=\"center\"\u003e\n  \u0026amp;lt;TAG\u0026amp;gt;, **NOT BOLD**\n\u0026lt;/p\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\\\u0026lt;TAG\u003e, \\*\\*NOT BOLD\\*\\*\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;sup\u003e\\\u0026lt;TAG\u003e, \\*\\*NOT BOLD\\*\\*\u0026lt;/sup\u003e\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;p align=\"center\"\u003e\n  \u0026amp;lt;TAG\u003e, **NOT BOLD**\n\u0026lt;/p\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003cbr\u003e\n\n## Handling of edge cases\n\nAdding separators in-between adjacent lists to prevent them from being combined by markdown-renderers:\n\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth width=500\u003eInput HTML\u003c/th\u003e\n            \u003cth width=500\u003eOutput Markdown\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e\u0026lt;ul\u003e\n  \u0026lt;li\u003eList 1 \u003e item 1\u0026lt;/li\u003e\n  \u0026lt;li\u003eList 1 \u003e item 2\u0026lt;/li\u003e\n\u0026lt;/ul\u003e\n\u0026lt;ul\u003e\n  \u0026lt;li\u003eList 2 \u003e item 1\u0026lt;/li\u003e\n  \u0026lt;li\u003eList 2 \u003e item 2\u0026lt;/li\u003e\n\u0026lt;/ul\u003e\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n\u003cpre lang=\"html\"\u003e\u003ccode\u003e- List 1 \u003e item 1\n- List 1 \u003e item 2\n\u003c!-- BLANK_LINE --\u003e\n\u0026lt;!-- LIST_SEPARATOR --\u003e\n\u003c!-- BLANK_LINE --\u003e\n- List 2 \u003e item 1\n- List 2 \u003e item 2\n\u003c/code\u003e\u003c/pre\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\nAnd more!  \nBut this section is getting too long so...\n\n\u003cbr\u003e\n\n# Installation\n\n```bash\nnpm install htmlarkdown\n```\n\n\u003cbr\u003e\n\n# Usage\n\n## Markdown conversion _(either from `Element` or `string`)_\n\n```js\nimport { HTMLarkdown } from 'htmlarkdown'\n\n/** Convert an element! */\nconst htmlarkdown = new HTMLarkdown()\nconst container = document.getElementById('container')\nconsole.log(container.outerHTML)\n// =\u003e '\u003cdiv id=\"container\"\u003e\u003ch1\u003eHeading\u003c/h1\u003e\u003c/div\u003e'\nhtmlarkdown.convert(container)\n// =\u003e '# Heading'\n\n\n/** \n * Or a HTML string! \n * Whichever u prefer. It's 2022, I don't judge :^)\n */\nconst htmlString = `\n\u003ch1\u003eHeading\u003c/h1\u003e\n\u003cp\u003eParagraph\u003c/p\u003e\n`\nconst htmlStrWithContainer = `\u003cdiv\u003e${htmlString}\u003c/div\u003e`\nhtmlarkdown.convert(htmlString)\n// Set 2nd param 'hasContainer' to true, for container-wrapped string.\nhtmlarkdown.convert(htmlStrWithContainer, true)\n// Both output =\u003e '# Heading\\n\\nParagraph'\n```\n\n\u003e \u003ca id=\"deep-clone\"\u003e\u003c/a\u003e\n\u003e **Note:** If an element is given to `convert`, it's deep-cloned before any processing/conversion.  \n\u003e Thus, you don't have to worry about it mutating the original element :)\n\n\u003cbr\u003e\n\n## Configuring\n\n```js\n/** Configure when creating an instance. */\nconst htmlarkdown = new HTMLarkdown({\n    htmlEscapingMode: '\u0026\u003c\u003e',\n    maxPrettyTableWidth: Number.POSITIVE_INFINITY,\n    addTrailingLinebreak: true\n})\n\n/** Or on an existing instance. */\nhtmlarkdown.options.maxPrettyTableWidth = -1\n```\n\n\u003cbr\u003e\n\n## Plugins\n\nPlugins are of type `(htmlarkdown: HTMLarkdown): void`.  \nThey take in a `HTMLarkdown` instance and configure it by **\u003cins\u003emutating\u003c/ins\u003e** it.\n\nThere's 2 plugin-options available in the `options` object: `preloadPlugins` and `plugins`.  \nThe difference is:\n- `preloadPlugins` loads the plugins **\u003cins\u003efirst\u003c/ins\u003e**, before your other options. _(likes \"presets\")_  \n  Allowing you to overwrite the plugins' changes:\n  ```ts\n  const enableTrailingLinebreak: Plugin = (htmlarkdown) =\u003e {\n      htmlarkdown.options.addTrailingLinebreak = true\n  }\n  const htmlarkdown = new HTMLarkdown({\n      addTrailingLinebreak: false,\n      preloadPlugins: [enableTrailingLinebreak],\n  })\n  htmlarkdown.options.preloadPlugins // false\n  ```\n- `plugins` loads the plugins **\u003cins\u003eafter\u003c/ins\u003e** your other options.  \n  Meaning, plugins can overwrite your options.\n  ```ts\n  const enableTrailingLinebreak: Plugin = (htmlarkdown) =\u003e {\n      htmlarkdown.options.addTrailingLinebreak = true\n  }\n  const htmlarkdown = new HTMLarkdown({\n      addTrailingLinebreak: false,\n      plugins: [enableTrailingLinebreak],\n  })\n  htmlarkdown.options.preloadPlugins // true\n  ```\n\n\u003cbr\u003e\n\nYou can also load plugins on existing instances:\n```js\nhtmlarkdown.loadPlugins([myPlugin])\n```\n\n\u003cbr\u003e\n\n## Making a copy of an instance\n\nThe conversion of a `HTMLarkdown` instance **\u003cins\u003esolely\u003c/ins\u003e** depends on its `options` property.  \nMeaning, you create a copy of an instance like this:\n\n```js\nconst htmlarkdown = new HTMLarkdown()\nconst copy = new HTMLarkdown(htmlarkdown.options)\n```\n\n\u003cbr\u003e\n\n## Configuring rules/processes\n\nSee [this section](#how-it-works) for info on what the rules/processes do.\n\n```js\n/**\n * Overwriting default rules/processes.\n * (does NOT include the defaults)\n */\nconst htmlarkdown = new HTMLarkdown({\n    preProcesses: [myPreProcess1, myPreProcess2],\n    rules: [myRule1, myRule2],\n    textProcesses: [myTextProcess1, myTextProcess2],\n    postProcesses: [myPostProcess1, myPostProcess2]\n})\n\n/**\n * Adding on to default rules/processes.\n * (includes the defaults)\n */\nconst htmlarkdown = new HTMLarkdown()\nhtmlarkdown.addPreProcess(myPreProcess)\nhtmlarkdown.addRule(myRule)\nhtmlarkdown.addTextProcess(myTextProcess)\nhtmlarkdown.addPostProcess(myPostProcess)\n```\n\n\u003cbr\u003e\n\n# How it works\n\nHTMLarkdown has 3 distinct phases:\n\n1. **Pre-processing**  \n   The container-element that's received _(and [deep-cloned](#deep-clone))_ by the `convert` method is passed consecutively to each `PreProcess` in `options.preProcesses`.\n\n2. **Conversion**  \n   The pre-processed container-element is then recursively converted to markdown.  \n   Elements are converted by `Rule` in `options.rules`.  \n   Text-nodes are converted by `TextProcess` in `options.textProcesses`.  \n   The rule/text-process outputs strings are then appended to each other, to give the raw markdown.\n\n3. **Post-processing**  \n   The raw markdown string is then passed consecutively to each `PostProcess` in `options.postProcess`, to give the final markdown.\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/rule_processes_flow_chart_dark.jpg\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"./assets/rule_processes_flow_chart_light.jpg\"\u003e\n    \u003cimg alt=\"Rule-processes flowchart\" src=\"./assets/rule_processes_flow_chart_light.jpg\"\u003e\n  \u003c/picture\u003e\n  \u003cbr\u003e\u003ci\u003e(\u003cb\u003eimage:\u003c/b\u003e the general conversion flow of HTMLarkdown)\u003c/i\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n# Contributing\n\n## Bugs\n\nHTMLarkdown is still under-development, so there'll likely be bugs.\n\nSo the easiest way to contribute is submit an issue _(with the `bug` label)_, especially for any incorrect markdown-conversions :)\n\nFor any incorrect markdown-conversions, state the:\n- input HTML\n- current incorrect markdown output\n- expected markdown output\n\n\u003cbr\u003e\n\n## New conversions, ideas, features, tests\n\nIf you have any new elements-conversions / ideas / features / tests that you think should be added, leave an issue with `feature` or `improve` label!\n\n\u003e - `feature` label is for new features\n\u003e - `improve` label is for improvements on existing features\n\u003e \n\u003e Understandably, there are gray areas on what is a \"feature\" and what is an \"improvement\". So just go with whichever seems more appropriate :)\n\n\u003cbr\u003e\n\n## Other markdown specs\nCurrently, HTMLarkdown has been designed to output markdown for GitHub specifically _(ie. [GFM])_.  \nBUT, if there's another markdown spec. that you'd like to design for _(maybe as a plugin?)_, do leave an issue/discussion :D\n\n[GFM]: https://github.github.com/gfm/\n\n\u003cbr\u003e\n\n## Coding-related stuff\n\nCode-formatting is handled by [Prettier], so no need to worry bout it :)\n\nAny new feature should \n- be documented via TSDoc\n- come with new unit-tests for them\n- and should pass all new/existing tests\n\nAs for which merging method to use, check out the [discussion][merging-discussion].\n\n[merging-discussion]: https://github.com/EvitanRelta/htmlarkdown/discussions/41\n\n\u003cbr\u003e\n\n[Prettier]: https://prettier.io/\n\n\n# Contributors\n\nSo far it's just me, so pls send help! :^)\n\n\u003cbr\u003e\n\n# Roadmap\n\nIf you've any new ideas / features, check out the [Contributing section for it](#new-conversions-ideas-features-tests)!\n\n\u003cbr\u003e\n\n## Element conversions\n\n### Block-elements:\n- [x] Headings _([For now][setext-issue], only [ATX-style][atx])_\n- [x] Paragraph\n- [x] Codeblock\n- [x] Blockquote\n- [x] Lists  \n  _(ordered, unordered, [tight][tight] and [loose][loose])_\n- [x] _([GFM][gfm-table])_ Table\n- [ ] _([GFM][gfm-task-list])_ Task-list\n  \u003cbr\u003e\u003cbr\u003e_(Below are some planned block-elements that don't have markdown-equivalent)_\n- [x] `\u003cspan\u003e` _(handled by a [noop-rule](#noop-rule))_\n- [x] `\u003cdiv\u003e` _([For now][div-noop-issue], handled by a [noop-rule](#noop-rule))_\n- [ ] Definition list _(ie. `\u003cdl\u003e`, `\u003cdt\u003e`, `\u003cdd\u003e`)_\n- [ ] Collapsible section _(ie. `\u003cdetails\u003e`)_\n\n\n[setext-issue]: https://github.com/EvitanRelta/htmlarkdown/issues/36\n[atx]: https://spec.commonmark.org/0.30/#atx-heading\n[div-noop-issue]: https://github.com/EvitanRelta/htmlarkdown/issues/19\n[tight]: https://github.github.com/gfm/#tight\n[loose]: https://github.github.com/gfm/#loose\n[gfm-table]: https://github.github.com/gfm/#tables-extension-\n[gfm-task-list]: https://github.github.com/gfm/#task-list-items-extension-\n\n\u003cbr\u003e\n\n### Text-formattings:\n- [x] **Bold** _([For now][underscore-issue], only outputs in asterisks `**BOLD**`)_\n- [x] _Italic_ _([For now][underscore-issue], only outputs in asterisks `*ITALIC*`)_\n- [x] _([GFM][gfm-strikethrough])_ ~~Strikethrough~~\n- [x] `Code`\n- [x] [Link][secret] _([For now][ref-link-issue], only [inline links][inline-link])_\n- [x] \u003csup\u003eSuperscript\u003c/sup\u003e _(ie. `\u003csup\u003e`)_\n- [x] \u003csub\u003eSubscript\u003c/sub\u003e _(ie. `\u003csub\u003e`)_\n- [x] \u003cins\u003eUnderline\u003c/ins\u003e _(ie. `\u003cu\u003e`, `\u003cins\u003e`)_  \n  _(didn't know underlines possible till recently)_\n\n[underscore-issue]: https://github.com/EvitanRelta/htmlarkdown/issues/39\n[gfm-strikethrough]: https://github.github.com/gfm/#strikethrough-extension-\n[secret]: https://www.youtube.com/watch?v=dQw4w9WgXcQ\n[ref-link-issue]: https://github.com/EvitanRelta/htmlarkdown/issues/38\n[inline-link]: https://spec.commonmark.org/0.30/#inline-link\n\n\u003cbr\u003e\n\nMisc:\n- [x] Images _([For now][ref-link-issue], only [inline links][inline-link])_\n- [x] Horizontal-rule _(ie. `\u003chr\u003e`)_\n- [x] Linebreaks _(ie. `\u003cbrr\u003e`)_\n- [ ] Preserved HTML comments _([Issue \\#25][preserve-comment-issue])_\n  _(eg. `\u003c!-- COMMENT --\u003e`)_\n\n[preserve-comment-issue]: https://github.com/EvitanRelta/htmlarkdown/issues/25\n\n\u003cbr\u003e\n\nFeatures to be added:\n- Custom `id` attributes\n  ```html\n  Go to [section with id](#my-section)\n\n  \u003cp id=\"my-section\"\u003e\n    My section\n  \u003c/p\u003e\n  ```\n- Reversing GitHub's Issue/PR autolinks\n  \u003ctable\u003e\n      \u003cthead\u003e\n          \u003ctr\u003e\n              \u003cth width=500\u003eInput HTML\u003c/th\u003e\n              \u003cth width=500\u003eOutput Markdown\u003c/th\u003e\n          \u003c/tr\u003e\n      \u003c/thead\u003e\n      \u003ctbody\u003e\n          \u003ctr\u003e\n              \u003ctd\u003e\n  \u003cpre lang=\"html\"\u003e\u003ccode\u003e\u0026lt;p\u003e\n    Issue autolink: \n    \u0026lt;a href=\"https://github.com/user/repo/issues/7\"\u003e#7\u0026lt;/a\u003e\n  \u0026lt;/p\u003e\n  \u003c/code\u003e\u003c/pre\u003e\n              \u003c/td\u003e\n              \u003ctd\u003e\n  \u003cpre lang=\"html\"\u003e\u003ccode\u003eIssue autolink: #7\n  \u003c/code\u003e\u003c/pre\u003e\n              \u003c/td\u003e\n          \u003c/tr\u003e\n      \u003c/tbody\u003e\n  \u003c/table\u003e\n- Ability to customise how codeblock's syntax-highlighting langauge is obtained from the `\u003cpre\u003e\u003ccode\u003e` elements\n\n\u003cbr\u003e\n\n\u003cblockquote id=\"noop-rule\"\u003e\n  \u003ccode\u003enoop-rule\u003c/code\u003e: \n  \u003cbr\u003eThey only pass-on their converted inner-contents to their parents.\n  \u003cbr\u003eThey themselves don't have any markdown conversions, not even in HTML-syntax.\n\u003c/blockquote\u003e\n\n\u003cbr\u003e\n\n# License\n\nThe MIT License (MIT).  \nSo it's freeeeeee","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevitanrelta%2Fhtmlarkdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevitanrelta%2Fhtmlarkdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevitanrelta%2Fhtmlarkdown/lists"}