Compare commits

..

100 Commits

Author SHA1 Message Date
Tom Alexander
b06798f23f Prepare for publishing to crates.io. 2023-12-21 19:40:28 -05:00
Tom Alexander
35dff5cdaf Rename to natter. 2023-12-21 19:28:31 -05:00
Tom Alexander
d641c8d638 Merge branch 'pretty' 2023-12-21 18:36:23 -05:00
Tom Alexander
7e2fd70212 Style the homepage. 2023-12-21 18:34:42 -05:00
Tom Alexander
4fb08bc7d0 Wrap inline footnote definitions in a paragraph tag.
This is to match the behavior of the upstream org html exporter.
2023-12-21 18:09:43 -05:00
Tom Alexander
01b55b7256 Make paragraphs under footnote definitions display inline.
This seems to be the behavior of the upstream org html exporter.
2023-12-21 17:44:40 -05:00
Tom Alexander
bd68681e44 Increase the size of headlines.
This is to make them stand out more from the regular text.
2023-12-21 17:31:19 -05:00
Tom Alexander
27ff13e675 Also special-case plain list items containing only paragraphs and sublists.
This seems to be the behavior of the upstream org html exporter.
2023-12-21 17:27:19 -05:00
Tom Alexander
2914e42ba1 For plain list items with a single child that is a paragraph, do not wrap in paragraph html tags.
This is mimicking the behavior from org-mode's HTML exporter.
2023-12-21 17:18:51 -05:00
Tom Alexander
a8969f141d Style code and verbatim. 2023-12-21 16:49:44 -05:00
Tom Alexander
6f049e00d4 Style inline source blocks. 2023-12-21 16:42:22 -05:00
Tom Alexander
45a1076d18 Style descriptive plain lists. 2023-12-21 16:39:26 -05:00
Tom Alexander
775c88d67a Style footnotes. 2023-12-21 15:44:56 -05:00
Tom Alexander
efbf6cfc0c Style ordered and unordered plain lists. 2023-12-21 15:31:13 -05:00
Tom Alexander
5af4a372ae Make object trailing space dependent on post_blank. 2023-12-21 15:13:07 -05:00
Tom Alexander
72952adb6b Add post_blank to the rust types. 2023-12-21 15:09:13 -05:00
Tom Alexander
8b85c02ef1 Wrap the intermediate Registry in an IntermediateContext.
This is currently just to maintain consistency with the render phase's RenderContext but in the future it should allow us to include immutable data that is not locked behind the ArcMutex.
2023-12-21 13:53:56 -05:00
Tom Alexander
2ae4839ce0 Remove common whitespace prefix from src block lines. 2023-12-21 13:16:05 -05:00
Tom Alexander
5654c40d03 Get the real language for src blocks from the org source. 2023-12-21 12:07:36 -05:00
Tom Alexander
b538750287 Preserve whitespace in src blocks. 2023-12-21 12:04:29 -05:00
Tom Alexander
65ed754bfe Space out some elements. 2023-12-19 21:57:33 -05:00
Tom Alexander
80cdf5166b Style quote blocks, h2, and h3. 2023-12-19 21:41:41 -05:00
Tom Alexander
3968121d54 Style src blocks. 2023-12-19 21:30:59 -05:00
Tom Alexander
a29b625631 Apply a dark background. 2023-12-19 20:33:21 -05:00
Tom Alexander
e193fcc2ba Start applying styles to blog posts. 2023-12-19 19:23:56 -05:00
Tom Alexander
050b426f6f Merge branch 'homepage' 2023-12-19 18:08:50 -05:00
Tom Alexander
da81f93e4a Re-enable the CSS reset sheet. 2023-12-19 18:06:52 -05:00
Tom Alexander
1581e5c401 Rename the output root directory in the render context. 2023-12-19 18:03:59 -05:00
Tom Alexander
2e1c979127 Add a prefix to footnote IDs.
This avoids a conflict with multiple blog posts rendering in the same stream.
2023-12-19 18:01:54 -05:00
Tom Alexander
d4b290ebe6 Remove unnecessary let statements from render macro. 2023-12-19 17:31:50 -05:00
Tom Alexander
4bb1f9983a Standardize the construction of intermediate BlogPostPage. 2023-12-19 17:31:16 -05:00
Tom Alexander
261fe8a1a2 Fix the links to the blog posts. 2023-12-19 16:49:46 -05:00
Tom Alexander
add267d616 Switch over to using the render context in render calls. 2023-12-19 16:20:12 -05:00
Tom Alexander
cb3278aba5 Create a struct that will combine all the context for converting intermediate objects into the dust render context. 2023-12-19 14:54:12 -05:00
Tom Alexander
94d9a95967 Add a basic template for the blog stream page. 2023-12-19 14:13:29 -05:00
Tom Alexander
6511115b95 Implement a flawed version of RenderBlogStreamEntry::new.
There are some shortcomings in this implementation listed in the comments, but this is the general structure.
2023-12-19 10:59:34 -05:00
Tom Alexander
53cd55932b Implement RenderBlogStream::new.
I still need to implement RenderBlogStreamEntry::new.
2023-12-19 10:47:03 -05:00
Tom Alexander
cbe2010407 Invoke dust to render the stream pages.
At this point the render_blog_stream function is done, but RenderBlogStream::new needs to be implemented to actually generate the render context. The body of this function should be similar to convert_blog_post_page_to_render_context.
2023-12-17 17:26:15 -05:00
Tom Alexander
2ba4a5e3d7 Generate newer and older links. 2023-12-17 17:16:26 -05:00
Tom Alexander
c3482cf1e4 Chunking the blog posts for the stream. 2023-12-17 16:57:37 -05:00
Tom Alexander
fdf84e3d0b Finding the index page. 2023-12-17 15:45:50 -05:00
Tom Alexander
0a4376dfb8 Rename intermediate blog post source file. 2023-12-17 15:32:07 -05:00
Tom Alexander
e8ed4a4f4a Initial structure for rendering a blog post stream. 2023-12-17 15:32:07 -05:00
Tom Alexander
60555999db TEMP: Disable the css reset.
This is so I can develop the header without having any CSS written yet since the page is a mess without CSS.
2023-12-17 14:56:23 -05:00
Tom Alexander
6968a5b02c Merge branch 'header' 2023-12-17 14:47:45 -05:00
Tom Alexander
c84cfdc02b Basic template for a page header. 2023-12-17 14:45:42 -05:00
Tom Alexander
c98489cacb Add the page header to the render context. 2023-12-17 14:45:42 -05:00
Tom Alexander
35dbab0ceb Create a page header struct. 2023-12-17 14:45:42 -05:00
Tom Alexander
1ff41940a5 Merge branch 'css' 2023-12-17 14:02:20 -05:00
Tom Alexander
884215a7e1 Writing the stylesheets to the output folder. 2023-12-17 13:46:47 -05:00
Tom Alexander
20c55f0708 Loading stylesheets from the default environment. 2023-12-17 12:43:47 -05:00
Tom Alexander
9e3d72972c Add a CSS reset file. 2023-12-17 11:55:38 -05:00
Tom Alexander
806c45a453 Switch back to the published version of organic. 2023-12-17 11:54:59 -05:00
Tom Alexander
270c42a509 Update to use get_value from the latest organic code. 2023-10-31 22:03:22 -04:00
Tom Alexander
e8963e107b Merge branch 'table' 2023-10-31 20:38:36 -04:00
Tom Alexander
0b64551a23 Add templates for tables. 2023-10-31 20:31:36 -04:00
Tom Alexander
b654ca4859 Add render phase to tables. 2023-10-31 20:29:37 -04:00
Tom Alexander
386af57ce6 Add intermediate stage for tables. 2023-10-31 20:26:34 -04:00
Tom Alexander
ef4d315bf2 Run cargo fix. 2023-10-31 20:02:46 -04:00
Tom Alexander
2142b01967 Merge branch 'text_markup' 2023-10-31 20:02:13 -04:00
Tom Alexander
159d8fb72a Add render stage for text markup. 2023-10-31 20:02:04 -04:00
Tom Alexander
0fae417610 Add intermediate stage for text markup. 2023-10-31 19:57:04 -04:00
Tom Alexander
ae933b491e Use macros for the intermediate to render step.
This is largely to make changing the type signature of these functions easier by significantly reducing the amount of places that duplicates the signature.
2023-10-31 19:48:05 -04:00
Tom Alexander
5e476e189a Merge branch 'latex_fragment' 2023-10-31 19:18:20 -04:00
Tom Alexander
533997dbf5 Add a template for latex fragment. 2023-10-31 19:16:13 -04:00
Tom Alexander
8695cf17c5 Copy the value of latex fragments through the pipeline. 2023-10-31 19:14:36 -04:00
Tom Alexander
e2f9938437 Add notes about latex fragments.
The places they are currently occurring in my posts are unintentional, so I don't think I will be implementing latex fragments right now, but the notes are worth keeping.
2023-10-31 12:32:20 -04:00
Tom Alexander
ada11816fb Run cargo fix. 2023-10-29 22:31:29 -04:00
Tom Alexander
ff57242434 Merge branch 'footnote' 2023-10-29 22:29:38 -04:00
Tom Alexander
0da37b25e3 Assign the reference counts. 2023-10-29 22:29:29 -04:00
Tom Alexander
ff03140007 Order the footnotes based on when they start processing rather than when they finish.
This has the benefit of making the output order make sense when footnote definitions reference footnote references but I mostly did it to match the behavior of upstream org-mode.
2023-10-29 22:29:29 -04:00
Tom Alexander
0ae492f8d3 Promote waiting footnote definitions. 2023-10-29 22:29:29 -04:00
Tom Alexander
613d49c6ec Record on-deck footnote definitions. 2023-10-29 22:29:29 -04:00
Tom Alexander
0f7e5eea25 no-op the template for footnote definitions. 2023-10-29 22:29:29 -04:00
Tom Alexander
2e7cfd5637 Only parse footnote definitions if they target a reference that exists. 2023-10-29 22:29:28 -04:00
Tom Alexander
afe62de2b6 Re-enable AstNode. 2023-10-29 22:29:28 -04:00
Tom Alexander
1f3b5262b8 Fix build by making the registry guarded by an ArcMutex. 2023-10-29 22:29:28 -04:00
Tom Alexander
f63620b547 Registry being mutuably borrowed. 2023-10-29 22:29:28 -04:00
Tom Alexander
671159cb82 Does not work even without IntoAstNode. 2023-10-29 22:29:28 -04:00
Tom Alexander
f1e985fb32 Lifetime issue. 2023-10-29 22:29:28 -04:00
Tom Alexander
a966be8122 Remove closures from iselector macro. 2023-10-29 22:29:28 -04:00
Tom Alexander
24b9782146 Avoid closures for the intermediate macro. 2023-10-29 22:29:28 -04:00
Tom Alexander
3d44d20384 Running into borrow issue on intermediate. 2023-10-29 18:46:14 -04:00
Tom Alexander
f98a09bc59 Use macros for creating the intermediate stage.
This is to make it easier to change function signatures by consolidating the places where the signatures exist.
2023-10-29 18:46:14 -04:00
Tom Alexander
ba511b7f9e Add another test for footnote definitions. 2023-10-29 18:46:13 -04:00
Tom Alexander
3720558d93 Render the footnote definitions. 2023-10-29 18:46:13 -04:00
Tom Alexander
b66ec507ef Create a render ast node type. 2023-10-29 18:46:13 -04:00
Tom Alexander
645ae26701 Remove intermediate lifetime. 2023-10-29 14:53:11 -04:00
Tom Alexander
6109902945 Create an intermediate ast node type. 2023-10-29 14:45:02 -04:00
Tom Alexander
cd27869122 Populate render context for footnote references. 2023-10-29 14:45:02 -04:00
Tom Alexander
795945f0da Register footnote definitions. 2023-10-29 14:45:02 -04:00
Tom Alexander
cb7c28c1ae Add intermediate lifetime. 2023-10-29 12:24:49 -04:00
Tom Alexander
52ca300de3 Beginning to hand out footnote ids. 2023-10-29 12:24:49 -04:00
Tom Alexander
06dcd22e69 Switch to split inclusive instead of manually-implemented full lines iterator. 2023-10-29 10:59:33 -04:00
Tom Alexander
f87c453459 Move the full lines iterator to its own file. 2023-10-29 10:55:03 -04:00
Tom Alexander
e42edb3f49 Merge branch 'src_block' 2023-10-29 10:44:42 -04:00
Tom Alexander
6d83828012 Add inline source block. 2023-10-29 10:44:32 -04:00
Tom Alexander
eaea37f448 Add a basic template for source blocks. 2023-10-29 10:41:03 -04:00
Tom Alexander
fb99fd2b39 Get the source code lines. 2023-10-29 10:32:05 -04:00
Tom Alexander
313313ae53 Initial structure for unhighlighted source blocks. 2023-10-29 09:37:27 -04:00
176 changed files with 4255 additions and 2299 deletions

