diff --git a/scaladoc-js/resources/scaladoc-searchbar.css b/scaladoc-js/resources/scaladoc-searchbar.css index 035adbee6555..7f708b338fe8 100644 --- a/scaladoc-js/resources/scaladoc-searchbar.css +++ b/scaladoc-js/resources/scaladoc-searchbar.css @@ -100,5 +100,32 @@ .pull-right { float: right; - margin-left: auto + margin-left: auto; +} + +.snippet-comment-button { + position: absolute; + left: 50%; + width: 24px; + height: 24px; +} + +.show-snippet-comments-button { + -ms-transform: translate(calc(-50% + 5em), -50%); + transform: translate(calc(-50% + 5em), -50%); + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Ccircle cx='12' cy='12' r='12' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19 11.0053L19 13.1085H12.9873L12.988 19H10.8714L10.8721 13.1085L5 13.1085L5 11.0053L10.8721 11.0053V5L12.9865 5.00074L12.988 11.0045L19 11.0053Z' fill='%2327282C' fill-opacity='0.75'/%3E %3C/svg%3E"); +} + +.show-snippet-comments-button:hover { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Ccircle cx='12' cy='12' r='12' fill='light grey'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19 11.0053L19 13.1085H12.9873L12.988 19H10.8714L10.8721 13.1085L5 13.1085L5 11.0053L10.8721 11.0053V5L12.9865 5.00074L12.988 11.0045L19 11.0053Z' fill='%2327282C' fill-opacity='0.75'/%3E %3C/svg%3E"); +} + +.hide-snippet-comments-button { + -ms-transform: translate(calc(-50% + 5em), -50%) rotate(45deg); + transform: translate(calc(-50% + 5em), -50%) rotate(45deg); + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Ccircle cx='12' cy='12' r='12' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19 11.0053L19 13.1085H12.9873L12.988 19H10.8714L10.8721 13.1085L5 13.1085L5 11.0053L10.8721 11.0053V5L12.9865 5.00074L12.988 11.0045L19 11.0053Z' fill='%2327282C' fill-opacity='0.75'/%3E %3C/svg%3E"); +} + +.hide-snippet-comments-button:hover { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Ccircle cx='12' cy='12' r='12' fill='light grey'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19 11.0053L19 13.1085H12.9873L12.988 19H10.8714L10.8721 13.1085L5 13.1085L5 11.0053L10.8721 11.0053V5L12.9865 5.00074L12.988 11.0045L19 11.0053Z' fill='%2327282C' fill-opacity='0.75'/%3E %3C/svg%3E"); } diff --git a/scaladoc-js/src/Main.scala b/scaladoc-js/src/Main.scala index 7b32aed9a1ea..c31ad58568fa 100644 --- a/scaladoc-js/src/Main.scala +++ b/scaladoc-js/src/Main.scala @@ -3,4 +3,5 @@ package dotty.tools.scaladoc object Main extends App { Searchbar() SocialLinks() + CodeSnippets() } diff --git a/scaladoc-js/src/searchbar/code-snippets/CodeSnippets.scala b/scaladoc-js/src/searchbar/code-snippets/CodeSnippets.scala new file mode 100644 index 000000000000..b6ed3d476887 --- /dev/null +++ b/scaladoc-js/src/searchbar/code-snippets/CodeSnippets.scala @@ -0,0 +1,43 @@ +package dotty.tools.scaladoc + +import org.scalajs.dom._ +import org.scalajs.dom.ext._ + +class CodeSnippets: + val replacePatternsAndResults: Seq[(String, String)] = Seq( + """(\/\/{{\n)((.|\n)*?)(\/\/}}\n)""" -> """$2""", // wrap content of block directives + """(\/\/.*?)(\n|\$)""" -> """$1$2""", // wrap single line comment + """(\/\*)((.|\n)*?)(\*\/)""" -> """$0""", // wrap multi line comment + ) + + document.querySelectorAll("code").foreach { + case e: html.Element => e.innerHTML = replacePatternsAndResults.foldLeft(e.innerHTML) { + case (acc, (pattern, result)) => + acc.replaceAll(pattern, result) + } + } + + def toggleHide(e: html.Element | html.Document) = e.querySelectorAll("code span.hideable").foreach { + case e: html.Element if e.style.getPropertyValue("display").isEmpty => e.style.setProperty("display", "none") + case e: html.Element => e.style.removeProperty("display") + } + + toggleHide(document) + + document.querySelectorAll("pre").foreach { + case e: html.Element if e.querySelectorAll("code span.hideable").nonEmpty => + val a = document.createElement("a") + a.addEventListener("click", { (_: MouseEvent) => + if(a.classList.contains("hide-snippet-comments-button")) { + a.classList.add("show-snippet-comments-button") + a.classList.remove("hide-snippet-comments-button") + } else { + a.classList.add("hide-snippet-comments-button") + a.classList.remove("show-snippet-comments-button") + } + toggleHide(e) + }) + a.classList.add("snippet-comment-button") + a.classList.add("show-snippet-comments-button") + e.insertBefore(a, e.firstChild) + } diff --git a/scaladoc-testcases/src/tests/snippetComments.scala b/scaladoc-testcases/src/tests/snippetComments.scala new file mode 100644 index 000000000000..39b15648103e --- /dev/null +++ b/scaladoc-testcases/src/tests/snippetComments.scala @@ -0,0 +1,31 @@ +package tests.snippetComments + + +/** + * This is my codeblock + * + * ``` + * //{{ + * import xd + * import xd2 + * //}} + * + * + * val x = 1 // This is my valid comment + * + * /* + * multi line comment + * */ + * val reallyFLongDeclaration = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + * val y = 2 // comment in the same line + * // comment in new line + * val z = 3 + * + * //{{ + * val hideMe = 7 + * //}} + * ``` + * + * The end of my codeblock + */ +class A diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 948a377c9397..5c6580601308 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -5,7 +5,9 @@ --border-light: #DADFE6; --border-medium: #abc; + --body-bg: #f0f3f6; --code-bg: #F4F5FA; + --documentable-bg: #FFFFFF; --symbol-fg: #333; --link-fg: #00607D; --link-hover-fg: #00A0D0; @@ -45,6 +47,7 @@ body { padding: 0; font-family: "Lato", sans-serif; font-size: 16px; + background-color: var(--body-bg); } /* Page layout */ @@ -75,7 +78,12 @@ h1, h2, h3 { font-family: var(--title-font); color: var(--title-fg); } -pre, code, .monospace, .hljs { +.monospace { + font-family: var(--mono-font); + background: var(--documentable-bg); + font-variant-ligatures: none; +} +pre, code, .hljs { font-family: var(--mono-font); background: var(--code-bg); font-variant-ligatures: none; @@ -84,12 +92,16 @@ code { font-size: .8em; padding: 0 .3em; } +pre { + overflow-x: auto; + scrollbar-width: thin; +} pre code, pre code.hljs { font-size: 1em; padding: 0; } pre, .symbol.monospace { - padding: 10px 8px 10px 12px; + padding: 12px 8px 10px 12px; font-weight: 500; font-size: 12px; } @@ -468,12 +480,18 @@ footer .pull-right { padding-right: 0.5em; min-width: 10em; max-width: 10em; + width: 10em; overflow: hidden; direction: rtl; white-space: nowrap; text-indent: 0em; } +.documentableElement .docs { + width: 100%; + table-layout: fixed; +} + .documentableElement .modifiers .other-modifiers { color: gray; } @@ -514,8 +532,8 @@ footer .pull-right { padding: 5px 4px 5px 4px; font-weight: 500; font-size: 12px; - background: var(--code-bg); - border: 0.25em solid white; + background: var(--documentable-bg); + border: 0.25em solid var(--body-bg); } .documentableElement>div { @@ -524,12 +542,11 @@ footer .pull-right { .expand.documentableElement>div { display: block; - padding-left: 3em; } .expand.documentableElement>div.header { display: block; - padding-left: 7.5em; + padding-left: 4.5em; text-indent: -4.5em; }