Skip to content

Related verses (#385)#387

Merged
nathanvercaemert merged 1 commit into
copy-buttonfrom
master
May 20, 2026
Merged

Related verses (#385)#387
nathanvercaemert merged 1 commit into
copy-buttonfrom
master

Conversation

@nathanvercaemert

Copy link
Copy Markdown
Contributor
  • feat: semantic related verses (parallel to vocabulary flow)

Adds SemanticRelatedVersesService backed by an in-memory NRSV-keyed lookup over a 36 MB JSON resource shipped in step-core-data. Surfaced via a new relatedrefsSemantic search token routed through the existing masterSearch pipeline so URL share / bookmark / reload / column-link all work for free; SearchResult.searchType is normalized back to RELATED_VERSES on the wire so the existing frontend rendering case matches without a new switch arm.

Backend:

  • SemanticRelatedVersesService (interface) + impl: streaming Jackson parser with a local interner; eager singleton bound in StepCoreModule; pure NRSV-in / NRSV-out, no JSword dependency.
  • SearchServiceImpl: new field + ctor param; new dispatch in enhanceSearchTokens, runCorrectSearch, executeOneSearch; new runSemanticRelatedVerses executor handles user-v11n -> NRSV inbound and NRSV -> user-v11n outbound mapping verse-by-verse with DefaultKeyList to preserve ranking; reuses JSwordSearchService#getResultsFromTrimmedKeys (avoids rankAndTrimResults so order survives); top-50 cap, OSIS dedup.
  • SearchType.RELATED_VERSES_SEMANTIC (internal); normalization wrapper on getBestSearchType maps it back to RELATED_VERSES for the frontend.
  • SearchToken.RELATED_VERSES_SEMANTIC = "relatedrefsSemantic".
  • ValidateUtils XSS branch extended to accept the new token.
  • SearchServiceImplTest constructor call patched (extra null param).

Frontend:

  • step.util.js verse popup template restructured: new .relatedVersesChooser row above the vocab table with vocabulary | semantics anchors; .relatedVerses removed from the bottom .verseVocabLinks div; new click handler navigates via relatedrefsSemantic token; new getSource and renderEnhancedToken cases produce a distinct "Sem:" pill.
  • view_main_search.js: three sibling fall-through cases added next to RELATED_VERSES.
  • step_constants.js: RELATED_VERSES_SEMANTIC constant.
  • verse_popup.scss: .relatedVersesChooser block (mirror of .verseVocabLinks divider, dotted bottom border).

i18n: 5 new keys in InteractiveBundle.properties only (English base); locale bundles intentionally untouched per upstream sync policy.

Data: bible_semantic_export_minified.json (NRSV-keyed; 31,087 keys x 100 ranked refs each) staged under step-core-data/.../related-verses/.

  • fix(verse_popup): drop margin/padding on .relatedVersesChooser anchors

The 10px margin-right + 10px padding-right was copy-pasted from .verseVocabLinks where it brackets a CSS border-right divider; the chooser uses a literal "|" character instead, so the same rule just adds dead space and extends the underline 10px past "vocabulary". Removing the nested anchor block lets the popup-wide a { padding: 0px } rule apply.

  • fix(search): honor display mode for semantic related verses

Pass the user's full version stack to getResultsFromTrimmedKeys so COLUMN / INTERLINEAR / INTERLEAVED / COMPARE modes survive past getBestInterlinearMode's empty-extras short-circuit. Inlined NRSV-rank ordering via DefaultKeyList is preserved.

  • feat(verse_popup): move "See related subjects" into chooser row; drop empty vocab-links box

Inline the three chooser anchors as English literals ("meaning | vocabulary | topics") and add a third .relatedSubjects anchor that previously lived in the bottom .verseVocabLinks row. Delete the five locally-introduced i18n keys (display_verses_related_by, related_by_vocabulary, related_by_semantics, verse_related_semantic, semantic_related_prefix) from InteractiveBundle.properties. Reuse the upstream __s.related_prefix in the semantic-chip body so its rendering matches the vocabulary/topics chips; rename the semantic chip's hover tooltip to "Related verses (meaning)".

Also prune the now-often-empty .verseVocabLinks dotted box: when the verse has no translation tip and was not reached via search, the box would otherwise render with no anchors. Because templatedTable is a jQuery collection of three sibling top-level elements (not a single container), the prune must filter the element out of the collection itself — calling .remove() on a detached top-level element does not prevent qtip from re-attaching it via content.text:templatedTable.

  • refactor(search): route semantic related verses through shared Passage pipeline

Rewrite runSemanticRelatedVerses to mirror runRelatedVerses (lexical flow): build an NRSV Passage from the full ranked list, map to the user's versification with VersificationsMapper.map, and hand to buildCombinedVerseBasedResults. Drops the 50-verse cap, the manual DefaultKeyList/HashSet accumulator, per-ref it.next()-only mapping, the local countOnly branch, and the hand-rolled getResultsFromTrimmedKeys call (display-mode fix from 8780d60 now comes for free via the shared helper). Results are canonical-ordered and dedup'd by RangedPassage semantics; 1->N cross-v11n mappings (e.g. Psalm titling) are now kept.

  • update version number

* feat: semantic related verses (parallel to vocabulary flow)

Adds SemanticRelatedVersesService backed by an in-memory NRSV-keyed
lookup over a 36 MB JSON resource shipped in step-core-data. Surfaced
via a new relatedrefsSemantic search token routed through the existing
masterSearch pipeline so URL share / bookmark / reload / column-link
all work for free; SearchResult.searchType is normalized back to
RELATED_VERSES on the wire so the existing frontend rendering case
matches without a new switch arm.

Backend:
  - SemanticRelatedVersesService (interface) + impl: streaming Jackson
    parser with a local interner; eager singleton bound in StepCoreModule;
    pure NRSV-in / NRSV-out, no JSword dependency.
  - SearchServiceImpl: new field + ctor param; new dispatch in
    enhanceSearchTokens, runCorrectSearch, executeOneSearch; new
    runSemanticRelatedVerses executor handles user-v11n -> NRSV inbound
    and NRSV -> user-v11n outbound mapping verse-by-verse with
    DefaultKeyList to preserve ranking; reuses
    JSwordSearchService#getResultsFromTrimmedKeys (avoids
    rankAndTrimResults so order survives); top-50 cap, OSIS dedup.
  - SearchType.RELATED_VERSES_SEMANTIC (internal); normalization
    wrapper on getBestSearchType maps it back to RELATED_VERSES for
    the frontend.
  - SearchToken.RELATED_VERSES_SEMANTIC = "relatedrefsSemantic".
  - ValidateUtils XSS branch extended to accept the new token.
  - SearchServiceImplTest constructor call patched (extra null param).

Frontend:
  - step.util.js verse popup template restructured: new
    .relatedVersesChooser row above the vocab table with vocabulary |
    semantics anchors; .relatedVerses removed from the bottom
    .verseVocabLinks div; new click handler navigates via
    relatedrefsSemantic token; new getSource and renderEnhancedToken
    cases produce a distinct "Sem:" pill.
  - view_main_search.js: three sibling fall-through cases added next
    to RELATED_VERSES.
  - step_constants.js: RELATED_VERSES_SEMANTIC constant.
  - verse_popup.scss: .relatedVersesChooser block (mirror of
    .verseVocabLinks divider, dotted bottom border).

i18n: 5 new keys in InteractiveBundle.properties only (English base);
locale bundles intentionally untouched per upstream sync policy.

Data: bible_semantic_export_minified.json (NRSV-keyed; 31,087 keys x
100 ranked refs each) staged under step-core-data/.../related-verses/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(verse_popup): drop margin/padding on .relatedVersesChooser anchors

The 10px margin-right + 10px padding-right was copy-pasted from
.verseVocabLinks where it brackets a CSS border-right divider; the
chooser uses a literal "|" character instead, so the same rule just
adds dead space and extends the underline 10px past "vocabulary".
Removing the nested anchor block lets the popup-wide a { padding: 0px }
rule apply.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(search): honor display mode for semantic related verses

Pass the user's full version stack to getResultsFromTrimmedKeys so
COLUMN / INTERLINEAR / INTERLEAVED / COMPARE modes survive past
getBestInterlinearMode's empty-extras short-circuit. Inlined NRSV-rank
ordering via DefaultKeyList is preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(verse_popup): move "See related subjects" into chooser row; drop empty vocab-links box

Inline the three chooser anchors as English literals ("meaning |
vocabulary | topics") and add a third .relatedSubjects anchor that
previously lived in the bottom .verseVocabLinks row. Delete the five
locally-introduced i18n keys (display_verses_related_by,
related_by_vocabulary, related_by_semantics, verse_related_semantic,
semantic_related_prefix) from InteractiveBundle.properties. Reuse the
upstream __s.related_prefix in the semantic-chip body so its rendering
matches the vocabulary/topics chips; rename the semantic chip's hover
tooltip to "Related verses (meaning)".

Also prune the now-often-empty .verseVocabLinks dotted box: when the
verse has no translation tip and was not reached via search, the box
would otherwise render with no anchors. Because templatedTable is a
jQuery collection of three sibling top-level elements (not a single
container), the prune must filter the element out of the collection
itself — calling .remove() on a detached top-level element does not
prevent qtip from re-attaching it via content.text:templatedTable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(search): route semantic related verses through shared Passage pipeline

Rewrite runSemanticRelatedVerses to mirror runRelatedVerses (lexical flow):
build an NRSV Passage from the full ranked list, map to the user's
versification with VersificationsMapper.map, and hand to
buildCombinedVerseBasedResults. Drops the 50-verse cap, the manual
DefaultKeyList/HashSet accumulator, per-ref it.next()-only mapping, the
local countOnly branch, and the hand-rolled getResultsFromTrimmedKeys
call (display-mode fix from 8780d60 now comes for free via the shared
helper). Results are canonical-ordered and dedup'd by RangedPassage
semantics; 1->N cross-v11n mappings (e.g. Psalm titling) are now kept.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* update version number

---------

Co-authored-by: vercaemert <nvercaemert@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Nathan Vercaemert <nathan.vercaemert@gmail.com>
@nathanvercaemert nathanvercaemert merged commit 6dde084 into copy-button May 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant