@@ -1597,6 +1597,132 @@ describe('correctTranslatedContentStrings', () => {
15971597 // Valid table rows are not modified
15981598 expect ( fix ( '| a | b |\n| c | d |' , 'es' ) ) . toBe ( '| a | b |\n| c | d |' )
15991599 } )
1600+
1601+ test ( 'rejoins dangling heading markers (all languages)' , ( ) => {
1602+ const broken = '### \n {% data variables.product.github %} の使用'
1603+ const expected = '### {% data variables.product.github %} の使用'
1604+ for ( const lang of [ 'ja' , 'de' , 'es' , 'fr' , 'ko' , 'pt' , 'ru' , 'zh' ] ) {
1605+ expect ( fix ( broken , lang ) ) . toBe ( expected )
1606+ }
1607+ // All heading levels
1608+ expect ( fix ( '# \n Title' , 'ja' ) ) . toBe ( '# Title' )
1609+ expect ( fix ( '###### \n Title' , 'ja' ) ) . toBe ( '###### Title' )
1610+ // 0–3 leading spaces are accepted
1611+ expect ( fix ( ' ### \n Title' , 'ja' ) ) . toBe ( ' ### Title' )
1612+ // Valid headings are not modified
1613+ expect ( fix ( '### Already correct' , 'ja' ) ) . toBe ( '### Already correct' )
1614+ // 4-space indented heading-like text is not collapsed (looks like code)
1615+ expect ( fix ( ' ###\n code' , 'ja' ) ) . toBe ( ' ###\n code' )
1616+ // Shallow next-line indent (<6) is not collapsed
1617+ expect ( fix ( '### \n Title' , 'ja' ) ) . toBe ( '### \n Title' )
1618+ } )
1619+
1620+ test ( 'rejoins dangling blockquote markers (all languages)' , ( ) => {
1621+ const broken = '> \n {% data variables.product.github %} は preview 中です。'
1622+ const expected = '> {% data variables.product.github %} は preview 中です。'
1623+ for ( const lang of [ 'ja' , 'de' , 'es' , 'fr' , 'ko' , 'pt' , 'ru' , 'zh' ] ) {
1624+ expect ( fix ( broken , lang ) ) . toBe ( expected )
1625+ }
1626+ // 0–3 leading spaces are accepted
1627+ expect ( fix ( ' > \n Quote' , 'ja' ) ) . toBe ( ' > Quote' )
1628+ // Valid blockquotes are not modified
1629+ expect ( fix ( '> Already correct' , 'ja' ) ) . toBe ( '> Already correct' )
1630+ expect ( fix ( '>\n> Continued blockquote' , 'ja' ) ) . toBe ( '>\n> Continued blockquote' )
1631+ } )
1632+
1633+ test ( 'rejoins dangling bold-open after a marker (all languages)' , ( ) => {
1634+ const broken =
1635+ '* **\n {% data variables.product.prodname_copilot_short %}へのアクセス**。 More text'
1636+ const expected =
1637+ '* **{% data variables.product.prodname_copilot_short %}へのアクセス**。 More text'
1638+ for ( const lang of [ 'ja' , 'de' , 'es' , 'fr' , 'ko' , 'pt' , 'ru' , 'zh' ] ) {
1639+ expect ( fix ( broken , lang ) ) . toBe ( expected )
1640+ }
1641+ // Numbered list marker
1642+ expect ( fix ( '1. **\n Important**: text' , 'ja' ) ) . toBe ( '1. **Important**: text' )
1643+ // Heading marker
1644+ expect ( fix ( '### **\n Bold heading**' , 'ja' ) ) . toBe ( '### **Bold heading**' )
1645+ // Blockquote marker
1646+ expect ( fix ( '> **\n Quoted bold**' , 'ja' ) ) . toBe ( '> **Quoted bold**' )
1647+ // Table cell
1648+ expect ( fix ( '| **\n Cell bold** | x' , 'ja' ) ) . toBe ( '| **Cell bold** | x' )
1649+ // Bare `**` (no preceding marker) is not collapsed — could be a closing
1650+ // bold marker followed by legitimate indented continuation.
1651+ expect ( fix ( '**\n text' , 'ja' ) ) . toBe ( '**\n text' )
1652+ } )
1653+
1654+ test ( 'does not modify content inside fenced code blocks' , ( ) => {
1655+ // Markdown example inside ```md fence should be preserved verbatim
1656+ const fenced = '```md\n### \n Heading example\n```'
1657+ expect ( fix ( fenced , 'ja' ) ) . toBe ( fenced )
1658+ // Tilde fences are also respected
1659+ const tilde = '~~~md\n> \n Quote example\n~~~'
1660+ expect ( fix ( tilde , 'ja' ) ) . toBe ( tilde )
1661+ // Bold-open inside code fence
1662+ const boldFenced = '```md\n* **\n bold example**\n```'
1663+ expect ( fix ( boldFenced , 'ja' ) ) . toBe ( boldFenced )
1664+ } )
1665+
1666+ test ( 'does not modify YAML frontmatter' , ( ) => {
1667+ // Multiline YAML scalars and indented values must not be joined
1668+ const fm = `---
1669+ title: Example
1670+ intro: >
1671+ Multiline
1672+ continued
1673+ versions:
1674+ fpt: '*'
1675+ ---
1676+
1677+ ###
1678+ Real heading after frontmatter`
1679+ const expected = `---
1680+ title: Example
1681+ intro: >
1682+ Multiline
1683+ continued
1684+ versions:
1685+ fpt: '*'
1686+ ---
1687+
1688+ ### Real heading after frontmatter`
1689+ expect ( fix ( fm , 'ja' ) ) . toBe ( expected )
1690+ } )
1691+
1692+ test ( 'frontmatter containing fence-like characters does not break body fence tracking' , ( ) => {
1693+ // A multiline scalar in frontmatter that includes ``` (or ~~~) must
1694+ // NOT toggle the body's fence-tracking state. After frontmatter
1695+ // closes, dangling markers in the body should still be rejoined.
1696+ const fm = `---
1697+ title: Example
1698+ intro: |
1699+ \`\`\`
1700+ fence-like text inside frontmatter
1701+ \`\`\`
1702+ ---
1703+
1704+ ###
1705+ Real heading after frontmatter`
1706+ const expected = `---
1707+ title: Example
1708+ intro: |
1709+ \`\`\`
1710+ fence-like text inside frontmatter
1711+ \`\`\`
1712+ ---
1713+
1714+ ### Real heading after frontmatter`
1715+ expect ( fix ( fm , 'ja' ) ) . toBe ( expected )
1716+ } )
1717+
1718+ test ( 'does not collapse nested-list indented code blocks' , ( ) => {
1719+ // A list item followed by blank line + 6-space-indented "code" should
1720+ // be left alone because the marker line itself is empty (not a
1721+ // bare `>`/`#`/`* **` form), and the previous content line is not
1722+ // a heading/blockquote/bold-open marker.
1723+ const nested = '1. Run this command:\n\n gh auth login'
1724+ expect ( fix ( nested , 'ja' ) ) . toBe ( nested )
1725+ } )
16001726 } )
16011727
16021728 // ─── EDGE CASES ────────────────────────────────────────────────────
0 commit comments