Compare commits

...

57 Commits

Author SHA1 Message Date
Tom Alexander
0e9d74b2c8
Merge branch 'element_template' 2023-10-27 19:26:38 -04:00
Tom Alexander
6bf1480366
Add a template for paragraph. 2023-10-27 19:26:27 -04:00
Tom Alexander
c279bad13a
Add children to heading. 2023-10-27 19:22:17 -04:00
Tom Alexander
bd982fb62d
Add a template for section. 2023-10-27 18:30:29 -04:00
Tom Alexander
53a531f568
Add dispatcher for object and element. 2023-10-27 18:26:56 -04:00
Tom Alexander
67b60087af
Add templates for the ast nodes. 2023-10-27 18:15:53 -04:00
Tom Alexander
8a3b85d5fa
Merge branch 'element_noop' 2023-10-27 17:49:04 -04:00
Tom Alexander
b0ac14ee58
Add the skeletons for the objects. 2023-10-27 17:48:19 -04:00
Tom Alexander
23713a934c
Add the skeletons for the elements. 2023-10-27 17:08:58 -04:00
Tom Alexander
860b601f62
Merge branch 'build_site' 2023-10-27 16:19:39 -04:00
Tom Alexander
354d24cf69
Add comment as a no-op. 2023-10-27 16:14:37 -04:00
Tom Alexander
5891ac7fb7
Add keyword and as no-op. 2023-10-27 16:09:44 -04:00
Tom Alexander
f9377d7609
Make converstion to intermediate state async.
We are going to need to do things like call external tools for syntax highlighting so we are going to need async in there eventually.
2023-10-27 15:55:19 -04:00
Tom Alexander
4a6948cde7
Add paragraph. 2023-10-27 15:46:56 -04:00
Tom Alexander
5b34942b64
Add element. 2023-10-27 15:46:56 -04:00
Tom Alexander
7b01230234
Add target. 2023-10-27 15:05:50 -04:00
Tom Alexander
c6cf5f75ac
Introduce a registry into the conversion to intermediate format. 2023-10-27 15:05:49 -04:00
Tom Alexander
e3b5f7f74f
Rename blog_post module to intermediate.
This module is mostly the intermediate representation of the AST, so the renaming is to make that more clear. The three forms are parsed => intermediate => render.

Parsed comes from Organic and is a direct translation of the org-mode text.

Intermediate converts the parsed data into owned values and does any calculations that are needed on the data (for example: assigning numbers to footnotes.)

