markdownr 0.5.5 → 0.5.7
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 +147 -8
- data/lib/markdown_server/version.rb +1 -1
- data/views/layout.erb +60 -19
- 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: e9a74b1e181f0fd5361c73e64a6e00659451cf075e1e41ec4f45c0cee9167e9d
|
|
4
|
+
data.tar.gz: 44b5d07121159a9efadac6ee85bd4528d2490ec419b0752dbe15e1336e94eea2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 866416e07423170e5ec3c84e60da99682bfabb07b09cf1eb74f29e7e74f509c9982ec292641721ec0d054f5361bd6012fc00a34755ab46987c4462e63569926e
|
|
7
|
+
data.tar.gz: 1a18c15a57094d2a5d72670d760d82d1eeca80ab1c694cc550a7ff69e352c6dd9e889840e515b0a40c9e59a9b48e9aa85744d6983f37f33c572b90cdd39c28a8
|
data/lib/markdown_server/app.rb
CHANGED
|
@@ -137,10 +137,12 @@ module MarkdownServer
|
|
|
137
137
|
label = display || heading_text
|
|
138
138
|
%(<a class="wiki-link" href="##{h(anchor)}">#{h(label)}</a>)
|
|
139
139
|
else
|
|
140
|
-
|
|
140
|
+
file_part, anchor_part = target.split("#", 2)
|
|
141
|
+
anchor_suffix = anchor_part ? "##{anchor_part.downcase.gsub(/\s+/, '-').gsub(/[^\w-]/, '')}" : ""
|
|
142
|
+
resolved = resolve_wiki_link(file_part)
|
|
141
143
|
label = display || target
|
|
142
144
|
if resolved
|
|
143
|
-
%(<a class="wiki-link" href="/browse/#{encode_path_component(resolved).gsub('%2F', '/')}">#{h(label)}</a>)
|
|
145
|
+
%(<a class="wiki-link" href="/browse/#{encode_path_component(resolved).gsub('%2F', '/')}#{anchor_suffix}">#{h(label)}</a>)
|
|
144
146
|
else
|
|
145
147
|
%(<span class="wiki-link broken">#{h(label)}</span>)
|
|
146
148
|
end
|
|
@@ -227,6 +229,7 @@ module MarkdownServer
|
|
|
227
229
|
str.scan(/\[\[([^\]]+)\]\]/) do |match|
|
|
228
230
|
raw = match[0]
|
|
229
231
|
m_start = $~.begin(0)
|
|
232
|
+
m_end = $~.end(0)
|
|
230
233
|
result += h(str[last_end...m_start])
|
|
231
234
|
target, display = raw.include?("|") ? raw.split("|", 2) : [raw, nil]
|
|
232
235
|
label = display || target
|
|
@@ -234,14 +237,16 @@ module MarkdownServer
|
|
|
234
237
|
anchor = target[1..].downcase.gsub(/\s+/, "-").gsub(/[^\w-]/, "")
|
|
235
238
|
result += %(<a class="wiki-link" href="##{h(anchor)}">#{h(label)}</a>)
|
|
236
239
|
else
|
|
237
|
-
|
|
240
|
+
file_part, anchor_part = target.split("#", 2)
|
|
241
|
+
anchor_suffix = anchor_part ? "##{anchor_part.downcase.gsub(/\s+/, '-').gsub(/[^\w-]/, '')}" : ""
|
|
242
|
+
resolved = resolve_wiki_link(file_part)
|
|
238
243
|
if resolved
|
|
239
|
-
result += %(<a class="wiki-link" href="/browse/#{encode_path_component(resolved).gsub('%2F', '/')}">#{h(label)}</a>)
|
|
244
|
+
result += %(<a class="wiki-link" href="/browse/#{encode_path_component(resolved).gsub('%2F', '/')}#{anchor_suffix}">#{h(label)}</a>)
|
|
240
245
|
else
|
|
241
246
|
result += %(<span class="wiki-link broken">#{h(label)}</span>)
|
|
242
247
|
end
|
|
243
248
|
end
|
|
244
|
-
last_end =
|
|
249
|
+
last_end = m_end
|
|
245
250
|
end
|
|
246
251
|
result += h(str[last_end..])
|
|
247
252
|
result
|
|
@@ -252,7 +257,7 @@ module MarkdownServer
|
|
|
252
257
|
when Array
|
|
253
258
|
value.map { |v|
|
|
254
259
|
str = v.to_s
|
|
255
|
-
if str
|
|
260
|
+
if str.include?("[[")
|
|
256
261
|
render_inline_wiki_links(str)
|
|
257
262
|
else
|
|
258
263
|
%(<span class="tag">#{h(str)}</span>)
|
|
@@ -575,6 +580,133 @@ module MarkdownServer
|
|
|
575
580
|
out.length > 10_000 ? out[0, 10_000] : out
|
|
576
581
|
end
|
|
577
582
|
|
|
583
|
+
def blueletterbible_html(html, url)
|
|
584
|
+
base = "https://www.blueletterbible.org"
|
|
585
|
+
|
|
586
|
+
# ── Word ──────────────────────────────────────────────────────────────
|
|
587
|
+
word = html[/<h6[^>]+class="lexTitle(?:Gk|Hb)"[^>]*>(.*?)<\/h6>/im, 1]
|
|
588
|
+
&.gsub(/<[^>]+>/, "")&.strip || ""
|
|
589
|
+
|
|
590
|
+
# ── Transliteration ───────────────────────────────────────────────────
|
|
591
|
+
transliteration = html[/<div[^>]+id="lexTrans".*?<em>(.*?)<\/em>/im, 1]&.strip || ""
|
|
592
|
+
|
|
593
|
+
# ── Pronunciation + audio ─────────────────────────────────────────────
|
|
594
|
+
pronunciation = html[/class="[^"]*lexicon-pronunc[^"]*"[^>]*>\s*([^\n<]{1,50})/i, 1]&.strip || ""
|
|
595
|
+
data_pronunc = html[/data-pronunc="([a-fA-F0-9]{20,})"/i, 1] || ""
|
|
596
|
+
audio_btn = if data_pronunc.length > 10
|
|
597
|
+
au = "#{base}/lang/lexicon/lexPronouncePlayer.cfm?skin=#{data_pronunc}"
|
|
598
|
+
%(<button onclick="var a=this._a||(this._a=new Audio('#{h(au)}'));a.currentTime=0;a.play();" ) +
|
|
599
|
+
%(style="background:none;border:none;cursor:pointer;padding:0 0 0 4px;font-size:1.1em;vertical-align:middle;" title="Play pronunciation">🔊</button>)
|
|
600
|
+
else
|
|
601
|
+
""
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
# ── Part of speech ────────────────────────────────────────────────────
|
|
605
|
+
pos = html[/<div[^>]+id="lexPart".*?small-text-right"[^>]*>(.*?)<\/div>/im, 1]
|
|
606
|
+
&.gsub(/<[^>]+>/, "")&.strip || ""
|
|
607
|
+
|
|
608
|
+
# ── Info table ────────────────────────────────────────────────────────
|
|
609
|
+
info_rows = [
|
|
610
|
+
["Word", h(word)],
|
|
611
|
+
["Transliteration", "<em>#{h(transliteration)}</em>"],
|
|
612
|
+
["Pronunciation", "#{h(pronunciation)}#{audio_btn}"],
|
|
613
|
+
["Part of Speech", h(pos)],
|
|
614
|
+
]
|
|
615
|
+
info_html = %(<table class="blb-table">) +
|
|
616
|
+
info_rows.map { |label, v|
|
|
617
|
+
%(<tr><th class="blb-th">#{h(label)}</th><td>#{v}</td></tr>)
|
|
618
|
+
}.join + "</table>"
|
|
619
|
+
|
|
620
|
+
# ── Inflections ───────────────────────────────────────────────────────
|
|
621
|
+
infl_html = ""
|
|
622
|
+
if (m = html.match(/<div\s[^>]*id="greek-tr-inflections"[^>]*>/im))
|
|
623
|
+
after_infl = html[m.end(0)..]
|
|
624
|
+
stop = after_infl.index(/<div\s[^>]*id="greek-(?:mgnt|lxx)-inflections"/i) || after_infl.length
|
|
625
|
+
infl_section = after_infl[0...stop]
|
|
626
|
+
inflections = []
|
|
627
|
+
infl_section.scan(/<div\s[^>]*class="greekInflection"[^>]*>(.*?)<\/div>\s*<\/div>/im) do |mv|
|
|
628
|
+
chunk = mv[0]
|
|
629
|
+
href = chunk[/href="([^"]+)"/i, 1]
|
|
630
|
+
gk = chunk[/<span[^>]+class="Gk"[^>]*>(.*?)<\/span>/im, 1]&.gsub(/<[^>]+>/, "")&.strip || ""
|
|
631
|
+
freq = chunk[/—\s*(\d+)x<\/a>/i, 1]&.to_i || 0
|
|
632
|
+
next if gk.empty? || freq.zero?
|
|
633
|
+
inflections << { word: gk, freq: freq,
|
|
634
|
+
href: href ? base + href.gsub("&", "&") : nil }
|
|
635
|
+
end
|
|
636
|
+
inflections.sort_by! { |i| -i[:freq] }
|
|
637
|
+
if inflections.any?
|
|
638
|
+
rows = inflections.map { |i|
|
|
639
|
+
link = i[:href] ? %(<a href="#{h(i[:href])}" target="_blank" rel="noopener">#{h(i[:word])}</a>) : h(i[:word])
|
|
640
|
+
%(<tr><td>#{link}</td><td class="blb-right">#{i[:freq]}x</td></tr>)
|
|
641
|
+
}.join
|
|
642
|
+
infl_html = %(<h4 class="blb-heading">Inflections</h4>) +
|
|
643
|
+
%(<table class="blb-table"><thead><tr><th class="blb-th">Form</th>) +
|
|
644
|
+
%(<th class="blb-th blb-right">Count</th></tr></thead><tbody>#{rows}</tbody></table>)
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
# ── Biblical Usage ────────────────────────────────────────────────────
|
|
649
|
+
usage_html = ""
|
|
650
|
+
if (um = html.match(/<div[^>]+id="outlineBiblical"[^>]*>/im))
|
|
651
|
+
after_usage = html[um.end(0)..]
|
|
652
|
+
if (inner = after_usage.match(/\A\s*<div>([\s\S]*?)<\/div>\s*<\/div>/im))
|
|
653
|
+
cleaned = inner[1]
|
|
654
|
+
.gsub(/<(\/?)(\w+)[^>]*>/) { "<#{$1}#{$2.downcase}>" }
|
|
655
|
+
.gsub(/[ \t]+/, " ")
|
|
656
|
+
.strip
|
|
657
|
+
usage_html = %(<h4 class="blb-heading">Biblical Usage</h4><div class="blb-usage">#{cleaned}</div>)
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
# ── Concordance ───────────────────────────────────────────────────────
|
|
662
|
+
conc_html = ""
|
|
663
|
+
trans_name = html[/id="bibleTable"[^>]+data-translation="([^"]+)"/i, 1] || ""
|
|
664
|
+
verses = []
|
|
665
|
+
html.split(/<div\s[^>]*id="bVerse_\d+"[^>]*>/).drop(1).each do |chunk|
|
|
666
|
+
cite_href = chunk[/tablet-order-2[^>]*>[\s\S]{0,400}?href="([^"]+)"/im, 1] || ""
|
|
667
|
+
cite = chunk[/tablet-order-2[^>]*>[\s\S]{0,400}?<a[^>]*>(.*?)<\/a>/im, 1]
|
|
668
|
+
&.gsub(/<[^>]+>/, "")&.strip || ""
|
|
669
|
+
|
|
670
|
+
# Process verse HTML: highlight the matched word, strip all Strong's refs
|
|
671
|
+
raw_html = chunk[/class="EngBibleText[^"]*"[^>]*>([\s\S]*?)<\/div>/im, 1] || ""
|
|
672
|
+
raw_html.gsub!(/<img[^>]*>/, "")
|
|
673
|
+
raw_html.gsub!(/<a[^>]*class="hide-for-tablet"[^>]*>[\s\S]*?<\/a>/im, "")
|
|
674
|
+
raw_html.gsub!(/<span[^>]*class="hide-for-tablet"[^>]*>[\s\S]*?<\/span>/im, "")
|
|
675
|
+
verse_html = raw_html.gsub(/<span\s[^>]*class="word-phrase"[^>]*>([\s\S]*?)<\/span>/im) do
|
|
676
|
+
inner = $1
|
|
677
|
+
word = inner.sub(/<sup[\s\S]*/im, "").gsub(/<[^>]+>/, "")
|
|
678
|
+
.gsub(/ /i, " ").strip
|
|
679
|
+
inner.match?(/<sup[^>]*class="[^"]*strongs criteria[^"]*"/i) ?
|
|
680
|
+
%(<span class="blb-match">#{h(word)}</span>) : h(word)
|
|
681
|
+
end
|
|
682
|
+
verse_html.gsub!(/<sup[^>]*>[\s\S]*?<\/sup>/im, "")
|
|
683
|
+
verse_html.gsub!(/<[^>]+>/, "")
|
|
684
|
+
verse_html.gsub!(/ /i, " ")
|
|
685
|
+
verse_html.gsub!(/&#(\d+);/) { [$1.to_i].pack("U") rescue " " }
|
|
686
|
+
verse_html.gsub!(/&#x([\da-f]+);/i) { [$1.to_i(16)].pack("U") rescue " " }
|
|
687
|
+
verse_html.gsub!(/&/, "&").gsub!(/</, "<").gsub!(/>/, ">")
|
|
688
|
+
verse_html.gsub!(/\s+/, " ")
|
|
689
|
+
verse_html.strip!
|
|
690
|
+
# Strip the mobile citation prefix ("Mat 5:17 - ") left by hide-for-tablet removal
|
|
691
|
+
verse_html.sub!(/\A#{Regexp.escape(cite)}\s*-\s*/i, "")
|
|
692
|
+
|
|
693
|
+
next if cite.empty? || verse_html.empty?
|
|
694
|
+
full_href = cite_href.empty? ? nil : (cite_href.start_with?("http") ? cite_href : base + cite_href)
|
|
695
|
+
verses << { cite: cite, verse_html: verse_html, href: full_href }
|
|
696
|
+
end
|
|
697
|
+
if verses.any?
|
|
698
|
+
heading = trans_name.empty? ? "Concordance" : "Concordance (#{h(trans_name)})"
|
|
699
|
+
rows = verses.map { |v|
|
|
700
|
+
link = v[:href] ? %(<a href="#{h(v[:href])}" target="_blank" rel="noopener">#{h(v[:cite])}</a>) : h(v[:cite])
|
|
701
|
+
%(<tr><td class="blb-nowrap">#{link}</td><td>#{v[:verse_html]}</td></tr>)
|
|
702
|
+
}.join
|
|
703
|
+
conc_html = %(<h4 class="blb-heading">#{heading}</h4>) +
|
|
704
|
+
%(<table class="blb-table"><tbody>#{rows}</tbody></table>)
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
info_html + infl_html + usage_html + conc_html
|
|
708
|
+
end
|
|
709
|
+
|
|
578
710
|
def compile_regexes(query)
|
|
579
711
|
words = query.split(/\s+/).reject(&:empty?)
|
|
580
712
|
return nil if words.empty?
|
|
@@ -675,8 +807,15 @@ module MarkdownServer
|
|
|
675
807
|
html = fetch_external_page(url)
|
|
676
808
|
halt 502, '{"error":"fetch failed"}' unless html
|
|
677
809
|
|
|
678
|
-
|
|
679
|
-
|
|
810
|
+
if url.match?(/blueletterbible\.org\/lexicon\//i)
|
|
811
|
+
raw = page_title(html)
|
|
812
|
+
title = raw.match(/^([GH]\d+ - \w+)/i)&.[](1)&.sub(" - ", " – ") ||
|
|
813
|
+
raw.sub(/ [-–] .*/, "").strip
|
|
814
|
+
JSON.dump({ title: title, html: blueletterbible_html(html, url) })
|
|
815
|
+
else
|
|
816
|
+
title = page_title(html).sub(/ [-–] .*/, "").strip
|
|
817
|
+
JSON.dump({ title: title, html: page_html(html, url) })
|
|
818
|
+
end
|
|
680
819
|
end
|
|
681
820
|
|
|
682
821
|
get "/search/?*" do
|
data/views/layout.erb
CHANGED
|
@@ -909,6 +909,22 @@
|
|
|
909
909
|
.link-preview-popup th, .link-preview-popup td { border: 1px solid #ddd; padding: 0.3rem 0.5rem; }
|
|
910
910
|
.link-ctx-popup-body th, .link-preview-popup th { background: #f5f0e4; }
|
|
911
911
|
|
|
912
|
+
/* Blue Letter Bible popup tables */
|
|
913
|
+
.blb-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; margin-bottom: 0.6rem; }
|
|
914
|
+
.blb-table th, .blb-table td { padding: 3px 7px; border: 1px solid #ddd; }
|
|
915
|
+
.blb-th { text-align: left; font-weight: normal; background: #f5f0e4; color: #555; width: 38%; }
|
|
916
|
+
.blb-right { text-align: right; }
|
|
917
|
+
.blb-nowrap { white-space: nowrap; vertical-align: top; }
|
|
918
|
+
.blb-match { color: #b33; font-weight: 600; }
|
|
919
|
+
.blb-heading { font-size: 0.82rem; font-weight: 600; margin: 0.7rem 0 0.25rem; color: #555; text-transform: uppercase; letter-spacing: 0.04em; }
|
|
920
|
+
.blb-usage { font-size: 0.85rem; }
|
|
921
|
+
.blb-usage ol { margin: 0.1rem 0 0.1rem 1.3rem; padding: 0; list-style-type: decimal; }
|
|
922
|
+
.blb-usage ol ol { list-style-type: lower-alpha; }
|
|
923
|
+
.blb-usage ol ol ol { list-style-type: lower-roman; }
|
|
924
|
+
.blb-usage ol ol ol ol { list-style-type: lower-alpha; }
|
|
925
|
+
.blb-usage li { margin-bottom: 0.15rem; }
|
|
926
|
+
.blb-usage p { margin: 0; }
|
|
927
|
+
|
|
912
928
|
/* Footnote tooltips */
|
|
913
929
|
.footnote-tooltip {
|
|
914
930
|
position: absolute;
|
|
@@ -1704,6 +1720,26 @@
|
|
|
1704
1720
|
historyStack = [];
|
|
1705
1721
|
}
|
|
1706
1722
|
|
|
1723
|
+
function applyPopupAnchor(hash) {
|
|
1724
|
+
if (!hash || !popup) return;
|
|
1725
|
+
var id = hash.replace(/^#/, '');
|
|
1726
|
+
try {
|
|
1727
|
+
var target = popup.querySelector('[id="' + id.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"]');
|
|
1728
|
+
if (!target) return;
|
|
1729
|
+
// Scroll the popup container (which has overflow-y:auto) to the target,
|
|
1730
|
+
// accounting for the sticky header so the heading lands just below it
|
|
1731
|
+
var header = popup.querySelector('.link-ctx-popup-header');
|
|
1732
|
+
var headerHeight = header ? header.offsetHeight : 0;
|
|
1733
|
+
var targetTop = target.getBoundingClientRect().top;
|
|
1734
|
+
var popupTop = popup.getBoundingClientRect().top;
|
|
1735
|
+
popup.scrollTop += targetTop - popupTop - headerHeight - 8;
|
|
1736
|
+
// Append section heading text to the popup title
|
|
1737
|
+
if (/^H[1-6]$/.test(target.tagName)) {
|
|
1738
|
+
var titleEl = popup.querySelector('.link-ctx-popup-title span');
|
|
1739
|
+
if (titleEl) titleEl.textContent = titleEl.textContent + ' \u203a ' + target.textContent;
|
|
1740
|
+
}
|
|
1741
|
+
} catch(e) {}
|
|
1742
|
+
}
|
|
1707
1743
|
|
|
1708
1744
|
function handleLink(anchor, x, y, chained) {
|
|
1709
1745
|
if (!chained) historyStack = [];
|
|
@@ -1712,12 +1748,14 @@
|
|
|
1712
1748
|
var label = anchor.textContent.trim() || href;
|
|
1713
1749
|
// For chained popup navigation keep the current link rect; for new popups measure the anchor
|
|
1714
1750
|
var linkRect = chained ? currentPopupPos.linkRect : anchor.getBoundingClientRect();
|
|
1751
|
+
var linkHash = (function() { try { return new URL(href, location.href).hash; } catch(e) { return ''; } })();
|
|
1715
1752
|
|
|
1716
1753
|
if (isLocalMd(href)) {
|
|
1717
1754
|
var path = previewPath(href);
|
|
1718
1755
|
var cached = cache[path];
|
|
1719
1756
|
if (cached && typeof cached === 'object') {
|
|
1720
1757
|
showPopup(x, y, cached.title || label, cached.html, href, linkRect);
|
|
1758
|
+
applyPopupAnchor(linkHash);
|
|
1721
1759
|
} else if (cached === false) {
|
|
1722
1760
|
showPopup(x, y, label,
|
|
1723
1761
|
'<div class="link-ctx-popup-url">' + escHtml(href) + '</div>' +
|
|
@@ -1733,6 +1771,7 @@
|
|
|
1733
1771
|
var bodyHtml = data.html + (data.frontmatter_html || '');
|
|
1734
1772
|
cache[path] = { title: data.title, html: bodyHtml };
|
|
1735
1773
|
updatePopup(bodyHtml, data.title || label);
|
|
1774
|
+
applyPopupAnchor(linkHash);
|
|
1736
1775
|
})
|
|
1737
1776
|
.catch(function() {
|
|
1738
1777
|
cache[path] = false;
|
|
@@ -1786,7 +1825,7 @@
|
|
|
1786
1825
|
if (!anchor) { hidePopup(); return; }
|
|
1787
1826
|
var href = anchor.getAttribute('href');
|
|
1788
1827
|
if (!href || isAnchorOnly(href)) { hidePopup(); return; }
|
|
1789
|
-
if (!anchor.closest('.md-content')) { hidePopup(); return; }
|
|
1828
|
+
if (!anchor.closest('.md-content') && !anchor.closest('.frontmatter')) { hidePopup(); return; }
|
|
1790
1829
|
e.preventDefault();
|
|
1791
1830
|
handleLink(anchor, e.clientX, e.clientY);
|
|
1792
1831
|
});
|
|
@@ -1808,7 +1847,7 @@
|
|
|
1808
1847
|
if (!anchor) { hidePopup(); return; }
|
|
1809
1848
|
var href = anchor.getAttribute('href');
|
|
1810
1849
|
if (!href || isAnchorOnly(href)) { hidePopup(); return; }
|
|
1811
|
-
if (!anchor.closest('.md-content')) { hidePopup(); return; }
|
|
1850
|
+
if (!anchor.closest('.md-content') && !anchor.closest('.frontmatter')) { hidePopup(); return; }
|
|
1812
1851
|
e.preventDefault();
|
|
1813
1852
|
var touch = e.changedTouches[0];
|
|
1814
1853
|
handleLink(anchor, touch.clientX, touch.clientY);
|
|
@@ -1821,24 +1860,26 @@
|
|
|
1821
1860
|
<% if settings.link_tooltips %>
|
|
1822
1861
|
// Hover — same popup as click, triggered after a short delay when no popup is active
|
|
1823
1862
|
(function() {
|
|
1824
|
-
var content = document.querySelector('.md-content');
|
|
1825
|
-
if (!content) return;
|
|
1826
1863
|
var hoverTimer = null;
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
if (
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
if (
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1864
|
+
var containers = document.querySelectorAll('.md-content, .frontmatter');
|
|
1865
|
+
if (!containers.length) return;
|
|
1866
|
+
containers.forEach(function(container) {
|
|
1867
|
+
container.querySelectorAll('a').forEach(function(a) {
|
|
1868
|
+
var href = a.getAttribute('href');
|
|
1869
|
+
if (!href || isAnchorOnly(href)) return;
|
|
1870
|
+
if (!isLocalMd(href) && !isExternal(href)) return;
|
|
1871
|
+
a.addEventListener('mouseenter', function(e) {
|
|
1872
|
+
clearTimeout(hoverTimer);
|
|
1873
|
+
if (popup) return;
|
|
1874
|
+
var x = e.clientX, y = e.clientY;
|
|
1875
|
+
hoverTimer = setTimeout(function() {
|
|
1876
|
+
if (!popup) handleLink(a, x, y, false);
|
|
1877
|
+
}, 300);
|
|
1878
|
+
});
|
|
1879
|
+
a.addEventListener('mouseleave', function() {
|
|
1880
|
+
clearTimeout(hoverTimer);
|
|
1881
|
+
if (popup) mouseLeaveTimer = setTimeout(hidePopup, 150);
|
|
1882
|
+
});
|
|
1842
1883
|
});
|
|
1843
1884
|
});
|
|
1844
1885
|
})();
|