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 +4 -4
- data/lib/markdown_server/app.rb +1 -1
- data/lib/markdown_server/version.rb +1 -1
- data/views/layout.erb +68 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22318ff27259abe3a66849439a50b48103e0a7d2bea077290fd9b8d4a6329716
|
|
4
|
+
data.tar.gz: ce38b5daf5f53c9cf56ae41e1f343bd1db39a1af25a7d04f3fdd1205538ac0bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9996ded48092a440241e924b914a0ad12c054fd02b68e06debaf21cdfbfce6cd74f5f4f5e4657357aff00ae8f3824fc1eb8dc8fb62efdea9153c5ff55ac9b5e0
|
|
7
|
+
data.tar.gz: d9bca1a6f76dd9f578af6b135cfac6d0a12626a4a4720661ef2c46bfdd1c06b7228c73a1ee0f008b29f1ce32709e0ecdd5f060435044b17ee1c79c6f55a51044
|
data/lib/markdown_server/app.rb
CHANGED
|
@@ -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
|
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
|
-
|
|
1098
|
+
function showTooltip() {
|
|
1098
1099
|
sup.appendChild(tooltip);
|
|
1099
|
-
|
|
1100
|
-
|
|
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
|
})();
|