Merge pull request #1020 from Bilb/spell-check-fixes

fix spell checker using the electron one
pull/1028/head
Audric Ackermann 5 years ago committed by GitHub
commit 0d0439cacc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -166,6 +166,11 @@
"description":
"Only available on development modes, menu option to open up the standalone device setup sequence"
},
"contextMenuNoSuggestions": {
"message": "No Suggestions",
"description":
"Shown in the context menu for a misspelled word to indicate that there are no suggestions to replace the misspelled word"
},
"connectingLoad": {
"message": "Connecting To Server",
"description":
@ -1414,6 +1419,11 @@
"message": "Enable spell check of text entered in message composition box",
"description": "Description of the media permission description"
},
"spellCheckDirty": {
"message": "You must restart Session to apply your new settings",
"description":
"Shown when the user changes their spellcheck setting to indicate that they must restart Signal."
},
"clearDataHeader": {
"message": "Clear All Local Data",
"description":

@ -0,0 +1,88 @@
/* global exports, require */
/* eslint-disable strict */
const { Menu } = require('electron');
const osLocale = require('os-locale');
exports.setup = (browserWindow, messages) => {
const { session } = browserWindow.webContents;
const userLocale = osLocale.sync().replace(/_/g, '-');
const userLocales = [userLocale, userLocale.split('-')[0]];
const available = session.availableSpellCheckerLanguages;
const languages = userLocales.filter(l => available.includes(l));
console.log(`spellcheck: user locale: ${userLocale}`);
console.log('spellcheck: available spellchecker languages: ', available);
console.log('spellcheck: setting languages to: ', languages);
session.setSpellCheckerLanguages(languages);
browserWindow.webContents.on('context-menu', (_event, params) => {
const { editFlags } = params;
const isMisspelled = Boolean(params.misspelledWord);
const showMenu = params.isEditable || editFlags.canCopy;
// Popup editor menu
if (showMenu) {
const template = [];
if (isMisspelled) {
if (params.dictionarySuggestions.length > 0) {
template.push(
...params.dictionarySuggestions.map(label => ({
label,
click: () => {
browserWindow.webContents.replaceMisspelling(label);
},
}))
);
} else {
template.push({
label: messages.contextMenuNoSuggestions.message,
enabled: false,
});
}
template.push({ type: 'separator' });
}
if (params.isEditable) {
if (editFlags.canUndo) {
template.push({ label: messages.editMenuUndo.message, role: 'undo' });
}
// This is only ever `true` if undo was triggered via the context menu
// (not ctrl/cmd+z)
if (editFlags.canRedo) {
template.push({ label: messages.editMenuRedo.message, role: 'redo' });
}
if (editFlags.canUndo || editFlags.canRedo) {
template.push({ type: 'separator' });
}
if (editFlags.canCut) {
template.push({ label: messages.editMenuCut.message, role: 'cut' });
}
}
if (editFlags.canPaste) {
template.push({ label: messages.editMenuPaste.message, role: 'paste' });
}
if (editFlags.canPaste) {
template.push({
label: messages.editMenuPasteAndMatchStyle.message,
role: 'pasteAndMatchStyle',
});
}
// Only enable select all in editors because select all in non-editors
// results in all the UI being selected
if (editFlags.canSelectAll && params.isEditable) {
template.push({
label: messages.editMenuSelectAll.message,
role: 'selectall',
});
}
const menu = Menu.buildFromTemplate(template);
menu.popup(browserWindow);
}
});
};

@ -67,7 +67,6 @@ module.exports = {
ELECTRON_ENABLE_STACK_DUMPING: true,
ELECTRON_DISABLE_SANDBOX: 1,
},
startTimeout: 10000,
requireName: 'electronRequire',
// chromeDriverLogPath: '../chromedriverlog.txt',
chromeDriverArgs: [

@ -320,7 +320,6 @@
getSpellCheck: () => storage.get('spell-check', true),
setSpellCheck: value => {
storage.put('spell-check', value);
startSpellCheck();
},
addDarkOverlay: () => {
@ -419,19 +418,6 @@
}
});
const startSpellCheck = () => {
if (!window.enableSpellCheck || !window.disableSpellCheck) {
return;
}
if (window.Events.getSpellCheck()) {
window.enableSpellCheck();
} else {
window.disableSpellCheck();
}
};
startSpellCheck();
const themeSetting = window.Events.getThemeSetting();
const newThemeSetting = mapOldThemeToNew(themeSetting);
window.Events.setThemeSetting(newThemeSetting);
@ -1037,8 +1023,16 @@
};
window.toggleSpellCheck = () => {
const newValue = !window.getSettingValue('spell-check');
const currentValue = window.getSettingValue('spell-check');
// if undefined, it means 'default' so true. but we have to toggle it, so false
// if not undefined, we take the opposite
const newValue = currentValue !== undefined ? !currentValue : false;
window.Events.setSpellCheck(newValue);
window.pushToast({
description: window.i18n('spellCheckDirty'),
type: 'info',
id: 'spellCheckDirty',
});
};
window.toggleLinkPreview = () => {

@ -1,185 +0,0 @@
/* global require, process, _ */
/* eslint-disable strict */
const electron = require('electron');
const Typo = require('typo-js');
const fs = require('fs');
const osLocale = require('os-locale');
const path = require('path');
const { remote, webFrame } = electron;
// `remote.require` since `Menu` is a main-process module.
const buildEditorContextMenu = remote.require('electron-editor-context-menu');
const EN_VARIANT = /^en/;
// Prevent the spellchecker from showing contractions as errors.
const ENGLISH_SKIP_WORDS = [
'ain',
'couldn',
'didn',
'doesn',
'hadn',
'hasn',
'mightn',
'mustn',
'needn',
'oughtn',
'shan',
'shouldn',
'wasn',
'weren',
'wouldn',
];
function setupLinux(locale) {
if (process.env.HUNSPELL_DICTIONARIES || locale !== 'en_US') {
// apt-get install hunspell-<locale> can be run for easy access
// to other dictionaries
const location = process.env.HUNSPELL_DICTIONARIES || '/usr/share/hunspell';
const affDataPath = path.join(location, `${locale}.aff`);
const dicDataPath = path.join(location, `${locale}.dic`);
window.log.info(
'Detected Linux. Setting up spell check with locale',
locale,
'and dictionary location',
location
);
if (fs.existsSync(affDataPath) && fs.existsSync(dicDataPath)) {
const affData = fs.readFileSync(affDataPath, 'utf-8');
const dicData = fs.readFileSync(dicDataPath, 'utf-8');
return new Typo(locale, affData, dicData);
}
window.log.error(
`Could not find one of ${affDataPath} or ${dicDataPath} on filesystem`
);
}
window.log.info('Detected Linux. Using default en_US spell check dictionary');
return new Typo('en_US');
}
// We load locale this way and not via app.getLocale() because this call returns
// 'es_ES' and not just 'es.' And hunspell requires the fully-qualified locale.
const locale = osLocale.sync().replace('-', '_');
// The LANG environment variable is how node spellchecker finds its default language:
// https://github.com/atom/node-spellchecker/blob/59d2d5eee5785c4b34e9669cd5d987181d17c098/lib/spellchecker.js#L29
if (!process.env.LANG) {
process.env.LANG = locale;
}
let spellchecker = null;
if (process.platform === 'linux') {
spellchecker = setupLinux(locale);
} else {
spellchecker = new Typo(locale);
// OSX and Windows 8+ have OS-level spellcheck APIs
window.log.info(
'Using OS-level spell check API with locale',
process.env.LANG
);
}
const simpleChecker = {
spellCheck(words, callback) {
let mispelled;
if (Array.isArray(words)) {
mispelled = words.filter(word => this.isMisspelled(word));
} else {
mispelled = this.isMisspelled(words);
}
callback(mispelled);
},
isMisspelled(word) {
const misspelled = !spellchecker.check(word);
// The idea is to make this as fast as possible. For the many, many calls which
// don't result in the red squiggly, we minimize the number of checks.
if (!misspelled) {
return false;
}
// Only if we think we've found an error do we check the locale and skip list.
if (locale.match(EN_VARIANT) && _.contains(ENGLISH_SKIP_WORDS, word)) {
return false;
}
return true;
},
getSuggestions(text) {
return spellchecker.suggest(text);
},
add() {},
};
const dummyChecker = {
spellCheck(words, callback) {
callback([]);
},
isMisspelled() {
return false;
},
getSuggestions() {
return [];
},
add() {
// nothing
},
};
window.spellChecker = simpleChecker;
window.disableSpellCheck = () => {
window.removeEventListener('contextmenu', spellCheckHandler);
window.addEventListener('contextmenu', defaultContextMenuHandler);
webFrame.setSpellCheckProvider('en-US', dummyChecker);
};
window.enableSpellCheck = () => {
webFrame.setSpellCheckProvider('en-US', simpleChecker);
window.addEventListener('contextmenu', spellCheckHandler);
window.removeEventListener('contextmenu', defaultContextMenuHandler);
};
const defaultContextMenuHandler = () => {
const menu = buildEditorContextMenu({});
// @see js/spell_check.js:183
setTimeout(() => {
menu.popup(remote.getCurrentWindow());
}, 30);
};
const spellCheckHandler = e => {
// Only show the context menu in text editors.
if (!e.target.closest('textarea, input, [contenteditable="true"]')) {
return;
}
const selectedText = window.getSelection().toString();
const isMisspelled = selectedText && simpleChecker.isMisspelled(selectedText);
const spellingSuggestions =
isMisspelled && simpleChecker.getSuggestions(selectedText).slice(0, 5);
const menu = buildEditorContextMenu({
isMisspelled,
spellingSuggestions,
});
// The 'contextmenu' event is emitted after 'selectionchange' has fired
// but possibly before the visible selection has changed. Try to wait
// to show the menu until after that, otherwise the visible selection
// will update after the menu dismisses and look weird.
setTimeout(() => {
menu.popup(remote.getCurrentWindow());
}, 30);
};

@ -9,7 +9,7 @@ const crypto = require('crypto');
const _ = require('lodash');
const pify = require('pify');
const electron = require('electron');
const { setup: setupSpellChecker } = require('./app/spell_check');
const packageJson = require('./package.json');
const GlobalErrors = require('./app/global_errors');
@ -82,6 +82,18 @@ const {
} = require('./app/protocol_filter');
const { installPermissionsHandler } = require('./app/permissions');
let appStartInitialSpellcheckSetting = true;
async function getSpellCheckSetting() {
const json = await sql.getItemById('spell-check');
// Default to `true` if setting doesn't exist yet
if (!json) {
return true;
}
return json.value;
}
function showWindow() {
if (!mainWindow) {
return;
@ -166,6 +178,7 @@ function prepareURL(pathSegments, moreKeys) {
contentProxyUrl: config.contentProxyUrl,
importMode: importMode ? true : undefined, // for stringify()
serverTrustRoot: config.get('serverTrustRoot'),
appStartInitialSpellcheckSetting,
defaultFileServer: config.get('defaultFileServer'),
...moreKeys,
},
@ -216,7 +229,7 @@ function isVisible(window, bounds) {
);
}
function createWindow() {
async function createWindow() {
const { screen } = electron;
const windowOptions = Object.assign(
{
@ -233,7 +246,7 @@ function createWindow() {
contextIsolation: false,
preload: path.join(__dirname, 'preload.js'),
nativeWindowOpen: true,
spellcheck: false,
spellcheck: await getSpellCheckSetting(),
},
icon: path.join(__dirname, 'images', 'session', 'icon_64.png'),
},
@ -284,6 +297,8 @@ function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow(windowOptions);
setupSpellChecker(mainWindow, locale.messages);
// Disable system main menu
mainWindow.setMenu(null);
@ -775,6 +790,7 @@ async function showMainWindow(sqlKey, passwordAttempt = false) {
messages: locale.messages,
passwordAttempt,
});
appStartInitialSpellcheckSetting = await getSpellCheckSetting();
await sqlChannels.initialize();
try {

@ -70,8 +70,6 @@
"config": "1.28.1",
"cross-env": "^6.0.3",
"dompurify": "^2.0.7",
"electron-context-menu": "^0.15.0",
"electron-editor-context-menu": "1.1.1",
"electron-is-dev": "^1.1.0",
"electron-localshortcut": "^3.2.1",
"electron-updater": "^4.2.2",
@ -123,7 +121,6 @@
"testcheck": "1.0.0-rc.2",
"tmp": "0.0.33",
"to-arraybuffer": "1.0.1",
"typo-js": "1.1.0",
"underscore": "1.9.0",
"uuid": "3.3.2",
"websocket": "1.0.28"
@ -264,7 +261,6 @@
"config/local-${env.SIGNAL_ENV}.json",
"background.html",
"about.html",
"settings.html",
"password.html",
"permissions_popup.html",
"debug_log.html",

@ -376,34 +376,17 @@ window.Signal.Backup = require('./js/modules/backup');
window.Signal.Debug = require('./js/modules/debug');
window.Signal.Logs = require('./js/modules/logs');
// Add right-click listener for selected text and urls
const contextMenu = require('electron-context-menu');
const isQR = params =>
params.mediaType === 'image' && params.titleText === 'Scan me!';
// QR saving doesn't work so we just disable it
contextMenu({
showInspectElement: false,
shouldShowMenu: (event, params) => {
const isRegular =
params.mediaType === 'none' && (params.linkURL || params.selectionText);
return Boolean(!params.isEditable && (isQR(params) || isRegular));
},
menu: (actions, params) => {
// If it's not a QR then show the default options
if (!isQR(params)) {
return actions;
}
return [actions.copyImage()];
},
window.addEventListener('contextmenu', e => {
const editable = e.target.closest(
'textarea, input, [contenteditable="true"]'
);
const link = e.target.closest('a');
const selection = Boolean(window.getSelection().toString());
if (!editable && !selection && !link) {
e.preventDefault();
}
});
// We pull this in last, because the native module involved appears to be sensitive to
// /tmp mounted as noexec on Linux.
require('./js/spell_check');
window.shortenPubkey = pubkey => `(...${pubkey.substring(pubkey.length - 6)})`;
window.pubkeyPattern = /@[a-fA-F0-9]{64,66}\b/g;

@ -1,184 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Security-Policy"
content="default-src 'none';
child-src 'self';
connect-src 'self' https: wss:;
font-src 'self';
form-action 'self';
frame-src 'none';
img-src 'self' blob: data:;
media-src 'self' blob:;
object-src 'none';
script-src 'self';
style-src 'self' 'unsafe-inline';"
>
<link href="stylesheets/manifest.css" rel="stylesheet" type="text/css" />
<style>
</style>
</head>
<body>
</body>
<script type='text/x-tmpl-mustache' id='syncSettings'>
<hr>
<h3>{{ sync }}</h3>
<div>
<button class='grey sync'>{{ syncNow }}</button>
<p>
{{ syncExplanation }}
<div class='synced_at'>
{{ lastSynced }} {{ syncDate }} {{ syncTime }}
</div>
<div class='sync_failed'>{{ syncFailed }}</div>
<div class='clearfix'></div>
</p>
</div>
</script>
<script type='text/x-tmpl-mustache' id='blockedUserSettings'>
<h3>{{ blockedHeader }}</h3>
<div class='blocked-user-settings'>
<button class='grey unblock-button'>{{ unblockMessage }}</button>
</div>
</script>
<script type='text/x-tmpl-mustache' id='settings'>
<div class='content'>
<a class='x close' alt='close settings' href='#'></a>
<h2>{{ settings }}</h2>
<div class='device-name-settings'>
<b>{{ deviceNameLabel }}:</b> {{ deviceName }}
</div>
<hr>
<div class='theme-settings'>
<h3>{{ theme }}</h3>
<div>
<input type='radio' name='theme' id='theme-setting-light' value='light'>
<label for='theme-setting-light'>{{ themeLight }}</label>
</div>
<div>
<input type='radio' name='theme' id='theme-setting-dark' value='dark'>
<label for='theme-setting-dark'>{{ themeDark }}</label>
</div>
</div>
<br />
{{ #isHideMenuBarSupported }}
<div class='menu-bar-setting'>
<input type='checkbox' name='hide-menu-bar' id='hide-menu-bar'/>
<label for='hide-menu-bar'>{{ hideMenuBar }}</label>
</div>
{{ /isHideMenuBarSupported }}
<hr>
<div class='notification-settings'>
<h3>{{ notifications }}</h3>
<p>{{ notificationSettingsDialog }}</p>
<div>
<input type='radio' name='notifications' id='notification-setting-message' value='message'>
<label for='notification-setting-message'>{{ nameAndMessage }} </label>
</div>
<div>
<input type='radio' name='notifications' id='notification-setting-name' value='name'/>
<label for='notification-setting-name'>{{ nameOnly }} </label>
</div>
<div>
<input type='radio' name='notifications' id='notification-setting-count' value='count'/>
<label for='notification-setting-count'>{{ noNameOrMessage }} </label>
</div>
<div>
<input type='radio' name='notifications' id='notification-setting-off' value='off'/>
<label for='notification-setting-off'>{{ disableNotifications }} </label>
</div>
</div>
<br />
{{ #isAudioNotificationSupported }}
<div class='audio-notification-setting'>
<input type='checkbox' name='audio-notification' id='audio-notification'/>
<label for='audio-notification'>{{ audioNotificationDescription }}</label>
</div>
{{ /isAudioNotificationSupported }}
<hr>
<h3>{{ generalHeader }}</h3>
<div class='spell-check-setting'>
<input type='checkbox' name='spell-check-setting' id='spell-check-setting' />
<label for='spell-check-setting'>{{ spellCheckDescription }}</label>
</div>
<div class='link-preview-setting'>
<input type='checkbox' name='link-preview-setting' id='link-preview-setting' />
<label for='link-preview-setting'>{{ linkPreviewsSettingDescription }}</label>
</div>
<hr>
<div class='permissions-setting'>
<h3>{{ permissions }}</h3>
<div class='media-permissions'>
<input type='checkbox' name='media-permissions' id='media-permissions' />
<label for='media-permissions'>{{ mediaPermissionsDescription }}</label>
</div>
<div class='read-receipt-setting'>
<input type='checkbox' name='read-receipt-setting' id='read-receipt-setting' />
<label for='read-receipt-setting'>{{ readReceiptSettingDescription }}</label>
</div>
<div class='typing-indicators-setting'>
<input type='checkbox' name='typing-indicators-setting' id='typing-indicators-setting' />
<label for='typing-indicators-setting'>{{ typingIndicatorsSettingDescription }}</label>
</div>
</div>
<div class='sync-setting'></div>
<hr>
<div class='message-ttl-setting'>
<h3>{{ messageTTL }}</h3>
<div>{{ messageTTLSettingDescription }}</div>
<div id='warning'>{{ messageTTLSettingWarning }}</div>
<div class='inputs'>
<input
name='message-ttl-setting'
id='message-ttl-setting'
type='range'
list='tickmarks'
min='12'
max='96'
step='6'
value='24'
>
<label for='message-ttl-setting'>24 Hours</label>
<datalist id='tickmarks'>
<option value='12'>
<option value='18'>
<option value='24'>
<option value='30'>
<option value='36'>
<option value='42'>
<option value='48'>
<option value='54'>
<option value='60'>
<option value='66'>
<option value='72'>
<option value='78'>
<option value='84'>
<option value='90'>
<option value='96'>
</datalist>
</div>
</div>
<hr>
<div class='clear-data-settings'>
<h3>{{ clearDataHeader }}</h3>
<div>
<button class='grey destructive clear-data'>{{ clearDataButton }}</button>
<p>{{ clearDataExplanation }}</p>
</div>
</div>
<hr>
<div class='blocked-user-setting'>
</div>
</div>
</script>
<script type='text/javascript' src='js/components.js'></script>
<script type='text/javascript' src='js/storage.js'></script>
<script type='text/javascript' src='js/models/blockedNumbers.js'></script>
<script type='text/javascript' src='js/blocked_number_controller.js'></script>
<script type='text/javascript' src='js/views/whisper_view.js'></script>
<script type='text/javascript' src='js/views/list_view.js'></script>
<script type='text/javascript' src='js/views/blocked_number_view.js'></script>
<script type='text/javascript' src='js/views/settings_view.js'></script>
<script type='text/javascript' src='js/settings_start.js'></script>
</html>

@ -586,7 +586,6 @@
<script type="text/javascript" src="crypto_test.js"></script>
<script type="text/javascript" src="database_test.js"></script>
<script type="text/javascript" src="i18n_test.js"></script>
<script type="text/javascript" src="spellcheck_test.js"></script>
<script type="text/javascript" src="fixtures.js"></script>
<script type="text/javascript" src="fixtures_test.js"></script>

@ -1,15 +0,0 @@
describe('spellChecker', () => {
it('should work', () => {
let result = null;
window.spellChecker.spellCheck(['correct'], answer => {
result = answer;
});
assert.deepEqual(result, []);
window.spellChecker.spellCheck(['fhqwgads'], answer => {
result = answer;
});
assert.deepEqual(result, ['fhqwgads']);
});
});

@ -116,9 +116,14 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
const description = setting.description || '';
const comparisonValue = setting.comparisonValue || null;
const storedSetting = window.getSettingValue(
setting.id,
comparisonValue
);
const value =
window.getSettingValue(setting.id, comparisonValue) ||
(setting.content && setting.content.defaultValue);
storedSetting !== undefined
? storedSetting
: setting.content && setting.content.defaultValue;
const sliderFn =
setting.type === SessionSettingType.Slider
@ -356,7 +361,7 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
type: SessionSettingType.Toggle,
category: SessionSettingCategory.Appearance,
setFn: window.toggleSpellCheck,
content: undefined,
content: { defaultValue: true },
comparisonValue: undefined,
onClick: undefined,
confirmationDialogParams: undefined,

@ -938,11 +938,6 @@ ast-types@^0.7.2:
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.7.8.tgz#902d2e0d60d071bdcd46dc115e1809ed11c138a9"
integrity sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk=
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
async-each@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
@ -1438,7 +1433,7 @@ buffer-alloc@^1.2.0:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-crc32@0.2.13, buffer-crc32@^0.2.1:
buffer-crc32@0.2.13, buffer-crc32@^0.2.1, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
@ -1887,14 +1882,6 @@ cli-spinners@^1.1.0:
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a"
integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==
cli-truncate@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
dependencies:
slice-ansi "^3.0.0"
string-width "^4.2.0"
cli-width@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
@ -2169,7 +2156,7 @@ concat-stream@1.6.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.0:
concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
@ -3015,24 +3002,6 @@ electron-chromedriver@^8.0.0:
electron-download "^4.1.1"
extract-zip "^1.6.7"
electron-context-menu@^0.15.0:
version "0.15.2"
resolved "https://registry.yarnpkg.com/electron-context-menu/-/electron-context-menu-0.15.2.tgz#66f544a06d2099dafdecade2e9214a66e26b5764"
integrity sha512-r4Zv/NWKe6smezz66yIZSt0geRPx3wdfVlMYXNSGsPcN7LiyZXGlxWvCX9gsqN8Rg8nWC3Q2EcXzt8d9NQFUyg==
dependencies:
cli-truncate "^2.0.0"
electron-dl "^1.2.0"
electron-is-dev "^1.0.1"
electron-dl@^1.2.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/electron-dl/-/electron-dl-1.14.0.tgz#1466f1b945664ca3d784268307c2b935728177bf"
integrity sha512-4okyei42a1mLsvLK7hLrIfd20EQzB18nIlLTwBV992aMSmTGLUEFRTmO1MfSslGNrzD8nuPuy1l/VxO8so4lig==
dependencies:
ext-name "^5.0.0"
pupa "^1.0.0"
unused-filename "^1.0.0"
electron-download@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
@ -3048,17 +3017,6 @@ electron-download@^4.1.1:
semver "^5.4.1"
sumchecker "^2.0.2"
electron-editor-context-menu@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/electron-editor-context-menu/-/electron-editor-context-menu-1.1.1.tgz#dc30098e0dfb37f62628e43303124c7f3379572d"
integrity sha1-3DAJjg37N/YmKOQzAxJMfzN5Vy0=
dependencies:
lodash.clonedeep "^4.3.0"
lodash.defaults "^4.0.1"
lodash.isarray "^4.0.0"
lodash.isempty "^4.1.2"
lodash.isfunction "^3.0.8"
electron-icon-maker@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/electron-icon-maker/-/electron-icon-maker-0.0.3.tgz#bcd2e91896d7200f84fcc6652aed924fdaaa8307"
@ -3073,7 +3031,7 @@ electron-is-accelerator@^0.1.0:
resolved "https://registry.yarnpkg.com/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz#509e510c26a56b55e17f863a4b04e111846ab27b"
integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns=
electron-is-dev@*, electron-is-dev@^1.0.1, electron-is-dev@^1.1.0:
electron-is-dev@*, electron-is-dev@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.1.0.tgz#b15a2a600bdc48a51a857d460e05f15b19a2522c"
integrity sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ==
@ -3618,21 +3576,6 @@ express@^4.16.2:
utils-merge "1.0.1"
vary "~1.1.2"
ext-list@^2.0.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37"
integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==
dependencies:
mime-db "^1.28.0"
ext-name@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6"
integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==
dependencies:
ext-list "^2.0.0"
sort-keys-length "^1.0.0"
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@ -3693,7 +3636,7 @@ extract-zip@1.6.6:
mkdirp "0.5.0"
yauzl "2.4.1"
extract-zip@^1.0.3, extract-zip@^1.6.5, extract-zip@^1.6.7:
extract-zip@^1.0.3, extract-zip@^1.6.5:
version "1.6.7"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9"
integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=
@ -3703,6 +3646,16 @@ extract-zip@^1.0.3, extract-zip@^1.6.5, extract-zip@^1.6.7:
mkdirp "0.5.1"
yauzl "2.4.1"
extract-zip@^1.6.7:
version "1.7.0"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
dependencies:
concat-stream "^1.6.2"
debug "^2.6.9"
mkdirp "^0.5.4"
yauzl "^2.10.0"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@ -3759,6 +3712,13 @@ fd-slicer@~1.0.1:
dependencies:
pend "~1.2.0"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies:
pend "~1.2.0"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
@ -6115,7 +6075,7 @@ lodash.camelcase@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash.clonedeep@^4.3.0, lodash.clonedeep@^4.3.2:
lodash.clonedeep@^4.3.2:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
@ -6125,36 +6085,16 @@ lodash.cond@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5"
integrity sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=
lodash.defaults@^4.0.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isarray@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403"
integrity sha1-KspJayjEym1yZxUxNZDALm6jRAM=
lodash.isempty@^4.1.2:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
integrity sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isfunction@^3.0.8:
version "3.0.9"
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051"
integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@ -6482,7 +6422,7 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
mime-db@1.43.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0:
mime-db@1.43.0, "mime-db@>= 1.43.0 < 2":
version "1.43.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
@ -6618,13 +6558,20 @@ mkdirp@0.5.0:
dependencies:
minimist "0.0.8"
mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
mkdirp@^0.5.4, mkdirp@~0.5.1:
version "0.5.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512"
integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==
dependencies:
minimist "^1.2.5"
mkpath@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-0.1.0.tgz#7554a6f8d871834cc97b5462b122c4c124d6de91"
@ -6662,11 +6609,6 @@ mocha@4.1.0:
mkdirp "0.5.1"
supports-color "4.4.0"
modify-filename@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/modify-filename/-/modify-filename-1.1.0.tgz#9a2dec83806fbb2d975f22beec859ca26b393aa1"
integrity sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=
moment@2.21.0:
version "2.21.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
@ -8159,9 +8101,9 @@ pseudomap@^1.0.2:
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
psl@^1.1.28:
version "1.7.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
public-encrypt@^4.0.0:
version "4.0.3"
@ -8215,11 +8157,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
pupa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pupa/-/pupa-1.0.0.tgz#9a9568a5af7e657b8462a6e9d5328743560ceff6"
integrity sha1-mpVopa9+ZXuEYqbp1TKHQ1YM7/Y=
pupa@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726"
@ -9527,7 +9464,12 @@ shell-quote@1.6.1:
array-reduce "~0.0.0"
jsonify "~0.0.0"
signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2:
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
signal-exit@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
@ -9571,15 +9513,6 @@ slice-ansi@1.0.0:
dependencies:
is-fullwidth-code-point "^2.0.0"
slice-ansi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
dependencies:
ansi-styles "^4.0.0"
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
slide@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
@ -9656,13 +9589,6 @@ socks@~2.3.2:
ip "1.1.5"
smart-buffer "^4.1.0"
sort-keys-length@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=
dependencies:
sort-keys "^1.0.0"
sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
@ -10632,11 +10558,6 @@ typescript@3.3.3333:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6"
integrity sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==
typo-js@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.1.0.tgz#a5a9f592bcb453666bf70c9694da58705d025ed8"
integrity sha512-W3kLbx+ML9PBl5Bzso/lTvVxk4BCveSNAtQeht59FEtxCdGThmn6wSHA4Xq3eQYAK24NHdisMM4JmsK0GFy/pg==
uc.micro@^1.0.1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
@ -10844,14 +10765,6 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
unused-filename@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unused-filename/-/unused-filename-1.0.0.tgz#d340880f71ae2115ebaa1325bef05cc6684469c6"
integrity sha1-00CID3GuIRXrqhMlvvBcxmhEacY=
dependencies:
modify-filename "^1.1.0"
path-exists "^3.0.0"
upath@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
@ -11508,6 +11421,14 @@ yauzl@2.4.1:
dependencies:
fd-slicer "~1.0.1"
yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
zip-stream@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"

Loading…
Cancel
Save