Skip to content

Commit 452ece7

Browse files
committed
chore: update code blocks KTL-1707
1 parent d095249 commit 452ece7

35 files changed

+631
-694
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,90 @@
11
package org.jetbrains.dokka.uitest.markdown
22

33
/**
4+
* Contains examples of Markdown code showcasing Kotlin syntax highlighting.
45
*
5-
* Contains examples of Markdown code.
6-
*
7-
* Here's a code block:
6+
* Here's a code block with various Kotlin features to test syntax highlighting:
87
*
98
* ```
10-
* class MyUIClass {
11-
* val scope = MainScope() // the scope of MyUIClass, uses Dispatchers.Main
9+
* // Single-line comment token
10+
* /* Multi-line comment token */
11+
* /** Documentation comment token */
12+
*
13+
* // Package declaration to test namespace token
14+
* package com.example.highlighting
15+
*
16+
* // Imports to test namespace tokens
17+
* import kotlin.random.Random
18+
* import kotlin.collections.List
19+
*
20+
* // Type alias to test symbol token
21+
* typealias Handler<T> = (T) -> Unit
22+
* typealias AsyncOperation = suspend () -> Unit
23+
*
24+
* // Sealed interface to test class-name and keyword tokens
25+
* sealed interface State {
26+
* object Loading : State
27+
* data class Success(val data: String) : State
28+
* data class Error(val message: String) : State
29+
* }
30+
*
31+
* // Class with various token types
32+
* class SyntaxDemo {
33+
* // Properties to test property and symbol tokens
34+
* private val number: Int = 42 // number token
35+
* protected var text: String = "Hello" // string token
36+
* internal const val PI = 3.14159 // number token
1237
*
13-
* fun destroy() { // destroys an instance of MyUIClass
14-
* scope.cancel() // cancels all coroutines launched in this scope
15-
* // ... do the rest of cleanup here ...
16-
* }
38+
* protected var url: String = "https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/min.html"
1739
*
18-
* /*
19-
* * Note: if this instance is destroyed or any of the launched coroutines
20-
* * in this method throws an exception, then all nested coroutines are cancelled.
21-
* */
22-
* fun showSomeData() = scope.launch { // launched in the main thread
23-
* // ... here we can use suspending functions or coroutine builders with other dispatchers
24-
* draw(data) // draw in the main thread
40+
* var pattern = Regex("""\b\d{3}-\d{3}-\d{4}\b""")
41+
*
42+
* // Companion with property tokens
43+
* companion object {
44+
* const val DEBUG = true // boolean token
45+
* const val CHAR_SAMPLE = 'A' // char token
46+
* @JvmField val EMPTY = "" // string token
47+
* }
48+
*
49+
* // Function to test various tokens
50+
* fun calculate(x: Double): Double {
51+
* val multiplier = 2.5 // number token
52+
* val enabled: Boolean = false // boolean token
53+
*
54+
* // Operators test
55+
* val result = when {
56+
* x <= 0 -> x * multiplier
57+
* x >= 100 -> x / multiplier
58+
* else -> x + multiplier
59+
* }
60+
*
61+
* // Built-in types and functions test
62+
* val numbers: List<Int> = listOf(1, 2, 3)
63+
* val filtered = numbers
64+
* .filter { it > 0 } // lambda and operator tokens
65+
* .map { it.toString() } // function token
66+
* .joinToString(separator = ", ")
67+
*
68+
* // String template and escape sequence tokens
69+
* println("Result: $result\nFiltered: $filtered")
70+
*
71+
* return result
72+
* }
73+
*
74+
* // Extension function with operator and symbol tokens
75+
* infix fun Int.power(exponent: Int): Int {
76+
* require(exponent >= 0) { "Exponent must be non-negative" }
77+
* return when (exponent) {
78+
* 0 -> 1
79+
* 1 -> this
80+
* else -> this * (this power (exponent - 1))
81+
* }
2582
* }
2683
* }
2784
* ```
2885
*
29-
* Here's inline code: `this` and `that` and `fun foo()` and `class Omg : MyInterface`
86+
* Here's inline code with various token types:
87+
* `val x: Int = 0`, `fun interface EventHandler`, `object : Runnable`,
88+
* `class Sample<T : Any>`, `@Deprecated fun old()`, `var name: String?`
3089
*/
3190
class MarkdownCode {}

dokka-subprojects/core/src/main/kotlin/org/jetbrains/dokka/pages/ContentNodes.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ public enum class TokenStyle : Style {
393393
public enum class TextStyle : Style {
394394
Bold, Italic, Strong, Strikethrough, Paragraph,
395395
Block, Span, Monospace, Indented, Cover, UnderCoverText, BreakableAfter, Breakable, InlineComment, Quotation,
396-
FloatingRight, Var, Underlined
396+
SourceLink, Var, Underlined
397397
}
398398

399399
public enum class ContentStyle : Style {

dokka-subprojects/plugin-base-frontend/package-lock.json

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dokka-subprojects/plugin-base-frontend/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
"dependencies": {
3636
"@babel/core": "^7.16.0",
3737
"@babel/preset-env": "^7.24.5",
38+
"@fontsource/inter": "^5.1.1",
39+
"@fontsource/jetbrains-mono": "^5.1.2",
3840
"@jetbrains/babel-preset-jetbrains": "^2.3.1",
3941
"@jetbrains/logos": "1.4.27",
4042
"@jetbrains/ring-ui": "^5.1.28",

dokka-subprojects/plugin-base-frontend/src/main/ui-kit/_tokens/colors.scss

+6-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
--color-background-page-dt: rgb(38, 38, 40);
1313
--color-background-footer: rgb(235, 235, 235);
1414
--color-background-footer-dt: rgb(50, 50, 55);
15-
--color-background-code: rgba(230, 230, 230, 1); //#E6E6E6
1615

1716
// Text colors (headings, paragraphs, labels)
1817
--color-text: rgb(0, 0, 0);
@@ -36,21 +35,16 @@
3635
--color-b70: rgba(0, 0, 0, 0.7);
3736

3837
// Code area colors
39-
--color-cd-punctuation: rgb(153, 153, 153); // #999999;
40-
--color-cd-keyword: rgb(0, 51, 179); // #0033B3;
41-
--color-cd-keyword-alternative: rgba(204, 120, 50); // #CC7832;
42-
--color-cd-builtin: rgb(6, 125, 23); // #067D17;
43-
--color-cd-builtin-alternative: rgb(231, 191, 106); // #E8BF6A;
44-
--color-cd-function: rgb(0, 98, 122); // #00627A;
45-
--color-cd-function-alternative: rgb(255, 198, 109); // #FFC66D;
46-
--color-cd-operator: rgb(154, 110, 58); // #9A6E3A;
47-
--color-cd-operator-alternative: rgb(169, 183, 198); // #A9B7C6;
48-
--color-cd-body: rgb(0, 0, 0); // #000000;
49-
--color-cd-body-alternative: rgb(169, 183, 198); // #A9B7C6;
38+
--color-background-inline-code: var(--color-b08);
39+
--color-background-code-block: rgba(25, 25, 28, 0.05);
5040

5141
// Targets and source sets
5242
--color-generic: rgb(83, 157, 243);
5343
--color-jvm: rgb(77, 187, 95);
5444
--color-js: rgb(255, 199, 0);
5545
--color-wasm: rgb(255, 255, 255);
46+
47+
// Copy icon colors
48+
--copy-icon-color: var(--color-b50);
49+
--copy-icon-hover-color: var(--color-b70);
5650
}

dokka-subprojects/plugin-base-frontend/src/main/ui-kit/_tokens/typography.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
:root {
6-
--font-family-default: JetBrains Sans, Inter, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
6+
--font-family-default: Inter, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
77
Ubuntu, Cantarell, Droid Sans, Helvetica Neue, Arial, sans-serif;
88
--font-family-mono: JetBrains Mono, SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;
99
--font-h1: 600 44px/44px var(--font-family-default);
@@ -12,5 +12,5 @@
1212
--font-h4: 600 16px/24px var(--font-family-default);
1313
--font-text-m: 400 16px/24px var(--font-family-default);
1414
--font-text-s: 400 14px/20px var(--font-family-default);
15-
--font-code: 400 16px/24px var(--font-family-mono);
15+
--font-code: 400 15.5px/24px var(--font-family-mono);
1616
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2014-2025 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
import './styles.scss';
5+
6+
// helps with some corner cases where <wbr> starts working already,
7+
// but the signature is not yet long enough to be wrapped
8+
9+
const CODE_BLOCK_PADDING = 16 * 2;
10+
11+
const symbolsObserver = new ResizeObserver((entries) => entries.forEach(wrapSymbolParameters));
12+
13+
function initHandlers() {
14+
document.querySelectorAll('div.symbol').forEach((symbol) => symbolsObserver.observe(symbol));
15+
}
16+
17+
if (document.readyState === 'loading') {
18+
window.addEventListener('DOMContentLoaded', initHandlers);
19+
} else {
20+
initHandlers();
21+
}
22+
23+
function createNbspIndent() {
24+
const indent = document.createElement('span');
25+
indent.append(document.createTextNode('\u00A0\u00A0\u00A0\u00A0'));
26+
indent.classList.add('nbsp-indent');
27+
return indent;
28+
}
29+
30+
function wrapSymbolParameters(entry: ResizeObserverEntry) {
31+
const symbol = entry.target;
32+
const symbolBlockWidth = entry.borderBoxSize && entry.borderBoxSize[0] && entry.borderBoxSize[0].inlineSize;
33+
const sourceButtonWidth = symbol.querySelector('[data-element-type="source-link"]')?.getBoundingClientRect().width || 0;
34+
35+
// Even though the script is marked as `defer` and we wait for `DOMContentLoaded` event,
36+
// or if this block is a part of hidden tab, it can happen that `symbolBlockWidth` is 0,
37+
// indicating that something hasn't been loaded.
38+
// In this case, observer will be triggered onсe again when it will be ready.
39+
if (symbolBlockWidth > 0) {
40+
const node = symbol.querySelector('.parameters');
41+
42+
if (node) {
43+
// if window resize happened and observer was triggered, reset previously wrapped
44+
// parameters as they might not need wrapping anymore, and check again
45+
node.classList.remove('wrapped');
46+
node.querySelectorAll('.parameter .nbsp-indent').forEach((indent) => indent.remove());
47+
48+
const innerTextWidth = Array.from(symbol.children)
49+
.filter((it) => !it.classList.contains('block')) // blocks are usually on their own (like annotations), so ignore it
50+
.map((it) => it.getBoundingClientRect().width)
51+
.reduce((a, b) => a + b, 0);
52+
53+
// if signature text takes up more than a single line, wrap params for readability
54+
if (innerTextWidth > symbolBlockWidth - CODE_BLOCK_PADDING - sourceButtonWidth) {
55+
node.classList.add('wrapped');
56+
node.querySelectorAll('.parameter').forEach((param) => {
57+
// has to be a physical indent so that it can be copied. styles like
58+
// paddings and `::before { content: " " }` do not work for that
59+
param.prepend(createNbspIndent());
60+
});
61+
}
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*!
2+
* Copyright 2014-2025 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
@import '../_tokens/index';
5+
6+
/**
7+
http://localhost:8001/jvm/org.jetbrains.dokka.uitest.markdown/-markdown-code/index.html
8+
*/
9+
.symbol:not(.token, .wrapped), code.block {
10+
display: block;
11+
box-sizing: border-box;
12+
position: relative;
13+
padding: 12px 16px;
14+
border-radius: var(--size-s1);
15+
background-color: var(--color-background-code-block);
16+
font: var(--font-code);
17+
white-space: pre-wrap;
18+
overflow: scroll;
19+
}
20+
21+
code.block {
22+
overflow-x: auto;
23+
max-width: 100%;
24+
}
25+
26+
.source-link-wrapper::after {
27+
display: block;
28+
content: '';
29+
clear: both;
30+
height: 0;
31+
}
32+
33+
@media screen and (width <= 759px) {
34+
.source-link-wrapper {
35+
margin-top: 8px;
36+
display: block;
37+
}
38+
}
39+
40+
.source-link {
41+
float: right;
42+
}
43+
44+
/**
45+
http://localhost:8001/jvm/org.jetbrains.dokka.uitest.types/-simple-deprecated-kotlin-class/index.html
46+
*/
47+
48+
.sample-container, div.CodeMirror {
49+
position: relative;
50+
display: flex;
51+
flex-direction: column;
52+
}
53+
54+
.sample-container span.copy-icon {
55+
display: none;
56+
57+
&::before {
58+
width: 24px;
59+
height: 24px;
60+
display: inline-block;
61+
content: '';
62+
/* masks are required if you want to change color of the icon dynamically instead of using those provided with the SVG */
63+
mask: url("../_assets/copy-icon.svg") no-repeat 50% 50%;
64+
-webkit-mask-size: cover;
65+
mask-size: cover;
66+
background-color: var(--copy-icon-color);
67+
}
68+
69+
&:hover::before {
70+
background-color: var(--copy-icon-hover-color);
71+
}
72+
}
73+
74+
.js .sample-container:hover span.copy-icon {
75+
display: inline-block;
76+
}

dokka-subprojects/plugin-base-frontend/src/main/ui-kit/global.scss

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
--color-background: var(--color-background-page-dt);
1616
--text-color: var(--color-text-dt);
1717
--text-outline: var(--color-w16);
18+
--color-background-inline-code: var(--color-w10);
19+
--color-background-code-block: var(--color-w05);
1820
}
1921

2022
body {

dokka-subprojects/plugin-base-frontend/src/main/ui-kit/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ import * as tocTree from './toc-tree/index';
1919
import * as link from './link/index';
2020
import * as breadcrumbs from './breadcrumbs/index';
2121
import * as inlineCode from './inline-code/index';
22+
import * as codeBlock from './code-block/index';
2223
import { removeBackwardCompatibilityStyles } from './utils';
2324
import './helpers.scss';
2425
import './global.scss';
2526

27+
import '@fontsource/inter/latin-400.css';
28+
import '@fontsource/inter/latin-600.css';
29+
import '@fontsource/jetbrains-mono/latin-400.css';
30+
import '@fontsource/jetbrains-mono/latin-600.css';
31+
2632
export {
2733
button,
2834
checkbox,
@@ -42,6 +48,7 @@ export {
4248
link,
4349
breadcrumbs,
4450
inlineCode,
51+
codeBlock,
4552
};
4653

4754
document.addEventListener('DOMContentLoaded', () => {

dokka-subprojects/plugin-base-frontend/src/main/ui-kit/inline-code/styles.scss

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66

77
code:not(.block) {
88
font: var(--font-code);
9-
background: var(--color-background-code);
9+
background: var(--color-background-inline-code);
1010
display: inline-block;
1111
padding: 0 4px;
1212
border-radius: 2px;
1313
}
14-
15-
.theme-dark code:not(.block) {
16-
color: var(--color-text);
17-
}

0 commit comments

Comments
 (0)