124
Cargo.lock generated
View File

@@ -17,15 +17,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.4"
@@ -188,7 +179,8 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "duster"
version = "0.1.1"
source = "git+https://code.fizz.buzz/talexander/duster.git?branch=master#3428a3f5097c7d2cc252d1bfd9aae7771553ab69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17d19cdf8e1ae4aead0978a30e99817af1c36abaf22f81901952b1310abb6989"
dependencies = [
"nom 6.1.2",
"serde",
@@ -355,12 +347,6 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lexical-core"
version = "0.7.6"
@@ -401,6 +387,22 @@ dependencies = [
"adler",
]
[[package]]
name = "natter"
version = "0.0.1"
dependencies = [
"clap",
"duster",
"futures",
"include_dir",
"organic",
"serde",
"serde_json",
"tokio",
"toml",
"walkdir",
]
[[package]]
name = "nom"
version = "6.1.2"
@@ -445,7 +447,9 @@ dependencies = [
[[package]]
name = "organic"
version = "0.1.12"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61b01691695303b42f9a2ff318bec83853fbeb65c96569f2fb391e7636801c6"
dependencies = [
"nom 7.1.3",
"walkdir",
@@ -487,35 +491,6 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@@ -609,26 +584,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.33.0"
@@ -675,26 +630,6 @@ dependencies = [
"winnow",
]
[[package]]
name = "tree-sitter"
version = "0.20.10"
source = "git+https://github.com/tree-sitter/tree-sitter.git?rev=52f7eaff3182a726eb064a91d4e49dfbaecd4ee3#52f7eaff3182a726eb064a91d4e49dfbaecd4ee3"
dependencies = [
"cc",
"regex",
]
[[package]]
name = "tree-sitter-highlight"
version = "0.20.2"
source = "git+https://github.com/tree-sitter/tree-sitter.git?rev=52f7eaff3182a726eb064a91d4e49dfbaecd4ee3#52f7eaff3182a726eb064a91d4e49dfbaecd4ee3"
dependencies = [
"lazy_static",
"regex",
"thiserror",
"tree-sitter",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
@@ -829,23 +764,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "writer"
version = "0.0.1"
dependencies = [
"clap",
"duster",
"futures",
"include_dir",
"organic",
"serde",
"serde_json",
"tokio",
"toml",
"tree-sitter-highlight",
"walkdir",
]
[[package]]
name = "wyz"
version = "0.2.0"

View File

@@ -1,19 +1,32 @@
[package]
name = "writer"
name = "natter"
version = "0.0.1"
edition = "2021"
authors = ["Tom Alexander <tom@fizz.buzz>"]
description = "A static site generator using org source files."
license = "0BSD"
repository = "https://code.fizz.buzz/talexander/natter"
readme = "README.md"
keywords = ["static", "site", "generator"]
categories = ["command-line-utilities"]
resolver = "2"
include = [
"LICENSE",
"**/*.rs",
"Cargo.toml",
"Cargo.lock",
"default_environment/"
]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.4.6", default-features = false, features = ["std", "color", "help", "derive"] }
duster = { git = "https://code.fizz.buzz/talexander/duster.git", branch = "master" }
tree-sitter-highlight = { git = "https://github.com/tree-sitter/tree-sitter.git", rev = "52f7eaff3182a726eb064a91d4e49dfbaecd4ee3" }
duster = "0.1.1"
futures = "0.3.29"
include_dir = "0.7.3"
# TODO: This is temporary to work on the latest organic code. Eventually switch back to using the published crate.
organic = { path = "../organic" }
# organic = "0.1.12"
# organic = { path = "../organic" }
organic = "0.1.13"
serde = { version = "1.0.189", default-features = false, features = ["std", "derive"] }
serde_json = "1.0.107"
tokio = { version = "1.30.0", default-features = false, features = ["rt", "rt-multi-thread", "fs", "io-util"] }

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# Natter
Natter is a static site generator for blogs using org as an input format. It is at a very early stage, and will have deep sweeping changes.

View File

@@ -0,0 +1,187 @@
:root {
--main-max-width: 800px;
--site-background-color: #0a0a0a;
--site-text-color: #fffffc;
--header-divider-color: #6a687a;
--stream-divider-color: #6ccff6;
--src-font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
--src-block-background-color: #141414;
--src-block-border-color: #84828f;
--src-block-language-color: #0a0a0a;
--src-block-language-background: #84828f;
--quote-block-border-color: #84828f;
}
body {
color: var(--site-text-color);
background-color: var(--site-background-color);
font-family: source-sans-pro, Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', sans-serif;
a:link, a:visited {
/* TODO: Should I use a different color for links? */
color: var(--site-text-color);
}
}
.page_centering {
display: flex;
flex-direction: column;
align-items: center;
}
.page_header {
width: 100%;
max-width: var(--main-max-width);
border-bottom: 0.1rem solid var(--header-divider-color);
.home_link {
font-size: 1.2rem;
font-weight: 600;
text-decoration: none;
&:link, &:visited {
color: var(--site-text-color);
}
}
}
.main_content {
width: 100%;
max-width: var(--main-max-width);
font-size: 1.2rem;
line-height: 1.2;
/* A stand-alone blog post (not in a blog stream). */
.blog_post {
padding: 1rem 0 3rem 0;
}
.blog_stream {
.stream_divider {
color: var(--stream-divider-color);
}
}
/* A blog post in a blog stream (for example, the homepage). */
.blog_stream_post {
background: #1F1F1F;
padding: 1rem 0.2rem;
}
.blog_post_title {
font-size: 2.5rem;
font-weight: 700;
padding-bottom: 1rem;
}
p {
margin: 1rem 0;
}
.src_block {
background: var(--src-block-background-color);
border-radius: 3px;
border: 1px solid var(--src-block-border-color);
font-size: 1rem;
font-family: var(--src-font-family);
margin: 1rem 0;
.src_language {
display: inline-block;
color: var(--src-block-language-color);
background: var(--src-block-language-background);
border-radius: 0 0 3px 0;
padding: 0.1rem 0.5rem;
font-size: 0.8rem;
vertical-align: top;
}
.src_body {
margin: 0.5rem;
.src_line {
white-space: pre-wrap;
}
}
}
.inline_source_block {
font-family: var(--src-font-family);
font-size: 1rem;
}
.code, .verbatim {
font-family: var(--src-font-family);
font-size: 1rem;
}
.quote_block {
border-left: 1px solid var(--quote-block-border-color);
padding: 0 0 0 1rem;
margin: 1rem 0 1rem 2rem;
}
h2, h3 {
margin: 1rem 0;
padding-bottom: 0.5rem;
}
h2 {
font-size: 2.3rem;
font-weight: 600;
}
h3 {
font-size: 2.1rem;
font-weight: 600;
}
.plain_list {
&.unordered {
list-style-type: disc;
padding-left: 2.5rem;
}
&.ordered {
list-style-type: decimal;
padding-left: 2.5rem;
}
&.descriptive {
font-size: 1rem;
> dt {
font-weight: 600;
}
> dd {
padding-left: 2.5rem;
}
}
}
.footnote_reference {
vertical-align: super;
font-size: 80%;
> a {
text-decoration: none;
}
}
.footnote_definition {
.label {
text-decoration: none;
}
.definition {
display: inline;
> p {
display: inline;
}
}
}
}

View File

@@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@@ -0,0 +1,57 @@
{@select key=.type}
{@eq value="heading"}{>heading/}{/eq}
{@eq value="section"}{>section/}{/eq}
{@eq value="paragraph"}{>paragraph/}{/eq}
{@eq value="plain_list"}{>plain_list/}{/eq}
{@eq value="center_block"}{>center_block/}{/eq}
{@eq value="quote_block"}{>quote_block/}{/eq}
{@eq value="special_block"}{>special_block/}{/eq}
{@eq value="dynamic_block"}{>dynamic_block/}{/eq}
{@eq value="footnote_definition"}{>footnote_definition/}{/eq}
{@eq value="comment"}{>comment/}{/eq}
{@eq value="drawer"}{>drawer/}{/eq}
{@eq value="property_drawer"}{>property_drawer/}{/eq}
{@eq value="table"}{>table/}{/eq}
{@eq value="verse_block"}{>verse_block/}{/eq}
{@eq value="comment_block"}{>comment_block/}{/eq}
{@eq value="example_block"}{>example_block/}{/eq}
{@eq value="export_block"}{>export_block/}{/eq}
{@eq value="src_block"}{>src_block/}{/eq}
{@eq value="clock"}{>clock/}{/eq}
{@eq value="diary_sexp"}{>diary_sexp/}{/eq}
{@eq value="planning"}{>planning/}{/eq}
{@eq value="fixed_width_area"}{>fixed_width_area/}{/eq}
{@eq value="horizontal_rule"}{>horizontal_rule/}{/eq}
{@eq value="keyword"}{>keyword/}{/eq}
{@eq value="babel_call"}{>babel_call/}{/eq}
{@eq value="latex_environment"}{>latex_environment/}{/eq}
{@eq value="bold"}{>bold/}{/eq}
{@eq value="italic"}{>italic/}{/eq}
{@eq value="underline"}{>underline/}{/eq}
{@eq value="strike_through"}{>strike_through/}{/eq}
{@eq value="code"}{>code/}{/eq}
{@eq value="verbatim"}{>verbatim/}{/eq}
{@eq value="plain_text"}{>plain_text/}{/eq}
{@eq value="regular_link"}{>regular_link/}{/eq}
{@eq value="radio_link"}{>radio_link/}{/eq}
{@eq value="radio_target"}{>radio_target/}{/eq}
{@eq value="plain_link"}{>plain_link/}{/eq}
{@eq value="angle_link"}{>angle_link/}{/eq}
{@eq value="org_macro"}{>org_macro/}{/eq}
{@eq value="entity"}{>entity/}{/eq}
{@eq value="latex_fragment"}{>latex_fragment/}{/eq}
{@eq value="export_snippet"}{>export_snippet/}{/eq}
{@eq value="footnote_reference"}{>footnote_reference/}{/eq}
{@eq value="citation"}{>citation/}{/eq}
{@eq value="citation_reference"}{>citation_reference/}{/eq}
{@eq value="inline_babel_call"}{>inline_babel_call/}{/eq}
{@eq value="inline_source_block"}{>inline_source_block/}{/eq}
{@eq value="line_break"}{>line_break/}{/eq}
{@eq value="target"}{>target/}{/eq}
{@eq value="statistics_cookie"}{>statistics_cookie/}{/eq}
{@eq value="subscript"}{>subscript/}{/eq}
{@eq value="superscript"}{>superscript/}{/eq}
{@eq value="timestamp"}{>timestamp/}{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized type {.type}.{/none}
{/select}
{! TODO: Maybe the final space should be conditional on end blank in the org source !}

View File

@@ -1,8 +1,6 @@
<div class="blog_post">
<div class="blog_post_intro">
{?.title}{?.self_link}<a class="blog_post_title" href="{.link}">{.title}</a>{:else}<div class="blog_post_title">{.title}</div>{/.self_link}{/.title}
<article class="blog_post">
{?.title}<h1 class="blog_post_title"><span>{.title}</span></h1>{/.title}
{! TODO: date? !}
</div>
{! TODO: Table of contents? !}
@@ -10,5 +8,12 @@
{#.children}
{>document_element/}
{/.children}
{?.footnotes}
<h2>Footnotes:</h2>
{#.footnotes}
{>real_footnote_definition/}
{/.footnotes}
{/.footnotes}
</div>
</div>
</article>

View File

@@ -0,0 +1,32 @@
<div class="blog_stream">
{#.children}
{@gt key=$idx value=0}<hr class="stream_divider" />{/gt}
<div class="blog_stream_post">
<div class="blog_post_intro">
{?.title}{?.self_link}<a class="blog_post_title" href="{.self_link}">{.title}</a>{:else}<div class="blog_post_title">{.title}</div>{/.self_link}{/.title}
{! TODO: date? !}
</div>
{! TODO: Table of contents? !}
<div class="blog_post_body">
{#.children}
{>document_element/}
{/.children}
{?.footnotes}
<h2>Footnotes:</h2>
{#.footnotes}
{>real_footnote_definition/}
{/.footnotes}
{/.footnotes}
</div>
</div>
{/.children}
{#.stream_pagination}
<div class="stream_nav">
{?.older_link}<a href="{.older_link}">Older</a>{/.older_link}
{?.newer_link}<a href="{.newer_link}">Newer</a>{/.newer_link}
</div>
{/.stream_pagination}
</div>

View File

@@ -1 +1 @@
<code>{.source}</code>
<code class="code">{.contents}</code>

View File

@@ -1,6 +1,7 @@
{@select key=.type}
{@eq value="paragraph"}{>paragraph/}{/eq}
{@eq value="plain_list"}{>plain_list/}{/eq}
{@eq value="plain_list_simple_item"}{>plain_list_simple_item/}{/eq}
{@eq value="center_block"}{>center_block/}{/eq}
{@eq value="quote_block"}{>quote_block/}{/eq}
{@eq value="special_block"}{>special_block/}{/eq}

View File

@@ -1 +1 @@
!!!!!!!! footnote_definition
{! noop !}

View File

@@ -1 +1 @@
!!!!!!!! footnote_reference
<sup class="footnote_reference"><a id="{.reference_id}" href="{.definition_link}">{.label}</a></sup>

View File

@@ -1 +1 @@
!!!!!!!! inline_source_block
<code class="inline_source_block">{.value}</code>

View File

@@ -1 +1,2 @@
!!!!!!!! latex_fragment
{! TODO: Should I be including MathJax somewhere? !}
{.value}

View File

@@ -6,13 +6,14 @@
{#global_settings.js_files}<script type="text/javascript" src="{.}"></script>{/global_settings.js_files}
{?global_settings.page_title}<title>{global_settings.page_title}</title>{/global_settings.page_title}
</head>
<body>
{! TODO: Header bar with links? !}
<div class="main_content">
<body class="page_centering">
{#.page_header}{>page_header/}{/.page_header}
<main class="main_content">
{@select key=.type}
{@eq value="blog_post_page"}{>blog_post_page/}{/eq}
{@eq value="blog_stream"}{>blog_stream/}{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized page content type{/none}
{/select}
</div>
</main>
</body>
</html>

View File

@@ -27,5 +27,4 @@
{@eq value="superscript"}{>superscript/}{/eq}
{@eq value="timestamp"}{>timestamp/}{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized type {.type}.{/none}
{/select}{~s}
{! TODO: Maybe the final space should be conditional on end blank in the org source !}
{/select}{@gt key=.post_blank value=0}{~s}{/gt}

View File

@@ -0,0 +1,4 @@
<header class="page_header">
<a class="home_link" href="{.home_link}">{.website_title}</a>
{! TODO: Additional links? Probably using the nav semantic element. !}
</header>

View File

@@ -1,6 +1,6 @@
{@select key=.list_type}
{@eq value="unordered"}<ul>{#.children}{>plain_list_item/}{/.children}</ul>{/eq}
{@eq value="ordered"}<ol>{#.children}{>plain_list_item/}{/.children}</ol>{/eq}
{@eq value="descriptive"}<dl>{#.children}{>plain_list_item/}{/.children}</dl>{/eq}
{@eq value="unordered"}<ul class="plain_list unordered">{#.children}{>plain_list_item/}{/.children}</ul>{/eq}
{@eq value="ordered"}<ol class="plain_list ordered">{#.children}{>plain_list_item/}{/.children}</ol>{/eq}
{@eq value="descriptive"}<dl class="plain_list descriptive">{#.children}{>plain_list_item/}{/.children}</dl>{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized list type {.list_type}.{/none}
{/select}

View File

@@ -0,0 +1,3 @@
{#.children}
{>object/}
{/.children}

View File

@@ -1,3 +1,3 @@
<blockquote>{#.children}
<blockquote class="quote_block">{#.children}
{>element/}
{/.children}</blockquote>

View File

@@ -0,0 +1 @@
<div class="footnote_definition"><a id="{.definition_id}" href="{.reference_link}" class="label">{.label}.</a> <div class="definition">{#.contents}{>ast_node/}{/.contents}</div></div>

View File

@@ -1 +1,12 @@
!!!!!!!! src_block
<div class="src_block">
{?.language}<div class="src_language">{.language}</div>{/.language}
<table class="src_body">
<tbody>
{#.lines}
<tr>
<td><code class="src_line">{.}</code></td>
</tr>
{/.lines}
</tbody>
</table>
</div>

View File

@@ -1 +1 @@
!!!!!!!! table
<table>{#.children}{>table_row/}{/.children}</table>

View File

@@ -0,0 +1 @@
<td>{#.children}{>object/}{/.children}</td>

View File

@@ -0,0 +1 @@
<tr>{#.children}{>table_cell/}{/.children}</tr>

View File

@@ -1 +1 @@
<code>{.source}</code>
<code class="verbatim">{.contents}</code>

View File

@@ -0,0 +1,21 @@
# This test shows that footnote references only count if the definition containing them is rendered.
foo[fn:a:bar]
[fn:a] lorem
[fn:b] ipsum
[fn:d] fizz
[fn:c] dolar
yo[fn:b]
hello[fn:c]
[fn:e] buzz
sup[fn:d]

View File

@@ -0,0 +1,25 @@
# Test proves that:
#
# - Anonymous references with identical content get unique IDs.
# - Unreferenced footnote definitions are dropped.
# - Footnote definitions that come before their first reference are dropped.
foo[fn:2:something]
bar[fn::something]
baz[fn::something]
cat[fn::something]
dog[fn:3]
[fn:3] ipsum
[fn:4] lorem
[fn:3] dolar
[fn:5] not referenced
stuff[fn:4] and things

View File

@@ -0,0 +1,36 @@
* Double dollar
#+begin_src org
$$CONTENTS$$
#+end_src
becomes
#+begin_src text
\[CONTENTS\]
#+end_src
#+begin_src org
$$1+1=2$$
#+end_src
#+begin_src text
\[1+1=2\]
#+end_src
This gets interpreted by mathjax.
* Single Dollar
#+begin_src org
PRE$BORDER1 BODY BORDER2$POST
#+end_src
becomes
#+begin_src text
\(BORDER1 BODY BORDER2\)
#+end_src
#+begin_src org
foo$a bar b$.
#+end_src
becomes
#+begin_src text
foo\(a bar b\).
#+end_src
This gets interpreted by mathjax.

View File

@@ -4,7 +4,7 @@ use clap::Subcommand;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(name = "Writer")]
#[command(name = "Natter")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(about = "Generate a static site.", long_about = None)]
#[command(propagate_version = true)]
@@ -24,14 +24,14 @@ pub(crate) enum Commands {
#[derive(Args, Debug)]
pub(crate) struct InitArgs {
/// Path where you want the initial writer structure to be located.
/// Path where you want the initial natter structure to be located.
#[arg(short, long)]
pub(crate) path: PathBuf,
}
#[derive(Args, Debug)]
pub(crate) struct BuildArgs {
/// Path to the writer config file.
/// Path to the natter config file.
#[arg(short, long)]
pub(crate) config: PathBuf,
}

View File

@@ -1,4 +1,5 @@
mod render;
mod runner;
mod stylesheet;
pub(crate) use runner::build_site;

View File

@@ -5,30 +5,41 @@ use include_dir::include_dir;
use include_dir::Dir;
use crate::config::Config;
use crate::context::RenderBlogPostPage;
use crate::context::RenderBlogPostPageInput;
use crate::context::RenderBlogStream;
use crate::context::RenderBlogStreamInput;
use crate::context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::convert_blog_post_page_to_render_context;
use crate::intermediate::get_web_path;
use crate::intermediate::BlogPost;
use crate::render::DusterRenderer;
use crate::render::RendererIntegration;
use super::stylesheet::Stylesheet;
static MAIN_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/default_environment/templates/html");
pub(crate) struct SiteRenderer {
output_directory: PathBuf,
blog_posts: Vec<BlogPost>,
stylesheets: Vec<Stylesheet>,
}
impl SiteRenderer {
pub(crate) fn new<P: Into<PathBuf>>(
output_directory: P,
blog_posts: Vec<BlogPost>,
stylesheets: Vec<Stylesheet>,
) -> SiteRenderer {
SiteRenderer {
output_directory: output_directory.into(),
blog_posts,
stylesheets,
}
}
pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> {
fn init_renderer_integration(&self) -> Result<DusterRenderer<'_>, CustomError> {
let mut renderer_integration = DusterRenderer::new();
let sources: Vec<_> = MAIN_TEMPLATES
@@ -56,21 +67,27 @@ impl SiteRenderer {
renderer_integration.load_template(name, contents)?;
}
Ok(renderer_integration)
}
pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> {
let renderer_integration = self.init_renderer_integration()?;
for blog_post in &self.blog_posts {
for blog_post_page in &blog_post.pages {
let output_path = self
.output_directory
.join("posts")
.join(&blog_post.id)
.join(config.get_relative_path_to_post(&blog_post.id))
.join(blog_post_page.get_output_path());
let render_context = convert_blog_post_page_to_render_context(
let convert_input = RenderBlogPostPageInput::new(blog_post, blog_post_page);
let render_context = RenderContext::new(
config,
&self.output_directory,
&output_path,
blog_post,
blog_post_page,
self.output_directory.as_path(),
output_path.as_path(),
None,
)?;
let render_context = RenderBlogPostPage::new(render_context, &convert_input)?;
let rendered_output = renderer_integration.render(render_context)?;
let parent_directory = output_path
.parent()
@@ -82,6 +99,103 @@ impl SiteRenderer {
Ok(())
}
pub(crate) async fn render_blog_stream(&self, config: &Config) -> Result<(), CustomError> {
let renderer_integration = self.init_renderer_integration()?;
// Sort blog posts by date, newest first.
let sorted_blog_posts = {
let mut sorted_blog_posts: Vec<_> = self.blog_posts.iter().collect();
sorted_blog_posts
.sort_by_key(|blog_post| (blog_post.get_date(), blog_post.id.as_str()));
sorted_blog_posts.reverse();
sorted_blog_posts
};
for blog_post in &sorted_blog_posts {
if blog_post.get_date().is_none() {
return Err(format!("Blog post {} does not have a date.", blog_post.id).into());
}
}
// Group blog posts based on # of posts per page.
let stream_chunks: Vec<_> = sorted_blog_posts
.chunks(config.get_stream_entries_per_page())
.collect();
// For each group, create a RenderBlogStream.
let num_stream_pages = stream_chunks.len();
for (page_num, chunk) in stream_chunks.into_iter().enumerate() {
let output_file = if page_num == 0 {
self.output_directory.join("index.html")
} else {
self.output_directory
.join("stream")
.join(format!("{}.html", page_num))
};
let newer_link = if page_num == 0 {
None
} else if page_num == 1 {
Some(get_web_path(
config,
&self.output_directory,
&output_file,
"index.html",
)?)
} else {
Some(get_web_path(
config,
&self.output_directory,
&output_file,
format!("stream/{}.html", page_num - 1),
)?)
};
let older_link = if page_num == (num_stream_pages - 1) {
None
} else {
Some(get_web_path(
config,
&self.output_directory,
&output_file,
format!("stream/{}.html", page_num + 1),
)?)
};
let convert_input = RenderBlogStreamInput::new(chunk, older_link, newer_link);
let render_context = RenderContext::new(
config,
self.output_directory.as_path(),
output_file.as_path(),
None,
)?;
let blog_stream = RenderBlogStream::new(render_context, &convert_input)?;
// Pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages.
let rendered_output = renderer_integration.render(blog_stream)?;
let parent_directory = output_file
.parent()
.ok_or("Output file should have a containing directory.")?;
tokio::fs::create_dir_all(parent_directory).await?;
tokio::fs::write(output_file, rendered_output).await?;
}
Ok(())
}
pub(crate) async fn render_stylesheets(&self) -> Result<(), CustomError> {
let stylesheet_output_directory = self.output_directory.join("stylesheet");
if !stylesheet_output_directory.exists() {
tokio::fs::create_dir(&stylesheet_output_directory).await?;
}
for stylesheet in &self.stylesheets {
let file_output_path = stylesheet_output_directory.join(&stylesheet.path);
let parent_directory = file_output_path
.parent()
.ok_or("Output file should have a containing directory.")?;
tokio::fs::create_dir_all(parent_directory).await?;
tokio::fs::write(file_output_path, stylesheet.contents.as_bytes()).await?;
}
Ok(())
}
}
fn build_name_contents_pairs<'a>(

View File

@@ -1,16 +1,30 @@
use std::ffi::OsStr;
use std::path::PathBuf;
use super::stylesheet::Stylesheet;
use crate::cli::parameters::BuildArgs;
use crate::command::build::render::SiteRenderer;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::BlogPost;
use include_dir::include_dir;
use include_dir::Dir;
static DEFAULT_STYLESHEETS: Dir =
include_dir!("$CARGO_MANIFEST_DIR/default_environment/stylesheet");
pub(crate) async fn build_site(args: BuildArgs) -> Result<(), CustomError> {
let config = Config::load_from_file(args.config).await?;
let blog_posts = load_blog_posts(&config).await?;
let renderer = SiteRenderer::new(get_output_directory(&config).await?, blog_posts);
let stylesheets = load_stylesheets().await?;
let renderer = SiteRenderer::new(
get_output_directory(&config).await?,
blog_posts,
stylesheets,
);
renderer.render_blog_posts(&config).await?;
renderer.render_blog_stream(&config).await?;
renderer.render_stylesheets().await?;
Ok(())
}
@@ -58,3 +72,18 @@ async fn load_blog_posts(config: &Config) -> Result<Vec<BlogPost>, CustomError>
}
Ok(blog_posts)
}
async fn load_stylesheets() -> Result<Vec<Stylesheet>, CustomError> {
let sources: Vec<_> = DEFAULT_STYLESHEETS
.files()
.filter(|f| f.path().extension() == Some(OsStr::new("css")))
.collect();
let mut ret = Vec::with_capacity(sources.len());
for entry in sources {
let path = entry.path().to_path_buf();
let contents = String::from_utf8(entry.contents().to_vec())?;
let stylesheet = Stylesheet::new(path, contents).await?;
ret.push(stylesheet);
}
Ok(ret)
}

View File

@@ -0,0 +1,15 @@
use std::path::PathBuf;
use crate::error::CustomError;
#[derive(Debug)]
pub(crate) struct Stylesheet {
pub(crate) path: PathBuf,
pub(crate) contents: String,
}
impl Stylesheet {
pub(crate) async fn new(path: PathBuf, contents: String) -> Result<Stylesheet, CustomError> {
Ok(Stylesheet { path, contents })
}
}

View File

@@ -1,3 +1,3 @@
mod runner;
pub(crate) use runner::init_writer_folder;
pub(crate) use runner::init_natter_folder;

View File

@@ -2,7 +2,7 @@ use crate::cli::parameters::InitArgs;
use crate::config::Config;
use crate::error::CustomError;
pub(crate) async fn init_writer_folder(args: InitArgs) -> Result<(), CustomError> {
pub(crate) async fn init_natter_folder(args: InitArgs) -> Result<(), CustomError> {
if args.path.exists() && !args.path.is_dir() {
return Err("The supplied path exists but is not a directory. Aborting.".into());
}

View File

@@ -8,6 +8,7 @@ use crate::error::CustomError;
use super::raw::RawConfig;
/// This is the config struct used by most of the code, which is an interpreted version of the RawConfig struct which is the raw disk-representation of the config.
#[derive(Debug)]
pub(crate) struct Config {
raw: RawConfig,
config_path: PathBuf,
@@ -16,7 +17,7 @@ pub(crate) struct Config {
impl Config {
pub(crate) fn new<P: AsRef<Path>>(root_dir: P) -> Result<Config, CustomError> {
fn inner(root_dir: &Path) -> Result<Config, CustomError> {
let file_path = root_dir.join("writer.toml");
let file_path = root_dir.join("natter.toml");
Ok(Config {
raw: RawConfig::default(),
config_path: file_path,
@@ -56,6 +57,15 @@ impl Config {
self.get_root_directory().join("posts")
}
/// Get the relative path to the folder containing a blog post.
///
/// This could be appended to the output root directory to get the
/// blog post output folder or it could be used to generate a link
/// to the blog post.
pub(crate) fn get_relative_path_to_post<P: AsRef<Path>>(&self, post_id: P) -> PathBuf {
Path::new("posts").join(post_id)
}
pub(crate) fn get_output_directory(&self) -> PathBuf {
self.get_root_directory().join("output")
}
@@ -67,4 +77,17 @@ impl Config {
pub(crate) fn get_web_root(&self) -> Option<&str> {
self.raw.web_root.as_deref()
}
pub(crate) fn get_site_title(&self) -> Option<&str> {
self.raw.site_title.as_deref()
}
pub(crate) fn get_stream_entries_per_page(&self) -> usize {
self.raw
.stream
.as_ref()
.map(|stream| stream.entries_per_page)
.flatten()
.unwrap_or(5)
}
}

View File

@@ -1,24 +1,39 @@
use serde::Deserialize;
use serde::Serialize;
/// This is the struct for the writer.toml config file that ends up in each site's root directory.
#[derive(Deserialize, Serialize)]
/// This is the struct for the natter.toml config file that ends up in each site's root directory.
#[derive(Debug, Deserialize, Serialize)]
pub(crate) struct RawConfig {
site_title: String,
pub(super) site_title: Option<String>,
author: Option<String>,
email: Option<String>,
pub(super) use_relative_paths: Option<bool>,
pub(super) web_root: Option<String>,
pub(super) stream: Option<RawConfigStream>,
}
impl Default for RawConfig {
fn default() -> Self {
RawConfig {
site_title: "My super awesome website".to_owned(),
site_title: None,
author: None,
email: None,
use_relative_paths: None,
web_root: None,
stream: None,
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub(crate) struct RawConfigStream {
pub(super) entries_per_page: Option<usize>,
}
impl Default for RawConfigStream {
fn default() -> Self {
RawConfigStream {
entries_per_page: None,
}
}
}

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IAngleLink;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "angle_link")]
pub(crate) struct RenderAngleLink {}
pub(crate) struct RenderAngleLink {
post_blank: organic::types::PostBlank,
}
impl RenderAngleLink {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IAngleLink,
) -> Result<RenderAngleLink, CustomError> {
Ok(RenderAngleLink {})
}
}
rnoop!(RenderAngleLink, IAngleLink);

327
src/context/ast_node.rs Normal file
View File

@@ -0,0 +1,327 @@
use serde::Serialize;
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::render_context::RenderContext;
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,
render_context: RenderContext<'_>,
) -> Result<RenderAstNode, CustomError>;
}
impl IntoRenderAstNode for IAstNode {
fn into_render_ast_node(
&self,
render_context: RenderContext<'_>,
) -> Result<RenderAstNode, CustomError> {
match self {
IAstNode::Heading(inner) => Ok(RenderAstNode::Heading(RenderHeading::new(
render_context,
inner,
)?)),
IAstNode::Section(inner) => Ok(RenderAstNode::Section(RenderSection::new(
render_context,
inner,
)?)),
IAstNode::Paragraph(inner) => Ok(RenderAstNode::Paragraph(RenderParagraph::new(
render_context,
inner,
)?)),
IAstNode::PlainList(inner) => Ok(RenderAstNode::PlainList(RenderPlainList::new(
render_context,
inner,
)?)),
IAstNode::CenterBlock(inner) => Ok(RenderAstNode::CenterBlock(RenderCenterBlock::new(
render_context,
inner,
)?)),
IAstNode::QuoteBlock(inner) => Ok(RenderAstNode::QuoteBlock(RenderQuoteBlock::new(
render_context,
inner,
)?)),
IAstNode::SpecialBlock(inner) => Ok(RenderAstNode::SpecialBlock(
RenderSpecialBlock::new(render_context, inner)?,
)),
IAstNode::DynamicBlock(inner) => Ok(RenderAstNode::DynamicBlock(
RenderDynamicBlock::new(render_context, inner)?,
)),
IAstNode::FootnoteDefinition(inner) => Ok(RenderAstNode::FootnoteDefinition(
RenderFootnoteDefinition::new(render_context, inner)?,
)),
IAstNode::Comment(inner) => Ok(RenderAstNode::Comment(RenderComment::new(
render_context,
inner,
)?)),
IAstNode::Drawer(inner) => Ok(RenderAstNode::Drawer(RenderDrawer::new(
render_context,
inner,
)?)),
IAstNode::PropertyDrawer(inner) => Ok(RenderAstNode::PropertyDrawer(
RenderPropertyDrawer::new(render_context, inner)?,
)),
IAstNode::Table(inner) => Ok(RenderAstNode::Table(RenderTable::new(
render_context,
inner,
)?)),
IAstNode::VerseBlock(inner) => Ok(RenderAstNode::VerseBlock(RenderVerseBlock::new(
render_context,
inner,
)?)),
IAstNode::CommentBlock(inner) => Ok(RenderAstNode::CommentBlock(
RenderCommentBlock::new(render_context, inner)?,
)),
IAstNode::ExampleBlock(inner) => Ok(RenderAstNode::ExampleBlock(
RenderExampleBlock::new(render_context, inner)?,
)),
IAstNode::ExportBlock(inner) => Ok(RenderAstNode::ExportBlock(RenderExportBlock::new(
render_context,
inner,
)?)),
IAstNode::SrcBlock(inner) => Ok(RenderAstNode::SrcBlock(RenderSrcBlock::new(
render_context,
inner,
)?)),
IAstNode::Clock(inner) => Ok(RenderAstNode::Clock(RenderClock::new(
render_context,
inner,
)?)),
IAstNode::DiarySexp(inner) => Ok(RenderAstNode::DiarySexp(RenderDiarySexp::new(
render_context,
inner,
)?)),
IAstNode::Planning(inner) => Ok(RenderAstNode::Planning(RenderPlanning::new(
render_context,
inner,
)?)),
IAstNode::FixedWidthArea(inner) => Ok(RenderAstNode::FixedWidthArea(
RenderFixedWidthArea::new(render_context, inner)?,
)),
IAstNode::HorizontalRule(inner) => Ok(RenderAstNode::HorizontalRule(
RenderHorizontalRule::new(render_context, inner)?,
)),
IAstNode::Keyword(inner) => Ok(RenderAstNode::Keyword(RenderKeyword::new(
render_context,
inner,
)?)),
IAstNode::BabelCall(inner) => Ok(RenderAstNode::BabelCall(RenderBabelCall::new(
render_context,
inner,
)?)),
IAstNode::LatexEnvironment(inner) => Ok(RenderAstNode::LatexEnvironment(
RenderLatexEnvironment::new(render_context, inner)?,
)),
IAstNode::Bold(inner) => {
Ok(RenderAstNode::Bold(RenderBold::new(render_context, inner)?))
}
IAstNode::Italic(inner) => Ok(RenderAstNode::Italic(RenderItalic::new(
render_context,
inner,
)?)),
IAstNode::Underline(inner) => Ok(RenderAstNode::Underline(RenderUnderline::new(
render_context,
inner,
)?)),
IAstNode::StrikeThrough(inner) => Ok(RenderAstNode::StrikeThrough(
RenderStrikeThrough::new(render_context, inner)?,
)),
IAstNode::Code(inner) => {
Ok(RenderAstNode::Code(RenderCode::new(render_context, inner)?))
}
IAstNode::Verbatim(inner) => Ok(RenderAstNode::Verbatim(RenderVerbatim::new(
render_context,
inner,
)?)),
IAstNode::PlainText(inner) => Ok(RenderAstNode::PlainText(RenderPlainText::new(
render_context,
inner,
)?)),
IAstNode::RegularLink(inner) => Ok(RenderAstNode::RegularLink(RenderRegularLink::new(
render_context,
inner,
)?)),
IAstNode::RadioLink(inner) => Ok(RenderAstNode::RadioLink(RenderRadioLink::new(
render_context,
inner,
)?)),
IAstNode::RadioTarget(inner) => Ok(RenderAstNode::RadioTarget(RenderRadioTarget::new(
render_context,
inner,
)?)),
IAstNode::PlainLink(inner) => Ok(RenderAstNode::PlainLink(RenderPlainLink::new(
render_context,
inner,
)?)),
IAstNode::AngleLink(inner) => Ok(RenderAstNode::AngleLink(RenderAngleLink::new(
render_context,
inner,
)?)),
IAstNode::OrgMacro(inner) => Ok(RenderAstNode::OrgMacro(RenderOrgMacro::new(
render_context,
inner,
)?)),
IAstNode::Entity(inner) => Ok(RenderAstNode::Entity(RenderEntity::new(
render_context,
inner,
)?)),
IAstNode::LatexFragment(inner) => Ok(RenderAstNode::LatexFragment(
RenderLatexFragment::new(render_context, inner)?,
)),
IAstNode::ExportSnippet(inner) => Ok(RenderAstNode::ExportSnippet(
RenderExportSnippet::new(render_context, inner)?,
)),
IAstNode::FootnoteReference(inner) => Ok(RenderAstNode::FootnoteReference(
RenderFootnoteReference::new(render_context, inner)?,
)),
IAstNode::Citation(inner) => Ok(RenderAstNode::Citation(RenderCitation::new(
render_context,
inner,
)?)),
IAstNode::CitationReference(inner) => Ok(RenderAstNode::CitationReference(
RenderCitationReference::new(render_context, inner)?,
)),
IAstNode::InlineBabelCall(inner) => Ok(RenderAstNode::InlineBabelCall(
RenderInlineBabelCall::new(render_context, inner)?,
)),
IAstNode::InlineSourceBlock(inner) => Ok(RenderAstNode::InlineSourceBlock(
RenderInlineSourceBlock::new(render_context, inner)?,
)),
IAstNode::LineBreak(inner) => Ok(RenderAstNode::LineBreak(RenderLineBreak::new(
render_context,
inner,
)?)),
IAstNode::Target(inner) => Ok(RenderAstNode::Target(RenderTarget::new(
render_context,
inner,
)?)),
IAstNode::StatisticsCookie(inner) => Ok(RenderAstNode::StatisticsCookie(
RenderStatisticsCookie::new(render_context, inner)?,
)),
IAstNode::Subscript(inner) => Ok(RenderAstNode::Subscript(RenderSubscript::new(
render_context,
inner,
)?)),
IAstNode::Superscript(inner) => Ok(RenderAstNode::Superscript(RenderSuperscript::new(
render_context,
inner,
)?)),
IAstNode::Timestamp(inner) => Ok(RenderAstNode::Timestamp(RenderTimestamp::new(
render_context,
inner,
)?)),
}
}
}

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IBabelCall;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "babel_call")]
pub(crate) struct RenderBabelCall {}
pub(crate) struct RenderBabelCall {
post_blank: organic::types::PostBlank,
}
impl RenderBabelCall {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IBabelCall,
) -> Result<RenderBabelCall, CustomError> {
Ok(RenderBabelCall {})
}
}
rnoop!(RenderBabelCall, IBabelCall);

View File

@@ -1,34 +1,123 @@
use serde::Serialize;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::get_web_path;
use crate::intermediate::BlogPost;
use crate::intermediate::BlogPostPage;
use super::footnote_definition::RenderRealFootnoteDefinition;
use super::macros::render;
use super::GlobalSettings;
use super::PageHeader;
use super::RenderDocumentElement;
#[derive(Debug)]
pub(crate) struct RenderBlogPostPageInput<'a> {
post: &'a BlogPost,
page: &'a BlogPostPage,
}
impl<'a> RenderBlogPostPageInput<'a> {
pub(crate) fn new(post: &'a BlogPost, page: &'a BlogPostPage) -> RenderBlogPostPageInput<'a> {
RenderBlogPostPageInput { post, page }
}
}
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "blog_post_page")]
pub(crate) struct RenderBlogPostPage {
global_settings: GlobalSettings,
page_header: Option<PageHeader>,
/// The title that will be shown visibly on the page.
title: Option<String>,
self_link: Option<String>,
children: Vec<RenderDocumentElement>,
footnotes: Vec<RenderRealFootnoteDefinition>,
}
impl RenderBlogPostPage {
pub(crate) fn new(
global_settings: GlobalSettings,
title: Option<String>,
self_link: Option<String>,
children: Vec<RenderDocumentElement>,
) -> RenderBlogPostPage {
RenderBlogPostPage {
render!(
RenderBlogPostPage,
RenderBlogPostPageInput,
original,
render_context,
{
let css_files = vec![
get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"stylesheet/reset.css",
)?,
get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"stylesheet/main.css",
)?,
];
let js_files = vec![get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"blog_post.js",
)?];
let global_settings = GlobalSettings::new(original.page.title.clone(), css_files, js_files);
let page_header = PageHeader::new(
render_context.config.get_site_title().map(str::to_string),
Some(get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"",
)?),
);
let link_to_blog_post = get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
render_context
.output_file
.strip_prefix(render_context.output_root_directory)?,
)?;
let children = {
let mut children = Vec::new();
for child in original.page.children.iter() {
children.push(RenderDocumentElement::new(render_context.clone(), child)?);
}
children
};
let footnotes = {
let mut ret = Vec::new();
for footnote in original.page.footnotes.iter() {
ret.push(RenderRealFootnoteDefinition::new(
render_context.clone(),
footnote,
)?);
}
ret
};
let ret = RenderBlogPostPage {
global_settings,
title,
self_link,
page_header: Some(page_header),
title: original.page.title.clone(),
self_link: Some(link_to_blog_post),
children,
footnotes,
};
Ok(ret)
}
}
}
);

213
src/context/blog_stream.rs Normal file
View File

@@ -0,0 +1,213 @@
use serde::Serialize;
use super::macros::render;
use super::render_context::RenderContext;
use crate::context::RenderDocumentElement;
use crate::context::RenderRealFootnoteDefinition;
use crate::error::CustomError;
use crate::intermediate::get_web_path;
use crate::intermediate::BlogPost;
use super::GlobalSettings;
use super::PageHeader;
#[derive(Debug)]
pub(crate) struct RenderBlogStreamInput<'a, 'b> {
original: &'a [&'b BlogPost],
older_link: Option<String>,
newer_link: Option<String>,
}
impl<'a, 'b> RenderBlogStreamInput<'a, 'b> {
pub(crate) fn new(
original: &'a [&'b BlogPost],
older_link: Option<String>,
newer_link: Option<String>,
) -> RenderBlogStreamInput<'a, 'b> {
RenderBlogStreamInput {
original,
older_link,
newer_link,
}
}
}
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "blog_stream")]
pub(crate) struct RenderBlogStream {
global_settings: GlobalSettings,
page_header: Option<PageHeader>,
children: Vec<RenderBlogStreamEntry>,
stream_pagination: Option<RenderBlogStreamPagination>,
}
render!(
RenderBlogStream,
RenderBlogStreamInput,
original,
render_context,
{
let css_files = vec![
get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"stylesheet/reset.css",
)?,
get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"stylesheet/main.css",
)?,
];
let js_files = vec![get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"blog_post.js",
)?];
let global_settings = GlobalSettings::new(
render_context.config.get_site_title().map(str::to_string),
css_files,
js_files,
);
let page_header = PageHeader::new(
render_context.config.get_site_title().map(str::to_string),
Some(get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
"",
)?),
);
let children = original
.original
.into_iter()
.enumerate()
.map(|(i, blog_post)| {
RenderBlogStreamEntry::new(
render_context.clone(),
&RenderBlogStreamEntryInput::new(blog_post, i),
)
})
.collect::<Result<Vec<_>, _>>()?;
let stream_pagination = if original.older_link.is_some() || original.newer_link.is_some() {
Some(RenderBlogStreamPagination::new(
original.older_link.clone(),
original.newer_link.clone(),
)?)
} else {
None
};
Ok(RenderBlogStream {
global_settings,
page_header: Some(page_header),
children,
stream_pagination,
})
}
);
#[derive(Debug)]
pub(crate) struct RenderBlogStreamEntryInput<'a> {
original: &'a BlogPost,
offset: usize,
}
impl<'a> RenderBlogStreamEntryInput<'a> {
fn new(original: &'a BlogPost, offset: usize) -> RenderBlogStreamEntryInput<'a> {
RenderBlogStreamEntryInput { original, offset }
}
}
#[derive(Debug, Serialize)]
pub(crate) struct RenderBlogStreamEntry {
/// The title that will be shown visibly on the page.
title: Option<String>,
self_link: Option<String>,
children: Vec<RenderDocumentElement>,
footnotes: Vec<RenderRealFootnoteDefinition>,
}
render!(
RenderBlogStreamEntry,
RenderBlogStreamEntryInput,
original,
render_context,
{
let offset_string = original.offset.to_string();
let render_context = {
let mut render_context = render_context.clone();
render_context.id_addition = Some(offset_string.as_str());
render_context
};
let link_to_blog_post = get_web_path(
render_context.config,
render_context.output_root_directory,
render_context.output_file,
render_context
.config
.get_relative_path_to_post(&original.original.id),
)?;
// TODO: Should I guess an index page instead of erroring out?
let index_page = original
.original
.get_index_page()
.ok_or_else(|| format!("Blog post {} needs an index page.", original.original.id))?;
let title = index_page.title.clone();
let children = index_page
.children
.iter()
.map(|child| RenderDocumentElement::new(render_context.clone(), child))
.collect::<Result<Vec<_>, _>>()?;
let footnotes = {
let mut ret = Vec::new();
for footnote in index_page.footnotes.iter() {
ret.push(RenderRealFootnoteDefinition::new(
render_context.clone(),
footnote,
)?);
}
ret
};
Ok(RenderBlogStreamEntry {
title,
self_link: Some(link_to_blog_post),
children,
footnotes,
})
}
);
#[derive(Debug, Serialize)]
pub(crate) struct RenderBlogStreamPagination {
older_link: Option<String>,
newer_link: Option<String>,
}
impl RenderBlogStreamPagination {
fn new(
older_link: Option<String>,
newer_link: Option<String>,
) -> Result<RenderBlogStreamPagination, CustomError> {
Ok(RenderBlogStreamPagination {
older_link,
newer_link,
})
}
}

View File

@@ -1,23 +1,31 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IBold;
use super::macros::render;
use super::render_context::RenderContext;
use super::RenderObject;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "bold")]
pub(crate) struct RenderBold {}
pub(crate) struct RenderBold {
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
impl RenderBold {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IBold,
) -> Result<RenderBold, CustomError> {
Ok(RenderBold {})
}
render!(RenderBold, IBold, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderBold {
children,
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ICenterBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "center_block")]
pub(crate) struct RenderCenterBlock {}
pub(crate) struct RenderCenterBlock {
post_blank: organic::types::PostBlank,
}
impl RenderCenterBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ICenterBlock,
) -> Result<RenderCenterBlock, CustomError> {
Ok(RenderCenterBlock {})
}
}
rnoop!(RenderCenterBlock, ICenterBlock);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ICitation;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "citation")]
pub(crate) struct RenderCitation {}
pub(crate) struct RenderCitation {
post_blank: organic::types::PostBlank,
}
impl RenderCitation {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ICitation,
) -> Result<RenderCitation, CustomError> {
Ok(RenderCitation {})
}
}
rnoop!(RenderCitation, ICitation);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ICitationReference;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "citation_reference")]
pub(crate) struct RenderCitationReference {}
pub(crate) struct RenderCitationReference {
post_blank: organic::types::PostBlank,
}
impl RenderCitationReference {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ICitationReference,
) -> Result<RenderCitationReference, CustomError> {
Ok(RenderCitationReference {})
}
}
rnoop!(RenderCitationReference, ICitationReference);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IClock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "clock")]
pub(crate) struct RenderClock {}
pub(crate) struct RenderClock {
post_blank: organic::types::PostBlank,
}
impl RenderClock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IClock,
) -> Result<RenderClock, CustomError> {
Ok(RenderClock {})
}
}
rnoop!(RenderClock, IClock);

View File

@@ -1,23 +1,22 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ICode;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "code")]
pub(crate) struct RenderCode {}
pub(crate) struct RenderCode {
contents: String,
post_blank: organic::types::PostBlank,
}
impl RenderCode {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ICode,
) -> Result<RenderCode, CustomError> {
Ok(RenderCode {})
}
}
render!(RenderCode, ICode, original, _render_context, {
Ok(RenderCode {
contents: original.contents.clone(),
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IComment;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "comment")]
pub(crate) struct RenderComment {}
pub(crate) struct RenderComment {
post_blank: organic::types::PostBlank,
}
impl RenderComment {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IComment,
) -> Result<RenderComment, CustomError> {
Ok(RenderComment {})
}
}
rnoop!(RenderComment, IComment);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ICommentBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "comment_block")]
pub(crate) struct RenderCommentBlock {}
pub(crate) struct RenderCommentBlock {
post_blank: organic::types::PostBlank,
}
impl RenderCommentBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ICommentBlock,
) -> Result<RenderCommentBlock, CustomError> {
Ok(RenderCommentBlock {})
}
}
rnoop!(RenderCommentBlock, ICommentBlock);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IDiarySexp;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "diary_sexp")]
pub(crate) struct RenderDiarySexp {}
pub(crate) struct RenderDiarySexp {
post_blank: organic::types::PostBlank,
}
impl RenderDiarySexp {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IDiarySexp,
) -> Result<RenderDiarySexp, CustomError> {
Ok(RenderDiarySexp {})
}
}
rnoop!(RenderDiarySexp, IDiarySexp);

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IDocumentElement;
use super::macros::render;
use super::RenderHeading;
use super::RenderSection;
@@ -16,20 +15,19 @@ pub(crate) enum RenderDocumentElement {
Section(RenderSection),
}
impl RenderDocumentElement {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IDocumentElement,
) -> Result<RenderDocumentElement, CustomError> {
render!(
RenderDocumentElement,
IDocumentElement,
original,
render_context,
{
match original {
IDocumentElement::Heading(inner) => Ok(RenderDocumentElement::Heading(
RenderHeading::new(config, output_directory, output_file, inner)?,
RenderHeading::new(render_context.clone(), inner)?,
)),
IDocumentElement::Section(inner) => Ok(RenderDocumentElement::Section(
RenderSection::new(config, output_directory, output_file, inner)?,
RenderSection::new(render_context.clone(), inner)?,
)),
}
}
}
);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IDrawer;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "drawer")]
pub(crate) struct RenderDrawer {}
pub(crate) struct RenderDrawer {
post_blank: organic::types::PostBlank,
}
impl RenderDrawer {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IDrawer,
) -> Result<RenderDrawer, CustomError> {
Ok(RenderDrawer {})
}
}
rnoop!(RenderDrawer, IDrawer);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IDynamicBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "dynamic_block")]
pub(crate) struct RenderDynamicBlock {}
pub(crate) struct RenderDynamicBlock {
post_blank: organic::types::PostBlank,
}
impl RenderDynamicBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IDynamicBlock,
) -> Result<RenderDynamicBlock, CustomError> {
Ok(RenderDynamicBlock {})
}
}
rnoop!(RenderDynamicBlock, IDynamicBlock);

View File

@@ -1,8 +1,7 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::plain_list_simple_item::RenderPlainListSimpleItem;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IElement;
@@ -21,6 +20,7 @@ use super::footnote_definition::RenderFootnoteDefinition;
use super::horizontal_rule::RenderHorizontalRule;
use super::keyword::RenderKeyword;
use super::latex_environment::RenderLatexEnvironment;
use super::macros::render;
use super::paragraph::RenderParagraph;
use super::plain_list::RenderPlainList;
use super::planning::RenderPlanning;
@@ -36,6 +36,7 @@ use super::verse_block::RenderVerseBlock;
pub(crate) enum RenderElement {
Paragraph(RenderParagraph),
PlainList(RenderPlainList),
PlainListSimpleItem(RenderPlainListSimpleItem),
CenterBlock(RenderCenterBlock),
QuoteBlock(RenderQuoteBlock),
SpecialBlock(RenderSpecialBlock),
@@ -60,131 +61,101 @@ pub(crate) enum RenderElement {
LatexEnvironment(RenderLatexEnvironment),
}
impl RenderElement {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
element: &IElement,
) -> Result<RenderElement, CustomError> {
match element {
render!(RenderElement, IElement, original, render_context, {
match original {
IElement::Paragraph(inner) => Ok(RenderElement::Paragraph(RenderParagraph::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::PlainList(inner) => Ok(RenderElement::PlainList(RenderPlainList::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::PlainListSimpleItem(inner) => Ok(RenderElement::PlainListSimpleItem(
RenderPlainListSimpleItem::new(render_context.clone(), inner)?,
)),
IElement::CenterBlock(inner) => Ok(RenderElement::CenterBlock(RenderCenterBlock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::QuoteBlock(inner) => Ok(RenderElement::QuoteBlock(RenderQuoteBlock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::SpecialBlock(inner) => Ok(RenderElement::SpecialBlock(RenderSpecialBlock::new(
render_context.clone(),
inner,
)?)),
IElement::DynamicBlock(inner) => Ok(RenderElement::DynamicBlock(RenderDynamicBlock::new(
render_context.clone(),
inner,
)?)),
IElement::SpecialBlock(inner) => Ok(RenderElement::SpecialBlock(
RenderSpecialBlock::new(config, output_directory, output_file, inner)?,
)),
IElement::DynamicBlock(inner) => Ok(RenderElement::DynamicBlock(
RenderDynamicBlock::new(config, output_directory, output_file, inner)?,
)),
IElement::FootnoteDefinition(inner) => Ok(RenderElement::FootnoteDefinition(
RenderFootnoteDefinition::new(config, output_directory, output_file, inner)?,
RenderFootnoteDefinition::new(render_context.clone(), inner)?,
)),
IElement::Comment(inner) => Ok(RenderElement::Comment(RenderComment::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::Drawer(inner) => Ok(RenderElement::Drawer(RenderDrawer::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::PropertyDrawer(inner) => Ok(RenderElement::PropertyDrawer(
RenderPropertyDrawer::new(config, output_directory, output_file, inner)?,
RenderPropertyDrawer::new(render_context.clone(), inner)?,
)),
IElement::Table(inner) => Ok(RenderElement::Table(RenderTable::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::VerseBlock(inner) => Ok(RenderElement::VerseBlock(RenderVerseBlock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::CommentBlock(inner) => Ok(RenderElement::CommentBlock(RenderCommentBlock::new(
render_context.clone(),
inner,
)?)),
IElement::ExampleBlock(inner) => Ok(RenderElement::ExampleBlock(RenderExampleBlock::new(
render_context.clone(),
inner,
)?)),
IElement::CommentBlock(inner) => Ok(RenderElement::CommentBlock(
RenderCommentBlock::new(config, output_directory, output_file, inner)?,
)),
IElement::ExampleBlock(inner) => Ok(RenderElement::ExampleBlock(
RenderExampleBlock::new(config, output_directory, output_file, inner)?,
)),
IElement::ExportBlock(inner) => Ok(RenderElement::ExportBlock(RenderExportBlock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::SrcBlock(inner) => Ok(RenderElement::SrcBlock(RenderSrcBlock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::Clock(inner) => Ok(RenderElement::Clock(RenderClock::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::DiarySexp(inner) => Ok(RenderElement::DiarySexp(RenderDiarySexp::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::Planning(inner) => Ok(RenderElement::Planning(RenderPlanning::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::FixedWidthArea(inner) => Ok(RenderElement::FixedWidthArea(
RenderFixedWidthArea::new(config, output_directory, output_file, inner)?,
RenderFixedWidthArea::new(render_context.clone(), inner)?,
)),
IElement::HorizontalRule(inner) => Ok(RenderElement::HorizontalRule(
RenderHorizontalRule::new(config, output_directory, output_file, inner)?,
RenderHorizontalRule::new(render_context.clone(), inner)?,
)),
IElement::Keyword(inner) => Ok(RenderElement::Keyword(RenderKeyword::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::BabelCall(inner) => Ok(RenderElement::BabelCall(RenderBabelCall::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IElement::LatexEnvironment(inner) => Ok(RenderElement::LatexEnvironment(
RenderLatexEnvironment::new(config, output_directory, output_file, inner)?,
RenderLatexEnvironment::new(render_context.clone(), inner)?,
)),
}
}
}
});

View File

@@ -1,27 +1,22 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IEntity;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "entity")]
pub(crate) struct RenderEntity {
html: String,
post_blank: organic::types::PostBlank,
}
impl RenderEntity {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
entity: &IEntity,
) -> Result<RenderEntity, CustomError> {
render!(RenderEntity, IEntity, original, _render_context, {
Ok(RenderEntity {
html: entity.html.clone(),
html: original.html.clone(),
post_blank: original.post_blank,
})
}
}
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IExampleBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "example_block")]
pub(crate) struct RenderExampleBlock {}
pub(crate) struct RenderExampleBlock {
post_blank: organic::types::PostBlank,
}
impl RenderExampleBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IExampleBlock,
) -> Result<RenderExampleBlock, CustomError> {
Ok(RenderExampleBlock {})
}
}
rnoop!(RenderExampleBlock, IExampleBlock);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IExportBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "export_block")]
pub(crate) struct RenderExportBlock {}
pub(crate) struct RenderExportBlock {
post_blank: organic::types::PostBlank,
}
impl RenderExportBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IExportBlock,
) -> Result<RenderExportBlock, CustomError> {
Ok(RenderExportBlock {})
}
}
rnoop!(RenderExportBlock, IExportBlock);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IExportSnippet;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "export_snippet")]
pub(crate) struct RenderExportSnippet {}
pub(crate) struct RenderExportSnippet {
post_blank: organic::types::PostBlank,
}
impl RenderExportSnippet {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IExportSnippet,
) -> Result<RenderExportSnippet, CustomError> {
Ok(RenderExportSnippet {})
}
}
rnoop!(RenderExportSnippet, IExportSnippet);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IFixedWidthArea;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "fixed_width_area")]
pub(crate) struct RenderFixedWidthArea {}
pub(crate) struct RenderFixedWidthArea {
post_blank: organic::types::PostBlank,
}
impl RenderFixedWidthArea {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IFixedWidthArea,
) -> Result<RenderFixedWidthArea, CustomError> {
Ok(RenderFixedWidthArea {})
}
}
rnoop!(RenderFixedWidthArea, IFixedWidthArea);

View File

@@ -1,23 +1,54 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IFootnoteDefinition;
use crate::intermediate::IRealFootnoteDefinition;
use super::ast_node::IntoRenderAstNode;
use super::ast_node::RenderAstNode;
use super::macros::render;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "footnote_definition")]
pub(crate) struct RenderFootnoteDefinition {}
pub(crate) struct RenderFootnoteDefinition {
post_blank: organic::types::PostBlank,
}
impl RenderFootnoteDefinition {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IFootnoteDefinition,
) -> Result<RenderFootnoteDefinition, CustomError> {
Ok(RenderFootnoteDefinition {})
rnoop!(RenderFootnoteDefinition, IFootnoteDefinition);
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "real_footnote_definition")]
pub(crate) struct RenderRealFootnoteDefinition {
definition_id: String,
reference_link: String,
label: String,
contents: Vec<RenderAstNode>,
// TODO: Do I need post_blank for real footnote definitions?
}
render!(
RenderRealFootnoteDefinition,
IRealFootnoteDefinition,
original,
render_context,
{
let contents = {
let mut ret = Vec::new();
for obj in original.contents.iter() {
ret.push(obj.into_render_ast_node(render_context.clone())?);
}
ret
};
Ok(RenderRealFootnoteDefinition {
definition_id: original.get_definition_id(render_context.id_addition),
reference_link: format!("#{}", original.get_reference_id(render_context.id_addition)),
label: original.get_display_label(),
contents,
})
}
);

View File

@@ -1,23 +1,35 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IFootnoteReference;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "footnote_reference")]
pub(crate) struct RenderFootnoteReference {}
pub(crate) struct RenderFootnoteReference {
reference_id: String,
definition_link: String,
label: String,
post_blank: organic::types::PostBlank,
}
impl RenderFootnoteReference {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IFootnoteReference,
) -> Result<RenderFootnoteReference, CustomError> {
Ok(RenderFootnoteReference {})
}
render!(
RenderFootnoteReference,
IFootnoteReference,
original,
render_context,
{
Ok(RenderFootnoteReference {
reference_id: original.get_reference_id(render_context.id_addition),
definition_link: format!(
"#{}",
original.get_definition_id(render_context.id_addition)
),
label: original.get_display_label(),
post_blank: original.post_blank,
})
}
);

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IHeading;
use super::macros::render;
use super::RenderDocumentElement;
use super::RenderObject;
@@ -16,45 +15,30 @@ pub(crate) struct RenderHeading {
level: organic::types::HeadlineLevel,
title: Vec<RenderObject>,
children: Vec<RenderDocumentElement>,
post_blank: organic::types::PostBlank,
}
impl RenderHeading {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
heading: &IHeading,
) -> Result<RenderHeading, CustomError> {
render!(RenderHeading, IHeading, original, render_context, {
let title = {
let mut ret = Vec::new();
for obj in heading.title.iter() {
ret.push(RenderObject::new(
config,
&output_directory,
&output_file,
obj,
)?);
for obj in original.title.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
let children = {
let mut ret = Vec::new();
for obj in heading.children.iter() {
ret.push(RenderDocumentElement::new(
config,
&output_directory,
&output_file,
obj,
)?);
for obj in original.children.iter() {
ret.push(RenderDocumentElement::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderHeading {
level: heading.level + 1, // Adding 1 because the page title is going to be h1.
level: original.level + 1, // Adding 1 because the page title is going to be h1.
title,
children,
post_blank: original.post_blank,
})
}
}
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IHorizontalRule;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "horizontal_rule")]
pub(crate) struct RenderHorizontalRule {}
pub(crate) struct RenderHorizontalRule {
post_blank: organic::types::PostBlank,
}
impl RenderHorizontalRule {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IHorizontalRule,
) -> Result<RenderHorizontalRule, CustomError> {
Ok(RenderHorizontalRule {})
}
}
rnoop!(RenderHorizontalRule, IHorizontalRule);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IInlineBabelCall;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "inline_babel_call")]
pub(crate) struct RenderInlineBabelCall {}
pub(crate) struct RenderInlineBabelCall {
post_blank: organic::types::PostBlank,
}
impl RenderInlineBabelCall {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IInlineBabelCall,
) -> Result<RenderInlineBabelCall, CustomError> {
Ok(RenderInlineBabelCall {})
}
}
rnoop!(RenderInlineBabelCall, IInlineBabelCall);

View File

@@ -1,23 +1,28 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IInlineSourceBlock;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "inline_source_block")]
pub(crate) struct RenderInlineSourceBlock {}
pub(crate) struct RenderInlineSourceBlock {
value: String,
post_blank: organic::types::PostBlank,
}
impl RenderInlineSourceBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IInlineSourceBlock,
) -> Result<RenderInlineSourceBlock, CustomError> {
Ok(RenderInlineSourceBlock {})
}
render!(
RenderInlineSourceBlock,
IInlineSourceBlock,
original,
_render_context,
{
Ok(RenderInlineSourceBlock {
value: original.value.clone(),
post_blank: original.post_blank,
})
}
);

View File

@@ -1,23 +1,31 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IItalic;
use super::macros::render;
use super::RenderObject;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "italic")]
pub(crate) struct RenderItalic {}
pub(crate) struct RenderItalic {
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
impl RenderItalic {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IItalic,
) -> Result<RenderItalic, CustomError> {
Ok(RenderItalic {})
}
render!(RenderItalic, IItalic, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderItalic {
children,
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IKeyword;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "keyword")]
pub(crate) struct RenderKeyword {}
pub(crate) struct RenderKeyword {
post_blank: organic::types::PostBlank,
}
impl RenderKeyword {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
keyword: &IKeyword,
) -> Result<RenderKeyword, CustomError> {
Ok(RenderKeyword {})
}
}
rnoop!(RenderKeyword, IKeyword);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ILatexEnvironment;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "latex_environment")]
pub(crate) struct RenderLatexEnvironment {}
pub(crate) struct RenderLatexEnvironment {
post_blank: organic::types::PostBlank,
}
impl RenderLatexEnvironment {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ILatexEnvironment,
) -> Result<RenderLatexEnvironment, CustomError> {
Ok(RenderLatexEnvironment {})
}
}
rnoop!(RenderLatexEnvironment, ILatexEnvironment);

View File

@@ -1,23 +1,28 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ILatexFragment;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "latex_fragment")]
pub(crate) struct RenderLatexFragment {}
pub(crate) struct RenderLatexFragment {
value: String,
post_blank: organic::types::PostBlank,
}
impl RenderLatexFragment {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ILatexFragment,
) -> Result<RenderLatexFragment, CustomError> {
Ok(RenderLatexFragment {})
}
render!(
RenderLatexFragment,
ILatexFragment,
original,
_render_context,
{
Ok(RenderLatexFragment {
value: original.value.clone(),
post_blank: original.post_blank,
})
}
);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ILineBreak;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "line_break")]
pub(crate) struct RenderLineBreak {}
pub(crate) struct RenderLineBreak {
post_blank: organic::types::PostBlank,
}
impl RenderLineBreak {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ILineBreak,
) -> Result<RenderLineBreak, CustomError> {
Ok(RenderLineBreak {})
}
}
rnoop!(RenderLineBreak, ILineBreak);

