markdownr 0.3.3 → 0.3.4

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: 3218025cb46f3cb61158188eeea5957b3d797abb2c63970a9fa2c873b39da870
4
- data.tar.gz: 36df70282be17b496d6e6706e568fc5c585adba12bba091cf534176ea56182a2
3
+ metadata.gz: 22318ff27259abe3a66849439a50b48103e0a7d2bea077290fd9b8d4a6329716
4
+ data.tar.gz: ce38b5daf5f53c9cf56ae41e1f343bd1db39a1af25a7d04f3fdd1205538ac0bd
5
5
  SHA512:
6
- metadata.gz: 90edee3edf4003ebcf4605e0488db495e8d460964595944aa478e8be5a72d6b9c7dc0e276b855f0148c4113a2cf9360dc8ab6ea01f823b1061b3718bab76a67c
7
- data.tar.gz: ad890bdaa976d1eb179fd9945656b27238103a93974cbf232950567ce08eaa87da2100e910bd33d9cbda0db8e67252275937fe8ff780f4abd0e34f2569e9cb15
6
+ metadata.gz: 9996ded48092a440241e924b914a0ad12c054fd02b68e06debaf21cdfbfce6cd74f5f4f5e4657357aff00ae8f3824fc1eb8dc8fb62efdea9153c5ff55ac9b5e0
7
+ data.tar.gz: d9bca1a6f76dd9f578af6b135cfac6d0a12626a4a4720661ef2c46bfdd1c06b7228c73a1ee0f008b29f1ce32709e0ecdd5f060435044b17ee1c79c6f55a51044
@@ -219,7 +219,7 @@ module MarkdownServer
219
219
  def extract_toc(html)
220
220
  headings = []
221
221
  html.scan(/<h([1-6])\s[^>]*id="([^"]*)"[^>]*>(.*?)<\/h\1>/mi) do |level, id, text|
222
- clean_text = text.gsub(/<[^>]+>/, "").strip
222
+ clean_text = text.gsub(/<sup[^>]*id="fnref:[^"]*"[^>]*>.*?<\/sup>/i, "").gsub(/<[^>]+>/, "").strip
223
223
  headings << { level: level.to_i, id: id, text: clean_text }
224
224
  end
225
225
  headings
@@ -1,3 +1,3 @@
1
1
  module MarkdownServer
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.4"
3
3
  end
data/views/layout.erb CHANGED
@@ -731,15 +731,15 @@
731
731
  max-width: 350px;
732
732
  width: max-content;
733
733
  z-index: 150;
734
- pointer-events: none;
735
734
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
736
735
  margin-bottom: 6px;
737
736
  }
737
+ .footnote-tooltip { cursor: pointer; }
738
738
  .footnote-tooltip::after {
739
739
  content: '';
740
740
  position: absolute;
741
741
  top: 100%;
742
- left: 50%;
742
+ left: calc(50% + var(--arrow-offset, 0px));
743
743
  transform: translateX(-50%);
744
744
  border: 5px solid transparent;
745
745
  border-top-color: #2d2d2d;
@@ -1093,12 +1093,75 @@
1093
1093
  var tooltip = document.createElement('span');
1094
1094
  tooltip.className = 'footnote-tooltip';
1095
1095
  tooltip.innerHTML = html;
1096
+ var fnHref = link.getAttribute('href');
1096
1097
 
1097
- sup.addEventListener('mouseenter', function() {
1098
+ function showTooltip() {
1098
1099
  sup.appendChild(tooltip);
1099
- });
1100
- sup.addEventListener('mouseleave', function() {
1100
+ // Reset any previous adjustment
1101
+ tooltip.style.left = '50%';
1102
+ tooltip.style.transform = 'translateX(-50%)';
1103
+ tooltip.style.removeProperty('--arrow-offset');
1104
+ // Clamp tooltip to viewport.
1105
+ // document.documentElement.clientWidth is more reliable than window.innerWidth
1106
+ // on Android browsers (e.g. EinkBro) which may return a pre-scaled layout
1107
+ // viewport width for window.innerWidth rather than the CSS viewport width.
1108
+ var viewportWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
1109
+ var rect = tooltip.getBoundingClientRect();
1110
+ var shift = 0;
1111
+ if (rect.left < 8) {
1112
+ shift = 8 - rect.left;
1113
+ } else if (rect.right > viewportWidth - 8) {
1114
+ shift = (viewportWidth - 8) - rect.right;
1115
+ }
1116
+ if (shift !== 0) {
1117
+ tooltip.style.transform = 'translateX(calc(-50% + ' + shift + 'px))';
1118
+ tooltip.style.setProperty('--arrow-offset', (-shift) + 'px');
1119
+ }
1120
+ }
1121
+
1122
+ function hideTooltip() {
1101
1123
  if (tooltip.parentNode === sup) sup.removeChild(tooltip);
1124
+ }
1125
+
1126
+ // Hover devices: show/hide on mouseenter/mouseleave
1127
+ sup.addEventListener('mouseenter', showTooltip);
1128
+ sup.addEventListener('mouseleave', hideTooltip);
1129
+
1130
+ // Touch: first tap shows tooltip, second tap navigates
1131
+ // Using touchend instead of click so no hover media query check is needed —
1132
+ // touchend only fires on real touch, regardless of what (hover:none) reports.
1133
+ var linkTouchMoved = false;
1134
+ link.addEventListener('touchstart', function() { linkTouchMoved = false; }, { passive: true });
1135
+ link.addEventListener('touchmove', function() { linkTouchMoved = true; }, { passive: true });
1136
+ link.addEventListener('touchend', function(e) {
1137
+ if (linkTouchMoved) return; // scroll, not a tap
1138
+ if (tooltip.parentNode === sup) {
1139
+ // Tooltip already showing — let the link navigate
1140
+ return;
1141
+ }
1142
+ e.preventDefault();
1143
+ // Dismiss any other open tooltip
1144
+ document.querySelectorAll('.footnote-tooltip').forEach(function(t) {
1145
+ if (t.parentNode) t.parentNode.removeChild(t);
1146
+ });
1147
+ showTooltip();
1148
+ });
1149
+
1150
+ var tooltipTouchMoved = false;
1151
+ tooltip.addEventListener('touchstart', function() { tooltipTouchMoved = false; }, { passive: true });
1152
+ tooltip.addEventListener('touchmove', function() { tooltipTouchMoved = true; }, { passive: true });
1153
+ tooltip.addEventListener('touchend', function(e) {
1154
+ if (tooltipTouchMoved) return;
1155
+ e.stopPropagation();
1156
+ hideTooltip();
1157
+ window.location.hash = fnHref;
1158
+ });
1159
+
1160
+ // Dismiss tooltip when tapping elsewhere
1161
+ document.addEventListener('click', function(e) {
1162
+ if (tooltip.parentNode === sup && !sup.contains(e.target)) {
1163
+ hideTooltip();
1164
+ }
1102
1165
  });
1103
1166
  });
1104
1167
  })();
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdownr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Dunn