aboutsummaryrefslogtreecommitdiffstats
path: root/spellchecker.js
blob: de521a8bbfcc085f19281733cde2f97165ed05f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * ==VimperatorPlugin==
 * @name            spellchecker.js
 * @description     provide the object for spell check.
 * @description-ja  スペルチェック用のオブジェクトを提供する。
 * @author          janus_wel <janus_wel@fb3.so-net.ne.jp>
 * @version         0.10
 * @minversion      2.0pre 2008/10/16
 * ==/VimperatorPlugin==
 *
 * LICENSE
 *   New BSD License
 *
 * USAGE
 *   the object is available in liberator.modules.plugins.spellchecker.
 *   set the dictionary and call check or suggest method.
 *   you can use :availabledictionaries and :adict commands
 *   to know available dictionaries.
 *   all 'set' method is return the reference of spellchecker object itself,
 *   so you can connect methods.
 *
 * METHOD
 *  setDictionary(dict)     set dictionary to check the spell
 *  setBeginningWith(bool)  set 
 *  getDictionaryList()     get available dictionaries
 *  getDictionary()         return dictionary name to use for spell checking
 *  check(word)             if word exists in dictionary, return true, not exists, return false
 *  suggest(word)           word suggestion. return generator of iterator
 *
 * EXAMPLE
 *  1. plugins.spellchecker.setDictionary('en-US').suggest('liberater');
 *      -> liberate
 *         liberate r
 *         liberated
 *         liberates
 *         liberator
 *
 *  2. plugins.spellchecker.check('liberater');
 *      -> false
 * */

( function () {

// SpellChecker
function SpellChecker() {
    this._initialize.apply(this, arguments);
}

SpellChecker.prototype = {
    _initialize: function (dict) {
        // refer: https://developer.mozilla.org/En/Using_spell_checking_in_XUL
        const MOZILLA  = '@mozilla.org/spellchecker/';
        const MYSPELL  = MOZILLA + 'myspell;1';
        const HUNSPELL = MOZILLA + 'hunspell;1';
        const ENGINE   = MOZILLA + 'engine;1';
        const Cc = Components.classes;
        const Ci = Components.interfaces;

        let spellclass = MYSPELL;
        if (HUNSPELL in Cc) spellclass = HUNSPELL;
        if (ENGINE in Cc)   spellclass = ENGINE;
        this._engine = Cc[spellclass].createInstance(Ci.mozISpellCheckingEngine);

        // if dictionary is assigned, set it.
        if (dict) this.setDictionary(dict);
    },

    // list of available dictionaries
    getDictionaryList: function () {
        let dictionaries = {};
        this._engine.getDictionaryList(dictionaries, {});
        for (let [, v] in Iterator(dictionaries.value)) yield v;
    },

    setDictionary: function (dict) {
        for (let d in this.getDictionaryList()) {
            if (d === dict) {
                this._engine.dictionary = dict;
                return this;
            }
        }
        throw new Error('the assigned dictionary is unavailable.');
    },

    getDictionary: function () {
        let dict;
        try { dict = this._engine.dictionary; }
        catch (e) {}
        return dict || null;
    },

    setBeginningWith: function (isBeginningWith) {
        this.isBeginningWith = isBeginningWith;
        return this;
    },

    check: function (spell) this._engine.check(spell),

    suggest: function (spell) {
        let suggestions = {};
        this._engine.suggest(spell, suggestions, {});
        suggestions = suggestions.value;

        if (this.isBeginningWith) {
            suggestions = suggestions.filter( function (cand) {
                return (cand.toLowerCase().indexOf(spell) === 0);
            });
        }

        for (let [, v] in Iterator(suggestions)) yield v;
    },
};

plugins.spellchecker = new SpellChecker();
commands.addUserCommand(
    ['availabledictionaries', 'adict'],
    'display available dictionaries',
    function () liberator.echo('available dictionaries: ' + [a for (a in plugins.spellchecker.getDictionaryList())].join(', ')),
    {}
);

})();

