parent
f9ae897190
commit
b313c97ceb
|
@ -1,7 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## 0.13.0 (unreleased)
|
||||
## 0.12.1 (unreleased)
|
||||
|
||||
- Add line
|
||||
- Fix the new `zola serve` being broken on Windows
|
||||
- Fix slugified taxonomies not being rendered at the right path
|
||||
|
||||
## 0.12.0 (2020-09-04)
|
||||
|
||||
|
|
|
@ -17,10 +17,7 @@ lazy_static! {
|
|||
}
|
||||
|
||||
/// Returns the highlighter and whether it was found in the extra or not
|
||||
pub fn get_highlighter(
|
||||
language: Option<&str>,
|
||||
config: &Config
|
||||
) -> (HighlightLines<'static>, bool) {
|
||||
pub fn get_highlighter(language: Option<&str>, config: &Config) -> (HighlightLines<'static>, bool) {
|
||||
let theme = &THEME_SET.themes[&config.highlight_theme];
|
||||
let mut in_extra = false;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ impl<'a> Paginator<'a> {
|
|||
paginate_reversed: false,
|
||||
root: PaginationRoot::Taxonomy(taxonomy, item),
|
||||
permalink: item.permalink.clone(),
|
||||
path: format!("/{}/{}/", taxonomy.kind.name, item.slug),
|
||||
path: format!("/{}/{}/", taxonomy.slug, item.slug),
|
||||
paginate_path: taxonomy
|
||||
.kind
|
||||
.paginate_path
|
||||
|
@ -129,7 +129,7 @@ impl<'a> Paginator<'a> {
|
|||
}
|
||||
|
||||
for key in self.all_pages.to_mut().iter_mut() {
|
||||
let page = library.get_page_by_key(key.clone());
|
||||
let page = library.get_page_by_key(*key);
|
||||
current_page.push(page.to_serialized_basic(library));
|
||||
|
||||
if current_page.len() == self.paginate_by {
|
||||
|
@ -416,7 +416,11 @@ mod tests {
|
|||
permalink: "https://vincent.is/tags/something/".to_string(),
|
||||
pages: library.pages().keys().collect(),
|
||||
};
|
||||
let taxonomy = Taxonomy { kind: taxonomy_def, items: vec![taxonomy_item.clone()] };
|
||||
let taxonomy = Taxonomy {
|
||||
kind: taxonomy_def,
|
||||
slug: "tags".to_string(),
|
||||
items: vec![taxonomy_item.clone()],
|
||||
};
|
||||
let paginator = Paginator::from_taxonomy(&taxonomy, &taxonomy_item, &library);
|
||||
assert_eq!(paginator.pagers.len(), 2);
|
||||
|
||||
|
@ -431,6 +435,39 @@ mod tests {
|
|||
assert_eq!(paginator.pagers[1].path, "/tags/something/page/2/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_create_paginator_for_slugified_taxonomy() {
|
||||
let (_, library) = create_library(false, 3, false);
|
||||
let taxonomy_def = TaxonomyConfig {
|
||||
name: "some tags".to_string(),
|
||||
paginate_by: Some(2),
|
||||
..TaxonomyConfig::default()
|
||||
};
|
||||
let taxonomy_item = TaxonomyItem {
|
||||
name: "Something".to_string(),
|
||||
slug: "something".to_string(),
|
||||
permalink: "https://vincent.is/some-tags/something/".to_string(),
|
||||
pages: library.pages().keys().collect(),
|
||||
};
|
||||
let taxonomy = Taxonomy {
|
||||
kind: taxonomy_def,
|
||||
slug: "some-tags".to_string(),
|
||||
items: vec![taxonomy_item.clone()],
|
||||
};
|
||||
let paginator = Paginator::from_taxonomy(&taxonomy, &taxonomy_item, &library);
|
||||
assert_eq!(paginator.pagers.len(), 2);
|
||||
|
||||
assert_eq!(paginator.pagers[0].index, 1);
|
||||
assert_eq!(paginator.pagers[0].pages.len(), 2);
|
||||
assert_eq!(paginator.pagers[0].permalink, "https://vincent.is/some-tags/something/");
|
||||
assert_eq!(paginator.pagers[0].path, "/some-tags/something/");
|
||||
|
||||
assert_eq!(paginator.pagers[1].index, 2);
|
||||
assert_eq!(paginator.pagers[1].pages.len(), 2);
|
||||
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/some-tags/something/page/2/");
|
||||
assert_eq!(paginator.pagers[1].path, "/some-tags/something/page/2/");
|
||||
}
|
||||
|
||||
// https://github.com/getzola/zola/issues/866
|
||||
#[test]
|
||||
fn works_with_empty_paginate_path() {
|
||||
|
|
|
@ -53,6 +53,7 @@ impl TaxonomyItem {
|
|||
pub fn new(
|
||||
name: &str,
|
||||
taxonomy: &TaxonomyConfig,
|
||||
taxo_slug: &str,
|
||||
config: &Config,
|
||||
keys: Vec<DefaultKey>,
|
||||
library: &Library,
|
||||
|
@ -72,7 +73,6 @@ impl TaxonomyItem {
|
|||
.collect();
|
||||
let (mut pages, ignored_pages) = sort_pages_by_date(data);
|
||||
let item_slug = slugify_paths(name, config.slugify.taxonomies);
|
||||
let taxo_slug = slugify_paths(&taxonomy.name, config.slugify.taxonomies);
|
||||
let permalink = if taxonomy.lang != config.default_language {
|
||||
config.make_permalink(&format!("/{}/{}/{}", taxonomy.lang, taxo_slug, item_slug))
|
||||
} else {
|
||||
|
@ -118,6 +118,7 @@ impl<'a> SerializedTaxonomy<'a> {
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Taxonomy {
|
||||
pub kind: TaxonomyConfig,
|
||||
pub slug: String,
|
||||
// this vec is sorted by the count of item
|
||||
pub items: Vec<TaxonomyItem>,
|
||||
}
|
||||
|
@ -130,8 +131,9 @@ impl Taxonomy {
|
|||
library: &Library,
|
||||
) -> Taxonomy {
|
||||
let mut sorted_items = vec![];
|
||||
let slug = slugify_paths(&kind.name, config.slugify.taxonomies);
|
||||
for (name, pages) in items {
|
||||
sorted_items.push(TaxonomyItem::new(&name, &kind, config, pages, library));
|
||||
sorted_items.push(TaxonomyItem::new(&name, &kind, &slug, config, pages, library));
|
||||
}
|
||||
//sorted_items.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
sorted_items.sort_by(|a, b| match a.slug.cmp(&b.slug) {
|
||||
|
@ -150,7 +152,7 @@ impl Taxonomy {
|
|||
false
|
||||
}
|
||||
});
|
||||
Taxonomy { kind, items: sorted_items }
|
||||
Taxonomy { kind, slug, items: sorted_items }
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use syntect::html::{IncludeBackground, styled_line_to_highlighted_html};
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::parsing::SyntaxSet;
|
||||
use syntect::highlighting::{Color, Theme, Style};
|
||||
use config::Config;
|
||||
use config::highlighting::{get_highlighter, SYNTAX_SET, THEME_SET};
|
||||
use config::Config;
|
||||
use std::cmp::min;
|
||||
use std::collections::HashSet;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::{Color, Style, Theme};
|
||||
use syntect::html::{styled_line_to_highlighted_html, IncludeBackground};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
|
||||
use super::fence::{FenceSettings, Range};
|
||||
|
||||
|
@ -22,11 +22,7 @@ pub struct CodeBlock<'config> {
|
|||
}
|
||||
|
||||
impl<'config> CodeBlock<'config> {
|
||||
pub fn new(
|
||||
fence_info: &str,
|
||||
config: &'config Config,
|
||||
background: IncludeBackground,
|
||||
) -> Self {
|
||||
pub fn new(fence_info: &str, config: &'config Config, background: IncludeBackground) -> Self {
|
||||
let fence_info = FenceSettings::new(fence_info);
|
||||
let theme = &THEME_SET.themes[&config.highlight_theme];
|
||||
let (highlighter, in_extra) = get_highlighter(fence_info.language, config);
|
||||
|
@ -45,10 +41,8 @@ impl<'config> CodeBlock<'config> {
|
|||
}
|
||||
|
||||
pub fn highlight(&mut self, text: &str) -> String {
|
||||
let highlighted = self.highlighter.highlight(
|
||||
text,
|
||||
self.extra_syntax_set.unwrap_or(&SYNTAX_SET),
|
||||
);
|
||||
let highlighted =
|
||||
self.highlighter.highlight(text, self.extra_syntax_set.unwrap_or(&SYNTAX_SET));
|
||||
let line_boundaries = self.find_line_boundaries(&highlighted);
|
||||
|
||||
// First we make sure that `highlighted` is split at every line
|
||||
|
@ -61,9 +55,8 @@ impl<'config> CodeBlock<'config> {
|
|||
// we don't use it later.
|
||||
let mut highlighted = perform_split(&highlighted, line_boundaries);
|
||||
|
||||
let hl_background = self.theme.settings.line_highlight
|
||||
.unwrap_or(Color { r: 255, g: 255, b: 0, a: 0 });
|
||||
|
||||
let hl_background =
|
||||
self.theme.settings.line_highlight.unwrap_or(Color { r: 255, g: 255, b: 0, a: 0 });
|
||||
|
||||
let hl_lines = self.get_highlighted_lines();
|
||||
color_highlighted_lines(&mut highlighted, &hl_lines, hl_background);
|
||||
|
@ -76,10 +69,7 @@ impl<'config> CodeBlock<'config> {
|
|||
for (vec_idx, (_style, s)) in styled.iter().enumerate() {
|
||||
for (str_idx, character) in s.char_indices() {
|
||||
if character == '\n' {
|
||||
boundaries.push(StyledIdx {
|
||||
vec_idx,
|
||||
str_idx,
|
||||
});
|
||||
boundaries.push(StyledIdx { vec_idx, str_idx });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +80,7 @@ impl<'config> CodeBlock<'config> {
|
|||
fn get_highlighted_lines(&self) -> HashSet<usize> {
|
||||
let mut lines = HashSet::new();
|
||||
for range in &self.highlight_lines {
|
||||
for line in range.from ..= min(range.to, self.num_lines) {
|
||||
for line in range.from..=min(range.to, self.num_lines) {
|
||||
// Ranges are one-indexed
|
||||
lines.insert(line.saturating_sub(1));
|
||||
}
|
||||
|
@ -123,7 +113,7 @@ fn get_str_idx_if_vec_idx_is(idx: Option<&StyledIdx>, vec_idx: usize) -> Option<
|
|||
/// the `StyledIdx` type.
|
||||
fn perform_split<'b>(
|
||||
split: &[(Style, &'b str)],
|
||||
line_boundaries: Vec<StyledIdx>
|
||||
line_boundaries: Vec<StyledIdx>,
|
||||
) -> Vec<(Style, &'b str)> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
|
@ -172,11 +162,7 @@ fn perform_split<'b>(
|
|||
result
|
||||
}
|
||||
|
||||
fn color_highlighted_lines(
|
||||
data: &mut [(Style, &str)],
|
||||
lines: &HashSet<usize>,
|
||||
background: Color,
|
||||
) {
|
||||
fn color_highlighted_lines(data: &mut [(Style, &str)], lines: &HashSet<usize>, background: Color) {
|
||||
if lines.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,22 +9,16 @@ impl Range {
|
|||
match s.find('-') {
|
||||
Some(dash) => {
|
||||
let mut from = s[..dash].parse().ok()?;
|
||||
let mut to = s[dash+1..].parse().ok()?;
|
||||
let mut to = s[dash + 1..].parse().ok()?;
|
||||
if to < from {
|
||||
std::mem::swap(&mut from, &mut to);
|
||||
}
|
||||
Some(Range {
|
||||
from,
|
||||
to,
|
||||
})
|
||||
},
|
||||
Some(Range { from, to })
|
||||
}
|
||||
None => {
|
||||
let val = s.parse().ok()?;
|
||||
Some(Range {
|
||||
from: val,
|
||||
to: val,
|
||||
})
|
||||
},
|
||||
Some(Range { from: val, to: val })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +31,7 @@ pub struct FenceSettings<'a> {
|
|||
}
|
||||
impl<'a> FenceSettings<'a> {
|
||||
pub fn new(fence_info: &'a str) -> Self {
|
||||
let mut me = Self {
|
||||
language: None,
|
||||
line_numbers: false,
|
||||
highlight_lines: Vec::new(),
|
||||
};
|
||||
let mut me = Self { language: None, line_numbers: false, highlight_lines: Vec::new() };
|
||||
|
||||
for token in FenceIter::new(fence_info) {
|
||||
match token {
|
||||
|
@ -67,9 +57,7 @@ struct FenceIter<'a> {
|
|||
}
|
||||
impl<'a> FenceIter<'a> {
|
||||
fn new(fence_info: &'a str) -> Self {
|
||||
Self {
|
||||
split: fence_info.split(','),
|
||||
}
|
||||
Self { split: fence_info.split(',') }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,10 +80,10 @@ impl<'a> Iterator for FenceIter<'a> {
|
|||
}
|
||||
}
|
||||
return Some(FenceToken::HighlightLines(ranges));
|
||||
},
|
||||
}
|
||||
lang => {
|
||||
return Some(FenceToken::Language(lang));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ use tera::Tera;
|
|||
use config::Config;
|
||||
use front_matter::InsertAnchor;
|
||||
use rendering::{render_content, RenderContext};
|
||||
use templates::ZOLA_TERA;
|
||||
use utils::slugs::SlugifyStrategy;
|
||||
|
||||
macro_rules! colored_html_line {
|
||||
( @no $s:expr ) => {{
|
||||
|
@ -41,19 +39,26 @@ fn hl_lines_simple() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar",
|
||||
@no "bar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar",
|
||||
@no "bar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -63,19 +68,26 @@ fn hl_lines_in_middle() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=2-3
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -85,17 +97,24 @@ fn hl_lines_all() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=1-4
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -105,18 +124,25 @@ fn hl_lines_start_from_one() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=1-3
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -126,18 +152,25 @@ fn hl_lines_start_from_zero() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=0-3
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -147,18 +180,25 @@ fn hl_lines_end() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=3-4
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo\nbar",
|
||||
@hl "bar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo\nbar",
|
||||
@hl "bar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -168,18 +208,25 @@ fn hl_lines_end_out_of_bounds() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=3-4294967295
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo\nbar",
|
||||
@hl "bar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo\nbar",
|
||||
@hl "bar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -189,18 +236,25 @@ fn hl_lines_overlap() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=2-3 1-2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn hl_lines_multiple() {
|
||||
|
@ -209,18 +263,25 @@ fn hl_lines_multiple() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=2-3,hl_lines=1-2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -230,18 +291,25 @@ fn hl_lines_extra_spaces() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
``` hl_lines = 2 - 3 1 - 2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo\nbar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -251,19 +319,26 @@ fn hl_lines_int_and_range() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=1 3-4
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@hl "foo",
|
||||
@no "bar",
|
||||
@hl "bar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@hl "foo",
|
||||
@no "bar",
|
||||
@hl "bar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -273,22 +348,28 @@ fn hl_lines_single_line_range() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=2-2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar",
|
||||
@no "bar\nbaz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar",
|
||||
@no "bar\nbaz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn hl_lines_reverse_range() {
|
||||
let tera_ctx = Tera::default();
|
||||
|
@ -296,17 +377,24 @@ fn hl_lines_reverse_range() {
|
|||
let mut config = Config::default();
|
||||
config.highlight_code = true;
|
||||
let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, InsertAnchor::None);
|
||||
let res = render_content(r#"
|
||||
let res = render_content(
|
||||
r#"
|
||||
```hl_lines=3-2
|
||||
foo
|
||||
bar
|
||||
bar
|
||||
baz
|
||||
```
|
||||
"#, &context).unwrap();
|
||||
assert_eq!(res.body, colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar\nbar",
|
||||
@no "baz",
|
||||
));
|
||||
"#,
|
||||
&context,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res.body,
|
||||
colored_html!(
|
||||
@no "foo",
|
||||
@hl "bar\nbar",
|
||||
@no "baz",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -452,12 +452,17 @@ impl Site {
|
|||
let cfg = &Cfg { minify_js: false };
|
||||
let mut input_bytes = html.as_bytes().to_vec();
|
||||
match with_friendly_error(&mut input_bytes, cfg) {
|
||||
Ok(_len) => match std::str::from_utf8(&mut input_bytes) {
|
||||
Ok(_len) => match std::str::from_utf8(&input_bytes) {
|
||||
Ok(result) => Ok(result.to_string()),
|
||||
Err(err) => bail!("Failed to convert bytes to string : {}", err),
|
||||
},
|
||||
Err(minify_error) => {
|
||||
bail!("Failed to truncate html at character {}: {} \n {}", minify_error.position, minify_error.message, minify_error.code_context);
|
||||
bail!(
|
||||
"Failed to truncate html at character {}: {} \n {}",
|
||||
minify_error.position,
|
||||
minify_error.message,
|
||||
minify_error.code_context
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +553,7 @@ impl Site {
|
|||
let site_path =
|
||||
if filename != "index.html" { site_path.join(filename) } else { site_path };
|
||||
|
||||
&SITE_CONTENT.write().unwrap().insert(site_path, final_content);
|
||||
SITE_CONTENT.write().unwrap().insert(site_path, final_content);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,7 +768,7 @@ impl Site {
|
|||
components.push(taxonomy.kind.lang.as_ref());
|
||||
}
|
||||
|
||||
components.push(taxonomy.kind.name.as_ref());
|
||||
components.push(taxonomy.slug.as_ref());
|
||||
|
||||
let list_output =
|
||||
taxonomy.render_all_terms(&self.tera, &self.config, &self.library.read().unwrap())?;
|
||||
|
@ -793,7 +798,7 @@ impl Site {
|
|||
if taxonomy.kind.feed {
|
||||
self.render_feed(
|
||||
item.pages.iter().map(|p| library.get_page_by_key(*p)).collect(),
|
||||
Some(&PathBuf::from(format!("{}/{}", taxonomy.kind.name, item.slug))),
|
||||
Some(&PathBuf::from(format!("{}/{}", taxonomy.slug, item.slug))),
|
||||
if self.config.is_multilingual() && !taxonomy.kind.lang.is_empty() {
|
||||
&taxonomy.kind.lang
|
||||
} else {
|
||||
|
|
|
@ -154,6 +154,10 @@ fn can_build_site_without_live_reload() {
|
|||
assert_eq!(file_exists!(public, "categories/index.html"), true);
|
||||
assert_eq!(file_exists!(public, "categories/a-category/index.html"), true);
|
||||
assert_eq!(file_exists!(public, "categories/a-category/atom.xml"), true);
|
||||
// and podcast_authors (https://github.com/getzola/zola/issues/1177)
|
||||
assert_eq!(file_exists!(public, "podcast-authors/index.html"), true);
|
||||
assert_eq!(file_exists!(public, "podcast-authors/some-person/index.html"), true);
|
||||
assert_eq!(file_exists!(public, "podcast-authors/some-person/atom.xml"), true);
|
||||
// But no tags
|
||||
assert_eq!(file_exists!(public, "tags/index.html"), false);
|
||||
|
||||
|
|
|
@ -572,6 +572,7 @@ mod tests {
|
|||
let tag = TaxonomyItem::new(
|
||||
"Programming",
|
||||
&taxo_config,
|
||||
"tags",
|
||||
&config,
|
||||
vec![],
|
||||
&library.read().unwrap(),
|
||||
|
@ -579,12 +580,14 @@ mod tests {
|
|||
let tag_fr = TaxonomyItem::new(
|
||||
"Programmation",
|
||||
&taxo_config_fr,
|
||||
"tags",
|
||||
&config,
|
||||
vec![],
|
||||
&library.read().unwrap(),
|
||||
);
|
||||
let tags = Taxonomy { kind: taxo_config, items: vec![tag] };
|
||||
let tags_fr = Taxonomy { kind: taxo_config_fr, items: vec![tag_fr] };
|
||||
let tags = Taxonomy { kind: taxo_config, slug: "tags".to_string(), items: vec![tag] };
|
||||
let tags_fr =
|
||||
Taxonomy { kind: taxo_config_fr, slug: "tags".to_string(), items: vec![tag_fr] };
|
||||
|
||||
let taxonomies = vec![tags.clone(), tags_fr.clone()];
|
||||
let static_fn =
|
||||
|
@ -647,10 +650,12 @@ mod tests {
|
|||
..TaxonomyConfig::default()
|
||||
};
|
||||
let library = Library::new(0, 0, false);
|
||||
let tag = TaxonomyItem::new("Programming", &taxo_config, &config, vec![], &library);
|
||||
let tag_fr = TaxonomyItem::new("Programmation", &taxo_config_fr, &config, vec![], &library);
|
||||
let tags = Taxonomy { kind: taxo_config, items: vec![tag] };
|
||||
let tags_fr = Taxonomy { kind: taxo_config_fr, items: vec![tag_fr] };
|
||||
let tag = TaxonomyItem::new("Programming", &taxo_config, "tags", &config, vec![], &library);
|
||||
let tag_fr =
|
||||
TaxonomyItem::new("Programmation", &taxo_config_fr, "tags", &config, vec![], &library);
|
||||
let tags = Taxonomy { kind: taxo_config, slug: "tags".to_string(), items: vec![tag] };
|
||||
let tags_fr =
|
||||
Taxonomy { kind: taxo_config_fr, slug: "tags".to_string(), items: vec![tag_fr] };
|
||||
|
||||
let taxonomies = vec![tags.clone(), tags_fr.clone()];
|
||||
let static_fn =
|
||||
|
|
|
@ -94,7 +94,7 @@ async fn handle_request(req: Request<Body>, root: PathBuf) -> Result<Response<Bo
|
|||
ResolveResult::MethodNotMatched => return Ok(method_not_allowed()),
|
||||
ResolveResult::NotFound | ResolveResult::UriNotMatched => {
|
||||
let not_found_path = RelativePath::new("404.html");
|
||||
let content_404 = SITE_CONTENT.read().unwrap().get(not_found_path).map(|x| x.clone());
|
||||
let content_404 = SITE_CONTENT.read().unwrap().get(not_found_path).cloned();
|
||||
return Ok(not_found(content_404));
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -16,7 +16,7 @@ fn main() {
|
|||
"." => env::current_dir().unwrap(),
|
||||
path => PathBuf::from(path)
|
||||
.canonicalize()
|
||||
.expect(&format!("Cannot find root directory: {}", path)),
|
||||
.unwrap_or_else(|_| panic!("Cannot find root directory: {}", path)),
|
||||
};
|
||||
let config_file = match matches.value_of("config") {
|
||||
Some(path) => PathBuf::from(path),
|
||||
|
|
|
@ -4,16 +4,21 @@ highlight_code = true
|
|||
compile_sass = true
|
||||
generate_feed = true
|
||||
theme = "sample"
|
||||
slugify_paths = true
|
||||
|
||||
taxonomies = [
|
||||
{name = "categories", feed = true},
|
||||
{name = "podcast_authors", feed = true},
|
||||
]
|
||||
|
||||
extra_syntaxes = ["syntaxes"]
|
||||
|
||||
ignored_content = ["*/ignored.md"]
|
||||
|
||||
[slugify]
|
||||
paths = "on"
|
||||
taxonomies = "on"
|
||||
anchors = "on"
|
||||
|
||||
[link_checker]
|
||||
skip_prefixes = [
|
||||
"http://[2001:db8::]/",
|
||||
|
|
|
@ -5,6 +5,7 @@ date = 2017-01-01
|
|||
|
||||
[taxonomies]
|
||||
categories = ["a-category"]
|
||||
podcast_authors = ["Some Person"]
|
||||
+++
|
||||
|
||||
# A title
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{% for term in terms %}
|
||||
{{ term.name }} {{ term.slug }} {{ term.pages | length }}
|
||||
{% endfor %}
|
||||
Current path: {{ current_path }}
|
|
@ -0,0 +1,10 @@
|
|||
Category: {{ term.name }}
|
||||
|
||||
|
||||
{% for page in term.pages %}
|
||||
<article>
|
||||
<h3 class="post__title"><a href="{{ page.permalink }}">{{ page.title }}</a></h3>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
||||
Current path: {{ current_path }}
|
Loading…
Reference in New Issue