16
16
17
17
package laika .rewrite .link
18
18
19
- import laika .ast .{ Path , Target }
20
- import laika .config ._
19
+ import laika .ast .{ ExternalTarget , InternalTarget , Path , Target , VirtualPath }
20
+ import laika .config .*
21
21
22
- /** @author Jens Halm
23
- */
24
- case class LinkConfig (
25
- targets : Seq [TargetDefinition ] = Nil ,
26
- apiLinks : Seq [ApiLinks ] = Nil ,
27
- sourceLinks : Seq [SourceLinks ] = Nil
28
- )
22
+ sealed abstract class LinkConfig {
23
+
24
+ /** List of global link definitions, mapping an identifier to an internal or external target.
25
+ *
26
+ * Allows to centralize commonly used URLs and associate them with an id that can be used
27
+ * in markup sources, avoiding the repetitive definition of those URLs in the markup.
28
+ *
29
+ * The use of these ids in markup does not require a directive, it can be used with
30
+ * "native" markup syntax, e.g. `[linkText][linkId]` in Markdown where `linkId` is
31
+ * the identifier defined here.
32
+ */
33
+ def targets : Seq [TargetDefinition ]
34
+
35
+ /** Defines a list of base URLs for API links which allows the use
36
+ * of the `@:api` directive in markup.
37
+ *
38
+ * Different base URLs can be defined for different packages,
39
+ * so that fully qualified class names point to the correct external sources.
40
+ * In markup it is then sufficient to pass the fully qualified class name
41
+ * to the directive (e.g. `@:api(com.foo.Person)`)
42
+ */
43
+ def apiLinks : Seq [ApiLinks ]
44
+
45
+ /** Defines a list of base URLs for links to the sources of referenced classes
46
+ * which allows the use of the `@:source` directive in markup.
47
+ *
48
+ * Different base URLs can be defined for different packages,
49
+ * so that fully qualified class names or a relative path to a markup source file
50
+ * point to the correct external sources.
51
+ * In markup it is then sufficient to pass the fully qualified class name
52
+ * to the directive (e.g. `@:source(com.foo.Person)`) or, when pointing to
53
+ * markup sources, its relative path (e.g. `@:source(setup/intro.md)`)
54
+ */
55
+ def sourceLinks : Seq [SourceLinks ]
56
+
57
+ def addTargets (newTargets : TargetDefinition * ): LinkConfig
58
+
59
+ def addApiLinks (newLinks : ApiLinks * ): LinkConfig
60
+
61
+ def addSourceLinks (newLinks : SourceLinks * ): LinkConfig
62
+
63
+ }
29
64
30
65
object LinkConfig {
31
66
32
- val empty : LinkConfig = LinkConfig (Nil , Nil , Nil )
67
+ private final case class Impl (
68
+ targets : Seq [TargetDefinition ],
69
+ apiLinks : Seq [ApiLinks ],
70
+ sourceLinks : Seq [SourceLinks ]
71
+ ) extends LinkConfig {
72
+
73
+ override def productPrefix : String = " LinkConfig"
74
+
75
+ def addTargets (newTargets : TargetDefinition * ): LinkConfig =
76
+ copy(targets = targets ++ newTargets)
77
+
78
+ def addApiLinks (newLinks : ApiLinks * ): LinkConfig = copy(apiLinks = apiLinks ++ newLinks)
79
+
80
+ def addSourceLinks (newLinks : SourceLinks * ): LinkConfig =
81
+ copy(sourceLinks = sourceLinks ++ newLinks)
82
+
83
+ }
84
+
85
+ val empty : LinkConfig = Impl (Nil , Nil , Nil )
33
86
34
87
implicit val key : DefaultKey [LinkConfig ] = DefaultKey (LaikaKeys .links)
35
88
@@ -42,7 +95,7 @@ object LinkConfig {
42
95
val mappedTargets = targets.map { case (id, targetURL) =>
43
96
TargetDefinition (id, Target .parse(targetURL))
44
97
}
45
- LinkConfig (mappedTargets.toSeq, apiLinks, sourceLinks)
98
+ Impl (mappedTargets.toSeq, apiLinks, sourceLinks)
46
99
}
47
100
}
48
101
@@ -111,19 +164,49 @@ object LinkValidation {
111
164
112
165
}
113
166
114
- case class TargetDefinition (id : String , target : Target )
167
+ sealed abstract class TargetDefinition {
168
+ def id : String
169
+ def target : Target
170
+ }
171
+
172
+ object TargetDefinition {
173
+
174
+ private final case class Impl (id : String , target : Target ) extends TargetDefinition {
175
+ override def productPrefix : String = " TargetDefinition"
176
+ }
177
+
178
+ private [link] def apply (id : String , target : Target ): TargetDefinition = Impl (id, target)
115
179
116
- case class SourceLinks (baseUri : String , suffix : String , packagePrefix : String = " *" )
180
+ def external (id : String , uri : String ): TargetDefinition = Impl (id, ExternalTarget (uri))
181
+
182
+ def internal (id : String , path : VirtualPath ): TargetDefinition = Impl (id, InternalTarget (path))
183
+ }
184
+
185
+ sealed abstract class SourceLinks {
186
+ def baseUri : String
187
+ def suffix : String
188
+ def packagePrefix : String
189
+
190
+ def withPackagePrefix (prefix : String ): SourceLinks
191
+ }
117
192
118
193
object SourceLinks {
119
194
195
+ private final case class Impl (baseUri : String , suffix : String , packagePrefix : String )
196
+ extends SourceLinks {
197
+ override def productPrefix : String = " SourceLinks"
198
+ def withPackagePrefix (prefix : String ): SourceLinks = copy(packagePrefix = prefix)
199
+ }
200
+
201
+ def apply (baseUri : String , suffix : String ): SourceLinks = Impl (baseUri, suffix, " *" )
202
+
120
203
implicit val decoder : ConfigDecoder [SourceLinks ] = ConfigDecoder .config.flatMap { config =>
121
204
for {
122
205
baseUri <- config.get[String ](" baseUri" )
123
206
prefix <- config.get[String ](" packagePrefix" , " *" )
124
207
suffix <- config.get[String ](" suffix" )
125
208
} yield {
126
- SourceLinks (baseUri, suffix, prefix)
209
+ Impl (baseUri, suffix, prefix)
127
210
}
128
211
}
129
212
@@ -137,21 +220,39 @@ object SourceLinks {
137
220
138
221
}
139
222
140
- case class ApiLinks (
141
- baseUri : String ,
142
- packagePrefix : String = " *" ,
143
- packageSummary : String = " index.html"
144
- )
223
+ sealed abstract class ApiLinks {
224
+ def baseUri : String
225
+ def packagePrefix : String
226
+ def packageSummary : String
227
+
228
+ def withPackagePrefix (prefix : String ): ApiLinks
229
+ def withPackageSummary (prefix : String ): ApiLinks
230
+ }
145
231
146
232
object ApiLinks {
147
233
234
+ private final case class Impl (
235
+ baseUri : String ,
236
+ packagePrefix : String ,
237
+ packageSummary : String
238
+ ) extends ApiLinks {
239
+
240
+ override def productPrefix : String = " ApiLinks"
241
+
242
+ def withPackagePrefix (prefix : String ): ApiLinks = copy(packagePrefix = prefix)
243
+
244
+ def withPackageSummary (summary : String ): ApiLinks = copy(packageSummary = summary)
245
+ }
246
+
247
+ def apply (baseUri : String ): ApiLinks = Impl (baseUri, " *" , " index.html" )
248
+
148
249
implicit val decoder : ConfigDecoder [ApiLinks ] = ConfigDecoder .config.flatMap { config =>
149
250
for {
150
251
baseUri <- config.get[String ](" baseUri" )
151
252
prefix <- config.get[String ](" packagePrefix" , " *" )
152
253
summary <- config.get[String ](" packageSummary" , " index.html" )
153
254
} yield {
154
- ApiLinks (baseUri, prefix, summary)
255
+ Impl (baseUri, prefix, summary)
155
256
}
156
257
}
157
258
0 commit comments