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

dotty.tools.scaladoc.site.StaticSiteContext.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 site

import java.io.File
import java.nio.file.Files
import java.nio.file.FileVisitOption
import java.nio.file.Path
import java.nio.file.Paths

import scala.jdk.CollectionConverters._
import scala.util.control.NonFatal

class StaticSiteContext(
  val root: File,
  val args: Scaladoc.Args,
  val sourceLinks: SourceLinks,
  val snippetCompilerArgs: snippets.SnippetCompilerArgs,
  val snippetChecker: snippets.SnippetChecker)(using val outerCtx: CompilerContext):

  var memberLinkResolver: String => Option[DRI] = _ => None

  val docsPath = root.toPath.resolve("_docs")
  val blogPath = root.toPath.resolve("_blog")

  def resolveNewBlogPath(stringPath: String): Path =
    if stringPath.nonEmpty then root.toPath.resolve(stringPath)
    else blogPath

  def relativize(path: Path): Path =
    if args.apiSubdirectory then
      docsPath.relativize(path)
    else
      val relativised = docsPath.relativize(path)
      Paths.get("docs").resolve(relativised)

  val siteExtensions = Set(".html", ".md")

  lazy val layouts: Map[String, TemplateFile] =
    val layoutRoot = new File(root, "_layouts")
    val dirs: Array[File] = Option(layoutRoot.listFiles()).getOrElse(Array())
    dirs.map { it => loadTemplateFile(it)(using this) }.map { it => it.name -> it }.toMap

  lazy val staticSiteRoot: StaticSiteRoot = StaticSiteLoader(root, args)(using this, outerCtx).load()

  lazy val allTemplates =
    def process(l: LoadedTemplate): List[LoadedTemplate] =
      l +: l.children.flatMap(process)
    process(staticSiteRoot.rootTemplate)
  /** Handles redirecting from multiple locations to one page
   *
   * For each entry in redirectFrom setting, create a page which contains code that redirects you to the page where the redirectFrom is defined.
   */
  lazy val redirectTemplates: Seq[(LoadedTemplate, DRI, DRI)] =
    allTemplates.flatMap { loadedTemplate =>
      val redirectFrom = loadedTemplate.templateFile.settings.getOrElse("page", Map.empty).asInstanceOf[Map[String, Object]].get("redirectFrom")
      def redirectToTemplate(redirectFrom: String) =
        val path = if redirectFrom.startsWith("/")
          then docsPath.resolve(redirectFrom.drop(1))
          else loadedTemplate.file.toPath.resolveSibling(redirectFrom)
        val driFrom = driFor(path)
        val driTo = driFor(loadedTemplate.file.toPath)
        (LoadedTemplate(layouts("redirect"), List.empty, path.toFile), driFrom, driTo)
      redirectFrom.map {
        case redirectFrom: String => Seq(redirectToTemplate(redirectFrom))
        case redirects: List[?] => redirects.asInstanceOf[List[String]].map(redirectToTemplate)
      }.getOrElse(Nil)
    }

  def driForLink(loadedTemplateFile: File, link: String): Seq[DRI] =
    def possibleLinks(link: String): Seq[Path] =
      // Destination file of template
      val templateDestLocation = loadedTemplateFile.toPath
      // Source file of template (may not exist - e.g. redirect templates)
      val templateSourceLocation = staticSiteRoot.reverseSiteMappings.get(templateDestLocation)

      // Check if link is relative or absolute
      try
        if link.startsWith("/")
        then Seq(root.toPath.resolve(link.drop(1)))
        else Seq(templateDestLocation.getParent.resolve(link).normalize) ++
          templateSourceLocation.map(_.getParent.resolve(link).normalize)
      catch
        case NonFatal(_) => Seq.empty

    // Try to strip site extension and create all possible file paths
    val fileNames = if siteExtensions.exists(link.endsWith(_))
      then {
        val withoutExt = siteExtensions.find(link.endsWith(_)).fold(link)(ext => link.stripSuffix(ext))
        siteExtensions.map(withoutExt + _).toSeq
      }
      else Seq(link)

    val baseFiles = fileNames.flatMap(possibleLinks)

    // If file exists in source files, map it to destination file. If file exists in destination file, just take it.
    val links = baseFiles.flatMap(p =>
      Option.when(staticSiteRoot.sources.contains(p))(p).map(p => staticSiteRoot.siteMappings(p))
        .orElse(Option.when(staticSiteRoot.dests.contains(p))(p))
    )

    links match {
      case link :: rest => Seq(driFor(link))
      case Nil => memberLinkResolver(link).toSeq
    }

  def driFor(dest: Path): DRI =
    val rawFilePath = relativize(dest)
    val pageName = dest.getFileName.toString
    val dotIndex = pageName.lastIndexOf('.')

    val relativePath =
      if (dotIndex < 0) rawFilePath.resolve("index")
      else rawFilePath.resolveSibling(pageName.substring(0, dotIndex))

    DRI.forPath(relativePath)

  def pathFromRoot(myTemplate: LoadedTemplate) = root.toPath.relativize(myTemplate.file.toPath)

  val projectWideProperties =
    Seq("projectName" -> args.name) ++
      args.projectVersion.map("projectVersion" -> _)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy