mirror of
https://github.com/getzola/zola
synced 2024-11-10 06:14:19 +00:00
Add very copy/pasty impl of anchor checking
This commit is contained in:
parent
83cf19877a
commit
0aee33f9c5
15 changed files with 326 additions and 100 deletions
|
@ -12,6 +12,7 @@
|
|||
- Fix image processing not happening if called from the template
|
||||
- Add a `zola check` command to that validates the site and checks all external links
|
||||
- Sections can have `aliases` as well
|
||||
- Anchors in internal links are now checked for existence
|
||||
|
||||
## 0.7.0 (2019-04-28)
|
||||
|
||||
|
|
95
Cargo.lock
generated
95
Cargo.lock
generated
|
@ -6,7 +6,7 @@ version = "0.7.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"actix_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -61,7 +61,7 @@ dependencies = [
|
|||
"actix 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"actix-net 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -69,7 +69,7 @@ dependencies = [
|
|||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"h2 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -177,7 +177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.26"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -216,7 +216,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -299,7 +299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -311,7 +311,7 @@ name = "cloudabi"
|
|||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -499,10 +499,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.1.2"
|
||||
version = "3.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -623,7 +623,7 @@ name = "error-chain"
|
|||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -631,7 +631,7 @@ name = "error-chain"
|
|||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -639,7 +639,7 @@ dependencies = [
|
|||
name = "errors"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tera 1.0.0-beta.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -650,7 +650,7 @@ name = "failure"
|
|||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -734,7 +734,7 @@ name = "fsevent"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -756,7 +756,7 @@ name = "fuchsia-zircon"
|
|||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -841,7 +841,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.1.21"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -852,7 +852,7 @@ dependencies = [
|
|||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -933,7 +933,7 @@ dependencies = [
|
|||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"h2 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -995,7 +995,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.21.1"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1015,7 +1015,7 @@ name = "imageproc"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"errors 0.1.0",
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1041,7 +1041,7 @@ name = "inotify"
|
|||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1366,10 +1366,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1395,7 +1395,7 @@ name = "notify"
|
|||
version = "4.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1472,7 +1472,7 @@ name = "onig"
|
|||
version = "4.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1497,7 +1497,7 @@ name = "openssl"
|
|||
version = "0.10.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1653,7 +1653,7 @@ name = "png"
|
|||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1689,7 +1689,7 @@ name = "pulldown-cmark"
|
|||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2225,8 +2225,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "string"
|
||||
version = "0.1.3"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
|
@ -2307,7 +2310,7 @@ version = "3.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2343,7 +2346,7 @@ dependencies = [
|
|||
"config 0.1.0",
|
||||
"csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"errors 0.1.0",
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"imageproc 0.1.0",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"library 0.1.0",
|
||||
|
@ -2388,7 +2391,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2457,7 +2460,7 @@ dependencies = [
|
|||
"tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2539,7 +2542,7 @@ dependencies = [
|
|||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2560,7 +2563,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-sync"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3070,14 +3073,14 @@ dependencies = [
|
|||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctrlc 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"errors 0.1.0",
|
||||
"front_matter 0.1.0",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rebuild 0.1.0",
|
||||
"site 0.1.0",
|
||||
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utils 0.1.0",
|
||||
|
@ -3097,11 +3100,11 @@ dependencies = [
|
|||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
|
||||
"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b"
|
||||
"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
"checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
|
||||
"checksum bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59604ece62a407dc9164732e5adea02467898954c3a5811fd2dc140af14ef15b"
|
||||
|
@ -3132,7 +3135,7 @@ dependencies = [
|
|||
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
|
||||
"checksum csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9044e25afb0924b5a5fc5511689b0918629e85d68ea591e5e87fbf1e85ea1b3b"
|
||||
"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
|
||||
"checksum ctrlc 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5531b7f0698d9220b4729f8811931dbe0e91a05be2f7b3245fdc50dd856bae26"
|
||||
"checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f"
|
||||
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
||||
"checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
|
||||
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
|
||||
|
@ -3172,7 +3175,7 @@ dependencies = [
|
|||
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
|
||||
"checksum globwalk 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53cbcf0368596897b0a3b8ff2110acf2400e80ffad4ca9238b52ff282a9b267b"
|
||||
"checksum h2 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "876d91114d78abbde2e1910e3b2d9d0fd1d89b769e20816dfb68d77992cf4158"
|
||||
"checksum h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "1e42e3daed5a7e17b12a0c23b5b2fbff23a925a570938ebee4baca1a9a1a2240"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
|
||||
"checksum html5ever 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce65ac8028cf5a287a7dbf6c4e0a6cf2dcf022ed5b167a81bae66ebf599a8b7"
|
||||
|
@ -3185,7 +3188,7 @@ dependencies = [
|
|||
"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f"
|
||||
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
|
||||
"checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002"
|
||||
"checksum image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116"
|
||||
"checksum image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "99198e595d012efccf12abf4abc08da2d97be0b0355a2b08d101347527476ba4"
|
||||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
|
||||
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
|
||||
|
@ -3223,7 +3226,7 @@ dependencies = [
|
|||
"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
|
||||
"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b"
|
||||
"checksum nix 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d10caafde29a846a82ae0af70414e4643e072993441033b2c93217957e2f867"
|
||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
"checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943"
|
||||
|
@ -3312,7 +3315,7 @@ dependencies = [
|
|||
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
|
||||
"checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b"
|
||||
"checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995"
|
||||
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
|
||||
"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
|
||||
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
|
||||
|
@ -3325,7 +3328,7 @@ dependencies = [
|
|||
"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef"
|
||||
"checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
|
||||
"checksum tera 1.0.0-beta.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ce487c4707b73b38d186115f82bba243714cb5b8fc5315f2fbfeaee5d159ee8"
|
||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
|
||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
|
@ -3340,7 +3343,7 @@ dependencies = [
|
|||
"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926"
|
||||
"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce"
|
||||
"checksum tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd6dc5276ea05ce379a16de90083ec80836440d5ef8a6a39545a3207373b8296"
|
||||
"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a"
|
||||
"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7"
|
||||
"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119"
|
||||
"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2"
|
||||
"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e"
|
||||
|
|
|
@ -7,3 +7,94 @@ pub use self::file_info::FileInfo;
|
|||
pub use self::page::Page;
|
||||
pub use self::section::Section;
|
||||
pub use self::ser::{SerializingPage, SerializingSection};
|
||||
|
||||
use rendering::Header;
|
||||
|
||||
pub fn has_anchor(headings: &[Header], anchor: &str) -> bool {
|
||||
for heading in headings {
|
||||
if heading.id == anchor {
|
||||
return true;
|
||||
}
|
||||
if has_anchor(&heading.children, anchor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_find_anchor_at_root() {
|
||||
let input = vec![
|
||||
Header {
|
||||
level: 1,
|
||||
id: "1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
Header {
|
||||
level: 2,
|
||||
id: "1-1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
Header {
|
||||
level: 3,
|
||||
id: "1-1-1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
Header {
|
||||
level: 2,
|
||||
id: "1-2".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
];
|
||||
|
||||
assert!(has_anchor(&input, "1-2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_find_anchor_in_children() {
|
||||
let input = vec![Header {
|
||||
level: 1,
|
||||
id: "1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![
|
||||
Header {
|
||||
level: 2,
|
||||
id: "1-1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
Header {
|
||||
level: 3,
|
||||
id: "1-1-1".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
Header {
|
||||
level: 2,
|
||||
id: "1-2".to_string(),
|
||||
permalink: String::new(),
|
||||
title: String::new(),
|
||||
children: vec![],
|
||||
},
|
||||
],
|
||||
}];
|
||||
|
||||
assert!(has_anchor(&input, "1-2"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use utils::site::get_reading_analytics;
|
|||
use utils::templates::render_template;
|
||||
|
||||
use content::file_info::FileInfo;
|
||||
use content::has_anchor;
|
||||
use content::ser::SerializingPage;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -76,6 +77,11 @@ pub struct Page {
|
|||
pub lang: String,
|
||||
/// Contains all the translated version of that page
|
||||
pub translations: Vec<Key>,
|
||||
/// Contains the internal links that have an anchor: we can only check the anchor
|
||||
/// after all pages have been built and their ToC compiled. The page itself should exist otherwise
|
||||
/// it would have errored before getting there
|
||||
/// (path to markdown, anchor value)
|
||||
pub internal_links_with_anchors: Vec<(String, String)>,
|
||||
/// Contains the external links that need to be checked
|
||||
pub external_links: Vec<String>,
|
||||
}
|
||||
|
@ -106,6 +112,7 @@ impl Page {
|
|||
reading_time: None,
|
||||
lang: String::new(),
|
||||
translations: Vec::new(),
|
||||
internal_links_with_anchors: Vec::new(),
|
||||
external_links: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +274,7 @@ impl Page {
|
|||
self.content = res.body;
|
||||
self.toc = res.toc;
|
||||
self.external_links = res.external_links;
|
||||
self.internal_links_with_anchors = res.internal_links_with_anchors;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -313,6 +321,10 @@ impl Page {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn has_anchor(&self, anchor: &str) -> bool {
|
||||
has_anchor(&self.toc, anchor)
|
||||
}
|
||||
|
||||
pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializingPage<'a> {
|
||||
SerializingPage::from_page(self, library)
|
||||
}
|
||||
|
@ -346,6 +358,7 @@ impl Default for Page {
|
|||
reading_time: None,
|
||||
lang: String::new(),
|
||||
translations: Vec::new(),
|
||||
internal_links_with_anchors: Vec::new(),
|
||||
external_links: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use utils::site::get_reading_analytics;
|
|||
use utils::templates::render_template;
|
||||
|
||||
use content::file_info::FileInfo;
|
||||
use content::has_anchor;
|
||||
use content::ser::SerializingSection;
|
||||
use library::Library;
|
||||
|
||||
|
@ -56,6 +57,11 @@ pub struct Section {
|
|||
pub lang: String,
|
||||
/// Contains all the translated version of that section
|
||||
pub translations: Vec<Key>,
|
||||
/// Contains the internal links that have an anchor: we can only check the anchor
|
||||
/// after all pages have been built and their ToC compiled. The page itself should exist otherwise
|
||||
/// it would have errored before getting there
|
||||
/// (path to markdown, anchor value)
|
||||
pub internal_links_with_anchors: Vec<(String, String)>,
|
||||
/// Contains the external links that need to be checked
|
||||
pub external_links: Vec<String>,
|
||||
}
|
||||
|
@ -87,6 +93,7 @@ impl Section {
|
|||
reading_time: None,
|
||||
lang: String::new(),
|
||||
translations: Vec::new(),
|
||||
internal_links_with_anchors: Vec::new(),
|
||||
external_links: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +200,7 @@ impl Section {
|
|||
self.content = res.body;
|
||||
self.toc = res.toc;
|
||||
self.external_links = res.external_links;
|
||||
self.internal_links_with_anchors = res.internal_links_with_anchors;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -229,6 +237,10 @@ impl Section {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn has_anchor(&self, anchor: &str) -> bool {
|
||||
has_anchor(&self.toc, anchor)
|
||||
}
|
||||
|
||||
pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializingSection<'a> {
|
||||
SerializingSection::from_section(self, library)
|
||||
}
|
||||
|
@ -260,6 +272,7 @@ impl Default for Section {
|
|||
word_count: None,
|
||||
lang: String::new(),
|
||||
translations: Vec::new(),
|
||||
internal_links_with_anchors: Vec::new(),
|
||||
external_links: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
tera = { version = "1.0.0-alpha.3", features = ["preserve_order"] }
|
||||
tera = { version = "1.0.0-beta.8", features = ["preserve_order"] }
|
||||
syntect = "3"
|
||||
pulldown-cmark = "0.5"
|
||||
slug = "0.1"
|
||||
|
|
|
@ -24,6 +24,7 @@ pub struct Rendered {
|
|||
pub body: String,
|
||||
pub summary_len: Option<usize>,
|
||||
pub toc: Vec<Header>,
|
||||
pub internal_links_with_anchors: Vec<(String, String)>,
|
||||
pub external_links: Vec<String>,
|
||||
}
|
||||
|
||||
|
@ -70,6 +71,7 @@ fn fix_link(
|
|||
link_type: LinkType,
|
||||
link: &str,
|
||||
context: &RenderContext,
|
||||
internal_links_with_anchors: &mut Vec<(String, String)>,
|
||||
external_links: &mut Vec<String>,
|
||||
) -> Result<String> {
|
||||
if link_type == LinkType::Email {
|
||||
|
@ -81,7 +83,13 @@ fn fix_link(
|
|||
// - it could be a normal link
|
||||
let result = if link.starts_with("@/") {
|
||||
match resolve_internal_link(&link, context.permalinks) {
|
||||
Ok(url) => url,
|
||||
Ok(resolved) => {
|
||||
if resolved.anchor.is_some() {
|
||||
internal_links_with_anchors
|
||||
.push((resolved.md_path.unwrap(), resolved.anchor.unwrap()));
|
||||
}
|
||||
resolved.permalink
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(format!("Relative link {} not found.", link).into());
|
||||
}
|
||||
|
@ -141,6 +149,7 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<Render
|
|||
|
||||
let mut inserted_anchors: Vec<String> = vec![];
|
||||
let mut headers: Vec<Header> = vec![];
|
||||
let mut internal_links_with_anchors = Vec::new();
|
||||
let mut external_links = Vec::new();
|
||||
|
||||
let mut opts = Options::empty();
|
||||
|
@ -207,14 +216,19 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<Render
|
|||
Event::Start(Tag::Image(link_type, src, title))
|
||||
}
|
||||
Event::Start(Tag::Link(link_type, link, title)) => {
|
||||
let fixed_link =
|
||||
match fix_link(link_type, &link, context, &mut external_links) {
|
||||
Ok(fixed_link) => fixed_link,
|
||||
Err(err) => {
|
||||
error = Some(err);
|
||||
return Event::Html("".into());
|
||||
}
|
||||
};
|
||||
let fixed_link = match fix_link(
|
||||
link_type,
|
||||
&link,
|
||||
context,
|
||||
&mut internal_links_with_anchors,
|
||||
&mut external_links,
|
||||
) {
|
||||
Ok(fixed_link) => fixed_link,
|
||||
Err(err) => {
|
||||
error = Some(err);
|
||||
return Event::Html("".into());
|
||||
}
|
||||
};
|
||||
|
||||
Event::Start(Tag::Link(link_type, fixed_link.into(), title))
|
||||
}
|
||||
|
@ -303,6 +317,7 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<Render
|
|||
summary_len: if has_summary { html.find(CONTINUE_READING) } else { None },
|
||||
body: html,
|
||||
toc: make_table_of_contents(headers),
|
||||
internal_links_with_anchors,
|
||||
external_links,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -244,6 +244,9 @@ impl Site {
|
|||
self.render_markdown()?;
|
||||
self.register_tera_global_fns();
|
||||
|
||||
// Needs to be done after rendering markdown as we only get the anchors at that point
|
||||
self.check_internal_links_with_anchors()?;
|
||||
|
||||
if self.config.check_external_links {
|
||||
self.check_external_links()?;
|
||||
}
|
||||
|
@ -251,6 +254,78 @@ impl Site {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Very similar to check_external_links but can't be merged as far as I can see since we always
|
||||
/// want to check the internal links but only the external in zola check :/
|
||||
pub fn check_internal_links_with_anchors(&self) -> Result<()> {
|
||||
let library = self.library.write().expect("Get lock for check_internal_links_with_anchors");
|
||||
let page_links = library
|
||||
.pages()
|
||||
.values()
|
||||
.map(|p| {
|
||||
let path = &p.file.path;
|
||||
p.internal_links_with_anchors.iter().map(move |l| (path.clone(), l))
|
||||
})
|
||||
.flatten();
|
||||
let section_links = library
|
||||
.sections()
|
||||
.values()
|
||||
.map(|p| {
|
||||
let path = &p.file.path;
|
||||
p.internal_links_with_anchors.iter().map(move |l| (path.clone(), l))
|
||||
})
|
||||
.flatten();
|
||||
let all_links = page_links.chain(section_links).collect::<Vec<_>>();
|
||||
let mut full_path = self.base_path.clone();
|
||||
full_path.push("content");
|
||||
|
||||
let errors: Vec<_> = all_links
|
||||
.iter()
|
||||
.filter_map(|(page_path, (md_path, anchor))| {
|
||||
// There are a few `expect` here since the presence of the .md file will
|
||||
// already have been checked in the markdown rendering
|
||||
let mut p = full_path.clone();
|
||||
for part in md_path.split('/') {
|
||||
p.push(part);
|
||||
}
|
||||
if md_path.contains("_index.md") {
|
||||
let section = library
|
||||
.get_section(&p)
|
||||
.expect("Couldn't find section in check_internal_links_with_anchors");
|
||||
if section.has_anchor(&anchor) {
|
||||
None
|
||||
} else {
|
||||
Some((page_path, md_path, anchor))
|
||||
}
|
||||
} else {
|
||||
let page = library
|
||||
.get_page(&p)
|
||||
.expect("Couldn't find section in check_internal_links_with_anchors");
|
||||
if page.has_anchor(&anchor) {
|
||||
None
|
||||
} else {
|
||||
Some((page_path, md_path, anchor))
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
if errors.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let msg = errors
|
||||
.into_iter()
|
||||
.map(|(page_path, md_path, anchor)| {
|
||||
format!(
|
||||
"The anchor in the link `@/{}#{}` in {} does not exist.",
|
||||
md_path,
|
||||
anchor,
|
||||
page_path.to_string_lossy(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
Err(Error { kind: ErrorKind::Msg(msg.into()), source: None })
|
||||
}
|
||||
|
||||
pub fn check_external_links(&self) -> Result<()> {
|
||||
let library = self.library.write().expect("Get lock for check_external_links");
|
||||
let page_links = library
|
||||
|
@ -282,34 +357,33 @@ impl Site {
|
|||
let errors: Vec<_> = pool.install(|| {
|
||||
all_links
|
||||
.par_iter()
|
||||
.filter_map(|(path, link)| {
|
||||
.filter_map(|(page_path, link)| {
|
||||
let res = check_url(&link);
|
||||
if res.is_valid() {
|
||||
None
|
||||
} else {
|
||||
Some((path, link, res))
|
||||
Some((page_path, link, res))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
let msg = errors
|
||||
.into_iter()
|
||||
.map(|(path, link, check_res)| {
|
||||
format!(
|
||||
"Dead link in {} to {}: {}",
|
||||
path.to_string_lossy(),
|
||||
link,
|
||||
check_res.message()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
Err(Error { kind: ErrorKind::Msg(msg.into()), source: None })
|
||||
return Ok(());
|
||||
}
|
||||
let msg = errors
|
||||
.into_iter()
|
||||
.map(|(page_path, link, check_res)| {
|
||||
format!(
|
||||
"Dead link in {} to {}: {}",
|
||||
page_path.to_string_lossy(),
|
||||
link,
|
||||
check_res.message()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
Err(Error { kind: ErrorKind::Msg(msg.into()), source: None })
|
||||
}
|
||||
|
||||
/// Insert a default index section for each language if necessary so we don't need to create
|
||||
|
|
|
@ -64,7 +64,7 @@ impl TeraFn for GetUrl {
|
|||
);
|
||||
if path.starts_with("@/") {
|
||||
match resolve_internal_link(&path, &self.permalinks) {
|
||||
Ok(url) => Ok(to_value(url).unwrap()),
|
||||
Ok(resolved) => Ok(to_value(resolved.permalink).unwrap()),
|
||||
Err(_) => {
|
||||
Err(format!("Could not resolve URL for link `{}` not found.", path).into())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
|
|||
|
||||
[dependencies]
|
||||
errors = { path = "../errors" }
|
||||
tera = "1.0.0-alpha.3"
|
||||
tera = "1.0.0-beta.8"
|
||||
unicode-segmentation = "1.2"
|
||||
walkdir = "2"
|
||||
toml = "0.4"
|
||||
|
|
|
@ -77,7 +77,7 @@ pub fn read_file_with_error(path: &Path, message: &str) -> Result<String> {
|
|||
pub fn find_related_assets(path: &Path) -> Vec<PathBuf> {
|
||||
let mut assets = vec![];
|
||||
|
||||
for entry in read_dir(path).unwrap().filter_map(|e| e.ok()) {
|
||||
for entry in read_dir(path).unwrap().filter_map(std::result::Result::ok) {
|
||||
let entry_path = entry.path();
|
||||
if entry_path.is_file() {
|
||||
match entry_path.extension() {
|
||||
|
@ -108,7 +108,7 @@ pub fn copy_file(src: &Path, dest: &PathBuf, base_path: &PathBuf) -> Result<()>
|
|||
}
|
||||
|
||||
pub fn copy_directory(src: &PathBuf, dest: &PathBuf) -> Result<()> {
|
||||
for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) {
|
||||
for entry in WalkDir::new(src).into_iter().filter_map(std::result::Result::ok) {
|
||||
let relative_path = entry.path().strip_prefix(src).unwrap();
|
||||
let target_path = dest.join(relative_path);
|
||||
|
||||
|
|
|
@ -5,8 +5,5 @@ pub fn get_available_port(avoid: u16) -> Option<u16> {
|
|||
}
|
||||
|
||||
pub fn port_is_available(port: u16) -> bool {
|
||||
match TcpListener::bind(("127.0.0.1", port)) {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
TcpListener::bind(("127.0.0.1", port)).is_ok()
|
||||
}
|
||||
|
|
|
@ -12,8 +12,21 @@ pub fn get_reading_analytics(content: &str) -> (usize, usize) {
|
|||
(word_count, (word_count / 200))
|
||||
}
|
||||
|
||||
/// Resolves an internal link (of the `./posts/something.md#hey` sort) to its absolute link
|
||||
pub fn resolve_internal_link(link: &str, permalinks: &HashMap<String, String>) -> Result<String> {
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ResolvedInternalLink {
|
||||
pub permalink: String,
|
||||
// The 2 fields below are only set when there is an anchor
|
||||
// as we will need that to check if it exists after the markdown rendering is done
|
||||
pub md_path: Option<String>,
|
||||
pub anchor: Option<String>,
|
||||
}
|
||||
|
||||
/// Resolves an internal link (of the `@/posts/something.md#hey` sort) to its absolute link and
|
||||
/// returns the path + anchor as well
|
||||
pub fn resolve_internal_link(
|
||||
link: &str,
|
||||
permalinks: &HashMap<String, String>,
|
||||
) -> Result<ResolvedInternalLink> {
|
||||
// First we remove the ./ since that's zola specific
|
||||
let clean_link = link.replacen("@/", "", 1);
|
||||
// Then we remove any potential anchor
|
||||
|
@ -22,9 +35,13 @@ pub fn resolve_internal_link(link: &str, permalinks: &HashMap<String, String>) -
|
|||
match permalinks.get(parts[0]) {
|
||||
Some(p) => {
|
||||
if parts.len() > 1 {
|
||||
Ok(format!("{}#{}", p, parts[1]))
|
||||
Ok(ResolvedInternalLink {
|
||||
permalink: format!("{}#{}", p, parts[1]),
|
||||
md_path: Some(parts[0].to_string()),
|
||||
anchor: Some(parts[1].to_string()),
|
||||
})
|
||||
} else {
|
||||
Ok(p.to_string())
|
||||
Ok(ResolvedInternalLink { permalink: p.to_string(), md_path: None, anchor: None })
|
||||
}
|
||||
}
|
||||
None => bail!(format!("Relative link {} not found.", link)),
|
||||
|
@ -42,7 +59,7 @@ mod tests {
|
|||
let mut permalinks = HashMap::new();
|
||||
permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
|
||||
let res = resolve_internal_link("@/pages/about.md", &permalinks).unwrap();
|
||||
assert_eq!(res, "https://vincent.is/about");
|
||||
assert_eq!(res.permalink, "https://vincent.is/about");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -50,7 +67,7 @@ mod tests {
|
|||
let mut permalinks = HashMap::new();
|
||||
permalinks.insert("about.md".to_string(), "https://vincent.is/about".to_string());
|
||||
let res = resolve_internal_link("@/about.md", &permalinks).unwrap();
|
||||
assert_eq!(res, "https://vincent.is/about");
|
||||
assert_eq!(res.permalink, "https://vincent.is/about");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -58,7 +75,9 @@ mod tests {
|
|||
let mut permalinks = HashMap::new();
|
||||
permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
|
||||
let res = resolve_internal_link("@/pages/about.md#hello", &permalinks).unwrap();
|
||||
assert_eq!(res, "https://vincent.is/about#hello");
|
||||
assert_eq!(res.permalink, "https://vincent.is/about#hello");
|
||||
assert_eq!(res.md_path, Some("pages/about.md".to_string()));
|
||||
assert_eq!(res.anchor, Some("hello".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -11,7 +11,7 @@ macro_rules! render_default_tpl {
|
|||
let mut context = Context::new();
|
||||
context.insert("filename", $filename);
|
||||
context.insert("url", $url);
|
||||
Tera::one_off(DEFAULT_TPL, context, true).map_err(|e| e.into())
|
||||
Tera::one_off(DEFAULT_TPL, context, true).map_err(std::convert::Into::into)
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -27,21 +27,21 @@ pub fn render_template(
|
|||
) -> Result<String> {
|
||||
// check if it is in the templates
|
||||
if tera.templates.contains_key(name) {
|
||||
return tera.render(name, context).map_err(|e| e.into());
|
||||
return tera.render(name, context).map_err(std::convert::Into::into);
|
||||
}
|
||||
|
||||
// check if it is part of a theme
|
||||
if let Some(ref t) = *theme {
|
||||
let theme_template_name = format!("{}/templates/{}", t, name);
|
||||
if tera.templates.contains_key(&theme_template_name) {
|
||||
return tera.render(&theme_template_name, context).map_err(|e| e.into());
|
||||
return tera.render(&theme_template_name, context).map_err(std::convert::Into::into);
|
||||
}
|
||||
}
|
||||
|
||||
// check if it is part of ZOLA_TERA defaults
|
||||
let default_name = format!("__zola_builtins/{}", name);
|
||||
if tera.templates.contains_key(&default_name) {
|
||||
return tera.render(&default_name, context).map_err(|e| e.into());
|
||||
return tera.render(&default_name, context).map_err(std::convert::Into::into);
|
||||
}
|
||||
|
||||
// maybe it's a default one?
|
||||
|
|
|
@ -3,9 +3,9 @@ title = "Internal links & deep linking"
|
|||
weight = 50
|
||||
+++
|
||||
|
||||
## Header id and anchor insertion
|
||||
While rendering the markdown content, a unique id will automatically be assigned to each header. This id is created
|
||||
by converting the header text to a [slug](https://en.wikipedia.org/wiki/Semantic_URL#Slug), appending numbers at the end
|
||||
## Heading id and anchor insertion
|
||||
While rendering the markdown content, a unique id will automatically be assigned to each heading. This id is created
|
||||
by converting the heading text to a [slug](https://en.wikipedia.org/wiki/Semantic_URL#Slug), appending numbers at the end
|
||||
if the slug already exists for that article. For example:
|
||||
|
||||
```md
|
||||
|
@ -16,16 +16,16 @@ if the slug already exists for that article. For example:
|
|||
## Example code <- example-code-1
|
||||
```
|
||||
|
||||
You can also manually specify an id with a `{#…}` suffix on the header line:
|
||||
You can also manually specify an id with a `{#…}` suffix on the heading line:
|
||||
|
||||
```md
|
||||
# Something manual! {#manual}
|
||||
```
|
||||
|
||||
This is useful for making deep links robust, either proactively (so that you can later change the text of a header without breaking links to it) or retroactively (keeping the slug of the old header text, when changing the text). It can also be useful for migration of existing sites with different header id schemes, so that you can keep deep links working.
|
||||
This is useful for making deep links robust, either proactively (so that you can later change the text of a heading without breaking links to it) or retroactively (keeping the slug of the old header text, when changing the text). It can also be useful for migration of existing sites with different header id schemes, so that you can keep deep links working.
|
||||
|
||||
## Anchor insertion
|
||||
It is possible to have Zola automatically insert anchor links next to the header, as you can see on the site you are currently
|
||||
It is possible to have Zola automatically insert anchor links next to the heading, as you can see on the site you are currently
|
||||
reading if you hover a title.
|
||||
|
||||
This option is set at the section level: the `insert_anchor_links` variable on the
|
||||
|
@ -36,9 +36,9 @@ If you want to change the anchor template, it can easily be overwritten by
|
|||
creating a `anchor-link.html` file in the `templates` directory.
|
||||
|
||||
## Internal links
|
||||
Linking to other pages and their headers is so common that Zola adds a
|
||||
Linking to other pages and their headings is so common that Zola adds a
|
||||
special syntax to Markdown links to handle them: start the link with `@/` and point to the `.md` file you want
|
||||
to link to. The path to the file starts from the `content` directory.
|
||||
|
||||
For example, linking to a file located at `content/pages/about.md` would be `[my link](@/pages/about.md)`.
|
||||
You can still link to a header directly: `[my link](@/pages/about.md#example)` will work as expected.
|
||||
You can still link to an anchor directly: `[my link](@/pages/about.md#example)` will work as expected.
|
||||
|
|
Loading…
Reference in a new issue