diff --git a/default_environment/templates/html/ast_node.dust b/default_environment/templates/html/ast_node.dust new file mode 100644 index 0000000..e69de29 diff --git a/default_environment/templates/html/blog_post_page.dust b/default_environment/templates/html/blog_post_page.dust index 361823b..9ca2f8e 100644 --- a/default_environment/templates/html/blog_post_page.dust +++ b/default_environment/templates/html/blog_post_page.dust @@ -10,5 +10,9 @@ {#.children} {>document_element/} {/.children} + + {?.footnotes} + {>real_footnote_definition/} + {/.footnotes} diff --git a/default_environment/templates/html/real_footnote_definition.dust b/default_environment/templates/html/real_footnote_definition.dust new file mode 100644 index 0000000..9c6be4b --- /dev/null +++ b/default_environment/templates/html/real_footnote_definition.dust @@ -0,0 +1 @@ +
{.label}
{#.contents}{>ast_node/}{/.contents}
diff --git a/src/context/ast_node.rs b/src/context/ast_node.rs new file mode 100644 index 0000000..7a2ffcd --- /dev/null +++ b/src/context/ast_node.rs @@ -0,0 +1,407 @@ +use std::path::Path; + +use serde::Serialize; + +use crate::config::Config; +use crate::error::CustomError; +use crate::intermediate::IAstNode; + +use super::angle_link::RenderAngleLink; +use super::babel_call::RenderBabelCall; +use super::bold::RenderBold; +use super::center_block::RenderCenterBlock; +use super::citation::RenderCitation; +use super::citation_reference::RenderCitationReference; +use super::clock::RenderClock; +use super::code::RenderCode; +use super::comment::RenderComment; +use super::comment_block::RenderCommentBlock; +use super::diary_sexp::RenderDiarySexp; +use super::drawer::RenderDrawer; +use super::dynamic_block::RenderDynamicBlock; +use super::entity::RenderEntity; +use super::example_block::RenderExampleBlock; +use super::export_block::RenderExportBlock; +use super::export_snippet::RenderExportSnippet; +use super::fixed_width_area::RenderFixedWidthArea; +use super::footnote_definition::RenderFootnoteDefinition; +use super::footnote_reference::RenderFootnoteReference; +use super::horizontal_rule::RenderHorizontalRule; +use super::inline_babel_call::RenderInlineBabelCall; +use super::inline_source_block::RenderInlineSourceBlock; +use super::italic::RenderItalic; +use super::keyword::RenderKeyword; +use super::latex_environment::RenderLatexEnvironment; +use super::latex_fragment::RenderLatexFragment; +use super::line_break::RenderLineBreak; +use super::org_macro::RenderOrgMacro; +use super::paragraph::RenderParagraph; +use super::plain_link::RenderPlainLink; +use super::plain_list::RenderPlainList; +use super::plain_text::RenderPlainText; +use super::planning::RenderPlanning; +use super::property_drawer::RenderPropertyDrawer; +use super::quote_block::RenderQuoteBlock; +use super::radio_link::RenderRadioLink; +use super::radio_target::RenderRadioTarget; +use super::regular_link::RenderRegularLink; +use super::special_block::RenderSpecialBlock; +use super::src_block::RenderSrcBlock; +use super::statistics_cookie::RenderStatisticsCookie; +use super::strike_through::RenderStrikeThrough; +use super::subscript::RenderSubscript; +use super::superscript::RenderSuperscript; +use super::table::RenderTable; +use super::target::RenderTarget; +use super::timestamp::RenderTimestamp; +use super::underline::RenderUnderline; +use super::verbatim::RenderVerbatim; +use super::verse_block::RenderVerseBlock; +use super::RenderHeading; +use super::RenderSection; + +#[derive(Debug, Serialize)] +#[serde(untagged)] +pub(crate) enum RenderAstNode { + Heading(RenderHeading), + Section(RenderSection), + Paragraph(RenderParagraph), + PlainList(RenderPlainList), + CenterBlock(RenderCenterBlock), + QuoteBlock(RenderQuoteBlock), + SpecialBlock(RenderSpecialBlock), + DynamicBlock(RenderDynamicBlock), + FootnoteDefinition(RenderFootnoteDefinition), + Comment(RenderComment), + Drawer(RenderDrawer), + PropertyDrawer(RenderPropertyDrawer), + Table(RenderTable), + VerseBlock(RenderVerseBlock), + CommentBlock(RenderCommentBlock), + ExampleBlock(RenderExampleBlock), + ExportBlock(RenderExportBlock), + SrcBlock(RenderSrcBlock), + Clock(RenderClock), + DiarySexp(RenderDiarySexp), + Planning(RenderPlanning), + FixedWidthArea(RenderFixedWidthArea), + HorizontalRule(RenderHorizontalRule), + Keyword(RenderKeyword), + BabelCall(RenderBabelCall), + LatexEnvironment(RenderLatexEnvironment), + Bold(RenderBold), + Italic(RenderItalic), + Underline(RenderUnderline), + StrikeThrough(RenderStrikeThrough), + Code(RenderCode), + Verbatim(RenderVerbatim), + PlainText(RenderPlainText), + RegularLink(RenderRegularLink), + RadioLink(RenderRadioLink), + RadioTarget(RenderRadioTarget), + PlainLink(RenderPlainLink), + AngleLink(RenderAngleLink), + OrgMacro(RenderOrgMacro), + Entity(RenderEntity), + LatexFragment(RenderLatexFragment), + ExportSnippet(RenderExportSnippet), + FootnoteReference(RenderFootnoteReference), + Citation(RenderCitation), + CitationReference(RenderCitationReference), + InlineBabelCall(RenderInlineBabelCall), + InlineSourceBlock(RenderInlineSourceBlock), + LineBreak(RenderLineBreak), + Target(RenderTarget), + StatisticsCookie(RenderStatisticsCookie), + Subscript(RenderSubscript), + Superscript(RenderSuperscript), + Timestamp(RenderTimestamp), +} + +pub(crate) trait IntoRenderAstNode { + fn into_render_ast_node( + &self, + config: &Config, + output_directory: &Path, + output_file: &Path, + ) -> Result; +} + +impl IntoRenderAstNode for IAstNode { + fn into_render_ast_node( + &self, + config: &Config, + output_directory: &Path, + output_file: &Path, + ) -> Result { + match self { + IAstNode::Heading(inner) => Ok(RenderAstNode::Heading(RenderHeading::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Section(inner) => Ok(RenderAstNode::Section(RenderSection::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Paragraph(inner) => Ok(RenderAstNode::Paragraph(RenderParagraph::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::PlainList(inner) => Ok(RenderAstNode::PlainList(RenderPlainList::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::CenterBlock(inner) => Ok(RenderAstNode::CenterBlock(RenderCenterBlock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::QuoteBlock(inner) => Ok(RenderAstNode::QuoteBlock(RenderQuoteBlock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::SpecialBlock(inner) => Ok(RenderAstNode::SpecialBlock( + RenderSpecialBlock::new(config, output_directory, output_file, inner)?, + )), + IAstNode::DynamicBlock(inner) => Ok(RenderAstNode::DynamicBlock( + RenderDynamicBlock::new(config, output_directory, output_file, inner)?, + )), + IAstNode::FootnoteDefinition(inner) => Ok(RenderAstNode::FootnoteDefinition( + RenderFootnoteDefinition::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Comment(inner) => Ok(RenderAstNode::Comment(RenderComment::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Drawer(inner) => Ok(RenderAstNode::Drawer(RenderDrawer::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::PropertyDrawer(inner) => Ok(RenderAstNode::PropertyDrawer( + RenderPropertyDrawer::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Table(inner) => Ok(RenderAstNode::Table(RenderTable::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::VerseBlock(inner) => Ok(RenderAstNode::VerseBlock(RenderVerseBlock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::CommentBlock(inner) => Ok(RenderAstNode::CommentBlock( + RenderCommentBlock::new(config, output_directory, output_file, inner)?, + )), + IAstNode::ExampleBlock(inner) => Ok(RenderAstNode::ExampleBlock( + RenderExampleBlock::new(config, output_directory, output_file, inner)?, + )), + IAstNode::ExportBlock(inner) => Ok(RenderAstNode::ExportBlock(RenderExportBlock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::SrcBlock(inner) => Ok(RenderAstNode::SrcBlock(RenderSrcBlock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Clock(inner) => Ok(RenderAstNode::Clock(RenderClock::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::DiarySexp(inner) => Ok(RenderAstNode::DiarySexp(RenderDiarySexp::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Planning(inner) => Ok(RenderAstNode::Planning(RenderPlanning::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::FixedWidthArea(inner) => Ok(RenderAstNode::FixedWidthArea( + RenderFixedWidthArea::new(config, output_directory, output_file, inner)?, + )), + IAstNode::HorizontalRule(inner) => Ok(RenderAstNode::HorizontalRule( + RenderHorizontalRule::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Keyword(inner) => Ok(RenderAstNode::Keyword(RenderKeyword::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::BabelCall(inner) => Ok(RenderAstNode::BabelCall(RenderBabelCall::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::LatexEnvironment(inner) => Ok(RenderAstNode::LatexEnvironment( + RenderLatexEnvironment::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Bold(inner) => Ok(RenderAstNode::Bold(RenderBold::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Italic(inner) => Ok(RenderAstNode::Italic(RenderItalic::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Underline(inner) => Ok(RenderAstNode::Underline(RenderUnderline::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::StrikeThrough(inner) => Ok(RenderAstNode::StrikeThrough( + RenderStrikeThrough::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Code(inner) => Ok(RenderAstNode::Code(RenderCode::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Verbatim(inner) => Ok(RenderAstNode::Verbatim(RenderVerbatim::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::PlainText(inner) => Ok(RenderAstNode::PlainText(RenderPlainText::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::RegularLink(inner) => Ok(RenderAstNode::RegularLink(RenderRegularLink::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::RadioLink(inner) => Ok(RenderAstNode::RadioLink(RenderRadioLink::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::RadioTarget(inner) => Ok(RenderAstNode::RadioTarget(RenderRadioTarget::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::PlainLink(inner) => Ok(RenderAstNode::PlainLink(RenderPlainLink::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::AngleLink(inner) => Ok(RenderAstNode::AngleLink(RenderAngleLink::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::OrgMacro(inner) => Ok(RenderAstNode::OrgMacro(RenderOrgMacro::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Entity(inner) => Ok(RenderAstNode::Entity(RenderEntity::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::LatexFragment(inner) => Ok(RenderAstNode::LatexFragment( + RenderLatexFragment::new(config, output_directory, output_file, inner)?, + )), + IAstNode::ExportSnippet(inner) => Ok(RenderAstNode::ExportSnippet( + RenderExportSnippet::new(config, output_directory, output_file, inner)?, + )), + IAstNode::FootnoteReference(inner) => Ok(RenderAstNode::FootnoteReference( + RenderFootnoteReference::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Citation(inner) => Ok(RenderAstNode::Citation(RenderCitation::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::CitationReference(inner) => Ok(RenderAstNode::CitationReference( + RenderCitationReference::new(config, output_directory, output_file, inner)?, + )), + IAstNode::InlineBabelCall(inner) => Ok(RenderAstNode::InlineBabelCall( + RenderInlineBabelCall::new(config, output_directory, output_file, inner)?, + )), + IAstNode::InlineSourceBlock(inner) => Ok(RenderAstNode::InlineSourceBlock( + RenderInlineSourceBlock::new(config, output_directory, output_file, inner)?, + )), + IAstNode::LineBreak(inner) => Ok(RenderAstNode::LineBreak(RenderLineBreak::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Target(inner) => Ok(RenderAstNode::Target(RenderTarget::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::StatisticsCookie(inner) => Ok(RenderAstNode::StatisticsCookie( + RenderStatisticsCookie::new(config, output_directory, output_file, inner)?, + )), + IAstNode::Subscript(inner) => Ok(RenderAstNode::Subscript(RenderSubscript::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Superscript(inner) => Ok(RenderAstNode::Superscript(RenderSuperscript::new( + config, + output_directory, + output_file, + inner, + )?)), + IAstNode::Timestamp(inner) => Ok(RenderAstNode::Timestamp(RenderTimestamp::new( + config, + output_directory, + output_file, + inner, + )?)), + } + } +} diff --git a/src/context/footnote_definition.rs b/src/context/footnote_definition.rs index 589658e..1734c66 100644 --- a/src/context/footnote_definition.rs +++ b/src/context/footnote_definition.rs @@ -5,6 +5,10 @@ use serde::Serialize; use crate::config::Config; use crate::error::CustomError; use crate::intermediate::IFootnoteDefinition; +use crate::intermediate::IRealFootnoteDefinition; + +use super::ast_node::IntoRenderAstNode; +use super::ast_node::RenderAstNode; #[derive(Debug, Serialize)] #[serde(tag = "type")] @@ -21,3 +25,35 @@ impl RenderFootnoteDefinition { Ok(RenderFootnoteDefinition {}) } } + +#[derive(Debug, Serialize)] +#[serde(tag = "type")] +#[serde(rename = "footnote_reference")] +pub(crate) struct RenderRealFootnoteDefinition { + definition_id: String, + reference_link: String, + contents: Vec, +} + +impl RenderRealFootnoteDefinition { + pub(crate) fn new( + config: &Config, + output_directory: &Path, + output_file: &Path, + original: &IRealFootnoteDefinition, + ) -> Result { + let contents = { + let mut ret = Vec::new(); + for obj in original.contents.iter() { + ret.push(obj.into_render_ast_node(config, output_directory, output_file)?); + } + ret + }; + + Ok(RenderRealFootnoteDefinition { + definition_id: original.get_definition_id(), + reference_link: format!("#{}", original.get_reference_id()), + contents, + }) + } +} diff --git a/src/context/heading.rs b/src/context/heading.rs index ec6399f..d69f659 100644 --- a/src/context/heading.rs +++ b/src/context/heading.rs @@ -30,8 +30,8 @@ impl RenderHeading { for obj in heading.title.iter() { ret.push(RenderObject::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } @@ -43,8 +43,8 @@ impl RenderHeading { for obj in heading.children.iter() { ret.push(RenderDocumentElement::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/mod.rs b/src/context/mod.rs index 25ae64c..eb6a770 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -1,4 +1,5 @@ mod angle_link; +mod ast_node; mod babel_call; mod blog_post_page; mod bold; diff --git a/src/context/paragraph.rs b/src/context/paragraph.rs index 2e0e1c3..c211535 100644 --- a/src/context/paragraph.rs +++ b/src/context/paragraph.rs @@ -27,8 +27,8 @@ impl RenderParagraph { for obj in paragraph.children.iter() { ret.push(RenderObject::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/plain_list.rs b/src/context/plain_list.rs index b6b61b9..25840b8 100644 --- a/src/context/plain_list.rs +++ b/src/context/plain_list.rs @@ -33,8 +33,8 @@ impl RenderPlainList { for obj in original.children.iter() { ret.push(RenderPlainListItem::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/plain_list_item.rs b/src/context/plain_list_item.rs index 0cfe106..df18dee 100644 --- a/src/context/plain_list_item.rs +++ b/src/context/plain_list_item.rs @@ -29,8 +29,8 @@ impl RenderPlainListItem { for obj in original.tag.iter() { ret.push(RenderObject::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } @@ -42,8 +42,8 @@ impl RenderPlainListItem { for obj in original.children.iter() { ret.push(RenderElement::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/quote_block.rs b/src/context/quote_block.rs index 8a5d7f0..5866442 100644 --- a/src/context/quote_block.rs +++ b/src/context/quote_block.rs @@ -27,8 +27,8 @@ impl RenderQuoteBlock { for obj in original.children.iter() { ret.push(RenderElement::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/regular_link.rs b/src/context/regular_link.rs index 0cecb38..58ccd4a 100644 --- a/src/context/regular_link.rs +++ b/src/context/regular_link.rs @@ -28,8 +28,8 @@ impl RenderRegularLink { for obj in regular_link.children.iter() { ret.push(RenderObject::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/context/section.rs b/src/context/section.rs index 45d66bf..87c5a12 100644 --- a/src/context/section.rs +++ b/src/context/section.rs @@ -27,8 +27,8 @@ impl RenderSection { for obj in section.children.iter() { ret.push(RenderElement::new( config, - &output_directory, - &output_file, + output_directory, + output_file, obj, )?); } diff --git a/src/intermediate/angle_link.rs b/src/intermediate/angle_link.rs index a92e3a7..888d339 100644 --- a/src/intermediate/angle_link.rs +++ b/src/intermediate/angle_link.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IAngleLink {} impl IAngleLink { diff --git a/src/intermediate/ast_node.rs b/src/intermediate/ast_node.rs index 82bd540..189bc7b 100644 --- a/src/intermediate/ast_node.rs +++ b/src/intermediate/ast_node.rs @@ -55,7 +55,7 @@ use super::IVerseBlock; use crate::error::CustomError; use futures::future::{BoxFuture, FutureExt}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) enum IAstNode { Heading(IHeading), Section(ISection), diff --git a/src/intermediate/babel_call.rs b/src/intermediate/babel_call.rs index 8e92165..957bd11 100644 --- a/src/intermediate/babel_call.rs +++ b/src/intermediate/babel_call.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IBabelCall {} impl IBabelCall { diff --git a/src/intermediate/bold.rs b/src/intermediate/bold.rs index 3d94ae7..f69cbe7 100644 --- a/src/intermediate/bold.rs +++ b/src/intermediate/bold.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IBold {} impl IBold { diff --git a/src/intermediate/center_block.rs b/src/intermediate/center_block.rs index 8b95dab..bc37461 100644 --- a/src/intermediate/center_block.rs +++ b/src/intermediate/center_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ICenterBlock {} impl ICenterBlock { diff --git a/src/intermediate/citation.rs b/src/intermediate/citation.rs index e14cffd..b9b5176 100644 --- a/src/intermediate/citation.rs +++ b/src/intermediate/citation.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ICitation {} impl ICitation { diff --git a/src/intermediate/citation_reference.rs b/src/intermediate/citation_reference.rs index 30e2a77..ce46683 100644 --- a/src/intermediate/citation_reference.rs +++ b/src/intermediate/citation_reference.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ICitationReference {} impl ICitationReference { diff --git a/src/intermediate/clock.rs b/src/intermediate/clock.rs index 4db4185..30626f0 100644 --- a/src/intermediate/clock.rs +++ b/src/intermediate/clock.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IClock {} impl IClock { diff --git a/src/intermediate/code.rs b/src/intermediate/code.rs index 0eb3a76..634e5f2 100644 --- a/src/intermediate/code.rs +++ b/src/intermediate/code.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ICode {} impl ICode { diff --git a/src/intermediate/comment.rs b/src/intermediate/comment.rs index d54cee7..75b8cf8 100644 --- a/src/intermediate/comment.rs +++ b/src/intermediate/comment.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; /// Essentially a no-op since the comment is not rendered. -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IComment {} impl IComment { diff --git a/src/intermediate/comment_block.rs b/src/intermediate/comment_block.rs index b2cdc73..2560408 100644 --- a/src/intermediate/comment_block.rs +++ b/src/intermediate/comment_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ICommentBlock {} impl ICommentBlock { diff --git a/src/intermediate/diary_sexp.rs b/src/intermediate/diary_sexp.rs index 664bdec..3a65fbf 100644 --- a/src/intermediate/diary_sexp.rs +++ b/src/intermediate/diary_sexp.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IDiarySexp {} impl IDiarySexp { diff --git a/src/intermediate/document_element.rs b/src/intermediate/document_element.rs index d348269..2e0591e 100644 --- a/src/intermediate/document_element.rs +++ b/src/intermediate/document_element.rs @@ -5,7 +5,7 @@ use super::IHeading; use super::ISection; use futures::future::{BoxFuture, FutureExt}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) enum IDocumentElement { Heading(IHeading), Section(ISection), diff --git a/src/intermediate/drawer.rs b/src/intermediate/drawer.rs index 506428f..6efaf1d 100644 --- a/src/intermediate/drawer.rs +++ b/src/intermediate/drawer.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IDrawer {} impl IDrawer { diff --git a/src/intermediate/dynamic_block.rs b/src/intermediate/dynamic_block.rs index 6e31c19..3f3f419 100644 --- a/src/intermediate/dynamic_block.rs +++ b/src/intermediate/dynamic_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IDynamicBlock {} impl IDynamicBlock { diff --git a/src/intermediate/element.rs b/src/intermediate/element.rs index 1fe3360..2deaf6a 100644 --- a/src/intermediate/element.rs +++ b/src/intermediate/element.rs @@ -27,7 +27,7 @@ use super::ITable; use super::IVerseBlock; use futures::future::{BoxFuture, FutureExt}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) enum IElement { Paragraph(IParagraph), PlainList(IPlainList), diff --git a/src/intermediate/entity.rs b/src/intermediate/entity.rs index a2fa594..1323143 100644 --- a/src/intermediate/entity.rs +++ b/src/intermediate/entity.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IEntity { pub(crate) html: String, } diff --git a/src/intermediate/example_block.rs b/src/intermediate/example_block.rs index c10c77c..7ea73b3 100644 --- a/src/intermediate/example_block.rs +++ b/src/intermediate/example_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IExampleBlock {} impl IExampleBlock { diff --git a/src/intermediate/export_block.rs b/src/intermediate/export_block.rs index d9fa9f8..86afacc 100644 --- a/src/intermediate/export_block.rs +++ b/src/intermediate/export_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IExportBlock {} impl IExportBlock { diff --git a/src/intermediate/export_snippet.rs b/src/intermediate/export_snippet.rs index 3759564..dd0bc5b 100644 --- a/src/intermediate/export_snippet.rs +++ b/src/intermediate/export_snippet.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IExportSnippet {} impl IExportSnippet { diff --git a/src/intermediate/fixed_width_area.rs b/src/intermediate/fixed_width_area.rs index 6147514..e3736c4 100644 --- a/src/intermediate/fixed_width_area.rs +++ b/src/intermediate/fixed_width_area.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IFixedWidthArea {} impl IFixedWidthArea { diff --git a/src/intermediate/footnote_definition.rs b/src/intermediate/footnote_definition.rs index ea2774a..011242e 100644 --- a/src/intermediate/footnote_definition.rs +++ b/src/intermediate/footnote_definition.rs @@ -5,7 +5,7 @@ use super::registry::Registry; use super::IElement; use super::IObject; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IFootnoteDefinition {} impl IFootnoteDefinition { @@ -22,8 +22,8 @@ impl IFootnoteDefinition { #[derive(Debug)] pub(crate) struct IRealFootnoteDefinition { - footnote_id: usize, - contents: Vec, + pub(crate) footnote_id: usize, + pub(crate) contents: Vec, } impl IRealFootnoteDefinition { @@ -37,4 +37,22 @@ impl IRealFootnoteDefinition { contents, }) } + + pub(crate) fn get_display_label(&self) -> String { + format!("{}", self.footnote_id + 1) + } + + /// Get an ID to refer to the first reference to this footnote definition. + /// + /// This ID could, for example, be used for the id attribute in HTML for the reference anchor tag. + pub(crate) fn get_reference_id(&self) -> String { + format!("fnr.{}", self.get_display_label()) + } + + /// Get an ID to refer to the footnote definition. + /// + /// This ID could, for example, be used for the id attribute in HTML for the definition anchor tag. + pub(crate) fn get_definition_id(&self) -> String { + format!("fn.{}", self.get_display_label()) + } } diff --git a/src/intermediate/footnote_reference.rs b/src/intermediate/footnote_reference.rs index d0ef6bb..c04951a 100644 --- a/src/intermediate/footnote_reference.rs +++ b/src/intermediate/footnote_reference.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IFootnoteReference { footnote_id: usize, duplicate_offset: usize, diff --git a/src/intermediate/heading.rs b/src/intermediate/heading.rs index 2d6bfd9..a5e3e66 100644 --- a/src/intermediate/heading.rs +++ b/src/intermediate/heading.rs @@ -4,7 +4,7 @@ use super::registry::Registry; use super::IDocumentElement; use super::IObject; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IHeading { pub(crate) level: organic::types::HeadlineLevel, pub(crate) title: Vec, diff --git a/src/intermediate/horizontal_rule.rs b/src/intermediate/horizontal_rule.rs index ca7b2e5..59795ee 100644 --- a/src/intermediate/horizontal_rule.rs +++ b/src/intermediate/horizontal_rule.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IHorizontalRule {} impl IHorizontalRule { diff --git a/src/intermediate/inline_babel_call.rs b/src/intermediate/inline_babel_call.rs index 659a7c7..8e5e56d 100644 --- a/src/intermediate/inline_babel_call.rs +++ b/src/intermediate/inline_babel_call.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IInlineBabelCall {} impl IInlineBabelCall { diff --git a/src/intermediate/inline_source_block.rs b/src/intermediate/inline_source_block.rs index 2f798f1..41492bb 100644 --- a/src/intermediate/inline_source_block.rs +++ b/src/intermediate/inline_source_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IInlineSourceBlock { pub(crate) value: String, } diff --git a/src/intermediate/italic.rs b/src/intermediate/italic.rs index 91677b8..8cb0140 100644 --- a/src/intermediate/italic.rs +++ b/src/intermediate/italic.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IItalic {} impl IItalic { diff --git a/src/intermediate/keyword.rs b/src/intermediate/keyword.rs index c0d7567..c187f87 100644 --- a/src/intermediate/keyword.rs +++ b/src/intermediate/keyword.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; /// Essentially a no-op since the keyword is not rendered and any relevant impact on other elements is pulled from the parsed form of keyword. -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IKeyword {} impl IKeyword { diff --git a/src/intermediate/latex_environment.rs b/src/intermediate/latex_environment.rs index 05d82cb..6699078 100644 --- a/src/intermediate/latex_environment.rs +++ b/src/intermediate/latex_environment.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ILatexEnvironment {} impl ILatexEnvironment { diff --git a/src/intermediate/latex_fragment.rs b/src/intermediate/latex_fragment.rs index 804985c..82e03d9 100644 --- a/src/intermediate/latex_fragment.rs +++ b/src/intermediate/latex_fragment.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ILatexFragment {} impl ILatexFragment { diff --git a/src/intermediate/line_break.rs b/src/intermediate/line_break.rs index 9534d07..8c87978 100644 --- a/src/intermediate/line_break.rs +++ b/src/intermediate/line_break.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ILineBreak {} impl ILineBreak { diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index dd316f9..0281285 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -62,6 +62,7 @@ mod util; mod verbatim; mod verse_block; pub(crate) use angle_link::IAngleLink; +pub(crate) use ast_node::IAstNode; pub(crate) use babel_call::IBabelCall; pub(crate) use bold::IBold; pub(crate) use center_block::ICenterBlock; @@ -84,6 +85,7 @@ pub(crate) use export_block::IExportBlock; pub(crate) use export_snippet::IExportSnippet; pub(crate) use fixed_width_area::IFixedWidthArea; pub(crate) use footnote_definition::IFootnoteDefinition; +pub(crate) use footnote_definition::IRealFootnoteDefinition; pub(crate) use footnote_reference::IFootnoteReference; pub(crate) use heading::IHeading; pub(crate) use horizontal_rule::IHorizontalRule; diff --git a/src/intermediate/object.rs b/src/intermediate/object.rs index c51584a..3eee490 100644 --- a/src/intermediate/object.rs +++ b/src/intermediate/object.rs @@ -30,7 +30,7 @@ use super::verbatim::IVerbatim; use super::ITarget; use futures::future::{BoxFuture, FutureExt}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) enum IObject { Bold(IBold), Italic(IItalic), diff --git a/src/intermediate/org_macro.rs b/src/intermediate/org_macro.rs index f231a38..7fb3fe5 100644 --- a/src/intermediate/org_macro.rs +++ b/src/intermediate/org_macro.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IOrgMacro {} impl IOrgMacro { diff --git a/src/intermediate/page.rs b/src/intermediate/page.rs index 66514e2..0333f75 100644 --- a/src/intermediate/page.rs +++ b/src/intermediate/page.rs @@ -39,13 +39,23 @@ impl BlogPostPage { )); } - // TODO: Get footnote definitions + let footnotes = { + let footnote_definitions: Vec<_> = registry + .get_footnote_ids() + .map(|(id, def)| (id, def.clone())) + .collect(); + let mut ret = Vec::new(); + for (id, def) in footnote_definitions.into_iter() { + ret.push(IRealFootnoteDefinition::new(registry, id, def).await?); + } + ret + }; Ok(BlogPostPage { path, title: get_title(&document), children, - footnotes: Vec::new(), // TODO + footnotes, }) } diff --git a/src/intermediate/paragraph.rs b/src/intermediate/paragraph.rs index f41dc70..d9b0893 100644 --- a/src/intermediate/paragraph.rs +++ b/src/intermediate/paragraph.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; use super::IObject; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IParagraph { pub(crate) children: Vec, } diff --git a/src/intermediate/plain_link.rs b/src/intermediate/plain_link.rs index f79d0de..a6503c3 100644 --- a/src/intermediate/plain_link.rs +++ b/src/intermediate/plain_link.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPlainLink {} impl IPlainLink { diff --git a/src/intermediate/plain_list.rs b/src/intermediate/plain_list.rs index 5b74769..17ac7cb 100644 --- a/src/intermediate/plain_list.rs +++ b/src/intermediate/plain_list.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; use super::IPlainListItem; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPlainList { pub(crate) list_type: organic::types::PlainListType, pub(crate) children: Vec, diff --git a/src/intermediate/plain_list_item.rs b/src/intermediate/plain_list_item.rs index b0308fb..9e8f7ad 100644 --- a/src/intermediate/plain_list_item.rs +++ b/src/intermediate/plain_list_item.rs @@ -4,7 +4,7 @@ use super::registry::Registry; use super::IElement; use super::IObject; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPlainListItem { pub(crate) tag: Vec, pub(crate) children: Vec, diff --git a/src/intermediate/plain_text.rs b/src/intermediate/plain_text.rs index c75ae2d..30114ab 100644 --- a/src/intermediate/plain_text.rs +++ b/src/intermediate/plain_text.rs @@ -3,7 +3,7 @@ use crate::intermediate::util::coalesce_whitespace; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPlainText { pub(crate) source: String, } diff --git a/src/intermediate/planning.rs b/src/intermediate/planning.rs index f6a689c..968f288 100644 --- a/src/intermediate/planning.rs +++ b/src/intermediate/planning.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPlanning {} impl IPlanning { diff --git a/src/intermediate/property_drawer.rs b/src/intermediate/property_drawer.rs index 70bea94..000946a 100644 --- a/src/intermediate/property_drawer.rs +++ b/src/intermediate/property_drawer.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IPropertyDrawer {} impl IPropertyDrawer { diff --git a/src/intermediate/quote_block.rs b/src/intermediate/quote_block.rs index b08429e..db7c062 100644 --- a/src/intermediate/quote_block.rs +++ b/src/intermediate/quote_block.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; use super::IElement; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IQuoteBlock { pub(crate) children: Vec, } diff --git a/src/intermediate/radio_link.rs b/src/intermediate/radio_link.rs index fff2e36..0f382ee 100644 --- a/src/intermediate/radio_link.rs +++ b/src/intermediate/radio_link.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IRadioLink {} impl IRadioLink { diff --git a/src/intermediate/radio_target.rs b/src/intermediate/radio_target.rs index 0efcbce..e8f4735 100644 --- a/src/intermediate/radio_target.rs +++ b/src/intermediate/radio_target.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IRadioTarget {} impl IRadioTarget { diff --git a/src/intermediate/registry.rs b/src/intermediate/registry.rs index da5183b..a7a847f 100644 --- a/src/intermediate/registry.rs +++ b/src/intermediate/registry.rs @@ -31,6 +31,13 @@ impl<'parse> Registry<'parse> { }) } + pub(crate) fn get_footnote_ids(&self) -> impl Iterator)> { + self.footnote_ids + .iter() + .map(|(_label, definition)| definition) + .enumerate() + } + /// Get a 0-indexed ID for a footnote. /// /// This needs to be incremented to be 1-indexed for render. diff --git a/src/intermediate/regular_link.rs b/src/intermediate/regular_link.rs index 36ec9ae..87b34b2 100644 --- a/src/intermediate/regular_link.rs +++ b/src/intermediate/regular_link.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; use super::IObject; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IRegularLink { pub(crate) raw_link: String, pub(crate) children: Vec, diff --git a/src/intermediate/section.rs b/src/intermediate/section.rs index 6642061..658a3d2 100644 --- a/src/intermediate/section.rs +++ b/src/intermediate/section.rs @@ -3,7 +3,7 @@ use crate::error::CustomError; use super::registry::Registry; use super::IElement; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ISection { pub(crate) children: Vec, } diff --git a/src/intermediate/special_block.rs b/src/intermediate/special_block.rs index b10cff0..952468b 100644 --- a/src/intermediate/special_block.rs +++ b/src/intermediate/special_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ISpecialBlock {} impl ISpecialBlock { diff --git a/src/intermediate/src_block.rs b/src/intermediate/src_block.rs index ddf9534..d5a4c92 100644 --- a/src/intermediate/src_block.rs +++ b/src/intermediate/src_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ISrcBlock { pub(crate) lines: Vec, } diff --git a/src/intermediate/statistics_cookie.rs b/src/intermediate/statistics_cookie.rs index 0b0a3db..b2915eb 100644 --- a/src/intermediate/statistics_cookie.rs +++ b/src/intermediate/statistics_cookie.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IStatisticsCookie {} impl IStatisticsCookie { diff --git a/src/intermediate/strike_through.rs b/src/intermediate/strike_through.rs index ca80c17..c81ee12 100644 --- a/src/intermediate/strike_through.rs +++ b/src/intermediate/strike_through.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IStrikeThrough {} impl IStrikeThrough { diff --git a/src/intermediate/subscript.rs b/src/intermediate/subscript.rs index 3a79239..18c57ef 100644 --- a/src/intermediate/subscript.rs +++ b/src/intermediate/subscript.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ISubscript {} impl ISubscript { diff --git a/src/intermediate/superscript.rs b/src/intermediate/superscript.rs index fef68c1..247e250 100644 --- a/src/intermediate/superscript.rs +++ b/src/intermediate/superscript.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ISuperscript {} impl ISuperscript { diff --git a/src/intermediate/table.rs b/src/intermediate/table.rs index 43c44f5..e5ceb9d 100644 --- a/src/intermediate/table.rs +++ b/src/intermediate/table.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ITable {} impl ITable { diff --git a/src/intermediate/target.rs b/src/intermediate/target.rs index 43013ad..4bc57ec 100644 --- a/src/intermediate/target.rs +++ b/src/intermediate/target.rs @@ -3,7 +3,7 @@ use crate::intermediate::util::coalesce_whitespace; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ITarget { pub(crate) id: String, value: String, diff --git a/src/intermediate/timestamp.rs b/src/intermediate/timestamp.rs index f6f95f3..f590f64 100644 --- a/src/intermediate/timestamp.rs +++ b/src/intermediate/timestamp.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct ITimestamp {} impl ITimestamp { diff --git a/src/intermediate/underline.rs b/src/intermediate/underline.rs index 4c7b5b9..a2e5c83 100644 --- a/src/intermediate/underline.rs +++ b/src/intermediate/underline.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IUnderline {} impl IUnderline { diff --git a/src/intermediate/verbatim.rs b/src/intermediate/verbatim.rs index bddaf37..4d60d54 100644 --- a/src/intermediate/verbatim.rs +++ b/src/intermediate/verbatim.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IVerbatim {} impl IVerbatim { diff --git a/src/intermediate/verse_block.rs b/src/intermediate/verse_block.rs index 2e725b7..bd37207 100644 --- a/src/intermediate/verse_block.rs +++ b/src/intermediate/verse_block.rs @@ -2,7 +2,7 @@ use crate::error::CustomError; use super::registry::Registry; -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct IVerseBlock {} impl IVerseBlock {