Skip to content

Commit 3d28a2d

Browse files
Integrate LocalResources into markdown generation
1 parent 62e7207 commit 3d28a2d

File tree

8 files changed

+102
-17
lines changed

8 files changed

+102
-17
lines changed

src/librustdoc/externalfiles.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ impl ExternalHtml {
4747
edition,
4848
playground,
4949
heading_offset: HeadingOffset::H2,
50+
depth: 0,
51+
local_resources: None,
5052
}
5153
.into_string()
5254
);
@@ -63,6 +65,8 @@ impl ExternalHtml {
6365
edition,
6466
playground,
6567
heading_offset: HeadingOffset::H2,
68+
depth: 0,
69+
local_resources: None,
6670
}
6771
.into_string()
6872
);

src/librustdoc/formats/cache.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
520520
}
521521

522522
#[derive(Default)]
523-
pub(crate) struct LocalResources {
523+
pub struct LocalResources {
524524
/// The key is the original location of the resource. The value is the new name.
525525
pub(crate) resources_to_copy: FxHashMap<PathBuf, String>,
526526
/// This will be used when generating the HTML, once everything is generated, we copy these
@@ -529,20 +529,18 @@ pub(crate) struct LocalResources {
529529
/// The key is the depth and the value is hashmap where the key is the path of the resource in
530530
/// the markdown and the value is the new path to the resources in the rustdoc output folder.
531531
pub(crate) resources_correspondance: FxHashMap<usize, FxHashMap<String, String>>,
532-
pub(crate) total_entries: usize,
533532
}
534533

535534
impl LocalResources {
536535
pub(crate) fn add_entry_at_depth(&mut self, depth: usize, key: String, value: String) {
537-
if self
538-
.resources_correspondance
536+
self.resources_correspondance
539537
.entry(depth)
540538
.or_insert_with(FxHashMap::default)
541-
.insert(key, value)
542-
.is_none()
543-
{
544-
self.total_entries += 1;
545-
}
539+
.insert(key, value);
540+
}
541+
542+
pub(crate) fn get_at_depth(&self, depth: usize, key: &str) -> Option<&String> {
543+
self.resources_correspondance.get(&depth).and_then(|e| e.get(key))
546544
}
547545
}
548546

src/librustdoc/html/markdown.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use std::str;
4242

4343
use crate::clean::RenderedLink;
4444
use crate::doctest;
45+
use crate::formats::cache::LocalResources;
4546
use crate::html::escape::Escape;
4647
use crate::html::format::Buffer;
4748
use crate::html::highlight;
@@ -101,6 +102,8 @@ pub struct Markdown<'a> {
101102
/// Offset at which we render headings.
102103
/// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `<h2>`.
103104
pub heading_offset: HeadingOffset,
105+
pub depth: usize,
106+
pub local_resources: Option<&'a LocalResources>,
104107
}
105108
/// A tuple struct like `Markdown` that renders the markdown with a table of contents.
106109
pub(crate) struct MarkdownWithToc<'a> {
@@ -109,13 +112,50 @@ pub(crate) struct MarkdownWithToc<'a> {
109112
pub(crate) error_codes: ErrorCodes,
110113
pub(crate) edition: Edition,
111114
pub(crate) playground: &'a Option<Playground>,
115+
pub(crate) depth: usize,
116+
pub(crate) local_resources: Option<&'a LocalResources>,
112117
}
113118
/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags
114119
/// and includes no paragraph tags.
115120
pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap);
116121
/// A tuple struct like `Markdown` that renders only the first paragraph.
117122
pub(crate) struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [RenderedLink]);
118123

124+
struct LocalResourcesReplacer<'b, I> {
125+
inner: I,
126+
local_resources: Option<&'b LocalResources>,
127+
depth: usize,
128+
}
129+
130+
impl<'b, I> LocalResourcesReplacer<'b, I> {
131+
fn new(iter: I, local_resources: Option<&'b LocalResources>, depth: usize) -> Self {
132+
Self { inner: iter, local_resources, depth }
133+
}
134+
}
135+
136+
impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for LocalResourcesReplacer<'b, I> {
137+
type Item = Event<'a>;
138+
139+
fn next(&mut self) -> Option<Self::Item> {
140+
let event = self.inner.next()?;
141+
// We only modify
142+
if let Event::Start(Tag::Image(type_, ref path, ref title)) = event &&
143+
!path.starts_with("http://") &&
144+
!path.starts_with("https://") &&
145+
let Some(local_resources) = &self.local_resources &&
146+
let Some(correspondance) = local_resources.get_at_depth(self.depth, &*path)
147+
{
148+
Some(Event::Start(Tag::Image(
149+
type_,
150+
CowStr::Boxed(correspondance.clone().into_boxed_str()),
151+
title.clone(),
152+
)))
153+
} else {
154+
Some(event)
155+
}
156+
}
157+
}
158+
119159
#[derive(Copy, Clone, PartialEq, Debug)]
120160
pub enum ErrorCodes {
121161
Yes,
@@ -1017,6 +1057,8 @@ impl Markdown<'_> {
10171057
edition,
10181058
playground,
10191059
heading_offset,
1060+
depth,
1061+
local_resources,
10201062
} = self;
10211063

10221064
// This is actually common enough to special-case
@@ -1038,6 +1080,7 @@ impl Markdown<'_> {
10381080
let p = HeadingLinks::new(p, None, ids, heading_offset);
10391081
let p = Footnotes::new(p);
10401082
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
1083+
let p = LocalResourcesReplacer::new(p, local_resources, depth);
10411084
let p = TableWrapper::new(p);
10421085
let p = CodeBlocks::new(p, codes, edition, playground);
10431086
html::push_html(&mut s, p);
@@ -1048,7 +1091,15 @@ impl Markdown<'_> {
10481091

10491092
impl MarkdownWithToc<'_> {
10501093
pub(crate) fn into_string(self) -> String {
1051-
let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self;
1094+
let MarkdownWithToc {
1095+
content: md,
1096+
ids,
1097+
error_codes: codes,
1098+
edition,
1099+
playground,
1100+
depth,
1101+
local_resources,
1102+
} = self;
10521103

10531104
let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
10541105

@@ -1059,7 +1110,8 @@ impl MarkdownWithToc<'_> {
10591110
{
10601111
let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
10611112
let p = Footnotes::new(p);
1062-
let p = TableWrapper::new(p.map(|(ev, _)| ev));
1113+
let p = LocalResourcesReplacer::new(p.map(|(ev, _)| ev), local_resources, depth);
1114+
let p = TableWrapper::new(p);
10631115
let p = CodeBlocks::new(p, codes, edition, playground);
10641116
html::push_html(&mut s, p);
10651117
}

src/librustdoc/html/render/context.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,22 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
719719
}
720720
}
721721

722+
{
723+
// Copying the local resources to the destination folder.
724+
let resources = &shared.cache.local_resources.resources_to_copy;
725+
if !resources.is_empty() {
726+
let dst = self
727+
.dst
728+
.join(crate::html::LOCAL_RESOURCES_FOLDER_NAME)
729+
.join(crate_name.as_str());
730+
shared.ensure_dir(&dst)?;
731+
for (original_path, dest_name) in resources.iter() {
732+
let dst = dst.join(dest_name);
733+
try_err!(std::fs::copy(original_path, &dst), &dst);
734+
}
735+
}
736+
}
737+
722738
// No need for it anymore.
723739
drop(shared);
724740

src/librustdoc/html/render/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,9 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
404404
error_codes: shared.codes,
405405
edition: shared.edition(),
406406
playground: &shared.playground,
407-
heading_offset: HeadingOffset::H1
407+
heading_offset: HeadingOffset::H1,
408+
depth: 0,
409+
local_resources: None,
408410
}
409411
.into_string()
410412
)
@@ -447,6 +449,8 @@ fn render_markdown(
447449
edition: cx.shared.edition(),
448450
playground: &cx.shared.playground,
449451
heading_offset,
452+
depth: cx.current.len(),
453+
local_resources: Some(&cx.shared.cache.local_resources),
450454
}
451455
.into_string()
452456
)
@@ -1755,7 +1759,9 @@ fn render_impl(
17551759
error_codes: cx.shared.codes,
17561760
edition: cx.shared.edition(),
17571761
playground: &cx.shared.playground,
1758-
heading_offset: HeadingOffset::H4
1762+
heading_offset: HeadingOffset::H4,
1763+
depth: cx.current.len(),
1764+
local_resources: Some(&cx.shared.cache.local_resources),
17591765
}
17601766
.into_string()
17611767
);

src/librustdoc/html/render/write_shared.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
329329
md_opts.output = cx.dst.clone();
330330
md_opts.external_html = (*cx.shared).layout.external_html.clone();
331331

332-
crate::markdown::render(&index_page, md_opts, cx.shared.edition())
332+
crate::markdown::render(&index_page, md_opts, cx.shared.edition(), Some(&cx))
333333
.map_err(|e| Error::new(e, &index_page))?;
334334
} else {
335335
let shared = Rc::clone(&cx.shared);

src/librustdoc/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ fn main_args(at_args: &[String]) -> MainResult {
749749
return wrap_return(
750750
&diag,
751751
interface::run_compiler(config, |_compiler| {
752-
markdown::render(&input, render_options, edition)
752+
markdown::render(&input, render_options, edition, None)
753753
}),
754754
);
755755
}

src/librustdoc/markdown.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use rustc_span::source_map::DUMMY_SP;
99
use crate::config::{Options, RenderOptions};
1010
use crate::doctest::{Collector, GlobalTestOptions};
1111
use crate::html::escape::Escape;
12-
use crate::html::markdown;
1312
use crate::html::markdown::{
14-
find_testable_code, ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc,
13+
self, find_testable_code, ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc,
1514
};
15+
use crate::html::render::Context;
1616

1717
/// Separate any lines at the start of the file that begin with `# ` or `%`.
1818
fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
@@ -41,6 +41,7 @@ pub(crate) fn render<P: AsRef<Path>>(
4141
input: P,
4242
options: RenderOptions,
4343
edition: Edition,
44+
cx: Option<&Context<'_>>,
4445
) -> Result<(), String> {
4546
if let Err(e) = create_dir_all(&options.output) {
4647
return Err(format!("{}: {}", options.output.display(), e));
@@ -71,13 +72,19 @@ pub(crate) fn render<P: AsRef<Path>>(
7172

7273
let mut ids = IdMap::new();
7374
let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
75+
let (local_resources, depth) = match cx {
76+
Some(cx) => (Some(&cx.shared.cache.local_resources), cx.current.len()),
77+
None => (None, 0),
78+
};
7479
let text = if !options.markdown_no_toc {
7580
MarkdownWithToc {
7681
content: text,
7782
ids: &mut ids,
7883
error_codes,
7984
edition,
8085
playground: &playground,
86+
local_resources,
87+
depth,
8188
}
8289
.into_string()
8390
} else {
@@ -89,6 +96,8 @@ pub(crate) fn render<P: AsRef<Path>>(
8996
edition,
9097
playground: &playground,
9198
heading_offset: HeadingOffset::H1,
99+
local_resources,
100+
depth,
92101
}
93102
.into_string()
94103
};

0 commit comments

Comments
 (0)