With this plugin, you can use ::include{file=./included.md}
GitLab transclusion syntax
statements to compose markdown files together.
Additional features:
- GitLab
::includedirectives are ignored inside the included file, but this plugin supports recursive transclusion - It is possible to use globs (
::include{file=./included*.md}) infileattribute - New attribute
optional. This attribute prevents fatal errors from occurring when the file (or files) specified by thefileattribute does not exist - Relative images and links in the imported files will have their paths rewritten
to be relative to the original document rather than the imported file
(with
@it-service-npm/remark-relative-url-adjustment) - An imported markdown file will “inherit” the heading levels.
If the
::include{file=./included.md}statement happens under Heading 2, for example, any heading 1 in the included file will be “translated” to have header level 3 (with@it-service-npm/remark-heading-adjustment)
This plugin is a modern version of
remark-import plugin
and remark-include plugin,
written in Typescript, and compatible with Remark v15.
There are two plugins: remarkInclude (preferred) and remarkIncludeSync.
Important
remark-directive plugin expected before
@it-service-npm/remark-include.
This package provides two plugins presets:
-
remarkIncludePreset. This preset contains:remarkIncluderemarkDirectiveremarkHeadingsAdjustmentremarkRelativeUrlsAdjustmentremarkRelativeCodePathsAdjustment
-
remarkIncludePresetSync. This preset contains:remarkIncludeSyncremarkDirectiveremarkHeadingsAdjustmentremarkRelativeUrlsAdjustmentremarkRelativeCodePathsAdjustment
npm install --save-dev @it-service-npm/remark-include@it-service-npm/remark-include can include sub-documents in markdown document.
Tip
This plugin has two named entry points:
- ‘sync’ ('@it-service-npm/remark-include/sync’)
- ‘async’ ('@it-service-npm/remark-include/async’)
With sync and async plugin function and preset.
Async plugin using example:
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import { remarkIncludePreset } from '@it-service-npm/remark-include/async';
import type { VFile } from 'vfile';
export async function remarkDirectiveUsingExample(
filePath: string
): Promise<VFile> {
return remark()
.use(remarkIncludePreset)
.process(await vFile.read(filePath));
};Source files:
main.md:
Hello. I am an main markdown file with `::include` directive.
::include{file=./included1.md}
After first file.
::include{file="./included 2.md"}
After second file.
_That_ should do it!included1.md:
Hello. I am the included1 file.included 2.md:
Hello. I am the included2 file.Remark output:
Hello. I am an main markdown file with `::include` directive.
Hello. I am the included1 file.
After first file.
Hello. I am the included2 file.
After second file.
*That* should do it!@it-service-npm/remark-include supports recursive transclusion.
Tip
This plugin has two named entry points:
- ‘sync’ ('@it-service-npm/remark-include/sync’)
- ‘async’ ('@it-service-npm/remark-include/async’)
With sync and async plugin function and preset.
Sync plugin using example:
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import { remarkIncludePreset } from '@it-service-npm/remark-include/sync';
import type { VFile } from 'vfile';
export function remarkDirectiveUsingExample(
filePath: string
): VFile {
return remark()
.use(remarkIncludePreset)
.processSync(vFile.readSync(filePath));
};Source files:
main.md:
Hello. I am an main markdown file with `::include` directive.
::include{file=./included1.md}
_That_ should do it!included1.md:
Hello. I am the included1 file with `::include` directive
for recursive transclusion example.
::include{file=./included2.md}included2.md:
Hello. I am the included2 file.Remark output:
Hello. I am an main markdown file with `::include` directive.
Hello. I am the included1 file with `::include` directive
for recursive transclusion example.
Hello. I am the included2 file.
*That* should do it!@it-service-npm/remark-include adjusts the headings level within the included content.
An imported markdown file will “inherit” the headings level.
If the ::include{file=./included.md} statement happens under Heading 2,
for example, any Heading 1 in the included file
will be “translated” to have header level 3
(with @it-service-npm/remark-heading-adjustment)
Source files:
main.md:
# Main file
Hello. I am an main markdown file with `::include` directive.
::include{file=./included1.md}
## H2 in main file
End of main file.included1.md:
# included1 file H1 (should be changed to H2 in output file)
Hello. I am the included1.
## in included1 file H2 (should be changed to H3 in output file)
::include{file=./included2.md}
## in included1 file after included2 H2 (should be changed to H3 in output file)
text text text.included2.md:
# included2 file H1 (should be changed to H4 in output file)
Hello. I am the included2.Remark output:
# Main file
Hello. I am an main markdown file with `::include` directive.
## included1 file H1 (should be changed to H2 in output file)
Hello. I am the included1.
### in included1 file H2 (should be changed to H3 in output file)
#### included2 file H1 (should be changed to H4 in output file)
Hello. I am the included2.
### in included1 file after included2 H2 (should be changed to H3 in output file)
text text text.
## H2 in main file
End of main file.@it-service-npm/remark-include supports
glob
as file attribute value.
Source files:
main.md:
# main file
Hello. I am an main markdown file with `::include` directive.
::include{file=./included*.md}
_That_ should do it!included1.md:
# included 1
Hello. I am the included1.included2.md:
# included 2
Hello. I am the included2.included3.md:
# included 3
Hello. I am the included3.Remark output:
# main file
Hello. I am an main markdown file with `::include` directive.
## included 1
Hello. I am the included1.
## included 2
Hello. I am the included2.
## included 3
Hello. I am the included3.
*That* should do it!Relative images and links in the imported files will have their paths rewritten to be relative to the original document rather than the imported file.
Source files:
main.md:
Hello. I am an main markdown file with `::include` directive.
::include{file=./subfolder1/included.md}
_That_ should do it!included.md:
Hello. I am the included. Test image:


Remark output:
Hello. I am an main markdown file with `::include` directive.
Hello. I am the included. Test image:



*That* should do it!Relative images and links in the imported files will have their paths rewritten to be relative to the original document rather than the imported file.
Source files:
main.md:
Hello. I am an main markdown file with `::include` directive.
::include{file=./subfolder1/included.md}
_That_ should do it!included.md:
Hello. I am the included. Test for code file path rebasing:
```typescript file=../../example.ts
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import remarkDirective from 'remark-directive';
import { remarkInclude } from '@it-service-npm/remark-include';
import type { VFile } from 'vfile';
export async function remarkDirectiveUsingExample(
filePath: string
): Promise<VFile> {
return remark()
.use(remarkDirective)
.use(remarkInclude)
.process(await vFile.read(filePath));
};
```
Code with file path with spaces and lines range:
```typescript file=code\ with\ spaces.ts#L11-L15
return remark()
.use(remarkDirective)
.use([codeImport])
.use(remarkInclude)
.process(await vFile.read(filePath));
```
And code without file attribute:
```typescript
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import remarkDirective from 'remark-directive';
import { remarkInclude } from '@it-service-npm/remark-include';
import type { VFile } from 'vfile';
```Remark output:
Hello. I am an main markdown file with `::include` directive.
Hello. I am the included. Test for code file path rebasing:
```typescript file=../example.ts
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import remarkDirective from 'remark-directive';
import { remarkInclude } from '@it-service-npm/remark-include';
import type { VFile } from 'vfile';
export async function remarkDirectiveUsingExample(
filePath: string
): Promise<VFile> {
return remark()
.use(remarkDirective)
.use(remarkInclude)
.process(await vFile.read(filePath));
};
```
Code with file path with spaces and lines range:
```typescript file=subfolder1/code\ with\ spaces.ts#L11-L15
return remark()
.use(remarkDirective)
.use([codeImport])
.use(remarkInclude)
.process(await vFile.read(filePath));
```
And code without file attribute:
```typescript
import { remark } from 'remark';
import * as vFile from 'to-vfile';
import remarkDirective from 'remark-directive';
import { remarkInclude } from '@it-service-npm/remark-include';
import type { VFile } from 'vfile';
```
*That* should do it!Please, read the API reference.
Do not edit this file. It is a report generated by API Extractor.
import type { Plugin } from 'unified';
import type { Preset } from 'unified';
import type { Root } from 'mdast';
// @public
export const remarkInclude: Plugin<[], Root>;
// @public
const remarkIncludePreset: Preset;
export default remarkIncludePreset;
export { remarkIncludePreset }
// @public
export const remarkIncludePresetSync: Preset;
// @public
export const remarkIncludeSync: Plugin<[], Root>;