// vim: sw=4 sts=4 ts=4 et
an class="o"><dt>%TITLE%</dt> <dd>to the title of the current page</dd> <dt>%URL%</dt> <dd>to the currenet URL</dd> <dt>%SEL</dt> <dd>to the string of selection</dd> <dt>%HTMLSEL</dt> <dd>to the html string of selection</dd> <dt>%HOSTNAME%</dt> <dd>to the hostname of the current location</dd> <dt>%PATHNAME%</dt> <dd>to the pathname of the current location</dd> <dt>%HOST%</dt> <dd>to the host of the current location</dd> <dt>%PORT%</dt> <dd>to the port of the current location</dd> <dt>%PROTOCOL%</dt> <dd>to the protocol of the current location</dd> <dt>%SERCH%</dt> <dd>to the search(?...) of the curernt location</dd> <dt>%HASH%</dt> <dd>to the hash(anchor #..) of the current location</dd> </dl> </description> </item> <item> <tags>copy-template</tags> <spec>copy-template</spec> <description> <p>you can set your own template using inline JavaScript</p> <code><![CDATA[ javascript <<EOM liberator.globalVariables.copy_templates = [ { label: 'titleAndURL', value: '%TITLE%\n%URL%' }, { label: 'title', value: '%TITLE%', map: ',y' }, { label: 'anchor', value: '<a href="%URL%">%TITLE%</a>' }, { label: 'selanchor', value: '<a href="%URL%" title="%TITLE%">%SEL%</a>' }, { label: 'htmlblockquote', value: '<blockquote cite="%URL%" title="%TITLE%">%HTMLSEL%</blockquote>' } { label: 'ASIN', value: 'copy ASIN code from Amazon', custom: function(){return content.document.getElementById('ASIN').value;} }, ]; EOM ]]></code> <dl> <dt>label</dt> <dd>template name which is command argument</dd> <dt>value</dt> <dd>copy string. <a>copy-keyword</a> is replaced</dd> <dt>map</dt> <dd>key map <a>lhs</a> (optional)</dd> <dt>custom</dt> <dd> <a>function</a> or <a>Array</a> (optional) <dl> <dt><a>function</a></dt> <dd>execute the function and copy return value, if specified</dd> <dt><a>Array</a></dt> <dd> replace to the <a>value</a> by normal way at first. then replace words matched <a>Array</a>[0] in the repalced string to <a>Array</a>[1]. <dl> <dt><a>Array</a>[0]</dt> <dd>String or RegExp</dd> <dt><a>Array</a>[1]</dt> <dd>String or Function</dd> </dl> see: <link topic="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:String:replace">http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:String:replace</link> </dd> </dl> </dd> </dl> </description> </item> <item> <tags>copy-option</tags> <spec>copy-option</spec> <description> <code><ex>liberator.globalVariables.copy_use_wedata = false; // false by default</ex></code> <p>true に設定すると wedata からテンプレートを読込みます</p> <code><ex>liberator.globalVariables.copy_wedata_include_custom = true; // false by default</ex></code> <p>custom が設定された wedata を読込みます SandBox でなくwindow.eval を利用してオブジェクトする為 セキュリティ上の理由で初期設定は false になっています true に設定する場合は動作を理解したうえ自己責任でご利用ください</p> <code><ex>liberator.globalVariables.copy_wedata_exclude_labels = ['pathtraqnormalize', ];</ex></code> <p>wedata から読込まない label のリストを定義します</p> </description> </item> </plugin>; var PLUGIN_INFO = <VimperatorPlugin> <name>{NAME}</name> <description>enable to copy strings from a template (like CopyURL+)</description> <description lang="ja">テンプレートから文字列のコピーを可能にしますCopyURL+みたいなもの</description> <minVersion>2.0pre</minVersion> <maxVersion>2.0pre</maxVersion> <updateURL>https://github.com/vimpr/vimperator-plugins/raw/master/copy.js</updateURL> <author mail="teramako@gmail.com" homepage="http://vimperator.g.hatena.ne.jp/teramako/">teramako</author> <license>MPL 1.1/GPL 2.0/LGPL 2.1</license> <version>0.7.5</version> </VimperatorPlugin>; liberator.plugins.exCopy = (function(){ var excludeLabelsMap = {}; var copy_templates = []; if (!liberator.globalVariables.copy_templates){ liberator.globalVariables.copy_templates = [ { label: 'titleAndURL', value: '%TITLE%\n%URL%' }, { label: 'title', value: '%TITLE%' }, { label: 'anchor', value: '<a href="%URL%">%TITLE%</a>' }, { label: 'selanchor', value: '<a href="%URL%" title="%TITLE%">%SEL%</a>' }, { label: 'htmlblockquote', value: '<blockquote cite="%URL%" title="%TITLE%">%HTMLSEL%</blockquote>' } ]; } copy_templates = liberator.globalVariables.copy_templates.map(function(t){ return { label: t.label, value: t.value, custom: t.custom, map: t.map } }); copy_templates.forEach(function(template){ if (typeof template.map == 'string') addUserMap(template.label, [template.map]); else if (template.map instanceof Array) addUserMap(template.label, template.map); }); const REPLACE_TABLE = { get TITLE () buffer.title, get URL () buffer.URL, get SEL () { var sel = ''; var win = new XPCNativeWrapper(window.content.window); var selection = win.getSelection(); if (selection.rangeCount < 1) return ''; for (var i=0, c=selection.rangeCount; i<c; i++){ sel += selection.getRangeAt(i).toString(); } return sel; }, get HTMLSEL () { var htmlsel = ''; var win = new XPCNativeWrapper(window.content.window); var selection = win.getSelection(); if (selection.rangeCount < 1) return ''; var serializer = new XMLSerializer(); for (var i=0, c=selection.rangeCount; i<c; i++){ htmlsel += serializer.serializeToString(selection.getRangeAt(i).cloneContents()); } return htmlsel.replace(/<(\/)?(\w+)([\s\S]*?)>/g, function(all, close, tag, attr){ return "<" + close + tag.toLowerCase() + attr + ">"; }); }, get CLIP () { return util.readFromClipboard(); } }; 'hostname pathname host port protocol search hash'.split(' ').forEach(function (name){ REPLACE_TABLE[name.toUpperCase()] = function () content.location && content.location[name]; }); // used when argument is none //const defaultValue = templates[0].label; commands.addUserCommand(['copy'],'Copy to clipboard', function(args){ liberator.plugins.exCopy.copy(args.literalArg, args.bang, !!args["-append"]); },{ completer: function(context, args){ if (args.bang){ completion.javascript(context); return; } context.title = ['Template','Value']; var templates = copy_templates.map(function(template) [template.label, liberator.modules.util.escapeString(template.value, '"')] ); if (!context.filter){ context.completions = templates; return; } var candidates = []; var filter = context.filter.toLowerCase(); context.completions = templates.filter(function(template) template[0].toLowerCase().indexOf(filter) == 0); }, literal: 0, bang: true, options: [ [["-append","-a"], commands.OPTION_NOARG] ] }, true ); function addUserMap(label, map){ mappings.addUserMap([modes.NORMAL,modes.VISUAL], map, label, function(){ liberator.plugins.exCopy.copy(label); }, { rhs: label } ); } function getCopyTemplate(label){ var ret = null; copy_templates.some(function(template) template.label == label ? (ret = template) && true : false); return ret; } function replaceVariable(str){ if (!str) return ''; function replacer(orig, name){ //{{{ if (name == '') return '%'; if (!REPLACE_TABLE.hasOwnProperty(name)) return orig; let value = REPLACE_TABLE[name]; if (typeof value == 'function') return value(); else return value.toString(); return orig; } //}}} return str.replace(/%([A-Z]*)%/g, replacer); } function wedataRegister(item){ var libly = liberator.plugins.libly; var logger = libly.$U.getLogger("copy"); item = item.data; if (excludeLabelsMap[item.label]) return; if (item.custom && item.custom.toLowerCase().indexOf('function') != -1) { if (!liberator.globalVariables.copy_wedata_include_custom || item.label == 'test') { logger.log('skip: ' + item.label); return; } let custom = (function(item){ return function(value, value2){ var STORE_KEY = 'plugins-copy-ok-func'; var store = storage.newMap(STORE_KEY, {store: true}); var check = store.get(item.label); var ans; if (!check){ ans = window.confirm( 'warning!!!: execute "' + item.label + '" ok ?\n' + '(this function is working with unsafe sandbox.)\n\n' + '----- execute code -----\n\n' + 'value: ' + item.value + '\n' + 'function: ' + item.custom ); } else { if (item.value == check.value && item.custom == check.custom && item.map == check.map){ ans = true; } else { ans = window.confirm( 'warning!!!: "' + item.label + '" was changed when you registered the function.\n' + '(this function is working with unsafe sandbox.)\n\n' + '----- execute code -----\n\n' + 'value: ' + item.value + '\n' + 'function: ' + item.custom ); } } if (!ans) return; store.set(item.label, item); store.save(); var func; try{ func = window.eval('(' + item.custom + ')'); } catch (e){ logger.echoerr(e); logger.log(item.custom); return; } return func(value, value2); }; })(item); exCopyManager.add(item.label, item.value, custom, item.map); } else { exCopyManager.add(item.label, item.value, null, item.map); } } var exCopyManager = { add: function(label, value, custom, map){ var template = {label: label, value: value, custom: custom, map: map}; copy_templates.unshift(template); if (map) addUserMap(label, map); return template; }, get: function(label){ return getCopyTemplate(label); }, copy: function(arg, special, appendMode){ var copyString = ''; var isError = false; if (special && arg){ try { copyString = liberator.eval(arg); switch (typeof copyString){ case 'object': copyString = copyString === null ? 'null' : copyString.toSource(); break; case 'function': copyString = copyString.toString(); break; case 'number': case 'boolean': copyString = '' + copyString; break; case 'undefined': copyString = 'undefined'; break; } } catch (e){ isError = true; copyString = e.toString(); } } else { if (!arg) arg = copy_templates[0].label; var template = getCopyTemplate(arg) || {value: arg}; if (typeof template.custom == 'function'){ copyString = template.custom.call(this, template.value, replaceVariable(template.value)); } else if (template.custom instanceof Array){ copyString = replaceVariable(template.value).replace(template.custom[0], template.custom[1]); } else { copyString = replaceVariable(template.value); } } if (appendMode){ copyString = util.readFromClipboard() + copyString; } if (copyString) util.copyToClipboard(copyString); if (isError){ liberator.echoerr('CopiedErrorString: `' + copyString + "'"); } else { liberator.echo('CopiedString: `' + util.escapeHTML(copyString || '') + "'"); } } }; if (liberator.globalVariables.copy_use_wedata){ function loadWedata(){ if (!liberator.plugins.libly){ liberator.echomsg("need a _libly.js when use wedata."); return; } var libly = liberator.plugins.libly; copy_templates.forEach(function(item) excludeLabelsMap[item.label] = item.value); if (liberator.globalVariables.copy_wedata_exclude_labels) liberator.globalVariables.copy_wedata_exclude_labels.forEach(function(item) excludeLabelsMap[item] = 1); var wedata = new libly.Wedata("vimp%20copy"); wedata.getItems(24 * 60 * 60 * 1000, wedataRegister); } loadWedata(); } return exCopyManager; })(); // vim: set fdm=marker sw=4 ts=4 et: