-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscaladocPatch.sc
More file actions
119 lines (97 loc) · 6.13 KB
/
scaladocPatch.sc
File metadata and controls
119 lines (97 loc) · 6.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//> using scala 3.6
// run with: scala run scaladocPatch.scala -- ~/git/hub/reqT/reqT-lang/target/scala-3.3.5/api/
// forked from https://github.com/dixine55/Scaladoc-Local-Version-Patcher
import java.io.{BufferedWriter, File, FileWriter}
import java.util.regex.{Matcher, Pattern}
import java.nio.file.{Files, Path, Paths}
if args.length != 1 then println("give api dir as argument")
else if !File(args(0)).exists then println(s"does not exist: ${args(0)}")
val wd = File(args(0))
HtmlFilePatcher(Paths.get(args(0))).processDirectory(wd)
/** HtmlFilePatcher object that handles the reading and patching of broken linking in an html file.
*/
class HtmlFilePatcher(workDir: Path):
/** Reads and stores all HTML files in local directory.*/
val htmlFiles: Seq[File] = Files.list(workDir)
.toArray
.map(_.asInstanceOf[Path])
.filter(file => file.toString.toLowerCase.endsWith(".html") && file.getFileName.toString.toLowerCase != "index.html")
.map(_.toFile).toIndexedSeq
/** Takes the head from htmlFiles and converts it to a string, then proceeds to split it into smaller arrays and removes the .html part.*/
val htmlFilterName: String = htmlFiles.headOption
.map(file => file.toString.split("\\\\").last.dropRight(5))
.getOrElse("")
println(s"Localizing links in $htmlFilterName")
/** Reads an html file
* @param file The HTML file to read and patch.
*/
def processHtmlFile(file: File): Unit =
/** Loads the input from the HTML file. */
val content: String = scala.io.Source.fromFile(file).mkString
/** Defines the content that we want to match and save as groups.
*
* <a\s+ # Match the opening <a> tag and one or more whitespace characters
* (?:href="([^"]+)")? # Match the href attribute and capture its value in group 1
* \s*(?:t="([^"]+)")? # Match the t attribute and capture its value in group 2
* \s*(?:class="([^"]+)")? # Match the class attribute and capture its value in group 3
* \s*.*?> # Match any remaining attributes and the closing > of the <a> tag
* (.*?) # Capture the content between the opening and closing tags in group 4
* </a>
*/
val pattern = Pattern.compile("""<a\s+(?:href="([^"]+)")?\s*(?:t="([^"]+)")?\s*(?:class="([^"]+)")?\s*.*?>(.*?)</a>""")
/** Using the pattern logic, the matcher finds matches fitting those criterias and group them accordingly.
*/
val matcher = pattern.matcher(content)
/** String buffer to rewrite the HTML code to, modifying it as we go.
*/
val modifiedContentA = new StringBuffer()
/** Iterating through the file until we can't find matches according to our pattern criterias
*/
while (matcher.find()) do
/** The href link*/
val url = matcher.group(1)
/** The t value*/
val tAttribute = matcher.group(2)
/** The class value*/
val classAttribute = matcher.group(3)
/** Text between opening and closing a element. ( <a> </a> )*/
val linkText = matcher.group(4)
// Process based on different conditions
/** As long as url isn't empty, apply the following logic*/
if (url != null) then
/** If the filename contains the local directory at the end, then take the local directory.*/
val filename = if (url.contains(s"https://scala-lang.org/api/3.x/$htmlFilterName")) new File(url).getName else url
/** If we've opened the main html file in the top folder, change directory to one level deeper in order to keep folder structure intact.*/
val href = if (htmlFiles.headOption.exists(_.toString == file.getAbsolutePath)) s"$htmlFilterName/$filename" else filename
/** If we have a type attribute and the href is pointing to our local project, but on scala-lang.org, then attach an onclick event and change the link to filename.class */
if (tAttribute != null && url.contains(s"https://scala-lang.org/api/3.x/$htmlFilterName")) then
val modifiedUrl = s"""<a href="$href" t="$tAttribute" onclick="window.location.href='$href'">$linkText</a>"""
matcher.appendReplacement(modifiedContentA, Matcher.quoteReplacement(modifiedUrl))
/** If we have a class attribute that equals documentableName, change the link to our local project. */
else if (classAttribute != null && classAttribute == "documentableName") then
val modifiedUrl = s"""<a href="$href" t="$tAttribute" class="$classAttribute">$linkText</a>"""
matcher.appendReplacement(modifiedContentA, Matcher.quoteReplacement(modifiedUrl))
/** As long as the href doesnt link to scala/Predef or oracle, add an onclick event to the local path for that filename. */
else if (!url.contains("https://scala-lang.org/api/3.x/scala/Predef") && !url.contains("https://docs.oracle.com/")) then
val modifiedUrl =
/** Checks whether the file we've opened is the main one and applies the folder structure logic from val href if true.*/
if (htmlFiles.headOption.exists(_.toString == file.getAbsolutePath)) s"""<a href="$filename" t="$tAttribute" onclick="window.location.href='$filename'">$linkText</a>"""
else s"""<a href="$href" onclick="window.location.href='$href'">$linkText</a>"""
matcher.appendReplacement(modifiedContentA, Matcher.quoteReplacement(modifiedUrl))
else
matcher.appendReplacement(modifiedContentA, Matcher.quoteReplacement(matcher.group()))
matcher.appendTail(modifiedContentA)
/** Writes back the modified content to the HTML file.*/
val writer = new BufferedWriter(new FileWriter(file))
writer.write(modifiedContentA.toString)
writer.close()
/** Opens up a directory and it's subdirectiories looking for files that ends with .html and adds found ones to our files array.*/
def apply(): Unit = processDirectory(workDir.toFile)
def processDirectory(directory: File): Unit =
val files: Array[File] = directory.listFiles()
if (files != null)
for (file <- files)
if (file.isDirectory)
processDirectory(file)
else if (file.getName.endsWith(".html"))
processHtmlFile(file)