• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JamesBrill / react-speech-recognition / 14200126755

01 Apr 2025 03:47PM UTC coverage: 40.406% (-53.8%) from 94.226%
14200126755

Pull #247

github

smorimoto
_

Signed-off-by: Sora Morimoto <sora@morimoto.io>
Pull Request #247: TypeScript

21 of 25 branches covered (84.0%)

Branch coverage included in aggregate %.

60 of 111 new or added lines in 8 files covered. (54.05%)

238 of 616 relevant lines covered (38.64%)

1.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.0
/src/utils.ts
1
import type { Phrase } from "./types";
2

3
declare global {
4
  interface Window {
5
    webkitAudioContext?: typeof AudioContext;
6
  }
7
}
8

9
const concatTranscripts = (...transcriptParts: string[]) => {
1✔
10
  return transcriptParts
9✔
11
    .map((t) => t.trim())
9✔
12
    .join(" ")
9✔
13
    .trim();
9✔
14
};
9✔
15

16
// The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
17
const optionalParam = /\s*\((.*?)\)\s*/g;
1✔
18
const optionalRegex = /(\(\?:[^)]+\))\?/g;
1✔
19
const namedParam = /(\(\?)?:\w+/g;
1✔
20
const splatParam = /\*/g;
1✔
21
const escapeRegExp = /[-{}[\]+?.,\\^$|#]/g;
1✔
22
const commandToRegExp = (command: Phrase) => {
1✔
23
  if (command instanceof RegExp) {
×
24
    return new RegExp(command.source, "i");
×
25
  }
×
26
  command = command
×
27
    .replace(escapeRegExp, "\\$&")
×
28
    .replace(optionalParam, "(?:$1)?")
×
29
    .replace(namedParam, (match, optional) => {
×
30
      return optional ? match : "([^\\s]+)";
×
31
    })
×
32
    .replace(splatParam, "(.*?)")
×
33
    .replace(optionalRegex, "\\s*$1?\\s*");
×
34
  return new RegExp("^" + command + "$", "i");
×
35
};
×
36

37
// this is from https://github.com/aceakash/string-similarity
38
const compareTwoStringsUsingDiceCoefficient = (
1✔
NEW
39
  first: string,
×
NEW
40
  second: string,
×
NEW
41
) => {
×
42
  first = first.replace(/\s+/g, "").toLowerCase();
×
43
  second = second.replace(/\s+/g, "").toLowerCase();
×
44

45
  if (!first.length && !second.length) return 1; // if both are empty strings
×
46
  if (!first.length || !second.length) return 0; // if only one is empty string
×
47
  if (first === second) return 1; // identical
×
48
  if (first.length === 1 && second.length === 1) return 0; // both are 1-letter strings
×
49
  if (first.length < 2 || second.length < 2) return 0; // if either is a 1-letter string
×
50

NEW
51
  const firstBigrams = new Map<string, number>();
×
52
  for (let i = 0; i < first.length - 1; i++) {
×
53
    const bigram = first.substring(i, i + 2);
×
NEW
54
    const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram)! + 1 : 1;
×
55

56
    firstBigrams.set(bigram, count);
×
57
  }
×
58

59
  let intersectionSize = 0;
×
60
  for (let i = 0; i < second.length - 1; i++) {
×
61
    const bigram = second.substring(i, i + 2);
×
NEW
62
    const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram)! : 0;
×
63

64
    if (count > 0) {
×
65
      firstBigrams.set(bigram, count - 1);
×
66
      intersectionSize++;
×
67
    }
×
68
  }
×
69

70
  return (2.0 * intersectionSize) / (first.length + second.length - 2);
×
71
};
×
72

73
const browserSupportsPolyfills = () => {
1✔
74
  return (
×
75
    typeof window !== "undefined" &&
×
76
    window.navigator !== undefined &&
×
77
    window.navigator.mediaDevices !== undefined &&
×
78
    window.navigator.mediaDevices.getUserMedia !== undefined &&
×
79
    (window.AudioContext !== undefined ||
×
80
      window.webkitAudioContext !== undefined)
×
81
  );
82
};
×
83

84
export {
85
  concatTranscripts,
86
  commandToRegExp,
87
  compareTwoStringsUsingDiceCoefficient,
88
  browserSupportsPolyfills,
89
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc