@untemps/vocal 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,97 +1,100 @@
1
1
  {
2
- "name": "@untemps/vocal",
3
- "version": "1.2.1",
4
- "description": "Class wrapped around the SpeechRecognition Web API",
5
- "repository": "git@github.com:untemps/vocal.git",
6
- "keywords": [
7
- "Web Speech API",
8
- "SpeechRecognition",
9
- "speech",
10
- "speech-to-text",
11
- "javascript"
12
- ],
13
- "author": "Vincent Le Badezet <v.lebadezet@untemps.net>",
14
- "license": "MIT",
15
- "private": false,
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
- "main": "dist/index.js",
20
- "module": "dist/index.es.js",
21
- "file": [
22
- "dist"
23
- ],
24
- "devDependencies": {
25
- "@babel/cli": "^7.10.1",
26
- "@babel/core": "^7.10.2",
27
- "@babel/plugin-proposal-class-properties": "^7.8.3",
28
- "@babel/plugin-transform-runtime": "^7.10.1",
29
- "@babel/preset-env": "^7.9.6",
30
- "@rollup/plugin-babel": "^5.0.2",
31
- "@rollup/plugin-commonjs": "^12.0.0",
32
- "@rollup/plugin-node-resolve": "^8.0.0",
33
- "@semantic-release/changelog": "^5.0.1",
34
- "@semantic-release/git": "^9.0.0",
35
- "@semantic-release/github": "^7.0.7",
36
- "@testing-library/jest-dom": "^5.11.9",
37
- "babel-jest": "^26.0.1",
38
- "cross-env": "^7.0.2",
39
- "husky": "^4.2.5",
40
- "jest": "^26.0.1",
41
- "prettier": "^2.0.5",
42
- "rollup": "^2.12.0",
43
- "rollup-plugin-filesize": "^9.0.0",
44
- "rollup-plugin-terser": "^6.1.0",
45
- "rollup-plugin-visualizer": "^4.0.4",
46
- "semantic-release": "^17.0.7"
47
- },
48
- "dependencies": {
49
- "@untemps/user-permissions-utils": "^1.0.3"
50
- },
51
- "husky": {
52
- "hooks": {
53
- "pre-commit": "yarn test:ci && yarn prettier"
54
- }
55
- },
56
- "jest": {
57
- "coverageDirectory": "./coverage/",
58
- "collectCoverage": true,
59
- "setupFilesAfterEnv": [
60
- "<rootDir>/jest/jest.setup.js"
61
- ],
62
- "restoreMocks": true
63
- },
64
- "release": {
65
- "branches": [
66
- "main"
67
- ],
68
- "plugins": [
69
- [
70
- "@semantic-release/commit-analyzer",
71
- {
72
- "releaseRules": [
73
- {
74
- "type": "chore",
75
- "release": "patch"
76
- }
77
- ]
78
- }
79
- ],
80
- "@semantic-release/release-notes-generator",
81
- "@semantic-release/changelog",
82
- "@semantic-release/npm",
83
- "@semantic-release/git",
84
- "@semantic-release/github"
85
- ]
86
- },
87
- "scripts": {
88
- "dev": "cd dev && yarn && yarn start",
89
- "test": "jest -u --watch",
90
- "test:ci": "CI=true jest -u -b --coverage",
91
- "build": " rm -rf dist && yarn build:cjs && yarn build:es && yarn build:umd",
92
- "build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs rollup -c",
93
- "build:es": "cross-env NODE_ENV=production BABEL_ENV=es rollup -c",
94
- "build:umd": "cross-env NODE_ENV=production BABEL_ENV=umd rollup -c",
95
- "prettier": "prettier \"*/**/*.js\" --ignore-path ./.prettierignore --write"
96
- }
2
+ "name": "@untemps/vocal",
3
+ "version": "1.3.1",
4
+ "description": "Class wrapped around the SpeechRecognition Web API",
5
+ "repository": "git@github.com:untemps/vocal.git",
6
+ "keywords": [
7
+ "Web Speech API",
8
+ "SpeechRecognition",
9
+ "speech",
10
+ "speech-to-text",
11
+ "javascript"
12
+ ],
13
+ "author": "Vincent Le Badezet <v.lebadezet@untemps.net>",
14
+ "license": "MIT",
15
+ "private": false,
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "engines": {
20
+ "node": ">=22"
21
+ },
22
+ "files": [
23
+ "dist/index.js",
24
+ "dist/index.es.js",
25
+ "dist/index.umd.js",
26
+ "CHANGELOG.md"
27
+ ],
28
+ "main": "dist/index.js",
29
+ "module": "dist/index.es.js",
30
+ "devDependencies": {
31
+ "@commitlint/cli": "^21.0.1",
32
+ "@commitlint/config-conventional": "^21.0.1",
33
+ "@semantic-release/changelog": "^6.0.3",
34
+ "@semantic-release/git": "^10.0.1",
35
+ "@semantic-release/github": "^12.0.6",
36
+ "@testing-library/jest-dom": "^6.9.1",
37
+ "@vitest/coverage-v8": "^4.1.5",
38
+ "husky": "^9.1.7",
39
+ "jsdom": "^29.1.1",
40
+ "prettier": "^3.8.3",
41
+ "semantic-release": "^25.0.3",
42
+ "vite": "^8.0.13",
43
+ "vitest": "^4.1.5"
44
+ },
45
+ "dependencies": {
46
+ "@untemps/user-permissions-utils": "^1.3.0"
47
+ },
48
+ "release": {
49
+ "branches": [
50
+ "main",
51
+ {
52
+ "name": "beta",
53
+ "prerelease": true
54
+ }
55
+ ],
56
+ "plugins": [
57
+ [
58
+ "@semantic-release/commit-analyzer",
59
+ {
60
+ "releaseRules": [
61
+ {
62
+ "type": "chore",
63
+ "release": "patch"
64
+ }
65
+ ]
66
+ }
67
+ ],
68
+ "@semantic-release/release-notes-generator",
69
+ "@semantic-release/changelog",
70
+ "@semantic-release/npm",
71
+ "@semantic-release/git",
72
+ [
73
+ "@semantic-release/github",
74
+ {
75
+ "assets": [
76
+ {
77
+ "path": "dist/index.js",
78
+ "label": "CJS distribution"
79
+ },
80
+ {
81
+ "path": "dist/index.es.js",
82
+ "label": "ES distribution"
83
+ },
84
+ {
85
+ "path": "dist/index.umd.js",
86
+ "label": "UMD distribution"
87
+ }
88
+ ]
89
+ }
90
+ ]
91
+ ]
92
+ },
93
+ "scripts": {
94
+ "test": "vitest",
95
+ "test:ci": "vitest run --coverage",
96
+ "build": "vite build",
97
+ "prepare": "husky",
98
+ "prettier": "prettier \"*/**/*.js\" --ignore-path ./.prettierignore --write"
99
+ }
97
100
  }
