// Hatena from: // http://tech.nitoyon.com/javascript/application/texthatena/wordpro/text-hatena.js CmdUtils.CreateCommand({ name: "hatena", execute: function() { this._init(); /* * test h3 ** test h4 paragraph 1 paragraph 2 >|| this is code block. <> are become <> ||< - list1 ul - list2 ul + list1 ol + list2 ol */ CmdUtils.setSelection( this.parse(CmdUtils.getSelection()) ); }, preview: function(pblock){ this._init(); pblock.innerHTML='
'+this.parse(CmdUtils.getSelection())+'
'; }, parse: function(str){ var h=this.hatena(); h.parse(str); return (h.html()).replace(/&/g,"&").replace(//g, ">"); s = s.replace(/"/g, """); s = s.replace(/\'/g, "'"); s = s.replace(/\\/g, "\"); return s; } String._unescapeHTML = function(s){ s = s.replace(/&/g, "&"); s = s.replace(/</g, "<"); s = s.replace(/>/g, ">"); s = s.replace(/"/g, "\""); return s; } // Hatena::Hatena_HTMLFilter Hatena_HTMLFilter = function(args){ this.self = { context : args["context"], html : '' }; this.init(); } Hatena_HTMLFilter.prototype = { init :function(){ // HTML::Parser を利用すべきなんだけど JavaScript ではなんとも... }, parse : function(html){ var c = this.self.context; this.self.html = c.self.texthandler(html, c); }, html : function(){ return this.self.html; } } // Hatena Hatena = function(args){ if(args == null) args = {}; this.self = { html : '', baseuri : args["baseuri"], permalink : args["permalink"] || "", ilevel : args["ilevel"] || 0, invalidnode : args["invalidnode"] || [], sectionanchor : args["sectionanchor"] || 'o-', texthandler : args["texthandler"] || function(text, c){ // footnote var p = c.self.permalink; var html = ""; var foot = text.split("(("); for(var i = 0; i < foot.length; i++){ if(i == 0){ html += foot[i]; continue; } var s = foot[i].split("))", 2); if(s.length != 2){ html += "((" + foot[i]; continue; } var pre = foot[i - i]; var note = s[0]; var post = foot[i].substr(s[0].length + 2); if(pre.match(/\)$/) && post.match(/^\(/)){ html += "((" + post; } else { var notes = c.footnotes(note); var num = notes.length; note = note.replace(/<.*?>/g, ""); note = note.replace(/&/g, "&"); html += '*' + num + '' + post; } } return html; } }; } Hatena.prototype = { parse : function(text){ this.self.context = new Hatena_Context({ text : text || "", baseuri : this.self.baseuri, permalink : this.self.permalink, invalidnode : this.self.invalidnode, sectionanchor : this.self.sectionanchor, texthandler : this.self.texthandler }); var c = this.self.context; var node = new Hatena_BodyNode(); node._new({ context : c, ilevel : this.self.ilevel }); node.parse(); var parser = new Hatena_HTMLFilter({ context : c }); parser.parse(c.html()); this.self.html = parser.html(); if (this.self.context.footnotes().length != 0) { var node = new Hatena_FootnoteNode(); node._new({ context : this.self.context, ilevel : this.self.ilevel }); node.parse(); this.self.html += "\n"; this.self.html += node.self.html; } }, html : function(){ return this.self.html; } } // Hatena::Context Hatena_Context = function(args){ this.self = { text : args["text"], baseuri : args["baseuri"], permalink : args["permalink"], invalidnode : args["invalidnode"], sectionanchor : args["sectionanchor"], texthandler : args["texthandler"], _htmllines : [], footnotes : Array(), sectioncount : 0, syntaxrefs : [], noparagraph : 0 }; this.init(); } Hatena_Context.prototype = { init : function() { this.self.text = this.self.text.replace(/\r/g, ""); this.self.lines = this.self.text.split('\n'); this.self.index = -1; }, hasnext : function() { return (this.self.lines != null && this.self.lines.length - 1 > this.self.index); }, nextline : function() { return this.self.lines[this.self.index + 1]; }, shiftline : function() { return this.self.lines[++this.self.index]; }, currentline : function() { return this.self.lines[this.self.index]; }, html : function() { return this.self._htmllines.join ("\n"); }, htmllines : function(line) { if(line != null) this.self._htmllines.push(line); return this.self._htmllines; }, lasthtmlline : function() {return this.self._htmllines[this.self._htmllines.length - 1]; }, footnotes : function(line) { if(line != null) this.self.footnotes.push(line); return this.self.footnotes; }, syntaxrefs : function(line) { if(line != null) this.self.syntaxrefs.push(line); return this.self.syntaxrefs; }, syntaxpattern : function(pattern) { if(pattern != null) this.self.syntaxpattern = pattern; return this.self.syntaxpattern; }, noparagraph : function(noparagraph) { if(noparagraph != null) this.self.noparagraph = noparagraph; return this.self.noparagraph; }, incrementsection : function() { return this.self.sectioncount++; } } // Hatena::Node Hatena_Node = function(){} Hatena_Node.prototype = { html : "", pattern : "", _new : function(args){ if(args == null) args = Array(); this.self = { context : args["context"], ilevel : args["ilevel"], html : '' }; this.init(); }, init : function(){ this.self.pattern = ''; }, parse : function(){ alert('die'); }, context : function(v){ this.self.context = v; } }; // Hatena::BodyNode Hatena_BodyNode = function(){}; Hatena_BodyNode.prototype = Object.extend(new Hatena_Node(), { parse : function(){ var c = this.self.context; while (this.self.context.hasnext()) { var node = new Hatena_SectionNode(); node._new({ context : c, ilevel : this.self.ilevel }); node.parse(); } } }) // Hatena::BrNode Hatena_BrNode = function(){}; Hatena_BrNode.prototype = Object.extend(new Hatena_Node(), { parse : function(){ var c = this.self.context; var l = c.shiftline(); if(l.length != 0) return; var t = String.times("\t", this.self.ilevel); if (c.lasthtmlline() == t + "
" || c.lasthtmlline() == t) { c.htmllines(t + "
"); } else { c.htmllines(t); } } }) // Hatena::CDataNode Hatena_CDataNode = function(){}; Hatena_CDataNode.prototype = Object.extend(new Hatena_Node(), { parse : function(){ var c = this.self.context; var t = String.times("\t", this.self.ilevel); var l = c.shiftline(); var text = new Hatena_Text(); text._new({context : c}); text.parse(l); l = text.html(); c.htmllines(t + l); } }) // Hatena::DlNode Hatena_DlNode = function(){}; Hatena_DlNode.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^\:((?:<[^>]+>|\[\].+?\[\]|\[[^\]]+\]|\[\]|[^\:<\[]+)+)\:(.+)$/; }, parse : function(){ var c = this.self.context; var l = c.nextline(); if(!l.match(this.self.pattern)) return; this.self.llevel = RegExp.$1.length; var t = String.times("\t", this.self.ilevel); c.htmllines(t + "
"); while (l = c.nextline()) { if(!l.match(this.self.pattern)) break; c.shiftline(); c.htmllines(t + "\t
" + RegExp.$1 + "
"); c.htmllines(t + "\t
" + RegExp.$2 + "
"); } c.htmllines(t + "
"); } }) // Hatena::FootnoteNode Hatena_FootnoteNode = function(){}; Hatena_FootnoteNode.prototype = Object.extend(new Hatena_Node(), { html : "", parse : function(){ var c = this.self["context"]; if(c.self.footnotes == null || c.self.footnotes.length == 0) return; var t = String.times("\t", this.self["ilevel"]); var p = c.self.permalink; this.self["html"] = ''; this.self.html += t + '
\n'; var num = 0; var text = new Hatena_Text(); text._new({context : c}); for(var i = 0; i < c.self.footnotes.length; i++) { var note = c.self.footnotes[i]; num++; text.parse(note); var l = t + '\t

*' + num + ': ' + text.html() + '

'; this.self["html"] += l + "\n"; } this.self["html"] += t + '
\n'; } }) // Hatena::H3Node Hatena_H3Node = function(){}; Hatena_H3Node.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^\*(?:(\d{9,10}|[a-zA-Z]\w*)\*)?((?:\[[^\:\[\]]+\])+)?(.*)$/; }, parse : function(){ var c = this.self.context; var l = c.shiftline(); if(l == null) return; if(!l.match(this.self.pattern)) return; var name = RegExp.$1; var cat = RegExp.$2; var title = RegExp.$3; var b = c.self.baseuri; var p = c.self.permalink; var t = String.times("\t", this.self.ilevel); var sa = c.self.sectionanchor; /* TODO: カテゴリは未対応 if (cat) { if(cat.match(/\[([^\:\[\]]+)\]/)){ // 繰り返しできないなぁ... var w = RegExp.$1; var ew = escape(RegExp.$1); cat = cat.replace(/\[([^\:\[\]]+)\]/, '[' + w + ']'); } }*/ var extra = ''; var ret = this._formatname(name); var name = (ret[0] != undefined ? ret[0] : ""); extra = (ret[1] != undefined ? ret[1] : ""); c.htmllines(t + '

' + sa + ' ' + cat + title + '

