├── .envrc ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── example └── index.md ├── flake.lock ├── flake.nix └── src ├── html.rs └── main.rs /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.direnv 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "atty" 7 | version = "0.2.14" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 10 | dependencies = [ 11 | "hermit-abi", 12 | "libc", 13 | "winapi", 14 | ] 15 | 16 | [[package]] 17 | name = "autocfg" 18 | version = "1.0.1" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 21 | 22 | [[package]] 23 | name = "bitflags" 24 | version = "1.3.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 27 | 28 | [[package]] 29 | name = "clap" 30 | version = "3.0.7" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "12e8611f9ae4e068fa3e56931fded356ff745e70987ff76924a6e0ab1c8ef2e3" 33 | dependencies = [ 34 | "atty", 35 | "bitflags", 36 | "clap_derive", 37 | "indexmap", 38 | "lazy_static", 39 | "os_str_bytes", 40 | "strsim", 41 | "termcolor", 42 | "textwrap", 43 | ] 44 | 45 | [[package]] 46 | name = "clap_derive" 47 | version = "3.0.6" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" 50 | dependencies = [ 51 | "heck", 52 | "proc-macro-error", 53 | "proc-macro2", 54 | "quote", 55 | "syn", 56 | ] 57 | 58 | [[package]] 59 | name = "eyre" 60 | version = "0.6.5" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" 63 | dependencies = [ 64 | "indenter", 65 | "once_cell", 66 | ] 67 | 68 | [[package]] 69 | name = "hashbrown" 70 | version = "0.11.2" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 73 | 74 | [[package]] 75 | name = "heck" 76 | version = "0.4.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 79 | 80 | [[package]] 81 | name = "hermit-abi" 82 | version = "0.1.19" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 85 | dependencies = [ 86 | "libc", 87 | ] 88 | 89 | [[package]] 90 | name = "indenter" 91 | version = "0.3.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 94 | 95 | [[package]] 96 | name = "indexmap" 97 | version = "1.8.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" 100 | dependencies = [ 101 | "autocfg", 102 | "hashbrown", 103 | ] 104 | 105 | [[package]] 106 | name = "lazy_static" 107 | version = "1.4.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 110 | 111 | [[package]] 112 | name = "libc" 113 | version = "0.2.112" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" 116 | 117 | [[package]] 118 | name = "memchr" 119 | version = "2.4.1" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 122 | 123 | [[package]] 124 | name = "minijinja" 125 | version = "0.13.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "a30f17c534db2eedae437efc317ff3b9a8921dff9bdaa9003b61c8187515e2d4" 128 | dependencies = [ 129 | "serde", 130 | ] 131 | 132 | [[package]] 133 | name = "once_cell" 134 | version = "1.9.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" 137 | 138 | [[package]] 139 | name = "os_str_bytes" 140 | version = "6.0.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" 143 | dependencies = [ 144 | "memchr", 145 | ] 146 | 147 | [[package]] 148 | name = "polar" 149 | version = "0.1.0" 150 | dependencies = [ 151 | "clap", 152 | "eyre", 153 | "minijinja", 154 | "pulldown-cmark", 155 | ] 156 | 157 | [[package]] 158 | name = "proc-macro-error" 159 | version = "1.0.4" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 162 | dependencies = [ 163 | "proc-macro-error-attr", 164 | "proc-macro2", 165 | "quote", 166 | "syn", 167 | "version_check", 168 | ] 169 | 170 | [[package]] 171 | name = "proc-macro-error-attr" 172 | version = "1.0.4" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 175 | dependencies = [ 176 | "proc-macro2", 177 | "quote", 178 | "version_check", 179 | ] 180 | 181 | [[package]] 182 | name = "proc-macro2" 183 | version = "1.0.36" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 186 | dependencies = [ 187 | "unicode-xid", 188 | ] 189 | 190 | [[package]] 191 | name = "pulldown-cmark" 192 | version = "0.9.1" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" 195 | dependencies = [ 196 | "bitflags", 197 | "memchr", 198 | "unicase", 199 | ] 200 | 201 | [[package]] 202 | name = "quote" 203 | version = "1.0.14" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" 206 | dependencies = [ 207 | "proc-macro2", 208 | ] 209 | 210 | [[package]] 211 | name = "serde" 212 | version = "1.0.133" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" 215 | 216 | [[package]] 217 | name = "strsim" 218 | version = "0.10.0" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 221 | 222 | [[package]] 223 | name = "syn" 224 | version = "1.0.85" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" 227 | dependencies = [ 228 | "proc-macro2", 229 | "quote", 230 | "unicode-xid", 231 | ] 232 | 233 | [[package]] 234 | name = "termcolor" 235 | version = "1.1.2" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 238 | dependencies = [ 239 | "winapi-util", 240 | ] 241 | 242 | [[package]] 243 | name = "textwrap" 244 | version = "0.14.2" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" 247 | 248 | [[package]] 249 | name = "unicase" 250 | version = "2.6.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 253 | dependencies = [ 254 | "version_check", 255 | ] 256 | 257 | [[package]] 258 | name = "unicode-xid" 259 | version = "0.2.2" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 262 | 263 | [[package]] 264 | name = "version_check" 265 | version = "0.9.4" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 268 | 269 | [[package]] 270 | name = "winapi" 271 | version = "0.3.9" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 274 | dependencies = [ 275 | "winapi-i686-pc-windows-gnu", 276 | "winapi-x86_64-pc-windows-gnu", 277 | ] 278 | 279 | [[package]] 280 | name = "winapi-i686-pc-windows-gnu" 281 | version = "0.4.0" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 284 | 285 | [[package]] 286 | name = "winapi-util" 287 | version = "0.1.5" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 290 | dependencies = [ 291 | "winapi", 292 | ] 293 | 294 | [[package]] 295 | name = "winapi-x86_64-pc-windows-gnu" 296 | version = "0.4.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 299 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "polar" 3 | version = "0.1.0" 4 | authors = ["anirudhb "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | eyre = "0.6.5" 11 | clap = { version = "3.0.7", features = ["derive"] } 12 | pulldown-cmark = { version = "0.9.1", default-features = false, features = ["simd"] } 13 | minijinja = "0.13.0" 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # polar 2 | 3 | the best static site generator you've ever seen 4 | 5 | features: 6 | * 📦 one executable (fast, lightweight) 7 | * 🖼 image optimization 8 | * 🖌 awesome, jinja2-like templating with [tera](https://github.com/Keats/tera) 9 | * 🔃 super nice TUI with [indicatif](https://github.com/mitsuhiko/indicatif) and [dialoguer](https://github.com/mitsuhiko/dialoguer) 10 | * ⚡ extremely fast dev server with hot-reloading 11 | -------------------------------------------------------------------------------- /example/index.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | {{ "test" | safe }} 3 | 4 | {{ 5 + 7 }} 5 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "fenix": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs", 6 | "rust-analyzer-src": "rust-analyzer-src" 7 | }, 8 | "locked": { 9 | "lastModified": 1642227974, 10 | "narHash": "sha256-zrqUfbk3g47yGCzx8cWggCPvgiBYc/uFQhVk0n+M+wc=", 11 | "owner": "nix-community", 12 | "repo": "fenix", 13 | "rev": "2e2c7ccdba995148ea0110ad51e0bdc7977830bc", 14 | "type": "github" 15 | }, 16 | "original": { 17 | "owner": "nix-community", 18 | "repo": "fenix", 19 | "type": "github" 20 | } 21 | }, 22 | "flake-utils": { 23 | "locked": { 24 | "lastModified": 1638122382, 25 | "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", 26 | "owner": "numtide", 27 | "repo": "flake-utils", 28 | "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", 29 | "type": "github" 30 | }, 31 | "original": { 32 | "owner": "numtide", 33 | "repo": "flake-utils", 34 | "type": "github" 35 | } 36 | }, 37 | "nixpkgs": { 38 | "locked": { 39 | "lastModified": 1641887635, 40 | "narHash": "sha256-kDGpufwzVaiGe5e1sBUBPo9f1YN+nYHJlYqCaVpZTQQ=", 41 | "owner": "nixos", 42 | "repo": "nixpkgs", 43 | "rev": "b2737d4980a17cc2b7d600d7d0b32fd7333aca88", 44 | "type": "github" 45 | }, 46 | "original": { 47 | "owner": "nixos", 48 | "ref": "nixos-unstable", 49 | "repo": "nixpkgs", 50 | "type": "github" 51 | } 52 | }, 53 | "nixpkgs_2": { 54 | "locked": { 55 | "lastModified": 1640328990, 56 | "narHash": "sha256-KQbvJx4qO9bo04tfTZuISyY4vRC5k3ZB3lyLS21XWIw=", 57 | "owner": "NixOS", 58 | "repo": "nixpkgs", 59 | "rev": "ab93217a2b74a1c36bc892c14f44ee5959c33f12", 60 | "type": "github" 61 | }, 62 | "original": { 63 | "owner": "NixOS", 64 | "ref": "nixpkgs-unstable", 65 | "repo": "nixpkgs", 66 | "type": "github" 67 | } 68 | }, 69 | "root": { 70 | "inputs": { 71 | "fenix": "fenix", 72 | "flake-utils": "flake-utils", 73 | "nixpkgs": "nixpkgs_2" 74 | } 75 | }, 76 | "rust-analyzer-src": { 77 | "flake": false, 78 | "locked": { 79 | "lastModified": 1642187035, 80 | "narHash": "sha256-E5lBHUMQRG0qNLDz9jyOsqEsWqC4DUMzpR2arCeJef0=", 81 | "owner": "rust-analyzer", 82 | "repo": "rust-analyzer", 83 | "rev": "844c152fd1be8f0142343a095d5b45586189f435", 84 | "type": "github" 85 | }, 86 | "original": { 87 | "owner": "rust-analyzer", 88 | "ref": "nightly", 89 | "repo": "rust-analyzer", 90 | "type": "github" 91 | } 92 | } 93 | }, 94 | "root": "root", 95 | "version": 7 96 | } 97 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A very basic flake with a shell"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | fenix.url = "github:nix-community/fenix"; 8 | }; 9 | 10 | outputs = { self, nixpkgs, flake-utils, fenix }: flake-utils.lib.eachDefaultSystem (system: 11 | let 12 | pkgs = nixpkgs.legacyPackages.${system}; 13 | fenixPkgs = fenix.packages.${system}; 14 | in rec { 15 | devShell = pkgs.mkShell { 16 | nativeBuildInputs = with pkgs; [ 17 | (fenixPkgs.latest.withComponents [ 18 | "cargo" 19 | "rustc" 20 | "rust-src" 21 | "rustfmt" 22 | ]) 23 | fenixPkgs.rust-analyzer 24 | cargo-edit 25 | cargo-bloat 26 | libiconv 27 | ]; 28 | }; 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /src/html.rs: -------------------------------------------------------------------------------- 1 | /**! 2 | * HTML writer which is better suited to our needs than the pulldown_cmark one. 3 | * Mostly taken from pulldown_cmark though. 4 | */ 5 | use pulldown_cmark::{CowStr, Event, LinkType, Tag}; 6 | use std::io::{self, Write}; 7 | 8 | enum TableState { 9 | Head, 10 | Body, 11 | } 12 | 13 | /// FIXME: take an iterator over (Event, Range) 14 | /// so that errors can be emitted and shown 15 | /// 16 | /// FIXME: implement tables and footnotes 17 | /// TODO: detect heading links and slugify them 18 | pub(crate) struct HtmlWriter<'a, I, W> 19 | where 20 | I: Iterator>, 21 | W: Write, 22 | { 23 | iter: I, 24 | writer: W, 25 | 26 | table_state: Option, 27 | } 28 | 29 | impl<'a, I, W> HtmlWriter<'a, I, W> 30 | where 31 | I: Iterator>, 32 | W: Write, 33 | { 34 | pub(crate) fn new(iter: I, writer: W) -> Self { 35 | Self { 36 | iter, 37 | writer, 38 | table_state: None, 39 | } 40 | } 41 | 42 | pub(crate) fn run(&mut self) -> io::Result<()> { 43 | use Event::*; 44 | while let Some(event) = self.iter.next() { 45 | match event { 46 | Start(tag) => self.start_tag(tag)?, 47 | End(tag) => self.end_tag(tag)?, 48 | Text(text) => self.write_text(&text)?, 49 | Code(text) => self.write_code(&text)?, 50 | Html(html) => self.write_html(&html)?, 51 | SoftBreak => self.write_newline()?, 52 | HardBreak => self.write_break()?, 53 | Rule => self.write_rule()?, 54 | TaskListMarker(checked) => self.write_task_list_marker(checked)?, 55 | _ => todo!("rest of the owl"), 56 | } 57 | } 58 | Ok(()) 59 | } 60 | 61 | fn write_task_list_marker(&mut self, checked: bool) -> io::Result<()> { 62 | if checked { 63 | write!(self.writer, "")?; 64 | } else { 65 | write!(self.writer, "")?; 66 | } 67 | Ok(()) 68 | } 69 | 70 | fn write_rule(&mut self) -> io::Result<()> { 71 | write!(self.writer, "
")?; 72 | Ok(()) 73 | } 74 | 75 | fn write_break(&mut self) -> io::Result<()> { 76 | write!(self.writer, "
")?; 77 | Ok(()) 78 | } 79 | 80 | fn write_newline(&mut self) -> io::Result<()> { 81 | write!(self.writer, "\n")?; 82 | Ok(()) 83 | } 84 | 85 | // FIXME: figure out html stuff 86 | fn write_html(&mut self, html: &str) -> io::Result<()> { 87 | self.write_text(html) 88 | } 89 | 90 | fn write_code(&mut self, code: &str) -> io::Result<()> { 91 | write!(self.writer, "")?; 92 | self.write_text(code)?; 93 | write!(self.writer, "")?; 94 | Ok(()) 95 | } 96 | 97 | // FIXME: escape text 98 | fn write_text(&mut self, text: &str) -> io::Result<()> { 99 | write!(self.writer, "{}", text)?; 100 | Ok(()) 101 | } 102 | 103 | fn write_linkish( 104 | &mut self, 105 | tag: &str, 106 | ty: LinkType, 107 | dest: CowStr, 108 | title: CowStr, 109 | ) -> io::Result<()> { 110 | write!(self.writer, "<{} href=\"{}", tag, get_link_url(ty, dest))?; 111 | if !title.is_empty() { 112 | write!(self.writer, "\" title=\"{}", title)?; 113 | } 114 | write!(self.writer, "\">")?; 115 | Ok(()) 116 | } 117 | 118 | // FIXME: tables and footnote definitions 119 | fn start_tag(&mut self, tag: Tag<'a>) -> io::Result<()> { 120 | use pulldown_cmark::CodeBlockKind; 121 | use Tag::*; 122 | match tag { 123 | Paragraph => write!(self.writer, "

")?, 124 | Heading(level, _, _) => write!(self.writer, "<{}>", level)?, 125 | Table(alignments) => todo!(), 126 | TableHead => todo!(), 127 | TableRow => todo!(), 128 | TableCell => todo!(), 129 | BlockQuote => write!(self.writer, "

")?, 130 | CodeBlock(kind) => match kind { 131 | CodeBlockKind::Fenced(lang) => { 132 | if lang.is_empty() { 133 | write!(self.writer, "
")?
134 |                     } else {
135 |                         write!(self.writer, "
", lang)?
136 |                     }
137 |                 }
138 |                 CodeBlockKind::Indented => write!(self.writer, "
")?,
139 |             },
140 |             List(Some(start)) => write!(self.writer, "
    ", start)?, 141 | List(None) => write!(self.writer, "
      ")?, 142 | Item => write!(self.writer, "
    • ")?, 143 | Emphasis => write!(self.writer, "")?, 144 | Strong => write!(self.writer, "")?, 145 | Strikethrough => write!(self.writer, "")?, 146 | Link(ty, dest, title) => self.write_linkish("a", ty, dest, title)?, 147 | Image(ty, dest, title) => self.write_linkish("img", ty, dest, title)?, 148 | FootnoteDefinition(name) => todo!(), 149 | } 150 | Ok(()) 151 | } 152 | 153 | fn end_tag(&mut self, tag: Tag<'a>) -> io::Result<()> { 154 | use Tag::*; 155 | match tag { 156 | Paragraph => write!(self.writer, "

      ")?, 157 | Heading(level, _, _) => write!(self.writer, "", level)?, 158 | Table(..) => todo!(), 159 | TableHead => todo!(), 160 | TableRow => todo!(), 161 | TableCell => todo!(), 162 | BlockQuote => write!(self.writer, "
")?, 163 | CodeBlock(..) => write!(self.writer, "")?, 164 | List(Some(_)) => write!(self.writer, "")?, 165 | List(None) => write!(self.writer, "")?, 166 | Item => write!(self.writer, "")?, 167 | Emphasis => write!(self.writer, "")?, 168 | Strong => write!(self.writer, "")?, 169 | Strikethrough => write!(self.writer, "")?, 170 | Link(..) => write!(self.writer, "")?, 171 | Image(..) => write!(self.writer, "")?, 172 | FootnoteDefinition(..) => todo!(), 173 | } 174 | Ok(()) 175 | } 176 | } 177 | 178 | fn get_link_url(ty: LinkType, url: CowStr) -> CowStr { 179 | match ty { 180 | LinkType::Email => format!("mailto:{}", url).into(), 181 | _ => url, 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use minijinja::Environment; 3 | use std::path::PathBuf; 4 | 5 | mod html; 6 | 7 | #[derive(Parser)] 8 | #[clap( 9 | version = "0.1", 10 | author = "anirudhb " 11 | )] 12 | struct Opts { 13 | #[clap(short, long, default_value = "out")] 14 | outdir: PathBuf, 15 | filename: PathBuf, 16 | } 17 | 18 | struct Polar<'a> { 19 | env: Environment<'a>, 20 | outdir: PathBuf, 21 | } 22 | 23 | /* Convert markdown to html */ 24 | fn htmlify(markdown: &str) -> String { 25 | use pulldown_cmark::{Options, Parser}; 26 | let mut options = Options::empty(); 27 | options.insert(Options::ENABLE_TABLES); 28 | options.insert(Options::ENABLE_TASKLISTS); 29 | options.insert(Options::ENABLE_STRIKETHROUGH); 30 | let parser = Parser::new_ext(markdown, options); 31 | let mut output = Vec::new(); 32 | let mut writer = html::HtmlWriter::new(parser, &mut output); 33 | // safe to unwrap since output is a Vec 34 | writer.run().unwrap(); 35 | String::from_utf8(output).unwrap() 36 | } 37 | 38 | fn main() -> eyre::Result<()> { 39 | let opts = Opts::parse(); 40 | let mut polar = Polar { 41 | env: Environment::new(), 42 | outdir: opts.outdir, 43 | }; 44 | 45 | println!("Filename = {:?}", opts.filename); 46 | let contents = std::fs::read_to_string(&opts.filename)?; 47 | let out_html = htmlify(&contents); 48 | println!("HTMLified = {}", out_html); 49 | polar.env.add_template("main", &out_html)?; 50 | let out = polar.env.get_template("main")?.render(())?; 51 | println!("templated = {}", out); 52 | 53 | Ok(()) 54 | } 55 | --------------------------------------------------------------------------------