├── .github
├── CODEOWNERS
├── auto_assign.yml
└── workflows
│ ├── pr.yml
│ └── release.yml
├── .gitignore
├── .scalafmt.conf
├── .sdkmanrc
├── LICENSE
├── README.md
├── app
├── assets
│ ├── css
│ │ └── main.css
│ └── js
│ │ ├── swiper-settings.js
│ │ └── switch-theme.js
├── controllers
│ ├── ContextualController.scala
│ └── HealthController.scala
├── handlers
│ └── ErrorHandler.scala
├── models
│ └── Contributor.scala
├── services
│ └── OpenCollectiveService.scala
├── support
│ └── MongoConnection.scala
├── views
│ ├── contributors.scala.html
│ ├── includes
│ │ ├── advertisement.scala.html
│ │ ├── browserhappy.scala.html
│ │ ├── footer.scala.html
│ │ ├── forkme.scala.html
│ │ ├── header.scala.html
│ │ ├── individual_card.scala.html
│ │ ├── navigation.scala.html
│ │ ├── opencollective.scala.html
│ │ ├── organization_card.scala.html
│ │ ├── scripts.scala.html
│ │ └── statuspage.scala.html
│ ├── index.scala.html
│ ├── install.scala.html
│ ├── jdks.scala.html
│ ├── main.scala.html
│ ├── notfound.scala.html
│ ├── sdks.scala.html
│ ├── usage.scala.html
│ └── vendors.scala.html
└── wrappers
│ ├── OpenCollectiveWebApi.scala
│ └── package.scala
├── build.sbt
├── conf
├── application.conf
├── jdks.conf
├── logback.xml
└── routes
├── libexec
└── sbt-launch.jar
├── project
├── build.properties
├── metals.sbt
└── plugins.sbt
├── public
├── css
│ ├── bootstrap.min.css
│ ├── carbon.css
│ ├── prism-dark.min.css
│ └── prism.min.css
├── img
│ ├── bubble-logo-sdkman-groovy-color.png
│ ├── bubble-logo-sdkman-groovy-color.svg
│ ├── chain-web.png
│ ├── city.png
│ ├── crypton-web.png
│ ├── duke-thumbsup-comic.png
│ ├── favicon.ico
│ ├── icons-comic-colset-red.png
│ ├── icons-comic-colset.png
│ ├── logo-sdkman.png
│ ├── logo.png
│ ├── sdk-man-small-pattern.jpg
│ ├── sdk-man-small-pattern.png
│ ├── sdk-man-small-pattern.svg
│ └── sdkman-web.png
└── js
│ ├── plugins.js
│ └── vendor
│ ├── bootstrap.bundle.min.js
│ └── prism.min.js
└── sbt
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @sdkman/sdkman-website
2 |
--------------------------------------------------------------------------------
/.github/auto_assign.yml:
--------------------------------------------------------------------------------
1 | ---
2 | addReviewers: true
3 | addAssignees: author
4 |
5 | reviewers:
6 | - marc0der
7 | - helpermethod
8 | - eddumelendez
9 |
10 | numberOfReviewers: 0
11 |
--------------------------------------------------------------------------------
/.github/workflows/pr.yml:
--------------------------------------------------------------------------------
1 | name: Pull Requests
2 | on: pull_request_target
3 | jobs:
4 | test:
5 | runs-on: ubuntu-latest
6 | services:
7 | mongodb:
8 | image: mongo:3.2
9 | ports:
10 | - 27017:27017
11 | steps:
12 | - name: Checkout source code
13 | uses: actions/checkout@v2
14 | with:
15 | ref: ${{ github.event.pull_request.head.sha }}
16 | - name: Set up JDK 11.0.11
17 | uses: actions/setup-java@v1
18 | with:
19 | java-version: 11.0.11
20 | - name: Run tests
21 | run: ./sbt test
22 | - uses: kentaro-m/auto-assign-action@v1.1.2
23 | with:
24 | configuration-path: ".github/auto_assign.yml"
25 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches:
5 | - master
6 |
7 | jobs:
8 | build:
9 | name: "Release"
10 | runs-on: ubuntu-latest
11 | environment: production
12 | services:
13 | mongodb:
14 | image: mongo:3.2
15 | ports:
16 | - 27017:27017
17 | steps:
18 | - uses: actions/checkout@v3
19 | with:
20 | fetch-depth: 0
21 | - name: Install doctl
22 | uses: digitalocean/action-doctl@v2
23 | with:
24 | token: ${{ secrets.DIGITALOCEAN_TOKEN }}
25 | - name: Log in to DigitalOcean Docker Registry
26 | run: |
27 | doctl registry login --expiry-seconds=300
28 | - name: Publish local Docker image
29 | run: ./sbt docker:publishLocal
30 | - name: Push image to DO registry
31 | run: |
32 | version=$(git rev-parse --short HEAD)
33 | docker push registry.digitalocean.com/sdkman/sdkman-website:$version
34 | docker push registry.digitalocean.com/sdkman/sdkman-website:latest
35 |
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/sbt,scala,bloop,metals,intellij+all,playframework
3 | # Edit at https://www.gitignore.io/?templates=sbt,scala,bloop,metals,intellij+all,playframework
4 |
5 | ### Bloop ###
6 | .bloop/
7 | .bsp/
8 |
9 | ### Intellij+all ###
10 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
11 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
12 |
13 | # User-specific stuff
14 | .idea/**/workspace.xml
15 | .idea/**/tasks.xml
16 | .idea/**/usage.statistics.xml
17 | .idea/**/dictionaries
18 | .idea/**/shelf
19 |
20 | # Generated files
21 | .idea/**/contentModel.xml
22 |
23 | # Sensitive or high-churn files
24 | .idea/**/dataSources/
25 | .idea/**/dataSources.ids
26 | .idea/**/dataSources.local.xml
27 | .idea/**/sqlDataSources.xml
28 | .idea/**/dynamic.xml
29 | .idea/**/uiDesigner.xml
30 | .idea/**/dbnavigator.xml
31 |
32 | # Gradle
33 | .idea/**/gradle.xml
34 | .idea/**/libraries
35 |
36 | # Gradle and Maven with auto-import
37 | # When using Gradle or Maven with auto-import, you should exclude module files,
38 | # since they will be recreated, and may cause churn. Uncomment if using
39 | # auto-import.
40 | # .idea/modules.xml
41 | # .idea/*.iml
42 | # .idea/modules
43 | # *.iml
44 | # *.ipr
45 |
46 | # CMake
47 | cmake-build-*/
48 |
49 | # Mongo Explorer plugin
50 | .idea/**/mongoSettings.xml
51 |
52 | # File-based project format
53 | *.iws
54 |
55 | # IntelliJ
56 | out/
57 |
58 | # mpeltonen/sbt-idea plugin
59 | .idea_modules/
60 |
61 | # JIRA plugin
62 | atlassian-ide-plugin.xml
63 |
64 | # Cursive Clojure plugin
65 | .idea/replstate.xml
66 |
67 | # Crashlytics plugin (for Android Studio and IntelliJ)
68 | com_crashlytics_export_strings.xml
69 | crashlytics.properties
70 | crashlytics-build.properties
71 | fabric.properties
72 |
73 | # Editor-based Rest Client
74 | .idea/httpRequests
75 |
76 | # Android studio 3.1+ serialized cache file
77 | .idea/caches/build_file_checksums.ser
78 |
79 | ### Intellij+all Patch ###
80 | # Ignores the whole .idea folder and all .iml files
81 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
82 |
83 | .idea/
84 |
85 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
86 |
87 | *.iml
88 | modules.xml
89 | .idea/misc.xml
90 | *.ipr
91 |
92 | # Sonarlint plugin
93 | .idea/sonarlint
94 |
95 | ### Metals ###
96 | .metals/
97 |
98 | ### PlayFramework ###
99 | # Ignore Play! working directory #
100 | bin/
101 | /db
102 | .eclipse
103 | /lib/
104 | /logs/
105 | /modules
106 | /project/project
107 | /project/target
108 | /target
109 | tmp/
110 | test-result
111 | server.pid
112 | *.eml
113 | /dist/
114 | .cache
115 |
116 | ### SBT ###
117 | # Simple Build Tool
118 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
119 |
120 | dist/*
121 | target/
122 | lib_managed/
123 | src_managed/
124 | project/boot/
125 | project/plugins/project/
126 | .history
127 | .lib/
128 |
129 | ### Scala ###
130 | *.class
131 | *.log
132 | *.metals
133 |
134 | ### VSCODE ###
135 | .vscode/
136 |
137 | ### Mac OS ###
138 | .DS_Store
139 |
140 | # End of https://www.gitignore.io/api/sbt,scala,bloop,metals,intellij+all,playframework
141 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = "3.7.10"
2 | runner.dialect = scala213
--------------------------------------------------------------------------------
/.sdkmanrc:
--------------------------------------------------------------------------------
1 | # Enable auto-env through the sdkman_auto_env config
2 | # Add key=value pairs of SDKs to use below
3 | java=11.0.19-tem
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SDKMAN! website
2 |
3 | 
4 |
5 | This is the service backing the SDKMAN! website at https://sdkman.io
6 |
7 | ## Run local
8 |
9 | Make sure you have mongodb running locally or in a Docker Container:
10 |
11 | $ docker run -d --net=host --name mongo mongo:3.2
12 |
13 | Start the app:
14 |
15 | $ ./sbt run
16 |
--------------------------------------------------------------------------------
/app/assets/css/main.css:
--------------------------------------------------------------------------------
1 | :root, [data-bs-theme=light] {
2 | --bs-primary: #0276c6;
3 | --bs-secondary: #343f52;
4 | --bs-secondary-rgb: 70, 86, 111;
5 | --bs-success: #16a34a;
6 | --bs-success-rgb: 22, 163, 74;
7 | --bs-emphasis-color-rgb: 25, 33, 46;
8 |
9 | /* Custom */
10 | --card-bg: #f3f6fc;
11 | --footer-bg: #f3f6fc;
12 | --swiper-btn-bg-rgb: 224, 229, 237;
13 | --swiper-btn-text: #000000;
14 | }
15 |
16 | [data-bs-theme=dark] {
17 | --bs-secondary: #8094b6;
18 | --bs-body-bg: #151f32;
19 | --bs-emphasis-color-rgb: 154, 171, 202;
20 |
21 | /* Custom */
22 | --card-bg: #18273f;
23 | --footer-bg: #0c1421;
24 | --swiper-btn-bg-rgb: 12, 20, 33;
25 | --swiper-btn-text: #ffffff;
26 | }
27 |
28 | .btn-outline-primary {
29 | --bs-btn-color: #0276c6;
30 | --bs-btn-border-color: #0276c6;
31 | --bs-btn-hover-bg: #0276c6;
32 | --bs-btn-hover-border-color: #0276c6;
33 | --bs-btn-active-bg: #0276c6;
34 | --bs-btn-active-border-color: #0276c6;
35 | --bs-btn-disabled-color: #0276c6;
36 | --bs-btn-disabled-border-color: #0276c6;
37 | }
38 |
39 | *, html {
40 | font-family: "Inter", sans-serif;
41 | }
42 |
43 | body {
44 | overflow-x: hidden;
45 | }
46 |
47 | pre {
48 | background-color: var(--card-bg) !important;
49 | border-radius: 8px;
50 | margin: 1rem 0 !important;
51 | }
52 |
53 | .swiper-button-prev, .swiper-button-next {
54 | width: 2.5rem !important;
55 | height: 2.5rem !important;
56 | border-radius: 100%;
57 | display: flex;
58 | align-items: center;
59 | justify-content: center;
60 | background-color: rgba(var(--swiper-btn-bg-rgb), 40%);
61 | color: var(--swiper-btn-text) !important;
62 | padding: .5rem;
63 | }
64 |
65 | .swiper-button-prev:after, .swiper-button-next:after {
66 | content: "" !important;
67 | }
68 |
69 | .swiper-button-prev {
70 | left: -.75rem !important;
71 | }
72 |
73 | .swiper-button-next {
74 | right: -.75rem !important;
75 | }
76 |
77 | .page-wrapper {
78 | padding-top: 80px;
79 | padding-bottom: 80px;
80 | }
81 |
82 | .h-20 {
83 | height: 80px;
84 | }
85 |
86 | .bg-page {
87 | position: absolute;
88 | left: -50vw;
89 | top: -50vw;
90 | width: 100vw;
91 | height: 100vw;
92 | background: radial-gradient(
93 | ellipse at center,
94 | rgba(2, 118, 198, 30%) 0%,
95 | transparent 50%
96 | );
97 | }
98 |
99 | .bg-footer {
100 | background-color: var(--footer-bg);
101 | }
102 |
103 | .navbar {
104 | height: 64px;
105 | backdrop-filter: blur(10px);
106 | -webkit-backdrop-filter: blur(10px);
107 | }
108 |
109 | .nav-link > svg {
110 | height: 18px;
111 | width: 18px;
112 | }
113 |
114 | .nav-sidebar {
115 | max-height: calc(100vh - 160px);
116 | overflow-y: auto;
117 | position: sticky;
118 | top: 144px;
119 | }
120 |
121 | .nav-sidebar > .nav {
122 | color: var(--bs-secondary);
123 | }
124 |
125 | .nav-sidebar .nav-link {
126 | color: var(--bs-secondary);
127 | }
128 |
129 | .nav-sidebar .active {
130 | color: var(--bs-nav-link-color);
131 | font-weight: 500;
132 | border-left: solid 2px var(--bs-nav-link-color);
133 | }
134 |
135 | /* Sections */
136 | .home-section {
137 | padding: 80px 0;
138 | }
139 |
140 | .hero-section-top {
141 | display: flex;
142 | flex-direction: column;
143 | align-items: center;
144 | }
145 |
146 | .hero-section-top-img {
147 | width: 250px;
148 | margin: 80px auto 0;
149 | }
150 |
151 | .hero-section-top-title {
152 | font-size: 48px;
153 | font-weight: 700;
154 | letter-spacing: 1.2;
155 | text-transform: capitalize;
156 | margin: 24px 0 16px 0;
157 | text-align: center;
158 | }
159 |
160 | .hero-section-top-text {
161 | font-size: 18px;
162 | width: 100%;
163 | max-width: 768px;
164 | text-align: center;
165 | color: var(--bs-secondary);
166 | }
167 |
168 | .hero-section-bottom {
169 | display: flex;
170 | flex-direction: column;
171 | align-items: center;
172 | margin: 1rem 0;
173 | }
174 |
175 | .hero-section-bottom-title {
176 | font-size: 24px;
177 | font-weight: 700;
178 | letter-spacing: 1.2;
179 | text-transform: capitalize;
180 | }
181 |
182 | .hero-section-bottom-text {
183 | text-align: center;
184 | color: var(--bs-secondary);
185 | }
186 |
187 | .open-collective-section-title {
188 | font-size: 24px;
189 | font-weight: 700;
190 | letter-spacing: 1.2;
191 | }
192 |
193 | .open-collective-section-subtitle {
194 | font-size: 20px;
195 | font-weight: 500;
196 | letter-spacing: 1.2;
197 | }
198 |
199 | /* Cards */
200 | .card {
201 | height: 100%;
202 | border-radius: 16px;
203 | border: none;
204 | background-color: var(--card-bg);
205 | }
206 |
207 | .card .card-icon {
208 | height: 3.5rem;
209 | width: 3.5rem;
210 | display: flex;
211 | align-items: center;
212 | justify-content: center;
213 | color: var(--bs-primary);
214 | margin-bottom: 1.5rem;
215 | }
216 |
217 | .card .card-icon > svg {
218 | height: inherit;
219 | width: inherit;
220 | }
221 |
222 | .card .card-avatar {
223 | height: 4rem;
224 | width: 4rem;
225 | border-radius: 100%;
226 | overflow: hidden;
227 | margin-bottom: 1.5rem;
228 | }
229 |
230 | .card .card-avatar img {
231 | height: inherit;
232 | width: inherit;
233 | object-fit: cover;
234 | }
235 |
236 | .card .card-title {
237 | font-size: 20px;
238 | margin-bottom: 12px;
239 | }
240 |
241 | .card .card-text {
242 | font-size: 14px;
243 | color: var(--bs-secondary);
244 | }
245 |
246 | .open-collective-card {
247 | text-decoration: none;
248 | }
249 |
250 | .open-collective-card .card-title {
251 | font-size: 16px;
252 | font-weight: 500;
253 | }
254 |
255 | .open-collective-card-date {
256 | color: var(--bs-secondary);
257 | }
258 |
259 | .fs-7 {
260 | font-size: 14px;
261 | line-height: 24px;
262 | }
263 |
264 | .scroll-offset {
265 | scroll-margin: 80px 0;
266 | }
267 |
268 | /* Media queries */
269 | @media (min-width: 576px) {
270 | .swiper-button-prev {
271 | left: -1.25rem !important;
272 | }
273 |
274 | .swiper-button-next {
275 | right: -1.25rem !important;
276 | }
277 | }
278 |
279 | @media (min-width: 992px) {
280 | .hero-section-top-img {
281 | margin: 0 auto;
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/app/assets/js/swiper-settings.js:
--------------------------------------------------------------------------------
1 | new Swiper('#swiper-organization', {
2 | loop: true,
3 | slidesPerView: 1,
4 | spaceBetween: 16,
5 | breakpointsBase: 'container',
6 | breakpoints: {
7 | 696: {
8 | slidesPerView: 2
9 | },
10 | 936: {
11 | slidesPerView: 3
12 | },
13 | 1296: {
14 | slidesPerView: 4
15 | }
16 | },
17 | navigation: {
18 | nextEl: '#swiper-next-organization',
19 | prevEl: '#swiper-prev-organization',
20 | }
21 | });
22 |
23 | new Swiper('#swiper-individual', {
24 | loop: true,
25 | slidesPerView: 1,
26 | spaceBetween: 16,
27 | breakpointsBase: 'container',
28 | breakpoints: {
29 | 516: {
30 | slidesPerView: 2
31 | },
32 | 696: {
33 | slidesPerView: 3
34 | },
35 | 936: {
36 | slidesPerView: 4
37 | },
38 | 1296: {
39 | slidesPerView: 6
40 | }
41 | },
42 | navigation: {
43 | nextEl: '#swiper-next-individual',
44 | prevEl: '#swiper-prev-individual',
45 | }
46 | });
47 |
--------------------------------------------------------------------------------
/app/assets/js/switch-theme.js:
--------------------------------------------------------------------------------
1 | (() => {
2 | 'use strict'
3 |
4 | const THEME_STORAGE_NAME = 'theme';
5 | const getStoredTheme = () => localStorage.getItem(THEME_STORAGE_NAME)
6 | const setStoredTheme = theme => localStorage.setItem(THEME_STORAGE_NAME, theme)
7 |
8 | const getPreferredTheme = () => {
9 | const storedTheme = getStoredTheme()
10 |
11 | if (storedTheme) {
12 | return storedTheme
13 | }
14 |
15 | return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
16 | }
17 |
18 | const setPrismjsTheme = theme => {
19 | const link = document.getElementById('prism-theme')
20 |
21 | if (link) {
22 | const href = `/assets/css/prism${theme === 'dark' ? '-dark' : ''}.min.css`
23 |
24 | link.setAttribute('href', href)
25 | }
26 | }
27 |
28 | const setTheme = theme => {
29 | if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
30 | document.documentElement.setAttribute('data-bs-theme', 'dark')
31 | setPrismjsTheme('dark')
32 | } else {
33 | document.documentElement.setAttribute('data-bs-theme', theme)
34 | setPrismjsTheme(theme)
35 | }
36 | }
37 |
38 | setTheme(getPreferredTheme())
39 |
40 | const showActiveTheme = theme => {
41 | const activeThemeIcon = document.querySelector(`[data-bs-theme-value="${theme}"]`)
42 |
43 | document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
44 | element.classList.add('d-none')
45 | })
46 |
47 | activeThemeIcon.classList.remove('d-none')
48 | }
49 |
50 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
51 | const storedTheme = getStoredTheme()
52 |
53 | if (storedTheme !== 'light' && storedTheme !== 'dark') {
54 | setTheme(getPreferredTheme())
55 | }
56 | })
57 |
58 | window.addEventListener('DOMContentLoaded', () => {
59 | const themeSwitcher = document.querySelector('#bd-theme')
60 |
61 | if (!themeSwitcher) {
62 | return
63 | }
64 |
65 | showActiveTheme(getPreferredTheme())
66 |
67 | themeSwitcher.addEventListener('click', () => {
68 | const theme = getStoredTheme() === 'light' ? 'dark' : 'light'
69 |
70 | setStoredTheme(theme)
71 | setTheme(theme)
72 | showActiveTheme(theme)
73 | })
74 | })
75 | })()
76 |
--------------------------------------------------------------------------------
/app/controllers/ContextualController.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import com.typesafe.config.Config
4 | import io.sdkman.repos.{CandidatesRepo => ICandidatesRepo}
5 | import net.ceedubs.ficus.Ficus._
6 | import net.ceedubs.ficus.readers.ArbitraryTypeReader._
7 | import play.api.mvc._
8 | import support.MongoConnection
9 |
10 | import javax.inject._
11 | import scala.concurrent.ExecutionContext.Implicits.global
12 | import scala.concurrent.Future
13 |
14 | import services.OpenCollectiveService
15 | import models.Contributor
16 |
17 | @Singleton
18 | class ContextualController @Inject() (
19 | cc: ControllerComponents,
20 | applicationRepo: ApplicationRepo,
21 | candidatesRepo: CandidatesRepo,
22 | conf: Config,
23 | openCollectiveService: OpenCollectiveService
24 | ) extends AbstractController(cc) {
25 |
26 | val index = Action.async { implicit request: Request[AnyContent] =>
27 | openCollectiveService.getContributors().map { result =>
28 | val data = result.groupBy(_.`type`)
29 | val organizationContributors = data.getOrElse("ORGANIZATION", Seq[Contributor]())
30 | val individualContributors = data.getOrElse("USER", Seq[Contributor]())
31 |
32 | Ok(views.html.index(organizationContributors, individualContributors))
33 | }
34 | }
35 |
36 | val install = Action.async { implicit request: Request[AnyContent] =>
37 | applicationRepo.findApplication().map { app =>
38 | val scriptCliVersion = app.map(_.stableCliVersion).getOrElse("6.0.0")
39 | val nativeCliVersion = app.map(_.stableNativeCliVersion).getOrElse("1.0.0")
40 | Ok(views.html.install(scriptCliVersion, nativeCliVersion))
41 | }
42 | }
43 |
44 | val usage = Action.async { implicit request: Request[AnyContent] =>
45 | candidatesRepo.findAllCandidates().map { candidates =>
46 | val candidateVersions = candidates
47 | .map(c => Tuple2(c.candidate, c.default.getOrElse("x.y.z")))
48 | .toMap
49 | Ok(views.html.usage(candidateVersions))
50 | }
51 | }
52 |
53 | val vendors = Action { implicit request: Request[AnyContent] =>
54 | Ok(views.html.vendors())
55 | }
56 |
57 | def jdks = Action.async { implicit request: Request[AnyContent] =>
58 | Future.successful(
59 | Ok(
60 | views.html.jdks(
61 | conf.as[Seq[Jdk]]("jdks.vendors").sortBy(_.distribution)
62 | )
63 | )
64 | )
65 | }
66 |
67 | def sdks = Action.async { implicit request: Request[AnyContent] =>
68 | candidatesRepo.findAllCandidates().map { candidates =>
69 | val sanitisedCandidates =
70 | candidates.filter(c => !Seq("java", "test").contains(c.candidate))
71 | Ok(views.html.sdks(sanitisedCandidates))
72 | }
73 | }
74 |
75 | def contributors = Action.async { implicit request: Request[AnyContent] =>
76 | openCollectiveService.getContributors().map { result =>
77 | val data = result.groupBy(_.`type`)
78 | val organizationContributors = data.getOrElse("ORGANIZATION", Seq[Contributor]())
79 | val individualContributors = data.getOrElse("USER", Seq[Contributor]())
80 |
81 | Ok(views.html.contributors(organizationContributors, individualContributors))
82 | }
83 | }
84 | }
85 |
86 | case class Jdk(
87 | id: String,
88 | vendor: String,
89 | distribution: String,
90 | url: String,
91 | description: String
92 | )
93 |
94 | @Singleton
95 | class CandidatesRepo extends ICandidatesRepo with MongoConnection
96 |
--------------------------------------------------------------------------------
/app/controllers/HealthController.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import com.typesafe.scalalogging.LazyLogging
4 | import io.sdkman.repos.{ApplicationRepo => IApplicationRepo}
5 | import javax.inject._
6 | import play.api.libs.json.Json
7 | import play.api.mvc._
8 | import support.MongoConnection
9 |
10 | import scala.concurrent.ExecutionContext.Implicits.global
11 |
12 | @Singleton
13 | class HealthController @Inject() (
14 | cc: ControllerComponents,
15 | applicationRepo: ApplicationRepo
16 | ) extends AbstractController(cc)
17 | with LazyLogging {
18 |
19 | def alive = Action.async { _ =>
20 | applicationRepo
21 | .findApplication()
22 | .map { maybeApp =>
23 | maybeApp.fold(NotFound(statusMessage("KO"))) { app =>
24 | val message = statusMessage(app.alive)
25 | logger.info(s"/alive 200 response: $message")
26 | Ok(message)
27 | }
28 | }
29 | .recover { case e =>
30 | val message = errorMessage(e)
31 | logger.error(s"/alive 503 response $message")
32 | ServiceUnavailable(message)
33 | }
34 | }
35 |
36 | private def statusMessage(s: String) = Json.obj("status" -> s)
37 |
38 | private def errorMessage(e: Throwable) =
39 | Json.obj("status" -> "KO", "error" -> e.getMessage)
40 | }
41 |
42 | class ApplicationRepo extends IApplicationRepo with MongoConnection
43 |
--------------------------------------------------------------------------------
/app/handlers/ErrorHandler.scala:
--------------------------------------------------------------------------------
1 | package handlers
2 |
3 | import javax.inject.Singleton
4 | import play.api.http.HttpErrorHandler
5 | import play.api.mvc.Results._
6 | import play.api.mvc._
7 |
8 | import scala.concurrent._
9 |
10 | @Singleton
11 | class ErrorHandler extends HttpErrorHandler {
12 |
13 | def onClientError(
14 | requestHeader: RequestHeader,
15 | statusCode: Int,
16 | message: String
17 | ) =
18 | statusCode match {
19 | case 404 =>
20 | Future.successful(
21 | NotFound(views.html.notfound(Request(requestHeader, AnyContent())))
22 | )
23 | case _ =>
24 | Future.successful(
25 | Status(statusCode)("A client error occurred: " + message)
26 | )
27 | }
28 |
29 | def onServerError(requestHeader: RequestHeader, exception: Throwable) =
30 | Future.successful(
31 | InternalServerError("A server error occurred: " + exception.getMessage)
32 | )
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/models/Contributor.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import java.util.Date
4 | import play.api.libs.json._
5 | import java.time.LocalDateTime
6 |
7 | case class Contributor(
8 | name: String,
9 | since: LocalDateTime,
10 | totalAmountDonated: Int,
11 | `type`: String,
12 | description: Option[String],
13 | collectiveSlug: Option[String],
14 | image: String
15 | )
16 |
17 | object Contributor {
18 | implicit val format: OFormat[Contributor] = Json.format[Contributor]
19 | }
20 |
--------------------------------------------------------------------------------
/app/services/OpenCollectiveService.scala:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import javax.inject.Inject
4 | import play.api.cache.AsyncCacheApi
5 | import play.api.libs.json.JsValue
6 |
7 | import scala.concurrent.duration.{Duration, HOURS}
8 | import scala.concurrent.{ExecutionContext, Future}
9 |
10 | import wrappers.OpenCollectiveWebApi
11 | import models.Contributor
12 |
13 | class OpenCollectiveService @Inject() (
14 | openCollectiveWebApi: OpenCollectiveWebApi,
15 | cache: AsyncCacheApi,
16 | implicit val ec: ExecutionContext
17 | ) {
18 | val cacheExpiry: Duration = Duration(1, HOURS)
19 |
20 | def getContributors(): Future[Seq[Contributor]] = {
21 | cache.getOrElseUpdate[JsValue]("open-collective-cache", cacheExpiry) {
22 | openCollectiveWebApi.getContributors()
23 | }
24 | .map(_.as[Seq[Contributor]].filter(_.totalAmountDonated > 0))
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/support/MongoConnection.scala:
--------------------------------------------------------------------------------
1 | package support
2 |
3 | import com.typesafe.config.{Config, ConfigFactory}
4 | import io.sdkman.db.{MongoConfiguration, MongoConnectivity}
5 |
6 | trait MongoConnection extends MongoConnectivity with MongoConfiguration {
7 | override lazy val config: Config = ConfigFactory.load()
8 | }
9 |
--------------------------------------------------------------------------------
/app/views/contributors.scala.html:
--------------------------------------------------------------------------------
1 | @(organizationContributors: Seq[Contributor], individualContributors: Seq[Contributor])(implicit request: Request[AnyContent])
2 | @main(title = "Contributors", request) {
3 |
4 |
5 |
6 |
7 |
8 |
Open Collective
9 |
10 |
11 |
12 |
13 |
@organizationContributors.size Organizations
14 |
15 | Contribute to our collective
16 |
17 |
18 |
19 |
20 | @for(organizationContributor <- organizationContributors) {
21 |
22 | @includes.organization_card(organizationContributor)
23 |
24 | }
25 |
26 |
27 |
28 |
29 |
@individualContributors.size People
30 |
31 | Contribute to our collective
32 |
33 |
34 |
35 |
36 | @for(individualContributor <- individualContributors) {
37 |
38 | @includes.individual_card(individualContributor)
39 |
40 | }
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/app/views/includes/advertisement.scala.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/views/includes/browserhappy.scala.html:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/app/views/includes/footer.scala.html:
--------------------------------------------------------------------------------
1 | @import java.time.format.DateTimeFormatter
2 | @import java.time.LocalDate
3 |
17 |
--------------------------------------------------------------------------------
/app/views/includes/forkme.scala.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/views/includes/header.scala.html:
--------------------------------------------------------------------------------
1 | @(title: String, request: Request[AnyContent])
2 |
3 |
4 |
5 |
6 | @title - SDKMAN! the Software Development Kit Manager
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/views/includes/individual_card.scala.html:
--------------------------------------------------------------------------------
1 | @(contributor: Contributor)
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
@contributor.name
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/views/includes/navigation.scala.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
92 |
--------------------------------------------------------------------------------
/app/views/includes/opencollective.scala.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/views/includes/organization_card.scala.html:
--------------------------------------------------------------------------------
1 | @import java.time.format.DateTimeFormatter
2 | @(contributor: Contributor)
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if(contributor.description.nonEmpty) {
12 |
@contributor.description
13 | }
14 |
15 |
16 |
@contributor.name
17 |
18 |
19 | $ @Math.round(contributor.totalAmountDonated / 100)
20 | since @contributor.since.format(DateTimeFormatter.ofPattern("MMM YYYY"))
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/views/includes/scripts.scala.html:
--------------------------------------------------------------------------------
1 | @()
2 |
3 |
4 |
5 |
6 |
7 |
8 | @includes.statuspage()
9 |
18 |
--------------------------------------------------------------------------------
/app/views/includes/statuspage.scala.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/views/index.scala.html:
--------------------------------------------------------------------------------
1 | @(organizationContributors: Seq[Contributor], individualContributors: Seq[Contributor])(implicit request: Request[AnyContent])
2 | @main(title = "Home", request) {
3 |
4 |
5 | @includes.advertisement()
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
The Software Development Kit Manager
14 |
15 |
16 | Meet SDKMAN! – your reliable companion for effortlessly managing multiple Software
17 | Development Kits on Unix systems. Imagine having different versions of SDKs and needing a
18 | stress-free
19 | way to switch between them. SDKMAN! steps in with its easy-to-use Command Line Interface (CLI) and
20 | API.
21 |
22 | Formerly known as GVM, the Groovy enVironment Manager, SDKMAN! draws inspiration from familiar tools
23 | like
24 | apt, pip, RVM, and rbenv and even Git. Think of it as your helpful toolkit friend, ready to
25 | streamline SDK
26 | management for you. 🛠️
27 |
28 |
29 |
30 |
31 |
Get started now!>
32 |
33 |
34 | Go on then, paste and run the following in a terminal:
35 |
36 | curl -s "https://get.sdkman.io" | bash
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
55 |
56 |
By Developers, for Developers
57 |
58 | Simplifying life. No more hunting for downloads, extracting archives, or tinkering with
59 | HOME
and PATH
environment variables.
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
75 |
76 |
Java all the way down
77 |
78 | Install Software Development Kits for the JVM such as Java, Scala,
79 | Kotlin and Groovy.
80 | Ant, Gradle, Grails, Maven, SBT, Spark, Spring Boot, Vert.x and many others
81 | also supported.
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
99 |
100 |
Lightweight
101 |
102 | Written in Rust and bash and only requires curl , zip , and
103 | unzip dependencies to be present on your system. Even works with
104 | ZSH too.
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
120 |
121 |
Multi-platform
122 |
123 | Operates seamlessly across various UNIX-based platforms, including macOS, Linux, and Windows
124 | Subsystem for Linux (WSL) on Windows.
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
140 |
141 |
APIs
142 |
143 | New Clients can easily be written by consuming our open Broker API.
144 | Vendors can publish and announce their own releases through a secure Vendor API.
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
160 |
161 |
Open Source
162 |
163 | Backed by a global community of developers.
164 |
165 | Licensed under Apache 2.0
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
Open Collective
181 |
182 |
183 |
184 |
185 |
@organizationContributors.size Organizations
186 |
187 | Contribute to our collective
188 |
189 |
190 |
191 |
192 |
193 |
194 | @for(organizationContributor <- organizationContributors.slice(0, 8)) {
195 |
196 | @includes.organization_card(organizationContributor)
197 |
198 | }
199 |
200 |
201 |
202 |
203 |
208 |
213 |
214 |
215 |
216 |
217 |
@individualContributors.size People
218 |
219 | Contribute to our collective
220 |
221 |
222 |
223 |
224 |
225 |
226 | @for(individualContributor <- individualContributors.slice(0, 12)) {
227 |
228 | @includes.individual_card(individualContributor)
229 |
230 | }
231 |
232 |
233 |
234 |
235 |
240 |
245 |
246 |
247 |
256 |
257 |
258 |
259 |
263 |
264 | }
265 |
--------------------------------------------------------------------------------
/app/views/install.scala.html:
--------------------------------------------------------------------------------
1 | @(scriptCliVersion: String, nativeCliVersion: String)(implicit request: Request[AnyContent])
2 | @main(title = "Installation", request) {
3 |
4 |
Installation
5 | @includes.advertisement()
6 |
7 |
Installing SDKMAN! on UNIX is a breeze. It effortlessly sets up on macOS, Linux and Windows (with
8 | WSL).
9 | Plus, it's compatible with both Bash and ZSH shells.
10 |
Just launch a new terminal and type in:
11 |
$ curl -s "https://get.sdkman.io" | bash
12 |
Follow the on-screen instructions to wrap up the installation. Afterward, open a new terminal or run
13 | the following in the same shell:
14 |
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
15 |
Lastly, run the following snippet to confirm the installation's success:
16 |
$ sdk version
17 |
You should see output containing the latest script and native versions:
18 |
SDKMAN!
19 | script: @scriptCliVersion
20 | native: @nativeCliVersion
21 |
22 |
Windows installation
23 |
For Windows, there are two installation routes:
24 |
25 | WSL Approach: Install Windows Subsystem for Linux (WSL) before attempting
26 | SDKMAN installation. A basic toolset (bash, zip, unzip, curl) is necessary. Most times, it works
27 | out of the box.
28 | Git Bash Solution: If you use Git Bash for Windows, you'll need to supplement
29 | it with MinGW to have the required toolset for SDKMAN. There are some issues with this approach,
30 | but it works for the most part.
31 |
32 |
Remember, SDKMAN requires a bash environment to run. On Windows, it can't be natively installed;
33 | you need WSL or MSYS+MinGW. We no longer support Cygwin.
34 |
35 |
Beta channel
36 |
Feeling adventurous? We've got a beta channel. New CLI features hit this channel first for trial. You
37 | can join by installing it directly:
38 |
$ curl -s "https://beta.sdkman.io" | bash
39 |
To leave the beta channel, simply set sdkman_beta_channel
to false
in
40 | ~/.sdkman/etc/config
, then run:
41 |
42 |
$ sdk selfupdate force
43 |
44 |
Uninstallation
45 |
Here is how you go about removing SDKMAN! from your system:
46 |
47 | Optionally backup and then remove the installation:
48 | $ tar zcvf ~/sdkman-backup_$(date +%F-%kh%M).tar.gz -C ~/ .sdkman
49 | $ rm -rf ~/.sdkman
50 | Remove initialization snippet from your shell configs.
51 | Edit and remove the initialisation snippet from your
52 | .bashrc
, .bash_profile
and/or .profile
53 | files. If you use ZSH, remove it from the .zshrc
file. The snippet
54 | of code to be removed looks something like this:
55 | #THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
56 | [[ -s "/home/dudette/.sdkman/bin/sdkman-init.sh" ]] && source "/home/dudette/.sdkman/bin/sdkman-init.sh"
57 | Once removed, you have successfully uninstalled SDKMAN! from your machine.
58 |
59 |
60 |
Install to a custom location
61 |
Lastly, if you want to install SDKMAN! in a custom location, like /usr/local/sdkman
,
62 | make sure you have full access rights and that the folder doesn't exist. Export
63 | SDKMAN_DIR
before installing:
64 |
65 |
$ export SDKMAN_DIR="/usr/local/sdkman" && curl -s "https://get.sdkman.io" | bash
66 |
67 |
Install without modifying shell config
68 |
And for installs on CI where shell config modification isn't appropriate, add
69 | rcupdate=false
70 | as a parameter when downloading the installer:
71 |
$ curl -s "https://get.sdkman.io?rcupdate=false" | bash
72 |
73 |
That's all there is to it! Now let's dive into Usage .
74 | }
75 |
--------------------------------------------------------------------------------
/app/views/jdks.scala.html:
--------------------------------------------------------------------------------
1 | @(jdks: Seq[Jdk])(implicit request: Request[AnyContent])
2 | @main(title = "JDK Distributions", request) {
3 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
JDK Distributions
18 | @includes.advertisement()
19 |
20 |
21 | @for(jdk <- jdks) {
22 |
23 |
24 | @jdk.description
25 | $ sdk install java x.y.z-@jdk.id
26 |
27 |
28 | }
29 |
30 |
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/views/main.scala.html:
--------------------------------------------------------------------------------
1 | @(title: String, request: Request[AnyContent])(content: Html)
2 |
3 |
5 |
7 |
9 |
10 |
11 | @includes.header(title, request)
12 |
13 | @includes.scripts()
14 |
15 |
16 |
17 | @includes.browserhappy()
18 | @includes.navigation()
19 |
20 | @content
21 |
22 | @includes.footer()
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/notfound.scala.html:
--------------------------------------------------------------------------------
1 | @(request: Request[AnyContent])
2 | @main(title = "Not Found!", request) {
3 |
4 |
5 |
Oops!
6 |
The page you are looking for does not exist!
7 |
We could not find the page you are looking for. Maybe you are looking for one of these?
8 |
9 | The Home Page .
10 | The Installation Page .
11 | The JDKs Page .
12 | The SDKs Page .
13 | The Usage Page .
14 | The Vendors Page .
15 |
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/views/sdks.scala.html:
--------------------------------------------------------------------------------
1 | @import io.sdkman.model.Candidate
2 | @(candidates: Seq[Candidate])(implicit request: Request[AnyContent])
3 | @main(title = "Available SDKs", request) {
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
SDK Installation Candidates
19 | @includes.advertisement()
20 |
21 | @for(c <- candidates) {
22 |
23 | @c.name (@c.default.getOrElse("Coming soon!"))
24 | @c.websiteUrl
25 | @c.description
26 | $ sdk install @c.candidate
27 |
28 |
29 | }
30 |
31 |
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/views/usage.scala.html:
--------------------------------------------------------------------------------
1 | @(candidates: Map[String, String])(implicit request: Request[AnyContent])
2 | @groovyVersion = @{candidates.getOrElse("groovy", "x.y.z")}
3 | @gradleVersion = @{candidates.getOrElse("gradle", "x.y.z")}
4 | @grailsVersion = @{candidates.getOrElse("grails", "x.y.z")}
5 | @javaVersion = @{candidates.getOrElse("java", "x.y.z")}
6 | @scalaVersion = @{candidates.getOrElse("scala", "x.y.z")}
7 | @springbootVersion = @{candidates.getOrElse("springboot", "x.y.z")}
8 | @main(title = "Usage", request) {
9 |
10 |
11 |
12 |
36 |
37 |
38 |
39 |
Usage
40 | @includes.advertisement()
41 |
42 |
43 |
44 |
45 |
46 | Latest Stable
47 |
48 | Install the latest stable version of your SDK of choice
49 | (say, Java JDK) by running the following command:
50 |
51 | $ sdk install java
52 | You will see something like the following output:
53 | Downloading: java @javaVersion
54 |
55 | In progress...
56 |
57 | ######################################################################## 100.0%
58 |
59 | Installing: java @javaVersion
60 | Done installing!
61 |
62 | Now you will be prompted if you want this version to be set asdefault.
63 | Do you want java @javaVersion to be set as default? (Y/n):
64 |
65 | Answering yes (or hitting enter ) will ensure that all
66 | subsequent shells opened will have this version of the SDK in use by default.
67 |
68 | Setting java @javaVersion as default.
69 |
70 |
71 |
72 |
73 | Need a specific version of an SDK? Simply qualify the
74 | version you require:
75 |
76 | $ sdk install scala @scalaVersion
77 | All subsequent steps same as above.
78 |
79 |
80 |
81 |
82 | Using a snapshot version? Already have a local installation? Setup a local version by specifying
83 | the path to the local installation:
84 |
85 | $ sdk install groovy 3.0.0-SNAPSHOT /path/to/groovy-3.0.0-SNAPSHOT
86 | $ sdk install java 17-zulu /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
87 |
88 | Note that the local version name (3.0.0-SNAPSHOT and
89 | 17-zulu in the examples above) must be a unique name
90 | which is not already in the list of available version names.
91 |
92 |
93 |
94 |
95 |
96 |
97 | Remove an installed version.
98 | $ sdk uninstall scala @scalaVersion
99 | Note that removing a local version will not remove the local installation.
100 |
101 |
102 |
103 |
104 |
105 | To get a listing of available Candidates:
106 | $ sdk list
107 |
108 | This will render a searchable alphabetic list with name, current stable default
109 | version, website URL, description and easy install command for each Candidate.
110 | The output is piped to less
so standard keyboard shortcuts may be
111 | used with q
to exit.
112 |
113 | ================================================================================
114 | Available Candidates
115 | ================================================================================
116 | q-quit /-search down
117 | j-down ?-search up
118 | k-up h-help
119 | --------------------------------------------------------------------------------
120 | ...
121 | --------------------------------------------------------------------------------
122 | Java (@javaVersion) https://projects.eclipse.org/projects/adoptium.temurin/
123 |
124 | Java Platform, Standard Edition (or Java SE) is a widely used platform for
125 | development and deployment of portable code for desktop and server environments.
126 | Java SE uses the object-oriented Java programming language. It is part of the
127 | Java software-platform family. Java SE defines a wide range of general-purpose
128 | APIs – such as Java APIs for the Java Class Library – and also includes the Java
129 | Language Specification and the Java Virtual Machine Specification.
130 |
131 | $ sdk install java
132 | --------------------------------------------------------------------------------
133 | ...
134 |
135 |
136 |
137 |
138 |
139 |
140 | To get a listing of Candidate Versions:
141 | $ sdk list groovy
142 |
143 | This will result in a list view showing the available, local, installed and
144 | current versions of the SDK.
145 |
146 | ================================================================================
147 | Available Groovy Versions
148 | ================================================================================
149 | > * 2.4.4 2.3.1 2.0.8 1.8.3
150 | 2.4.3 2.3.0 2.0.7 1.8.2
151 | 2.4.2 2.2.2 2.0.6 1.8.1
152 | 2.4.1 2.2.1 2.0.5 1.8.0
153 | 2.4.0 2.2.0 2.0.4 1.7.9
154 | 2.3.9 2.1.9 2.0.3 1.7.8
155 | 2.3.8 2.1.8 2.0.2 1.7.7
156 | 2.3.7 2.1.7 2.0.1 1.7.6
157 | 2.3.6 2.1.6 2.0.0 1.7.5
158 | 2.3.5 2.1.5 1.8.9 1.7.4
159 | 2.3.4 2.1.4 1.8.8 1.7.3
160 | 2.3.3 2.1.3 1.8.7 1.7.2
161 | 2.3.2 2.1.2 1.8.6 1.7.11
162 | 2.3.11 2.1.1 1.8.5 1.7.10
163 | 2.3.10 2.1.0 1.8.4 1.7.1
164 |
165 | ================================================================================
166 | + - local version
167 | * - installed
168 | > - currently in use
169 | ================================================================================
170 |
171 |
172 |
173 |
174 |
175 |
176 | Choose to use a given version in the current terminal:
177 | $ sdk use scala @scalaVersion
178 |
179 | It is important to realise that this will switch the candidate version for
180 | the current shell only . To make this change permanent, use the default
command instead.
181 |
182 |
183 |
184 |
185 |
186 |
187 | Chose to make a given version the default:
188 | $ sdk default scala @scalaVersion
189 | This will ensure that all subsequent shells will start with version @scalaVersion in use.
190 |
191 |
192 |
193 |
194 |
195 | To see what is currently in use for a Candidate:
196 | $ sdk current java
197 | Using java version @javaVersion
198 |
199 | To see what is currently in use for all Candidates:
200 | $ sdk current
201 | Using:
202 | groovy: @groovyVersion
203 | java: @javaVersion
204 | scala: @scalaVersion
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | Want to switch to a specific JDK or SDK every time you visit a project?
213 | This can be achieved through an .sdkmanrc
file in the base
214 | directory of your project. This file can be generated automatically by
215 | issuing the following command:
216 |
217 | $ sdk env init
218 | A config file with the following content has now been created in the current directory:
219 | # Enable auto-env through the sdkman_auto_env config
220 | # Add key=value pairs of SDKs to use below
221 | java=@javaVersion
222 |
223 |
224 | The file is pre-populated with the current JDK version in use, but can
225 | contain as many key-value pairs of supported SDKs as needed.
226 | To switch to the configuration present in your .sdkmanrc
file,
227 | simply issue the following command:
228 |
229 | sdk env
230 | You should see output that looks something like this:
231 | Using java version @javaVersion in this shell.
232 |
233 | Your path has now also been updated to use any of these SDKs in your current shell.
234 | When leaving a project, you may want to reset the SDKs to their default version.
235 | This can be achieved by entering:
236 |
237 | $ sdk env clear
238 | Restored java version to @javaVersion (default)
239 |
240 |
241 | After checking out a new project, you may be missing some SDKs specified in the project's
242 | .sdkmanrc
file. To install these missing SDKs, just type:
243 |
244 | $ sdk env install
245 |
246 | Downloading: java @javaVersion
247 |
248 | In progress...
249 |
250 | ######################################################################## 100,0%
251 |
252 | Repackaging Java @javaVersion...
253 |
254 | Done repackaging...
255 |
256 | Installing: java @javaVersion
257 | Done installing!
258 |
259 |
260 | Do you want to switch SDK versions automatically when you cd
into a
261 | directory? This can be done by setting the sdkman_auto_env=true
in
262 | the SDKMAN configuration.
263 | Note that this will also reset any project-specific SDKs to their default version
264 | when leaving the directory.
265 |
266 |
267 |
268 |
269 |
270 |
271 | To see what is currently out of date for a Candidate on your system:
272 | $ sdk upgrade springboot
273 | Upgrade:
274 | springboot (1.2.4.RELEASE, 1.2.3.RELEASE < @springbootVersion)
275 |
276 | To see what is outdated for all Candidates:
277 | $ sdk upgrade
278 | Upgrade:
279 | gradle (2.3, 1.11, 2.4, 2.5 < @gradleVersion)
280 | grails (2.5.1 < @grailsVersion)
281 | springboot (1.2.4.RELEASE, 1.2.3.RELEASE < @springbootVersion
282 |
283 |
284 |
285 |
286 |
287 |
288 | Display the current script and native versions of SDKMAN!:
289 | $ sdk version
290 |
291 | SDKMAN!
292 | script: 5.7.0
293 | native: 0.1.3
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 | Initially called Aeroplane Mode , this allows SDKMAN! to function
302 | when working offline. It has a parameter that can be passed
303 | toenable or disable the offline mode.
304 |
305 | $ sdk offline enable
306 | Forced offline mode enabled.
307 |
308 | $ sdk offline disable
309 | Online mode re-enabled!
310 |
311 |
312 | When operating in offline mode, most commands will still work
313 | even though they will operate in a scaled down capacity. An example is the list
314 | command, which will only display the currently installed and active version(s):
315 |
316 | $ sdk list groovy
317 | ------------------------------------------------------------
318 | Offline Mode: only showing installed groovy versions
319 | ------------------------------------------------------------
320 | > 2.4.4
321 | * 2.4.3
322 | ------------------------------------------------------------
323 | * - installed
324 | > - currently in use
325 | ------------------------------------------------------------
326 |
327 | The offline mode will also be disabled/enabled automatically when the internet
328 | becomes available/unavailable. Naturally, commands that require internet
329 | connectivity will not function but give a warning.
330 |
331 |
332 |
333 |
334 |
335 | Installs a new version of SDKMAN! if available.
336 | $ sdk selfupdate
337 |
338 | If no new version is available an appropriate message will be displayed.
339 | Re-installation may be forced by passing the force parameter to the command:
340 |
341 | $ sdk selfupdate force
342 |
343 | Automatic daily checks for new versions of SDKMAN! will also be performed on the
344 | behalf of the user.
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 | Periodically SDKMAN! requires a refresh to become aware of new (or removed)
353 | candidates.
354 | When candidate metadata has potentially grown stale, a warning is displayed
355 | with instruction
356 | on how to update. By simply running the following command, the candidate
357 | cache will be refreshed and new candidates will become available for
358 | installation:
359 |
360 | WARNING: SDKMAN is out-of-date and requires an update.
361 |
362 | $ sdk update
363 | Adding new candidates(s): kotlin
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 | It should rarely be necessary to flush SDKMAN!'s local state.
372 | The flush command helps with this, so you don't need to delete any directories.
373 |
374 |
375 | Manually deleting directories like the .sdkman/tmp
directory will
376 | break SDKMAN! Always usethe flush
command instead!
377 |
378 |
379 | $ sdk flush
380 |
381 |
382 |
383 |
384 |
385 |
386 | When using SDKMAN in scripts, it is often useful to get the absolute
387 | path of where an SDK resides (similar to how the java_home
388 | command works on macOS). For this we have the home
command.
389 |
390 | $ sdk home java @javaVersion
391 | /home/myuser/.sdkman/candidates/java/@javaVersion
392 |
393 |
394 |
395 |
396 |
397 |
398 | You can get basic help by running the following command:
399 | $ sdk help
400 |
401 | This should render a useful top-level help page. You can add qualifier to this command to get help
402 | about a specific sub-command.
403 |
404 | $ sdk help install
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 | Configuration can be found in the ~/.sdkman/etc/config
file. To edit the
413 | configuration, the sdk config
command may be issued to edit this file
414 | in the system editor. The following configurations are available:
415 |
416 | # make sdkman non-interactive, preferred for CI environments
417 | sdkman_auto_answer=true|false
418 |
419 | # check for newer versions and prompt for update
420 | sdkman_selfupdate_feature=true|false
421 |
422 | # disables SSL certificate verification
423 | # https://github.com/sdkman/sdkman-cli/issues/327
424 | # HERE BE DRAGONS....
425 | sdkman_insecure_ssl=true|false
426 |
427 | # configure curl timeouts
428 | sdkman_curl_connect_timeout=5
429 | sdkman_curl_continue=true
430 | sdkman_curl_max_time=10
431 |
432 | # subscribe to the beta channel
433 | sdkman_beta_channel=true|false
434 |
435 | # enable verbose debugging
436 | sdkman_debug_mode=true|false
437 |
438 | # enable colour mode
439 | sdkman_colour_enable=true|false
440 |
441 | # enable automatic env
442 | sdkman_auto_env=true|false
443 |
444 | # enable bash or zsh auto-completion
445 | sdkman_auto_complete=true|false
446 |
447 |
448 |
449 |
450 |
451 | }
--------------------------------------------------------------------------------
/app/views/vendors.scala.html:
--------------------------------------------------------------------------------
1 | @()(implicit request: Request[AnyContent])
2 | @main(title = "Vendors", request) {
3 |
4 |
5 |
6 |
16 |
17 |
18 |
19 |
Vendors
20 | @includes.advertisement()
21 |
22 |
23 | SDKMAN! is unique in that it empowers SDK Vendors to publish their candidate releases on our
24 | platform. We provide a secure API that can be used to manage all aspects of a release on SDKMAN!.
25 | Such aspects include Releasing a new version, setting an existing version as
26 | Default (Stable) and Announcing the release on the SDKMAN! CLI
27 | broadcast and Twitter feed.
28 |
29 |
30 |
31 |
32 |
33 | The API is a simple JSON REST API that allows three basic operations:
34 |
35 | Release a new candidate version
36 | Set the default for a candidate
37 | Broadcast a release message
38 |
39 |
40 |
41 |
42 |
43 |
44 | This is a secured API, and requires appropriate credentials to perform the
45 | above operations. Access will be granted on a
46 | case-by-case basis to Vendors who are interested in making their SDK
47 | available on SDKMAN!. If you want to publish your releases on SDKMAN!, please follow the Vendor Onboarding
48 | wiki page
49 | and then contact us for help with setting up your credentials.
50 |
51 |
52 |
53 |
54 |
55 | The simplest way to call the API is by using curl . Of course,
56 | any other client can be used to perform the API operations.
57 |
58 | Release a new Candidate Version
59 | This will perform a minor release on SDKMAN!. It will
60 | simply add the new candidate version, but will not make it the default version
61 | for that candidate. This endpoint supports POST
and DELETE
HTTP methods.
62 | The POST
endpoint is idempotent.
63 | curl -X POST \
64 | -H "Consumer-Key: CONSUMER_KEY" \
65 | -H "Consumer-Token: CONSUMER_TOKEN" \
66 | -H "Content-Type: application/json" \
67 | -H "Accept: application/json" \
68 | -d '{"candidate": "groovy", "version": "2.4.2", "url": "https://groovy.jfrog.io/artifactory/dist-release-local/groovy-zips/apache-groovy-binary-2.4.6.zip"}' \
69 | https://vendors.sdkman.io/release
70 |
71 | Multi-platform binary distributions
72 | We support both universal and multi-platform binary distributions. Universal binaries run on all
73 | platforms, so you need to publish only a single SDK archive to our API. Multi-platform APIs are
74 | compiled specifically for the target platform and require an archive per target platform to be
75 | published. We currently support the following platforms:
76 |
77 | LINUX_64
78 | LINUX_ARM64
79 | LINUX_32
80 | LINUX_ARM32SF
81 | LINUX_ARM32HF
82 | MAC_OSX
83 | MAC_ARM64
84 | WINDOWS_64
85 |
86 |
87 | To indicate the target platform, a platform
key with associated platform
88 | should be included in the payload. If no platform
is included, we assume the
89 | value to be UNIVERSAL
.
90 |
91 | Multi-vendor candidates
92 | For vendors who wish to publish to a multi-vendor candidate like Java or JMC,
93 | we require the presence of a vendor string in the JSON payload.
94 | This will result in a new version comprised of $version-$vendor
,
95 | so in this case it would appear as 11.0.10-zulu
on SDKMAN!.
96 |
97 | Checksums
98 | An optional map of checksums
may be provided in the payload for each published binary.
99 | Supported checksum algorithms are:
100 |
101 | MD5
102 | SHA-1
103 | SHA-224
104 | SHA-256
105 | SHA-384
106 | SHA-512
107 |
108 |
109 | Sample payload
110 | An example payload demonstrating the release of a multi-platform Java binary
111 | for LINUX_64
published by Azul as zulu
with two checksums
112 | will look something like this:
113 | {
114 | "candidate": "java",
115 | "version": "11.0.10",
116 | "vendor": "zulu",
117 | "url": "https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-linux_x64.tar.gz",
118 | "platform": "LINUX_64",
119 | "checksums": {
120 | "MD5": "93c9d427af64f2da8c00c9219360815b",
121 | "SHA-256": "0bd85593bae021314378f3b146cfe36a6c9b0afd964d897c34201034ace3e785"
122 | }
123 | }
124 |
125 |
Set existing Version as Default for Candidate
126 | When calling this endpoint for an existing candidate version, it will make it the default version
127 | for that candidate. This makes a minor release a major release!
128 | curl -X PUT \
129 | -H "Consumer-Key: CONSUMER_KEY" \
130 | -H "Consumer-Token: CONSUMER_TOKEN" \
131 | -H "Content-Type: application/json" \
132 | -H "Accept: application/json" \
133 | -d '{"candidate": "groovy", "version": "2.3.8"}' \
134 | https://vendors.sdkman.io/default
135 |
136 |
Broadcast a Structured Message This will result in a structured
137 | message announcement on social media and SDKMAN! CLI. The result will look
138 | something like: grails 3.0.0 available for download. https://git.io/release
.
139 | The url can point to the github release page or the version's changelog.
140 | This message will be announced to the broadcast channel of SDKMAN! CLI, as well
141 | as on the @@sdkman_ Twitter feed.
142 | curl -X POST \
143 | -H "Consumer-Key: CONSUMER_KEY" \
144 | -H "Consumer-Token: CONSUMER_TOKEN" \
145 | -H "Content-Type: application/json" \
146 | -H "Accept: application/json" \
147 | -d '{"candidate": "grails", "version": "3.0.0", "url": "https://git.io/release"}' \
148 | https://vendors.sdkman.io/announce/struct
149 |
150 |
151 |
152 |
153 |
154 | If fiddling with cURL (or HttpClient) isn’t your thing, you could consider
155 | using our Gradle plugin. The plugin allows the release to be done as a side
156 | effect of your CI build! It exposes several useful tasks like:
157 |
158 | sdkReleaseVersion
159 | sdkDefaultVersion
160 | sdkAnnounceVersion
161 |
162 | It also exposes some convenience tasks that roll the above into single tasks:
163 |
164 | sdkMajorRelease
: performs release, default and structured
165 | announce
166 |
167 | sdkMinorRelease
: performs release and structured announce,
168 | no default
169 |
170 |
171 | For more details of about this plugin, as well as how to configure it, please
172 | refer to the Github
173 | Page for the project.
174 |
175 |
176 |
177 |
178 |
179 | If fiddling with cURL (or HttpClient) or Gradle isn’t your thing, you could consider
180 | using our Maven plugin. The plugin allows the release to be done as a side
181 | effect of your CI build! It exposes several useful goals like:
182 |
183 | release
184 | default
185 | announce
186 |
187 | It also exposes some convenience goals that roll the above into single goals:
188 |
189 | major-release
: performs release, default and structured
190 | announce
191 |
192 | minor-release
: performs release and structured announce,
193 | no default
194 |
195 |
196 | For more details of about this plugin, as well as how to configure it, please
197 | refer to the Github
198 | Page for the project.
199 |
200 |
201 |
202 |
203 | }
204 |
--------------------------------------------------------------------------------
/app/wrappers/OpenCollectiveWebApi.scala:
--------------------------------------------------------------------------------
1 | package wrappers
2 |
3 | import javax.inject.Inject
4 | import com.typesafe.config.Config
5 | import play.api.http.Status._
6 | import play.api.libs.ws.WSClient
7 | import play.api.libs.json.{Json, JsValue}
8 |
9 | import scala.concurrent.{ExecutionContext, Future}
10 |
11 | class OpenCollectiveWebApi @Inject() (
12 | ws: WSClient,
13 | conf: Config,
14 | implicit val ec: ExecutionContext
15 | ) {
16 | val url = conf.getString("openCollective.url")
17 |
18 | val query = Json.obj(
19 | "query" -> """
20 | query Collective {
21 | collective(slug: "sdkman") {
22 | contributors(limit: 200, offset: 0) {
23 | totalCount
24 | nodes {
25 | name
26 | since
27 | totalAmountDonated
28 | type
29 | description
30 | collectiveSlug
31 | image
32 | }
33 | }
34 | }
35 | }
36 | """
37 | )
38 |
39 | def getContributors(): Future[JsValue] = {
40 | ws
41 | .url(url)
42 | .addHttpHeaders("Accept" -> "application/json")
43 | .post(query)
44 | .map { response =>
45 | if (response.status == OK) {
46 | (response.json \ "data" \ "collective" \ "contributors" \ "nodes").as[JsValue]
47 | } else {
48 | throw ApiError(response.status, Some(response.statusText))
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/wrappers/package.scala:
--------------------------------------------------------------------------------
1 | package object wrappers {
2 | case class ApiError(
3 | status: Int,
4 | statusText: Option[String] = None,
5 | data: Option[Any] = None
6 | ) extends Exception(statusText.orNull)
7 | }
8 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | enablePlugins(JavaServerAppPackaging)
2 | enablePlugins(DockerPlugin)
3 | enablePlugins(GitVersioning)
4 |
5 | name := """sdkman-website"""
6 |
7 | organization := "io.sdkman"
8 |
9 | git.formattedShaVersion := git.gitHeadCommit.value.map(_.take(7))
10 |
11 | Docker / packageName := "registry.digitalocean.com/sdkman/sdkman-website"
12 |
13 | dockerUpdateLatest := true
14 |
15 | dockerBaseImage := "openjdk:11"
16 |
17 | dockerExposedPorts ++= Seq(9000)
18 |
19 | Universal / javaOptions ++= Seq(
20 | "-Dpidfile.path=/dev/null"
21 | )
22 |
23 | lazy val root = (project in file(".")).enablePlugins(PlayScala)
24 |
25 | scalaVersion := "2.12.13"
26 |
27 | resolvers ++= Seq(
28 | Resolver.mavenCentral,
29 | "jitpack" at "https://jitpack.io"
30 | )
31 |
32 | libraryDependencies ++= Seq(
33 | ws,
34 | guice,
35 | caffeine,
36 | "com.github.sdkman" % "sdkman-mongodb-persistence" % "2.4",
37 | "com.typesafe.scala-logging" %% "scala-logging" % "3.9.3",
38 | "com.iheart" %% "ficus" % "1.5.0"
39 | )
40 |
41 |
--------------------------------------------------------------------------------
/conf/application.conf:
--------------------------------------------------------------------------------
1 | play.http.secret.key = "66c19d060036a87266e76678bd798af4896fe53c55baf611afde542f59a658d1"
2 |
3 | mongo {
4 | url {
5 | host = "localhost"
6 | host = ${?MONGO_HOST}
7 |
8 | port = 27017
9 | port = ${?MONGO_PORT}
10 | }
11 |
12 | database = "sdkman"
13 | database = ${?MONGO_DATABASE}
14 |
15 | username = ""
16 | username = ${?MONGO_USERNAME}
17 |
18 | password = ""
19 | password = ${?MONGO_PASSWORD}
20 | }
21 |
22 | openCollective {
23 | url = "https://api.opencollective.com/graphql/v2"
24 | url = ${?OPEN_COLLECTIVE_URL}
25 | }
26 |
27 | play.http.errorHandler = handlers.ErrorHandler
28 |
29 | play.filters.hosts {
30 | allowed = [
31 | "sdkman.io",
32 | "site.sdkman.io",
33 | "www.sdkman.io",
34 | "sdkman-website-rxljo.ondigitalocean.app",
35 | "localhost"
36 | ]
37 | }
38 |
39 | include "jdks.conf"
40 |
--------------------------------------------------------------------------------
/conf/jdks.conf:
--------------------------------------------------------------------------------
1 | jdks {
2 | vendors: [
3 | {
4 | id = "amzn"
5 | vendor = "Amazon"
6 | distribution = "Corretto"
7 | url = "https://aws.amazon.com/corretto/"
8 | description = """
9 | Amazon Corretto is a no-cost, multiplatform, production-ready distribution
10 | of the Open Java Development Kit (OpenJDK). Corretto comes with long-term
11 | support that will include performance enhancements and security fixes.
12 | Amazon runs Corretto internally on thousands of production services and
13 | Corretto is certified as compatible with the Java SE standard. With
14 | Corretto, you can develop and run Java applications on popular operating
15 | systems, including Linux, Windows, and macOS.
16 | """
17 | },
18 | {
19 | id = "albba",
20 | vendor = "Alibaba",
21 | distribution = "Dragonwell",
22 | url = "http://dragonwell-jdk.io",
23 | description = """
24 | Dragonwell, as a downstream version of OpenJDK, is the in-house
25 | OpenJDK implementation at Alibaba. It is optimized for online e-commerce,
26 | financial and logistics applications running on 100,000+ servers. Alibaba
27 | Dragonwell is the engine that runs these distributed Java applications in
28 | extreme scaling.
29 | """
30 | },
31 | {
32 | id = "bsg"
33 | vendor = "Huawei",
34 | distribution = "Bisheng",
35 | url = "https://bishengjdk.openeuler.org/"
36 | description = """
37 | BiSheng JDK, an open-source adaptation of Huawei JDK derived from
38 | OpenJDK, is utilized across 500+ Huawei products, benefitting from
39 | the R&D team's extensive experience in addressing service-related
40 | challenges. As a downstream product of OpenJDK, it serves as a
41 | high-performance distribution for production environments,
42 | specifically addressing performance and stability issues in Huawei
43 | applications. BiSheng JDK excels in optimizing ARM architecture
44 | performance and stability, delivering enhanced results in big data
45 | scenarios. Its primary goal is to offer Java developers a stable,
46 | high-performance JDK, particularly excelling on the ARM architecture.
47 | """
48 | },
49 | {
50 | id = "graal"
51 | vendor = "Oracle"
52 | distribution = "GraalVM"
53 | url = "https://www.graalvm.org/"
54 | description = """
55 | Oracle GraalVM is the free GraalVM distribution from Oracle, based on
56 | Oracle JDK, and includes the high-performance Graal JIT compiler.
57 | GraalVM can compile Java applications ahead of time into standalone
58 | binaries that start instantly, scale fast, and use fewer compute
59 | resources. Oracle GraalVM Native Image provides advanced features
60 | including G1 GC, SBOM, as well as performance and size optimizations.
61 | It also makes it possible to embed Python, JavaScript, Ruby, and other
62 | languages into Java applications.
63 | """
64 | },
65 | {
66 | id = "graalce"
67 | vendor = "GraalVM Community"
68 | distribution = "GraalVM"
69 | url = "https://www.graalvm.org/"
70 | description = """
71 | GraalVM CE is the open source distribution of GraalVM, based on OpenJDK,
72 | and includes the high-performance Graal JIT compiler. GraalVM can
73 | compile Java applications ahead of time into standalone binaries that
74 | start instantly, scale fast, and use fewer compute resources. It also
75 | makes it possible to embed Python, JavaScript, Ruby, and other languages
76 | into Java applications.
77 | """
78 | },
79 | {
80 | id = "kona"
81 | vendor = "Tencent"
82 | distribution = "Kona"
83 | url = "https://tencent.github.io/konajdk/"
84 | description = """
85 | Tencent Kona is a free, multi-platform, and production-ready distribution
86 | of OpenJDK, featuring Long-Term Support (LTS) releases. It serves as the
87 | default JDK within Tencent for cloud computing, big data, and numerous
88 | other Java applications.
89 | """
90 | },
91 | {
92 | id = "oracle"
93 | vendor = "Oracle"
94 | distribution = "Java SE Development Kit"
95 | url = "https://www.oracle.com/java/"
96 | description = """
97 | This proprietary Java Development Kit is an implementation of the Java Platform,
98 | Standard Edition released by Oracle Corporation in the form of a binary
99 | product aimed at Java developers on Linux, macOS or Windows. The JDK
100 | includes a private JVM and a few other resources to finish the development
101 | of a Java application. It is distributed under the Oracle No-Fee Terms and
102 | Conditions License
103 | """
104 | },
105 | {
106 | id = "librca"
107 | vendor = "Bellsoft"
108 | distribution = "Liberica"
109 | url = "https://bell-sw.com/"
110 | description = """
111 | Liberica is a 100% open-source Java implementation. It is built from
112 | OpenJDK which BellSoft contributes to, is thoroughly tested and passed the
113 | JCK provided under the license from OpenJDK. All supported versions of
114 | Liberica also contain JavaFX.
115 | """
116 | },
117 | {
118 | id = "nik"
119 | vendor = "Bellsoft"
120 | distribution = "Liberica NIK"
121 | url = "https://bell-sw.com/pages/liberica-native-image-kit"
122 | description = """
123 | Liberica Native Image Kit is a utility that converts your JVM-based application
124 | into a fully compiled native executable ahead-of-time under the closed-world
125 | assumption with an almost instant startup time. Being compatible with various
126 | platforms, including lightweight musl-based Alpine Linux, it optimizes resource
127 | consumption and minimizes the static footprint.
128 | """
129 | },
130 | {
131 | id = "mandrel"
132 | vendor = "Red Hat"
133 | distribution = "Mandrel"
134 | url = "https://github.com/graalvm/mandrel"
135 | description = """
136 | Mandrel focuses on GraalVM's native-image component in order to provide
137 | an easy way for Quarkus users to generate native images for their
138 | applications. Developers using Quarkus should be able to go all the way
139 | from Java source code to lean, native, platform-dependent applications
140 | running on Linux. This capability is vital for deploying to containers
141 | in a cloud-native application development model.
142 | """
143 | },
144 | {
145 | id = "open"
146 | vendor = "jdk.java.net"
147 | distribution = "OpenJDK"
148 | url = "https://jdk.java.net/"
149 | description = """
150 | OpenJDK (Open Java Development Kit) is a free and open-source
151 | implementation of the Java Platform, Standard Edition (Java SE). It is the
152 | result of an effort Sun Microsystems began in 2006. The implementation is
153 | licensed under the GNU General Public License (GNU GPL) version 2 with a
154 | linking exception. Were it not for the GPL linking exception, components
155 | that linked to the Java class library would be subject to the terms of the
156 | GPL license. OpenJDK is the official reference implementation of Java SE
157 | since version 7.
158 | """
159 | },
160 | {
161 | id = "ms"
162 | vendor = "Microsoft"
163 | distribution = "OpenJDK"
164 | url = "https://www.microsoft.com/openjdk"
165 | description = """
166 | The Microsoft Build of OpenJDK is a no-cost distribution of OpenJDK that's
167 | open source and available for free for anyone to deploy anywhere. It
168 | includes Long-Term Support (LTS) binaries for Java 11 on x64 server and
169 | desktop environments on macOS, Linux, and Windows, and AArch64/ARM64 on
170 | Linux and Windows. Microsoft also publishes Java 16 binaries for all three
171 | major Operating Systems and both x64 and AArch64 (M1/ARM64) architectures.
172 | """
173 | },
174 | {
175 | id = "sapmchn"
176 | vendor = "SAP"
177 | distribution = "SapMachine"
178 | url = "https://sap.github.io/SapMachine/"
179 | description = """
180 | SapMachine is a downstream version of the OpenJDK
181 | project. It is used to build and maintain a SAP supported version of
182 | OpenJDK for SAP customers and partners who wish to use OpenJDK to run their
183 | applications. SAP is committed to ensuring the continued success of the
184 | Java platform.
185 | """
186 | },
187 | {
188 | id = "sem",
189 | vendor = "IBM",
190 | distribution = "Semeru",
191 | url = "https://developer.ibm.com/languages/java/semeru-runtimes/",
192 | description = """
193 | Semeru Runtimes use the class libraries from OpenJDK, along with
194 | the Eclipse OpenJ9 Java Virtual Machine to enable developers to build
195 | and deploy Java applications that will start quickly, deliver great
196 | performance, all while using less memory.
197 | """
198 | },
199 | {
200 | id = "tem",
201 | vendor = "Eclipse",
202 | distribution = "Temurin",
203 | url = "https://projects.eclipse.org/projects/adoptium.temurin",
204 | description = """
205 | Formerly AdoptOpenJDK, the Eclipse Adoptium Temurin™ project provides
206 | code and processes that support the building of runtime binaries and
207 | associated technologies that are high performance, enterprise-caliber,
208 | cross-platform, open-source licensed, and Java SE TCK-tested for general
209 | use across the Java ecosystem.
210 | """
211 | },
212 | {
213 | id = "trava",
214 | vendor = "Trava",
215 | distribution = "Trava",
216 | url = "https://github.com/TravaOpenJDK/trava-jdk-11-dcevm",
217 | description = """
218 | TravaOpenJDK is OpenJDK for developers. It is based on dcevm
219 | and uses an integrated HotswapAgent, so allowing advanced hotswapping of
220 | classes by method and field addition or updates at runtime.
221 | """
222 | },
223 | {
224 | id = "zulu"
225 | vendor = "Azul Systems"
226 | distribution = "Zulu"
227 | url = "https://www.azul.com/downloads/zulu/"
228 | description = """
229 | Azul Zulu Builds of OpenJDK are no-cost, production-ready open-source, TCK-tested,
230 | and certified OpenJDK distributions. They are available for a wide range of hardware
231 | platforms and operating systems and are compatible with special requirements, such
232 | as stripped-down JREs and builds, including OpenJFX and Coordinated Restore at
233 | Checkpoint (CRaC). They are supported as part of Azul Platform Core, which provides
234 | stabilized security updates for rapid, assured deployment into production and
235 | solution-oriented engineering assistance.
236 | """
237 | },
238 | ]
239 | }
240 |
--------------------------------------------------------------------------------
/conf/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/conf/routes:
--------------------------------------------------------------------------------
1 | # Routes
2 | # This file defines all application routes (Higher priority routes first)
3 | # https://www.playframework.com/documentation/latest/ScalaRouting
4 | # ~~~~
5 |
6 | # An example controller showing a sample home page
7 | GET /alive controllers.HealthController.alive
8 | GET / controllers.ContextualController.index
9 | GET /install controllers.ContextualController.install
10 | GET /usage controllers.ContextualController.usage
11 | GET /vendors controllers.ContextualController.vendors
12 | GET /sdks controllers.ContextualController.sdks
13 | GET /jdks controllers.ContextualController.jdks
14 | GET /contributors controllers.ContextualController.contributors
15 |
16 | # Map static resources from the /public folder to the /assets URL path
17 | GET /assets/*file controllers.Assets.at(path="/public", file: String)
18 |
--------------------------------------------------------------------------------
/libexec/sbt-launch.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/libexec/sbt-launch.jar
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.4.9
2 |
--------------------------------------------------------------------------------
/project/metals.sbt:
--------------------------------------------------------------------------------
1 | // format: off
2 | // DO NOT EDIT! This file is auto-generated.
3 |
4 | // This file enables sbt-bloop to create bloop config files.
5 |
6 | addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.17")
7 |
8 | // format: on
9 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.8")
2 | addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
3 | addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.1")
4 | addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.1")
5 |
--------------------------------------------------------------------------------
/public/css/carbon.css:
--------------------------------------------------------------------------------
1 | #carbonads {
2 | display: block;
3 | overflow: hidden;
4 | padding: 1em;
5 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
6 | max-width: 400px;
7 | }
8 |
9 | #carbonads a {
10 | text-decoration: none;
11 | }
12 |
13 | #carbonads span {
14 | position: relative;
15 | display: block;
16 | overflow: hidden;
17 | }
18 |
19 | .carbon-img {
20 | float: right;
21 | margin-left: 1em;
22 | }
23 |
24 | .carbon-img img {
25 | display: block;
26 | }
27 |
28 | .carbon-text {
29 | display: block;
30 | line-height: 1.4;
31 | max-width: calc(100% - 130px - 1em);
32 | text-align: right;
33 | font-size: 14px;
34 | }
35 |
36 | .carbon-poweredby {
37 | position: absolute;
38 | right: calc(130px + 1rem);
39 | bottom: 0;
40 | display: block;
41 | font-size: 10px;
42 | text-transform: uppercase;
43 | line-height: 1;
44 | letter-spacing: 1px;
45 | }
46 |
47 | .carbon-band {
48 | display: flex;
49 | justify-content: flex-end;
50 | }
--------------------------------------------------------------------------------
/public/css/prism-dark.min.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.29.0
2 | https://prismjs.com/download.html#themes=prism-okaidia&languages=bash+json */
3 | code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
4 |
--------------------------------------------------------------------------------
/public/css/prism.min.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.29.0
2 | https://prismjs.com/download.html#themes=prism&languages=bash+json */
3 | code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
4 |
--------------------------------------------------------------------------------
/public/img/bubble-logo-sdkman-groovy-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/bubble-logo-sdkman-groovy-color.png
--------------------------------------------------------------------------------
/public/img/bubble-logo-sdkman-groovy-color.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
31 |
32 |
39 |
43 |
45 |
47 |
49 |
52 |
55 |
56 |
57 |
67 |
69 |
72 |
74 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/public/img/chain-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/chain-web.png
--------------------------------------------------------------------------------
/public/img/city.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/city.png
--------------------------------------------------------------------------------
/public/img/crypton-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/crypton-web.png
--------------------------------------------------------------------------------
/public/img/duke-thumbsup-comic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/duke-thumbsup-comic.png
--------------------------------------------------------------------------------
/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/favicon.ico
--------------------------------------------------------------------------------
/public/img/icons-comic-colset-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/icons-comic-colset-red.png
--------------------------------------------------------------------------------
/public/img/icons-comic-colset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/icons-comic-colset.png
--------------------------------------------------------------------------------
/public/img/logo-sdkman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/logo-sdkman.png
--------------------------------------------------------------------------------
/public/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/logo.png
--------------------------------------------------------------------------------
/public/img/sdk-man-small-pattern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/sdk-man-small-pattern.jpg
--------------------------------------------------------------------------------
/public/img/sdk-man-small-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/sdk-man-small-pattern.png
--------------------------------------------------------------------------------
/public/img/sdk-man-small-pattern.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
32 |
33 |
40 |
44 |
46 |
48 |
50 |
53 |
56 |
57 |
60 |
61 |
71 |
73 |
75 |
77 |
80 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/public/img/sdkman-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdkman/sdkman-website-playframework/062523cd309629c59d3826e458ce87d2e7be132b/public/img/sdkman-web.png
--------------------------------------------------------------------------------
/public/js/plugins.js:
--------------------------------------------------------------------------------
1 | (function(){var e;var d=function(){};var b=["assert","clear","count","debug","dir","dirxml","error","exception","group","groupCollapsed","groupEnd","info","log","markTimeline","profile","profileEnd","table","time","timeEnd","timeStamp","trace","warn"];var c=b.length;var a=(window.console=window.console||{});while(c--){e=b[c];if(!a[e]){a[e]=d}}}());
--------------------------------------------------------------------------------
/public/js/vendor/prism.min.js:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.29.0
2 | https://prismjs.com/download.html#themes=prism&languages=bash+json */
3 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(j
g.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
4 | !function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i