├── .editorconfig ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── .travis.yml ├── .vscode ├── launch.json └── settings.json ├── CHANGELOG.md ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── VERSION ├── docs ├── architecture.md └── assets │ ├── parser-formatter-diagram.png │ └── simple-parser-diagram.png ├── index.ts ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── Interfaces.ts ├── SpeechMarkdown.ts ├── SpeechMarkdownGrammar.ts ├── SpeechMarkdownParser.ts ├── SpeechOptions.ts └── formatters │ ├── AmazonAlexaSsmlFormatter.ts │ ├── AmazonPollyNeuralSsmlFormatter.ts │ ├── AmazonPollySsmlFormatter.ts │ ├── FormatterBase.ts │ ├── FormatterFactory.ts │ ├── GoogleAssistantSsmlFormatter.ts │ ├── MicrosoftAzureSsmlFormatter.ts │ ├── SamsungBixbySsmlFormatter.ts │ ├── SsmlFormatterBase.ts │ └── TextFormatter.ts ├── tests ├── address-standard.spec.ts ├── audio-standard.spec.ts ├── break-short.spec.ts ├── break-strength.spec.ts ├── break-time.spec.ts ├── cardinal-standard.spec.ts ├── characters-standard.spec.ts ├── date-standard.spec.ts ├── digits-standard.spec.ts ├── disappointed-section.spec.ts ├── disappointed-standard.spec.ts ├── dj-section.spec.ts ├── drc-standard.spec.ts ├── emphasis-short-edge-cases.spec.ts ├── emphasis-short.spec.ts ├── emphasis-standard.spec.ts ├── escape-xml.spec.ts ├── excited-section.spec.ts ├── excited-standard.spec.ts ├── expletive-standard.spec.ts ├── fraction-standard.spec.ts ├── interjection-standard.spec.ts ├── ipa-standard-alphabet-uk.spec.ts ├── ipa-standard-alphabet-us.spec.ts ├── ipa-standard.spec.ts ├── lang-standard.spec.ts ├── mark-standard.spec.ts ├── modifier-text-allowed-chars.spec.ts ├── multiple-modifiers-same-text.spec.ts ├── newscaster-section.spec.ts ├── no-markdown.spec.ts ├── no-modifiers.spec.ts ├── number-standard.spec.ts ├── options-includeFormatterComment.spec.ts ├── options-includeParagraphTag.spec.ts ├── options-includeSpeakTag.spec.ts ├── ordinal-standard.spec.ts ├── pitch-standard.spec.ts ├── prosody-multiple-modifiers.spec.ts ├── rate-standard.spec.ts ├── say-as-modifiers.spec.ts ├── sections-standard.spec.ts ├── sub-standard.spec.ts ├── telephone-standard.spec.ts ├── timbre-standard.spec.ts ├── time-standard.spec.ts ├── unit-standard.spec.ts ├── voice-customize.spec.ts ├── voice-standard.spec.ts ├── volume-standard.spec.ts └── whisper-standard.spec.ts ├── tsconfig.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | 9 | [*.md] 10 | insert_final_newline = false 11 | trim_trailing_whitespace = false 12 | 13 | [*.{js,jsx,json,ts,tsx,yml}] 14 | indent_size = 2 15 | indent_style = space 16 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: NPM test 2 | 3 | on: 4 | push: 5 | branches: ['master'] 6 | pull_request: 7 | branches: ['master'] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [14.x, 16.x, 18.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v3 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | 25 | - name: Install 26 | run: npm install 27 | 28 | - name: Check formatting 29 | run: node_modules/.bin/prettier --check $(find src -type f) 30 | 31 | - name: Check lint 32 | run: npm run lint 33 | 34 | - name: Test 35 | run: npm test 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Dependencies 7 | node_modules/ 8 | 9 | # Coverage 10 | coverage 11 | 12 | # Transpiled files 13 | dist/ 14 | dist.browser/ 15 | 16 | # JetBrains IDEs 17 | .idea/ 18 | 19 | # Optional npm cache directory 20 | .npm 21 | 22 | # Optional eslint cache 23 | .eslintcache 24 | 25 | # Misc 26 | .DS_Store 27 | 28 | # Sample 29 | .sample 30 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | coverage/ 3 | src/ 4 | tests/ 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "overrides": [ 5 | { 6 | "files": "*.ts", 7 | "options": { 8 | "parser": "typescript" 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "stable" 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Jest All", 8 | "program": "${workspaceFolder}/node_modules/.bin/jest", 9 | "args": ["--runInBand"], 10 | "console": "integratedTerminal", 11 | "internalConsoleOptions": "neverOpen", 12 | "disableOptimisticBPs": true, 13 | "windows": { 14 | "program": "${workspaceFolder}/node_modules/jest/bin/jest", 15 | } 16 | }, 17 | { 18 | "type": "node", 19 | "request": "launch", 20 | "name": "Jest Current File", 21 | "program": "${workspaceFolder}/node_modules/.bin/jest", 22 | "args": [ 23 | "${fileBasenameNoExtension}", 24 | "--config", 25 | "jest.config.js" 26 | ], 27 | "console": "integratedTerminal", 28 | "internalConsoleOptions": "neverOpen", 29 | "disableOptimisticBPs": true, 30 | "windows": { 31 | "program": "${workspaceFolder}/node_modules/jest/bin/jest", 32 | } 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "Aditi", 4 | "Bixby", 5 | "Celine", 6 | "Conchita", 7 | "Giorgio", 8 | "Mathieu", 9 | "Mizuki", 10 | "Raveena", 11 | "Salli", 12 | "Takumi", 13 | "dedent", 14 | "implicity", 15 | "speechmarkdown", 16 | "ssml", 17 | "transpiled", 18 | "tsify", 19 | "uglifyjs" 20 | ] 21 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to the speechmarkdown-js project will be documented in this file. 3 | 4 | ## 2.1.0 - (December 22, 2022) 5 | ### Added 6 | - Support for audio captions 7 | 8 | ## 2.0.0 - (October 28, 2021) 9 | ### Added 10 | - Support for `voice` and `language` for `google-assistant` 11 | - Formatters for `amazon-polly`, `amazon-polly-neural`, and `microsoft-azure` 12 | 13 | ## 0.8.0-beta.0 - (July 7, 2019) 14 | ### Added 15 | - Support for sections with the `voice` and `lang` tags 16 | 17 | ## 0.7.0-alpha.0 - (July 6, 2019) 18 | ### Added 19 | - Support for `audio` tag 20 | 21 | ## 0.6.0-alpha.0 - (July 6, 2019) 22 | ### Added 23 | - Support for `voice` and `lang` tags 24 | 25 | ## 0.5.0-alpha.0 - (July 5, 2019) 26 | ### Fixed 27 | - Issue #7 - Grammar - multiple modifiers for the same text 28 | ### Added 29 | - Grammar and formatters for standard: 30 | - volume / vol 31 | - rate 32 | - pitch 33 | - sub 34 | - ipa 35 | 36 | ## 0.4.0-alpha.0 - (June 30, 2019) 37 | ### Added 38 | - Update grammar and formatters for standard: 39 | - emphasis 40 | - address 41 | - characters / chars 42 | - date (skipped tests) 43 | - expletive / bleep 44 | - fraction (skipped tests) 45 | - interjection 46 | - number 47 | - ordinal 48 | - phone / telephone (skipped tests) 49 | - time 50 | - unit 51 | - whisper 52 | 53 | 54 | - Add tests to increase coverage 55 | 56 | ## 0.3.0-alpha.0 - (June 30, 2019) 57 | ### Added 58 | - Update grammar and formatters for emphasis short format 59 | - Change speechmarkdown.toString(markdown) to speechmarkdown.toText(markdown) 60 | 61 | 62 | ## 0.2.0-alpha.0 - (June 29, 2019) 63 | ### Added 64 | - CHANGELOG.md 65 | 66 | ### Update 67 | - Links in package.json -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Speech Markdown Open Source Code of Conduct 2 | 3 | This code of conduct provides guidance on participation in Speech Markdown-managed open source communities, and outlines the process for reporting unacceptable behavior. As an organization and community, we are committed to providing an inclusive environment for everyone. Anyone violating this code of conduct may be removed and banned from the community. 4 | 5 | **Our open source communities endeavor to:** 6 | 7 | - Use welcoming and inclusive language; 8 | - Be respectful of differing viewpoints at all times; 9 | - Accept constructive criticism and work together toward decisions; 10 | - Focus on what is best for the community and users. 11 | 12 | **Our Responsibility.** As contributors, members, or bystanders we each individually have the responsibility to behave professionally and respectfully at all times. Disrespectful and unacceptable behaviors include, but are not limited to: 13 | 14 | - The use of violent threats, abusive, discriminatory, or derogatory language; 15 | - Offensive comments related to gender, gender identity and expression, sexual - orientation, disability, mental illness, race, political or religious affiliation; 16 | - Posting of sexually explicit or violent content; 17 | - The use of sexualized language and unwelcome sexual attention or advances; 18 | - Public or private harassment of any kind; 19 | - Publishing private information, such as physical or electronic address, without permission; 20 | - Other conduct which could reasonably be considered inappropriate in a professional setting; 21 | - Advocating for or encouraging any of the above behaviors. 22 | 23 | **Enforcement and Reporting Code of Conduct Issues.** Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting opensource-codeofconduct@speechmarkdown.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Guidelines for contributing 2 | 3 | Thank you for your interest in contributing to a Speech Markdown project! We greatly value feedback and contributions from our community. 4 | 5 | Please read through this document before you submit any pull requests or issues. It will help us work together more effectively. 6 | 7 | ## What to expect when you contribute 8 | 9 | When you submit a pull request, our team is notified and will respond as quickly as we can. We'll do our best to work with you to ensure that your pull request adheres to our style and standards. If we merge your pull request, we might make additional edits later for style or clarity. 10 | 11 | We look forward to receiving your pull requests for: 12 | 13 | * New content you'd like to contribute (such as new code samples or tutorials) 14 | * Inaccuracies in the content 15 | * Information gaps in the content that need more detail to be complete 16 | * Typos or grammatical errors 17 | * Suggested rewrites that improve clarity and reduce confusion 18 | 19 | **Note:** We all write differently, and you might not like how we've written or organized something currently. We want that feedback. But please be sure that your request for a rewrite is supported by the previous criteria. If it isn't, we might decline to merge it. 20 | 21 | ## How to contribute 22 | 23 | To contribute, send us a pull request. For small changes, such as fixing a typo or adding a link, you can use the [GitHub Edit Button](https://blog.github.com/2011-04-26-forking-with-the-edit-button/). For larger changes: 24 | 25 | 1. [Fork the repository](https://help.github.com/articles/fork-a-repo/). 26 | 2. In your fork, make your change in a branch that's based on this repo's **master** branch. 27 | 3. Commit the change to your fork, using a clear and descriptive commit message. 28 | 4. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/), answering any questions in the pull request form. 29 | 30 | Before you send us a pull request, please be sure that: 31 | 32 | 1. You're working from the latest source on the **master** branch. 33 | 2. You check [existing open](https://github.com/speechmarkdown/speechmarkdown-js/pulls), and [recently closed](https://github.com/speechmarkdown/speechmarkdown-js/pulls?q=is%3Apr+is%3Aclosed), pull requests to be sure that someone else hasn't already addressed the problem. 34 | 3. You [create an issue](https://github.com/speechmarkdown/speechmarkdown-js/issues/new) before working on a contribution that will take a significant amount of your time. 35 | 36 | For contributions that will take a significant amount of time, [open a new issue](https://github.com/speechmarkdown/speechmarkdown-js/issues/new) to pitch your idea before you get started. Explain the problem and describe the content you want to see added to the documentation. Let us know if you'll write it yourself or if you'd like us to help. We'll discuss your proposal with you and let you know whether we're likely to accept it. We don't want you to spend a lot of time on a contribution that might be outside the scope of the documentation or that's already in the works. 37 | 38 | ## Finding contributions to work on 39 | 40 | If you'd like to contribute, but don't have a project in mind, look at the [open issues](https://github.com/speechmarkdown/speechmarkdown-js/issues) in this repository for some ideas. Any issues with the [help wanted](https://github.com/speechmarkdown/speechmarkdown-js/labels/help%20wanted) or [enhancement](https://github.com/speechmarkdown/speechmarkdown-js/labels/enhancement) labels are a great place to start. 41 | 42 | In addition to written content, we really appreciate new examples and code samples for our documentation, such as examples for different platforms or environments, and code samples in additional languages. 43 | 44 | ## Code of conduct 45 | 46 | This project has adopted the [Speech Markdown Open Source Code of Conduct](https://github.com/speechmarkdown/speechmarkdown-js/blob/master/CODE-OF-CONDUCT). Contact [opensource-codeofconduct@speechmarkdown.org](mailto:opensource-codeofconduct@speechmarkdown.org) with any additional questions or comments. 47 | 48 | 49 | ## Licensing 50 | 51 | See the [LICENSE](https://github.com/speechmarkdown/speechmarkdown-js/blob/master/LICENSE) file for this project's licensing. We will ask you to confirm the licensing of your contribution. We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Speech Markdown 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![TypeScript version][ts-badge]][typescript-34] 2 | [![Node.js version][nodejs-badge]][nodejs] 3 | [![MIT][license-badge]][license] 4 | 5 | # speechmarkdown-js 6 | 7 | Speech Markdown grammar, parser, and formatters for use with JavaScript. 8 | 9 | Supported platforms: 10 | 11 | - amazon-alexa 12 | - amazon-polly 13 | - amazon-polly-neural 14 | - google-assistant 15 | - microsoft-azure 16 | - samsung-bixby 17 | 18 | Find the architecture [here](./docs/architecture.md) 19 | 20 | ## Quick start 21 | 22 | ### SSML - Amazon Alexa 23 | 24 | Convert Speech Markdown to SSML for Amazon Alexa 25 | 26 | ```js 27 | const smd = require('speechmarkdown-js'); 28 | 29 | const markdown = `Sample [3s] speech [250ms] markdown`; 30 | const options = { 31 | platform: 'amazon-alexa', 32 | }; 33 | 34 | const speech = new smd.SpeechMarkdown(); 35 | const ssml = speech.toSSML(markdown, options); 36 | ``` 37 | 38 | The resulting SSML is: 39 | 40 | ```xml 41 | 42 | Sample speech markdown 43 | 44 | ``` 45 | 46 | ### SSML - Google Assistant 47 | 48 | Convert Speech Markdown to SSML for Google Assistant 49 | 50 | ```js 51 | const smd = require('speechmarkdown-js'); 52 | 53 | const markdown = `Sample [3s] speech [250ms] markdown`; 54 | const options = { 55 | platform: 'google-assistant', 56 | }; 57 | 58 | const speech = new smd.SpeechMarkdown(); 59 | const ssml = speech.toSSML(markdown, options); 60 | ``` 61 | 62 | The resulting SSML is: 63 | 64 | ```xml 65 | 66 | Sample speech markdown 67 | 68 | ``` 69 | 70 | ### Plain Text 71 | 72 | Convert Speech Markdown to Plain Text 73 | 74 | ```js 75 | const smd = require('speechmarkdown-js'); 76 | 77 | const markdown = `Sample [3s] speech [250ms] markdown`; 78 | const options = {}; 79 | 80 | const speech = new smd.SpeechMarkdown(); 81 | const text = speech.toText(markdown, options); 82 | ``` 83 | 84 | The resulting text is: 85 | 86 | ```text 87 | Sample speech markdown 88 | ``` 89 | 90 | ## More 91 | 92 | ### Options 93 | 94 | You can pass `options` into the constructor: 95 | 96 | ```js 97 | const smd = require('speechmarkdown-js'); 98 | 99 | const markdown = `Sample [3s] speech [250ms] markdown`; 100 | const options = { 101 | platform: 'amazon-alexa', 102 | }; 103 | 104 | const speech = new smd.SpeechMarkdown(options); 105 | const ssml = speech.toSSML(markdown); 106 | ``` 107 | 108 | Or in the methods `toSSML` and `toText`: 109 | 110 | ```js 111 | const smd = require('speechmarkdown-js'); 112 | 113 | const markdown = `Sample [3s] speech [250ms] markdown`; 114 | const options = { 115 | platform: 'amazon-alexa', 116 | }; 117 | 118 | const speech = new smd.SpeechMarkdown(); 119 | const ssml = speech.toSSML(markdown, options); 120 | ``` 121 | 122 | Available options are: 123 | 124 | - `platform` (string) - Determines the formatter to use to render SSML. Valid values are: 125 | 126 | - "amazon-alexa" 127 | - "amazon-polly" 128 | - "amazon-polly-neural" 129 | - "google-assistant" 130 | - "microsoft-azure" 131 | - "samsung-bixby" 132 | 133 | - `includeFormatterComment` (boolean) - Adds an XML comment to the SSML output indicating the formatter used. Default is `false`. 134 | 135 | - `includeSpeakTag` (boolean) - Determines if the `` tag will be rendered in the SSML output. Default is `true`. 136 | 137 | - `includeParagraphTag` (boolean) - Determines if the `

` tag will be rendered in the SSML output. Default is `false`. 138 | 139 | - `preserveEmptyLines` (boolean) - keep empty lines in markdown in SSML. Default is `true`. 140 | 141 | - `escapeXmlSymbols` (boolean) - Currently only for `amazon-alexa` and `microsoft-azure`. Escape XML text. Default is `false`. 142 | 143 | - `voices` (object) - give custom names to voices and use that in your markdown: 144 | 145 | ```json 146 | { 147 | "platform": "amazon-alexa", 148 | "voices": { 149 | "Scott": { "voice": { "name": "Brian" } }, 150 | "Sarah": { "voice": { "name": "Kendra" } } 151 | } 152 | } 153 | ``` 154 | 155 | ```json 156 | { 157 | "platform": "google-assistant", 158 | "voices": { 159 | "Brian": { 160 | "voice": { "gender": "male", "variant": 1, "language": "en-US" } 161 | }, 162 | "Sarah": { 163 | "voice": { "gender": "female", "variant": 3, "language": "en-US" } 164 | } 165 | } 166 | } 167 | ``` 168 | 169 | ## Working on this project? 170 | 171 | ### Grammar 172 | 173 | The biggest place we need help right now is with the completion of the grammar and formatters. 174 | 175 | #### Short Format 176 | 177 | - [x] break 178 | - [x] emphasis - strong 179 | - [x] emphasis - moderate 180 | - [x] emphasis - none 181 | - [x] emphasis - reduced 182 | - [ ] ipa 183 | - [ ] sub 184 | 185 | #### Standard Format 186 | 187 | - [x] address 188 | - [x] audio 189 | - [x] break (time) 190 | - [x] break (strength) 191 | - [x] characters / chars 192 | - [x] date 193 | - [x] defaults (section) 194 | - [x] disappointed 195 | - [x] disappointed (section) 196 | - [x] dj (section) 197 | - [x] emphasis 198 | - [x] excited 199 | - [x] excited (section) 200 | - [x] expletive / bleep 201 | - [x] fraction 202 | - [x] interjection 203 | - [x] ipa 204 | - [x] lang 205 | - [x] lang (section) 206 | - [x] mark 207 | - [x] newscaster (section) 208 | - [x] number 209 | - [x] ordinal 210 | - [x] telephone / phone 211 | - [x] pitch 212 | - [x] rate 213 | - [x] sub 214 | - [x] time 215 | - [x] unit 216 | - [x] voice 217 | - [x] voice (section) 218 | - [x] volume / vol 219 | - [x] whisper 220 | 221 | ### Available scripts 222 | 223 | - `clean` - remove coverage data, Jest cache and transpiled files, 224 | - `build` - perform all build tasks 225 | - `build:ts` - transpile TypeScript to ES5 226 | - `build:browser` - creates single file `./dist.browser/speechmarkdown.js` file for use in browser, 227 | - `build:minify` - creates single file `./dist.browser/speechmarkdown.min.js` file for use in browser, 228 | - `watch` - interactive watch mode to automatically transpile source files, 229 | - `lint` - lint source files and tests, 230 | - `test` - run tests, 231 | - `test:watch` - interactive watch mode to automatically re-run tests 232 | 233 | ## License 234 | 235 | Licensed under the MIT. See the [LICENSE](https://github.com/speechmarkdown/speechmarkdown-js/blob/master/LICENSE) file for details. 236 | 237 | [ts-badge]: https://img.shields.io/badge/TypeScript-3.4-blue.svg 238 | [typescript]: https://www.typescriptlang.org/ 239 | [typescript-34]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html 240 | [nodejs-badge]: https://img.shields.io/badge/Node.js->=%2010.13-blue.svg 241 | [nodejs]: https://nodejs.org/dist/latest-v10.x/docs/api/ 242 | [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg 243 | [license]: https://github.com/speechmarkdown/speechmarkdown-js/blob/master/LICENSE 244 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.1.1 -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | 3 | ## Simple Parser 4 | Instead of a simple parser architecture as shown here: 5 | 6 | ![](./assets/simple-parser-diagram.png) 7 | 8 | ## Parser-Formatter Architecture 9 | Speech Markdown is first translated into an Abstract Syntax Tree (AST) and a formatter transforms that into the correct format: 10 | 11 | ![](./assets/parser-formatter-diagram.png) 12 | 13 | This is more powerful as formatters have the ability to customize the output based on the differences of each platform. -------------------------------------------------------------------------------- /docs/assets/parser-formatter-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/speechmarkdown/speechmarkdown-js/cc967a13c488af808acbe9e0757de9e1658441cb/docs/assets/parser-formatter-diagram.png -------------------------------------------------------------------------------- /docs/assets/simple-parser-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/speechmarkdown/speechmarkdown-js/cc967a13c488af808acbe9e0757de9e1658441cb/docs/assets/simple-parser-diagram.png -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export { SpeechMarkdown } from './src/SpeechMarkdown'; 2 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | transform: { 4 | "^.+\\.tsx?$": "ts-jest" 5 | }, 6 | moduleFileExtensions: [ 7 | "ts", 8 | "tsx", 9 | "js", 10 | "jsx", 11 | "json", 12 | "node", 13 | ], 14 | testRegex: '(/tests/.*|(\\.|/)(test|spec))\\.(ts|js)x?$', 15 | coverageDirectory: 'coverage', 16 | collectCoverageFrom: [ 17 | 'src/**/*.{ts,tsx,js,jsx}', 18 | '!src/**/*.d.ts', 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "speechmarkdown-js", 3 | "version": "2.1.1", 4 | "description": "Speech Markdown parser and formatters in TypeScript.", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "files": [ 8 | "dist", 9 | "dist.browser" 10 | ], 11 | "engines": { 12 | "node": ">= 10.13" 13 | }, 14 | "author": "Mark Tucker ", 15 | "license": "MIT", 16 | "homepage": "https://github.com/speechmarkdown/speechmarkdown-js#readme", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/speechmarkdown/speechmarkdown-js" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/speechmarkdown/speechmarkdown-js/issues" 23 | }, 24 | "scripts": { 25 | "clean": "rimraf coverage dist tmp", 26 | "build": "npm-run-all --parallel build:*", 27 | "build:ts": "tsc -p tsconfig.json", 28 | "build:browser": "browserify index.ts -p [tsify --noImplicityAny ] -s speechmarkdown -o ./dist.browser/speechmarkdown.js", 29 | "build:minify": "browserify index.ts -p [tsify --noImplicityAny ] -s speechmarkdown | uglifyjs -cm -o ./dist.browser/speechmarkdown.min.js", 30 | "watch": "tsc -w -p tsconfig.json", 31 | "lint": "tslint -t stylish --project \"tsconfig.json\"", 32 | "test": "jest --coverage", 33 | "test:single": "jest -t $1", 34 | "test:watch": "jest --watch" 35 | }, 36 | "devDependencies": { 37 | "@types/jest": "^24.0.18", 38 | "@types/node": "^12.7.11", 39 | "acorn": ">=5.7.4", 40 | "browserify": "^16.5.0", 41 | "clean-css": ">=4.1.11", 42 | "jest": "^29.3.1", 43 | "lodash": "^4.17.19", 44 | "mixin-deep": ">=1.3.2", 45 | "node-notifier": ">=8.0.1", 46 | "npm-run-all": "^4.1.5", 47 | "prettier": "^1.18.2", 48 | "rimraf": "^3.0.0", 49 | "set-value": ">=2.0.1", 50 | "ts-dedent": "^1.1.0", 51 | "ts-jest": "^29.0.3", 52 | "tsify": "^4.0.1", 53 | "tslint": "^5.20.0", 54 | "tslint-config-prettier": "1.18.0", 55 | "tsutils": "^3.17.1", 56 | "typescript": "^4.9.4", 57 | "uglify": "^0.1.5", 58 | "uglify-js": "^3.6.0", 59 | "underscore.string": ">=3.3.5" 60 | }, 61 | "dependencies": { 62 | "myna-parser": "^2.5.1", 63 | "tslib": "^1.10.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface Parser { 2 | parse(markdown: string): any; 3 | } 4 | 5 | export interface Formatter { 6 | format(syntaxTree: any): string; 7 | } 8 | -------------------------------------------------------------------------------- /src/SpeechMarkdown.ts: -------------------------------------------------------------------------------- 1 | import * as factory from './formatters/FormatterFactory'; 2 | import { Parser } from './Interfaces'; 3 | import { SpeechMarkdownParser } from './SpeechMarkdownParser'; 4 | import { SpeechOptions } from './SpeechOptions'; 5 | 6 | export class SpeechMarkdown { 7 | private parser: Parser; 8 | 9 | private readonly defaults: SpeechOptions = { 10 | includeFormatterComment: false, 11 | includeParagraphTag: false, 12 | includeSpeakTag: true, 13 | platform: '', // default - text formatter 14 | preserveEmptyLines: true, 15 | }; 16 | 17 | constructor(private options?: SpeechOptions) { 18 | this.options = { 19 | ...this.defaults, 20 | ...options, 21 | }; 22 | } 23 | 24 | get Parser(): Parser { 25 | if (!this.parser) { 26 | this.parser = new SpeechMarkdownParser(); 27 | } 28 | 29 | return this.parser; 30 | } 31 | 32 | public toText(speechmarkdown: string, options?: SpeechOptions): string { 33 | const methodOptions = { 34 | ...this.options, 35 | ...options, 36 | }; 37 | 38 | const ast = this.Parser.parse(speechmarkdown); 39 | const formatter = factory.createTextFormatter(methodOptions); 40 | 41 | return formatter.format(ast); 42 | } 43 | 44 | public toSSML(speechmarkdown: string, options?: SpeechOptions): string { 45 | const methodOptions = { 46 | ...this.options, 47 | ...options, 48 | }; 49 | 50 | const ast = this.Parser.parse(speechmarkdown); 51 | // console.log(`AST: ${ast}`); 52 | const formatter = factory.createFormatter(methodOptions); 53 | 54 | return formatter.format(ast); 55 | } 56 | 57 | public toAST(speechmarkdown: string): any { 58 | return this.Parser.parse(speechmarkdown); 59 | } 60 | 61 | public toASTString(speechmarkdown: string): string { 62 | const ast = this.Parser.parse(speechmarkdown); 63 | return ast.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/SpeechMarkdownParser.ts: -------------------------------------------------------------------------------- 1 | import { Myna } from 'myna-parser'; 2 | import { Parser } from './Interfaces'; 3 | import { speechMarkdownGrammar } from './SpeechMarkdownGrammar'; 4 | 5 | export class SpeechMarkdownParser implements Parser { 6 | private parser: any; 7 | private myna: any; 8 | 9 | constructor() { 10 | this.myna = Myna; 11 | speechMarkdownGrammar(this.myna); 12 | this.parser = this.myna.parsers.speechmarkdown; 13 | } 14 | 15 | public parse(speechmarkdown: string): any { 16 | // tslint:disable-next-line: no-unnecessary-local-variable 17 | return this.parser(speechmarkdown); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/SpeechOptions.ts: -------------------------------------------------------------------------------- 1 | export interface SpeechOptions { 2 | platform?: string; 3 | includeFormatterComment?: boolean; 4 | includeParagraphTag?: boolean; 5 | includeSpeakTag?: boolean; 6 | preserveEmptyLines?: boolean; 7 | escapeXmlSymbols?: boolean; 8 | voices?: object; // voiceName -> {tag -> {attribute -> value}} 9 | } 10 | -------------------------------------------------------------------------------- /src/formatters/AmazonPollyNeuralSsmlFormatter.ts: -------------------------------------------------------------------------------- 1 | import { SpeechOptions } from '../SpeechOptions'; 2 | import { SsmlFormatterBase, TagsObject } from './SsmlFormatterBase'; 3 | 4 | export class AmazonPollyNeuralSsmlFormatter extends SsmlFormatterBase { 5 | constructor(public options: SpeechOptions) { 6 | super(options); 7 | 8 | this.modifierKeyToSsmlTagMappings.cardinal = 'say-as'; 9 | this.modifierKeyToSsmlTagMappings.digits = 'say-as'; 10 | this.modifierKeyToSsmlTagMappings.drc = 'amazon:effect'; 11 | this.modifierKeyToSsmlTagMappings.lang = 'lang'; 12 | this.modifierKeyToSsmlTagMappings.newscaster = 'amazon:domain'; 13 | 14 | this.modifierKeyMappings.digits = 'digits'; 15 | this.modifierKeyMappings.cardinal = 'cardinal'; 16 | } 17 | 18 | // tslint:disable-next-line: max-func-body-length 19 | private getTextModifierObject(ast: any): any { 20 | let textModifierObject = new TagsObject(this); 21 | 22 | for (let index = 0; index < ast.children.length; index++) { 23 | const child = ast.children[index]; 24 | 25 | switch (child.name) { 26 | case 'plainText': 27 | case 'plainTextSpecialChars': 28 | case 'plainTextEmphasis': 29 | case 'plainTextPhone': 30 | case 'plainTextModifier': { 31 | textModifierObject['text'] = child.allText; 32 | break; 33 | } 34 | case 'textModifierKeyOptionalValue': { 35 | let key = child.children[0].allText; 36 | key = this.modifierKeyMappings[key] || key; 37 | const value = 38 | child.children.length === 2 ? child.children[1].allText : ''; 39 | const ssmlTag = this.modifierKeyToSsmlTagMappings[key]; 40 | 41 | switch (key) { 42 | case 'address': 43 | case 'cardinal': 44 | case 'characters': 45 | case 'digits': 46 | case 'expletive': 47 | case 'fraction': 48 | case 'number': 49 | case 'ordinal': 50 | case 'telephone': 51 | case 'unit': 52 | textModifierObject.tag(ssmlTag, { 'interpret-as': key }); 53 | break; 54 | 55 | case 'date': 56 | textModifierObject.tag(ssmlTag, { 57 | 'interpret-as': key, 58 | format: value || 'ymd', 59 | }); 60 | break; 61 | 62 | case 'time': 63 | textModifierObject.tag(ssmlTag, { 64 | 'interpret-as': key, 65 | format: value || 'hms12', 66 | }); 67 | break; 68 | 69 | case 'ipa': 70 | textModifierObject.tag(ssmlTag, { alphabet: key, ph: value }); 71 | break; 72 | 73 | case 'sub': 74 | textModifierObject.tag(ssmlTag, { alias: value }); 75 | break; 76 | 77 | case 'volume': 78 | case 'rate': { 79 | const attrs = {}; 80 | attrs[key] = value || 'medium'; 81 | textModifierObject.tag(ssmlTag, attrs, true); 82 | break; 83 | } 84 | 85 | case 'lang': 86 | textModifierObject.tag(ssmlTag, { 'xml:lang': value }); 87 | break; 88 | 89 | case 'drc': 90 | textModifierObject.tag(ssmlTag, { name: key }); 91 | break; 92 | 93 | // unavailable tags 94 | case 'excited': 95 | case 'disappointed': 96 | case 'emphasis': 97 | case 'interjection': 98 | case 'voice': 99 | case 'whisper': { 100 | break; 101 | } 102 | 103 | default: { 104 | } 105 | } 106 | break; 107 | } 108 | } 109 | } 110 | 111 | return textModifierObject; 112 | } 113 | 114 | // tslint:disable-next-line: max-func-body-length 115 | private getSectionObject(ast: any): any { 116 | let sectionObject = new TagsObject(this); 117 | 118 | for (let index = 0; index < ast.children.length; index++) { 119 | const child = ast.children[index]; 120 | 121 | if (child.name === 'sectionModifierKeyOptionalValue') { 122 | let key = child.children[0].allText; 123 | const value = 124 | child.children.length === 2 ? child.children[1].allText : ''; 125 | const ssmlTag = this.modifierKeyToSsmlTagMappings[key]; 126 | 127 | switch (key) { 128 | case 'lang': 129 | sectionObject.tag(ssmlTag, { 'xml:lang': value }); 130 | break; 131 | 132 | case 'newscaster': 133 | sectionObject.tag(ssmlTag, { name: 'news' }); 134 | break; 135 | 136 | case 'defaults': { 137 | break; 138 | } 139 | 140 | case 'voice': 141 | case 'dj': 142 | case 'excited': 143 | case 'disappointed': { 144 | break; 145 | } 146 | 147 | default: { 148 | } 149 | } 150 | } 151 | } 152 | 153 | return sectionObject; 154 | } 155 | 156 | // tslint:disable-next-line: max-func-body-length 157 | protected formatFromAst(ast: any, lines: string[] = []): string[] { 158 | switch (ast.name) { 159 | case 'document': { 160 | if (this.options.includeFormatterComment) { 161 | this.addComment( 162 | 'Converted from Speech Markdown to SSML for Amazon Polly', 163 | lines, 164 | ); 165 | } 166 | 167 | if (this.options.includeSpeakTag) { 168 | return this.addSpeakTag(ast.children, true, false, null, lines); 169 | } else { 170 | this.processAst(ast.children, lines); 171 | return lines; 172 | } 173 | } 174 | case 'paragraph': { 175 | if (this.options.includeParagraphTag) { 176 | return this.addTag('p', ast.children, true, false, null, lines); 177 | } else { 178 | this.processAst(ast.children, lines); 179 | return lines; 180 | } 181 | } 182 | case 'shortBreak': { 183 | const time = ast.children[0].allText; 184 | return this.addTagWithAttrs(lines, null, 'break', { time: time }); 185 | } 186 | case 'break': { 187 | const val = ast.children[0].allText; 188 | let attrs = {}; 189 | switch (ast.children[0].children[0].name) { 190 | case 'breakStrengthValue': 191 | attrs = { strength: val }; 192 | break; 193 | case 'time': 194 | attrs = { time: val }; 195 | break; 196 | } 197 | return this.addTagWithAttrs(lines, null, 'break', attrs); 198 | } 199 | 200 | case 'markTag': { 201 | const name = ast.children[0].allText; 202 | return this.addTagWithAttrs(lines, null, 'mark', { name: name }); 203 | } 204 | case 'textModifier': { 205 | const tmo = this.getTextModifierObject(ast); 206 | 207 | const tagsSortedDesc = Object.keys(tmo.tags).sort((a: any, b: any) => { 208 | return tmo.tags[b].sortId - tmo.tags[a].sortId; 209 | }); 210 | 211 | let inner = tmo.text; 212 | 213 | for (let index = 0; index < tagsSortedDesc.length; index++) { 214 | const tag = tagsSortedDesc[index]; 215 | const attrs = tmo.tags[tag].attrs; 216 | 217 | inner = this.getTagWithAttrs(inner, tag, attrs); 218 | } 219 | lines.push(inner); 220 | 221 | return lines; 222 | } 223 | case 'section': { 224 | const so = this.getSectionObject(ast); 225 | 226 | const tagsSortedAsc = Object.keys(so.tags).sort((a: any, b: any) => { 227 | return so.tags[a].sortId - so.tags[b].sortId; 228 | }); 229 | 230 | this.addSectionEndTag(lines); 231 | this.addSectionStartTag(tagsSortedAsc, so, lines); 232 | 233 | return lines; 234 | } 235 | case 'simpleLine': { 236 | this.processAst(ast.children, lines); 237 | return lines; 238 | } 239 | case 'lineEnd': { 240 | lines.push(ast.allText); 241 | return lines; 242 | } 243 | case 'emptyLine': { 244 | if (this.options.preserveEmptyLines) { 245 | lines.push(ast.allText); 246 | } 247 | 248 | return lines; 249 | } 250 | 251 | case 'shortEmphasisModerate': 252 | case 'shortEmphasisStrong': 253 | case 'shortEmphasisNone': 254 | case 'shortEmphasisReduced': { 255 | lines.push(ast.allText.replace(/\+/g, '')); 256 | return lines; 257 | } 258 | 259 | case 'plainText': 260 | case 'plainTextSpecialChars': { 261 | lines.push(ast.allText); 262 | return lines; 263 | } 264 | 265 | default: { 266 | this.processAst(ast.children, lines); 267 | return lines; 268 | } 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/formatters/FormatterBase.ts: -------------------------------------------------------------------------------- 1 | import { Formatter } from '../Interfaces'; 2 | import { SpeechOptions } from '../SpeechOptions'; 3 | 4 | export abstract class FormatterBase implements Formatter { 5 | protected constructor(public options: SpeechOptions) { 6 | this.options = options; 7 | } 8 | 9 | public abstract format(ast: any): string; 10 | 11 | // Adds each element of the array as markdown 12 | protected addArray(ast: any, lines: string[]): string[] { 13 | for (const child of ast) { 14 | this.formatFromAst(child, lines); 15 | } 16 | return lines; 17 | } 18 | 19 | protected processAst(ast: any, lines: string[]): void { 20 | if (ast instanceof Array) { 21 | this.addArray(ast, lines); 22 | } else { 23 | this.formatFromAst(ast, lines); 24 | } 25 | } 26 | 27 | protected abstract formatFromAst(ast: any, lines: string[]): string[]; 28 | } 29 | -------------------------------------------------------------------------------- /src/formatters/FormatterFactory.ts: -------------------------------------------------------------------------------- 1 | import { Formatter } from '../Interfaces'; 2 | import { SpeechOptions } from '../SpeechOptions'; 3 | import { TextFormatter } from './TextFormatter'; 4 | import { AmazonAlexaSsmlFormatter } from './AmazonAlexaSsmlFormatter'; 5 | import { AmazonPollySsmlFormatter } from './AmazonPollySsmlFormatter'; 6 | import { AmazonPollyNeuralSsmlFormatter } from './AmazonPollyNeuralSsmlFormatter'; 7 | import { GoogleAssistantSsmlFormatter } from './GoogleAssistantSsmlFormatter'; 8 | import { SamsungBixbySsmlFormatter } from './SamsungBixbySsmlFormatter'; 9 | import { MicrosoftAzureSsmlFormatter } from './MicrosoftAzureSsmlFormatter'; 10 | 11 | export function createFormatter(options: SpeechOptions): Formatter { 12 | switch (options.platform) { 13 | case 'amazon-alexa': 14 | return new AmazonAlexaSsmlFormatter(options); 15 | case 'amazon-polly': 16 | return new AmazonPollySsmlFormatter(options); 17 | case 'amazon-polly-neural': 18 | return new AmazonPollyNeuralSsmlFormatter(options); 19 | case 'google-assistant': 20 | return new GoogleAssistantSsmlFormatter(options); 21 | case 'samsung-bixby': 22 | return new SamsungBixbySsmlFormatter(options); 23 | case 'microsoft-azure': 24 | return new MicrosoftAzureSsmlFormatter(options); 25 | default: 26 | return new TextFormatter(options); 27 | } 28 | } 29 | 30 | export function createTextFormatter(options: SpeechOptions): Formatter { 31 | return new TextFormatter(options); 32 | } 33 | -------------------------------------------------------------------------------- /src/formatters/SsmlFormatterBase.ts: -------------------------------------------------------------------------------- 1 | import { SpeechOptions } from '../SpeechOptions'; 2 | import { FormatterBase } from './FormatterBase'; 3 | 4 | export class TagsObject { 5 | private base: SsmlFormatterBase; 6 | public tags: Record; 7 | public text: string; 8 | 9 | public constructor(base: SsmlFormatterBase) { 10 | this.base = base; 11 | this.tags = {}; 12 | this.text = ''; 13 | } 14 | 15 | public tag(tag: string, attrs: object, augment: boolean = false) { 16 | const sortId = this.base.ssmlTagSortOrder.indexOf(tag); 17 | 18 | if (!this.tags[tag]) { 19 | this.tags[tag] = { sortId: sortId, attrs: null }; 20 | } 21 | if (augment) { 22 | this.tags[tag].attrs = { ...this.tags[tag].attrs, ...attrs }; 23 | } else { 24 | this.tags[tag].attrs = attrs; 25 | } 26 | } 27 | 28 | protected voiceTagNamed(voices: null | object, name: string) { 29 | let info = voices && voices[name]; 30 | if (info) { 31 | if (typeof info !== 'object') { 32 | info = { 33 | voice: { name: name }, 34 | //lang: { 'xml:lang': info } 35 | }; 36 | } 37 | 38 | Object.keys(info).forEach((tag: string) => { 39 | const attributes = info[tag]; 40 | this.tag(tag, attributes); 41 | }); 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | public voiceTag(tag: string, value: string) { 48 | const name = this.base.sentenceCase(value || 'device'); 49 | 50 | const handled = 51 | this.voiceTagNamed(this.base.options && this.base.options.voices, name) || 52 | this.voiceTagNamed(this.base.validVoices, name); 53 | } 54 | } 55 | 56 | type Dictionary = { [key: string]: T }; 57 | 58 | export abstract class SsmlFormatterBase extends FormatterBase { 59 | public validVoices: Record = {}; 60 | 61 | public static readonly XML_ESCAPE_MAPPING: Dictionary = { 62 | '<': '<', 63 | '>': '>', 64 | '&': '&', 65 | '"': '"', 66 | "'": ''', 67 | }; 68 | 69 | public static readonly XML_UNESCAPE_MAPPING: Dictionary< 70 | string 71 | > = (function swapJSON(dictionary: Dictionary) { 72 | return Object.keys(dictionary).reduce((acc: any, key: string) => { 73 | acc[dictionary[key]] = key; 74 | return acc; 75 | }, {}); 76 | })(SsmlFormatterBase.XML_ESCAPE_MAPPING); 77 | 78 | protected constructor(public options: SpeechOptions) { 79 | super(options); 80 | } 81 | 82 | protected sectionTags: string[] = []; 83 | 84 | protected modifierKeyMappings: any = { 85 | chars: 'characters', 86 | cardinal: 'number', 87 | digits: 'characters', 88 | bleep: 'expletive', 89 | phone: 'telephone', 90 | vol: 'volume', 91 | }; 92 | 93 | public ssmlTagSortOrder: string[] = [ 94 | 'emphasis', 95 | 'say-as', 96 | 'prosody', 97 | 'amazon:domain', 98 | 'amazon:effect', 99 | 'amazon:emotion', 100 | 'voice', 101 | 'lang', 102 | 'sub', 103 | 'phoneme', 104 | ]; 105 | 106 | protected modifierKeyToSsmlTagMappings: any = { 107 | emphasis: 'emphasis', 108 | address: 'say-as', 109 | number: 'say-as', 110 | characters: 'say-as', 111 | expletive: 'say-as', 112 | fraction: 'say-as', 113 | interjection: 'say-as', 114 | ordinal: 'say-as', 115 | telephone: 'say-as', 116 | unit: 'say-as', 117 | time: 'say-as', 118 | date: 'say-as', 119 | whisper: null, 120 | sub: 'sub', 121 | ipa: 'phoneme', 122 | rate: 'prosody', 123 | pitch: 'prosody', 124 | volume: 'prosody', 125 | drc: null, 126 | timbre: null, 127 | lang: null, 128 | voice: null, 129 | dj: null, 130 | defaults: null, 131 | newscaster: null, 132 | excited: null, 133 | disappointed: null, 134 | }; 135 | 136 | public format(ast: any): string { 137 | const lines = this.formatFromAst(ast, []); 138 | 139 | return lines.join(''); 140 | } 141 | 142 | protected addSectionStartTag( 143 | tagsSortedAsc: string[], 144 | so: any, 145 | lines: string[], 146 | ) { 147 | this.sectionTags = [...tagsSortedAsc].reverse(); 148 | 149 | for (let index = 0; index < tagsSortedAsc.length; index++) { 150 | const tag = tagsSortedAsc[index]; 151 | const attrs = so.tags[tag].attrs; 152 | lines.push('\n'); 153 | lines.push(this.startTag(tag, attrs, false)); 154 | } 155 | } 156 | 157 | protected addSectionEndTag(lines: string[]) { 158 | if (this.sectionTags.length > 0) { 159 | // add previous end tag(s) 160 | for (let index = 0; index < this.sectionTags.length; index++) { 161 | const tag = this.sectionTags[index]; 162 | lines.push(this.endTag(tag, false)); 163 | lines.push('\n'); 164 | } 165 | } 166 | } 167 | 168 | // Adds tagged content 169 | protected addTag( 170 | tag: string, 171 | ast: any, 172 | newLine: boolean, 173 | newLineAfterEnd: boolean, 174 | attr: any, 175 | lines: string[], 176 | ): string[] { 177 | lines.push(this.startTag(tag, attr, newLine)); 178 | 179 | this.processAst(ast, lines); 180 | 181 | lines.push(this.endTag(tag, newLine)); 182 | 183 | if (newLineAfterEnd) { 184 | lines.push('\n'); 185 | } 186 | 187 | return lines; 188 | } 189 | 190 | protected addSpeakTag( 191 | ast: any, 192 | newLine: boolean, 193 | newLineAfterEnd: boolean, 194 | attr: any, 195 | lines: string[], 196 | ): string[] { 197 | lines.push(this.startTag('speak', attr, newLine)); 198 | 199 | this.processAst(ast, lines); 200 | 201 | this.addSectionEndTag(lines); 202 | 203 | lines.push(this.endTag('speak', newLine)); 204 | 205 | if (newLineAfterEnd) { 206 | lines.push('\n'); 207 | } 208 | 209 | return lines; 210 | } 211 | 212 | protected addComment(commentText: string, lines: string[]): string[] { 213 | lines.push(`\n`); 214 | return lines; 215 | } 216 | 217 | // Returns the SSML for a start tag 218 | protected startTag(tag: string, attr: any, newLine: boolean = false): string { 219 | let attrStr = ''; 220 | if (attr) { 221 | attrStr = 222 | ' ' + 223 | Object.keys(attr) 224 | .map((k: any) => { 225 | return k + '="' + attr[k] + '"'; 226 | }) 227 | .join(' '); 228 | } 229 | 230 | return '<' + tag + attrStr + '>' + (newLine ? '\n' : ''); 231 | } 232 | 233 | // Returns the SSML for an end tag 234 | protected endTag(tag: string, newLine: boolean = false): string { 235 | return (newLine ? '\n' : '') + ''; 236 | // return ''; 237 | } 238 | 239 | protected voidTag(tag: string, attr: any): string { 240 | let attrStr = ''; 241 | if (attr) { 242 | attrStr = 243 | ' ' + 244 | Object.keys(attr) 245 | .map((k: any) => { 246 | return k + '="' + attr[k] + '"'; 247 | }) 248 | .join(' '); 249 | } 250 | return '<' + tag + attrStr + '/>'; 251 | } 252 | 253 | protected addTagWithAttrs( 254 | lines: string[], 255 | text: string, 256 | tag: string, 257 | attrs: any, 258 | forceEndTag: boolean = false, 259 | ): string[] { 260 | if (text || forceEndTag) { 261 | lines.push(this.startTag(tag, attrs)); 262 | 263 | if (text) { 264 | lines.push(text); 265 | } 266 | 267 | lines.push(this.endTag(tag, false)); 268 | } else { 269 | lines.push(this.voidTag(tag, attrs)); 270 | } 271 | 272 | return lines; 273 | } 274 | 275 | protected getTagWithAttrs(text: string, tag: string, attrs: any): string { 276 | let lines: string[] = []; 277 | 278 | if (text) { 279 | lines.push(this.startTag(tag, attrs)); 280 | lines.push(text); 281 | lines.push(this.endTag(tag, false)); 282 | } else { 283 | lines.push(this.voidTag(tag, attrs)); 284 | } 285 | 286 | return lines.join(''); 287 | } 288 | 289 | public sentenceCase(text: string) { 290 | return text 291 | .replace(/[a-z]/i, (letter: string) => { 292 | return letter.toUpperCase(); 293 | }) 294 | .trim(); 295 | } 296 | 297 | public escapeXmlCharacters(unescaped: string): string { 298 | // Only process once (by unescaping) 299 | let revPattern = `${Object.keys( 300 | SsmlFormatterBase.XML_UNESCAPE_MAPPING, 301 | ).join('|')}]`; 302 | let reversed = unescaped.replace( 303 | new RegExp(revPattern, 'g'), 304 | (s: string) => SsmlFormatterBase.XML_UNESCAPE_MAPPING[s], 305 | ); 306 | 307 | // Escape XML characters 308 | let pattern = `[${Object.keys(SsmlFormatterBase.XML_ESCAPE_MAPPING).join( 309 | '', 310 | )}]`; 311 | let escaped = reversed.replace( 312 | new RegExp(pattern, 'g'), 313 | (s: string) => SsmlFormatterBase.XML_ESCAPE_MAPPING[s], 314 | ); 315 | 316 | // console.log([unescaped, reversed, escaped].join('\n')); 317 | 318 | return escaped; 319 | } 320 | 321 | protected abstract formatFromAst(ast: any, lines: string[]): string[]; 322 | } 323 | -------------------------------------------------------------------------------- /src/formatters/TextFormatter.ts: -------------------------------------------------------------------------------- 1 | import { SpeechOptions } from '../SpeechOptions'; 2 | import { FormatterBase } from './FormatterBase'; 3 | 4 | export class TextFormatter extends FormatterBase { 5 | constructor(public options: SpeechOptions) { 6 | super(options); 7 | } 8 | 9 | public format(ast: any): string { 10 | const lines = this.formatFromAst(ast, []); 11 | let txt = lines.join('').trim(); 12 | 13 | // replace multiple whitespace with a single space 14 | // tslint:disable-next-line: no-regex-spaces 15 | txt = txt.replace(/ +/g, ' '); 16 | 17 | return txt; 18 | } 19 | 20 | protected formatFromAst(ast: any, lines: string[] = []): string[] { 21 | switch (ast.name) { 22 | case 'document': { 23 | this.processAst(ast.children, lines); 24 | return lines; 25 | } 26 | case 'paragraph': { 27 | this.processAst(ast.children, lines); 28 | return lines; 29 | } 30 | case 'simpleLine': { 31 | this.processAst(ast.children, lines); 32 | return lines; 33 | } 34 | case 'lineEnd': { 35 | lines.push(ast.allText); 36 | return lines; 37 | } 38 | case 'emptyLine': { 39 | if (this.options.preserveEmptyLines) { 40 | lines.push(ast.allText); 41 | } 42 | 43 | return lines; 44 | } 45 | case 'plainText': 46 | case 'plainTextSpecialChars': 47 | case 'plainTextEmphasis': 48 | case 'plainTextPhone': 49 | case 'plainTextModifier': { 50 | lines.push(ast.allText); 51 | return lines; 52 | } 53 | 54 | case 'audio': 55 | return lines; 56 | 57 | default: { 58 | this.processAst(ast.children, lines); 59 | return lines; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/address-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('address-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | I'm at (150th CT NE, Redmond, WA)[address]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I'm at 150th CT NE, Redmond, WA. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | const expected = dedent` 33 | 34 | I'm at 150th CT NE, Redmond, WA. 35 | 36 | `; 37 | 38 | expect(ssml).toBe(expected); 39 | }); 40 | 41 | test('converts to SSML - Amazon Polly (Neural)', () => { 42 | const options = { 43 | platform: 'amazon-polly-neural', 44 | }; 45 | const ssml = speech.toSSML(markdown, options); 46 | const expected = dedent` 47 | 48 | I'm at 150th CT NE, Redmond, WA. 49 | 50 | `; 51 | 52 | expect(ssml).toBe(expected); 53 | }); 54 | 55 | test('converts to SSML - Google Assistant', () => { 56 | const options = { 57 | platform: 'google-assistant', 58 | }; 59 | const ssml = speech.toSSML(markdown, options); 60 | 61 | const expected = dedent` 62 | 63 | I'm at 150th CT NE, Redmond, WA. 64 | 65 | `; 66 | 67 | expect(ssml).toBe(expected); 68 | }); 69 | 70 | test('converts to SSML - Samsung Bixby', () => { 71 | const options = { 72 | platform: 'samsung-bixby', 73 | }; 74 | const ssml = speech.toSSML(markdown, options); 75 | 76 | const expected = dedent` 77 | 78 | I'm at 150th CT NE, Redmond, WA. 79 | 80 | `; 81 | 82 | expect(ssml).toBe(expected); 83 | }); 84 | 85 | test('converts to SSML - Microsoft Azure', () => { 86 | const options = { 87 | platform: 'microsoft-azure', 88 | }; 89 | const ssml = speech.toSSML(markdown, options); 90 | 91 | const expected = dedent` 92 | 93 | I'm at 150th CT NE, Redmond, WA. 94 | 95 | `; 96 | 97 | expect(ssml).toBe(expected); 98 | }); 99 | 100 | test('converts to Plain Text', () => { 101 | const options = {}; 102 | const text = speech.toText(markdown, options); 103 | 104 | const expected = dedent` 105 | I'm at 150th CT NE, Redmond, WA. 106 | `; 107 | 108 | expect(text).toBe(expected); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /tests/break-short.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('break-short', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Sample [3s] speech [250ms] markdown 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Sample speech markdown 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Sample speech markdown 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Sample speech markdown 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Sample speech markdown 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Sample speech markdown 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Sample speech markdown 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Sample speech markdown 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/break-strength.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('break-strength', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Sample [break:"weak"] speech [break:"strong"] markdown 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Sample speech markdown 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Sample speech markdown 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Sample speech markdown 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Sample speech markdown 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Sample speech markdown 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Sample speech markdown 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Sample speech markdown 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/break-time.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('break-time', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Sample [break:"3s"] speech [break:"250ms"] markdown 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Sample speech markdown 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Sample speech markdown 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Sample speech markdown 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Sample speech markdown 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Sample speech markdown 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Sample speech markdown 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Sample speech markdown 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/cardinal-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('cardinal-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Your balance is: (12345)[cardinal]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Your balance is: 12345. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Your balance is: 12345. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Your balance is: 12345. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Your balance is: 12345. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Your balance is: 12345. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Your balance is: 12345. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Your balance is: 12345. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/characters-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('characters-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Countdown: (321)[characters] 10 | The word is spelled: (park)[chars] 11 | `; 12 | 13 | test('converts to SSML - Amazon Alexa', () => { 14 | const options = { 15 | platform: 'amazon-alexa', 16 | }; 17 | const ssml = speech.toSSML(markdown, options); 18 | 19 | const expected = dedent` 20 | 21 | Countdown: 321 22 | The word is spelled: park 23 | 24 | `; 25 | 26 | expect(ssml).toBe(expected); 27 | }); 28 | 29 | test('converts to SSML - Amazon Polly', () => { 30 | const options = { 31 | platform: 'amazon-polly', 32 | }; 33 | const ssml = speech.toSSML(markdown, options); 34 | 35 | const expected = dedent` 36 | 37 | Countdown: 321 38 | The word is spelled: park 39 | 40 | `; 41 | 42 | expect(ssml).toBe(expected); 43 | }); 44 | 45 | test('converts to SSML - Amazon Polly (Neural)', () => { 46 | const options = { 47 | platform: 'amazon-polly-neural', 48 | }; 49 | const ssml = speech.toSSML(markdown, options); 50 | 51 | const expected = dedent` 52 | 53 | Countdown: 321 54 | The word is spelled: park 55 | 56 | `; 57 | 58 | expect(ssml).toBe(expected); 59 | }); 60 | 61 | test('converts to SSML - Google Assistant', () => { 62 | const options = { 63 | platform: 'google-assistant', 64 | }; 65 | const ssml = speech.toSSML(markdown, options); 66 | 67 | const expected = dedent` 68 | 69 | Countdown: 321 70 | The word is spelled: park 71 | 72 | `; 73 | 74 | expect(ssml).toBe(expected); 75 | }); 76 | 77 | test('converts to SSML - Samsung Bixby', () => { 78 | const options = { 79 | platform: 'samsung-bixby', 80 | }; 81 | const ssml = speech.toSSML(markdown, options); 82 | 83 | const expected = dedent` 84 | 85 | Countdown: 321 86 | The word is spelled: park 87 | 88 | `; 89 | 90 | expect(ssml).toBe(expected); 91 | }); 92 | 93 | test('converts to SSML - Microsoft Azure', () => { 94 | const options = { 95 | platform: 'microsoft-azure', 96 | }; 97 | const ssml = speech.toSSML(markdown, options); 98 | 99 | const expected = dedent` 100 | 101 | Countdown: 321 102 | The word is spelled: park 103 | 104 | `; 105 | 106 | expect(ssml).toBe(expected); 107 | }); 108 | 109 | test('converts to Plain Text', () => { 110 | const options = {}; 111 | const text = speech.toText(markdown, options); 112 | 113 | const expected = dedent` 114 | Countdown: 321 115 | The word is spelled: park 116 | `; 117 | 118 | expect(text).toBe(expected); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /tests/date-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('date-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | The date is (10-19-2016)[date:"mdy"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | The date is 10-19-2016. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | The date is 10-19-2016. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | The date is 10-19-2016. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | The date is 10-19-2016. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | The date is 10-19-2016. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | The date is 10-19-2016. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | The date is 10-19-2016. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/digits-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('digits-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Countdown: (321)[digits] 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Countdown: 321 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Countdown: 321 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Countdown: 321 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Countdown: 321 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Countdown: 321 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Countdown: 321 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Countdown: 321 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/disappointed-section.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('disappointed-section normal to disappointed intensities to normal', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Normal speech. 10 | 11 | #[disappointed] 12 | I am disappointed - medium. 13 | 14 | #[disappointed:"medium"] 15 | I am disappointed - medium. 16 | 17 | #[disappointed:"low"] 18 | I am disappointed - low. 19 | 20 | #[disappointed:"high"] 21 | I am disappointed - high. 22 | 23 | #[defaults] 24 | Now back to normal speech. 25 | `; 26 | 27 | test('converts to SSML - Amazon Alexa', () => { 28 | const options = { 29 | platform: 'amazon-alexa', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Normal speech. 36 | 37 | 38 | 39 | I am disappointed - medium. 40 | 41 | 42 | 43 | 44 | I am disappointed - medium. 45 | 46 | 47 | 48 | 49 | I am disappointed - low. 50 | 51 | 52 | 53 | 54 | I am disappointed - high. 55 | 56 | 57 | 58 | Now back to normal speech. 59 | 60 | `; 61 | 62 | expect(ssml).toBe(expected); 63 | }); 64 | 65 | test('converts to SSML - Amazon Polly', () => { 66 | const options = { 67 | platform: 'amazon-polly', 68 | }; 69 | const ssml = speech.toSSML(markdown, options); 70 | 71 | const expected = dedent` 72 | 73 | Normal speech. 74 | 75 | 76 | I am disappointed - medium. 77 | 78 | 79 | I am disappointed - medium. 80 | 81 | 82 | I am disappointed - low. 83 | 84 | 85 | I am disappointed - high. 86 | 87 | 88 | Now back to normal speech. 89 | 90 | `; 91 | 92 | expect(ssml).toBe(expected); 93 | }); 94 | 95 | test('converts to SSML - Amazon Polly (Neural)', () => { 96 | const options = { 97 | platform: 'amazon-polly-neural', 98 | }; 99 | const ssml = speech.toSSML(markdown, options); 100 | 101 | const expected = dedent` 102 | 103 | Normal speech. 104 | 105 | 106 | I am disappointed - medium. 107 | 108 | 109 | I am disappointed - medium. 110 | 111 | 112 | I am disappointed - low. 113 | 114 | 115 | I am disappointed - high. 116 | 117 | 118 | Now back to normal speech. 119 | 120 | `; 121 | 122 | expect(ssml).toBe(expected); 123 | }); 124 | 125 | test('converts to SSML - Google Assistant', () => { 126 | const options = { 127 | platform: 'google-assistant', 128 | preserveEmptyLines: false, 129 | }; 130 | const ssml = speech.toSSML(markdown, options); 131 | 132 | const expected = dedent` 133 | 134 | Normal speech. 135 | I am disappointed - medium. 136 | I am disappointed - medium. 137 | I am disappointed - low. 138 | I am disappointed - high. 139 | Now back to normal speech. 140 | 141 | `; 142 | 143 | expect(ssml).toBe(expected); 144 | }); 145 | 146 | test('converts to SSML - Samsung Bixby', () => { 147 | const options = { 148 | platform: 'samsung-bixby', 149 | preserveEmptyLines: false, 150 | }; 151 | const ssml = speech.toSSML(markdown, options); 152 | 153 | const expected = dedent` 154 | 155 | Normal speech. 156 | I am disappointed - medium. 157 | I am disappointed - medium. 158 | I am disappointed - low. 159 | I am disappointed - high. 160 | Now back to normal speech. 161 | 162 | `; 163 | 164 | expect(ssml).toBe(expected); 165 | }); 166 | 167 | test('converts to Plain Text', () => { 168 | const options = {}; 169 | const text = speech.toText(markdown, options); 170 | 171 | const expected = dedent` 172 | Normal speech. 173 | 174 | 175 | I am disappointed - medium. 176 | 177 | 178 | I am disappointed - medium. 179 | 180 | 181 | I am disappointed - low. 182 | 183 | 184 | I am disappointed - high. 185 | 186 | 187 | Now back to normal speech. 188 | `; 189 | 190 | expect(text).toBe(expected); 191 | }); 192 | }); 193 | 194 | describe('disappointed-section end speak tag at end', () => { 195 | const speech = new SpeechMarkdown(); 196 | 197 | const markdown = dedent` 198 | #[disappointed] 199 | Section 1 200 | `; 201 | 202 | test('converts to SSML - Amazon Alexa', () => { 203 | const options = { 204 | platform: 'amazon-alexa', 205 | }; 206 | const ssml = speech.toSSML(markdown, options); 207 | 208 | const expected = dedent` 209 | 210 | 211 | 212 | Section 1 213 | 214 | 215 | `; 216 | 217 | expect(ssml).toBe(expected); 218 | }); 219 | 220 | test('converts to SSML - Google Assistant', () => { 221 | const options = { 222 | platform: 'google-assistant', 223 | preserveEmptyLines: false, 224 | }; 225 | const ssml = speech.toSSML(markdown, options); 226 | 227 | const expected = dedent` 228 | 229 | Section 1 230 | 231 | `; 232 | 233 | expect(ssml).toBe(expected); 234 | }); 235 | 236 | test('converts to SSML - Samsung Bixby', () => { 237 | const options = { 238 | platform: 'samsung-bixby', 239 | preserveEmptyLines: false, 240 | }; 241 | const ssml = speech.toSSML(markdown, options); 242 | 243 | const expected = dedent` 244 | 245 | Section 1 246 | 247 | `; 248 | 249 | expect(ssml).toBe(expected); 250 | }); 251 | 252 | test('converts to Plain Text', () => { 253 | const options = {}; 254 | const text = speech.toText(markdown, options); 255 | 256 | const expected = dedent` 257 | Section 1 258 | `; 259 | expect(text).toBe(expected); 260 | }); 261 | }); 262 | 263 | describe('disappointed-section section on same line', () => { 264 | const speech = new SpeechMarkdown(); 265 | 266 | const markdown = dedent` 267 | #[disappointed] Hey there, nice to meet you 268 | `; 269 | 270 | test('converts to SSML - Amazon Alexa', () => { 271 | const options = { 272 | platform: 'amazon-alexa', 273 | }; 274 | const ssml = speech.toSSML(markdown, options); 275 | 276 | const expected = dedent` 277 | 278 | 279 | Hey there, nice to meet you 280 | 281 | 282 | `; 283 | 284 | expect(ssml).toBe(expected); 285 | }); 286 | 287 | test('converts to SSML - Google Assistant', () => { 288 | const options = { 289 | platform: 'google-assistant', 290 | }; 291 | const ssml = speech.toSSML(markdown, options); 292 | 293 | const expected = dedent` 294 | 295 | Hey there, nice to meet you 296 | 297 | `; 298 | 299 | expect(ssml).toBe(expected); 300 | }); 301 | 302 | test('converts to SSML - Samsung Bixby', () => { 303 | const options = { 304 | platform: 'samsung-bixby', 305 | }; 306 | const ssml = speech.toSSML(markdown, options); 307 | 308 | const expected = dedent` 309 | 310 | Hey there, nice to meet you 311 | 312 | `; 313 | 314 | expect(ssml).toBe(expected); 315 | }); 316 | 317 | test('converts to Plain Text', () => { 318 | const options = {}; 319 | const text = speech.toText(markdown, options); 320 | 321 | const expected = 'Hey there, nice to meet you'; 322 | 323 | expect(text).toBe(expected); 324 | }); 325 | }); 326 | -------------------------------------------------------------------------------- /tests/disappointed-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('disappointed-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | We can switch (from disappointed)[disappointed] to (really disappointed)[disappointed:"high"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | We can switch from disappointed to really disappointed. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | We can switch from disappointed to really disappointed. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | We can switch from disappointed to really disappointed. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | We can switch from disappointed to really disappointed. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | We can switch from disappointed to really disappointed. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to Plain Text', () => { 88 | const options = {}; 89 | const text = speech.toText(markdown, options); 90 | 91 | const expected = dedent` 92 | We can switch from disappointed to really disappointed. 93 | `; 94 | 95 | expect(text).toBe(expected); 96 | }); 97 | }); 98 | 99 | describe('disappointed-standard non-lowercase intensity', () => { 100 | const speech = new SpeechMarkdown(); 101 | 102 | const markdown = dedent` 103 | We can switch (from disappointed)[disappointed] to (really disappointed)[disappointed:"HigH"]. 104 | `; 105 | 106 | test('converts to SSML - Amazon Alexa', () => { 107 | const options = { 108 | platform: 'amazon-alexa', 109 | }; 110 | const ssml = speech.toSSML(markdown, options); 111 | 112 | const expected = dedent` 113 | 114 | We can switch from disappointed to really disappointed. 115 | 116 | `; 117 | 118 | expect(ssml).toBe(expected); 119 | }); 120 | 121 | test('converts to SSML - Google Assistant', () => { 122 | const options = { 123 | platform: 'google-assistant', 124 | }; 125 | const ssml = speech.toSSML(markdown, options); 126 | 127 | const expected = dedent` 128 | 129 | We can switch from disappointed to really disappointed. 130 | 131 | `; 132 | 133 | expect(ssml).toBe(expected); 134 | }); 135 | 136 | test('converts to SSML - Samsung Bixby', () => { 137 | const options = { 138 | platform: 'samsung-bixby', 139 | }; 140 | const ssml = speech.toSSML(markdown, options); 141 | 142 | const expected = dedent` 143 | 144 | We can switch from disappointed to really disappointed. 145 | 146 | `; 147 | 148 | expect(ssml).toBe(expected); 149 | }); 150 | 151 | test('converts to Plain Text', () => { 152 | const options = {}; 153 | const text = speech.toText(markdown, options); 154 | 155 | const expected = dedent` 156 | We can switch from disappointed to really disappointed. 157 | `; 158 | 159 | expect(text).toBe(expected); 160 | }); 161 | }); 162 | 163 | describe('disappointed-standard invalid intensity', () => { 164 | const speech = new SpeechMarkdown(); 165 | 166 | const markdown = dedent` 167 | We can switch (from disappointed)[disappointed] to (really disappointed)[disappointed:"pizza"]. 168 | `; 169 | 170 | test('converts to SSML - Amazon Alexa', () => { 171 | const options = { 172 | platform: 'amazon-alexa', 173 | }; 174 | const ssml = speech.toSSML(markdown, options); 175 | 176 | const expected = dedent` 177 | 178 | We can switch from disappointed to really disappointed. 179 | 180 | `; 181 | 182 | expect(ssml).toBe(expected); 183 | }); 184 | 185 | test('converts to SSML - Google Assistant', () => { 186 | const options = { 187 | platform: 'google-assistant', 188 | }; 189 | const ssml = speech.toSSML(markdown, options); 190 | 191 | const expected = dedent` 192 | 193 | We can switch from disappointed to really disappointed. 194 | 195 | `; 196 | 197 | expect(ssml).toBe(expected); 198 | }); 199 | 200 | test('converts to SSML - Samsung Bixby', () => { 201 | const options = { 202 | platform: 'samsung-bixby', 203 | }; 204 | const ssml = speech.toSSML(markdown, options); 205 | 206 | const expected = dedent` 207 | 208 | We can switch from disappointed to really disappointed. 209 | 210 | `; 211 | 212 | expect(ssml).toBe(expected); 213 | }); 214 | 215 | test('converts to Plain Text', () => { 216 | const options = {}; 217 | const text = speech.toText(markdown, options); 218 | 219 | const expected = dedent` 220 | We can switch from disappointed to really disappointed. 221 | `; 222 | 223 | expect(text).toBe(expected); 224 | }); 225 | }); 226 | -------------------------------------------------------------------------------- /tests/dj-section.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('dj-section normal to dj to normal', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Normal speech. 10 | 11 | #[dj] 12 | Switching to a music/media announcer. 13 | 14 | #[defaults] 15 | Now back to normal speech. 16 | `; 17 | 18 | test('converts to SSML - Amazon Alexa', () => { 19 | const options = { 20 | platform: 'amazon-alexa', 21 | }; 22 | const ssml = speech.toSSML(markdown, options); 23 | 24 | const expected = dedent` 25 | 26 | Normal speech. 27 | 28 | 29 | 30 | Switching to a music/media announcer. 31 | 32 | 33 | 34 | Now back to normal speech. 35 | 36 | `; 37 | 38 | expect(ssml).toBe(expected); 39 | }); 40 | 41 | test('converts to SSML - Amazon Polly', () => { 42 | const options = { 43 | platform: 'amazon-polly', 44 | }; 45 | const ssml = speech.toSSML(markdown, options); 46 | 47 | const expected = dedent` 48 | 49 | Normal speech. 50 | 51 | 52 | Switching to a music/media announcer. 53 | 54 | 55 | Now back to normal speech. 56 | 57 | `; 58 | 59 | expect(ssml).toBe(expected); 60 | }); 61 | 62 | test('converts to SSML - Amazon Polly (Neural)', () => { 63 | const options = { 64 | platform: 'amazon-polly-neural', 65 | }; 66 | const ssml = speech.toSSML(markdown, options); 67 | 68 | const expected = dedent` 69 | 70 | Normal speech. 71 | 72 | 73 | Switching to a music/media announcer. 74 | 75 | 76 | Now back to normal speech. 77 | 78 | `; 79 | 80 | expect(ssml).toBe(expected); 81 | }); 82 | 83 | test('converts to SSML - Google Assistant', () => { 84 | const options = { 85 | platform: 'google-assistant', 86 | preserveEmptyLines: false, 87 | }; 88 | const ssml = speech.toSSML(markdown, options); 89 | 90 | const expected = dedent` 91 | 92 | Normal speech. 93 | Switching to a music/media announcer. 94 | Now back to normal speech. 95 | 96 | `; 97 | 98 | expect(ssml).toBe(expected); 99 | }); 100 | 101 | test('converts to SSML - Samsung Bixby', () => { 102 | const options = { 103 | platform: 'samsung-bixby', 104 | preserveEmptyLines: false, 105 | }; 106 | const ssml = speech.toSSML(markdown, options); 107 | 108 | const expected = dedent` 109 | 110 | Normal speech. 111 | Switching to a music/media announcer. 112 | Now back to normal speech. 113 | 114 | `; 115 | 116 | expect(ssml).toBe(expected); 117 | }); 118 | 119 | test('converts to Plain Text', () => { 120 | const options = {}; 121 | const text = speech.toText(markdown, options); 122 | 123 | const expected = dedent` 124 | Normal speech. 125 | 126 | 127 | Switching to a music/media announcer. 128 | 129 | 130 | Now back to normal speech. 131 | `; 132 | 133 | expect(text).toBe(expected); 134 | }); 135 | }); 136 | 137 | describe('dj-section end speak tag at end', () => { 138 | const speech = new SpeechMarkdown(); 139 | 140 | const markdown = dedent` 141 | #[dj] 142 | Section 1 143 | `; 144 | 145 | test('converts to SSML - Amazon Alexa', () => { 146 | const options = { 147 | platform: 'amazon-alexa', 148 | }; 149 | const ssml = speech.toSSML(markdown, options); 150 | 151 | const expected = dedent` 152 | 153 | 154 | 155 | Section 1 156 | 157 | 158 | `; 159 | 160 | expect(ssml).toBe(expected); 161 | }); 162 | 163 | test('converts to SSML - Google Assistant', () => { 164 | const options = { 165 | platform: 'google-assistant', 166 | preserveEmptyLines: false, 167 | }; 168 | const ssml = speech.toSSML(markdown, options); 169 | 170 | const expected = dedent` 171 | 172 | Section 1 173 | 174 | `; 175 | 176 | expect(ssml).toBe(expected); 177 | }); 178 | 179 | test('converts to SSML - Samsung Bixby', () => { 180 | const options = { 181 | platform: 'samsung-bixby', 182 | preserveEmptyLines: false, 183 | }; 184 | const ssml = speech.toSSML(markdown, options); 185 | 186 | const expected = dedent` 187 | 188 | Section 1 189 | 190 | `; 191 | 192 | expect(ssml).toBe(expected); 193 | }); 194 | 195 | test('converts to Plain Text', () => { 196 | const options = {}; 197 | const text = speech.toText(markdown, options); 198 | 199 | const expected = dedent` 200 | Section 1 201 | `; 202 | expect(text).toBe(expected); 203 | }); 204 | }); 205 | 206 | describe('dj-section section on same line', () => { 207 | const speech = new SpeechMarkdown(); 208 | 209 | const markdown = dedent` 210 | #[dj] Hey there, nice to meet you 211 | `; 212 | 213 | test('converts to SSML - Amazon Alexa', () => { 214 | const options = { 215 | platform: 'amazon-alexa', 216 | }; 217 | const ssml = speech.toSSML(markdown, options); 218 | 219 | const expected = dedent` 220 | 221 | 222 | Hey there, nice to meet you 223 | 224 | 225 | `; 226 | 227 | expect(ssml).toBe(expected); 228 | }); 229 | 230 | test('converts to SSML - Google Assistant', () => { 231 | const options = { 232 | platform: 'google-assistant', 233 | }; 234 | const ssml = speech.toSSML(markdown, options); 235 | 236 | const expected = dedent` 237 | 238 | Hey there, nice to meet you 239 | 240 | `; 241 | 242 | expect(ssml).toBe(expected); 243 | }); 244 | 245 | test('converts to SSML - Samsung Bixby', () => { 246 | const options = { 247 | platform: 'samsung-bixby', 248 | }; 249 | const ssml = speech.toSSML(markdown, options); 250 | 251 | const expected = dedent` 252 | 253 | Hey there, nice to meet you 254 | 255 | `; 256 | 257 | expect(ssml).toBe(expected); 258 | }); 259 | 260 | test('converts to Plain Text', () => { 261 | const options = {}; 262 | const text = speech.toText(markdown, options); 263 | 264 | const expected = 'Hey there, nice to meet you'; 265 | 266 | expect(text).toBe(expected); 267 | }); 268 | }); 269 | -------------------------------------------------------------------------------- /tests/drc-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('drc-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Some audio is difficult to hear in a moving vehicle, but (this audio is less difficult to hear in a moving vehicle.)[drc] 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Some audio is difficult to hear in a moving vehicle, but this audio is less difficult to hear in a moving vehicle. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/emphasis-short-edge-cases.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 3 | 4 | describe('emphasis-short-edge-cases', () => { 5 | const speech = new SpeechMarkdown(); 6 | 7 | const equalCases = [ 8 | 'a+moderate+level', 9 | 'mother-in-law', 10 | '2020-10-10', 11 | '01-01-2021', 12 | ]; 13 | 14 | test('converts to Plain Text', () => { 15 | for (let input of equalCases) { 16 | const text = speech.toText(input, {}); 17 | expect(text).toBe(input); 18 | } 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/escape-xml.spec.ts: -------------------------------------------------------------------------------- 1 | import dedent from 'ts-dedent'; 2 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 3 | 4 | const speech = new SpeechMarkdown(); 5 | 6 | const markdown = dedent` 7 | Hallo Wie geht's? & Was machst Du hier? 8 | `; 9 | 10 | describe('escape-xml', () => { 11 | ['amazon-alexa', 'microsoft-azure'].forEach((platform) => { 12 | describe(`Platform: ${platform}`, () => { 13 | test('No special symbol', () => { 14 | const options = { 15 | platform, 16 | escapeXmlSymbols: true, 17 | }; 18 | const text = `Procter and Gamble`; 19 | const ssml = speech.toSSML(text, options); 20 | 21 | const exp = dedent` 22 | 23 | Procter and Gamble 24 | `; 25 | 26 | expect(ssml).toEqual(exp); 27 | }); 28 | 29 | test('Symbol &', () => { 30 | const options = { 31 | platform, 32 | escapeXmlSymbols: true, 33 | }; 34 | const text = `Procter & Gamble`; 35 | const ssml = speech.toSSML(text, options); 36 | 37 | const exp = dedent` 38 | 39 | Procter & Gamble 40 | `; 41 | 42 | expect(ssml).toEqual(exp); 43 | }); 44 | 45 | test('Already escaped symbol &', () => { 46 | const options = { 47 | platform, 48 | escapeXmlSymbols: true, 49 | }; 50 | const text = `Procter & Gamble`; 51 | const ssml = speech.toSSML(text, options); 52 | 53 | const exp = dedent` 54 | 55 | Procter & Gamble 56 | `; 57 | 58 | expect(ssml).toEqual(exp); 59 | }); 60 | 61 | test("Symbol '", () => { 62 | const options = { 63 | platform, 64 | escapeXmlSymbols: true, 65 | }; 66 | const text = `Levi's`; 67 | const ssml = speech.toSSML(text, options); 68 | 69 | const exp = dedent` 70 | 71 | Levi's 72 | `; 73 | 74 | expect(ssml).toEqual(exp); 75 | }); 76 | 77 | test('German with both symbols', () => { 78 | const options = { 79 | platform, 80 | escapeXmlSymbols: true, 81 | }; 82 | const ssml = speech.toSSML(markdown, options); 83 | 84 | const expected = dedent` 85 | 86 | Hallo Wie geht's? & Was machst Du hier? 87 | 88 | `; 89 | 90 | expect(ssml).toBe(expected); 91 | }); 92 | 93 | test('No escaping', () => { 94 | const options = { 95 | platform, 96 | escapeXmlSymbols: false, 97 | }; 98 | const ssml = speech.toSSML(markdown, options); 99 | 100 | const expected = dedent` 101 | 102 | ${markdown} 103 | 104 | `; 105 | 106 | expect(ssml).toBe(expected); 107 | }); 108 | 109 | test('Google with no support of escapeXmlSymbols', () => { 110 | const options = { 111 | platform: 'google-assistant', 112 | escapeXmlSymbols: true, 113 | }; 114 | const ssml = speech.toSSML(markdown, options); 115 | 116 | const expected = dedent` 117 | 118 | ${markdown} 119 | 120 | `; 121 | 122 | expect(ssml).toBe(expected); 123 | }); 124 | 125 | describe('non-regression with SpeechMarkdown elements', () => { 126 | test('break short syntax', () => { 127 | const options = { 128 | platform, 129 | escapeXmlSymbols: true, 130 | }; 131 | const text = `Procter [250ms] and Gamble`; 132 | const ssml = speech.toSSML(text, options); 133 | 134 | const exp = dedent` 135 | 136 | Procter and Gamble 137 | `; 138 | 139 | expect(ssml).toEqual(exp); 140 | }); 141 | 142 | test('break long syntax', () => { 143 | const options = { 144 | platform, 145 | escapeXmlSymbols: true, 146 | }; 147 | const text = `Procter [break:"500ms"] and [break:"weak"] Gamble`; 148 | const ssml = speech.toSSML(text, options); 149 | 150 | const exp = dedent` 151 | 152 | Procter and Gamble 153 | `; 154 | 155 | expect(ssml).toEqual(exp); 156 | }); 157 | 158 | if (platform !== 'microsoft-azure') { 159 | test('lang', () => { 160 | const options = { 161 | platform, 162 | escapeXmlSymbols: true, 163 | }; 164 | const text = `In Paris, they pronounce it (Paris)[lang:"fr-FR"]`; 165 | const ssml = speech.toSSML(text, options); 166 | 167 | const exp = dedent` 168 | 169 | In Paris, they pronounce it Paris 170 | `; 171 | 172 | expect(ssml).toEqual(exp); 173 | }); 174 | } 175 | }); 176 | }); 177 | }); 178 | }); 179 | -------------------------------------------------------------------------------- /tests/excited-section.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('excited-section normal to excited intensities to normal', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Normal speech. 10 | 11 | #[excited] 12 | I am excited - medium. 13 | 14 | #[excited:"medium"] 15 | I am excited - medium. 16 | 17 | #[excited:"low"] 18 | I am excited - low. 19 | 20 | #[excited:"high"] 21 | I am excited - high. 22 | 23 | #[defaults] 24 | Now back to normal speech. 25 | `; 26 | 27 | test('converts to SSML - Amazon Alexa', () => { 28 | const options = { 29 | platform: 'amazon-alexa', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Normal speech. 36 | 37 | 38 | 39 | I am excited - medium. 40 | 41 | 42 | 43 | 44 | I am excited - medium. 45 | 46 | 47 | 48 | 49 | I am excited - low. 50 | 51 | 52 | 53 | 54 | I am excited - high. 55 | 56 | 57 | 58 | Now back to normal speech. 59 | 60 | `; 61 | 62 | expect(ssml).toBe(expected); 63 | }); 64 | 65 | test('converts to SSML - Amazon Polly', () => { 66 | const options = { 67 | platform: 'amazon-polly', 68 | }; 69 | const ssml = speech.toSSML(markdown, options); 70 | 71 | const expected = dedent` 72 | 73 | Normal speech. 74 | 75 | 76 | I am excited - medium. 77 | 78 | 79 | I am excited - medium. 80 | 81 | 82 | I am excited - low. 83 | 84 | 85 | I am excited - high. 86 | 87 | 88 | Now back to normal speech. 89 | 90 | `; 91 | 92 | expect(ssml).toBe(expected); 93 | }); 94 | 95 | test('converts to SSML - Amazon Polly (Neural)', () => { 96 | const options = { 97 | platform: 'amazon-polly-neural', 98 | }; 99 | const ssml = speech.toSSML(markdown, options); 100 | 101 | const expected = dedent` 102 | 103 | Normal speech. 104 | 105 | 106 | I am excited - medium. 107 | 108 | 109 | I am excited - medium. 110 | 111 | 112 | I am excited - low. 113 | 114 | 115 | I am excited - high. 116 | 117 | 118 | Now back to normal speech. 119 | 120 | `; 121 | 122 | expect(ssml).toBe(expected); 123 | }); 124 | 125 | test('converts to SSML - Google Assistant', () => { 126 | const options = { 127 | platform: 'google-assistant', 128 | preserveEmptyLines: false, 129 | }; 130 | const ssml = speech.toSSML(markdown, options); 131 | 132 | const expected = dedent` 133 | 134 | Normal speech. 135 | I am excited - medium. 136 | I am excited - medium. 137 | I am excited - low. 138 | I am excited - high. 139 | Now back to normal speech. 140 | 141 | `; 142 | 143 | expect(ssml).toBe(expected); 144 | }); 145 | 146 | test('converts to SSML - Samsung Bixby', () => { 147 | const options = { 148 | platform: 'samsung-bixby', 149 | preserveEmptyLines: false, 150 | }; 151 | const ssml = speech.toSSML(markdown, options); 152 | 153 | const expected = dedent` 154 | 155 | Normal speech. 156 | I am excited - medium. 157 | I am excited - medium. 158 | I am excited - low. 159 | I am excited - high. 160 | Now back to normal speech. 161 | 162 | `; 163 | 164 | expect(ssml).toBe(expected); 165 | }); 166 | 167 | test('converts to Plain Text', () => { 168 | const options = {}; 169 | const text = speech.toText(markdown, options); 170 | 171 | const expected = dedent` 172 | Normal speech. 173 | 174 | 175 | I am excited - medium. 176 | 177 | 178 | I am excited - medium. 179 | 180 | 181 | I am excited - low. 182 | 183 | 184 | I am excited - high. 185 | 186 | 187 | Now back to normal speech. 188 | `; 189 | 190 | expect(text).toBe(expected); 191 | }); 192 | }); 193 | 194 | describe('excited-section end speak tag at end', () => { 195 | const speech = new SpeechMarkdown(); 196 | 197 | const markdown = dedent` 198 | #[excited] 199 | Section 1 200 | `; 201 | 202 | test('converts to SSML - Amazon Alexa', () => { 203 | const options = { 204 | platform: 'amazon-alexa', 205 | }; 206 | const ssml = speech.toSSML(markdown, options); 207 | 208 | const expected = dedent` 209 | 210 | 211 | 212 | Section 1 213 | 214 | 215 | `; 216 | 217 | expect(ssml).toBe(expected); 218 | }); 219 | 220 | test('converts to SSML - Google Assistant', () => { 221 | const options = { 222 | platform: 'google-assistant', 223 | preserveEmptyLines: false, 224 | }; 225 | const ssml = speech.toSSML(markdown, options); 226 | 227 | const expected = dedent` 228 | 229 | Section 1 230 | 231 | `; 232 | 233 | expect(ssml).toBe(expected); 234 | }); 235 | 236 | test('converts to SSML - Samsung Bixby', () => { 237 | const options = { 238 | platform: 'samsung-bixby', 239 | preserveEmptyLines: false, 240 | }; 241 | const ssml = speech.toSSML(markdown, options); 242 | 243 | const expected = dedent` 244 | 245 | Section 1 246 | 247 | `; 248 | 249 | expect(ssml).toBe(expected); 250 | }); 251 | 252 | test('converts to Plain Text', () => { 253 | const options = {}; 254 | const text = speech.toText(markdown, options); 255 | 256 | const expected = dedent` 257 | Section 1 258 | `; 259 | expect(text).toBe(expected); 260 | }); 261 | }); 262 | 263 | describe('excited-section section on same line', () => { 264 | const speech = new SpeechMarkdown(); 265 | 266 | const markdown = dedent` 267 | #[excited] Hey there, nice to meet you 268 | `; 269 | 270 | test('converts to SSML - Amazon Alexa', () => { 271 | const options = { 272 | platform: 'amazon-alexa', 273 | }; 274 | const ssml = speech.toSSML(markdown, options); 275 | 276 | const expected = dedent` 277 | 278 | 279 | Hey there, nice to meet you 280 | 281 | 282 | `; 283 | 284 | expect(ssml).toBe(expected); 285 | }); 286 | 287 | test('converts to SSML - Google Assistant', () => { 288 | const options = { 289 | platform: 'google-assistant', 290 | }; 291 | const ssml = speech.toSSML(markdown, options); 292 | 293 | const expected = dedent` 294 | 295 | Hey there, nice to meet you 296 | 297 | `; 298 | 299 | expect(ssml).toBe(expected); 300 | }); 301 | 302 | test('converts to SSML - Samsung Bixby', () => { 303 | const options = { 304 | platform: 'samsung-bixby', 305 | }; 306 | const ssml = speech.toSSML(markdown, options); 307 | 308 | const expected = dedent` 309 | 310 | Hey there, nice to meet you 311 | 312 | `; 313 | 314 | expect(ssml).toBe(expected); 315 | }); 316 | 317 | test('converts to Plain Text', () => { 318 | const options = {}; 319 | const text = speech.toText(markdown, options); 320 | 321 | const expected = 'Hey there, nice to meet you'; 322 | 323 | expect(text).toBe(expected); 324 | }); 325 | }); 326 | -------------------------------------------------------------------------------- /tests/excited-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('excited-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | We can switch (from excited)[excited] to (really excited)[excited:"high"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | We can switch from excited to really excited. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | We can switch from excited to really excited. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | We can switch from excited to really excited. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | We can switch from excited to really excited. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | We can switch from excited to really excited. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to Plain Text', () => { 88 | const options = {}; 89 | const text = speech.toText(markdown, options); 90 | 91 | const expected = dedent` 92 | We can switch from excited to really excited. 93 | `; 94 | 95 | expect(text).toBe(expected); 96 | }); 97 | }); 98 | 99 | describe('excited-standard non-lowercase intensity', () => { 100 | const speech = new SpeechMarkdown(); 101 | 102 | const markdown = dedent` 103 | We can switch (from excited)[excited] to (really excited)[excited:"HigH"]. 104 | `; 105 | 106 | test('converts to SSML - Amazon Alexa', () => { 107 | const options = { 108 | platform: 'amazon-alexa', 109 | }; 110 | const ssml = speech.toSSML(markdown, options); 111 | 112 | const expected = dedent` 113 | 114 | We can switch from excited to really excited. 115 | 116 | `; 117 | 118 | expect(ssml).toBe(expected); 119 | }); 120 | 121 | test('converts to SSML - Google Assistant', () => { 122 | const options = { 123 | platform: 'google-assistant', 124 | }; 125 | const ssml = speech.toSSML(markdown, options); 126 | 127 | const expected = dedent` 128 | 129 | We can switch from excited to really excited. 130 | 131 | `; 132 | 133 | expect(ssml).toBe(expected); 134 | }); 135 | 136 | test('converts to SSML - Samsung Bixby', () => { 137 | const options = { 138 | platform: 'samsung-bixby', 139 | }; 140 | const ssml = speech.toSSML(markdown, options); 141 | 142 | const expected = dedent` 143 | 144 | We can switch from excited to really excited. 145 | 146 | `; 147 | 148 | expect(ssml).toBe(expected); 149 | }); 150 | 151 | test('converts to Plain Text', () => { 152 | const options = {}; 153 | const text = speech.toText(markdown, options); 154 | 155 | const expected = dedent` 156 | We can switch from excited to really excited. 157 | `; 158 | 159 | expect(text).toBe(expected); 160 | }); 161 | }); 162 | 163 | describe('excited-standard invalid intensity', () => { 164 | const speech = new SpeechMarkdown(); 165 | 166 | const markdown = dedent` 167 | We can switch (from excited)[excited] to (really excited)[excited:"pizza"]. 168 | `; 169 | 170 | test('converts to SSML - Amazon Alexa', () => { 171 | const options = { 172 | platform: 'amazon-alexa', 173 | }; 174 | const ssml = speech.toSSML(markdown, options); 175 | 176 | const expected = dedent` 177 | 178 | We can switch from excited to really excited. 179 | 180 | `; 181 | 182 | expect(ssml).toBe(expected); 183 | }); 184 | 185 | test('converts to SSML - Google Assistant', () => { 186 | const options = { 187 | platform: 'google-assistant', 188 | }; 189 | const ssml = speech.toSSML(markdown, options); 190 | 191 | const expected = dedent` 192 | 193 | We can switch from excited to really excited. 194 | 195 | `; 196 | 197 | expect(ssml).toBe(expected); 198 | }); 199 | 200 | test('converts to SSML - Samsung Bixby', () => { 201 | const options = { 202 | platform: 'samsung-bixby', 203 | }; 204 | const ssml = speech.toSSML(markdown, options); 205 | 206 | const expected = dedent` 207 | 208 | We can switch from excited to really excited. 209 | 210 | `; 211 | 212 | expect(ssml).toBe(expected); 213 | }); 214 | 215 | test('converts to Plain Text', () => { 216 | const options = {}; 217 | const text = speech.toText(markdown, options); 218 | 219 | const expected = dedent` 220 | We can switch from excited to really excited. 221 | `; 222 | 223 | expect(text).toBe(expected); 224 | }); 225 | }); 226 | -------------------------------------------------------------------------------- /tests/expletive-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('expletive-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | You said (word)[bleep] and (word)[expletive] at school. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | You said word and word at school. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | You said word and word at school. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | You said word and word at school. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | You said word and word at school. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | You said word and word at school. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to Plain Text', () => { 88 | const options = {}; 89 | const text = speech.toText(markdown, options); 90 | 91 | const expected = dedent` 92 | You said word and word at school. 93 | `; 94 | 95 | expect(text).toBe(expected); 96 | }); 97 | }); 98 | -------------------------------------------------------------------------------- /tests/fraction-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('fraction-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Add (2/3)[fraction] cup of milk. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Add 2/3 cup of milk. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Add 2/3 cup of milk. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Add 2/3 cup of milk. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Add 2/3 cup of milk. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Add 2/3 cup of milk. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Add 2/3 cup of milk. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Add 2/3 cup of milk. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | 114 | describe('fraction-standard includes a plus sign', () => { 115 | const speech = new SpeechMarkdown(); 116 | 117 | const markdown = dedent` 118 | Add (1+1/2)[fraction] cups of flour. 119 | `; 120 | 121 | test('converts to SSML - Amazon Alexa', () => { 122 | const options = { 123 | platform: 'amazon-alexa', 124 | }; 125 | const ssml = speech.toSSML(markdown, options); 126 | 127 | const expected = dedent` 128 | 129 | Add 1+1/2 cups of flour. 130 | 131 | `; 132 | 133 | expect(ssml).toBe(expected); 134 | }); 135 | 136 | test('converts to SSML - Google Assistant', () => { 137 | const options = { 138 | platform: 'google-assistant', 139 | }; 140 | const ssml = speech.toSSML(markdown, options); 141 | 142 | const expected = dedent` 143 | 144 | Add 1+1/2 cups of flour. 145 | 146 | `; 147 | 148 | expect(ssml).toBe(expected); 149 | }); 150 | 151 | test('converts to SSML - Samsung Bixby', () => { 152 | const options = { 153 | platform: 'samsung-bixby', 154 | }; 155 | const ssml = speech.toSSML(markdown, options); 156 | 157 | const expected = dedent` 158 | 159 | Add 1+1/2 cups of flour. 160 | 161 | `; 162 | 163 | expect(ssml).toBe(expected); 164 | }); 165 | 166 | test('converts to SSML - Microsoft Azure', () => { 167 | const options = { 168 | platform: 'microsoft-azure', 169 | }; 170 | const ssml = speech.toSSML(markdown, options); 171 | 172 | const expected = dedent` 173 | 174 | Add 1+1/2 cups of flour. 175 | 176 | `; 177 | 178 | expect(ssml).toBe(expected); 179 | }); 180 | 181 | test('converts to Plain Text', () => { 182 | const options = {}; 183 | const text = speech.toText(markdown, options); 184 | 185 | const expected = dedent` 186 | Add 1+1/2 cups of flour. 187 | `; 188 | 189 | expect(text).toBe(expected); 190 | }); 191 | }); 192 | -------------------------------------------------------------------------------- /tests/interjection-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('interjection-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | (Wow)[interjection], I didn't see that coming. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Wow, I didn't see that coming. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Wow, I didn't see that coming. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Wow, I didn't see that coming. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Wow, I didn't see that coming. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Wow, I didn't see that coming. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Wow, I didn't see that coming. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Wow, I didn't see that coming. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/ipa-standard-alphabet-uk.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('ipa-standard-alphabet-uk', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | I say, (ipa)[ipa:"ˈˌb.d.f.g.h.j.k.l.m.n.p.s.t.v.w.z.i.u.æ.ð.ʃ.θ.ʒ.ə.aɪ.aʊ.ɑ.eɪ.ɝ.ɛ.ɪ.əʊ.ɔ.ɔɪ.ʊ.ʌ.ɒ.ɛə.ɪə.ʊə.ŋ.ɹ.d͡ʒ.t͡ʃ"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I say, ipa. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | I say, ipa. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | I say, ipa. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | I say, ipa. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | I say, ipa. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | I say, ipa. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | I say, ipa. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/ipa-standard-alphabet-us.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('ipa-standard-alphabet-us', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | I say, (ipa)[ipa:"ˈˌb.d.f.g.h.j.k.l.m.n.p.s.t.v.w.z.i.u.æ.ð.ʃ.θ.ʒ.ə.ɚ.aɪ.aʊ.ɑ.eɪ.ɝ.ɛ.ɪ.oʊ.ɔ.ɔɪ.ʊ.ʌ.ŋ.ɹ.d͡ʒ.t͡ʃ"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I say, ipa. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | I say, ipa. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | I say, ipa. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | I say, ipa. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | I say, ipa. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | I say, ipa. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | I say, ipa. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/ipa-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('ipa-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | I say, (pecan)[ipa:"'pi.kæn"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I say, pecan. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | I say, pecan. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | I say, pecan. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | I say, pecan. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | I say, pecan. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | I say, pecan. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | I say, pecan. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/lang-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('lang-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | In Paris, they pronounce it (Paris)[lang:"fr-FR"]. 10 | In Paris, they pronounce it (Paris)[lang:'fr-FR']. 11 | `; 12 | 13 | test('converts to SSML - Amazon Alexa', () => { 14 | const options = { 15 | platform: 'amazon-alexa', 16 | }; 17 | const ssml = speech.toSSML(markdown, options); 18 | 19 | const expected = dedent` 20 | 21 | In Paris, they pronounce it Paris. 22 | In Paris, they pronounce it Paris. 23 | 24 | `; 25 | 26 | expect(ssml).toBe(expected); 27 | }); 28 | 29 | test('converts to SSML - Amazon Polly', () => { 30 | const options = { 31 | platform: 'amazon-polly', 32 | }; 33 | const ssml = speech.toSSML(markdown, options); 34 | 35 | const expected = dedent` 36 | 37 | In Paris, they pronounce it Paris. 38 | In Paris, they pronounce it Paris. 39 | 40 | `; 41 | 42 | expect(ssml).toBe(expected); 43 | }); 44 | 45 | test('converts to SSML - Amazon Polly (Neural)', () => { 46 | const options = { 47 | platform: 'amazon-polly-neural', 48 | }; 49 | const ssml = speech.toSSML(markdown, options); 50 | 51 | const expected = dedent` 52 | 53 | In Paris, they pronounce it Paris. 54 | In Paris, they pronounce it Paris. 55 | 56 | `; 57 | 58 | expect(ssml).toBe(expected); 59 | }); 60 | 61 | test('converts to SSML - Google Assistant', () => { 62 | const options = { 63 | platform: 'google-assistant', 64 | }; 65 | const ssml = speech.toSSML(markdown, options); 66 | 67 | const expected = dedent` 68 | 69 | In Paris, they pronounce it Paris. 70 | In Paris, they pronounce it Paris. 71 | 72 | `; 73 | 74 | expect(ssml).toBe(expected); 75 | }); 76 | 77 | test('converts to SSML - Samsung Bixby', () => { 78 | const options = { 79 | platform: 'samsung-bixby', 80 | }; 81 | const ssml = speech.toSSML(markdown, options); 82 | 83 | const expected = dedent` 84 | 85 | In Paris, they pronounce it Paris. 86 | In Paris, they pronounce it Paris. 87 | 88 | `; 89 | 90 | expect(ssml).toBe(expected); 91 | }); 92 | 93 | test('converts to SSML - Microsoft Azure', () => { 94 | const options = { 95 | platform: 'microsoft-azure', 96 | }; 97 | const ssml = speech.toSSML(markdown, options); 98 | 99 | const expected = dedent` 100 | 101 | In Paris, they pronounce it Paris. 102 | In Paris, they pronounce it Paris. 103 | 104 | `; 105 | 106 | expect(ssml).toBe(expected); 107 | }); 108 | 109 | test('converts to Plain Text', () => { 110 | const options = {}; 111 | const text = speech.toText(markdown, options); 112 | 113 | const expected = dedent` 114 | In Paris, they pronounce it Paris. 115 | In Paris, they pronounce it Paris. 116 | `; 117 | 118 | expect(text).toBe(expected); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /tests/mark-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('mark-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Sample [mark:"here"] speech [mark:"to-there"] markdown 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Sample speech markdown 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Sample speech markdown 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Sample speech markdown 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Sample speech markdown 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Sample speech markdown 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Sample speech markdown 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Sample speech markdown 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/multiple-modifiers-same-text.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('multiple-modifiers-same-text', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Your balance is: (12345)[number;emphasis:"strong";whisper;pitch:"high"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Your balance is: 12345. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Your balance is: 12345. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Your balance is: 12345. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Your balance is: 12345. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Your balance is: 12345. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Your balance is: 12345. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Your balance is: 12345. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/newscaster-section.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('newscaster-section normal to dj to normal', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Normal speech. 10 | 11 | #[newscaster] 12 | Switching to a newscaster. 13 | 14 | #[defaults] 15 | Now back to normal speech. 16 | `; 17 | 18 | test('converts to SSML - Amazon Alexa', () => { 19 | const options = { 20 | platform: 'amazon-alexa', 21 | }; 22 | const ssml = speech.toSSML(markdown, options); 23 | 24 | const expected = dedent` 25 | 26 | Normal speech. 27 | 28 | 29 | 30 | Switching to a newscaster. 31 | 32 | 33 | 34 | Now back to normal speech. 35 | 36 | `; 37 | 38 | expect(ssml).toBe(expected); 39 | }); 40 | 41 | test('converts to SSML - Amazon Polly', () => { 42 | const options = { 43 | platform: 'amazon-polly', 44 | }; 45 | const ssml = speech.toSSML(markdown, options); 46 | 47 | const expected = dedent` 48 | 49 | Normal speech. 50 | 51 | 52 | Switching to a newscaster. 53 | 54 | 55 | Now back to normal speech. 56 | 57 | `; 58 | 59 | expect(ssml).toBe(expected); 60 | }); 61 | 62 | test('converts to SSML - Amazon Polly (Neural)', () => { 63 | const options = { 64 | platform: 'amazon-polly-neural', 65 | }; 66 | const ssml = speech.toSSML(markdown, options); 67 | 68 | const expected = dedent` 69 | 70 | Normal speech. 71 | 72 | 73 | 74 | Switching to a newscaster. 75 | 76 | 77 | 78 | Now back to normal speech. 79 | 80 | `; 81 | 82 | expect(ssml).toBe(expected); 83 | }); 84 | 85 | test('converts to SSML - Google Assistant', () => { 86 | const options = { 87 | platform: 'google-assistant', 88 | preserveEmptyLines: false, 89 | }; 90 | const ssml = speech.toSSML(markdown, options); 91 | 92 | const expected = dedent` 93 | 94 | Normal speech. 95 | Switching to a newscaster. 96 | Now back to normal speech. 97 | 98 | `; 99 | 100 | expect(ssml).toBe(expected); 101 | }); 102 | 103 | test('converts to SSML - Samsung Bixby', () => { 104 | const options = { 105 | platform: 'samsung-bixby', 106 | preserveEmptyLines: false, 107 | }; 108 | const ssml = speech.toSSML(markdown, options); 109 | 110 | const expected = dedent` 111 | 112 | Normal speech. 113 | Switching to a newscaster. 114 | Now back to normal speech. 115 | 116 | `; 117 | 118 | expect(ssml).toBe(expected); 119 | }); 120 | 121 | test('converts to SSML - Microsoft Azure', () => { 122 | const options = { 123 | platform: 'microsoft-azure', 124 | }; 125 | const ssml = speech.toSSML(markdown, options); 126 | 127 | const expected = dedent` 128 | 129 | Normal speech. 130 | 131 | 132 | 133 | Switching to a newscaster. 134 | 135 | 136 | 137 | Now back to normal speech. 138 | 139 | `; 140 | 141 | expect(ssml).toBe(expected); 142 | }); 143 | 144 | test('converts to Plain Text', () => { 145 | const options = {}; 146 | const text = speech.toText(markdown, options); 147 | 148 | const expected = dedent` 149 | Normal speech. 150 | 151 | 152 | Switching to a newscaster. 153 | 154 | 155 | Now back to normal speech. 156 | `; 157 | 158 | expect(text).toBe(expected); 159 | }); 160 | }); 161 | 162 | describe('newscaster-section end speak tag at end', () => { 163 | const speech = new SpeechMarkdown(); 164 | 165 | const markdown = dedent` 166 | #[newscaster] 167 | Section 1 168 | `; 169 | 170 | test('converts to SSML - Amazon Alexa', () => { 171 | const options = { 172 | platform: 'amazon-alexa', 173 | }; 174 | const ssml = speech.toSSML(markdown, options); 175 | 176 | const expected = dedent` 177 | 178 | 179 | 180 | Section 1 181 | 182 | 183 | `; 184 | 185 | expect(ssml).toBe(expected); 186 | }); 187 | 188 | test('converts to SSML - Google Assistant', () => { 189 | const options = { 190 | platform: 'google-assistant', 191 | preserveEmptyLines: false, 192 | }; 193 | const ssml = speech.toSSML(markdown, options); 194 | 195 | const expected = dedent` 196 | 197 | Section 1 198 | 199 | `; 200 | 201 | expect(ssml).toBe(expected); 202 | }); 203 | 204 | test('converts to SSML - Samsung Bixby', () => { 205 | const options = { 206 | platform: 'samsung-bixby', 207 | preserveEmptyLines: false, 208 | }; 209 | const ssml = speech.toSSML(markdown, options); 210 | 211 | const expected = dedent` 212 | 213 | Section 1 214 | 215 | `; 216 | 217 | expect(ssml).toBe(expected); 218 | }); 219 | 220 | test('converts to SSML - Microsoft Azure', () => { 221 | const options = { 222 | platform: 'microsoft-azure', 223 | }; 224 | const ssml = speech.toSSML(markdown, options); 225 | 226 | const expected = dedent` 227 | 228 | 229 | 230 | Section 1 231 | 232 | 233 | `; 234 | 235 | expect(ssml).toBe(expected); 236 | }); 237 | 238 | test('converts to Plain Text', () => { 239 | const options = {}; 240 | const text = speech.toText(markdown, options); 241 | 242 | const expected = dedent` 243 | Section 1 244 | `; 245 | expect(text).toBe(expected); 246 | }); 247 | }); 248 | 249 | describe('newscaster-section section on same line', () => { 250 | const speech = new SpeechMarkdown(); 251 | 252 | const markdown = dedent` 253 | #[newscaster] Hey there, nice to meet you 254 | `; 255 | 256 | test('converts to SSML - Amazon Alexa', () => { 257 | const options = { 258 | platform: 'amazon-alexa', 259 | }; 260 | const ssml = speech.toSSML(markdown, options); 261 | 262 | const expected = dedent` 263 | 264 | 265 | Hey there, nice to meet you 266 | 267 | 268 | `; 269 | 270 | expect(ssml).toBe(expected); 271 | }); 272 | 273 | test('converts to SSML - Google Assistant', () => { 274 | const options = { 275 | platform: 'google-assistant', 276 | }; 277 | const ssml = speech.toSSML(markdown, options); 278 | 279 | const expected = dedent` 280 | 281 | Hey there, nice to meet you 282 | 283 | `; 284 | 285 | expect(ssml).toBe(expected); 286 | }); 287 | 288 | test('converts to SSML - Samsung Bixby', () => { 289 | const options = { 290 | platform: 'samsung-bixby', 291 | }; 292 | const ssml = speech.toSSML(markdown, options); 293 | 294 | const expected = dedent` 295 | 296 | Hey there, nice to meet you 297 | 298 | `; 299 | 300 | expect(ssml).toBe(expected); 301 | }); 302 | 303 | test('converts to SSML - Microsoft Azure', () => { 304 | const options = { 305 | platform: 'microsoft-azure', 306 | }; 307 | const ssml = speech.toSSML(markdown, options); 308 | 309 | const expected = dedent` 310 | 311 | 312 | Hey there, nice to meet you 313 | 314 | 315 | `; 316 | 317 | expect(ssml).toBe(expected); 318 | }); 319 | 320 | test('converts to Plain Text', () => { 321 | const options = {}; 322 | const text = speech.toText(markdown, options); 323 | 324 | const expected = 'Hey there, nice to meet you'; 325 | 326 | expect(text).toBe(expected); 327 | }); 328 | }); 329 | -------------------------------------------------------------------------------- /tests/no-markdown.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('no-markdown', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Text line 1 10 | 11 | Text line 2 12 | `; 13 | 14 | test('converts to SSML - Amazon Alexa', () => { 15 | const options = { 16 | platform: 'amazon-alexa', 17 | }; 18 | const ssml = speech.toSSML(markdown, options); 19 | 20 | const expected = dedent` 21 | 22 | Text line 1 23 | 24 | Text line 2 25 | 26 | `; 27 | 28 | expect(ssml).toBe(expected); 29 | }); 30 | 31 | test('converts to SSML - Amazon Polly', () => { 32 | const options = { 33 | platform: 'amazon-polly', 34 | }; 35 | const ssml = speech.toSSML(markdown, options); 36 | 37 | const expected = dedent` 38 | 39 | Text line 1 40 | 41 | Text line 2 42 | 43 | `; 44 | 45 | expect(ssml).toBe(expected); 46 | }); 47 | 48 | test('converts to SSML - Amazon Polly (Neural)', () => { 49 | const options = { 50 | platform: 'amazon-polly-neural', 51 | }; 52 | const ssml = speech.toSSML(markdown, options); 53 | 54 | const expected = dedent` 55 | 56 | Text line 1 57 | 58 | Text line 2 59 | 60 | `; 61 | 62 | expect(ssml).toBe(expected); 63 | }); 64 | 65 | test('converts to SSML - Google Assistant', () => { 66 | const options = { 67 | platform: 'google-assistant', 68 | }; 69 | const ssml = speech.toSSML(markdown, options); 70 | 71 | const expected = dedent` 72 | 73 | Text line 1 74 | 75 | Text line 2 76 | 77 | `; 78 | 79 | expect(ssml).toBe(expected); 80 | }); 81 | 82 | test('converts to SSML - Samsung Bixby', () => { 83 | const options = { 84 | platform: 'samsung-bixby', 85 | }; 86 | const ssml = speech.toSSML(markdown, options); 87 | 88 | const expected = dedent` 89 | 90 | Text line 1 91 | 92 | Text line 2 93 | 94 | `; 95 | 96 | expect(ssml).toBe(expected); 97 | }); 98 | 99 | test('converts to SSML - Microsoft Azure', () => { 100 | const options = { 101 | platform: 'microsoft-azure', 102 | }; 103 | const ssml = speech.toSSML(markdown, options); 104 | 105 | const expected = dedent` 106 | 107 | Text line 1 108 | 109 | Text line 2 110 | 111 | `; 112 | 113 | expect(ssml).toBe(expected); 114 | }); 115 | 116 | test('converts to Plain Text', () => { 117 | const options = {}; 118 | const text = speech.toText(markdown, options); 119 | 120 | const expected = dedent` 121 | Text line 1 122 | 123 | Text line 2 124 | `; 125 | 126 | expect(text).toBe(expected); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /tests/no-modifiers.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('no-modifiers', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Some (text)[] 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Some text 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Some text 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Some text 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Some text 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Some text 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Some text 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Some text 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/number-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('number-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Your balance is: (12345)[number]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Your balance is: 12345. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Your balance is: 12345. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Your balance is: 12345. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Your balance is: 12345. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Your balance is: 12345. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Your balance is: 12345. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | Your balance is: 12345. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/options-includeFormatterComment.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('options-includeFormatterComment default to false', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Text line 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Text line 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Text line 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Text line 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Text line 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Text line 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Text line 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | }); 102 | 103 | describe('options-includeFormatterComment set to false', () => { 104 | const speech = new SpeechMarkdown(); 105 | 106 | const markdown = dedent` 107 | Text line 108 | `; 109 | 110 | test('converts to SSML - Amazon Alexa', () => { 111 | const options = { 112 | platform: 'amazon-alexa', 113 | includeFormatterComment: false, 114 | }; 115 | const ssml = speech.toSSML(markdown, options); 116 | 117 | const expected = dedent` 118 | 119 | Text line 120 | 121 | `; 122 | 123 | expect(ssml).toBe(expected); 124 | }); 125 | 126 | test('converts to SSML - Google Assistant', () => { 127 | const options = { 128 | platform: 'google-assistant', 129 | includeFormatterComment: false, 130 | }; 131 | const ssml = speech.toSSML(markdown, options); 132 | 133 | const expected = dedent` 134 | 135 | Text line 136 | 137 | `; 138 | 139 | expect(ssml).toBe(expected); 140 | }); 141 | 142 | test('converts to SSML - Samsung Bixby', () => { 143 | const options = { 144 | platform: 'samsung-bixby', 145 | includeFormatterComment: false, 146 | }; 147 | const ssml = speech.toSSML(markdown, options); 148 | 149 | const expected = dedent` 150 | 151 | Text line 152 | 153 | `; 154 | 155 | expect(ssml).toBe(expected); 156 | }); 157 | 158 | test('converts to SSML - Microsoft Azure', () => { 159 | const options = { 160 | platform: 'microsoft-azure', 161 | includeFormatterComment: false, 162 | }; 163 | const ssml = speech.toSSML(markdown, options); 164 | 165 | const expected = dedent` 166 | 167 | Text line 168 | 169 | `; 170 | 171 | expect(ssml).toBe(expected); 172 | }); 173 | }); 174 | 175 | describe('options-includeFormatterComment set to true', () => { 176 | const speech = new SpeechMarkdown(); 177 | 178 | const markdown = dedent` 179 | Text line 180 | `; 181 | 182 | test('converts to SSML - Amazon Alexa', () => { 183 | const options = { 184 | platform: 'amazon-alexa', 185 | includeFormatterComment: true, 186 | }; 187 | const ssml = speech.toSSML(markdown, options); 188 | 189 | const expected = dedent` 190 | 191 | 192 | Text line 193 | 194 | `; 195 | 196 | expect(ssml).toBe(expected); 197 | }); 198 | 199 | test('converts to SSML - Google Assistant', () => { 200 | const options = { 201 | platform: 'google-assistant', 202 | includeFormatterComment: true, 203 | }; 204 | const ssml = speech.toSSML(markdown, options); 205 | 206 | const expected = dedent` 207 | 208 | 209 | Text line 210 | 211 | `; 212 | 213 | expect(ssml).toBe(expected); 214 | }); 215 | 216 | test('converts to SSML - Samsung Bixby', () => { 217 | const options = { 218 | platform: 'samsung-bixby', 219 | includeFormatterComment: true, 220 | }; 221 | const ssml = speech.toSSML(markdown, options); 222 | 223 | const expected = dedent` 224 | 225 | 226 | Text line 227 | 228 | `; 229 | 230 | expect(ssml).toBe(expected); 231 | }); 232 | 233 | test('converts to SSML - Microsoft Azure', () => { 234 | const options = { 235 | platform: 'microsoft-azure', 236 | includeFormatterComment: true, 237 | }; 238 | const ssml = speech.toSSML(markdown, options); 239 | 240 | const expected = dedent` 241 | 242 | 243 | Text line 244 | 245 | `; 246 | 247 | expect(ssml).toBe(expected); 248 | }); 249 | }); 250 | -------------------------------------------------------------------------------- /tests/options-includeParagraphTag.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('options-includeParagraphTag default to false', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Text line 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Text line 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Text line 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Text line 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Text line 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Text line 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Text line 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | }); 102 | 103 | describe('options-includeParagraphTag set to false', () => { 104 | const speech = new SpeechMarkdown(); 105 | 106 | const markdown = dedent` 107 | Text line 108 | `; 109 | 110 | test('converts to SSML - Amazon Alexa', () => { 111 | const options = { 112 | platform: 'amazon-alexa', 113 | includeParagraphTag: false, 114 | }; 115 | const ssml = speech.toSSML(markdown, options); 116 | 117 | const expected = dedent` 118 | 119 | Text line 120 | 121 | `; 122 | 123 | expect(ssml).toBe(expected); 124 | }); 125 | 126 | test('converts to SSML - Google Assistant', () => { 127 | const options = { 128 | platform: 'google-assistant', 129 | includeParagraphTag: false, 130 | }; 131 | const ssml = speech.toSSML(markdown, options); 132 | 133 | const expected = dedent` 134 | 135 | Text line 136 | 137 | `; 138 | 139 | expect(ssml).toBe(expected); 140 | }); 141 | 142 | test('converts to SSML - Samsung Bixby', () => { 143 | const options = { 144 | platform: 'samsung-bixby', 145 | includeParagraphTag: false, 146 | }; 147 | const ssml = speech.toSSML(markdown, options); 148 | 149 | const expected = dedent` 150 | 151 | Text line 152 | 153 | `; 154 | 155 | expect(ssml).toBe(expected); 156 | }); 157 | 158 | test('converts to SSML - Microsoft Azure', () => { 159 | const options = { 160 | platform: 'microsoft-azure', 161 | includeParagraphTag: false, 162 | }; 163 | const ssml = speech.toSSML(markdown, options); 164 | 165 | const expected = dedent` 166 | 167 | Text line 168 | 169 | `; 170 | 171 | expect(ssml).toBe(expected); 172 | }); 173 | }); 174 | 175 | describe('options-includeFormatterComment set to true', () => { 176 | const speech = new SpeechMarkdown(); 177 | 178 | const markdown = dedent` 179 | Text line 180 | `; 181 | 182 | test('converts to SSML - Amazon Alexa', () => { 183 | const options = { 184 | platform: 'amazon-alexa', 185 | includeParagraphTag: true, 186 | }; 187 | const ssml = speech.toSSML(markdown, options); 188 | 189 | const expected = dedent` 190 | 191 |

192 | Text line 193 |

194 |
195 | `; 196 | 197 | expect(ssml).toBe(expected); 198 | }); 199 | 200 | test('converts to SSML - Google Assistant', () => { 201 | const options = { 202 | platform: 'google-assistant', 203 | includeParagraphTag: true, 204 | }; 205 | const ssml = speech.toSSML(markdown, options); 206 | 207 | const expected = dedent` 208 | 209 |

210 | Text line 211 |

212 |
213 | `; 214 | 215 | expect(ssml).toBe(expected); 216 | }); 217 | 218 | test('converts to SSML - Samsung Bixby', () => { 219 | const options = { 220 | platform: 'samsung-bixby', 221 | includeParagraphTag: true, 222 | }; 223 | const ssml = speech.toSSML(markdown, options); 224 | 225 | const expected = dedent` 226 | 227 |

228 | Text line 229 |

230 |
231 | `; 232 | 233 | expect(ssml).toBe(expected); 234 | }); 235 | 236 | test('converts to SSML - Microsoft Azure', () => { 237 | const options = { 238 | platform: 'microsoft-azure', 239 | includeParagraphTag: true, 240 | }; 241 | const ssml = speech.toSSML(markdown, options); 242 | 243 | const expected = dedent` 244 | 245 |

246 | Text line 247 |

248 |
249 | `; 250 | 251 | expect(ssml).toBe(expected); 252 | }); 253 | }); 254 | -------------------------------------------------------------------------------- /tests/options-includeSpeakTag.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('options-includeSpeakTag default to true', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Text line 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | Text line 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | Text line 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | Text line 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | Text line 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | Text line 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | Text line 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | }); 102 | 103 | describe('options-includeSpeakTag set to true', () => { 104 | const speech = new SpeechMarkdown(); 105 | 106 | const markdown = dedent` 107 | Text line 108 | `; 109 | 110 | test('converts to SSML - Amazon Alexa', () => { 111 | const options = { 112 | platform: 'amazon-alexa', 113 | includeSpeakTag: true, 114 | }; 115 | const ssml = speech.toSSML(markdown, options); 116 | 117 | const expected = dedent` 118 | 119 | Text line 120 | 121 | `; 122 | 123 | expect(ssml).toBe(expected); 124 | }); 125 | 126 | test('converts to SSML - Google Assistant', () => { 127 | const options = { 128 | platform: 'google-assistant', 129 | includeSpeakTag: true, 130 | }; 131 | const ssml = speech.toSSML(markdown, options); 132 | 133 | const expected = dedent` 134 | 135 | Text line 136 | 137 | `; 138 | 139 | expect(ssml).toBe(expected); 140 | }); 141 | 142 | test('converts to SSML - Samsung Bixby', () => { 143 | const options = { 144 | platform: 'samsung-bixby', 145 | includeSpeakTag: true, 146 | }; 147 | const ssml = speech.toSSML(markdown, options); 148 | 149 | const expected = dedent` 150 | 151 | Text line 152 | 153 | `; 154 | 155 | expect(ssml).toBe(expected); 156 | }); 157 | 158 | test('converts to SSML - Microsoft Azure', () => { 159 | const options = { 160 | platform: 'microsoft-azure', 161 | includeSpeakTag: true, 162 | }; 163 | const ssml = speech.toSSML(markdown, options); 164 | 165 | const expected = dedent` 166 | 167 | Text line 168 | 169 | `; 170 | 171 | expect(ssml).toBe(expected); 172 | }); 173 | }); 174 | 175 | describe('options-includeSpeakTag set to false', () => { 176 | const speech = new SpeechMarkdown(); 177 | 178 | const markdown = dedent` 179 | Text line 180 | `; 181 | 182 | test('converts to SSML - Amazon Alexa', () => { 183 | const options = { 184 | platform: 'amazon-alexa', 185 | includeSpeakTag: false, 186 | }; 187 | const ssml = speech.toSSML(markdown, options); 188 | 189 | const expected = dedent` 190 | Text line 191 | `; 192 | 193 | expect(ssml).toBe(expected); 194 | }); 195 | 196 | test('converts to SSML - Google Assistant', () => { 197 | const options = { 198 | platform: 'google-assistant', 199 | includeSpeakTag: false, 200 | }; 201 | const ssml = speech.toSSML(markdown, options); 202 | 203 | const expected = dedent` 204 | Text line 205 | `; 206 | 207 | expect(ssml).toBe(expected); 208 | }); 209 | 210 | test('converts to SSML - Samsung Bixby', () => { 211 | const options = { 212 | platform: 'samsung-bixby', 213 | includeSpeakTag: false, 214 | }; 215 | const ssml = speech.toSSML(markdown, options); 216 | 217 | const expected = dedent` 218 | Text line 219 | `; 220 | 221 | expect(ssml).toBe(expected); 222 | }); 223 | 224 | test('converts to SSML - Microsoft Azure', () => { 225 | const options = { 226 | platform: 'microsoft-azure', 227 | includeSpeakTag: false, 228 | }; 229 | const ssml = speech.toSSML(markdown, options); 230 | 231 | const expected = dedent` 232 | Text line 233 | `; 234 | 235 | expect(ssml).toBe(expected); 236 | }); 237 | }); 238 | -------------------------------------------------------------------------------- /tests/ordinal-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('ordinal-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | The others came in 2nd and (3)[ordinal]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | The others came in 2nd and 3. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | The others came in 2nd and 3. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | The others came in 2nd and 3. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | The others came in 2nd and 3. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | The others came in 2nd and 3. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | The others came in 2nd and 3. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | The others came in 2nd and 3. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/say-as-modifiers.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('say-as-modifiers last modifier wins', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Some (text)[address;number;time:"hms12";date;chars] 10 | Some (text)[address;number;time:'hms12';date;chars] 11 | `; 12 | 13 | test('converts to SSML - Amazon Alexa', () => { 14 | const options = { 15 | platform: 'amazon-alexa', 16 | }; 17 | const ssml = speech.toSSML(markdown, options); 18 | 19 | const expected = dedent` 20 | 21 | Some text 22 | Some text 23 | 24 | `; 25 | 26 | expect(ssml).toBe(expected); 27 | }); 28 | 29 | test('converts to SSML - Amazon Polly', () => { 30 | const options = { 31 | platform: 'amazon-polly', 32 | }; 33 | const ssml = speech.toSSML(markdown, options); 34 | 35 | const expected = dedent` 36 | 37 | Some text 38 | Some text 39 | 40 | `; 41 | 42 | expect(ssml).toBe(expected); 43 | }); 44 | 45 | test('converts to SSML - Amazon Polly (Neural)', () => { 46 | const options = { 47 | platform: 'amazon-polly-neural', 48 | }; 49 | const ssml = speech.toSSML(markdown, options); 50 | 51 | const expected = dedent` 52 | 53 | Some text 54 | Some text 55 | 56 | `; 57 | 58 | expect(ssml).toBe(expected); 59 | }); 60 | 61 | test('converts to SSML - Google Assistant', () => { 62 | const options = { 63 | platform: 'google-assistant', 64 | }; 65 | const ssml = speech.toSSML(markdown, options); 66 | 67 | const expected = dedent` 68 | 69 | Some text 70 | Some text 71 | 72 | `; 73 | 74 | expect(ssml).toBe(expected); 75 | }); 76 | 77 | test('converts to SSML - Samsung Bixby', () => { 78 | const options = { 79 | platform: 'samsung-bixby', 80 | }; 81 | const ssml = speech.toSSML(markdown, options); 82 | 83 | const expected = dedent` 84 | 85 | Some text 86 | Some text 87 | 88 | `; 89 | 90 | expect(ssml).toBe(expected); 91 | }); 92 | 93 | test('converts to SSML - Microsoft Azure', () => { 94 | const options = { 95 | platform: 'microsoft-azure', 96 | }; 97 | const ssml = speech.toSSML(markdown, options); 98 | 99 | const expected = dedent` 100 | 101 | Some text 102 | Some text 103 | 104 | `; 105 | 106 | expect(ssml).toBe(expected); 107 | }); 108 | 109 | test('converts to Plain Text', () => { 110 | const options = {}; 111 | const text = speech.toText(markdown, options); 112 | 113 | const expected = dedent` 114 | Some text 115 | Some text 116 | `; 117 | 118 | expect(text).toBe(expected); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /tests/sub-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('sub-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | The element is (Al)[sub:"aluminum"]. 10 | Visit our website at (www.speechmarkdown.org)[sub:"speech mark down dot org"]. 11 | `; 12 | 13 | test('converts to SSML - Amazon Alexa', () => { 14 | const options = { 15 | platform: 'amazon-alexa', 16 | }; 17 | const ssml = speech.toSSML(markdown, options); 18 | 19 | const expected = dedent` 20 | 21 | The element is Al. 22 | Visit our website at www.speechmarkdown.org. 23 | 24 | `; 25 | 26 | expect(ssml).toBe(expected); 27 | }); 28 | 29 | test('converts to SSML - Amazon Polly', () => { 30 | const options = { 31 | platform: 'amazon-polly', 32 | }; 33 | const ssml = speech.toSSML(markdown, options); 34 | 35 | const expected = dedent` 36 | 37 | The element is Al. 38 | Visit our website at www.speechmarkdown.org. 39 | 40 | `; 41 | 42 | expect(ssml).toBe(expected); 43 | }); 44 | 45 | test('converts to SSML - Amazon Polly (Neural)', () => { 46 | const options = { 47 | platform: 'amazon-polly-neural', 48 | }; 49 | const ssml = speech.toSSML(markdown, options); 50 | 51 | const expected = dedent` 52 | 53 | The element is Al. 54 | Visit our website at www.speechmarkdown.org. 55 | 56 | `; 57 | 58 | expect(ssml).toBe(expected); 59 | }); 60 | 61 | test('converts to SSML - Google Assistant', () => { 62 | const options = { 63 | platform: 'google-assistant', 64 | }; 65 | const ssml = speech.toSSML(markdown, options); 66 | 67 | const expected = dedent` 68 | 69 | The element is Al. 70 | Visit our website at www.speechmarkdown.org. 71 | 72 | `; 73 | 74 | expect(ssml).toBe(expected); 75 | }); 76 | 77 | test('converts to SSML - Samsung Bixby', () => { 78 | const options = { 79 | platform: 'samsung-bixby', 80 | }; 81 | const ssml = speech.toSSML(markdown, options); 82 | 83 | const expected = dedent` 84 | 85 | The element is Al. 86 | Visit our website at www.speechmarkdown.org. 87 | 88 | `; 89 | 90 | expect(ssml).toBe(expected); 91 | }); 92 | 93 | test('converts to SSML - Microsoft Azure', () => { 94 | const options = { 95 | platform: 'microsoft-azure', 96 | }; 97 | const ssml = speech.toSSML(markdown, options); 98 | 99 | const expected = dedent` 100 | 101 | The element is Al. 102 | Visit our website at www.speechmarkdown.org. 103 | 104 | `; 105 | 106 | expect(ssml).toBe(expected); 107 | }); 108 | 109 | test('converts to Plain Text', () => { 110 | const options = {}; 111 | const text = speech.toText(markdown, options); 112 | 113 | const expected = dedent` 114 | The element is Al. 115 | Visit our website at www.speechmarkdown.org. 116 | `; 117 | 118 | expect(text).toBe(expected); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /tests/telephone-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('telephone-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdownNumber = dedent` 9 | The number is (5558675309)[telephone]. 10 | `; 11 | 12 | const markdownParenthesis = dedent` 13 | The number is ((888) 555-1212)[phone]. 14 | `; 15 | 16 | test('converts to SSML - Number - Amazon Alexa', () => { 17 | const options = { 18 | platform: 'amazon-alexa', 19 | }; 20 | const ssml = speech.toSSML(markdownNumber, options); 21 | 22 | const expected = dedent` 23 | 24 | The number is 5558675309. 25 | 26 | `; 27 | 28 | expect(ssml).toBe(expected); 29 | }); 30 | 31 | test('converts to SSML - Number - Amazon Polly', () => { 32 | const options = { 33 | platform: 'amazon-polly', 34 | }; 35 | const ssml = speech.toSSML(markdownNumber, options); 36 | 37 | const expected = dedent` 38 | 39 | The number is 5558675309. 40 | 41 | `; 42 | 43 | expect(ssml).toBe(expected); 44 | }); 45 | 46 | test('converts to SSML - Number - Amazon Polly (Neural)', () => { 47 | const options = { 48 | platform: 'amazon-polly-neural', 49 | }; 50 | const ssml = speech.toSSML(markdownNumber, options); 51 | 52 | const expected = dedent` 53 | 54 | The number is 5558675309. 55 | 56 | `; 57 | 58 | expect(ssml).toBe(expected); 59 | }); 60 | 61 | test('converts to SSML - Number - Google Assistant', () => { 62 | const options = { 63 | platform: 'google-assistant', 64 | }; 65 | const ssml = speech.toSSML(markdownNumber, options); 66 | 67 | const expected = dedent` 68 | 69 | The number is 5558675309. 70 | 71 | `; 72 | 73 | expect(ssml).toBe(expected); 74 | }); 75 | 76 | test('converts to SSML - Samsung Bixby', () => { 77 | const options = { 78 | platform: 'samsung-bixby', 79 | }; 80 | const ssml = speech.toSSML(markdownNumber, options); 81 | 82 | const expected = dedent` 83 | 84 | The number is 5558675309. 85 | 86 | `; 87 | 88 | expect(ssml).toBe(expected); 89 | }); 90 | 91 | test('converts to SSML - Microsoft Azure', () => { 92 | const options = { 93 | platform: 'microsoft-azure', 94 | }; 95 | const ssml = speech.toSSML(markdownNumber, options); 96 | 97 | const expected = dedent` 98 | 99 | The number is 5558675309. 100 | 101 | `; 102 | 103 | expect(ssml).toBe(expected); 104 | }); 105 | 106 | test('converts to Plain Text - Number', () => { 107 | const options = {}; 108 | const text = speech.toText(markdownNumber, options); 109 | 110 | const expected = dedent` 111 | The number is 5558675309. 112 | `; 113 | 114 | expect(text).toBe(expected); 115 | }); 116 | 117 | test('converts to SSML - Parenthesis - Amazon Alexa', () => { 118 | const options = { 119 | platform: 'amazon-alexa', 120 | }; 121 | 122 | const ssml = speech.toSSML(markdownParenthesis, options); 123 | 124 | const expected = dedent` 125 | 126 | The number is (888) 555-1212. 127 | 128 | `; 129 | 130 | expect(ssml).toBe(expected); 131 | }); 132 | 133 | test('converts to SSML - Parenthesis - Google Assistant', () => { 134 | const options = { 135 | platform: 'google-assistant', 136 | }; 137 | 138 | const ssml = speech.toSSML(markdownParenthesis, options); 139 | 140 | const expected = dedent` 141 | 142 | The number is (888) 555-1212. 143 | 144 | `; 145 | 146 | expect(ssml).toBe(expected); 147 | }); 148 | 149 | test('converts to SSML - Samsung Bixby', () => { 150 | const options = { 151 | platform: 'samsung-bixby', 152 | }; 153 | const ssml = speech.toSSML(markdownParenthesis, options); 154 | 155 | const expected = dedent` 156 | 157 | The number is (888) 555-1212. 158 | 159 | `; 160 | 161 | expect(ssml).toBe(expected); 162 | }); 163 | 164 | test('converts to SSML - Microsoft Azure', () => { 165 | const options = { 166 | platform: 'microsoft-azure', 167 | }; 168 | const ssml = speech.toSSML(markdownParenthesis, options); 169 | 170 | const expected = dedent` 171 | 172 | The number is (888) 555-1212. 173 | 174 | `; 175 | 176 | expect(ssml).toBe(expected); 177 | }); 178 | 179 | test('converts to Plain Text - Parenthesis', () => { 180 | const options = {}; 181 | 182 | const text = speech.toText(markdownParenthesis, options); 183 | 184 | const expected = dedent` 185 | The number is (888) 555-1212. 186 | `; 187 | 188 | expect(text).toBe(expected); 189 | }); 190 | }); 191 | -------------------------------------------------------------------------------- /tests/timbre-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('timbre-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | This is my original voice, without any modifications. 10 | (Now, imagine that I am much bigger.)[timbre:"+15%"] 11 | (Or, perhaps you prefer my voice when I'm very small.)[timbre:"-15%"] 12 | `; 13 | 14 | test('converts to SSML - Amazon Alexa', () => { 15 | const options = { 16 | platform: 'amazon-alexa', 17 | }; 18 | const ssml = speech.toSSML(markdown, options); 19 | 20 | const expected = dedent` 21 | 22 | This is my original voice, without any modifications. 23 | Now, imagine that I am much bigger. 24 | Or, perhaps you prefer my voice when I'm very small. 25 | 26 | `; 27 | 28 | expect(ssml).toBe(expected); 29 | }); 30 | 31 | test('converts to SSML - Amazon Polly', () => { 32 | const options = { 33 | platform: 'amazon-polly', 34 | }; 35 | const ssml = speech.toSSML(markdown, options); 36 | 37 | const expected = dedent` 38 | 39 | This is my original voice, without any modifications. 40 | Now, imagine that I am much bigger. 41 | Or, perhaps you prefer my voice when I'm very small. 42 | 43 | `; 44 | 45 | expect(ssml).toBe(expected); 46 | }); 47 | 48 | test('converts to SSML - Amazon Polly (Neural)', () => { 49 | const options = { 50 | platform: 'amazon-polly-neural', 51 | }; 52 | const ssml = speech.toSSML(markdown, options); 53 | 54 | const expected = dedent` 55 | 56 | This is my original voice, without any modifications. 57 | Now, imagine that I am much bigger. 58 | Or, perhaps you prefer my voice when I'm very small. 59 | 60 | `; 61 | 62 | expect(ssml).toBe(expected); 63 | }); 64 | 65 | test('converts to SSML - Google Assistant', () => { 66 | const options = { 67 | platform: 'google-assistant', 68 | }; 69 | const ssml = speech.toSSML(markdown, options); 70 | 71 | const expected = dedent` 72 | 73 | This is my original voice, without any modifications. 74 | Now, imagine that I am much bigger. 75 | Or, perhaps you prefer my voice when I'm very small. 76 | 77 | `; 78 | 79 | expect(ssml).toBe(expected); 80 | }); 81 | 82 | test('converts to SSML - Samsung Bixby', () => { 83 | const options = { 84 | platform: 'samsung-bixby', 85 | }; 86 | const ssml = speech.toSSML(markdown, options); 87 | 88 | const expected = dedent` 89 | 90 | This is my original voice, without any modifications. 91 | Now, imagine that I am much bigger. 92 | Or, perhaps you prefer my voice when I'm very small. 93 | 94 | `; 95 | 96 | expect(ssml).toBe(expected); 97 | }); 98 | 99 | test('converts to SSML - Microsoft Azure', () => { 100 | const options = { 101 | platform: 'microsoft-azure', 102 | }; 103 | const ssml = speech.toSSML(markdown, options); 104 | 105 | const expected = dedent` 106 | 107 | This is my original voice, without any modifications. 108 | Now, imagine that I am much bigger. 109 | Or, perhaps you prefer my voice when I'm very small. 110 | 111 | `; 112 | 113 | expect(ssml).toBe(expected); 114 | }); 115 | 116 | test('converts to Plain Text', () => { 117 | const options = {}; 118 | const text = speech.toText(markdown, options); 119 | 120 | const expected = dedent` 121 | This is my original voice, without any modifications. 122 | Now, imagine that I am much bigger. 123 | Or, perhaps you prefer my voice when I'm very small. 124 | `; 125 | 126 | expect(text).toBe(expected); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /tests/time-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('time-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | The time is (2:30pm)[time:"hms12"]. 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | The time is 2:30pm. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | The time is 2:30pm. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | The time is 2:30pm. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | The time is 2:30pm. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | The time is 2:30pm. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | The time is 2:30pm. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | test('converts to Plain Text', () => { 102 | const options = {}; 103 | const text = speech.toText(markdown, options); 104 | 105 | const expected = dedent` 106 | The time is 2:30pm. 107 | `; 108 | 109 | expect(text).toBe(expected); 110 | }); 111 | }); 112 | -------------------------------------------------------------------------------- /tests/unit-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('unit-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | I would walk (500 mi)[unit] 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I would walk 500 mi 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | I would walk 500 mi 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | I would walk 500 mi 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | I would walk 500 mi 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | I would walk 500 mi 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | I would walk 500 mi 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | I would walk 500 mi 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tests/voice-customize.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('voice-customize custom name', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | Why do you keep switching voices (from Scott)[voice:"Scott"] to (Sarah)[voice:"Sarah"]? 10 | Why do you keep switching voices (from Scott)[voice:'Scott'] to (Sarah)[voice:'Sarah']? 11 | `; 12 | 13 | test('converts to SSML - Amazon Alexa', () => { 14 | const options = { 15 | platform: 'amazon-alexa', 16 | voices: { 17 | Scott: { voice: { name: 'Brian' } }, 18 | Sarah: { voice: { name: 'Kendra' } }, 19 | }, 20 | }; 21 | const ssml = speech.toSSML(markdown, options); 22 | 23 | const expected = dedent` 24 | 25 | Why do you keep switching voices from Scott to Sarah? 26 | Why do you keep switching voices from Scott to Sarah? 27 | 28 | `; 29 | 30 | expect(ssml).toBe(expected); 31 | }); 32 | 33 | test('converts to SSML - Google Assistant', () => { 34 | const options = { 35 | platform: 'google-assistant', 36 | voices: { 37 | Scott: { voice: { gender: 'male' } }, 38 | Sarah: { voice: { gender: 'female' } }, 39 | }, 40 | }; 41 | const ssml = speech.toSSML(markdown, options); 42 | 43 | const expected = dedent` 44 | 45 | Why do you keep switching voices from Scott to Sarah? 46 | Why do you keep switching voices from Scott to Sarah? 47 | 48 | `; 49 | 50 | expect(ssml).toBe(expected); 51 | }); 52 | }); 53 | 54 | describe('voice-customize lowercase name', () => { 55 | const speech = new SpeechMarkdown(); 56 | 57 | const markdown = dedent` 58 | Why do you keep switching voices (from Scott)[voice:"scott"] to (Sarah)[voice:"sarah"]? 59 | Why do you keep switching voices (from Scott)[voice:'scott'] to (Sarah)[voice:'sarah']? 60 | `; 61 | 62 | test('converts to SSML - Amazon Alexa', () => { 63 | const options = { 64 | platform: 'amazon-alexa', 65 | voices: { 66 | Scott: { voice: { name: 'Brian' } }, 67 | Sarah: { voice: { name: 'Kendra' } }, 68 | }, 69 | }; 70 | const ssml = speech.toSSML(markdown, options); 71 | 72 | const expected = dedent` 73 | 74 | Why do you keep switching voices from Scott to Sarah? 75 | Why do you keep switching voices from Scott to Sarah? 76 | 77 | `; 78 | 79 | expect(ssml).toBe(expected); 80 | }); 81 | 82 | test('converts to SSML - Google Assistant', () => { 83 | const options = { 84 | platform: 'google-assistant', 85 | voices: { 86 | Scott: { voice: { gender: 'male' } }, 87 | Sarah: { voice: { gender: 'female' } }, 88 | }, 89 | }; 90 | const ssml = speech.toSSML(markdown, options); 91 | 92 | const expected = dedent` 93 | 94 | Why do you keep switching voices from Scott to Sarah? 95 | Why do you keep switching voices from Scott to Sarah? 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | }); 102 | 103 | describe('voice-customize override default', () => { 104 | const speech = new SpeechMarkdown(); 105 | 106 | const markdown = dedent` 107 | Why do you keep switching voices (from Brian)[voice:"Brian"] to (Sarah)[voice:"Sarah"]? 108 | Why do you keep switching voices (from Brian)[voice:'Brian'] to (Sarah)[voice:'Sarah']? 109 | `; 110 | 111 | test('converts to SSML - Amazon Alexa', () => { 112 | const options = { 113 | platform: 'amazon-alexa', 114 | voices: { 115 | Brian: { voice: { name: 'Joey' } }, 116 | Sarah: { voice: { name: 'Kendra' } }, 117 | }, 118 | }; 119 | const ssml = speech.toSSML(markdown, options); 120 | 121 | const expected = dedent` 122 | 123 | Why do you keep switching voices from Brian to Sarah? 124 | Why do you keep switching voices from Brian to Sarah? 125 | 126 | `; 127 | 128 | expect(ssml).toBe(expected); 129 | }); 130 | 131 | test('converts to SSML - Google Assistant', () => { 132 | const options = { 133 | platform: 'google-assistant', 134 | voices: { 135 | Brian: { voice: { gender: 'male' } }, 136 | Sarah: { voice: { gender: 'female' } }, 137 | }, 138 | }; 139 | const ssml = speech.toSSML(markdown, options); 140 | 141 | const expected = dedent` 142 | 143 | Why do you keep switching voices from Brian to Sarah? 144 | Why do you keep switching voices from Brian to Sarah? 145 | 146 | `; 147 | 148 | expect(ssml).toBe(expected); 149 | }); 150 | }); 151 | 152 | describe('voice-customize custom tags', () => { 153 | const speech = new SpeechMarkdown(); 154 | 155 | const markdown = dedent` 156 | Why do you keep switching voices (from Scott)[voice:"Scott"] to (Sarah)[voice:"Sarah"]? 157 | Why do you keep switching voices (from Scott)[voice:'Scott'] to (Sarah)[voice:'Sarah']? 158 | `; 159 | 160 | test('converts to SSML - Amazon Alexa', () => { 161 | const options = { 162 | platform: 'amazon-alexa', 163 | voices: { 164 | Scott: { voice: { name: 'Brian' } }, 165 | Sarah: { 166 | voice: { name: 'Brian' }, 167 | prosody: { pitch: 'high', volume: 'soft' }, 168 | }, 169 | }, 170 | }; 171 | const ssml = speech.toSSML(markdown, options); 172 | 173 | const expected = dedent` 174 | 175 | Why do you keep switching voices from Scott to Sarah? 176 | Why do you keep switching voices from Scott to Sarah? 177 | 178 | `; 179 | 180 | expect(ssml).toBe(expected); 181 | }); 182 | 183 | test('converts to SSML - Google Assistant', () => { 184 | const options = { 185 | platform: 'google-assistant', 186 | voices: { 187 | Scott: { voice: { gender: 'male' } }, 188 | Sarah: { 189 | voice: { gender: 'male' }, 190 | prosody: { pitch: 'high', volume: 'soft' }, 191 | }, 192 | }, 193 | }; 194 | const ssml = speech.toSSML(markdown, options); 195 | 196 | const expected = dedent` 197 | 198 | Why do you keep switching voices from Scott to Sarah? 199 | Why do you keep switching voices from Scott to Sarah? 200 | 201 | `; 202 | 203 | expect(ssml).toBe(expected); 204 | }); 205 | }); 206 | -------------------------------------------------------------------------------- /tests/whisper-standard.spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:import-name 2 | import dedent from 'ts-dedent'; 3 | import { SpeechMarkdown } from '../src/SpeechMarkdown'; 4 | 5 | describe('whisper-standard', () => { 6 | const speech = new SpeechMarkdown(); 7 | 8 | const markdown = dedent` 9 | (I am not a real human.)[whisper] 10 | `; 11 | 12 | test('converts to SSML - Amazon Alexa', () => { 13 | const options = { 14 | platform: 'amazon-alexa', 15 | }; 16 | const ssml = speech.toSSML(markdown, options); 17 | 18 | const expected = dedent` 19 | 20 | I am not a real human. 21 | 22 | `; 23 | 24 | expect(ssml).toBe(expected); 25 | }); 26 | 27 | test('converts to SSML - Amazon Polly', () => { 28 | const options = { 29 | platform: 'amazon-polly', 30 | }; 31 | const ssml = speech.toSSML(markdown, options); 32 | 33 | const expected = dedent` 34 | 35 | I am not a real human. 36 | 37 | `; 38 | 39 | expect(ssml).toBe(expected); 40 | }); 41 | 42 | test('converts to SSML - Amazon Polly (Neural)', () => { 43 | const options = { 44 | platform: 'amazon-polly-neural', 45 | }; 46 | const ssml = speech.toSSML(markdown, options); 47 | 48 | const expected = dedent` 49 | 50 | I am not a real human. 51 | 52 | `; 53 | 54 | expect(ssml).toBe(expected); 55 | }); 56 | 57 | test('converts to SSML - Google Assistant', () => { 58 | const options = { 59 | platform: 'google-assistant', 60 | }; 61 | const ssml = speech.toSSML(markdown, options); 62 | 63 | const expected = dedent` 64 | 65 | I am not a real human. 66 | 67 | `; 68 | 69 | expect(ssml).toBe(expected); 70 | }); 71 | 72 | test('converts to SSML - Samsung Bixby', () => { 73 | const options = { 74 | platform: 'samsung-bixby', 75 | }; 76 | const ssml = speech.toSSML(markdown, options); 77 | 78 | const expected = dedent` 79 | 80 | I am not a real human. 81 | 82 | `; 83 | 84 | expect(ssml).toBe(expected); 85 | }); 86 | 87 | test('converts to SSML - Microsoft Azure', () => { 88 | const options = { 89 | platform: 'microsoft-azure', 90 | }; 91 | const ssml = speech.toSSML(markdown, options); 92 | 93 | const expected = dedent` 94 | 95 | I am not a real human. 96 | 97 | `; 98 | 99 | expect(ssml).toBe(expected); 100 | }); 101 | 102 | test('converts to Plain Text', () => { 103 | const options = {}; 104 | const text = speech.toText(markdown, options); 105 | 106 | const expected = dedent` 107 | I am not a real human. 108 | `; 109 | 110 | expect(text).toBe(expected); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": [ "es2017" ], 4 | "module": "commonjs", 5 | "declaration": true, 6 | "noImplicitAny": false, 7 | "noImplicitThis": false, 8 | "removeComments": false, 9 | "preserveConstEnums": true, 10 | "strict": true, 11 | "outDir": "dist", 12 | "rootDir": ".", 13 | "target": "ES5", 14 | "sourceMap": true, 15 | "strictNullChecks": false, 16 | "moduleResolution": "node", 17 | "esModuleInterop": true 18 | }, 19 | "include": [ 20 | "index.ts", 21 | "src/**/*", 22 | "test/**/*" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint-config-prettier"], 3 | "linterOptions": { 4 | "exclude": ["node_modules/**/*"] 5 | }, 6 | "rules": { 7 | "mocha-no-side-effect-code": false, 8 | "missing-jsdoc": false, 9 | "no-relative-imports": false, 10 | "export-name": false, 11 | "promise-function-async": false, 12 | "no-void-expression": false, 13 | "no-redundant-jsdoc": false, 14 | "prefer-type-cast": false, 15 | "typedef": [ 16 | true, 17 | "parameter", 18 | "arrow-parameter", 19 | "property-declaration", 20 | "member-variable-declaration" 21 | ] 22 | } 23 | } 24 | --------------------------------------------------------------------------------