) {
33 | val contact = Contact(1, "mary@gmail.com")
34 | println(contact.id)
35 | }
36 | ```
37 |
38 | Turns into:
39 |
40 |
41 |
42 | ```kotlin
43 | class Contact(val id: Int, var email: String)
44 |
45 | fun main(args: Array) {
46 | val contact = Contact(1, "mary@gmail.com")
47 | println(contact.id)
48 | }
49 | ```
50 |
51 |
52 |
53 | You can also change the playground theme or disable run button using `theme` and `data-highlight-only` attributes.
54 |
55 | ```html
56 |
57 | ```
58 |
59 |
60 | ```kotlin
61 | fun main(args: Array) {
62 | println("Hello World!")
63 | }
64 | ```
65 |
66 |
67 |
68 | Or theme `kotlin-dark`
69 |
70 |
71 |
72 | ```kotlin
73 | fun main(args: Array) {
74 | println("Hello World!")
75 | }
76 | ```
77 |
78 |
79 |
80 | Set another target platform with attribute `data-target-platform`.
81 |
82 | ```html
83 |
84 | ```
85 |
86 |
87 | ```kotlin
88 | fun sum(a: Int, b: Int): Int {
89 | return a + b
90 | }
91 |
92 | fun main(args: Array) {
93 | print(sum(-1, 8))
94 | }
95 | ```
96 |
97 |
98 |
99 | You can use JS IR compiler also.
100 |
101 | ```html
102 |
103 | ```
104 |
105 |
106 | ```kotlin
107 | fun mul(a: Int, b: Int): Int {
108 | return a * b
109 | }
110 |
111 | fun main(args: Array) {
112 | print(mul(-2, 4))
113 | }
114 | ```
115 |
116 |
117 |
118 | You can use Wasm compiler.
119 |
120 | ```html
121 |
122 | ```
123 |
124 |
125 | ```kotlin
126 | fun mul(a: Int, b: Int): Int {
127 | return a * b
128 | }
129 |
130 | fun main(args: Array) {
131 | print(mul(-2, 4))
132 | println(" + 7 =")
133 | print(mul(-2, 4) + 7)
134 | }
135 | ```
136 |
137 |
138 |
139 | You can use Compose Wasm.
140 |
141 | ```html
142 |
143 | ```
144 |
145 |
146 | ```kotlin
147 | import androidx.compose.ui.ExperimentalComposeUiApi
148 | import androidx.compose.ui.window.CanvasBasedWindow
149 | import androidx.compose.animation.AnimatedVisibility
150 | import androidx.compose.foundation.Image
151 | import androidx.compose.foundation.layout.Column
152 | import androidx.compose.foundation.layout.fillMaxWidth
153 | import androidx.compose.material.Button
154 | import androidx.compose.material.MaterialTheme
155 | import androidx.compose.material.Text
156 | import androidx.compose.runtime.Composable
157 | import androidx.compose.runtime.getValue
158 | import androidx.compose.runtime.mutableStateOf
159 | import androidx.compose.runtime.remember
160 | import androidx.compose.runtime.setValue
161 | import androidx.compose.ui.Alignment
162 | import androidx.compose.ui.Modifier
163 |
164 | //sampleStart
165 | @OptIn(ExperimentalComposeUiApi::class)
166 | fun main() {
167 | CanvasBasedWindow { App() }
168 | }
169 |
170 | @Composable
171 | fun App() {
172 | MaterialTheme {
173 | var greetingText by remember { mutableStateOf("Hello World!") }
174 | var showImage by remember { mutableStateOf(false) }
175 | var counter by remember { mutableStateOf(0) }
176 | Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
177 | Button(onClick = {
178 | counter++
179 | greetingText = "Compose: ${Greeting().greet()}"
180 | showImage = !showImage
181 | }) {
182 | Text(greetingText)
183 | }
184 | AnimatedVisibility(showImage) {
185 | Text(counter.toString())
186 | }
187 | }
188 | }
189 | }
190 |
191 | private val platform = object : Platform {
192 |
193 | override val name: String
194 | get() = "Web with Kotlin/Wasm"
195 | }
196 |
197 | fun getPlatform(): Platform = platform
198 |
199 | class Greeting {
200 | private val platform = getPlatform()
201 |
202 | fun greet(): String {
203 | return "Hello, ${platform.name}!"
204 | }
205 | }
206 |
207 | interface Platform {
208 | val name: String
209 | }
210 | //sampleEnd
211 |
212 | ```
213 |
214 |
215 |
216 |
217 | You can try Kotlin export to Swift.
218 |
219 | ```html
220 |
221 | ```
222 |
223 |
224 | ```kotlin
225 | fun mul(a: Int, b: Int): Int {
226 | return a * b
227 | }
228 |
229 | fun main(args: Array) {
230 | print(mul(-2, 4))
231 | println(" + 7 =")
232 | print(mul(-2, 4) + 7)
233 | }
234 | ```
235 |
236 |
237 |
238 |
239 |
240 | ```kotlin
241 | fun mul(a: Int, b: Int): Int {
242 | return a * b
243 | }
244 |
245 | fun main(args: Array) {
246 | print(mul(-2, 4))
247 | println(" + 7 =")
248 | print(mul(-2, 4) + 7)
249 | }
250 | ```
251 |
252 |
253 |
254 | Use `data-target-platform` attribute with value `junit` for creating examples with tests:
255 |
256 |
257 |
258 | ```kotlin
259 | import org.junit.Test
260 | import org.junit.Assert
261 |
262 | class TestExtensionFunctions() {
263 | @Test fun testIntExtension() {
264 | Assert.assertEquals("Rational number creation error: ", RationalNumber(4, 1), 4.r())
265 | }
266 |
267 | @Test fun testPairExtension() {
268 | Assert.assertEquals("Rational number creation error: ", RationalNumber(2, 3), Pair(2, 3).r())
269 | }
270 | }
271 | //sampleStart
272 | /*
273 | Then implement extension functions Int.r() and Pair.r() and make them convert Int and Pair to RationalNumber.
274 | */
275 | fun Int.r(): RationalNumber = RationalNumber(this, 2)
276 | fun Pair.r(): RationalNumber = RationalNumber(first, second)
277 |
278 | data class RationalNumber(val numerator: Int, val denominator: Int)
279 | //sampleEnd
280 | ```
281 |
282 |
283 | The test clases in this code snippet are folded away thanks to the `//sampleStart` and `//sampleEnd` comments in the code.
284 | If you want to hide test classes completely just set the attribute `folded-button` to `false` value.
285 |
286 | Also you can mark arbitrary code by putting it between `[mark]your code[/mark]`.
287 |
288 | ```html
289 |
290 | ```
291 |
292 |
293 |
294 | ```kotlin
295 | import org.junit.Test
296 | import org.junit.Assert
297 |
298 | class TestLambdas() {
299 | @Test fun contains() {
300 | Assert.assertTrue("The result should be true if the collection contains an even number",
301 | containsEven(listOf(1, 2, 3, 126, 555)))
302 | }
303 |
304 | @Test fun notContains() {
305 | Assert.assertFalse("The result should be false if the collection doesn't contain an even number",
306 | containsEven(listOf(43, 33)))
307 | }
308 | }
309 | //sampleStart
310 | /*
311 | Pass a lambda to any function to check if the collection contains an even number.
312 | The function any gets a predicate as an argument and returns true if there is at least one element satisfying the predicate.
313 | */
314 | fun containsEven(collection: Collection): Boolean = collection.any {[mark]TODO()[/mark]}
315 | //sampleEnd
316 | ```
317 |
318 |
319 |
320 | Use `data-target-platform` attribute with value `canvas` for working with canvas in Kotlin:
321 |
322 | ```html
323 |
324 | ```
325 |
326 |
327 |
328 | ```kotlin
329 | package fancylines
330 |
331 | import org.w3c.dom.CanvasRenderingContext2D
332 | import org.w3c.dom.HTMLCanvasElement
333 | import kotlinx.browser.document
334 | import kotlinx.browser.window
335 | import kotlin.random.Random
336 |
337 |
338 |
339 | val canvas = initalizeCanvas()
340 | fun initalizeCanvas(): HTMLCanvasElement {
341 | val canvas = document.createElement("canvas") as HTMLCanvasElement
342 | val context = canvas.getContext("2d") as CanvasRenderingContext2D
343 | context.canvas.width = window.innerWidth.toInt();
344 | context.canvas.height = window.innerHeight.toInt();
345 | document.body!!.appendChild(canvas)
346 | return canvas
347 | }
348 |
349 | class FancyLines() {
350 | val context = canvas.getContext("2d") as CanvasRenderingContext2D
351 | val height = canvas.height
352 | val width = canvas.width
353 | var x = width * Random.nextDouble()
354 | var y = height * Random.nextDouble()
355 | var hue = 0;
356 |
357 | fun line() {
358 | context.save();
359 |
360 | context.beginPath();
361 |
362 | context.lineWidth = 20.0 * Random.nextDouble();
363 | context.moveTo(x, y);
364 |
365 | x = width * Random.nextDouble();
366 | y = height * Random.nextDouble();
367 |
368 | context.bezierCurveTo(width * Random.nextDouble(), height * Random.nextDouble(),
369 | width * Random.nextDouble(), height * Random.nextDouble(), x, y);
370 |
371 | hue += (Random.nextDouble() * 10).toInt();
372 |
373 | context.strokeStyle = "hsl($hue, 50%, 50%)";
374 |
375 | context.shadowColor = "white";
376 | context.shadowBlur = 10.0;
377 |
378 | context.stroke();
379 |
380 | context.restore();
381 | }
382 |
383 | fun blank() {
384 | context.fillStyle = "rgba(255,255,1,0.1)";
385 | context.fillRect(0.0, 0.0, width.toDouble(), height.toDouble());
386 | }
387 |
388 | fun run() {
389 | window.setInterval({ line() }, 40);
390 | window.setInterval({ blank() }, 100);
391 | }
392 | }
393 | //sampleStart
394 | fun main(args: Array) {
395 | FancyLines().run()
396 | }
397 | //sampleEnd
398 | ```
399 |
400 |
401 |
402 | Use `data-js-libs` with a comma-separated list of URLs to specify additional javascript libraries to load.
403 |
404 | ```html
405 |
406 | ```
407 |
408 |
409 |
410 | ```kotlin
411 | external fun moment(): dynamic
412 |
413 | fun main() {
414 | val startOfDay = moment().startOf("day").fromNow()
415 | println("The start of the day was $startOfDay")
416 | }
417 | ```
418 |
419 |
420 |
421 |
422 |
423 |
424 | ```kotlin
425 | external fun moment(): dynamic
426 |
427 | fun main() {
428 | val startOfDay = moment().startOf("day").fromNow()
429 | println("The start of the day was $startOfDay")
430 | }
431 | ```
432 |
433 |
434 |
435 | ## Manual initialization
436 |
437 | If you want to init Kotlin Playground manually - omit `data-selector` attribute and call it when it's needed:
438 |
439 | ```html
440 |
441 |
446 | ```
447 | Add additional hidden files:
448 | Put your files between `