Stackedit/public/res/extensions/spellCheck.js

198 lines
6.5 KiB
JavaScript
Raw Normal View History

2013-10-03 01:02:52 +00:00
define([
"jquery",
"underscore",
2013-10-04 00:34:58 +00:00
"crel",
2013-10-03 01:02:52 +00:00
"utils",
"classes/Extension",
"typo-js",
"xregexp",
2013-10-05 01:30:54 +00:00
"text!bower-libs/Typo.js/typo/typo.js",
"text!workers/spellCheckWorker.js",
2013-10-03 01:02:52 +00:00
"text!dictionaries/en_US.dic",
"text!dictionaries/en_US.aff",
"text!html/tocSettingsBlock.html",
2013-10-05 01:30:54 +00:00
], function($, _, crel, utils, Extension, Typo, XRegExp, typoJS, spellCheckWorkerJS, dic, aff, tocSettingsBlockHTML) {
2013-10-03 01:02:52 +00:00
2013-10-05 01:30:54 +00:00
var spellCheck = new Extension("spellCheck", "Spell Check", true, true, true);
2013-10-03 01:02:52 +00:00
spellCheck.settingsBlock = tocSettingsBlockHTML;
2013-10-05 01:30:54 +00:00
// Create a web worker
var worker = new Worker('res/worker.js');
worker.postMessage(spellCheckWorkerJS);
worker.postMessage(JSON.stringify(['init', typoJS, 'en_US', aff, dic]));
2013-10-03 01:02:52 +00:00
var aceEditor = undefined;
2013-10-06 14:34:40 +00:00
var wordRegExp = XRegExp('\\p{L}+(?:\'\\p{L}+)*', 'g');
2013-10-04 00:34:58 +00:00
var markers = [];
2013-10-05 01:30:54 +00:00
var timeoutId = undefined;
var currentRowCheck = undefined;
function rowCheck(rowIndex) {
var tokens = aceEditor.session.getTokens(rowIndex).slice();
var tokenOffset = 0;
var self = this;
self.checkToken = function() {
if (tokens.length === 0) {
!timeoutId && (timeoutId = setTimeout(check, 5));
return;
}
var token = tokens.shift();
var words = [];
if (!/code|code_block|reference|markup\.underline/.test(token.type)) {
2013-10-04 00:34:58 +00:00
token.value.replace(wordRegExp, function(word, offset) {
2013-10-05 01:30:54 +00:00
words.push({
value: word,
offset: offset + tokenOffset
});
2013-10-04 00:34:58 +00:00
});
}
tokenOffset += token.value.length;
2013-10-05 01:30:54 +00:00
if (words.length === 0) {
self.checkToken();
2013-10-04 00:34:58 +00:00
return;
}
2013-10-05 01:30:54 +00:00
worker.onmessage = function(e) {
var message = JSON.parse(e.data);
if(message[0] != 'check') {
return;
}
var checkedWords = message[1];
if (self.stopped) {
return;
}
var Range = require('ace/range').Range;
_.each(checkedWords, function(word) {
if (!word.check) {
var range = new Range(rowIndex, word.offset, rowIndex, word.offset + word.value.length);
var markerId = aceEditor.session.addMarker(range, "misspelled", "typo", true);
var marker = aceEditor.session.getMarkers(true)[markerId];
markers.push(marker);
}
});
self.checkToken();
};
worker.postMessage(JSON.stringify(['check', words]));
};
}
var rowIndex = 0;
function check() {
timeoutId = undefined;
currentRowCheck && (currentRowCheck.stopped = true);
currentRowCheck = new rowCheck(rowIndex++);
currentRowCheck.checkToken();
2013-10-04 00:34:58 +00:00
}
function stop() {
2013-10-05 01:30:54 +00:00
currentRowCheck && (currentRowCheck.stopped = true);
2013-10-04 00:34:58 +00:00
timeoutId && clearTimeout(timeoutId);
timeoutId = undefined;
}
function start() {
var savedMarkers = [];
_.each(markers, function(marker) {
if (marker.range.start.row < rowIndex) {
savedMarkers.push(marker);
}
else {
aceEditor.session.removeMarker(marker.id);
}
});
markers = savedMarkers;
timeoutId = setTimeout(check, 700);
}
2013-10-05 01:30:54 +00:00
var dropdownElt = undefined;
var $dropdownElt = undefined;
var liEltTmpl = [
'<li>',
' <a href="#">',
' <%= suggestion %>',
' </a>',
'</li>'
].join('');
var currentWordSuggest = undefined;
function wordSuggest(marker) {
var word = aceEditor.session.getTextRange(marker.range);
var self = this;
self.run = function() {
worker.onmessage = function(e) {
var message = JSON.parse(e.data);
if(message[0] != 'suggest') {
return;
}
var suggestions = message[1];
if (self.stopped) {
return;
}
console.log(suggestions);
var liListHtml = _.reduce(suggestions, function(result, suggestion) {
return result + _.template(liEltTmpl, {
suggestion: suggestion,
});
}, '');
dropdownElt.innerHTML = liListHtml;
$(dropdownElt).dropdown('toggle');
};
worker.postMessage(JSON.stringify(['suggest', word]));
};
}
2013-10-04 00:34:58 +00:00
var fileOpen = false;
spellCheck.onFileClose = function() {
stop();
fileOpen = false;
2013-10-03 01:02:52 +00:00
};
spellCheck.onFileOpen = function() {
2013-10-04 00:34:58 +00:00
fileOpen = true;
rowIndex = 0;
stop();
start();
};
2013-10-05 01:30:54 +00:00
2013-10-04 00:34:58 +00:00
spellCheck.onAceCreated = function(aceEditorParam) {
aceEditor = aceEditorParam;
aceEditor.session.on('change', function(e) {
if (fileOpen === true) {
var modifiedRowIndex = e.data.range.start.row;
if (modifiedRowIndex < rowIndex) {
rowIndex = modifiedRowIndex;
}
stop();
start();
}
});
2013-10-05 01:30:54 +00:00
// Suggestions are disabled. Too much CPU consumption.
2013-10-04 00:34:58 +00:00
/*
aceEditor.on("click", function(ev) {
var screenCoordinates = aceEditor.renderer.pixelToScreenCoordinates(ev.x, ev.y);
var documentPosition = aceEditor.session.screenToDocumentPosition(screenCoordinates.row, screenCoordinates.column);
_.each(markers, function(marker) {
if (marker.range.contains(documentPosition.row, documentPosition.column)) {
2013-10-05 01:30:54 +00:00
currentWordSuggest && (currentWordSuggest.stopped = true);
currentWordSuggest = new wordSuggest(marker);
currentWordSuggest.run();
2013-10-03 01:02:52 +00:00
}
});
});
};
2013-10-04 00:34:58 +00:00
spellCheck.onReady = function() {
dropdownElt = crel('ul', {
class: 'dropdown-menu dropdown-spell-checker'
});
document.querySelector('.ui-layout-resizer-north').appendChild(crel('div', crel('div', {
'data-toggle': 'dropdown'
}), dropdownElt));
$dropdownElt = $(dropdownElt).dropdown();
*/
};
2013-10-03 01:02:52 +00:00
return spellCheck;
});