diff --git a/Cargo.toml b/Cargo.toml
index 6efb188..e178095 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,11 +1,6 @@
[package]
-description = "static site generator fit for a dog"
edition = "2021"
-homepage = "https://webdog.zyl.gay"
-license = "AGPL-3.0-or-later"
name = "webdog"
-readme = "README.md"
-repository = "https://github.com/zyllian/webdog"
version = "0.1.0"
[dependencies]
diff --git a/README.md b/README.md
index d083a2d..8a9584c 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,3 @@
# webdog
-webdog, the static site generator fit for a dog :3
-
-```sh
-cargo install webdog
-```
-
-after installing, you can create your first site:
-
-```sh
-webdog create https://example.com "My First Site!" --site my-site
-cd my-site
-webdog serve # your site is now running at http://127.0.0.1:8080 🥳
-```
-
-from there, you can start editing your site and adding pages or [more advanced things](https://webdog.zyl.gay/docs/)
-
-```sh
-webdog page new my-first-page "My First Page"
-```
+Source for webdog, the static site generator fit for a dog. See our website at https://webdog.zyl.gay for more details.
diff --git a/site/pages/index.md b/site/pages/index.md
index 0c4de07..78e9937 100644
--- a/site/pages/index.md
+++ b/site/pages/index.md
@@ -5,7 +5,7 @@ welcome to webdog, the static site generator fit for a dog :3
if you have [rust](https://rust-lang.org) installed, all you need to do to install webdog is run the following command:
```sh
-cargo install webdog
+cargo install webdog --git https://github.com/zyllian/webdog
```
then you can make your first webdog site!
diff --git a/site/sass/index.scss b/site/sass/index.scss
index 13c1808..4ebf304 100644
--- a/site/sass/index.scss
+++ b/site/sass/index.scss
@@ -183,7 +183,6 @@ abbr {
.wd-codeblock {
position: relative;
- tab-size: 2;
.copy {
display: none;
@@ -207,6 +206,6 @@ abbr {
& > pre {
padding: 8px;
- overflow: auto;
+ overflow: scroll;
}
}
diff --git a/src/builder.rs b/src/builder.rs
index d5da847..2222afe 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -4,6 +4,7 @@ use std::{collections::HashMap, path::PathBuf};
use eyre::{eyre, Context, OptionExt};
use lol_html::{element, html_content::ContentType, HtmlRewriter, Settings};
+use pulldown_cmark::{Options, Parser};
use rayon::prelude::*;
use serde::Serialize;
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
@@ -260,28 +261,10 @@ impl SiteBuilder {
Ok(())
}),
- element!("img", |el| {
- if let Some(mut src) = el.get_attribute("src") {
- if let Some((command, new_src)) = src.split_once('$') {
- let mut new_src = new_src.to_string();
- #[allow(clippy::single_match)]
- match command {
- "cdn" => {
- new_src = self.site.config.cdn_url(&new_src)?.to_string();
- }
- _ => new_src = src,
- }
- src = new_src;
- el.set_attribute("src", &src)?;
- }
- }
-
- Ok(())
- }),
element!("a", |el| {
if let Some(mut href) = el.get_attribute("href") {
- if let Some((command, new_href)) = href.split_once('$') {
- let mut new_href = new_href.to_string();
+ if let Some((command, mut new_href)) = href.split_once('$') {
+ #[allow(clippy::single_match)]
match command {
"me" => {
el.set_attribute(
@@ -290,14 +273,11 @@ impl SiteBuilder {
+ " me"),
)?;
}
- "cdn" => {
- new_href = self.site.config.cdn_url(&new_href)?.to_string();
- }
_ => {
- new_href = href;
+ new_href = &href;
}
}
- href = new_href;
+ href = new_href.to_string();
el.set_attribute("href", &href)?;
}
if let Ok(url) = Url::parse(&href) {
@@ -314,6 +294,47 @@ impl SiteBuilder {
}
}
+ Ok(())
+ }),
+ element!("md", |el| {
+ el.remove();
+ let class = el.get_attribute("class");
+
+ let md_type = el
+ .get_attribute("type")
+ .ok_or_eyre("missing type attribute on markdown tag")?;
+
+ if md_type == "blog-image" {
+ let mut src = el
+ .get_attribute("src")
+ .ok_or_eyre("missing src attribute")?;
+
+ if src.starts_with("cdn$") {
+ src = self.site.config.cdn_url(&src[4..])?.to_string();
+ }
+
+ let class = format!("image {}", class.unwrap_or_default());
+ let content = el
+ .get_attribute("content")
+ .ok_or_eyre("missing content attribute")?;
+
+ el.replace(
+ &format!(
+ r#"
+
+
+
+
+
{content}
+
+ "#
+ ),
+ ContentType::Html,
+ );
+ } else {
+ return Err(eyre!("unknown markdown tag type: {md_type}").into());
+ }
+
Ok(())
}),
],
@@ -398,7 +419,49 @@ impl SiteBuilder {
.with_context(|| format!("Failed to read page at {}", page_path.display()))?;
let page = crate::frontmatter::FrontMatter::parse(input)?;
- let page_html = util::render_markdown(self, &page.content)?;
+ let mut language = None;
+ let parser = Parser::new_ext(&page.content, Options::all()).filter_map(|event| {
+ // syntax highlighting for code blocks
+ match event {
+ pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(
+ pulldown_cmark::CodeBlockKind::Fenced(name),
+ )) => {
+ language = Some(name);
+ None
+ }
+ pulldown_cmark::Event::Text(code) => {
+ if let Some(language) = language.take() {
+ let syntax_reference = self
+ .syntax_set
+ .find_syntax_by_token(&language)
+ .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
+ let html = format!(
+ r#"
+
+ {}
+
"#,
+ syntect::html::highlighted_html_for_string(
+ &code,
+ &self.syntax_set,
+ syntax_reference,
+ self.theme_set
+ .themes
+ .get(&self.site.config.code_theme)
+ .as_ref()
+ .expect("should never fail"),
+ )
+ .expect("failed to highlight syntax")
+ );
+ Some(pulldown_cmark::Event::Html(html.into()))
+ } else {
+ Some(pulldown_cmark::Event::Text(code))
+ }
+ }
+ _ => Some(event),
+ }
+ });
+ let mut page_html = String::new();
+ pulldown_cmark::html::push_html(&mut page_html, parser);
let out = self.build_page_raw(page.data.unwrap_or_default(), &page_html, ())?;
diff --git a/src/embedded/default_site/sass/index.scss b/src/embedded/default_site/sass/index.scss
index 06ef3d6..239ad7e 100644
--- a/src/embedded/default_site/sass/index.scss
+++ b/src/embedded/default_site/sass/index.scss
@@ -5,7 +5,6 @@
.wd-codeblock {
position: relative;
- tab-size: 2;
.copy {
display: none;
@@ -29,6 +28,6 @@
& > pre {
padding: 8px;
- overflow: auto;
+ overflow: scroll;
}
}
diff --git a/src/resource.rs b/src/resource.rs
index 433584c..d4d5bf1 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -5,13 +5,14 @@ use std::{
use eyre::Context;
use itertools::Itertools;
+use pulldown_cmark::{Options, Parser};
use rss::{validation::Validate, ChannelBuilder, ItemBuilder};
use serde::{Deserialize, Serialize};
use time::{format_description::well_known::Rfc2822, OffsetDateTime};
use crate::{
builder::SiteBuilder, frontmatter::FrontMatterRequired, link_list::Link,
- util::{self, format_timestamp}, PageMetadata,
+ util::format_timestamp, PageMetadata,
};
/// Metadata for resources.
@@ -181,7 +182,10 @@ impl ResourceBuilder {
let mut page = FrontMatterRequired::::parse(input)
.wrap_err_with(|| eyre::eyre!("Failed to parse resource front matter"))?;
- *page.content_mut() = util::render_markdown(builder, &page.content)?;
+ let parser = Parser::new_ext(&page.content, Options::all());
+ let mut html = String::new();
+ pulldown_cmark::html::push_html(&mut html, parser);
+ *page.content_mut() = html;
let data = page.data_mut();
if let Some(cdn_file) = &data.cdn_file {
diff --git a/src/util.rs b/src/util.rs
index 0f42680..d8ebf18 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -2,11 +2,8 @@
use std::path::Path;
-use pulldown_cmark::{Options, Parser};
use time::OffsetDateTime;
-use crate::builder::SiteBuilder;
-
/// Simple helper to remove the contents of a directory without removing the directory itself.
pub fn remove_dir_contents(path: &Path) -> eyre::Result<()> {
for entry in path.read_dir()? {
@@ -27,52 +24,3 @@ pub fn format_timestamp(ts: OffsetDateTime, format: &str) -> eyre::Result(format)?;
Ok(ts.format(&fmt)?)
}
-
-/// Helper to render markdown.
-pub fn render_markdown(builder: &SiteBuilder, input: &str) -> eyre::Result {
- let mut language = None;
- let parser = Parser::new_ext(input, Options::all()).filter_map(|event| {
- // syntax highlighting for code blocks
- match event {
- pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(
- pulldown_cmark::CodeBlockKind::Fenced(name),
- )) => {
- language = Some(name);
- None
- }
- pulldown_cmark::Event::Text(code) => {
- if let Some(language) = language.take() {
- let syntax_reference = builder
- .syntax_set
- .find_syntax_by_token(&language)
- .unwrap_or_else(|| builder.syntax_set.find_syntax_plain_text());
- let html = format!(
- r#"
-
- {}
-
"#,
- syntect::html::highlighted_html_for_string(
- &code,
- &builder.syntax_set,
- syntax_reference,
- builder.theme_set
- .themes
- .get(&builder.site.config.code_theme)
- .as_ref()
- .expect("should never fail"),
- )
- .expect("failed to highlight syntax")
- );
- Some(pulldown_cmark::Event::Html(html.into()))
- } else {
- Some(pulldown_cmark::Event::Text(code))
- }
- }
- _ => Some(event),
- }
- });
- let mut page_html = String::new();
- pulldown_cmark::html::push_html(&mut page_html, parser);
-
- Ok(page_html)
-}