diff --git a/build.sbt b/build.sbt
index 4725f5357..507ef83ed 100644
--- a/build.sbt
+++ b/build.sbt
@@ -13,4 +13,5 @@ val testsChrome = Build.testsChrome
val testsFirefox = Build.testsFirefox
val testsNodeJsdom = Build.testsNodeJsdom
val example = Build.example
-val readme = Build.readme
+val jsdocs = Build.jsdocs
+val docs = Build.docs
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 000000000..733d0a335
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,225 @@
+---
+layout: doc
+title: scalajs-dom
+---
+
+#### Statically typed DOM API for Scala.js
+
+Scalajs-dom provides a nice statically typed interface to the DOM such that it can be called from Scala code without resorting to `js.Dynamic`.
+All javascript globals functions, singletons and classes are members of the `org.scalajs.dom`,
+`org.scalajs.dom.html`, `org.scalajs.dom.svg`, etc. packages.
+
+For example:
+
+```scala
+import org.scalajs.dom
+
+def main() = dom.window.alert("Hi from scala-js-dom!")
+```
+
+## Usage
+
+Add the following to your sbt build definition:
+
+```scala
+libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "@VERSION@"
+```
+
+then enjoy the types available in org.scalajs.dom. scalajs-dom @VERSION@ is built and published for Scala.js 1.7+ with Scala 2.11, 2.12, 2.13, and 3.1+.
+
+To begin with, scalajs-dom organizes the full-list of DOM APIs into a number of buckets:
+
+- dom.html: HTML element APIs
+- dom.svg: SVG element APIs
+- dom.idb: IndexedDB APIs
+- dom: Miscellanious, unclassified APIs
+
+Most names have been shortened from names of the raw browser APIs, since the namespacing avoids collisions. By convention these types are imported qualified: e.g. as `html.Canvas` instead of directly as `Canvas`.
+
+## Examples
+
+You can start using the bindings using the following import:
+
+```scala mdoc:js:shared
+import org.scalajs.dom._
+```
+
+### Appending a child to a `Node`
+
+```scala mdoc:js:shared
+def appendElement(div: html.Div): Unit = {
+ val child = document.createElement("div")
+ child.textContent = "I can add elements to DOM elements!"
+ div.appendChild(child)
+}
+```
+
+```scala mdoc:js:invisible
+
+---
+val mouseArea = document.getElementById("mouse-container").asInstanceOf[html.Div]
+val info = document.getElementById("demo2-output").asInstanceOf[html.Pre]
+showOnMouseCoordinates(mouseArea, info)
+```
+
+### Storing an item in `localStorage`
+
+```scala mdoc:js:shared
+def storeInputInLocalStorage(input: html.Input, box: html.Div) = {
+ val key = "myKey"
+ input.value = window.localStorage.getItem(key)
+
+ input.onkeyup = { (e: Event) =>
+ window.localStorage.setItem(key, input.value)
+
+ box.textContent = s"Saved: ${input.value} to local storage!"
+ }
+}
+```
+
+```scala mdoc:js:invisible
+
+
+
+---
+val input = document.getElementById("demo3-input").asInstanceOf[html.Input]
+val output = document.getElementById("demo3-output").asInstanceOf[html.Div]
+storeInputInLocalStorage(input, output)
+```
+
+### Using `Canvas` to draw
+
+```scala mdoc:js:shared
+type Context2D = CanvasRenderingContext2D
+
+def drawCuteSmiley(canvas: html.Canvas) = {
+ val context = canvas.getContext("2d").asInstanceOf[Context2D]
+
+ val size = 150
+ canvas.width = size
+ canvas.height = size
+
+ context.strokeStyle = "red"
+ context.lineWidth = 3
+ context.beginPath()
+ context.moveTo(size/3, 0)
+ context.lineTo(size/3, size/3)
+ context.moveTo(size*2/3, 0)
+ context.lineTo(size*2/3, size/3)
+ context.moveTo(size, size/2)
+ context.arc(size/2, size/2, size/2, 0, 3.14)
+
+ context.stroke()
+}
+```
+
+```scala mdoc:js:invisible
+
+---
+
+val canvas = document.getElementById("demo4-canvas").asInstanceOf[html.Canvas]
+drawCuteSmiley(canvas)
+```
+
+### Using `Fetch` to make API calls in the browser
+
+```scala mdoc:js:shared
+import scala.concurrent.ExecutionContext.Implicits.global
+
+def fetchBoredApi(element: html.Pre) = {
+ val url = "https://www.boredapi.com/api/activity"
+
+ val responseText = for {
+ response <- fetch(url).toFuture
+ text <- response.text().toFuture
+ } yield {
+ text
+ }
+
+ for (text <- responseText)
+ element.textContent = text
+}
+```
+
+```scala mdoc:js:invisible
+
+
+---
+val output = document.getElementById("demo5-output").asInstanceOf[html.Pre]
+document.getElementById("demo5-btn").addEventListener("click", (ev: Event) => {
+ fetchBoredApi(output)
+})
+```
+
+### Styling an HTML element
+
+```scala mdoc:js:shared
+def changeColor(div: html.Div) = {
+ val colors = Seq("red", "green", "blue")
+ val index = util.Random.nextInt(colors.length)
+
+ div.style.color = colors(index)
+}
+```
+
+```scala mdoc:js:invisible
+
Color me!
+
+---
+document.getElementById("demo6-btn").addEventListener("click", (ev: Event) => {
+ changeColor(document.getElementById("demo6-text").asInstanceOf[html.Div])
+})
+```
+
+### Encode in base64
+
+```scala mdoc:js:shared
+def encodeBase64(in: html.Input, out: html.Div) = {
+ in.onkeyup = { (e: Event) =>
+ out.textContent = window.btoa(in.value)
+ }
+}
+```
+
+```scala mdoc:js:invisible
+
+
+---
+val input = document.getElementById("demo7-input").asInstanceOf[html.Input]
+val output = document.getElementById("demo7-output").asInstanceOf[html.Div]
+encodeBase64(input, output)
+```
+
+## Contributing
+
+The DOM API is always evolving, and `scalajs-dom` tries to provide a thin-but-idiomatic Scala interface to modern browser APIs, without breaking the spec.
+
+If you see something that you think can be improved, feel free to send a pull request.
+See our [Contributing Guide](https://github.com/scala-js/scala-js-dom/blob/main/CONTRIBUTING.md) for a detailed overview for starting hacking on `scala-js-dom` and making a PR!
diff --git a/prePR.sbt b/prePR.sbt
index 100a174e9..34733824c 100644
--- a/prePR.sbt
+++ b/prePR.sbt
@@ -41,7 +41,8 @@ ThisBuild / prePR_nonCross := Def.sequential(
Def.taskDyn {
if (scalaVersion.value.startsWith("2.12."))
- Def.task[Unit]((readme / Compile / compile).value)
+ // TODO should this really be docs / Compile?
+ Def.task[Unit]((docs / Compile / compile).value)
else
Def.task(())
},
diff --git a/project/Build.scala b/project/Build.scala
index bab9374c2..98c428f85 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -14,9 +14,11 @@ import sbtbuildinfo.BuildInfoPlugin
import sbtbuildinfo.BuildInfoPlugin.autoImport._
import scalafix.sbt.ScalafixPlugin
import scalafix.sbt.ScalafixPlugin.autoImport._
-import scalatex.ScalatexReadme
import Dependencies._
import Lib._
+import mdoc.MdocPlugin
+import sbtdynver.DynVerPlugin.autoImport.previousStableVersion
+import mdoc.MdocPlugin.autoImport._
object Build {
@@ -37,7 +39,6 @@ object Build {
testsFirefox,
testsNodeJsdom,
example,
- // readme, // This is a Scala 2.12 only module
)
lazy val dom = project
@@ -141,18 +142,20 @@ object Build {
.enablePlugins(ScalaJSPlugin)
.configure(commonSettings, crossScala, preventPublication)
- lazy val readme =
- ScalatexReadme(
- projectId = "readme",
- wd = file(""),
- url = "https://github.com/scala-js/scala-js-dom/tree/main",
- source = "Index",
- autoResources = Seq("example-opt.js"),
- )
- .configure(commonSettings, preventPublication)
+ lazy val jsdocs = project
+ .in(file("mdocs-js"))
+ .dependsOn(dom)
+ .enablePlugins(ScalaJSPlugin)
+ .configure(commonSettings, crossScala, preventPublication)
+
+ lazy val docs = project
+ .in(file("mdocs"))
.settings(
- scalaVersion := Ver.scala212,
- Compile / resources += (example / Compile / fullOptJS).value.data,
+ mdocJS := Some(jsdocs),
+ mdocVariables := Map(
+ "VERSION" -> previousStableVersion.value.getOrElse("2.3.0")
+ )
)
-
+ .enablePlugins(MdocPlugin)
+ .configure(commonSettings, crossScala, preventPublication)
}
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 3ff46f291..9bd17f7b1 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -7,3 +7,4 @@ addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
addSbtPlugin("com.lihaoyi" % "scalatex-sbt-plugin" % "0.3.11")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
+addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7")
diff --git a/readme/Index.scalatex b/readme/Index.scalatex
deleted file mode 100644
index 34b6a7cf6..000000000
--- a/readme/Index.scalatex
+++ /dev/null
@@ -1,163 +0,0 @@
-@import ammonite.ops._
-@import Main._
-@a(
- href:="https://github.com/scala-js/scala-js-dom",
- position.absolute,
- top:=0,right:=0,border:=0,
- img(
- src:="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67",
- alt:="Fork me on GitHub"
- )
-)
-@def pair(example: String,
- frags: Seq[scalatags.Text.TypedTag[String]],
- autorun: Boolean = false) = {
- val ids = (0 until frags.length).map(_ => util.Random.nextInt(999999))
- val queries = ids.map(id => s"document.getElementById('$id')").mkString(", ")
- div(
- div(width:="50%", float.left)(
- hl.ref(
- pwd/'example/'src/'main/'scala/'example/"Example.scala",
- Seq(s"object $example", "main")
- )
- ),
- div(width:="50%", float.left, padding:="8px", boxSizing.`border-box`)(
- if (!autorun)
- a(cls:="pure-button", onclick:=s"Example$example.main($queries)", "Run"),
- div(
- frags.zip(ids).map{case (f, i) => f(id:=i, backgroundColor:="#fafafa")}
- ),
- if (autorun)
- script(s"Example$example.main($queries)")
- ),
- div(clear.both)
- )
-}
-
-@scalatags.Text.tags2.style
- pre{
- margin: 0px;
-
- }
-
-@sect{scala-js-dom}
-
- @p
- Scala-js-dom provides a nice statically typed interface to the DOM such that it can be called from Scala code without resorting to @hl.scala{js.Dynamic}. All javascript globals functions, singletons and classes are members of the @hl.scala{org.scalajs.dom}, @hl.scala{org.scalajs.dom.html}, @hl.scala{org.scalajs.dom.svg}, etc. packages. For example:
-
- @pair("Alert", Nil)
-
- @p
- Will cause a javascript alert box saying `Hi from Scala-js-dom` to appear. Other javascript classes and objects can be similarly accessed e.g. @hl.scala{new dom.XMLHttpRequest()} to perform a new Ajax request, @hl.scala{dom.document} to access the global @hl.scala{document} object, or @hl.scala{html.Div} to to refer to the type of a @hl.scala{
} element.
-
- @sect{Usage}
- @p
- Add the following to your sbt build definition:
-
- @hl.scala
- libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.2.0"
-
- @p
- then enjoy the types available in @hl.scala{org.scalajs.dom}. scalajs-dom 2.2.0 is built and published for Scala.js 1.5+ with Scala 2.11, 2.12, 2.13, and 3.0+.
-
- @p
- To begin with, @code{scala-js-dom} organizes the full-list of DOM APIs into a number of buckets:
-
- @ul
- @li
- @code{dom.html}: HTML element APIs
- @li
- @code{dom.svg}: SVG element APIs
- @li
- @code{dom.idb}: IndexedDB APIs
- @li
- @code{dom.css}: CSS APIs
- @li
- @code{dom}: Miscellanious, unclassified APIs
-
- @p
- Most names have been shortened from names of the @a("raw browser APIs", href:="https://developer.mozilla.org/en-US/docs/Web/API"), since the namespacing avoids collisions. By convention these types are imported qualified: e.g. as @hl.scala{html.Canvas} instead of directly as @hl.scala{Canvas}. There is also the @code{dom.raw} namespace which contains everything with their full, un-shortened name.
-
- @p
- Here are some examples to get you started:
-
- @sect{Node.appendChild}
- @pair(
- "NodeAppendChild",
- Seq(div("div"))
- )
-
- @sect{Node.onmousemove}
- @pair(
- "EventHandler",
- Seq(pre("Hover this box!")),
- autorun=true
- )
-
- @sect{dom.btoa}
- @pair(
- "Base64",
- Seq(input(width:="100%", placeholder:="Enter text to b64 encode"), div),
- autorun=true
- )
-
- @sect{dom.localStorage}
- @pair(
- "LocalStorage",
- Seq(input(width:="100%"), div),
- autorun=true
- )
-
- @sect{dom.HTMLCanvasElement}
- @pair(
- "Canvas",
- Seq(canvas),
- autorun=true
- )
-
- @sect{dom.Fetch}
- @pair(
- "Fetch",
- Seq(
- pre("output")
- )
- )
-
- @sect{dom.Websocket}
- @pair(
- "Websocket",
- Seq(
- input(placeholder:="Type something in"),
- pre("output")
- ),
- autorun=true
- )
-
- @sect{Element.style}
- @pair(
- "ElementStyle",
- Seq(div(b("div"), height:="50px"))
- )
-
- @p
- The goal of this project is to provide a thin-but-idiomatic-scala interface to modern browser APIs. In particular:
- @ul
- @li
- Deprecated properties/methods/types will not be present.
- @li
- IE-only, Chrome-only, FF-only, and in general browser-specific attributes will typically not be present.
- @li
- The name of a Scala type should map directly to the name of the corresponding Javascript type.
- @li
- Any type which is a Javascript type (e.g. you can @hl.scala{instanceof} in javascript) should be a Scala @hl.scala{class}; any other interface which isn't a Javascript type should be a @hl.scala{trait}.
- @li
- Read-only members should be @hl.scala{def}, and not-directly-instantiable classes should have @hl.scala{private} constructors.
-
- @sect{Contributing}
- @p
- The DOM API is always evolving, and scala-js-dom is a hodgepodge of auto-generated/scraped/hand-tweaked code full of rough edges. If you see something that you think can be improved, feel free to send a pull request. These could include:
- @ul
- @li
- Improved doc-comments; who doesn't love better docs?
- @li
- Missing methods/properties/classes; send the PR adding it in including it together with a link to an authoritative source (e.g. MDN) and it should get merged.