@@ -6,34 +6,39 @@ import liqp.Template
6
6
import dotty .dokka .model .api ._
7
7
import dotty .tools .dotc .core .Contexts .Context
8
8
9
+ def pathToString (p : Path ) = p.toString.replace('\\ ' , '/' )
10
+
9
11
trait SourceLink :
10
12
val path : Option [Path ] = None
11
- def render (path : String , operation : String , line : Option [Int ]): String
13
+ def render (path : Path , operation : String , line : Option [Int ]): String
12
14
13
15
case class PrefixedSourceLink (val myPath : Path , nested : SourceLink ) extends SourceLink :
14
- export nested . render
16
+ val myPrefix = pathToString(myPath)
15
17
override val path = Some (myPath)
18
+ override def render (path : Path , operation : String , line : Option [Int ]): String =
19
+ nested.render(myPath.relativize(path), operation, line)
20
+
16
21
17
22
case class TemplateSourceLink (val urlTemplate : Template ) extends SourceLink :
18
23
override val path : Option [Path ] = None
19
- override def render (path : String , operation : String , line : Option [Int ]): String =
24
+ override def render (path : Path , operation : String , line : Option [Int ]): String =
20
25
val config = java.util.HashMap [String , Object ]()
21
- config.put(" path" , path)
26
+ config.put(" path" , pathToString( path) )
22
27
line.foreach(l => config.put(" line" , l.toString))
23
28
config.put(" operation" , operation)
24
29
25
30
urlTemplate.render(config)
26
31
27
- case class WebBasedSourceLink (prefix : String , revision : String ) extends SourceLink :
32
+ case class WebBasedSourceLink (prefix : String , revision : String , subPath : String ) extends SourceLink :
28
33
override val path : Option [Path ] = None
29
- override def render (path : String , operation : String , line : Option [Int ]): String =
34
+ override def render (path : Path , operation : String , line : Option [Int ]): String =
30
35
val action = if operation == " view" then " blob" else operation
31
36
val linePart = line.fold(" " )(l => s " #L $l" )
32
- s " $prefix/ $action/ $revision/ $path$linePart"
37
+ s " $prefix/ $action/ $revision$subPath / $path$linePart"
33
38
34
39
object SourceLink :
35
40
val SubPath = " ([^=]+)=(.+)" .r
36
- val KnownProvider = raw " (\w+):\/\/([^\/]+)\/([^\/]+) " .r
41
+ val KnownProvider = raw " (\w+):\/\/([^\/# ]+)\/([^\/# ]+)(\/[^\/#]+)?(#.+)? " .r
37
42
val BrokenKnownProvider = raw " (\w+):\/\/.+ " .r
38
43
val ScalaDocPatten = raw " €\{(TPL_NAME|TPL_NAME|FILE_PATH|FILE_EXT|FILE_LINE|FILE_PATH_EXT)\} " .r
39
44
val SupportedScalaDocPatternReplacements = Map (
@@ -55,15 +60,20 @@ object SourceLink:
55
60
Left (s " Failed to parse template: ${e.getMessage}" )
56
61
57
62
string match
58
- case KnownProvider (name, organization, repo) =>
63
+ case KnownProvider (name, organization, repo, rawRevision, rawSubPath) =>
64
+ val subPath = Option (rawSubPath).fold(" " )(" /" + _.drop(1 ))
65
+ val pathRev = Option (rawRevision).map(_.drop(1 )).orElse(revision)
66
+
59
67
def withRevision (template : String => SourceLink ) =
60
- revision .fold(Left (s " No revision provided " ))(r => Right (template(r)))
68
+ pathRev .fold(Left (s " No revision provided " ))(r => Right (template(r)))
61
69
62
70
name match
63
71
case " github" =>
64
- withRevision(rev => WebBasedSourceLink (githubPrefix(organization, repo), rev))
72
+ withRevision(rev =>
73
+ WebBasedSourceLink (githubPrefix(organization, repo), rev, subPath))
65
74
case " gitlab" =>
66
- withRevision(rev => WebBasedSourceLink (gitlabPrefix(organization, repo), rev))
75
+ withRevision(rev =>
76
+ WebBasedSourceLink (gitlabPrefix(organization, repo), rev, subPath))
67
77
case other =>
68
78
Left (s " ' $other' is not a known provider, please provide full source path template. " )
69
79
@@ -93,7 +103,7 @@ case class SourceLinks(links: Seq[SourceLink], projectRoot: Path):
93
103
def resolveRelativePath (path : Path ) =
94
104
links
95
105
.find(_.path.forall(p => path.startsWith(p)))
96
- .map(_.render(path.toString.replace( ' \\ ' , '/' ) , operation, line))
106
+ .map(_.render(path, operation, line))
97
107
98
108
if rawPath.isAbsolute then
99
109
if rawPath.startsWith(projectRoot) then resolveRelativePath(projectRoot.relativize(rawPath))
@@ -113,8 +123,12 @@ object SourceLinks:
113
123
|<source-link>
114
124
|
115
125
|where <source-link> is one of following:
116
- | - `github://<organization>/<repository>` (requires revision to be specified as argument for scala3doc)
117
- | - `gitlab://<organization>/<repository>` (requires revision to be specified as argument for scala3doc)
126
+ | - `github://<organization>/<repository>[/revision][#subpath]`
127
+ | will match https://github.com/$organization/$repository/[blob|edit]/$revision[/$subpath]/$filePath[$lineNumber]
128
+ | when revision is not provided then requires revision to be specified as argument for scala3doc
129
+ | - `gitlab://<organization>/<repository>`
130
+ | will match https://gitlab.com/$organization/$repository/-/[blob|edit]/$revision[/$subpath]/$filePath[$lineNumber]
131
+ | when revision is not provided then requires revision to be specified as argument for scala3doc
118
132
| - <scaladoc-template>
119
133
| - <template>
120
134
|
@@ -127,7 +141,8 @@ object SourceLinks:
127
141
| - `line`: optional parameter that specify line number within a file
128
142
|
129
143
|
130
- |Template can defined only by subset of sources defined by path prefix represented by `<sub-path>`""" .stripMargin
144
+ |Template can defined only by subset of sources defined by path prefix represented by `<sub-path>`.
145
+ |In such case paths used in templates will be relativized against `<sub-path>`""" .stripMargin
131
146
132
147
def load (
133
148
configs : Seq [String ],
0 commit comments