Skip to content

Commit 50310ed

Browse files
authored
Merge pull request #106 from ContentSquare/fix/syllable-bug
fix(visual-engine): syllables alternations between nodes of text
2 parents 8d4f04d + 80b493e commit 50310ed

2 files changed

Lines changed: 73 additions & 22 deletions

File tree

packages/visual-engine/src/adaptTextContent.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ import { AnaliseTextFn, Liaison, Syllable } from '@readapt/text-engine'
22
import { ColoredItem, Settings } from '@readapt/settings'
33
import xor from 'lodash/xor'
44

5+
interface Context {
6+
processedSyllables: number
7+
}
8+
59
const buildAdaptTextContentForText =
610
(analyse: AnaliseTextFn) =>
711
(htmlText: string, settings: Settings, liaisonsPhonemes: Set<string>): string => {
8-
const adaptNodeForText = buildAdaptTextNodeForText(analyse, settings, liaisonsPhonemes)
12+
const context: Context = {
13+
processedSyllables: 0
14+
}
15+
const adaptNodeForText = buildAdaptTextNodeForText(analyse, settings, liaisonsPhonemes, context)
916

1017
return adaptNodeForText(htmlText)
1118
}
@@ -15,7 +22,7 @@ const buildAdaptTextContentForText =
1522
* adaptTextNode manipulates the DOM to add readapt styles and classes
1623
*/
1724
const buildAdaptTextNodeForText =
18-
(analyse: AnaliseTextFn, settings: Settings, liaisonsPhonemes: Set<string>) =>
25+
(analyse: AnaliseTextFn, settings: Settings, liaisonsPhonemes: Set<string>, context: Context) =>
1926
(textToAdapt: string): string => {
2027
if (!hasTextRulesSettings(settings)) {
2128
return `${textToAdapt}`
@@ -26,7 +33,7 @@ const buildAdaptTextNodeForText =
2633
const classList = []
2734

2835
if (settings.syllableActive) {
29-
const syllable = isSyllable(textIndex, textEngineResult.syllables)
36+
const syllable = isSyllable(textIndex, textEngineResult.syllables, context)
3037
if (syllable) {
3138
classList.push(syllable)
3239
}
@@ -74,6 +81,8 @@ const buildAdaptTextNodeForText =
7481
}
7582
})
7683

84+
context.processedSyllables += textEngineResult.syllables.length
85+
7786
return `${textAdapted.join('')}`
7887
}
7988

@@ -98,7 +107,10 @@ const buildAdaptTextContent =
98107
return NodeFilter.FILTER_ACCEPT
99108
}
100109
})
101-
const adaptNode = buildAdaptTextNode(analyse, settings, liaisonsPhonemes)
110+
const context: Context = {
111+
processedSyllables: 0
112+
}
113+
const adaptNode = buildAdaptTextNode(analyse, settings, liaisonsPhonemes, context)
102114
let currentNode
103115
while ((currentNode = treeWalker.nextNode())) {
104116
try {
@@ -124,7 +136,7 @@ const hasTextRulesSettings = (settings: Settings): boolean => {
124136

125137
const hasItemActive = (items: ColoredItem[]): boolean => items.some((item) => item.active)
126138

127-
const isSyllable = (charIndex: number, syllables: Syllable[]): string | undefined => {
139+
const isSyllable = (charIndex: number, syllables: Syllable[], context: Context): string | undefined => {
128140
const indexSyllable = syllables.findIndex(([initPos, endPos]: Syllable) => {
129141
return charIndex >= initPos && charIndex <= endPos
130142
})
@@ -133,7 +145,7 @@ const isSyllable = (charIndex: number, syllables: Syllable[]): string | undefine
133145
return
134146
}
135147

136-
return indexSyllable % 2 ? 'readapt-syllable-2' : 'readapt-syllable-1'
148+
return (indexSyllable + context.processedSyllables) % 2 ? 'readapt-syllable-2' : 'readapt-syllable-1'
137149
}
138150

139151
const findLiaison = (index: number, liaisons: Liaison[]) => {
@@ -178,7 +190,7 @@ const adaptPhoneme = (settings: Settings, phoneme: number): string[] => {
178190
* adaptTextNode manipulates the DOM to add readapt styles and classes
179191
*/
180192
const buildAdaptTextNode =
181-
(analyse: AnaliseTextFn, settings: Settings, liaisonsPhonemes: Set<string>) =>
193+
(analyse: AnaliseTextFn, settings: Settings, liaisonsPhonemes: Set<string>, context: Context) =>
182194
(textNode: Text): void => {
183195
const text = textNode.nodeValue
184196
if (!text) {
@@ -200,7 +212,7 @@ const buildAdaptTextNode =
200212
const classList = []
201213

202214
if (settings.syllableActive) {
203-
const syllable = isSyllable(textIndex, textEngineResult.syllables)
215+
const syllable = isSyllable(textIndex, textEngineResult.syllables, context)
204216
if (syllable) {
205217
classList.push(syllable)
206218
}
@@ -258,6 +270,8 @@ const buildAdaptTextNode =
258270
}
259271
})
260272

273+
context.processedSyllables += textEngineResult.syllables.length
274+
261275
// clean the node
262276
textNode.textContent = ''
263277
}

packages/visual-engine/tests/adaptHtmlElement.spec.ts

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,21 +119,58 @@ describe('visual engine tests', () => {
119119
expect(adaptedElement.innerHTML).toBe('<span class="readapt-content">save the w<span class="readapt-silent-letter">h</span>ale!</span>')
120120
})
121121

122-
it('should adapt syllables', () => {
123-
const settings = buildDefaultSettings('en')
124-
settings.syllableActive = true
125-
settings.syllableColor1 = '#5fa2ce'
126-
settings.syllableColor1 = '#59a14f'
127-
const pElement = `<p>hello</p>`
128-
document.body.innerHTML = `${pElement}`
129-
130-
adaptHtmlElement(document.body, settings, 'jsdom')
131-
132-
const adaptedElement = document.body.firstElementChild as HTMLElement
122+
describe('syllables', () => {
123+
it('should adapt syllables of one word', () => {
124+
const settings = buildDefaultSettings('en')
125+
settings.syllableActive = true
126+
settings.syllableColor1 = '#5fa2ce'
127+
settings.syllableColor2 = '#59a14f'
128+
const pElement = `<p>hello</p>`
129+
document.body.innerHTML = `${pElement}`
130+
131+
adaptHtmlElement(document.body, settings, 'jsdom')
132+
133+
const adaptedElement = document.body.firstElementChild as HTMLElement
134+
135+
expect(adaptedElement.innerHTML).toEqualIgnoringWhitespace(
136+
`<span class="readapt-content">
137+
<span class="readapt-syllable-1">hel</span>
138+
<span class="readapt-syllable-2">lo</span>
139+
</span>`
140+
)
141+
})
133142

134-
expect(adaptedElement.innerHTML).toBe(
135-
'<span class="readapt-content"><span class="readapt-syllable-1">hel</span><span class="readapt-syllable-2">lo</span></span>'
136-
)
143+
it('should alternate syllables between multiple elements', () => {
144+
const settings = buildDefaultSettings('en')
145+
settings.syllableActive = true
146+
settings.syllableColor1 = '#5fa2ce'
147+
settings.syllableColor2 = '#59a14f'
148+
const pElement = `
149+
<p>
150+
<a href="http://example.com/path-a/">hi</a>
151+
<a href="http://example.com/path-b/">hello</a>
152+
</p>
153+
`
154+
document.body.innerHTML = pElement
155+
156+
adaptHtmlElement(document.body, settings, 'jsdom')
157+
158+
const adaptedElement = document.body.firstElementChild as HTMLElement
159+
160+
expect(adaptedElement.innerHTML).toEqualIgnoringWhitespace(
161+
`
162+
<a href="http://example.com/path-a/">
163+
<span class="readapt-content">
164+
<span class="readapt-syllable-1">hi</span>
165+
</span>
166+
</a>
167+
<a href="http://example.com/path-b/">
168+
<span class="readapt-content">
169+
<span class="readapt-syllable-2">hel</span>
170+
<span class="readapt-syllable-1">lo</span>
171+
</span></a>`
172+
)
173+
})
137174
})
138175

139176
it('should adapt letters', () => {

0 commit comments

Comments
 (0)