Compare commits
10 commits
beb753bd39
...
5c454c0233
Author | SHA1 | Date | |
---|---|---|---|
5c454c0233 | |||
Jan-Erik Rediger | 61c9ab5ee4 | ||
Jan-Erik Rediger | d703e66df1 | ||
Jan-Erik Rediger | febe468843 | ||
Jan-Erik Rediger | 7aaed9865b | ||
Jan-Erik Rediger | 8faae2a1bb | ||
113362a944 | |||
e897dbffcc | |||
a6280bf91f | |||
3f9ceee047 |
|
@ -1,3 +1,12 @@
|
||||||
|
# v0.14.1 (2023-08-05)
|
||||||
|
|
||||||
|
* Upgrade mdbook and downgrade toml
|
||||||
|
|
||||||
|
# v0.14.0 (2023-08-02)
|
||||||
|
|
||||||
|
* Use custom header IDs if present
|
||||||
|
* Upgrade dependencies
|
||||||
|
|
||||||
# v0.13.0 (2023-07-18)
|
# v0.13.0 (2023-07-18)
|
||||||
|
|
||||||
* Upgrade dependencies
|
* Upgrade dependencies
|
||||||
|
|
649
Cargo.lock
generated
649
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
18
Cargo.toml
18
Cargo.toml
|
@ -1,22 +1,22 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mdbook-toc"
|
name = "mdbook-toc"
|
||||||
version = "0.13.0"
|
version = "0.14.1"
|
||||||
authors = ["Jan-Erik Rediger <janerik@fnordig.de>"]
|
authors = ["Jan-Erik Rediger <janerik@fnordig.de>"]
|
||||||
description = "mdbook preprocessor to add Table of Contents"
|
description = "mdbook preprocessor to add Table of Contents"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
homepage = "https://github.com/badboy/mdbook-toc"
|
homepage = "https://github.com/badboy/mdbook-toc"
|
||||||
repository = "https://github.com/badboy/mdbook-toc"
|
repository = "https://github.com/badboy/mdbook-toc"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
rust-version = "1.58"
|
rust-version = "1.66"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mdbook = "0.4.32"
|
mdbook = "0.4.33"
|
||||||
pulldown-cmark = "0.9.1"
|
pulldown-cmark = "0.9.3"
|
||||||
log = "0.4.11"
|
log = "0.4.19"
|
||||||
clap = { version = "4.0.29", features = ["cargo"] }
|
clap = { version = "4.3.19", features = ["cargo", "derive"] }
|
||||||
serde_json = "1.0.57"
|
serde_json = "1.0.104"
|
||||||
toml = "0.7.6"
|
toml = "0.5.11"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1.0.0"
|
pretty_assertions = "1.4.0"
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
|
|
94
flake.lock
Normal file
94
flake.lock
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1692799911,
|
||||||
|
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"naersk": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1692351612,
|
||||||
|
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1692808169,
|
||||||
|
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1692808169,
|
||||||
|
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"naersk": "naersk",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
29
flake.nix
Normal file
29
flake.nix
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
naersk.url = "github:nix-community/naersk";
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, flake-utils, naersk, nixpkgs }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = (import nixpkgs) {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
|
||||||
|
naersk' = pkgs.callPackage naersk {};
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
# For `nix build` & `nix run`:
|
||||||
|
defaultPackage = naersk'.buildPackage {
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
|
|
||||||
|
# For `nix develop`:
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = with pkgs; [ rustc cargo ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ extern crate mdbook;
|
||||||
extern crate mdbook_toc;
|
extern crate mdbook_toc;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use clap::{crate_version, Arg, ArgMatches, Command};
|
use clap::{Parser, Subcommand};
|
||||||
use mdbook::errors::Error;
|
use mdbook::errors::Error;
|
||||||
use mdbook::preprocess::{CmdPreprocessor, Preprocessor};
|
use mdbook::preprocess::{CmdPreprocessor, Preprocessor};
|
||||||
use mdbook_toc::Toc;
|
use mdbook_toc::Toc;
|
||||||
|
@ -11,22 +11,24 @@ use mdbook_toc::Toc;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
pub fn make_app() -> Command {
|
#[derive(Parser)]
|
||||||
Command::new("mdbook-toc")
|
#[command(about, version)]
|
||||||
.version(crate_version!())
|
struct App {
|
||||||
.about("mdbook preprocessor to add Table of Contents")
|
#[command(subcommand)]
|
||||||
.subcommand(
|
cmd: Option<Cmd>,
|
||||||
Command::new("supports")
|
}
|
||||||
.arg(Arg::new("renderer").required(true))
|
|
||||||
.about("Check whether a renderer is supported by this preprocessor"),
|
#[derive(Subcommand)]
|
||||||
)
|
enum Cmd {
|
||||||
|
/// Check whether a renderer is supported by this preprocessor
|
||||||
|
Supports { renderer: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = make_app().get_matches();
|
let app = App::parse();
|
||||||
|
|
||||||
if let Some(sub_args) = matches.subcommand_matches("supports") {
|
if let Some(Cmd::Supports { renderer }) = app.cmd {
|
||||||
handle_supports(sub_args);
|
handle_supports(&renderer);
|
||||||
} else if let Err(e) = handle_preprocessing() {
|
} else if let Err(e) = handle_preprocessing() {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
|
@ -51,10 +53,7 @@ fn handle_preprocessing() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_supports(sub_args: &ArgMatches) -> ! {
|
fn handle_supports(renderer: &str) -> ! {
|
||||||
let renderer = sub_args
|
|
||||||
.get_one::<String>("renderer")
|
|
||||||
.expect("Required argument");
|
|
||||||
let supported = Toc.supports_renderer(renderer);
|
let supported = Toc.supports_renderer(renderer);
|
||||||
|
|
||||||
// Signal whether the renderer is supported by exiting with 1 or 0.
|
// Signal whether the renderer is supported by exiting with 1 or 0.
|
||||||
|
|
35
src/lib.rs
35
src/lib.rs
|
@ -140,11 +140,11 @@ fn add_toc(content: &str, cfg: &Config) -> Result<String> {
|
||||||
let mut current_header_level: Option<u32> = None;
|
let mut current_header_level: Option<u32> = None;
|
||||||
let mut id_counter = HashMap::new();
|
let mut id_counter = HashMap::new();
|
||||||
|
|
||||||
let mut opts = Options::empty();
|
let opts = Options::ENABLE_TABLES
|
||||||
opts.insert(Options::ENABLE_TABLES);
|
| Options::ENABLE_FOOTNOTES
|
||||||
opts.insert(Options::ENABLE_FOOTNOTES);
|
| Options::ENABLE_STRIKETHROUGH
|
||||||
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
| Options::ENABLE_TASKLISTS
|
||||||
opts.insert(Options::ENABLE_TASKLISTS);
|
| Options::ENABLE_HEADING_ATTRIBUTES;
|
||||||
|
|
||||||
let mark: Vec<Event> = Parser::new(&cfg.marker).collect();
|
let mark: Vec<Event> = Parser::new(&cfg.marker).collect();
|
||||||
log::trace!("Marker: {mark:?}");
|
log::trace!("Marker: {mark:?}");
|
||||||
|
@ -179,20 +179,27 @@ fn add_toc(content: &str, cfg: &Config) -> Result<String> {
|
||||||
current_header_level = Some(lvl as u32);
|
current_header_level = Some(lvl as u32);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Event::End(Heading(..)) = e {
|
if let Event::End(Heading(_, fragment, _)) = e {
|
||||||
// Skip if this header is nested too deeply.
|
// Skip if this header is nested too deeply.
|
||||||
if let Some(level) = current_header_level.take() {
|
if let Some(level) = current_header_level.take() {
|
||||||
let header = current_header.clone();
|
let header = current_header.clone();
|
||||||
let mut slug = mdbook::utils::normalize_id(&header);
|
let slug = if let Some(slug) = fragment {
|
||||||
let id_count = id_counter.entry(slug.clone()).or_insert(0);
|
// If a fragment is defined, take it as is, not trying to append an extra ID
|
||||||
|
// in case of duplicates (same behavior as mdBook)
|
||||||
|
slug.to_owned()
|
||||||
|
} else {
|
||||||
|
let mut slug = mdbook::utils::normalize_id(&header);
|
||||||
|
let id_count = id_counter.entry(slug.clone()).or_insert(0);
|
||||||
|
|
||||||
// Append unique ID if multiple headers with the same name exist
|
// Append unique ID if multiple headers with the same name exist
|
||||||
// to follow what mdBook does
|
// to follow what mdBook does
|
||||||
if *id_count > 0 {
|
if *id_count > 0 {
|
||||||
write!(slug, "-{id_count}").unwrap();
|
write!(slug, "-{id_count}").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
*id_count += 1;
|
*id_count += 1;
|
||||||
|
slug
|
||||||
|
};
|
||||||
|
|
||||||
if level <= cfg.max_level {
|
if level <= cfg.max_level {
|
||||||
toc_content.push((level, header, slug));
|
toc_content.push((level, header, slug));
|
||||||
|
|
11
tests/attributes.in.md
Normal file
11
tests/attributes.in.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Chapter
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
# Header 1
|
||||||
|
|
||||||
|
## Header {#header-1-sub}
|
||||||
|
|
||||||
|
# Header 2
|
||||||
|
|
||||||
|
## Header {#header-2-sub .class1 .class2}
|
14
tests/attributes.out.md
Normal file
14
tests/attributes.out.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Chapter
|
||||||
|
|
||||||
|
* [Header 1](#header-1)
|
||||||
|
* [Header](#header-1-sub)
|
||||||
|
* [Header 2](#header-2)
|
||||||
|
* [Header](#header-2-sub)
|
||||||
|
|
||||||
|
# Header 1
|
||||||
|
|
||||||
|
## Header {#header-1-sub}
|
||||||
|
|
||||||
|
# Header 2
|
||||||
|
|
||||||
|
## Header {#header-2-sub .class1 .class2}
|
19
tests/it.rs
19
tests/it.rs
|
@ -7,15 +7,17 @@ fn default<T: Default>() -> T {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_marker<S: Into<String>>(marker: S) -> Config {
|
fn with_marker<S: Into<String>>(marker: S) -> Config {
|
||||||
let mut cfg = Config::default();
|
Config {
|
||||||
cfg.marker = marker.into();
|
marker: marker.into(),
|
||||||
cfg
|
..Config::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_max_level(level: u32) -> Config {
|
fn with_max_level(level: u32) -> Config {
|
||||||
let mut cfg = Config::default();
|
Config {
|
||||||
cfg.max_level = level;
|
max_level: level,
|
||||||
cfg
|
..Config::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FromContent {
|
trait FromContent {
|
||||||
|
@ -169,3 +171,8 @@ fn empty_document() {
|
||||||
fn crlf() {
|
fn crlf() {
|
||||||
assert_toc!("crlf");
|
assert_toc!("crlf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes() {
|
||||||
|
assert_toc!("attributes");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue