Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a6ee264
Fix enable disable of passages in passages basket and document
linearcombination Jan 24, 2026
5ad0564
Fill in each missing localized book name with non localized book name
linearcombination Jan 30, 2026
4aefa10
Better naming of local vars
linearcombination Jan 30, 2026
b0e33ef
Passages: Handle up to two languages
linearcombination Jan 30, 2026
f1dac87
Fix runtime bug if only one language chosen
linearcombination Jan 31, 2026
e15c595
Get rid of unnecessary extra var declaration
linearcombination Jan 31, 2026
3336314
Reformat string to fit preferred width
linearcombination Jan 31, 2026
d88b0c7
Tighter typing
linearcombination Jan 31, 2026
ac3f5ac
Handle case where resource type is not valid
linearcombination Jan 31, 2026
b8da61d
O(n^2) -> O(n) on lookup
linearcombination Jan 31, 2026
fb7cc06
Reset passages stores when language(s) change
linearcombination Jan 31, 2026
6d5683b
Reuse doc.reviewers_guide.model.BibleReference
linearcombination Jan 31, 2026
7d945e9
Small refactor for cleanness
linearcombination Jan 31, 2026
476d051
Refactor generate_docx_document to DRY
linearcombination Jan 31, 2026
77cfbf9
Improve font styling for missing references
linearcombination Jan 31, 2026
1678d5c
Use Word styles to style passages and increase width
linearcombination Feb 1, 2026
5006380
Remove unused import
linearcombination Feb 3, 2026
626a549
Add and update a couple JS packages
linearcombination Feb 3, 2026
b672a9d
Adjust loading message based on language count
linearcombination Feb 3, 2026
0bbfe90
Pass the language code for passage reference from backend to front
linearcombination Feb 3, 2026
a821e84
Update passages models in frontend
linearcombination Feb 3, 2026
0665e1a
Improve handling of passages stores
linearcombination Feb 3, 2026
a54a319
Make sure passages basket keeps up to date with stores
linearcombination Feb 3, 2026
a75fbd2
Adjustments for updates in prior commits
linearcombination Feb 3, 2026
5b751fd
Filter out passages for a language when it is removed
linearcombination Feb 3, 2026
83054ef
Update state of checkbox according to passages already chosen
linearcombination Feb 3, 2026
0528c35
Updated python packages
linearcombination Feb 3, 2026
793b27d
Handle mypy errors after package upgrade
linearcombination Feb 3, 2026
753988d
Update state of checkbox according to passages already chosen
linearcombination Feb 4, 2026
09cbd3b
Make sure isAvailable always has latest state
linearcombination Feb 5, 2026
015e521
Update passages when languages chosen change
linearcombination Feb 5, 2026
05a2627
Fix frontend test
linearcombination Feb 6, 2026
c2aca07
Update or specify certain packages
linearcombination Feb 15, 2026
946af56
Whitespace formatting
linearcombination Feb 18, 2026
13b7fbf
Make passages basket appropriately reactive
linearcombination Feb 19, 2026
ea93a4e
Enable tighter scoping in frontend tests
linearcombination Feb 19, 2026
dfaee08
Split big frontend test file into multiple files
linearcombination Feb 19, 2026
904e930
Improve logic for when to show certain page elements
linearcombination Feb 19, 2026
f9ed0f4
Add frontend test
linearcombination Feb 19, 2026
1ef20f6
Add some timeouts to frontend tests
linearcombination Feb 19, 2026
5956bb3
Update playwright config
linearcombination Feb 19, 2026
0e48ca2
Put weasyprint package back in place
linearcombination Feb 19, 2026
90eecc9
See if playwright config change helps github actions ci speed
linearcombination Feb 20, 2026
6161634
Implement issue #266 https://github.com/WycliffeAssociates/DOC/issues…
linearcombination Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ endif

.PHONY: pipupgrade
pipupgrade: checkvenv
pip install --upgrade pip
# pip-tools is not ready for pip 26
pip install pip==25.2
# pip install --upgrade pip

.PHONY: pyupgrade
pyupgrade: checkvenv pipupgrade
# checks if pip-tools is installed
ifeq ("$(wildcard .venv/bin/pip-compile)","")
@echo "Installing Pip-tools..."
@pip install --no-cache-dir pip-tools
# @pip install --no-cache-dir pip-tools
# pip-tools is not ready for pip 26
@pip install --no-cache-dir pip-tools==7.5.2
endif

ifeq ("$(wildcard .venv/bin/pip-sync)","")
@echo "Installing Pip-tools..."
@pip install --no-cache-dir pip-tools
# @pip install --no-cache-dir pip-tools
# pip-tools is not ready for pip 26
@pip install --no-cache-dir pip-tools==7.5.2
endif

.PHONY: install-cython
Expand Down
70 changes: 39 additions & 31 deletions backend/doc/domain/resource_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
from filelock import FileLock
from pydantic import HttpUrl, ValidationError


logger = settings.logger(__name__)

fetch_source_data_cache: TTLCache[str, SourceData] = TTLCache(
Expand Down Expand Up @@ -821,24 +820,16 @@ def get_book_codes_for_lang_(
manifest_name = book_codes_and_names_localized_from_manifest.get(
code, ""
)
if not name and manifest_name:
book_codes_and_names_localized.append(
(
code,
maybe_correct_book_name(
lang_code, normalize_localized_book_name(manifest_name)
),
)
)
else:
book_codes_and_names_localized.append(
(
code,
maybe_correct_book_name(
lang_code, normalize_localized_book_name(name)
),
)
chosen_name = name or manifest_name
book_codes_and_names_localized.append(
(
code,
maybe_correct_book_name(
lang_code,
normalize_localized_book_name(chosen_name),
),
)
)
elif (
use_localized_book_name
and len(repo_components) > 2
Expand All @@ -862,7 +853,8 @@ def get_book_codes_for_lang_(
(
repo_components[1],
maybe_correct_book_name(
lang_code, normalize_localized_book_name(book_name_)
lang_code,
normalize_localized_book_name(book_name_),
),
)
)
Expand All @@ -882,14 +874,22 @@ def get_book_codes_for_lang_(
)
logger.debug("book_codes_and_names: %s", book_codes_and_names)
logger.debug("book_codes_and_names_localized: %s", book_codes_and_names_localized)
if not book_codes_and_names_localized or any(
name == "" for _, name in book_codes_and_names_localized
):
unique_values = unique_book_codes(book_codes_and_names)
else:
unique_values = unique_book_codes(book_codes_and_names_localized)
localized_map: dict[str, str] = {
code: name for code, name in book_codes_and_names_localized
}
non_localized_map: dict[str, str] = {
code: name for code, name in book_codes_and_names
}
merged: list[tuple[str, str]] = []
for code in set(localized_map) | set(non_localized_map):
name = localized_map.get(code, "")
if not name:
name = non_localized_map.get(code, "")
merged.append((code, name))
unique_values = unique_book_codes(merged)
return sorted(
unique_values, key=lambda book_code_and_name: book_id_map[book_code_and_name[0]]
unique_values,
key=lambda book_code_and_name: book_id_map[book_code_and_name[0]],
)


Expand Down Expand Up @@ -1212,11 +1212,14 @@ def nt_survey_rg_passages(
resource_dir: str = settings.EN_RG_DIR,
) -> list[BibleReference]:
"""
>>> from doc.domain import resource_lookup
>>> ();rg_books = resource_lookup.nt_survey_rg_passages() ;() # doctest: +ELLIPSIS
(...)
>>> rg_books[0]
BibleReference(book_code='mat', book_name='Matthew', start_chapter=2, start_chapter_verse_ref='1-12', end_chapter=None, end_chapter_verse_ref=None)
Returns the list of all NT RG passages from the docx_file_path, but with
book names localized for language chosen.

>>> from doc.domain import resource_lookup
>>> ();rg_books = resource_lookup.nt_survey_rg_passages() ;() # doctest: +ELLIPSIS
(...)
>>> rg_books[0]
BibleReference(book_code='mat', book_name='Matthew', start_chapter=2, start_chapter_verse_ref='1-12', end_chapter=None, end_chapter_verse_ref=None)
"""
path = join(resource_dir, docx_file_path)
rg_books = get_rg_books(
Expand All @@ -1241,6 +1244,7 @@ def nt_survey_rg_passages(
maybe_localized_book_name = book_name_map.get(
bible_reference.book_code, bible_reference.book_name
)
bible_reference.lang_code = lang_code
bible_reference.book_name = maybe_localized_book_name
return bible_references

Expand Down Expand Up @@ -1283,6 +1287,7 @@ def ot_survey_rg1_passages(
maybe_localized_book_name = book_name_map.get(
bible_reference.book_code, bible_reference.book_name
)
bible_reference.lang_code = lang_code
bible_reference.book_name = maybe_localized_book_name
return bible_references

Expand Down Expand Up @@ -1325,6 +1330,7 @@ def ot_survey_rg2_passages(
maybe_localized_book_name = book_name_map.get(
bible_reference.book_code, bible_reference.book_name
)
bible_reference.lang_code = lang_code
bible_reference.book_name = maybe_localized_book_name
return bible_references

Expand Down Expand Up @@ -1367,6 +1373,7 @@ def ot_survey_rg3_passages(
maybe_localized_book_name = book_name_map.get(
bible_reference.book_code, bible_reference.book_name
)
bible_reference.lang_code = lang_code
bible_reference.book_name = maybe_localized_book_name
return bible_references

Expand Down Expand Up @@ -1409,6 +1416,7 @@ def ot_survey_rg4_passages(
maybe_localized_book_name = book_name_map.get(
bible_reference.book_code, bible_reference.book_name
)
bible_reference.lang_code = lang_code
bible_reference.book_name = maybe_localized_book_name
return bible_references

Expand Down
15 changes: 11 additions & 4 deletions backend/doc/entrypoints/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Sequence
from typing import Sequence, cast

import celery.states
from celery.result import AsyncResult
Expand Down Expand Up @@ -113,21 +113,28 @@ async def resource_types(
Return the list of available resource types tuples for lang_code
with book_codes.
"""
return resource_lookup.resource_types(lang_code, book_codes)
return cast(
Sequence[tuple[str, str]], resource_lookup.resource_types(lang_code, book_codes)
)


@router.get("/book_codes_for_lang/{lang_code}")
async def book_codes_for_lang(lang_code: str) -> Sequence[tuple[str, str]]:
"""Return list of all available resource codes."""
return resource_lookup.book_codes_for_lang(lang_code)
return cast(
Sequence[tuple[str, str]], resource_lookup.book_codes_for_lang(lang_code)
)


@router.get("/book_codes_for_lang_from_usfm_only/{lang_code}")
async def book_codes_for_lang_from_usfm_only(
lang_code: str,
) -> Sequence[tuple[str, str]]:
"""Return list of all available resource codes."""
return resource_lookup.book_codes_for_lang_from_usfm_only(lang_code)
return cast(
Sequence[tuple[str, str]],
resource_lookup.book_codes_for_lang_from_usfm_only(lang_code),
)


@router.get("/chapters_in_books")
Expand Down
4 changes: 4 additions & 0 deletions backend/doc/reviewers_guide/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Part2Item(BaseModel):

@final
class BibleReference(BaseModel):
lang_code: Optional[str]
book_code: str
book_name: str
start_chapter: ChapterNum
Expand All @@ -32,6 +33,7 @@ class BibleReference(BaseModel):
def __hash__(self: "BibleReference") -> int:
return hash(
(
self.lang_code,
self.book_code,
self.book_name,
self.start_chapter,
Expand All @@ -45,13 +47,15 @@ def __eq__(self: "BibleReference", other: object) -> bool:
if not isinstance(other, BibleReference):
return NotImplemented
return (
self.lang_code,
self.book_code,
self.book_name,
self.start_chapter,
self.start_chapter_verse_ref,
self.end_chapter,
self.end_chapter_verse_ref,
) == (
other.lang_code,
other.book_code,
other.book_name,
other.start_chapter,
Expand Down
2 changes: 2 additions & 0 deletions backend/doc/reviewers_guide/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def get_ordinal_bible_reference(
start_chapter = chapter_verse_components[0]
start_chapter_verse_ref = chapter_verse_components[1]
bible_reference = BibleReference(
lang_code=None,
book_code=book_code,
book_name=book_name,
start_chapter=int(start_chapter),
Expand Down Expand Up @@ -176,6 +177,7 @@ def get_bible_reference_spanning_chapter_boundary(
chapter_verse_components[2] if len(chapter_verse_components) >= 3 else None
)
bible_reference = BibleReference(
lang_code=None,
book_code=book_code,
book_name=book_name,
start_chapter=int(start_chapter),
Expand Down
55 changes: 55 additions & 0 deletions backend/doc/utils/docx_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from docx import Document
from docx.document import Document as DocxDocument
from docx.enum.style import WD_STYLE_TYPE
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import RGBColor
Expand Down Expand Up @@ -217,3 +218,57 @@ def style_superscripts(
position = OxmlElement("w:position")
position.set(qn("w:val"), str(lift_half_points))
rPr.append(position)


def _ensure_character_style_based_on_default(
doc: DocxDocument,
name: str,
*,
color: RGBColor | None = None,
italic: bool | None = None,
) -> None:
styles = doc.styles
if name in styles:
return
style = styles.add_style(name, WD_STYLE_TYPE.CHARACTER)
# ---- Base on Default Paragraph Font ----
style_elm = style._element
based_on = OxmlElement("w:basedOn")
based_on.set(qn("w:val"), "DefaultParagraphFont")
style_elm.insert(0, based_on)
# ---- Only override what is explicitly requested ----
font = style.font
if color is not None:
font.color.rgb = color
if italic is not None:
font.italic = italic


def ensure_reference_styles(
doc: DocxDocument,
*,
available_color: RGBColor | None = None,
unavailable_color: RGBColor,
) -> None:
"""
Create semantic character styles for passage references.

AvailableReference:
- Based on Default Paragraph Font
- Usually no overrides (inherits document defaults)

UnavailableReference:
- Based on Default Paragraph Font
- Lighter color + italics to signal intentional absence
"""
_ensure_character_style_based_on_default(
doc,
"AvailableReference",
color=available_color, # usually None
)
_ensure_character_style_based_on_default(
doc,
"UnavailableReference",
color=unavailable_color,
italic=True,
)
6 changes: 4 additions & 2 deletions backend/doc/utils/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ def epub_filepath(


def docx_filepath(
document_request_key: str, output_dir: str = settings.DOCUMENT_OUTPUT_DIR
document_request_key: str,
prefix: str = "",
output_dir: str = settings.DOCUMENT_OUTPUT_DIR,
) -> str:
"""Given document_request_key, return the docx output file path."""
return join(output_dir, "{}.docx".format(document_request_key))
return join(output_dir, "{}{}.docx".format(prefix, document_request_key))
Loading