{"id":15047011,"url":"https://github.com/activescott/agentmarkdown","last_synced_at":"2025-04-10T00:44:13.291Z","repository":{"id":35015161,"uuid":"193412946","full_name":"activescott/agentmarkdown","owner":"activescott","description":"An accurate, extensible, and fast HTML-to-markdown converter.","archived":false,"fork":false,"pushed_at":"2025-04-01T21:45:37.000Z","size":4742,"stargazers_count":18,"open_issues_count":10,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T00:44:06.201Z","etag":null,"topics":["css","html","javascript","markdown","markdown-converter","typescript","user-agent"],"latest_commit_sha":null,"homepage":"https://agentmarkdown.now.sh","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/activescott.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-24T01:20:36.000Z","updated_at":"2025-04-07T01:54:41.000Z","dependencies_parsed_at":"2023-10-01T23:19:47.817Z","dependency_job_id":"272ace54-fe0f-4774-b7bb-98c4230027a8","html_url":"https://github.com/activescott/agentmarkdown","commit_stats":{"total_commits":232,"total_committers":4,"mean_commits":58.0,"dds":0.4612068965517241,"last_synced_commit":"180e1728df7a351c76eb208c6318ed5374730053"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/activescott%2Fagentmarkdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/activescott%2Fagentmarkdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/activescott%2Fagentmarkdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/activescott%2Fagentmarkdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/activescott","download_url":"https://codeload.github.com/activescott/agentmarkdown/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137998,"owners_count":21053775,"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":["css","html","javascript","markdown","markdown-converter","typescript","user-agent"],"created_at":"2024-09-24T20:53:52.383Z","updated_at":"2025-04-10T00:44:13.273Z","avatar_url":"https://github.com/activescott.png","language":"TypeScript","readme":"[![npm version](https://badge.fury.io/js/agentmarkdown.svg)](https://www.npmjs.com/package/agentmarkdown)\n[![npm downloads](https://img.shields.io/npm/dt/agentmarkdown.svg?logo=npm)](https://www.npmjs.com/package/agentmarkdown)\n[![Build Status](https://github.com/activescott/agentmarkdown/workflows/main/badge.svg)](https://github.com/activescott/agentmarkdown/actions)\n[![Coverage Status](https://coveralls.io/repos/github/activescott/agentmarkdown/badge.svg?branch=master)](https://coveralls.io/github/activescott/agentmarkdown?branch=master)\n[![Greenkeeper badge](https://badges.greenkeeper.io/activescott/agentmarkdown.svg)](https://greenkeeper.io/)\n[![Code Quality](https://api.codacy.com/project/badge/Grade/1b9057ec20bb473295303334bfd2ccd8)](https://app.codacy.com/app/activescott/agentmarkdown?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=activescott/agentmarkdown\u0026utm_campaign=Badge_Grade_Dashboard)\n[![Minified Size](https://badgen.net/bundlephobia/min/agentmarkdown)](https://bundlephobia.com/result?p=agentmarkdown)\n[![License](https://img.shields.io/github/license/activescott/agentmarkdown.svg)](https://github.com/activescott/agentmarkdown/blob/master/LICENSE)\n[![GitHub stars](https://img.shields.io/github/stars/activescott/agentmarkdown.svg?style=social)](https://github.com/activescott/agentmarkdown)\n\n# Agent Markdown\n\nAn accurate, extensible, and fast HTML-to-markdown converter.\n\nAgent Markdown is a [HTML user agent](https://en.wikipedia.org/wiki/User_agent) that parses HTML, performs a document layout according to the [CSS stylesheet for HTML](https://html.spec.whatwg.org/multipage/rendering.html#the-css-user-agent-style-sheet-and-presentational-hints) and then \"renders\" the laid out document to Markdown. This results in markdown that looks very similar to the way the HTML document looked when parsed and rendered in a browser (user agent).\n\n\u003c!-- TOC --\u003e\n\n- [Usage / Quick Start](#usage--quick-start)\n- [Install](#install)\n- [Features](#features)\n- [CLI Example](#cli-example)\n- [Live Example](#live-example)\n- [Customize \u0026 Extend with Plugins](#customize--extend-with-plugins)\n- [Show your support](#show-your-support)\n- [Contributing 🤝](#contributing-🤝)\n- [Release Process (Deploying to NPM) 🚀](#release-process-deploying-to-npm-🚀)\n- [License 📝](#license-📝)\n\n\u003c!-- /TOC --\u003e\n\n## Usage / Quick Start\n\n```\nimport { AgentMarkdown } from \"agentmarkdown\"\nconst markdownString = await AgentMarkdown.produce(htmlString)\n```\n\n## Install\n\nnpm (`npm install agentmarkdown`)\n\n## Features\n\n- Accurately converts HTML to [CommonMark-compliant](https://commonmark.org/) markdown\n  - uses [GitHub-Flavored Markdown's Strikethrough extention](https://github.github.com/gfm/#strikethrough-extension-) for \u0026lt;strike\u0026gt; and \u0026lt;del\u0026gt;.\n- Supports even wonky technically incorrect HTML\n- Supports nested lists\n- Supports [implied paragraphs](https://html.spec.whatwg.org/#paragraphs) / [CSS anonymous bock box layout](https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level)\n- Can be used client side (in the browser) or server side (with Node.js)\n- Add support for new elements [with plugins](#customize--extend-with-plugins)\n- Fast?\n\n## CLI Example\n\nYou can convert any HTML file to Markdown at the command line using the following command, and the markdown output will be printed to stdout:\n\n    agentmarkdown \u003cfilename.html\u003e\n\nIt also responds to stdin, if you pipe html to it. So you can do things like:\n\n    echo \"\u003cb\u003ebold\u003c/bold\u003e\" | agentmarkdown \u003e myfile.md\n\nThe above commands assume you installed agentmarkdown with `npm install --global agentmarkdown` but it also works with `npx` so you can run it without installing like:\n\n    npx agentmarkdown \u003cfilename.html\u003e\n\n## Live Example\n\nYou can view the live online web example at [https://agentmarkdown.now.sh](https://agentmarkdown.now.sh).\n\nYou can build and the web example locally with the following commands:\n\n```\ncd example/\nnpm install\nnpm run start\n```\n\n_NOTE: If you have trouble starting the example on macOS related to `fsevents` errors, it may require running `xcode-select --install`. If that doesn't work, then possibly a `sudo rm -rf $(xcode-select -print-path)` followed by `xcode-select --install` will be necessary._\n\n## Customize \u0026 Extend with Plugins\n\nTo customize how the markdown is generated or add support for new elements, implement the `LayoutPlugin` interface to handle a particular HTML element. The `LayoutPlugin` interface is defined as follows:\n\n```TypeScript\nexport interface LayoutPlugin {\n  /**\n   * Specifies the name of the HTML element that this plugin renders markdown for.\n   * NOTE: Must be all lowercase\n   */\n  elementName: string\n  /**\n   * This is the core of the implementation that will be called for each instance of the HTML element that this plugin is registered for.\n   */\n  layout: LayoutGenerator\n}\n```\n\nThe `LayoutGenerator` is a single function that performs a [CSS2 box generation layout algorithm](https://www.w3.org/TR/CSS22/visuren.html#box-gen) on the an HTML element. Essentially it creates zero or more boxes for the given element that AgentMarkdown will render to text. A box can contain text content and/or other boxes, and each box has a type of `inline` or `block`. Inline blocks are laid out horizontally. Block boxes are laid out vertically (i.e. they have new line characters before and after their contents). The `LayoutGenerator` function definition is as follows:\n\n```TypeScript\nexport interface LayoutGenerator {\n  (\n    context: LayoutContext,\n    manager: LayoutManager,\n    element: HtmlNode\n  ): CssBox | null\n}\n```\n\nAn example of how the HTML `\u003cb\u003e` element could be implemented as a plugin like the following:\n\n```TypeScript\nclass BoldPlugin {\n  elementName: \"b\"\n\n  layout: LayoutGenerator = (\n    context: LayoutContext,\n    manager: LayoutManager,\n    element: HtmlNode\n  ): CssBox | null =\u003e {\n    // let the manager use other plugins to layout any child elements:\n    const kids = manager.layout(context, element.children)\n    // wrap the child elements in the markdown ** syntax for bold/strong:\n    kids.unshift(manager.createBox(BoxType.inline, \"**\"))\n    kids.push(manager.createBox(BoxType.inline, \"**\"))\n    // return a new box containing everything:\n    return manager.createBox(BoxType.inline, \"\", kids)\n  }\n}\n```\n\nTo initialize AgentMarkdown with plugins pass them in as an array value for the `layoutPlugins` option as follows. To customize the rendering an element you can just specify a plugin for the elementName and your plugin will override the built-in plugin.\n\n```TypeScript\nconst result = await AgentMarkdown.render({\n    html: myHtmlString,\n    layoutPlugins: [\n      new BoldPlugin()\n    ]\n  })\n```\n\n## Show your support\n\nPlease give a ⭐️ if this project helped you!\n\n## Contributing 🤝\n\nThis is a community project. We invite your participation through issues and pull requests! You can peruse the [contributing guidelines](.github/CONTRIBUTING.md).\n\n# Building\n\nThe package is written in TypeScript. To build the package run the following from the root of the repo:\n\n    npm run build # It will be built in /dist\n\n## Release Process (Deploying to NPM) 🚀\n\nWe use [semantic-release](https://github.com/semantic-release/semantic-release) to consistently release [semver](https://semver.org/)-compatible versions. This project deploys to multiple [npm distribution tags](https://docs.npmjs.com/cli/dist-tag). Each of the below branches correspond to the following npm distribution tags:\n\n| branch | npm distribution tag |\n| ------ | -------------------- |\n| master | latest               |\n| beta   | beta                 |\n\nTo trigger a release use a Conventional Commit following [Angular Commit Message Conventions](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) on one of the above branches.\n\n# Todo / Roadmap\n\nsee [/docs/todo.md](docs/todo.md)\n\n# Alternatives\n\n- http://domchristie.github.io/turndown/\n- https://github.com/rehypejs/rehype-remark\n\n## License 📝\n\nCopyright © 2019 [Scott Willeke](https://github.com/activescott).\n\nThis project is licensed via [Mozilla Public License 2.0](https://github.com/activescott/agentmarkdown/blob/master/LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Factivescott%2Fagentmarkdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Factivescott%2Fagentmarkdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Factivescott%2Fagentmarkdown/lists"}