| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
Β | Β | |||
β¨ Add a little magic to your markdown! β¨
Markdown magic uses comment blocks in markdown files to automatically sync or transform its contents.
The comments markdown magic uses are hidden in markdown and when viewed as HTML.
This README.md is generated with markdown-magic view the raw file to see how.
Click to expandVia npm
npm install markdown-magic --save-devVia binary (no Node.js required)
Download the prebuilt binary for your platform from GitHub Releases:
# macOS (Apple Silicon)
curl -fsSL https://github.com/DavidWells/markdown-magic/releases/latest/download/md-magic-darwin-arm64 -o md-magic
chmod +x md-magic
# macOS (Intel)
curl -fsSL https://github.com/DavidWells/markdown-magic/releases/latest/download/md-magic-darwin-x64 -o md-magic
chmod +x md-magic
# Linux (x64)
curl -fsSL https://github.com/DavidWells/markdown-magic/releases/latest/download/md-magic-linux-x64 -o md-magic
chmod +x md-magic
# Linux (ARM64)
curl -fsSL https://github.com/DavidWells/markdown-magic/releases/latest/download/md-magic-linux-arm64 -o md-magic
chmod +x md-magicUse comment blocks in your markdown
Example:
<!-- docs remote url=http://url-to-raw-md-file.md -->
This content will be dynamically replaced from the remote url
<!-- /docs -->Then run markdown-magic via it's CLI or programmatically.
Run markdown --help to see all available CLI options
markdown
# or
md-magicCLI usage example with options
md-magic --file '**/*.md' --config ./config.file.jsIn NPM scripts, npm run docs would run the markdown magic and parse all the .md files in the directory.
"scripts": {
"docs": "md-magic --file '**/*.md'"
},If you have an md.config.js or markdown.config.js file where markdown-magic is invoked, it will automatically use that as the configuration unless otherwise specified by --config flag.
const { markdownMagic } = require('../src')
/* By default all .md files in cwd will be processed */
markdownMagic().then((results) => {
console.log('result keys', Object.keys(results))
})import path from 'path'
import markdownMagic from 'markdown-magic'
// Process a Single File
const markdownPath = path.join(__dirname, 'README.md')
markdownMagic(markdownPath)Use the prebuilt binary to automatically update markdown files on push:
name: Update Markdown
on:
push:
paths:
- '**.md'
- 'src/**'
jobs:
update-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download md-magic
run: |
curl -fsSL https://github.com/DavidWells/markdown-magic/releases/latest/download/md-magic-linux-x64 -o md-magic
chmod +x md-magic
- name: Run markdown-magic
run: ./md-magic --files '**/*.md'
- name: Commit changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git diff --staged --quiet || git commit -m "docs: update markdown"
git pushThere are various syntax options. Choose your favorite.
openWord transformName [opts]
<!-- docs transformName optionOne='hello' optionTwo='there' -->
content to be replaced
<!-- /docs -->openWord {transformName} [opts]
<!-- docs {transformName} optionOne='hello' optionTwo='there' -->
content to be replaced
<!-- /docs -->openWord [transformName] [opts]
<!-- docs [transformName] optionOne='hello' optionTwo='there' -->
content to be replaced
<!-- /docs -->openWord (transformName) [opts]
<!-- docs (transformName) optionOne='hello' optionTwo='there' -->
content to be replaced
<!-- /docs -->openWord transformName([opts])
<!-- docs transformName(
foo='bar'
baz=['qux', 'quux']
) -->
content to be replaced
<!-- /docs -->Markdown Magic Instance
markdownMagic(globOrOpts, options)| Name | Type | Description |
|---|---|---|
| globOrOpts | FilePathsOrGlobs or MarkdownMagicOptions | Files to process or config. |
| options (optional) | MarkdownMagicOptions | Markdown magic config. |
Returns
Promise<MarkdownMagicResult>
Example
markdownMagic(['**.**.md'], options).then((result) => {
console.log(`Processing complete`, result)
})Configuration for markdown magic
Below is the main config for markdown-magic
| Name | Type | Description |
|---|---|---|
| files (optional) | FilePathsOrGlobs | Files to process. |
| transforms (optional) | Array | Custom commands to transform block contents, see transforms & custom transforms sections below. Default: defaultTransforms |
| output (optional) | OutputConfig | Output configuration. |
| syntax (optional) | SyntaxType | Syntax to parse. Default: md |
| open (optional) | string | Opening match word. Default: docs |
| close (optional) | string | Closing match word. If not defined will be same as opening word. Default: /docs |
| cwd (optional) | string | Current working directory. Default process.cwd(). Default: process.cwd() |
| outputFlatten (optional) | boolean | Flatten files that are output. |
| useGitGlob (optional) | boolean | Use git glob for LARGE file directories. |
| dryRun (optional) | boolean | See planned execution of matched blocks. Default: false |
| debug (optional) | boolean | See debug details. Default: false |
| silent (optional) | boolean | Silence all console output. Default: false |
| applyTransformsToSource (optional) | boolean | Apply transforms to source file. Default is true. Default: true |
| failOnMissingTransforms (optional) | boolean | Fail if transform functions are missing. Default skip blocks. Default: false |
| failOnMissingRemote (optional) | boolean | Fail if remote file is missing. Default: true |
| allowPrivateGithub (optional) | boolean | Allow REMOTE/CODE blocks to use GitHub tokens or gh auth for private repository files. Default: false |
| logRemoteRequests (optional) | boolean | Log each unique remote HTTP request as it is attempted. Default: true |
| remoteCache (optional) | RemoteCacheOptions or boolean | Remote fetch cache options. Use false or { enabled: false } to disable. |
Remote fetch cache options
| Name | Type | Description |
|---|---|---|
| enabled (optional) | boolean | Enable the remote fetch cache. Default: true |
| directory (optional) | string | Cache directory. Defaults to the user's OS cache directory outside the project. |
| ttl (optional) | number | Milliseconds to reuse normal remote responses. Default is 5 minutes. Default: 300000 |
| immutableTtl (optional) | number | Milliseconds to reuse GitHub files pinned to a full 40-character commit SHA. Default is 30 days. |
| cachePrivate (optional) | boolean | Persist authenticated private GitHub responses. Set false to keep private reads memory-only for the current run. Default: true |
| logHits (optional) | boolean | Log cache hits as remote requests marked with (from cache). Default: true |
Optional output configuration
| Name | Type | Description |
|---|---|---|
| directory (optional) | string | Change output path of new content. Default behavior is replacing the original file. |
| removeComments (optional) | boolean | Remove comments from output. Default is false. Default: false |
| pathFormatter (optional) | function | Custom function for altering output paths. |
| applyTransformsToSource (optional) | boolean | Apply transforms to source file. Default is true. This is for when outputDir is set. Default: false |
Result of markdown processing
| Name | Type | Description |
|---|---|---|
| errors | Array | Any errors encountered. |
| filesChanged | Array<string> | Modified files. |
| results | Array | md data. |
Markdown Magic comes with a couple of built-in transforms for you to use or you can extend it with your own transforms. See 'Custom Transforms' below.
Generate table of contents from markdown file
Options:
Example:
<!-- docs TOC -->
toc will be generated here
<!-- /docs -->Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Get code from file or URL and put in markdown
Options:
Example:
<!-- docs CODE src="./relative/path/to/code.js" -->
This content will be dynamically replaced with code from the file
<!-- /docs --> <!-- docs CODE src="./relative/path/to/code.js" lines=22-44 -->
This content will be dynamically replaced with code from the file lines 22 through 44
<!-- /docs -->Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Get local file contents.
Options:
Example:
<!-- docs FILE src=./path/to/file -->
This content will be dynamically replaced from the local file
<!-- /docs -->Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Get any remote Data and put in markdown
Options:
Example:
<!-- docs REMOTE url=http://url-to-raw-md-file.md -->
This content will be dynamically replaced from the remote url
<!-- /docs -->GitHub blob and raw.githubusercontent.com file URLs are resolved with GitHub-aware fallbacks. Public files use anonymous raw GitHub content first. Private files are opt-in and can be fetched with GITHUB_ACCESS_TOKEN, GITHUB_TOKEN, githubToken, or an authenticated GitHub CLI session only when allowPrivateGithub is enabled:
<!-- docs REMOTE
src='https://github.com/owner/private-repo/blob/main/README.md'
removeLeadingH1
-->
Existing content is kept if failOnMissingRemote is false.
<!-- /docs -->Enable private GitHub reads from config:
module.exports = {
allowPrivateGithub: true
}Or for a single CLI run:
md-magic --allow-private-github --files README.mdTo use local GitHub CLI auth instead of a token, run gh auth status first. Set MARKDOWN_MAGIC_GH_CLI=0 to disable gh api fallback in CI or locked-down environments.
Remote requests are logged once per unique URL as they are attempted. Set logRemoteRequests: false in config to disable this output.
Successful remote responses are cached outside the project in the user's OS cache directory by default. Normal responses are reused for 5 minutes. GitHub files pinned to a full 40-character commit SHA use a longer immutable cache TTL. Set remoteCache: false or remoteCache: { enabled: false } to disable the cache, or pass --no-cache / --no-remote-cache for a single CLI run. Set remoteCache.cachePrivate: false to avoid persisting authenticated private GitHub responses to disk. Cache hits are logged as Getting remote (from cache): unless remoteCache.logHits or logRemoteRequests is disabled.
Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Generate a file tree table of contents
Options:
Example:
<!-- docs fileTree src="./src" maxDepth=2 -->
file tree will be generated here
<!-- /docs -->Example Output (tree format):
βββ src/
βββ transforms/
β βββ code/
β β ...
β βββ fileTree.js
β βββ index.js
β βββ toc.js
βββ utils/
β βββ fs.js
β βββ logs.js
β βββ text.js
βββ index.js
Example Output (list format):
- **src/**
- **transforms/**
- **code/**
- ...
- fileTree.js
- index.js
- toc.js
- **utils/**
- fs.js
- logs.js
- text.js
- index.jsExample with file sizes:
βββ src/
βββ index.js (15.2 KB)
βββ package.json (552 B)
Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Generate installation instructions in a markdown table format
Options:
Example:
<!-- docs install -->
Installation instructions will be generated here
<!-- /docs -->Default matchWord is docs
| Name | Type | Description |
|---|---|---|
| content | string | The current content of the comment block. |
| options | object | The options passed in from the comment declaration. |
Any transform, including custom transforms can be used inline as well to insert content into paragraphs and other places.
The face symbol π βββΏβγ€ is auto generated inline.
Example:
<!-- docs (FILE:src=./path/to/file) -->xyz<!-- /docs -->These plugins are maintained and compatible with the latest markdown-magic v4+ plugin API.
These plugins work with older versions of markdown-magic. Adapting them to the newer plugin syntax should be pretty straight forward.
Markdown Magic is extendable via plugins.
Plugins allow developers to add new transforms to the config.transforms object. This allows for things like using different rendering engines, custom formatting, or any other logic you might want.
Plugins run in order of registration.
The below code is used to generate this markdown file via the plugin system.
const path = require('path')
const { readFileSync } = require('fs')
const { parseComments } = require('doxxx')
const { markdownMagic } = require('../src')
const { deepLog } = require('../src/utils/logs')
const config = {
matchWord: 'MD-MAGIC-EXAMPLE', // default matchWord is AUTO-GENERATED-CONTENT
transforms: {
/* Match <!-- AUTO-GENERATED-CONTENT:START (customTransform:optionOne=hi&optionOne=DUDE) --> */
customTransform({ content, options }) {
console.log('original content in comment block', content)
console.log('options defined on transform', options)
// options = { optionOne: hi, optionOne: DUDE}
return `This will replace all the contents of inside the comment ${options.optionOne}`
},
/* Match <!-- AUTO-GENERATED-CONTENT:START JSDocs path="../file.js" --> */
JSDocs(markdownMagicPluginAPI) {
const { options } = markdownMagicPluginAPI
const fileContents = readFileSync(options.path, 'utf8')
const docBlocs = parseComments(fileContents, { skipSingleStar: true })
.filter((item) => {
return !item.isIgnored
})
/* Remove empty comments with no tags */
.filter((item) => {
return item.tags.length
})
/* Remove inline type defs */
.filter((item) => {
return item.description.text !== ''
})
/* Sort types to end */
.sort((a, b) => {
if (a.type && !b.type) return 1
if (!a.type && b.type) return -1
return 0
})
docBlocs.forEach((data) => {
// console.log('data', data)
delete data.code
})
// console.log('docBlocs', docBlocs)
if (docBlocs.length === 0) {
throw new Error('No docBlocs found')
}
// console.log(docBlocs.length)
let updatedContent = ''
docBlocs.forEach((data) => {
if (data.type) {
updatedContent += `#### \`${data.type}\`\n\n`
}
updatedContent += `${data.description.text}\n`
if (data.tags.length) {
let table = '| Name | Type | Description |\n'
table += '|:---------------------------|:---------------:|:-----------|\n'
data.tags.filter((tag) => {
if (tag.tagType === 'param') return true
if (tag.tagType === 'property') return true
return false
}).forEach((tag) => {
const optionalText = tag.isOptional ? ' (optional) ' : ' '
const defaultValueText = (typeof tag.defaultValue !== 'undefined') ? ` Default: \`${tag.defaultValue}\` ` : ' '
table += `| \`${tag.name}\`${optionalText}`
table += `| \`${tag.type.replace('|', 'or')}\` `
table += `| ${tag.description.replace(/\.\s?$/, '')}.${defaultValueText}|\n`
})
updatedContent+= `\n${table}\n`
const returnValues = data.tags.filter((tag) => tag.tagType === 'returns')
if (returnValues.length) {
returnValues.forEach((returnValue) => {
updatedContent += `**Returns**\n\n`
updatedContent += `\`${returnValue.type}\`\n\n`
})
}
const examples = data.tags.filter((tag) => tag.tagType === 'example')
if (examples.length) {
examples.forEach((example) => {
updatedContent += `**Example**\n\n`
updatedContent += `\`\`\`js\n${example.tagValue}\n\`\`\`\n\n`
})
}
}
})
return updatedContent.replace(/^\s+|\s+$/g, '')
},
INLINE_EXAMPLE: () => {
return '**βββΏβγ€**'
},
lolz() {
return `This section was generated by the cli config md.config.js file`
},
/* Match <!-- AUTO-GENERATED-CONTENT:START (pluginExample) --> */
pluginExample: require('./plugin-example')({ addNewLine: true }),
/* Include plugins from NPM */
// count: require('markdown-magic-wordcount'),
// github: require('markdown-magic-github-contributors')
}
}
const markdownPath = path.join(__dirname, '..', 'README.md')
markdownMagic(markdownPath, config, () => {
console.log('Docs ready')
})Plugins must return a transform function with the following signature.
return function myCustomTransform (content, options)/* Custom Transform Plugin example */
module.exports = function customPlugin(pluginOptions) {
// set plugin defaults
const defaultOptions = {
addNewLine: false
}
const userOptions = pluginOptions || {}
const pluginConfig = Object.assign(defaultOptions, userOptions)
// return the transform function
return function myCustomTransform ({ content, options }) {
const newLine = (pluginConfig.addNewLine) ? '\n' : ''
const updatedContent = content + newLine
return updatedContent
}
}View the raw file file and run npm run docs to see this plugin run
This content is altered by the pluginExample plugin registered in examples/generate-readme.js
View the raw source of this README.md file to see the comment block and see how the customTransform function in examples/generate-readme.js works
This will replace all the contents of inside the comment DUDE
This was inspired by Kent C Dodds and jfmengels's all contributors cli project.
MIT Β© DavidWells
| Back | FazBrowse Home | New Git URL |