Skip to content

Commit

Permalink
Split out submodules.
Browse files Browse the repository at this point in the history
  • Loading branch information
KmolYuan committed Jul 26, 2021
1 parent 335b388 commit 4216bf6
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 242 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, and anchor function for specific fields.
This work supports YAML 1.2, and anchor function for specific fields, such as content blocks.

### Layout

Expand Down
46 changes: 46 additions & 0 deletions src/loader/background.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use yaml_peg::Node;

#[derive(Default)]
pub(crate) struct Background {
src: String,
size: String,
position: String,
repeat: String,
opacity: String,
}

impl Background {
pub(crate) fn new(meta: &Node) -> Result<Self, u64> {
if let Ok(n) = meta.get("background") {
Ok(Self {
src: n.get_default("src", "", Node::as_str)?.to_string(),
size: n.get_default("size", "", Node::as_value)?.to_string(),
position: n.get_default("position", "", Node::as_value)?.to_string(),
repeat: n.get_default("repeat", "", Node::as_value)?.to_string(),
opacity: n.get_default("opacity", "", Node::as_value)?.to_string(),
})
} else {
Ok(Self::default())
}
}

pub(crate) fn is_valid(&self) -> bool {
!self.src.is_empty()
}

pub(crate) fn attr(&self) -> String {
let mut doc = String::new();
for (attr, member) in [
("", &self.src),
("-size", &self.size),
("-position", &self.position),
("-repeat", &self.repeat),
("-opacity", &self.opacity),
] {
if !member.is_empty() {
doc += &format!(" data-background{}=\"{}\"", attr, member);
}
}
doc
}
}
42 changes: 42 additions & 0 deletions src/loader/content/frag_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use super::Error;
use std::collections::HashMap;
use yaml_peg::Node;

pub(crate) struct FragMap(HashMap<String, HashMap<usize, String>>);

impl FragMap {
pub(crate) fn new(slide: &Node, count: &mut usize) -> Result<Self, Error> {
let mut frag_map = HashMap::new();
for h in slide.get_default("fragment", vec![], Node::as_array)? {
for (k, v) in h.as_map()?.iter() {
let k = k.as_str()?;
let v = v.as_str()?;
if !frag_map.contains_key(k) {
frag_map.insert(k.to_string(), HashMap::new());
}
frag_map.get_mut(k).unwrap().insert(*count, v.to_string());
}
*count += 1;
}
Ok(Self(frag_map))
}

pub(crate) 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();
if let Some(frag) = self.0.get(&tag) {
for (index, frag) in frag {
head += &format!(
"<span class=\"fragment {}\" data-fragment-index=\"{}\">",
frag, index
);
end += "</span>";
}
}
head + inner + &end
}
}
43 changes: 43 additions & 0 deletions src/loader/content/marked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use pulldown_cmark::{html::push_html, CodeBlockKind, Event, Options, Parser, Tag};

const MARKED: Options = Options::from_bits_truncate(
Options::ENABLE_TABLES.bits()
| Options::ENABLE_SMART_PUNCTUATION.bits()
| Options::ENABLE_TASKLISTS.bits()
| Options::ENABLE_STRIKETHROUGH.bits(),
);

fn marked(e: Event) -> Event {
match e {
// Support line number for code block
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(info))) => {
let info = info.replace(' ', "");
let mut head = String::new();
if info.is_empty() {
head += "<pre><code>"
} else {
let lang = info.split('[').next().unwrap();
let line = info
.replace(lang, "")
.replace(|s| (s == '[') | (s == ']'), "");
head += &format!("<pre><code class=\"language-{}\"", lang);
if !line.is_empty() {
head += &format!(" data-line-numbers=\"{}\"", line);
}
head += ">";
}
Event::Html(head.into())
}
_ => e,
}
}

pub(in crate::loader) fn md2html(text: &str) -> String {
if text.is_empty() {
"".to_string()
} else {
let mut out = String::new();
push_html(&mut out, Parser::new_ext(text, MARKED).map(marked));
out
}
}
99 changes: 7 additions & 92 deletions src/loader/content.rs → src/loader/content/mod.rs
Original file line number Diff line number Diff line change
@@ -1,96 +1,11 @@
use self::frag_map::FragMap;
pub(super) use self::marked::md2html;
use super::*;
use pulldown_cmark::{html::push_html, CodeBlockKind, Event, Options, Parser, Tag};
use std::{collections::HashMap, fs::read_to_string};
use std::fs::read_to_string;
use yaml_peg::{Anchors, Node, Yaml};

const MARKED: Options = Options::from_bits_truncate(
Options::ENABLE_TABLES.bits()
| Options::ENABLE_SMART_PUNCTUATION.bits()
| Options::ENABLE_TASKLISTS.bits()
| Options::ENABLE_STRIKETHROUGH.bits(),
);

fn marked(e: Event) -> Event {
match e {
// Support line number for code block
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(info))) => {
let info = info.replace(' ', "");
let mut head = String::new();
if info.is_empty() {
head += "<pre><code>"
} else {
let lang = info.split('[').next().unwrap();
let line = info
.replace(lang, "")
.replace(|s| (s == '[') | (s == ']'), "");
head += &format!("<pre><code class=\"language-{}\"", lang);
if !line.is_empty() {
head += &format!(" data-line-numbers=\"{}\"", line);
}
head += ">";
}
Event::Html(head.into())
}
_ => e,
}
}

pub(crate) fn md2html(text: &str) -> String {
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>>);

impl FragMap {
fn new(slide: &Node, count: &mut usize) -> Result<Self, Error> {
let mut frag_map = HashMap::new();
for h in slide.get_default("fragment", vec![], Node::as_array)? {
for (k, v) in h.as_map()?.iter() {
let k = k.as_str()?;
let v = v.as_str()?;
if !frag_map.contains_key(k) {
frag_map.insert(k.to_string(), HashMap::new());
}
frag_map.get_mut(k).unwrap().insert(*count, v.to_string());
}
*count += 1;
}
Ok(Self(frag_map))
}

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();
if let Some(frag) = self.0.get(&tag) {
for (index, frag) in frag {
head += &format!(
"<span class=\"fragment {}\" data-fragment-index=\"{}\">",
frag, index
);
end += "</span>";
}
}
head + inner + &end
}
}
mod frag_map;
mod marked;

pub(crate) fn sized_block(img: &Node) -> Result<(String, String), Error> {
let src = img.get_default("src", "", Node::as_str)?;
Expand Down Expand Up @@ -150,12 +65,12 @@ pub(crate) fn content_block(
}
}
if let Ok(n) = slide.get("math") {
doc += &frag.fragment("math", &math(n.as_anchor(v).as_str()?));
doc += &frag.fragment("math", &n.as_anchor(v).as_str()?.wrap("\\[", "\\]"));
}
let media: [(_, fn(&Node) -> Result<String, Error>); 2] =
[("img", img_block), ("video", video_block)];
for (tag, f) in media {
if let Ok(img) = slide.get(tag) {
if let Ok(img) = slide.as_anchor(v).get(tag) {
match img.yaml() {
Yaml::Array(imgs) => {
if !imgs.is_empty() {
Expand Down
13 changes: 13 additions & 0 deletions src/loader/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub(crate) struct Error(pub &'static str, pub u64);

impl From<u64> for Error {
fn from(pos: u64) -> Self {
Self("invalid value type", pos)
}
}

impl From<(&'static str, u64)> for Error {
fn from((v, pos): (&'static str, u64)) -> Self {
Self(v, pos)
}
}
32 changes: 32 additions & 0 deletions src/loader/footer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use super::{sized_block, Error};
use yaml_peg::Node;

pub(crate) fn footer(meta: &Node) -> Result<String, Error> {
let footer = match meta.get("footer") {
Ok(n) => n,
Err(_) => return Ok(String::new()),
};
let src = footer.get_default("src", "", Node::as_str)?;
let label = footer.get_default("label", "", Node::as_str)?;
if src.is_empty() && label.is_empty() {
return Ok(String::new());
}
let mut doc =
"<div id=\"hidden\" style=\"display: none\"><div id=\"footer\"><div id=\"footer-left\">\n"
.to_string();
let link = footer.get_default("link", "", Node::as_str)?;
if !link.is_empty() {
doc += &format!("<a href=\"{}\">", link);
}
let (src, size) = sized_block(&footer)?;
doc += &format!("<img{}{}/>", src, size);
let label = footer.get_default("label", "", Node::as_str)?;
if !label.is_empty() {
doc += &format!("<span>&nbsp;{}</span>", label);
}
if !link.is_empty() {
doc += "</a>";
}
doc += "\n</div></div></div>";
Ok(doc)
}
39 changes: 39 additions & 0 deletions src/loader/js_option.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use super::Error;
use yaml_peg::Node;

fn lower_camelcase(doc: &str) -> String {
let mut s = String::new();
let mut is_word = false;
for c in doc.chars() {
if " -_".contains(c) {
is_word = true;
continue;
}
s.push(if is_word {
is_word = false;
c.to_ascii_uppercase()
} else {
c
});
}
s
}

pub(crate) fn js_option(meta: &Node) -> Result<String, Error> {
let meta = match meta.get("option") {
Ok(n) => n,
Err(_) => return Ok(String::new()),
};
let mut doc = String::new();
for (k, v) in meta.as_map()? {
doc += &lower_camelcase(k.as_str()?);
doc += ": ";
if let Ok(s) = v.as_str() {
doc += &format!("\"{}\"", s);
} else {
doc += v.as_value()?;
}
doc += ", ";
}
Ok(doc)
}
Loading

0 comments on commit 4216bf6

Please sign in to comment.