' + extra); }, _formatname : function(name){ /* TODO: 時間も未対応。表示時の時間が表示されてしまう... if (name && name.match(/^\d{9,10}$/)) { var m = sprintf('%02d', (localtime($name))[1]); var h = sprintf('%02d', (localtime($name))[2]); return ( $name, qq| $h:$m|, ); } elsif ($name) {*/ if(name != ""){ return [name]; } else { this.self.context.incrementsection(); name = 'p' + this.self.context.self.sectioncount; return [name]; } } }) // Hatena::H4Node Hatena_H4Node = function(){}; Hatena_H4Node.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^\*\*((?:[^\*]).*)$/; }, parse : function(){ var c = this.self.context; var l = c.shiftline(); if(l == null) return; if(!l.match(this.self.pattern)) return; var t = String.times("\t", this.self.ilevel); c.htmllines(t + "

" + RegExp.$1 + "

"); } }) // Hatena::H5Node Hatena_H5Node = function(){}; Hatena_H5Node.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^\*\*\*((?:[^\*]).*)$/; }, parse : function(){ var c = this.self.context; var l = c.shiftline(); if(l == null) return; if(!l.match(this.self.pattern)) return; var t = String.times("\t", this.self.ilevel); c.htmllines(t + "
" + RegExp.$1 + "
"); } }) // Hatena::ListNode Hatena_ListNode = function(){}; Hatena_ListNode.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^([\-\+]+)([^>\-\+].*)$/; }, parse : function(){ var c = this.self.context; var l = c.nextline(); if(!l.match(this.self.pattern)) return; this.self.llevel = RegExp.$1.length; var t = String.times("\t", this.self.ilevel + this.self.llevel - 1); this.self.type = RegExp.$1.substr(0, 1) == '-' ? 'ul' : 'ol'; c.htmllines(t + "<" + this.self.type + ">"); while (l = c.nextline()) { if(!l.match(this.self.pattern)) break; if (RegExp.$1.length > this.self.llevel) { //c.htmllines(t + "\t
  • "); bug?? var node = new Hatena_ListNode(); node._new({ context : this.self.context, ilevel : this.self.ilevel }); node.parse(); //c.htmllines(t + "\t
  • "); bug?? } else if(RegExp.$1.length < this.self.llevel) { break; } else { l = c.shiftline(); c.htmllines(t + "\t
  • " + RegExp.$2 + "
  • "); } } c.htmllines(t + ""); } }) // Hatena::PNode Hatena_PNode = function(){}; Hatena_PNode.prototype = Object.extend(new Hatena_Node(), { parse :function(){ var c = this.self.context; var t = String.times("\t", this.self.ilevel); var l = c.shiftline(); var text = new Hatena_Text(); text._new({context : c}); text.parse(l); l = text.html(); c.htmllines(t + "

    " + l + "

    "); } }); // Hatena::PreNode Hatena_PreNode = function(){}; Hatena_PreNode.prototype = Object.extend(new Hatena_Node(), { init :function(){ this.self.pattern = /^>\|$/; this.self.endpattern = /(.*)\|<$/; this.self.startstring = "
    ";
    				this.self.endstring = "
    "; }, parse : function(){ c = this.self.context; if(!c.nextline().match(this.self.pattern)) return; c.shiftline(); var t = String.times("\t", this.self.ilevel); c.htmllines(t + this.self.startstring); var x = ''; while (c.hasnext()) { var l = c.nextline(); if (l.match(this.self.endpattern)) { var x = RegExp.$1; c.shiftline(); break; } c.htmllines(this.escape_pre(c.shiftline())); } c.htmllines(x + this.self.endstring); }, escape_pre : function(text){ return text; } }) // Hatena::SuperpreNode Hatena_SuperpreNode = function(){}; Hatena_SuperpreNode.prototype = Object.extend(new Hatena_PreNode(), { init : function(){ this.self.pattern = /^>\|\|$/; this.self.endpattern = /^\|\|<$/; this.self.startstring = "
    ";
    				this.self.endstring = "
    "; }, escape_pre : function(s){ return String._escapeHTML(s); } }) // Hatena::SuperpreNode Hatena_TableNode = function(){}; Hatena_TableNode.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.pattern = /^\|([^\|]*\|(?:[^\|]*\|)+)$/; }, parse : function(s){ var c = this.self.context; var l = c.nextline(); if(!l.match(this.self.pattern)) return; var t = String.times("\t", this.self.ilevel); c.htmllines(t + ""); while (l = c.nextline()) { if(!l.match(this.self.pattern)) break; l = c.shiftline(); c.htmllines(t + "\t"); var td = l.split("|"); td.pop(); td.shift(); for (var i = 0; i < td.length; i++) { var item = td[i]; if (item.match(/^\*(.*)/)) { c.htmllines(t + "\t\t"); } else { c.htmllines(t + "\t\t"); } } c.htmllines(t + "\t"); } c.htmllines(t + "
    " + RegExp.$1 + "" + item + "
    "); } }) // Hatena::Section Hatena_SectionNode = function(){}; Hatena_SectionNode.prototype = Object.extend(new Hatena_Node(), { init : function(){ this.self.childnode = ["h5", "h4", "h3", "blockquote", "dl", "list", "pre", "superpre", "table", "tagline", "tag"]; this.self.startstring = '
    '; this.self.endstring = '
    '; this.self.child_node_refs = Array(); }, parse : function(){ var c = this.self.context; var t = String.times("\t", this.self.ilevel); this._set_child_node_refs(); c.htmllines(t + this.self.startstring); while (c.hasnext()) { var l = c.nextline(); var node = this._findnode(l); if(node == null) return; // TODO: ref == instanceof ??? //if (ref(node) eq 'Hatena_H3Node') { // if(this.self.started++) break; //} node.parse(); } c.htmllines(t + this.self.endstring); }, _set_child_node_refs : function(){ var c = this.self.context; var nodeoption = { context : c, ilevel : this.self.ilevel + 1 }; var invalid = Array(); if(c.self.invalidnode) invalid[c.self.invalidnode] = Array(); for(var i = 0; i < this.self.childnode.length; i++) { var node = this.self.childnode[i]; if(invalid[node]) continue; var mod = 'Hatena_' + node.charAt(0).toUpperCase() + node.substr(1).toLowerCase() + 'Node'; var n = eval("new "+ mod +"()"); n._new(nodeoption); this.self.child_node_refs.push(n); } }, _findnode : function(l){ for(var i = 0; i < this.self.child_node_refs.length; i++) { var node = this.self.child_node_refs[i]; var pat = node.self.pattern; if(pat == null) continue; if (l.match(pat)) { return node; } } var nodeoption = { context : this.self.context, ilevel : this.self.ilevel + 1 }; if (l.length == 0) { var node = new Hatena_BrNode(nodeoption); node._new(nodeoption); return node; } else if (this.self.context.noparagraph()) { var node = new Hatena_CDataNode(); node._new(nodeoption); return node; } else { var node = new Hatena_PNode; node._new(nodeoption); return node; } } }) // Hatena::BrockquoteNode Hatena_BlockquoteNode = function(){}; Hatena_BlockquoteNode.prototype = Object.extend(new Hatena_SectionNode(), { init : function(){ this.self.pattern = /^>>$/; this.self.endpattern = /^<<$/; this.self.childnode = ["h4", "h5", "blockquote", "dl", "list", "pre", "superpre", "table"];//, "tagline", "tag"]; this.self.startstring = "
    "; this.self.endstring = "
    "; }, parse : function(){ var c = this.self.context; if(!c.nextline().match(this.self.pattern)) return; c.shiftline(); var t = String.times("\t", this.self.ilevel); this._set_child_node_refs(); c.htmllines(t + this.self.startstring); while (c.hasnext()) { var l = c.nextline(); if (l.match(this.self.endpattern)) { c.shiftline(); break; } var node = this._findnode(l); if(node == null) break; node.parse(); } c.htmllines(t + this.self.endstring); } }) // Hatena::TagNode Hatena_TagNode = function(){}; Hatena_TagNode.prototype = Object.extend(new Hatena_SectionNode(), { init : function(){ this.self.pattern = /^>(<.*)$/; this.self.endpattern = /^(.*>)<$/; this.self.childnode = ["h4", "h5", "blockquote", "dl", "list", "pre", "superpre", "table"]; this.self.child_node_refs = Array(); }, parse : function(){ var c = this.self.context; var t = String.times("\t", this.self.ilevel); if(!c.nextline().match(this.self.pattern)) return; c.shiftline(); c.noparagraph(1); this._set_child_node_refs(); var x =this._parse_text(RegExp.$1); c.htmllines(t + x); while (c.hasnext()) { var l = c.nextline(); if (l.match(this.self.endpattern)) { c.shiftline(); x = this._parse_text(RegExp.$1); c.htmllines(t + x); break; } var node = this._findnode(l); if(node == null) break; node.parse(); } c.noparagraph(0); }, _parse_text : function(l){ var text = new Hatena_Text(); text._new({context : this.self.context}); text.parse(l); return text.html(); } }) // Hatena::TaglineNode Hatena_TaglineNode = function(){}; Hatena_TaglineNode.prototype = Object.extend(new Hatena_SectionNode(), { init : function(){ this.self.pattern = /^>(<.*>)<$/; this.self.child_node_refs = Array(); }, parse : function(){ var c = this.self.context; var t = String.times("\t", this.self.ilevel); if(!c.nextline().match(this.self.pattern)) return; c.shiftline(); c.htmllines(t + RegExp.$1); } }) // Hatena::Text Hatena_Text = function(){} Hatena_Text.prototype = { _new : function(args){ this.self = { context : args["context"], html : '' }; }, parse : function(text){ this.self.html = ''; if(text == null) return; this.self.html = text; }, html : function(){return this.self.html;} } /*var h = new Hatena(); h.parse("hoge((a))aaa))aaaa\n>hoge