4个版本 (2个破坏性更新)

0.3.1 2020年6月10日
0.3.0 2020年6月2日
0.2.0 2020年5月26日
0.1.0 2020年5月25日

#2503 in 解析器实现

每月38次下载

自定义许可

200KB
1.5K SLoC

md-inc - 将文件包含在Markdown文档中

概览

Preview

  • 将外部文件包含到您的Markdown文档中 - 内联!
    • 输入插入在命令块和结束块之间
    • 覆盖之前的内容
  • 转换包含的文件
    • 将输入包裹在代码块或自定义文本中
    • 筛选特定行
    • 添加行号或其他行装饰
  • 通过.md-inc.toml文件轻松配置。
    • 指定1个或多个要转换的文件。
    • 指定用于相对文件包含的基路径。
    • 替换<!--{}-->标签 - 如果需要避免冲突或现有注释,则很有用。

示例

这是一个我们想在Markdown文档中包含的代码文件,file.rs

fn main() {
    println!("Hello, World!");
}

该文件可以使用命令标签包含,巧妙地伪装成注释,以便它们不在实际文档中渲染

Look at the following rust code:
<!--{ "file.rs" | code: rust }-->
<!--{ end }-->
This will print 'Hello World' to the console.

运行md-inc后,文件将被转换成

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.

注意:周围的```rust```行是插入的,因为我们通过code: rust命令将输入管道传输。稍后将有更多关于这个话题的讨论!

安装

cargo install md-inc

运行

md-inc [FLAGS] [OPTIONS] [files]...

如果没有指定文件,则使用.md-inc.toml中的files字段。

配置

.md-inc.toml可以通过设置以下任何一项进行配置

open_tag:命令的起始标签

# <!--{ COMMAND }-->
# ^^^^^
open_tag = "<!--{" 

close_tag:命令的结束标签

# <!--{ COMMAND }-->
#               ^^^^
close_tag = "}-->"

end_command:要使用的结束命令的名称

# <!--{ COMMAND }-->
# <<FILE_CONTENTS>>
# <!--{ end }-->
#       ^^^
end_command = "end"

base_dir:相对导入文件路径的基目录,相对于配置文件

# 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:要转换的文件列表,相对于配置文件

files = ["README.md", "doc/file.md"]

depend_dirs:包含 ".md-inc.toml" 的目录列表,在当前目录之前访问。

depend_dirs = ["doc/example1", "doc/example2"]

next_dirs:包含 ".md-inc.toml" 的目录列表,在当前目录之后访问。

next_dirs = ["doc/example1", "doc/example2"]

注意:"depend_dirs" 和 "next_dirs" 不会递归调用。

out_dir:生成文件的可选输出目录。如果定义了该值,则生成的文件将写入此目录而不是覆盖原始文件。

out_dir = "path/to/output"

命令

可以通过管道命令组合来操作包含的文件。

通用语法

包含 file.txt

<!--{ "file.txt }-->
<!--{ end }-->

在代码块中包含 file.txt

<!--{ "file.txt | code }-->
<!--{ end }-->

在带有 Python 语法高亮的代码块中包含 file.py

<!--{ "file.py" | code: python }-->
<!--{ end }-->

在带有 Python 语法高亮的代码块中仅包含 file.py 的第 4 到 10 行

<!--{ "file.py" | lines: 4 10 | code: python }-->
<!--{ end }-->
  • 第一个值应该是文件名。
  • 可以使用管道运算符 (|) 连接命令。"file.txt" | code
  • 某些命令在冒号 (:) 字符后可能需要空格分隔的参数。"file.txt | lines: 4 10"
  • 命令从左到右应用于包含的文件。

code: [language]

  • 将文件包裹在代码块(三重反引号)中
  • language:用于语法高亮的语言。如果提供,则直接添加到顶部反引号之后。

没有语言

<!--{ "doc/file.txt" | code }-->
```
FILE_CONTENTS
```
<!--{ end }-->

有语言

<!--{ "doc/file.html" | code: html }-->
```html
FILE_CONTENTS
```
<!--{ end }-->

lines:first[last]

  • 限制输入到给定的行范围
    • (包括行,如果 first <= line <= last)
  • first:要导入的第一行
  • last:要导入的最后一行(基于1的索引)
    • 如果没有提供 last,则从 first 到输入的末尾包含所有行。

给定文件,alphabet.txt

A
B
C
D
E

删除前导行

输入

<!--{ "alphabet.txt" | lines: 4 }-->
<!--{ end }-->

这保留第 4 行直到文件末尾。

输出

<!--{ "alphabet.txt" | lines: 4 }-->
D
E
<!--{ end }-->

删除尾随行

输入

<!--{ "alphabet.txt" | lines: 1 3 }-->
<!--{ end }-->

这仅保留第 1 到 3 行 输出:

<!--{ "alphabet.txt" | lines: 1 3 }-->
A
B
C
<!--{ end }-->

删除前导和尾随行

输入

<!--{ "alphabet.txt" | lines: 2 4 }-->
<!--{ end }-->

这仅保留第 2 到 4 行

输出

<!--{ "alphabet.txt" | lines: 2 4 }-->
B
C
D
<!--{ end }-->

line:list...

  • 限制输入到给定的行号列表(基于1的索引)。
  • list...:要包含的行号列表

输入

<!--{ "alphabet.txt" | line: 3 2 1 }-->
<!--{ end }-->

输出

<!--{ "alphabet.txt" | line: 3 2 1 }-->
C
B
A
<!--{ end }-->

line-numbers: [separator] [width]

  • 为每行添加行号
  • [separator]:行号和行其余部分之间使用的可选分隔符。
    • 如果没有提供,使用 :
  • [width]:行号的可选宽度。
    • 如果没有提供,则使用最长行号的宽度。

使用默认参数

输入

<!--{ "full_alphabet.txt" | line-numbers | lines: 8 14 }-->
<!--{ end }-->

输出

<!--{ "full_alphabet.txt" | line-numbers | lines: 8 14 }-->
 8: H
 9: I
10: J
11: K
12: L
13: M
14: N
<!--{ end }-->

使用提供的参数

输入

<!--{ "alphabet.txt" | line-numbers: " " 4 }-->
<!--{ end }-->

输出

<!--{ "alphabet.txt" | line-numbers: " " 4 }-->
   1 A
   2 B
   3 C
   4 D
   5 E
<!--{ end }-->

wrap: textwrap: before after

  • 在输入前后插入文本。
  • text:在输入前后插入的文本(不含换行符)
  • before:在输入前插入的文本(不含换行符)。
  • after:在输入后插入的文本(不含换行符)。

wrap-lines: textwrap-lines: before after

  • 在输入的每一行前后插入文本。
  • text:在输入的每一行前后插入的文本。
  • before:在输入的每一行前插入的文本。
  • after:在输入的每一行后插入的文本。

match:pattern[group_num]

  • 从匹配模式的文件中插入文本。
  • pattern:正则表达式模式
  • group_num:匹配 group_num 的捕获组将被插入。
    • 0 的 group_num 是整个正则表达式模式

对于文件,hello_world.rs

// Main
fn main() {
    println!("Hello, World!");
}
// Goodbye
fn goodbye() {
    println!("Goodbye, World!");
}

使用 match 命令可以从 main() 函数中提取

输入

<!--{ "hello_world.rs" | match: "\n(fn main[\s\S]*?\n\})" 1 | code: rust }-->
<!--{ end }-->

输出

<!--{ "hello_world.rs" | match: "\n(fn main[\s\S]*?\n\})" 1 | code: rust }-->
```rust
fn main() {
    println!("Hello, World!");
}
```
<!--{ end }-->

依赖关系

~5–7MB
~114K SLoC