@@ -22,6 +22,7 @@ import org.intellij.markdown.ast.getTextInNode
22
22
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
23
23
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
24
24
import org.intellij.markdown.html.*
25
+ import org.intellij.markdown.html.entities.EntityConverter
25
26
import org.intellij.markdown.parser.LinkMap
26
27
import org.intellij.markdown.parser.MarkdownParser
27
28
import org.rust.cargo.util.AutoInjectedCrates.STD
@@ -137,13 +138,12 @@ private class RustDocMarkdownFlavourDescriptor(
137
138
generatingProviders[MarkdownElementTypes .ATX_2 ] = SimpleTagProvider (" h3" )
138
139
generatingProviders[MarkdownElementTypes .CODE_FENCE ] = RsCodeFenceProvider (context, renderMode)
139
140
140
- val absolutizeAnchorLinks = true
141
141
generatingProviders[MarkdownElementTypes .SHORT_REFERENCE_LINK ] =
142
- RsReferenceLinksGeneratingProvider (linkMap, uri ? : baseURI, absolutizeAnchorLinks )
142
+ RsReferenceLinksGeneratingProvider (linkMap, uri ? : baseURI, resolveAnchors = true )
143
143
generatingProviders[MarkdownElementTypes .FULL_REFERENCE_LINK ] =
144
- RsReferenceLinksGeneratingProvider (linkMap, uri ? : baseURI, absolutizeAnchorLinks )
144
+ RsReferenceLinksGeneratingProvider (linkMap, uri ? : baseURI, resolveAnchors = true )
145
145
generatingProviders[MarkdownElementTypes .INLINE_LINK ] =
146
- RsInlineLinkGeneratingProvider (uri ? : baseURI, absolutizeAnchorLinks )
146
+ RsInlineLinkGeneratingProvider (uri ? : baseURI, resolveAnchors = true )
147
147
148
148
return generatingProviders
149
149
}
@@ -250,20 +250,48 @@ enum class RsDocRenderMode {
250
250
INLINE_DOC_COMMENT
251
251
}
252
252
253
- private fun markLinkAsLanguageItemIfItIsValidRustPath (link : CharSequence ): CharSequence {
254
- return if ( link.none { it in " /.#" }) " ${ DocumentationManagerProtocol . PSI_ELEMENT_PROTOCOL }$link " else link
253
+ private fun linkIsProbablyValidRustPath (link : CharSequence ): Boolean {
254
+ return link.none { it in " /.#" || it.isWhitespace() }
255
255
}
256
256
257
- open class RsReferenceLinksGeneratingProvider (linkMap : LinkMap , baseURI : URI ? , resolveAnchors : Boolean )
257
+ private fun markLinkAsLanguageItemIfItIsRustPath (link : CharSequence ): CharSequence {
258
+ return if (linkIsProbablyValidRustPath(link)) " ${DocumentationManagerProtocol .PSI_ELEMENT_PROTOCOL }$link " else link
259
+ }
260
+
261
+ open class RsReferenceLinksGeneratingProvider (private val linkMap : LinkMap , baseURI : URI ? , resolveAnchors : Boolean )
258
262
: ReferenceLinksGeneratingProvider (linkMap, baseURI, resolveAnchors) {
259
263
override fun renderLink (visitor : HtmlGenerator .HtmlGeneratingVisitor , text : String , node : ASTNode , info : RenderInfo ) {
260
- super .renderLink(visitor, text, node, info.copy(destination = markLinkAsLanguageItemIfItIsValidRustPath(info.destination)))
264
+ super .renderLink(visitor, text, node, info.copy(destination = markLinkAsLanguageItemIfItIsRustPath(info.destination)))
265
+ }
266
+
267
+ override fun getRenderInfo (text : String , node : ASTNode ): RenderInfo ? {
268
+ val label = node.children.firstOrNull { it.type == MarkdownElementTypes .LINK_LABEL } ? : return null
269
+ val labelText = label.getTextInNode(text)
270
+
271
+ val linkInfo = linkMap.getLinkInfo(labelText)
272
+ val (linkDestination, linkTitle) = if (linkInfo != null ) {
273
+ linkInfo.destination to linkInfo.title
274
+ } else {
275
+ // then maybe it's implied shortcut reference link, i.e. shortcut reference link without a matching link reference definition
276
+ // (see https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html#implied-shortcut-reference-links)
277
+ // so "[Iterator]" is the same as "[Iterator](Iterator)" and will be eventually rendered as "<a href="psi_element://Iterator">Iterator</a>"
278
+ val linkText = labelText.removeSurrounding(" [" , " ]" ).removeSurrounding(" `" )
279
+ if (! linkIsProbablyValidRustPath(linkText)) return null
280
+ linkText to null
281
+ }
282
+
283
+ val linkTextNode = node.children.firstOrNull { it.type == MarkdownElementTypes .LINK_TEXT }
284
+ return RenderInfo (
285
+ linkTextNode ? : label,
286
+ EntityConverter .replaceEntities(linkDestination, processEntities = true , processEscapes = true ),
287
+ linkTitle?.let { EntityConverter .replaceEntities(it, processEntities = true , processEscapes = true ) }
288
+ )
261
289
}
262
290
}
263
291
264
292
open class RsInlineLinkGeneratingProvider (baseURI : URI ? , resolveAnchors : Boolean )
265
293
: InlineLinkGeneratingProvider (baseURI, resolveAnchors) {
266
294
override fun renderLink (visitor : HtmlGenerator .HtmlGeneratingVisitor , text : String , node : ASTNode , info : RenderInfo ) {
267
- super .renderLink(visitor, text, node, info.copy(destination = markLinkAsLanguageItemIfItIsValidRustPath (info.destination)))
295
+ super .renderLink(visitor, text, node, info.copy(destination = markLinkAsLanguageItemIfItIsRustPath (info.destination)))
268
296
}
269
297
}
0 commit comments