let PLUGIN_INFO = {NAME} Show/Open related blog 現在ページへリンクしているブログを表示または開くプラグイン teramako 1.0 MPL 1.1/GPL 2.0/LGPL 2.1 2.0pre 2.0 https://github.com/vimpr/vimperator-plugins/raw/master/relatedBlogSearch.js || tab relatedblog {URL} ||< とすることで新規タブに開けます。 また、リストを表示した後、";o" などのヒントからも開けるでしょう。(historyコマンドに似ている) == 変数 == let コマンドで設定してください(しない場合はデフォルト値が使用されます) :g:blogSearchHeaderTemplate: リストを表示する時のヘッダとなるXML文字列 省略時は以下が使用されます。 >|| '
TitleAuthorContent
'; ||< :g:blogSearchBodyTemplate: リストを表示する時のコンテンツとなるXML文字列 省略時は以下が使用されます。 >|| '%title%%author%%content%'; ||< また、%で囲まれた特定の文字列が変数として使用されます。 %link%: 対象ページのURL %title%: 対象ページのタイトル %author%: 対象ページの著者 %content%: 対象ページの内容(一部) %rootURI%: 対象ページのトップページのURL %id%: 不明(ドメイン、日付、パスが含まれる) %published%: 投稿された日時(%Y-%m-%dT%H:%M:%SZ) %updated%: 更新された日時(%Y-%m-%dT%H:%M:%SZ) ]]>
; liberator.plugins.relatedBlogSearch = (function(){ const LANG = window.navigator.language; const BLOGSEARCH_URL = 'http://blogsearch.google.com/blogsearch_feeds?output=atom&hl=' + LANG + '&q='; /** * Serach with Google blogsearch and get entries * @param {String} name query string */ function BlogSearch() { this._init.apply(this, arguments); } BlogSearch.prototype = { _init: function(name){ if (!name) throw Components.results.NS_ERROR_XPC_NOT_ENOUGH_ARGS; this.date = new Date(); this.name = name; this.query = BLOGSEARCH_URL + this.name; let self = this; this.items = Array.map( util.httpGet(this.query).responseXML.getElementsByTagName("entry"), function(entry) self._parse(entry) ); }, /** * @param {Element} entryElm Atom entry element * @return {Object} */ _parse: function(entryElm){ let entry = {}; Array.forEach(entryElm.childNodes, function(elm){ let tagName = elm.localName; switch(tagName){ case 'link': entry.link = elm.getAttribute('href'); break; case 'author': entry.author = elm.childNodes[0].textContent; entry.rootURI = elm.childNodes[1].textContent; break; default: entry[tagName] = elm.textContent; } }); return entry; }, /** * @param {RegExp} reg * @param {String[]} itemNames item's property names * @return {Object[]} item list */ search: function(reg, itemNames){ if (!itemNames) itemNames = [name for (name in this.items[0])]; return this.items.filter(function(item) itemNames.some(function(name) reg.test(item[name]))); }, /** * @param {String} template * @param {XMLList} xml header XML * @param {Object[]} items if omitted, used all items * template e.g.) * '%title%%author%%content%' */ toXMLByTemplate: function(template, xml, items){ if (!items) items = this.items; function entryToXML(item){ function replacer(all, name) name in item ? item[name] : all; return new XMLList(template.replace(/%(\w+?)%/g, replacer).replace(/&/g,"&")); } items.forEach(function(item){xml.* += entryToXML(item);}); return xml; }, }; /** * -query option completion list * e.g.) * return [ * ["link:https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects", "-"], * ["link:https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference", "-"], * ["link:https://developer.mozilla.org/en", "-"], * ["link:https://developer.mozilla.org", "-"], * ] * when current url is "https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects" * @return {String[][]} */ function getQueryList(){ return buffer.URL.split(/\/(?!\/)/).reduce(function(p,c){ p.length == 0 ? p.push(c) : p.push(p[p.length-1]+"/"+c); return p; },[]).splice(1).map(function(url) ["link:" + url, "-"]).reverse(); } // ---------------------------------------------- // command // ---------------------------------------------- commands.addUserCommand(["relatedblog"], "search linked blog from google blogsearch", function(args){ let query = args["-query"] ? args["-query"] : "link:" + buffer.URL; let entry = manager.getCache(query); let header = new XMLList(manager.headerTemplate); if (args.length == 0){ let xml = entry.toXMLByTemplate(manager.bodyTemplate, header); liberator.echo(xml, true); } else { let reg = new RegExp(args[0], "i"); let items = entry.search(reg); if (items.length > 1){ liberator.echo(entry.toXMLByTemplate(manager.bodyTemplate, header, items),true); } else if (items.length == 1){ let url = items[0].link; liberator.open(url); } else { liberator.echomsg("related blog is none",5); } } },{ options: [ [["-query", "-q"], commands.OPTION_STRING, null, getQueryList] ], argCount: "?", completer: function(context, args){ manager.completer(context, args); }, },true); // ---------------------------------------------- // public // ---------------------------------------------- var manager = { get bodyTemplate(){ return liberator.globalVariables.blogSearchBodyTemplate ? liberator.globalVariables.blogSearchBodyTemplate : '%title%%author%%content%'; }, get headerTemplate(){ return liberator.globalVariables.blogSearchHeaderTemplate ? liberator.globalVariables.blogSearchHeaderTemplate : '
TitleAuthorContent
'; }, /** * @type {BlogSerach[]} */ cache: [], /** * キャッシュからエントリを取得 * キャッシュがないまたは期限切れの場合は新たに取得 * キャッシュのリストは10個まで XXX: 外だししたほうが良いかもしれない * XXX: 有効期限を変数に持たせた方が良いかもしれない * @param {String} name query string * @return {BlogSearch} */ getCache: function(name){ let cache = this.cache.filter(function(entry) entry.name == name); if (cache.length == 0){ let entry = new BlogSearch(name); if(this.cache.push(entry) > 10) this.cache.shift(); return entry; } else if (cache[0].date < Date.now() - 5*60*1000){ cache[0]._init(name); } return cache[0]; }, /** * relatedblog コマンド用の補完関数 * @param {CompletionContext} context * @param {String[]} args */ completer: function(context, args){ let query = args["-query"] ? args["-query"] : "link:" + buffer.URL; let entry = this.getCache(query) context.title = ["URL", "Title"]; if (args.length == 0){ context.completions = entry.items.map(function(item) [item.link, item.title]); } else { let reg = new RegExp(context.filter, "i"); context.completions = entry.search(reg).map(function(item) [item.link, item.title]); } }, }; return manager; })(); // vim: sw=2 ts=2 et: 145'>145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
/* {{{
Copyright (c) 2008, anekos.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. The names of the authors may not be used to endorse or promote products
       derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.


###################################################################################
# http://sourceforge.jp/projects/opensource/wiki/licenses%2Fnew_BSD_license       #
# に参考になる日本語訳がありますが、有効なのは上記英文となります。                #
###################################################################################

}}} */

// PLUGIN_INFO {{{
let PLUGIN_INFO =
<VimperatorPlugin>
  <name>translaten</name>
  <name lang="ja">自動一括翻訳</name>
  <description>Automatically translate by clipboard changes</description>
  <description lang="ja">クリップボードの変更を監視して一括翻訳サービスに流し込む</description>
  <version>1.0</version>
  <author mail="anekos@snca.net" homepage="http://d.hatena.ne.jp/nokturnalmortum/">anekos</author>
  <license>new BSD License (Please read the source code comments of this plugin)</license>
  <license lang="ja">修正BSDライセンス (ソースコードのコメントを参照してください)</license>
  <minVersion>2.0pre</minVersion>
  <maxVersion>2.0pre</maxVersion>
  <detail><![CDATA[
    == Activation ==
      >||
        set translaten
      ||<
  ]]></detail>
  <detail lang="ja"><![CDATA[
    == Usage ==
      特に操作は必要ありません
      >||
        set translaten
      ||<
      有効化した後にクリップボードに変化があればその内容を 'http://7go.biz/translation/' に流し込んで翻訳します
    == Link ==
      http://vimperator.g.hatena.ne.jp/nokturnalmortum/20090104/1231070505
  ]]></detail>
</VimperatorPlugin>;
// }}}

(function () {

  const URL = 'http://7go.biz/translation/';

  function TranslaTen () {
    this.handle;
    this.running = false;
  }

  function inTheSite ()
    (~buffer.URL.indexOf(URL))

  TranslaTen.prototype = {
    get clipboard () util.readFromClipboard(),

    open: function () {
      if (inTheSite())
        return;
      if (buffer.URL == 'about:blank')
        return liberator.open(URL, liberator.CURRENT_TAB);
      for (let [number, browser] in Iterator(tabs.browsers)) {
        if (~browser.contentDocument.location.href.indexOf(URL))
          return liberator.modules.tabs.select(number, false);
      }
      liberator.open(URL, liberator.NEW_TAB);
    },

    stop: function () {
      if (this.handle) {
        clearInterval(this.handle);
        this.handle = null;
      }
      this.running = false;
    },

    run: function () {
      let self = this;
      if (this.running)
        return;
      this.running = true;
      this.prev = this.clipboard;
      this.open();
      this.handle = setInterval(
        function () {
          let now = self.clipboard;
          if (now == self.prev)
            return;
          self.prev = now;
          self.open();
          let f = function () { self.elements.textarea.value = now; self.elements.submit.click(); };
          if (inTheSite()) {
            f();
          } else {
            let handle = setInterval(
              function () {
                if (inTheSite() && buffer.loaded