Add placeholders

pull/1/head
trivernis 5 years ago
parent 7319907c2e
commit 1c47888a05

100
Cargo.lock generated

@ -93,39 +93,6 @@ dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
@ -136,11 +103,6 @@ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "flate2"
version = "1.0.14"
@ -219,19 +181,6 @@ name = "linked-hash-map"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memoffset"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "minify"
version = "1.1.1"
@ -262,15 +211,6 @@ dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "numtoa"
version = "0.1.0"
@ -354,28 +294,6 @@ dependencies = [
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-queue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
@ -412,11 +330,6 @@ dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.111"
@ -444,12 +357,11 @@ dependencies = [
[[package]]
name = "snekdown"
version = "0.2.5"
version = "0.3.0"
dependencies = [
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"minify 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -631,11 +543,7 @@ dependencies = [
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
"checksum crossbeam-queue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2"
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum flate2 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
@ -648,13 +556,10 @@ dependencies = [
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
"checksum line-wrap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
"checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
"checksum minify 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ef7c582bd7587da887914eaf294897e82f2f5c98b741f137f2a918cd26a885b"
"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum onig 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd91ccd8a02fce2f7e8a86655aec67bc6c171e6f8e704118a0e8c4b866a05a8a"
"checksum onig_sys 69.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3814583fad89f3c60ae0701d80e87e1fd3028741723deda72d0d4a0ecf0cb0db"
@ -664,15 +569,12 @@ dependencies = [
"checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
"checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
"checksum ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
"checksum serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
"checksum serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)" = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"

@ -1,6 +1,6 @@
[package]
name = "snekdown"
version = "0.2.5"
version = "0.3.0"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
license-file = "LICENSE"
@ -25,4 +25,3 @@ termion = "1.5.5"
minify = "1.1.1"
htmlescape = "0.3.1"
syntect = "4.2.0"
rayon = "1.3.0"

@ -23,7 +23,14 @@ macro_rules! test_block {
};
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub enum Element {
Block(Box<Block>),
Inline(Box<Inline>),
SubText(Box<SubText>),
}
#[derive(Clone, Debug)]
pub enum Block {
Section(Section),
Paragraph(Paragraph),
@ -32,44 +39,47 @@ pub enum Block {
CodeBlock(CodeBlock),
Quote(Quote),
Import(Import),
Placeholder(Arc<Mutex<Placeholder>>),
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub enum Inline {
Text(Text),
Ruler(Ruler),
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Document {
pub(crate) elements: Vec<Block>,
pub(crate) is_root: bool,
pub(crate) path: Option<String>,
pub(crate) placeholders: Vec<Arc<Mutex<Placeholder>>>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Section {
pub(crate) header: Header,
pub(crate) elements: Vec<Block>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Header {
pub(crate) size: u8,
pub(crate) line: Inline,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Paragraph {
pub(crate) elements: Vec<Inline>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct List {
pub(crate) ordered: bool,
pub(crate) items: Vec<ListItem>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct ListItem {
pub(crate) text: Inline,
pub(crate) level: u16,
@ -77,34 +87,29 @@ pub struct ListItem {
pub(crate) children: Vec<ListItem>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Table {
pub(crate) header: Row,
pub(crate) rows: Vec<Row>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Row {
pub(crate) cells: Vec<Cell>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Cell {
pub(crate) text: Inline,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct CodeBlock {
pub(crate) language: String,
pub(crate) code: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Code {
code: String,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Quote {
pub(crate) metadata: Option<InlineMetadata>,
pub(crate) text: Vec<Text>,
@ -116,28 +121,27 @@ pub struct Import {
pub(crate) anchor: Arc<Mutex<ImportAnchor>>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct ImportAnchor {
pub(crate) document: Option<Document>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct InlineMetadata {
pub(crate) data: String,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Ruler {}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Text {
pub subtext: Vec<SubText>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub enum SubText {
Plain(PlainText),
Code(Code),
Bold(BoldText),
Italic(ItalicText),
Underlined(UnderlinedText),
@ -145,50 +149,57 @@ pub enum SubText {
Monospace(MonospaceText),
Url(Url),
Image(Image),
Placeholder(Arc<Mutex<Placeholder>>),
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct PlainText {
pub(crate) value: String,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct BoldText {
pub(crate) value: Box<SubText>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct ItalicText {
pub(crate) value: Box<SubText>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct UnderlinedText {
pub(crate) value: Box<SubText>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct StrikedText {
pub(crate) value: Box<SubText>,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct MonospaceText {
pub(crate) value: PlainText,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Url {
pub description: Option<String>,
pub url: String,
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Image {
pub(crate) url: Url,
pub(crate) metadata: Option<InlineMetadata>,
}
#[derive(Clone, Debug)]
pub struct Placeholder {
pub(crate) name: String,
pub(crate) value: Option<Element>,
}
// implementations
impl Document {
@ -196,6 +207,8 @@ impl Document {
Self {
elements: Vec::new(),
is_root,
path: None,
placeholders: Vec::new(),
}
}
@ -203,6 +216,10 @@ impl Document {
self.elements.push(element)
}
pub fn add_placeholder(&mut self, placeholder: Arc<Mutex<Placeholder>>) {
self.placeholders.push(placeholder);
}
pub fn find(&self, block_type: &str, nested: bool) -> Vec<&Block> {
let mut found = Vec::new();
let mut found_self = self
@ -223,6 +240,32 @@ impl Document {
found
}
pub fn create_toc(&self) -> List {
let mut list = List::new();
list.ordered = true;
self.elements.iter().for_each(|e| {
if let Block::Section(sec) = e {
let mut item = ListItem::new(sec.header.line.clone(), 1, true);
item.children.append(&mut sec.get_toc_list().items);
list.add_item(item);
}
});
list
}
pub fn parse_placeholders(&mut self) {
self.placeholders.iter().for_each(|p| {
let mut pholder = p.lock().unwrap();
match pholder.name.to_ascii_lowercase().as_str() {
"toc" => {
pholder.set_value(Element::Block(Box::new(Block::List(self.create_toc()))))
}
_ => {}
}
})
}
}
impl Section {
@ -256,6 +299,19 @@ impl Section {
found
}
pub fn get_toc_list(&self) -> List {
let mut list = List::new();
self.elements.iter().for_each(|e| {
if let Block::Section(sec) = e {
let mut item = ListItem::new(sec.header.line.clone(), 1, true);
item.children.append(&mut sec.get_toc_list().items);
list.add_item(item);
}
});
list
}
}
impl Paragraph {
@ -367,3 +423,13 @@ impl PartialEq for Import {
self.path == other.path
}
}
impl Placeholder {
pub fn new(name: String) -> Self {
Self { name, value: None }
}
pub fn set_value(&mut self, value: Element) {
self.value = Some(value);
}
}

@ -1,7 +1,6 @@
use crate::elements::*;
use htmlescape::{encode_attribute, encode_minimal};
use minify::html::minify;
use rayon::prelude::*;
use std::cell::RefCell;
use syntect::highlighting::ThemeSet;
use syntect::html::highlighted_html_for_string;
@ -21,6 +20,16 @@ pub trait ToHtml {
fn to_html(&self) -> String;
}
impl ToHtml for Element {
fn to_html(&self) -> String {
match self {
Element::Block(block) => block.to_html(),
Element::Inline(inline) => inline.to_html(),
Element::SubText(sub) => sub.to_html(),
}
}
}
impl ToHtml for Inline {
fn to_html(&self) -> String {
match self {
@ -41,7 +50,7 @@ impl ToHtml for SubText {
SubText::Underlined(under) => under.to_html(),
SubText::Bold(bold) => bold.to_html(),
SubText::Image(img) => img.to_html(),
_ => "".to_string(),
SubText::Placeholder(placeholder) => placeholder.lock().unwrap().to_html(),
}
}
}
@ -56,6 +65,7 @@ impl ToHtml for Block {
Block::Quote(quote) => quote.to_html(),
Block::Section(section) => section.to_html(),
Block::Import(import) => import.to_html(),
Block::Placeholder(placeholder) => placeholder.lock().unwrap().to_html(),
}
}
}
@ -64,19 +74,23 @@ impl ToHtml for Document {
fn to_html(&self) -> String {
let inner = self
.elements
.par_iter()
.map(|e| e.to_html())
.reduce(|| "".to_string(), |a, b| format!("{}{}", a, b));
.iter()
.fold("".to_string(), |a, b| format!("{}{}", a, b.to_html()));
let path = if let Some(path) = &self.path {
format!("path='{}'", encode_attribute(path.as_str()))
} else {
"".to_string()
};
if self.is_root {
let style = minify(std::include_str!("assets/style.css"));
format!(
"<!DOCTYPE html>\n<html><head><style>{}</style></head><body><div class='content'>{}</div></body></html>",
style, inner
"<!DOCTYPE html>\n<html><head {}><style>{}</style></head><body><div class='content'>{}</div></body></html>",
path, style, inner
)
} else {
format!(
"<div class='documentImport' document-import=true>{}</div>",
inner
"<div class='documentImport' document-import=true {}>{}</div>",
path, inner
)
}
}
@ -328,3 +342,13 @@ impl ToHtml for PlainText {
encode_minimal(self.value.clone().as_str())
}
}
impl ToHtml for Placeholder {
fn to_html(&self) -> String {
if let Some(value) = &self.value {
value.to_html()
} else {
format!("Unknown placeholder '{}'!", encode_minimal(&self.name))
}
}
}

@ -98,6 +98,7 @@ pub struct Parser {
wg: WaitGroup,
is_child: bool,
subtext_break_at: Vec<char>,
document: Document,
}
impl Parser {
@ -142,6 +143,7 @@ impl Parser {
wg: WaitGroup::new(),
is_child,
subtext_break_at: Vec::new(),
document: Document::new(!is_child),
}
}
@ -331,10 +333,11 @@ impl Parser {
/// parses the given text into a document
pub fn parse(&mut self) -> Document {
let mut document = Document::new(!self.is_child);
self.document.path = self.path.clone();
while self.index < self.text.len() {
match self.parse_block() {
Ok(block) => document.add_element(block),
Ok(block) => self.document.add_element(block),
Err(err) => {
if let Some(path) = &self.path {
if let Some(position) = err.get_position(&self.get_text()) {
@ -359,14 +362,18 @@ impl Parser {
let wg = self.wg.clone();
self.wg = WaitGroup::new();
self.document.parse_placeholders();
wg.wait();
let document = self.document.clone();
self.document = Document::new(!self.is_child);
document
}
/// Parses a block Token
pub fn parse_block(&mut self) -> Result<Block, ParseError> {
if let Some(section) = self.section_return {
if section <= self.section_nesting {
if section <= self.section_nesting && (self.section_nesting > 0) {
return Err(ParseError::new_with_message(
self.index,
"invalid section nesting",
@ -389,6 +396,10 @@ impl Parser {
Block::Quote(quote)
} else if let Ok(import) = self.parse_import() {
Block::Import(import)
} else if let Some(_) = self.section_return {
return Err(ParseError::new(self.index));
} else if let Ok(pholder) = self.parse_placeholder() {
Block::Placeholder(pholder)
} else if let Ok(paragraph) = self.parse_paragraph() {
Block::Paragraph(paragraph)
} else {
@ -555,6 +566,15 @@ impl Parser {
if self.check_special(&IMPORT_CLOSE) {
parse_option!(self.next_char(), self.index);
}
// parsing success
if self.section_nesting > 0 {
self.section_return = Some(0);
let err = ParseError::new_with_message(self.index, "import section nesting error");
self.revert_to(start_index)?;
return Err(err);
}
self.seek_whitespace();
if let Ok(anchor) = self.import_document(path.clone()) {
@ -751,6 +771,30 @@ impl Parser {
}
}
/// parses a placeholder element
fn parse_placeholder(&mut self) -> Result<Arc<Mutex<Placeholder>>, ParseError> {
let start_index = self.index;
self.check_special_sequence(&SQ_PHOLDER_START)?;
let mut name = String::new();
while let Some(char) = self.next_char() {
if self.check_special_group(&SQ_PHOLDER_STOP) || self.check_linebreak() {
break;
}
name.push(char);
}
if self.check_special(&PHOLDER_CLOSE) {
let _ = self.next_char();
let _ = self.next_char();
} else {
return Err(self.revert_with_error(start_index));
}
let placeholder = Arc::new(Mutex::new(Placeholder::new(name)));
self.document.add_placeholder(Arc::clone(&placeholder));
Ok(placeholder)
}
/// parses a ruler
fn parse_ruler(&mut self) -> Result<Ruler, ParseError> {
let start_index = self.index;
@ -798,6 +842,9 @@ impl Parser {
if let Ok(url) = self.parse_url(false) {
return Ok(SubText::Url(url));
}
if let Ok(pholder) = self.parse_placeholder() {
return Ok(SubText::Placeholder(pholder));
}
match self.current_char {
ASTERISK if !self.check_escaped() => {
parse_option!(self.next_char(), self.index);

@ -35,6 +35,8 @@ pub(crate) const URL_CLOSE: char = L_PARENTH;
pub(crate) const IMPORT_START: char = LT;
pub(crate) const IMPORT_OPEN: char = R_BRACKET;
pub(crate) const IMPORT_CLOSE: char = L_BRACKET;
pub(crate) const PHOLDER_OPEN: char = R_BRACKET;
pub(crate) const PHOLDER_CLOSE: char = L_BRACKET;
// groups
@ -57,6 +59,8 @@ pub(crate) const LIST_SPECIAL_CHARS: [char; 4] = [MINUS, PLUS, ASTERISK, O];
pub(crate) const SQ_CODE_BLOCK: [char; 3] = [BACKTICK, BACKTICK, BACKTICK];
pub(crate) const SQ_RULER: [char; 5] = [MINUS, SPACE, MINUS, SPACE, MINUS];
pub(crate) const SQ_PHOLDER_START: [char; 2] = [PHOLDER_OPEN, PHOLDER_OPEN];
pub(crate) const SQ_PHOLDER_STOP: [char; 2] = [PHOLDER_CLOSE, PHOLDER_CLOSE];
// expressions

Loading…
Cancel
Save