@@ -1,23 +0,0 @@
1
- name: "deploy"
2
- on:
3
- push:
4
- branches:
5
- - main
6
- jobs:
7
- release:
8
- runs-on: ubuntu-latest
9
- steps:
10
- - uses: actions/checkout@v2
11
- - uses: actions/setup-node@v1
12
- with:
13
- node-version: '12'
14
- - run: yarn install
15
- - run: yarn test:ci
16
- - run: yarn build
17
- - run: npx semantic-release
18
- env:
19
- GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
20
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
21
- - uses: codecov/codecov-action@v1
22
- with:
23
- file: coverage/lcov.info
package/.prettierignore DELETED
@@ -1,2 +0,0 @@
1
- build/
2
- node_modules/
package/.prettierrc DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "printWidth": 120,
3
- "useTabs": true,
4
- "tabWidth": 4,
5
- "singleQuote": true,
6
- "semi": false,
7
- "trailingComma": "es5",
8
- "bracketSpacing": true,
9
- "overrides": [
10
- {
11
- "files": "./**/*.js",
12
- "options": {
13
- "parser": "babylon"
14
- }
15
- },
16
- {
17
- "files": "./**/*.json",
18
- "options": {
19
- "parser": "json"
20
- }
21
- },
22
- {
23
- "files": ".prettierrc",
24
- "options": {
25
- "parser": "json"
26
- }
27
- }
28
- ]
29
- }
package/CONTRIBUTING.md DELETED
@@ -1,15 +0,0 @@
1
- ## How to contribute to `@untemps/vocal`
2
-
3
- **Contributions are warmly welcomed**
4
-
5
- Please follow those simple steps:
6
- - Fork the repository
7
- - Create a feature branch
8
- Preferred name convention: [feature type]/[imperative verb]-[description of the feature] > `feat/add-foo-support`
9
- - Develop the feature AND write the tests (or write the tests AND develop the feature)
10
- - Commit your changes using Angular Git Commit Guidelines
11
- - Submit a Pull Request
12
-
13
- Thanks! :heart: :heart: :heart:
14
-
15
- `@untemps/vocal` Team
package/babel.config.js DELETED
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- "presets": [
3
- "@babel/preset-env"
4
- ],
5
- "plugins": [
6
- "@babel/plugin-proposal-class-properties",
7
- "@babel/plugin-transform-runtime"
8
- ]
9
- }
10
-
@@ -1,59 +0,0 @@
1
- const { toBeInTheDocument, toHaveAttribute, toHaveStyle } = require('@testing-library/jest-dom/matchers')
2
- import '@testing-library/jest-dom/extend-expect'
3
-
4
- expect.extend({ toBeInTheDocument, toHaveAttribute, toHaveStyle })
5
-
6
- global.PermissionStatus = jest.fn(() => ({
7
- state: 'granted',
8
- addEventListener: jest.fn(),
9
- }))
10
- const status = new PermissionStatus()
11
- global.Permissions = jest.fn(() => ({
12
- query: jest.fn().mockResolvedValue(status),
13
- }))
14
- global.navigator.permissions = new Permissions()
15
- global.MediaDevices = jest.fn(() => ({
16
- getUserMedia: jest.fn().mockResolvedValue('foo'),
17
- }))
18
- global.navigator.mediaDevices = new MediaDevices()
19
- global.SpeechGrammarList = jest.fn(() => ({
20
- length: 0,
21
- }))
22
- global.SpeechRecognition = jest.fn(() => {
23
- const handlers = {}
24
- return {
25
- addEventListener: jest.fn((type, callback) => {
26
- handlers[type] = callback
27
- }),
28
- removeEventListener: jest.fn(),
29
- dispatchEvent: jest.fn(),
30
- start: jest.fn(() => {
31
- !!handlers.start && handlers.start()
32
- }),
33
- stop: jest.fn(() => {
34
- !!handlers.end && handlers.end()
35
- }),
36
- abort: jest.fn(() => {
37
- !!handlers.end && handlers.end()
38
- }),
39
- say: jest.fn((sentence) => {
40
- !!handlers.speechstart && handlers.speechstart()
41
-
42
- const resultEvent = new Event('result')
43
- resultEvent.resultIndex = 0
44
- resultEvent.results = [
45
- [
46
- {
47
- transcript: sentence,
48
- },
49
- ],
50
- ]
51
- if (sentence) {
52
- !!handlers.result && handlers.result(resultEvent)
53
- } else {
54
- !!handlers.nomatch && handlers.nomatch()
55
- }
56
- !!handlers.speechend && handlers.speechend()
57
- }),
58
- }
59
- })
package/rollup.config.js DELETED
@@ -1,38 +0,0 @@
1
- import babel from '@rollup/plugin-babel'
2
- import commonjs from '@rollup/plugin-commonjs'
3
- import resolve from '@rollup/plugin-node-resolve'
4
- import filesize from "rollup-plugin-filesize"
5
- import { terser } from 'rollup-plugin-terser'
6
- import visualizer from 'rollup-plugin-visualizer'
7
-
8
- const production = process.env.NODE_ENV === 'production'
9
- const target = process.env.BABEL_ENV
10
-
11
- export default {
12
- input: 'src/index.js',
13
- output: {
14
- name: 'vocal',
15
- file: {
16
- cjs: 'dist/index.js',
17
- es: 'dist/index.es.js',
18
- umd: 'dist/index.umd.js'
19
- }[target],
20
- format: target,
21
- sourcemap: 'inline'
22
- },
23
- external: ['@babel/plugin-transform-runtime'],
24
- plugins: [
25
- babel({
26
- exclude: 'node_modules/**',
27
- babelHelpers: 'runtime'
28
- }),
29
- resolve(),
30
- commonjs(),
31
- filesize(),
32
- production && terser(),
33
- visualizer({
34
- sourcemap: true,
35
- open: true
36
- })
37
- ],
38
- }
package/src/Vocal.js DELETED
@@ -1,169 +0,0 @@
1
- import { getUserMediaStream } from '@untemps/user-permissions-utils'
2
-
3
- class Vocal {
4
- static defaultOptions = {
5
- grammars: null,
6
- lang: 'en-US',
7
- continuous: false,
8
- interimResults: false,
9
- maxAlternatives: 1,
10
- serviceURI: null,
11
- }
12
-
13
- static eventTypes = {
14
- AUDIO_END: 'audioend',
15
- AUDIO_START: 'audiostart',
16
- END: 'end',
17
- ERROR: 'error',
18
- NO_MATCH: 'nomatch',
19
- RESULT: 'result',
20
- SOUND_END: 'soundend',
21
- SOUND_START: 'soundstart',
22
- SPEECH_END: 'speechend',
23
- SPEECH_START: 'speechstart',
24
- START: 'start',
25
- }
26
-
27
- static get isSupported() {
28
- return !!Vocal._resolveSpeechRecognition()
29
- }
30
-
31
- static set isSupported(_) {
32
- throw new Error('You cannot set isSupported directly.')
33
- }
34
-
35
- _instance = null
36
- _listeners = null
37
-
38
- constructor(options) {
39
- const SpeechRecognition = Vocal._resolveSpeechRecognition()
40
- if (!SpeechRecognition) {
41
- throw new DOMException('SpeechRecognition not supported', 'NOT_SUPPORTED_ERR')
42
- }
43
-
44
- this._instance = new SpeechRecognition()
45
- this._listeners = {}
46
-
47
- Object.entries({
48
- ...Vocal.defaultOptions,
49
- ...(options || {}),
50
- }).forEach(([key, value]) => {
51
- if (key === 'grammars' && !value) {
52
- const SpeechGrammarList = Vocal._resolveSpeechGrammarList()
53
- if (!!SpeechGrammarList) {
54
- value = new SpeechGrammarList()
55
- }
56
- }
57
- this._instance[key] = value
58
- })
59
- }
60
-
61
- get instance() {
62
- return this._instance
63
- }
64
-
65
- set instance(_) {
66
- throw new Error('You cannot set instance directly.')
67
- }
68
-
69
- async start() {
70
- if (!!this._instance) {
71
- try {
72
- const stream = await getUserMediaStream('microphone', { audio: true })
73
- if (!stream) {
74
- throw new Error('Unable to retrieve the stream from media device')
75
- }
76
- this._instance.start()
77
- } catch (error) {
78
- const errorHandler = this._listeners.error
79
- if (!!errorHandler) {
80
- errorHandler(error)
81
- }
82
- }
83
- }
84
-
85
- return this
86
- }
87
-
88
- stop() {
89
- if (!!this._instance) {
90
- this._instance.stop()
91
- }
92
-
93
- return this
94
- }
95
-
96
- abort() {
97
- if (!!this._instance) {
98
- this._instance.abort()
99
- }
100
-
101
- return this
102
- }
103
-
104
- addEventListener(eventType, callback) {
105
- if (!!this._instance && this._includesEventType(eventType)) {
106
- if (!!this._listeners[eventType]) {
107
- this.removeEventListener(eventType)
108
- }
109
-
110
- const handler = (event) => {
111
- let additionalArgs = []
112
- if (eventType === Vocal.eventTypes.RESULT) {
113
- if (!!event.results && event.results.length > 0) {
114
- additionalArgs.push(event.results[0][0].transcript)
115
- }
116
- }
117
-
118
- !!callback && callback.apply(this, [event, ...additionalArgs])
119
- }
120
- this._instance.addEventListener(eventType, handler)
121
-
122
- this._listeners[eventType] = handler
123
- }
124
-
125
- return this
126
- }
127
-
128
- removeEventListener(eventType) {
129
- const handler = this._listeners[eventType]
130
- this._instance.removeEventListener(eventType, handler)
131
-
132
- delete this._listeners[eventType]
133
-
134
- return this
135
- }
136
-
137
- cleanup() {
138
- this.stop()
139
-
140
- Object.keys(this._listeners).forEach((key) => this.removeEventListener(key))
141
- this._instance = null
142
-
143
- return this
144
- }
145
-
146
- _includesEventType(eventType) {
147
- return !!Object.values(Vocal.eventTypes).find((type) => type === eventType)
148
- }
149
-
150
- static _resolveSpeechRecognition() {
151
- return (
152
- window.SpeechRecognition ||
153
- window.webkitSpeechRecognition ||
154
- window.mozSpeechRecognition ||
155
- window.msSpeechRecognition
156
- )
157
- }
158
-
159
- static _resolveSpeechGrammarList() {
160
- return (
161
- window.SpeechGrammarList ||
162
- window.webkitSpeechGrammarList ||
163
- window.mozSpeechGrammarList ||
164
- window.msSpeechGrammarList
165
- )
166
- }
167
- }
168
-
169
- export default Vocal
@@ -1,34 +0,0 @@
1
- import Vocal from '../Vocal'
2
- import * as userPermissionsUtils from '@untemps/user-permissions-utils'
3
-
4
- describe('Vocal', () => {
5
- it('throws error when setting isSupported explicitly', () => {
6
- expect(() => (Vocal.isSupported = false)).toThrow()
7
- })
8
-
9
- it('throws error when setting instance explicitly', () => {
10
- const wrapper = new Vocal()
11
- expect(() => (wrapper.instance = null)).toThrow()
12
- })
13
-
14
- it('throws error when getUserMediaStream returns false value', async () => {
15
- const onError = jest.fn()
16
- jest.spyOn(userPermissionsUtils, 'getUserMediaStream').mockResolvedValueOnce(null)
17
- const wrapper = new Vocal()
18
- wrapper.addEventListener('error', onError)
19
- await wrapper.start()
20
- expect(onError).toHaveBeenCalledWith(new Error('Unable to retrieve the stream from media device'))
21
- })
22
-
23
- it('throws error when getUserMediaStream throws', async () => {
24
- const onError = jest.fn()
25
- const error = new Error('foo')
26
- jest.spyOn(userPermissionsUtils, 'getUserMediaStream').mockImplementationOnce(() => {
27
- throw error
28
- })
29
- const wrapper = new Vocal()
30
- wrapper.addEventListener('error', onError)
31
- await wrapper.start()
32
- expect(onError).toHaveBeenCalledWith(error)
33
- })
34
- })
package/src/index.js DELETED
@@ -1 +0,0 @@
1
- export { default as Vocal } from './Vocal'