summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/bg/data/default-anki-field-templates.handlebars161
-rw-r--r--ext/bg/js/backend.js20
-rw-r--r--ext/bg/js/options.js177
-rw-r--r--ext/bg/js/settings/anki-templates.js16
-rw-r--r--ext/bg/js/settings/backup.js8
-rw-r--r--ext/mixed/js/api.js4
-rw-r--r--package-lock.json672
-rw-r--r--package.json5
-rw-r--r--test/data/html/test-document1.html264
-rw-r--r--test/data/html/test-stylesheet.css32
-rw-r--r--test/test-document.js224
-rw-r--r--test/test-stylesheet.css32
12 files changed, 1418 insertions, 197 deletions
diff --git a/ext/bg/data/default-anki-field-templates.handlebars b/ext/bg/data/default-anki-field-templates.handlebars
new file mode 100644
index 00000000..0442f7c5
--- /dev/null
+++ b/ext/bg/data/default-anki-field-templates.handlebars
@@ -0,0 +1,161 @@
+{{#*inline "glossary-single"}}
+ {{~#unless brief~}}
+ {{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}
+ {{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
+ {{~/unless~}}
+ {{~#if glossary.[1]~}}
+ {{~#if compactGlossaries~}}
+ {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}}
+ {{~else~}}
+ <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>
+ {{~/if~}}
+ {{~else~}}
+ {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "audio"}}{{/inline}}
+
+{{#*inline "character"}}
+ {{~definition.character~}}
+{{/inline}}
+
+{{#*inline "dictionary"}}
+ {{~definition.dictionary~}}
+{{/inline}}
+
+{{#*inline "expression"}}
+ {{~#if merge~}}
+ {{~#if modeTermKana~}}
+ {{~#each definition.reading~}}
+ {{{.}}}
+ {{~#unless @last}}、{{/unless~}}
+ {{~else~}}
+ {{~#each definition.expression~}}
+ {{{.}}}
+ {{~#unless @last}}、{{/unless~}}
+ {{~/each~}}
+ {{~/each~}}
+ {{~else~}}
+ {{~#each definition.expression~}}
+ {{{.}}}
+ {{~#unless @last}}、{{/unless~}}
+ {{~/each~}}
+ {{~/if~}}
+ {{~else~}}
+ {{~#if modeTermKana~}}
+ {{~#if definition.reading~}}
+ {{definition.reading}}
+ {{~else~}}
+ {{definition.expression}}
+ {{~/if~}}
+ {{~else~}}
+ {{definition.expression}}
+ {{~/if~}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "furigana"}}
+ {{~#if merge~}}
+ {{~#each definition.expressions~}}
+ <span class="expression-{{termFrequency}}">{{~#furigana}}{{{.}}}{{/furigana~}}</span>
+ {{~#unless @last}}、{{/unless~}}
+ {{~/each~}}
+ {{~else~}}
+ {{#furigana}}{{{definition}}}{{/furigana}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "furigana-plain"}}
+ {{~#if merge~}}
+ {{~#each definition.expressions~}}
+ <span class="expression-{{termFrequency}}">{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}</span>
+ {{~#unless @last}}、{{/unless~}}
+ {{~/each~}}
+ {{~else~}}
+ {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}}
+ {{~/if~}}
+{{/inline}}
+
+{{#*inline "glossary"}}
+ <div style="text-align: left;">
+ {{~#if modeKanji~}}
+ {{~#if definition.glossary.[1]~}}
+ <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol>
+ {{~else~}}
+ {{definition.glossary.[0]}}
+ {{~/if~}}
+ {{~else~}}
+ {{~#if group~}}
+ {{~#if definition.definitions.[1]~}}
+ <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
+ {{~else~}}
+ {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
+ {{~/if~}}
+ {{~else if merge~}}
+ {{~#if definition.definitions.[1]~}}
+ <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
+ {{~else~}}
+ {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
+ {{~/if~}}
+ {{~else~}}
+ {{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries~}}
+ {{~/if~}}
+ {{~/if~}}
+ </div>
+{{/inline}}
+
+{{#*inline "glossary-brief"}}
+ {{~> glossary brief=true ~}}
+{{/inline}}
+
+{{#*inline "kunyomi"}}
+ {{~#each definition.kunyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
+{{/inline}}
+
+{{#*inline "onyomi"}}
+ {{~#each definition.onyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
+{{/inline}}
+
+{{#*inline "reading"}}
+ {{~#unless modeTermKana~}}
+ {{~#if merge~}}
+ {{~#each definition.reading~}}
+ {{{.}}}
+ {{~#unless @last}}、{{/unless~}}
+ {{~/each~}}
+ {{~else~}}
+ {{~definition.reading~}}
+ {{~/if~}}
+ {{~/unless~}}
+{{/inline}}
+
+{{#*inline "sentence"}}
+ {{~#if definition.cloze}}{{definition.cloze.sentence}}{{/if~}}
+{{/inline}}
+
+{{#*inline "cloze-prefix"}}
+ {{~#if definition.cloze}}{{definition.cloze.prefix}}{{/if~}}
+{{/inline}}
+
+{{#*inline "cloze-body"}}
+ {{~#if definition.cloze}}{{definition.cloze.body}}{{/if~}}
+{{/inline}}
+
+{{#*inline "cloze-suffix"}}
+ {{~#if definition.cloze}}{{definition.cloze.suffix}}{{/if~}}
+{{/inline}}
+
+{{#*inline "tags"}}
+ {{~#each definition.definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}}
+{{/inline}}
+
+{{#*inline "url"}}
+ <a href="{{definition.url}}">{{definition.url}}</a>
+{{/inline}}
+
+{{#*inline "screenshot"}}
+ <img src="{{definition.screenshotFileName}}" />
+{{/inline}}
+
+{{~> (lookup . "marker") ~}} \ No newline at end of file
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 238ac52c..b99d1ca4 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -17,7 +17,7 @@
*/
/*global optionsSave, utilIsolate
-conditionsTestValue, profileConditionsDescriptor, profileOptionsGetDefaultFieldTemplates
+conditionsTestValue, profileConditionsDescriptor
handlebarsRenderDynamic
requestText, requestJson, optionsLoad
dictConfigured, dictTermsSort, dictEnabledSet, dictNoteFormat
@@ -33,6 +33,7 @@ class Backend {
this.clipboardMonitor = new ClipboardMonitor();
this.options = null;
this.optionsSchema = null;
+ this.defaultAnkiFieldTemplates = null;
this.optionsContext = {
depth: 0,
url: window.location.href
@@ -74,7 +75,8 @@ class Backend {
['getDisplayTemplatesHtml', this._onApiGetDisplayTemplatesHtml.bind(this)],
['getQueryParserTemplatesHtml', this._onApiGetQueryParserTemplatesHtml.bind(this)],
['getZoom', this._onApiGetZoom.bind(this)],
- ['getMessageToken', this._onApiGetMessageToken.bind(this)]
+ ['getMessageToken', this._onApiGetMessageToken.bind(this)],
+ ['getDefaultAnkiFieldTemplates', this._onApiGetDefaultAnkiFieldTemplates.bind(this)]
]);
this._commandHandlers = new Map([
@@ -89,6 +91,7 @@ class Backend {
await this.translator.prepare();
this.optionsSchema = await requestJson(chrome.runtime.getURL('/bg/data/options-schema.json'), 'GET');
+ this.defaultAnkiFieldTemplates = await requestText(chrome.runtime.getURL('/bg/data/default-anki-field-templates.handlebars'), 'GET');
this.options = await optionsLoad();
try {
this.options = JsonSchema.getValidValueOrDefault(this.optionsSchema, this.options);
@@ -423,7 +426,7 @@ class Backend {
async _onApiDefinitionAdd({definition, mode, context, optionsContext}) {
const options = await this.getOptions(optionsContext);
- const templates = Backend._getTemplates(options);
+ const templates = this.defaultAnkiFieldTemplates;
if (mode !== 'kanji') {
await audioInject(
@@ -448,7 +451,7 @@ class Backend {
async _onApiDefinitionsAddable({definitions, modes, optionsContext}) {
const options = await this.getOptions(optionsContext);
- const templates = Backend._getTemplates(options);
+ const templates = this.defaultAnkiFieldTemplates;
const states = [];
try {
@@ -656,6 +659,10 @@ class Backend {
return this.messageToken;
}
+ async _onApiGetDefaultAnkiFieldTemplates() {
+ return this.defaultAnkiFieldTemplates;
+ }
+
// Command handlers
async _onCommandSearch(params) {
@@ -896,11 +903,6 @@ class Backend {
return 'chrome';
}
}
-
- static _getTemplates(options) {
- const templates = options.anki.fieldTemplates;
- return typeof templates === 'string' ? templates : profileOptionsGetDefaultFieldTemplates();
- }
}
window.yomichanBackend = new Backend();
diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js
index f9db99a2..879b4a59 100644
--- a/ext/bg/js/options.js
+++ b/ext/bg/js/options.js
@@ -58,22 +58,17 @@ const profileOptionsVersionUpdates = [
options.scanning.modifier = options.scanning.requireShift ? 'shift' : 'none';
},
(options) => {
- const fieldTemplatesDefault = profileOptionsGetDefaultFieldTemplates();
options.general.resultOutputMode = options.general.groupResults ? 'group' : 'split';
- options.anki.fieldTemplates = (
- (utilStringHashCode(options.anki.fieldTemplates) !== -805327496) ?
- `{{#if merge}}${fieldTemplatesDefault}{{else}}${options.anki.fieldTemplates}{{/if}}` :
- fieldTemplatesDefault
- );
+ options.anki.fieldTemplates = null;
},
(options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) {
- options.anki.fieldTemplates = profileOptionsGetDefaultFieldTemplates();
+ options.anki.fieldTemplates = null;
}
},
(options) => {
if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) {
- options.anki.fieldTemplates = profileOptionsGetDefaultFieldTemplates();
+ options.anki.fieldTemplates = null;
}
},
(options) => {
@@ -97,172 +92,6 @@ const profileOptionsVersionUpdates = [
}
];
-function profileOptionsGetDefaultFieldTemplates() {
- return `
-{{#*inline "glossary-single"}}
- {{~#unless brief~}}
- {{~#if definitionTags~}}<i>({{#each definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each}})</i> {{/if~}}
- {{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
- {{~/unless~}}
- {{~#if glossary.[1]~}}
- {{~#if compactGlossaries~}}
- {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}}
- {{~else~}}
- <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>
- {{~/if~}}
- {{~else~}}
- {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}}
- {{~/if~}}
-{{/inline}}
-
-{{#*inline "audio"}}{{/inline}}
-
-{{#*inline "character"}}
- {{~definition.character~}}
-{{/inline}}
-
-{{#*inline "dictionary"}}
- {{~definition.dictionary~}}
-{{/inline}}
-
-{{#*inline "expression"}}
- {{~#if merge~}}
- {{~#if modeTermKana~}}
- {{~#each definition.reading~}}
- {{{.}}}
- {{~#unless @last}}、{{/unless~}}
- {{~else~}}
- {{~#each definition.expression~}}
- {{{.}}}
- {{~#unless @last}}、{{/unless~}}
- {{~/each~}}
- {{~/each~}}
- {{~else~}}
- {{~#each definition.expression~}}
- {{{.}}}
- {{~#unless @last}}、{{/unless~}}
- {{~/each~}}
- {{~/if~}}
- {{~else~}}
- {{~#if modeTermKana~}}
- {{~#if definition.reading~}}
- {{definition.reading}}
- {{~else~}}
- {{definition.expression}}
- {{~/if~}}
- {{~else~}}
- {{definition.expression}}
- {{~/if~}}
- {{~/if~}}
-{{/inline}}
-
-{{#*inline "furigana"}}
- {{~#if merge~}}
- {{~#each definition.expressions~}}
- <span class="expression-{{termFrequency}}">{{~#furigana}}{{{.}}}{{/furigana~}}</span>
- {{~#unless @last}}、{{/unless~}}
- {{~/each~}}
- {{~else~}}
- {{#furigana}}{{{definition}}}{{/furigana}}
- {{~/if~}}
-{{/inline}}
-
-{{#*inline "furigana-plain"}}
- {{~#if merge~}}
- {{~#each definition.expressions~}}
- <span class="expression-{{termFrequency}}">{{~#furiganaPlain}}{{{.}}}{{/furiganaPlain~}}</span>
- {{~#unless @last}}、{{/unless~}}
- {{~/each~}}
- {{~else~}}
- {{#furiganaPlain}}{{{definition}}}{{/furiganaPlain}}
- {{~/if~}}
-{{/inline}}
-
-{{#*inline "glossary"}}
- <div style="text-align: left;">
- {{~#if modeKanji~}}
- {{~#if definition.glossary.[1]~}}
- <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol>
- {{~else~}}
- {{definition.glossary.[0]}}
- {{~/if~}}
- {{~else~}}
- {{~#if group~}}
- {{~#if definition.definitions.[1]~}}
- <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
- {{~else~}}
- {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
- {{~/if~}}
- {{~else if merge~}}
- {{~#if definition.definitions.[1]~}}
- <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries}}</li>{{/each}}</ol>
- {{~else~}}
- {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries~}}
- {{~/if~}}
- {{~else~}}
- {{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries~}}
- {{~/if~}}
- {{~/if~}}
- </div>
-{{/inline}}
-
-{{#*inline "glossary-brief"}}
- {{~> glossary brief=true ~}}
-{{/inline}}
-
-{{#*inline "kunyomi"}}
- {{~#each definition.kunyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
-{{/inline}}
-
-{{#*inline "onyomi"}}
- {{~#each definition.onyomi}}{{.}}{{#unless @last}}, {{/unless}}{{/each~}}
-{{/inline}}
-
-{{#*inline "reading"}}
- {{~#unless modeTermKana~}}
- {{~#if merge~}}
- {{~#each definition.reading~}}
- {{{.}}}
- {{~#unless @last}}、{{/unless~}}
- {{~/each~}}
- {{~else~}}
- {{~definition.reading~}}
- {{~/if~}}
- {{~/unless~}}
-{{/inline}}
-
-{{#*inline "sentence"}}
- {{~#if definition.cloze}}{{definition.cloze.sentence}}{{/if~}}
-{{/inline}}
-
-{{#*inline "cloze-prefix"}}
- {{~#if definition.cloze}}{{definition.cloze.prefix}}{{/if~}}
-{{/inline}}
-
-{{#*inline "cloze-body"}}
- {{~#if definition.cloze}}{{definition.cloze.body}}{{/if~}}
-{{/inline}}
-
-{{#*inline "cloze-suffix"}}
- {{~#if definition.cloze}}{{definition.cloze.suffix}}{{/if~}}
-{{/inline}}
-
-{{#*inline "tags"}}
- {{~#each definition.definitionTags}}{{name}}{{#unless @last}}, {{/unless}}{{/each~}}
-{{/inline}}
-
-{{#*inline "url"}}
- <a href="{{definition.url}}">{{definition.url}}</a>
-{{/inline}}
-
-{{#*inline "screenshot"}}
- <img src="{{definition.screenshotFileName}}" />
-{{/inline}}
-
-{{~> (lookup . "marker") ~}}
-`.trim();
-}
-
function profileOptionsCreateDefaults() {
return {
general: {
diff --git a/ext/bg/js/settings/anki-templates.js b/ext/bg/js/settings/anki-templates.js
index 770716d4..244ec42e 100644
--- a/ext/bg/js/settings/anki-templates.js
+++ b/ext/bg/js/settings/anki-templates.js
@@ -17,21 +17,23 @@
*/
/*global getOptionsContext, getOptionsMutable, settingsSaveOptions
-profileOptionsGetDefaultFieldTemplates, ankiGetFieldMarkers, ankiGetFieldMarkersHtml, dictFieldFormat
-apiOptionsGet, apiTermsFind*/
+ankiGetFieldMarkers, ankiGetFieldMarkersHtml, dictFieldFormat
+apiOptionsGet, apiTermsFind, apiGetDefaultAnkiFieldTemplates*/
function onAnkiFieldTemplatesReset(e) {
e.preventDefault();
$('#field-template-reset-modal').modal('show');
}
-function onAnkiFieldTemplatesResetConfirm(e) {
+async function onAnkiFieldTemplatesResetConfirm(e) {
e.preventDefault();
$('#field-template-reset-modal').modal('hide');
+ const value = await apiGetDefaultAnkiFieldTemplates();
+
const element = document.querySelector('#field-templates');
- element.value = profileOptionsGetDefaultFieldTemplates();
+ element.value = value;
element.dispatchEvent(new Event('change'));
}
@@ -57,7 +59,7 @@ async function ankiTemplatesUpdateValue() {
const optionsContext = getOptionsContext();
const options = await apiOptionsGet(optionsContext);
let templates = options.anki.fieldTemplates;
- if (typeof templates !== 'string') { templates = profileOptionsGetDefaultFieldTemplates(); }
+ if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); }
$('#field-templates').val(templates);
onAnkiTemplatesValidateCompile();
@@ -89,7 +91,7 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i
if (definition !== null) {
const options = await apiOptionsGet(optionsContext);
let templates = options.anki.fieldTemplates;
- if (typeof templates !== 'string') { templates = profileOptionsGetDefaultFieldTemplates(); }
+ if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); }
result = await dictFieldFormat(field, definition, mode, options, templates, exceptions);
}
} catch (e) {
@@ -109,7 +111,7 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i
async function onAnkiFieldTemplatesChanged(e) {
// Get value
let templates = e.currentTarget.value;
- if (templates === profileOptionsGetDefaultFieldTemplates()) {
+ if (templates === await apiGetDefaultAnkiFieldTemplates()) {
// Default
templates = null;
}
diff --git a/ext/bg/js/settings/backup.js b/ext/bg/js/settings/backup.js
index f4d622a4..e945d186 100644
--- a/ext/bg/js/settings/backup.js
+++ b/ext/bg/js/settings/backup.js
@@ -16,10 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*global apiOptionsGetFull, apiGetEnvironmentInfo
+/*global apiOptionsGetFull, apiGetEnvironmentInfo, apiGetDefaultAnkiFieldTemplates
utilBackend, utilIsolate, utilBackgroundIsolate, utilReadFileArrayBuffer
-optionsGetDefault, optionsUpdateVersion
-profileOptionsGetDefaultFieldTemplates*/
+optionsGetDefault, optionsUpdateVersion*/
// Exporting
@@ -47,8 +46,7 @@ function _getSettingsExportDateString(date, dateSeparator, dateTimeSeparator, ti
async function _getSettingsExportData(date) {
const optionsFull = await apiOptionsGetFull();
const environment = await apiGetEnvironmentInfo();
-
- const fieldTemplatesDefault = profileOptionsGetDefaultFieldTemplates();
+ const fieldTemplatesDefault = await apiGetDefaultAnkiFieldTemplates();
// Format options
for (const {options} of optionsFull.profiles) {
diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js
index 7ea68d59..26f4389d 100644
--- a/ext/mixed/js/api.js
+++ b/ext/mixed/js/api.js
@@ -117,6 +117,10 @@ function apiGetMessageToken() {
return _apiInvoke('getMessageToken');
}
+function apiGetDefaultAnkiFieldTemplates() {
+ return _apiInvoke('getDefaultAnkiFieldTemplates');
+}
+
function _apiInvoke(action, params={}) {
const data = {action, params};
return new Promise((resolve, reject) => {
diff --git a/package-lock.json b/package-lock.json
index 505c71db..88ba43f6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,18 +24,48 @@
"js-tokens": "^4.0.0"
}
},
+ "abab": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
+ "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
+ "dev": true
+ },
"acorn": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
"dev": true
},
+ "acorn-globals": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
+ "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.1",
+ "acorn-walk": "^6.0.1"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
+ "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==",
+ "dev": true
+ }
+ }
+ },
"acorn-jsx": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
"integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
"dev": true
},
+ "acorn-walk": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
+ "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+ "dev": true
+ },
"ajv": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
@@ -81,12 +111,45 @@
"sprintf-js": "~1.0.2"
}
},
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
"astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true
},
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
+ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==",
+ "dev": true
+ },
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -99,6 +162,15 @@
"integrity": "sha512-UCIPaDJrNNj5jG2ZL+nzJ7czvZV/ZYX6LaIRgfVU1k1edJOQg7dkbiSKzwHkNp6aHEHER/PhlFBrMYnlvJJQEw==",
"dev": true
},
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -109,12 +181,24 @@
"concat-map": "0.0.1"
}
},
+ "browser-process-hrtime": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
+ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==",
+ "dev": true
+ },
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true
},
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -162,6 +246,15 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -174,6 +267,12 @@
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
"dev": true
},
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -195,6 +294,77 @@
}
}
},
+ "cssom": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz",
+ "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==",
+ "dev": true
+ },
+ "cssstyle": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz",
+ "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==",
+ "dev": true,
+ "requires": {
+ "cssom": "~0.3.6"
+ },
+ "dependencies": {
+ "cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true
+ }
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "data-urls": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
+ "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.3",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.0.0"
+ },
+ "dependencies": {
+ "tr46": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz",
+ "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.1"
+ }
+ },
+ "webidl-conversions": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+ "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.0.0.tgz",
+ "integrity": "sha512-41ou2Dugpij8/LPO5Pq64K5q++MnRCBpEHvQr26/mArEKTkCV5aoXIqyhuYtE0pkqScXwhf2JP57rkRTYM29lQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^2.0.0",
+ "webidl-conversions": "^5.0.0"
+ }
+ }
+ }
+ },
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -204,12 +374,24 @@
"ms": "^2.1.1"
}
},
+ "decimal.js": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz",
+ "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==",
+ "dev": true
+ },
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -228,6 +410,16 @@
"webidl-conversions": "^4.0.2"
}
},
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -240,6 +432,19 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
+ "escodegen": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
+ "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
+ "dev": true,
+ "requires": {
+ "esprima": "^4.0.1",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
+ }
+ },
"eslint": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
@@ -363,6 +568,12 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
"external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -374,6 +585,12 @@
"tmp": "^0.0.33"
}
},
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
"fake-indexeddb": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/fake-indexeddb/-/fake-indexeddb-3.0.0.tgz",
@@ -437,6 +654,23 @@
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
"dev": true
},
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -449,6 +683,15 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -481,12 +724,48 @@
"type-fest": "^0.8.1"
}
},
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
+ "html-encoding-sniffer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.0.tgz",
+ "integrity": "sha512-Y9prnPKkM7FXxQevZ5UH8Z6aVTY0ede1tHquck5UxGmKWDshxXh95gSa2xXYjS8AsGO5iOvrCI5+GttRKnLdNA==",
+ "dev": true,
+ "requires": {
+ "whatwg-encoding": "^1.0.5"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -555,6 +834,12 @@
"through": "^2.3.6"
}
},
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -576,18 +861,36 @@
"is-extglob": "^2.1.1"
}
},
+ "is-potential-custom-element-name": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz",
+ "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=",
+ "dev": true
+ },
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -604,6 +907,89 @@
"esprima": "^4.0.0"
}
},
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsdom": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.0.tgz",
+ "integrity": "sha512-6VaW3UWyKbm9DFVIAgTfhuwnvqiqlRYNg5Rk6dINTVoZT0eKz+N86vQZr+nqt1ny1lSB1TWZJWSEWQAfu8oTpA==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.3",
+ "acorn": "^7.1.0",
+ "acorn-globals": "^4.3.4",
+ "cssom": "^0.4.4",
+ "cssstyle": "^2.2.0",
+ "data-urls": "^2.0.0",
+ "decimal.js": "^10.2.0",
+ "domexception": "^2.0.1",
+ "escodegen": "^1.13.0",
+ "html-encoding-sniffer": "^2.0.0",
+ "is-potential-custom-element-name": "^1.0.0",
+ "nwsapi": "^2.2.0",
+ "parse5": "5.1.1",
+ "request": "^2.88.0",
+ "request-promise-native": "^1.0.8",
+ "saxes": "^4.0.2",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^3.0.1",
+ "w3c-hr-time": "^1.0.1",
+ "w3c-xmlserializer": "^2.0.0",
+ "webidl-conversions": "^5.0.0",
+ "whatwg-encoding": "^1.0.5",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.0.0",
+ "ws": "^7.2.1",
+ "xml-name-validator": "^3.0.0"
+ },
+ "dependencies": {
+ "domexception": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
+ "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==",
+ "dev": true,
+ "requires": {
+ "webidl-conversions": "^5.0.0"
+ }
+ },
+ "tr46": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz",
+ "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.1"
+ }
+ },
+ "webidl-conversions": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+ "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.0.0.tgz",
+ "integrity": "sha512-41ou2Dugpij8/LPO5Pq64K5q++MnRCBpEHvQr26/mArEKTkCV5aoXIqyhuYtE0pkqScXwhf2JP57rkRTYM29lQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^2.0.0",
+ "webidl-conversions": "^5.0.0"
+ }
+ }
+ }
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -616,6 +1002,24 @@
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@@ -638,6 +1042,21 @@
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
"dev": true
},
+ "mime-db": {
+ "version": "1.43.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+ "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.26",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+ "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.43.0"
+ }
+ },
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@@ -692,6 +1111,18 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
+ "nwsapi": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
+ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -739,6 +1170,12 @@
"callsites": "^3.0.0"
}
},
+ "parse5": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
+ "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
+ "dev": true
+ },
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -751,6 +1188,12 @@
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -763,12 +1206,24 @@
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
+ "psl": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
+ "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==",
+ "dev": true
+ },
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
"realistic-structured-clone": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/realistic-structured-clone/-/realistic-structured-clone-2.0.2.tgz",
@@ -787,6 +1242,78 @@
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
+ "request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ }
+ }
+ },
+ "request-promise-core": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
+ "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.15"
+ }
+ },
+ "request-promise-native": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
+ "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
+ "dev": true,
+ "requires": {
+ "request-promise-core": "1.1.3",
+ "stealthy-require": "^1.1.1",
+ "tough-cookie": "^2.3.3"
+ },
+ "dependencies": {
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ }
+ }
+ },
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -830,12 +1357,27 @@
"tslib": "^1.9.0"
}
},
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+ "dev": true
+ },
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
+ "saxes": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-4.0.2.tgz",
+ "integrity": "sha512-EZOTeQ4bgkOaGCDaTKux+LaRNcLNbdbvMH7R3/yjEEULPEmqvkFbFub6DJhJTub2iGMT93CfpZ5LTdKZmAbVeQ==",
+ "dev": true,
+ "requires": {
+ "xmlchars": "^2.2.0"
+ }
+ },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -888,12 +1430,42 @@
}
}
},
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "stealthy-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
+ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
+ "dev": true
+ },
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
@@ -948,6 +1520,12 @@
"has-flag": "^3.0.0"
}
},
+ "symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true
+ },
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
@@ -1006,6 +1584,17 @@
"os-tmpdir": "~1.0.2"
}
},
+ "tough-cookie": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
+ "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
+ "dev": true,
+ "requires": {
+ "ip-regex": "^2.1.0",
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ },
"tr46": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
@@ -1021,6 +1610,21 @@
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
"dev": true
},
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -1062,18 +1666,68 @@
"punycode": "^2.1.0"
}
},
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "dev": true
+ },
"v8-compile-cache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
"dev": true
},
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "w3c-hr-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",
+ "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=",
+ "dev": true,
+ "requires": {
+ "browser-process-hrtime": "^0.1.2"
+ }
+ },
+ "w3c-xmlserializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
+ "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==",
+ "dev": true,
+ "requires": {
+ "xml-name-validator": "^3.0.0"
+ }
+ },
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
"dev": true
},
+ "whatwg-encoding": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
+ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.24"
+ }
+ },
+ "whatwg-mimetype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
+ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
+ "dev": true
+ },
"whatwg-url": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
@@ -1114,6 +1768,24 @@
"requires": {
"mkdirp": "^0.5.1"
}
+ },
+ "ws": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz",
+ "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==",
+ "dev": true
+ },
+ "xml-name-validator": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true
+ },
+ "xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true
}
}
}
diff --git a/package.json b/package.json
index 17fdfa82..74d89dda 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"scripts": {
"test": "npm run test-lint && npm run test-code",
"test-lint": "eslint .",
- "test-code": "node ./test/test-schema.js && node ./test/test-dictionary.js && node ./test/test-database.js"
+ "test-code": "node ./test/test-schema.js && node ./test/test-dictionary.js && node ./test/test-database.js && node ./test/test-document.js"
},
"repository": {
"type": "git",
@@ -29,6 +29,7 @@
"devDependencies": {
"eslint": "^6.8.0",
"eslint-plugin-no-unsanitized": "^3.0.2",
- "fake-indexeddb": "^3.0.0"
+ "fake-indexeddb": "^3.0.0",
+ "jsdom": "^16.2.0"
}
}
diff --git a/test/data/html/test-document1.html b/test/data/html/test-document1.html
new file mode 100644
index 00000000..0754a314
--- /dev/null
+++ b/test/data/html/test-document1.html
@@ -0,0 +1,264 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
+ <title>Yomichan Tests</title>
+ <link rel="icon" type="image/gif" href="data:image/gif;base64,R0lGODlhEAAQAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAQABAAAAImFI6Zpt0B4YkS0TCpq07xbmEgcGVRUpLaI46ZG7ppalY0jDCwUAAAOw==" />
+ <link rel="stylesheet" href="test-stylesheet.css" />
+ </head>
+<body>
+
+ <h1>Yomichan Tests</h1>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="span"
+ data-caret-range-from-point-selector="span"
+ data-start-node-selector="span"
+ data-start-offset="0"
+ data-end-node-selector="span"
+ data-end-offset="0"
+ data-result-type="TextSourceRange",
+ data-sentence-extent="100"
+ data-sentence="真白「心配してくださって、ありがとございます」"
+ >
+ <span>真白「心配してくださって、ありがとございます」</span>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="span"
+ data-caret-range-from-point-selector="span"
+ data-start-node-selector="span"
+ data-start-offset="5"
+ data-end-node-selector="span"
+ data-end-offset="5"
+ data-result-type="TextSourceRange",
+ data-sentence-extent="100"
+ data-sentence="心配してくださって、ありがとございます"
+ >
+ <span>真白「心配してくださって、ありがとございます」</span>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="input"
+ data-caret-range-from-point-selector="input"
+ data-start-node-selector="input"
+ data-start-offset="0"
+ data-end-node-selector="input"
+ data-end-offset="0"
+ data-result-type="TextSourceRange",
+ data-sentence-extent="100"
+ data-sentence="真白「心配してくださって、ありがとございます」"
+ data-has-imposter="true"
+ >
+ <input type="text" value="真白「心配してくださって、ありがとございます」" style="width: 100%; box-sizing: border-box; font-family: inherit; font-size: inherit; border: 1px solid #d8d8d8; padding: 0.2em;" />
+ </div>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="textarea"
+ data-caret-range-from-point-selector="textarea"
+ data-start-node-selector="textarea"
+ data-start-offset="0"
+ data-end-node-selector="textarea"
+ data-end-offset="0"
+ data-result-type="TextSourceRange",
+ data-sentence-extent="100"
+ data-sentence="真白「心配してくださって、ありがとございます」"
+ data-has-imposter="true"
+ >
+ <textarea style="width: 100%; height: 3em; box-sizing: border-box; font-family: inherit; font-size: inherit; border: 1px solid #d8d8d8; padding: 0.2em;">真白「心配してくださって、ありがとございます」</textarea>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="button"
+ data-caret-range-from-point-selector="button"
+ data-start-node-selector="button"
+ data-start-offset="0"
+ data-end-node-selector="button"
+ data-end-offset="0"
+ data-result-type="TextSourceElement",
+ data-sentence-extent="100"
+ data-sentence="よみちゃん"
+ >
+ <button style="width: 100%; box-sizing: border-box; font-family: inherit; font-size: inherit; border: 1px solid #d8d8d8; background-color: #f0f0f0; padding: 0.2em;">よみちゃん</button>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="scan"
+ data-element-from-point-selector="img"
+ data-caret-range-from-point-selector="img"
+ data-start-node-selector="img"
+ data-start-offset="0"
+ data-end-node-selector="img"
+ data-end-offset="0"
+ data-result-type="TextSourceElement"
+ data-sentence="よみちゃん"
+ >
+ <img src="data:image/gif;base64,R0lGODdhBwAHAIABAAAAAP///ywAAAAABwAHAAACDIRvEaC32FpCbEkKCgA7" alt="よみちゃん" title="よみちゃん" style="width: 70px; height: 70px; image-rendering: crisp-edges; image-rendering: pixelated; display: block;" />
+ </div>
+
+ <div
+ class="test"
+ data-test-type="text-source-range-seek"
+ data-seek-node-selector="span:nth-of-type(1)"
+ data-seek-node-is-text="true"
+ data-seek-offset="0"
+ data-seek-length="149"
+ data-seek-direction="forward"
+ data-expected-result-node-selector="span:nth-of-type(1)"
+ data-expected-result-node-is-text="true"
+ data-expected-result-offset="149"
+ data-expected-result-content="
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ "
+ >
+ <span>
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ </span><span>trailing content</span>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="text-source-range-seek"
+ data-seek-node-selector="span:nth-of-type(1)"
+ data-seek-node-is-text="true"
+ data-seek-offset="149"
+ data-seek-length="149"
+ data-seek-direction="backward"
+ data-expected-result-node-selector="span:nth-of-type(1)"
+ data-expected-result-node-is-text="true"
+ data-expected-result-offset="0"
+ data-expected-result-content="
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ "
+ >
+ <span>
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ </span><span>trailing content</span>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="text-source-range-seek"
+ data-seek-node-selector="span:nth-of-type(1)"
+ data-seek-node-is-text="true"
+ data-seek-offset="0"
+ data-seek-length="150"
+ data-seek-direction="forward"
+ data-expected-result-node-selector="span:nth-of-type(2)"
+ data-expected-result-node-is-text="true"
+ data-expected-result-offset="1"
+ data-expected-result-content="
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ t"
+ >
+ <span>
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ </span><span>trailing content</span>
+ </div>
+
+ <div
+ class="test"
+ data-test-type="text-source-range-seek"
+ data-seek-node-selector="span:nth-of-type(2)"
+ data-seek-node-is-text="true"
+ data-seek-offset="1"
+ data-seek-length="150"
+ data-seek-direction="backward"
+ data-expected-result-node-selector="span:nth-of-type(1)"
+ data-expected-result-node-is-text="true"
+ data-expected-result-offset="0"
+ data-expected-result-content="
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ t"
+ >
+ <span>
+ あいうえお
+ かきくけこ
+ さしすせそ
+ たちつてと
+ なにぬねの
+ はひふへほ
+ まみむめも
+ や&#x3000;ゆ&#x3000;よ
+ らりるれろ
+ わゐ&#x3000;ゑを
+ </span><span>trailing content</span>
+ </div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/test/data/html/test-stylesheet.css b/test/data/html/test-stylesheet.css
new file mode 100644
index 00000000..ab25732e
--- /dev/null
+++ b/test/data/html/test-stylesheet.css
@@ -0,0 +1,32 @@
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ max-width: 680px;
+ padding: 0 1em;
+ box-sizing: border-box;
+ margin: 0 auto;
+ background-color: #f8f8f8;
+ counter-reset: test-id;
+}
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+.test {
+ background-color: #ffffff;
+ margin: 1em 0;
+ padding: 0.5em;
+ box-shadow: rgba(64, 64, 64, 0.3) 0px 1px 2px 0px, rgba(64, 64, 64, 0.15) 0px 1px 3px 1px;
+ border-radius: 4px;
+}
+
+.test:before {
+ content: "Test " counter(test-id);
+ display: block;
+ counter-increment: test-id;
+ margin-bottom: 0.5em;
+ border-bottom: 1px solid #d8d8d8;
+ font-weight: bold;
+}
diff --git a/test/test-document.js b/test/test-document.js
new file mode 100644
index 00000000..edf6bbea
--- /dev/null
+++ b/test/test-document.js
@@ -0,0 +1,224 @@
+const fs = require('fs');
+const path = require('path');
+const assert = require('assert');
+const {JSDOM} = require('jsdom');
+const yomichanTest = require('./yomichan-test');
+
+
+// DOMRect class definition
+class DOMRect {
+ constructor(x, y, width, height) {
+ this._x = x;
+ this._y = y;
+ this._width = width;
+ this._height = height;
+ }
+
+ get x() { return this._x; }
+ get y() { return this._y; }
+ get width() { return this._width; }
+ get height() { return this._height; }
+ get left() { return this._x + Math.min(0, this._width); }
+ get right() { return this._x + Math.max(0, this._width); }
+ get top() { return this._y + Math.min(0, this._height); }
+ get bottom() { return this._y + Math.max(0, this._height); }
+}
+
+
+function createJSDOM(fileName) {
+ const domSource = fs.readFileSync(fileName, {encoding: 'utf8'});
+ const dom = new JSDOM(domSource);
+ const document = dom.window.document;
+ const window = dom.window;
+
+ // Define innerText setter as an alias for textContent setter
+ Object.defineProperty(window.HTMLDivElement.prototype, 'innerText', {
+ set(value) { this.textContent = value; }
+ });
+
+ // Placeholder for feature detection
+ document.caretRangeFromPoint = () => null;
+
+ return dom;
+}
+
+function querySelectorChildOrSelf(element, selector) {
+ return selector ? element.querySelector(selector) : element;
+}
+
+function getChildTextNodeOrSelf(dom, node) {
+ if (node === null) { return null; }
+ const Node = dom.window.Node;
+ const childNode = node.firstChild;
+ return (childNode !== null && childNode.nodeType === Node.TEXT_NODE ? childNode : node);
+}
+
+function getPrototypeOfOrNull(value) {
+ try {
+ return Object.getPrototypeOf(value);
+ } catch (e) {
+ return null;
+ }
+}
+
+function findImposterElement(document) {
+ // Finds the imposter element based on it's z-index style
+ return document.querySelector('div[style*="2147483646"]>*');
+}
+
+
+async function testDocument1() {
+ const dom = createJSDOM(path.join(__dirname, 'data', 'html', 'test-document1.html'));
+ const window = dom.window;
+ const document = window.document;
+ const Node = window.Node;
+ const Range = window.Range;
+
+ const {DOM} = yomichanTest.requireScript(
+ 'ext/mixed/js/dom.js',
+ ['DOM']
+ );
+ const {TextSourceRange, TextSourceElement} = yomichanTest.requireScript(
+ 'ext/fg/js/source.js',
+ ['TextSourceRange', 'TextSourceElement'],
+ {document, window, Range, Node}
+ );
+ const {docRangeFromPoint, docSentenceExtract} = yomichanTest.requireScript(
+ 'ext/fg/js/document.js',
+ ['docRangeFromPoint', 'docSentenceExtract'],
+ {document, window, Node, TextSourceElement, TextSourceRange, DOM}
+ );
+
+ try {
+ await testDocumentTextScanningFunctions(dom, {docRangeFromPoint, docSentenceExtract, TextSourceRange, TextSourceElement});
+ await testTextSourceRangeSeekFunctions(dom, {TextSourceRange});
+ } finally {
+ window.close();
+ }
+}
+
+async function testDocumentTextScanningFunctions(dom, {docRangeFromPoint, docSentenceExtract, TextSourceRange, TextSourceElement}) {
+ const document = dom.window.document;
+
+ for (const testElement of document.querySelectorAll('.test[data-test-type=scan]')) {
+ // Get test parameters
+ let {
+ elementFromPointSelector,
+ caretRangeFromPointSelector,
+ startNodeSelector,
+ startOffset,
+ endNodeSelector,
+ endOffset,
+ resultType,
+ sentenceExtent,
+ sentence,
+ hasImposter
+ } = testElement.dataset;
+
+ const elementFromPointValue = querySelectorChildOrSelf(testElement, elementFromPointSelector);
+ const caretRangeFromPointValue = querySelectorChildOrSelf(testElement, caretRangeFromPointSelector);
+ const startNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, startNodeSelector));
+ const endNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, endNodeSelector));
+
+ startOffset = parseInt(startOffset, 10);
+ endOffset = parseInt(endOffset, 10);
+ sentenceExtent = parseInt(sentenceExtent, 10);
+
+ assert.notStrictEqual(elementFromPointValue, null);
+ assert.notStrictEqual(caretRangeFromPointValue, null);
+ assert.notStrictEqual(startNode, null);
+ assert.notStrictEqual(endNode, null);
+
+ // Setup functions
+ document.elementFromPoint = () => elementFromPointValue;
+
+ document.caretRangeFromPoint = (x, y) => {
+ const imposter = getChildTextNodeOrSelf(dom, findImposterElement(document));
+ assert.strictEqual(!!imposter, hasImposter === 'true');
+
+ const range = document.createRange();
+ range.setStart(imposter ? imposter : startNode, startOffset);
+ range.setEnd(imposter ? imposter : startNode, endOffset);
+
+ // Override getClientRects to return a rect guaranteed to contain (x, y)
+ range.getClientRects = () => [new DOMRect(x - 1, y - 1, 2, 2)];
+ return range;
+ };
+
+ // Test docRangeFromPoint
+ const source = docRangeFromPoint(0, 0, false);
+ switch (resultType) {
+ case 'TextSourceRange':
+ assert.strictEqual(getPrototypeOfOrNull(source), TextSourceRange.prototype);
+ break;
+ case 'TextSourceElement':
+ assert.strictEqual(getPrototypeOfOrNull(source), TextSourceElement.prototype);
+ break;
+ case 'null':
+ assert.strictEqual(source, null);
+ break;
+ default:
+ assert.ok(false);
+ break;
+ }
+ if (source === null) { continue; }
+
+ // Test docSentenceExtract
+ const sentenceActual = docSentenceExtract(source, sentenceExtent).text;
+ assert.strictEqual(sentenceActual, sentence);
+
+ // Clean
+ source.cleanup();
+ }
+}
+
+async function testTextSourceRangeSeekFunctions(dom, {TextSourceRange}) {
+ const document = dom.window.document;
+
+ for (const testElement of document.querySelectorAll('.test[data-test-type=text-source-range-seek]')) {
+ // Get test parameters
+ let {
+ seekNodeSelector,
+ seekNodeIsText,
+ seekOffset,
+ seekLength,
+ seekDirection,
+ expectedResultNodeSelector,
+ expectedResultNodeIsText,
+ expectedResultOffset,
+ expectedResultContent
+ } = testElement.dataset;
+
+ seekOffset = parseInt(seekOffset, 10);
+ seekLength = parseInt(seekLength, 10);
+ expectedResultOffset = parseInt(expectedResultOffset, 10);
+
+ let seekNode = testElement.querySelector(seekNodeSelector);
+ if (seekNodeIsText === 'true') {
+ seekNode = seekNode.firstChild;
+ }
+
+ let expectedResultNode = testElement.querySelector(expectedResultNodeSelector);
+ if (expectedResultNodeIsText === 'true') {
+ expectedResultNode = expectedResultNode.firstChild;
+ }
+
+ const {node, offset, content} = (
+ seekDirection === 'forward' ?
+ TextSourceRange.seekForward(seekNode, seekOffset, seekLength) :
+ TextSourceRange.seekBackward(seekNode, seekOffset, seekLength)
+ );
+
+ assert.strictEqual(node, expectedResultNode);
+ assert.strictEqual(offset, expectedResultOffset);
+ assert.strictEqual(content, expectedResultContent);
+ }
+}
+
+
+async function main() {
+ await testDocument1();
+}
+
+
+if (require.main === module) { main(); }
diff --git a/test/test-stylesheet.css b/test/test-stylesheet.css
new file mode 100644
index 00000000..ab25732e
--- /dev/null
+++ b/test/test-stylesheet.css
@@ -0,0 +1,32 @@
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ max-width: 680px;
+ padding: 0 1em;
+ box-sizing: border-box;
+ margin: 0 auto;
+ background-color: #f8f8f8;
+ counter-reset: test-id;
+}
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+.test {
+ background-color: #ffffff;
+ margin: 1em 0;
+ padding: 0.5em;
+ box-shadow: rgba(64, 64, 64, 0.3) 0px 1px 2px 0px, rgba(64, 64, 64, 0.15) 0px 1px 3px 1px;
+ border-radius: 4px;
+}
+
+.test:before {
+ content: "Test " counter(test-id);
+ display: block;
+ counter-increment: test-id;
+ margin-bottom: 0.5em;
+ border-bottom: 1px solid #d8d8d8;
+ font-weight: bold;
+}