diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fa8c67c5990c..70f69d1fd568 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -470,9 +470,12 @@ jobs: if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'" env: NIGHTLYBUILD: yes - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} # If you need to change this: - # Generate one at https://github.com/settings/tokens - # Make sure you have the write permissions to the repo: https://github.com/lampepfl/dotty-website + DOTTY_WEBSITE_BOT_TOKEN: ${{ secrets.BOT_TOKEN }} # If you need to change this: + # Generate one at https://github.com/settings/tokens + # Make sure you have the write permissions to the repo: https://github.com/lampepfl/dotty-website + DOCS_SCALALANG_BOT_TOKEN: ${{ secrets.DOCS_SCALALANG_BOT_TOKEN }} # If you need to change this: + # Generate one at https://github.com/settings/tokens + # Make sure you have the write permissions to the repo: https://github.com/scala/docs.scala-lang steps: - name: Reset existing repo @@ -494,14 +497,26 @@ jobs: run: | ./project/scripts/genDocs -doc-snapshot - - name: Deploy Website + - name: Deploy Website to dotty-website uses: peaceiris/actions-gh-pages@v3 with: - personal_token: ${{ secrets.BOT_TOKEN }} + personal_token: ${{ env.DOTTY_WEBSITE_BOT_TOKEN }} publish_dir: docs/_site external_repository: lampepfl/dotty-website publish_branch: gh-pages + - name: Generate docs.scala-lang preprocessed files + run: | + ./project/scripts/genDocsScalaLang + + - name: Deploy Website to docs.scala-lang + uses: peaceiris/actions-gh-pages@v3 + with: + personal_token: ${{ env.DOCS_SCALALANG_BOT_TOKEN }} + publish_dir: docsScalaLang + external_repository: BarkingBad/docs.scala-lang + publish_branch: dev + publish_release: runs-on: [self-hosted, Linux] container: diff --git a/.gitignore b/.gitignore index 3fe2a41f8d2b..fd9530725f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,7 @@ compiler/test-coursier/run/*.jar # Docs docs-for-dotty-page/* + +# docs.scala-lang deplyment temp dir +docsScalaLang/ +docs/_site/ diff --git a/docs/docs/reference/changed-features.md b/docs/docs/reference/changed-features.md index c23a9031bef0..7a8f717f2394 100644 --- a/docs/docs/reference/changed-features.md +++ b/docs/docs/reference/changed-features.md @@ -1,8 +1,8 @@ --- title: "Other Changed Features" type: chapter -num: 51 -previous-page: /scala3/reference/other-new-features/type-test +num: 52 +previous-page: /scala3/reference/other-new-features/experimental-defs next-page: /scala3/reference/changed-features/numeric-literals --- diff --git a/docs/docs/reference/changed-features/compiler-plugins.md b/docs/docs/reference/changed-features/compiler-plugins.md index c77796d71df1..b8e108c560c4 100644 --- a/docs/docs/reference/changed-features/compiler-plugins.md +++ b/docs/docs/reference/changed-features/compiler-plugins.md @@ -1,7 +1,7 @@ --- title: "Changes in Compiler Plugins" type: section -num: 67 +num: 68 previous-page: /scala3/reference/changed-features/eta-expansion next-page: /scala3/reference/changed-features/lazy-vals-init --- diff --git a/docs/docs/reference/changed-features/eta-expansion.md b/docs/docs/reference/changed-features/eta-expansion.md index 91516edca5a5..f21cb54406ad 100644 --- a/docs/docs/reference/changed-features/eta-expansion.md +++ b/docs/docs/reference/changed-features/eta-expansion.md @@ -1,7 +1,7 @@ --- title: "Automatic Eta Expansion" type: section -num: 66 +num: 67 previous-page: /scala3/reference/changed-features/pattern-matching next-page: /scala3/reference/changed-features/compiler-plugins --- diff --git a/docs/docs/reference/changed-features/implicit-conversions.md b/docs/docs/reference/changed-features/implicit-conversions.md index 39b4cde31e63..aab1baa32373 100644 --- a/docs/docs/reference/changed-features/implicit-conversions.md +++ b/docs/docs/reference/changed-features/implicit-conversions.md @@ -1,7 +1,7 @@ --- title: "Implicit Conversions" type: section -num: 60 +num: 61 previous-page: /scala3/reference/changed-features/implicit-resolution next-page: /scala3/reference/changed-features/overload-resolution --- diff --git a/docs/docs/reference/changed-features/implicit-resolution.md b/docs/docs/reference/changed-features/implicit-resolution.md index 410784834f95..2a563aceeb19 100644 --- a/docs/docs/reference/changed-features/implicit-resolution.md +++ b/docs/docs/reference/changed-features/implicit-resolution.md @@ -1,7 +1,7 @@ --- title: "Changes in Implicit Resolution" type: section -num: 59 +num: 60 previous-page: /scala3/reference/changed-features/type-inference next-page: /scala3/reference/changed-features/implicit-conversions --- diff --git a/docs/docs/reference/changed-features/imports.md b/docs/docs/reference/changed-features/imports.md index 39568769a270..e46fbc8fc44b 100644 --- a/docs/docs/reference/changed-features/imports.md +++ b/docs/docs/reference/changed-features/imports.md @@ -1,7 +1,7 @@ --- title: "Imports" type: section -num: 56 +num: 57 previous-page: /scala3/reference/changed-features/wildcards next-page: /scala3/reference/changed-features/type-checking --- diff --git a/docs/docs/reference/changed-features/lazy-vals-init.md b/docs/docs/reference/changed-features/lazy-vals-init.md index a065cebb2a49..f70ec622f6e1 100644 --- a/docs/docs/reference/changed-features/lazy-vals-init.md +++ b/docs/docs/reference/changed-features/lazy-vals-init.md @@ -1,7 +1,7 @@ --- title: Lazy Vals Initialization type: section -num: 68 +num: 69 previous-page: /scala3/reference/changed-features/compiler-plugins next-page: /scala3/reference/changed-features/main-functions --- diff --git a/docs/docs/reference/changed-features/main-functions.md b/docs/docs/reference/changed-features/main-functions.md index 6f035278ed05..777532e7110b 100644 --- a/docs/docs/reference/changed-features/main-functions.md +++ b/docs/docs/reference/changed-features/main-functions.md @@ -1,7 +1,7 @@ --- title: "Main Methods" type: section -num: 69 +num: 70 previous-page: /scala3/reference/changed-features/lazy-vals-init next-page: /scala3/reference/dropped-features --- diff --git a/docs/docs/reference/changed-features/match-syntax.md b/docs/docs/reference/changed-features/match-syntax.md index 7ebc85b6d003..12e35cfa94df 100644 --- a/docs/docs/reference/changed-features/match-syntax.md +++ b/docs/docs/reference/changed-features/match-syntax.md @@ -1,7 +1,7 @@ --- title: "Match Expressions" type: section -num: 62 +num: 63 previous-page: /scala3/reference/changed-features/overload-resolution next-page: /scala3/reference/changed-features/vararg-splices --- diff --git a/docs/docs/reference/changed-features/numeric-literals.md b/docs/docs/reference/changed-features/numeric-literals.md index 8a21d97bd4a4..1cc07e3b1c8e 100644 --- a/docs/docs/reference/changed-features/numeric-literals.md +++ b/docs/docs/reference/changed-features/numeric-literals.md @@ -1,9 +1,9 @@ --- title: "Numeric Literals" type: section -num: 52 +num: 53 previous-page: /scala3/reference/changed-features next-page: /scala3/reference/changed-features/structural-types --- -[Document was moved](../experimental/numeric-literals.md) \ No newline at end of file +[Document was moved](../experimental/numeric-literals.md) diff --git a/docs/docs/reference/changed-features/operators.md b/docs/docs/reference/changed-features/operators.md index 5e05c6bfbcae..953aa18c8408 100644 --- a/docs/docs/reference/changed-features/operators.md +++ b/docs/docs/reference/changed-features/operators.md @@ -1,7 +1,7 @@ --- title: "Rules for Operators" type: section -num: 54 +num: 55 previous-page: /scala3/reference/changed-features/structural-types next-page: /scala3/reference/changed-features/wildcards --- diff --git a/docs/docs/reference/changed-features/overload-resolution.md b/docs/docs/reference/changed-features/overload-resolution.md index 6b203299707f..4205acdd412f 100644 --- a/docs/docs/reference/changed-features/overload-resolution.md +++ b/docs/docs/reference/changed-features/overload-resolution.md @@ -1,7 +1,7 @@ --- title: "Changes in Overload Resolution" type: section -num: 61 +num: 62 previous-page: /scala3/reference/changed-features/implicit-conversions next-page: /scala3/reference/changed-features/match-syntax --- diff --git a/docs/docs/reference/changed-features/pattern-bindings.md b/docs/docs/reference/changed-features/pattern-bindings.md index 307ff6387cce..a5eb39e98da6 100644 --- a/docs/docs/reference/changed-features/pattern-bindings.md +++ b/docs/docs/reference/changed-features/pattern-bindings.md @@ -1,7 +1,7 @@ --- title: "Pattern Bindings" type: section -num: 64 +num: 65 previous-page: /scala3/reference/changed-features/vararg-splices next-page: /scala3/reference/changed-features/pattern-matching --- diff --git a/docs/docs/reference/changed-features/pattern-matching.md b/docs/docs/reference/changed-features/pattern-matching.md index 2216d145a80d..93712f004307 100644 --- a/docs/docs/reference/changed-features/pattern-matching.md +++ b/docs/docs/reference/changed-features/pattern-matching.md @@ -1,7 +1,7 @@ --- title: "Option-less pattern matching" type: section -num: 65 +num: 66 previous-page: /scala3/reference/changed-features/pattern-bindings next-page: /scala3/reference/changed-features/eta-expansion --- diff --git a/docs/docs/reference/changed-features/structural-types.md b/docs/docs/reference/changed-features/structural-types.md index fe20a3aa5483..3ce3d6ac88bd 100644 --- a/docs/docs/reference/changed-features/structural-types.md +++ b/docs/docs/reference/changed-features/structural-types.md @@ -1,7 +1,7 @@ --- title: "Programmatic Structural Types" type: section -num: 53 +num: 54 previous-page: /scala3/reference/changed-features/numeric-literals next-page: /scala3/reference/changed-features/operators --- diff --git a/docs/docs/reference/changed-features/type-checking.md b/docs/docs/reference/changed-features/type-checking.md index 81ca345a6c7e..f647e57ac462 100644 --- a/docs/docs/reference/changed-features/type-checking.md +++ b/docs/docs/reference/changed-features/type-checking.md @@ -1,7 +1,7 @@ --- title: "Changes in Type Checking" type: section -num: 57 +num: 58 previous-page: /scala3/reference/changed-features/imports next-page: /scala3/reference/changed-features/type-inference --- diff --git a/docs/docs/reference/changed-features/type-inference.md b/docs/docs/reference/changed-features/type-inference.md index 873c91831210..2432cb8e4339 100644 --- a/docs/docs/reference/changed-features/type-inference.md +++ b/docs/docs/reference/changed-features/type-inference.md @@ -1,7 +1,7 @@ --- title: "Changes in Type Inference" type: section -num: 58 +num: 59 previous-page: /scala3/reference/changed-features/type-checking next-page: /scala3/reference/changed-features/implicit-resolution --- diff --git a/docs/docs/reference/changed-features/vararg-splices.md b/docs/docs/reference/changed-features/vararg-splices.md index efa7f034acea..2da55ee79945 100644 --- a/docs/docs/reference/changed-features/vararg-splices.md +++ b/docs/docs/reference/changed-features/vararg-splices.md @@ -1,7 +1,7 @@ --- title: "Vararg Splices" type: section -num: 63 +num: 64 previous-page: /scala3/reference/changed-features/match-syntax next-page: /scala3/reference/changed-features/pattern-bindings --- diff --git a/docs/docs/reference/changed-features/wildcards.md b/docs/docs/reference/changed-features/wildcards.md index fdf69fdcd954..0a84ebbf2a48 100644 --- a/docs/docs/reference/changed-features/wildcards.md +++ b/docs/docs/reference/changed-features/wildcards.md @@ -1,7 +1,7 @@ --- title: Wildcard Arguments in Types type: section -num: 55 +num: 56 previous-page: /scala3/reference/changed-features/operators next-page: /scala3/reference/changed-features/imports --- @@ -49,4 +49,4 @@ These rules make it possible to cross build between Scala 2 using the kind proje There is also a migration path for users that want a one-time transition to syntax with `_` as a type parameter placeholder. With option `-Ykind-projector:underscores` Scala 3 will regard `_` as a type parameter placeholder, leaving `?` as the only syntax for wildcards. -To cross-compile with old Scala 2 sources, while using `_` a placeholder, you must use options `-Xsource:3 -P:kind-projector:underscore-placeholders` together with a recent version of kind-projector (`0.13` and higher) and most recent versions of Scala 2 (`2.13.5` and higher and `2.12.14` and higher) +To cross-compile with old Scala 2 sources, while using `_` a placeholder, you must use options `-Xsource:3 -P:kind-projector:underscore-placeholders` together with a recent version of kind-projector (`0.13` and higher) and most recent versions of Scala 2 (`2.13.5` and higher and `2.12.14` and higher) diff --git a/docs/docs/reference/dropped-features.md b/docs/docs/reference/dropped-features.md index b2fb1fbe9fe2..6ccff5c40425 100644 --- a/docs/docs/reference/dropped-features.md +++ b/docs/docs/reference/dropped-features.md @@ -1,7 +1,7 @@ --- title: "Dropped Features" type: chapter -num: 70 +num: 71 previous-page: /scala3/reference/changed-features/main-functions next-page: /scala3/reference/dropped-features/delayed-init --- diff --git a/docs/docs/reference/dropped-features/auto-apply.md b/docs/docs/reference/dropped-features/auto-apply.md index 8670850f7903..6696bd8165d8 100644 --- a/docs/docs/reference/dropped-features/auto-apply.md +++ b/docs/docs/reference/dropped-features/auto-apply.md @@ -1,7 +1,7 @@ --- title: "Dropped: Auto-Application" type: section -num: 83 +num: 84 previous-page: /scala3/reference/dropped-features/symlits next-page: /scala3/reference/dropped-features/weak-conformance --- diff --git a/docs/docs/reference/dropped-features/class-shadowing.md b/docs/docs/reference/dropped-features/class-shadowing.md index b3a4ab2dc1ad..50101bf1d0b4 100644 --- a/docs/docs/reference/dropped-features/class-shadowing.md +++ b/docs/docs/reference/dropped-features/class-shadowing.md @@ -1,7 +1,7 @@ --- title: "Dropped: Class Shadowing" type: section -num: 79 +num: 80 previous-page: /scala3/reference/dropped-features/early-initializers next-page: /scala3/reference/dropped-features/limit22 --- diff --git a/docs/docs/reference/dropped-features/delayed-init.md b/docs/docs/reference/dropped-features/delayed-init.md index 5673db5dfb8e..f0b65a242c1a 100644 --- a/docs/docs/reference/dropped-features/delayed-init.md +++ b/docs/docs/reference/dropped-features/delayed-init.md @@ -1,7 +1,7 @@ --- title: "Dropped: DelayedInit" type: section -num: 71 +num: 72 previous-page: /scala3/reference/dropped-features next-page: /scala3/reference/dropped-features/macros --- diff --git a/docs/docs/reference/dropped-features/do-while.md b/docs/docs/reference/dropped-features/do-while.md index 3fd59430ac3b..7bc3b73e0091 100644 --- a/docs/docs/reference/dropped-features/do-while.md +++ b/docs/docs/reference/dropped-features/do-while.md @@ -1,7 +1,7 @@ --- title: "Dropped: Do-While" type: section -num: 75 +num: 76 previous-page: /scala3/reference/dropped-features/type-projection next-page: /scala3/reference/dropped-features/procedure-syntax --- diff --git a/docs/docs/reference/dropped-features/early-initializers.md b/docs/docs/reference/dropped-features/early-initializers.md index 18d97640b12f..234de159c30c 100644 --- a/docs/docs/reference/dropped-features/early-initializers.md +++ b/docs/docs/reference/dropped-features/early-initializers.md @@ -1,7 +1,7 @@ --- title: "Dropped: Early Initializers" type: section -num: 78 +num: 79 previous-page: /scala3/reference/dropped-features/package-objects next-page: /scala3/reference/dropped-features/class-shadowing --- diff --git a/docs/docs/reference/dropped-features/existential-types.md b/docs/docs/reference/dropped-features/existential-types.md index df624cbd0721..ea176659fd77 100644 --- a/docs/docs/reference/dropped-features/existential-types.md +++ b/docs/docs/reference/dropped-features/existential-types.md @@ -1,7 +1,7 @@ --- title: "Dropped: Existential Types" type: section -num: 73 +num: 74 previous-page: /scala3/reference/dropped-features/macros next-page: /scala3/reference/dropped-features/type-projection --- diff --git a/docs/docs/reference/dropped-features/limit22.md b/docs/docs/reference/dropped-features/limit22.md index 2e21efec58f6..1c2bb0e2882a 100644 --- a/docs/docs/reference/dropped-features/limit22.md +++ b/docs/docs/reference/dropped-features/limit22.md @@ -1,7 +1,7 @@ --- title: "Dropped: Limit 22" type: section -num: 80 +num: 81 previous-page: /scala3/reference/dropped-features/class-shadowing next-page: /scala3/reference/dropped-features/xml --- diff --git a/docs/docs/reference/dropped-features/macros.md b/docs/docs/reference/dropped-features/macros.md index f7a23edb0057..8208e8ee630c 100644 --- a/docs/docs/reference/dropped-features/macros.md +++ b/docs/docs/reference/dropped-features/macros.md @@ -1,7 +1,7 @@ --- title: "Dropped: Scala 2 Macros" type: section -num: 72 +num: 73 previous-page: /scala3/reference/dropped-features/delayed-init next-page: /scala3/reference/dropped-features/existential-types --- diff --git a/docs/docs/reference/dropped-features/package-objects.md b/docs/docs/reference/dropped-features/package-objects.md index d9099eef9805..12004c37dea3 100644 --- a/docs/docs/reference/dropped-features/package-objects.md +++ b/docs/docs/reference/dropped-features/package-objects.md @@ -1,7 +1,7 @@ --- title: "Dropped: Package Objects" type: section -num: 77 +num: 78 previous-page: /scala3/reference/dropped-features/procedure-syntax next-page: /scala3/reference/dropped-features/early-initializers --- diff --git a/docs/docs/reference/dropped-features/procedure-syntax.md b/docs/docs/reference/dropped-features/procedure-syntax.md index f3bf8cc9d47f..d7a33cf374f8 100644 --- a/docs/docs/reference/dropped-features/procedure-syntax.md +++ b/docs/docs/reference/dropped-features/procedure-syntax.md @@ -1,7 +1,7 @@ --- title: "Dropped: Procedure Syntax" type: section -num: 76 +num: 77 previous-page: /scala3/reference/dropped-features/do-while next-page: /scala3/reference/dropped-features/package-objects --- diff --git a/docs/docs/reference/dropped-features/symlits.md b/docs/docs/reference/dropped-features/symlits.md index 3cb7243af964..1c71608f40fa 100644 --- a/docs/docs/reference/dropped-features/symlits.md +++ b/docs/docs/reference/dropped-features/symlits.md @@ -1,7 +1,7 @@ --- title: "Dropped: Symbol Literals" type: section -num: 82 +num: 83 previous-page: /scala3/reference/dropped-features/xml next-page: /scala3/reference/dropped-features/auto-apply --- diff --git a/docs/docs/reference/dropped-features/this-qualifier.md b/docs/docs/reference/dropped-features/this-qualifier.md index c25f896415f5..69906351ca67 100644 --- a/docs/docs/reference/dropped-features/this-qualifier.md +++ b/docs/docs/reference/dropped-features/this-qualifier.md @@ -1,7 +1,7 @@ --- title: "Dropped: private[this] and protected[this]" type: section -num: 85 +num: 86 previous-page: /scala3/reference/dropped-features/weak-conformance next-page: /scala3/reference/dropped-features/wildcard-init --- diff --git a/docs/docs/reference/dropped-features/type-projection.md b/docs/docs/reference/dropped-features/type-projection.md index fb87ef79be23..f2d2f215ed21 100644 --- a/docs/docs/reference/dropped-features/type-projection.md +++ b/docs/docs/reference/dropped-features/type-projection.md @@ -1,7 +1,7 @@ --- title: "Dropped: General Type Projection" type: section -num: 74 +num: 75 previous-page: /scala3/reference/dropped-features/existential-types next-page: /scala3/reference/dropped-features/do-while --- diff --git a/docs/docs/reference/dropped-features/weak-conformance.md b/docs/docs/reference/dropped-features/weak-conformance.md index deca70b60714..1b6db185fad8 100644 --- a/docs/docs/reference/dropped-features/weak-conformance.md +++ b/docs/docs/reference/dropped-features/weak-conformance.md @@ -1,7 +1,7 @@ --- title: "Dropped: Weak Conformance" type: section -num: 84 +num: 85 previous-page: /scala3/reference/dropped-features/auto-apply next-page: /scala3/reference/dropped-features/this-qualifier --- diff --git a/docs/docs/reference/dropped-features/wildcard-init.md b/docs/docs/reference/dropped-features/wildcard-init.md index be633fb1ca21..078ec138b3bb 100644 --- a/docs/docs/reference/dropped-features/wildcard-init.md +++ b/docs/docs/reference/dropped-features/wildcard-init.md @@ -1,7 +1,7 @@ --- title: "Dropped: Wildcard Initializer" type: section -num: 86 +num: 87 previous-page: /scala3/reference/dropped-features/this-qualifier next-page: /scala3/reference/syntax --- diff --git a/docs/docs/reference/dropped-features/xml.md b/docs/docs/reference/dropped-features/xml.md index cab3d0663a55..c094408909f4 100644 --- a/docs/docs/reference/dropped-features/xml.md +++ b/docs/docs/reference/dropped-features/xml.md @@ -1,7 +1,7 @@ --- title: "Dropped: XML Literals" type: section -num: 81 +num: 82 previous-page: /scala3/reference/dropped-features/limit22 next-page: /scala3/reference/dropped-features/symlits --- diff --git a/docs/docs/reference/language-versions.md b/docs/docs/reference/language-versions.md index ec16e8bed3cc..a17a567d7362 100644 --- a/docs/docs/reference/language-versions.md +++ b/docs/docs/reference/language-versions.md @@ -2,7 +2,7 @@ title: "Language Versions" type: chapter description: This page lists the different flavours of language supported by the Scala 3 compiler. -num: 100 +num: 101 previous-page: overview --- diff --git a/docs/docs/reference/other-new-features/experimental-defs.md b/docs/docs/reference/other-new-features/experimental-defs.md index 11121f1d0fcd..5060ffb889d5 100644 --- a/docs/docs/reference/other-new-features/experimental-defs.md +++ b/docs/docs/reference/other-new-features/experimental-defs.md @@ -1,8 +1,12 @@ --- -layout: doc-page title: "Experimental definitions" +type: section +num: 51 +previous-page: /scala3/reference/other-new-features/type-test +next-page: /scala3/reference/changed-features --- + ## Experimental definitions The `@experimental` annotation allows the definition of an API that is not guaranteed backward binary or source compatibility. diff --git a/docs/docs/reference/other-new-features/type-test.md b/docs/docs/reference/other-new-features/type-test.md index 1fab03490e98..62b8d59eec6d 100644 --- a/docs/docs/reference/other-new-features/type-test.md +++ b/docs/docs/reference/other-new-features/type-test.md @@ -3,7 +3,7 @@ title: "TypeTest" type: section num: 50 previous-page: /scala3/reference/other-new-features/safe-initialization -next-page: /scala3/reference/changed-features +next-page: /scala3/reference/other-new-features/experimental-defs --- ## TypeTest diff --git a/docs/docs/reference/syntax.md b/docs/docs/reference/syntax.md index 5bb53ddac00b..4561ad7c91b6 100644 --- a/docs/docs/reference/syntax.md +++ b/docs/docs/reference/syntax.md @@ -1,7 +1,7 @@ --- title: "Scala 3 Syntax Summary" type: chapter -num: 87 +num: 88 previous-page: /scala3/reference/dropped-features/wildcard-init --- diff --git a/docs/docs/resources/talks.md b/docs/docs/resources/talks.md deleted file mode 100644 index 9991d847fb9a..000000000000 --- a/docs/docs/resources/talks.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -layout: singlepage-overview -title: "Talks" ---- - -Let’s Talk About Scala 3 Series -------------------------------- - -[Let’s Talk About Scala 3](https://www.youtube.com/playlist?list=PLTx-VKTe8yLxYQfX_eGHCxaTuWvvG28Ml) is a series -of short (around 15 min) talks about Scala 3. It covers a variety of themes like how to get started, how to take -advantage of the new language features, or how to migrate from Scala 2. - -Talks on Scala 3 ----------------- -- (ScalaDays 2019, Lausanne) [A Tour of Scala 3](https://www.youtube.com/watch?v=_Rnrx2lo9cw) by [Martin Odersky](http://twitter.com/odersky) [\[slides\]](https://www.slideshare.net/Odersky/a-tour-of-scala-3) - -- (ScalaDays 2016, Berlin) [Scala's Road Ahead](https://www.youtube.com/watch?v=GHzWqJKFCk4) by [Martin Odersky](http://twitter.com/odersky) [\[slides\]](http://www.slideshare.net/Odersky/scala-days-nyc-2016) - -- (JVMLS 2015) [Compilers are Databases](https://www.youtube.com/watch?v=WxyyJyB_Ssc) by [Martin Odersky](http://twitter.com/odersky) [\[slides\]](http://www.slideshare.net/Odersky/compilers-are-databases) - -- (Scala World 2015) [Dotty: Exploring the future of Scala](https://www.youtube.com/watch?v=aftdOFuVU1o) by [Dmitry Petrashko](http://twitter.com/darkdimius) [\[slides\]](https://d-d.me/scalaworld2015/#/). - Dmitry covers many of the new features that Dotty brings on the table such as Intersection and Union types, improved lazy val initialization and more. - Dmitry also covers dotty internals and in particular the high-level of contextual abstractions of Dotty. You will get to - become familiar with many core concepts such as `Denotations`, their evolution through (compilation) time, their - transformations and more. - -Deep Dive with Scala 3 ----------------------- -- (ScalaDays 2019, Lausanne) [Metaprogramming in Dotty](https://www.youtube.com/watch?v=ZfDS_gJyPTc) by [Nicolas Stucki](https://github.com/nicolasstucki). - -- (ScalaDays 2019, Lausanne) [Future-proofing Scala: the TASTY intermediate representation](https://www.youtube.com/watch?v=zQFjC3zLYwo) by [Guillaume Martres](http://guillaume.martres.me/). - -- (Mar 21, 2017) [Dotty Internals 1: Trees & Symbols](https://www.youtube.com/watch?v=yYd-zuDd3S8) by [Dmitry Petrashko](http://twitter.com/darkdimius) [\[meeting notes\]](https://dotty.epfl.ch/docs/internals/dotty-internals-1-notes.html). - This is a recorded meeting between EPFL and Waterloo, where we introduce first notions inside Dotty: Trees and Symbols. - -- (Mar 21, 2017) [Dotty Internals 2: Types](https://www.youtube.com/watch?v=3gmLIYlGbKc) by [Martin Odersky](http://twitter.com/odersky) and [Dmitry Petrashko](http://twitter.com/darkdimius). - This is a recorded meeting between EPFL and Waterloo, where we introduce how types are represented inside Dotty. - -- (Jun 15, 2017) [Dotty Internals 3: Denotations](https://youtu.be/9iPA7zMRGKY) by [Martin Odersky](http://twitter.com/odersky) and [Dmitry Petrashko](http://twitter.com/darkdimius). - This is a recorded meeting between EPFL and Waterloo, where we introduce denotations in Dotty. - -- (JVM Language Summit) [How do we make the Dotty compiler fast](https://www.youtube.com/watch?v=9xYoSwnSPz0) by [Dmitry Petrashko](http://twitter.com/darkdimius). - [Dmitry Petrashko](http://twitter.com/darkdimius) gives a high-level introduction on what was done to make Dotty . - - -- (Typelevel Summit Oslo, May 2016) [Dotty and types: the story so far](https://www.youtube.com/watch?v=YIQjfCKDR5A) by - Guillaume Martres [\[slides\]](http://guillaume.martres.me/talks/typelevel-summit-oslo/). - Guillaume focused on some of the practical improvements to the type system that Dotty makes, like the new type parameter - inference algorithm that is able to reason about the type safety of more situations than scalac. - -- (flatMap(Oslo) 2016) [AutoSpecialization in Dotty](https://vimeo.com/165928176) by [Dmitry Petrashko](http://twitter.com/darkdimius) [\[slides\]](https://d-d.me/talks/flatmap2016/#/). - The Dotty Linker analyses your program and its dependencies to - apply a new specialization scheme. It builds on our experience from Specialization, Miniboxing and the Valhalla Project, - and drastically reduces the size of the emitted bytecode. And, best of all, it's always enabled, happens behind the - scenes without annotations, and results in speedups in excess of 20x. Additionally, it "just works" on Scala collections. - -- (ScalaSphere 2016) [Hacking on Dotty: A live demo](https://www.youtube.com/watch?v=0OOYGeZLHs4) by Guillaume Martres [\[slides\]](http://guillaume.martres.me/talks/dotty-live-demo/). - Guillaume hacks on Dotty: a live demo during which he - creates a simple compiler phase to trace method calls at run-time. - -- (Scala By the Bay 2016) [Dotty: what is it and how it works](https://www.youtube.com/watch?v=wCFbYu7xEJA) by Guillaume - Martres [\[slides\]](http://guillaume.martres.me/talks/dotty-tutorial/#/). Guillaume provides a high-level view of the - compilation-pipeline of Dotty. - -- (ScalaDays 2015, Amsterdam) [Making your Scala applications smaller and faster with the Dotty linker](https://www.youtube.com/watch?v=xCeI1ArdXM4) by Dmitry Petrashko [\[slides\]](https://d-d.me/scaladays2015/#/). - Dmitry introduces the call-graph analysis algorithm - that Dotty implements and the performance benefits we can get in terms of number of methods, bytecode size, JVM code size - and the number of objects allocated in the end. - diff --git a/docs/docs/usage/getting-started.md b/docs/docs/usage/getting-started.md deleted file mode 100644 index c888285fb39c..000000000000 --- a/docs/docs/usage/getting-started.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -layout: singlepage-overview -title: Getting Started with Scala 3 -languages: ["ja"] ---- - - - -## Try Scala without installing anything - -To start experimenting with Scala 3 right away, use “Scastie” in your browser. -_Scastie_ is an online “playground” where you can experiment with Scala examples to see how things work, with access to all Scala compilers and published libraries. - - - -## Install Scala on your computer - -Installing Scala means installing various command-line tools and build tools. -We recommend using the Scala installer tool "Coursier" that automatically installs all the requirements, but you can still manually install each tool. - - -### Using the Scala Installer (recommended way) - -The Scala installer is a tool named [Coursier](https://get-coursier.io/docs/cli-overview), whose main command is named `cs`. -It ensures that a JVM and standard Scala tools are installed on your system. -Install it on your system with the following instructions. - -
-
-

Follow the instructions to install the cs launcher then run:

-

$ cs install scala3-repl

-

$ cs install scala3-compiler

-
-
- -Along with managing JVMs, `cs setup` also installs useful command line tools: - -- A JDK -- The [sbt](https://www.scala-sbt.org) and [mill](https://com-lihaoyi.github.io/mill/) build tools -- [Ammonite](https://ammonite.io), an enhanced REPL -- [scalafmt](https://scalameta.org/scalafmt), the Scala formatter -- The [Coursier CLI](https://get-coursier.io/docs/cli-overview), to install further Scala-based applications -- (the `scala` and `scalac` command-line tools for Scala 2.13 -- not Scala 3). - -For more information, read the [coursier-cli documentation](https://get-coursier.io/docs/cli-overview). - - -### ... or manually - -You only need two tools to compile, run, test, and package a Scala project: Java 8 or 11, and sbt. -To install these manually: - -1. Download Java from [Oracle Java 8](https://www.oracle.com/java/technologies/javase-jdk8-downloads.html), [Oracle Java 11](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html), or [AdoptOpenJDK 8/11](https://adoptopenjdk.net/). Refer to [JDK Compatibility](/overviews/jdk-compatibility/overview.html) for Scala/Java compatibility detail. -2. Install [sbt](https://www.scala-sbt.org/download.html) - - - -## Create a “Hello, world” project with sbt - -To create a project, you can either use a command-line tool or an IDE. -If you are familiar with the command line, we recommend that approach. - - -### Using the command line - -sbt is a build tool for Scala. -sbt compiles, runs, and tests your Scala code. -(It can also publish libraries and do many other tasks.) - -To create a new Scala project with sbt: - -1. `cd` to an empty folder. -1. Run this command `sbt new scala/scala3.g8`. -This pulls the ['hello-world' template][template-url] from GitHub. -It also creates a _target_ folder, which you can ignore. -1. When prompted, name the application `hello world`. - This will create a project called "hello-world". -1. Let’s take a look at what just got generated: - -``` -hello-world/ - project/ (sbt uses this for its own files) - build.properties - src/main/scala/ (all of your Scala code goes here) - Main.scala (entry point of program) - build.sbt (sbt’s build definition file) -``` -The scala file `Main.scala` in `src/main/scala` is all we need for now. - -More documentation about sbt can be found in the [Scala Book](/scala3/book/scala-tools.html) and in the official sbt [documentation](https://www.scala-sbt.org/1.x/docs/index.html) - - -{% comment %} -### With IntelliJ IDEA - -You can skip the rest of this page and go directly to [Building a Scala Project with IntelliJ and sbt](/getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.html) -{% endcomment %} - - -## Open the “Hello, world” project - -Let’s use an IDE to open the project. -The most popular ones are IntelliJ IDEA and VS Code. -They both offer rich IDE features, but you can still use [many other editors.](https://scalameta.org/metals/docs/editors/overview.html) - -### Using IntelliJ IDEA - -1. Download and install [IntelliJ Community Edition](https://www.jetbrains.com/idea/download/) -1. Install the Scala plugin by following [the instructions on how to install IntelliJ plugins](https://www.jetbrains.com/help/idea/managing-plugins.html) -1. Open the _build.sbt_ file, then choose _Open as a project_ - -### Using VS Code with Metals - -1. Download [VS Code](https://code.visualstudio.com/Download) -1. Install the Metals extension from [the Marketplace](https://marketplace.visualstudio.com/items?itemName=scalameta.metals) -1. Next, open the directory containing your _build.sbt_ file. - When prompted to do so, select _Import build_. - ->[Metals](https://scalameta.org/metals) is a “Scala language server” that provides support for writing Scala code in VS Code and other editors like [Atom, Sublime Text, and more](https://scalameta.org/metals/docs/editors/overview.html), using the Language Server Protocol. -> -> Under the hood, Metals communicates with the build tool by using -> the [Build Server Protocol (BSP)](https://build-server-protocol.github.io/). For details on how Metals works, see, [“Write Scala in VS Code, Vim, Emacs, Atom and Sublime Text with Metals”](https://www.scala-lang.org/2019/04/16/metals.html). - - -### View the source code - -View these two files in your IDE: - -- _build.sbt_ -- _src/main/scala/Main.scala_ - -When you run your project in the next step, the configuration in _build.sbt_ will be used to run the code in _src/main/scala/Main.scala_. - - - -## Run the “Hello, world” project - -If you’re comfortable using your IDE, you can run the code in _Main.scala_ from your IDE. - -Otherwise, you can run the application from a terminal with these steps: - -1. `cd` into _hello-world_. -1. Run `sbt`. - This opens up the sbt console. -1. Type `~run`. - The `~` is optional and causes sbt to re-run on every file save, allowing for a fast edit/run/debug cycle. - sbt also generates a `target` directory for its own use, which you can ignore. - -When you’re finished experimenting with this project, press `[Enter]` to interrupt the `run` command. -Then type `exit` or press `[Ctrl][d]` to exit sbt and return to your command line prompt. - - - -## Next steps - -Now that you’ve created a first “Hello, world” example with Scala 3, you’re ready for some next steps. -Consider checking out: - -- [The Scala 3 Book](/scala3/book/introduction.html), which provides a set of short lessons introducing Scala’s main features -- [The migration guide](/scala3/guides/migration/compatibility-intro.html) helps you to migrate your existing Scala 2 code base to Scala 3. - -When you want to connect with other Scala users, there are several mailing lists and real-time chat rooms available. -Check out our [Scala community page](https://scala-lang.org/community/) for a list of these resources, and for where to reach out for help. - - - - - - - - - - - -[template-url]: https://github.com/scala/scala3.g8 diff --git a/docs/docs/usage/scaladoc/search-engine.md b/docs/docs/usage/scaladoc/search-engine.md index b338d38792a7..1bac1d37635d 100644 --- a/docs/docs/usage/scaladoc/search-engine.md +++ b/docs/docs/usage/scaladoc/search-engine.md @@ -83,4 +83,4 @@ Inkuire works as a JavaScript worker in the browser thanks to the power of [Scal To enable Inkuire when running scaladoc, add the flag `-Ygenerate-inkuire`. By adding this flag two files are generated: - `inkuire-db.json` - this is the file containing all the searchable declarations from the currently documented project in a format readable to the Inkuire search engine. -- `inkuire-config.json` - this file contains the locations of the database files that should be searchable from the documentation of the current project. By default, it will be generated with the location of the local db file as well as the default implied locations of database files in [External mappings](/scala3/guides/scaladoc/settings.html#-external-mappings). +- `inkuire-config.json` - this file contains the locations of the database files that should be searchable from the documentation of the current project. By default, it will be generated with the location of the local db file as well as the default implied locations of database files in [External mappings](https://docs.scala-lang.org/scala3/guides/scaladoc/settings.html#-external-mappings). diff --git a/docs/docs/usage/tools-worksheets.md b/docs/docs/usage/tools-worksheets.md deleted file mode 100644 index e503e72f0c23..000000000000 --- a/docs/docs/usage/tools-worksheets.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Worksheets -type: section -description: This section looks at worksheets, an alternative to Scala projects. -num: 71 -previous-page: tools-sbt -next-page: interacting-with-java ---- - -A worksheet is a Scala file that is evaluated on save, and the result of each expression is shown -in a column to the right of your program. Worksheets are like a [REPL session] on steroids, and -enjoy 1st class editor support: completion, hyperlinking, interactive errors-as-you-type, etc. -Worksheets use the extension `.worksheet.sc`. - -In the following, we show how to use worksheets in IntelliJ, and in VS Code (with the Metals extension). - -1. Open a Scala project, or create one. - - To create a project in IntelliJ, select “File” -> “New” -> “Project…”, select “Scala” - in the left column, and click “Next” to set the project name and location. - - To create a project in VS Code, run the command “Metals: New Scala project”, select the - seed `scala/scala3.g8`, set the project location, open it in a new VS Code window, and - import its build. -1. Create a file named `hello.worksheet.sc` in the directory `src/main/scala/`. - - In IntelliJ, right-click on the directory `src/main/scala/`, and select “New”, and - then “File”. - - In VS Code, right-click on the directory `src/main/scala/`, and select “New File”. -1. Paste the following content in the editor: - ~~~ - println("Hello, world!") - - val x = 1 - x + x - ~~~ -1. Evaluate the worksheet. - - In IntelliJ, click on the green arrow at the top of the editor to evaluate the worksheet. - - In VS Code, save the file. - - You should see the result of the evaluation of every line on the right panel (IntelliJ), or - as comments (VS Code). - -![]({{ site.baseurl }}/resources/images/scala3-book/intellij-worksheet.png) - -A worksheet evaluated in IntelliJ. - -![]({{ site.baseurl }}/resources/images/scala3-book/metals-worksheet.png) - -A worksheet evaluated in VS Code (with the Metals extension). - -Note that the worksheet will use the Scala version defined by your project (set by the key `scalaVersion`, -in your file `build.sbt`, typically). - -Also note that worksheets don’t have a [program entry point]. Instead, top-level statements and expressions -are evaluated from top to bottom. - -[REPL session]: {% link _overviews/scala3-book/taste-repl.md %} -[program entry point]: {% link _overviews/scala3-book/methods-main-methods.md %} diff --git a/docs/docsScalaLangResources/scaladoc-assets.html b/docs/docsScalaLangResources/scaladoc-assets.html new file mode 100644 index 000000000000..504a93b25fa8 --- /dev/null +++ b/docs/docsScalaLangResources/scaladoc-assets.html @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/images/scaladoc/inkuire-1.0.0-M2_js_flatMap.gif b/docs/images/scaladoc/inkuire-1.0.0-M2_js_flatMap.gif new file mode 100644 index 000000000000..1cc25b5683f7 Binary files /dev/null and b/docs/images/scaladoc/inkuire-1.0.0-M2_js_flatMap.gif differ diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 4b47033e64cb..7a534eb42ae8 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -2,10 +2,8 @@ sidebar: - title: Blog - title: Usage subsection: - - page: docs/usage/getting-started.md - page: docs/usage/sbt-projects.md - page: docs/usage/ide-support.md - - page: docs/usage/tools-worksheets.md - page: docs/usage/cbt-projects.md - page: docs/usage/scaladoc - title: Reference @@ -147,6 +145,3 @@ sidebar: - page: docs/internals/type-system.md - page: docs/internals/dotty-internals-1-notes.md - page: docs/internals/debug-macros.md - - title: Resources - subsection: - - page: docs/resources/talks.md diff --git a/project/Build.scala b/project/Build.scala index 8520a5de6839..65daf5ee280c 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -24,6 +24,7 @@ import sbtbuildinfo.BuildInfoPlugin.autoImport._ import scala.util.Properties.isJavaAtLeast import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._ +import org.scalajs.linker.interface.ModuleInitializer object DottyJSPlugin extends AutoPlugin { import Build._ @@ -1246,6 +1247,7 @@ object Build { // Note: the two tasks below should be one, but a bug in Tasty prevents that val generateScalaDocumentation = inputKey[Unit]("Generate documentation for dotty lib") val generateTestcasesDocumentation = taskKey[Unit]("Generate documentation for testcases, usefull for debugging tests") + val renderScaladocScalajsToFile = inputKey[Unit]("Copy the output of the scaladoc js files") lazy val `scaladoc-testcases` = project.in(file("scaladoc-testcases")). dependsOn(`scala3-compiler-bootstrapped`). @@ -1254,8 +1256,12 @@ object Build { enablePlugins(DottyJSPlugin). dependsOn(`scala3-library-bootstrappedJS`). settings( + Compile / scalaJSMainModuleInitializer := (sys.env.get("scaladoc.projectFormat") match { + case Some("md") => Some(ModuleInitializer.mainMethod("dotty.tools.scaladoc.Main", "markdownMain")) + case _ => Some(ModuleInitializer.mainMethod("dotty.tools.scaladoc.Main", "main")) + }), Test / fork := false, - scalaJSUseMainModuleInitializer := true, + Compile / scalaJSUseMainModuleInitializer := true, libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0").cross(CrossVersion.for3Use2_13) ) @@ -1309,7 +1315,7 @@ object Build { ). settings( Compile / resourceGenerators += Def.task { - val jsDestinationFile = (Compile / resourceManaged).value / "dotty_res" / "scripts" / "searchbar.js" + val jsDestinationFile = (Compile / resourceManaged).value / "dotty_res" / "scripts" / "scaladoc-scalajs.js" sbt.IO.copyFile((`scaladoc-js` / Compile / fullOptJS).value.data, jsDestinationFile) Seq(jsDestinationFile) }.taskValue, @@ -1359,7 +1365,7 @@ object Build { Seq(inkuireDestinationFile) }.taskValue, libraryDependencies ++= Dependencies.flexmarkDeps ++ Seq( - "nl.big-o" % "liqp" % "0.6.7", + "nl.big-o" % "liqp" % "0.6.8", "org.jsoup" % "jsoup" % "1.13.1", // Needed to process .html files for static site Dependencies.`jackson-dataformat-yaml`, @@ -1439,6 +1445,23 @@ object Build { ) }.value, + renderScaladocScalajsToFile := Def.inputTask { + val extraArgs = spaceDelimited("").parsed + val (destJS, destCSS, csses) = extraArgs match { + case js :: css :: tail => (js, css, tail) + case js :: Nil => (js, "", Nil) + case _ => throw new IllegalArgumentException("No js destination provided") + } + val jsDestinationFile: File = Paths.get(destJS).toFile + sbt.IO.copyFile((`scaladoc-js` / Compile / fullOptJS).value.data, jsDestinationFile) + csses.map { file => + val cssDesitnationFile = Paths.get(destCSS).toFile / file + val cssSourceFile = (`scaladoc-js` / Compile / resourceDirectory).value / file + sbt.IO.copyFile(cssSourceFile, cssDesitnationFile) + cssDesitnationFile + } + }.evaluated, + Test / buildInfoKeys := Seq[BuildInfoKey]( (Test / Build.testcasesOutputDir), (Test / Build.testcasesSourceRoot), diff --git a/project/CopyDocs.scala b/project/CopyDocs.scala index 5713f15e71ef..d8bcd4474824 100644 --- a/project/CopyDocs.scala +++ b/project/CopyDocs.scala @@ -22,11 +22,11 @@ object CopyDocs { implicit def stringToFun(s: String): MyParams => String = _ => s // Patterns, for convenience - val titlePattern = "(?s)^---\n.*title: ([^\n]*).*---" - val jekyllLinkPattern = """\{\% link _overviews/scala3-scaladoc(.*) %\}""" + val titlePattern = "(?s)^---\n.*?title: ([^\n]*).*?---" + val jekyllLinkPattern = """\{\% link _overviews/scala3-reference(.*) %\}""" val jekyllLinkSubstitution = "..$1" - val jekyllLinkPattern2 = """\{\% link |_overviews/scala3-scaladoc/(.*) %\}""" - val jekyllLinkSubstitution2 = "$1" + val jekyllLinkPattern2 = """\{\% link _overviews/scala3-scaladoc(.*) %\}""" + val jekyllLinkSubstitution2 = ".$1" val localLinkPattern = """\((?!http|www)(.*).html\)""" val localLinkSubstitution = "($1.md)" @@ -44,25 +44,29 @@ object CopyDocs { * The inner set is a collection of pairs `regex pattern` -> `substitution value`. */ val transformationMap: Map[String, Set[(String, MyParams => String)]] = Map( - "docs/docs/reference/" -> (commonTransformations + - (titlePattern -> ((p) => s"---\nlayout: doc-page\ntitle: $$1\nmovedTo: https://docs.scala-lang.org/scala3/reference/${p.newPath}.html\n---")), + "docs/docs/usage/scaladoc/index.md" -> Set( + ("""\{\{ site\.baseurl \}\}/resources/images/scala3/scaladoc/logo\.svg""" -> "images/scaladoc_logo.svg"), ), - "docs/docs/usage/scaladoc/" -> (commonTransformations + - (titlePattern -> s"---\ntitle: $$1\n---"), + "docs/docs/usage/scaladoc/site-versioning.md" -> Set( + ("""/resources/images/scala3/scaladoc/nightly\.gif""" -> "images/scaladoc/nightly.gif"), ), - "docs/docs/usage/getting-started" -> (commonTransformations + - (titlePattern -> "---\nlayout: doc-page\ntitle: Getting Started: Users\nmovedTo: https://docs.scala-lang.org/scala3/getting-started.html\n---"), + "docs/docs/usage/scaladoc/search-engine.md" -> Set( + ("""/resources/images/scala3/scaladoc/inkuire-1\.0\.0-M2_js_flatMap\.gif""" -> "images/scaladoc/inkuire-1.0.0-M2_js_flatMap.gif"), ), - "docs/docs/usage/tools-worksheets" -> (commonTransformations + - (titlePattern -> "---\nlayout: doc-page\ntitle: \"Worksheet mode with Dotty IDE\"\nmovedTo: https://docs.scala-lang.org/scala3/book/tools-worksheets.html\n---") + "docs/docs/reference/other-new-features/explicit-nulls.md" -> Set( + ("""/resources/images/scala3/explicit-nulls/explicit-nulls-type-hierarchy\.png""" -> "images/explicit-nulls/explicit-nulls-type-hierarchy.png"), ), - "docs/docs/resources/talks" -> (commonTransformations + - (titlePattern -> "---\nlayout: doc-page\ntitle: Talks\nmovedTo: https://docs.scala-lang.org/scala3/talks.html\n---") - ) + "docs/docs/reference/" -> (commonTransformations + + (titlePattern -> ((p) => s"---\nlayout: doc-page\ntitle: $$1\nmovedTo: https://docs.scala-lang.org/scala3/reference/${p.newPath}.html\n---")), + ), + + "docs/docs/usage/scaladoc/" -> (commonTransformations + + (titlePattern -> s"---\ntitle: $$1\n---"), + ), ) def copyDocs() = { @@ -76,7 +80,7 @@ object CopyDocs { val fileContent = inputStream.getLines().mkString("\n") new PrintStream(newPath.toFile) { - val patterns = transformationMap.find { case (k, v) => path.toString.startsWith(k) }.map(_._2).getOrElse(Set.empty) + val patterns = transformationMap.filter { case (k, v) => path.toString.startsWith(k) }.flatMap(_._2) val params = MyParams(newPath = s.stripPrefix("docs/docs/reference/").stripSuffix(".md")) val transformed = patterns.foldLeft(fileContent) { case (res, (pattern, substitution)) => res.replaceAll(pattern, substitution(params)) } write(transformed.getBytes("UTF8")) diff --git a/project/scripts/genDocsScalaLang b/project/scripts/genDocsScalaLang new file mode 100755 index 000000000000..1ce53899fd33 --- /dev/null +++ b/project/scripts/genDocsScalaLang @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -e +shopt -s extglob # needed for rm everything but x +echo "Working directory: $PWD" + +GENDOC_EXTRA_ARGS=$@ +GIT_HEAD=$(git rev-parse HEAD) # save current head for commit message in gh-pages +PREVIOUS_SNAPSHOTS_DIR="$PWD/../prev_snapshots" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >& /dev/null && pwd)" +SITE_OUT_DIR="$PWD/docs/_site" + +DOCS_SCALA_LANG_DIR="$PWD/docsScalaLang" + +rm -rf $DOCS_SCALA_LANG_DIR +mkdir -pv $DOCS_SCALA_LANG_DIR +git clone "https://github.com/scala/docs.scala-lang.git" $DOCS_SCALA_LANG_DIR + +SBT="$SCRIPT_DIR/sbt" +mkdir -pv $SITE_OUT_DIR + +env "scaladoc.projectFormat=md" "$SBT" "scaladoc/renderScaladocScalajsToFile $DOCS_SCALA_LANG_DIR/scripts/scaladoc-scalajs.js $DOCS_SCALA_LANG_DIR/resources/css code-snippets.css" + +DOTTY_NONBOOTSTRAPPED_VERSION_COMMAND="$SBT \"eval println(Build.dottyNonBootstrappedVersion)\"" +DOTTY_NONBOOTSTRAPPED_VERSION=$(eval $DOTTY_NONBOOTSTRAPPED_VERSION_COMMAND | tail -n 2 | head -n 1) + +DOTTY_BOOTSTRAPPED_VERSION_COMMAND="$SBT \"eval println(Build.dottyVersion)\"" +DOTTY_BOOTSTRAPPED_VERSION=$(eval $DOTTY_BOOTSTRAPPED_VERSION_COMMAND | tail -n 2 | head -n 1) + +GITHUB_REPOSITORY="lampepfl/dotty" +GITHUB_SHA="3.0.0" + +"bin/scaladoc" "-d" "$SITE_OUT_DIR" "-format" "md" "-siteroot" "docs" "/dev/null " \ + -source-links:out/bootstrap/stdlib-bootstrapped/scala-"${DOTTY_NONBOOTSTRAPPED_VERSION}"/src_managed/main/scala-library-src=github://scala/scala/v"${STDLIB_VERSION}"#src/library \ + -source-links:out/bootstrap/stdlib-bootstrapped/scala-"${DOTTY_NONBOOTSTRAPPED_VERSION}"/src_managed/main/dotty-library-src=github://"${GITHUB_REPOSITORY}"/"${GITHUB_SHA}"\#library/src \ + -source-links:github://"${GITHUB_REPOSITORY}"/"${GITHUB_SHA}" \ + +if [ ! -d "$SITE_OUT_DIR" ]; then + echo "Output directory did not exist: $SITE_OUT_DIR" 1>&2 + exit 1 +fi + +# Copy reference and scaladoc docs +cp -rf "$SITE_OUT_DIR/docs/reference"/* "$DOCS_SCALA_LANG_DIR/_scala3-reference" +cp -rf "$SITE_OUT_DIR/docs/usage/scaladoc"/* "$DOCS_SCALA_LANG_DIR/_overviews/scala3-scaladoc" + +# Copy csses and html importing these assets +cp -f "$SITE_OUT_DIR/styles/colors.css" "$DOCS_SCALA_LANG_DIR/resources/css/colors.css" +cp -f "$PWD/docs/docsScalaLangResources/scaladoc-assets.html" "$DOCS_SCALA_LANG_DIR/_includes/scaladoc-assets.html" + +# Copy images and resources +cp -f "$PWD/scaladoc/resources/dotty_res/images/scaladoc_logo.svg" "$DOCS_SCALA_LANG_DIR/resources/images/scala3/scaladoc/logo.svg" +cp -f "$PWD/docs/images/scaladoc/nightly.gif" "$DOCS_SCALA_LANG_DIR/resources/images/scala3/scaladoc/nightly.gif" +cp -f "$PWD/docs/images/scaladoc/inkuire-1.0.0-M2_js_flatMap.gif" "$DOCS_SCALA_LANG_DIR/resources/images/scala3/scaladoc/inkuire-1\.0\.0-M2_js_flatMap.gif" +cp -f "$PWD/docs/images/explicit-nulls/explicit-nulls-type-hierarchy.png" "$DOCS_SCALA_LANG_DIR/resources/images/scala3/explicit-nulls/explicit-nulls-type-hierarchy.png" + +# Hack inclusion of these assests by the docs.scala-lang jekyll builder +echo "{% include scaladoc-assets.html %}" >> "$DOCS_SCALA_LANG_DIR/_layouts/inner-page-parent-dropdown.html" diff --git a/scaladoc-js/src/Main.scala b/scaladoc-js/src/Main.scala index a7d7e8d552be..f7075766e3b4 100644 --- a/scaladoc-js/src/Main.scala +++ b/scaladoc-js/src/Main.scala @@ -1,9 +1,22 @@ package dotty.tools.scaladoc -object Main extends App { - Searchbar() - SocialLinks() - CodeSnippets() - DropdownHandler() - Ux() -} +object Main: + + private def common(): Unit = + CodeSnippets() + + def main(): Unit = + Searchbar() + SocialLinks() + DropdownHandler() + Ux() + common() + + /** + * This main is conditionally enabled by system env variable `scaladoc.projectFormat=md` + * passed in ./projects/scripts/genDocsScalaLang + * The reason why we have to pass the condition by env variable is because js is build before scaladoc, + * so we cannot access its args + */ + def markdownMain(): Unit = + common() diff --git a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala index 487eebf7a1b6..bd8493ebb9ec 100644 --- a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala +++ b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala @@ -59,7 +59,8 @@ object Scaladoc: versionsDictionaryUrl: Option[String] = None, generateInkuire : Boolean = false, apiSubdirectory : Boolean = false, - scastieConfiguration: String = "" + scastieConfiguration: String = "", + projectFormat: String = "html", ) def run(args: Array[String], rootContext: CompilerContext): Reporter = @@ -236,7 +237,8 @@ object Scaladoc: versionsDictionaryUrl.nonDefault, generateInkuire.get, apiSubdirectory.get, - scastieConfiguration.get + scastieConfiguration.get, + projectFormat.get, ) (Some(docArgs), newContext) } @@ -245,6 +247,10 @@ object Scaladoc: given docContext: DocContext = new DocContext(args, ctx) val module = ScalaModuleProvider.mkModule() - new dotty.tools.scaladoc.renderers.HtmlRenderer(module.rootPackage, module.members).render() + val renderer = args.projectFormat match + case "html" => new dotty.tools.scaladoc.renderers.HtmlRenderer(module.rootPackage, module.members) + case "md" => new dotty.tools.scaladoc.renderers.MarkdownRenderer(module.rootPackage, module.members) + + renderer.render() report.inform("generation completed successfully") docContext diff --git a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala index e9058c504147..4697783de20c 100644 --- a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala +++ b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala @@ -129,5 +129,15 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings: val scastieConfiguration: Setting[String] = StringSetting("-scastie-configuration", "Scastie configuration", "Additional configuration passed to Scastie in code snippets", "") + val projectFormat: Setting[String] = + ChoiceSetting( + "-format", + "format of the static site output", + "Format of the static site output. The default value is html, which converts all static articles into a webpage. " + + "The md format only preprocess markdown files and should not be used as a direct output, but rather as a sources generator for an outer templating engine like Jekyll", + List("html", "md"), + "html" + ) + def scaladocSpecificSettings: Set[Setting[_]] = Set(sourceLinks, legacySourceLink, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent, snippetCompiler, generateInkuire, scastieConfiguration) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala index 8db1dc2e5b87..3b6876238436 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala @@ -14,120 +14,21 @@ import java.nio.file.Files import java.nio.file.FileVisitOption import java.io.File -case class Page(link: Link, content: Member | ResolvedTemplate | String, children: Seq[Page]): - def withNewChildren(newChildren: Seq[Page]) = copy(children = children ++ newChildren) +class HtmlRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: DocContext) + extends Renderer(rootPackage, members, extension = "html"): - def withTitle(newTitle: String) = copy(link = link.copy(name = newTitle)) - - def hasFrame = content match - case t: ResolvedTemplate => t.hasFrame - case _ => true - -class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx: DocContext) - extends SiteRenderer, Resources, Locations, Writer: - private val args = summon[DocContext].args - val staticSite = summon[DocContext].staticSiteContext - - val effectiveMembers = members - - private def memberPage(member: Member): Page = - val childrenPages = member.members.filter(_.needsOwnPage) - Page(Link(member.name, member.dri), member, childrenPages.map(memberPage)) - - val navigablePage: Page = - val rootPckPage = memberPage(rootPackage) - staticSite match - case None => rootPckPage.withTitle(args.name) - case Some(siteContext) => - val (indexes, templates) = siteContext.templates.partition(f => - f.templateFile.isIndexPage() && f.file.toPath.getParent() == siteContext.docsPath) - if (indexes.size > 1) - val msg = s"ERROR: Multiple index pages for doc found ${indexes.map(_.file)}" - report.error(msg) - - val templatePages = templates.map(templateToPage(_, siteContext)) - - indexes.headOption match - case None if templatePages.isEmpty=> - rootPckPage.withTitle(args.name) - case None => - Page(Link(args.name, docsRootDRI),"", templatePages :+ rootPckPage.withTitle("API")) - case Some(indexPage) => - val newChildren = templatePages :+ rootPckPage.withTitle("API") - templateToPage(indexPage, siteContext).withNewChildren(newChildren) - - val hiddenPages: Seq[Page] = - staticSite match - case None => - Seq(navigablePage.copy( // Add index page that is a copy of api/index.html - link = navigablePage.link.copy(dri = docsRootDRI), - children = Nil - )) - case Some(siteContext) => - // In case that we do not have an index page and we do not have any API entries - // we want to create empty index page, so there is one - val actualIndexTemplate = siteContext.indexTemplate() match { - case None if effectiveMembers.isEmpty => Seq(siteContext.emptyIndexTemplate) - case templates => templates.toSeq - } - - (siteContext.orphanedTemplates ++ actualIndexTemplate).map(templateToPage(_, siteContext)) - - /** - * Here we have to retrive index pages from hidden pages and replace fake index pages in navigable page tree. - */ - val allPages: Seq[Page] = - def traversePages(page: Page): (Page, Seq[Page]) = - val (newChildren, newPagesToRemove): (Seq[Page], Seq[Page]) = page.children.map(traversePages(_)).foldLeft((Seq[Page](), Seq[Page]())) { - case ((pAcc, ptrAcc), (p, ptr)) => (pAcc :+ p, ptrAcc ++ ptr) - } - hiddenPages.find(_.link == page.link) match - case None => - (page.copy(children = newChildren), newPagesToRemove) - case Some(newPage) => - (newPage.copy(children = newChildren), newPagesToRemove :+ newPage) - - val (newNavigablePage, pagesToRemove) = traversePages(navigablePage) - - val all = newNavigablePage +: hiddenPages.filterNot(pagesToRemove.contains) - // We need to check for conflicts only if we have top-level member called blog or docs - val hasPotentialConflict = - rootPackage.members.exists(m => m.name.startsWith("docs") || m.name.startsWith("blog")) - - if hasPotentialConflict then - def walk(page: Page): Unit = - if page.link.dri.isStaticFile then - val dest = absolutePath(page.link.dri) - if apiPaths.contains(dest) then - report.error(s"Conflict between static page and API member for $dest. $pathsConflictResoultionMsg") - page.children.foreach(walk) - - all.foreach (walk) - - all - - def renderContent(page: Page) = page.content match - case m: Member => - val signatureRenderer = new SignatureRenderer: - def currentDri: DRI = page.link.dri - def link(dri: DRI): Option[String] = - Some(pathToPage(currentDri, dri)).filter(_ != UnresolvedLocationLink) - - MemberRenderer(signatureRenderer).fullMember(m) - case t: ResolvedTemplate => siteContent(page.link.dri, t) - case a: String => raw(a) - - - def renderPage(page: Page, parents: Vector[Link]): Seq[String] = - val newParents = parents :+ page.link - val content = html( + override def pageContent(page: Page, parents: Vector[Link]): AppliedTag = + html( mkHead(page), body( if !page.hasFrame then renderContent(page) - else mkFrame(page.link, newParents, renderContent(page)) + else mkFrame(page.link, parents, renderContent(page)) ) ) - write(page.link.dri, content) +: page.children.flatMap(renderPage(_, newParents)) + + override def render(): Unit = + val renderedResources = renderResources() + super.render() private def specificResources(page: Page): Set[String] = page.children.toSet.flatMap(specificResources) ++ (page.content match @@ -157,10 +58,6 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx val resources = siteResourcesPaths.toSeq.map(pathToResource) ++ allResources(allPages) ++ onlyRenderedResources resources.flatMap(renderResource) - def render(): Unit = - val renderedResources = renderResources() - val sites = allPages.map(renderPage(_, Vector.empty)) - def mkHead(page: Page): AppliedTag = val resources = page.content match case t: ResolvedTemplate => @@ -229,14 +126,6 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx renderNested(navigablePage, toplevel = true)._2 - private def canonicalUrl(l: String): AppliedTag | String = - val canon = args.docCanonicalBaseUrl - if !canon.isEmpty then - val canonicalUrl = if canon.endsWith("/") then canon else canon + "/" - link(rel := "canonical", href := canonicalUrl + l) - else - "" // return empty tag - private def hasSocialLinks = !args.socialLinks.isEmpty private def socialLinks(whiteIcon: Boolean = true) = diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Locations.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Locations.scala index 23b5c9d9479a..81baf34b778e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Locations.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Locations.scala @@ -21,7 +21,7 @@ trait Locations(using ctx: DocContext): // We generate this collection only if there may be a conflict with resources. // Potentially can be quite big. - lazy val apiPaths = effectiveMembers.keySet.filterNot(_.isStaticFile).map(absolutePath) + lazy val apiPaths = effectiveMembers.keySet.filterNot(_.isStaticFile).map(absolutePath(_)) var cache = new JHashMap[DRI, Seq[String]]() @@ -80,7 +80,7 @@ trait Locations(using ctx: DocContext): pathToRaw(from, to.split("/").toList) def resolveRoot(dri: DRI, path: String): String = resolveRoot(rawLocation(dri), path) - def absolutePath(dri: DRI): String = rawLocation(dri).mkString("", "/", ".html") + def absolutePath(dri: DRI, extension: String = "html"): String = rawLocation(dri).mkString("", "/", s".$extension") def resolveLink(dri: DRI, url: String): String = if URI(url).isAbsolute then url else resolveRoot(dri, url) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/MarkdownRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/MarkdownRenderer.scala new file mode 100644 index 000000000000..b49c1e268678 --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/MarkdownRenderer.scala @@ -0,0 +1,28 @@ +package dotty.tools.scaladoc +package renderers + +import util.HTML._ +import collection.JavaConverters._ +import java.net.URI +import java.net.URL +import dotty.tools.scaladoc.site._ +import scala.util.Try +import org.jsoup.Jsoup +import java.nio.file.Paths +import java.nio.file.Path +import java.nio.file.Files +import java.nio.file.FileVisitOption +import java.io.File + +class MarkdownRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: DocContext) + extends Renderer(rootPackage, members, extension = "md"): + + override def render(): Unit = + renderResources() + super.render() + + override def pageContent(page: Page, parents: Vector[Link]): AppliedTag = + renderContent(page) + + private def renderResources(): Seq[String] = + allResources(Nil).flatMap(renderResource) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala new file mode 100644 index 000000000000..7664a542c2bb --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala @@ -0,0 +1,149 @@ +package dotty.tools.scaladoc +package renderers + +import util.HTML._ +import collection.JavaConverters._ +import java.net.URI +import java.net.URL +import dotty.tools.scaladoc.site._ +import scala.util.Try +import org.jsoup.Jsoup +import java.nio.file.Paths +import java.nio.file.Path +import java.nio.file.Files +import java.nio.file.FileVisitOption +import java.io.File + +case class Page(link: Link, content: Member | ResolvedTemplate | String, children: Seq[Page]): + def withNewChildren(newChildren: Seq[Page]) = copy(children = children ++ newChildren) + + def withTitle(newTitle: String) = copy(link = link.copy(name = newTitle)) + + def hasFrame = content match + case t: ResolvedTemplate => t.hasFrame + case _ => true + +abstract class Renderer(rootPackage: Member, val members: Map[DRI, Member], protected val extension: String = "html")(using ctx: DocContext) + extends SiteRenderer, Resources, Locations, Writer: + protected val args = summon[DocContext].args + val staticSite = summon[DocContext].staticSiteContext + + val effectiveMembers = members + + protected def memberPage(member: Member): Page = + val childrenPages = member.members.filter(_.needsOwnPage) + Page(Link(member.name, member.dri), member, childrenPages.map(memberPage)) + + val navigablePage: Page = + val rootPckPage = memberPage(rootPackage) + staticSite match + case None => rootPckPage.withTitle(args.name) + case Some(siteContext) => + val (indexes, templates) = siteContext.templates.partition(f => + f.templateFile.isIndexPage() && f.file.toPath.getParent() == siteContext.docsPath) + if (indexes.size > 1) + val msg = s"ERROR: Multiple index pages for doc found ${indexes.map(_.file)}" + report.error(msg) + + val templatePages = templates.map(templateToPage(_, siteContext)) + + indexes.headOption match + case None if templatePages.isEmpty=> + rootPckPage.withTitle(args.name) + case None => + Page(Link(args.name, docsRootDRI),"", templatePages :+ rootPckPage.withTitle("API")) + case Some(indexPage) => + val newChildren = templatePages :+ rootPckPage.withTitle("API") + templateToPage(indexPage, siteContext).withNewChildren(newChildren) + + val hiddenPages: Seq[Page] = + staticSite match + case None => + Seq(navigablePage.copy( // Add index page that is a copy of api/index.html + link = navigablePage.link.copy(dri = docsRootDRI), + children = Nil + )) + case Some(siteContext) => + // In case that we do not have an index page and we do not have any API entries + // we want to create empty index page, so there is one + val actualIndexTemplate = siteContext.indexTemplate() match { + case None if effectiveMembers.isEmpty => Seq(siteContext.emptyIndexTemplate) + case templates => templates.toSeq + } + + (siteContext.orphanedTemplates ++ actualIndexTemplate).map(templateToPage(_, siteContext)) + + /** + * Here we have to retrive index pages from hidden pages and replace fake index pages in navigable page tree. + */ + val allPages: Seq[Page] = + def traversePages(page: Page): (Page, Seq[Page]) = + val (newChildren, newPagesToRemove): (Seq[Page], Seq[Page]) = page.children.map(traversePages(_)).foldLeft((Seq[Page](), Seq[Page]())) { + case ((pAcc, ptrAcc), (p, ptr)) => (pAcc :+ p, ptrAcc ++ ptr) + } + hiddenPages.find(_.link == page.link) match + case None => + (page.copy(children = newChildren), newPagesToRemove) + case Some(newPage) => + (newPage.copy(children = newChildren), newPagesToRemove :+ newPage) + + val (newNavigablePage, pagesToRemove) = traversePages(navigablePage) + + val all = newNavigablePage +: hiddenPages.filterNot(pagesToRemove.contains) + // We need to check for conflicts only if we have top-level member called blog or docs + val hasPotentialConflict = + rootPackage.members.exists(m => m.name.startsWith("docs") || m.name.startsWith("blog")) + + if hasPotentialConflict then + def walk(page: Page): Unit = + if page.link.dri.isStaticFile then + val dest = absolutePath(page.link.dri) + if apiPaths.contains(dest) then + report.error(s"Conflict between static page and API member for $dest. $pathsConflictResoultionMsg") + page.children.foreach(walk) + + all.foreach(walk) + + all + + def renderContent(page: Page) = page.content match + case m: Member => + val signatureRenderer = new SignatureRenderer: + def currentDri: DRI = page.link.dri + def link(dri: DRI): Option[String] = + Some(pathToPage(currentDri, dri)).filter(_ != UnresolvedLocationLink) + + MemberRenderer(signatureRenderer).fullMember(m) + case t: ResolvedTemplate => siteContent(page.link.dri, t) + case a: String => raw(a) + + + + protected def canonicalUrl(l: String): AppliedTag | String = + val canon = args.docCanonicalBaseUrl + if !canon.isEmpty then + val canonicalUrl = if canon.endsWith("/") then canon else canon + "/" + link(rel := "canonical", href := canonicalUrl + l) + else + "" // return empty tag + + /** + * Main method rendering all the pages + */ + def render(): Unit = + val sites = allPages.map(renderPage(_, Vector.empty)) + + /** + * Handler to prepare the content to be rendered. It's a good place to organize frame, footers, front-matter, etc. + */ + def pageContent(page: Page, parents: Vector[Link]): AppliedTag + + /** + * Method to be overriden by concrete renderer to render single page + */ + def renderPage(page: Page, parents: Vector[Link]): Seq[String] = + val newParents = parents :+ page.link + val content = pageContent(page, newParents) + write(page.link.dri, content, extension) +: page.children.flatMap(renderPage(_, newParents)) + + diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala index 7dc40f68c322..3cb97316ad2f 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala @@ -105,7 +105,7 @@ trait Resources(using ctx: DocContext) extends Locations, Writer: "scripts/components/Input.js", "scripts/components/FilterGroup.js", "scripts/components/Filter.js", - "scripts/searchbar.js" + "scripts/scaladoc-scalajs.js" ).map(dottyRes) val urls = List( diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/SiteRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/SiteRenderer.scala index a1dd1e4e71fb..a5a30b41681b 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/SiteRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/SiteRenderer.scala @@ -56,11 +56,24 @@ trait SiteRenderer(using DocContext) extends Locations: else processLocalLink(str) - val document = Jsoup.parse(content.resolved.code) - document.select("a").forEach(element => - element.attr("href", processLocalLinkWithGuard(element.attr("href"))) - ) - document.select("img").forEach { element => - element.attr("src", processLocalLink(element.attr("src"))) - } // foreach does not work here. Why? - raw(document.outerHtml()) + summon[DocContext].args.projectFormat match + case "html" => + val document = Jsoup.parse(content.resolved.code) + document.select("a").forEach(element => + element.attr("href", processLocalLinkWithGuard(element.attr("href"))) + ) + document.select("img").forEach { element => + element.attr("src", processLocalLink(element.attr("src"))) + } // foreach does not work here. Why? + raw(document.outerHtml()) + case "md" => + val links = """(? s"[${m.group(1)}](${processLocalLink(m.group(2))})" + ), + m => s"[${m.group(1)}](${processLocalLinkWithGuard(m.group(2))})" + )) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Writer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Writer.scala index 313cef340d41..029da21bdda7 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Writer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Writer.scala @@ -18,8 +18,8 @@ trait Writer(using ctx: DocContext) extends Locations: if !Files.exists(absPath.getParent) then Files.createDirectories(absPath.getParent) absPath - def write(dri: DRI, content: AppliedTag): String = - val path = absolutePath(dri) + def write(dri: DRI, content: AppliedTag, extension: String = "html"): String = + val path = absolutePath(dri, extension) Files.write(dest(path), content.toString.getBytes) path diff --git a/scaladoc/src/dotty/tools/scaladoc/site/FrontMatterRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/site/FrontMatterRenderer.scala new file mode 100644 index 000000000000..2e02918b5b39 --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/site/FrontMatterRenderer.scala @@ -0,0 +1,24 @@ +package dotty.tools.scaladoc +package site + + +/** + * Object for rendering yaml front-matter for preprocessed markdowns. + */ +object FrontMatterRenderer: + def render(properties: Map[String, Object]): String = + + def renderProperties(newProps: Map[String, Object]): List[String] = newProps.collect { + case (k: String, v: String) => s"$k: $v" + }.toList + + val rows = renderProperties(properties) ++ renderProperties(properties("page").asInstanceOf[Map[String, Object]]) + + rows.mkString("---\n", "\n", "\n---") + "\n\n\n\n" + + + diff --git a/scaladoc/src/dotty/tools/scaladoc/site/LoadedTemplate.scala b/scaladoc/src/dotty/tools/scaladoc/site/LoadedTemplate.scala index f7623d79c7c0..3a7ba6c98d07 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/LoadedTemplate.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/LoadedTemplate.scala @@ -40,15 +40,9 @@ case class LoadedTemplate( def resolveToHtml(ctx: StaticSiteContext): ResolvedPage = val posts = children.map(_.lazyTemplateProperties(ctx)) def getMap(key: String) = templateFile.settings.getOrElse(key, Map.empty).asInstanceOf[Map[String, Object]] - val sourceLinks = if !file.exists() then Nil else - // TODO (https://github.com/lampepfl/scala3doc/issues/240): configure source root - // toRealPath is used to turn symlinks into proper paths - val actualPath = Paths.get("").toAbsolutePath.relativize(file.toPath.toRealPath()) - ctx.sourceLinks.pathTo(actualPath).map("viewSource" -> _ ) ++ - ctx.sourceLinks.pathTo(actualPath, operation = "edit", optionalRevision = Some("master")).map("editSource" -> _ ) val updatedSettings = templateFile.settings ++ ctx.projectWideProperties + - ("site" -> (getMap("site") + ("posts" -> posts))) + ("urls" -> sourceLinks.toMap) + + ("site" -> (getMap("site") + ("posts" -> posts))) + ("page" -> (getMap("page") + ("title" -> templateFile.title.name))) templateFile.resolveInner(RenderingContext(updatedSettings, ctx.layouts))(using ctx) diff --git a/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteContext.scala b/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteContext.scala index 8d09a949c143..ded1a1ff20db 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteContext.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/StaticSiteContext.scala @@ -40,7 +40,7 @@ class StaticSiteContext( lazy val layouts: Map[String, TemplateFile] = val layoutRoot = new File(root, "_layouts") val dirs: Array[File] = Option(layoutRoot.listFiles()).getOrElse(Array()) - dirs.map { it => loadTemplateFile(it) }.map { it => it.name -> it }.toMap + dirs.map { it => loadTemplateFile(it)(using this) }.map { it => it.name -> it }.toMap lazy val sideBarConfig = val sidebarFile = root.toPath.resolve("sidebar.yml") @@ -96,7 +96,7 @@ class StaticSiteContext( val msg = s"ERROR: Multiple index pages for $from found in ${indexes.map(_.file)}" throw new java.lang.RuntimeException(msg) - val templateFile = if (from.isDirectory) loadIndexPage() else loadTemplateFile(from) + val templateFile = if (from.isDirectory) loadIndexPage() else loadTemplateFile(from)(using this) def dateFrom(p: LoadedTemplate, default: String = "1900-01-01"): String = val pageSettings = p.templateFile.settings.get("page").collect{ case m: Map[String @unchecked, _] => m } diff --git a/scaladoc/src/dotty/tools/scaladoc/site/common.scala b/scaladoc/src/dotty/tools/scaladoc/site/common.scala index bb09cd92f452..5873863ed6c0 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/common.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/common.scala @@ -14,13 +14,14 @@ import com.vladsch.flexmark.ext.yaml.front.matter.{AbstractYamlFrontMatterVisito import com.vladsch.flexmark.parser.{Parser, ParserEmulationProfile} import com.vladsch.flexmark.util.options.{DataHolder, MutableDataSet} import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension +import com.vladsch.flexmark.formatter.Formatter import scala.collection.JavaConverters._ val docsRootDRI: DRI = DRI(location = "docs/index", symbolUUID = staticFileSymbolUUID) val apiPageDRI: DRI = DRI(location = "api/index") -val defaultMarkdownOptions: DataHolder = +def defaultMarkdownOptions(using ctx: StaticSiteContext): DataHolder = new MutableDataSet() .setFrom(ParserEmulationProfile.COMMONMARK.getOptions) .set(AnchorLinkExtension.ANCHORLINKS_WRAP_TEXT, false) @@ -36,7 +37,10 @@ val defaultMarkdownOptions: DataHolder = YamlFrontMatterExtension.create(), StrikethroughExtension.create(), WikiLinkExtension.create(), - tasty.comments.markdown.SnippetRenderingExtension + (ctx.args.projectFormat match + case "html" => tasty.comments.markdown.SnippetRenderingExtension + case "md" => tasty.comments.markdown.SnippetFormattingExtension + ), )) def emptyTemplate(file: File, title: String): TemplateFile = TemplateFile( @@ -55,9 +59,9 @@ def emptyTemplate(file: File, title: String): TemplateFile = TemplateFile( final val ConfigSeparator = "---" final val LineSeparator = "\n" -val yamlParser: Parser = Parser.builder(defaultMarkdownOptions).build() +def yamlParser(using ctx: StaticSiteContext): Parser = Parser.builder(defaultMarkdownOptions).build() -def loadTemplateFile(file: File): TemplateFile = { +def loadTemplateFile(file: File)(using ctx: StaticSiteContext): TemplateFile = { val lines = Files.readAllLines(file.toPath).asScala.toList val (config, content) = if (lines.head == ConfigSeparator) { @@ -77,7 +81,7 @@ def loadTemplateFile(file: File): TemplateFile = { val globalKeys = Set("extraJS", "extraCSS", "layout", "hasFrame", "name", "title") val allSettings = yamlCollector.getData.asScala.toMap.transform(getSettingValue) val (global, inner) = allSettings.partition((k,_) => globalKeys.contains(k)) - val settings = Map("page" -> inner) + val settings = Map("page" -> inner) ++ global def stringSetting(settings: Map[String, Object], name: String): Option[String] = settings.get(name).map { case List(elem: String) => elem diff --git a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala index 6d59a87e5f85..8ca2601f9b63 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala @@ -14,7 +14,11 @@ import com.vladsch.flexmark.ext.yaml.front.matter.{AbstractYamlFrontMatterVisito import com.vladsch.flexmark.parser.{Parser, ParserEmulationProfile} import com.vladsch.flexmark.util.options.{DataHolder, MutableDataSet} import com.vladsch.flexmark.html.HtmlRenderer +import com.vladsch.flexmark.formatter.Formatter import liqp.Template +import liqp.TemplateContext +import liqp.tags.Tag +import liqp.nodes.LNode import scala.collection.JavaConverters._ import scala.io.Source @@ -88,7 +92,7 @@ case class TemplateFile( if (ctx.resolving.contains(file.getAbsolutePath)) throw new RuntimeException(s"Cycle in templates involving $file: ${ctx.resolving}") - val layoutTemplate = layout.map(name => + val layoutTemplate = layout.filter(_ => ssctx.args.projectFormat == "html").map(name => ctx.layouts.getOrElse(name, throw new RuntimeException(s"No layouts named $name in ${ctx.layouts}"))) def asJavaElement(o: Object): Object = o match @@ -100,16 +104,39 @@ case class TemplateFile( // Library requires mutable maps.. val mutableProperties = new JHashMap(ctx.properties.transform((_, v) => asJavaElement(v)).asJava) - val rendered = Template.parse(this.rawCode).render(mutableProperties) + + // Register escaping {% link ... %} in markdown + val tag = new Tag("link"): + override def render(context: TemplateContext, nodes: Array[? <: LNode]): Object = + val link = super.asString(nodes(0).render(context)) + s"{% link $link %}" + + val rendered = ssctx.args.projectFormat match + case "html" => Template.parse(this.rawCode).`with`(tag).render(mutableProperties) + case "md" => this.rawCode + + val sourceLinks = if !file.exists() then Nil else + // TODO (https://github.com/lampepfl/scala3doc/issues/240): configure source root + // toRealPath is used to turn symlinks into proper paths + val actualPath = Paths.get("").toAbsolutePath.relativize(file.toPath.toRealPath()) + ssctx.sourceLinks.pathTo(actualPath).map("viewSource" -> _ ) ++ + // List("editSource" -> ssctx.sourceLinks.pathTo(actualPath)) + ssctx.sourceLinks.pathTo(actualPath, operation = "edit", optionalRevision = Some("master")).map("editSource" -> _ ) + // We want to render markdown only if next template is html val code = if (isHtml || layoutTemplate.exists(!_.isHtml)) rendered else // Snippet compiler currently supports markdown only val parser: Parser = Parser.builder(defaultMarkdownOptions).build() val parsedMd = parser.parse(rendered) val processed = FlexmarkSnippetProcessor.processSnippets(parsedMd, None, snippetCheckingFunc, withContext = false)(using ssctx.outerCtx) - HtmlRenderer.builder(defaultMarkdownOptions).build().render(processed) - layoutTemplate match - case None => ResolvedPage(code, resources ++ ctx.resources) - case Some(layoutTemplate) => - layoutTemplate.resolveInner(ctx.nest(code, file, resources)) + ssctx.args.projectFormat match + case "html" => HtmlRenderer.builder(defaultMarkdownOptions).build().render(processed) + case "md" => FrontMatterRenderer.render(settings + ("urls" -> sourceLinks.toMap)) + + Formatter.builder(defaultMarkdownOptions).build().render(processed) + + + if layoutTemplate.isEmpty || ssctx.args.projectFormat == "md" then + ResolvedPage(code, resources ++ ctx.resources) + else + layoutTemplate.get.resolveInner(ctx.nest(code, file, resources)) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetFormattingExtension.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetFormattingExtension.scala new file mode 100644 index 000000000000..7833c0c5d669 --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetFormattingExtension.scala @@ -0,0 +1,40 @@ +package dotty.tools.scaladoc +package tasty.comments.markdown + +import dotty.tools.scaladoc.snippets._ + +import com.vladsch.flexmark.formatter._ +import com.vladsch.flexmark.parser._ +import com.vladsch.flexmark.ext.wikilink._ +import com.vladsch.flexmark.ext.wikilink.internal.WikiLinkLinkRefProcessor +import com.vladsch.flexmark.util.ast._ +import com.vladsch.flexmark.util.options._ +import com.vladsch.flexmark.util.sequence.BasedSequence +import com.vladsch.flexmark._ + +/** + * SnippetFormattingExtension is a clone of the [[SnippetRenderingExtension]] used as a fallback strategy when the `-format` setting is set up to `md` + */ +object SnippetFormattingExtension extends Formatter.FormatterExtension: + + def rendererOptions(opt: MutableDataHolder): Unit = () + + object ExtendedFencedCodeBlockHandler extends CustomNodeFormatter[ExtendedFencedCodeBlock]: + override def render(node: ExtendedFencedCodeBlock, c: NodeFormatterContext, markdown: MarkdownWriter): Unit = + markdown.append( + SnippetRenderer.renderSnippetWithMessages(node) + ) + + object Format extends NodeFormatter: + override def getNodeFormattingHandlers: JSet[NodeFormattingHandler[?]] = + JSet( + new NodeFormattingHandler(classOf[ExtendedFencedCodeBlock], ExtendedFencedCodeBlockHandler), + ) + + def getNodeClasses: JSet[Class[?]] = null + + object Factory extends NodeFormatterFactory: + override def create(options: DataHolder): NodeFormatter = Format + + def extend(formatterBuilder: Formatter.Builder) = + formatterBuilder.nodeFormatterFactory(Factory) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderer.scala index 7a27bddab892..55f3ac31a7bb 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderer.scala @@ -137,4 +137,12 @@ object SnippetRenderer: def renderSnippetWithMessages(snippetName: Option[String], codeLines: Seq[String], messages: Seq[SnippetCompilerMessage], hasContext: Boolean): String = val transformedLines = wrapCodeLines.andThen(addCompileMessages(messages)).apply(codeLines).map(_.toHTML) val codeHTML = s"""${transformedLines.mkString("")}""" - s"""
$codeHTML
${snippetName.fold("")(snippetLabel(_))}
""" \ No newline at end of file + s"""
$codeHTML
${snippetName.fold("")(snippetLabel(_))}
""" + + def renderSnippetWithMessages(node: ExtendedFencedCodeBlock): String = + renderSnippetWithMessages( + node.name, + node.codeBlock.getContentChars.toString.split("\n").map(_ + "\n").toSeq, + node.compilationResult.toSeq.flatMap(_.messages), + node.hasContext + ) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderingExtension.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderingExtension.scala index ae2de8afdef9..7a7edc0f5e86 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderingExtension.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SnippetRenderingExtension.scala @@ -13,17 +13,17 @@ import com.vladsch.flexmark.util.options._ import com.vladsch.flexmark.util.sequence.BasedSequence import com.vladsch.flexmark._ +/** + * SnippetRenderingExtension is responsible for running an analysis for scala codeblocks in the static documentation/scaladoc comments. + * For each codeblock we run compiler to check whether snippet works in the newest scala version and to produce rich html codeblocks with + * compiler warnings/errors for IDE-like live experience. + */ object SnippetRenderingExtension extends HtmlRenderer.HtmlRendererExtension: def rendererOptions(opt: MutableDataHolder): Unit = () object ExtendedFencedCodeBlockHandler extends CustomNodeRenderer[ExtendedFencedCodeBlock]: override def render(node: ExtendedFencedCodeBlock, c: NodeRendererContext, html: HtmlWriter): Unit = html.raw( - SnippetRenderer.renderSnippetWithMessages( - node.name, - node.codeBlock.getContentChars.toString.split("\n").map(_ + "\n").toSeq, - node.compilationResult.toSeq.flatMap(_.messages), - node.hasContext - ) + SnippetRenderer.renderSnippetWithMessages(node) ) object Render extends NodeRenderer: @@ -36,4 +36,4 @@ object SnippetRenderingExtension extends HtmlRenderer.HtmlRendererExtension: override def create(options: DataHolder): NodeRenderer = Render def extend(htmlRendererBuilder: HtmlRenderer.Builder, tpe: String): Unit = - htmlRendererBuilder.nodeRendererFactory(Factory) \ No newline at end of file + htmlRendererBuilder.nodeRendererFactory(Factory)