{"id":15775811,"url":"https://github.com/agentender/markdown-factory","last_synced_at":"2025-04-28T16:41:14.779Z","repository":{"id":146631507,"uuid":"617784290","full_name":"AgentEnder/markdown-factory","owner":"AgentEnder","description":"A JS library to generate markdown via a functional API","archived":false,"fork":false,"pushed_at":"2024-09-12T22:32:46.000Z","size":2196,"stargazers_count":3,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-24T17:02:42.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://craigory.dev/markdown-factory/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AgentEnder.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-23T05:14:05.000Z","updated_at":"2024-09-12T22:31:46.000Z","dependencies_parsed_at":"2024-08-07T06:41:36.846Z","dependency_job_id":"ba795f98-d495-4478-ac50-5a2b6145c29a","html_url":"https://github.com/AgentEnder/markdown-factory","commit_stats":{"total_commits":20,"total_committers":2,"mean_commits":10.0,"dds":0.09999999999999998,"last_synced_commit":"b9af794fe1181acd01e5f41a33caf94d80e0475a"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AgentEnder%2Fmarkdown-factory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AgentEnder%2Fmarkdown-factory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AgentEnder%2Fmarkdown-factory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AgentEnder%2Fmarkdown-factory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AgentEnder","download_url":"https://codeload.github.com/AgentEnder/markdown-factory/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251347599,"owners_count":21575112,"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":[],"created_at":"2024-10-04T17:02:47.950Z","updated_at":"2025-04-28T16:41:14.729Z","avatar_url":"https://github.com/AgentEnder.png","language":"TypeScript","readme":"1. [Markdown Factory](#markdown-factory)\n\n   1. [Why?](#why)\n\n   2. [Getting Started](#getting-started)\n\n      1. [Installation](#installation)\n\n      2. [Usage](#usage)\n\n   3. [Examples](#examples)\n\n   4. [API](#api)\n\n      1. [Headers](#headers)\n\n      2. [`link`](#link)\n\n      3. [`linkToHeader`](#linktoheader)\n\n      4. [`table`](#table)\n\n      5. [`tableOfContents`](#tableofcontents)\n\n      6. [`codeBlock`](#codeblock)\n\n      7. [`stripIndents`](#stripindents)\n\n      8. [`blockQuote`](#blockquote)\n\n      9. [`orderedList`](#orderedlist)\n\n      10. [`unorderedList`](#unorderedlist)\n\n# Markdown Factory\n\nUtilities to easily generate valid markdown from within JavaScript\n\n## Why?\n\nFor static content, this library is **mostly** unnecessary. However, when generating a report from a dynamic data source this library can be rather useful.\n\nAn example of using this library for dynamic data, could be the implementation of the `tableOfContents` function. Inside it, we parse the headings and then use the utils to generate an appropriate table of contents. You can read more about it here: [`tableOfContents`](#tableofcontents)\n\n## Getting Started\n\n### Installation\n\nnpm install markdown-factory\n\n### Usage\n\nImport the functions you need from markdown-factory, they are named based on the markdown they generate. For the most part, they take text content as the first argument, and any additional arguments are treated as sub-elements.\n\n```typescript\nimport { h1, h2, h3 } from 'markdown-factory';\nh1('Hello World', h2('subheading', h3('sub-subheading', 'foo-bar')));\n```\n\n## Examples\n\nSome advanced usages of the library can be found below:\n\n- The [`generate-readme`](https://github.com/agentender/markdown-factory/tree/main/tools/generate-readme.ts) script generates this document\n\n- The [implementation file](https://github.com/agentender/markdown-factory/tree/main/packages/markdown-factory/src/lib/markdown.ts) for this library contains `tableOfContents` which dynamically composes several of these utility functions.\n\n## API\n\n### Headers\n\nHeaders are generated using the `h1`, `h2`, `h3`, `h4`, `h5`, and `h6` functions. For example, a document with a title and 3 subsections could be generated like this:\n\n```typescript\nh1('Title', h2('Section 1', h3('Subsection 1', 'foo')), h2('Section 2', h3('Subsection 2', 'bar')), h2('Section 3', h3('Subsection 3', 'baz')));\n```\n\n### `link`\n\nA link can be generated using the `link` function. It takes a url and optionally a label as arguments.\n\n```typescript\nlink('https://google.com', 'Google');\n```\n\n### `linkToHeader`\n\nA link to a header can be generated using the `linkToHeader` function. It takes a header and optionally a label as arguments.\n\nThis differs from `link` in that the contents of the ref are sanitized and parsed from header text first. This involves removing all non-alphanumeric characters, and replacing spaces with dashes. If this doesn't suit your use case, you should use `link` directly instead.\n\n```typescript\nlinkToHeader('Resources!', 'More Resources and Information');\n```\n\n```markdown\n[More Resources and Information](#resources)\n```\n\n### `table`\n\nOne of the more useful functions in this library is the `table` function. It takes an array of objects, and a list of fields to display. The fields are described in one of 3 forms:\n\n1. A simple string, which will be used as the label and the field name\n\n2. An object with a `label` and `field` property, which will be used as the label and the field name, respectively.\n\n3. An object with a `label` and `mapFn` property, which will be used as the label and a function to map the item to a string value.\n\nThese can be mixed and matched within the `fields` array as needed. For example, if you needed to relabel 1 field, and map another, you could do the following:\n\n```typescript\ntable(items, [\n  {\n    label: 'First Name',\n    field: 'name',\n  },\n  'age',\n  {\n    label: 'City',\n    mapFn: (item) =\u003e item.address.city,\n  },\n]);\n```\n\n### `tableOfContents`\n\nThe `tableOfContents` function takes a depth and the contents that it should cover. It will generate a table of contents for the headers up to the specified depth. For example, if you had a document with the following headers:\n\n```markdown\n# Title\n\n## Section 1\n\n### Subsection 1\n\n### Subsection 2\n\n## Section 2\n\n### Subsection 3\n\n#### Subsubsection 1\n\n### Subsection 4\n```\n\nYou could generate a table of contents like this:\n\n```typescript\ntableOfContents(3, mrkdwnContents);\n```\n\nThe expected output would be:\n\n```markdown\n- [Section 1](#section-1)\n  - [Subsection 1](#subsection-1)\n  - [Subsection 2](#subsection-2)\n- [Section 2](#section-2)\n  - [Subsection 3](#subsection-3)\n  - [Subsection 4](#subsection-4)\n```\n\n\u003e Note: The depth passed into the function is equivalent to the maximum \"level\" of the headings displayed. e.g., `depth=3` would not show any h4 or h5 headings.\n\n### `codeBlock`\n\nThe `codeBlock` function takes a string of code and an optional language. It will wrap the code in a code block, and optionally add syntax highlighting for the language. For example:\n\n```typescript\nimport { codeBlock } from 'markdown-factory';\ncodeBlock('const foo = \"bar\";', 'typescript');\n```\n\n### `stripIndents`\n\nThe `stripIndents` function is rather unique in terms of this libraries functions. It doesn directly correlate to a markdown element, but is rather a utility function that strips leading whitespace from each line of a string. This doesn't affect the rendered markdown, but can be useful when writing code in a template string. For example, we can write this:\n\n```typescript\nimport { codeBlock, stripIndents } from 'markdown-factory';\nif (someCondition) {\n  if (someOtherCondition) {\n    codeBlock(\n      stripIndents`\n      const foo = \"bar\";\n      const baz = \"qux\";\n    `,\n      'typescript'\n    );\n  }\n}\n```\n\nInstead of this:\n\n```typescript\nimport { codeBlock } from 'markdown-factory';\nif (someCondition) {\n  if (someOtherCondition) {\n    codeBlock(\n      `const foo = \"bar\";\nconst baz = \"qux\";`,\n      'typescript'\n    );\n  }\n}\n```\n\n### `blockQuote`\n\nThe `blockQuote` function takes a string of text to render as a quote. For example:\n\n```typescript\nimport { blockQuote } from 'markdown-factory';\nblockQuote('This is a quote');\n```\n\n### `orderedList`\n\nThe `orderedList` function takes a list of strings to render as an ordered list. For example:\n\n```typescript\nimport { h1, orderedList } from 'markdown-factory';\nh1('Sandwich Recipe', orderedList('Slice bread', 'Spread mayo', 'Add lettuce', 'Add tomato', 'Add cheese', 'Add meat', 'Add condiments', 'Eat'));\n```\n\nYou can also pass an options object as the first argument to the `orderedList` function. The options object can contain the following properties:\n\n- `startIdx` - The number to start the list at. Defaults to 1.\n\n- level - The level of the list (for nesting lists). Defaults to 1.\n\nFor example, the following code would produce a nested list that starts at 3:\n\n```typescript\nimport { h1, orderedList } from 'markdown-factory';\nh1('Sandwich Recipe', orderedList(\n  lines(\n    'Slice bread',\n    orderedList(\n      {startIdx: 3, level: 2},\n      'Grab knife',\n      'Cut bread',\n      'Place on plate'\n    )\n  ),\n  'Spread mayo'\n)\n```\n\n\u003e Note - The actual numbers in an ordered list are not used in rendered markdown, but they are visible in the source. This is why the `startIdx` option is useful. For example, the following two lists are identical once rendered:\n\u003e\n\u003e ```markdown\n\u003e # List 1\n\u003e\n\u003e 1. Item 1\n\u003e 2. Item 2\n\u003e 3. Item 3\n\u003e\n\u003e # List 2\n\u003e\n\u003e 1. Item 1\n\u003e 1. Item 2\n\u003e 1. Item 3\n\u003e ```\n\n### `unorderedList`\n\nThe `unorderedList` function takes a list of strings to render as an unordered list. For example:\n\n```typescript\nimport { h1, unorderedList } from 'markdown-factory';\nh1('Sandwich Ingredients', unorderedList('Bread', 'Mayo', 'Lettuce', 'Tomato', 'Cheese', 'Meat', 'Condiments'));\n```\n\nYou can also pass an options object as the first argument to the `unorderedList` function. The options object can contain the following properties:\n\n- level - The level of the list (for nesting lists). Defaults to 1.\n\nFor example, the following code would produce a nested list:\n\n```typescript\nimport { h1, unorderedList } from 'markdown-factory';\nh1('Sandwich Ingredients', unorderedList(\n  'Bread',\n  'Ham',\n  lines(\n    'Condiments',\n    unorderedList(\n      { level: 2 },\n      'Ketchup',\n      'Mayo',\n      'Mustard'\n    )\n  ),\n  'Spread mayo'\n)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagentender%2Fmarkdown-factory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagentender%2Fmarkdown-factory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagentender%2Fmarkdown-factory/lists"}