37
src/context/macros.rs Normal file
View File

@@ -0,0 +1,37 @@
/// Write the implementation for the render ast node.
///
/// This exists to make changing the type signature easier.
macro_rules! render {
($rstruct:ident, $istruct:ident, $original:ident, $render_context:ident, $fnbody:tt) => {
impl $rstruct {
pub(crate) fn new(
$render_context: RenderContext<'_>,
$original: &$istruct,
) -> Result<$rstruct, CustomError> {
$fnbody
}
}
};
}
pub(crate) use render;
/// Write the implementation for a render ast node that has no fields.
///
/// This exists to make changing the type signature easier.
macro_rules! rnoop {
($rstruct:ident, $istruct:ident) => {
impl $rstruct {
pub(crate) fn new(
_render_context: RenderContext<'_>,
original: &$istruct,
) -> Result<$rstruct, CustomError> {
Ok($rstruct {
post_blank: original.post_blank,
})
}
}
};
}
pub(crate) use rnoop;

View File

@@ -1,6 +1,8 @@
mod angle_link;
mod ast_node;
mod babel_call;
mod blog_post_page;
mod blog_stream;
mod bold;
mod center_block;
mod citation;
@@ -31,12 +33,15 @@ mod keyword;
mod latex_environment;
mod latex_fragment;
mod line_break;
mod macros;
mod object;
mod org_macro;
mod page_header;
mod paragraph;
mod plain_link;
mod plain_list;
mod plain_list_item;
mod plain_list_simple_item;
mod plain_text;
mod planning;
mod property_drawer;
@@ -44,6 +49,7 @@ mod quote_block;
mod radio_link;
mod radio_target;
mod regular_link;
mod render_context;
mod section;
mod special_block;
mod src_block;
@@ -52,6 +58,8 @@ mod strike_through;
mod subscript;
mod superscript;
mod table;
mod table_cell;
mod table_row;
mod target;
mod timestamp;
mod underline;
@@ -59,9 +67,15 @@ mod verbatim;
mod verse_block;
pub(crate) use blog_post_page::RenderBlogPostPage;
pub(crate) use blog_post_page::RenderBlogPostPageInput;
pub(crate) use blog_stream::RenderBlogStream;
pub(crate) use blog_stream::RenderBlogStreamInput;
pub(crate) use document_element::RenderDocumentElement;
pub(crate) use element::RenderElement;
pub(crate) use footnote_definition::RenderRealFootnoteDefinition;
pub(crate) use global_settings::GlobalSettings;
pub(crate) use heading::RenderHeading;
pub(crate) use object::RenderObject;
pub(crate) use page_header::PageHeader;
pub(crate) use render_context::RenderContext;
pub(crate) use section::RenderSection;

View File

@@ -1,8 +1,6 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IObject;
@@ -19,6 +17,7 @@ use super::inline_source_block::RenderInlineSourceBlock;
use super::italic::RenderItalic;
use super::latex_fragment::RenderLatexFragment;
use super::line_break::RenderLineBreak;
use super::macros::render;
use super::org_macro::RenderOrgMacro;
use super::plain_link::RenderPlainLink;
use super::plain_text::RenderPlainText;
@@ -66,152 +65,110 @@ pub(crate) enum RenderObject {
Timestamp(RenderTimestamp),
}
impl RenderObject {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
object: &IObject,
) -> Result<RenderObject, CustomError> {
match object {
render!(RenderObject, IObject, original, render_context, {
match original {
IObject::Bold(inner) => Ok(RenderObject::Bold(RenderBold::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Italic(inner) => Ok(RenderObject::Italic(RenderItalic::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Underline(inner) => Ok(RenderObject::Underline(RenderUnderline::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::StrikeThrough(inner) => Ok(RenderObject::StrikeThrough(RenderStrikeThrough::new(
render_context.clone(),
inner,
)?)),
IObject::StrikeThrough(inner) => Ok(RenderObject::StrikeThrough(
RenderStrikeThrough::new(config, output_directory, output_file, inner)?,
)),
IObject::Code(inner) => Ok(RenderObject::Code(RenderCode::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Verbatim(inner) => Ok(RenderObject::Verbatim(RenderVerbatim::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::PlainText(inner) => Ok(RenderObject::PlainText(RenderPlainText::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::RegularLink(inner) => Ok(RenderObject::RegularLink(RenderRegularLink::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::RadioLink(inner) => Ok(RenderObject::RadioLink(RenderRadioLink::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::RadioTarget(inner) => Ok(RenderObject::RadioTarget(RenderRadioTarget::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::PlainLink(inner) => Ok(RenderObject::PlainLink(RenderPlainLink::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::AngleLink(inner) => Ok(RenderObject::AngleLink(RenderAngleLink::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::OrgMacro(inner) => Ok(RenderObject::OrgMacro(RenderOrgMacro::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Entity(inner) => Ok(RenderObject::Entity(RenderEntity::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::LatexFragment(inner) => Ok(RenderObject::LatexFragment(RenderLatexFragment::new(
render_context.clone(),
inner,
)?)),
IObject::ExportSnippet(inner) => Ok(RenderObject::ExportSnippet(RenderExportSnippet::new(
render_context.clone(),
inner,
)?)),
IObject::LatexFragment(inner) => Ok(RenderObject::LatexFragment(
RenderLatexFragment::new(config, output_directory, output_file, inner)?,
)),
IObject::ExportSnippet(inner) => Ok(RenderObject::ExportSnippet(
RenderExportSnippet::new(config, output_directory, output_file, inner)?,
)),
IObject::FootnoteReference(inner) => Ok(RenderObject::FootnoteReference(
RenderFootnoteReference::new(config, output_directory, output_file, inner)?,
RenderFootnoteReference::new(render_context.clone(), inner)?,
)),
IObject::Citation(inner) => Ok(RenderObject::Citation(RenderCitation::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::CitationReference(inner) => Ok(RenderObject::CitationReference(
RenderCitationReference::new(config, output_directory, output_file, inner)?,
RenderCitationReference::new(render_context.clone(), inner)?,
)),
IObject::InlineBabelCall(inner) => Ok(RenderObject::InlineBabelCall(
RenderInlineBabelCall::new(config, output_directory, output_file, inner)?,
RenderInlineBabelCall::new(render_context.clone(), inner)?,
)),
IObject::InlineSourceBlock(inner) => Ok(RenderObject::InlineSourceBlock(
RenderInlineSourceBlock::new(config, output_directory, output_file, inner)?,
RenderInlineSourceBlock::new(render_context.clone(), inner)?,
)),
IObject::LineBreak(inner) => Ok(RenderObject::LineBreak(RenderLineBreak::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Target(inner) => Ok(RenderObject::Target(RenderTarget::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::StatisticsCookie(inner) => Ok(RenderObject::StatisticsCookie(
RenderStatisticsCookie::new(config, output_directory, output_file, inner)?,
RenderStatisticsCookie::new(render_context.clone(), inner)?,
)),
IObject::Subscript(inner) => Ok(RenderObject::Subscript(RenderSubscript::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Superscript(inner) => Ok(RenderObject::Superscript(RenderSuperscript::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
IObject::Timestamp(inner) => Ok(RenderObject::Timestamp(RenderTimestamp::new(
config,
output_directory,
output_file,
render_context.clone(),
inner,
)?)),
}
}
}
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IOrgMacro;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "org_macro")]
pub(crate) struct RenderOrgMacro {}
pub(crate) struct RenderOrgMacro {
post_blank: organic::types::PostBlank,
}
impl RenderOrgMacro {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IOrgMacro,
) -> Result<RenderOrgMacro, CustomError> {
Ok(RenderOrgMacro {})
}
}
rnoop!(RenderOrgMacro, IOrgMacro);

View File

@@ -0,0 +1,19 @@
use serde::Serialize;
/// The header that goes above the content of the page.
///
/// This header will be mostly the same on every page.
#[derive(Debug, Serialize)]
pub(crate) struct PageHeader {
website_title: Option<String>,
home_link: Option<String>,
}
impl PageHeader {
pub(crate) fn new(website_title: Option<String>, home_link: Option<String>) -> PageHeader {
PageHeader {
website_title,
home_link,
}
}
}

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IParagraph;
use super::macros::render;
use super::RenderObject;
#[derive(Debug, Serialize)]
@@ -13,28 +12,20 @@ use super::RenderObject;
#[serde(rename = "paragraph")]
pub(crate) struct RenderParagraph {
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
impl RenderParagraph {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
paragraph: &IParagraph,
) -> Result<RenderParagraph, CustomError> {
render!(RenderParagraph, IParagraph, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in paragraph.children.iter() {
ret.push(RenderObject::new(
config,
&output_directory,
&output_file,
obj,
)?);
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderParagraph { children })
}
}
Ok(RenderParagraph {
children,
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlainLink;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "plain_link")]
pub(crate) struct RenderPlainLink {}
pub(crate) struct RenderPlainLink {
post_blank: organic::types::PostBlank,
}
impl RenderPlainLink {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IPlainLink,
) -> Result<RenderPlainLink, CustomError> {
Ok(RenderPlainLink {})
}
}
rnoop!(RenderPlainLink, IPlainLink);

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlainList;
use super::macros::render;
use super::plain_list_item::RenderPlainListItem;
#[derive(Debug, Serialize)]
@@ -14,15 +13,10 @@ use super::plain_list_item::RenderPlainListItem;
pub(crate) struct RenderPlainList {
list_type: String,
children: Vec<RenderPlainListItem>,
post_blank: organic::types::PostBlank,
}
impl RenderPlainList {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IPlainList,
) -> Result<RenderPlainList, CustomError> {
render!(RenderPlainList, IPlainList, original, render_context, {
let list_type = match original.list_type {
organic::types::PlainListType::Unordered => "unordered".to_owned(),
organic::types::PlainListType::Ordered => "ordered".to_owned(),
@@ -31,12 +25,7 @@ impl RenderPlainList {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderPlainListItem::new(
config,
&output_directory,
&output_file,
obj,
)?);
ret.push(RenderPlainListItem::new(render_context.clone(), obj)?);
}
ret
};
@@ -44,6 +33,6 @@ impl RenderPlainList {
Ok(RenderPlainList {
list_type,
children,
post_blank: original.post_blank,
})
}
}
});

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlainListItem;
use super::macros::render;
use super::RenderElement;
use super::RenderObject;
@@ -17,22 +16,16 @@ pub(crate) struct RenderPlainListItem {
children: Vec<RenderElement>,
}
impl RenderPlainListItem {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IPlainListItem,
) -> Result<RenderPlainListItem, CustomError> {
render!(
RenderPlainListItem,
IPlainListItem,
original,
render_context,
{
let tag = {
let mut ret = Vec::new();
for obj in original.tag.iter() {
ret.push(RenderObject::new(
config,
&output_directory,
&output_file,
obj,
)?);
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
@@ -40,15 +33,10 @@ impl RenderPlainListItem {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderElement::new(
config,
&output_directory,
&output_file,
obj,
)?);
ret.push(RenderElement::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderPlainListItem { tag, children })
}
}
);

View File

@@ -0,0 +1,38 @@
use serde::Serialize;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlainListSimpleItem;
use super::macros::render;
use super::RenderObject;
/// Special case for list items with only paragraphs and sublists as their children. In those cases, the paragraph tags are omitted. This is equivalent to a Paragraph but in a different struct to have a different type tag.
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "plain_list_simple_item")]
pub(crate) struct RenderPlainListSimpleItem {
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
render!(
RenderPlainListSimpleItem,
IPlainListSimpleItem,
original,
render_context,
{
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderPlainListSimpleItem {
children,
post_blank: original.post_blank,
})
}
);

View File

@@ -1,27 +1,22 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlainText;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "plain_text")]
pub(crate) struct RenderPlainText {
source: String,
post_blank: organic::types::PostBlank,
}
impl RenderPlainText {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IPlainText,
) -> Result<RenderPlainText, CustomError> {
render!(RenderPlainText, IPlainText, original, _render_context, {
Ok(RenderPlainText {
source: original.source.clone(),
post_blank: original.post_blank,
})
}
}
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPlanning;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "planning")]
pub(crate) struct RenderPlanning {}
pub(crate) struct RenderPlanning {
post_blank: organic::types::PostBlank,
}
impl RenderPlanning {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IPlanning,
) -> Result<RenderPlanning, CustomError> {
Ok(RenderPlanning {})
}
}
rnoop!(RenderPlanning, IPlanning);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IPropertyDrawer;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "property_drawer")]
pub(crate) struct RenderPropertyDrawer {}
pub(crate) struct RenderPropertyDrawer {
post_blank: organic::types::PostBlank,
}
impl RenderPropertyDrawer {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IPropertyDrawer,
) -> Result<RenderPropertyDrawer, CustomError> {
Ok(RenderPropertyDrawer {})
}
}
rnoop!(RenderPropertyDrawer, IPropertyDrawer);

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IQuoteBlock;
use super::macros::render;
use super::RenderElement;
#[derive(Debug, Serialize)]
@@ -13,28 +12,20 @@ use super::RenderElement;
#[serde(rename = "quote_block")]
pub(crate) struct RenderQuoteBlock {
children: Vec<RenderElement>,
post_blank: organic::types::PostBlank,
}
impl RenderQuoteBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IQuoteBlock,
) -> Result<RenderQuoteBlock, CustomError> {
render!(RenderQuoteBlock, IQuoteBlock, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderElement::new(
config,
&output_directory,
&output_file,
obj,
)?);
ret.push(RenderElement::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderQuoteBlock { children })
}
}
Ok(RenderQuoteBlock {
children,
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IRadioLink;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "radio_link")]
pub(crate) struct RenderRadioLink {}
pub(crate) struct RenderRadioLink {
post_blank: organic::types::PostBlank,
}
impl RenderRadioLink {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IRadioLink,
) -> Result<RenderRadioLink, CustomError> {
Ok(RenderRadioLink {})
}
}
rnoop!(RenderRadioLink, IRadioLink);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IRadioTarget;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "radio_target")]
pub(crate) struct RenderRadioTarget {}
pub(crate) struct RenderRadioTarget {
post_blank: organic::types::PostBlank,
}
impl RenderRadioTarget {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IRadioTarget,
) -> Result<RenderRadioTarget, CustomError> {
Ok(RenderRadioTarget {})
}
}
rnoop!(RenderRadioTarget, IRadioTarget);

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IRegularLink;
use super::macros::render;
use super::RenderObject;
#[derive(Debug, Serialize)]
@@ -14,31 +13,21 @@ use super::RenderObject;
pub(crate) struct RenderRegularLink {
raw_link: String,
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
impl RenderRegularLink {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
regular_link: &IRegularLink,
) -> Result<RenderRegularLink, CustomError> {
render!(RenderRegularLink, IRegularLink, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in regular_link.children.iter() {
ret.push(RenderObject::new(
config,
&output_directory,
&output_file,
obj,
)?);
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderRegularLink {
raw_link: regular_link.raw_link.clone(),
raw_link: original.raw_link.clone(),
children,
post_blank: original.post_blank,
})
}
}
});

View File

@@ -0,0 +1,36 @@
use std::path::Path;
use crate::config::Config;
use crate::error::CustomError;
/// The supporting information used for converting the intermediate representation into the dust context for rendering.
#[derive(Debug, Clone)]
pub(crate) struct RenderContext<'intermediate> {
pub(crate) config: &'intermediate Config,
// TODO: Perhaps rename to output_root_directory.
pub(crate) output_root_directory: &'intermediate Path,
pub(crate) output_file: &'intermediate Path,
/// An optional string that gets added to IDs in HTML.
///
/// This is useful for cases where you may have conflicting HTML
/// IDs, for example, multiple blog posts with footnotes in a blog
/// stream.
pub(crate) id_addition: Option<&'intermediate str>,
}
impl<'intermediate> RenderContext<'intermediate> {
pub(crate) fn new(
config: &'intermediate Config,
output_directory: &'intermediate Path,
output_file: &'intermediate Path,
id_addition: Option<&'intermediate str>,
) -> Result<RenderContext<'intermediate>, CustomError> {
Ok(RenderContext {
config,
output_root_directory: output_directory,
output_file,
id_addition,
})
}
}

View File

@@ -1,11 +1,10 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ISection;
use super::macros::render;
use super::RenderElement;
#[derive(Debug, Serialize)]
@@ -13,28 +12,20 @@ use super::RenderElement;
#[serde(rename = "section")]
pub(crate) struct RenderSection {
children: Vec<RenderElement>,
post_blank: organic::types::PostBlank,
}
impl RenderSection {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
section: &ISection,
) -> Result<RenderSection, CustomError> {
render!(RenderSection, ISection, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in section.children.iter() {
ret.push(RenderElement::new(
config,
&output_directory,
&output_file,
obj,
)?);
for obj in original.children.iter() {
ret.push(RenderElement::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderSection { children })
}
}
Ok(RenderSection {
children,
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ISpecialBlock;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "special_block")]
pub(crate) struct RenderSpecialBlock {}
pub(crate) struct RenderSpecialBlock {
post_blank: organic::types::PostBlank,
}
impl RenderSpecialBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ISpecialBlock,
) -> Result<RenderSpecialBlock, CustomError> {
Ok(RenderSpecialBlock {})
}
}
rnoop!(RenderSpecialBlock, ISpecialBlock);

View File

@@ -1,23 +1,24 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ISrcBlock;
use super::macros::render;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "src_block")]
pub(crate) struct RenderSrcBlock {}
pub(crate) struct RenderSrcBlock {
lines: Vec<String>,
language: Option<String>,
post_blank: organic::types::PostBlank,
}
impl RenderSrcBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ISrcBlock,
) -> Result<RenderSrcBlock, CustomError> {
Ok(RenderSrcBlock {})
}
}
render!(RenderSrcBlock, ISrcBlock, original, _render_context, {
Ok(RenderSrcBlock {
lines: original.lines.clone(),
language: original.language.clone(),
post_blank: original.post_blank,
})
});

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IStatisticsCookie;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "statistics_cookie")]
pub(crate) struct RenderStatisticsCookie {}
pub(crate) struct RenderStatisticsCookie {
post_blank: organic::types::PostBlank,
}
impl RenderStatisticsCookie {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IStatisticsCookie,
) -> Result<RenderStatisticsCookie, CustomError> {
Ok(RenderStatisticsCookie {})
}
}
rnoop!(RenderStatisticsCookie, IStatisticsCookie);

View File

@@ -1,23 +1,37 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::IStrikeThrough;
use super::macros::render;
use super::RenderObject;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "strike_through")]
pub(crate) struct RenderStrikeThrough {}
pub(crate) struct RenderStrikeThrough {
children: Vec<RenderObject>,
post_blank: organic::types::PostBlank,
}
impl RenderStrikeThrough {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IStrikeThrough,
) -> Result<RenderStrikeThrough, CustomError> {
Ok(RenderStrikeThrough {})
render!(
RenderStrikeThrough,
IStrikeThrough,
original,
render_context,
{
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderStrikeThrough {
children,
post_blank: original.post_blank,
})
}
);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ISubscript;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "subscript")]
pub(crate) struct RenderSubscript {}
pub(crate) struct RenderSubscript {
post_blank: organic::types::PostBlank,
}
impl RenderSubscript {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ISubscript,
) -> Result<RenderSubscript, CustomError> {
Ok(RenderSubscript {})
}
}
rnoop!(RenderSubscript, ISubscript);

View File

@@ -1,23 +1,16 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ISuperscript;
use super::macros::rnoop;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "superscript")]
pub(crate) struct RenderSuperscript {}
pub(crate) struct RenderSuperscript {
post_blank: organic::types::PostBlank,
}
impl RenderSuperscript {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ISuperscript,
) -> Result<RenderSuperscript, CustomError> {
Ok(RenderSuperscript {})
}
}
rnoop!(RenderSuperscript, ISuperscript);

View File

@@ -1,23 +1,31 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ITable;
use super::macros::render;
use super::table_row::RenderTableRow;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "table")]
pub(crate) struct RenderTable {}
pub(crate) struct RenderTable {
children: Vec<RenderTableRow>,
post_blank: organic::types::PostBlank,
}
impl RenderTable {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &ITable,
) -> Result<RenderTable, CustomError> {
Ok(RenderTable {})
}
render!(RenderTable, ITable, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderTableRow::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderTable {
children,
post_blank: original.post_blank,
})
});

27
src/context/table_cell.rs Normal file
View File

@@ -0,0 +1,27 @@
use serde::Serialize;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ITableCell;
use super::macros::render;
use super::RenderObject;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "table_cell")]
pub(crate) struct RenderTableCell {
children: Vec<RenderObject>,
}
render!(RenderTableCell, ITableCell, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderObject::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderTableCell { children })
});

27
src/context/table_row.rs Normal file
View File

@@ -0,0 +1,27 @@
use serde::Serialize;
use super::render_context::RenderContext;
use crate::error::CustomError;
use crate::intermediate::ITableRow;
use super::macros::render;
use super::table_cell::RenderTableCell;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "table_row")]
pub(crate) struct RenderTableRow {
children: Vec<RenderTableCell>,
}
render!(RenderTableRow, ITableRow, original, render_context, {
let children = {
let mut ret = Vec::new();
for obj in original.children.iter() {
ret.push(RenderTableCell::new(render_context.clone(), obj)?);
}
ret
};
Ok(RenderTableRow { children })
});

Some files were not shown because too many files have changed in this diff Show More