Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/eiffelfly/markdown-indexed-block
This lib will annotate every block in the markdown file with site wise unique identifier and generate HTML accroding to the new markdown.
https://github.com/eiffelfly/markdown-indexed-block
Last synced: 2 days ago
JSON representation
This lib will annotate every block in the markdown file with site wise unique identifier and generate HTML accroding to the new markdown.
- Host: GitHub
- URL: https://github.com/eiffelfly/markdown-indexed-block
- Owner: EiffelFly
- Created: 2022-06-29T01:58:21.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-07-15T03:06:16.000Z (over 2 years ago)
- Last Synced: 2024-05-30T16:28:47.144Z (7 months ago)
- Language: TypeScript
- Homepage:
- Size: 68.4 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# Markdown indexed block
This lib will annotate every block in the markdown file with site wise unique identifier and generate HTML accroding to the new markdown.
It contains three elements, a remark plugin, a set of rehype handler and a rehype plugin. The remark plugin introduce two new node type:
- IndexedBlock
- IndexedBlockChildrenAfter we had modified the markdown, we have two rehype handlers for these two types to generate apporiate HAST, then we have a rehype plugin to insert desired element and finally we stringify the hast to HTML.
## How to use
### Regular flow
```js
const buffer = fs.readFileSync("example.md");const file = await unified()
.use(remarkParse)
.use(remarkIndexedBlock, {
fileName: "",
domainName: "the site's domain name",
})
.use(remarkRehype, { handlers: { indexedBlock, indexedBlockChildren } })
.use(rehypeIndexedBlock)
.use(rehypeStringify)
.process(buffer);fs.writeFileSync("example-html.html", file.value);
```### Dev flow
If you want to know how remark and rehype operate at different stage, you could use this flow.
```js
const ast = unified().use(remarkParse).parse(buffer);
const transformedAst = await unified()
.use(remarkIndexedBlock, {
fileName: "example",
domainName: "https://test.com",
})
.run(ast);const hast = await unified()
.use(remarkRehype, { handlers: { indexedBlock, indexedBlockChildren } })
.run(transformedAst);const transformedHast = await unified().use(rehypeIndexedBlock).run(hast);
const transformedHTML = unified()
.use(rehypeStringify)
.stringify(transformedHast);
```## How it works
1. It will use the input fileName to tokenize the identifier, you can input with path like `path/to/blog/post/hi-i-am-indexed-block`
2. It will use the first 6 character as the prefix.
3. The suffix is depend on the order of the section.```md
# Header 1## Sub Header 1
hi, I am a block!
> I am a blockquote
```Every unique representation will be a block besides from every header, take above markdown for example, the `hi, I am a block!` and `> I am a blockquote` are two separated blocks, but `# Header 1` and `## Sub Header 1` are not block. The suffix will be determined by their order. If the calculated prefix is r43erf the overall index of `hi, I am a block!` will be `r43erf-3`
## Worth notice Caveat
- Because remark is a esm module, we have to keep an eye one that:
- We use `tsc` to build the package and imply that we are using esm by type config in package.json `type: "module"`
- When testing the plugin, we run the script with `node`, but node is running with CommonJS by default, you need to imply that you want to run with esm by this flag `--experimental-specifier-resolution=node`
- unified.parse will generate a syntax tree, but does not run plugins/transformers.
- ref: https://github.com/unifiedjs/unified/discussions/162
- If you want unified to run plugin you could write something like this
```js
const ast = unified().use(remarkParse).parse(buffer);
const transformedAst = await unified().use(remarkIndexedBlock).run(ast);
```
- You could declare custom node type```js
type IndexedBlock = {
type: "IndexedBlock";
id: string;
children: Content[];
};declare module "mdast" {
interface BlockContentMap {
indexedBlock: IndexedBlock;
}
}
```