4 releases (2 breaking)
0.3.1 | Jun 10, 2020 |
---|---|
0.3.0 | Jun 2, 2020 |
0.2.0 | May 26, 2020 |
0.1.0 | May 25, 2020 |
#2847 in Parser implementations
200KB
1.5K
SLoC
md-inc
- Include files in Markdown docs
Overview
- Include external files into your markdown documents - inline!
- Input is inserted between command block and end block
- Overwrites anything that was previously there
- Transform included files
- Wrap your input in code blocks or custom text
- Filter specific lines
- Add line numbers or other line decorators
- Easily configure with
.md-inc.toml
file.- Specify 1 or more files to transform.
- Specify base path used for relative file includes.
- Replace
<!--{
and}-->
tags - useful if you need to avoid conflicts or existing comments.
Example
Here is a code file, file.rs
, that we want to include in our Markdown document:
fn main() {
println!("Hello, World!");
}
The file can be included using command tags, sneakily disguised as comments so they aren't rendered in the actual document:
Look at the following rust code:
<!--{ "file.rs" | code: rust }-->
<!--{ end }-->
This will print 'Hello World' to the console.
After running md-inc
, the file will be transformed into:
Look at the following rust code:
<!--{ "file.rs" | code: rust }-->
```rust
fn main() {
println!("Hello, World!");
}
```
<!--{ end }-->
This will print 'Hello World' to the console.
Note: The surrounding ```rust
and ```
lines were inserted
because we piped the input into the code: rust
command. More on this later!
Install
cargo install md-inc
Run
md-inc [FLAGS] [OPTIONS] [files]...
If no files are given, the files
field in .md-inc.toml
is used.
Configuration
.md-inc.toml
can be configured by setting any of the following:
open_tag
: The opening tag for a command
# <!--{ COMMAND }-->
# ^^^^^
open_tag = "<!--{"
close_tag
: The closing tag for a command
# <!--{ COMMAND }-->
# ^^^^
close_tag = "}-->"
end_command
: The name to use for the end command
# <!--{ COMMAND }-->
# <<FILE_CONTENTS>>
# <!--{ end }-->
# ^^^
end_command = "end"
base_dir
: The base directory for relative imported file paths, relative to the config file
# For the directory tree:
# ├╼ README.md
# ├╼ .md-inc.toml
# ╰╼ doc
# ├╼ file.txt
# ╰╼ other
# ╰╼ file2.txt
# If base_dir = "doc", then files can be named relative to doc
# <!--{ "file.txt" }-->
# ...
# <!--{ "other/file2.txt" }-->
base_dir = "doc"
files
: A list of files to be transformed, relative to the config file
files = ["README.md", "doc/file.md"]
depend_dirs
:
A list of directories containing ".md-inc.toml" that will be visited before this one.
depend_dirs = ["doc/example1", "doc/example2"]
next_dirs
:
A list of directories containing ".md-inc.toml" that will be visited after this one.
next_dirs = ["doc/example1", "doc/example2"]
Note: "depend_dirs" and "next_dirs" are NOT called recursively.
out_dir
:
An optional output directory for generated files.
If this is defined, the generated files will be written to this directory
instead of overwriting the original files.
out_dir = "path/to/output"
Commands
Included files can be manipulated by piping commands together.
General Syntax:
Include file.txt
:
<!--{ "file.txt }-->
<!--{ end }-->
Include file.txt
inside a code block:
<!--{ "file.txt | code }-->
<!--{ end }-->
Include file.py
inside a code block with python syntax highlighting:
<!--{ "file.py" | code: python }-->
<!--{ end }-->
Include only lines 4 to 10 of file.py
inside a code block with python syntax highlighting:
<!--{ "file.py" | lines: 4 10 | code: python }-->
<!--{ end }-->
- The first value should always be the filename.
- Commands can be chained together using the pipe (
|
) operator."file.txt" | code
- Some commands may take space-separated arguments after a colon (
:
) character."file.txt | lines: 4 10
- Commands are applied to the included file from left to right.
code: [language]
- Wraps the file in a code block (triple backticks)
language
: the language used for syntax highlighting. If given, this will be added directly after the top backticks.
Without language:
<!--{ "doc/file.txt" | code }-->
```
FILE_CONTENTS
```
<!--{ end }-->
With language:
<!--{ "doc/file.html" | code: html }-->
```html
FILE_CONTENTS
```
<!--{ end }-->
lines: first [last]
- Restricts the input to the given range of lines
- (include line, if
first <= line <= last
)
- (include line, if
first
: The first line to importlast
: The last line to import (1-based index)- If
last
is not provided, all lines will be included fromfirst
until the end of the input.
- If
Given the file, alphabet.txt:
A
B
C
D
E
Trim leading lines
Input:
<!--{ "alphabet.txt" | lines: 4 }-->
<!--{ end }-->
This keeps the 4th line until the end of the file.
Output:
<!--{ "alphabet.txt" | lines: 4 }-->
D
E
<!--{ end }-->
Trim trailing lines
Input:
<!--{ "alphabet.txt" | lines: 1 3 }-->
<!--{ end }-->
This keeps only lines 1 to 3 Output:
<!--{ "alphabet.txt" | lines: 1 3 }-->
A
B
C
<!--{ end }-->
Trim both leading and trailing lines
Input:
<!--{ "alphabet.txt" | lines: 2 4 }-->
<!--{ end }-->
This keeps only lines 2 to 4
Output:
<!--{ "alphabet.txt" | lines: 2 4 }-->
B
C
D
<!--{ end }-->
line: list...
- Restricts the input to the given list of line numbers (1-based index).
list...
: A list of line numbers to included
Input:
<!--{ "alphabet.txt" | line: 3 2 1 }-->
<!--{ end }-->
Output:
<!--{ "alphabet.txt" | line: 3 2 1 }-->
C
B
A
<!--{ end }-->
line-numbers: [separator] [width]
- Adds a line number to each line
[separator]
: Optional separator used between the line number and the rest of the line.- If not provided,
:
is used.
- If not provided,
[width]
: Optional width for line numbers.- If not provided, the width of the longest line number is used.
With Default Arguments:
Input:
<!--{ "full_alphabet.txt" | line-numbers | lines: 8 14 }-->
<!--{ end }-->
Output:
<!--{ "full_alphabet.txt" | line-numbers | lines: 8 14 }-->
8: H
9: I
10: J
11: K
12: L
13: M
14: N
<!--{ end }-->
With Provided Arguments:
Input:
<!--{ "alphabet.txt" | line-numbers: " " 4 }-->
<!--{ end }-->
Output:
<!--{ "alphabet.txt" | line-numbers: " " 4 }-->
1 A
2 B
3 C
4 D
5 E
<!--{ end }-->
wrap: text
or wrap: before after
- Inserts text before and after the input.
text
: Text that is inserted before and after the input (no newline)before
: Text that is inserted before the input (no newline).after
: Text that is inserted after the input (no newline).
wrap-lines: text
or wrap-lines: before after
- Inserts text before and after each line of the input.
text
: Text that is inserted before and after each line of the input.before
: Text that is inserted before each line of the input.after
: Text that is inserted after each line of the input.
match: pattern [group_num]
- Inserts text from a file that matches the pattern.
pattern
: A regex patterngroup_num
: The capture group matchinggroup_num
is inserted.- A group_num of
0
is the whole regex pattern
- A group_num of
For a file, hello_world.rs
:
// Main
fn main() {
println!("Hello, World!");
}
// Goodbye
fn goodbye() {
println!("Goodbye, World!");
}
The main()
function can be extracted using the match
command:
Input:
<!--{ "hello_world.rs" | match: "\n(fn main[\s\S]*?\n\})" 1 | code: rust }-->
<!--{ end }-->
Output:
<!--{ "hello_world.rs" | match: "\n(fn main[\s\S]*?\n\})" 1 | code: rust }-->
```rust
fn main() {
println!("Hello, World!");
}
```
<!--{ end }-->
Dependencies
~8.5MB
~150K SLoC