21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // webpack.config.js
2 | var path = require('path');
3 |
4 | var config = {
5 | entry: {
6 | demo: [ path.resolve(__dirname, 'demo/demo.js') ],
7 | },
8 | output: {
9 | path: path.resolve(__dirname, 'demo/build'),
10 | filename: '[name].bundle.js'
11 | },
12 | module: {
13 | rules: [
14 | {
15 | test: /\.(js)$/,
16 | exclude: /node_modules/,
17 | use: ['babel-loader']
18 | }
19 | ]
20 | },
21 | resolve: {
22 | extensions: ['*', '.js']
23 | },
24 | devServer: {
25 | contentBase: path.resolve(__dirname, 'demo/build')
26 | }
27 | };
28 |
29 | module.exports = config;
--------------------------------------------------------------------------------
/demo/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "speak-tts",
3 | "version": "2.0.8",
4 | "description": "Browser TTS (using Web speech API) made easy",
5 | "main": "lib/speak-tts.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --devtool eval --progress --colors --content-base demo/build --hot --inline --mode development",
8 | "deploy": "NODE_ENV=production webpack -p --config webpack.production.config.js --mode production",
9 | "compile": "npx babel -d lib/ src/",
10 | "prepublish": "npm run compile"
11 | },
12 | "author": "tom-s",
13 | "homepage": "https://github.com/tom-s/speak-tts#readme",
14 | "keywords": [
15 | "web speech api",
16 | "speech synthesis",
17 | "speak",
18 | "speechSynthesis",
19 | "SpeechSynthesisUtterance",
20 | "tts",
21 | "text to speech",
22 | "browser speech",
23 | "browser tts"
24 | ],
25 | "license": "MIT",
26 | "devDependencies": {
27 | "@babel/cli": "^7.1.2",
28 | "@babel/core": "^7.1.2",
29 | "@babel/preset-env": "^7.1.0",
30 | "babel-loader": "^8.0.4",
31 | "json-loader": "^0.5.4",
32 | "webpack": "^4.20.2",
33 | "webpack-cli": "^3.1.2",
34 | "webpack-dev-server": "^3.1.9"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | export const splitSentences = (text = '') => text.replace(/\.+/g,'.|')
2 | .replace(/\?/g,'?|')
3 | .replace(/\!/g,'!|')
4 | .split("|")
5 | .map(sentence => trim(sentence))
6 | .filter(Boolean)
7 |
8 | const bcp47LocalePattern = /^(?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))$|^((?:[a-z]{2,3}(?:(?:-[a-z]{3}){1,3})?)|[a-z]{4}|[a-z]{5,8})(?:-([a-z]{4}))?(?:-([a-z]{2}|\d{3}))?((?:-(?:[\da-z]{5,8}|\d[\da-z]{3}))*)?((?:-[\da-wy-z](?:-[\da-z]{2,8})+)*)?(-x(?:-[\da-z]{1,8})+)?$|^(x(?:-[\da-z]{1,8})+)$/i; // eslint-disable-line max-len
9 |
10 | /**
11 | * Validate a locale string to test if it is bcp47 compliant
12 | * @param {String} locale The tag locale to parse
13 | * @return {Boolean} True if tag is bcp47 compliant false otherwise
14 | */
15 | export const validateLocale = locale => (typeof locale !== 'string')
16 | ? false
17 | : bcp47LocalePattern.test(locale)
18 |
19 | export const isString = value =>
20 | typeof value === 'string' || value instanceof String
21 |
22 | export const size = value => value && Array.isArray(value) && value.length
23 | ? value.length
24 | : 0
25 |
26 | export const isNan = value =>
27 | typeof value === "number" && isNaN(value)
28 |
29 | export const isNil = value =>
30 | value === null || value === undefined
31 |
32 | export const isObject = value =>
33 | Object.prototype.toString.call(value) === '[object Object]'
34 |
35 | export const trim = value => isString(value)
36 | ? value.trim()
37 | : ''
38 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.trim = exports.isObject = exports.isNil = exports.isNan = exports.size = exports.isString = exports.validateLocale = exports.splitSentences = void 0;
7 |
8 | var splitSentences = function splitSentences() {
9 | var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
10 | return text.replace(/\.+/g, '.|').replace(/\?/g, '?|').replace(/\!/g, '!|').split("|").map(function (sentence) {
11 | return trim(sentence);
12 | }).filter(Boolean);
13 | };
14 |
15 | exports.splitSentences = splitSentences;
16 | var bcp47LocalePattern = /^(?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))$|^((?:[a-z]{2,3}(?:(?:-[a-z]{3}){1,3})?)|[a-z]{4}|[a-z]{5,8})(?:-([a-z]{4}))?(?:-([a-z]{2}|\d{3}))?((?:-(?:[\da-z]{5,8}|\d[\da-z]{3}))*)?((?:-[\da-wy-z](?:-[\da-z]{2,8})+)*)?(-x(?:-[\da-z]{1,8})+)?$|^(x(?:-[\da-z]{1,8})+)$/i; // eslint-disable-line max-len
17 |
18 | /**
19 | * Validate a locale string to test if it is bcp47 compliant
20 | * @param {String} locale The tag locale to parse
21 | * @return {Boolean} True if tag is bcp47 compliant false otherwise
22 | */
23 |
24 | var validateLocale = function validateLocale(locale) {
25 | return typeof locale !== 'string' ? false : bcp47LocalePattern.test(locale);
26 | };
27 |
28 | exports.validateLocale = validateLocale;
29 |
30 | var isString = function isString(value) {
31 | return typeof value === 'string' || value instanceof String;
32 | };
33 |
34 | exports.isString = isString;
35 |
36 | var size = function size(value) {
37 | return value && Array.isArray(value) && value.length ? value.length : 0;
38 | };
39 |
40 | exports.size = size;
41 |
42 | var isNan = function isNan(value) {
43 | return typeof value === "number" && isNaN(value);
44 | };
45 |
46 | exports.isNan = isNan;
47 |
48 | var isNil = function isNil(value) {
49 | return value === null || value === undefined;
50 | };
51 |
52 | exports.isNil = isNil;
53 |
54 | var isObject = function isObject(value) {
55 | return Object.prototype.toString.call(value) === '[object Object]';
56 | };
57 |
58 | exports.isObject = isObject;
59 |
60 | var trim = function trim(value) {
61 | return isString(value) ? value.trim() : '';
62 | };
63 |
64 | exports.trim = trim;
--------------------------------------------------------------------------------
/demo/demo.js:
--------------------------------------------------------------------------------
1 | import Speech from '../src/speak-tts.js'
2 |
3 | const _addVoicesList = (voices) => {
4 | const list = window.document.createElement('div')
5 | let html = '
Available Voices