@@ -83,6 +83,9 @@ pub struct Context {
83
83
/// String representation of how to get back to the root path of the 'doc/'
84
84
/// folder in terms of a relative URL.
85
85
pub root_path : String ,
86
+ /// The path to the crate root source minus the file name.
87
+ /// Used for simplifying paths to the highlighted source code files.
88
+ pub src_root : Path ,
86
89
/// The current destination folder of where HTML artifacts should be placed.
87
90
/// This changes as the context descends into the module hierarchy.
88
91
pub dst : Path ,
@@ -249,6 +252,7 @@ pub fn run(mut krate: clean::Crate,
249
252
passes : HashSet < String > ) -> io:: IoResult < ( ) > {
250
253
let mut cx = Context {
251
254
dst : dst,
255
+ src_root : krate. src . dir_path ( ) ,
252
256
passes : passes,
253
257
current : Vec :: new ( ) ,
254
258
root_path : String :: new ( ) ,
@@ -642,8 +646,13 @@ fn mkdir(path: &Path) -> io::IoResult<()> {
642
646
/// things like ".." to components which preserve the "top down" hierarchy of a
643
647
/// static HTML tree.
644
648
// FIXME (#9639): The closure should deal with &[u8] instead of &str
645
- fn clean_srcpath ( src : & [ u8 ] , f: |& str|) {
649
+ // FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths
650
+ fn clean_srcpath ( src_root : & Path , src : & [ u8 ] , f: |& str|) {
646
651
let p = Path :: new ( src) ;
652
+
653
+ // make it relative, if possible
654
+ let p = p. path_relative_from ( src_root) . unwrap_or ( p) ;
655
+
647
656
if p. as_vec ( ) != b"." {
648
657
for c in p. str_components ( ) . map ( |x|x. unwrap ( ) ) {
649
658
if ".." == c {
@@ -749,7 +758,7 @@ impl<'a> SourceCollector<'a> {
749
758
// Create the intermediate directories
750
759
let mut cur = self . dst . clone ( ) ;
751
760
let mut root_path = String :: from_str ( "../../" ) ;
752
- clean_srcpath ( p. dirname ( ) , |component| {
761
+ clean_srcpath ( & self . cx . src_root , p. dirname ( ) , |component| {
753
762
cur. push ( component) ;
754
763
mkdir ( & cur) . unwrap ( ) ;
755
764
root_path. push_str ( "../" ) ;
@@ -1299,13 +1308,13 @@ impl<'a> Item<'a> {
1299
1308
/// If `None` is returned, then a source link couldn't be generated. This
1300
1309
/// may happen, for example, with externally inlined items where the source
1301
1310
/// of their crate documentation isn't known.
1302
- fn href ( & self ) -> Option < String > {
1311
+ fn href ( & self , cx : & Context ) -> Option < String > {
1303
1312
// If this item is part of the local crate, then we're guaranteed to
1304
1313
// know the span, so we plow forward and generate a proper url. The url
1305
1314
// has anchors for the line numbers that we're linking to.
1306
1315
if ast_util:: is_local ( self . item . def_id ) {
1307
1316
let mut path = Vec :: new ( ) ;
1308
- clean_srcpath ( self . item . source . filename . as_bytes ( ) , |component| {
1317
+ clean_srcpath ( & cx . src_root , self . item . source . filename . as_bytes ( ) , |component| {
1309
1318
path. push ( component. to_string ( ) ) ;
1310
1319
} ) ;
1311
1320
let href = if self . item . source . loline == self . item . source . hiline {
@@ -1412,7 +1421,7 @@ impl<'a> fmt::Show for Item<'a> {
1412
1421
// this page, and this link will be auto-clicked. The `id` attribute is
1413
1422
// used to find the link to auto-click.
1414
1423
if self . cx . include_sources && !is_primitive {
1415
- match self . href ( ) {
1424
+ match self . href ( self . cx ) {
1416
1425
Some ( l) => {
1417
1426
try!( write ! ( fmt, "<a id='src-{}' href='{}'>[src]</a>" ,
1418
1427
self . item. def_id. node, l) ) ;
0 commit comments