yard 0.9.40 → 0.9.41

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: f30a7254915dfc58291d8bdbf05f6e65bbb392d9c359bb0df535c5d290dbf2f8
4
- data.tar.gz: bd261832603492535a89218415f59c84c3e5c732dd8a0cc25f5a294a0b2c98a5
3
+ metadata.gz: b498d65eea07bb8fc6b7f6e43b210a66d2a7b37ff19159ca4312d254b006ff36
4
+ data.tar.gz: be2ebd8ff2e23d88afd7adebeb7520b4ece385c3faac5a564c91eb7137185034
5
5
  SHA512:
6
- metadata.gz: 132b2b6ea721780a3f36001216fa16aade784e2936d89684249f92c3ddd2180f2820e24c339551ce33405779c627b82bb085978b6f3a785b1450f17204b00d88
7
- data.tar.gz: e4410e47b0b7871241611b3328fa2e5219ba5632c4648e3d4f3d5ac66bf54986ac046bae935bc68911d905210159cc1dc70ca6aba0870056aef9ba36f70dbae3
6
+ metadata.gz: 40cb9115aafad9eb4b31dbc4f80d6bb3afe77d0935e4a52c435895a679730cccc1d0f53c2c2c54a908881e7bcf96c2585d1c638d8738d1b75834c164b3c2e825
7
+ data.tar.gz: 363ac81a03972f3e3d86f917d3db3db8beb50ae813a52f80104fcc9d57073d9717c203b0b885d34218bdc0739f20fc1f9b7ad5fd390f7672c6f0fb1e890b9a0a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # main
2
2
 
3
+ # [0.9.41] - April 14th, 2026
4
+
5
+ [0.9.41]: https://github.com/lsegal/yard/compare/v0.9.40...v0.9.41
6
+
7
+ - Add support for `rdoc-image:...` syntax in HybridMarkup (#1676)
8
+ - Add support for colon suffix code blocks in HybridMarkup (rdoc compatibility)
9
+ - Fix responsiveness and state issues with nav frame links in `yard server`
3
10
  # [0.9.40] - April 12th, 2026
4
11
 
5
12
  [0.9.40]: https://github.com/lsegal/yard/compare/v0.9.39...v0.9.40
@@ -503,6 +503,7 @@ module YARD
503
503
  while index < lines.length
504
504
  line = lines[index]
505
505
  break if blank_line?(line)
506
+ break if !buffer.empty? && colon_indented_code_block_start?(lines, index)
506
507
  break if thematic_break?(line)
507
508
  break if parse_setext_heading(lines, index)
508
509
  break if parse_heading(line)
@@ -528,6 +529,7 @@ module YARD
528
529
  text = protect_code_spans(text, placeholders)
529
530
  text = protect_autolinks(text, placeholders)
530
531
  text = protect_hard_breaks(text, placeholders)
532
+ text = protect_rdoc_images(text, placeholders)
531
533
  text = protect_inline_images(text, placeholders)
532
534
  text = protect_inline_links(text, placeholders)
533
535
  text = protect_braced_text_links(text, placeholders)
@@ -634,6 +636,14 @@ module YARD
634
636
  text.gsub(/(?:\\|\s{2,})\n/) { store_placeholder(placeholders, "<br />\n") }
635
637
  end
636
638
 
639
+ def protect_rdoc_images(text, placeholders)
640
+ text.gsub(/(^|[ \t\n])rdoc-image:([A-Za-z][A-Za-z0-9+.-]*:\/\/\S+)(?=$|[ \t\n])/) do
641
+ prefix = Regexp.last_match(1)
642
+ dest = Regexp.last_match(2)
643
+ prefix + store_placeholder(placeholders, image_html('', dest))
644
+ end
645
+ end
646
+
637
647
  def protect_inline_images(text, placeholders)
638
648
  replace_inline_constructs(text, placeholders, '!') do |label, dest, title|
639
649
  store_placeholder(placeholders, image_html(
@@ -918,6 +928,7 @@ module YARD
918
928
  def indented_code_block_start?(lines, index, previous_block_type = nil)
919
929
  return false unless indented_code_start?(lines[index])
920
930
  return true if leading_columns(lines[index]) >= 4
931
+ return true if colon_indented_code_block_start?(lines, index)
921
932
  return false if previous_block_type == :list
922
933
  return false if html_block_start?(lines[index])
923
934
  return false if parse_setext_heading(lines, index)
@@ -925,6 +936,17 @@ module YARD
925
936
  !index.zero? && blank_line?(lines[index - 1])
926
937
  end
927
938
 
939
+ def colon_indented_code_block_start?(lines, index)
940
+ return false if index.zero?
941
+ return false unless leading_columns(lines[index]) >= 2
942
+ return false if leading_columns(lines[index]) >= 4
943
+
944
+ previous_line = lines[index - 1]
945
+ return false if blank_line?(previous_line)
946
+
947
+ previous_line.rstrip.end_with?(':')
948
+ end
949
+
928
950
  def yard_indented_code_start?(lines, index)
929
951
  return false unless leading_columns(lines[index]) >= 2
930
952
  return false unless consume_columns(lines[index], 2) =~ /^!!!([\w.+-]+)[ \t]*$/
data/lib/yard/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module YARD
5
- VERSION = '0.9.40'
5
+ VERSION = '0.9.41'
6
6
  end
@@ -46,6 +46,37 @@ body {
46
46
  padding-top: 0.2em;
47
47
  box-sizing: border-box;
48
48
  }
49
+ #main_progress {
50
+ position: absolute;
51
+ top: 0;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 3px;
55
+ overflow: hidden;
56
+ opacity: 0;
57
+ z-index: 20;
58
+ pointer-events: none;
59
+ transition: opacity 0.18s ease;
60
+ }
61
+ #main_progress::before {
62
+ content: "";
63
+ display: block;
64
+ width: 35%;
65
+ height: 100%;
66
+ background: linear-gradient(90deg, #1b6ac9 0%, #4ea3ff 100%);
67
+ transform: translateX(-120%);
68
+ }
69
+ #main.loading #main_progress {
70
+ opacity: 1;
71
+ }
72
+ #main.loading #main_progress::before {
73
+ animation: yard-progress-slide 1s ease-in-out infinite;
74
+ }
75
+
76
+ @keyframes yard-progress-slide {
77
+ 0% { transform: translateX(-120%); }
78
+ 100% { transform: translateX(320%); }
79
+ }
49
80
 
50
81
  @media (max-width: 920px) {
51
82
  body { display: block; }
@@ -3,7 +3,11 @@
3
3
  navigationListenerBound: false,
4
4
  navigationChangeBound: false,
5
5
  navResizerBound: false,
6
- searchFrameGlobalsBound: false
6
+ searchFrameGlobalsBound: false,
7
+ latestNavigationId: 0,
8
+ loadingIndicatorTimer: null,
9
+ navExpanderTimer: null,
10
+ navExpanderToken: 0
7
11
  });
8
12
  var safeLocalStorage = {};
9
13
  var safeSessionStorage = {};
@@ -36,6 +40,29 @@
36
40
  element.style.display = visible ? (displayValue || "") : "none";
37
41
  }
38
42
 
43
+ function setMainLoading(loading) {
44
+ var main = query("#main");
45
+ if (!main) return;
46
+ main.classList.toggle("loading", !!loading);
47
+ main.setAttribute("aria-busy", loading ? "true" : "false");
48
+ }
49
+
50
+ function scheduleMainLoading(navigationId) {
51
+ clearTimeout(appState.loadingIndicatorTimer);
52
+ appState.loadingIndicatorTimer = setTimeout(function() {
53
+ if (navigationId === appState.latestNavigationId) {
54
+ setMainLoading(true);
55
+ }
56
+ appState.loadingIndicatorTimer = null;
57
+ }, 50);
58
+ }
59
+
60
+ function cancelMainLoading() {
61
+ clearTimeout(appState.loadingIndicatorTimer);
62
+ appState.loadingIndicatorTimer = null;
63
+ setMainLoading(false);
64
+ }
65
+
39
66
  function firstNextMatchingSibling(element, selector) {
40
67
  var current = element;
41
68
  while (current) {
@@ -453,18 +480,24 @@
453
480
  function navExpander() {
454
481
  if (typeof pathId === "undefined") return;
455
482
 
456
- var done = false;
457
- var timer = setTimeout(postMessage, 500);
483
+ var frame = document.getElementById("nav");
484
+ var token = ++appState.navExpanderToken;
458
485
 
459
486
  function postMessage() {
460
- var frame;
461
- if (done) return;
462
- clearTimeout(timer);
463
- frame = document.getElementById("nav");
464
- if (!frame || !frame.contentWindow) return;
465
- frame.contentWindow.postMessage({ action: "expand", path: pathId }, "*");
466
- done = true;
487
+ if (token !== appState.navExpanderToken) return;
488
+ expandNavPath(pathId);
467
489
  }
490
+
491
+ clearTimeout(appState.navExpanderTimer);
492
+ if (frame) frame.addEventListener("load", postMessage, { once: true });
493
+ appState.navExpanderTimer = setTimeout(postMessage, 50);
494
+ }
495
+
496
+ function expandNavPath(path) {
497
+ var frame = document.getElementById("nav");
498
+
499
+ if (path == null || !frame || !frame.contentWindow) return;
500
+ frame.contentWindow.postMessage({ action: "expand", path: path }, "*");
468
501
  }
469
502
 
470
503
  function focusHashTarget() {
@@ -523,53 +556,81 @@
523
556
  window.addEventListener(
524
557
  "message",
525
558
  async function(event) {
559
+ var navigationId;
560
+ var response;
561
+ var text;
562
+ var parser;
563
+ var doc;
564
+ var classListLink;
565
+ var contentNode;
566
+ var content;
567
+ var url;
568
+ var hash;
569
+
526
570
  if (!event.data || event.data.action !== "navigate") return;
527
571
 
528
- var response = await fetch(event.data.url);
529
- var text = await response.text();
530
- var parser = new DOMParser();
531
- var doc = parser.parseFromString(text, "text/html");
532
- var classListLink = document.getElementById("class_list_link");
533
- var content = doc.querySelector("#main").innerHTML;
534
-
535
- document.querySelector("#main").innerHTML = content;
536
- document.title = doc.head.querySelector("title").innerText;
537
-
538
- queryAll("script", document.head).forEach(function(script) {
539
- if (
540
- !script.type ||
541
- (script.type.indexOf("text/javascript") !== -1 && !script.src)
542
- ) {
543
- script.remove();
544
- }
545
- });
572
+ navigationId = ++appState.latestNavigationId;
573
+ expandNavPath(event.data.path);
574
+ scheduleMainLoading(navigationId);
575
+
576
+ try {
577
+ response = await fetch(event.data.url);
578
+ if (navigationId !== appState.latestNavigationId) return;
579
+
580
+ text = await response.text();
581
+ if (navigationId !== appState.latestNavigationId) return;
582
+
583
+ parser = new DOMParser();
584
+ doc = parser.parseFromString(text, "text/html");
585
+ classListLink = document.getElementById("class_list_link");
586
+ contentNode = doc.querySelector("#main");
587
+ if (!contentNode) return;
588
+ content = contentNode.innerHTML;
589
+
590
+ document.querySelector("#main").innerHTML = content;
591
+ document.title = doc.head.querySelector("title").innerText;
592
+
593
+ queryAll("script", document.head).forEach(function(script) {
594
+ if (
595
+ !script.type ||
596
+ (script.type.indexOf("text/javascript") !== -1 && !script.src)
597
+ ) {
598
+ script.remove();
599
+ }
600
+ });
546
601
 
547
- queryAll("script", doc.head).forEach(function(script) {
548
- if (
549
- !script.type ||
550
- (script.type.indexOf("text/javascript") !== -1 && !script.src)
551
- ) {
552
- var newScript = document.createElement("script");
553
- newScript.type = "text/javascript";
554
- newScript.textContent = script.textContent;
555
- document.head.appendChild(newScript);
556
- }
557
- });
602
+ queryAll("script", doc.head).forEach(function(script) {
603
+ if (
604
+ !script.type ||
605
+ (script.type.indexOf("text/javascript") !== -1 && !script.src)
606
+ ) {
607
+ var newScript = document.createElement("script");
608
+ newScript.type = "text/javascript";
609
+ newScript.textContent = script.textContent;
610
+ document.head.appendChild(newScript);
611
+ }
612
+ });
558
613
 
559
- window.__app();
614
+ window.__app();
615
+ if (navigationId !== appState.latestNavigationId) return;
560
616
 
561
- if (classListLink && document.getElementById("class_list_link")) {
562
- document.getElementById("class_list_link").className =
563
- classListLink.className;
564
- }
617
+ if (classListLink && document.getElementById("class_list_link")) {
618
+ document.getElementById("class_list_link").className =
619
+ classListLink.className;
620
+ }
565
621
 
566
- var url = new URL(event.data.url, "http://localhost");
567
- var hash = decodeURIComponent(url.hash || "");
568
- if (hash) {
569
- var target = document.getElementById(hash.substring(1));
570
- if (target) target.scrollIntoView();
622
+ url = new URL(event.data.url, "http://localhost");
623
+ hash = decodeURIComponent(url.hash || "");
624
+ if (hash) {
625
+ var target = document.getElementById(hash.substring(1));
626
+ if (target) target.scrollIntoView();
627
+ }
628
+ history.pushState({}, document.title, event.data.url);
629
+ } finally {
630
+ if (navigationId === appState.latestNavigationId) {
631
+ cancelMainLoading();
632
+ }
571
633
  }
572
- history.pushState({}, document.title, event.data.url);
573
634
  },
574
635
  false
575
636
  );
@@ -59,18 +59,39 @@
59
59
  if (clicked) clicked.classList.add("clicked");
60
60
  }
61
61
 
62
+ function pathForItem(item) {
63
+ if (!item || !item.id || item.id.indexOf("object_") !== 0) return null;
64
+ return item.id.substring("object_".length);
65
+ }
66
+
62
67
  function enableLinks() {
63
68
  queryAll("#full_list li").forEach(function(item) {
64
- item.addEventListener("click", function(event) {
69
+ var itemRow = item.querySelector(":scope > .item");
70
+
71
+ if (!itemRow) return;
72
+
73
+ itemRow.addEventListener("click", function(event) {
65
74
  var targetLink;
66
75
  var mouseEvent;
67
76
  var url;
68
77
 
78
+ if (
79
+ event.defaultPrevented ||
80
+ event.button !== 0 ||
81
+ event.metaKey ||
82
+ event.ctrlKey ||
83
+ event.shiftKey ||
84
+ event.altKey
85
+ ) {
86
+ return true;
87
+ }
88
+
69
89
  setClicked(item);
70
90
  event.stopPropagation();
91
+ targetLink = event.target.closest("a");
71
92
 
72
93
  if (window.origin === "null") {
73
- if (event.target.tagName === "A") return true;
94
+ if (targetLink) return true;
74
95
 
75
96
  targetLink = item.querySelector(":scope > .item .object_link a");
76
97
  if (!targetLink) return false;
@@ -94,11 +115,20 @@
94
115
  targetLink.dispatchEvent(mouseEvent);
95
116
  event.preventDefault();
96
117
  } else {
97
- url = item.querySelector(".object_link a").getAttribute("href");
118
+ if (!targetLink || !targetLink.matches(".object_link a")) {
119
+ targetLink = item.querySelector(":scope > .item .object_link a");
120
+ }
121
+ if (!targetLink) return false;
122
+
123
+ event.preventDefault();
124
+ url = targetLink.getAttribute("href");
98
125
  try {
99
126
  url = new URL(url, window.location.href).href;
100
127
  } catch (error) {}
101
- window.top.postMessage({ action: "navigate", url: url }, "*");
128
+ window.top.postMessage(
129
+ { action: "navigate", url: url, path: pathForItem(item) },
130
+ "*"
131
+ );
102
132
  }
103
133
  return false;
104
134
  });
@@ -291,7 +321,7 @@
291
321
 
292
322
  if (!target) return;
293
323
 
294
- target.classList.add("clicked");
324
+ setClicked(target);
295
325
  target.classList.remove("collapsed");
296
326
 
297
327
  var current = target.parentElement;
@@ -10,6 +10,7 @@
10
10
  </div>
11
11
 
12
12
  <div id="main" tabindex="-1">
13
+ <div id="main_progress" aria-hidden="true"></div>
13
14
  <div id="header">
14
15
  <%= erb(:breadcrumb) %>
15
16
  <%= erb(:search) %>
@@ -21,4 +22,4 @@
21
22
  <%= erb(:footer) %>
22
23
  </div>
23
24
  </body>
24
- </html>
25
+ </html>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.40
4
+ version: 0.9.41
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loren Segal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-13 00:00:00.000000000 Z
11
+ date: 2026-04-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  YARD is a documentation generation tool for the Ruby programming language.