Skip to content

Commit 0d3a27a

Browse files
committed
PoC
1 parent b7405bb commit 0d3a27a

File tree

12 files changed

+240
-0
lines changed

12 files changed

+240
-0
lines changed

build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ val `tasty-core-bootstrapped` = Build.`tasty-core-bootstrapped`
2222
val `tasty-core-scala2` = Build.`tasty-core-scala2`
2323
val scala3doc = Build.scala3doc
2424
val `scala3doc-testcases` = Build.`scala3doc-testcases`
25+
val `scala3doc-js` = Build.`scala3doc-js`
2526
val `scala3-bench-run` = Build.`scala3-bench-run`
2627
val dist = Build.dist
2728
val `community-build` = Build.`community-build`

project/Build.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import sbtbuildinfo.BuildInfoPlugin.autoImport._
2828

2929
import scala.util.Properties.isJavaAtLeast
3030

31+
import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._
32+
3133
object MyScalaJSPlugin extends AutoPlugin {
3234
import Build._
3335

@@ -1228,6 +1230,8 @@ object Build {
12281230
lazy val `scala3doc` = project.in(file("scala3doc")).asScala3doc
12291231
lazy val `scala3doc-testcases` = project.in(file("scala3doc-testcases")).asScala3docTestcases
12301232

1233+
lazy val `scala3doc-js` = project.in(file("scala3doc-js")).asScala3docJs
1234+
12311235
// sbt plugin to use Dotty in your own build, see
12321236
// https://github.com/lampepfl/scala3-example-project for usage.
12331237
lazy val `sbt-dotty` = project.in(file("sbt-dotty")).
@@ -1643,6 +1647,17 @@ object Build {
16431647
def asScala3docTestcases: Project =
16441648
project.dependsOn(`scala3-compiler-bootstrapped`).settings(commonBootstrappedSettings)
16451649

1650+
def asScala3docJs: Project =
1651+
project.
1652+
enablePlugins(MyScalaJSPlugin).
1653+
dependsOn(`scala3-library-bootstrappedJS`).
1654+
settings(
1655+
fork in Test := false,
1656+
scalaJSUseMainModuleInitializer := true,
1657+
libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0").withDottyCompat(scalaVersion.value)
1658+
)
1659+
1660+
16461661
def asDist(implicit mode: Mode): Project = project.
16471662
enablePlugins(PackPlugin).
16481663
withCommonSettings.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
:root {
2+
--inkuire-logo-size: 20px;
3+
}
4+
5+
#scala3doc-search {
6+
margin-top: 2px;
7+
cursor: pointer;
8+
position: fixed;
9+
top: 0;
10+
right: 20px;
11+
z-index: 5;
12+
}
13+
14+
#scala3doc-search::before {
15+
content: "";
16+
display:block;
17+
height: var(--inkuire-logo-size);
18+
width: var(--inkuire-logo-size);
19+
}
20+
21+
#scala3doc-searchbar.hidden {
22+
display: none;
23+
}
24+
25+
#scala3doc-searchbar {
26+
position: absolute;
27+
top: 50px;
28+
right: 40px;
29+
width: calc(100% - 360px);
30+
box-shadow: 0 2px 16px 0 rgba(0, 42, 76, 0.15);
31+
font-size: 13px;
32+
font-family: system-ui, -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, Arial, sans-serif;
33+
}
34+
35+
#scala3doc-searchbar-input {
36+
width: 100%;
37+
min-height: 32px;
38+
border: none;
39+
border-bottom: 1px solid #bbb;
40+
padding: 10px;
41+
}
42+
43+
#scala3doc-searchbar-input:focus {
44+
outline: none;
45+
}
46+
47+
#scala3doc-searchbar-results {
48+
background: white;
49+
display: flex;
50+
flex-direction: column;
51+
max-height: 500px;
52+
overflow: auto;
53+
}
54+
55+
.scala3doc-searchbar-result {
56+
line-height: 32px;
57+
padding-left: 10px;
58+
padding-right: 10px;
59+
}
60+
61+
.scala3doc-searchbar-result:first-of-type {
62+
margin-top: 10px;
63+
}
64+
65+
.scala3doc-searchbar-result:hover {
66+
background-color: #d4edff;
67+
}
68+
69+
.scala3doc-searchbar-result a {
70+
color: #1f2326;
71+
}
72+
73+
.scala3doc-searchbar-result .scala3doc-searchbar-location {
74+
color: gray;
75+
}
76+
77+
#searchBar {
78+
display: inline-flex;
79+
}
80+
81+
.pull-right {
82+
float: right;
83+
margin-left: auto
84+
}

scala3doc-js/src/Globals.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dotty.dokka
2+
3+
import scala.scalajs.js
4+
import scala.scalajs.js.annotation.JSGlobalScope
5+
6+
@js.native
7+
@JSGlobalScope
8+
object Globals extends js.Object {
9+
val pathToRoot: String = js.native
10+
}

scala3doc-js/src/Main.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dotty.dokka
2+
3+
object Main extends App {
4+
def initializeSearchbar(): Unit = Searchbar()
5+
6+
initializeSearchbar()
7+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dotty.dokka
2+
3+
import scala.scalajs.js
4+
5+
@js.native
6+
trait PageEntryJS extends js.Object {
7+
val name: String = js.native
8+
val description: String = js.native
9+
val location: String = js.native
10+
val searchKeys: js.Array[String] = js.native
11+
}
12+
13+
case class PageEntry(
14+
name: String,
15+
description: String,
16+
location: String,
17+
searchKeys: Array[String]
18+
)
19+
20+
object PageEntry {
21+
def apply(jsObj: PageEntryJS): PageEntry = PageEntry(
22+
jsObj.name,
23+
jsObj.description,
24+
jsObj.location,
25+
jsObj.searchKeys.toArray
26+
)
27+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dotty.dokka
2+
3+
class Searchbar {
4+
val pages = SearchbarGlobals.pages.toList.map(PageEntry.apply)
5+
val engine = SearchbarEngine(pages)
6+
val component = SearchbarComponent(engine.query)
7+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package dotty.dokka
2+
3+
import org.scalajs.dom._
4+
import org.scalajs.dom.html.Input
5+
6+
class SearchbarComponent(val callback: (String) => List[PageEntry]) {
7+
extension (p: PageEntry)
8+
def toHTML = {
9+
val wrapper = document.createElement("div")
10+
wrapper.classList.add("scala3doc-searchbar-result")
11+
wrapper.classList.add("monospace")
12+
13+
val resultA = document.createElement("a").asInstanceOf[html.Anchor]
14+
resultA.href = Globals.pathToRoot + p.location
15+
resultA.text = s"${p.name}"
16+
17+
val location = document.createElement("span")
18+
location.classList.add("pull-right")
19+
location.classList.add("scala3doc-searchbar-location")
20+
location.textContent = p.description
21+
22+
wrapper.appendChild(resultA)
23+
wrapper.appendChild(location)
24+
wrapper
25+
}
26+
27+
def handleNewQuery(query: String) = {
28+
val result = callback(query).map(_.toHTML)
29+
while (resultsDiv.hasChildNodes()) resultsDiv.removeChild(resultsDiv.lastChild)
30+
result.foreach(resultsDiv.appendChild)
31+
}
32+
33+
private val logoClick: html.Span = {
34+
val element = document.createElement("span").asInstanceOf[html.Span]
35+
element.id = "scala3doc-search"
36+
element.onclick = (event: Event) =>
37+
if (rootDiv.className.contains("hidden"))
38+
rootDiv.className = rootShowClasses
39+
else rootDiv.className = rootHiddenClasses
40+
document.getElementById("searchBar").appendChild(element)
41+
element
42+
}
43+
44+
private val input: html.Input = {
45+
val element = document.createElement("input").asInstanceOf[html.Input]
46+
element.id = "scala3doc-searchbar-input"
47+
element.addEventListener("keyup", (e) => handleNewQuery(e.target.asInstanceOf[html.Input].value))
48+
element
49+
}
50+
51+
private val resultsDiv: html.Div = {
52+
val element = document.createElement("div").asInstanceOf[html.Div]
53+
element.id = "scala3doc-searchbar-results"
54+
element
55+
}
56+
57+
private val rootHiddenClasses = "hidden"
58+
private val rootShowClasses = ""
59+
private val rootDiv: html.Div = {
60+
val element = document.createElement("div").asInstanceOf[html.Div]
61+
element.addEventListener("click", (e: Event) => e.stopPropagation())
62+
logoClick.addEventListener("click", (e: Event) => e.stopPropagation())
63+
document.body.addEventListener("click", (e: Event) => element.className = rootHiddenClasses)
64+
element.className = rootHiddenClasses
65+
element.id = "scala3doc-searchbar"
66+
element.appendChild(input)
67+
element.appendChild(resultsDiv)
68+
document.body.appendChild(element)
69+
element
70+
}
71+
72+
handleNewQuery("")
73+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dotty.dokka
2+
3+
import scala.scalajs.js
4+
import scala.scalajs.js.annotation.JSGlobalScope
5+
6+
@js.native
7+
@JSGlobalScope
8+
object SearchbarGlobals extends js.Object {
9+
val pages: js.Array[PageEntryJS] = js.native
10+
}

scala3doc-js/src/searchbar/engine/Matchers.scala

Whitespace-only changes.

scala3doc-js/src/searchbar/engine/QueryParser.scala

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package dotty.dokka
2+
3+
class SearchbarEngine(pages: List[PageEntry]) {
4+
//TODO: Query should be parsed by QueryParser to list of filtering strategies called Matchers
5+
def query(query: String): List[PageEntry] = pages
6+
}

0 commit comments

Comments
 (0)