diff --git a/guide/book.toml b/guide/book.toml index 6b01202e..a37c2a7f 100644 --- a/guide/book.toml +++ b/guide/book.toml @@ -11,6 +11,7 @@ edition = "2018" mathjax-support = true site-url = "/mdBook/" git-repository-url = "https://github.com/rust-lang/mdBook/tree/master/guide" +edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}" [output.html.playground] editable = true diff --git a/guide/src/format/config.md b/guide/src/format/config.md index d9c77e66..b3110194 100644 --- a/guide/src/format/config.md +++ b/guide/src/format/config.md @@ -201,6 +201,14 @@ The following configuration options are available: an icon link will be output in the menu bar of the book. - **git-repository-icon:** The FontAwesome icon class to use for the git repository link. Defaults to `fa-github`. +- **edit-url-template:** Edit url template, when provided shows a + "Suggest an edit" button for directly jumping to editing the currently + viewed page. For e.g. GitHub projects set this to + `https://github.com///edit/master/{path}` or for + Bitbucket projects set it to + `https://bitbucket.org///src/master/{path}?mode=edit` + where {path} will be replaced with the full path of the file in the + repository. - **redirect:** A subtable used for generating redirects when a page is moved. The table contains key-value pairs where the key is where the redirect file needs to be created, as an absolute path from the build directory, (e.g. @@ -286,6 +294,7 @@ additional-js = ["custom.js"] no-section-label = false git-repository-url = "https://github.com/rust-lang/mdBook" git-repository-icon = "fa-github" +edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}" site-url = "/example-book/" cname = "myproject.rs" input-404 = "not-found.md" diff --git a/src/book/book.rs b/src/book/book.rs index 95382960..048aef28 100644 --- a/src/book/book.rs +++ b/src/book/book.rs @@ -160,6 +160,8 @@ pub struct Chapter { pub sub_items: Vec, /// The chapter's location, relative to the `SUMMARY.md` file. pub path: Option, + /// The chapter's source file, relative to the `SUMMARY.md` file. + pub source_path: Option, /// An ordered list of the names of each chapter above this one in the hierarchy. pub parent_names: Vec, } @@ -169,13 +171,15 @@ impl Chapter { pub fn new>( name: &str, content: String, - path: P, + p: P, parent_names: Vec, ) -> Chapter { + let path: PathBuf = p.into(); Chapter { name: name.to_string(), content, - path: Some(path.into()), + path: Some(path.clone()), + source_path: Some(path), parent_names, ..Default::default() } @@ -188,6 +192,7 @@ impl Chapter { name: name.to_string(), content: String::new(), path: None, + source_path: None, parent_names, ..Default::default() } @@ -438,6 +443,7 @@ And here is some \ content: String::from("Hello World!"), number: Some(SectionNumber(vec![1, 2])), path: Some(PathBuf::from("second.md")), + source_path: Some(PathBuf::from("second.md")), parent_names: vec![String::from("Chapter 1")], sub_items: Vec::new(), }; @@ -446,6 +452,7 @@ And here is some \ content: String::from(DUMMY_SRC), number: None, path: Some(PathBuf::from("chapter_1.md")), + source_path: Some(PathBuf::from("chapter_1.md")), parent_names: Vec::new(), sub_items: vec![ BookItem::Chapter(nested.clone()), @@ -470,6 +477,7 @@ And here is some \ name: String::from("Chapter 1"), content: String::from(DUMMY_SRC), path: Some(PathBuf::from("chapter_1.md")), + source_path: Some(PathBuf::from("chapter_1.md")), ..Default::default() })], ..Default::default() @@ -510,6 +518,7 @@ And here is some \ content: String::from(DUMMY_SRC), number: None, path: Some(PathBuf::from("Chapter_1/index.md")), + source_path: Some(PathBuf::from("Chapter_1/index.md")), parent_names: Vec::new(), sub_items: vec![ BookItem::Chapter(Chapter::new( @@ -562,6 +571,7 @@ And here is some \ content: String::from(DUMMY_SRC), number: None, path: Some(PathBuf::from("Chapter_1/index.md")), + source_path: Some(PathBuf::from("Chapter_1/index.md")), parent_names: Vec::new(), sub_items: vec![ BookItem::Chapter(Chapter::new( diff --git a/src/config.rs b/src/config.rs index be7dae62..78fdc3ad 100644 --- a/src/config.rs +++ b/src/config.rs @@ -522,6 +522,10 @@ pub struct HtmlConfig { /// /// [custom domain]: https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site pub cname: Option, + /// Edit url template, when set shows a "Suggest an edit" button for + /// directly jumping to editing the currently viewed page. + /// Contains {path} that is replaced with chapter source file path + pub edit_url_template: Option, /// This is used as a bit of a workaround for the `mdbook serve` command. /// Basically, because you set the websocket port from the command line, the /// `mdbook serve` command needs a way to let the HTML renderer know where @@ -554,6 +558,7 @@ impl Default for HtmlConfig { search: None, git_repository_url: None, git_repository_icon: None, + edit_url_template: None, input_404: None, site_url: None, cname: None, diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 254f189f..56324331 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -37,6 +37,18 @@ impl HtmlHandlebars { _ => return Ok(()), }; + if let Some(ref edit_url_template) = ctx.html_config.edit_url_template { + let full_path = "src/".to_owned() + + ch.source_path + .clone() + .unwrap_or_default() + .to_str() + .unwrap_or_default(); + let edit_url = edit_url_template.replace("{path}", &full_path); + ctx.data + .insert("git_repository_edit_url".to_owned(), json!(edit_url)); + } + let content = ch.content.clone(); let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); diff --git a/src/theme/index.hbs b/src/theme/index.hbs index 84c00952..966eedbc 100644 --- a/src/theme/index.hbs +++ b/src/theme/index.hbs @@ -148,6 +148,12 @@ {{/if}} + {{#if git_repository_edit_url}} + + + + {{/if}} +