Render takes intermediate and translates it into the format expected by the dust templates. The processing in this step should be minimal since all the logic should be in the intermediate step.
2023-10-27 13:10:21 -04:00
Tom Alexander
1ac39c2a6f
Add RenderPlainText. 2023-10-27 13:01:45 -04:00
Tom Alexander
744d3e50fb
Convert intermediate objects into render objects. 2023-10-27 12:47:12 -04:00
Tom Alexander
4c59011389
Copy heading level. 2023-10-27 12:14:07 -04:00
Tom Alexander
ba2756c762
Create intermediate representation for plain text. 2023-10-27 10:23:05 -04:00
Tom Alexander
31a3efe417
Only print the contexts.
This allows us to pipe the output to jq to see the context easier. We can see the rendered output in the files written to disk.
2023-10-24 00:51:28 -04:00
Tom Alexander
2b7a19a1d4
Introduce the corresponding non-render types. 2023-10-24 00:36:08 -04:00
Tom Alexander
3b472a9e96
Introduce element and object enums. 2023-10-24 00:04:44 -04:00
Tom Alexander
77f8375d7a
Introduce an array of document elements. 2023-10-24 00:01:40 -04:00
Tom Alexander
3cfcae25a9
Move the render context to its own folder.
We are going to have a lot of render context types because there are so many org-mode elements/objects so I'm moving it to a separate folder for organization.
2023-10-23 23:49:35 -04:00
Tom Alexander
448e9bb8c6
Add comments. 2023-10-23 23:36:47 -04:00
Tom Alexander
2413923b3f
Render the page title and self link. 2023-10-23 23:06:14 -04:00
Tom Alexander
ab36a60545
Generate the minimum relative path by chopping off the shared stem. 2023-10-23 23:04:05 -04:00
Tom Alexander
68cae57f16
Add a function to get the shared portion of a path. 2023-10-23 22:50:43 -04:00
Tom Alexander
11bfb6836f
Include a self-link for the blog. 2023-10-23 22:38:00 -04:00
Tom Alexander
3ac7826d2c
Move the logic into convert_blog_post_page_to_render_context.
I was writing it in the build command's rust files for convenience, but now its getting long enough to warrant moving it into its final location.
2023-10-23 22:10:26 -04:00
Tom Alexander
178ce877bc
Render the head for the page. 2023-10-23 21:51:15 -04:00
Tom Alexander
2b6f86d4e9
Switch to rendering blog post pages instead of blog posts. 2023-10-23 20:30:43 -04:00
Tom Alexander
dc233d26b1
Store the title in BlogPostPage. 2023-10-23 18:39:54 -04:00
Tom Alexander
e543a5db74
Starting to introduce a BlogPostPage struct.
Blog posts are going to be constructed of multiple documents each forming their own page. This will allow me to link to supporting documents without having to promote them to their own pages.
2023-10-23 16:03:37 -04:00
Tom Alexander
199621b6f1
Remove the separation of the main template.
I don't think this is necessary, and it certainly isn't necessary at this level.
2023-10-22 18:39:05 -04:00
Tom Alexander
586fd8a066
Getting rendered output from duster. 2023-10-22 18:31:56 -04:00
Tom Alexander
043cc5eda4
I think I have worked around the lifetime issue by keeping references to the intermediate str's. 2023-10-22 18:12:45 -04:00
Tom Alexander
58aba8efd5
Invoking the compile function.
I am going to have to address the lifetime issue of "compiled" duster templates borrowing the input str.
2023-10-22 17:37:27 -04:00
Tom Alexander
ce0819e85b
Feeding the templates into the renderer integration. 2023-10-22 17:31:12 -04:00
Tom Alexander
fc5342adce
Make the renderer a bit more generic. 2023-10-22 16:40:58 -04:00
Tom Alexander
aed88cf05a
Add include_dir.
This will let us embed the default versions of templates, stylesheets, javascript, etc into the binary. Naturally, we will eventually support overriding the defaults.
2023-10-22 16:28:54 -04:00
Tom Alexander
24bac982f1
Starting to create the renderer integrations.
These are the layer directly over dust which can be used by anything, not just blog posts.
2023-10-22 16:26:43 -04:00
Tom Alexander
5f34cb2dd5
Creating a SiteRenderer struct to handle the logic for invoking dust. 2023-10-22 16:10:41 -04:00
Tom Alexander
0b6900eeca
Serialize the RenderBlogPost to JSON.
This struct still does not contain anything, but I'm just setting up the skeleton for this code.
2023-10-22 16:01:42 -04:00
Tom Alexander
b72aec9d20
Starting a struct for what will be passed as the context into dust. 2023-10-22 15:31:45 -04:00
Tom Alexander
a510d0809f
Add serde_json. 2023-10-22 15:06:31 -04:00
Tom Alexander
87d32323f2
Add duster. 2023-10-22 15:01:30 -04:00
Tom Alexander
a0c5b2d852
Don't use walkdir for getting the post directories.
We are only iterating a single level of depth anyway, so read_dir is enough.
2023-10-22 14:49:08 -04:00
Tom Alexander
a9fbb4cd63
Get the output directory and clear it. 2023-10-22 14:40:59 -04:00
Tom Alexander
07e4209048
Setting the post id based on the folder name. 2023-10-22 13:50:11 -04:00
Tom Alexander
2f0f3ab346
Switch to using CustomError because a boxed StdError is not Send. 2023-10-22 13:44:03 -04:00
Tom Alexander
d8fc49797e
Moving into a load_blog_post function to create a BlogPost struct. 2023-10-22 12:04:09 -04:00
Tom Alexander
816780589f
Parse the org-mode files. 2023-10-21 18:00:51 -04:00
Tom Alexander
acaa12cb6e
Read the org files inside the writer directory. 2023-10-20 20:16:22 -04:00
194 changed files with 4330 additions and 21 deletions

257
Cargo.lock generated
View File

@ -65,6 +65,18 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
@ -80,6 +92,24 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "0.19.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "bytes"
version = "1.5.0"
@ -146,12 +176,117 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "duster"
version = "0.1.1"
source = "git+https://code.fizz.buzz/talexander/duster.git?branch=master#3428a3f5097c7d2cc252d1bfd9aae7771553ab69"
dependencies = [
"nom 6.1.2",
"serde",
"serde_json",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "futures"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gimli"
version = "0.28.0"
@ -176,6 +311,25 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "include_dir"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e"
dependencies = [
"include_dir_macros",
]
[[package]]
name = "include_dir_macros"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "indexmap"
version = "2.0.2"
@ -186,6 +340,25 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "lexical-core"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
dependencies = [
"arrayvec",
"bitflags",
"cfg-if",
"ryu",
"static_assertions",
]
[[package]]
name = "libc"
version = "0.2.149"
@ -213,6 +386,19 @@ dependencies = [
"adler",
]
[[package]]
name = "nom"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [
"bitvec",
"funty",
"lexical-core",
"memchr",
"version_check",
]
[[package]]
name = "nom"
version = "7.1.3"
@ -245,10 +431,8 @@ dependencies = [
[[package]]
name = "organic"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f0f8a2a6d31c3cac7ebf543d8cb2e8f648300462fc2f6b1a09cac10daf0387"
dependencies = [
"nom",
"nom 7.1.3",
"walkdir",
]
@ -258,6 +442,12 @@ version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro2"
version = "1.0.69"
@ -276,12 +466,24 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "same-file"
version = "1.0.6"
@ -311,6 +513,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_spanned"
version = "0.6.3"
@ -320,6 +533,21 @@ dependencies = [
"serde",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.38"
@ -331,6 +559,12 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tokio"
version = "1.33.0"
@ -389,6 +623,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.4.0"
@ -510,8 +750,19 @@ name = "writer"
version = "0.0.1"
dependencies = [
"clap",
"duster",
"futures",
"include_dir",
"organic",
"serde",
"serde_json",
"tokio",
"toml",
"walkdir",
]
[[package]]
name = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"

View File

@ -6,11 +6,15 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# error-context, suggestions, usage | env
clap = { version = "4.4.6", default-features = false, features = ["std", "color", "help", "derive"] }
organic = "0.1.12"
# | alloc, rc, serde_derive, unstable
duster = { git = "https://code.fizz.buzz/talexander/duster.git", branch = "master" }
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"
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"] }
# display, parse | indexmap, preserve_order
toml = "0.8.2"
walkdir = "2.4.0"

View File

@ -0,0 +1 @@
angle_link

View File

@ -0,0 +1 @@
babel_call

View File

@ -0,0 +1,14 @@
<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}
{! TODO: date? !}
</div>
{! TODO: Table of contents? !}
<div class="blog_post_body">
{#.children}
{>document_element/}
{/.children}
</div>
</div>

View File

@ -0,0 +1 @@
bold

View File

@ -0,0 +1 @@
center_block

View File

@ -0,0 +1 @@
citation

View File

@ -0,0 +1 @@
citation_reference

View File

@ -0,0 +1 @@
clock

View File

@ -0,0 +1 @@
code

View File

@ -0,0 +1 @@
comment

View File

@ -0,0 +1 @@
comment_block

View File

@ -0,0 +1 @@
diary_sexp

View File

@ -0,0 +1,5 @@
{@select key=.type}
{@eq value="heading"}{>heading/}{/eq}
{@eq value="section"}{>section/}{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized type {.type}.{/none}
{/select}

View File

@ -0,0 +1 @@
drawer

View File

@ -0,0 +1 @@
dynamic_block

View File

@ -0,0 +1,27 @@
{@select key=.type}
{@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}
{@none}{!TODO: make this panic!}ERROR: Unrecognized type {.type}.{/none}
{/select}

View File

@ -0,0 +1 @@
entity

View File

@ -0,0 +1 @@
example_block

View File

@ -0,0 +1 @@
export_block

View File

@ -0,0 +1 @@
export_snippet

View File

@ -0,0 +1 @@
fixed_width_area

View File

@ -0,0 +1 @@
footnote_definition

View File

@ -0,0 +1 @@
footnote_reference

View File

@ -0,0 +1 @@
global_settings

View File

@ -0,0 +1,11 @@
{@lte key=.level value=4}
<h{.level}>{#.title}{>object/}{/.title}</h{.level}>
{:else}
<ol>
<li>{#.title}{>object/}{/.title}</li>
</ol>
{/lte}
{#.children}
{>document_element/}
{/.children}

View File

@ -0,0 +1 @@
horizontal_rule

View File

@ -0,0 +1 @@
inline_babel_call

View File

@ -0,0 +1 @@
inline_source_block

View File

@ -0,0 +1 @@
italic

View File

@ -0,0 +1 @@
keyword

View File

@ -0,0 +1 @@
latex_environment

View File

@ -0,0 +1 @@
latex_fragment

View File

@ -0,0 +1 @@
line_break

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
{#global_settings.css_files}<link rel="stylesheet" href="{.}">{/global_settings.css_files}
{#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">
{@select key=.type}
{@eq value="blog_post_page"}{>blog_post_page/}{/eq}
{@none}{!TODO: make this panic!}ERROR: Unrecognized page content type{/none}
{/select}
</div>
</body>
</html>

View File

@ -0,0 +1,30 @@
{@select key=.type}
{@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}

View File

@ -0,0 +1 @@
org_macro

View File

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

View File

@ -0,0 +1 @@
plain_link

View File

@ -0,0 +1 @@
plain_list

View File

@ -0,0 +1 @@
plain_text

View File

@ -0,0 +1 @@
planning

View File

@ -0,0 +1 @@
property_drawer

View File

@ -0,0 +1 @@
quote_block

View File

@ -0,0 +1 @@
radio_link

View File

@ -0,0 +1 @@
radio_target

View File

@ -0,0 +1 @@
regular_link

View File

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

View File

@ -0,0 +1 @@
special_block

View File

@ -0,0 +1 @@
src_block

View File

@ -0,0 +1 @@
statistics_cookie

View File

@ -0,0 +1 @@
strike_through

View File

@ -0,0 +1 @@
subscript

View File

@ -0,0 +1 @@
superscript

View File

@ -0,0 +1 @@
table

View File

@ -0,0 +1 @@
target

View File

@ -0,0 +1 @@
timestamp

View File

@ -0,0 +1 @@
underline

View File

@ -0,0 +1 @@
verbatim

View File

@ -0,0 +1 @@
verse_block

View File

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

View File

@ -0,0 +1,98 @@
use std::ffi::OsStr;
use std::path::PathBuf;
use include_dir::include_dir;
use include_dir::Dir;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::convert_blog_post_page_to_render_context;
use crate::intermediate::BlogPost;
use crate::render::DusterRenderer;
use crate::render::RendererIntegration;
static MAIN_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/default_environment/templates/html");
pub(crate) struct SiteRenderer {
output_directory: PathBuf,
blog_posts: Vec<BlogPost>,
}
impl SiteRenderer {
pub(crate) fn new<P: Into<PathBuf>>(
output_directory: P,
blog_posts: Vec<BlogPost>,
) -> SiteRenderer {
SiteRenderer {
output_directory: output_directory.into(),
blog_posts,
}
}
pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> {
let mut renderer_integration = DusterRenderer::new();
let sources: Vec<_> = MAIN_TEMPLATES
.files()
.filter(|f| f.path().extension() == Some(OsStr::new("dust")))
.collect();
if sources
.iter()
.filter(|f| f.path().file_stem() == Some(OsStr::new("main")))
.count()
!= 1
{
return Err("Expect exactly 1 main.dust template file.".into());
}
let decoded_templates = {
let mut decoded_templates = Vec::with_capacity(sources.len());
for entry in sources {
decoded_templates.push(build_name_contents_pairs(entry)?);
}
decoded_templates
};
for (name, contents) in decoded_templates {
renderer_integration.load_template(name, contents)?;
}
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(blog_post_page.get_output_path());
let render_context = convert_blog_post_page_to_render_context(
config,
&self.output_directory,
&output_path,
blog_post,
blog_post_page,
)?;
let rendered_output = renderer_integration.render(render_context)?;
let parent_directory = output_path
.parent()
.ok_or("Output file should have a containing directory.")?;
tokio::fs::create_dir_all(parent_directory).await?;
tokio::fs::write(output_path, rendered_output).await?;
}
}
Ok(())
}
}
fn build_name_contents_pairs<'a>(
entry: &'a include_dir::File<'_>,
) -> Result<(&'a str, &'a str), CustomError> {
let path = entry.path();
let name = path
.file_stem()
.ok_or("All templates should have a stem.")?
.to_str()
.ok_or("All template filenames should be valid utf-8.")?;
let contents = std::str::from_utf8(entry.contents())?;
Ok((name, contents))
}

View File

@ -1,7 +1,60 @@
use crate::cli::parameters::BuildArgs;
use crate::config::Config;
use std::path::PathBuf;
use crate::cli::parameters::BuildArgs;
use crate::command::build::render::SiteRenderer;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::BlogPost;
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);
renderer.render_blog_posts(&config).await?;
pub(crate) async fn build_site(args: BuildArgs) -> Result<(), Box<dyn std::error::Error>> {
let _config = Config::load_from_file(args.config).await?;
Ok(())
}
/// Delete everything inside the output directory and return the path to that directory.
async fn get_output_directory(config: &Config) -> Result<PathBuf, CustomError> {
let output_directory = config.get_output_directory();
if !output_directory.exists() {
tokio::fs::create_dir(&output_directory).await?;
} else {
let mut existing_entries = tokio::fs::read_dir(&output_directory).await?;
while let Some(entry) = existing_entries.next_entry().await? {
let file_type = entry.file_type().await?;
if file_type.is_dir() {
tokio::fs::remove_dir_all(entry.path()).await?;
} else {
tokio::fs::remove_file(entry.path()).await?;
}
}
}
Ok(output_directory)
}
async fn get_post_directories(config: &Config) -> Result<Vec<PathBuf>, CustomError> {
let mut ret = Vec::new();
let mut entries = tokio::fs::read_dir(config.get_posts_directory()).await?;
while let Some(entry) = entries.next_entry().await? {
let file_type = entry.file_type().await?;
if file_type.is_dir() {
ret.push(entry.path());
}
}
Ok(ret)
}
async fn load_blog_posts(config: &Config) -> Result<Vec<BlogPost>, CustomError> {
let root_directory = config.get_root_directory().to_owned();
let post_directories = get_post_directories(&config).await?;
let load_jobs = post_directories
.into_iter()
.map(|path| tokio::spawn(BlogPost::load_blog_post(root_directory.clone(), path)));
let mut blog_posts = Vec::new();
for job in load_jobs {
blog_posts.push(job.await??);
}
Ok(blog_posts)
}

View File

@ -1,7 +1,8 @@
use crate::cli::parameters::InitArgs;
use crate::config::Config;
use crate::error::CustomError;
pub(crate) async fn init_writer_folder(args: InitArgs) -> Result<(), Box<dyn std::error::Error>> {
pub(crate) async fn init_writer_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

@ -3,6 +3,8 @@ use std::path::PathBuf;
use tokio::fs::File;
use tokio::io::AsyncWriteExt;
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.
@ -12,8 +14,8 @@ pub(crate) struct Config {
}
impl Config {
pub(crate) fn new<P: AsRef<Path>>(root_dir: P) -> Result<Config, Box<dyn std::error::Error>> {
fn inner(root_dir: &Path) -> Result<Config, Box<dyn std::error::Error>> {
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");
Ok(Config {
raw: RawConfig::default(),
@ -23,10 +25,8 @@ impl Config {
inner(root_dir.as_ref())
}
pub(crate) async fn load_from_file<P: Into<PathBuf>>(
path: P,
) -> Result<Config, Box<dyn std::error::Error>> {
async fn inner(path: PathBuf) -> Result<Config, Box<dyn std::error::Error>> {
pub(crate) async fn load_from_file<P: Into<PathBuf>>(path: P) -> Result<Config, CustomError> {
async fn inner(path: PathBuf) -> Result<Config, CustomError> {
let contents = tokio::fs::read_to_string(&path).await?;
let parsed_contents: RawConfig = toml::from_str(contents.as_str())?;
Ok(Config {
@ -37,11 +37,34 @@ impl Config {
inner(path.into()).await
}
pub(crate) async fn write_to_disk(&self) -> Result<(), Box<dyn std::error::Error>> {
pub(crate) async fn write_to_disk(&self) -> Result<(), CustomError> {
let mut config_file = File::create(&self.config_path).await?;
config_file
.write_all(toml::to_string(&self.raw)?.as_bytes())
.await?;
Ok(())
}
pub(crate) fn get_root_directory(&self) -> &Path {
&self
.config_path
.parent()
.expect("Config file must exist inside a directory.")
}
pub(crate) fn get_posts_directory(&self) -> PathBuf {
self.get_root_directory().join("posts")
}
pub(crate) fn get_output_directory(&self) -> PathBuf {
self.get_root_directory().join("output")
}
pub(crate) fn use_relative_paths(&self) -> bool {
self.raw.use_relative_paths.unwrap_or(true)
}
pub(crate) fn get_web_root(&self) -> Option<&str> {
self.raw.web_root.as_deref()
}
}

View File

@ -7,6 +7,8 @@ pub(crate) struct RawConfig {
site_title: String,
author: Option<String>,
email: Option<String>,
pub(super) use_relative_paths: Option<bool>,
pub(super) web_root: Option<String>,
}
impl Default for RawConfig {
@ -15,6 +17,8 @@ impl Default for RawConfig {
site_title: "My super awesome website".to_owned(),
author: None,
email: None,
use_relative_paths: None,
web_root: None,
}
}
}

23
src/context/angle_link.rs Normal file
View File

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

23
src/context/babel_call.rs Normal file
View File

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

View File

@ -0,0 +1,34 @@
use serde::Serialize;
use super::GlobalSettings;
use super::RenderDocumentElement;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "blog_post_page")]
pub(crate) struct RenderBlogPostPage {
global_settings: GlobalSettings,
/// The title that will be shown visibly on the page.
title: Option<String>,
self_link: Option<String>,
children: Vec<RenderDocumentElement>,
}
impl RenderBlogPostPage {
pub(crate) fn new(
global_settings: GlobalSettings,
title: Option<String>,
self_link: Option<String>,
children: Vec<RenderDocumentElement>,
) -> RenderBlogPostPage {
RenderBlogPostPage {
global_settings,
title,
self_link,
children,
}
}
}

23
src/context/bold.rs Normal file
View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IBold;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "bold")]
pub(crate) struct RenderBold {}
impl RenderBold {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IBold,
) -> Result<RenderBold, CustomError> {
Ok(RenderBold {})
}
}

View File

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

23
src/context/citation.rs Normal file
View File

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

View File

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

23
src/context/clock.rs Normal file
View File

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

23
src/context/code.rs Normal file
View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::ICode;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "code")]
pub(crate) struct RenderCode {}
impl RenderCode {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ICode,
) -> Result<RenderCode, CustomError> {
Ok(RenderCode {})
}
}

23
src/context/comment.rs Normal file
View File

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

View File

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

23
src/context/diary_sexp.rs Normal file
View File

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

View File

@ -0,0 +1,35 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IDocumentElement;
use super::RenderHeading;
use super::RenderSection;
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub(crate) enum RenderDocumentElement {
Heading(RenderHeading),
Section(RenderSection),
}
impl RenderDocumentElement {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IDocumentElement,
) -> Result<RenderDocumentElement, CustomError> {
match original {
IDocumentElement::Heading(inner) => Ok(RenderDocumentElement::Heading(
RenderHeading::new(config, output_directory, output_file, inner)?,
)),
IDocumentElement::Section(inner) => Ok(RenderDocumentElement::Section(
RenderSection::new(config, output_directory, output_file, inner)?,
)),
}
}
}

23
src/context/drawer.rs Normal file
View File

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

View File

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

190
src/context/element.rs Normal file
View File

@ -0,0 +1,190 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IElement;
use super::babel_call::RenderBabelCall;
use super::center_block::RenderCenterBlock;
use super::clock::RenderClock;
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::example_block::RenderExampleBlock;
use super::export_block::RenderExportBlock;
use super::fixed_width_area::RenderFixedWidthArea;
use super::footnote_definition::RenderFootnoteDefinition;
use super::horizontal_rule::RenderHorizontalRule;
use super::keyword::RenderKeyword;
use super::latex_environment::RenderLatexEnvironment;
use super::paragraph::RenderParagraph;
use super::plain_list::RenderPlainList;
use super::planning::RenderPlanning;
use super::property_drawer::RenderPropertyDrawer;
use super::quote_block::RenderQuoteBlock;
use super::special_block::RenderSpecialBlock;
use super::src_block::RenderSrcBlock;
use super::table::RenderTable;
use super::verse_block::RenderVerseBlock;
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub(crate) enum RenderElement {
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),
}
impl RenderElement {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
element: &IElement,
) -> Result<RenderElement, CustomError> {
match element {
IElement::Paragraph(inner) => Ok(RenderElement::Paragraph(RenderParagraph::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::PlainList(inner) => Ok(RenderElement::PlainList(RenderPlainList::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::CenterBlock(inner) => Ok(RenderElement::CenterBlock(RenderCenterBlock::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::QuoteBlock(inner) => Ok(RenderElement::QuoteBlock(RenderQuoteBlock::new(
config,
output_directory,
output_file,
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)?,
)),
IElement::Comment(inner) => Ok(RenderElement::Comment(RenderComment::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::Drawer(inner) => Ok(RenderElement::Drawer(RenderDrawer::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::PropertyDrawer(inner) => Ok(RenderElement::PropertyDrawer(
RenderPropertyDrawer::new(config, output_directory, output_file, inner)?,
)),
IElement::Table(inner) => Ok(RenderElement::Table(RenderTable::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::VerseBlock(inner) => Ok(RenderElement::VerseBlock(RenderVerseBlock::new(
config,
output_directory,
output_file,
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,
inner,
)?)),
IElement::SrcBlock(inner) => Ok(RenderElement::SrcBlock(RenderSrcBlock::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::Clock(inner) => Ok(RenderElement::Clock(RenderClock::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::DiarySexp(inner) => Ok(RenderElement::DiarySexp(RenderDiarySexp::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::Planning(inner) => Ok(RenderElement::Planning(RenderPlanning::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::FixedWidthArea(inner) => Ok(RenderElement::FixedWidthArea(
RenderFixedWidthArea::new(config, output_directory, output_file, inner)?,
)),
IElement::HorizontalRule(inner) => Ok(RenderElement::HorizontalRule(
RenderHorizontalRule::new(config, output_directory, output_file, inner)?,
)),
IElement::Keyword(inner) => Ok(RenderElement::Keyword(RenderKeyword::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::BabelCall(inner) => Ok(RenderElement::BabelCall(RenderBabelCall::new(
config,
output_directory,
output_file,
inner,
)?)),
IElement::LatexEnvironment(inner) => Ok(RenderElement::LatexEnvironment(
RenderLatexEnvironment::new(config, output_directory, output_file, inner)?,
)),
}
}
}

23
src/context/entity.rs Normal file
View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IEntity;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "entity")]
pub(crate) struct RenderEntity {}
impl RenderEntity {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IEntity,
) -> Result<RenderEntity, CustomError> {
Ok(RenderEntity {})
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IFootnoteDefinition;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "footnote_definition")]
pub(crate) struct RenderFootnoteDefinition {}
impl RenderFootnoteDefinition {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
original: &IFootnoteDefinition,
) -> Result<RenderFootnoteDefinition, CustomError> {
Ok(RenderFootnoteDefinition {})
}
}

View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IFootnoteReference;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "footnote_reference")]
pub(crate) struct RenderFootnoteReference {}
impl RenderFootnoteReference {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IFootnoteReference,
) -> Result<RenderFootnoteReference, CustomError> {
Ok(RenderFootnoteReference {})
}
}

View File

@ -0,0 +1,24 @@
use serde::Serialize;
/// The settings that a "global" to a single dustjs render.
#[derive(Debug, Serialize)]
pub(crate) struct GlobalSettings {
/// The title that goes in the html <title> tag in the <head>.
page_title: Option<String>,
css_files: Vec<String>,
js_files: Vec<String>,
}
impl GlobalSettings {
pub(crate) fn new(
page_title: Option<String>,
css_files: Vec<String>,
js_files: Vec<String>,
) -> GlobalSettings {
GlobalSettings {
page_title,
css_files,
js_files,
}
}
}

60
src/context/heading.rs Normal file
View File

@ -0,0 +1,60 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IHeading;
use super::RenderDocumentElement;
use super::RenderObject;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "heading")]
pub(crate) struct RenderHeading {
level: organic::types::HeadlineLevel,
title: Vec<RenderObject>,
children: Vec<RenderDocumentElement>,
}
impl RenderHeading {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
heading: &IHeading,
) -> Result<RenderHeading, CustomError> {
let title = {
let mut ret = Vec::new();
for obj in heading.title.iter() {
ret.push(RenderObject::new(
config,
&output_directory,
&output_file,
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,
)?);
}
ret
};
Ok(RenderHeading {
level: heading.level + 1, // Adding 1 because the page title is going to be h1.
title,
children,
})
}
}

View File

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

View File

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

View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IInlineSourceBlock;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "inline_source_block")]
pub(crate) struct RenderInlineSourceBlock {}
impl RenderInlineSourceBlock {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IInlineSourceBlock,
) -> Result<RenderInlineSourceBlock, CustomError> {
Ok(RenderInlineSourceBlock {})
}
}

23
src/context/italic.rs Normal file
View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::IItalic;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "italic")]
pub(crate) struct RenderItalic {}
impl RenderItalic {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &IItalic,
) -> Result<RenderItalic, CustomError> {
Ok(RenderItalic {})
}
}

23
src/context/keyword.rs Normal file
View File

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

View File

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

View File

@ -0,0 +1,23 @@
use std::path::Path;
use serde::Serialize;
use crate::config::Config;
use crate::error::CustomError;
use crate::intermediate::ILatexFragment;
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "latex_fragment")]
pub(crate) struct RenderLatexFragment {}
impl RenderLatexFragment {
pub(crate) fn new(
config: &Config,
output_directory: &Path,
output_file: &Path,
comment: &ILatexFragment,
) -> Result<RenderLatexFragment, CustomError> {
Ok(RenderLatexFragment {})
}
}

23
src/context/line_break.rs Normal file
View File

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

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