我希望为纯文本使用CodeMirror的功能(例如,编号,包装,搜索等),而不需要代码高亮显示,而是使用Google Chrome拼写检查器或其他自然语言(特别是英文)拼写检查激活(我不需要在其他浏览器上工作)。我怎样才能做到这一点?是否可以写一个纯文本模式插件来启用拼写检查?带拼写检查器的CodeMirror
回答
我实际上CodeMirror集成typo.js而编码NoTex.ch;你可以在这里看看它CodeMirror.rest.js;我需要一种方法来检查标记拼写,并且由于我使用了CodeMirror出色的语法高亮功能,因此非常简单。
您可以在提供的链接检查代码,但我会总结一下,我做了什么:
初始化typo.js库;又见作者的博客/文件:
var typo = new Typo ("en_US", AFF_DATA, DIC_DATA, { platform: 'any' });
定义正则表达式为你的单词分隔符:
var rx_word = "!\"#$%&()*+,-./:;<=>[email protected][\\\\\\]^_`{|}~";
定义的覆盖模式CodeMirror:
CodeMirror.defineMode ("myoverlay", function (config, parserConfig) { var overlay = { token: function (stream, state) { if (stream.match (rx_word) && typo && !typo.check (stream.current())) return "spell-error"; //CSS class: cm-spell-error while (stream.next() != null) { if (stream.match (rx_word, false)) return null; } return null; } }; var mode = CodeMirror.getMode ( config, parserConfig.backdrop || "text/x-myoverlay" ); return CodeMirror.overlayMode (mode, overlay); });
使用与CodeMirror叠加;请参阅用户手册以了解您如何完成此操作。我已经在我的代码中完成了它,所以你也可以在那里查看它,但我推荐用户手册。
定义CSS类:
.CodeMirror .cm-spell-error { background: url(images/red-wavy-underline.gif) bottom repeat-x; }
这种做法的伟大工程的德语,英语和西班牙语。用法语字典typo.js似乎有一些(口音)问题,以及像希伯来语,匈牙利语和意大利语这样的语言 - 词缀数很多或字典相当广泛 - 它不能真正起作用,因为在目前的实现中,typo.js使用的内存太多,速度太慢。
德国(和西班牙语)typo.js可以阻止JavaScript的VM几百毫秒(但只能在初始化过程中!),所以你可能要考虑与HTML5网页工人后台线程(见CodeMirror。 typo.worker。例如js)。进一步typo.js似乎不支持Unicode(由于JavaScript限制):至少,我没有设法让它与俄文,希腊文,印地文等非拉丁语言一起工作。
我'除了(现在相当大)NoTex.ch之外,我没有将所描述的解决方案重构成一个很好的独立项目,但我很快就可以做到这一点;直到那时你必须根据上面的描述或暗示的代码修补你自己的解决方案。我希望这有帮助。
CodeMirror不是基于一个HTML textarea的,所以你can't use the built-in spell check
你可以用一些实施CodeMirror自己的拼写检查类似typo.js
我不相信任何人还没有这样做。
这是hsk81的答案的工作版本。它使用CodeMirror的覆盖模式,并在引号,html标签等内查找任何单词。它有一个样本typo.check,应该用Typo.js替换。它用红色的波浪线突出了未知的单词。
这是使用IPython的%% html单元格进行测试的。
<style>
.CodeMirror .cm-spell-error {
background: url("https://raw.githubusercontent.com/jwulf/typojs-project/master/public/images/red-wavy-underline.gif") bottom repeat-x;
}
</style>
<h2>Overlay Parser Demo</h2>
<form><textarea id="code" name="code">
</textarea></form>
<script>
var typo = { check: function(current) {
var dictionary = {"apple": 1, "banana":1, "can't":1, "this":1, "that":1, "the":1};
return current.toLowerCase() in dictionary;
}
}
CodeMirror.defineMode("spell-check", function(config, parserConfig) {
var rx_word = new RegExp("[^\!\"\#\$\%\&\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~\ ]");
var spellOverlay = {
token: function (stream, state) {
var ch;
if (stream.match(rx_word)) {
while ((ch = stream.peek()) != null) {
if (!ch.match(rx_word)) {
break;
}
stream.next();
}
if (!typo.check(stream.current()))
return "spell-error";
return null;
}
while (stream.next() != null && !stream.match(rx_word, false)) {}
return null;
}
};
return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), spellOverlay);
});
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "spell-check"});
</script>
我创建了错别字建议/更正拼写检查:
https://gist.github.com/kofifus/4b2f79cadc871a29439d919692099406
演示:https://plnkr.co/edit/0y1wCHXx3k3mZaHFOpHT
下面是代码的相关部分:
首先,我许下诺言加载词典。我用typo.js的字典,加载可能需要一段时间,如果他们没有当地举办的,所以最好是尽快启动加载作为登录之前,你的开始/ CM初始化等:
function loadTypo() {
// hosting the dicts on your local domain will give much faster results
const affDict='https://rawgit.com/ropensci/hunspell/master/inst/dict/en_US.aff';
const dicDict='https://rawgit.com/ropensci/hunspell/master/inst/dict/en_US.dic';
return new Promise(function(resolve, reject) {
var xhr_aff = new XMLHttpRequest();
xhr_aff.open('GET', affDict, true);
xhr_aff.onload = function() {
if (xhr_aff.readyState === 4 && xhr_aff.status === 200) {
//console.log('aff loaded');
var xhr_dic = new XMLHttpRequest();
xhr_dic.open('GET', dicDict, true);
xhr_dic.onload = function() {
if (xhr_dic.readyState === 4 && xhr_dic.status === 200) {
//console.log('dic loaded');
resolve(new Typo('en_US', xhr_aff.responseText, xhr_dic.responseText, { platform: 'any' }));
} else {
console.log('failed loading aff');
reject();
}
};
//console.log('loading dic');
xhr_dic.send(null);
} else {
console.log('failed loading aff');
reject();
}
};
//console.log('loading aff');
xhr_aff.send(null);
});
}
其次,我添加一个覆盖检测和标记错别字这样的:
cm.spellcheckOverlay={
token: function(stream) {
var ch = stream.peek();
var word = "";
if (rx_word.includes(ch) || ch==='\uE000' || ch==='\uE001') {
stream.next();
return null;
}
while ((ch = stream.peek()) && !rx_word.includes(ch)) {
word += ch;
stream.next();
}
if (! /[a-z]/i.test(word)) return null; // no letters
if (startSpellCheck.ignoreDict[word]) return null;
if (!typo.check(word)) return "spell-error"; // CSS class: cm-spell-error
}
}
cm.addOverlay(cm.spellcheckOverlay);
三我用一个列表框中显示的建议和修复错误:
function getSuggestionBox(typo) {
function sboxShow(cm, sbox, items, x, y) {
let selwidget=sbox.children[0];
let options='';
if (items==='hourglass') {
options='<option>⌛</option>'; // hourglass
} else {
items.forEach(s => options += '<option value="' + s + '">' + s + '</option>');
options+='<option value="##ignoreall##">ignore all</option>';
}
selwidget.innerHTML=options;
selwidget.disabled=(items==='hourglass');
selwidget.size = selwidget.length;
selwidget.value=-1;
// position widget inside cm
let cmrect=cm.getWrapperElement().getBoundingClientRect();
sbox.style.left=x+'px';
sbox.style.top=(y-sbox.offsetHeight/2)+'px';
let widgetRect = sbox.getBoundingClientRect();
if (widgetRect.top<cmrect.top) sbox.style.top=(cmrect.top+2)+'px';
if (widgetRect.right>cmrect.right) sbox.style.left=(cmrect.right-widgetRect.width-2)+'px';
if (widgetRect.bottom>cmrect.bottom) sbox.style.top=(cmrect.bottom-widgetRect.height-2)+'px';
}
function sboxHide(sbox) {
sbox.style.top=sbox.style.left='-1000px';
}
// create suggestions widget
let sbox=document.getElementById('suggestBox');
if (!sbox) {
sbox=document.createElement('div');
sbox.style.zIndex=100000;
sbox.id='suggestBox';
sbox.style.position='fixed';
sboxHide(sbox);
let selwidget=document.createElement('select');
selwidget.multiple='yes';
sbox.appendChild(selwidget);
sbox.suggest=((cm, e) => { // e is the event from cm contextmenu event
if (!e.target.classList.contains('cm-spell-error')) return false; // not on typo
let token=e.target.innerText;
if (!token) return false; // sanity
// save cm instance, token, token coordinates in sbox
sbox.codeMirror=cm;
sbox.token=token;
let tokenRect = e.target.getBoundingClientRect();
let start=cm.coordsChar({left: tokenRect.left+1, top: tokenRect.top+1});
let end=cm.coordsChar({left: tokenRect.right-1, top: tokenRect.top+1});
sbox.cmpos={ line: start.line, start: start.ch, end: end.ch};
// show hourglass
sboxShow(cm, sbox, 'hourglass', e.pageX, e.pageY);
// let the ui refresh with the hourglass & show suggestions
setTimeout(() => {
sboxShow(cm, sbox, typo.suggest(token), e.pageX, e.pageY); // typo.suggest takes a while
}, 100);
e.preventDefault();
return false;
});
sbox.onmouseleave=(e => {
sboxHide(sbox)
});
selwidget.onchange=(e => {
sboxHide(sbox)
let cm=sbox.codeMirror, correction=e.target.value;
if (correction=='##ignoreall##') {
startSpellCheck.ignoreDict[sbox.token]=true;
cm.setOption('maxHighlightLength', (--cm.options.maxHighlightLength) +1); // ugly hack to rerun overlays
} else {
cm.replaceRange(correction, { line: sbox.cmpos.line, ch: sbox.cmpos.start}, { line: sbox.cmpos.line, ch: sbox.cmpos.end});
cm.focus();
cm.setCursor({line: sbox.cmpos.line, ch: sbox.cmpos.start+correction.length});
}
});
document.body.appendChild(sbox);
}
return sbox;
}
希望这有助于!
- 1. 带拼写纠错算法的拼写检查器
- 2. 拼写检查器
- 3. IE6的拼写检查器?
- 4. Python的拼写检查器
- 5. emacs __approximate__拼写检查器
- 6. C#Lucene.Net拼写检查器
- 7. Python拼写检查器
- 8. 拼写检查器API
- 9. Silverlight拼写检查器
- 10. NetSpell拼写检查器
- 11. 拼写检查
- 12. 拼写检查器有什么好处? Google拼写检查器或Hunspell
- 13. javascript拼写检查
- 14. Solr拼写检查
- 15. WPF拼写检查
- 16. hunspell拼写检查
- 17. Solr拼写检查
- 18. 拼写检查textfield
- 19. Iphone拼写检查
- 20. UISearchBar拼写检查
- 21. GWT拼写检查
- 22. 带同义词的英语拼写检查器c#
- 23. 带有Gmail样式拼写检查的富文本编辑器
- 24. 带动态内联拼写检查的Windows文本编辑器
- 25. R拼写检查器/标记器
- 26. Java中的拼写检查器
- 27. asp.net的自定义拼写检查器
- 28. Xcode的自动拼写检查器
- 29. 在Nutch 1.0中的拼写检查器
- 30. iPhone上的Aspell拼写检查器?
太好了。我还没有完全尝试过,但我相信它。 – sawa
这太棒了!您可能还想使用新增的“addOverlay”功能(http://codemirror.net/doc/manual.html#addOverlay),该功能提供了一种更有效且侵害性更小的添加实用程序叠加层的方式。 – Marijn
在这个答案中的链接不再解决,被移动的文件,它已经被杀死了? –