Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 4 additions & 3 deletions crates/doc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl DocBuilder {
.collect::<Vec<_>>();

let out_dir = self.out_dir()?;
let out_target_dir = out_dir.clone();
let documents = compiler.enter_mut(|compiler| -> eyre::Result<Vec<Vec<Document>>> {
let gcx = compiler.gcx();
let documents = combined_sources
Expand Down Expand Up @@ -197,7 +198,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(DocumentContent::Single(item), ident))
})
Expand Down Expand Up @@ -231,7 +232,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(DocumentContent::Constants(consts), identity),
)
Expand All @@ -250,7 +251,7 @@ impl DocBuilder {
path.clone(),
target_path,
from_library,
self.config.out.clone(),
out_target_dir.clone(),
)
.with_content(
DocumentContent::OverloadedFunctions(funcs),
Expand Down
4 changes: 2 additions & 2 deletions crates/doc/src/document.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{DocBuilder, ParseItem, PreprocessorId, PreprocessorOutput};
use crate::{ParseItem, PreprocessorId, PreprocessorOutput};
use alloy_primitives::map::HashMap;
use std::{
path::{Path, PathBuf},
Expand Down Expand Up @@ -69,7 +69,7 @@ impl Document {
}

fn try_relative_output_path(&self) -> Option<&Path> {
self.target_path.strip_prefix(&self.out_target_dir).ok()?.strip_prefix(DocBuilder::SRC).ok()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we still need this, as docs target paths are composed prefixed with SRC here:

let target_path = out_dir.join(Self::SRC).join(relative_path);

let target_path = out_dir.join(Self::SRC).join(relative_path);

let target_path = out_dir.join(Self::SRC).join(relative_path);

so it's a doubled src e.g. target path is /home/flow/docs/src/src/interfaces/IFlowNFTDescriptor.sol/interface.IFlowNFTDescriptor.md and out target is /home/flow/docs hence relative path will result in doubled src. Or we could just not join src in target dirs, maybe that's better

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added strip_prefixback there.

self.target_path.strip_prefix(&self.out_target_dir).ok()
}

/// Returns the relative path of the document output.
Expand Down
2 changes: 1 addition & 1 deletion crates/doc/src/preprocessor/contract_inheritance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl ContractInheritance {
&& let ParseSource::Contract(ref contract) = item.source
&& base == contract.name.safe_unwrap().name
{
return Some(candidate.target_path.clone());
return Some(candidate.relative_output_path().to_path_buf());
}
}
None
Expand Down
16 changes: 2 additions & 14 deletions crates/doc/src/writer/as_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
};
use itertools::Itertools;
use solang_parser::pt::{Base, FunctionDefinition};
use std::path::{Path, PathBuf};
use std::path::Path;

/// The result of [`AsDoc::as_doc`].
pub type AsDocResult = Result<String, std::fmt::Error>;
Expand Down Expand Up @@ -141,9 +141,6 @@ impl AsDoc for Document {
if !contract.base.is_empty() {
writer.write_bold("Inherits:")?;

// we need this to find the _relative_ paths
let src_target_dir = self.target_src_dir();

let mut bases = vec![];
let linked =
read_context!(self, CONTRACT_INHERITANCE_ID, ContractInheritance);
Expand All @@ -155,11 +152,7 @@ impl AsDoc for Document {
.as_ref()
.and_then(|link| {
link.get(base_ident).map(|path| {
let path = Path::new("/").join(
path.strip_prefix(&src_target_dir)
.ok()
.unwrap_or(path),
);
let path = Path::new("/").join(path);
Markdown::Link(&base_doc, &path.display().to_string())
.as_doc()
})
Expand Down Expand Up @@ -287,11 +280,6 @@ impl AsDoc for Document {
}

impl Document {
/// Where all the source files are written to
fn target_src_dir(&self) -> PathBuf {
self.out_target_dir.join("src")
}

/// Writes a function to the buffer.
fn write_function(
&self,
Expand Down
48 changes: 48 additions & 0 deletions crates/forge/tests/cli/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,51 @@ contract Example is IExample {
assert!(content.contains("Process multiple addresses"));
assert!(content.contains("Process an address with a value"));
});

// Test that hyperlinks use relative paths, not absolute paths
// fixes <https://github.com/foundry-rs/foundry/issues/12361>
forgetest_init!(hyperlinks_use_relative_paths, |prj, cmd| {
prj.add_source(
"IBase.sol",
r#"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IBase {
function baseFunction() external;
}
"#,
);

prj.add_source(
"Derived.sol",
r#"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./IBase.sol";

/// @dev Inherits: {IBase}
contract Derived is IBase {
function baseFunction() external override {}
}
"#,
);

cmd.args(["doc", "--build"]).assert_success();

let doc_path = prj.root().join("docs/src/src/Derived.sol/contract.Derived.md");
let content = std::fs::read_to_string(&doc_path).unwrap();

assert!(
content.contains("[IBase](/src/"),
"Hyperlink should use relative path starting with /src/, but found: {:?}",
content.lines().find(|line| line.contains("[IBase]")).unwrap_or("not found")
);
assert!(!content.contains("/Users/"), "Hyperlink should not contain absolute path /Users/");
assert!(!content.contains("/home/"), "Hyperlink should not contain absolute path /home/");
assert!(
content.contains("IBase.sol/interface.IBase.md"),
"Hyperlink should point to IBase.sol/interface.IBase.md"
);
});
Loading