electron-spell-check-provider
Version:
Because Electron's spell-check APIs are just a little too low-level.
166 lines (126 loc) • 5.67 kB
Markdown
# electron-spell-check-provider
Electron's [spell-check API][setSpellCheckProvider] looks straightforward… until
you have to pull in and configure `node-spellchecker`:
```diff
webFrame.setSpellCheckProvider('en-US', true, {
spellCheck: function(text) {
+ return !(require('spellchecker').isMisspelled(text));
}
});
```
Which improperly flags contractions:
<img src="docs/false_positive.png" height="300" alt="false positive">
And only underlines misspelled words, leaving you to show suggestions [yourself][DIY context menu]…
Or you can use this module:
```js
webFrame.setSpellCheckProvider('en-US', true, new SpellCheckProvider('en-US'));
```
## Installation
```js
yarn add electron-spell-check-provider
```
or
```js
npm install electron-spell-check-provider --save
```
_Note:_ This uses a native module, so you will need to [rebuild your modules][rebuild] after installing.
## Usage
```js
// In the renderer process:
var webFrame = require('electron').webFrame;
var SpellCheckProvider = require('electron-spell-check-provider');
webFrame.setSpellCheckProvider('en-US', true, new SpellCheckProvider('en-US'));
```
'en-US' is the only supported language at present.
### But how do I show spelling suggestions (in the context menu)?
As the text selection changes, Electron will poll the spell-check provider.
If the current word is misspelled, the provider will emit a `'misspelling'` event
with spelling suggestions:
```js
webFrame.setSpellCheckProvider('en-US', true,
new SpellCheckProvider('en-US').on('misspelling', function(suggestions) {
console.log('The text at the site of the cursor is misspelled.',
'Maybe the user meant to type:', suggestions);
}
}));
```
If you save these suggestions, you can then show them in a [menu][menu] when the
`'contextmenu'` event next fires.
Here's a full implementation that uses
[`electron-editor-context-menu`][electron-editor-context-menu] to build the menu
for you in addition to handling some other gotchas:
```js
/**
* Enables spell-checking and the right-click context menu in text editors.
* Electron (`webFrame.setSpellCheckProvider`) only underlines misspelled words;
* we must manage the menu ourselves.
*
* Run this in the renderer process.
*/
var remote = require('electron').remote;
var webFrame = require('electron').webFrame;
var SpellCheckProvider = require('electron-spell-check-provider');
// `remote.require` since `Menu` is a main-process module.
var buildEditorContextMenu = remote.require('electron-editor-context-menu');
var selection;
function resetSelection() {
selection = {
isMisspelled: false,
spellingSuggestions: []
};
}
resetSelection();
// Reset the selection when clicking around, before the spell-checker runs and the context menu shows.
window.addEventListener('mousedown', resetSelection);
// The spell-checker runs when the user clicks on text and before the 'contextmenu' event fires.
// Thus, we may retrieve spell-checking suggestions to put in the menu just before it shows.
webFrame.setSpellCheckProvider(
'en-US',
// Not sure what this parameter (`autoCorrectWord`) does: https://github.com/atom/electron/issues/4371
// The documentation for `webFrame.setSpellCheckProvider` passes `true` so we do too.
true,
new SpellCheckProvider('en-US').on('misspelling', function(suggestions) {
// Prime the context menu with spelling suggestions _if_ the user has selected text. Electron
// may sometimes re-run the spell-check provider for an outdated selection e.g. if the user
// right-clicks some misspelled text and then an image.
if (window.getSelection().toString()) {
selection.isMisspelled = true;
// Take the first three suggestions if any.
selection.spellingSuggestions = suggestions.slice(0, 3);
}
}));
window.addEventListener('contextmenu', function(e) {
// Only show the context menu in text editors.
if (!e.target.closest('textarea, input, [contenteditable="true"]')) return;
var menu = buildEditorContextMenu(selection);
// 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(function() {
menu.popup(remote.getCurrentWindow());
}, 30);
});
```
### Adding words to the dictionary
You can add a word to the spell-check dictionary by calling the `add` instance method. Pass the word to add as an argument. Additions to the dictionary are persistent.
```javascript
let provider = new SpellCheckProvider('en-US');
// ...
let newWord = window.getSelection().toString();
provider.add(newWord);
```
You can do this in a context menu click handler function for an "Add to Dictionary" menu item.
## Contributing
We welcome pull requests! In particular, we'd love to see support for additional
languages.
Please lint your code.
## Copyright and License
Copyright 2016 Mixmax, Inc., licensed under the MIT License.
[setSpellCheckProvider]: https://github.com/atom/electron/blob/master/docs/api/web-frame.md#webframesetspellcheckproviderlanguage-autocorrectword-provider
[DIY context menu]: https://github.com/atom/electron/pull/942#issuecomment-136223543
[menu]: https://github.com/atom/electron/blob/master/docs/api/menu.md
[electron-editor-context-menu]: https://github.com/mixmaxhq/electron-editor-context-menu
[rebuild]: https://github.com/atom/electron/blob/master/docs/tutorial/using-native-node-modules.md#the-easy-way
## Release History
* 1.1.0 Support adding words to the dictionary (#6)
* 1.0.0 Initial release.