Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,026 changes: 230 additions & 796 deletions Cargo.lock

Large diffs are not rendered by default.

29 changes: 18 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,35 @@ name = "mdbook-epub"
doc = false

[dependencies]
clap = { version = "4.5", default-features = false, features = ["derive"] }
clap = { version = "4.5", default-features = false, features = [
"derive",
"std",
] }
epub-builder = "0.8"
thiserror = "2.0"
pulldown-cmark = "0.10.0"
pulldown-cmark = "0.13.0"
semver = "1.0"
serde = { version = "1.0.163", features = ["derive"] }
toml = "0.9.8"
env_logger = "0.11.1"
serde = { version = "1.0.228", features = ["derive"] }
serde_derive = "1.0"
serde_json = "1.0.96"
serde_json = "1.0.145"
mime_guess = "2.0"
env_logger = "0.11.1"
log = "0.4.17"
mdbook = { version = "0.4.51", default-features = true }
handlebars = "6.0"
toml = "0.5.11" # downgraded due to parent 'mdbook' dependency and error there
#log = "0.4.17"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
mdbook-core = { version = "0.5.1", default-features = false } # I'm kinda anxious about it as they say it's for internal use, examples still outdated
mdbook-driver = { version = "0.5.1", default-features = false } # Because we support standalone rendering...
mdbook-renderer = { version = "0.5.1", default-features = false }
handlebars = "6.3.2" # downgraded due to parent 'mdbook' dependency and error there
html_parser = "0.7.0"
url = "2.5"
ureq = "3.0"
ureq = "3.1"
infer = "0.19"
const_format = "0.2"

[dev-dependencies]
tempfile = "3.19"
tempfile = "3.23"
epub = "2.1"
serial_test = "3.2"
mockall = "0.13"
Expand Down
15 changes: 7 additions & 8 deletions src/bin/mdbook-epub.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
#[macro_use]
extern crate log;

use std::io;
use std::path::PathBuf;
use std::process;

use ::env_logger;
use ::mdbook;
use ::serde_json;
use clap::Parser;
use mdbook::renderer::RenderContext;
use mdbook::MDBook;
use mdbook_driver::MDBook;
use mdbook_renderer::RenderContext;

use ::mdbook_epub;
use mdbook_epub::errors::Error;
use tracing::{debug, error, info};

fn main() {
env_logger::init();
Expand All @@ -22,7 +19,7 @@ fn main() {
debug!("prepared generator args = {:?}", args);

if let Err(e) = run(&args) {
log::error!("{}", e);
error!("{}", e);

process::exit(1);
}
Expand All @@ -47,7 +44,9 @@ fn run(args: &Args) -> Result<(), Error> {
debug!("EPUB book config is : {:?}", md.config);
RenderContext::new(md.root, md.book, md.config, destination)
} else {
println!("Running mdbook-epub as plugin waiting on the STDIN input. If you wanted to process the files in the current folder, use the -s flag from documentation, See: mdbook-epub --help");
println!(
"Running mdbook-epub as plugin waiting on the STDIN input. If you wanted to process the files in the current folder, use the -s flag from documentation, See: mdbook-epub --help"
);
serde_json::from_reader(io::stdin()).map_err(|_| Error::RenderContext)?
};
debug!("calling the main code for epub creation");
Expand Down
16 changes: 8 additions & 8 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::Error;
use mdbook::renderer::RenderContext;
use mdbook_renderer::RenderContext;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

pub const DEFAULT_TEMPLATE: &str = include_str!("index.hbs");
Expand Down Expand Up @@ -34,10 +35,8 @@ impl Config {
/// Get the `output.epub` table from the provided `book.toml` config,
/// falling back to the default if
pub fn from_render_context(ctx: &RenderContext) -> Result<Config, Error> {
match ctx.config.get("output.epub") {
Some(table) => {
let mut cfg: Config = table.clone().try_into()?;

match ctx.config.get::<Config>("output.epub")? {
Some(mut cfg) => {
// make sure we update the `index_template` to make it relative
// to the book root
if let Some(template_file) = cfg.index_template.take() {
Expand Down Expand Up @@ -82,6 +81,7 @@ impl Default for Config {
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
use std::path::Path;
use tempfile::TempDir;

Expand All @@ -100,11 +100,11 @@ mod tests {

fn ctx_with_template(source: &str, destination: &Path) -> serde_json::Value {
json!({
"version": mdbook::MDBOOK_VERSION,
"version": mdbook_core::MDBOOK_VERSION,
"root": "tests/long_book_example",
"book": {"sections": [], "__non_exhaustive": null},
"book": {"items": [], "__non_exhaustive": null},
"config": {
"book": {"authors": [], "language": "en", "multilingual": false,
"book": {"authors": [], "language": "en", "text-direction": "ltr",
"src": source, "title": "DummyBook"},
"output": {"epub": {"optional": true}}},
"destination": destination
Expand Down
2 changes: 1 addition & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub enum Error {
AssetOutsideSrcDir(#[from] std::path::StripPrefixError),

#[error(transparent)]
Book(#[from] mdbook::errors::Error),
Book(#[from] mdbook_core::errors::Error),
#[error(transparent)]
Semver(#[from] semver::Error),
#[error(transparent)]
Expand Down
1 change: 1 addition & 0 deletions src/filters/asset_link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::collections::HashMap;
use std::ffi::OsString;
use std::iter;
use std::path::{Component, Path};
use tracing::{debug, error, trace};
use url::Url;

/// Filter is used for replacing remote urls with local images downloaded from internet
Expand Down
1 change: 1 addition & 0 deletions src/filters/footnote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ impl<'a> FootnoteFilter<'a> {
mod tests {
use super::*;
use pulldown_cmark::{Event, Options, Parser, Tag, TagEnd};
use tracing::debug;

fn parse_markdown_with_footnotes(input: &str) -> Vec<Event<'_>> {
let mut footnote_filter = FootnoteFilter::new(true);
Expand Down
20 changes: 11 additions & 9 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use crate::validation::validate_config_epub_version;
use crate::{Error, utils};
use epub_builder::{EpubBuilder, EpubContent, ZipLibrary};
use handlebars::{Handlebars, RenderError, RenderErrorReason};
use mdbook::book::{BookItem, Chapter};
use mdbook::renderer::RenderContext;
use mdbook_core::book::{BookItem, Chapter};
use mdbook_renderer::RenderContext;
use pulldown_cmark::html;
use serde_json::json;
use std::collections::HashSet;
use std::path::Path;
use std::{
Expand All @@ -23,6 +24,7 @@ use std::{
iter,
path::PathBuf,
};
use tracing::{debug, error, info, trace, warn};

/// The actual EPUB book renderer.
pub struct Generator<'a> {
Expand Down Expand Up @@ -136,7 +138,7 @@ impl<'a> Generator<'a> {
info!("3.1 Generate chapters == ");

let mut added_count = 0;
for (idx, item) in self.ctx.book.sections.iter().enumerate() {
for (idx, item) in self.ctx.book.iter().enumerate() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.ctx.book.iter() - now returns Items + SubItems as one long list.
So that code is ok.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But code at the end of method
fn add_chapter(&mut self, ch: &Chapter, is_first: Option<bool>) -> Result<(), Error>

that block

// second pass to actually add the sub-chapters
        for sub_item in &ch.sub_items {
            if let BookItem::Chapter(ref sub_ch) = *sub_item {
                trace!("add sub-item = {:?}", sub_ch.name);
                self.add_chapter(sub_ch, None)?;
            }
        }

Should be removed because it causes duplicate Chapter is added to book.

let is_first = idx == 0;
if let BookItem::Chapter(ref ch) = *item {
trace!("Adding chapter \"{}\"", ch);
Expand Down Expand Up @@ -602,7 +604,7 @@ mod tests {
}
});
let mut json = ctx_with_template("", "src", dest_dir.as_path());
let chvalue = json["book"]["sections"].as_array_mut().unwrap();
let chvalue = json["book"]["items"].as_array_mut().unwrap();
chvalue.clear();
chvalue.push(ch1);
chvalue.push(ch2);
Expand All @@ -615,7 +617,7 @@ mod tests {
let pat = |heading, prefix| {
format!("<h1>{heading}</h1>\n<p><img src=\"{prefix}e3825a3756080f55.svg\"")
};
if let BookItem::Chapter(ref ch) = ctx.book.sections[0] {
if let BookItem::Chapter(ref ch) = ctx.book.items[0] {
let rendered: String = g.render_chapter(ch).unwrap();
debug!("1. rendered ===\n{}", &rendered);
assert!(rendered.contains(&pat("Chapter 1", "../")));
Expand All @@ -630,7 +632,7 @@ mod tests {
} else {
panic!();
}
if let BookItem::Chapter(ref ch) = ctx.book.sections[1] {
if let BookItem::Chapter(ref ch) = ctx.book.items[1] {
let rendered: String = g.render_chapter(ch).unwrap();
assert!(rendered.contains(&pat("Chapter 2", "")));
} else {
Expand All @@ -656,9 +658,9 @@ mod tests {

fn ctx_with_template(content: &str, source: &str, destination: &Path) -> serde_json::Value {
json!({
"version": mdbook::MDBOOK_VERSION,
"version": mdbook_core::MDBOOK_VERSION,
"root": "tests/long_book_example",
"book": {"sections": [{
"book": {"items": [{
"Chapter": {
"name": "Chapter 1",
"content": content,
Expand All @@ -668,7 +670,7 @@ mod tests {
"parent_names": []
}}], "__non_exhaustive": null},
"config": {
"book": {"authors": [], "language": "en", "multilingual": false,
"book": {"authors": [], "language": "en", "text-direction": "ltr",
"src": source, "title": "DummyBook"},
"output": {"epub": {"curly-quotes": true}}},
"destination": destination
Expand Down
16 changes: 5 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
//! A `mdbook` backend for generating a book in the `EPUB` format.

#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

use std::fs::{File, create_dir_all};
use std::path::{Path, PathBuf};

use ::mdbook;
use ::mdbook_core;
use ::semver;
use ::thiserror::Error;
use mdbook::config::Config as MdConfig;
use mdbook::renderer::RenderContext;
use mdbook_core::config::Config as MdConfig;
use mdbook_renderer::RenderContext;
use semver::{Version, VersionReq};
use tracing::{debug, info};

use errors::Error;

Expand All @@ -35,7 +29,7 @@ mod validation;
pub const DEFAULT_CSS: &str = include_str!("master.css");

/// The exact version of `mdbook` this crate is compiled against.
pub const MDBOOK_VERSION: &str = mdbook::MDBOOK_VERSION;
pub const MDBOOK_VERSION: &str = mdbook_core::MDBOOK_VERSION;

/// Check that the version of `mdbook` we're called by is compatible with this
/// backend.
Expand Down
1 change: 1 addition & 0 deletions src/resources/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use mime_guess::Mime;
use std::fmt::{Display, Formatter};
use std::hash::Hash;
use std::path::{MAIN_SEPARATOR_STR, Path, PathBuf};
use tracing::{debug, trace};
use url::Url;

/// The type of asset, remote or local
Expand Down
15 changes: 8 additions & 7 deletions src/resources/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::path::MAIN_SEPARATOR_STR;

use const_format::concatcp;
use html_parser::{Dom, Element, Node};
use mdbook::book::BookItem;
use mdbook::renderer::RenderContext;
use mdbook_core::book::BookItem;
use mdbook_renderer::RenderContext;
use pulldown_cmark::{Event, Tag};
use tracing::{debug, trace, warn};
use url::Url;

use crate::resources::asset::{Asset, AssetKind};
Expand Down Expand Up @@ -35,7 +36,7 @@ pub(crate) fn find(ctx: &RenderContext) -> Result<HashMap<String, Asset>, Error>

debug!(
"Start iteration over a [{:?}] sections in src_dir = {:?}",
ctx.book.sections.len(),
ctx.book.items.len(),
src_dir
);
for section in ctx.book.iter() {
Expand Down Expand Up @@ -396,13 +397,13 @@ mod tests {
fn ctx_with_chapters(
chapters: &Value,
destination: &str,
) -> Result<RenderContext, mdbook::errors::Error> {
) -> Result<RenderContext, mdbook_core::errors::Error> {
let json_ctx = json!({
"version": mdbook::MDBOOK_VERSION,
"version": mdbook_core::MDBOOK_VERSION,
"root": "tests/long_book_example",
"book": {"sections": chapters, "__non_exhaustive": null},
"book": {"items": chapters, "__non_exhaustive": null},
"config": {
"book": {"authors": [], "language": "en", "multilingual": false,
"book": {"authors": [], "language": "en", "text-direction": "ltr",
"src": "src", "title": "DummyBook"},
"output": {"epub": {"curly-quotes": true}}},
"destination": destination
Expand Down
2 changes: 2 additions & 0 deletions src/resources/retrieve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::{
io::{self, Read},
path::Path,
};
use tracing::debug;

/// Struct to keep file (image) data 'mime type' after recognizing downloaded content
#[allow(dead_code)]
Expand Down Expand Up @@ -210,6 +211,7 @@ mod tests {
use mime_guess::Mime;
use std::path::PathBuf;
use tempfile::TempDir;
use tracing::trace;
use url::Url;

use super::{ContentRetriever, ResourceHandler, RetrievedContent, UpdatedAssetData};
Expand Down
6 changes: 3 additions & 3 deletions src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::errors::Error;
use crate::Config;
use crate::errors::Error;
use epub_builder::EpubVersion;
use mdbook::Config as MdConfig;
use mdbook_core::config::Config as MdConfig;
use std::path::Path;

pub(crate) fn validate_config_epub_version(
Expand All @@ -14,7 +14,7 @@ pub(crate) fn validate_config_epub_version(
return Err(Error::EpubDocCreate(format!(
"Unsupported epub version specified in book.toml: {}",
v
)))
)));
}
None => None,
};
Expand Down
6 changes: 3 additions & 3 deletions tests/common/epub.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::common::init_logging::init_logging;
use epub::doc::EpubDoc;
use log::{debug, error};
use mdbook::MDBook;
use mdbook::renderer::RenderContext;
use mdbook_driver::MDBook;
use mdbook_epub::errors::Error;
use mdbook_renderer::RenderContext;
use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::process::Command;
use tempfile::TempDir;
use tracing::{debug, error};

/// Convenience function for compiling the dummy book into an `EpubDoc`.
#[allow(dead_code)]
Expand Down
2 changes: 1 addition & 1 deletion tests/footnote_epub3_example.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use log::debug;
use serial_test::serial;
use std::path::Path;
use tracing::debug;

mod common;
use crate::common::epub::{create_dummy_book, output_epub_is_valid};
Expand Down
4 changes: 2 additions & 2 deletions tests/footnote_epub3_example/book.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[book]
title = "FootnoteEpub3Example"
authors = []
multilingual = false

src = "src"
lang = "en"
language = "en"

[output.epub]
epub-version = 3
Expand Down
3 changes: 0 additions & 3 deletions tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
pub mod common;

extern crate log;
extern crate serial_test;
Loading
Loading