Skip to content

Commit

Permalink
Support anchors.
Browse files Browse the repository at this point in the history
  • Loading branch information
KmolYuan committed Jul 25, 2021
1 parent 183a131 commit d353f45
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The vertical slides work under the `sub` node of first slide, the attributes are
- title: Vertical slide 2
- title: Horizontal slide 2
```
This work supports YAML 1.2 without anchor function.
This work supports YAML 1.2, and anchor function for specific fields.

### Layout

Expand Down
14 changes: 14 additions & 0 deletions src/assets/reveal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,17 @@ footer:
There are also have **markdown** *syntax*!
```
- title: Anchors
doc: |
```yaml
$hstack:
- &content
doc: Content A
- *content
- *content
```
$hstack:
- &content
doc: Content A
- *content
- *content
43 changes: 30 additions & 13 deletions src/loader/content.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use pulldown_cmark::{html::push_html, CodeBlockKind, Event, Options, Parser, Tag};
use std::{collections::HashMap, fs::read_to_string};
use yaml_peg::{Node, Yaml};
use yaml_peg::{Anchors, Node, Yaml};

const MARKED: Options = Options::from_bits_truncate(
Options::ENABLE_TABLES.bits()
Expand Down Expand Up @@ -36,9 +36,21 @@ fn marked(e: Event) -> Event {
}

pub(crate) fn md2html(text: &str) -> String {
let mut out = String::new();
push_html(&mut out, Parser::new_ext(text, MARKED).map(marked));
out
if text.is_empty() {
"".to_string()
} else {
let mut out = String::new();
push_html(&mut out, Parser::new_ext(text, MARKED).map(marked));
out
}
}

fn math(text: &str) -> String {
if text.is_empty() {
"".to_string()
} else {
format!("\\[{}\\]", text)
}
}

struct FragMap(HashMap<String, HashMap<usize, String>>);
Expand All @@ -61,6 +73,9 @@ impl FragMap {
}

fn fragment(&mut self, tag: &str, inner: &str) -> String {
if inner.is_empty() {
return "".to_string();
}
let tag = tag.to_string();
let mut head = String::new();
let mut end = String::new();
Expand Down Expand Up @@ -117,23 +132,25 @@ fn video_block(video: &Node) -> Result<String, Error> {
Ok(doc)
}

pub(crate) fn content_block(slide: &Node, frag_count: &mut usize) -> Result<String, Error> {
pub(crate) fn content_block(
slide: &Node,
v: &Anchors,
frag_count: &mut usize,
) -> Result<String, Error> {
let mut doc = String::new();
let mut frag = FragMap::new(slide, frag_count)?;
let mut t = slide.get_default("doc", "", Node::as_str)?;
if !t.is_empty() {
doc += &frag.fragment("doc", &md2html(t));
if let Ok(n) = slide.get("doc") {
doc += &frag.fragment("doc", &md2html(n.as_anchor(v).as_str()?));
}
if let Ok(n) = slide.get("include") {
t = n.as_str()?;
let t = n.as_str()?;
if !t.is_empty() {
let include = read_to_string(t).map_err(|_| ("read file error", n.pos()))?;
doc += &frag.fragment("include", &md2html(&include));
}
}
t = slide.get_default("math", "", Node::as_str)?;
if !t.is_empty() {
doc += &frag.fragment("math", &format!("\\[{}\\]", t));
if let Ok(n) = slide.get("math") {
doc += &frag.fragment("math", &math(n.as_anchor(v).as_str()?));
}
let media: [(_, fn(&Node) -> Result<String, Error>); 2] =
[("img", img_block), ("video", video_block)];
Expand Down Expand Up @@ -184,7 +201,7 @@ pub(crate) fn content_block(slide: &Node, frag_count: &mut usize) -> Result<Stri
""
};
doc += &format!("<div{}{}>", border, head);
doc += &content_block(slide, frag_count)?;
doc += &content_block(&slide.as_anchor(v), v, frag_count)?;
doc += "</div>";
}
doc += "</div>";
Expand Down
36 changes: 24 additions & 12 deletions src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use self::content::*;
use std::io::{Error as IoError, ErrorKind};
use yaml_peg::{indicated_msg, parse, repr::RcRepr, Array, Node};
use yaml_peg::{indicated_msg, parse, repr::RcRepr, Anchors, Array, Node};

mod content;

Expand Down Expand Up @@ -65,7 +65,20 @@ impl Background {
}
}

fn slide_block(slide: &Node, bg: &Background, first_column: bool) -> Result<String, Error> {
fn note(text: &str) -> String {
if text.is_empty() {
"".to_string()
} else {
format!("<aside class=\"notes\">{}</aside>", text)
}
}

fn slide_block(
slide: &Node,
v: &Anchors,
bg: &Background,
first_column: bool,
) -> Result<String, Error> {
if slide.as_map()?.is_empty() {
return Err(Error("empty slide", slide.pos()));
}
Expand Down Expand Up @@ -105,10 +118,9 @@ fn slide_block(slide: &Node, bg: &Background, first_column: bool) -> Result<Stri
doc += ">";
}
}
doc += &content_block(slide, &mut 0)?;
t = slide.get_default("note", "", Node::as_str)?;
if !t.is_empty() {
doc += &format!("<aside class=\"notes\">{}</aside>", md2html(&t));
doc += &content_block(slide, v, &mut 0)?;
if let Ok(n) = slide.get("note") {
doc += &note(&md2html(n.as_anchor(v).as_str()?));
}
doc += "</section>";
Ok(doc)
Expand Down Expand Up @@ -181,17 +193,18 @@ fn footer_block(meta: &Node) -> Result<String, Error> {
Ok(doc)
}

fn load_main(yaml: Array<RcRepr>, mount: &str) -> Result<String, Error> {
fn load_main(yaml: Array<RcRepr>, v: &Anchors, mount: &str) -> Result<String, Error> {
let mut title = String::new();
let meta = &yaml[0];
let slides = yaml[1].as_array()?;
let bg = Background::new(meta)?;
let mut doc = String::new();
for (i, slide) in slides.iter().enumerate() {
let slide = slide.as_anchor(v);
doc += "<section>";
doc += &slide_block(slide, &bg, i == 0)?;
doc += &slide_block(&slide, v, &bg, i == 0)?;
for slide in slide.get_default("sub", &vec![], Node::as_array)? {
doc += &slide_block(slide, &bg, false)?;
doc += &slide_block(&slide.as_anchor(v), v, &bg, false)?;
}
if i == 0 {
title += slide.get_default("title", "", Node::as_str)?;
Expand Down Expand Up @@ -258,15 +271,14 @@ fn load_main(yaml: Array<RcRepr>, mount: &str) -> Result<String, Error> {

/// Load YAML string as HTML.
pub fn loader(yaml_str: &str, mount: &str) -> Result<String, IoError> {
// TODO: anchors
let (yaml, _anchor) = parse(yaml_str).map_err(|s| IoError::new(ErrorKind::InvalidData, s))?;
let (yaml, anchor) = parse(yaml_str).map_err(|s| IoError::new(ErrorKind::InvalidData, s))?;
if yaml.len() < 2 {
return Err(IoError::new(
ErrorKind::InvalidData,
"Missing metadata or slides".to_string(),
));
}
load_main(yaml, mount).map_err(|Error(name, pos)| {
load_main(yaml, &anchor, mount).map_err(|Error(name, pos)| {
IoError::new(
ErrorKind::InvalidData,
format!("{}:\n{}", name, indicated_msg(yaml_str, pos)),
Expand Down

0 comments on commit d353f45

Please sign in to comment.