Refactor resource reading logic to improve selection handling and enhance text extraction from articles

This commit is contained in:
2025-11-30 13:26:25 -05:00
parent 3681359291
commit 9466da7cc0
2 changed files with 26 additions and 45 deletions
+25 -8
View File
@@ -1881,13 +1881,13 @@
window.KJVResourceSpeech.suppressSpace = true;
return;
}
var highlighted = document.querySelector('[style*=\"outline: 2px solid\"]:not(.toc)') ||
document.querySelector('[style*=\"outline:2px solid\"]:not(.toc)') ||
document.querySelector('.selected:not(.toc)');
var highlighted = document.querySelector('[style*=\"outline: 2px solid\"]:not(.toc):not(.breadcrumb):not(.chapters-section)') ||
document.querySelector('[style*=\"outline:2px solid\"]:not(.toc):not(.breadcrumb):not(.chapters-section)') ||
document.querySelector('.selected:not(.toc):not(.breadcrumb):not(.chapters-section)');
var combined = '';
if (highlighted) {
var hclone = highlighted.cloneNode(true);
hclone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, script, style').forEach(function(el) { el.remove(); });
hclone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, .chapters-section, script, style').forEach(function(el) { el.remove(); });
combined = (hclone.textContent || hclone.innerText || '').trim();
} else {
var article = document.querySelector('article');
@@ -1896,12 +1896,29 @@
var selectedCard = article.querySelector('.resource-card[style*=\"outline\"]') || article.querySelector('.resource-card');
if (selectedCard) {
var cclone = selectedCard.cloneNode(true);
cclone.querySelectorAll('.breadcrumb, .toc, script, style').forEach(function(el) { el.remove(); });
cclone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, .chapters-section, script, style').forEach(function(el) { el.remove(); });
combined = (cclone.textContent || cclone.innerText || '').trim();
} else {
var aclone = article.cloneNode(true);
aclone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, script, style').forEach(function(el) { el.remove(); });
combined = (aclone.textContent || aclone.innerText || '').trim();
// Prefer reading substantive text blocks instead of the whole article
var textBlocks = Array.from(article.querySelectorAll('h1, h2, h3, p, li, blockquote, .intro-text, .verse-text, .resource-description, .resource-description-body, .resource-item-description, .parable-description, .angel-description, .covenant-description, .festival-description, .prophet-description, .fruit-description, .name-description, .woman-description, .apostle-description'))
.filter(function(el) {
if (el.closest('.toc') || el.closest('.chapters-section') || el.closest('.breadcrumb')) return false;
var txt = (el.textContent || el.innerText || '').trim();
return txt.length > 120;
})
.map(function(el) {
var clone = el.cloneNode(true);
clone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, .chapters-section, script, style').forEach(function(x) { x.remove(); });
return (clone.textContent || clone.innerText || '').trim();
})
.filter(Boolean);
if (textBlocks.length > 0) {
combined = textBlocks.join('\\n\\n');
} else {
var aclone = article.cloneNode(true);
aclone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, .breadcrumb, .toc, .chapters-section, script, style').forEach(function(el) { el.remove(); });
combined = (aclone.textContent || aclone.innerText || '').trim();
}
}
}
}
+1 -37
View File
@@ -337,10 +337,6 @@
{% endblock %}
{% block content %}
<script>
// Use homepage-specific reader; disable global resource reader
document.body.dataset.resourceReader = 'false';
</script>
<div class="title-page">
<h1>The Holy Bible</h1>
<p class="subtitle">Authorized King James Version · <em>Anno Domini</em> 1611</p>
@@ -627,6 +623,7 @@ function selectCard(index) {
}
document.addEventListener('keydown', function(e) {
if (e.defaultPrevented) return;
var el = document.activeElement;
var isTyping = el.tagName === 'INPUT' || el.tagName === 'TEXTAREA';
@@ -673,39 +670,6 @@ document.addEventListener('keydown', function(e) {
window.location.href = '/books';
}
}
// Space: read selected element or first intro paragraph
if (e.key === ' ' && !isTyping && el.tagName !== 'A' && el.tagName !== 'BUTTON') {
e.preventDefault();
if (!('speechSynthesis' in window)) return;
// Toggle off if currently speaking
if (speechSynthesis.speaking || speechSynthesis.pending || speechSynthesis.paused) {
speechSynthesis.cancel();
return;
}
var target = selectedCardIndex >= 0 && selectedCardIndex < allCards.length
? allCards[selectedCardIndex]
: (introParagraphs.length ? introParagraphs[0] : null);
if (!target) return;
var clone = target.cloneNode(true);
clone.querySelectorAll('.sidenote, .marginnote, .sidenote-number, .margin-toggle, script, style').forEach(function(el) { el.remove(); });
var text = (clone.textContent || clone.innerText || '').trim();
if (!text) return;
var utter = new SpeechSynthesisUtterance(text);
var voices = speechSynthesis.getVoices();
var englishVoice = voices.find(function(v) { return v.lang && v.lang.toLowerCase().startsWith('en') && v.name.includes('Daniel'); }) ||
voices.find(function(v) { return v.lang && v.lang.toLowerCase().startsWith('en-gb'); }) ||
voices.find(function(v) { return v.lang && v.lang.toLowerCase().startsWith('en'); });
if (englishVoice) utter.voice = englishVoice;
speechSynthesis.cancel();
speechSynthesis.speak(utter);
}
});
</script>
{% endblock %}