jekyll-vitepress-theme 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f175074cdc25f3c9545388ece6e5140ac1b31e514641a6c1ab66612b996ba5fc
4
- data.tar.gz: 98d3593dae2959af719fe81d7b01cba9d7a8ca739cb6bd573d9a710d653b96be
3
+ metadata.gz: 992b88a492650795d8c8b03703aea31012b504cdda681d76e454e5743ff47ade
4
+ data.tar.gz: d34d89e4083b7ae20af406913383308eba839cd5bc8b90cbbbcf0c05db409df7
5
5
  SHA512:
6
- metadata.gz: 44d14ac6e9e6785003b8e9d99e53961f6a6b8c0d4559f5e77f5ee4ff159ff69cc412a03377ce70d6087db59b795ee86f01fcd3816c0b00aea3c1c76040f4d6b5
7
- data.tar.gz: 1ea58cd6c5e5f2326bf166bbebd6fb6aed35c851ede6a8715116f32a5c24409f176df8794efff35d3070ab484553d7317e371c9f6b237fc7ff0359a299cdf9ec
6
+ metadata.gz: c40225a00e75eb8bebe940bcbaf67d9e4d2c2e7d54030febdcd8723f270991485d3439d0719fb9295abe6725bb953d2657a45b166f6df92a563242d12c6b5aa4
7
+ data.tar.gz: f1c5114a6edc146394b35a854077dd59462229402aa2d4eef40edc51e1a770f038610802a5817ff171f267354370ca8208c21ee9b23d6cfa6bac4f5e29089549
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Jekyll VitePress Theme
6
6
 
7
- <strong>Turbo-fast documentation for Jekyll projects.</strong>
7
+ <strong>Ruby deserves beautiful docs. Jekyll VitePress Theme brings VitePress-level polish to Jekyll.</strong>
8
8
 
9
9
  [![Gem Version](https://img.shields.io/gem/v/jekyll-vitepress-theme.svg)](https://rubygems.org/gems/jekyll-vitepress-theme)
10
10
  [![CI](https://github.com/crmne/jekyll-vitepress-theme/actions/workflows/main.yml/badge.svg)](https://github.com/crmne/jekyll-vitepress-theme/actions/workflows/main.yml)
@@ -15,20 +15,19 @@
15
15
 
16
16
  ---
17
17
 
18
- Ruby projects should not need a JavaScript app just to get beautiful, fast docs.
18
+ Ruby projects should not need to leave Ruby just to get documentation that feels designed.
19
19
 
20
- `jekyll-vitepress-theme` brings the VitePress documentation experience to Jekyll: the familiar nav, sidebar, outline, search, code blocks, dark mode, and polished default theme, packaged as a Ruby gem.
20
+ `jekyll-vitepress-theme` brings VitePress-level documentation polish to Jekyll: a product-like homepage, familiar navigation, sidebars, outlines, search, dark mode, code blocks, callouts, and doc footers, packaged as a Ruby gem.
21
21
 
22
- The unusual part is navigation. Internal docs links use Turbo Frames, so page changes feel close to VitePress while the site remains plain Jekyll output: Markdown, Liquid, YAML, Ruby, and static files.
22
+ The unusual part is navigation. Jekyll VitePress uses Turbo Frames like a Rails app, swapping only the content frame while the nav, sidebar, and shell stay in place. Page changes feel instant, while the output remains plain Jekyll: Markdown, Liquid, YAML, Ruby, and static files.
23
23
 
24
24
  ## Why Use It
25
25
 
26
- - **VitePress-like UX:** top nav, persistent sidebar, right outline, doc footer pager, search modal, theme toggle, and optional GitHub Star/Sponsor buttons.
27
- - **Turbo page navigation:** only the docs content frame swaps, so the shell stays in place and page changes feel fast.
28
- - **Jekyll-native setup:** configure everything with `_config.yml`, `_data/*.yml`, collections, includes, and frontmatter.
29
- - **Ruby syntax pipeline:** Rouge powers light and dark syntax themes without a separate JavaScript build.
30
- - **Static deployment:** build once with Jekyll and publish to GitHub Pages, any CDN, or any static host.
31
- - **Useful extras:** GitHub star count, version selector, last-updated labels, copy buttons, and "Copy page" Markdown export.
26
+ - **VitePress polish for Jekyll:** give Ruby projects a docs homepage, sidebar, outline, search, dark mode, callouts, code blocks, and doc footers that feel designed.
27
+ - **Jekyll-native setup:** keep your Markdown, Liquid, YAML, and static hosting. Add the gem, set a few options, and publish.
28
+ - **Fast docs navigation:** Turbo Frames update the content area while the nav, sidebar, and shell stay mounted.
29
+ - **More than VitePress:** add GitHub Star and Sponsor buttons, versions, generated local search, and Copy Page/View as Markdown for LLM workflows.
30
+ - **Static Ruby output:** build with Jekyll and deploy the generated HTML to GitHub Pages, any CDN, or any static host.
32
31
 
33
32
  ## Quick Start
34
33
 
data/_includes/head.html CHANGED
@@ -2,8 +2,36 @@
2
2
  <meta charset="UTF-8">
3
3
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
4
  {% assign page_title = page.title | default: site.title %}
5
- <title>{% if page_title and page_title != site.title %}{{ page_title }} | {{ site.title }}{% else %}{{ site.title }}{% endif %}</title>
6
- <meta name="description" content="{{ page.description | default: site.description | escape }}">
5
+ {% capture full_title %}{% if page_title and page_title != site.title %}{{ page_title }} | {{ site.title }}{% else %}{{ site.title }}{% endif %}{% endcapture %}
6
+ {% assign full_title = full_title | strip %}
7
+ {% assign page_description = page.description | default: site.description %}
8
+ {% assign canonical_url = page.canonical_url | default: page.url | absolute_url %}
9
+ {% assign page_image = page.image %}
10
+ {% assign seo_image = site.logo | default: '/assets/images/favicon/web-app-manifest-512x512.png' %}
11
+ {% if page_image %}
12
+ {% if page_image.src %}
13
+ {% assign seo_image = page_image.src %}
14
+ {% elsif page_image.path %}
15
+ {% assign seo_image = page_image.path %}
16
+ {% else %}
17
+ {% assign seo_image = page_image %}
18
+ {% endif %}
19
+ {% endif %}
20
+ {% assign seo_image_url = seo_image | absolute_url %}
21
+ <title>{{ full_title }}</title>
22
+ <meta name="description" content="{{ page_description | escape }}">
23
+ <meta name="robots" content="index,follow,max-image-preview:large">
24
+ <link rel="canonical" href="{{ canonical_url }}">
25
+ <meta property="og:site_name" content="{{ site.title | escape }}">
26
+ <meta property="og:title" content="{{ full_title | escape }}">
27
+ <meta property="og:description" content="{{ page_description | escape }}">
28
+ <meta property="og:url" content="{{ canonical_url }}">
29
+ <meta property="og:type" content="{% if page.url == '/' %}website{% else %}article{% endif %}">
30
+ <meta property="og:image" content="{{ seo_image_url }}">
31
+ <meta name="twitter:card" content="summary_large_image">
32
+ <meta name="twitter:title" content="{{ full_title | escape }}">
33
+ <meta name="twitter:description" content="{{ page_description | escape }}">
34
+ <meta name="twitter:image" content="{{ seo_image_url }}">
7
35
 
8
36
  {% assign theme = site.jekyll_vitepress %}
9
37
  {% assign branding = theme.branding %}
@@ -99,6 +127,9 @@
99
127
  </style>
100
128
  {% endif %}
101
129
 
130
+ {% if page.url == '/' or page.url == '/index.html' %}
131
+ {% ai_json_ld %}
132
+ {% endif %}
102
133
  {% include jekyll_vitepress/head_end.html %}
103
134
  <script src="{{ '/assets/vendor/turbo.js' | relative_url }}" defer></script>
104
135
  <script src="{{ '/assets/js/vitepress-theme.js' | relative_url }}" defer></script>
@@ -4,7 +4,8 @@
4
4
  {% assign theme = site.jekyll_vitepress %}
5
5
  {% assign behavior = theme.behavior %}
6
6
  {% assign page_theme = page.jekyll_vitepress %}
7
- <body data-vp-scroll-offset="{{ behavior.scroll_offset | default: 134 }}">
7
+ {% assign scroll_offset = behavior.scroll_offset | default: 134 %}
8
+ <body data-vp-scroll-offset="{{ scroll_offset }}" style="--vp-scroll-offset: {{ scroll_offset }}px;">
8
9
  {% assign is_home = false %}
9
10
  {% if page.layout == 'home' or page.url == '/' %}
10
11
  {% assign is_home = true %}
@@ -1306,6 +1306,15 @@ html:not(.dark) .shiki span {
1306
1306
  outline: none;
1307
1307
  }
1308
1308
 
1309
+ .vp-doc h1[id],
1310
+ .vp-doc h2[id],
1311
+ .vp-doc h3[id],
1312
+ .vp-doc h4[id],
1313
+ .vp-doc h5[id],
1314
+ .vp-doc h6[id] {
1315
+ scroll-margin-top: calc(var(--vp-scroll-offset, 134px) - var(--vp-heading-anchor-offset, 0px));
1316
+ }
1317
+
1309
1318
  .vp-doc h1 {
1310
1319
  letter-spacing: -0.02em;
1311
1320
  line-height: 40px;
@@ -1313,6 +1322,8 @@ html:not(.dark) .shiki span {
1313
1322
  }
1314
1323
 
1315
1324
  .vp-doc h2 {
1325
+ --vp-heading-anchor-offset: 24px;
1326
+
1316
1327
  margin: 48px 0 16px;
1317
1328
  border-top: 1px solid var(--vp-c-divider);
1318
1329
  padding-top: 24px;
@@ -0,0 +1,86 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Adapted from Jekyll brand artwork: https://github.com/jekyll/brand/blob/master/jekyll-test-tube.svg -->
3
+ <!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
4
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
5
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48"
6
+ height="48" viewBox="100 35 310 450" enable-background="new 0 0 512 512" xml:space="preserve">
7
+ <g id="logo-bg-dark" display="none">
8
+ <rect id="bg" fill="#333333" width="512" height="512"/>
9
+ <g id="test-tube">
10
+ <path id="shadow_2_" opacity="0.3" d="M269.02,59.151c-0.184,0.737-0.188,1.529-0.033,2.365c0,0,2.507,16.642-0.339,24.048
11
+ L147.643,400.197l0.009,0.004c-8.636,23.11,2.937,48.911,26.014,57.787c23.077,8.875,48.955-2.524,58.03-25.464l0.011,0.005
12
+ l121.005-314.634c2.366-6.155,15.86-18.079,15.86-18.079c0.677-0.516,1.202-1.108,1.56-1.778l0.059-0.122
13
+ c0.065-0.132,0.141-0.258,0.193-0.395c3.12-8.113-17.005-23.405-44.952-34.152c-27.948-10.748-53.133-12.884-56.253-4.771
14
+ c-0.053,0.137-0.083,0.281-0.122,0.422L269.02,59.151z"/>
15
+
16
+ <linearGradient id="tube_3_" gradientUnits="userSpaceOnUse" x1="206.4585" y1="215.2629" x2="283.1295" y2="291.9339" gradientTransform="matrix(0.9138 -0.4062 0.4062 0.9138 -80.6459 125.703)">
17
+ <stop offset="0" style="stop-color:#919191"/>
18
+ <stop offset="1" style="stop-color:#FFFFFF"/>
19
+ </linearGradient>
20
+ <path id="tube_2_" fill="url(#tube_3_)" d="M265.523,56.477c-0.185,0.737-0.19,1.529-0.033,2.365c0,0,2.508,16.642-0.34,24.048
21
+ L144.144,397.522l0.011,0.004c-8.635,23.11,2.937,48.911,26.014,57.787c23.075,8.875,48.955-2.524,58.03-25.464l0.011,0.005
22
+ L349.215,115.22c2.365-6.155,15.86-18.079,15.86-18.079c0.677-0.516,1.202-1.107,1.56-1.778l0.058-0.122
23
+ c0.065-0.131,0.141-0.258,0.193-0.395c3.12-8.113-17.005-23.404-44.951-34.152c-27.948-10.748-53.133-12.884-56.253-4.771
24
+ c-0.053,0.137-0.083,0.281-0.122,0.422L265.523,56.477z"/>
25
+
26
+ <linearGradient id="liquid_2_" gradientUnits="userSpaceOnUse" x1="177.6289" y1="273.7523" x2="224.0456" y2="320.1689" gradientTransform="matrix(0.9138 -0.4062 0.4062 0.9138 -80.6459 125.703)">
27
+ <stop offset="0" style="stop-color:#990000"/>
28
+ <stop offset="1" style="stop-color:#E80000"/>
29
+ </linearGradient>
30
+ <path id="liquid" fill="url(#liquid_2_)" d="M303.48,198.814L216.218,425.71l0.057,0.021
31
+ c-6.436,16.262-25.166,24.723-41.781,18.333c-16.615-6.39-25.608-25.512-19.488-41.897l0,0l55.758-144.982
32
+ c0,0,6.964-11.233,20.637-19.225c13.673-7.991,24.949-6.305,40.132-13.053C286.715,218.159,303.48,198.814,303.48,198.814z"/>
33
+
34
+ <ellipse id="top" transform="matrix(0.9334 0.359 -0.359 0.9334 48.4129 -108.3439)" fill="#333333" cx="315.97" cy="76.201" rx="33.648" ry="8.85"/>
35
+ <path id="side-reflection" opacity="0.3" fill="#FFFFFF" d="M265.489,58.841c0,0,2.471,16.737-0.34,24.048L144.144,397.522
36
+ l0.011,0.004c-8.635,23.11,2.937,48.911,26.014,57.787c4.005,1.54,8.092,2.455,12.164,2.822
37
+ c-15.556-11.702-22.23-32.632-15.093-51.73l-0.011-0.004L285.833,98.009C285.833,98.009,269.689,82.85,265.489,58.841z"/>
38
+ <g id="bubbles">
39
+ <circle opacity="0.5" fill="#FFFFFF" cx="226.531" cy="261.806" r="3.506"/>
40
+ <circle opacity="0.5" fill="#FFFFFF" cx="249.514" cy="287.227" r="5.285"/>
41
+ <circle opacity="0.5" fill="#FFFFFF" cx="214.429" cy="317.459" r="9.915"/>
42
+ <circle opacity="0.5" fill="#FFFFFF" cx="198.375" cy="335.795" r="5.286"/>
43
+ <circle opacity="0.5" fill="#FFFFFF" cx="219.43" cy="375.008" r="3.506"/>
44
+ </g>
45
+ </g>
46
+ </g>
47
+ <g id="logo-bg-light">
48
+ <g id="test-tube_1_" display="inline">
49
+ <path id="shadow_1_" opacity="0.1" d="M269.02,59.151c-0.184,0.737-0.188,1.529-0.033,2.365c0,0,2.507,16.642-0.339,24.048
50
+ L147.643,400.197l0.009,0.004c-8.636,23.11,2.937,48.911,26.014,57.787c23.077,8.875,48.955-2.524,58.03-25.464l0.011,0.005
51
+ l121.005-314.634c2.366-6.155,15.86-18.079,15.86-18.079c0.677-0.516,1.202-1.108,1.56-1.778l0.059-0.122
52
+ c0.065-0.132,0.141-0.258,0.193-0.395c3.12-8.113-17.005-23.405-44.952-34.152c-27.948-10.748-53.133-12.884-56.253-4.771
53
+ c-0.053,0.137-0.083,0.281-0.122,0.422L269.02,59.151z"/>
54
+
55
+ <linearGradient id="tube_4_" gradientUnits="userSpaceOnUse" x1="206.4585" y1="215.2629" x2="283.1295" y2="291.9339" gradientTransform="matrix(0.9138 -0.4062 0.4062 0.9138 -80.6459 125.703)">
56
+ <stop offset="0" style="stop-color:#919191"/>
57
+ <stop offset="1" style="stop-color:#FFFFFF"/>
58
+ </linearGradient>
59
+ <path id="tube_1_" fill="url(#tube_4_)" d="M265.523,56.477c-0.185,0.737-0.19,1.529-0.033,2.365c0,0,2.508,16.642-0.34,24.048
60
+ L144.144,397.522l0.011,0.004c-8.635,23.11,2.937,48.911,26.014,57.787c23.075,8.875,48.955-2.524,58.03-25.464l0.011,0.005
61
+ L349.215,115.22c2.365-6.155,15.86-18.079,15.86-18.079c0.677-0.516,1.202-1.107,1.56-1.778l0.058-0.122
62
+ c0.065-0.131,0.141-0.258,0.193-0.395c3.12-8.113-17.005-23.404-44.951-34.152c-27.948-10.748-53.133-12.884-56.253-4.771
63
+ c-0.053,0.137-0.083,0.281-0.122,0.422L265.523,56.477z"/>
64
+
65
+ <linearGradient id="liquid_3_" gradientUnits="userSpaceOnUse" x1="177.6289" y1="273.7523" x2="224.0456" y2="320.1689" gradientTransform="matrix(0.9138 -0.4062 0.4062 0.9138 -80.6459 125.703)">
66
+ <stop offset="0" style="stop-color:#990000"/>
67
+ <stop offset="1" style="stop-color:#E80000"/>
68
+ </linearGradient>
69
+ <path id="liquid_1_" fill="url(#liquid_3_)" d="M303.48,198.814L216.218,425.71l0.057,0.021
70
+ c-6.436,16.262-25.166,24.723-41.781,18.333c-16.615-6.39-25.608-25.512-19.488-41.897l0,0l55.758-144.982
71
+ c0,0,6.964-11.233,20.637-19.225c13.673-7.991,24.949-6.305,40.132-13.053C286.715,218.159,303.48,198.814,303.48,198.814z"/>
72
+
73
+ <ellipse id="top_1_" transform="matrix(0.9334 0.359 -0.359 0.9334 48.4129 -108.3439)" fill="#333333" cx="315.97" cy="76.201" rx="33.648" ry="8.85"/>
74
+ <path id="side-reflection_1_" opacity="0.3" fill="#FFFFFF" d="M265.489,58.841c0,0,2.471,16.737-0.34,24.048L144.144,397.522
75
+ l0.011,0.004c-8.635,23.11,2.937,48.911,26.014,57.787c4.005,1.54,8.092,2.455,12.164,2.822
76
+ c-15.556-11.702-22.23-32.632-15.093-51.73l-0.011-0.004L285.833,98.009C285.833,98.009,269.689,82.85,265.489,58.841z"/>
77
+ <g id="bubbles_1_">
78
+ <circle opacity="0.5" fill="#FFFFFF" cx="226.531" cy="261.806" r="3.506"/>
79
+ <circle opacity="0.5" fill="#FFFFFF" cx="249.514" cy="287.227" r="5.285"/>
80
+ <circle opacity="0.5" fill="#FFFFFF" cx="214.429" cy="317.459" r="9.915"/>
81
+ <circle opacity="0.5" fill="#FFFFFF" cx="198.375" cy="335.795" r="5.286"/>
82
+ <circle opacity="0.5" fill="#FFFFFF" cx="219.43" cy="375.008" r="3.506"/>
83
+ </g>
84
+ </g>
85
+ </g>
86
+ </svg>
@@ -0,0 +1,21 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" role="img" aria-label="More than VitePress">
2
+ <defs>
3
+ <linearGradient id="more-card" x1="9" x2="38" y1="10" y2="39" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#41D1FF"/>
5
+ <stop offset="1" stop-color="#BD34FE"/>
6
+ </linearGradient>
7
+ <linearGradient id="more-plus" x1="19" x2="34" y1="19" y2="34" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#FFEA83"/>
9
+ <stop offset="1" stop-color="#FFA800"/>
10
+ </linearGradient>
11
+ <filter id="more-shadow" x="5" y="5" width="38" height="39" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
12
+ <feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#1F2A44" flood-opacity=".18"/>
13
+ </filter>
14
+ </defs>
15
+ <g filter="url(#more-shadow)">
16
+ <path fill="#fff" d="M13.3 8.8 33 6.2a4.1 4.1 0 0 1 4.6 3.5l3.4 25.6a4.1 4.1 0 0 1-3.5 4.6l-19.7 2.6a4.1 4.1 0 0 1-4.6-3.5L9.8 13.4a4.1 4.1 0 0 1 3.5-4.6Z"/>
17
+ <path fill="url(#more-card)" d="M14.1 11.4 32.9 9a1.6 1.6 0 0 1 1.8 1.4l3.2 24.1a1.6 1.6 0 0 1-1.4 1.8l-18.8 2.5a1.6 1.6 0 0 1-1.8-1.4l-3.2-24.1a1.6 1.6 0 0 1 1.4-1.9Z" opacity=".9"/>
18
+ <path fill="#fff" d="M17 17.6a1.1 1.1 0 0 1 1-1.3l12.8-1.7a1.1 1.1 0 1 1 .3 2.2l-12.8 1.7a1.1 1.1 0 0 1-1.3-.9Zm.8 6.3a1.1 1.1 0 0 1 1-1.3l7.7-1a1.1 1.1 0 1 1 .3 2.2l-7.7 1a1.1 1.1 0 0 1-1.3-.9Z" opacity=".72"/>
19
+ <path fill="url(#more-plus)" d="M28.7 26.4a1.5 1.5 0 0 1 1.3-1.7a1.5 1.5 0 0 1 1.7 1.3l.4 2.8 2.8-.4a1.5 1.5 0 0 1 .4 3l-2.8.4.4 2.8a1.5 1.5 0 1 1-3 .4l-.4-2.8-2.8.4a1.5 1.5 0 0 1-.4-3l2.8-.4-.4-2.8Z"/>
20
+ </g>
21
+ </svg>
@@ -0,0 +1,28 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" role="img" aria-label="Turbo frame navigation">
2
+ <defs>
3
+ <linearGradient id="turbo-shell" x1="6" x2="42" y1="8" y2="40" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#55D7FF"/>
5
+ <stop offset="1" stop-color="#BD34FE"/>
6
+ </linearGradient>
7
+ <linearGradient id="turbo-fill" x1="13" x2="36" y1="15" y2="34" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#F8FCFF"/>
9
+ <stop offset="1" stop-color="#EAF3FF"/>
10
+ </linearGradient>
11
+ <linearGradient id="turbo-arrow" x1="16" x2="36" y1="25" y2="25" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#FFE05D"/>
13
+ <stop offset="1" stop-color="#FF9F1C"/>
14
+ </linearGradient>
15
+ <filter id="turbo-shadow" x="3" y="6" width="42" height="38" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
16
+ <feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#1F2A44" flood-opacity=".18"/>
17
+ </filter>
18
+ </defs>
19
+ <g filter="url(#turbo-shadow)">
20
+ <rect x="7" y="9" width="34" height="30" rx="7" fill="url(#turbo-fill)" stroke="url(#turbo-shell)" stroke-width="2.5"/>
21
+ <path fill="#D8E5F4" d="M8.8 17.4h30.4v2.3H8.8z"/>
22
+ <circle cx="13.3" cy="14.4" r="1.4" fill="#55D7FF"/>
23
+ <circle cx="17.5" cy="14.4" r="1.4" fill="#9B66FF"/>
24
+ <rect x="12.2" y="23" width="8.2" height="9.5" rx="2" fill="#DDF6FF"/>
25
+ <rect x="23.3" y="23" width="12.4" height="9.5" rx="2" fill="#F1E6FF"/>
26
+ <path fill="url(#turbo-arrow)" d="M29.7 20.7a1.3 1.3 0 0 1 1.8 0l5 4.9a1.3 1.3 0 0 1 0 1.8l-5 4.9a1.3 1.3 0 0 1-2.2-.9v-2.2H17.2a1.8 1.8 0 1 1 0-3.6h12.1v-4a1.3 1.3 0 0 1 .4-.9Z"/>
27
+ </g>
28
+ </svg>
@@ -0,0 +1,22 @@
1
+ <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Source: https://github.com/vuejs/vitepress/blob/main/art/vitepress-logo-mini.svg -->
3
+ <path d="M5.03628 7.87818C4.75336 5.83955 6.15592 3.95466 8.16899 3.66815L33.6838 0.0367403C35.6969 -0.24977 37.5581 1.1706 37.841 3.20923L42.9637 40.1218C43.2466 42.1604 41.8441 44.0453 39.831 44.3319L14.3162 47.9633C12.3031 48.2498 10.4419 46.8294 10.159 44.7908L5.03628 7.87818Z" fill="url(#paint0_linear_1287_1214)"/>
4
+ <path d="M6.85877 7.6188C6.71731 6.59948 7.41859 5.65703 8.42512 5.51378L33.9399 1.88237C34.9465 1.73911 35.8771 2.4493 36.0186 3.46861L41.1412 40.3812C41.2827 41.4005 40.5814 42.343 39.5749 42.4862L14.0601 46.1176C13.0535 46.2609 12.1229 45.5507 11.9814 44.5314L6.85877 7.6188Z" fill="white"/>
5
+ <path d="M33.1857 14.9195L25.8505 34.1576C25.6991 34.5547 25.1763 34.63 24.9177 34.2919L12.3343 17.8339C12.0526 17.4655 12.3217 16.9339 12.7806 16.9524L22.9053 17.3607C22.9698 17.3633 23.0344 17.3541 23.0956 17.3337L32.5088 14.1992C32.9431 14.0546 33.3503 14.4878 33.1857 14.9195Z" fill="url(#paint1_linear_1287_1214)"/>
6
+ <path d="M27.0251 12.5756L19.9352 15.0427C19.8187 15.0832 19.7444 15.1986 19.7546 15.3231L20.3916 23.063C20.4066 23.2453 20.5904 23.3628 20.7588 23.2977L22.7226 22.5392C22.9064 22.4682 23.1021 22.6138 23.0905 22.8128L22.9102 25.8903C22.8982 26.0974 23.1093 26.2436 23.295 26.1567L24.4948 25.5953C24.6808 25.5084 24.892 25.6549 24.8795 25.8624L24.5855 30.6979C24.5671 31.0004 24.9759 31.1067 25.1013 30.8321L25.185 30.6487L29.4298 17.8014C29.5008 17.5863 29.2968 17.3809 29.0847 17.454L27.0519 18.1547C26.8609 18.2205 26.6675 18.0586 26.6954 17.8561L27.3823 12.8739C27.4103 12.6712 27.2163 12.5091 27.0251 12.5756Z" fill="url(#paint2_linear_1287_1214)"/>
7
+ <defs>
8
+ <linearGradient id="paint0_linear_1287_1214" x1="6.48163" y1="1.9759" x2="39.05" y2="48.2064" gradientUnits="userSpaceOnUse">
9
+ <stop stop-color="#49C7FF"/>
10
+ <stop offset="1" stop-color="#BD36FF"/>
11
+ </linearGradient>
12
+ <linearGradient id="paint1_linear_1287_1214" x1="11.8848" y1="16.4266" x2="26.7246" y2="31.4177" gradientUnits="userSpaceOnUse">
13
+ <stop stop-color="#41D1FF"/>
14
+ <stop offset="1" stop-color="#BD34FE"/>
15
+ </linearGradient>
16
+ <linearGradient id="paint2_linear_1287_1214" x1="21.8138" y1="13.7046" x2="26.2464" y2="28.8069" gradientUnits="userSpaceOnUse">
17
+ <stop stop-color="#FFEA83"/>
18
+ <stop offset="0.0833333" stop-color="#FFDD35"/>
19
+ <stop offset="1" stop-color="#FFA800"/>
20
+ </linearGradient>
21
+ </defs>
22
+ </svg>
@@ -1320,12 +1320,20 @@
1320
1320
  return;
1321
1321
  }
1322
1322
 
1323
+ function getHeadingLabel(heading) {
1324
+ var clone = heading.cloneNode(true);
1325
+ clone.querySelectorAll('.header-anchor').forEach(function (anchor) {
1326
+ anchor.remove();
1327
+ });
1328
+ return clone.textContent ? clone.textContent.trim() : heading.id;
1329
+ }
1330
+
1323
1331
  content.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').forEach(function (heading) {
1324
1332
  if (heading.querySelector('.header-anchor')) {
1325
1333
  return;
1326
1334
  }
1327
1335
 
1328
- var title = heading.textContent ? heading.textContent.trim() : heading.id;
1336
+ var title = getHeadingLabel(heading);
1329
1337
  var anchor = document.createElement('a');
1330
1338
  anchor.className = 'header-anchor';
1331
1339
  anchor.href = '#' + heading.id;
@@ -1409,7 +1417,7 @@
1409
1417
 
1410
1418
  var li = document.createElement('li');
1411
1419
  var link = document.createElement('a');
1412
- var label = entry.heading.textContent ? entry.heading.textContent.trim() : entry.heading.id;
1420
+ var label = getHeadingLabel(entry.heading);
1413
1421
 
1414
1422
  link.className = 'outline-link';
1415
1423
  link.href = '#' + entry.heading.id;
@@ -1536,38 +1544,38 @@
1536
1544
  return 134;
1537
1545
  }
1538
1546
 
1539
- function scrollToHashWithOffset(hash, smooth) {
1547
+ function getHashTarget(hash) {
1540
1548
  if (!hash) {
1541
- return;
1549
+ return null;
1542
1550
  }
1543
1551
 
1544
- var target = null;
1552
+ var id = hash.slice(1);
1545
1553
  try {
1546
- target = document.getElementById(decodeURIComponent(hash).slice(1));
1554
+ id = decodeURIComponent(id);
1547
1555
  } catch (error) {
1548
- target = null;
1556
+ id = hash.slice(1);
1549
1557
  }
1550
1558
 
1559
+ return document.getElementById(id);
1560
+ }
1561
+
1562
+ function scrollToHash(hash, smooth) {
1563
+ var target = getHashTarget(hash);
1551
1564
  if (!target) {
1552
- return;
1565
+ return false;
1553
1566
  }
1554
1567
 
1555
- var targetTop = window.scrollY +
1556
- target.getBoundingClientRect().top -
1557
- getConfiguredScrollOffset() +
1558
- (parseInt(window.getComputedStyle(target).paddingTop, 10) || 0);
1559
-
1560
1568
  var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
1561
1569
  var behavior = 'auto';
1562
- if (!reduceMotion && smooth && Math.abs(targetTop - window.scrollY) <= window.innerHeight) {
1570
+ if (!reduceMotion && smooth && Math.abs(target.getBoundingClientRect().top) <= window.innerHeight) {
1563
1571
  behavior = 'smooth';
1564
1572
  }
1565
1573
 
1566
- window.scrollTo({ left: 0, top: targetTop, behavior: behavior });
1574
+ target.scrollIntoView({ block: 'start', inline: 'nearest', behavior: behavior });
1567
1575
 
1568
1576
  target.focus({ preventScroll: true });
1569
1577
  if (document.activeElement === target || target.hasAttribute('tabindex')) {
1570
- return;
1578
+ return true;
1571
1579
  }
1572
1580
 
1573
1581
  var restoreTabindex = function () {
@@ -1581,51 +1589,98 @@
1581
1589
  if (document.activeElement !== target) {
1582
1590
  restoreTabindex();
1583
1591
  }
1592
+
1593
+ return true;
1594
+ }
1595
+
1596
+ function getSamePageHash(link) {
1597
+ if (!link) {
1598
+ return null;
1599
+ }
1600
+
1601
+ var href = link.getAttribute('href');
1602
+ if (!href || href === '#') {
1603
+ return null;
1604
+ }
1605
+
1606
+ if (href.charAt(0) === '#') {
1607
+ return href;
1608
+ }
1609
+
1610
+ var url;
1611
+ try {
1612
+ url = new URL(href, window.location.href);
1613
+ } catch (error) {
1614
+ return null;
1615
+ }
1616
+
1617
+ if (url.origin !== window.location.origin ||
1618
+ normalizePathname(url.pathname) !== normalizePathname(window.location.pathname) ||
1619
+ url.search !== window.location.search ||
1620
+ !url.hash) {
1621
+ return null;
1622
+ }
1623
+
1624
+ return url.hash;
1584
1625
  }
1585
1626
 
1586
- function handleOutlineLinkClick(event) {
1627
+ function handleHashLinkClick(event) {
1628
+ if (event.defaultPrevented || (typeof event.button === 'number' && event.button !== 0) ||
1629
+ event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
1630
+ return;
1631
+ }
1632
+
1587
1633
  var link = event.currentTarget;
1588
1634
  if (!link) {
1589
1635
  return;
1590
1636
  }
1591
1637
 
1592
- var hash = link.getAttribute('href');
1593
- if (!hash || hash.charAt(0) !== '#') {
1638
+ var target = link.getAttribute('target');
1639
+ if (target && target !== '_self') {
1640
+ return;
1641
+ }
1642
+
1643
+ var hash = getSamePageHash(link);
1644
+ if (!hash || !getHashTarget(hash)) {
1594
1645
  return;
1595
1646
  }
1596
1647
 
1597
1648
  event.preventDefault();
1598
1649
 
1599
1650
  if (window.history && typeof window.history.pushState === 'function') {
1651
+ if (window.location.hash === hash) {
1652
+ scrollToHash(hash, true);
1653
+ return;
1654
+ }
1600
1655
  window.history.pushState(null, '', hash);
1601
1656
  } else {
1602
1657
  window.location.hash = hash;
1603
1658
  }
1604
1659
 
1605
- scrollToHashWithOffset(hash, true);
1660
+ scrollToHash(hash, true);
1606
1661
  }
1607
1662
 
1608
- function bindOutlineLinkHandlers() {
1609
- document.querySelectorAll('.outline-link').forEach(function (link) {
1610
- if (link.hasAttribute('data-vp-bound')) {
1663
+ function bindHashLinkHandlers() {
1664
+ document.querySelectorAll('.outline-link, .vp-doc a[href]').forEach(function (link) {
1665
+ if (link.hasAttribute('data-vp-hash-bound') || !getSamePageHash(link)) {
1611
1666
  return;
1612
1667
  }
1613
- link.setAttribute('data-vp-bound', 'true');
1614
- link.addEventListener('click', handleOutlineLinkClick);
1668
+ link.setAttribute('data-vp-hash-bound', 'true');
1669
+ link.addEventListener('click', handleHashLinkClick);
1615
1670
  });
1616
1671
  }
1617
1672
 
1618
- bindOutlineLinkHandlers();
1673
+ bindHashLinkHandlers();
1619
1674
 
1620
1675
  if (window.location.hash) {
1621
1676
  window.requestAnimationFrame(function () {
1622
- scrollToHashWithOffset(window.location.hash, false);
1677
+ scrollToHash(window.location.hash, false);
1623
1678
  });
1624
1679
  }
1625
1680
 
1626
1681
  window.addEventListener('hashchange', function () {
1627
1682
  if (window.location.hash) {
1628
- scrollToHashWithOffset(window.location.hash, false);
1683
+ scrollToHash(window.location.hash, false);
1629
1684
  }
1630
1685
  });
1631
1686
 
@@ -1646,10 +1701,7 @@
1646
1701
  }
1647
1702
 
1648
1703
  function getOutlineScrollOffset() {
1649
- var styles = window.getComputedStyle(root);
1650
- var navHeight = parseFloat(styles.getPropertyValue('--vp-nav-height')) || 0;
1651
- var layoutTopHeight = parseFloat(styles.getPropertyValue('--vp-layout-top-height')) || 0;
1652
- return navHeight + layoutTopHeight;
1704
+ return getConfiguredScrollOffset();
1653
1705
  }
1654
1706
 
1655
1707
  function activateOutlineHash(activeHash) {
@@ -1798,6 +1850,46 @@
1798
1850
  });
1799
1851
  }
1800
1852
 
1853
+ function getSidebarItemScrollDistance(item) {
1854
+ if (!sidebar) {
1855
+ return 0;
1856
+ }
1857
+
1858
+ var sidebarRect = sidebar.getBoundingClientRect();
1859
+ var itemRect = item.getBoundingClientRect();
1860
+ var itemTop = itemRect.top - sidebarRect.top + sidebar.scrollTop;
1861
+
1862
+ return Math.abs(itemTop - sidebar.scrollTop);
1863
+ }
1864
+
1865
+ function getActiveSidebarItemClosestToScrollPosition() {
1866
+ if (!sidebar) {
1867
+ return null;
1868
+ }
1869
+
1870
+ var activeItems = Array.from(sidebar.querySelectorAll('.VPSidebarItem.level-1.is-link.is-active'));
1871
+
1872
+ if (!activeItems.length) {
1873
+ return null;
1874
+ }
1875
+
1876
+ return activeItems.reduce(function (closestItem, item) {
1877
+ if (!closestItem) {
1878
+ return item;
1879
+ }
1880
+
1881
+ return getSidebarItemScrollDistance(item) < getSidebarItemScrollDistance(closestItem) ? item : closestItem;
1882
+ }, null);
1883
+ }
1884
+
1885
+ function scrollActiveSidebarItemIntoView() {
1886
+ var activeItem = getActiveSidebarItemClosestToScrollPosition();
1887
+
1888
+ if (activeItem) {
1889
+ activeItem.scrollIntoView({ block: 'nearest' });
1890
+ }
1891
+ }
1892
+
1801
1893
  function syncPersistentNavState() {
1802
1894
  var frameState = document.getElementById('vp-page-state');
1803
1895
  if (!frameState) {
@@ -1831,6 +1923,8 @@
1831
1923
  normalizePathname(link.getAttribute('href')) === currentPath;
1832
1924
  link.classList.toggle('active', active);
1833
1925
  });
1926
+
1927
+ scrollActiveSidebarItemIntoView();
1834
1928
  }
1835
1929
 
1836
1930
  function refreshDocPageState() {
@@ -1854,7 +1948,7 @@
1854
1948
  return;
1855
1949
  }
1856
1950
 
1857
- var title = heading.textContent ? heading.textContent.trim() : heading.id;
1951
+ var title = getHeadingLabel(heading);
1858
1952
  var anchor = document.createElement('a');
1859
1953
  anchor.className = 'header-anchor';
1860
1954
  anchor.href = '#' + heading.id;
@@ -1936,7 +2030,7 @@
1936
2030
  localOutlineItems.hidden = true;
1937
2031
  }
1938
2032
 
1939
- bindOutlineLinkHandlers();
2033
+ bindHashLinkHandlers();
1940
2034
  syncLocalOutlineViewportHeight();
1941
2035
  syncActiveHeading();
1942
2036
  }
@@ -1971,7 +2065,7 @@
1971
2065
  refreshDocPageState();
1972
2066
 
1973
2067
  if (window.location.hash) {
1974
- scrollToHashWithOffset(window.location.hash, false);
2068
+ scrollToHash(window.location.hash, false);
1975
2069
  } else {
1976
2070
  window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
1977
2071
  activateOutlineHash(null);
@@ -1,5 +1,5 @@
1
1
  module Jekyll
2
2
  module VitePressTheme
3
- VERSION = "1.4.0".freeze
3
+ VERSION = "1.4.2".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-vitepress-theme
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-26 00:00:00.000000000 Z
11
+ date: 2026-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -116,8 +116,12 @@ files:
116
116
  - assets/images/social-icons/twitter.svg
117
117
  - assets/images/social-icons/x.svg
118
118
  - assets/images/social-icons/youtube.svg
119
+ - assets/images/theme/jekyll-test-tube.svg
120
+ - assets/images/theme/more-than-vitepress.svg
121
+ - assets/images/theme/turbo-frame-swap.svg
119
122
  - assets/images/theme/vitepress-logo-large.svg
120
123
  - assets/images/theme/vitepress-logo-mini.svg
124
+ - assets/images/theme/vitepress-logo-official.svg
121
125
  - assets/js/vitepress-theme.js
122
126
  - assets/vendor/turbo.js
123
127
  - lib/jekyll-vitepress-theme.rb