markdownr 0.4.8 → 0.5.0

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: bc26010b968e9e71f263a712100cac36ff0f6254b5c3a7f89c4f71e5dfc42e8e
4
- data.tar.gz: 45fbe7488f164f1fa99e4e7a23bfb0c2c4794ac0f9f549ef9bb7d63408991a89
3
+ metadata.gz: 03b8c1c4665231a3fb1ead89abea54e0630131743216938a1c293945c942e710
4
+ data.tar.gz: 004d43321fcda1b894c6481eed4b755f29a9fae14c6e0f6bbb5c1f9d82b6afd9
5
5
  SHA512:
6
- metadata.gz: b7037aaf1b59865d8d5abab5d4e1887dee3ed3b2e8abaccc179a7faedc5e909397c7a5ee48de4504ecd2b52eb67171dc54f6bcd5e981d450117df42c1f772dd3
7
- data.tar.gz: 0fa16c47e3ae9d72f84ba87b5c4f9da0872d86c248716db8614ac3f6f3ce9b8624fa9618049368d352635b1b26e7659d82f9e630cb97743dde3f7712ca76f461
6
+ metadata.gz: 0d44c7b65617670e54d450d5d958294bd78914407cf925087f1547b551b5b91dd3b556820009aa197491bdd14bff9fc6e205a47bf6662fb5b5a495d8e5d8c71d
7
+ data.tar.gz: 07f03bc67cc2b668c90c1c9467eb7eafe60f2c58c4030553adbec8af4309bdbf3943c9ffdd454cdde0283619f702c6a7ef75992ed679e84983557c5ed5fc3675
@@ -491,13 +491,16 @@ module MarkdownServer
491
491
  } || ""
492
492
  end
493
493
 
494
- def page_html(raw)
494
+ def page_html(raw, base_url = nil)
495
495
  w = raw.dup
496
496
  # Remove inert elements and their entire contents
497
497
  STRIP_FULL.each { |t| w.gsub!(/<#{t}[^>]*>.*?<\/#{t}>/im, " ") }
498
498
  w.gsub!(/<!--.*?-->/m, " ")
499
499
  # Remove known ad/recommendation blocks
500
500
  w.gsub!(/Bible\s+Gateway\s+Recommends[\s\S]*?View\s+more\s+titles/i, " ")
501
+ # Remove BibleGateway header/toolbar noise (promo text + login/toolbar block)
502
+ w.gsub!(/trusted\s+resources\s+beside\s+every\s+verse[\s\S]*?Your\s+Content/i, " ")
503
+ w.gsub!(/Log\s+In\s*\/\s*Sign\s+Up[\s\S]*?Your\s+Content/i, " ")
501
504
 
502
505
  # Prefer a focused content block
503
506
  content = w.match(/<article[^>]*>(.*?)<\/article>/im)&.[](1) ||
@@ -505,15 +508,36 @@ module MarkdownServer
505
508
  w.match(/<body[^>]*>(.*?)<\/body>/im)&.[](1) ||
506
509
  w
507
510
 
508
- # Rewrite tags: keep allowed (strip attrs), block→newline, rest→empty
509
- out = content.gsub(/<(\/?)(\w+)[^>]*>/) do
510
- slash, tag = $1, $2.downcase
511
- if ALLOWED_HTML.include?(tag) then "<#{slash}#{tag}>"
512
- elsif BLOCK_HTML.include?(tag) then "\n"
513
- else ""
511
+ # Rewrite tags: keep allowed (strip attrs), preserve <a href>, block→newline, rest→empty
512
+ out = content.gsub(/<(\/?)(\w+)([^>]*)>/) do
513
+ slash, tag, attrs = $1, $2.downcase, $3
514
+ if ALLOWED_HTML.include?(tag)
515
+ "<#{slash}#{tag}>"
516
+ elsif tag == "a"
517
+ if slash.empty?
518
+ m = attrs.match(/href\s*=\s*["']([^"']*)["']/i)
519
+ if m && !m[1].match?(/\Ajavascript:/i)
520
+ href = m[1]
521
+ if base_url && href !~ /\Ahttps?:\/\//i && !href.start_with?("#")
522
+ href = (URI.join(base_url, href).to_s rescue href)
523
+ end
524
+ %(<a href="#{h(href)}" target="_blank" rel="noopener">)
525
+ else
526
+ ""
527
+ end
528
+ else
529
+ "</a>"
530
+ end
531
+ elsif BLOCK_HTML.include?(tag)
532
+ "\n"
533
+ else
534
+ ""
514
535
  end
515
536
  end
516
537
 
538
+ # Strip any preamble before the first heading (site chrome, toolbars, etc.)
539
+ out.sub!(/\A[\s\S]*?(?=<h[1-6]>)/i, "")
540
+
517
541
  # Decode HTML entities
518
542
  out = out
519
543
  .gsub(/&nbsp;/i, " ").gsub(/&amp;/i, "&").gsub(/&lt;/i, "<").gsub(/&gt;/i, ">")
@@ -527,6 +551,9 @@ module MarkdownServer
527
551
  .gsub(/<(\w+)>\s*<\/\1>/, "") # drop empty tags
528
552
  .strip
529
553
 
554
+ # Strip all footer navigation after "Read full chapter" up to (but not including) copyright
555
+ out.gsub!(/(<a[^>]*>Read\s+full\s+chapter<\/a>)[\s\S]*?(?=©|Copyright\b)/i, "\\1\n")
556
+
530
557
  out.length > 10_000 ? out[0, 10_000] : out
531
558
  end
532
559
 
@@ -621,7 +648,8 @@ module MarkdownServer
621
648
  html = fetch_external_page(url)
622
649
  halt 502, '{"error":"fetch failed"}' unless html
623
650
 
624
- JSON.dump({ title: page_title(html), html: page_html(html) })
651
+ title = page_title(html).sub(/ [-–] .*/, "").strip
652
+ JSON.dump({ title: title, html: page_html(html, url) })
625
653
  end
626
654
 
627
655
  get "/search/?*" do
@@ -1,3 +1,3 @@
1
1
  module MarkdownServer
2
- VERSION = "0.4.8"
2
+ VERSION = "0.5.0"
3
3
  end
data/views/layout.erb CHANGED
@@ -726,10 +726,6 @@
726
726
  .link-ctx-popup-close:hover { color: #2c2c2c; }
727
727
  .link-ctx-popup-body {
728
728
  padding: 0.75rem 1rem;
729
- font-family: Georgia, "Times New Roman", serif;
730
- font-size: 0.85rem;
731
- line-height: 1.6;
732
- color: #2c2c2c;
733
729
  }
734
730
  .link-ctx-popup-url {
735
731
  font-family: "SF Mono", Menlo, Consolas, monospace;
@@ -741,49 +737,8 @@
741
737
  border-radius: 4px;
742
738
  margin-bottom: 0.5rem;
743
739
  }
744
- .link-ctx-popup-body h1, .link-ctx-popup-body h2, .link-ctx-popup-body h3,
745
- .link-ctx-popup-body h4, .link-ctx-popup-body h5, .link-ctx-popup-body h6 {
746
- margin: 0.7rem 0 0.3rem; color: #3a3a3a;
747
- }
748
- .link-ctx-popup-body h1 { font-size: 1.2rem; }
749
- .link-ctx-popup-body h2 { font-size: 1.05rem; border-bottom: none; padding-bottom: 0; }
750
- .link-ctx-popup-body h3 { font-size: 0.95rem; }
751
- .link-ctx-popup-body p { margin: 0 0 0.5rem; }
752
- .link-ctx-popup-body p:last-child { margin-bottom: 0; }
753
- .link-ctx-popup-body a { color: #8b6914; text-decoration: none; border-bottom: 1px solid #d4b96a; }
754
- .link-ctx-popup-body a.wiki-link { color: #6a8e3e; border-bottom-color: #6a8e3e; }
755
- .link-ctx-popup-body code {
756
- font-family: "SF Mono", Menlo, Consolas, monospace;
757
- font-size: 0.82em;
758
- background: #f0ece3;
759
- padding: 0.1em 0.3em;
760
- border-radius: 3px;
761
- }
762
- .link-ctx-popup-body pre {
763
- background: #2d2d2d;
764
- color: #f0f0f0;
765
- padding: 0.6rem 0.8rem;
766
- border-radius: 4px;
767
- font-size: 0.78rem;
768
- line-height: 1.4;
769
- overflow-x: auto;
770
- margin: 0.4rem 0;
771
- }
772
- .link-ctx-popup-body pre code { background: none; padding: 0; font-size: 1em; color: inherit; }
773
- .link-ctx-popup-body ul, .link-ctx-popup-body ol { padding-left: 1.4rem; margin: 0.3rem 0; }
774
- .link-ctx-popup-body li { margin-bottom: 0.2rem; }
775
- .link-ctx-popup-body blockquote {
776
- border-left: 3px solid #d4b96a;
777
- margin: 0.5rem 0;
778
- padding: 0.3rem 0.8rem;
779
- color: #4a4a4a;
780
- font-style: italic;
781
- }
782
- .link-ctx-popup-body table { border-collapse: collapse; font-size: 0.8rem; margin: 0.5rem 0; }
783
- .link-ctx-popup-body th, .link-ctx-popup-body td { border: 1px solid #ddd; padding: 0.3rem 0.5rem; }
784
- .link-ctx-popup-body th { background: #f5f0e4; }
785
740
 
786
- /* Link preview popup */
741
+ /* Link preview popup (hover) */
787
742
  .link-tooltip-anchor { position: relative; }
788
743
  .link-preview-popup {
789
744
  position: absolute;
@@ -799,10 +754,6 @@
799
754
  border-radius: 6px;
800
755
  box-shadow: 0 4px 20px rgba(0,0,0,0.18);
801
756
  padding: 0.8rem 1rem;
802
- font-family: Georgia, "Times New Roman", serif;
803
- font-size: 0.85rem;
804
- line-height: 1.6;
805
- color: #2c2c2c;
806
757
  cursor: auto;
807
758
  -webkit-overflow-scrolling: touch;
808
759
  }
@@ -814,26 +765,36 @@
814
765
  border-bottom: 1px solid #e0d8c8;
815
766
  color: #3a3a3a;
816
767
  }
768
+
769
+ /* Shared popup content styles */
770
+ .link-ctx-popup-body,
771
+ .link-preview-popup {
772
+ font-family: Georgia, "Times New Roman", serif;
773
+ font-size: 0.85rem;
774
+ line-height: 1.6;
775
+ color: #2c2c2c;
776
+ }
777
+ .link-ctx-popup-body h1, .link-ctx-popup-body h2, .link-ctx-popup-body h3,
778
+ .link-ctx-popup-body h4, .link-ctx-popup-body h5, .link-ctx-popup-body h6,
817
779
  .link-preview-popup h1, .link-preview-popup h2, .link-preview-popup h3,
818
780
  .link-preview-popup h4, .link-preview-popup h5, .link-preview-popup h6 {
819
- margin: 0.7rem 0 0.3rem;
820
- color: #3a3a3a;
781
+ margin: 0.7rem 0 0.3rem; color: #3a3a3a;
821
782
  }
822
- .link-preview-popup h1 { font-size: 1.2rem; }
823
- .link-preview-popup h2 { font-size: 1.05rem; border-bottom: none; padding-bottom: 0; }
824
- .link-preview-popup h3 { font-size: 0.95rem; }
825
- .link-preview-popup p { margin: 0 0 0.5rem; }
826
- .link-preview-popup p:last-child { margin-bottom: 0; }
827
- .link-preview-popup a { color: #8b6914; text-decoration: none; border-bottom: 1px solid #d4b96a; }
828
- .link-preview-popup a.wiki-link { color: #6a8e3e; border-bottom-color: #6a8e3e; }
829
- .link-preview-popup code {
783
+ .link-ctx-popup-body h1, .link-preview-popup h1 { font-size: 1.2rem; }
784
+ .link-ctx-popup-body h2, .link-preview-popup h2 { font-size: 1.05rem; border-bottom: none; padding-bottom: 0; }
785
+ .link-ctx-popup-body h3, .link-preview-popup h3 { font-size: 0.95rem; }
786
+ .link-ctx-popup-body p, .link-preview-popup p { margin: 0 0 0.5rem; }
787
+ .link-ctx-popup-body p:last-child, .link-preview-popup p:last-child { margin-bottom: 0; }
788
+ .link-ctx-popup-body a, .link-preview-popup a { color: #8b6914; text-decoration: none; border-bottom: 1px solid #d4b96a; }
789
+ .link-ctx-popup-body a.wiki-link, .link-preview-popup a.wiki-link { color: #6a8e3e; border-bottom-color: #6a8e3e; }
790
+ .link-ctx-popup-body code, .link-preview-popup code {
830
791
  font-family: "SF Mono", Menlo, Consolas, monospace;
831
792
  font-size: 0.82em;
832
793
  background: #f0ece3;
833
794
  padding: 0.1em 0.3em;
834
795
  border-radius: 3px;
835
796
  }
836
- .link-preview-popup pre {
797
+ .link-ctx-popup-body pre, .link-preview-popup pre {
837
798
  background: #2d2d2d;
838
799
  color: #f0f0f0;
839
800
  padding: 0.6rem 0.8rem;
@@ -843,26 +804,21 @@
843
804
  overflow-x: auto;
844
805
  margin: 0.4rem 0;
845
806
  }
846
- .link-preview-popup pre code { background: none; padding: 0; font-size: 1em; }
807
+ .link-ctx-popup-body pre code, .link-preview-popup pre code { background: none; padding: 0; font-size: 1em; color: inherit; }
808
+ .link-ctx-popup-body ul, .link-ctx-popup-body ol,
847
809
  .link-preview-popup ul, .link-preview-popup ol { padding-left: 1.4rem; margin: 0.3rem 0; }
848
- .link-preview-popup li { margin-bottom: 0.2rem; }
849
- .link-preview-popup blockquote {
810
+ .link-ctx-popup-body li, .link-preview-popup li { margin-bottom: 0.2rem; }
811
+ .link-ctx-popup-body blockquote, .link-preview-popup blockquote {
850
812
  border-left: 3px solid #d4b96a;
851
813
  margin: 0.5rem 0;
852
814
  padding: 0.3rem 0.8rem;
853
815
  color: #4a4a4a;
854
816
  font-style: italic;
855
817
  }
856
- .link-preview-popup table {
857
- border-collapse: collapse;
858
- font-size: 0.8rem;
859
- margin: 0.5rem 0;
860
- }
861
- .link-preview-popup th, .link-preview-popup td {
862
- border: 1px solid #ddd;
863
- padding: 0.3rem 0.5rem;
864
- }
865
- .link-preview-popup th { background: #f5f0e4; }
818
+ .link-ctx-popup-body table, .link-preview-popup table { border-collapse: collapse; font-size: 0.8rem; margin: 0.5rem 0; }
819
+ .link-ctx-popup-body th, .link-ctx-popup-body td,
820
+ .link-preview-popup th, .link-preview-popup td { border: 1px solid #ddd; padding: 0.3rem 0.5rem; }
821
+ .link-ctx-popup-body th, .link-preview-popup th { background: #f5f0e4; }
866
822
 
867
823
  /* Footnote tooltips */
868
824
  .footnote-tooltip {
@@ -1539,9 +1495,7 @@
1539
1495
  var extKey = 'ext:' + href;
1540
1496
  var extCached = cache[extKey];
1541
1497
  if (extCached && typeof extCached === 'object') {
1542
- showPopup(x, y, extCached.title || label,
1543
- '<div class="link-ctx-popup-url">' + escHtml(href) + '</div>' +
1544
- extCached.html);
1498
+ showPopup(x, y, extCached.title || label, extCached.html);
1545
1499
  } else if (extCached === false) {
1546
1500
  showPopup(x, y, label,
1547
1501
  '<div class="link-ctx-popup-url">' + escHtml(href) + '</div>' +
@@ -1561,10 +1515,7 @@
1561
1515
  return;
1562
1516
  }
1563
1517
  cache[extKey] = { title: data.title, html: data.html };
1564
- updatePopup(
1565
- '<div class="link-ctx-popup-url">' + escHtml(href) + '</div>' +
1566
- data.html,
1567
- data.title || label);
1518
+ updatePopup(data.html, data.title || label);
1568
1519
  })
1569
1520
  .catch(function() {
1570
1521
  cache[extKey] = false;
@@ -1639,10 +1590,11 @@
1639
1590
  document.addEventListener('keydown', function(e) {
1640
1591
  if (e.key === 'Escape' && popup) hidePopup();
1641
1592
  });
1593
+
1642
1594
  })();
1643
1595
 
1644
1596
  <% if settings.link_tooltips %>
1645
- // Link preview popup for local markdown links
1597
+ // Link preview popup for local markdown links and external links
1646
1598
  (function() {
1647
1599
  var content = document.querySelector('.md-content');
1648
1600
  if (!content) return;
@@ -1667,48 +1619,79 @@
1667
1619
  return /\.md$/i.test(path);
1668
1620
  }
1669
1621
 
1622
+ function isExternalLink(a) {
1623
+ var href = a.getAttribute('href');
1624
+ return href && /^https?:\/\//i.test(href);
1625
+ }
1626
+
1670
1627
  function previewUrl(a) {
1671
1628
  var resolved = new URL(a.getAttribute('href'), location.href);
1672
1629
  return '/preview/' + resolved.pathname.replace(/^\/browse\//, '');
1673
1630
  }
1674
1631
 
1632
+ // Returns true if el has an ancestor that clips overflow (prevents absolute children escaping)
1633
+ function hasOverflowClip(el) {
1634
+ var parent = el.parentElement;
1635
+ while (parent && parent !== document.body) {
1636
+ var s = window.getComputedStyle(parent);
1637
+ if (s.overflow !== 'visible' || s.overflowX !== 'visible' || s.overflowY !== 'visible') return true;
1638
+ parent = parent.parentElement;
1639
+ }
1640
+ return false;
1641
+ }
1642
+
1675
1643
  function showPopup(anchor, html) {
1676
1644
  hidePopup();
1677
1645
  var pop = document.createElement('div');
1678
1646
  pop.className = 'link-preview-popup';
1679
1647
  pop.innerHTML = html;
1680
- anchor.appendChild(pop);
1681
1648
  activePopup = pop;
1682
1649
  activeAnchor = anchor;
1683
1650
 
1684
- // Clamp right edge to viewport
1685
1651
  var vw = Math.min(window.innerWidth, document.documentElement.clientWidth);
1686
- var rect = pop.getBoundingClientRect();
1687
- if (rect.right > vw - 8) {
1688
- pop.style.left = Math.max(0, parseFloat(pop.style.left || 0) - (rect.right - (vw - 8))) + 'px';
1689
- }
1690
- // If top goes off screen, flip below the link instead
1691
- rect = pop.getBoundingClientRect();
1692
- if (rect.top < 8) {
1693
- pop.style.bottom = 'auto';
1694
- pop.style.top = '100%';
1652
+ var vh = window.innerHeight;
1653
+
1654
+ if (hasOverflowClip(anchor)) {
1655
+ // Anchor is inside an overflow container — use fixed positioning to escape clipping
1656
+ pop.style.position = 'fixed';
1657
+ pop.style.bottom = 'auto'; // override the CSS class's bottom: 100%
1658
+ document.body.appendChild(pop);
1659
+ var aRect = anchor.getBoundingClientRect();
1660
+ var popH = pop.offsetHeight;
1661
+ var popW = pop.offsetWidth;
1662
+ // Prefer above the link, fall back to below
1663
+ var top = aRect.top - popH - 4;
1664
+ if (top < 8) top = aRect.bottom + 4;
1665
+ if (top + popH > vh - 8) top = Math.max(8, vh - popH - 8);
1666
+ var left = aRect.left;
1667
+ if (left + popW > vw - 8) left = Math.max(8, vw - popW - 8);
1668
+ pop.style.top = top + 'px';
1669
+ pop.style.left = left + 'px';
1670
+ } else {
1671
+ // Normal anchor-attached positioning
1672
+ anchor.appendChild(pop);
1673
+ var rect = pop.getBoundingClientRect();
1674
+ var shift = 0;
1675
+ if (rect.right > vw - 8) shift = (vw - 8) - rect.right;
1676
+ if (rect.left + shift < 8) shift = 8 - rect.left;
1677
+ if (shift !== 0) pop.style.left = (parseFloat(pop.style.left || 0) + shift) + 'px';
1678
+ // If top goes off screen, flip below the link instead
1679
+ rect = pop.getBoundingClientRect();
1680
+ if (rect.top < 8) {
1681
+ pop.style.bottom = 'auto';
1682
+ pop.style.top = '100%';
1683
+ }
1695
1684
  }
1696
1685
 
1697
1686
  // Keep popup open while hovering over it
1698
1687
  pop.addEventListener('mouseenter', function() { clearTimeout(hideTimer); });
1699
1688
  pop.addEventListener('mouseleave', function() { hideTimer = setTimeout(hidePopup, 10); });
1700
1689
 
1701
- // Stop clicks/touches inside the popup from triggering the outer link
1690
+ // Stop clicks inside the popup from triggering the outer link
1702
1691
  pop.addEventListener('click', function(e) {
1703
1692
  e.stopPropagation();
1704
1693
  if (!e.target.closest('a')) e.preventDefault();
1705
1694
  });
1706
- pop.addEventListener('touchstart', function(e) { e.stopPropagation(); }, { passive: true });
1707
- pop.addEventListener('touchmove', function(e) { e.stopPropagation(); }, { passive: true });
1708
- pop.addEventListener('touchend', function(e) {
1709
- e.stopPropagation();
1710
- if (!e.target.closest('a')) e.preventDefault();
1711
- });
1712
1695
  }
1713
1696
 
1714
1697
  function hidePopup() {
@@ -1737,36 +1720,49 @@
1737
1720
  }
1738
1721
  }
1739
1722
 
1723
+ function fetchExternalAndShow(anchor) {
1724
+ var href = anchor.getAttribute('href');
1725
+ var key = 'ext:' + href;
1726
+ var cached = cache[key];
1727
+ if (cached === undefined) {
1728
+ cache[key] = null; // in-flight
1729
+ showPopup(anchor, '<p style="opacity:0.5;margin:0">Loading\u2026</p>');
1730
+ fetch('/fetch?url=' + encodeURIComponent(href))
1731
+ .then(function(r) { return r.ok ? r.json() : null; })
1732
+ .then(function(data) {
1733
+ if (!data || data.error) { cache[key] = false; if (activeAnchor === anchor) hidePopup(); return; }
1734
+ var html = '<div class="link-preview-popup-title">' + escHtml(data.title) + '</div>' + data.html;
1735
+ cache[key] = html;
1736
+ if (activeAnchor === anchor) showPopup(anchor, html);
1737
+ })
1738
+ .catch(function() { cache[key] = false; if (activeAnchor === anchor) hidePopup(); });
1739
+ } else if (typeof cached === 'string') {
1740
+ showPopup(anchor, cached);
1741
+ }
1742
+ }
1743
+
1740
1744
  content.querySelectorAll('a').forEach(function(a) {
1741
- if (!isLocalMdLink(a)) return;
1745
+ var localMd = isLocalMdLink(a);
1746
+ var external = isExternalLink(a);
1747
+ if (!localMd && !external) return;
1742
1748
  a.classList.add('link-tooltip-anchor');
1743
1749
 
1744
1750
  var hoverTimer = null;
1745
1751
  a.addEventListener('click', hidePopup);
1746
1752
  a.addEventListener('mouseenter', function() {
1747
- hoverTimer = setTimeout(function() { fetchAndShow(a); }, 300);
1753
+ hoverTimer = setTimeout(function() {
1754
+ if (localMd) fetchAndShow(a);
1755
+ else fetchExternalAndShow(a);
1756
+ }, 300);
1748
1757
  });
1749
1758
  a.addEventListener('mouseleave', function() {
1750
1759
  clearTimeout(hoverTimer);
1751
- hideTimer = setTimeout(hidePopup, 10);
1752
- });
1753
-
1754
- var touchMoved = false;
1755
- a.addEventListener('touchstart', function() { touchMoved = false; }, { passive: true });
1756
- a.addEventListener('touchmove', function() { touchMoved = true; }, { passive: true });
1757
- a.addEventListener('touchend', function(e) {
1758
- if (touchMoved) return;
1759
- if (activeAnchor === a && activePopup) return; // second tap → navigate
1760
- e.preventDefault();
1761
- document.querySelectorAll('.link-preview-popup').forEach(function(p) {
1762
- if (p.parentNode) p.parentNode.removeChild(p);
1763
- });
1764
- fetchAndShow(a);
1760
+ hideTimer = setTimeout(hidePopup, 150);
1765
1761
  });
1766
1762
  });
1767
1763
 
1768
1764
  document.addEventListener('click', function(e) {
1769
- if (activePopup && activeAnchor && !activeAnchor.contains(e.target)) hidePopup();
1765
+ if (activePopup && !activePopup.contains(e.target) && activeAnchor && !activeAnchor.contains(e.target)) hidePopup();
1770
1766
  });
1771
1767
  })();
1772
1768
  <% end %>
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.4.8
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Dunn