Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor link transforming #109

Merged
merged 4 commits into from
Jan 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
orgize = { version = "0.9.0", features = ["chrono"]}
orgize = { version = "0.9.0", features = ["chrono", "syntect"]}
tera = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.48"
Expand All @@ -19,7 +19,6 @@ chrono = "0.4"
slugify = "0.1.0"
sass-rs = "0.2"
# for server (borrowed from zola)
# hyper = { version = "0.14.1", default-features = false, features = ["runtime", "server", "http2", "http1"] }
tokio = { version = "1.0.1", default-features = false, features = ["rt", "fs", "full"] }
warp = "0.3"
notify = "4"
65 changes: 59 additions & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,54 @@ use std::process::Command;
use std::{collections::HashMap, fs::create_dir_all};
use tera;

// TODO: move this to another file
#[derive(Debug, Clone)]
pub struct BaseUrl {
pub base_url: String,
dir_source: PathBuf,
dir_data_name: String,
}

impl BaseUrl {
pub fn new(base_url: String, dir_source: PathBuf, dir_data_files_src: PathBuf) -> BaseUrl {
let dir_data_name = dir_data_files_src
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or("".into());

BaseUrl {
base_url,
dir_source,
dir_data_name,
}
}
// check if a link is linking to our data directory (in which case we don't
// want to preface it with a sibling directory parent)
pub fn link_starts_with_data_dir(&self, link: String) -> bool {
link.starts_with(&self.dir_data_name)
}

fn strip_source_cwd(&self, file_path: PathBuf) -> PathBuf {
file_path
.strip_prefix(self.dir_source.clone())
.unwrap()
.parent()
.unwrap()
.to_path_buf()
}

pub fn build(self, link: String, file_path: PathBuf) -> String {
let parent_dirs = self.strip_source_cwd(file_path);
let mut link_res = PathBuf::from(self.base_url.clone());
if parent_dirs != PathBuf::from("") && !self.link_starts_with_data_dir(link.clone()) {
link_res.push(parent_dirs);
}
link_res.push(link);

util::path_to_string(&link_res)
}
}

pub struct Config<'a> {
pub dir_source: PathBuf,
pub dir_firn: PathBuf,
Expand Down Expand Up @@ -50,7 +98,7 @@ pub struct Config<'a> {
pub tag_page: PathBuf,
pub tags_map: HashMap<String, Vec<OrgMetadata<'a>>>,
pub tags_list: Vec<LinkData>,
pub base_url: String,
pub base_url: BaseUrl,
}

