/**
* ==VimperatorPlugin==
* @name lookup dictionary (Vimperator plugin)
* @description Lookup words from Web dictionaries, and show the results in the bottom of the window
* @description-ja Web上の辞書を引いた結果をコマンドライン・バッファへ出力します
* @author teramako teramako@gmail.com
* @version 0.3
* ==/VimperatorPlugin==
*/
(function(){
const SITE_DEFINITION = [{
names: ['eiji[ro]'],
url: 'http://eow.alc.co.jp/%s/UTF-8/',
shortHelp: 'SPACE ALC (英辞郎 on the Web)',
xpath: 'id("resultList")'
},{
names: ['goo'],
url: 'http://dictionary.goo.ne.jp/search.php?MT=%s&kind=all&mode=0',
shortHelp: 'goo 辞書',
encode: 'EUC-JP',
xpath: '//div[@id="incontents"]/*[@class="ch04" or @class="fs14" or contains(@class,"diclst")]',
multi: true
},{
names: ['infokanji'],
url: 'http://dictionary.www.infoseek.co.jp/?sc=1&se=on&lp=0&gr=kj&sv=KJ&qt=&qty=%s&qtb=&qtk=0',
shorthelp: 'Infoseek 漢字辞書',
encode: 'EUC-JP',
xpath: '//div[@class="NetDicHead"]'
},{
names: ['answers'],
url: 'http://www.answers.com/%s',
shortHelp: 'Answers.com(英英辞書)',
xpath: 'id("firstDs")'
}];
// class definition
function SpellChecker() {
this.initialize.apply(this, arguments);
}
SpellChecker.prototype = {
initialize: function () {
const MYSPELL = "@mozilla.org/spellchecker/myspell;1";
const HUNSPELL = "@mozilla.org/spellchecker/hunspell;1";
const ENGINE = "@mozilla.org/spellchecker/engine;1";
var spellclass = MYSPELL;
if (HUNSPELL in Components.classes)
spellclass = HUNSPELL;
if (ENGINE in Components.classes)
spellclass = ENGINE;
this.engine = Components.classes[spellclass]
.createInstance(Components.interfaces.mozISpellCheckingEngine);
},
/**
* @return {Array}
*/
getDictionaryList: function () {
var dictionaries = {};
this.engine.getDictionaryList(dictionaries, {});
return dictionaries.value;
},
/**
* @return {String}
*/
dictionary: function () {
var dict;
try { dict = this.engine.dictionary; }
catch (e) {}
return dict ? dict : null;
},
/**
* @param {String} dict
*/
setDictionary: function (dict) {
this.engine.dictionary = dict;
},
/**
* @param {Boolean} isBeginningWith
*/
setBeginningWith: function (isBeginningWith) {
this.isBeginningWith = isBeginningWith;
},
/**
* @param {String} spell
* @return {Boolean}
*/
check: function (spell) {
return this.engine.check(spell);
},
/**
* @param {String} spell
* @return {Array}
*/
suggest: function (spell) {
var suggestions = {};
this.engine.suggest(spell, suggestions, {});
suggestions = suggestions.value;
if (this.isBeginningWith) {
suggestions = suggestions.filter( function (cand) {
return (cand.toLowerCase().indexOf(spell) === 0);
});
}
return suggestions;
},
};
var spellChecker = buildSpellChecker();
SITE_DEFINITION.forEach(function(dictionary){
liberator.commands.addUserCommand(
dictionary.names,
dictionary.shortHelp,
function(arg,special){
var sel = (window.content.window.getSelection) ?
window.content.window.getSelection().toString() : null;
if (special && sel) arg = sel;
if (!arg) return;
var url;
if (dictionary.encode){
var ttbu = Components.classes['@mozilla.org/intl/texttosuburi;1']
.getService( Components.interfaces.nsITextToSubURI);
url = dictionary.url.replace(/%s/g, ttbu.ConvertAndEscape(dictionary.encode, arg));
} else {
url = dictionary.url.replace(/%s/g,encodeURI(arg));
}
//liberator.log('URL: ' +url);
var result;
getHTML(url, function(str){
var doc = createHTMLDocument(str);
var result = getNodeFromXPath(dictionary.xpath, doc, dictionary.multi);
if (!result){
liberator.echoerr('Nothing to show...');
}
var xs = new XMLSerializer();
liberator.echo('' + xs.serializeToString( result ), true);
}, dictionary.encode ? dictionary.encode : 'UTF-8');
},
{
completer: function (arg) {
if (!spellChecker.dictionary()) return [0, []];
var suggestions = spellChecker.suggest(arg);
var candidates = [];
for (var i=0, max=suggestions.length ; i