forked from gbdev/gb-asm-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move admonition markup processing to preproc instead of renderer
This lets them work with `mdbook serve` (which hardcodes the HTML renderer), and at the same time is more robust (no more running regexes against HTML output!). The syntax was slightly adjusted to be closer to established VuePress etc.
- Loading branch information
Showing
24 changed files
with
171 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* This Source Code Form is subject to the | ||
* terms of the Mozilla Public License, v. | ||
* 2.0. If a copy of the MPL was not | ||
* distributed with this file, You can | ||
* obtain one at | ||
* http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
use std::{format, iter::Peekable, matches}; | ||
|
||
use anyhow::Error; | ||
use mdbook::book::Chapter; | ||
use pulldown_cmark::{Event, Options, Parser, Tag}; | ||
|
||
use crate::GbAsmTut; | ||
|
||
impl GbAsmTut { | ||
pub fn process_admonitions(&self, chapter: &mut Chapter) -> Result<(), Error> { | ||
let mut buf = String::with_capacity(chapter.content.len()); | ||
let extensions = | ||
Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES | Options::ENABLE_STRIKETHROUGH; | ||
|
||
let events = AdmonitionsGenerator::new(Parser::new_ext(&chapter.content, extensions)); | ||
|
||
pulldown_cmark_to_cmark::cmark(events, &mut buf, None) | ||
.map_err(|err| Error::from(err).context("Markdown serialization failed"))?; | ||
chapter.content = buf; | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
struct AdmonitionsGenerator<'a, Iter: Iterator<Item = Event<'a>>> { | ||
iter: Peekable<Iter>, | ||
nesting_level: usize, | ||
at_paragraph_start: bool, | ||
} | ||
|
||
impl<'a, Iter: Iterator<Item = Event<'a>>> AdmonitionsGenerator<'a, Iter> { | ||
const KINDS: [&'static str; 3] = ["tip", "warning", "danger"]; | ||
|
||
fn new(iter: Iter) -> Self { | ||
Self { | ||
iter: iter.peekable(), | ||
nesting_level: 0, | ||
at_paragraph_start: false, | ||
} | ||
} | ||
} | ||
|
||
impl<'a, Iter: Iterator<Item = Event<'a>>> Iterator for AdmonitionsGenerator<'a, Iter> { | ||
type Item = Event<'a>; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
let mut evt = self.iter.next()?; | ||
|
||
match evt { | ||
Event::Text(ref text) if self.at_paragraph_start => { | ||
if let Some(params) = text.strip_prefix(":::") { | ||
// Check that there is no more text in the paragraph; if there isn't, we'll consume the entire paragraph. | ||
// Note that this intentionally rejects any formatting within the paragraph—serialisation would be too complex. | ||
if matches!(self.iter.peek(), Some(Event::End(Tag::Paragraph))) { | ||
if params.is_empty() { | ||
if self.nesting_level != 0 { | ||
// Ending an admonition. | ||
self.nesting_level -= 1; | ||
|
||
evt = Event::Html("</div>".into()); | ||
} | ||
} else { | ||
let (kind, title) = | ||
match params.split_once(|c: char| c.is_ascii_whitespace()) { | ||
Some((kind, title)) => (kind, title.trim()), | ||
None => (params, ""), | ||
}; | ||
let (kind, decoration) = match kind.split_once(':') { | ||
Some((kind, decoration)) => (kind, Some(decoration)), | ||
None => (kind, None), | ||
}; | ||
if Self::KINDS.contains(&kind) { | ||
// Beginning an admonition. | ||
self.nesting_level += 1; | ||
|
||
evt = Event::Html( | ||
if let Some(decoration) = decoration { | ||
if title.is_empty() { | ||
format!("<div class=\"box {kind} decorated\"><p>{decoration}</p>") | ||
} else { | ||
format!("<div class=\"box {kind} decorated\"><p>{decoration}</p><p class=\"box-title\">{title}</p>") | ||
} | ||
} else if title.is_empty() { | ||
format!("<div class=\"box {kind}\">") | ||
} else { | ||
format!("<div class=\"box {kind}\"><p class=\"box-title\">{title}</p>") | ||
} | ||
.into(), | ||
); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
_ => {} | ||
} | ||
|
||
self.at_paragraph_start = matches!(evt, Event::Start(Tag::Paragraph)); | ||
|
||
Some(evt) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.