var PLUGIN_INFO = {NAME} Manage Vimperator Plugin Vimpeatorプラグインの管理 teramako 0.2 2.0pre 2.0pre || var PLUGIN_INFO = ... ||< とE4X形式でXMLを記述してください 各要素は下記参照 === 要素 === name: プラグイン名 description: 簡易説明 属性langに"ja"などと言語を指定するとFirefoxのlocaleに合わせたものになります。 author: 製作者名 属性mailにe-mail、homepageにURLを付けるとリンクされます license: ライセンスについて 属性documentにURLを付けるとリンクされます version: プラグインのバージョン maxVersion: プラグインが使用できるVimperatorの最大バージョン minVersion: プラグインが使用できるVimperatorの最小バージョン detail: ここにコマンドやマップ、プラグインの説明 CDATAセクションにwiki的に記述可能 == Wiki書式 == 見出し: - == heading1 == で第一見出し(h1) - === heading2 === で第二見出し(h2) - ==== heading3 ==== で第三見出し(h3) リスト: - "- "を先頭につけると箇条書きリスト(ul)になります。 - 改行が可能 >|| - 改行 可能 ||< の場合 - 改行 可能 となります。 - ネスト可能 - "+ "を先頭につけると番号付きリスト(ol)になります。 仕様は箇条書きリストと同じです。 定義リスト: - 末尾が":"で終わる行は定義リスト(dl,dt)になります。 - 次行をネストして始めるとdd要素になります。 - これもネスト可能です。 整形式テキスト: >|| と ||< で囲むと整形式テキスト(pre)になります。 コードなどを書きたい場合に使用できるでしょう。 インライン: - mailtoとhttp、httpsスキームのURLはリンクになります == ToDo == - 更新通知とアップデート機能 - スタイルの追加(これはすべき?) ]]> ; liberator.plugins.pluginManager = (function(){ function id(value) value; var lang = window.navigator.language; var tags = { name: function(info) fromUTF8Octets(info.toString()), author: function(info){ var xml = <>{fromUTF8Octets(info.toString())}; if (info.@homepage.toString() != '') xml += <> {makeLink(info.@homepage.toString())}; if (info.@mail.toString() != '') xml += <> ({makeLink("mailto:"+info.@mail)}); return xml; }, description: function(info) makeLink(fromUTF8Octets(info.toString())), license: function(info){ var xml = <>{fromUTF8Octets(info.toString())}; if (info.@document.toString() != '') xml += <> {makeLink(info.@document.toString())}; return xml; }, version: id, maxVersion: id, minVersion: id, detail: function(info){ if (info.* && info.*[0] && info.*[0].nodeKind() == 'element') return info.*; var text = fromUTF8Octets(info.*.toString()); var parser = new WikiParser(text); var xml = parser.parse(); return xml; } }; function chooseByLang(elems){ if (!elems) return null; function get(lang){ var i = elems.length(); while (i-->0){ if (elems[i].@lang.toString() == lang) return elems[i]; } } return get(lang) || get(lang.split('-', 2).shift()) || get('') || get('en-US') || get('en') || elems[0] || elems; } for (let it in Iterator(tags)){ let [name, value] = it; tags[name] = function(info){ if (!info[name]) return null; return value.call(tags, chooseByLang(info[name])); }; } function makeLink(str){ return XMLList(str.replace(/(?:https?:\/\/|mailto:)\S+/g, '$&')); } function fromUTF8Octets(octets){ return decodeURIComponent(octets.replace(/[%\x80-\xFF]/g, function(c){ return '%' + c.charCodeAt(0).toString(16); })); } function getPlugins(){ var list = []; var contexts = liberator.plugins.contexts; for (let path in contexts){ let context = contexts[path]; let info = context.PLUGIN_INFO || null; let plugin = [ ['path', path] ]; plugin['name'] = context.NAME; if (info){ for (let tag in tags){ let value = tags[tag](info); if (value && value.toString().length > 0) plugin.push([tag, value]); } } list.push(plugin); } return list; } function itemFormater(plugin, showDetails){ if (showDetails) return template.table(plugin.name, plugin); var data = plugin.filter(function($_) $_[0] != 'detail'); return template.table(plugin.name, data); } function WikiParser(text){ this.mode = ''; this.lines = text.split(/\n\r|[\r\n]/); this.preCount = 0; this.pendingMode = ''; this.xmlstack = new HTMLStack(); } WikiParser.prototype = { inlineParse: function(str){ function replacer(str){ switch(str){ case '<': return '<'; case '>': return '>'; case '&': return '&'; default: return ''+str+''; } } return XMLList(str.replace(/>|<|&|(?:https?:\/\/|mailto:)\S+/g, replacer)); }, wikiReg: { // {{{ hn: /^(={2,4})\s*(.*?)\s*(\1)$/, dt: /^(.*)\s*:$/, ul: /^\-\s+(.*)$/, ol: /^\+\s+(.*)$/, preStart: /^>\|\|$/, preEnd: /^\|\|<$/, }, // }}} blockParse: function(line, prevMode){ // {{{ if (prevMode == 'pre'){ if (this.wikiReg.preEnd.test(line)){ if (this.preCount > 0){ this.preCount--; return <>{line}; } else { this.mode = ''; return <>; } return <>{line}; } else if (this.wikiReg.preStart.test(line)){ this.preCount++; } return <>{line}; } else if (this.wikiReg.preStart.test(line)){ this.mode = 'pre'; this.pendingMode = prevMode; return
;
        } else if (this.wikiReg.hn.test(line)){
            var hn = RegExp.$1.length - 1;
            this.mode = '';
            return {this.inlineParse(RegExp.$2)};
        } else if (this.wikiReg.ul.test(line)){
            this.mode = 'ul';
            return ;
        } else if (this.wikiReg.ol.test(line)){
            this.mode = 'ol';
            return 
  1. {this.inlineParse(RegExp.$1)}
; } else if (this.wikiReg.dt.test(line)){ this.mode = 'dl'; return
{this.inlineParse(RegExp.$1)}
; } else if (prevMode == 'dl'){ return <>{this.inlineParse(line)}; } this.mode = ''; return <>{this.inlineParse(line)}; }, // }}} parse: function(){ var ite = Iterator(this.lines); var num, line, indent; var currentIndent = 0, indentList = [0], nest=0; var prevMode = ""; var stack = []; var nest; var isNest = false; var bufXML; //try { for ([num, line] in ite){ [,indent, line] = line.match(/^(\s*)(.*)\s*$/); currentIndent = indent.length; var prevIndent = indentList[indentList.length -1]; bufXML = this.blockParse(line, prevMode); if (prevMode == 'pre'){ if (this.mode){ this.xmlstack.appendLastChild(indent.substr(prevIndent) + line + "\n"); } else { this.xmlstack.reorg(-2); this.mode = this.pendingMode; indentList.pop(); if (indentList.length == 0) indentList = [0]; } prevMode = this.mode; continue; } if (!line) { //this.xmlstack.append(<>{"\n"}); continue; } if (currentIndent > prevIndent){ if (this.mode){ if (prevMode == 'dl'){ this.xmlstack.appendChild(
); } this.xmlstack.push(bufXML); indentList.push(currentIndent); } else { if (prevMode && this.xmlstack.length > 0){ this.xmlstack.appendLastChild(bufXML); } else { this.xmlstack.append(bufXML); } this.mode = prevMode; } } else if (currentIndent < prevIndent){ for (var i in indentList){ if (currentIndent == indentList[i] || currentIndent < indentList[i+1]){ nest = i; break; } } indentList.splice(nest); indentList.push(currentIndent); this.xmlstack.reorg(nest); this.xmlstack.append(bufXML); } else { this.xmlstack.append(bufXML); } prevMode = this.mode; } //} catch (e){ alert(num + ":"+ e); } this.xmlstack.reorg(); return this.xmlstack.last; } }; function HTMLStack(){ this.stack = []; } HTMLStack.prototype = { get length() this.stack.length, get last() this.stack[this.length-1], get lastLocalName() this.last[this.last.length()-1].localName(), get inlineElements() ['a','b','i','code','samp','dfn','kbd','br','em','strong','sub','sup','img','span'], isInline: function(xml){ return (xml.length() > 1 || xml.nodeKind() == 'text' || this.inlineElements.indexOf(xml.localName()) >= 0) ? true : false; }, push: function(xml) this.stack.push(xml), append: function(xml){ if (this.length == 0){ this.push(xml); return xml; } var buf = this.last[this.last.length()-1]; if (buf.nodeKind() == 'text'){ this.last[this.last.length()-1] += this.isInline(xml) ? <>
{xml} : xml; } else { if(this.isInline(xml)){ this.stack[this.length-1] += xml; } else if (buf.localName() == xml.localName()){ buf.* += xml.*; } else { this.stack[this.length-1] += xml; } } return this.last; }, appendChild: function(xml) { var buf = this.stack[this.length-1]; buf[buf.length()-1].* += xml; return this.last; }, appendLastChild: function(xml){ var buf = this.last[this.last.length()-1].*; if (buf.length() > 0 && buf[buf.length()-1].nodeKind() == 'element'){ var tmp = buf[buf.length()-1].*; if (tmp[tmp.length()-1].nodeKind() == 'element'){ buf[buf.length()-1].* += xml; } else { buf[buf.length()-1].* += <>
{xml}; } } else { this.last[this.last.length()-1].* += xml; } return this.last; }, reorg: function(from){ if (this.length == 0) return; if (!from) from = 0; var xmllist = this.stack.splice(from); var xml; if (xmllist.length > 1){ xml = xmllist.reduceRight(function(p, c){ var buf = c[c.length()-1].*; if (buf.length() > 0){ if (buf[buf.length()-1].nodeKind() == 'text'){ c += p; } else { buf[buf.length()-1].* += p; } } else { c += p; } return c; }); } else if (xmllist.length > 0){ xml = xmllist[0]; } this.push(xml); return this.last; }, }; commands.addUserCommand(['plugin[help]'], 'list Vimperator plugins', function(args){ liberator.plugins.pluginManager.list(args[0], args['-verbose']); }, { argCount: '*', options: [ [['-verbose', '-v'], commands.OPTION_NOARG], ], completer: function(context){ var all = getPlugins().map(function(plugin){ let desc = '-'; for (let i=plugin.length; i-->0;){ if (plugin[i][0] == 'description'){ desc = plugin[i][1]; break; } } return [plugin.name, desc]; }); context.title = ['PluginName', 'Description']; context.completions = all.filter(function(row) row[0].toLowerCase().indexOf(context.filter.toLowerCase()) >= 0); } }, true); var public = { list: function(name, showDetails){ var xml = <>; var plugins = getPlugins(); if (name){ let plugin = plugins.filter(function(plugin) plugin.name == name)[0]; if (plugin){ xml = itemFormater(plugin, showDetails); } } else { plugins.forEach(function(plugin) xml += itemFormater(plugin, showDetails)); } liberator.echo(xml, true); } }; return public; })(); // vim: sw=4 ts=4 et fdm=marker: