first commit

This commit is contained in:
Missdrop
2025-07-16 16:30:56 +00:00
commit 7ee33927cb
11326 changed files with 1230901 additions and 0 deletions

177
node_modules/speech-rule-engine/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

960
node_modules/speech-rule-engine/README.md generated vendored Normal file
View File

@@ -0,0 +1,960 @@
Speech Rule Engine
==================
[![Dependencies](https://img.shields.io/librariesio/release/npm/speech-rule-engine)](https://img.shields.io/librariesio/release/npm/speech-rule-engine) [![NPM version](https://img.shields.io/npm/v/speech-rule-engine.svg?style=flat)](https://www.npmjs.com/package/speech-rule-engine) [![NPM monthly downloads](https://img.shields.io/npm/dm/speech-rule-engine.svg?style=flat)](https://npmjs.org/package/speech-rule-engine) [![NPM total downloads](https://img.shields.io/npm/dt/speech-rule-engine.svg?style=flat)](https://npmjs.org/package/speech-rule-engine) [![](https://data.jsdelivr.com/v1/package/npm/speech-rule-engine/badge)](https://www.jsdelivr.com/package/npm/speech-rule-engine)
[![jsdelivr rank](https://flat.badgen.net/jsdelivr/rank/npm/speech-rule-engine)](https://www.jsdelivr.com/package/npm/speech-rule-engine)
![example workflow](https://github.com/zorkow/speech-rule-engine/actions/workflows/node.js.yml/badge.svg?branch=develop)
***
**Breaking Change:** Please move to v3.0.2 or later. [More info here.](#breaking-change)
***
NodeJS version of the ChromeVox speech rule engine.
Forked from ChromeVox release 1.31.0
Speech rule engine (SRE) can translate XML expressions into speech strings
according to rules that can be specified in a syntax using Xpath expressions.
It was originally designed for translation of MathML and MathJax DOM elements
for the ChromeVox screen reader. Besides the rules originally designed for the
use in ChromeVox, it also has an implemententation of the full set of Mathspeak
and Clearspeak rules, localisation into a number of languages and Braille output
currently in Nemeth.
SRE contains a library for semantic interpretation to re-represents any
mathematical expression in its own internal semantic format, overcoming the poor
design of presentation MathML by fully disassembling and reconstructing an
expression. For a better understanding of the representation have a look at its
[visualiser](https://zorkow.github.io/semantic-tree-visualiser/visualise.html).
The semantic trees can be used in their own XML format directly or used to
enrich the input MathML expressions with semantic information and speech
strings.
There are three ways of using SRE:
1. [**Node Module:**](#node-module) Download via npm or yarn. This is the easiest way to use the speech
rule engine via its API and is the preferred option if you just want to include
it in your project.
2. [**Standalone Tool:**](#standalone-tool) Download via github and build. This is useful
if you want to use the speech rule engine in batch mode or interactivley to add
your own code. Or simply run it with ```npx```, for example to get all SRE
options anywhere without local installation run:
```bash
npx speech-rule-engine -h
```
3. [**Browser Library:**](#browser-library) This gives you the option of loading
SRE in a browser and use its full functionality on your webesites.
Node Module
-----------
Install as a node module using npm:
npm install speech-rule-engine
Or add it with yarn:
yarn add speech-rule-engine
#### Package structure
#### Running in node
``` javascript
let SRE = require('./node_modules/speech-rule-engine/lib/sre.js');
let SRE = require('speech-rule-engine');
```
``` javascript
let SRE; import('speech-rule-engine').then((m) => SRE = m.default);
let SRE; import('./node_modules/speech-rule-engine/lib/sre.js').then((m) => SRE = m.default);
```
``` javascript
let SREfeature = {json: './node_modules/speech-rule-engine/lib/mathmaps/'};
let SRE = require('./node_modules/speech-rule-engine/cjs/index.js');
```
``` javascript
let SREfeature = {json: './node_modules/speech-rule-engine/lib/mathmaps/'};
let SRE; import('./node_modules/speech-rule-engine/js/index.js').then((m) => SRE = m);
```
Then import into a running node or a source file using require:
### API #######
Current API functions are divided into three categories.
#### Methods that take a string containing a MathML expression:
| Method | Return Value |
|-------------------------|---------------------------------------------------------------------|
| `toSpeech(mathml)` | Speech string for the MathML. |
| `toSemantic(mathml)` | XML representation of the semantic tree for the MathML. |
| `toJson(mathml)` | The semantic tree in JSON. |
| `toDescription(mathml)` | The array of auditory description objects of the MathML expression. |
| `toEnriched(mathml)` | The semantically enriched MathML expression. |
**Note that in asynchronous operation mode for these methods to work correctly,
it is necessary to ensure that the Engine is ready for processing. In other
words, you need to wait for the setup promise to resolve. See documentation of
`engineReady` and `setupEngine` below.**
#### Methods that take an input filename and optionally an output filename:
_Note that the file methods only work in Node!_
These methods load the given file, process its content and return the result.
In asynchronous mode they return a promise that resolves to the result. If the
output filename is given the result will also be written to this file. Note,
that this will overwrite the existing file.
| Method | Return Value |
| ---- | ---- |
| `file.toSpeech(input, output)` | Speech string for the MathML. |
| `file.toSemantic(input, output)` | XML representation of the semantic tree for the MathML. |
| `file.toJson(input, output)` | The semantic tree in JSON. |
| `file.toDescription(input, output)` | The array of auditory description objects of the MathML expression. |
| `file.toEnriched(input, output)` | The semantically enriched MathML expression. |
#### Methods for computing textual representations of numbers
These methods take a non-negative integer (either as string or number) as input
an return the number as text in the currently active locale. For the `vulgar`
method a vulgar fraction can be provided as a string of two slash separated
numbers, e.g., `"1/2"`.
| Method | Return Value |
|-------------------------|-------------------------------------------|
| `number(input)` | The number as text. |
| `ordinal(input)` | The word ordinal. |
| `numericOrdinal(input)` | The numeric ordinal. |
| `vulgar(input)` | Word representation of a vulgar fraction. |
| | |
#### Methods for querying and controlling the engine behaviour:
| Method | Return Value |
|------------------------|-------------------------------------------------------------------------------------|
| `version` | Returns SRE's version number. |
| `engineReady()` | Returns a promise that resolves as soon as the engine is ready for processing. |
| | I.e., all necessary rule files have been loaded and the engine is done updating. |
| | **This is important in asynchronous settings.** |
| `setupEngine(options)` | Takes an [options feature vector](#options) to parameterise the Speech Rule Engine. |
| | Returns a promise that resolves as soon as the engine is ready for processing. |
| `engineSetup()` | Returns the current setup of the engine as an [options feature vector](#options). |
| `localeLoader()` | SRE's standard method for loading locales, depending on SRE's mode. |
| | For more detail see [discussion on locale loading](#locale-loading). |
| | |
#### Methods for navigating math expressions:
For the following methods SRE maintains an internal state, hence they are only
useful when running in browser or in a Node REPL. Therefore, they are not
exposed via the command line interface.
| Method | Return Value |
| ---- | ---- |
| `walk(mathml)` | Speech string for the math expression. |
| `move(keycode)` | Speech string after the move. Keycodes are numerical strings representing cursor keys, space, enter, etc. |
For more information on keybindings for the walker see here [this dedicated
page](https://speechruleengine.org/www/keybindings.html).
### Configuration ####
There are a number of options that allow you to parameterise the Speech Rule
Engine. They can be set with the `setupEngine(options)` method, which takes an
options feature vector (an object of option/value pairs) to parameterise the
engine. The engine's setup can be queried with the `engineSetup()` method that
returns feature vector representing its current setup. Some options are quite
internal to SRE and are therefore not exposed via the command line interface.
In addition to programmatically configuring SRE using the ``setupEngine``
method, you can also set a configuration variable `SREfeature` before SRE is
loaded. This can be useful, when running SRE as a batch process or when changing
its locale loading behaviour on startup. For details see the section on [locale
loading below](#locale-loading).
`SREfeature` should be set in the `global` environment before SRE is loaded into
Node. The following example sets the locale on load to German:
``` javascript
var SREfeature = {locale: 'de'};
sre = require('speech-rule-engine');
sre.engineReady().then(() => console.log(sre.toSpeech('<mo>=</mo>')));
```
This should yield `ist gleich` as output.
### Options
The following is a list of configuration options that can be passed to SRE via
the `setupEngine` method or the `SREfeature` variable.
#### Options to control speech output
| Option | Value |
|------------|----------------------------------------------------------------------------------------------------------------|
| *domain* | Domain or subject area of speech rules (e.g., mathspeak, clearspeak). |
| *style* | Style or preference setting of speech rules (e.g., brief). |
| | In case of clearspeak, multiple preferences can be chosen using `:` as separator. |
| *locale* | Language locale in 639-1. |
| *subiso* | More fine grained specification of locale. E.g., for French fr, be, or ch |
| *markup* | Set output markup for speech: ```none```, ```ssml```, ```sable```, ```voicexml```, ```acss``` |
| *modality* | Set the modality SRE returns. E.g., ```speech```, ```braille```, ```prefix```, ```summary``` |
Observe that not every _domain_ (i.e., speech rule set) implements every
style. Similarly, not every speech rule set is implemneted in every locale. For
a more detailed overview of `locale, domain, style` combinations, use the
`--opt` switch on the command line interface.
#### Options for enriched MathML output
Enriched MathML output is markup that embeds the internal semantic structure SRE
uses into a modified representation of the original MathML. To get an idea of
the semantic tree, take a look at [its
visualisation](https://zorkow.github.io/semantic-tree-visualiser/visualise.html).
| Option | Value |
|-------------|-----------------------------------------------------------------------------------------------------------------|
| *speech* | Depth to which generated speech is stored in attributes during semantic enrichment. |
| | Values are ```none```, ```shallow```, ```deep```. Default is ```none```. |
| *pprint* | Boolean flag to switch on pretty printing of output. This works on any XML style output. Default is ```true```. |
| *structure* | Boolean flag to include attributes for aria tree view structure in enriched MathML. |
| | Also includes a `structure` attribute that summarises the semantic tree structure in form of an sexpression. |
| | |
#### Options for internal control of the engine
These other options give more fine grained control of SRE. They can be useful
during development and when integrating SRE into a larger project. They are
given in decreasing order of interestingness.
| Option | Value |
|-----------------|------------------------------------------------------------------------------------------------------|
| *json* | URL from where to pull the locale files, i.e., json files containing speech rule definitions. |
| *xpath* | URL where to pull an xpath library from. |
| | This is important for environments not supporting xpath, e.g., IE or former versions of Edge. |
| *rate* | Base value for speech rate in ```ssml``` markup |
| *strict* | Boolean flag indicating if only a directly matching rule should be used (default is ```false```). |
| | I.e., no default rules are used in case a rule is not available for a particular domain, style, etc. |
| *mode* | The running mode for SRE: ```sync```, ```async```, ```http``` |
| | By default SRE in node is in `async`, in browser in `http`, and on CLI in `sync` mode. |
| *custom* | Provide a custom method for locale loading. See below for more informaton. |
| *defaultLocale* | Allows customisation for default locale. Default is ```en``` for English. |
| | This option is not available in the CLI. See below for more informaton. |
| *delay* | Delays loading of base locales and automatic setup of engine. Default is ```false```. |
| | Option should be used only at startup. See below for more information. |
Standalone Tool
---------------
Install the library using `npm`:
npm install speech-rule-engine
Or add it with yarn:
yarn add speech-rule-engine
### Run on command line ############
SRE can be run on the command line by providing a set of processing options and
either a list of input files or a inputting an XML expression manually.
./node_modules/.bin/sre [options] infile1 infile2 infile3 ...
For example running
./node_modules/.bin/sre -j -p PATH_TO_SRE_RESOURCES/samples/sample1.xml PATH_TO_SRE_RESOURCES/samples/sample2.xml
will return the semantic tree in JSON as well as the speech translation for the
expressions in the two sample files.
(Note, that `-p` is the default option if no processing options are given).
If you have `npx` installed simply use this to run it from within the `speech-rule-engine` folder with
npx sre
This works equivalently with all options and file input.
SRE also enables direct input from command line using `stdin`. For example,
running
npx sre -j -p
will wait for a complete XML expression to be input for translation. Similarly,
shell piping is allowed:
npx sre -j -p < PATH_TO_SRE_RESOURCES/samples/sample1.xml
Note, that when providing the `-o outfile` option output is saved into the given file.
However, when processing from file only the very last output is reliably saved, while when
processing via pipes or command line input all output is saved.
### Command Line Options ###########
The following is a list of command line options for the speech rule engine.
| Short | Long | Meaning |
|-------|--------------------|:------------------------------------------------------------------------------------------------------------------------------|
| `-o` | --output [name] | Output file [name]. |
| | | If not given output is printed to stdout. |
| | | |
| | | |
| | | |
| `-d` | --domain [name] | Domain or subject area [name]. |
| | | This refers to a particular subject type of speech rules or subject area rules are defined for (e.g., mathspeak, clearspeak). |
| | | If no domain parameter is provided, default is used. |
| `-s` | --style [name] | Speech style [name]. |
| | | Selects a particular speech style (e.g., brief). |
| | | If no style parameter is provided, style default is used. |
| `-c` | --locale | Language locale in ISO 639-1. |
| `-k` | --markup [name] | Generate speech output with markup tags. Currently supported SSML, VoiceXML, Sable, ACSS (as sexpressions for Emacsspeak) |
| | | |
| | | |
| | | |
| `-p` | --speech | Generate speech output (default). |
| `-a` | --audit | Generate auditory descriptions (JSON format). |
| `-j` | --json | Generate JSON of semantic tree. |
| `-x` | --xml | Generate XML of semantic tree. |
| `-P` | --pprint | When given, output is pretty printed if possible. |
| | | |
| | | |
| | | |
| `-t` | --latex | Accept LaTeX input directly for certain locale/modality combinations. |
| `-m` | --mathml | Generate enriched MathML. |
| `-g` | --generate [depth] | Include generated speech in enriched MathML. Supported values: none, shallow, deep (default: none) |
| `-w` | --structure | Include aria tree view and structure attribute in enriched MathML. |
| | | |
| | | |
| | | |
| `-N` | --number | Translate number to words. |
| `-O` | --ordinal | Translate number to word ordinal. |
| `-S` | --numeric | Translate number to numeric ordinal. |
| `-F` | --vulgar | Translate vulgar fraction to words. Provide vulgar fraction as slash seperated numbers. |
| `-C` | --subiso | Subcategory of the locale given with -c. |
| | | |
| | | |
| | | |
| `-v` | --verbose | Verbose mode. Print additional information, useful for debugging. |
| `-l` | --log [name] | Log file [name]. Verbose output is redirected to this file. |
| | | If not given verbose output is printed to stdout. |
| `-h` | --help | Enumerates all command line options. |
| | --opt | Enumerates available options for current locale and modality. Output as markdown with -P option. |
| | --opt | List engine setup options for all available locales. Output as markdown with -P option. |
| `-V` | --version | Outputs the version number |
Building from Source
--------------------
Clone from github and install dependencies either by running:
npm install
Or install them manually. SRE depends on the following libraries to run:
commander
xmldom-sre
wicked-good-xpath
In addition SRE depends on a number of libraries for development, in particular
[TypeScript](https://www.typescriptlang.org/) and
[webpack](https://webpack.js.org/) as well as a number of plugins and libraries
to ensure source code hygiene. These are too numerous to list here and are best
viewed in the `devDependencies` section of the `package.json` file.
Running `npm install` will build the single JavaScript modules, webpack the
bundle file in `lib/sre.js` as well as assemble the locale files in
`lib/mathmaps`. For more details on the build process as well as how to use
different bundlers see the [developers documentation
below](#developers-documentation).
### Run interactively ############
You can work with SRE interactively in node or use it as a batch processor, by
loading JavaScript modules directly. For the generation of speech make sure to
set the `SRE_JSON_PATH` environment variable to the folder where your locale
files reside. For example, set
export SRE_JSON_PATH=./lib/mathmaps
before in the shell before running node in the `speech-rule-engine` directory.
You can then load the individual modules simply with node's `require`:
``` javascript
let sre = require('./js/index.js');
```
will give you the full API in the sre variable. On the other hand,
``` javascript
semantic = require('./js/semantic_tree/semantic.js');
```
will let you work with the semantic tree module only.
Browser Library
---------------
SRE can be used as a browser ready library giving you the option of loading it
in a browser and use its full functionality on your webesites. Since SRE version
4, the same bundle file works both in node and in a browser. Simply include the
file ``sre.js`` in your website in a script tag
``` html
<script src="[URL]/sre.js"></script>
```
The API will now be available in the ``SRE`` namespace.
### Configuration ####
In addition to programmatically configuring SRE using the ``setupEngine``
method, you can also include a configuration element in a website, that can take
the same options as ``setupEngine``. There are two ways of specifying the
configuration element:
1. Providing a JSON object in a special script tag of type `text/x-sre-config`.
2. Setting the `SREfeature` configuration variable.
An example of the first option is the configuration element
``` html
<script type="text/x-sre-config">
{
"json": "https://cdn.jsdelivr.net/gh/zorkow/speech-rule-engine@develop/mathmaps/",
"xpath": "https://cdn.jsdelivr.net/gh/google/wicked-good-xpath@master/dist/wgxpath.install.js",
"domain": "mathspeak",
"style": "sbrief"
}
</script>
```
which will cause SRE to load JSON files from rawgit and for IE or Edge it will also load Google's
[wicked good xpath library](https://github.com/google/wicked-good-xpath). In addition the speech rules are set to ``mathspeak`` in ``super brief`` style.
**Make sure the configuration element comes before the script tag loading SRE in your website!**
An alternative is the use of the `SREfeature` variable to specify the feature
vector to customise SRE when its loaded into the page. Again **make sure this
script tag comes before the script tag loading SRE in your website!**
``` javascript
<script>
var SREfeature = {
"locale": "de"
};
</script>
```
The use of `SREfeature` is particularly important for setting a custom load
method in the browser, that can not simply be passed to the JSON object in the
`x-sre-config` block. For more details see the section on [locale loading
below](#locale-loading).
# Developers Documentation
Since v4 SRE is distributed with the transpiled `.js` files via the npm
package. These can be directly included into your respective projects. To
control the location of the locale mappings, set the `SRE_JSON_PATH` environment
variable to the folder where your locale files reside. For example, set
export SRE_JSON_PATH=./lib/mathmaps
For more controlled integration or development fork or clone the repository from
github.
Building
--------
By default the build process consists of three steps:
1. Creating Locale files in 'lib/mathmaps'
1. Transpiling typescript from sources in 'ts/' to 'js/'
1. Webpacking the bundle in 'lib/sre.js'
Locales are created from the sources in `mathmaps` by combining the topically
split `.json` files into a single, minimized `.json` file, one for each
language. Note, that for ease of development JSON minimisation is done via an
intermediate step to generate `.min` files, which is handles in the `Makefile`
and ensures that only newly altered files have to be minimized.
While the entire build is best cleaned with `make clean`, this does not clean
the `.min` files. These should be cleaned with `make clean_min`.
Alternative Builds
------------------
### MathJax Library
This is only relevant for MathJax distributions version 2.7.X. As of version 3.0
MathJax uses sre directly via its `npm` release. The MathJax specific build can
be created using the `mjConfig` goal for webpack
npx webpack
that generates a build specific for [MathJax](https://mathjax.org) in ``mathjax_sre.js``.
SRE can then be configured locally on webpages as described above.
### Other Entry Points
For particular projects it might be useful and sufficient to create bespoke
bundles of SRE submodules. Depending on the bundler
Examples of entry points that provide separate API functionality to SRE
submodules are
| Module | Javascript entry point | Typescript entry point | Comments |
|------------|--------------------------------|--------------------------------|----------------------------------------------------|
| `semantic` | `js/semantic_tree/semantic.js` | `ts/semantic_tree/semantic.ts` | API for semantic tree generation |
| `enrich` | `js/enrich_mathml/enrich.js` | `ts/enrich_mathml/enrich.ts` | API for semantic enrichment of MathML expressions. |
| `mathjax` | `js/common/mathjax.js` | `ts/common/mathjax.ts` | API for MathJax version 2.7.X |
Using Bundlers
--------------
By default SRE works with webpack. But you can use a number of other bundlers to
build. Note, that for all bundlers the JSON locale files need to be build as
usual. Depending on the version of SRE you are using some of the alternative
bundlers might already be in the `devDependencies`.
### WebPack
The default webpack of SRE generates the `sre.js` library that can be used both
in node and the browser. Other goals are `mjConfig` that is defined in
`webpack.config.js` or alternative entry points as discussed in more detail in
the [Alternative Builds section](#alternative-builds).
### Rollupjs
Creates bundles similar to webpack, that can be used pretty much as
replacement. Rollup bundles are build from the Javascript modules in `js`, so
make sure to transpile first with `npx tsc`.
#### Build
Install the required packages:
``` shell
npm install --no-save rollup
npm install --no-save @rollup/plugin-commonjs
npm install --no-save @rollup/plugin-node-resolve
npm install --no-save @rollup/plugin-terser
```
Add a `rollup.config.js` file of the form:
``` javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from "@rollup/plugin-terser";
import pkg from './package.json';
export default [
{
input: 'js/index.js',
output: {
name: 'SRE',
file: pkg.browser,
format: 'umd'
},
plugins: [
resolve(),
commonjs(),
terser()
]
}
];
```
The resulting file in `./lib/sre.js` works as usual for both browser and node.
_Note, that in the Browser version there is currently an issue with Unicode
Braille Spaces that are being garbled._
### Esbuild
Creates small builds very fast, but has some backward compatibility issues, in
that it can work with ES6 modules only.
#### Build
Install the required packages:
``` shell
npm install --no-save esbuild
```
Build using the following command line:
``` shell
npx esbuild ./ts/index.ts --bundle --outfile=lib/sre.js --format=esm --minify
```
#### Node
To run in node you need ES6 modules enabled.
``` shell
npm install --no-save esm
```
Then start node with `node -r esm`. If you want to use the CLI interface, adapt
the `./bin/sre` script as follows:
``` javascript
#!/usr/bin/env -S node -r esm
let sre = require('../lib/sre.js');
(new sre.cli()).commandLine();
```
#### Browser
Import the SRE library as ES6 module into the browser, e.g.,
``` html
<script type="module">
import * as SRE from 'http://localhost/sre/speech-rule-engine/lib/sre.js'
...
</script>
```
### Parcel
SRE currently does not support bundling with `parcel`.
Locale Loading
--------------
### Custom Loading Methods ####
SRE loads its locales and rule sets via loading methods specific for the
particular environment and mode. I.e., it loads json files from the file system
in node or via XML HTTP requests in the browser using the `localLoader` method
that is exposed in the API. These methods can be customised via passing a new
method to the engine via the feature vector. A loader method takes the locale
string as input and returns a promise that resolves to the string containing the
JSON structure of the locale file once loading is successfully completed. In
other words it should be of type
``` typescript
(locale: string) => Promise<string>
```
In node the method can be directly set by passing it to the `setupEngine` method
via the feature vector. As an example the following method loads locales from a
local folder at `/tmp/mymaps`.
``` javascript
sre.setupEngine({
custom: loc => {
let file = `/tmp/mymaps/${loc}.json`;
return new Promise((res, rej) => {
try {
res(fs.readFileSync(file));
console.log(`Loading of locale ${loc} succeeded`);
} catch (_) {
console.log(`Loading of locale ${loc} failed`);
rej('');
}
});
}
});
```
### Custom Loading Methods in Node ####
Setting the custom load method with `setupEngine` will only allow you to change
locale loading behaviour after the SRE has performed basic setup, that is, it
has already tried to load the base and fallback locale. However, it is often
desirable to change SRE's loading behaviour before the initial locale files have
been loaded. This can be down by setting the `SREfeature` vector **before**
loading SRE. Here is a code snippet to demonstrate its use:
``` javascript
const fs = require('fs');
global.SREfeature = {
custom: loc => {
console.log(`Loading locale ${loc}`);
let file = `/tmp/mymaps/${loc}.json`;
return new Promise((res, rej) => {
try {
res(fs.readFileSync(file));
console.log(`Loading of locale ${loc} succeeded`);
} catch (_) {
console.log(`Loading of locale ${loc} failed`);
rej('');
}
});
}
};
let sre = require(process.cwd() + '/node_modules/speech-rule-engine/lib/sre.js');
```
### Custom Loading Methods in the Browser ####
Providing a custom loading method for locale loading in browser mode is very
similar to its use in node. However, note that since we now want to define a
function, it can not simply be given in the JSON configuration element in the
`x-sre-config` script tag. Instead we need to define the special `SREfeature`
variable in the header of the file. Again **make sure this script tag comes
before the script tag loading SRE in your website!**
Here is an example of a custom function to load locales from localhost:
``` javascript
<script>
var SREfeature = {
"custom": function(loc) {
let file = 'http://localhost/sre/lib/mathmaps/' + loc + '.json';
let httpRequest = new XMLHttpRequest();
return new Promise((res, rej) => {
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
console.log('Using my custom loader');
let status = httpRequest.status;
if (status === 0 || (status >= 200 && status < 400)) {
res(httpRequest.responseText);
} else {
rej(status);
}
}
};
httpRequest.open('GET', file, true);
httpRequest.send();
});
}
}
</script>
```
### Reusing the Standard Loader
SRE exposes its standard locale loader via the API method `localeLoader`. The
method returns the actual load method that can be applied to an iso locale
string, e.g., `SRE.localeLoader()('fr');` to load the French locale. This
allows its use as a fallback loader in a custom load method, which is particular
useful when a customised set of rules for a particular locale should be loaded
from a different location than the rest of the locales.
For example, consider the following code snippet that ensures that only the
German locale is loaded from a custom directory:
``` javascript
let SRE = null;
global.SREfeature = {
'custom': async function(loc) {
if (loc === 'de') {
return new Promise((res, rej) => {
try {
res(fs.readFileSync('/tmp/mymaps/de.json'));
} catch (_) {
rej('');
}
});
}
console.log('custom loader');
return SRE.localeLoader()(loc);
}
};
SRE = require('speech-rule-engine');
```
### Setting Default Locale ###
In standard setup SRE loads its base locale files together with a default locale
that acts as a fallback in case rules or symbol mappings are not available in
the locale that is being used. In standard setup the fallback locale is
English. This means SRE currently loads `base.json` together with `en.json` as
fallback rules on initialisation.
This behaviour can be changed by providing SRE with a different fallback locale
by using `defaultLocale` feature. Note the following:
* If `defaultLocale` is set to a locale that does not exist, English will be
retained as fallback.
* The `base` locale will always be loaded first, regardless of the value of
`defaultLocale`.
* The default locale can currently not be changed when using SRE via the
command line interface.
### Delaying Automatic Locale Loading ###
SRE's setup is automated as much as possible for ease of use, by performing the
following two steps:
1. On load SRE determines its environment (browser, node, command line) and
picks up any options provided via a feature vector.
2. It then loads the basic locales, taking the configuration options into
account, to be ready for translation.
Setting `delay` to `true`, suppresses this behaviour by postponing the second
step (i.e., the intial locale loading) to the first explicit call to
`setupEngine`.
This can be useful in case the custom load method can only be provided later or
the `json` path is constructed programmatically by a client application. It is
also helpful if some locales are webpacked into a distribution and need to be
loaded with a custom method.
Note, that using `delay` means that locale loading can and has to be handled by
the developer explicitly. In particular, it implies that English is not
necessarily loaded as fallback locale and that calling the `toSpeech` method
without another call to `setupEngine` generally leads to no speech output. Also,
while `delay` can be set on any call to `setupEngine`, it really only makes
sense during initial setup.
Coding Style
------------
SRE is implemented using coding format enforced by
[prettier](https://prettier.io/) and [eslint](https://eslint.org/). In addition
it requires full documentation using [JSDOC](https://jsdoc.app/). When creating
a pull request, please make sure that your code compiles and is fully linted.
### Code Formatting
We use [prettier](https://prettier.io/) for formatting code. Run
npm format
to see which files contain format violations. Use
npm format-fix
to automatically fix those format violations.
### Code Hygiene
We use [eslint](https://eslint.org/) for enforcing code style and
documentation. Run
npm lint
to see a list of linting errors and warnings. Use
npm lint-fix
to automatically fix those violations as much as possible.
### Documentation
Full [JSDOC](https://jsdoc.app/) documentation is required and enforced via the
[`eslint jsdoc plugin`](https://www.npmjs.com/package/eslint-plugin-jsdoc). To
generate documentation from the [JSDOC](https://jsdoc.app/), simply run
npm run docs
This will generate documentation using [typedoc](http://typedoc.org) for the
source code in the directory ``docs/``.
Node Package
------------
The speech rule engine is published as a node package in fully compiled form, together with the JSON libraries for translating atomic expressions. All relevant files are in the lib subdirectory.
To publish the node package run
npm publish
For manually going through the build steps see the `prepublish` script in `package.json`.
Removed or Deprecated Functionality
-----------------------------------
The following is an overview of functionality and options that were available at
some point in SRE. Depending on the version you are using they might still work,
do nothing or throw an error. Even if they still work they are strongly
discouraged to use.
### Removed or Deprecated Engine Setup Options
The following options are either deprecated or have been removed. Having them in
the feature vector for `setupEngine` should not throw an exception but will have
no effect.
| Option | Value | Release | Comments |
|-------------|---------------------------------------------------------------------------------------------------------------------------|---------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| *cache* | Boolean flag to switch expression caching during speech generation. Default is ```true```. | *Removed in v3.2.0* | Expression caching has been removed and the option has no longer any effect. |
| *rules* | A list of rulesets to use by SRE. | | |
| | This allows to artificially restrict available speech rules, which can be useful for testing and during rule development. | | |
| | ***Always expects a list, even if only one rule set is supplied!*** | *Deprecated in v4.0.0* | Note that setting rule sets is no longer useful with the new rule indexing structures. It is only retained for testing purposes. |
| *walker* | A walker to use for interactive exploration: ```None```, ```Syntax```, ```Semantic```, ```Table``` | *Deprecated since v4.0.0* | Defaults to Table walker. Other walkers are no longer maintained! |
| *semantics* | Boolean flag to switch **OFF** semantic interpretation. | *Removed in v3.0* | Non-semantic rule sets have been removed since v3.0. |
#### Removed API functions #########
| Method | Return Value | Release | Comments |
| ---- | ---- | ---- | ---- |
| `pprintXML(string)` | Returns pretty printed version of a serialised XML string. | *Removed v3.0* | Use the `pprint` option instead.` |
#### Removed Command Line Options #########
| Short | Long | Meaning | Release | Comments |
|-------|----------------|:-----------------------------------------|:------------------------------------------|:----------------------------------------------------------|
| `-i` | --input [name] | Input file [name]. | *Deprecated since v3.0. Removed in v4.0!* | Use standard input file handling or stdio piping instead. |
| `-s` | --semantics | Switch **OFF** semantics interpretation. | *Removed in v3.0* | There is no longer support for non-semantic rule sets. |
| | | | *New meaning in v4.1* | `-s` is now used to set `styles` on the command line. |
| `-t` | | | *Changed meaning in v4.1* | Now refers to direct LaTeX input. |
## Breaking Change
Due to a breaking change in
the [commander library](https://github.com/tj/commander.js/releases/tag/v6.0.0)
old versions of SRE might break when newly installed from `npm`. SRE relies on
commander for running its command line interface.
**Therefore, please move to SRE v3.0.2 or later.**
If you want to run older versions of SRE, you need to manually downgrade the
`commander` package to `v5.1.0` by running
```bash
npm install commander@5.1.0
```
Note, that the command line option `--options` has now been renamed to `--opt`.

4
node_modules/speech-rule-engine/bin/README.md generated vendored Normal file
View File

@@ -0,0 +1,4 @@
Location of standalone binaries for the speech rule engine.
When built separately, this directory will contain a script that allows to run
the engine as a command line application.

4
node_modules/speech-rule-engine/bin/sre generated vendored Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
let sre = require('../lib/sre.js');
(new sre.cli()).commandLine();

3
node_modules/speech-rule-engine/index.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
global.SRE_JSON_PATH = __dirname + '/lib/mathmaps';
var sre = require('./lib/sre.js');
module.exports = sre;

View File

@@ -0,0 +1,14 @@
import { KeyCode } from '../common/event_util.js';
import { AudioRenderer } from './audio_renderer.js';
import { AuditoryDescription } from './auditory_description.js';
import { Span } from './span.js';
export declare abstract class AbstractAudioRenderer implements AudioRenderer {
private separator_;
abstract markup(descrs: AuditoryDescription[]): string;
set separator(sep: string);
get separator(): string;
error(_key: KeyCode | string): string | null;
merge(spans: Span[]): string;
finalize(str: string): string;
pauseValue(value: string): number;
}

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractAudioRenderer = void 0;
const engine_js_1 = require("../common/engine.js");
class AbstractAudioRenderer {
constructor() {
this.separator_ = ' ';
}
set separator(sep) {
this.separator_ = sep;
}
get separator() {
return engine_js_1.Engine.getInstance().modality === 'braille' ? '' : this.separator_;
}
error(_key) {
return null;
}
merge(spans) {
let str = '';
const len = spans.length - 1;
for (let i = 0, span; (span = spans[i]); i++) {
str += span.speech;
if (i < len) {
const sep = span.attributes['separator'];
str += sep !== undefined ? sep : this.separator;
}
}
return str;
}
finalize(str) {
return str;
}
pauseValue(value) {
let numeric;
switch (value) {
case 'long':
numeric = 750;
break;
case 'medium':
numeric = 500;
break;
case 'short':
numeric = 250;
break;
default:
numeric = parseInt(value, 10);
}
return Math.floor((numeric * engine_js_1.Engine.getInstance().getRate()) / 100);
}
}
exports.AbstractAudioRenderer = AbstractAudioRenderer;

View File

@@ -0,0 +1,11 @@
import * as EngineConst from '../common/engine_const.js';
import * as AudioUtil from './audio_util.js';
import { AuditoryDescription } from './auditory_description.js';
import { MarkupRenderer } from './markup_renderer.js';
export declare class AcssRenderer extends MarkupRenderer {
markup(descrs: AuditoryDescription[]): string;
error(key: number): string;
prosodyElement(key: EngineConst.personalityProps, value: number): string;
pause(pause: AudioUtil.Pause): string;
private prosody_;
}

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AcssRenderer = void 0;
const EngineConst = require("../common/engine_const.js");
const EventUtil = require("../common/event_util.js");
const AudioUtil = require("./audio_util.js");
const markup_renderer_js_1 = require("./markup_renderer.js");
class AcssRenderer extends markup_renderer_js_1.MarkupRenderer {
markup(descrs) {
this.setScaleFunction(-2, 2, 0, 10, 0);
const markup = AudioUtil.personalityMarkup(descrs);
const result = [];
const currentPers = { open: [] };
let pause = null;
let isString = false;
for (let i = 0, descr; (descr = markup[i]); i++) {
if (AudioUtil.isMarkupElement(descr)) {
AudioUtil.mergeMarkup(currentPers, descr);
continue;
}
if (AudioUtil.isPauseElement(descr)) {
if (isString) {
pause = AudioUtil.mergePause(pause, descr, Math.max);
}
continue;
}
const str = '"' + this.merge(descr.span) + '"';
isString = true;
if (pause) {
result.push(this.pause(pause));
pause = null;
}
const prosody = this.prosody_(currentPers);
result.push(prosody ? '(text (' + prosody + ') ' + str + ')' : str);
}
return '(exp ' + result.join(' ') + ')';
}
error(key) {
return '(error "' + EventUtil.Move.get(key) + '")';
}
prosodyElement(key, value) {
value = this.applyScaleFunction(value);
switch (key) {
case EngineConst.personalityProps.RATE:
return '(richness . ' + value + ')';
case EngineConst.personalityProps.PITCH:
return '(average-pitch . ' + value + ')';
case EngineConst.personalityProps.VOLUME:
return '(stress . ' + value + ')';
}
return '(value . ' + value + ')';
}
pause(pause) {
return ('(pause . ' +
this.pauseValue(pause[EngineConst.personalityProps.PAUSE]) +
')');
}
prosody_(pros) {
const keys = pros.open;
const result = [];
for (let i = 0, key; (key = keys[i]); i++) {
result.push(this.prosodyElement(key, pros[key]));
}
return result.join(' ');
}
}
exports.AcssRenderer = AcssRenderer;

View File

@@ -0,0 +1,10 @@
import { KeyCode } from '../common/event_util.js';
import { AuditoryDescription } from './auditory_description.js';
import { Span } from './span.js';
export interface AudioRenderer {
separator: string;
markup(descrs: AuditoryDescription[]): string;
error(key: KeyCode | string): string | null;
merge(strs: Span[]): string;
finalize(str: string): string;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,19 @@
import * as EngineConst from '../common/engine_const.js';
import { AuditoryDescription } from './auditory_description.js';
export interface Tags {
open?: EngineConst.personalityProps[];
close?: EngineConst.personalityProps[];
[personality: string]: any;
}
export type PauseValue = number | string;
export interface Pause {
pause: PauseValue;
[personality: string]: any;
}
export type Markup = Pause | Tags;
export declare function mergePause(oldPause: Pause | null, newPause: Pause, opt_merge?: (p1: PauseValue, p2: PauseValue) => PauseValue): Pause;
export declare function mergeMarkup(oldPers: Tags, newPers: Tags): void;
export declare function sortClose(open: EngineConst.personalityProps[], descrs: Tags[]): EngineConst.personalityProps[];
export declare function personalityMarkup(descrs: AuditoryDescription[]): Markup[];
export declare function isMarkupElement(element: Markup): boolean;
export declare function isPauseElement(element: Markup): boolean;

300
node_modules/speech-rule-engine/js/audio/audio_util.js generated vendored Normal file
View File

@@ -0,0 +1,300 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergePause = mergePause;
exports.mergeMarkup = mergeMarkup;
exports.sortClose = sortClose;
exports.personalityMarkup = personalityMarkup;
exports.isMarkupElement = isMarkupElement;
exports.isPauseElement = isPauseElement;
const base_util_js_1 = require("../common/base_util.js");
const EngineConst = require("../common/engine_const.js");
const engine_js_1 = require("../common/engine.js");
const span_js_1 = require("./span.js");
function mergePause(oldPause, newPause, opt_merge) {
if (!oldPause) {
return newPause;
}
return { pause: mergePause_(oldPause.pause, newPause.pause, opt_merge) };
}
function mergePause_(oldPause, newPause, opt_merge) {
const merge = opt_merge ||
function (x, y) {
if (typeof x === 'number' && typeof y === 'number') {
return x + y;
}
if (typeof x === 'number') {
return y;
}
if (typeof y === 'number') {
return x;
}
return [oldPause, newPause].sort()[0];
};
return merge.call(null, oldPause, newPause);
}
function mergeMarkup(oldPers, newPers) {
delete oldPers.open;
newPers.close.forEach((x) => delete oldPers[x]);
newPers.open.forEach((x) => (oldPers[x] = newPers[x]));
const keys = Object.keys(oldPers);
oldPers.open = keys;
}
function sortClose(open, descrs) {
if (open.length <= 1) {
return open;
}
const result = [];
for (let i = 0, descr; (descr = descrs[i]), open.length; i++) {
if (!descr.close || !descr.close.length) {
continue;
}
descr.close.forEach(function (x) {
const index = open.indexOf(x);
if (index !== -1) {
result.unshift(x);
open.splice(index, 1);
}
});
}
return result;
}
let PersonalityRanges_ = {};
let LastOpen_ = [];
function personalityMarkup(descrs) {
PersonalityRanges_ = {};
LastOpen_ = [];
let result = [];
const currentPers = {};
for (let i = 0, descr; (descr = descrs[i]); i++) {
let pause = null;
const span = descr.descriptionSpan();
const pers = descr.personality;
const join = pers[EngineConst.personalityProps.JOIN];
delete pers[EngineConst.personalityProps.JOIN];
if (typeof pers[EngineConst.personalityProps.PAUSE] !== 'undefined') {
pause = {
[EngineConst.personalityProps.PAUSE]: pers[EngineConst.personalityProps.PAUSE]
};
delete pers[EngineConst.personalityProps.PAUSE];
}
const diff = personalityDiff_(pers, currentPers);
appendMarkup_(result, span, diff, join, pause, true);
}
result = result.concat(finaliseMarkup_());
result = simplifyMarkup_(result);
result = engine_js_1.Engine.getInstance().cleanpause ? cleanPause(result) : result;
return result;
}
function cleanPause(markup) {
while (isPauseElement(markup[0])) {
markup.shift();
}
while (isPauseElement(markup[markup.length - 1])) {
markup.pop();
}
return markup;
}
function appendElement_(markup, element) {
const last = markup[markup.length - 1];
if (!last) {
markup.push(element);
return;
}
if (isSpanElement(element) && isSpanElement(last)) {
if (typeof last.join === 'undefined') {
last.span = last.span.concat(element.span);
return;
}
const lstr = last['span'].pop();
const fstr = element['span'].shift();
last['span'].push(lstr + last.join + fstr);
last['span'] = last['span'].concat(element.span);
last.join = element.join;
return;
}
if (isPauseElement(element) && isPauseElement(last)) {
last.pause = mergePause_(last.pause, element.pause);
return;
}
markup.push(element);
}
function simplifyMarkup_(markup) {
const lastPers = {};
const result = [];
for (let i = 0, element; (element = markup[i]); i++) {
if (!isMarkupElement(element)) {
appendElement_(result, element);
continue;
}
if (!element.close || element.close.length !== 1 || element.open.length) {
copyValues_(element, lastPers);
result.push(element);
continue;
}
let nextElement = markup[i + 1];
if (!nextElement || isSpanElement(nextElement)) {
copyValues_(element, lastPers);
result.push(element);
continue;
}
const pauseElement = isPauseElement(nextElement) ? nextElement : null;
if (pauseElement) {
nextElement = markup[i + 2];
}
if (nextElement &&
isMarkupElement(nextElement) &&
nextElement.open[0] === element.close[0] &&
!nextElement.close.length &&
nextElement[nextElement.open[0]] === lastPers[nextElement.open[0]]) {
if (pauseElement) {
appendElement_(result, pauseElement);
i = i + 2;
}
else {
i = i + 1;
}
}
else {
copyValues_(element, lastPers);
result.push(element);
}
}
return result;
}
function copyValues_(from, to) {
if (from['rate']) {
to['rate'] = from['rate'];
}
if (from['pitch']) {
to['pitch'] = from['pitch'];
}
if (from['volume']) {
to['volume'] = from['volume'];
}
}
function finaliseMarkup_() {
const final = [];
for (let i = LastOpen_.length - 1; i >= 0; i--) {
const pers = LastOpen_[i];
if (pers.length) {
const markup = { open: [], close: [] };
for (let j = 0; j < pers.length; j++) {
const per = pers[j];
markup.close.push(per);
markup[per] = 0;
}
final.push(markup);
}
}
return final;
}
function isMarkupElement(element) {
return typeof element === 'object' && element.open;
}
function isPauseElement(element) {
return (typeof element === 'object' &&
Object.keys(element).length === 1 &&
Object.keys(element)[0] === EngineConst.personalityProps.PAUSE);
}
function isSpanElement(element) {
const keys = Object.keys(element);
return (typeof element === 'object' &&
((keys.length === 1 && keys[0] === 'span') ||
(keys.length === 2 &&
((keys[0] === 'span' && keys[1] === 'join') ||
(keys[1] === 'span' && keys[0] === 'join')))));
}
function appendMarkup_(markup, span, pers, join, pause, merge = false) {
if (merge) {
const last = markup[markup.length - 1];
let oldJoin;
if (last) {
oldJoin = last[EngineConst.personalityProps.JOIN];
}
if (last && !span.speech && pause && isPauseElement(last)) {
const pauseProp = EngineConst.personalityProps.PAUSE;
last[pauseProp] = mergePause_(last[pauseProp], pause[pauseProp]);
pause = null;
}
if (last &&
span.speech &&
Object.keys(pers).length === 0 &&
isSpanElement(last)) {
if (typeof oldJoin !== 'undefined') {
const lastSpan = last['span'].pop();
span = span_js_1.Span.stringAttr(lastSpan.speech + oldJoin + span.speech, lastSpan.attributes);
}
last['span'].push(span);
span = span_js_1.Span.empty();
last[EngineConst.personalityProps.JOIN] = join;
}
}
if (Object.keys(pers).length !== 0) {
markup.push(pers);
}
if (span.speech) {
markup.push({ span: [span], join: join });
}
if (pause) {
markup.push(pause);
}
}
function personalityDiff_(current, old) {
if (!old) {
return current;
}
const result = {};
for (const prop of EngineConst.personalityPropList) {
const currentValue = current[prop];
const oldValue = old[prop];
if ((!currentValue && !oldValue) ||
(currentValue && oldValue && currentValue === oldValue)) {
continue;
}
const value = currentValue || 0;
if (!isMarkupElement(result)) {
result.open = [];
result.close = [];
}
if (!currentValue) {
result.close.push(prop);
}
if (!oldValue) {
result.open.push(prop);
}
if (oldValue && currentValue) {
result.close.push(prop);
result.open.push(prop);
}
old[prop] = value;
result[prop] = value;
PersonalityRanges_[prop]
? PersonalityRanges_[prop].push(value)
: (PersonalityRanges_[prop] = [value]);
}
if (isMarkupElement(result)) {
let c = result.close.slice();
while (c.length > 0) {
let lo = LastOpen_.pop();
const loNew = (0, base_util_js_1.setdifference)(lo, c);
c = (0, base_util_js_1.setdifference)(c, lo);
lo = loNew;
if (c.length === 0) {
if (lo.length !== 0) {
LastOpen_.push(lo);
}
continue;
}
if (lo.length === 0) {
continue;
}
result.close = result.close.concat(lo);
result.open = result.open.concat(lo);
for (let i = 0, open; (open = lo[i]); i++) {
result[open] = old[open];
}
}
LastOpen_.push(result.open);
}
return result;
}

View File

@@ -0,0 +1,66 @@
import { Span } from './span.js';
interface AudioDescr {
context?: string;
text: string;
userValue?: string;
annotation?: string;
attributes?: {
[key: string]: string;
};
personality?: {
[key: string]: string;
};
layout?: string;
}
interface AudioFlags {
adjust?: boolean;
preprocess?: boolean;
correct?: boolean;
translate?: boolean;
}
export declare class AuditoryItem {
data: AuditoryDescription;
prev: AuditoryItem;
next: AuditoryItem;
constructor(data?: AuditoryDescription);
}
export declare class AuditoryList extends Set<AuditoryItem> {
annotations: AuditoryItem[];
private anchor;
constructor(descrs: AuditoryDescription[]);
first(): AuditoryItem;
last(): AuditoryItem;
push(item: AuditoryItem): void;
pop(): AuditoryItem;
delete(item: AuditoryItem): boolean;
insertAfter(descr: AuditoryDescription, item: AuditoryItem): void;
insertBefore(descr: AuditoryDescription, item: AuditoryItem): void;
prevText(item: AuditoryItem): AuditoryItem;
[Symbol.iterator](): IterableIterator<AuditoryItem>;
nextText(item: AuditoryItem): AuditoryItem;
clear(): void;
empty(): boolean;
toList(): AuditoryDescription[];
}
export declare class AuditoryDescription {
context: string;
text: string;
userValue: string;
annotation: string;
attributes: {
[key: string]: string;
};
personality: {
[key: string]: string;
};
layout: string;
static create(args: AudioDescr, flags?: AudioFlags): AuditoryDescription;
constructor({ context, text, userValue, annotation, attributes, personality, layout }: AudioDescr);
isEmpty(): boolean;
clone(): AuditoryDescription;
toString(): string;
descriptionString(): string;
descriptionSpan(): Span;
equals(that: AuditoryDescription): boolean;
}
export {};

View File

@@ -0,0 +1,185 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuditoryDescription = exports.AuditoryList = exports.AuditoryItem = void 0;
const grammar_js_1 = require("../rule_engine/grammar.js");
const span_js_1 = require("./span.js");
class AuditoryItem {
constructor(data = null) {
this.data = data;
this.prev = null;
this.next = null;
}
}
exports.AuditoryItem = AuditoryItem;
class AuditoryList extends Set {
constructor(descrs) {
super();
this.annotations = [];
this.anchor = new AuditoryItem();
this.anchor.next = this.anchor;
this.anchor.prev = this.anchor;
descrs.forEach((d) => {
const item = new AuditoryItem(d);
if (d.annotation) {
this.annotations.push(item);
}
this.push(item);
});
}
first() {
return this.empty ? null : this.anchor.next;
}
last() {
return this.empty ? null : this.anchor.prev;
}
push(item) {
item.next = this.anchor;
item.prev = this.anchor.prev;
item.prev.next = item;
this.anchor.prev = item;
super.add(item);
}
pop() {
const item = this.last();
if (!item) {
return null;
}
this.delete(item);
return item;
}
delete(item) {
if (!this.has(item)) {
return false;
}
super.delete(item);
item.prev.next = item.next;
item.next = item.prev;
return true;
}
insertAfter(descr, item) {
this.insertBefore(descr, item.next);
}
insertBefore(descr, item) {
const nitem = new AuditoryItem(descr);
if (!item || !this.has(item)) {
this.push(nitem);
return;
}
item.prev.next = nitem;
nitem.prev = item.prev;
nitem.next = item;
item.prev = nitem;
}
prevText(item) {
do {
item = item.prev;
} while (item !== this.anchor && !item.data.text);
return item === this.anchor ? null : item;
}
*[Symbol.iterator]() {
let current = this.anchor.next;
while (current !== this.anchor) {
yield current;
current = current.next;
}
}
nextText(item) {
while (item !== this.anchor && !item.data.text) {
item = item.next;
}
return item;
}
clear() {
this.anchor.next = this.anchor;
this.anchor.prev = this.anchor;
super.clear();
}
empty() {
return this.anchor.prev === this.anchor && this.anchor === this.anchor.next;
}
toList() {
const result = [];
let item = this.anchor.next;
while (item !== this.anchor) {
result.push(item.data);
item = item.next;
}
return result;
}
}
exports.AuditoryList = AuditoryList;
class AuditoryDescription {
static create(args, flags = {}) {
args.text = grammar_js_1.Grammar.getInstance().apply(args.text, flags);
return new AuditoryDescription(args);
}
constructor({ context, text, userValue, annotation, attributes, personality, layout }) {
this.context = context || '';
this.text = text || '';
this.userValue = userValue || '';
this.annotation = annotation || '';
this.attributes = attributes || {};
this.personality = personality || {};
this.layout = layout || '';
}
isEmpty() {
return (this.context.length === 0 &&
this.text.length === 0 &&
this.userValue.length === 0 &&
this.annotation.length === 0);
}
clone() {
let personality;
if (this.personality) {
personality = {};
for (const [key, val] of Object.entries(this.personality)) {
personality[key] = val;
}
}
let attributes;
if (this.attributes) {
attributes = {};
for (const [key, val] of Object.entries(this.attributes)) {
attributes[key] = val;
}
}
return new AuditoryDescription({
context: this.context,
text: this.text,
userValue: this.userValue,
annotation: this.annotation,
personality: personality,
attributes: attributes,
layout: this.layout
});
}
toString() {
return ('AuditoryDescription(context="' +
this.context +
'" ' +
' text="' +
this.text +
'" ' +
' userValue="' +
this.userValue +
'" ' +
' annotation="' +
this.annotation +
'")');
}
descriptionString() {
return this.context && this.text
? this.context + ' ' + this.text
: this.context || this.text;
}
descriptionSpan() {
return span_js_1.Span.stringAttr(this.descriptionString(), this.attributes);
}
equals(that) {
return (this.context === that.context &&
this.text === that.text &&
this.userValue === that.userValue &&
this.annotation === that.annotation);
}
}
exports.AuditoryDescription = AuditoryDescription;

View File

@@ -0,0 +1,12 @@
import * as EngineConst from '../common/engine_const.js';
import { AudioRenderer } from './audio_renderer.js';
import { AuditoryDescription } from './auditory_description.js';
import { Span } from './span.js';
export declare function setSeparator(sep: string): void;
export declare function getSeparator(): string;
export declare function markup(descrs: AuditoryDescription[]): string;
export declare function merge(strs: (Span | string)[]): string;
export declare function finalize(str: string): string;
export declare function error(key: string): string;
export declare function registerRenderer(type: EngineConst.Markup, renderer: AudioRenderer): void;
export declare function isXml(): boolean;

View File

@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setSeparator = setSeparator;
exports.getSeparator = getSeparator;
exports.markup = markup;
exports.merge = merge;
exports.finalize = finalize;
exports.error = error;
exports.registerRenderer = registerRenderer;
exports.isXml = isXml;
const engine_js_1 = require("../common/engine.js");
const EngineConst = require("../common/engine_const.js");
const acss_renderer_js_1 = require("./acss_renderer.js");
const layout_renderer_js_1 = require("./layout_renderer.js");
const punctuation_renderer_js_1 = require("./punctuation_renderer.js");
const sable_renderer_js_1 = require("./sable_renderer.js");
const span_js_1 = require("./span.js");
const ssml_renderer_js_1 = require("./ssml_renderer.js");
const string_renderer_js_1 = require("./string_renderer.js");
const xml_renderer_js_1 = require("./xml_renderer.js");
const xmlInstance = new ssml_renderer_js_1.SsmlRenderer();
const renderers = new Map([
[EngineConst.Markup.NONE, new string_renderer_js_1.StringRenderer()],
[EngineConst.Markup.COUNTING, new string_renderer_js_1.CountingRenderer()],
[EngineConst.Markup.PUNCTUATION, new punctuation_renderer_js_1.PunctuationRenderer()],
[EngineConst.Markup.LAYOUT, new layout_renderer_js_1.LayoutRenderer()],
[EngineConst.Markup.ACSS, new acss_renderer_js_1.AcssRenderer()],
[EngineConst.Markup.SABLE, new sable_renderer_js_1.SableRenderer()],
[EngineConst.Markup.VOICEXML, xmlInstance],
[EngineConst.Markup.SSML, xmlInstance]
]);
function setSeparator(sep) {
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
if (renderer) {
renderer.separator = sep;
}
}
function getSeparator() {
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
return renderer ? renderer.separator : '';
}
function markup(descrs) {
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
if (!renderer) {
return '';
}
return renderer.markup(descrs);
}
function merge(strs) {
const span = strs.map((s) => {
return typeof s === 'string' ? span_js_1.Span.stringEmpty(s) : s;
});
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
if (!renderer) {
return strs.join();
}
return renderer.merge(span);
}
function finalize(str) {
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
if (!renderer) {
return str;
}
return renderer.finalize(str);
}
function error(key) {
const renderer = renderers.get(engine_js_1.Engine.getInstance().markup);
if (!renderer) {
return '';
}
return renderer.error(key);
}
function registerRenderer(type, renderer) {
renderers.set(type, renderer);
}
function isXml() {
return renderers.get(engine_js_1.Engine.getInstance().markup) instanceof xml_renderer_js_1.XmlRenderer;
}

View File

@@ -0,0 +1,17 @@
import * as AudioUtil from './audio_util.js';
import { AuditoryDescription } from './auditory_description.js';
import { XmlRenderer } from './xml_renderer.js';
export declare class LayoutRenderer extends XmlRenderer {
static options: {
cayleyshort: boolean;
linebreaks: boolean;
};
finalize(str: string): string;
pause(_pause: AudioUtil.Pause): string;
prosodyElement(attr: string, value: number): string;
closeTag(tag: string): string;
markup(descrs: AuditoryDescription[]): string;
private processContent;
private values;
private layoutValue;
}

View File

@@ -0,0 +1,372 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LayoutRenderer = void 0;
const debugger_js_1 = require("../common/debugger.js");
const DomUtil = require("../common/dom_util.js");
const EngineConst = require("../common/engine_const.js");
const engine_js_1 = require("../common/engine.js");
const AudioUtil = require("./audio_util.js");
const xml_renderer_js_1 = require("./xml_renderer.js");
class LayoutRenderer extends xml_renderer_js_1.XmlRenderer {
constructor() {
super(...arguments);
this.values = new Map();
}
finalize(str) {
setRelValues(this.values.get('rel'));
return setTwoDim(str);
}
pause(_pause) {
return '';
}
prosodyElement(attr, value) {
return attr === EngineConst.personalityProps.LAYOUT ? `<${value}>` : '';
}
closeTag(tag) {
return `</${tag}>`;
}
markup(descrs) {
this.values.clear();
const result = [];
let content = [];
for (const descr of descrs) {
if (!descr.layout) {
content.push(descr);
continue;
}
result.push(this.processContent(content));
content = [];
const [pref, layout, value] = this.layoutValue(descr.layout);
if (pref === 'begin') {
result.push('<' + layout + (value ? ` value="${value}"` : '') + '>');
continue;
}
if (pref === 'end') {
result.push('</' + layout + '>');
continue;
}
console.warn('Something went wrong with layout markup: ' + layout);
}
result.push(this.processContent(content));
return result.join('');
}
processContent(content) {
const result = [];
const markup = AudioUtil.personalityMarkup(content);
for (let i = 0, descr; (descr = markup[i]); i++) {
if (descr.span) {
result.push(this.merge(descr.span));
continue;
}
if (AudioUtil.isPauseElement(descr)) {
continue;
}
}
return result.join('');
}
layoutValue(layout) {
const match = layout.match(/^(begin|end|)(.*\D)(\d*)$/);
const value = match[3];
if (!value) {
return [match[1], match[2], ''];
}
layout = match[2];
if (!this.values.has(layout)) {
this.values.set(layout, {});
}
this.values.get(layout)[value] = true;
return [match[1], layout, value];
}
}
exports.LayoutRenderer = LayoutRenderer;
LayoutRenderer.options = {
cayleyshort: engine_js_1.Engine.getInstance().cayleyshort,
linebreaks: engine_js_1.Engine.getInstance().linebreaks
};
let twodExpr = '';
const handlers = {
TABLE: handleTable,
CASES: handleCases,
CAYLEY: handleCayley,
MATRIX: handleMatrix,
CELL: recurseTree,
FENCE: recurseTree,
ROW: recurseTree,
FRACTION: handleFraction,
NUMERATOR: handleFractionPart,
DENOMINATOR: handleFractionPart,
REL: handleRelation,
OP: handleRelation
};
function applyHandler(element) {
const tag = DomUtil.tagName(element);
const handler = handlers[tag];
return handler ? handler(element) : element.textContent;
}
const relValues = new Map();
function setRelValues(values) {
relValues.clear();
if (!values)
return;
const keys = Object.keys(values)
.map((x) => parseInt(x))
.sort();
for (let i = 0, key; (key = keys[i]); i++) {
relValues.set(key, i + 1);
}
}
function setTwoDim(str) {
twodExpr = '';
const dom = DomUtil.parseInput(`<all>${str}</all>`);
debugger_js_1.Debugger.getInstance().output(DomUtil.formatXml(dom.toString()));
twodExpr = recurseTree(dom);
return twodExpr;
}
function combineContent(str1, str2) {
if (!str1 || !str2) {
return str1 + str2;
}
const height1 = strHeight(str1);
const height2 = strHeight(str2);
const diff = height1 - height2;
str1 = diff < 0 ? padCell(str1, height2, strWidth(str1)) : str1;
str2 = diff > 0 ? padCell(str2, height1, strWidth(str2)) : str2;
const lines1 = str1.split(/\r\n|\r|\n/);
const lines2 = str2.split(/\r\n|\r|\n/);
const result = [];
for (let i = 0; i < lines1.length; i++) {
result.push(lines1[i] + lines2[i]);
}
return result.join('\n');
}
function recurseTree(dom) {
let result = '';
for (const child of Array.from(dom.childNodes)) {
if (child.nodeType === DomUtil.NodeType.TEXT_NODE) {
result = combineContent(result, child.textContent);
continue;
}
result = combineContent(result, applyHandler(child));
}
return result;
}
function strHeight(str) {
return str.split(/\r\n|\r|\n/).length;
}
function strWidth(str) {
return str.split(/\r\n|\r|\n/).reduce((max, x) => Math.max(x.length, max), 0);
}
function padHeight(str, height) {
const padding = height - strHeight(str);
return str + (padding > 0 ? new Array(padding + 1).join('\n') : '');
}
function padWidth(str, width) {
const lines = str.split(/\r\n|\r|\n/);
const result = [];
for (const line of lines) {
const padding = width - line.length;
result.push(line + (padding > 0 ? new Array(padding + 1).join('') : ''));
}
return result.join('\n');
}
function padCell(str, height, width) {
str = padHeight(str, height);
return padWidth(str, width);
}
function assembleRows(matrix) {
const children = Array.from(matrix.childNodes);
const mat = [];
for (const row of children) {
if (row.nodeType !== DomUtil.NodeType.ELEMENT_NODE) {
continue;
}
mat.push(handleRow(row));
}
return mat;
}
function getMaxParameters(mat) {
const maxHeight = mat.reduce((max, x) => Math.max(x.height, max), 0);
const maxWidth = [];
for (let i = 0; i < mat[0].width.length; i++) {
maxWidth.push(mat.map((x) => x.width[i]).reduce((max, x) => Math.max(max, x), 0));
}
return [maxHeight, maxWidth];
}
function combineCells(mat, maxWidth) {
const newMat = [];
for (const row of mat) {
if (row.height === 0) {
continue;
}
const newCells = [];
for (let i = 0; i < row.cells.length; i++) {
newCells.push(padCell(row.cells[i], row.height, maxWidth[i]));
}
row.cells = newCells;
newMat.push(row);
}
return newMat;
}
function combineRows(mat, maxHeight) {
if (maxHeight === 1) {
return mat
.map((row) => row.lfence + row.cells.join(row.sep) + row.rfence)
.join('\n');
}
const result = [];
for (const row of mat) {
const sep = verticalArrange(row.sep, row.height);
let str = row.cells.shift();
while (row.cells.length) {
str = combineContent(str, sep);
str = combineContent(str, row.cells.shift());
}
str = combineContent(verticalArrange(row.lfence, row.height), str);
str = combineContent(str, verticalArrange(row.rfence, row.height));
result.push(str);
result.push(row.lfence + new Array(strWidth(str) - 3).join(row.sep) + row.rfence);
}
return result.slice(0, -1).join('\n');
}
function verticalArrange(char, height) {
let str = '';
while (height) {
str += char + '\n';
height--;
}
return str.slice(0, -1);
}
function getFence(node) {
if (node.nodeType === DomUtil.NodeType.ELEMENT_NODE &&
DomUtil.tagName(node) === 'FENCE') {
return applyHandler(node);
}
return '';
}
function handleMatrix(matrix) {
let mat = assembleRows(matrix);
const [maxHeight, maxWidth] = getMaxParameters(mat);
mat = combineCells(mat, maxWidth);
return combineRows(mat, maxHeight);
}
function handleTable(table) {
let mat = assembleRows(table);
mat.forEach((row) => {
row.cells = row.cells.slice(1).slice(0, -1);
row.width = row.width.slice(1).slice(0, -1);
});
const [maxHeight, maxWidth] = getMaxParameters(mat);
mat = combineCells(mat, maxWidth);
return combineRows(mat, maxHeight);
}
function handleCases(cases) {
let mat = assembleRows(cases);
mat.forEach((row) => {
row.cells = row.cells.slice(0, -1);
row.width = row.width.slice(0, -1);
});
const [maxHeight, maxWidth] = getMaxParameters(mat);
mat = combineCells(mat, maxWidth);
return combineRows(mat, maxHeight);
}
function handleCayley(cayley) {
let mat = assembleRows(cayley);
mat.forEach((row) => {
row.cells = row.cells.slice(1).slice(0, -1);
row.width = row.width.slice(1).slice(0, -1);
row.sep = row.sep + row.sep;
});
const [maxHeight, maxWidth] = getMaxParameters(mat);
const bar = {
lfence: '',
rfence: '',
cells: maxWidth.map((x) => '⠐' + new Array(x).join('⠒')),
width: maxWidth,
height: 1,
sep: mat[0].sep
};
if (engine_js_1.Engine.getInstance().cayleyshort && mat[0].cells[0] === '') {
bar.cells[0] = '';
}
mat.splice(1, 0, bar);
mat = combineCells(mat, maxWidth);
return combineRows(mat, maxHeight);
}
function handleRow(row) {
const children = Array.from(row.childNodes);
const lfence = getFence(children[0]);
const rfence = getFence(children[children.length - 1]);
if (lfence) {
children.shift();
}
if (rfence) {
children.pop();
}
let sep = '';
const cells = [];
for (const child of children) {
if (child.nodeType === DomUtil.NodeType.TEXT_NODE) {
sep = child.textContent;
continue;
}
const result = applyHandler(child);
cells.push(result);
}
return {
lfence: lfence,
rfence: rfence,
sep: sep,
cells: cells,
height: cells.reduce((max, x) => Math.max(strHeight(x), max), 0),
width: cells.map(strWidth)
};
}
function centerCell(cell, width) {
const cw = strWidth(cell);
const center = (width - cw) / 2;
const [lpad, rpad] = Math.floor(center) === center
? [center, center]
: [Math.floor(center), Math.ceil(center)];
const lines = cell.split(/\r\n|\r|\n/);
const result = [];
const [lstr, rstr] = [
new Array(lpad + 1).join(''),
new Array(rpad + 1).join('')
];
for (const line of lines) {
result.push(lstr + line + rstr);
}
return result.join('\n');
}
function handleFraction(frac) {
const [open, num, , den, close] = Array.from(frac.childNodes);
const numerator = applyHandler(num);
const denominator = applyHandler(den);
const nwidth = strWidth(numerator);
const dwidth = strWidth(denominator);
let maxWidth = Math.max(nwidth, dwidth);
const bar = open + new Array(maxWidth + 1).join('⠒') + close;
maxWidth = bar.length;
return (`${centerCell(numerator, maxWidth)}\n${bar}\n` +
`${centerCell(denominator, maxWidth)}`);
}
function handleFractionPart(prt) {
const fchild = prt.firstChild;
const content = recurseTree(prt);
if (fchild && fchild.nodeType === DomUtil.NodeType.ELEMENT_NODE) {
if (DomUtil.tagName(fchild) === 'ENGLISH') {
return '⠰' + content;
}
if (DomUtil.tagName(fchild) === 'NUMBER') {
return '⠼' + content;
}
}
return content;
}
function handleRelation(rel) {
if (!engine_js_1.Engine.getInstance().linebreaks) {
return recurseTree(rel);
}
const value = relValues.get(parseInt(rel.getAttribute('value')));
return (value ? `<br value="${value}"/>` : '') + recurseTree(rel);
}

View File

@@ -0,0 +1,11 @@
import { AbstractAudioRenderer } from './abstract_audio_renderer.js';
import { Pause } from './audio_util.js';
export declare abstract class MarkupRenderer extends AbstractAudioRenderer {
protected ignoreElements: string[];
private scaleFunction;
abstract pause(pause: Pause): void;
abstract prosodyElement(key: string, value: number): void;
setScaleFunction(a: number, b: number, c: number, d: number, decimals?: number): void;
applyScaleFunction(value: number): number;
protected ignoreElement(key: string): boolean;
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkupRenderer = void 0;
const EngineConst = require("../common/engine_const.js");
const abstract_audio_renderer_js_1 = require("./abstract_audio_renderer.js");
class MarkupRenderer extends abstract_audio_renderer_js_1.AbstractAudioRenderer {
constructor() {
super(...arguments);
this.ignoreElements = [EngineConst.personalityProps.LAYOUT];
this.scaleFunction = null;
}
setScaleFunction(a, b, c, d, decimals = 0) {
this.scaleFunction = (x) => {
const delta = (x - a) / (b - a);
const num = c * (1 - delta) + d * delta;
return +(Math.round((num + 'e+' + decimals)) +
'e-' +
decimals);
};
}
applyScaleFunction(value) {
return this.scaleFunction ? this.scaleFunction(value) : value;
}
ignoreElement(key) {
return this.ignoreElements.indexOf(key) !== -1;
}
}
exports.MarkupRenderer = MarkupRenderer;

View File

@@ -0,0 +1,8 @@
import { AbstractAudioRenderer } from './abstract_audio_renderer.js';
import * as AudioUtil from './audio_util.js';
import { AuditoryDescription } from './auditory_description.js';
export declare class PunctuationRenderer extends AbstractAudioRenderer {
private static PAUSE_PUNCTUATION;
markup(descrs: AuditoryDescription[]): string;
pause(pause: AudioUtil.PauseValue): string;
}

View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PunctuationRenderer = void 0;
const EngineConst = require("../common/engine_const.js");
const abstract_audio_renderer_js_1 = require("./abstract_audio_renderer.js");
const AudioUtil = require("./audio_util.js");
class PunctuationRenderer extends abstract_audio_renderer_js_1.AbstractAudioRenderer {
markup(descrs) {
const markup = AudioUtil.personalityMarkup(descrs);
let str = '';
let pause = null;
let span = false;
for (let i = 0, descr; (descr = markup[i]); i++) {
if (AudioUtil.isMarkupElement(descr)) {
continue;
}
if (AudioUtil.isPauseElement(descr)) {
pause = descr;
continue;
}
if (pause) {
str += this.pause(pause[EngineConst.personalityProps.PAUSE]);
pause = null;
}
str += (span ? this.separator : '') + this.merge(descr.span);
span = true;
}
return str;
}
pause(pause) {
let newPause;
if (typeof pause === 'number') {
if (pause <= 250) {
newPause = 'short';
}
else if (pause <= 500) {
newPause = 'medium';
}
else {
newPause = 'long';
}
}
else {
newPause = pause;
}
return PunctuationRenderer.PAUSE_PUNCTUATION.get(newPause) || '';
}
}
exports.PunctuationRenderer = PunctuationRenderer;
PunctuationRenderer.PAUSE_PUNCTUATION = new Map([
['short', ','],
['medium', ';'],
['long', '.']
]);

View File

@@ -0,0 +1,9 @@
import * as EngineConst from '../common/engine_const.js';
import { Pause } from './audio_util.js';
import { XmlRenderer } from './xml_renderer.js';
export declare class SableRenderer extends XmlRenderer {
finalize(str: string): string;
pause(pause: Pause): string;
prosodyElement(tag: EngineConst.personalityProps, value: number): string;
closeTag(tag: string): string;
}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SableRenderer = void 0;
const EngineConst = require("../common/engine_const.js");
const xml_renderer_js_1 = require("./xml_renderer.js");
class SableRenderer extends xml_renderer_js_1.XmlRenderer {
finalize(str) {
return ('<?xml version="1.0"?>' +
'<!DOCTYPE SABLE PUBLIC "-//SABLE//DTD SABLE speech mark up//EN"' +
' "Sable.v0_2.dtd" []><SABLE>' +
this.separator +
str +
this.separator +
'</SABLE>');
}
pause(pause) {
return ('<BREAK ' +
'MSEC="' +
this.pauseValue(pause[EngineConst.personalityProps.PAUSE]) +
'"/>');
}
prosodyElement(tag, value) {
value = this.applyScaleFunction(value);
switch (tag) {
case EngineConst.personalityProps.PITCH:
return '<PITCH RANGE="' + value + '%">';
case EngineConst.personalityProps.RATE:
return '<RATE SPEED="' + value + '%">';
case EngineConst.personalityProps.VOLUME:
return '<VOLUME LEVEL="' + value + '%">';
default:
return '<' + tag.toUpperCase() + ' VALUE="' + value + '">';
}
}
closeTag(tag) {
return '</' + tag.toUpperCase() + '>';
}
}
exports.SableRenderer = SableRenderer;

15
node_modules/speech-rule-engine/js/audio/span.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
export type SpanAttrs = {
[key: string]: string;
};
export declare class Span {
speech: string;
attributes: SpanAttrs;
constructor(speech: string, attributes: SpanAttrs);
static empty(): Span;
static stringEmpty(str: string): Span;
static stringAttr(str: string, attr: SpanAttrs): Span;
static singleton(str: string, def?: SpanAttrs): Span[];
static node(str: string, node: Element, def?: SpanAttrs): Span;
static attributeList: string[];
static getAttributes(node: Element): SpanAttrs;
}

37
node_modules/speech-rule-engine/js/audio/span.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Span = void 0;
class Span {
constructor(speech, attributes) {
this.speech = speech;
this.attributes = attributes;
}
static empty() {
return new Span('', {});
}
static stringEmpty(str) {
return new Span(str, {});
}
static stringAttr(str, attr) {
return new Span(str, attr);
}
static singleton(str, def = {}) {
return [Span.stringAttr(str, def)];
}
static node(str, node, def = {}) {
const attr = Span.getAttributes(node);
Object.assign(attr, def);
return new Span(str, attr);
}
static getAttributes(node) {
const attrs = {};
for (const attr of Span.attributeList) {
if (node.hasAttribute(attr)) {
attrs[attr] = node.getAttribute(attr);
}
}
return attrs;
}
}
exports.Span = Span;
Span.attributeList = ['id', 'extid'];

View File

@@ -0,0 +1,17 @@
import { Pause } from './audio_util.js';
import { AuditoryDescription } from './auditory_description.js';
import { Span } from './span.js';
import { XmlRenderer } from './xml_renderer.js';
export declare class SsmlRenderer extends XmlRenderer {
finalize(str: string): string;
pause(pause: Pause): string;
prosodyElement(attr: string, value: number): string;
closeTag(_tag: string): string;
static MARK_ONCE: boolean;
static MARK_KIND: boolean;
private static CHARACTER_ATTR;
private static MARKS;
markup(descrs: AuditoryDescription[]): string;
merge(spans: Span[]): string;
private isEmptySpan;
}

View File

@@ -0,0 +1,86 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SsmlRenderer = void 0;
const engine_js_1 = require("../common/engine.js");
const EngineConst = require("../common/engine_const.js");
const xml_renderer_js_1 = require("./xml_renderer.js");
class SsmlRenderer extends xml_renderer_js_1.XmlRenderer {
finalize(str) {
return ('<?xml version="1.0"?><speak version="1.1"' +
' xmlns="http://www.w3.org/2001/10/synthesis"' +
` xml:lang="${engine_js_1.Engine.getInstance().locale}">` +
'<prosody rate="' +
engine_js_1.Engine.getInstance().getRate() +
'%">' +
this.separator +
str +
this.separator +
'</prosody></speak>');
}
pause(pause) {
return ('<break ' +
'time="' +
this.pauseValue(pause[EngineConst.personalityProps.PAUSE]) +
'ms"/>');
}
prosodyElement(attr, value) {
value = Math.floor(this.applyScaleFunction(value));
const valueStr = value < 0 ? value.toString() : '+' + value.toString();
return ('<prosody ' +
attr.toLowerCase() +
'="' +
valueStr +
(attr === EngineConst.personalityProps.VOLUME ? '>' : '%">'));
}
closeTag(_tag) {
return '</prosody>';
}
markup(descrs) {
SsmlRenderer.MARKS = {};
return super.markup(descrs);
}
merge(spans) {
const result = [];
let lastMark = '';
for (let i = 0; i < spans.length; i++) {
const span = spans[i];
if (this.isEmptySpan(span))
continue;
const kind = SsmlRenderer.MARK_KIND ? span.attributes['kind'] : '';
const id = engine_js_1.Engine.getInstance().automark
? span.attributes['id']
: engine_js_1.Engine.getInstance().mark
? span.attributes['extid']
: '';
if (id &&
id !== lastMark &&
!(SsmlRenderer.MARK_ONCE && SsmlRenderer.MARKS[id])) {
result.push(kind ? `<mark name="${id}" kind="${kind}"/>` : `<mark name="${id}"/>`);
lastMark = id;
SsmlRenderer.MARKS[id] = true;
}
if (engine_js_1.Engine.getInstance().character &&
span.speech.length === 1 &&
span.speech.match(/[a-zA-Z]/)) {
result.push('<say-as interpret-as="' +
SsmlRenderer.CHARACTER_ATTR +
'">' +
span.speech +
'</say-as>');
}
else {
result.push(span.speech);
}
}
return result.join(this.separator);
}
isEmptySpan(span) {
const sep = span.attributes['separator'];
return span.speech.match(/^\s*$/) && (!sep || sep.match(/^\s*$/));
}
}
exports.SsmlRenderer = SsmlRenderer;
SsmlRenderer.MARK_ONCE = false;
SsmlRenderer.MARK_KIND = true;
SsmlRenderer.CHARACTER_ATTR = 'character';
SsmlRenderer.MARKS = {};

View File

@@ -0,0 +1,8 @@
import { AbstractAudioRenderer } from './abstract_audio_renderer.js';
import { AuditoryDescription } from './auditory_description.js';
export declare class StringRenderer extends AbstractAudioRenderer {
markup(descrs: AuditoryDescription[]): string;
}
export declare class CountingRenderer extends StringRenderer {
finalize(str: string): string;
}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CountingRenderer = exports.StringRenderer = void 0;
const engine_js_1 = require("../common/engine.js");
const abstract_audio_renderer_js_1 = require("./abstract_audio_renderer.js");
const audio_util_js_1 = require("./audio_util.js");
class StringRenderer extends abstract_audio_renderer_js_1.AbstractAudioRenderer {
markup(descrs) {
let str = '';
const markup = (0, audio_util_js_1.personalityMarkup)(descrs);
const clean = markup.filter((x) => x.span);
if (!clean.length) {
return str;
}
const len = clean.length - 1;
for (let i = 0, descr; (descr = clean[i]); i++) {
if (descr.span) {
str += this.merge(descr.span);
}
if (i >= len) {
continue;
}
const join = descr.join;
str += typeof join === 'undefined' ? this.separator : join;
}
return str;
}
}
exports.StringRenderer = StringRenderer;
class CountingRenderer extends StringRenderer {
finalize(str) {
const output = super.finalize(str);
const count = engine_js_1.Engine.getInstance().modality === 'braille' ? '⣿⠀⣿⠀⣿⠀⣿⠀⣿⠀' : '0123456789';
let second = new Array(Math.trunc(output.length / 10) + 1).join(count);
second += count.slice(0, output.length % 10);
return output + '\n' + second;
}
}
exports.CountingRenderer = CountingRenderer;

View File

@@ -0,0 +1,7 @@
import * as EngineConst from '../common/engine_const.js';
import { AuditoryDescription } from './auditory_description.js';
import { MarkupRenderer } from './markup_renderer.js';
export declare abstract class XmlRenderer extends MarkupRenderer {
abstract closeTag(tag: EngineConst.personalityProps): void;
markup(descrs: AuditoryDescription[]): string;
}

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XmlRenderer = void 0;
const engine_js_1 = require("../common/engine.js");
const AudioUtil = require("./audio_util.js");
const markup_renderer_js_1 = require("./markup_renderer.js");
class XmlRenderer extends markup_renderer_js_1.MarkupRenderer {
markup(descrs) {
this.setScaleFunction(-2, 2, -100, 100, 2);
const markup = AudioUtil.personalityMarkup(descrs);
const result = [];
const currentOpen = [];
for (let i = 0, descr; (descr = markup[i]); i++) {
if (descr.span) {
result.push(this.merge(descr.span));
continue;
}
if (AudioUtil.isPauseElement(descr)) {
result.push(this.pause(descr));
continue;
}
if (descr.close.length) {
for (let j = 0; j < descr.close.length; j++) {
const last = currentOpen.pop();
if (descr.close.indexOf(last) === -1) {
throw new engine_js_1.SREError('Unknown closing markup element: ' + last);
}
result.push(this.closeTag(last));
}
}
if (descr.open.length) {
const open = AudioUtil.sortClose(descr.open.slice(), markup.slice(i + 1));
open.forEach((o) => {
result.push(this.prosodyElement(o, descr[o]));
currentOpen.push(o);
});
}
}
return result.join(' ');
}
}
exports.XmlRenderer = XmlRenderer;

View File

@@ -0,0 +1,3 @@
export declare function removeEmpty(strs: string[]): string[];
export declare function interleaveLists(list1: any[], list2: any[]): any[];
export declare function setdifference(a: any[], b: any[]): any[];

29
node_modules/speech-rule-engine/js/common/base_util.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeEmpty = removeEmpty;
exports.interleaveLists = interleaveLists;
exports.setdifference = setdifference;
function removeEmpty(strs) {
return strs.filter((str) => str);
}
function interleaveLists(list1, list2) {
const result = [];
while (list1.length || list2.length) {
if (list1.length) {
result.push(list1.shift());
}
if (list2.length) {
result.push(list2.shift());
}
}
return result;
}
function setdifference(a, b) {
if (!a) {
return [];
}
if (!b) {
return a;
}
return a.filter((x) => b.indexOf(x) < 0);
}

View File

@@ -0,0 +1,5 @@
export declare function detectIE(): boolean;
export declare function detectEdge(): boolean;
export declare const mapsForIE: {
[key: string]: any;
};

View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapsForIE = void 0;
exports.detectIE = detectIE;
exports.detectEdge = detectEdge;
const system_external_js_1 = require("./system_external.js");
const xpath_util_js_1 = require("./xpath_util.js");
function detectIE() {
const isIE = typeof window !== 'undefined' &&
'ActiveXObject' in window &&
'clipboardData' in window;
if (!isIE) {
return false;
}
loadMapsForIE();
loadWGXpath();
return true;
}
function detectEdge() {
var _a;
const isEdge = typeof window !== 'undefined' &&
'MSGestureEvent' in window &&
((_a = window.chrome) === null || _a === void 0 ? void 0 : _a.loadTimes) === null;
if (!isEdge) {
return false;
}
document.evaluate = null;
loadWGXpath(true);
return true;
}
exports.mapsForIE = null;
function loadWGXpath(opt_isEdge) {
loadScript(system_external_js_1.SystemExternal.WGXpath);
installWGXpath(opt_isEdge);
}
function installWGXpath(opt_isEdge, opt_count) {
let count = opt_count || 1;
if (typeof wgxpath === 'undefined' && count < 10) {
setTimeout(function () {
installWGXpath(opt_isEdge, count++);
}, 200);
return;
}
if (count >= 10) {
return;
}
system_external_js_1.SystemExternal.wgxpath = wgxpath;
opt_isEdge
? system_external_js_1.SystemExternal.wgxpath.install({ document: document })
: system_external_js_1.SystemExternal.wgxpath.install();
xpath_util_js_1.xpath.evaluate = document.evaluate;
xpath_util_js_1.xpath.result = XPathResult;
xpath_util_js_1.xpath.createNSResolver = document.createNSResolver;
}
function loadMapsForIE() {
loadScript(system_external_js_1.SystemExternal.mathmapsIePath);
}
function loadScript(src) {
const scr = system_external_js_1.SystemExternal.document.createElement('script');
scr.type = 'text/javascript';
scr.src = src;
system_external_js_1.SystemExternal.document.head
? system_external_js_1.SystemExternal.document.head.appendChild(scr)
: system_external_js_1.SystemExternal.document.body.appendChild(scr);
}

20
node_modules/speech-rule-engine/js/common/cli.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
export declare class Cli {
static process: any;
static commander: any;
setup: {
[key: string]: string | boolean;
};
processors: string[];
dp: DOMParser;
private output;
constructor();
set(arg: string, value: string | boolean, _def: string): void;
processor(processor: string): void;
private loadLocales;
enumerate(all?: boolean): Promise<void>;
execute(input: string): void;
readline(): void;
commandLine(): Promise<void>;
private runProcessors_;
private readExpression_;
}

249
node_modules/speech-rule-engine/js/common/cli.js generated vendored Normal file
View File

@@ -0,0 +1,249 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cli = void 0;
const dynamic_cstr_js_1 = require("../rule_engine/dynamic_cstr.js");
const MathCompoundStore = require("../rule_engine/math_compound_store.js");
const speech_rule_engine_js_1 = require("../rule_engine/speech_rule_engine.js");
const clearspeak_preferences_js_1 = require("../speech_rules/clearspeak_preferences.js");
const debugger_js_1 = require("./debugger.js");
const engine_js_1 = require("./engine.js");
const EngineConst = require("./engine_const.js");
const ProcessorFactory = require("./processor_factory.js");
const System = require("./system.js");
const system_external_js_1 = require("./system_external.js");
const variables_js_1 = require("./variables.js");
class Cli {
constructor() {
this.setup = {
mode: EngineConst.Mode.SYNC
};
this.processors = [];
this.output = Cli.process.stdout;
this.dp = new system_external_js_1.SystemExternal.xmldom.DOMParser({
onError: (_key, _msg) => {
throw new engine_js_1.SREError('XML DOM error!');
}
});
}
set(arg, value, _def) {
this.setup[arg] = typeof value === 'undefined' ? true : value;
}
processor(processor) {
this.processors.push(processor);
}
loadLocales() {
return __awaiter(this, void 0, void 0, function* () {
for (const loc of variables_js_1.Variables.LOCALES.keys()) {
yield System.setupEngine({ locale: loc });
}
});
}
enumerate() {
return __awaiter(this, arguments, void 0, function* (all = false) {
const promise = System.setupEngine(this.setup);
const order = dynamic_cstr_js_1.DynamicCstr.DEFAULT_ORDER.slice(0, -1);
return (all ? this.loadLocales() : promise).then(() => engine_js_1.EnginePromise.getall().then(() => {
const length = order.map((x) => x.length);
const maxLength = (obj, index) => {
length[index] = Math.max.apply(null, Object.keys(obj)
.map((x) => x.length)
.concat(length[index]));
};
const compStr = (str, length) => str + new Array(length - str.length + 1).join(' ');
let dynamic = speech_rule_engine_js_1.SpeechRuleEngine.getInstance().enumerate();
dynamic = MathCompoundStore.enumerate(dynamic);
const table = [];
maxLength(dynamic, 0);
for (const [ax1, dyna1] of Object.entries(dynamic)) {
let clear1 = true;
maxLength(dyna1, 1);
for (const [ax2, dyna2] of Object.entries(dyna1)) {
let clear2 = true;
maxLength(dyna2, 2);
for (const [ax3, dyna3] of Object.entries(dyna2)) {
const styles = Object.keys(dyna3).sort();
if (ax3 === 'clearspeak') {
let clear3 = true;
const prefs = clearspeak_preferences_js_1.ClearspeakPreferences.getLocalePreferences(dynamic)[ax1];
if (!prefs) {
continue;
}
for (const dyna4 of Object.values(prefs)) {
table.push([
compStr(clear1 ? ax1 : '', length[0]),
compStr(clear2 ? ax2 : '', length[1]),
compStr(clear3 ? ax3 : '', length[2]),
dyna4.join(', ')
]);
clear1 = false;
clear2 = false;
clear3 = false;
}
}
else {
table.push([
compStr(clear1 ? ax1 : '', length[0]),
compStr(clear2 ? ax2 : '', length[1]),
compStr(ax3, length[2]),
styles.join(', ')
]);
}
clear1 = false;
clear2 = false;
}
}
}
let i = 0;
const header = order.map((x) => compStr(x, length[i++]));
const markdown = Cli.commander.opts().pprint;
const separator = length.map((x) => new Array(x + 1).join(markdown ? '-' : '='));
if (!markdown) {
separator[i - 1] = separator[i - 1] + '========================';
}
table.unshift(separator);
table.unshift(header);
let output = table.map((x) => x.join(' | '));
if (markdown) {
output = output.map((x) => `| ${x} |`);
output.unshift(`# Options SRE v${System.version}\n`);
}
console.info(output.join('\n'));
}));
});
}
execute(input) {
engine_js_1.EnginePromise.getall().then(() => {
this.runProcessors_((proc, file) => this.output.write(System.processFile(proc, file) + '\n'), input);
});
}
readline() {
Cli.process.stdin.setEncoding('utf8');
const inter = system_external_js_1.SystemExternal.extRequire('readline').createInterface({
input: Cli.process.stdin,
output: this.output
});
let input = '';
inter.on('line', ((expr) => {
input += expr;
if (this.readExpression_(input)) {
inter.close();
}
}).bind(this));
inter.on('close', (() => {
this.runProcessors_((proc, expr) => {
inter.output.write(ProcessorFactory.output(proc, expr) + '\n');
}, input);
System.engineReady().then(() => debugger_js_1.Debugger.getInstance().exit(() => System.exit(0)));
}).bind(this));
}
commandLine() {
return __awaiter(this, void 0, void 0, function* () {
const commander = Cli.commander;
const system = System;
const set = ((key) => {
return (val, def) => this.set(key, val, def);
}).bind(this);
const processor = this.processor.bind(this);
commander
.version(system.version)
.usage('[options] <file ...>')
.option('-i, --input [name]', 'Input file [name]. (Deprecated)')
.option('-o, --output [name]', 'Output file [name]. Defaults to stdout.')
.option('-d, --domain [name]', 'Speech rule set [name]. See --options' + ' for details.', set(dynamic_cstr_js_1.Axis.DOMAIN), dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_1.Axis.DOMAIN])
.option('-s, --style [name]', 'Speech style [name]. See --options' + ' for details.', set(dynamic_cstr_js_1.Axis.STYLE), dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_1.Axis.STYLE])
.option('-c, --locale [code]', 'Locale [code].', set(dynamic_cstr_js_1.Axis.LOCALE), dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_1.Axis.LOCALE])
.option('-b, --modality [name]', 'Modality [name].', set(dynamic_cstr_js_1.Axis.MODALITY), dynamic_cstr_js_1.DynamicCstr.DEFAULT_VALUES[dynamic_cstr_js_1.Axis.MODALITY])
.option('-k, --markup [name]', 'Generate speech output with markup tags.', set('markup'), 'none')
.option('-e, --automark', 'Automatically set marks for external reference.', set('automark'))
.option('-L, --linebreaks', 'Linebreak marking in 2D output.', set('linebreaks'))
.option('-r, --rate [value]', 'Base rate [value] for tagged speech' + ' output.', set('rate'), '100')
.option('-p, --speech', 'Generate speech output (default).', () => processor('speech'))
.option('-a, --audit', 'Generate auditory descriptions (JSON format).', () => processor('description'))
.option('-j, --json', 'Generate JSON of semantic tree.', () => processor('json'))
.option('-x, --xml', 'Generate XML of semantic tree.', () => processor('semantic'))
.option('-m, --mathml', 'Generate enriched MathML.', () => processor('enriched'))
.option('-u, --rebuild', 'Rebuild semantic tree from enriched MathML.', () => processor('rebuild'))
.option('-t, --latex', 'Accepts LaTeX input for certain locale/modality combinations.', () => processor('latex'))
.option('-g, --generate <depth>', 'Include generated speech in enriched' +
' MathML (with -m option only).', set('speech'), 'none')
.option('-w, --structure', 'Include structure attribute in enriched' +
' MathML (with -m option only).', set('structure'))
.option('-A, --aria', 'Include aria tree annotations' +
' MathML (with -m and -w option only).', set('aria'))
.option('-P, --pprint', 'Pretty print output whenever possible.', set('pprint'))
.option('-f, --rules [name]', 'Loads a local rule file [name].', set('rules'))
.option('-C, --subiso [name]', 'Supplementary country code (or similar) for the given locale.', set('subiso'))
.option('-N, --number', 'Translate number to word.', () => processor('number'))
.option('-O, --ordinal', 'Translate number to ordinal.', () => processor('ordinal'), 'ordinal')
.option('-S, --numeric', 'Translate number to numeric ordinal.', () => processor('numericOrdinal'))
.option('-F, --vulgar', 'Translate vulgar fraction to word. Provide vulgar fraction as slash seperated numbers.', () => processor('vulgar'))
.option('-v, --verbose', 'Verbose mode.')
.option('-l, --log [name]', 'Log file [name].')
.option('--opt', 'List engine setup options. Output as markdown with -P option.')
.option('--opt-all', 'List engine setup options for all available locales. Output as markdown with -P option.')
.on('option:opt', () => {
this.enumerate().then(() => System.exit(0));
})
.on('option:opt-all', () => {
this.enumerate(true).then(() => System.exit(0));
})
.parse(Cli.process.argv);
yield System.engineReady().then(() => System.setupEngine(this.setup));
const options = Cli.commander.opts();
if (options.output) {
this.output = system_external_js_1.SystemExternal.fs.createWriteStream(options.output);
}
if (options.verbose) {
yield debugger_js_1.Debugger.getInstance().init(options.log);
}
if (options.input) {
this.execute(options.input);
}
if (Cli.commander.args.length) {
Cli.commander.args.forEach(this.execute.bind(this));
System.engineReady().then(() => debugger_js_1.Debugger.getInstance().exit(() => System.exit(0)));
}
else {
this.readline();
}
});
}
runProcessors_(processor, input) {
try {
if (!this.processors.length) {
this.processors.push('speech');
}
if (input) {
this.processors.forEach((proc) => processor(proc, input));
}
}
catch (err) {
console.error(err.name + ': ' + err.message);
debugger_js_1.Debugger.getInstance().exit(() => Cli.process.exit(1));
}
}
readExpression_(input) {
try {
const testInput = input.replace(/(&|#|;)/g, '');
this.dp.parseFromString(testInput, 'text/xml');
}
catch (_err) {
return false;
}
return true;
}
}
exports.Cli = Cli;
Cli.process = system_external_js_1.SystemExternal.extRequire('process');
Cli.commander = system_external_js_1.SystemExternal.documentSupported
? null
: system_external_js_1.SystemExternal.extRequire('commander').program;

View File

@@ -0,0 +1,15 @@
export declare class Debugger {
private static instance;
private isActive_;
private outputFunction_;
private fileHandle;
private stream_;
static getInstance(): Debugger;
init(opt_file?: string): any;
output(...args: any[]): void;
generateOutput(func: () => string[]): void;
exit(callback?: () => any): void;
private constructor();
private startDebugFile_;
private output_;
}

65
node_modules/speech-rule-engine/js/common/debugger.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Debugger = void 0;
const system_external_js_1 = require("./system_external.js");
class Debugger {
static getInstance() {
Debugger.instance = Debugger.instance || new Debugger();
return Debugger.instance;
}
init(opt_file) {
if (opt_file) {
this.startDebugFile_(opt_file);
}
this.isActive_ = true;
return this.fileHandle;
}
output(...args) {
if (this.isActive_) {
this.output_(args);
}
}
generateOutput(func) {
if (this.isActive_) {
this.output_(func.apply(func, []));
}
}
exit(callback = () => { }) {
this.fileHandle.then(() => {
if (this.isActive_ && this.stream_) {
this.stream_.end('', '', callback);
}
});
}
constructor() {
this.isActive_ = false;
this.outputFunction_ = console.info;
this.fileHandle = Promise.resolve();
this.stream_ = null;
}
startDebugFile_(filename) {
this.fileHandle = system_external_js_1.SystemExternal.fs.promises.open(filename, 'w');
this.fileHandle = this.fileHandle.then((handle) => {
this.stream_ = handle.createWriteStream(filename);
this.outputFunction_ = function (...args) {
this.stream_.write(args.join(' '));
this.stream_.write('\n');
}.bind(this);
this.stream_.on('error', function (_error) {
console.info('Invalid log file. Debug information sent to console.');
this.outputFunction_ = console.info;
}.bind(this));
this.stream_.on('finish', function () {
console.info('Finalizing debug file.');
});
});
}
output_(outputList) {
if (console.info === this.outputFunction_) {
this.outputFunction_.apply(console, ['Speech Rule Engine Debugger:'].concat(outputList));
return;
}
this.fileHandle.then(() => this.outputFunction_.apply(this.outputFunction_, ['Speech Rule Engine Debugger:'].concat(outputList)));
}
}
exports.Debugger = Debugger;

View File

@@ -0,0 +1,27 @@
export declare function toArray(nodeList: NodeList | NamedNodeMap): any[];
export declare function parseInput(input: string): Element;
export declare enum NodeType {
ELEMENT_NODE = 1,
ATTRIBUTE_NODE = 2,
TEXT_NODE = 3,
CDATA_SECTION_NODE = 4,
ENTITY_REFERENCE_NODE = 5,
ENTITY_NODE = 6,
PROCESSING_INSTRUCTION_NODE = 7,
COMMENT_NODE = 8,
DOCUMENT_NODE = 9,
DOCUMENT_TYPE_NODE = 10,
DOCUMENT_FRAGMENT_NODE = 11,
NOTATION_NODE = 12
}
export declare function replaceNode(oldNode: Node, newNode: Node): void;
export declare function createElement(tag: string): Element;
export declare function createElementNS(url: string, tag: string): Element;
export declare function createTextNode(content: string): Text;
export declare function formatXml(xml: string): string;
export declare function querySelectorAllByAttr(node: Element, attr: string): Element[];
export declare function querySelectorAllByAttrValue(node: Element, attr: string, value: string): Element[];
export declare function querySelectorAll(node: Element, tag: string): Element[];
export declare function tagName(node: Element): string;
export declare function cloneNode(node: Element): Element;
export declare function serializeXml(node: Element): string;

172
node_modules/speech-rule-engine/js/common/dom_util.js generated vendored Normal file
View File

@@ -0,0 +1,172 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeType = void 0;
exports.toArray = toArray;
exports.parseInput = parseInput;
exports.replaceNode = replaceNode;
exports.createElement = createElement;
exports.createElementNS = createElementNS;
exports.createTextNode = createTextNode;
exports.formatXml = formatXml;
exports.querySelectorAllByAttr = querySelectorAllByAttr;
exports.querySelectorAllByAttrValue = querySelectorAllByAttrValue;
exports.querySelectorAll = querySelectorAll;
exports.tagName = tagName;
exports.cloneNode = cloneNode;
exports.serializeXml = serializeXml;
const engine_js_1 = require("./engine.js");
const EngineConst = require("../common/engine_const.js");
const system_external_js_1 = require("./system_external.js");
const XpathUtil = require("./xpath_util.js");
function toArray(nodeList) {
const nodeArray = [];
for (let i = 0, m = nodeList.length; i < m; i++) {
nodeArray.push(nodeList[i]);
}
return nodeArray;
}
function trimInput(input) {
input = input.replace(/&nbsp;/g, ' ');
return input.replace(/>[ \f\n\r\t\v\u200b]+</g, '><').trim();
}
function parseInput(input) {
const dp = new system_external_js_1.SystemExternal.xmldom.DOMParser();
const clean_input = trimInput(input);
const allValues = clean_input.match(/&(?!lt|gt|amp|quot|apos)\w+;/g);
const html = !!allValues;
if (!clean_input) {
throw new Error('Empty input!');
}
try {
const doc = dp.parseFromString(clean_input, html ? 'text/html' : 'text/xml');
if (engine_js_1.Engine.getInstance().mode === EngineConst.Mode.HTTP) {
XpathUtil.xpath.currentDocument = doc;
return html ? doc.body.childNodes[0] : doc.documentElement;
}
return doc.documentElement;
}
catch (err) {
throw new engine_js_1.SREError('Illegal input: ' + err.message);
}
}
var NodeType;
(function (NodeType) {
NodeType[NodeType["ELEMENT_NODE"] = 1] = "ELEMENT_NODE";
NodeType[NodeType["ATTRIBUTE_NODE"] = 2] = "ATTRIBUTE_NODE";
NodeType[NodeType["TEXT_NODE"] = 3] = "TEXT_NODE";
NodeType[NodeType["CDATA_SECTION_NODE"] = 4] = "CDATA_SECTION_NODE";
NodeType[NodeType["ENTITY_REFERENCE_NODE"] = 5] = "ENTITY_REFERENCE_NODE";
NodeType[NodeType["ENTITY_NODE"] = 6] = "ENTITY_NODE";
NodeType[NodeType["PROCESSING_INSTRUCTION_NODE"] = 7] = "PROCESSING_INSTRUCTION_NODE";
NodeType[NodeType["COMMENT_NODE"] = 8] = "COMMENT_NODE";
NodeType[NodeType["DOCUMENT_NODE"] = 9] = "DOCUMENT_NODE";
NodeType[NodeType["DOCUMENT_TYPE_NODE"] = 10] = "DOCUMENT_TYPE_NODE";
NodeType[NodeType["DOCUMENT_FRAGMENT_NODE"] = 11] = "DOCUMENT_FRAGMENT_NODE";
NodeType[NodeType["NOTATION_NODE"] = 12] = "NOTATION_NODE";
})(NodeType || (exports.NodeType = NodeType = {}));
function replaceNode(oldNode, newNode) {
if (!oldNode.parentNode) {
return;
}
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);
}
function createElement(tag) {
return system_external_js_1.SystemExternal.document.createElement(tag);
}
function createElementNS(url, tag) {
return system_external_js_1.SystemExternal.document.createElementNS(url, tag);
}
function createTextNode(content) {
return system_external_js_1.SystemExternal.document.createTextNode(content);
}
function formatXml(xml) {
let formatted = '';
let reg = /(>)(<)(\/*)/g;
xml = xml.replace(reg, '$1\r\n$2$3');
let pad = 0;
let split = xml.split('\r\n');
reg = /(\.)*(<)(\/*)/g;
split = split
.map((x) => x.replace(reg, '$1\r\n$2$3').split('\r\n'))
.reduce((x, y) => x.concat(y), []);
while (split.length) {
let node = split.shift();
if (!node) {
continue;
}
let indent = 0;
if (node.match(/^<\w[^>/]*>[^>]+$/)) {
const match = matchingStartEnd(node, split[0]);
if (match[0]) {
if (match[1]) {
node = node + split.shift().slice(0, -match[1].length);
if (match[1].trim()) {
split.unshift(match[1]);
}
}
else {
node = node + split.shift();
}
}
else {
indent = 1;
}
}
else if (node.match(/^<\/\w/)) {
if (pad !== 0) {
pad -= 1;
}
}
else if (node.match(/^<\w[^>]*[^/]>.*$/)) {
indent = 1;
}
else if (node.match(/^<\w[^>]*\/>.+$/)) {
const position = node.indexOf('>') + 1;
const rest = node.slice(position);
if (rest.trim()) {
split.unshift();
}
node = node.slice(0, position) + rest;
}
else {
indent = 0;
}
formatted += new Array(pad + 1).join(' ') + node + '\r\n';
pad += indent;
}
return formatted;
}
function matchingStartEnd(start, end) {
if (!end) {
return [false, ''];
}
const tag1 = start.match(/^<([^> ]+).*>/);
const tag2 = end.match(/^<\/([^>]+)>(.*)/);
return tag1 && tag2 && tag1[1] === tag2[1] ? [true, tag2[2]] : [false, ''];
}
function querySelectorAllByAttr(node, attr) {
return node.querySelectorAll
? toArray(node.querySelectorAll(`[${attr}]`))
: XpathUtil.evalXPath(`.//*[@${attr}]`, node);
}
function querySelectorAllByAttrValue(node, attr, value) {
return node.querySelectorAll
? toArray(node.querySelectorAll(`[${attr}="${value}"]`))
: XpathUtil.evalXPath(`.//*[@${attr}="${value}"]`, node);
}
function querySelectorAll(node, tag) {
return node.querySelectorAll
? toArray(node.querySelectorAll(tag))
: XpathUtil.evalXPath(`.//${tag}`, node);
}
function tagName(node) {
return node.tagName.toUpperCase();
}
function cloneNode(node) {
return node.cloneNode(true);
}
function serializeXml(node) {
const xmls = new system_external_js_1.SystemExternal.xmldom.XMLSerializer();
return xmls.serializeToString(node);
}

78
node_modules/speech-rule-engine/js/common/engine.d.ts generated vendored Normal file
View File

@@ -0,0 +1,78 @@
import { AuditoryDescription } from '../audio/auditory_description.js';
import * as Dcstr from '../rule_engine/dynamic_cstr.js';
import * as EngineConst from './engine_const.js';
export declare class SREError extends Error {
message: string;
name: string;
constructor(message?: string);
}
export declare class Engine {
static BINARY_FEATURES: string[];
static STRING_FEATURES: string[];
private static instance;
customLoader: (locale: string) => Promise<string>;
evaluator: (p1: string, p2: Dcstr.DynamicCstr) => string | null;
defaultParser: Dcstr.DynamicCstrParser;
parser: Dcstr.DynamicCstrParser;
parsers: {
[key: string]: Dcstr.DynamicCstrParser;
};
dynamicCstr: Dcstr.DynamicCstr;
comparator: Dcstr.Comparator;
mode: EngineConst.Mode;
init: boolean;
delay: boolean;
comparators: {
[key: string]: () => Dcstr.Comparator;
};
domain: string;
style: string;
_defaultLocale: string;
set defaultLocale(loc: string);
get defaultLocale(): string;
locale: string;
subiso: string;
modality: string;
speech: EngineConst.Speech;
markup: EngineConst.Markup;
mark: boolean;
automark: boolean;
character: boolean;
cleanpause: boolean;
cayleyshort: boolean;
linebreaks: boolean;
rate: string;
walker: string;
structure: boolean;
aria: boolean;
ruleSets: string[];
strict: boolean;
isIE: boolean;
isEdge: boolean;
pprint: boolean;
config: boolean;
rules: string;
prune: string;
static getInstance(): Engine;
static defaultEvaluator(str: string, _cstr: Dcstr.DynamicCstr): string;
static nodeEvaluator: (node: Element) => AuditoryDescription[];
static evaluateNode(node: Element): AuditoryDescription[];
getRate(): number;
setDynamicCstr(opt_dynamic?: Dcstr.AxisMap): void;
private constructor();
configurate(feature: {
[key: string]: boolean | string;
}): void;
setCustomLoader(fn: any): void;
}
export default Engine;
export declare class EnginePromise {
static loaded: {
[locale: string]: [boolean, boolean];
};
static promises: {
[locale: string]: Promise<string>;
};
static get(locale?: string): Promise<string>;
static getall(): Promise<string[]>;
}

181
node_modules/speech-rule-engine/js/common/engine.js generated vendored Normal file
View File

@@ -0,0 +1,181 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnginePromise = exports.Engine = exports.SREError = void 0;
const Dcstr = require("../rule_engine/dynamic_cstr.js");
const EngineConst = require("./engine_const.js");
const debugger_js_1 = require("./debugger.js");
const variables_js_1 = require("./variables.js");
class SREError extends Error {
constructor(message = '') {
super();
this.message = message;
this.name = 'SRE Error';
}
}
exports.SREError = SREError;
class Engine {
set defaultLocale(loc) {
this._defaultLocale = variables_js_1.Variables.ensureLocale(loc, this._defaultLocale);
}
get defaultLocale() {
return this._defaultLocale;
}
static getInstance() {
Engine.instance = Engine.instance || new Engine();
return Engine.instance;
}
static defaultEvaluator(str, _cstr) {
return str;
}
static evaluateNode(node) {
return Engine.nodeEvaluator(node);
}
getRate() {
const numeric = parseInt(this.rate, 10);
return isNaN(numeric) ? 100 : numeric;
}
setDynamicCstr(opt_dynamic) {
if (this.defaultLocale) {
Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.LOCALE] = this.defaultLocale;
}
if (opt_dynamic) {
const keys = Object.keys(opt_dynamic);
for (let i = 0; i < keys.length; i++) {
const feature = keys[i];
if (Dcstr.DynamicCstr.DEFAULT_ORDER.indexOf(feature) !== -1) {
const value = opt_dynamic[feature];
this[feature] = value;
}
}
}
EngineConst.DOMAIN_TO_STYLES[this.domain] = this.style;
const dynamic = [this.locale, this.modality, this.domain, this.style].join('.');
const fallback = Dcstr.DynamicProperties.createProp([Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.LOCALE]], [Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.MODALITY]], [Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.DOMAIN]], [Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.STYLE]]);
const comparator = this.comparators[this.domain];
const parser = this.parsers[this.domain];
this.parser = parser ? parser : this.defaultParser;
this.dynamicCstr = this.parser.parse(dynamic);
this.dynamicCstr.updateProperties(fallback.getProperties());
this.comparator = comparator
? comparator()
: new Dcstr.DefaultComparator(this.dynamicCstr);
}
constructor() {
this.customLoader = null;
this.parsers = {};
this.comparator = null;
this.mode = EngineConst.Mode.SYNC;
this.init = true;
this.delay = false;
this.comparators = {};
this.domain = 'mathspeak';
this.style = Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.STYLE];
this._defaultLocale = Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.LOCALE];
this.locale = Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.LOCALE];
this.subiso = '';
this.modality = Dcstr.DynamicCstr.DEFAULT_VALUES[Dcstr.Axis.MODALITY];
this.speech = EngineConst.Speech.NONE;
this.markup = EngineConst.Markup.NONE;
this.mark = true;
this.automark = false;
this.character = true;
this.cleanpause = true;
this.cayleyshort = true;
this.linebreaks = false;
this.rate = '100';
this.walker = 'Table';
this.structure = false;
this.aria = false;
this.ruleSets = [];
this.strict = false;
this.isIE = false;
this.isEdge = false;
this.pprint = false;
this.config = false;
this.rules = '';
this.prune = '';
this.locale = this.defaultLocale;
this.evaluator = Engine.defaultEvaluator;
this.defaultParser = new Dcstr.DynamicCstrParser(Dcstr.DynamicCstr.DEFAULT_ORDER);
this.parser = this.defaultParser;
this.dynamicCstr = Dcstr.DynamicCstr.defaultCstr();
}
configurate(feature) {
if (this.mode === EngineConst.Mode.HTTP && !this.config) {
configBlocks(feature);
this.config = true;
}
configFeature(feature);
}
setCustomLoader(fn) {
if (fn) {
this.customLoader = fn;
}
}
}
exports.Engine = Engine;
Engine.BINARY_FEATURES = [
'automark',
'mark',
'character',
'cleanpause',
'strict',
'structure',
'aria',
'pprint',
'cayleyshort',
'linebreaks'
];
Engine.STRING_FEATURES = [
'markup',
'style',
'domain',
'speech',
'walker',
'defaultLocale',
'locale',
'delay',
'modality',
'rate',
'rules',
'subiso',
'prune'
];
Engine.nodeEvaluator = function (_node) {
return [];
};
exports.default = Engine;
function configFeature(feature) {
if (typeof SREfeature !== 'undefined') {
for (const [name, feat] of Object.entries(SREfeature)) {
feature[name] = feat;
}
}
}
function configBlocks(feature) {
const scripts = document.documentElement.querySelectorAll('script[type="text/x-sre-config"]');
for (let i = 0, m = scripts.length; i < m; i++) {
let inner;
try {
inner = scripts[i].innerHTML;
const config = JSON.parse(inner);
for (const [key, val] of Object.entries(config)) {
feature[key] = val;
}
}
catch (_err) {
debugger_js_1.Debugger.getInstance().output('Illegal configuration ', inner);
}
}
}
class EnginePromise {
static get(locale = Engine.getInstance().locale) {
return EnginePromise.promises[locale] || Promise.resolve('');
}
static getall() {
return Promise.all(Object.values(EnginePromise.promises));
}
}
exports.EnginePromise = EnginePromise;
EnginePromise.loaded = {};
EnginePromise.promises = {};

View File

@@ -0,0 +1,32 @@
export declare enum Mode {
SYNC = "sync",
ASYNC = "async",
HTTP = "http"
}
export declare enum personalityProps {
PITCH = "pitch",
RATE = "rate",
VOLUME = "volume",
PAUSE = "pause",
JOIN = "join",
LAYOUT = "layout"
}
export declare const personalityPropList: personalityProps[];
export declare enum Speech {
NONE = "none",
SHALLOW = "shallow",
DEEP = "deep"
}
export declare enum Markup {
NONE = "none",
LAYOUT = "layout",
COUNTING = "counting",
PUNCTUATION = "punctuation",
SSML = "ssml",
ACSS = "acss",
SABLE = "sable",
VOICEXML = "voicexml"
}
export declare const DOMAIN_TO_STYLES: {
[key: string]: string;
};

View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DOMAIN_TO_STYLES = exports.Markup = exports.Speech = exports.personalityPropList = exports.personalityProps = exports.Mode = void 0;
var Mode;
(function (Mode) {
Mode["SYNC"] = "sync";
Mode["ASYNC"] = "async";
Mode["HTTP"] = "http";
})(Mode || (exports.Mode = Mode = {}));
var personalityProps;
(function (personalityProps) {
personalityProps["PITCH"] = "pitch";
personalityProps["RATE"] = "rate";
personalityProps["VOLUME"] = "volume";
personalityProps["PAUSE"] = "pause";
personalityProps["JOIN"] = "join";
personalityProps["LAYOUT"] = "layout";
})(personalityProps || (exports.personalityProps = personalityProps = {}));
exports.personalityPropList = [
personalityProps.PITCH,
personalityProps.RATE,
personalityProps.VOLUME,
personalityProps.PAUSE,
personalityProps.JOIN
];
var Speech;
(function (Speech) {
Speech["NONE"] = "none";
Speech["SHALLOW"] = "shallow";
Speech["DEEP"] = "deep";
})(Speech || (exports.Speech = Speech = {}));
var Markup;
(function (Markup) {
Markup["NONE"] = "none";
Markup["LAYOUT"] = "layout";
Markup["COUNTING"] = "counting";
Markup["PUNCTUATION"] = "punctuation";
Markup["SSML"] = "ssml";
Markup["ACSS"] = "acss";
Markup["SABLE"] = "sable";
Markup["VOICEXML"] = "voicexml";
})(Markup || (exports.Markup = Markup = {}));
exports.DOMAIN_TO_STYLES = {
mathspeak: 'default',
clearspeak: 'default'
};

View File

@@ -0,0 +1,3 @@
export declare function setup(feature: {
[key: string]: boolean | string;
}): Promise<string>;

View File

@@ -0,0 +1,108 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setup = setup;
const L10n = require("../l10n/l10n.js");
const MathMap = require("../speech_rules/math_map.js");
const BrowserUtil = require("./browser_util.js");
const debugger_js_1 = require("./debugger.js");
const engine_js_1 = require("./engine.js");
const FileUtil = require("./file_util.js");
const system_external_js_1 = require("./system_external.js");
const MATHSPEAK_ONLY = ['ca', 'da', 'es'];
const EN_RULES = [
'chromevox',
'clearspeak',
'mathspeak',
'emacspeak',
'html'
];
function ensureDomain(feature) {
if ((feature.modality && feature.modality !== 'speech') ||
(!feature.modality && engine_js_1.Engine.getInstance().modality !== 'speech')) {
return;
}
if (!feature.domain) {
return;
}
if (feature.domain === 'default') {
feature.domain = 'mathspeak';
return;
}
const locale = (feature.locale || engine_js_1.Engine.getInstance().locale);
const domain = feature.domain;
if (MATHSPEAK_ONLY.indexOf(locale) !== -1) {
if (domain !== 'mathspeak') {
feature.domain = 'mathspeak';
}
return;
}
if (locale === 'en') {
if (EN_RULES.indexOf(domain) === -1) {
feature.domain = 'mathspeak';
}
return;
}
if (domain !== 'mathspeak' && domain !== 'clearspeak') {
feature.domain = 'mathspeak';
}
}
function setup(feature) {
return __awaiter(this, void 0, void 0, function* () {
ensureDomain(feature);
const engine = engine_js_1.Engine.getInstance();
const setIf = (feat) => {
if (typeof feature[feat] !== 'undefined') {
engine[feat] = !!feature[feat];
}
};
const setMulti = (feat) => {
if (typeof feature[feat] !== 'undefined') {
engine[feat] = feature[feat];
}
};
setMulti('mode');
engine.configurate(feature);
engine_js_1.Engine.BINARY_FEATURES.forEach(setIf);
engine_js_1.Engine.STRING_FEATURES.forEach(setMulti);
if (feature.debug) {
debugger_js_1.Debugger.getInstance().init();
}
if (feature.json) {
system_external_js_1.SystemExternal.jsonPath = FileUtil.makePath(feature.json);
}
if (feature.xpath) {
system_external_js_1.SystemExternal.WGXpath = feature.xpath;
}
engine.setCustomLoader(feature.custom);
setupBrowsers(engine);
L10n.setLocale();
engine.setDynamicCstr();
if (engine.init) {
engine_js_1.EnginePromise.promises['init'] = new Promise((res, _rej) => {
setTimeout(() => {
res('init');
}, 10);
});
engine.init = false;
return engine_js_1.EnginePromise.get();
}
if (engine.delay) {
engine.delay = false;
return engine_js_1.EnginePromise.get();
}
return MathMap.loadLocale();
});
}
function setupBrowsers(engine) {
engine.isIE = BrowserUtil.detectIE();
engine.isEdge = BrowserUtil.detectEdge();
}

View File

@@ -0,0 +1,80 @@
export declare enum KeyCode {
ENTER = 13,
ESC = 27,
SPACE = 32,
PAGE_UP = 33,
PAGE_DOWN = 34,
END = 35,
HOME = 36,
LEFT = 37,
UP = 38,
RIGHT = 39,
DOWN = 40,
TAB = 9,
LESS = 188,
GREATER = 190,
DASH = 189,
ZERO = 48,
ONE = 49,
TWO = 50,
THREE = 51,
FOUR = 52,
FIVE = 53,
SIX = 54,
SEVEN = 55,
EIGHT = 56,
NINE = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90
}
export declare const Move: Map<number, string>;
declare enum EventType {
CLICK = "click",
DBLCLICK = "dblclick",
MOUSEDOWN = "mousedown",
MOUSEUP = "mouseup",
MOUSEOVER = "mouseover",
MOUSEOUT = "mouseout",
MOUSEMOVE = "mousemove",
SELECTSTART = "selectstart",
KEYPRESS = "keypress",
KEYDOWN = "keydown",
KEYUP = "keyup",
TOUCHSTART = "touchstart",
TOUCHMOVE = "touchmove",
TOUCHEND = "touchend",
TOUCHCANCEL = "touchcancel"
}
export declare class Event {
src: Node;
type: EventType;
callback: EventListener;
constructor(src: Node, type: EventType, callback: EventListener);
add(): void;
remove(): void;
}
export {};

142
node_modules/speech-rule-engine/js/common/event_util.js generated vendored Normal file
View File

@@ -0,0 +1,142 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Event = exports.Move = exports.KeyCode = void 0;
var KeyCode;
(function (KeyCode) {
KeyCode[KeyCode["ENTER"] = 13] = "ENTER";
KeyCode[KeyCode["ESC"] = 27] = "ESC";
KeyCode[KeyCode["SPACE"] = 32] = "SPACE";
KeyCode[KeyCode["PAGE_UP"] = 33] = "PAGE_UP";
KeyCode[KeyCode["PAGE_DOWN"] = 34] = "PAGE_DOWN";
KeyCode[KeyCode["END"] = 35] = "END";
KeyCode[KeyCode["HOME"] = 36] = "HOME";
KeyCode[KeyCode["LEFT"] = 37] = "LEFT";
KeyCode[KeyCode["UP"] = 38] = "UP";
KeyCode[KeyCode["RIGHT"] = 39] = "RIGHT";
KeyCode[KeyCode["DOWN"] = 40] = "DOWN";
KeyCode[KeyCode["TAB"] = 9] = "TAB";
KeyCode[KeyCode["LESS"] = 188] = "LESS";
KeyCode[KeyCode["GREATER"] = 190] = "GREATER";
KeyCode[KeyCode["DASH"] = 189] = "DASH";
KeyCode[KeyCode["ZERO"] = 48] = "ZERO";
KeyCode[KeyCode["ONE"] = 49] = "ONE";
KeyCode[KeyCode["TWO"] = 50] = "TWO";
KeyCode[KeyCode["THREE"] = 51] = "THREE";
KeyCode[KeyCode["FOUR"] = 52] = "FOUR";
KeyCode[KeyCode["FIVE"] = 53] = "FIVE";
KeyCode[KeyCode["SIX"] = 54] = "SIX";
KeyCode[KeyCode["SEVEN"] = 55] = "SEVEN";
KeyCode[KeyCode["EIGHT"] = 56] = "EIGHT";
KeyCode[KeyCode["NINE"] = 57] = "NINE";
KeyCode[KeyCode["A"] = 65] = "A";
KeyCode[KeyCode["B"] = 66] = "B";
KeyCode[KeyCode["C"] = 67] = "C";
KeyCode[KeyCode["D"] = 68] = "D";
KeyCode[KeyCode["E"] = 69] = "E";
KeyCode[KeyCode["F"] = 70] = "F";
KeyCode[KeyCode["G"] = 71] = "G";
KeyCode[KeyCode["H"] = 72] = "H";
KeyCode[KeyCode["I"] = 73] = "I";
KeyCode[KeyCode["J"] = 74] = "J";
KeyCode[KeyCode["K"] = 75] = "K";
KeyCode[KeyCode["L"] = 76] = "L";
KeyCode[KeyCode["M"] = 77] = "M";
KeyCode[KeyCode["N"] = 78] = "N";
KeyCode[KeyCode["O"] = 79] = "O";
KeyCode[KeyCode["P"] = 80] = "P";
KeyCode[KeyCode["Q"] = 81] = "Q";
KeyCode[KeyCode["R"] = 82] = "R";
KeyCode[KeyCode["S"] = 83] = "S";
KeyCode[KeyCode["T"] = 84] = "T";
KeyCode[KeyCode["U"] = 85] = "U";
KeyCode[KeyCode["V"] = 86] = "V";
KeyCode[KeyCode["W"] = 87] = "W";
KeyCode[KeyCode["X"] = 88] = "X";
KeyCode[KeyCode["Y"] = 89] = "Y";
KeyCode[KeyCode["Z"] = 90] = "Z";
})(KeyCode || (exports.KeyCode = KeyCode = {}));
exports.Move = new Map([
[13, 'ENTER'],
[27, 'ESC'],
[32, 'SPACE'],
[33, 'PAGE_UP'],
[34, 'PAGE_DOWN'],
[35, 'END'],
[36, 'HOME'],
[37, 'LEFT'],
[38, 'UP'],
[39, 'RIGHT'],
[40, 'DOWN'],
[9, 'TAB'],
[188, 'LESS'],
[190, 'GREATER'],
[189, 'DASH'],
[48, 'ZERO'],
[49, 'ONE'],
[50, 'TWO'],
[51, 'THREE'],
[52, 'FOUR'],
[53, 'FIVE'],
[54, 'SIX'],
[55, 'SEVEN'],
[56, 'EIGHT'],
[57, 'NINE'],
[65, 'A'],
[66, 'B'],
[67, 'C'],
[68, 'D'],
[69, 'E'],
[70, 'F'],
[71, 'G'],
[72, 'H'],
[73, 'I'],
[74, 'J'],
[75, 'K'],
[76, 'L'],
[77, 'M'],
[78, 'N'],
[79, 'O'],
[80, 'P'],
[81, 'Q'],
[82, 'R'],
[83, 'S'],
[84, 'T'],
[85, 'U'],
[86, 'V'],
[87, 'W'],
[88, 'X'],
[89, 'Y'],
[90, 'Z']
]);
var EventType;
(function (EventType) {
EventType["CLICK"] = "click";
EventType["DBLCLICK"] = "dblclick";
EventType["MOUSEDOWN"] = "mousedown";
EventType["MOUSEUP"] = "mouseup";
EventType["MOUSEOVER"] = "mouseover";
EventType["MOUSEOUT"] = "mouseout";
EventType["MOUSEMOVE"] = "mousemove";
EventType["SELECTSTART"] = "selectstart";
EventType["KEYPRESS"] = "keypress";
EventType["KEYDOWN"] = "keydown";
EventType["KEYUP"] = "keyup";
EventType["TOUCHSTART"] = "touchstart";
EventType["TOUCHMOVE"] = "touchmove";
EventType["TOUCHEND"] = "touchend";
EventType["TOUCHCANCEL"] = "touchcancel";
})(EventType || (EventType = {}));
class Event {
constructor(src, type, callback) {
this.src = src;
this.type = type;
this.callback = callback;
}
add() {
this.src.addEventListener(this.type, this.callback);
}
remove() {
this.src.removeEventListener(this.type, this.callback);
}
}
exports.Event = Event;

View File

@@ -0,0 +1,2 @@
export declare function makePath(path: string): string;
export declare function localePath(locale: string, ext?: string): string;

13
node_modules/speech-rule-engine/js/common/file_util.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makePath = makePath;
exports.localePath = localePath;
const system_external_js_1 = require("./system_external.js");
function makePath(path) {
return path.match('/$') ? path : path + '/';
}
function localePath(locale, ext = 'json') {
return (makePath(system_external_js_1.SystemExternal.jsonPath) +
locale +
(ext.match(/^\./) ? ext : '.' + ext));
}

View File

@@ -0,0 +1 @@
export {};

22
node_modules/speech-rule-engine/js/common/mathjax.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const engine_js_1 = require("./engine.js");
const EngineConst = require("../common/engine_const.js");
const System = require("./system.js");
(function () {
const SIGNAL = MathJax.Callback.Signal('Sre');
MathJax.Extension.Sre = {
version: System.version,
signal: SIGNAL,
ConfigSre: function () {
engine_js_1.EnginePromise.getall().then(() => MathJax.Callback.Queue(MathJax.Hub.Register.StartupHook('mml Jax Ready', {}), ['Post', MathJax.Hub.Startup.signal, 'Sre Ready']));
}
};
System.setupEngine({
mode: EngineConst.Mode.HTTP,
json: MathJax.Ajax.config.path['SRE'] + '/mathmaps',
xpath: MathJax.Ajax.config.path['SRE'] + '/wgxpath.install.js',
semantics: true
});
MathJax.Extension.Sre.ConfigSre();
})();

View File

@@ -0,0 +1,34 @@
import { Highlighter } from '../highlighter/highlighter.js';
import { SpeechGenerator } from '../speech_generator/speech_generator.js';
import { Walker } from '../walker/walker.js';
import { KeyCode } from './event_util.js';
export declare class Processor<T> {
name: string;
static LocalState: {
walker: Walker;
speechGenerator: SpeechGenerator;
highlighter: Highlighter;
};
process: (p1: string) => T;
postprocess: (p1: T, p2: string) => T;
print: (p1: T) => string;
pprint: (p1: T) => string;
processor: (p1: string) => T;
private static stringify_;
constructor(name: string, methods: {
processor: (p1: string) => T;
postprocessor?: (p1: T, p2: string) => T;
print?: (p1: T) => string;
pprint?: (p1: T) => string;
});
}
export declare class KeyProcessor<T> extends Processor<T> {
key: (p1: KeyCode | string) => KeyCode;
private static getKey_;
constructor(name: string, methods: {
processor: (p1: string) => T;
key?: (p1: KeyCode | string) => KeyCode;
print?: (p1: T) => string;
pprint?: (p1: T) => string;
});
}

37
node_modules/speech-rule-engine/js/common/processor.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeyProcessor = exports.Processor = void 0;
const event_util_js_1 = require("./event_util.js");
class Processor {
static stringify_(x) {
return x ? x.toString() : x;
}
constructor(name, methods) {
this.name = name;
this.process = methods.processor;
this.postprocess =
methods.postprocessor || ((x, _y) => x);
this.processor = this.postprocess
? function (x) {
return this.postprocess(this.process(x), x);
}
: this.process;
this.print = methods.print || Processor.stringify_;
this.pprint = methods.pprint || this.print;
}
}
exports.Processor = Processor;
Processor.LocalState = { walker: null, speechGenerator: null, highlighter: null };
class KeyProcessor extends Processor {
static getKey_(key) {
return typeof key === 'string'
?
event_util_js_1.KeyCode[key.toUpperCase()]
: key;
}
constructor(name, methods) {
super(name, methods);
this.key = methods.key || KeyProcessor.getKey_;
}
}
exports.KeyProcessor = KeyProcessor;

View File

@@ -0,0 +1,4 @@
import { KeyCode } from './event_util.js';
export declare function process<T>(name: string, expr: string): T;
export declare function output(name: string, expr: string): string;
export declare function keypress(name: string, expr: KeyCode | string): string;

View File

@@ -0,0 +1,261 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.process = process;
exports.output = output;
exports.keypress = keypress;
const AuralRendering = require("../audio/aural_rendering.js");
const Enrich = require("../enrich_mathml/enrich.js");
const HighlighterFactory = require("../highlighter/highlighter_factory.js");
const locale_js_1 = require("../l10n/locale.js");
const Semantic = require("../semantic_tree/semantic.js");
const SpeechGeneratorFactory = require("../speech_generator/speech_generator_factory.js");
const SpeechGeneratorUtil = require("../speech_generator/speech_generator_util.js");
const WalkerFactory = require("../walker/walker_factory.js");
const WalkerUtil = require("../walker/walker_util.js");
const rebuild_stree_js_1 = require("../walker/rebuild_stree.js");
const DomUtil = require("./dom_util.js");
const engine_js_1 = require("./engine.js");
const EngineConst = require("../common/engine_const.js");
const processor_js_1 = require("./processor.js");
const XpathUtil = require("./xpath_util.js");
const PROCESSORS = new Map();
function set(processor) {
PROCESSORS.set(processor.name, processor);
}
function get(name) {
const processor = PROCESSORS.get(name);
if (!processor) {
throw new engine_js_1.SREError('Unknown processor ' + name);
}
return processor;
}
function process(name, expr) {
const processor = get(name);
try {
return processor.processor(expr);
}
catch (_e) {
throw new engine_js_1.SREError('Processing error for expression ' + expr);
}
}
function print(name, data) {
const processor = get(name);
return engine_js_1.Engine.getInstance().pprint
? processor.pprint(data)
: processor.print(data);
}
function output(name, expr) {
const processor = get(name);
try {
const data = processor.processor(expr);
return engine_js_1.Engine.getInstance().pprint
? processor.pprint(data)
: processor.print(data);
}
catch (_e) {
console.log(_e);
throw new engine_js_1.SREError('Processing error for expression ' + expr);
}
}
function keypress(name, expr) {
const processor = get(name);
const key = processor instanceof processor_js_1.KeyProcessor ? processor.key(expr) : expr;
const data = processor.processor(key);
return engine_js_1.Engine.getInstance().pprint
? processor.pprint(data)
: processor.print(data);
}
set(new processor_js_1.Processor('semantic', {
processor: function (expr) {
const mml = DomUtil.parseInput(expr);
return Semantic.xmlTree(mml);
},
postprocessor: function (xml, _expr) {
const setting = engine_js_1.Engine.getInstance().speech;
if (setting === EngineConst.Speech.NONE) {
return xml;
}
const clone = DomUtil.cloneNode(xml);
let speech = SpeechGeneratorUtil.computeMarkup(clone);
if (setting === EngineConst.Speech.SHALLOW) {
xml.setAttribute('speech', AuralRendering.finalize(speech));
return xml;
}
const nodesXml = XpathUtil.evalXPath('.//*[@id]', xml);
const nodesClone = XpathUtil.evalXPath('.//*[@id]', clone);
for (let i = 0, orig, node; (orig = nodesXml[i]), (node = nodesClone[i]); i++) {
speech = SpeechGeneratorUtil.computeMarkup(node);
orig.setAttribute('speech', AuralRendering.finalize(speech));
}
return xml;
},
pprint: function (tree) {
return DomUtil.formatXml(tree.toString());
}
}));
set(new processor_js_1.Processor('speech', {
processor: function (expr) {
const mml = DomUtil.parseInput(expr);
const xml = Semantic.xmlTree(mml);
const descrs = SpeechGeneratorUtil.computeSpeech(xml);
return AuralRendering.finalize(AuralRendering.markup(descrs));
},
pprint: function (speech) {
const str = speech.toString();
return AuralRendering.isXml() ? DomUtil.formatXml(str) : str;
}
}));
set(new processor_js_1.Processor('json', {
processor: function (expr) {
const mml = DomUtil.parseInput(expr);
const stree = Semantic.getTree(mml);
return stree.toJson();
},
postprocessor: function (json, expr) {
const setting = engine_js_1.Engine.getInstance().speech;
if (setting === EngineConst.Speech.NONE) {
return json;
}
const mml = DomUtil.parseInput(expr);
const xml = Semantic.xmlTree(mml);
const speech = SpeechGeneratorUtil.computeMarkup(xml);
if (setting === EngineConst.Speech.SHALLOW) {
json.stree.speech = AuralRendering.finalize(speech);
return json;
}
const addRec = (json) => {
const node = XpathUtil.evalXPath(`.//*[@id=${json.id}]`, xml)[0];
const speech = SpeechGeneratorUtil.computeMarkup(node);
json.speech = AuralRendering.finalize(speech);
if (json.children) {
json.children.forEach(addRec);
}
};
addRec(json.stree);
return json;
},
print: function (json) {
return JSON.stringify(json);
},
pprint: function (json) {
return JSON.stringify(json, null, 2);
}
}));
set(new processor_js_1.Processor('description', {
processor: function (expr) {
const mml = DomUtil.parseInput(expr);
const xml = Semantic.xmlTree(mml);
const descrs = SpeechGeneratorUtil.computeSpeech(xml);
return descrs;
},
print: function (descrs) {
return JSON.stringify(descrs);
},
pprint: function (descrs) {
return JSON.stringify(descrs, null, 2);
}
}));
set(new processor_js_1.Processor('enriched', {
processor: function (expr) {
return Enrich.semanticMathmlSync(expr);
},
postprocessor: function (enr, _expr) {
const root = WalkerUtil.getSemanticRoot(enr);
let generator;
switch (engine_js_1.Engine.getInstance().speech) {
case EngineConst.Speech.NONE:
break;
case EngineConst.Speech.SHALLOW:
generator = SpeechGeneratorFactory.generator('Adhoc');
generator.getSpeech(root, enr);
break;
case EngineConst.Speech.DEEP:
generator = SpeechGeneratorFactory.generator('Tree');
generator.getSpeech(enr, enr);
break;
default:
break;
}
return enr;
},
pprint: function (tree) {
return DomUtil.formatXml(tree.toString());
}
}));
set(new processor_js_1.Processor('rebuild', {
processor: function (expr) {
const rebuilt = new rebuild_stree_js_1.RebuildStree(DomUtil.parseInput(expr));
return rebuilt.stree.xml();
},
pprint: function (tree) {
return DomUtil.formatXml(tree.toString());
}
}));
set(new processor_js_1.Processor('walker', {
processor: function (expr) {
const generator = SpeechGeneratorFactory.generator('Node');
processor_js_1.Processor.LocalState.speechGenerator = generator;
generator.setOptions({
modality: engine_js_1.Engine.getInstance().modality,
locale: engine_js_1.Engine.getInstance().locale,
domain: engine_js_1.Engine.getInstance().domain,
style: engine_js_1.Engine.getInstance().style
});
processor_js_1.Processor.LocalState.highlighter = HighlighterFactory.highlighter({ color: 'black' }, { color: 'white' }, { renderer: 'NativeMML' });
const node = process('enriched', expr);
const eml = print('enriched', node);
processor_js_1.Processor.LocalState.walker = WalkerFactory.walker(engine_js_1.Engine.getInstance().walker, node, generator, processor_js_1.Processor.LocalState.highlighter, eml);
return processor_js_1.Processor.LocalState.walker;
},
print: function (_walker) {
return processor_js_1.Processor.LocalState.walker.speech();
}
}));
set(new processor_js_1.KeyProcessor('move', {
processor: function (direction) {
if (!processor_js_1.Processor.LocalState.walker) {
return null;
}
const move = processor_js_1.Processor.LocalState.walker.move(direction);
return move === false
? AuralRendering.error(direction)
: processor_js_1.Processor.LocalState.walker.speech();
}
}));
set(new processor_js_1.Processor('number', {
processor: function (numb) {
const num = parseInt(numb, 10);
return isNaN(num) ? '' : locale_js_1.LOCALE.NUMBERS.numberToWords(num);
}
}));
set(new processor_js_1.Processor('ordinal', {
processor: function (numb) {
const num = parseInt(numb, 10);
return isNaN(num) ? '' : locale_js_1.LOCALE.NUMBERS.wordOrdinal(num);
}
}));
set(new processor_js_1.Processor('numericOrdinal', {
processor: function (numb) {
const num = parseInt(numb, 10);
return isNaN(num) ? '' : locale_js_1.LOCALE.NUMBERS.numericOrdinal(num);
}
}));
set(new processor_js_1.Processor('vulgar', {
processor: function (numb) {
const [en, den] = numb.split('/').map((x) => parseInt(x, 10));
return isNaN(en) || isNaN(den)
? ''
: process('speech', `<mfrac><mn>${en}</mn><mn>${den}</mn></mfrac>`);
}
}));
set(new processor_js_1.Processor('latex', {
processor: function (ltx) {
if (engine_js_1.Engine.getInstance().modality !== 'braille' ||
engine_js_1.Engine.getInstance().locale !== 'euro') {
console.info('LaTeX input currently only works for Euro Braille output.' +
' Please use the latex-to-speech package from npm for general' +
' LaTeX input to SRE.');
}
return process('speech', `<math data-latex="${ltx}"></math>`);
}
}));

28
node_modules/speech-rule-engine/js/common/system.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { AuditoryDescription } from '../audio/auditory_description.js';
import { KeyCode } from './event_util.js';
import * as FileUtil from './file_util.js';
import { standardLoader } from '../speech_rules/math_map.js';
export declare const version: string;
export declare function setupEngine(feature: {
[key: string]: boolean | string;
}): Promise<string>;
export declare function engineSetup(): {
[key: string]: boolean | string;
};
export declare function engineReady(): Promise<any>;
export declare const localeLoader: typeof standardLoader;
export declare function toSpeech(expr: string): string;
export declare function toSemantic(expr: string): Node;
export declare function toJson(expr: string): any;
export declare function toDescription(expr: string): AuditoryDescription[];
export declare function toEnriched(expr: string): Element;
export declare function number(expr: string): string;
export declare function ordinal(expr: string): string;
export declare function numericOrdinal(expr: string): string;
export declare function vulgar(expr: string): string;
export declare const file: Record<string, (input: string, output?: string) => any>;
export declare function processFile(processor: string, input: string, opt_output?: string): string | Promise<string>;
export declare function walk(expr: string): string;
export declare function move(direction: KeyCode | string): string | null;
export declare function exit(opt_value?: number): void;
export declare const localePath: typeof FileUtil.localePath;

173
node_modules/speech-rule-engine/js/common/system.js generated vendored Normal file
View File

@@ -0,0 +1,173 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.localePath = exports.file = exports.localeLoader = exports.version = void 0;
exports.setupEngine = setupEngine;
exports.engineSetup = engineSetup;
exports.engineReady = engineReady;
exports.toSpeech = toSpeech;
exports.toSemantic = toSemantic;
exports.toJson = toJson;
exports.toDescription = toDescription;
exports.toEnriched = toEnriched;
exports.number = number;
exports.ordinal = ordinal;
exports.numericOrdinal = numericOrdinal;
exports.vulgar = vulgar;
exports.processFile = processFile;
exports.walk = walk;
exports.move = move;
exports.exit = exit;
const engine_js_1 = require("./engine.js");
const engine_setup_js_1 = require("./engine_setup.js");
const EngineConst = require("./engine_const.js");
const FileUtil = require("./file_util.js");
const ProcessorFactory = require("./processor_factory.js");
const system_external_js_1 = require("./system_external.js");
const variables_js_1 = require("./variables.js");
const math_map_js_1 = require("../speech_rules/math_map.js");
exports.version = variables_js_1.Variables.VERSION;
function setupEngine(feature) {
return __awaiter(this, void 0, void 0, function* () {
return (0, engine_setup_js_1.setup)(feature);
});
}
function engineSetup() {
const engineFeatures = ['mode'].concat(engine_js_1.Engine.STRING_FEATURES, engine_js_1.Engine.BINARY_FEATURES);
const engine = engine_js_1.Engine.getInstance();
const features = {};
engineFeatures.forEach(function (x) {
features[x] = engine[x];
});
features.json = system_external_js_1.SystemExternal.jsonPath;
features.xpath = system_external_js_1.SystemExternal.WGXpath;
features.rules = engine.ruleSets.slice();
return features;
}
function engineReady() {
return __awaiter(this, void 0, void 0, function* () {
return setupEngine({}).then(() => engine_js_1.EnginePromise.getall());
});
}
exports.localeLoader = math_map_js_1.standardLoader;
function toSpeech(expr) {
return processString('speech', expr);
}
function toSemantic(expr) {
return processString('semantic', expr);
}
function toJson(expr) {
return processString('json', expr);
}
function toDescription(expr) {
return processString('description', expr);
}
function toEnriched(expr) {
return processString('enriched', expr);
}
function number(expr) {
return processString('number', expr);
}
function ordinal(expr) {
return processString('ordinal', expr);
}
function numericOrdinal(expr) {
return processString('numericOrdinal', expr);
}
function vulgar(expr) {
return processString('vulgar', expr);
}
function processString(processor, input) {
return ProcessorFactory.process(processor, input);
}
exports.file = {};
exports.file.toSpeech = function (input, opt_output) {
return processFile('speech', input, opt_output);
};
exports.file.toSemantic = function (input, opt_output) {
return processFile('semantic', input, opt_output);
};
exports.file.toJson = function (input, opt_output) {
return processFile('json', input, opt_output);
};
exports.file.toDescription = function (input, opt_output) {
return processFile('description', input, opt_output);
};
exports.file.toEnriched = function (input, opt_output) {
return processFile('enriched', input, opt_output);
};
function processFile(processor, input, opt_output) {
switch (engine_js_1.Engine.getInstance().mode) {
case EngineConst.Mode.ASYNC:
return processFileAsync(processor, input, opt_output);
case EngineConst.Mode.SYNC:
return processFileSync(processor, input, opt_output);
default:
throw new engine_js_1.SREError(`Can process files in ${engine_js_1.Engine.getInstance().mode} mode`);
}
}
function processFileSync(processor, input, opt_output) {
const expr = inputFileSync_(input);
const result = ProcessorFactory.output(processor, expr);
if (opt_output) {
try {
system_external_js_1.SystemExternal.fs.writeFileSync(opt_output, result);
}
catch (_err) {
throw new engine_js_1.SREError('Can not write to file: ' + opt_output);
}
}
return result;
}
function inputFileSync_(file) {
let expr;
try {
expr = system_external_js_1.SystemExternal.fs.readFileSync(file, { encoding: 'utf8' });
}
catch (_err) {
throw new engine_js_1.SREError('Can not open file: ' + file);
}
return expr;
}
function processFileAsync(processor, file, output) {
return __awaiter(this, void 0, void 0, function* () {
const expr = yield system_external_js_1.SystemExternal.fs.promises.readFile(file, {
encoding: 'utf8'
});
const result = ProcessorFactory.output(processor, expr);
if (output) {
try {
system_external_js_1.SystemExternal.fs.promises.writeFile(output, result);
}
catch (_err) {
throw new engine_js_1.SREError('Can not write to file: ' + output);
}
}
return result;
});
}
function walk(expr) {
return ProcessorFactory.output('walker', expr);
}
function move(direction) {
return ProcessorFactory.keypress('move', direction);
}
function exit(opt_value) {
const value = opt_value || 0;
engine_js_1.EnginePromise.getall().then(() => process.exit(value));
}
exports.localePath = FileUtil.localePath;
if (system_external_js_1.SystemExternal.documentSupported) {
setupEngine({ mode: EngineConst.Mode.HTTP }).then(() => setupEngine({}));
}
else {
setupEngine({ mode: EngineConst.Mode.SYNC }).then(() => setupEngine({ mode: EngineConst.Mode.ASYNC }));
}

View File

@@ -0,0 +1,16 @@
export declare class SystemExternal {
static nodeRequire(): any;
static extRequire(library: string): any;
static windowSupported: boolean;
static documentSupported: boolean;
static xmldom: any;
static document: Document;
static xpath: any;
static mathmapsIePath: string;
static fs: any;
static url: string;
static jsonPath: any;
static WGXpath: string;
static wgxpath: any;
}
export default SystemExternal;

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SystemExternal = void 0;
const variables_js_1 = require("./variables.js");
class SystemExternal {
static nodeRequire() {
return eval('require');
}
static extRequire(library) {
if (typeof process !== 'undefined' && typeof require !== 'undefined') {
return SystemExternal.nodeRequire()(library);
}
return null;
}
}
exports.SystemExternal = SystemExternal;
SystemExternal.windowSupported = (() => !(typeof window === 'undefined'))();
SystemExternal.documentSupported = (() => SystemExternal.windowSupported &&
!(typeof window.document === 'undefined'))();
SystemExternal.xmldom = SystemExternal.documentSupported
? window
: SystemExternal.extRequire('@xmldom/xmldom');
SystemExternal.document = SystemExternal.documentSupported
? window.document
: new SystemExternal.xmldom.DOMImplementation().createDocument('', '', 0);
SystemExternal.xpath = SystemExternal.documentSupported
? document
: (function () {
const window = { document: {}, XPathResult: {} };
const wgx = SystemExternal.extRequire('wicked-good-xpath');
wgx.install(window);
window.document.XPathResult = window.XPathResult;
return window.document;
})();
SystemExternal.mathmapsIePath = 'https://cdn.jsdelivr.net/npm/sre-mathmaps-ie@' +
variables_js_1.Variables.VERSION +
'mathmaps_ie.js';
SystemExternal.fs = SystemExternal.documentSupported
? null
: SystemExternal.extRequire('fs');
SystemExternal.url = variables_js_1.Variables.url;
SystemExternal.jsonPath = (function () {
if (SystemExternal.documentSupported) {
return SystemExternal.url;
}
if (process.env.SRE_JSON_PATH || global.SRE_JSON_PATH) {
return process.env.SRE_JSON_PATH || global.SRE_JSON_PATH;
}
try {
const path = SystemExternal.nodeRequire().resolve('speech-rule-engine');
return path.replace(/sre\.js$/, '') + 'mathmaps';
}
catch (_err) {
}
try {
const path = SystemExternal.nodeRequire().resolve('.');
return path.replace(/sre\.js$/, '') + 'mathmaps';
}
catch (_err) {
}
return typeof __dirname !== 'undefined'
? __dirname + (__dirname.match(/lib?$/) ? '/mathmaps' : '/lib/mathmaps')
: process.cwd() + '/lib/mathmaps';
})();
SystemExternal.WGXpath = variables_js_1.Variables.WGXpath;
SystemExternal.wgxpath = null;
exports.default = SystemExternal;

View File

@@ -0,0 +1,8 @@
export declare class Variables {
static readonly VERSION: string;
static readonly LOCALES: Map<string, string>;
static ensureLocale(loc: string, def: string): string;
static readonly mathjaxVersion: string;
static readonly url: string;
static readonly WGXpath: string;
}

37
node_modules/speech-rule-engine/js/common/variables.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Variables = void 0;
class Variables {
static ensureLocale(loc, def) {
if (!Variables.LOCALES.get(loc)) {
console.error(`Locale ${loc} does not exist! Using` +
` ${Variables.LOCALES.get(def)} instead.`);
return def;
}
return loc;
}
}
exports.Variables = Variables;
Variables.VERSION = '4.1.2';
Variables.LOCALES = new Map([
['af', 'Africaans'],
['ca', 'Catalan'],
['da', 'Danish'],
['de', 'German'],
['en', 'English'],
['es', 'Spanish'],
['euro', 'Euro'],
['fr', 'French'],
['hi', 'Hindi'],
['it', 'Italian'],
['ko', 'Korean'],
['nb', 'Bokmål'],
['nn', 'Nynorsk'],
['sv', 'Swedish'],
['nemeth', 'Nemeth']
]);
Variables.mathjaxVersion = '4.0.0-beta.5';
Variables.url = 'https://cdn.jsdelivr.net/npm/speech-rule-engine@' +
Variables.VERSION +
'/lib/mathmaps';
Variables.WGXpath = 'https://cdn.jsdelivr.net/npm/wicked-good-xpath@1.3.0/dist/wgxpath.install.js';

View File

@@ -0,0 +1,16 @@
export declare const xpath: {
currentDocument: Document;
evaluate: (x: string, node: Element, nsr: Resolver, rt: number, result: XPathResult) => XPathResult;
result: any;
createNSResolver: (nodeResolver: Element) => XPathNSResolver;
};
export declare function resolveNameSpace(prefix: string): string;
declare class Resolver {
lookupNamespaceURI: any;
constructor();
}
export declare function evalXPath(expression: string, rootNode: Element): Element[];
export declare function evaluateBoolean(expression: string, rootNode: Element): boolean;
export declare function evaluateString(expression: string, rootNode: Element): string;
export declare function updateEvaluator(node: Element): void;
export {};

View File

@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.xpath = void 0;
exports.resolveNameSpace = resolveNameSpace;
exports.evalXPath = evalXPath;
exports.evaluateBoolean = evaluateBoolean;
exports.evaluateString = evaluateString;
exports.updateEvaluator = updateEvaluator;
const engine_js_1 = require("./engine.js");
const EngineConst = require("../common/engine_const.js");
const system_external_js_1 = require("./system_external.js");
function xpathSupported() {
if (typeof XPathResult === 'undefined') {
return false;
}
return true;
}
exports.xpath = {
currentDocument: null,
evaluate: xpathSupported()
? document.evaluate
: system_external_js_1.SystemExternal.xpath.evaluate,
result: xpathSupported() ? XPathResult : system_external_js_1.SystemExternal.xpath.XPathResult,
createNSResolver: xpathSupported()
? document.createNSResolver
: system_external_js_1.SystemExternal.xpath.createNSResolver
};
const nameSpaces = {
xhtml: 'http://www.w3.org/1999/xhtml',
mathml: 'http://www.w3.org/1998/Math/MathML',
mml: 'http://www.w3.org/1998/Math/MathML',
svg: 'http://www.w3.org/2000/svg'
};
function resolveNameSpace(prefix) {
return nameSpaces[prefix] || null;
}
class Resolver {
constructor() {
this.lookupNamespaceURI = resolveNameSpace;
}
}
function evaluateXpath(expression, rootNode, type) {
return engine_js_1.Engine.getInstance().mode === EngineConst.Mode.HTTP &&
!engine_js_1.Engine.getInstance().isIE &&
!engine_js_1.Engine.getInstance().isEdge
? exports.xpath.currentDocument.evaluate(expression, rootNode, resolveNameSpace, type, null)
: exports.xpath.evaluate(expression, rootNode, new Resolver(), type, null);
}
function evalXPath(expression, rootNode) {
let iterator;
try {
iterator = evaluateXpath(expression, rootNode, exports.xpath.result.ORDERED_NODE_ITERATOR_TYPE);
}
catch (_err) {
return [];
}
const results = [];
for (let xpathNode = iterator.iterateNext(); xpathNode; xpathNode = iterator.iterateNext()) {
results.push(xpathNode);
}
return results;
}
function evaluateBoolean(expression, rootNode) {
let result;
try {
result = evaluateXpath(expression, rootNode, exports.xpath.result.BOOLEAN_TYPE);
}
catch (_err) {
return false;
}
return result.booleanValue;
}
function evaluateString(expression, rootNode) {
let result;
try {
result = evaluateXpath(expression, rootNode, exports.xpath.result.STRING_TYPE);
}
catch (_err) {
return '';
}
return result.stringValue;
}
function updateEvaluator(node) {
if (engine_js_1.Engine.getInstance().mode !== EngineConst.Mode.HTTP)
return;
let parent = node;
while (parent && !parent.evaluate) {
parent = parent.parentNode;
}
if (parent && parent.evaluate) {
exports.xpath.currentDocument = parent;
}
else if (node.ownerDocument) {
exports.xpath.currentDocument = node.ownerDocument;
}
}

View File

@@ -0,0 +1,7 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { EnrichCase } from './enrich_case.js';
export declare abstract class AbstractEnrichCase implements EnrichCase {
semantic: SemanticNode;
abstract getMathml(): Element;
constructor(semantic: SemanticNode);
}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractEnrichCase = void 0;
class AbstractEnrichCase {
constructor(semantic) {
this.semantic = semantic;
}
}
exports.AbstractEnrichCase = AbstractEnrichCase;

View File

@@ -0,0 +1,8 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseBinomial extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseBinomial = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const enrich_mathml_js_1 = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseBinomial extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return (!semantic.mathmlTree &&
semantic.type === semantic_meaning_js_1.SemanticType.LINE &&
semantic.role === semantic_meaning_js_1.SemanticRole.BINOMIAL);
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
if (!this.semantic.childNodes.length) {
return this.mml;
}
const child = this.semantic.childNodes[0];
this.mml = (0, enrich_mathml_js_1.walkTree)(child);
if (this.mml.hasAttribute(enrich_attr_js_1.Attribute.TYPE)) {
const mrow = (0, enrich_attr_js_1.addMrow)();
DomUtil.replaceNode(this.mml, mrow);
mrow.appendChild(this.mml);
this.mml = mrow;
}
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
return this.mml;
}
}
exports.CaseBinomial = CaseBinomial;

View File

@@ -0,0 +1,8 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseDoubleScript extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseDoubleScript = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseDoubleScript extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
if (!semantic.mathmlTree || !semantic.childNodes.length) {
return false;
}
const mmlTag = DomUtil.tagName(semantic.mathmlTree);
const role = semantic.childNodes[0].role;
return ((mmlTag === semantic_util_js_1.MMLTAGS.MSUBSUP && role === semantic_meaning_js_1.SemanticRole.SUBSUP) ||
(mmlTag === semantic_util_js_1.MMLTAGS.MUNDEROVER && role === semantic_meaning_js_1.SemanticRole.UNDEROVER));
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
const ignore = this.semantic.childNodes[0];
const baseSem = ignore.childNodes[0];
const supSem = this.semantic.childNodes[1];
const subSem = ignore.childNodes[1];
const supMml = EnrichMathml.walkTree(supSem);
const baseMml = EnrichMathml.walkTree(baseSem);
const subMml = EnrichMathml.walkTree(subSem);
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
this.mml.setAttribute(enrich_attr_js_1.Attribute.CHILDREN, (0, enrich_attr_js_1.makeIdList)([baseSem, subSem, supSem]));
[baseMml, subMml, supMml].forEach((child) => EnrichMathml.getInnerNode(child).setAttribute(enrich_attr_js_1.Attribute.PARENT, this.mml.getAttribute(enrich_attr_js_1.Attribute.ID)));
this.mml.setAttribute(enrich_attr_js_1.Attribute.TYPE, ignore.role);
EnrichMathml.addCollapsedAttribute(this.mml, [
this.semantic.id,
[ignore.id, baseSem.id, subSem.id],
supSem.id
]);
return this.mml;
}
}
exports.CaseDoubleScript = CaseDoubleScript;

View File

@@ -0,0 +1,32 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseEmbellished extends AbstractEnrichCase {
fenced: SemanticNode;
fencedMml: Element;
fencedMmlNodes: Element[];
ofence: SemanticNode;
ofenceMml: Element;
ofenceMap: {
[key: number]: Element;
};
cfence: SemanticNode;
cfenceMml: Element;
cfenceMap: {
[key: number]: Element;
};
parentCleanup: Element[];
static test(semantic: SemanticNode): boolean;
private static makeEmptyNode_;
private static fencedMap_;
constructor(semantic: SemanticNode);
getMathml(): Element;
private fencedElement;
private getFenced_;
private getFencedMml_;
private getFencesMml_;
private rewrite_;
private specialCase_;
private introduceNewLayer_;
private fullFence;
private cleanupParents_;
}

View File

@@ -0,0 +1,215 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseEmbellished = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_node_js_1 = require("../semantic_tree/semantic_node.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const case_double_script_js_1 = require("./case_double_script.js");
const case_multiscripts_js_1 = require("./case_multiscripts.js");
const case_tensor_js_1 = require("./case_tensor.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseEmbellished extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return !!(semantic.mathmlTree &&
semantic.fencePointer &&
!semantic.mathmlTree.getAttribute('data-semantic-type'));
}
static makeEmptyNode_(id) {
const mrow = (0, enrich_attr_js_1.addMrow)();
const empty = new semantic_node_js_1.SemanticNode(id);
empty.type = semantic_meaning_js_1.SemanticType.EMPTY;
empty.mathmlTree = mrow;
return empty;
}
static fencedMap_(fence, ids) {
ids[fence.id] = fence.mathmlTree;
if (!fence.embellished) {
return;
}
CaseEmbellished.fencedMap_(fence.childNodes[0], ids);
}
constructor(semantic) {
super(semantic);
this.fenced = null;
this.fencedMml = null;
this.fencedMmlNodes = [];
this.ofence = null;
this.ofenceMml = null;
this.ofenceMap = {};
this.cfence = null;
this.cfenceMml = null;
this.cfenceMap = {};
this.parentCleanup = [];
}
getMathml() {
this.getFenced_();
this.fencedMml = EnrichMathml.walkTree(this.fenced);
this.getFencesMml_();
if (this.fenced.type === semantic_meaning_js_1.SemanticType.EMPTY && !this.fencedMml.parentNode) {
this.fencedMml.setAttribute(enrich_attr_js_1.Attribute.ADDED, 'true');
this.cfenceMml.parentNode.insertBefore(this.fencedMml, this.cfenceMml);
}
this.getFencedMml_();
const rewrite = this.rewrite_();
return rewrite;
}
fencedElement(node) {
return (node.type === semantic_meaning_js_1.SemanticType.FENCED ||
node.type === semantic_meaning_js_1.SemanticType.MATRIX ||
node.type === semantic_meaning_js_1.SemanticType.VECTOR);
}
getFenced_() {
let currentNode = this.semantic;
while (!this.fencedElement(currentNode)) {
currentNode = currentNode.childNodes[0];
}
this.fenced = currentNode.childNodes[0];
this.ofence = currentNode.contentNodes[0];
this.cfence = currentNode.contentNodes[1];
CaseEmbellished.fencedMap_(this.ofence, this.ofenceMap);
CaseEmbellished.fencedMap_(this.cfence, this.cfenceMap);
}
getFencedMml_() {
let sibling = this.ofenceMml.nextSibling;
sibling = sibling === this.fencedMml ? sibling : this.fencedMml;
while (sibling && sibling !== this.cfenceMml) {
this.fencedMmlNodes.push(sibling);
sibling = sibling.nextSibling;
}
}
getFencesMml_() {
let currentNode = this.semantic;
const ofenceIds = Object.keys(this.ofenceMap);
const cfenceIds = Object.keys(this.cfenceMap);
while ((!this.ofenceMml || !this.cfenceMml) &&
currentNode !== this.fenced) {
if (ofenceIds.indexOf(currentNode.fencePointer) !== -1 &&
!this.ofenceMml) {
this.ofenceMml = currentNode.mathmlTree;
}
if (cfenceIds.indexOf(currentNode.fencePointer) !== -1 &&
!this.cfenceMml) {
this.cfenceMml = currentNode.mathmlTree;
}
currentNode = currentNode.childNodes[0];
}
if (!this.ofenceMml) {
this.ofenceMml = this.ofence.mathmlTree;
}
if (!this.cfenceMml) {
this.cfenceMml = this.cfence.mathmlTree;
}
if (this.ofenceMml) {
this.ofenceMml = EnrichMathml.ascendNewNode(this.ofenceMml);
}
if (this.cfenceMml) {
this.cfenceMml = EnrichMathml.ascendNewNode(this.cfenceMml);
}
}
rewrite_() {
let currentNode = this.semantic;
let result = null;
const newNode = this.introduceNewLayer_();
(0, enrich_attr_js_1.setAttributes)(newNode, this.fenced.parent);
while (!this.fencedElement(currentNode)) {
const mml = currentNode.mathmlTree;
const specialCase = this.specialCase_(currentNode, mml);
if (specialCase) {
currentNode = specialCase;
}
else {
(0, enrich_attr_js_1.setAttributes)(mml, currentNode);
const mmlChildren = [];
for (let i = 1, child; (child = currentNode.childNodes[i]); i++) {
mmlChildren.push(EnrichMathml.walkTree(child));
}
currentNode = currentNode.childNodes[0];
}
const dummy = DomUtil.createElement('dummy');
const saveChild = mml.childNodes[0];
DomUtil.replaceNode(mml, dummy);
DomUtil.replaceNode(newNode, mml);
DomUtil.replaceNode(mml.childNodes[0], newNode);
DomUtil.replaceNode(dummy, saveChild);
if (!result) {
result = mml;
}
}
EnrichMathml.walkTree(this.ofence);
EnrichMathml.walkTree(this.cfence);
this.cleanupParents_();
return result || newNode;
}
specialCase_(semantic, mml) {
const mmlTag = DomUtil.tagName(mml);
let parent = null;
let caller;
if (mmlTag === semantic_util_js_1.MMLTAGS.MSUBSUP) {
parent = semantic.childNodes[0];
caller = case_double_script_js_1.CaseDoubleScript;
}
else if (mmlTag === semantic_util_js_1.MMLTAGS.MMULTISCRIPTS) {
if (semantic.type === semantic_meaning_js_1.SemanticType.SUPERSCRIPT ||
semantic.type === semantic_meaning_js_1.SemanticType.SUBSCRIPT) {
caller = case_multiscripts_js_1.CaseMultiscripts;
}
else if (semantic.type === semantic_meaning_js_1.SemanticType.TENSOR) {
caller = case_tensor_js_1.CaseTensor;
}
if (caller &&
semantic.childNodes[0] &&
semantic.childNodes[0].role === semantic_meaning_js_1.SemanticRole.SUBSUP) {
parent = semantic.childNodes[0];
}
else {
parent = semantic;
}
}
if (!parent) {
return null;
}
const base = parent.childNodes[0];
const empty = CaseEmbellished.makeEmptyNode_(base.id);
parent.childNodes[0] = empty;
mml = new caller(semantic).getMathml();
parent.childNodes[0] = base;
this.parentCleanup.push(mml);
return parent.childNodes[0];
}
introduceNewLayer_() {
const fullOfence = this.fullFence(this.ofenceMml);
const fullCfence = this.fullFence(this.cfenceMml);
let newNode = (0, enrich_attr_js_1.addMrow)();
DomUtil.replaceNode(this.fencedMml, newNode);
this.fencedMmlNodes.forEach((node) => newNode.appendChild(node));
newNode.insertBefore(fullOfence, this.fencedMml);
newNode.appendChild(fullCfence);
if (!newNode.parentNode) {
const mrow = (0, enrich_attr_js_1.addMrow)();
while (newNode.childNodes.length > 0) {
mrow.appendChild(newNode.childNodes[0]);
}
newNode.appendChild(mrow);
newNode = mrow;
}
return newNode;
}
fullFence(fence) {
const parent = this.fencedMml.parentNode;
let currentFence = fence;
while (currentFence.parentNode && currentFence.parentNode !== parent) {
currentFence = currentFence.parentNode;
}
return currentFence;
}
cleanupParents_() {
this.parentCleanup.forEach(function (x) {
const parent = x.childNodes[1].getAttribute(enrich_attr_js_1.Attribute.PARENT);
x.childNodes[0].setAttribute(enrich_attr_js_1.Attribute.PARENT, parent);
});
}
}
exports.CaseEmbellished = CaseEmbellished;

View File

@@ -0,0 +1,11 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseEmpheq extends AbstractEnrichCase {
mml: Element;
private mrows;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
private recurseToTable;
private finalizeTable;
}

View File

@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseEmpheq = void 0;
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
const DomUtil = require("../common/dom_util.js");
class CaseEmpheq extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return !!semantic.mathmlTree && semantic.hasAnnotation('Emph', 'top');
}
constructor(semantic) {
super(semantic);
this.mrows = [];
this.mml = semantic.mathmlTree;
}
getMathml() {
this.recurseToTable(this.semantic);
if (this.mrows.length) {
const newRow = (0, enrich_attr_js_1.addMrow)();
const parent = this.mml.parentNode;
parent.insertBefore(newRow, this.mml);
for (const mrow of this.mrows) {
newRow.appendChild(mrow);
}
newRow.appendChild(this.mml);
}
return this.mml;
}
recurseToTable(node) {
var _a, _b;
if (!(node.hasAnnotation('Emph', 'top') || node.hasAnnotation('Emph', 'fence')) &&
(node.hasAnnotation('Emph', 'left') ||
node.hasAnnotation('Emph', 'right'))) {
EnrichMathml.walkTree(node);
return;
}
if (!node.mathmlTree ||
(DomUtil.tagName(node.mathmlTree) === semantic_util_js_1.MMLTAGS.MTABLE &&
((_a = node.annotation['Emph']) === null || _a === void 0 ? void 0 : _a.length) &&
node.annotation['Emph'][0] !== 'table')) {
const newNode = (0, enrich_attr_js_1.addMrow)();
(0, enrich_attr_js_1.setAttributes)(newNode, node);
this.mrows.unshift(newNode);
}
else {
if (DomUtil.tagName(node.mathmlTree) === semantic_util_js_1.MMLTAGS.MTABLE &&
((_b = node.annotation['Emph']) === null || _b === void 0 ? void 0 : _b.length) &&
node.annotation['Emph'][0] === 'table') {
this.finalizeTable(node);
return;
}
(0, enrich_attr_js_1.setAttributes)(node.mathmlTree, node);
}
node.childNodes.forEach(this.recurseToTable.bind(this));
if (node.textContent || node.type === 'punctuated') {
const newContent = node.contentNodes.map((x) => {
const newNode = EnrichMathml.cloneContentNode(x);
if (newNode.hasAttribute('data-semantic-added')) {
this.mrows.unshift(newNode);
}
else {
this.recurseToTable(x);
}
return newNode;
});
EnrichMathml.setOperatorAttribute(node, newContent);
return;
}
node.contentNodes.forEach(this.recurseToTable.bind(this));
}
finalizeTable(node) {
(0, enrich_attr_js_1.setAttributes)(node.mathmlTree, node);
node.contentNodes.forEach((x) => {
EnrichMathml.walkTree(x);
});
node.childNodes.forEach((x) => {
EnrichMathml.walkTree(x);
});
}
}
exports.CaseEmpheq = CaseEmpheq;

View File

@@ -0,0 +1,9 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseLimit extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
private static walkTree_;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseLimit = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseLimit extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
if (!semantic.mathmlTree || !semantic.childNodes.length) {
return false;
}
const mmlTag = DomUtil.tagName(semantic.mathmlTree);
const type = semantic.type;
return (((type === semantic_meaning_js_1.SemanticType.LIMUPPER || type === semantic_meaning_js_1.SemanticType.LIMLOWER) &&
(mmlTag === semantic_util_js_1.MMLTAGS.MSUBSUP || mmlTag === semantic_util_js_1.MMLTAGS.MUNDEROVER)) ||
(type === semantic_meaning_js_1.SemanticType.LIMBOTH &&
(mmlTag === semantic_util_js_1.MMLTAGS.MSUB ||
mmlTag === semantic_util_js_1.MMLTAGS.MUNDER ||
mmlTag === semantic_util_js_1.MMLTAGS.MSUP ||
mmlTag === semantic_util_js_1.MMLTAGS.MOVER)));
}
static walkTree_(node) {
if (node) {
EnrichMathml.walkTree(node);
}
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
const children = this.semantic.childNodes;
if (this.semantic.type !== semantic_meaning_js_1.SemanticType.LIMBOTH &&
this.mml.childNodes.length >= 3) {
this.mml = EnrichMathml.introduceNewLayer([this.mml], this.semantic);
}
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
if (!children[0].mathmlTree) {
children[0].mathmlTree = this.semantic.mathmlTree;
}
children.forEach(CaseLimit.walkTree_);
return this.mml;
}
}
exports.CaseLimit = CaseLimit;

View File

@@ -0,0 +1,8 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseLine extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseLine = void 0;
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseLine extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return !!semantic.mathmlTree && semantic.type === semantic_meaning_js_1.SemanticType.LINE;
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
if (this.semantic.contentNodes.length) {
EnrichMathml.walkTree(this.semantic.contentNodes[0]);
}
if (this.semantic.childNodes.length) {
EnrichMathml.walkTree(this.semantic.childNodes[0]);
}
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
return this.mml;
}
}
exports.CaseLine = CaseLine;

View File

@@ -0,0 +1,10 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { Sexp } from '../semantic_tree/semantic_skeleton.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare abstract class CaseMultiindex extends AbstractEnrichCase {
mml: Element;
static multiscriptIndex(index: SemanticNode): Sexp;
private static createNone_;
constructor(semantic: SemanticNode);
protected completeMultiscript(rightIndices: Sexp, leftIndices: Sexp): void;
}

View File

@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseMultiindex = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseMultiindex extends abstract_enrich_case_js_1.AbstractEnrichCase {
static multiscriptIndex(index) {
if (index.type === semantic_meaning_js_1.SemanticType.PUNCTUATED &&
index.contentNodes[0].role === semantic_meaning_js_1.SemanticRole.DUMMY) {
return EnrichMathml.collapsePunctuated(index);
}
EnrichMathml.walkTree(index);
return index.id;
}
static createNone_(semantic) {
const newNode = DomUtil.createElement('none');
if (semantic) {
(0, enrich_attr_js_1.setAttributes)(newNode, semantic);
}
newNode.setAttribute(enrich_attr_js_1.Attribute.ADDED, 'true');
return newNode;
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
completeMultiscript(rightIndices, leftIndices) {
const children = DomUtil.toArray(this.mml.childNodes).slice(1);
let childCounter = 0;
const completeIndices = (indices) => {
for (const index of indices) {
const child = children[childCounter];
if (child && index === parseInt(child.getAttribute(enrich_attr_js_1.Attribute.ID))) {
child.setAttribute(enrich_attr_js_1.Attribute.PARENT, this.semantic.id.toString());
childCounter++;
}
else if (!child ||
index !==
parseInt(EnrichMathml.getInnerNode(child).getAttribute(enrich_attr_js_1.Attribute.ID))) {
const query = this.semantic.querySelectorAll((x) => x.id === index);
this.mml.insertBefore(CaseMultiindex.createNone_(query[0]), child || null);
}
else {
EnrichMathml.getInnerNode(child).setAttribute(enrich_attr_js_1.Attribute.PARENT, this.semantic.id.toString());
childCounter++;
}
}
};
completeIndices(rightIndices);
if (children[childCounter] &&
DomUtil.tagName(children[childCounter]) !== semantic_util_js_1.MMLTAGS.MPRESCRIPTS) {
this.mml.insertBefore(children[childCounter], DomUtil.createElement('mprescripts'));
}
else {
childCounter++;
}
completeIndices(leftIndices);
}
}
exports.CaseMultiindex = CaseMultiindex;

View File

@@ -0,0 +1,7 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { CaseMultiindex } from './case_multiindex.js';
export declare class CaseMultiscripts extends CaseMultiindex {
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseMultiscripts = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_skeleton_js_1 = require("../semantic_tree/semantic_skeleton.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const case_multiindex_js_1 = require("./case_multiindex.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseMultiscripts extends case_multiindex_js_1.CaseMultiindex {
static test(semantic) {
if (!semantic.mathmlTree) {
return false;
}
const mmlTag = DomUtil.tagName(semantic.mathmlTree);
return (mmlTag === semantic_util_js_1.MMLTAGS.MMULTISCRIPTS &&
(semantic.type === semantic_meaning_js_1.SemanticType.SUPERSCRIPT ||
semantic.type === semantic_meaning_js_1.SemanticType.SUBSCRIPT));
}
constructor(semantic) {
super(semantic);
}
getMathml() {
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
let baseSem, rsup, rsub;
if (this.semantic.childNodes[0] &&
this.semantic.childNodes[0].role === semantic_meaning_js_1.SemanticRole.SUBSUP) {
const ignore = this.semantic.childNodes[0];
baseSem = ignore.childNodes[0];
rsup = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]);
rsub = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(ignore.childNodes[1]);
const collapsed = [this.semantic.id, [ignore.id, baseSem.id, rsub], rsup];
EnrichMathml.addCollapsedAttribute(this.mml, collapsed);
this.mml.setAttribute(enrich_attr_js_1.Attribute.TYPE, ignore.role);
this.completeMultiscript(semantic_skeleton_js_1.SemanticSkeleton.interleaveIds(rsub, rsup), []);
}
else {
baseSem = this.semantic.childNodes[0];
rsup = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]);
const collapsed = [this.semantic.id, baseSem.id, rsup];
EnrichMathml.addCollapsedAttribute(this.mml, collapsed);
}
const childIds = semantic_skeleton_js_1.SemanticSkeleton.collapsedLeafs(rsub || [], rsup);
const base = EnrichMathml.walkTree(baseSem);
EnrichMathml.getInnerNode(base).setAttribute(enrich_attr_js_1.Attribute.PARENT, this.semantic.id.toString());
childIds.unshift(baseSem.id);
this.mml.setAttribute(enrich_attr_js_1.Attribute.CHILDREN, childIds.join(','));
return this.mml;
}
}
exports.CaseMultiscripts = CaseMultiscripts;

View File

@@ -0,0 +1,8 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseProof extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseProof = void 0;
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseProof extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return (!!semantic.mathmlTree &&
(semantic.type === semantic_meaning_js_1.SemanticType.INFERENCE ||
semantic.type === semantic_meaning_js_1.SemanticType.PREMISES));
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
if (!this.semantic.childNodes.length) {
return this.mml;
}
this.semantic.contentNodes.forEach(function (x) {
EnrichMathml.walkTree(x);
(0, enrich_attr_js_1.setAttributes)(x.mathmlTree, x);
});
this.semantic.childNodes.forEach(function (x) {
EnrichMathml.walkTree(x);
});
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
if (this.mml.getAttribute('data-semantic-id') ===
this.mml.getAttribute('data-semantic-parent')) {
this.mml.removeAttribute('data-semantic-parent');
}
return this.mml;
}
}
exports.CaseProof = CaseProof;

View File

@@ -0,0 +1,9 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseTable extends AbstractEnrichCase {
mml: Element;
inner: Element[];
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseTable = void 0;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_util_js_1 = require("../semantic_tree/semantic_util.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseTable extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return (semantic.type === semantic_meaning_js_1.SemanticType.MATRIX ||
semantic.type === semantic_meaning_js_1.SemanticType.VECTOR ||
semantic.type === semantic_meaning_js_1.SemanticType.CASES);
}
constructor(semantic) {
super(semantic);
this.inner = [];
this.mml = semantic.mathmlTree;
}
getMathml() {
const lfence = EnrichMathml.cloneContentNode(this.semantic.contentNodes[0]);
const rfence = this.semantic.contentNodes[1]
? EnrichMathml.cloneContentNode(this.semantic.contentNodes[1])
: null;
this.inner = this.semantic.childNodes.map(EnrichMathml.walkTree);
if (!this.mml) {
this.mml = EnrichMathml.introduceNewLayer([lfence].concat(this.inner, [rfence]), this.semantic);
}
else if (DomUtil.tagName(this.mml) === semantic_util_js_1.MMLTAGS.MFENCED) {
const children = this.mml.childNodes;
this.mml.insertBefore(lfence, children[0] || null);
if (rfence) {
this.mml.appendChild(rfence);
}
this.mml = EnrichMathml.rewriteMfenced(this.mml);
}
else {
const newChildren = [lfence, this.mml];
if (rfence) {
newChildren.push(rfence);
}
this.mml = EnrichMathml.introduceNewLayer(newChildren, this.semantic);
}
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
return this.mml;
}
}
exports.CaseTable = CaseTable;

View File

@@ -0,0 +1,7 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { CaseMultiindex } from './case_multiindex.js';
export declare class CaseTensor extends CaseMultiindex {
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseTensor = void 0;
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const semantic_skeleton_js_1 = require("../semantic_tree/semantic_skeleton.js");
const case_multiindex_js_1 = require("./case_multiindex.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseTensor extends case_multiindex_js_1.CaseMultiindex {
static test(semantic) {
return !!semantic.mathmlTree && semantic.type === semantic_meaning_js_1.SemanticType.TENSOR;
}
constructor(semantic) {
super(semantic);
}
getMathml() {
EnrichMathml.walkTree(this.semantic.childNodes[0]);
const lsub = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]);
const lsup = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[2]);
const rsub = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[3]);
const rsup = case_multiindex_js_1.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[4]);
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
const collapsed = [
this.semantic.id,
this.semantic.childNodes[0].id,
lsub,
lsup,
rsub,
rsup
];
EnrichMathml.addCollapsedAttribute(this.mml, collapsed);
const childIds = semantic_skeleton_js_1.SemanticSkeleton.collapsedLeafs(lsub, lsup, rsub, rsup);
childIds.unshift(this.semantic.childNodes[0].id);
this.mml.setAttribute(enrich_attr_js_1.Attribute.CHILDREN, childIds.join(','));
this.completeMultiscript(semantic_skeleton_js_1.SemanticSkeleton.interleaveIds(rsub, rsup), semantic_skeleton_js_1.SemanticSkeleton.interleaveIds(lsub, lsup));
return this.mml;
}
}
exports.CaseTensor = CaseTensor;

View File

@@ -0,0 +1,8 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
import { AbstractEnrichCase } from './abstract_enrich_case.js';
export declare class CaseText extends AbstractEnrichCase {
mml: Element;
static test(semantic: SemanticNode): boolean;
constructor(semantic: SemanticNode);
getMathml(): Element;
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseText = void 0;
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const abstract_enrich_case_js_1 = require("./abstract_enrich_case.js");
const EnrichMathml = require("./enrich_mathml.js");
const enrich_attr_js_1 = require("./enrich_attr.js");
class CaseText extends abstract_enrich_case_js_1.AbstractEnrichCase {
static test(semantic) {
return (semantic.type === semantic_meaning_js_1.SemanticType.PUNCTUATED &&
(semantic.role === semantic_meaning_js_1.SemanticRole.TEXT ||
semantic.contentNodes.every((x) => x.role === semantic_meaning_js_1.SemanticRole.DUMMY)));
}
constructor(semantic) {
super(semantic);
this.mml = semantic.mathmlTree;
}
getMathml() {
const children = [];
const collapsed = EnrichMathml.collapsePunctuated(this.semantic, children);
this.mml = EnrichMathml.introduceNewLayer(children, this.semantic);
(0, enrich_attr_js_1.setAttributes)(this.mml, this.semantic);
this.mml.removeAttribute(enrich_attr_js_1.Attribute.CONTENT);
EnrichMathml.addCollapsedAttribute(this.mml, collapsed);
return this.mml;
}
}
exports.CaseText = CaseText;

View File

@@ -0,0 +1,6 @@
import './enrich_case_factory.js';
export declare function semanticMathmlNode(mml: Element): Element;
export declare function semanticMathmlSync(expr: string): Element;
export declare function semanticMathml(expr: string, callback: (p1: Element) => any): void;
export declare function testTranslation(expr: string): Element;
export declare function prepareMmlString(expr: string): string;

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.semanticMathmlNode = semanticMathmlNode;
exports.semanticMathmlSync = semanticMathmlSync;
exports.semanticMathml = semanticMathml;
exports.testTranslation = testTranslation;
exports.prepareMmlString = prepareMmlString;
const debugger_js_1 = require("../common/debugger.js");
const DomUtil = require("../common/dom_util.js");
const engine_js_1 = require("../common/engine.js");
const Semantic = require("../semantic_tree/semantic.js");
const EnrichMathml = require("./enrich_mathml.js");
require("./enrich_case_factory.js");
function semanticMathmlNode(mml) {
const clone = DomUtil.cloneNode(mml);
const tree = Semantic.getTree(clone);
return EnrichMathml.enrich(clone, tree);
}
function semanticMathmlSync(expr) {
const mml = DomUtil.parseInput(expr);
return semanticMathmlNode(mml);
}
function semanticMathml(expr, callback) {
engine_js_1.EnginePromise.getall().then(() => {
const mml = DomUtil.parseInput(expr);
callback(semanticMathmlNode(mml));
});
}
function testTranslation(expr) {
debugger_js_1.Debugger.getInstance().init();
const mml = semanticMathmlSync(prepareMmlString(expr));
debugger_js_1.Debugger.getInstance().exit();
return mml;
}
function prepareMmlString(expr) {
if (!expr.match(/^<math/)) {
expr = '<math>' + expr;
}
if (!expr.match(/\/math>$/)) {
expr += '</math>';
}
return expr;
}

View File

@@ -0,0 +1,30 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
export declare enum Attribute {
ADDED = "data-semantic-added",
ALTERNATIVE = "data-semantic-alternative",
CHILDREN = "data-semantic-children",
COLLAPSED = "data-semantic-collapsed",
CONTENT = "data-semantic-content",
EMBELLISHED = "data-semantic-embellished",
FENCEPOINTER = "data-semantic-fencepointer",
FONT = "data-semantic-font",
ID = "data-semantic-id",
ANNOTATION = "data-semantic-annotation",
ATTRIBUTES = "data-semantic-attributes",
OPERATOR = "data-semantic-operator",
OWNS = "data-semantic-owns",
PARENT = "data-semantic-parent",
POSTFIX = "data-semantic-postfix",
PREFIX = "data-semantic-prefix",
ROLE = "data-semantic-role",
SPEECH = "data-semantic-speech",
STRUCTURE = "data-semantic-structure",
SUMMARY = "data-semantic-summary",
TYPE = "data-semantic-type"
}
export declare const EnrichAttributes: string[];
export declare function makeIdList(nodes: SemanticNode[]): string;
export declare function setAttributes(mml: Element, semantic: SemanticNode): void;
export declare function removeAttributePrefix(mml: string): string;
export declare function addPrefix(attr: string): Attribute;
export declare function addMrow(): Element;

View File

@@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnrichAttributes = exports.Attribute = void 0;
exports.makeIdList = makeIdList;
exports.setAttributes = setAttributes;
exports.removeAttributePrefix = removeAttributePrefix;
exports.addPrefix = addPrefix;
exports.addMrow = addMrow;
const DomUtil = require("../common/dom_util.js");
const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
const Prefix = 'data-semantic-';
var Attribute;
(function (Attribute) {
Attribute["ADDED"] = "data-semantic-added";
Attribute["ALTERNATIVE"] = "data-semantic-alternative";
Attribute["CHILDREN"] = "data-semantic-children";
Attribute["COLLAPSED"] = "data-semantic-collapsed";
Attribute["CONTENT"] = "data-semantic-content";
Attribute["EMBELLISHED"] = "data-semantic-embellished";
Attribute["FENCEPOINTER"] = "data-semantic-fencepointer";
Attribute["FONT"] = "data-semantic-font";
Attribute["ID"] = "data-semantic-id";
Attribute["ANNOTATION"] = "data-semantic-annotation";
Attribute["ATTRIBUTES"] = "data-semantic-attributes";
Attribute["OPERATOR"] = "data-semantic-operator";
Attribute["OWNS"] = "data-semantic-owns";
Attribute["PARENT"] = "data-semantic-parent";
Attribute["POSTFIX"] = "data-semantic-postfix";
Attribute["PREFIX"] = "data-semantic-prefix";
Attribute["ROLE"] = "data-semantic-role";
Attribute["SPEECH"] = "data-semantic-speech";
Attribute["STRUCTURE"] = "data-semantic-structure";
Attribute["SUMMARY"] = "data-semantic-summary";
Attribute["TYPE"] = "data-semantic-type";
})(Attribute || (exports.Attribute = Attribute = {}));
exports.EnrichAttributes = [
Attribute.ADDED,
Attribute.ALTERNATIVE,
Attribute.CHILDREN,
Attribute.COLLAPSED,
Attribute.CONTENT,
Attribute.EMBELLISHED,
Attribute.FENCEPOINTER,
Attribute.FONT,
Attribute.ID,
Attribute.ANNOTATION,
Attribute.ATTRIBUTES,
Attribute.OPERATOR,
Attribute.OWNS,
Attribute.PARENT,
Attribute.POSTFIX,
Attribute.PREFIX,
Attribute.ROLE,
Attribute.SPEECH,
Attribute.STRUCTURE,
Attribute.SUMMARY,
Attribute.TYPE
];
function makeIdList(nodes) {
return nodes
.map(function (node) {
return node.id;
})
.join(',');
}
function setAttributes(mml, semantic) {
mml.setAttribute(Attribute.TYPE, semantic.type);
const attributes = semantic.allAttributes();
for (let i = 0, attr; (attr = attributes[i]); i++) {
mml.setAttribute(Prefix + attr[0].toLowerCase(), attr[1]);
}
if (semantic.childNodes.length) {
mml.setAttribute(Attribute.CHILDREN, makeIdList(semantic.childNodes));
}
if (semantic.contentNodes.length) {
mml.setAttribute(Attribute.CONTENT, makeIdList(semantic.contentNodes));
}
if (semantic.parent) {
mml.setAttribute(Attribute.PARENT, semantic.parent.id.toString());
}
const external = semantic.attributesXml();
if (external) {
mml.setAttribute(Attribute.ATTRIBUTES, external);
}
setPostfix(mml, semantic);
}
function setPostfix(mml, semantic) {
const postfix = [];
if (semantic.role === semantic_meaning_js_1.SemanticRole.MGLYPH) {
postfix.push('image');
}
if (semantic.attributes['href']) {
postfix.push('link');
}
if (postfix.length) {
mml.setAttribute(Attribute.POSTFIX, postfix.join(' '));
}
}
function removeAttributePrefix(mml) {
return mml.toString().replace(new RegExp(Prefix, 'g'), '');
}
function addPrefix(attr) {
return (Prefix + attr);
}
function addMrow() {
const mrow = DomUtil.createElement('mrow');
mrow.setAttribute(Attribute.ADDED, 'true');
return mrow;
}

View File

@@ -0,0 +1,11 @@
import { SemanticNode } from '../semantic_tree/semantic_node.js';
export interface EnrichCase {
getMathml(): Element;
}
interface Case {
test: (p1: SemanticNode) => boolean;
constr: (p1: SemanticNode) => EnrichCase;
}
export declare function getCase(node: SemanticNode): EnrichCase;
export declare const factory: Case[];
export {};

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.factory = void 0;
exports.getCase = getCase;
function getCase(node) {
for (let i = 0, enrich; (enrich = exports.factory[i]); i++) {
if (enrich.test(node)) {
return enrich.constr(node);
}
}
return null;
}
exports.factory = [];

View File

@@ -0,0 +1 @@
export {};

Some files were not shown because too many files have changed in this diff Show More