diff options
-rw-r--r-- | pluginManager.js | 528 |
1 files changed, 371 insertions, 157 deletions
diff --git a/pluginManager.js b/pluginManager.js index c94af07..4836cef 100644 --- a/pluginManager.js +++ b/pluginManager.js @@ -11,46 +11,79 @@ var PLUGIN_INFO = これはVimperatorプラグインの詳細情報orヘルプを表示するためのプラグインです。 == Command == :plugin[help] [pluginName] [-v]: - {pluginName}を入れるとそのプラグインの詳細を表示します。 - 省略すると全てのプラグインの詳細を表示します。 - オプション -v はより細かなデータを表示します + {pluginName}を入れるとそのプラグインの詳細を表示します。 + 省略すると全てのプラグインの詳細を表示します。 + オプション -v はより細かなデータを表示します == For plugin Developer == プラグインの先頭に - var PLUGIN_INFO = ... とE4X形式でXMLを記述してください - 各要素は下記参照 +>|| + var PLUGIN_INFO = ... +||< +とE4X形式でXMLを記述してください +各要素は下記参照 -== 要素 == +=== 要素 === name: - プラグイン名 + プラグイン名 description: - 簡易説明 - 属性langに"ja"などと言語を指定するとFirefoxのlocaleに合わせたものになります。 + 簡易説明 + 属性langに"ja"などと言語を指定するとFirefoxのlocaleに合わせたものになります。 author: - 製作者名 - 属性mailにe-mail、homepageにURLを付けるとリンクされます + 製作者名 + 属性mailにe-mail、homepageにURLを付けるとリンクされます license: - ライセンスについて - 属性documentにURLを付けるとリンクされます + ライセンスについて + 属性documentにURLを付けるとリンクされます version: - プラグインのバージョン + プラグインのバージョン maxVersion: - プラグインが使用できるVimperatorの最大バージョン + プラグインが使用できるVimperatorの最大バージョン minVersion: - プラグインが使用できるVimperatorの最小バージョン + プラグインが使用できるVimperatorの最小バージョン detail: - ここにコマンドやマップ、プラグインの説明 - CDATAセクションにwiki的に記述可能 + ここにコマンドやマップ、プラグインの説明 + CDATAセクションにwiki的に記述可能 == Wiki書式 == -* == title == でh1 -* 末尾が「:」で終わる行は定義リストのdt -* dtに続く行が空行でなく、かつ、末尾が「:」でない行は定義リストのdd -* mailtoとhttp、httpsスキームのURLはリンクになります +見出し: + - == heading1 == で第一見出し(h1) + - === heading2 === で第二見出し(h2) + - ==== heading3 ==== で第三見出し(h3) + +リスト: + - "- "を先頭につけると箇条書きリスト(ul)になります。 + - 改行が可能 + >|| + - 改行 + 可能 + ||< + の場合 + + - 改行 + 可能 + + となります。 + - ネスト可能 + + - "+ "を先頭につけると番号付きリスト(ol)になります。 + 仕様は箇条書きリストと同じです。 + +定義リスト: + - 末尾が":"で終わる行は定義リスト(dl,dt)になります。 + - 次行をネストして始めるとdd要素になります。 + - これもネスト可能です。 + +整形式テキスト: + >|| と ||< で囲むと整形式テキスト(pre)になります。 + コードなどを書きたい場合に使用できるでしょう。 + +インライン: + - mailtoとhttp、httpsスキームのURLはリンクになります == ToDo == -* 更新通知とアップデート機能 -* Wiki書式の追加 +- 更新通知とアップデート機能 +- スタイルの追加(これはすべき?) ]]></detail> </VimperatorPlugin>; @@ -60,155 +93,336 @@ 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 = <>{info.toString()}</>; - if (info.@homepage.toString() != '') - xml += <><span> </span>{makeLink(info.@homepage.toString())}</>; - if (info.@mail.toString() != '') - xml += <><span> </span>({makeLink("mailto:"+info.@mail)})</>; - return xml; - }, - description: function(info) makeLink(fromUTF8Octets(info.toString())), - license: function(info){ - var xml = <>{info.toString()}</>; - if (info.@document.toString() != '') - xml += <><span> </span>{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 lines = text.split(/\r\n|[\r\n]/); - var xml = <></>; - var ite = Iterator(lines); - var num, line; - try { while ([num, line] = ite.next()){ - if (!line) continue; - if (/^\s*==(.*)==\s*$/.test(line)){ - xml += <h1 style="font-weight:bold;font-size:medium;">{makeLink(RegExp.$1)}</h1>; - continue; - } - let reg = /^\s*(.+?)\s*:\s*$/; - if (reg.test(line)){ - let dl = <dl><dt>{makeLink(RegExp.$1)}</dt></dl>; - try { while ([num, line] = ite.next()){ - if (!line) break; - if (reg.test(line)){ - dl.* += <dt>{makeLink(RegExp.$1)}</dt>; - } else { - dl.* += <dd>{makeLink(line.replace(/^\s+|\s+$/g, ''))}</dd>; - } - } } catch (e){} - xml += dl; - continue; - } - xml += <>{makeLink(line)}<br/></>; - } } catch (e){} - return xml; - } + name: function(info) fromUTF8Octets(info.toString()), + author: function(info){ + var xml = <>{info.toString()}</>; + if (info.@homepage.toString() != '') + xml += <><span> </span>{makeLink(info.@homepage.toString())}</>; + if (info.@mail.toString() != '') + xml += <><span> </span>({makeLink("mailto:"+info.@mail)})</>; + return xml; + }, + description: function(info) makeLink(fromUTF8Octets(info.toString())), + license: function(info){ + var xml = <>{info.toString()}</>; + if (info.@document.toString() != '') + xml += <><span> </span>{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; + 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])); - }; + 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, '<a href="#" highlight="URL">$&</a>')); + return XMLList(str.replace(/(?:https?:\/\/|mailto:)\S+/g, '<a href="#" highlight="URL">$&</a>')); } function fromUTF8Octets(octets){ - return decodeURIComponent(octets.replace(/[%\x80-\xFF]/g, function(c){ - return '%' + c.charCodeAt(0).toString(16); - })); + 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.toString().length > 0) - plugin.push([tag, value]); - } - } - list.push(plugin); - } - return list; + 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.toString().length > 0) + plugin.push([tag, value]); + } + } + list.push(plugin); + } + return list; } function itemFormater(plugin, showDetails){ - if (showDetails) - return template.table(plugin.name, plugin); + if (showDetails) + return template.table(plugin.name, plugin); - var data = plugin.filter(function($_) $_[0] != 'detail'); - return template.table(plugin.name, data); + 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.xmlstack = new HTMLStack(); +} +WikiParser.prototype = { + inlineParse: function(str){ + function replacer(str){ + switch(str){ + case '<': return '<'; + case '>': return '>'; + case '&': return '&'; + default: + return '<a href="#" highlight="URL">'+str+'</a>'; + } + } + 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'; + return <pre/>; + } else if (this.wikiReg.hn.test(line)){ + var hn = RegExp.$1.length - 1; + this.mode = ''; + return <h{hn} highlight="Title" style={"font-size:"+(0.75+1/hn)+"em"}>{this.inlineParse(RegExp.$2)}</h{hn}>; + } else if (this.wikiReg.ul.test(line)){ + this.mode = 'ul'; + return <ul><li>{this.inlineParse(RegExp.$1)}</li></ul>; + } else if (this.wikiReg.ol.test(line)){ + this.mode = 'ol'; + return <ol><li>{this.inlineParse(RegExp.$1)}</li></ol>; + } else if (this.wikiReg.dt.test(line)){ + this.mode = 'dl'; + return <dl><dt style="font-weight:bold;">{this.inlineParse(RegExp.$1)}</dt></dl>; + } 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.xmlstack.lastLocalName; + if (this.mode == 'pre') this.mode = ''; + 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(<dd/>); + } + this.xmlstack.push(bufXML); + indentList.push(currentIndent); + } else { + if (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) ? <><br/>{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].* += <><br/>{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); + 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); - } + 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 fdm=marker: |