Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ipikuka/remark-flexible-code-titles
Remark plugin to add titles or/and containers for the code blocks with customizable properties
https://github.com/ipikuka/remark-flexible-code-titles
code-titles markdown remark remark-plugin unified
Last synced: 3 months ago
JSON representation
Remark plugin to add titles or/and containers for the code blocks with customizable properties
- Host: GitHub
- URL: https://github.com/ipikuka/remark-flexible-code-titles
- Owner: ipikuka
- License: mit
- Created: 2023-01-16T19:33:04.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-03-22T11:42:50.000Z (11 months ago)
- Last Synced: 2024-10-31T05:24:30.288Z (4 months ago)
- Topics: code-titles, markdown, remark, remark-plugin, unified
- Language: TypeScript
- Homepage:
- Size: 568 KB
- Stars: 17
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# remark-flexible-code-titles
[![NPM version][badge-npm-version]][npm-package-url]
[![NPM downloads][badge-npm-download]][npm-package-url]
[![Build][badge-build]][github-workflow-url]
[](https://codecov.io/gh/ipikuka/remark-flexible-code-titles)
[](https://github.com/ipikuka/remark-flexible-code-titles)
[![typescript][badge-typescript]][typescript-url]
[![License][badge-license]][github-license-url]This package is a [unified][unified] ([remark][remark]) plugin to add title or/and container for code blocks with customizable properties in markdown.
**[unified][unified]** is a project that transforms content with abstract syntax trees (ASTs) using the new parser **[micromark][micromark]**. **[remark][remark]** adds support for markdown to unified. **[mdast][mdast]** is the Markdown Abstract Syntax Tree (AST) which is a specification for representing markdown in a syntax tree.
**This plugin is a remark plugin that transforms the mdast.**
## When should I use this?
This plugin is useful if you want to **add title and container or any of two** for code blocks in markdown.
The plugin `remark-flexible-code-titles` can:
- add `title` node above the `code` node, providing _custom tag name, custom class name and also additional properties_.
- add `container` node for the `code` node, providing _custom tag name, custom class name and also additional properties_.
- correct the syntax of code highligting directives on behalf of related rehype plugins (like [rehype-prism-plus][rehypeprismplus])
- handle the titles even if there is no language provided,
- handle the titles composed by more than one word (handle spaces in the title),
- provide a fallback language as an option if the language is missing.## Installation
This package is suitable for ESM only. In Node.js (16.0+), install with npm:
```bash
npm install remark-flexible-code-titles
```or
```bash
yarn add remark-flexible-code-titles
```## Usage
Say we have the following file, `example.md`, which consists a code block. The code block's language is "javascript" and its title is "file.js" specified _after a colon_ **`:`**
````markdown
```javascript:file.js
/* code block */
```
````And our module, `example.js`, looks as follows:
```javascript
import { read } from "to-vfile";
import remark from "remark";
import gfm from "remark-gfm";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import remarkCodeTitles from "remark-flexible-code-titles";main();
async function main() {
const file = await remark()
.use(gfm)
.use(remarkCodeTitles)
.use(remarkRehype)
.use(rehypeStringify)
.process(await read("example.md"));console.log(String(file));
}
```Now, running `node example.js` yields:
```html
title.js
```Without `remark-flexible-code-titles`, you’d get:
```html
```You can use the `remark-flexible-code-titles` **without a language**, _setting the title just after a colon_ **`:`**
````markdown
```:title
This is a line of pseudo code.
```
````## Options
All options are **optional** and some of them have **default values**.
```tsx
type RestrictedRecord = Record & { className?: never };
type PropertyFunction = (language?: string, title?: string) => RestrictedRecord;use(remarkCodeTitles, {
title?: boolean; // default is true
titleTagName?: string; // default is "div"
titleClassName?: string; // default is "remark-code-title"
titleProperties?: PropertyFunction;
container?: boolean; // default is true
containerTagName?: string; // default is "div"
containerClassName?: string; // default is "remark-code-container"
containerProperties?: PropertyFunction;
handleMissingLanguageAs?: string;
tokenForSpaceInTitle?: string;
} as CodeTitleOptions);
```#### `title`
It is a **boolean** option for whether or not to add a `title` node.
By default, it is `true`, meaningly adds a `title` node if a title is provided in the language part of the code block.
```javascript
use(remarkCodeTitles, {
title: false,
});
```If the option is `false`, the plugin will not add any `title` node.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
console.log("Hi")
```#### `titleTagName`
It is a **string** option for providing custom HTML tag name for `title` nodes.
By default, it is `div`.
```javascript
use(remarkCodeTitles, {
titleTagName: "span",
});
```Now, the title element tag names will be `span`.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```#### `titleClassName`
It is a **string** option for providing custom class name for `title` nodes.
By default, it is `remark-code-title`, and all title elements' class names will contain `remark-code-title`.
```javascript
use(remarkCodeTitles, {
titleClassName: "custom-code-title",
});
```Now, the title element class names will be `custom-code-title`.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```#### `titleProperties`
It is a **callback** `(language?: string, title?: string) => Record & { className?: never }` option to set additional properties for the `title` node.
The callback function that takes the `language` and the `title` as optional arguments and returns **object** which is going to be used for adding additional properties into the `title` node.
**The `className` key is forbidden and effectless in the returned object.**
```javascript
use(remarkCodeTitles, {
titleProperties(language, title) {
return {
title,
["data-language"]: language,
};
},
});
```Now, the title elements will contain `title` and `data-color` properties.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```#### `container`
It is a **boolean** option for whether or not to add a `container` node.
By default, it is `true`, meaningly adds a `container` node.
```javascript
use(remarkCodeTitles, {
container: false,
});
```If the option is `false`, the plugin doesn't add any `container` node.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```
#### `containerTagName`
It is a **string** option for providing custom HTML tag name for `container` nodes.
By default, it is `div`.
```javascript
use(remarkCodeTitles, {
containerTagName: "section",
});
```Now, the container element tag names will be `section`.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```
#### `containerClassName`
It is a **string** option for providing custom class name for `container` nodes.
By default, it is `remark-code-container`, and all container elements' class names will contain `remark-code-container`.
```javascript
use(remarkCodeTitles, {
containerClassName: "custom-code-container",
});
```Now, the container element class names will be `custom-code-container`.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```#### `containerProperties`
It is a **callback** `(language?: string, title?: string) => Record & { className?: never }` option to set additional properties for the `container` node.
The callback function that takes the `language` and the `title` as optional arguments and returns **object** which is going to be used for adding additional properties into the `container` node.
**The `className` key is forbidden and effectless in the returned object.**
```javascript
use(remarkCodeTitles, {
titleProperties(language, title) {
return {
title,
["data-language"]: language,
};
},
});
```Now, the container elements will contain `title` and `data-color` properties.
````markdown
```javascript:file.js
console.log("Hi")
```
```````html
file.js
console.log("Hi")
```#### `handleMissingLanguageAs`
It is a **string** option for providing a fallback language if the language is missing.
```javascript
use(remarkCodeTitles, {
handleMissingLanguageAs: "unknown",
});
```Now, the class name of `
` elements will contain `language-unknown` if the language is missing. If this option was not set, the `class` property would not be presented in the `
`element.
````markdown
```
Hello from code block
```
```````html
Hello from code block
```#### `tokenForSpaceInTitle`
It is a **string** option for composing the title with more than one word.
Normally, the `remark-flexible-code-titles` can match a code title which is the word that comes after a colon and ends in the first space it encounters. This option is provided to replace a space with a token in order to specify a code title consisting of more than one word.
```javascript
use(remarkCodeTitles, {
tokenForSpaceInTitle: "@",
});
```Now, the titles that have more than one word can be set using the token `@`.
````markdown
```bash:Useful@Bash@Commands
mkdir project-directory
```
```````html
Useful Bash Commands
mkdir project-directory
```## Examples:
#### Example for only container
````markdown
```javascript:file.js
let me = "ipikuka";
```
```````javascript
use(remarkCodeTitles, {
title: false,
containerTagName: "section",
containerClassName: "custom-code-wrapper",
containerProperties(language, title) {
return {
["data-language"]: language,
title,
};
},
});
```is going to produce the container `section` element like below:
```html
let me = "ipikuka";
```
#### Example for only title
````markdown
```javascript:file.js
let me = "ipikuka";
```
```````javascript
use(remarkCodeTitles, {
container: false,
titleTagName: "span",
titleClassName: "custom-code-title",
titleProperties: (language, title) => {
["data-language"]: language,
title,
},
});
```is going to produce the title `span` element just before the code block, like below:
```html
file.js
let me = "ipikuka";
```#### Example for line highlighting and numbering
> [!NOTE]
> You need a rehype plugin like **rehype-prism-plus** for line highlighting and numbering features.````markdown
```javascript:file.js {1,3-6} showLineNumbers
let me = "ipikuka";
```
````The `remark-flexible-code-titles` takes the line highlighting and numbering syntax into consideration, and passes that information to other remark and rehype plugins.
But, if you want to highlight and number the lines **without specifying language**, you will get the language of the code block as for example `language-{2}` like strings. Let me give an example:
````markdown
```{2} showLineNumbers
This is a line which is going to be numbered with rehype-prism-plus.
This is a line which is going to be highlighted and numbered with rehype-prism-plus.
```
````The above markdown, with no language provided, will lead to produce a mdast "code" node as follows:
```json
{
"type": "code",
"lang": "{2}",
"meta": "showLineNumbers"
}
```As a result, the html `code` element will have wrong language `language-{2}`:
_(The class `code-highlight` in the `code` element is added by the rehype plugin `rehype-prism-plus`)_```html
...
```The `remark-flexible-code-titles` not only adds `title` and `container` elements but also **corrects the language** producing the below `mdast` which will lead the `
` element has accurate language or not have language as it sould be.
```json
{
"type": "code",
"lang": null,
"meta": "{2} showLineNumbers"
}
``````html
```If there is no space between the parts (_title, line range string and "showLineNumbers"_), or there is extra spaces inside the _line range string_, line highlighting or numbering features by the rehype plugin will not work. **The `remark-flexible-code-titles` can handles and corrects this kind of mis-typed situations**.
````markdown
```typescript:title{ 1, 3 - 6 }showLineNumbers
content
```
````There is mis-typed syntax in above markdown example; and without `remark-flexible-code-titles` will cause to produce the following `mdast`; and the rehype plugin not to work properly:
```json
{
"type": "code",
"lang": "typescript:title{",
"meta": " 1, 3 - 6 }showLineNumbers"
}
```The `remark-flexible-code-titles` will correct the syntax and ensure to produce the following `mdast` and `html`:
```json
{
"type": "code",
"lang": "typescript",
"meta": "{1,3-6} showLineNumbers"
}
``````html
title
```#### Example for providing a title without any language
You can provide a `title` without any language just using a colon **`:`** at the beginning.
````markdown
```:title
content
```
```````html
title
content
```### Another flexible usage
You can use `remark-flexible-code-titles` **just for only correcting language, line highlighting and numbering syntax** on behalf of related rehype plugins.
```javascript
use(remarkCodeTitles, {
container: false,
title: false,
});
```Now, the `remark-flexible-code-titles` will not add any node, but will correct language, line highlighting and numbering syntax.
## Syntax tree
This plugin only modifies the mdast (markdown abstract syntax tree) as explained.
## Types
This package is fully typed with [TypeScript][typescript]. The plugin options' type is exported as `CodeTitleOptions`.
## Compatibility
This plugin works with `unified` version 6+ and `remark` version 7+. It is compatible with `mdx` version 2+.
## Security
Use of `remark-flexible-code-titles` does not involve rehype (hast) or user content so there are no openings for cross-site scripting (XSS) attacks.
## My Plugins
I like to contribute the Unified / Remark / MDX ecosystem, so I recommend you to have a look my plugins.
### My Remark Plugins
- [`remark-flexible-code-titles`](https://www.npmjs.com/package/remark-flexible-code-titles)
– Remark plugin to add titles or/and containers for the code blocks with customizable properties
- [`remark-flexible-containers`](https://www.npmjs.com/package/remark-flexible-containers)
– Remark plugin to add custom containers with customizable properties in markdown
- [`remark-ins`](https://www.npmjs.com/package/remark-ins)
– Remark plugin to add `ins` element in markdown
- [`remark-flexible-paragraphs`](https://www.npmjs.com/package/remark-flexible-paragraphs)
– Remark plugin to add custom paragraphs with customizable properties in markdown
- [`remark-flexible-markers`](https://www.npmjs.com/package/remark-flexible-markers)
– Remark plugin to add custom `mark` element with customizable properties in markdown
- [`remark-flexible-toc`](https://www.npmjs.com/package/remark-flexible-toc)
– Remark plugin to expose the table of contents via Vfile.data or via an option reference
- [`remark-mdx-remove-esm`](https://www.npmjs.com/package/remark-mdx-remove-esm)
– Remark plugin to remove import and/or export statements (mdxjsEsm)### My Rehype Plugins
- [`rehype-pre-language`](https://www.npmjs.com/package/rehype-pre-language)
– Rehype plugin to add language information as a property to `pre` element### My Recma Plugins
- [`recma-mdx-escape-missing-components`](https://www.npmjs.com/package/recma-mdx-escape-missing-components)
– Recma plugin to set the default value `() => null` for the Components in MDX in case of missing or not provided so as not to throw an error
- [`recma-mdx-change-props`](https://www.npmjs.com/package/recma-mdx-change-props)
– Recma plugin to change the `props` parameter into the `_props` in the `function _createMdxContent(props) {/* */}` in the compiled source in order to be able to use `{props.foo}` like expressions. It is useful for the `next-mdx-remote` or `next-mdx-remote-client` users in `nextjs` applications.## License
[MIT License](./LICENSE) © ipikuka
### Keywords
🟩 [unified][unifiednpm] 🟩 [remark][remarknpm] 🟩 [remark plugin][remarkpluginnpm] 🟩 [mdast][mdastnpm] 🟩 [markdown][markdownnpm] 🟩 [remark code titles][remarkcodetitlesnpm]
[unifiednpm]: https://www.npmjs.com/search?q=keywords:unified
[remarknpm]: https://www.npmjs.com/search?q=keywords:remark
[remarkpluginnpm]: https://www.npmjs.com/search?q=keywords:remark%20plugin
[mdastnpm]: https://www.npmjs.com/search?q=keywords:mdast
[markdownnpm]: https://www.npmjs.com/search?q=keywords:markdown
[remarkcodetitlesnpm]: https://www.npmjs.com/search?q=keywords:remark%20code%20titles[unified]: https://github.com/unifiedjs/unified
[remark]: https://github.com/remarkjs/remark
[remarkplugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md
[mdast]: https://github.com/syntax-tree/mdast
[micromark]: https://github.com/micromark/micromark
[typescript]: https://www.typescriptlang.org/
[rehypeprismplus]: https://github.com/timlrx/rehype-prism-plus[badge-npm-version]: https://img.shields.io/npm/v/remark-flexible-code-titles
[badge-npm-download]: https://img.shields.io/npm/dt/remark-flexible-code-titles
[npm-package-url]: https://www.npmjs.com/package/remark-flexible-code-titles[badge-license]: https://img.shields.io/github/license/ipikuka/remark-flexible-code-titles
[github-license-url]: https://github.com/ipikuka/remark-flexible-code-titles/blob/main/LICENSE[badge-build]: https://github.com/ipikuka/remark-flexible-code-titles/actions/workflows/publish.yml/badge.svg
[github-workflow-url]: https://github.com/ipikuka/remark-flexible-code-titles/actions/workflows/publish.yml[badge-typescript]: https://img.shields.io/npm/types/remark-flexible-code-titles
[typescript-url]: https://www.typescriptlang.org/