Skip to content

Commit ceb9bc8

Browse files
committed
Optionally do not slugify paths (#875)
* maybe_slugify() only does simple sanitation if config.slugify is false * slugify is disabled by default, turn on for backwards-compatibility * First docs changes for optional slugification * Remove # from slugs but not & * Add/fix tests for utf8 slugs * Fix test sites for i18n slugs * fix templates tests for i18n slugs * Rename slugify setting to slugify_paths * Default slugify_paths * Update documentation for slugify_paths * quasi_slugify removes ?, /, # and newlines * Remove forbidden NTFS chars in quasi_slugify() * Slugification forbidden chars can be configured * Remove trailing dot/space in quasi_slugify * Fix NTFS path sanitation * Revert configurable slugification charset * Remove \r for windows newlines and \t tabulations in quasi_slugify() * Update docs for output paths * Replace slugify with slugify_paths * Fix test * Default to not slugifying * Move slugs utils to utils crate * Use slugify_paths for anchors as well
1 parent 0a0b6a3 commit ceb9bc8

File tree

21 files changed

+515
-39
lines changed

21 files changed

+515
-39
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ stage
2525

2626
# nixos dependencies snippet
2727
shell.nix
28+
# vim temporary files
29+
**/.*.sw*

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
### Breaking
66
- Remove `toc` variable in section/page context and pass it to `page.toc` and `section.toc` instead so they are
77
accessible everywhere
8+
- [Slugification](https://en.wikipedia.org/wiki/Slug_(web_publishing)#Slug) of page paths is now optional. By default, every path will be slugified as it is happening right now.
9+
To keep non-ASCII characters, set `slugify_paths = true` in your config.
810

911
### Other
1012
- Add zenburn syntax highlighting theme

Cargo.lock

Lines changed: 7 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/config/src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ pub struct Config {
130130
/// key into different language.
131131
translations: HashMap<String, TranslateTerm>,
132132

133+
/// Whether to slugify page and taxonomy URLs (disable for UTF-8 URLs)
134+
pub slugify_paths: bool,
133135
/// Whether to highlight all code blocks found in markdown files. Defaults to false
134136
pub highlight_code: bool,
135137
/// Which themes to use for code highlighting. See Readme for supported themes
@@ -354,6 +356,7 @@ impl Default for Config {
354356
title: None,
355357
description: None,
356358
theme: None,
359+
slugify_paths: true,
357360
highlight_code: false,
358361
highlight_theme: "base16-ocean-dark".to_string(),
359362
default_language: "en".to_string(),

components/library/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ chrono = { version = "0.4", features = ["serde"] }
1010
tera = "1"
1111
serde = "1"
1212
serde_derive = "1"
13-
slug = "0.1"
1413
regex = "1"
1514
lazy_static = "1"
1615

components/library/src/content/page.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::path::{Path, PathBuf};
44

55
use regex::Regex;
66
use slotmap::DefaultKey;
7-
use slug::slugify;
87
use tera::{Context as TeraContext, Tera};
98

109
use config::Config;
@@ -19,6 +18,7 @@ use utils::templates::render_template;
1918
use content::file_info::FileInfo;
2019
use content::has_anchor;
2120
use content::ser::SerializingPage;
21+
use utils::slugs::maybe_slugify_paths;
2222

2323
lazy_static! {
2424
// Based on https://regex101.com/r/H2n38Z/1/tests
@@ -160,21 +160,21 @@ impl Page {
160160

161161
page.slug = {
162162
if let Some(ref slug) = page.meta.slug {
163-
slugify(&slug.trim())
163+
maybe_slugify_paths(&slug.trim(), config.slugify_paths)
164164
} else if page.file.name == "index" {
165165
if let Some(parent) = page.file.path.parent() {
166166
if let Some(slug) = slug_from_dated_filename {
167-
slugify(&slug)
167+
maybe_slugify_paths(&slug, config.slugify_paths)
168168
} else {
169-
slugify(parent.file_name().unwrap().to_str().unwrap())
169+
maybe_slugify_paths(parent.file_name().unwrap().to_str().unwrap(), config.slugify_paths)
170170
}
171171
} else {
172-
slugify(&page.file.name)
172+
maybe_slugify_paths(&page.file.name, config.slugify_paths)
173173
}
174174
} else if let Some(slug) = slug_from_dated_filename {
175-
slugify(&slug)
175+
maybe_slugify_paths(&slug, config.slugify_paths)
176176
} else {
177-
slugify(&page.file.name)
177+
maybe_slugify_paths(&page.file.name, config.slugify_paths)
178178
}
179179
};
180180

@@ -443,7 +443,8 @@ Hello world"#;
443443
slug = "hello-&-world"
444444
+++
445445
Hello world"#;
446-
let config = Config::default();
446+
let mut config = Config::default();
447+
config.slugify_paths = true;
447448
let res = Page::parse(Path::new("start.md"), content, &config, &PathBuf::new());
448449
assert!(res.is_ok());
449450
let page = res.unwrap();
@@ -452,6 +453,23 @@ Hello world"#;
452453
assert_eq!(page.permalink, config.make_permalink("hello-world"));
453454
}
454455

456+
#[test]
457+
fn can_make_url_from_utf8_slug_frontmatter() {
458+
let content = r#"
459+
+++
460+
slug = "日本"
461+
+++
462+
Hello world"#;
463+
let mut config = Config::default();
464+
config.slugify_paths = false;
465+
let res = Page::parse(Path::new("start.md"), content, &config, &PathBuf::new());
466+
assert!(res.is_ok());
467+
let page = res.unwrap();
468+
assert_eq!(page.path, "日本/");
469+
assert_eq!(page.components, vec!["日本"]);
470+
assert_eq!(page.permalink, config.make_permalink("日本"));
471+
}
472+
455473
#[test]
456474
fn can_make_url_from_path() {
457475
let content = r#"
@@ -508,7 +526,8 @@ Hello world"#;
508526

509527
#[test]
510528
fn can_make_slug_from_non_slug_filename() {
511-
let config = Config::default();
529+
let mut config = Config::default();
530+
config.slugify_paths = true;
512531
let res =
513532
Page::parse(Path::new(" file with space.md"), "+++\n+++", &config, &PathBuf::new());
514533
assert!(res.is_ok());
@@ -517,6 +536,17 @@ Hello world"#;
517536
assert_eq!(page.permalink, config.make_permalink(&page.slug));
518537
}
519538

539+
#[test]
540+
fn can_make_path_from_utf8_filename() {
541+
let mut config = Config::default();
542+
config.slugify_paths = false;
543+
let res = Page::parse(Path::new("日本.md"), "+++\n++++", &config, &PathBuf::new());
544+
assert!(res.is_ok());
545+
let page = res.unwrap();
546+
assert_eq!(page.slug, "日本");
547+
assert_eq!(page.permalink, config.make_permalink(&page.slug));
548+
}
549+
520550
#[test]
521551
fn can_specify_summary() {
522552
let config = Config::default();

components/library/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
extern crate serde;
2-
extern crate slug;
32
extern crate tera;
43
#[macro_use]
54
extern crate serde_derive;

0 commit comments

Comments
 (0)