/// Builds common paths for the config object.
Expand Down Expand Up @@ -82,10 +130,14 @@ impl<'a> Config<'a> {
let tag_page = dir_firn.join("[tags].html");

Ok(Config {
dir_source: cwd,
dir_source: cwd.clone(),
global_attachments: Vec::new(),
tera: templates::tera::load_templates(&dir_templates.clone()),
base_url: user_config.site.url.clone(),
base_url: BaseUrl::new(
user_config.site.url.clone(),
cwd.clone(),
dir_data_files_src.clone(),
),
dir_static_src: dir_firn.join("static"),
dir_static_dest: dir_firn.join("_site/static"),
dir_sass: dir_firn.join("sass"),
Expand Down Expand Up @@ -288,8 +340,8 @@ impl<'a> Config<'a> {
let x = LinkData::new(
tag_url,
tag_name.to_string(),
LinkMeta::Tag{count: v.len()},
None
LinkMeta::Tag { count: v.len() },
None,
);
out.push(x);
}
Expand All @@ -310,7 +362,7 @@ impl<'a> Config<'a> {
sitemap_item_url,
v.originating_file.clone(),
LinkMeta::Sitemap,
Some(v.front_matter.clone())
Some(v.front_matter.clone()),
);
out.push(x);
}
Expand Down Expand Up @@ -401,6 +453,7 @@ impl<'a> Config<'a> {
.expect("Failed to parse port to an integer");
self.serve_port = port_int;
self.user_config.site.url = format!("http://localhost:{}", port);
self.base_url.base_url = format!("http://localhost:{}", port);
}

fn clean_up_attachments(&self) {
Expand Down
39 changes: 25 additions & 14 deletions src/html.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::config::BaseUrl;
use crate::util;
use orgize::export::{DefaultHtmlHandler, HtmlEscape, HtmlHandler};
use orgize::{elements, Element};
use std::io::{Error as IOError, Write};
use std::path::PathBuf;
use std::string::FromUtf8Error;
use crate::templates::links;
use crate::util;


// -- HTML Handlers for Orgize -------------------------------------------------

Expand Down Expand Up @@ -38,7 +38,6 @@ pub struct MyHtmlHandler(DefaultHtmlHandler);
impl HtmlHandler<MyError> for MyHtmlHandler {
fn start<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), MyError> {
match element {

Element::Document { .. } => write!(w, "<div>")?,
Element::Title(title) => {
if title.level > 6 {
Expand All @@ -48,7 +47,11 @@ impl HtmlHandler<MyError> for MyHtmlHandler {
write!(w, "<h6 id=\"{0}\">", &title.raw)?;
}
} else if let Some(keyword) = &title.keyword {
write!(w, "<h{0} class=\"firn-{2}\" id=\"{1}\">", title.level, &title.raw, keyword)?;
write!(
w,
"<h{0} class=\"firn-{2}\" id=\"{1}\">",
title.level, &title.raw, keyword
)?;
} else {
write!(w, "<h{0} id=\"{1}\">", title.level, &title.raw,)?;
}
Expand Down Expand Up @@ -85,34 +88,42 @@ impl HtmlHandler<MyError> for MyHtmlHandler {
}
}


// -- HTML Transformers
// -- HTML Renderes
//
// There are a few cases where we iterate over the parsed orgize content
// and then match over an orgize::Event::<title,Link, etc> and write html.
//
// Rather than write link/title rendering several times, we do it here.
//
// Before we hand off orgize-data structures to the above html handler for writing html
// we sometimes need to transform the data based on user customization / help etc.
// most of these need to just transfer the beginning of the html (the start fn needed by the trait.)

pub fn trx_link(
/// render_link transforms a link as orgize reads it to a happy little weblink.
/// namely, we need to handle for prepending the baseurl, and match any sibling/parent
/// linking when encountering a `./` or `../` type of link.
pub fn write_link(
link: &elements::Link,
handler: &mut MyHtmlHandler,
writer: &mut Vec<u8>,
base_url: String,
base_url: BaseUrl,
file_path: PathBuf,
) {
let link_web_path = links::link_transformer(base_url, link.path.to_owned().to_string());
let link_web_path =
util::transform_org_link_to_html(base_url, link.path.to_owned().to_string(), file_path);
let new_link = elements::Link {
path: std::borrow::Cow::Borrowed(&link_web_path),
desc: link.desc.to_owned(),
};
let new_link_enum = Element::Link(new_link);
handler.start(writer, &new_link_enum).unwrap()
handler.start(writer, &new_link_enum).unwrap()
}


pub fn trx_title(
pub fn write_title(
title: &elements::Title,
handler: &mut MyHtmlHandler,
writer: &mut Vec<u8>,
update_level: Option<i8>
update_level: Option<i8>,
) {
let update_level = update_level.unwrap_or(0);
let mut new_level = title.level as i8 + update_level;
Expand Down
4 changes: 2 additions & 2 deletions src/org.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl<'a> OrgFile<'a> {
.into_os_string()
.into_string()
.expect("Failed to convert web_path to string");
let full_url = util::make_site_url(cfg.clone_baseurl(), web_path_str);
let full_url = cfg.base_url.clone().build(web_path_str, file_path.clone());
let out_path = PathBuf::from(&cfg.dir_site_out).join(&web_path);
let parsed = Org::parse_string(read_file);
let front_matter = FrontMatter::new(&parsed);
Expand Down Expand Up @@ -373,7 +373,7 @@ impl<'a> OrgFile<'a> {
OrgMetadataType::Link(link) => {
let new_link_path = link.path.to_owned().to_string();
let web_link =
util::org_file_link_to_html_link(cfg.clone_baseurl(), new_link_path);
util::transform_org_link_to_html(cfg.base_url.clone(), new_link_path, self.file_path.clone());

let backlink_item_url = format!(
"{}/{}",
Expand Down
2 changes: 1 addition & 1 deletion src/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fn detect_change_kind(dir_source: &PathBuf, path: PathBuf) -> (PathBuf, ChangeKi
ChangeKind::Config
// this should be at the end of the block!
// detects if it's an org file that has changed
} else if let Some(parent) = changed_path.parent() {
} else if let Some(_parent) = changed_path.parent() {
if let Some(extension) = changed_path.extension() {
if extension == "org" {
ChangeKind::OrgFile
Expand Down
25 changes: 1 addition & 24 deletions src/templates/links.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
use crate::{front_matter::FrontMatter, util};
use crate::front_matter::FrontMatter;
use serde::Serialize;

/// Transforms the possible link *paths* we might get while parsing org links from orgize.
pub fn link_transformer(base_url: String, org_link_path: String) -> String {
let mut link_path = org_link_path;
// <1> -- It's a local org file.
if util::is_local_org_file(&link_path) {
link_path = util::clean_file_link(link_path);
link_path = str::replace(&link_path, ".org", ".html");
return util::make_site_url(base_url, link_path);

// <2> it's a local image
} else if util::is_local_img_file(&link_path) {
link_path = util::clean_file_link(link_path);
return util::make_site_url(base_url, link_path);
}

// <3> is a web link (doesn't start with baseurl.)
if !util::is_local_org_file(&link_path) {
return link_path;
}
// <4> We don't know? Just return the link.
link_path
}

// -- Link data for Tera to loop over --------------------------------------------

#[derive(Debug, PartialEq, Serialize)]
Expand Down
30 changes: 19 additions & 11 deletions src/templates/render.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
config::Config,
config::{BaseUrl, Config},
errors::{FirnError, FirnErrorType},
front_matter,
html::{self, MyHtmlHandler},
Expand All @@ -16,7 +16,7 @@ use tera::{Function as TeraFn, Result as TeraResult};
#[derive(Debug, Clone)]
pub struct Render {
original_org: String,
base_url: String,
base_url: BaseUrl,
file_path: PathBuf,
front_matter: front_matter::FrontMatter,
verbosity: i8,
Expand All @@ -35,7 +35,7 @@ impl Render {
original_org: o.original_org.clone(),
front_matter: o.front_matter.clone(),
file_path: o.file_path.clone(),
base_url: cfg.clone_baseurl(),
base_url: cfg.base_url.clone(),
verbosity: cfg.verbosity,
user_config: cfg.user_config.clone(),
}
Expand All @@ -56,11 +56,15 @@ impl Render {
match event {
Event::Start(el) => match el {
Element::Title(title) => {
html::trx_title(title, &mut handler, &mut wr, update_level)
}
Element::Link(link) => {
html::trx_link(link, &mut handler, &mut wr, self.base_url.clone())
html::write_title(title, &mut handler, &mut wr, update_level)
}
Element::Link(link) => html::write_link(
link,
&mut handler,
&mut wr,
self.base_url.clone(),
self.file_path.clone(),
),
_ => handler.start(&mut wr, el).unwrap(),
},
Event::End(el) => handler.end(&mut wr, el).unwrap(),
Expand Down Expand Up @@ -93,11 +97,15 @@ impl Render {
if is_writing {
match el {
Element::Title(title) => {
html::trx_title(title, &mut handler, &mut wr, update_level)
}
Element::Link(link) => {
html::trx_link(link, &mut handler, &mut wr, self.base_url.clone())
html::write_title(title, &mut handler, &mut wr, update_level)
}
Element::Link(link) => html::write_link(
link,
&mut handler,
&mut wr,
self.base_url.clone(),
self.file_path.clone(),
),
_ => handler.start(&mut wr, el).unwrap(),
}
}
Expand Down
Loading