markdownr 0.6.3 → 0.6.5
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 +47 -14
- data/views/popup_assets.erb +82 -11
- 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: af0a41eadcbe996f7165b92a56174857657a21698308b515a35a67ec81a9a3e0
|
|
4
|
+
data.tar.gz: 12f87ff3043049997f895f4dc0bde07d6d7e41c0195286b1abe29c91eada81e2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc617683848f464907a1f8d4e17986a80842e631b9e68dcd6d3eb340bb0b658d080a9849c8f1a6ec952f8ceaa23cb95fda4760e44dc02b36a6620a7b30dcbf53
|
|
7
|
+
data.tar.gz: 73bbfe99e65f7c50b4c4ffca35b4ab98d9a706f3c8367451b115e61919391ec95d987396cb75f5cbf7890822f4ec4b0456255a47a9872af5745b2dc90737e92b
|
data/lib/markdown_server/app.rb
CHANGED
|
@@ -750,7 +750,7 @@ module MarkdownServer
|
|
|
750
750
|
|
|
751
751
|
def scrip_html(html)
|
|
752
752
|
# Extract the passage content block
|
|
753
|
-
content = html[/<div\s+class="passage-text[^"]*"[^>]*>([\s\S]*?)<\/div>\s*(?:<nav
|
|
753
|
+
content = html[/<div\s+class="passage-text[^"]*"[^>]*>([\s\S]*?)<\/div>\s*(?:<nav|\z)/im, 1] || ""
|
|
754
754
|
return page_html(html) if content.empty?
|
|
755
755
|
|
|
756
756
|
# Add data-verse attributes to verse spans for popup scrolling.
|
data/views/layout.erb
CHANGED
|
@@ -883,6 +883,12 @@
|
|
|
883
883
|
margin-bottom: 0.5rem;
|
|
884
884
|
}
|
|
885
885
|
|
|
886
|
+
/* Verse range highlighting */
|
|
887
|
+
.verse-selected {
|
|
888
|
+
background: #e5eefb;
|
|
889
|
+
border-radius: 2px;
|
|
890
|
+
}
|
|
891
|
+
|
|
886
892
|
/* Mermaid diagrams */
|
|
887
893
|
.mermaid { text-align: center; margin: 1.2rem 0; overflow-x: auto; }
|
|
888
894
|
.mermaid svg { max-width: 100%; height: auto; }
|
|
@@ -2017,30 +2023,57 @@
|
|
|
2017
2023
|
historyStack = [];
|
|
2018
2024
|
}
|
|
2019
2025
|
|
|
2026
|
+
function findVerseSpans(root, verseNum) {
|
|
2027
|
+
var num = String(verseNum);
|
|
2028
|
+
// Prefer .verse spans (full verse text) with exact verse number match
|
|
2029
|
+
var all = root.querySelectorAll('.verse[data-verse]');
|
|
2030
|
+
var matches = [];
|
|
2031
|
+
for (var i = 0; i < all.length; i++) {
|
|
2032
|
+
var dv = all[i].getAttribute('data-verse');
|
|
2033
|
+
var after = dv.split(':').pop();
|
|
2034
|
+
if (after === num) matches.push(all[i]);
|
|
2035
|
+
}
|
|
2036
|
+
if (matches.length) return matches;
|
|
2037
|
+
// Fallback: bare data-verse="N" (e.g. sup elements from scrip_html)
|
|
2038
|
+
var span = root.querySelector('[data-verse="' + num + '"]');
|
|
2039
|
+
return span ? [span] : [];
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2020
2042
|
function applyPopupAnchor(hash) {
|
|
2021
2043
|
if (!hash || !popup) return;
|
|
2022
2044
|
var id = hash.replace(/^#/, '');
|
|
2023
2045
|
try {
|
|
2024
|
-
var
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2046
|
+
var body = popup.querySelector('.link-ctx-popup-body');
|
|
2047
|
+
if (!body) return;
|
|
2048
|
+
|
|
2049
|
+
// Verse range: #vN or #vN-M
|
|
2050
|
+
var vm = id.match(/^v(\d+)(?:-(\d+))?$/);
|
|
2051
|
+
if (vm) {
|
|
2052
|
+
var start = parseInt(vm[1], 10);
|
|
2053
|
+
var end = vm[2] ? parseInt(vm[2], 10) : start;
|
|
2054
|
+
var first = null;
|
|
2055
|
+
for (var v = start; v <= end; v++) {
|
|
2056
|
+
var spans = findVerseSpans(body, v);
|
|
2057
|
+
for (var i = 0; i < spans.length; i++) {
|
|
2058
|
+
spans[i].classList.add('verse-selected');
|
|
2059
|
+
if (!first) first = spans[i];
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
if (first) {
|
|
2063
|
+
var bodyTop = body.getBoundingClientRect().top;
|
|
2064
|
+
var targetTop = first.getBoundingClientRect().top;
|
|
2065
|
+
body.scrollTop += targetTop - bodyTop - 8;
|
|
2033
2066
|
}
|
|
2067
|
+
return;
|
|
2034
2068
|
}
|
|
2069
|
+
|
|
2070
|
+
// Standard anchor by ID
|
|
2071
|
+
var eid = id.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
2072
|
+
var target = popup.querySelector('[id="' + eid + '"]');
|
|
2035
2073
|
if (!target) return;
|
|
2036
|
-
// Scroll the body container (which has overflow-y:auto) to the target,
|
|
2037
|
-
// accounting for the sticky header so the heading lands just below it
|
|
2038
|
-
var body = popup.querySelector('.link-ctx-popup-body');
|
|
2039
|
-
if (!body) return;
|
|
2040
2074
|
var bodyTop = body.getBoundingClientRect().top;
|
|
2041
2075
|
var targetTop = target.getBoundingClientRect().top;
|
|
2042
2076
|
body.scrollTop += targetTop - bodyTop - 8;
|
|
2043
|
-
// Append section heading text to the popup title
|
|
2044
2077
|
if (/^H[1-6]$/.test(target.tagName)) {
|
|
2045
2078
|
var titleEl = popup.querySelector('.link-ctx-popup-title span');
|
|
2046
2079
|
if (titleEl) titleEl.textContent = titleEl.textContent + ' \u203a ' + target.textContent;
|
data/views/popup_assets.erb
CHANGED
|
@@ -142,6 +142,12 @@
|
|
|
142
142
|
margin-bottom: 0.5rem;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
/* Verse range highlighting */
|
|
146
|
+
.verse-selected {
|
|
147
|
+
background: #e5eefb;
|
|
148
|
+
border-radius: 2px;
|
|
149
|
+
}
|
|
150
|
+
|
|
145
151
|
/* Shared popup content styles */
|
|
146
152
|
.link-ctx-popup-body {
|
|
147
153
|
font-family: Georgia, "Times New Roman", serif;
|
|
@@ -589,24 +595,54 @@
|
|
|
589
595
|
historyStack = [];
|
|
590
596
|
}
|
|
591
597
|
|
|
598
|
+
function findVerseSpans(root, verseNum) {
|
|
599
|
+
var num = String(verseNum);
|
|
600
|
+
// Prefer .verse spans (full verse text) with exact verse number match
|
|
601
|
+
var all = root.querySelectorAll('.verse[data-verse]');
|
|
602
|
+
var matches = [];
|
|
603
|
+
for (var i = 0; i < all.length; i++) {
|
|
604
|
+
var dv = all[i].getAttribute('data-verse');
|
|
605
|
+
var after = dv.split(':').pop();
|
|
606
|
+
if (after === num) matches.push(all[i]);
|
|
607
|
+
}
|
|
608
|
+
if (matches.length) return matches;
|
|
609
|
+
// Fallback: bare data-verse="N" (e.g. sup elements from scrip_html)
|
|
610
|
+
var span = root.querySelector('[data-verse="' + num + '"]');
|
|
611
|
+
return span ? [span] : [];
|
|
612
|
+
}
|
|
613
|
+
|
|
592
614
|
function applyPopupAnchor(hash) {
|
|
593
615
|
if (!hash || !popup) return;
|
|
594
616
|
var id = hash.replace(/^#/, '');
|
|
595
617
|
try {
|
|
596
|
-
var
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
618
|
+
var body = popup.querySelector('.link-ctx-popup-body');
|
|
619
|
+
if (!body) return;
|
|
620
|
+
|
|
621
|
+
// Verse range: #vN or #vN-M
|
|
622
|
+
var vm = id.match(/^v(\d+)(?:-(\d+))?$/);
|
|
623
|
+
if (vm) {
|
|
624
|
+
var start = parseInt(vm[1], 10);
|
|
625
|
+
var end = vm[2] ? parseInt(vm[2], 10) : start;
|
|
626
|
+
var first = null;
|
|
627
|
+
for (var v = start; v <= end; v++) {
|
|
628
|
+
var spans = findVerseSpans(body, v);
|
|
629
|
+
for (var i = 0; i < spans.length; i++) {
|
|
630
|
+
spans[i].classList.add('verse-selected');
|
|
631
|
+
if (!first) first = spans[i];
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (first) {
|
|
635
|
+
var bodyTop = body.getBoundingClientRect().top;
|
|
636
|
+
var targetTop = first.getBoundingClientRect().top;
|
|
637
|
+
body.scrollTop += targetTop - bodyTop - 8;
|
|
605
638
|
}
|
|
639
|
+
return;
|
|
606
640
|
}
|
|
641
|
+
|
|
642
|
+
// Standard anchor by ID
|
|
643
|
+
var eid = id.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
644
|
+
var target = popup.querySelector('[id="' + eid + '"]');
|
|
607
645
|
if (!target) return;
|
|
608
|
-
var body = popup.querySelector('.link-ctx-popup-body');
|
|
609
|
-
if (!body) return;
|
|
610
646
|
var bodyTop = body.getBoundingClientRect().top;
|
|
611
647
|
var targetTop = target.getBoundingClientRect().top;
|
|
612
648
|
body.scrollTop += targetTop - bodyTop - 8;
|
|
@@ -847,4 +883,39 @@
|
|
|
847
883
|
})();
|
|
848
884
|
|
|
849
885
|
})();
|
|
886
|
+
|
|
887
|
+
// Full-page verse highlighting from URL hash (#vN or #vN-M)
|
|
888
|
+
(function() {
|
|
889
|
+
var m = window.location.hash.match(/^#v(\d+)(?:-(\d+))?$/);
|
|
890
|
+
if (!m) return;
|
|
891
|
+
var start = parseInt(m[1], 10);
|
|
892
|
+
var end = m[2] ? parseInt(m[2], 10) : start;
|
|
893
|
+
var bookMeta = document.querySelector('meta[name="book"]');
|
|
894
|
+
var chMeta = document.querySelector('meta[name="chapter"]');
|
|
895
|
+
var book = bookMeta && bookMeta.content;
|
|
896
|
+
var ch = chMeta && chMeta.content;
|
|
897
|
+
var first = null;
|
|
898
|
+
for (var v = start; v <= end; v++) {
|
|
899
|
+
var spans;
|
|
900
|
+
if (book && ch) {
|
|
901
|
+
spans = document.querySelectorAll('.verse[data-verse="' + book + ' ' + ch + ':' + v + '"]');
|
|
902
|
+
} else {
|
|
903
|
+
// No meta tags — filter all .verse spans by exact verse number
|
|
904
|
+
var all = document.querySelectorAll('.verse[data-verse]');
|
|
905
|
+
spans = [];
|
|
906
|
+
for (var i = 0; i < all.length; i++) {
|
|
907
|
+
if (all[i].getAttribute('data-verse').split(':').pop() === String(v)) spans.push(all[i]);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
for (var j = 0; j < spans.length; j++) {
|
|
911
|
+
spans[j].classList.add('verse-selected');
|
|
912
|
+
if (!first) first = spans[j];
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
if (!first) return;
|
|
916
|
+
var top = first.getBoundingClientRect().top + window.pageYOffset;
|
|
917
|
+
var toolbar = document.querySelector('.toolbar');
|
|
918
|
+
if (toolbar) top -= toolbar.offsetHeight + 4;
|
|
919
|
+
window.scrollTo({ top: top, behavior: 'instant' });
|
|
920
|
+
})();
|
|
850
921
|
</script>
|