Skip to content

Commit 7a6cabe

Browse files
authored
Merge pull request #13258 from pikinier20/scaladoc/scastie-integration
Scaladoc: Integrate Scastie into Scaladoc
2 parents a38ae20 + 237b4a5 commit 7a6cabe

33 files changed

+14459
-54
lines changed

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ object Build {
14171417
"scaladoc testcases",
14181418
"scaladoc/output/testcases",
14191419
"master",
1420-
Seq("-usejavacp")
1420+
Seq("-usejavacp", "-snippet-compiler:scaladoc-testcases/docs=compile", "-siteroot", "scaladoc-testcases/docs")
14211421
)
14221422
}.value,
14231423

project/scripts/cmdScaladocTests

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ DOTTY_NONBOOTSTRAPPED_VERSION=$(eval $DOTTY_NONBOOTSTRAPPED_VERSION_COMMAND | ta
1616
DOTTY_BOOTSTRAPPED_VERSION_COMMAND="$SBT \"eval println(Build.dottyVersion)\""
1717
DOTTY_BOOTSTRAPPED_VERSION=$(eval $DOTTY_BOOTSTRAPPED_VERSION_COMMAND | tail -n 2 | head -n 1)
1818

19+
GITHUB_REPOSITORY="lampepfl/dotty"
20+
GITHUB_SHA="3.0.0"
21+
1922
"$SBT" "scaladoc/generateTestcasesDocumentation" > "$tmp" 2>&1 || echo "generated testcases project with sbt"
2023
dist/target/pack/bin/scaladoc \
2124
-d "$OUT1" \
@@ -31,6 +34,8 @@ dist/target/pack/bin/scaladoc \
3134
-Ygenerate-inkuire \
3235
"-skip-by-id:scala.runtime.stdLibPatches" \
3336
"-skip-by-id:scala.runtime.MatchCase" \
37+
"-snippet-compiler:scaladoc-testcases/docs=compile" \
38+
-siteroot scaladoc-testcases/docs \
3439
-project-footer "Copyright (c) 2002-2021, LAMP/EPFL" \
3540
-author -groups -revision master -project-version "${DOTTY_BOOTSTRAPPED_VERSION}" \
3641
out/bootstrap/scaladoc-testcases/scala-"${DOTTY_NONBOOTSTRAPPED_VERSION}"/classes > "$tmp" 2>&1 || echo "generated testcases project with scripts"

scaladoc-js/resources/code-snippets.css

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
--slider-diameter: calc(var(--slider-height) - 4px);
4747
}
4848

