Skip to content

Commit 2c39190

Browse files
authored
fix: Don't truncate speech containing , (#26)
1 parent 2354c96 commit 2c39190

File tree

3 files changed

+62
-21
lines changed

3 files changed

+62
-21
lines changed

.changeset/quick-goats-sniff.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"screen-reader-testing-library": patch
3+
---
4+
5+
Speech containing a comma is no longer truncated
6+
7+
For example, `Choose time, selected time is ...` previously resulted in `["Choose tim"]`.
8+
The previous speech parser only used a regular expression which cannot handle context-sensitive languages.

src/__tests__/speechLogParser.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ it("ignores commands", () => {
200200
"Search…",
201201
],
202202
Array [
203-
"Too much output to announc",
204-
"",
203+
"Too much output to announce, navigate to rows manually to readteardown JestAssertionError: expect(received).toEqual(expected) // deep equality - Expected - 2 + Received + 2 Array [ Array [ + \\"angChangeCommand (\\\\",
205204
],
206205
Array [
207206
"nvda.ini (Working Tree) - nvda-snapshot-testing - Visual Studio Code",
@@ -217,7 +216,7 @@ it("ignores commands", () => {
217216
"complementary landmark",
218217
],
219218
Array [
220-
"Terminal ",
219+
"Terminal 2, PowerShell Integrated Console",
221220
"edit",
222221
"blank",
223222
],
@@ -234,3 +233,20 @@ it("ignores commands", () => {
234233
]
235234
`);
236235
});
236+
237+
it("is context sensitive", () => {
238+
expect(
239+
extractSpeechLines(
240+
"Speaking [LangChangeCommand ('en'), 'clickable', 'main landmark', 'button', 'Choose time, selected time is 12:00 AM']"
241+
)
242+
).toMatchInlineSnapshot(`
243+
Array [
244+
Array [
245+
"clickable",
246+
"main landmark",
247+
"button",
248+
"Choose time, selected time is 12:00 AM",
249+
],
250+
]
251+
`);
252+
});

src/logParser.js

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,44 @@ function extractSpeechLines(nvdaLog) {
1010
})
1111
.map((line) => {
1212
// In: "Speaking ['speech1', 'speech2', 'speech 3']"
13-
// Out: "['speech1', 'speech2', 'speech 3']"
13+
// Out: "'speech1', 'speech2', 'speech 3'"
1414
const listText = line.trim().replace(/^Speaking \[([^\]]+)\]/, "$1");
1515

16-
// In: "['speech1', 'speech2', 'speech 3']"
17-
// Out: the corresponding array structure in JS with added quotes
18-
return listText
19-
.split(",")
20-
.map((rawSpeech) => {
21-
const speech = rawSpeech.trim();
22-
if (speech.startsWith("'")) {
23-
return speech.slice(1, -1);
16+
// light-weight parser for
17+
// In: "'speech1', 'speech2, other', 'speech 3'"
18+
// Put: ['speech1', 'speech2, other', 'speech 3']
19+
/**
20+
* @type {string[]}
21+
*/
22+
const spoken = [];
23+
/**
24+
* @type {'type' | 'command' | 'speech'}
25+
*/
26+
let currentlyParsing = "type";
27+
let speech = "";
28+
for (const token of listText) {
29+
if (currentlyParsing === "type") {
30+
if (token === "'") {
31+
currentlyParsing = "speech";
32+
} else if (!/(\s|,)/.test(token)) {
33+
currentlyParsing = "command";
2434
}
25-
// ignore commands for now
26-
return null;
27-
})
28-
.filter(
29-
/**
30-
* @returns {speech is string}
31-
*/
32-
(speech) => speech !== null
33-
);
35+
} else if (currentlyParsing === "command") {
36+
if (token === ",") {
37+
currentlyParsing = "type";
38+
}
39+
} else if (currentlyParsing === "speech") {
40+
if (token === "'") {
41+
spoken.push(speech);
42+
speech = "";
43+
currentlyParsing = "type";
44+
} else {
45+
speech += token;
46+
}
47+
}
48+
}
49+
50+
return spoken;
3451
});
3552
}
3653

0 commit comments

Comments
 (0)