From 392e2dfb4f053815399196d8d5fcb89b6b37c9bb Mon Sep 17 00:00:00 2001 From: linearcombination <4829djaskdfj@gmail.com> Date: Fri, 10 Jul 2026 11:26:42 -0700 Subject: [PATCH 1/4] Filter out (See: ...) forms in TW, TN, and (in the future maybe, TA) By request of PO --- backend/doc/markdown_transforms/link_regexes.py | 6 +++++- .../markdown_transforms/markdown_transformer.py | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/doc/markdown_transforms/link_regexes.py b/backend/doc/markdown_transforms/link_regexes.py index cf3c3d03..9dbec6d6 100644 --- a/backend/doc/markdown_transforms/link_regexes.py +++ b/backend/doc/markdown_transforms/link_regexes.py @@ -2,7 +2,6 @@ import re - # Handle TW wikilink inner text TW_RC_LINK_RE = re.compile( ( @@ -185,3 +184,8 @@ BC_MARKDOWN_LINK_RE = re.compile( r"\[(?P.+?)\] *\(\.\.\/(?Particles.+?)\)" ) + +SEE_PARENTHETICAL_RE = re.compile( + r"\(\s*See:\s*.*?\)", + re.IGNORECASE, +) diff --git a/backend/doc/markdown_transforms/markdown_transformer.py b/backend/doc/markdown_transforms/markdown_transformer.py index b0d1e66e..436b2844 100644 --- a/backend/doc/markdown_transforms/markdown_transformer.py +++ b/backend/doc/markdown_transforms/markdown_transformer.py @@ -8,6 +8,7 @@ from doc.domain.model import ResourceRequest from doc.markdown_transforms.link_regexes import ( RC_QUESTION_LINK_RE, + SEE_PARENTHETICAL_RE, TA_MARKDOWN_HTTPS_LINK_RE, TA_PREFIXED_MARKDOWN_HTTPS_LINK_RE, TA_PREFIXED_MARKDOWN_LINK_RE, @@ -34,7 +35,6 @@ from doc.utils.file_utils import read_file from doc.utils.tw_utils import localized_translation_word - logger = settings.logger(__name__) TRANSLATION_WORD_ANCHOR_LINK_FMT_STR: str = "[{}](#{}-{})" @@ -124,6 +124,8 @@ def transform_tw_links( source = transform_rc_obe_tw_links( source, lang_code, resource_requests, translation_words_dict ) + + source = transform_see_parenthetical_links(source) return source @@ -158,6 +160,7 @@ def transform_ta_and_tn_links( source = transform_tn_missing_book_code_markdown_links_no_paren(source) source = transform_tn_obs_markdown_links(source) source = transform_rc_question_links(source) + source = transform_see_parenthetical_links(source) return source @@ -1045,3 +1048,14 @@ def wiki_link_parser( for link in finditer(wiki_link_re, source) ] return links + + +def transform_see_parenthetical_links( + source: str, + see_parenthetical_re: re.Pattern[str] = SEE_PARENTHETICAL_RE, +) -> str: + """ + Remove any parenthetical string beginning with 'See:'. + Example: '(See: something)' -> '' + """ + return see_parenthetical_re.sub("", source) From 8f878e967bbeac596c2cbcbb8abefcf6e3593271 Mon Sep 17 00:00:00 2001 From: linearcombination <4829djaskdfj@gmail.com> Date: Fri, 10 Jul 2026 12:10:21 -0700 Subject: [PATCH 2/4] Handle localized regex forms of '(See: ...)' --- backend/doc/markdown_transforms/link_regexes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/doc/markdown_transforms/link_regexes.py b/backend/doc/markdown_transforms/link_regexes.py index 9dbec6d6..619e49ec 100644 --- a/backend/doc/markdown_transforms/link_regexes.py +++ b/backend/doc/markdown_transforms/link_regexes.py @@ -185,7 +185,8 @@ r"\[(?P.+?)\] *\(\.\.\/(?Particles.+?)\)" ) + SEE_PARENTHETICAL_RE = re.compile( - r"\(\s*See:\s*.*?\)", + r"\((?P[^():]+:)\s*.*?\)", re.IGNORECASE, ) From db9c52593d8bf006119aa12d2bc95635ab61a854 Mon Sep 17 00:00:00 2001 From: linearcombination <4829djaskdfj@gmail.com> Date: Tue, 14 Jul 2026 14:15:21 -0700 Subject: [PATCH 3/4] Fix regex overreach and add unit test Per reviewer comments --- backend/doc/markdown_transforms/link_regexes.py | 2 +- .../doc/markdown_transforms/markdown_transformer.py | 10 +++++----- tests/unit/test_markdown_transformers.py | 13 +++++++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/backend/doc/markdown_transforms/link_regexes.py b/backend/doc/markdown_transforms/link_regexes.py index 619e49ec..1258bf54 100644 --- a/backend/doc/markdown_transforms/link_regexes.py +++ b/backend/doc/markdown_transforms/link_regexes.py @@ -187,6 +187,6 @@ SEE_PARENTHETICAL_RE = re.compile( - r"\((?P[^():]+:)\s*.*?\)", + r"\((?P[^\s():]+:)\s*.*?\)", re.IGNORECASE, ) diff --git a/backend/doc/markdown_transforms/markdown_transformer.py b/backend/doc/markdown_transforms/markdown_transformer.py index 436b2844..a3014a6d 100644 --- a/backend/doc/markdown_transforms/markdown_transformer.py +++ b/backend/doc/markdown_transforms/markdown_transformer.py @@ -125,7 +125,7 @@ def transform_tw_links( source, lang_code, resource_requests, translation_words_dict ) - source = transform_see_parenthetical_links(source) + source = remove_see_colon_prefixed_parenthicals(source) return source @@ -160,7 +160,7 @@ def transform_ta_and_tn_links( source = transform_tn_missing_book_code_markdown_links_no_paren(source) source = transform_tn_obs_markdown_links(source) source = transform_rc_question_links(source) - source = transform_see_parenthetical_links(source) + source = remove_see_colon_prefixed_parenthicals(source) return source @@ -1050,12 +1050,12 @@ def wiki_link_parser( return links -def transform_see_parenthetical_links( +def remove_see_colon_prefixed_parenthicals( source: str, see_parenthetical_re: re.Pattern[str] = SEE_PARENTHETICAL_RE, ) -> str: """ - Remove any parenthetical string beginning with 'See:'. - Example: '(See: something)' -> '' + Remove any parenthetical string beginning with localized '(See:'. + Example: '(Veja: foobar)' -> '' """ return see_parenthetical_re.sub("", source) diff --git a/tests/unit/test_markdown_transformers.py b/tests/unit/test_markdown_transformers.py index d8ea853d..39d6f2b3 100644 --- a/tests/unit/test_markdown_transformers.py +++ b/tests/unit/test_markdown_transformers.py @@ -148,3 +148,16 @@ def test_remove_pagination_symbols_from_commentary() -> None: """ source = markdown_transformer.remove_pagination_symbols(source) assert expected == source + + +def test_remove_localized_see_colon_patterns_only() -> None: + source = """Nullam eu ante vel est convallis dignissim. Fusce suscipit, wisi nec facilisis facilisis, est dui fermentum leo, quis tempor ligula erat quis odio. Nunc porta vulputate tellus. Nunc rutrum turpis sed pede. Sed bibendum. Aliquam posuere. Nunc aliquet, augue nec adipiscing interdum, lacus tellus malesuada massa, quis varius mi purus non odio. Pellentesque condimentum, magna ut suscipit hendrerit, ipsum augue ornare nulla, non luctus diam neque sit amet urna. Curabitur vulputate vestibulum lorem. Fusce sagittis, libero non molestie mollis, magna orci ultrices dolor, at vulputate neque nulla lacinia eros. Sed id ligula quis est convallis tempor precious in his sight (Isaiah 43:4). Curabitur lacinia pulvinar nibh keep provisions (see 2 Chronicles 8:3). Nam a sapien devour one another (Galatians 5:15). +(See: [[rc://...]]) +(Veja: Altar) +""" + expected = """Nullam eu ante vel est convallis dignissim. Fusce suscipit, wisi nec facilisis facilisis, est dui fermentum leo, quis tempor ligula erat quis odio. Nunc porta vulputate tellus. Nunc rutrum turpis sed pede. Sed bibendum. Aliquam posuere. Nunc aliquet, augue nec adipiscing interdum, lacus tellus malesuada massa, quis varius mi purus non odio. Pellentesque condimentum, magna ut suscipit hendrerit, ipsum augue ornare nulla, non luctus diam neque sit amet urna. Curabitur vulputate vestibulum lorem. Fusce sagittis, libero non molestie mollis, magna orci ultrices dolor, at vulputate neque nulla lacinia eros. Sed id ligula quis est convallis tempor precious in his sight (Isaiah 43:4). Curabitur lacinia pulvinar nibh keep provisions (see 2 Chronicles 8:3). Nam a sapien devour one another (Galatians 5:15). + + +""" + source = markdown_transformer.remove_see_colon_prefixed_parenthicals(source) + assert expected == source From 265b608bbad08ccde783a473707d19367f749134 Mon Sep 17 00:00:00 2001 From: linearcombination <4829djaskdfj@gmail.com> Date: Fri, 17 Jul 2026 19:56:57 -0700 Subject: [PATCH 4/4] Fix test Data API changed values returned so test must change to adapt --- frontend/tests/e2e/doc_test_3.ts | 38 +++++++------------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/frontend/tests/e2e/doc_test_3.ts b/frontend/tests/e2e/doc_test_3.ts index 65f7a55e..32134b18 100644 --- a/frontend/tests/e2e/doc_test_3.ts +++ b/frontend/tests/e2e/doc_test_3.ts @@ -61,9 +61,7 @@ test('ordering of books in document title(s) and body', async ({ page }) => { await page.getByPlaceholder('Search Heart Languages').fill('ont') await page.getByText('Ontenu').click() await page.getByRole('button', { name: 'Next' }).click() - await page.getByText('Matyu').click({ timeout: 32_000 }) - await page.getByText('Mak').click() - await page.getByText('Luk', { exact: true }).click() + await page.getByText('Efesus').click({ timeout: 32_000 }) await page.getByRole('button', { name: 'Next' }).click() await page.getByText('Unlocked Literal Bible').first().click() await page.getByText('Regular').click() @@ -82,44 +80,24 @@ test('ordering of books in document title(s) and body', async ({ page }) => { const page1 = await page1Promise // Perform text expectations on the popup page await expect(page1.locator('body')).toContainText( - 'Tok Pisin (Tok Pisin): Unlocked Literal Bible for Matyu, Mak, Luk' - ) - await expect(page1.locator('body')).toContainText( - 'Ontenu (Ontenu): Regular for Matthew, Maki, Luk' + 'Tok Pisin (Tok Pisin): Unlocked Literal Bible for Efesus' ) + await expect(page1.locator('body')).toContainText('Ontenu (Ontenu): Regular for Efeses') - // Order assertions const headings = await page1.locator('h2').allTextContents() // Ensure expected headings are present - expect(headings).toContain('Matyu') - expect(headings).toContain('Matthew') - expect(headings).toContain('Mak') - expect(headings).toContain('Maki') - expect(headings).toContain('Luk') + expect(headings).toContain('Efesus') + expect(headings).toContain('Efeses') + // Order assertions // Find the positions of each - const index1 = headings.indexOf('Matyu') - const index2 = headings.indexOf('Matthew') - const index3 = headings.indexOf('Mak') - const index4 = headings.indexOf('Maki') - const index5 = headings.indexOf('Luk') + const index1 = headings.indexOf('Efesus') + const index2 = headings.indexOf('Efeses') // Ensure all were found expect(index1).not.toBe(-1) expect(index2).not.toBe(-1) - expect(index3).not.toBe(-1) - expect(index4).not.toBe(-1) - expect(index5).not.toBe(-1) // Check the order expect(index1).toBeLessThan(index2) - expect(index1).toBeLessThan(index3) - expect(index2).toBeLessThan(index3) - expect(index1).toBeLessThan(index4) - expect(index2).toBeLessThan(index4) - expect(index3).toBeLessThan(index4) - expect(index1).toBeLessThan(index5) - expect(index2).toBeLessThan(index5) - expect(index3).toBeLessThan(index5) - expect(index4).toBeLessThan(index5) })