49-
.snippet-showhide p {
49+
.buttons p {
5050
margin-left: 4px;
5151
margin-bottom: 0;
5252
margin-top: 0;
@@ -160,8 +160,8 @@ input:checked + .slider:before {
160160
}
161161

162162

163-
.snippet .buttons>:not(:last-child) {
164-
border-left: 2px solid var(--inactive-bg);
163+
.snippet .buttons>:not(:first-child) {
164+
border-right: 2px solid var(--inactive-bg);
165165
}
166166

167167
.snippet .buttons>* {
@@ -194,28 +194,110 @@ input:checked + .slider:before {
194194
display: none;
195195
}
196196

197-
@media(max-width: 576px) {
198-
.snippet-showhide {
199-
--slider-width: 32px;
200-
--slider-height: 16px;
201-
}
197+
.snippet .scastie.embedded {
198+
width: 100%;
199+
}
200+
201+
.snippet .scastie.embedded .content {
202+
height: unset;
203+
}
204+
205+
.snippet .scastie.embedded .editor-container {
206+
height: unset;
207+
}
208+
209+
.snippet .scastie.embedded .editor-container .code {
210+
height: unset;
211+
}
212+
213+
.snippet .scastie.embedded .editor-container .editor-wrapper {
214+
height: unset;
215+
}
216+
217+
.snippet .scastie .CodeMirror, .snippet .scastie .CodeMirror-scroll {
218+
height:unset;
219+
}
220+
221+
.snippet .scastie.embedded .app.light .editor-container .code .CodeMirror-scroll {
222+
height:unset;
223+
min-height: 50px;
224+
}
225+
226+
.snippet .scastie .app.light .editor-container .console-container .console {
227+
height: unset;
228+
}
229+
230+
.snippet .scastie .app.light .CodeMirror-gutters {
231+
background-color: var(--code-bg) !important;
232+
border-color: var(--code-bg) !important;
233+
}
234+
235+
.snippet .scastie .app.light .CodeMirror {
236+
color: var(--code-fg);
237+
background-color: var(--code-bg);
238+
}
239+
240+
241+
.snippet .scastie .app.light .output-console pre {
242+
color: white;
243+
background-color: rgb(0, 43, 54);
244+
}
245+
246+
.snippet .scastie .app.light .editor-container .handler {
247+
background-color: var(--code-bg);
248+
}
249+
250+
.snippet .scastie .console-container {
251+
margin-left: 30px;
252+
}
253+
254+
.snippet .scastie .app.light .main-panel {
255+
background-color: unset;
256+
}
202257

258+
.snippet .scastie .cm-s-solarized.cm-s-light .CodeMirror-widget .fold,
259+
.snippet .scastie .cm-s-solarized.cm-s-light .CodeMirror-linewidget .compilation-info,
260+
.snippet .scastie .cm-s-solarized.cm-s-light .CodeMirror-linewidget .runtime-error,
261+
.snippet .scastie .cm-s-solarized.cm-s-light .CodeMirror-linewidget .line,
262+
.snippet .scastie .cm-s-solarized.cm-s-light .CodeMirror-linewidget .inline {
263+
background-color: var(--code-bg);
264+
}
265+
266+
.snippet .scastie .ansi-color-yellow {
267+
color: #b58900;
268+
}
269+
270+
.snippet .scastie .ansi-color-magenta {
271+
color: var(--red500);
272+
}
273+
274+
.snippet .fa-warning:before, .fa-exclamation-triangle:before {
275+
color: #b58900;
276+
}
277+
278+
@media(max-width: 836px) {
203279
.snippet .buttons {
204-
--icon-size: 16px;
205-
font-size: 16px;
280+
--icon-size: 16px;
281+
font-size: 0px;
206282
}
207283

284+
.snippet .buttons p {
285+
--icon-size: 16px;
286+
font-size: 0px;
287+
}
208288
}
209289

210-
@media(max-width: 360px) {
290+
@media(max-width: 576px) {
211291
.snippet-showhide {
212292
--slider-width: 32px;
213293
--slider-height: 16px;
214294
}
295+
}
215296

216-
.snippet .buttons {
217-
--icon-size: 16px;
218-
font-size: 0px;
297+
@media(max-width: 360px) {
298+
.snippet-showhide {
299+
--slider-width: 32px;
300+
--slider-height: 16px;
219301
}
220302
}
221303

@@ -224,9 +306,4 @@ input:checked + .slider:before {
224306
--slider-width: 24px;
225307
--slider-height: 10px;
226308
}
227-
228-
.snippet .buttons {
229-
--icon-size: 16px;
230-
font-size: 0px;
231-
}
232309
}

scaladoc-js/src/code-snippets/CodeSnippets.scala

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
package dotty.tools.scaladoc
22

3+
import scala.scalajs.js
34
import org.scalajs.dom._
45
import org.scalajs.dom.ext._
56

7+
import CodeSnippetsGlobals._
8+
69
class CodeSnippets:
10+
lazy val scastieConfig = getScastieConfiguration
11+
12+
private def getScastieConfiguration: js.Dynamic =
13+
js.Dynamic.literal(
14+
sbtConfig = scastieConfiguration,
15+
targetType = "scala3"
16+
)
717

818
private def getButtonsSection(snippet: html.Element): Option[html.Div] = snippet.querySelector("div.buttons") match {
919
case div: html.Div => Some(div)
@@ -12,7 +22,7 @@ class CodeSnippets:
1222

1323
def enrichSnippets() = document.querySelectorAll("div.snippet").foreach {
1424
case snippet: html.Element =>
15-
snippet.addEventListener("click", e => e.stopPropagation())
25+
snippet.addEventListener("click", (e: MouseEvent) => e.asInstanceOf[js.Dynamic].fromSnippet = true)
1626
snippetAnchor(snippet)
1727
handleHideableCode(snippet)
1828
handleImportedCode(snippet)
@@ -106,23 +116,103 @@ class CodeSnippets:
106116
div
107117
}
108118
def runButton = {
109-
val div = document.createElement("div")
110-
val button = document.createElement("button").asInstanceOf[html.Button]
111-
val icon = document.createElement("i")
112-
icon.classList.add("fas")
113-
icon.classList.add("fa-play")
114-
button.appendChild(icon)
115-
button.classList.add("run-button")
116-
button.addEventListener("click", _ => {}) // TODO: Run button #13065
117-
button.disabled = true
118-
div.appendChild(button)
119+
val div = document.createElement("div").asInstanceOf[html.Div]
120+
val runButton = document.createElement("button").asInstanceOf[html.Button]
121+
val runIcon = document.createElement("i")
122+
runIcon.classList.add("fas")
123+
runIcon.classList.add("fa-play")
124+
runButton.classList.add("run-button")
125+
runButton.appendChild(runIcon)
126+
127+
runButton.addEventListener("click", _ =>
128+
if !runButton.hasAttribute("opened") then {
129+
scastie.Embedded(snippet.querySelector("pre"), scastieConfig)
130+
runButton.setAttribute("opened", "opened")
131+
}
132+
snippet.querySelector(".scastie .embedded-menu") match {
133+
case btn: html.Element =>
134+
btn.style = "display:none;"
135+
case _ =>
136+
}
137+
snippet.querySelector(".scastie .embedded-menu .run-button") match {
138+
case btn: html.Element => btn.click()
139+
case _ =>
140+
}
141+
snippet.querySelector(".buttons .exit-button") match {
142+
case btn: html.Element => btn.parentElement.style = ""
143+
case _ =>
144+
}
145+
snippet.querySelector(".buttons .to-scastie-button") match {
146+
case btn: html.Element => btn.parentElement.style = ""
147+
case _ =>
148+
}
149+
)
150+
151+
div.appendChild(runButton)
152+
div
153+
}
154+
def exitButton = {
155+
val div = document.createElement("div").asInstanceOf[html.Div]
156+
val exitButton = document.createElement("button").asInstanceOf[html.Element]
157+
val exitIcon = document.createElement("i")
158+
exitIcon.classList.toggle("fas")
159+
exitIcon.classList.toggle("fa-times")
160+
exitButton.classList.add("exit-button")
161+
div.style = "display:none;"
162+
exitButton.appendChild(exitIcon)
163+
164+
exitButton.addEventListener("click", _ =>
165+
snippet.querySelector("pre") match {
166+
case p: html.Element => p.style = ""
167+
case _ =>
168+
}
169+
snippet.querySelector(".scastie.embedded") match {
170+
case s: html.Element => snippet.removeChild(s)
171+
case _ =>
172+
}
173+
snippet.querySelector(".buttons .run-button") match {
174+
case btn: html.Element => btn.removeAttribute("opened")
175+
case _ =>
176+
}
177+
snippet.querySelector(".buttons .to-scastie-button") match {
178+
case btn: html.Element => btn.parentElement.style = "display:none;"
179+
case _ =>
180+
}
181+
div.style = "display:none;"
182+
)
183+
184+
div.appendChild(exitButton)
185+
div
186+
}
187+
def toScastieButton = {
188+
val div = document.createElement("div").asInstanceOf[html.Div]
189+
val toScastieButton = document.createElement("button").asInstanceOf[html.Element]
190+
val toScastieIcon = document.createElement("i").asInstanceOf[html.Image]
191+
192+
toScastieIcon.classList.add("fas")
193+
toScastieIcon.classList.add("fa-external-link-alt")
194+
toScastieButton.classList.add("to-scastie-button")
195+
div.style = "display:none;"
196+
toScastieButton.appendChild(toScastieIcon)
197+
198+
toScastieButton.addEventListener("click", _ =>
199+
snippet.querySelector(".embedded-menu li.logo") match {
200+
case toScastie: html.Element => toScastie.click()
201+
case _ =>
202+
}
203+
)
204+
205+
div.appendChild(toScastieButton)
119206
div
120207
}
121208
val buttonsSection = getButtonsSection(snippet)
122209
buttonsSection.foreach(s =>
123210
s.appendChild(copyButton)
124-
// Temporarily disabled
125-
// s.appendChild(runButton)
211+
if !snippet.hasAttribute("hasContext") then {
212+
s.appendChild(toScastieButton)
213+
s.appendChild(runButton)
214+
s.appendChild(exitButton)
215+
}
126216
)
127217
}
128218

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package dotty.tools.scaladoc
2+
3+
import scala.scalajs.js
4+
import scala.scalajs.js.annotation.JSGlobalScope
5+
6+
@js.native
7+
@JSGlobalScope
8+
object CodeSnippetsGlobals extends js.Object {
9+
val scastie: Scastie = js.native
10+
val scastieConfiguration: String = js.native
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package dotty.tools.scaladoc
2+
3+
import scala.scalajs.js
4+
import org.scalajs.dom._
5+
6+
@js.native
7+
trait Scastie extends js.Object:
8+
def Embedded(selector: String | Node, config: js.Dynamic): Unit = js.native
9+
def Embedded(selector: String | Node): Unit = js.native

scaladoc-testcases/docs/docs/index.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33

44
---
55

6-
```scala sc:compile
7-
2 + List(0)
6+
```scala
7+
val someVariable: Int = 2
88
```
99

10-
```scala sc:compile
11-
new snippetCompiler.Snippet0 { }
10+
```scala sc:fail
11+
trait RenderingContext
12+
class Renderer(using RenderingContext)
13+
val renderer: Renderer = Renderer()
1214
```
1315

16+
17+

scaladoc/resources/dotty_res/scripts/ux.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ window.addEventListener("DOMContentLoaded", () => {
1010
if (elements) {
1111
for (i = 0; i < elements.length; i++) {
1212
elements[i].onclick = function(e) {
13-
if(!$(e.target).is("a"))
13+
if(!$(e.target).is("a") && e.fromSnippet !== true)
1414
this.classList.toggle("expand")
1515
}
1616
}

0 commit comments

Comments
 (0)