#markdown-parser #tags #extended #pulldown-cmark #events #footnotes #quote

extended_pulldown

包装 pulldown-cmark,为图书出版提供扩展功能

1 个不稳定版本

0.1.0 2020 年 10 月 23 日

#10 in #pulldown-cmark

35 次每月下载
4 个 crate 中使用 (3 直接使用)

MIT/Apache

87KB
2K SLoC

基于 pulldown_cmark 的 markdown 扩展定义和解析器,允许一些额外的事件和排版美观功能,如上标和下标。


lib.rs:

此 crate 扩展 pulldown_cmark 以实现以下功能

  • 根据更复杂但实质上更慢的算法智能引号,该算法比 8.0 以上版本的 pulldown_cmark 中使用的算法更复杂

  • 将 Unicode 的破折号、长破折号和省略号替换为 -----...

  • 通过将脚注内的缩进且未标记的代码块解释为要再次解析的文本,允许多段落脚注。

  • 允许几个新的标签

    • 无衬线
    • 居中
    • 右对齐
    • 小写字母
    • 下标
    • 上标

它还提供了一个函数 flatten_footnotes,该函数将脚注引用和定义替换为单个带标签的文本组;这使得渲染到需要将脚注定义在引用点的目标(如 LaTeX)成为可能。如果缺少定义,则插入空脚注。

总的来说,此 crate 模仿了 pulldown_cmark 的结构和方法。然而,它对 markdown 的更复杂概念以牺牲解析速度为代价。因此,除非需要这种复杂性,否则不推荐使用它来替代 pulldown_cmark

否则使用的 markdown 语法基本上是 CommonMark 的语法,以及 pulldown_cmark 的扩展。

示例

内联 Span

这些优先从 html span 解析

use extended_pulldown::Parser;
use extended_pulldown::Event::*;
use extended_pulldown::Tag::*;

let text = concat!(r#"<span class="sans">Sans text</span>"#,
r#"<span class="centred">Centred text</span>"#,
r#"<span class="right-aligned">Right-aligned text</span>"#,
r#"<span class="smallcaps">Small caps text</span>"#,
r#"<span class="subscript">Subscript text</span>"#,
r#"<span class="superscript">Superscript text</span>"#);
   
let parsed = Parser::new(text)
    .collect::<Vec<_>>();
let expected = vec![
    Start(Paragraph),
    Start(Sans),
    Text("Sans text".into()),
    End(Sans),
    Start(Centred),
    Text("Centred text".into()),
    End(Centred),
    Start(RightAligned),
    Text("Right-aligned text".into()),
    End(RightAligned),
    Start(SmallCaps),
    Text("Small caps text".into()),
    End(SmallCaps),
    Start(Subscript),
    Text("Subscript text".into()),
    End(Subscript),
    Start(Superscript),
    Text("Superscript text".into()),
    End(Superscript),
    End(Paragraph)
];
 assert_eq!(parsed, expected);

然而,Markdown语法也略有扩展,允许用^将数字或字母文本括起来表示上标,用~表示下标:例如25^th^ JulyH~2~O

多行脚注

use extended_pulldown::Parser;
use extended_pulldown::Event::*;
use extended_pulldown::Tag::*;
use pulldown_cmark::CodeBlockKind::Indented;
let text = "Hello World[^footnote]\n\n[^footnote]:\n\tA footnote\n\n\tIn *multiple* pieces";
let output = Parser::new(text)
    .collect::<Vec<_>>();
let pulldown_output = vec![
    Start(Paragraph),
    Text("Hello World".into()),
    FootnoteReference("footnote".into()),
    End(Paragraph),
    Start(FootnoteDefinition("footnote".into())),
    Start(CodeBlock(Indented)),
    Text("A footnote\n\n".into()),
    Text("In *multiple* pieces".into()),
    End(CodeBlock(Indented)),
    End(FootnoteDefinition("footnote".into()))
];
let extended_pulldown_output = vec![
    Start(Paragraph),
    Text("Hello World".into()),
    FootnoteReference("footnote".into()),
    End(Paragraph),
    Start(FootnoteDefinition("footnote".into())),
    Start(Paragraph),
    Text("A footnote".into()),
    End(Paragraph),
    Start(Paragraph),
    Text("In ".into()),
    Start(Emphasis),
    Text("multiple".into()),
    End(Emphasis),
    Text(" pieces".into()),
    End(Paragraph),
    End(FootnoteDefinition("footnote".into()))
];
assert!(output != pulldown_output);
assert_eq!(output, extended_pulldown_output);

脚注展平

use extended_pulldown::Event::*;
use extended_pulldown::Tag;

let events = vec![
  Start(Tag::Paragraph),
  Text("Hello".into()),
  FootnoteReference("1".into()),
 End(Tag::Paragraph),
  Start(Tag::FootnoteDefinition("1".into())),
  Start(Tag::Paragraph),
  Text("World".into()),
 End(Tag::Paragraph),
  End(Tag::FootnoteDefinition("1".into())),
];

let flattened = extended_pulldown::flatten_footnotes(events);
let expected = vec![
  Start(Tag::Paragraph),
  Text("Hello".into()),
  Start(Tag::FlattenedFootnote),
  Text("World".into()),
  End(Tag::FlattenedFootnote),
  End(Tag::Paragraph)
];

assert_eq!(flattened, expected);

依赖关系

~5MB
~87K SLoC