All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.scaladoc.tasty.comments.markdown.SectionRenderingExtension.scala Maven / Gradle / Ivy

There is a newer version: 3.6.0-RC1-bin-20240903-21a3d39-NIGHTLY
Show newest version
package dotty.tools.scaladoc
package tasty.comments.markdown

import com.vladsch.flexmark.html.*
import com.vladsch.flexmark.html.renderer.*
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler.CustomNodeRenderer
import com.vladsch.flexmark.parser.*
import com.vladsch.flexmark.ext.wikilink.*
import com.vladsch.flexmark.ext.wikilink.internal.WikiLinkLinkRefProcessor
import com.vladsch.flexmark.util.ast.*
import com.vladsch.flexmark.util.options.*
import com.vladsch.flexmark.util.sequence.BasedSequence
import com.vladsch.flexmark.*
import com.vladsch.flexmark.ast.FencedCodeBlock

import scala.collection.mutable
import com.vladsch.flexmark.util.data.MutableDataHolder
import com.vladsch.flexmark.util.html.Attributes
import com.vladsch.flexmark.util.html.AttributeImpl
import com.vladsch.flexmark.util.data.DataHolder
import com.vladsch.flexmark.util.html.Attribute
import com.vladsch.flexmark.util.html.MutableAttributes


object SectionRenderingExtension extends HtmlRenderer.HtmlRendererExtension:
  def rendererOptions(opt: MutableDataHolder): Unit = ()

  case class AnchorLink(link: String) extends BlankLine(BasedSequence.EmptyBasedSequence())
  object SectionHandler extends CustomNodeRenderer[Section]:
    val repeatedIds: mutable.Map[(NodeRendererContext, String), Int] = mutable.Map()
    val idGenerator = new HeaderIdGenerator.Factory().create()
    override def render(node: Section, c: NodeRendererContext, html: HtmlWriter): Unit =
      val Section(header, body) = node
      val headerText = header.getText.toString
      val idSuffix = repeatedIds.getOrElseUpdate((c, headerText), 0)
      val ifSuffixStr = if(idSuffix == 0) then "" else idSuffix.toString
      repeatedIds.update((c, headerText), idSuffix + 1)

      /* #19524 flexmark's `HeaderIdGenerator` does not appear to be thread-safe,
       * so we protect its usage with a full `synchronize`.
       */
      val id = idGenerator.synchronized {
        idGenerator.getId(headerText + ifSuffixStr)
      }

      val anchor = AnchorLink(s"#$id")
      val headerClass: String = header.getLevel match
        case 1 => "h500"
        case 2 => "h500"
        case 3 => "h400"
        case 4 => "h300"
        case _ => "h50"
      val attributes = MutableAttributes()
      attributes.addValue("class", headerClass)
      val embeddedAttributes = EmbeddedAttributeProvider.EmbeddedNodeAttributes(header, attributes)
      header.prependChild(embeddedAttributes)
      header.prependChild(anchor)
      html.attr("id", id).withAttr.tag("section", false, false, () => {
        c.render(header)
        body.foreach(c.render)
      })

  object AnchorLinkHandler extends CustomNodeRenderer[AnchorLink]:
    override def render(node: AnchorLink, c: NodeRendererContext, html: HtmlWriter): Unit =
      html.attr(AttributeImpl.of("href", node.link), AttributeImpl.of("class", "anchor")).withAttr.tag("a", false, false, () => ())


  object Render extends NodeRenderer:
    override def getNodeRenderingHandlers: JSet[NodeRenderingHandler[?]] =
      JSet(
        new NodeRenderingHandler(classOf[Section], SectionHandler),
        new NodeRenderingHandler(classOf[AnchorLink], AnchorLinkHandler)
      )

  object Factory extends NodeRendererFactory:
    override def apply(options: DataHolder): NodeRenderer = Render


  def extend(htmlRendererBuilder: HtmlRenderer.Builder, tpe: String): Unit =
    htmlRendererBuilder.nodeRendererFactory(Factory)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy