parent
769264e3e5
commit
51784aa60f
@ -10,6 +10,7 @@
|
|||||||
- Shorcodes and `anchor-link.html` can now access the `lang` context
|
- Shorcodes and `anchor-link.html` can now access the `lang` context
|
||||||
- Add prompt before replacing the output directory with `zola build` if the `output-dir` flag is given
|
- Add prompt before replacing the output directory with `zola build` if the `output-dir` flag is given
|
||||||
- Shortcode handling has been completely rewritten, solving many issues
|
- Shortcode handling has been completely rewritten, solving many issues
|
||||||
|
- Also add internal links starting with `#` without any internal Zola link
|
||||||
|
|
||||||
## 0.14.1 (2021-08-24)
|
## 0.14.1 (2021-08-24)
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ impl Page {
|
|||||||
anchor_insert,
|
anchor_insert,
|
||||||
);
|
);
|
||||||
context.set_shortcode_definitions(shortcode_definitions);
|
context.set_shortcode_definitions(shortcode_definitions);
|
||||||
|
context.set_current_page_path(&self.file.relative);
|
||||||
context.tera_context.insert("page", &SerializingPage::from_page_basic(self, None));
|
context.tera_context.insert("page", &SerializingPage::from_page_basic(self, None));
|
||||||
|
|
||||||
let res = render_content(&self.raw_content, &context).map_err(|e| {
|
let res = render_content(&self.raw_content, &context).map_err(|e| {
|
||||||
|
@ -10,7 +10,7 @@ use front_matter::{split_section_content, SectionFrontMatter};
|
|||||||
use rendering::{render_content, Heading, RenderContext};
|
use rendering::{render_content, Heading, RenderContext};
|
||||||
use utils::fs::read_file;
|
use utils::fs::read_file;
|
||||||
use utils::site::get_reading_analytics;
|
use utils::site::get_reading_analytics;
|
||||||
use utils::templates::render_template;
|
use utils::templates::{render_template, ShortcodeDefinition};
|
||||||
|
|
||||||
use crate::content::file_info::FileInfo;
|
use crate::content::file_info::FileInfo;
|
||||||
use crate::content::ser::SerializingSection;
|
use crate::content::ser::SerializingSection;
|
||||||
@ -147,6 +147,7 @@ impl Section {
|
|||||||
permalinks: &HashMap<String, String>,
|
permalinks: &HashMap<String, String>,
|
||||||
tera: &Tera,
|
tera: &Tera,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
|
shortcode_definitions: &HashMap<String, ShortcodeDefinition>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut context = RenderContext::new(
|
let mut context = RenderContext::new(
|
||||||
tera,
|
tera,
|
||||||
@ -156,7 +157,8 @@ impl Section {
|
|||||||
permalinks,
|
permalinks,
|
||||||
self.meta.insert_anchor_links,
|
self.meta.insert_anchor_links,
|
||||||
);
|
);
|
||||||
|
context.set_shortcode_definitions(shortcode_definitions);
|
||||||
|
context.set_current_page_path(&self.file.relative);
|
||||||
context.tera_context.insert("section", &SerializingSection::from_section_basic(self, None));
|
context.tera_context.insert("section", &SerializingSection::from_section_basic(self, None));
|
||||||
|
|
||||||
let res = render_content(&self.raw_content, &context).map_err(|e| {
|
let res = render_content(&self.raw_content, &context).map_err(|e| {
|
||||||
|
@ -12,6 +12,7 @@ pub struct RenderContext<'a> {
|
|||||||
pub tera: Cow<'a, Tera>,
|
pub tera: Cow<'a, Tera>,
|
||||||
pub config: &'a Config,
|
pub config: &'a Config,
|
||||||
pub tera_context: Context,
|
pub tera_context: Context,
|
||||||
|
pub current_page_path: Option<&'a str>,
|
||||||
pub current_page_permalink: &'a str,
|
pub current_page_permalink: &'a str,
|
||||||
pub permalinks: Cow<'a, HashMap<String, String>>,
|
pub permalinks: Cow<'a, HashMap<String, String>>,
|
||||||
pub insert_anchor: InsertAnchor,
|
pub insert_anchor: InsertAnchor,
|
||||||
@ -35,6 +36,7 @@ impl<'a> RenderContext<'a> {
|
|||||||
Self {
|
Self {
|
||||||
tera: Cow::Borrowed(tera),
|
tera: Cow::Borrowed(tera),
|
||||||
tera_context,
|
tera_context,
|
||||||
|
current_page_path: None,
|
||||||
current_page_permalink,
|
current_page_permalink,
|
||||||
permalinks: Cow::Borrowed(permalinks),
|
permalinks: Cow::Borrowed(permalinks),
|
||||||
insert_anchor,
|
insert_anchor,
|
||||||
@ -50,6 +52,11 @@ impl<'a> RenderContext<'a> {
|
|||||||
self.shortcode_definitions = Cow::Borrowed(def);
|
self.shortcode_definitions = Cow::Borrowed(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as above
|
||||||
|
pub fn set_current_page_path(&mut self, path: &'a str) {
|
||||||
|
self.current_page_path = Some(path);
|
||||||
|
}
|
||||||
|
|
||||||
// In use in the markdown filter
|
// In use in the markdown filter
|
||||||
// NOTE: This RenderContext is not i18n-aware, see MarkdownFilter::filter for details
|
// NOTE: This RenderContext is not i18n-aware, see MarkdownFilter::filter for details
|
||||||
// If this function is ever used outside of MarkdownFilter, take this into consideration
|
// If this function is ever used outside of MarkdownFilter, take this into consideration
|
||||||
@ -57,6 +64,7 @@ impl<'a> RenderContext<'a> {
|
|||||||
Self {
|
Self {
|
||||||
tera: Cow::Owned(Tera::default()),
|
tera: Cow::Owned(Tera::default()),
|
||||||
tera_context: Context::new(),
|
tera_context: Context::new(),
|
||||||
|
current_page_path: None,
|
||||||
current_page_permalink: "",
|
current_page_permalink: "",
|
||||||
permalinks: Cow::Owned(HashMap::new()),
|
permalinks: Cow::Owned(HashMap::new()),
|
||||||
insert_anchor: InsertAnchor::None,
|
insert_anchor: InsertAnchor::None,
|
||||||
|
@ -10,6 +10,7 @@ use errors::Result;
|
|||||||
|
|
||||||
pub use context::RenderContext;
|
pub use context::RenderContext;
|
||||||
use markdown::markdown_to_html;
|
use markdown::markdown_to_html;
|
||||||
|
pub use markdown::Rendered;
|
||||||
pub use table_of_contents::Heading;
|
pub use table_of_contents::Heading;
|
||||||
|
|
||||||
pub fn render_content(content: &str, context: &RenderContext) -> Result<markdown::Rendered> {
|
pub fn render_content(content: &str, context: &RenderContext) -> Result<markdown::Rendered> {
|
||||||
|
@ -92,9 +92,20 @@ fn fix_link(
|
|||||||
} else {
|
} else {
|
||||||
if is_external_link(link) {
|
if is_external_link(link) {
|
||||||
external_links.push(link.to_owned());
|
external_links.push(link.to_owned());
|
||||||
|
link.to_owned()
|
||||||
|
} else if link.starts_with("#") {
|
||||||
|
// local anchor without the internal zola path
|
||||||
|
if let Some(current_path) = context.current_page_path {
|
||||||
|
internal_links.push((current_path.to_owned(), Some(link[1..].to_owned())));
|
||||||
|
format!("{}{}", context.current_page_permalink, &link)
|
||||||
|
} else {
|
||||||
|
link.to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
link.to_string()
|
||||||
}
|
}
|
||||||
link.to_string()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,8 +132,7 @@ fn get_heading_refs(events: &[Event]) -> Vec<HeadingRef> {
|
|||||||
heading_refs.push(HeadingRef::new(i, *level));
|
heading_refs.push(HeadingRef::new(i, *level));
|
||||||
}
|
}
|
||||||
Event::End(Tag::Heading(_)) => {
|
Event::End(Tag::Heading(_)) => {
|
||||||
let msg = "Heading end before start?";
|
heading_refs.last_mut().expect("Heading end before start?").end_idx = i;
|
||||||
heading_refs.last_mut().expect(msg).end_idx = i;
|
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -1,82 +1,62 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use errors::Result;
|
||||||
|
use rendering::Rendered;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
macro_rules! test_links {
|
fn render_content(content: &str, permalinks: HashMap<String, String>) -> Result<Rendered> {
|
||||||
(
|
let config = config::Config::default_for_test();
|
||||||
$in_str:literal,
|
let tera = tera::Tera::default();
|
||||||
[$($id:literal => $perma_link:literal),*],
|
let mut context = rendering::RenderContext::new(
|
||||||
[$($abs_path:literal),*],
|
&tera,
|
||||||
[$($rel_path:literal:$opt_anchor:expr),*],
|
&config,
|
||||||
[$($shortcodes:ident),*]
|
&config.default_language,
|
||||||
) => {
|
"http://mypage.com",
|
||||||
let config = config::Config::default_for_test();
|
&permalinks,
|
||||||
|
front_matter::InsertAnchor::None,
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut tera = tera::Tera::default();
|
|
||||||
|
|
||||||
// Add all shortcodes
|
|
||||||
$(
|
|
||||||
tera.add_raw_template(
|
|
||||||
&format!("shortcodes/{}", $shortcodes.filename()),
|
|
||||||
$shortcodes.output
|
|
||||||
).expect("Failed to add raw template");
|
|
||||||
)*
|
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut permalinks = std::collections::HashMap::new();
|
|
||||||
|
|
||||||
$(
|
|
||||||
permalinks.insert($id.to_string(), $perma_link.to_string());
|
|
||||||
)*
|
|
||||||
|
|
||||||
let context = rendering::RenderContext::new(
|
|
||||||
&tera,
|
|
||||||
&config,
|
|
||||||
&config.default_language,
|
|
||||||
"",
|
|
||||||
&permalinks,
|
|
||||||
front_matter::InsertAnchor::None,
|
|
||||||
);
|
|
||||||
|
|
||||||
let rendered = rendering::render_content($in_str, &context);
|
|
||||||
assert!(rendered.is_ok(), "Rendering failed");
|
|
||||||
|
|
||||||
let rendered = rendered.unwrap();
|
|
||||||
|
|
||||||
let asserted_int_links = vec![
|
|
||||||
$(
|
|
||||||
($rel_path.to_string(), $opt_anchor.map(|x| x.to_string()))
|
|
||||||
),*
|
|
||||||
];
|
|
||||||
let asserted_ext_links: Vec<&str> = vec![$($abs_path),*];
|
|
||||||
|
|
||||||
assert_eq!(rendered.internal_links, asserted_int_links, "Internal links unequal");
|
|
||||||
assert_eq!(rendered.external_links, asserted_ext_links, "External links unequal");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn basic_internal() {
|
|
||||||
test_links!("Hello World!", [], [], [], []);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn absolute_links() {
|
|
||||||
test_links!("[abc](https://google.com/)", [], ["https://google.com/"], [], []);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn relative_links() {
|
|
||||||
test_links!(
|
|
||||||
"[abc](@/def/123.md)",
|
|
||||||
["def/123.md" => "https://xyz.com/def/123"],
|
|
||||||
[],
|
|
||||||
["def/123.md":<Option<&str>>::None],
|
|
||||||
[]
|
|
||||||
);
|
);
|
||||||
|
context.set_current_page_path("mine.md");
|
||||||
|
|
||||||
|
rendering::render_content(content, &context)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
fn can_detect_links() {
|
||||||
fn relative_links_no_perma() {
|
// no links
|
||||||
test_links!("[abc](@/def/123.md)", [], [], ["def/123.md": <Option<&str>>::None], []);
|
let rendered = render_content("Hello World!", HashMap::new()).unwrap();
|
||||||
|
assert_eq!(rendered.internal_links.len(), 0);
|
||||||
|
assert_eq!(rendered.external_links.len(), 0);
|
||||||
|
|
||||||
|
// external
|
||||||
|
let rendered = render_content("[abc](https://google.com/)", HashMap::new()).unwrap();
|
||||||
|
assert_eq!(rendered.internal_links.len(), 0);
|
||||||
|
assert_eq!(rendered.external_links.len(), 1);
|
||||||
|
assert_eq!(rendered.external_links[0], "https://google.com/");
|
||||||
|
|
||||||
|
// internal
|
||||||
|
let mut permalinks = HashMap::new();
|
||||||
|
permalinks.insert("def/123.md".to_owned(), "https://xyz.com/def/123".to_owned());
|
||||||
|
let rendered = render_content("[abc](@/def/123.md)", permalinks).unwrap();
|
||||||
|
assert_eq!(rendered.internal_links.len(), 1);
|
||||||
|
assert_eq!(rendered.internal_links[0], ("def/123.md".to_owned(), None));
|
||||||
|
assert_eq!(rendered.external_links.len(), 0);
|
||||||
|
|
||||||
|
// internal with anchors
|
||||||
|
let mut permalinks = HashMap::new();
|
||||||
|
permalinks.insert("def/123.md".to_owned(), "https://xyz.com/def/123".to_owned());
|
||||||
|
let rendered = render_content("[abc](@/def/123.md#hello)", permalinks).unwrap();
|
||||||
|
assert_eq!(rendered.internal_links.len(), 1);
|
||||||
|
assert_eq!(rendered.internal_links[0], ("def/123.md".to_owned(), Some("hello".to_owned())));
|
||||||
|
assert_eq!(rendered.external_links.len(), 0);
|
||||||
|
|
||||||
|
// internal link referring to self
|
||||||
|
let rendered = render_content("[abc](#hello)", HashMap::new()).unwrap();
|
||||||
|
assert_eq!(rendered.internal_links.len(), 1);
|
||||||
|
assert_eq!(rendered.internal_links[0], ("mine.md".to_owned(), Some("hello".to_owned())));
|
||||||
|
assert_eq!(rendered.external_links.len(), 0);
|
||||||
|
|
||||||
|
// Not pointing to anything so that's an error
|
||||||
|
let res = render_content("[abc](@/def/123.md)", HashMap::new());
|
||||||
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,9 @@ impl Site {
|
|||||||
.values_mut()
|
.values_mut()
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
.map(|section| section.render_markdown(permalinks, tera, config))
|
.map(|section| {
|
||||||
|
section.render_markdown(permalinks, tera, config, &self.shortcode_definitions)
|
||||||
|
})
|
||||||
.collect::<Result<()>>()?;
|
.collect::<Result<()>>()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -426,7 +428,12 @@ impl Site {
|
|||||||
pub fn add_section(&mut self, mut section: Section, render_md: bool) -> Result<()> {
|
pub fn add_section(&mut self, mut section: Section, render_md: bool) -> Result<()> {
|
||||||
self.permalinks.insert(section.file.relative.clone(), section.permalink.clone());
|
self.permalinks.insert(section.file.relative.clone(), section.permalink.clone());
|
||||||
if render_md {
|
if render_md {
|
||||||
section.render_markdown(&self.permalinks, &self.tera, &self.config)?;
|
section.render_markdown(
|
||||||
|
&self.permalinks,
|
||||||
|
&self.tera,
|
||||||
|
&self.config,
|
||||||
|
&self.shortcode_definitions,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
let mut library = self.library.write().expect("Get lock for add_section");
|
let mut library = self.library.write().expect("Get lock for add_section");
|
||||||
library.remove_section(§ion.file.path);
|
library.remove_section(§ion.file.path);
|
||||||
@ -847,7 +854,13 @@ impl Site {
|
|||||||
if taxonomy.kind.is_paginated() {
|
if taxonomy.kind.is_paginated() {
|
||||||
self.render_paginated(
|
self.render_paginated(
|
||||||
comp.clone(),
|
comp.clone(),
|
||||||
&Paginator::from_taxonomy(taxonomy, item, &library, &self.tera, &self.config.theme),
|
&Paginator::from_taxonomy(
|
||||||
|
taxonomy,
|
||||||
|
item,
|
||||||
|
&library,
|
||||||
|
&self.tera,
|
||||||
|
&self.config.theme,
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
let single_output =
|
let single_output =
|
||||||
|
Loading…
Reference in New Issue
Block a user