Skip to content

Commit 84fcfe7

Browse files
committed
Update style for info-blocks
1 parent 35f5bad commit 84fcfe7

3 files changed

Lines changed: 147 additions & 2 deletions

File tree

.vitepress/config.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { generateRss, rssPlugin } from './rss'
44
import { generateLlms, llmsPlugin } from './llms'
55
import { isBlogPath } from './locales'
66
import { faqPlugin } from './faq'
7+
import { infoBlockPlugin } from './info-block'
78

89
const baseUrl = 'https://php-testo.github.io'
910

@@ -17,6 +18,7 @@ export default defineConfig({
1718
markdown: {
1819
config: (md) => {
1920
md.use(faqPlugin)
21+
md.use(infoBlockPlugin)
2022
},
2123
},
2224
srcExclude: ['CLAUDE.md', 'README.md'],
@@ -71,6 +73,7 @@ gtag('config', 'G-VYGDN3X0PR');`],
7173
items: [
7274
{ text: 'Why Testo?', link: '/docs/why-testo' },
7375
{ text: 'Getting Started', link: '/docs/getting-started' },
76+
{ text: 'Configuration', link: '/docs/configuration' },
7477
],
7578
},
7679
{
@@ -124,6 +127,7 @@ gtag('config', 'G-VYGDN3X0PR');`],
124127
items: [
125128
{ text: 'Почему Testo?', link: '/ru/docs/why-testo' },
126129
{ text: 'Начало работы', link: '/ru/docs/getting-started' },
130+
{ text: 'Конфигурация', link: '/ru/docs/configuration' },
127131
],
128132
},
129133
{

.vitepress/info-block.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Custom block icon plugin for markdown-it.
3+
*
4+
* For `::: info`, `::: tip` and `::: danger` blocks without a custom title:
5+
* - Removes the default heading ("INFO" / "TIP" / "DANGER")
6+
* - Adds `data-*-icon` attribute so CSS can render an icon on the left border
7+
*
8+
* Blocks with custom titles (`::: info My Title`) are left untouched.
9+
*/
10+
import type MarkdownIt from 'markdown-it'
11+
12+
function wrapContainerRenderer(
13+
md: MarkdownIt,
14+
type: string,
15+
dataAttr: string,
16+
) {
17+
const defaultRender = md.renderer.rules[`container_${type}_open`]
18+
19+
md.renderer.rules[`container_${type}_open`] = (tokens, idx, options, env, self) => {
20+
const token = tokens[idx]
21+
const title = token.info.trim().slice(type.length).trim()
22+
23+
if (!title) {
24+
return `<div class="${type} custom-block" ${dataAttr}>\n`
25+
}
26+
27+
if (defaultRender) {
28+
return defaultRender(tokens, idx, options, env, self)
29+
}
30+
31+
return self.renderToken(tokens, idx, options)
32+
}
33+
}
34+
35+
export function infoBlockPlugin(md: MarkdownIt) {
36+
wrapContainerRenderer(md, 'info', 'data-info-icon')
37+
wrapContainerRenderer(md, 'tip', 'data-tip-icon')
38+
wrapContainerRenderer(md, 'danger', 'data-danger-icon')
39+
wrapContainerRenderer(md, 'warning', 'data-warning-icon')
40+
}

.vitepress/theme/style.css

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,37 @@ html {
1414
--vp-c-brand-dark: #e6c199;
1515
--vp-c-brand-darker: #f0d4b3;
1616
--vp-c-brand-dimm: rgba(230, 193, 153, 0.08);
17+
18+
--vp-custom-block-info-border: #abe1fc;
19+
--vp-custom-block-info-bg: rgba(0, 171, 255, 0.08);
20+
21+
--vp-custom-block-tip-border: #efcfa9;
22+
--vp-custom-block-tip-bg: linear-gradient(135deg, rgba(245, 222, 179, 0.05), rgba(245, 222, 179, 0.02));
23+
24+
--vp-custom-block-danger-border: #ff8686;
25+
--vp-custom-block-danger-bg: rgba(197, 56, 56, 0.13);
26+
27+
--vp-custom-block-warning-border: #e8b44e;
28+
--vp-custom-block-warning-bg: rgba(232, 180, 78, 0.08);
1729
}
1830

1931
.dark {
2032
--vp-c-brand-1: #e6c199;
2133
--vp-c-brand-2: #d4a574;
2234
--vp-c-brand-3: #c8995f;
2335
--vp-c-brand-soft: rgba(230, 193, 153, 0.16);
36+
37+
--vp-custom-block-info-border: #1f4f73;
38+
--vp-custom-block-info-bg: rgba(50, 119, 155, 0.16);
39+
40+
--vp-custom-block-tip-border: #564837;
41+
--vp-custom-block-tip-bg: linear-gradient(135deg, rgba(245, 222, 179, 0.05), rgba(245, 222, 179, 0.02));
42+
43+
--vp-custom-block-danger-border: #4d2929;
44+
--vp-custom-block-danger-bg: rgba(200, 50, 50, 0.08);
45+
46+
--vp-custom-block-warning-border: #6b5a2e;
47+
--vp-custom-block-warning-bg: rgba(232, 180, 78, 0.1);
2448
}
2549

2650
/* Show theme toggle and language switcher directly in nav bar */
@@ -155,11 +179,21 @@ html {
155179
transition: all 0.3s ease;
156180
}
157181

182+
.vp-doc .vp-code-group div[class*="language-"] {
183+
margin: 0 !important;
184+
border-radius: 0 !important;
185+
box-shadow: none !important;
186+
}
187+
158188
.vp-doc .vp-code-group:hover,
159189
.vp-doc div[class*="language-"]:hover {
160190
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
161191
}
162192

193+
.vp-doc .vp-code-group div[class*="language-"]:hover {
194+
box-shadow: none !important;
195+
}
196+
163197
/* Prevent inline code from wrapping */
164198
.vp-doc :not(pre) > code {
165199
white-space: nowrap;
@@ -173,9 +207,76 @@ html {
173207
margin: 24px 0 !important;
174208
}
175209

210+
/* Custom block colors */
211+
.vp-doc .custom-block.info[data-info-icon] {
212+
border-color: var(--vp-custom-block-info-border) !important;
213+
}
214+
176215
.vp-doc .custom-block.tip {
177-
background: linear-gradient(135deg, rgba(245, 222, 179, 0.05), rgba(245, 222, 179, 0.02));
178-
border-left-color: var(--vp-c-brand-1) !important;
216+
background: var(--vp-custom-block-tip-bg);
217+
border-left-color: var(--vp-custom-block-tip-border) !important;
218+
}
219+
220+
.vp-doc .custom-block.danger {
221+
background: var(--vp-custom-block-danger-bg);
222+
border-left-color: var(--vp-custom-block-danger-border) !important;
223+
}
224+
225+
.vp-doc .custom-block.warning {
226+
background: var(--vp-custom-block-warning-bg);
227+
border-left-color: var(--vp-custom-block-warning-border) !important;
228+
}
229+
230+
/* Icon blocks — shared styles */
231+
.vp-doc .custom-block[data-info-icon],
232+
.vp-doc .custom-block[data-tip-icon],
233+
.vp-doc .custom-block[data-danger-icon],
234+
.vp-doc .custom-block[data-warning-icon] {
235+
position: relative;
236+
overflow: visible;
237+
}
238+
239+
.vp-doc .custom-block[data-info-icon]::before,
240+
.vp-doc .custom-block[data-tip-icon]::before,
241+
.vp-doc .custom-block[data-danger-icon]::before,
242+
.vp-doc .custom-block[data-warning-icon]::before {
243+
position: absolute;
244+
left: -14px;
245+
top: 16px;
246+
width: 24px;
247+
height: 24px;
248+
border-radius: 50%;
249+
color: #fff;
250+
font-family: Georgia, serif;
251+
font-style: italic;
252+
font-weight: 700;
253+
font-size: 14px;
254+
line-height: 24px;
255+
text-align: center;
256+
}
257+
258+
/* Icon blocks — individual icons and colors */
259+
.vp-doc .custom-block[data-info-icon]::before {
260+
content: 'i';
261+
background: var(--vp-custom-block-info-border);
262+
}
263+
264+
.vp-doc .custom-block[data-tip-icon]::before {
265+
content: '✓';
266+
background: var(--vp-custom-block-tip-border);
267+
font-style: normal;
268+
}
269+
270+
.vp-doc .custom-block[data-danger-icon]::before {
271+
content: '✕';
272+
background: var(--vp-custom-block-danger-border);
273+
font-style: normal;
274+
font-size: 12px;
275+
}
276+
277+
.vp-doc .custom-block[data-warning-icon]::before {
278+
content: '!';
279+
background: var(--vp-custom-block-warning-border);
179280
}
180281

181282
/* Sponsors section */

0 commit comments

Comments
 (0)