|
|
@ -1,6 +1,29 @@
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub const SECTION: &str = "section";
|
|
|
|
|
|
|
|
pub const PARAGRAPH: &str = "paragraph";
|
|
|
|
|
|
|
|
pub const LIST: &str = "list";
|
|
|
|
|
|
|
|
pub const TABLE: &str = "table";
|
|
|
|
|
|
|
|
pub const CODE_BLOCK: &str = "code_block";
|
|
|
|
|
|
|
|
pub const QUOTE: &str = "quote";
|
|
|
|
|
|
|
|
pub const IMPORT: &str = "import";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
macro_rules! test_block {
|
|
|
|
|
|
|
|
($block:expr, $block_type:expr) => {
|
|
|
|
|
|
|
|
match $block {
|
|
|
|
|
|
|
|
Block::Section(_) if $block_type == SECTION => true,
|
|
|
|
|
|
|
|
Block::List(_) if $block_type == LIST => true,
|
|
|
|
|
|
|
|
Block::Table(_) if $block_type == TABLE => true,
|
|
|
|
|
|
|
|
Block::Paragraph(_) if $block_type == PARAGRAPH => true,
|
|
|
|
|
|
|
|
Block::CodeBlock(_) if $block_type == CODE_BLOCK => true,
|
|
|
|
|
|
|
|
Block::Quote(_) if $block_type == QUOTE => true,
|
|
|
|
|
|
|
|
Block::Import(_) if $block_type == IMPORT => true,
|
|
|
|
|
|
|
|
_ => false,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum Block {
|
|
|
|
pub enum Block {
|
|
|
|
Section(Section),
|
|
|
|
Section(Section),
|
|
|
|
Paragraph(Paragraph),
|
|
|
|
Paragraph(Paragraph),
|
|
|
@ -11,42 +34,42 @@ pub enum Block {
|
|
|
|
Import(Import),
|
|
|
|
Import(Import),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum Inline {
|
|
|
|
pub enum Inline {
|
|
|
|
Text(Text),
|
|
|
|
Text(Text),
|
|
|
|
Ruler(Ruler),
|
|
|
|
Ruler(Ruler),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Document {
|
|
|
|
pub struct Document {
|
|
|
|
pub(crate) elements: Vec<Block>,
|
|
|
|
pub(crate) elements: Vec<Block>,
|
|
|
|
pub(crate) is_root: bool,
|
|
|
|
pub(crate) is_root: bool,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Section {
|
|
|
|
pub struct Section {
|
|
|
|
pub(crate) header: Header,
|
|
|
|
pub(crate) header: Header,
|
|
|
|
pub(crate) elements: Vec<Block>,
|
|
|
|
pub(crate) elements: Vec<Block>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Header {
|
|
|
|
pub struct Header {
|
|
|
|
pub(crate) size: u8,
|
|
|
|
pub(crate) size: u8,
|
|
|
|
pub(crate) line: Inline,
|
|
|
|
pub(crate) line: Inline,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Paragraph {
|
|
|
|
pub struct Paragraph {
|
|
|
|
pub(crate) elements: Vec<Inline>,
|
|
|
|
pub(crate) elements: Vec<Inline>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct List {
|
|
|
|
pub struct List {
|
|
|
|
pub(crate) ordered: bool,
|
|
|
|
pub(crate) ordered: bool,
|
|
|
|
pub(crate) items: Vec<ListItem>,
|
|
|
|
pub(crate) items: Vec<ListItem>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct ListItem {
|
|
|
|
pub struct ListItem {
|
|
|
|
pub(crate) text: Inline,
|
|
|
|
pub(crate) text: Inline,
|
|
|
|
pub(crate) level: u16,
|
|
|
|
pub(crate) level: u16,
|
|
|
@ -54,34 +77,34 @@ pub struct ListItem {
|
|
|
|
pub(crate) children: Vec<ListItem>,
|
|
|
|
pub(crate) children: Vec<ListItem>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Table {
|
|
|
|
pub struct Table {
|
|
|
|
pub(crate) header: Row,
|
|
|
|
pub(crate) header: Row,
|
|
|
|
pub(crate) rows: Vec<Row>,
|
|
|
|
pub(crate) rows: Vec<Row>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Row {
|
|
|
|
pub struct Row {
|
|
|
|
pub(crate) cells: Vec<Cell>,
|
|
|
|
pub(crate) cells: Vec<Cell>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Cell {
|
|
|
|
pub struct Cell {
|
|
|
|
pub(crate) text: Inline,
|
|
|
|
pub(crate) text: Inline,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct CodeBlock {
|
|
|
|
pub struct CodeBlock {
|
|
|
|
pub(crate) language: String,
|
|
|
|
pub(crate) language: String,
|
|
|
|
pub(crate) code: String,
|
|
|
|
pub(crate) code: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Code {
|
|
|
|
pub struct Code {
|
|
|
|
code: String,
|
|
|
|
code: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Quote {
|
|
|
|
pub struct Quote {
|
|
|
|
pub(crate) metadata: Option<InlineMetadata>,
|
|
|
|
pub(crate) metadata: Option<InlineMetadata>,
|
|
|
|
pub(crate) text: Vec<Text>,
|
|
|
|
pub(crate) text: Vec<Text>,
|
|
|
@ -93,25 +116,25 @@ pub struct Import {
|
|
|
|
pub(crate) anchor: Arc<Mutex<ImportAnchor>>,
|
|
|
|
pub(crate) anchor: Arc<Mutex<ImportAnchor>>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct ImportAnchor {
|
|
|
|
pub struct ImportAnchor {
|
|
|
|
pub(crate) document: Option<Document>,
|
|
|
|
pub(crate) document: Option<Document>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct InlineMetadata {
|
|
|
|
pub struct InlineMetadata {
|
|
|
|
pub(crate) data: String,
|
|
|
|
pub(crate) data: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Ruler {}
|
|
|
|
pub struct Ruler {}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Text {
|
|
|
|
pub struct Text {
|
|
|
|
pub subtext: Vec<SubText>,
|
|
|
|
pub subtext: Vec<SubText>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum SubText {
|
|
|
|
pub enum SubText {
|
|
|
|
Plain(PlainText),
|
|
|
|
Plain(PlainText),
|
|
|
|
Code(Code),
|
|
|
|
Code(Code),
|
|
|
@ -124,43 +147,43 @@ pub enum SubText {
|
|
|
|
Image(Image),
|
|
|
|
Image(Image),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct PlainText {
|
|
|
|
pub struct PlainText {
|
|
|
|
pub(crate) value: String,
|
|
|
|
pub(crate) value: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct BoldText {
|
|
|
|
pub struct BoldText {
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct ItalicText {
|
|
|
|
pub struct ItalicText {
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct UnderlinedText {
|
|
|
|
pub struct UnderlinedText {
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct StrikedText {
|
|
|
|
pub struct StrikedText {
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
pub(crate) value: Box<SubText>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct MonospaceText {
|
|
|
|
pub struct MonospaceText {
|
|
|
|
pub(crate) value: PlainText,
|
|
|
|
pub(crate) value: PlainText,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Url {
|
|
|
|
pub struct Url {
|
|
|
|
pub description: Option<String>,
|
|
|
|
pub description: Option<String>,
|
|
|
|
pub url: String,
|
|
|
|
pub url: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Image {
|
|
|
|
pub struct Image {
|
|
|
|
pub(crate) url: Url,
|
|
|
|
pub(crate) url: Url,
|
|
|
|
pub(crate) metadata: Option<InlineMetadata>,
|
|
|
|
pub(crate) metadata: Option<InlineMetadata>,
|
|
|
@ -179,6 +202,27 @@ impl Document {
|
|
|
|
pub fn add_element(&mut self, element: Block) {
|
|
|
|
pub fn add_element(&mut self, element: Block) {
|
|
|
|
self.elements.push(element)
|
|
|
|
self.elements.push(element)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn find(&self, block_type: &str, nested: bool) -> Vec<&Block> {
|
|
|
|
|
|
|
|
let mut found = Vec::new();
|
|
|
|
|
|
|
|
let mut found_self = self
|
|
|
|
|
|
|
|
.elements
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter(|e| {
|
|
|
|
|
|
|
|
if nested {
|
|
|
|
|
|
|
|
match e {
|
|
|
|
|
|
|
|
Block::Section(sec) => found.append(&mut sec.find(block_type, nested)),
|
|
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test_block!(e, block_type)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
found.append(&mut found_self);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
found
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Section {
|
|
|
|
impl Section {
|
|
|
@ -192,6 +236,26 @@ impl Section {
|
|
|
|
pub fn add_element(&mut self, element: Block) {
|
|
|
|
pub fn add_element(&mut self, element: Block) {
|
|
|
|
self.elements.push(element)
|
|
|
|
self.elements.push(element)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn find(&self, block_type: &str, nested: bool) -> Vec<&Block> {
|
|
|
|
|
|
|
|
let mut found = Vec::new();
|
|
|
|
|
|
|
|
let mut found_self = self
|
|
|
|
|
|
|
|
.elements
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter(|e| {
|
|
|
|
|
|
|
|
if nested {
|
|
|
|
|
|
|
|
match e {
|
|
|
|
|
|
|
|
Block::Section(sec) => found.append(&mut sec.find(block_type, nested)),
|
|
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
test_block!(e, block_type)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
found.append(&mut found_self);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
found
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Paragraph {
|
|
|
|
impl Paragraph {
|
|
|
@ -297,3 +361,9 @@ impl ImportAnchor {
|
|
|
|
self.document = Some(document);
|
|
|
|
self.document = Some(document);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Import {
|
|
|
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
|
|
|
self.path == other.path
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|