きよしこの夜、WorkFlowyを魔改造する MarkFlowy

はじめに

様々なエディタを触っていると妄想が弾け出す。「Markdownが使えて、行単位で編集できるエディタは無いかなあ。スライドカーソルで、しかもスクリプトで拡張できるの」。ありそうでなかなか見つからない。個人の理想は他者の中にはない。なければ作るしかない。そういう妄想に形を与え、モックアップにするとしたらどんなモノになるだろう?


ブックマークレット MarkFlowy

iPhone/iPad限定。SafariでWorkFlowyを開き、下記ブックマークレットを起動すると妄想が現実化します。styleで赤ワインな画面にし、プレビュー機能を付けてみました。長押しすれば行単位の移動。これで少しイメージに近づいたかも。

javascript:(function(){style="#documentView{background:black;}.page{color:black;background:white;border-radius:10px;}.contentUnderline{border-bottom: 2px #00f solid;}.contentBold{border-bottom:2px #f00 solid;}.contentItalic{background-color:#bf9;text-style:normal;}.bullet{background-image:none;}.notes >.content{color:blue !important;} .parent>.name>.content{color:darkred;} .highlighted>.highlight{background:white;}.moving>.highlight{background:gray;}.corner,.edge{display:none;}";document.body.appendChild(document.createElement("style")).innerHTML=style;e=document.createElement("script");e.src="https://raw.github.com/chjj/marked/master/lib/marked.js";e.onload=function(){marked.setOptions({breaks:true, langPrefix:""});};document.body.appendChild(e);p=0;document.ontouchstart=Start;document.ontouchmove=Move;function Start(e){p=e.touches[0].pageX;}function Move(e){if(e.touches.length<2){x=e.touches[0].pageX;if(x-p>4){a=document.getSelection();a.modify("move","right","character");p=x;}if(p-x>4){a=document.getSelection();a.modify("move","left","character");;p=x;}}else{MarkdownStyle="body{font-family:Hiragino Mincho ProN;word-wrap:break-word;}h1,h2,h3{font-family:Hiragino Sans;padding:10px 0 0;border-bottom:1px #eee solid;} blockquote{font-family:Hiragino Sans;font-size:small;margin:0px;border-left:20px #fff groove;} table{border-left:1px gray solid;border-top:1px gray solid;border-spacing:0;} th{background:ivory;border-right:1px gray solid;border-bottom:1px gray solid;} td{border-right:1px gray solid;border-bottom:1px gray solid;} pre{background:#efe;padding:10px} u{border-bottom: 2px #00f solid;} strong{border-bottom:2px #f00 solid;} em{background-color:#bf9;} img{max-width:450px;}";p=pageContainer.innerHTML;p=p.replace(/<\/div>/g,"").replace(/<span .+?>/g,"").replace(/<\/span>/g,"\n");p=p.replace(/<div class=\"(.+?)\">/g,"\t$1\n").replace(/<div>/g,"").replace(/\n+/g,"\n");p=p.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&");s="";b=n=0;line=p.split("\n");for(i=0;i<line.length;i++){c=line[i];switch(true){case /^\t(.+?)selected/.test(c):s="";b=1;n=0;break;case /^\tnotes/.test(c):n=1;break;case /^\tchildrenEnd/.test(c):b--;break;case /^\tchildren/.test(c):b++;n=0;break;case /^\t/.test(c):break;case b<1:break;default: if(n){s+="> ";}else{switch(b){case 1:s+="## ";break;case 2:s+="\n### ";break;case 3:s+="\n";break;default:for(j=4;j<b;j++)s+="  ";s+="* ";}}c=c.replace(/<a class=\"contentLink\"(.+?)>(.+?)<\/a>/g,"$2");s+=c+"\n";}}s=s.replace(/\n([#\*])(.+?)\n([^\s\*])/g,"\n$1$2\n\n$3");s=marked(s);location="data:text/html;charset=UTF-8,<meta name=viewport content=initial-scale=1><style>"+MarkdownStyle+"</style>"+s;}}})();

登録リンクはこちら→ http://tinyurl.com/h36qv5d


スライドカーソル搭載

DarkRoomの応用ですね。編集モードのとき、左右にスワイプするとカーソルが移動します。さすがに別の行に指が掛かると編集が終了してしまうので、補助的な機能としてお使いください。多用はできません。細かなカーソル調整に役立つと思います。


Markdownプレビュー

二本指でスワイプするとMarkdownプレビューになります。ただし、文字の編集中にスワイプすると、作業用コードが入る不具合があります。一度キーボードを閉じてからお使いください(DuplicateやDeleteのメニューが用意されていてそのコードが紛れ込む。これ、iPhoneでも明示してくれたら良いのに)。WorkFlowyの画面に戻るのは「前のページに戻る」の操作で可能。左エッジスワイプでも戻れます。
Markdown化のルールは以前と同じ。

  • 親トピックをタイトルとします
  • 一段目は見出しとして扱います
  • 二段目が本文になります
  • 三段目以降はリストとして階層化されます
  • ノートをつけると引用になります(解除は、空白のみの行を末尾に置く)
  • 先頭に空白を4個置くとコード表示になります


機能拡張

Safariなので、拡張機能ブックマークレットで追加できます。たとえば、現在の画面をEvernoteに保存する場合、下記スクリプトを使います。

javascript:editor="evernote://x-callback-url/new-note?type=html&amp;title=WorkFlowy&amp;text=";p=pageContainer.innerHTML;p=p.replace(/&lt;\/div&gt;/g,"").replace(/&lt;span .+?&gt;/g,"").replace(/&lt;\/span&gt;/g,"\n");p=p.replace(/&lt;div class=\"(.+?)\"&gt;/g,"\t$1\n").replace(/&lt;div&gt;/g,"").replace(/\n+/g,"\n");p=p.replace(/&amp;lt;/g,"&lt;").replace(/&amp;gt;/g,"&gt;").replace(/&amp;amp;/g,"&amp;");s="";b=n=0;line=p.split("\n");for(i=0;i&lt;line.length;i++){c=line[i];switch(true){case /^\t(.+?)selected/.test(c):s="";b=1;n=0;break;case /^\tnotes/.test(c):n=1;break;case /^\tchildrenEnd/.test(c):b--;break;case /^\tchildren/.test(c):b++;n=0;break;case /^\t/.test(c):break;case b&lt;1:break;default: if(n){s+="&gt; ";}else{switch(b){case 1:s+="## ";break;case 2:s+="\n### ";break;case 3:break;default:for(j=4;j&lt;b;j++)s+="  ";s+="* ";}}c=c.replace(/&lt;a class=\"contentLink\"(.+?)&gt;(.+?)&lt;\/a&gt;/g,"$2");s+=c+"\n";if(n) s+="\n";}}s=s.replace(/\n([#\*])(.+?)\n([^\s\*])/g,"\n$1$2\n\n$3");location=editor+encodeURIComponent(marked(s));

Textwellへの書き出しは下記の通り。Markdownで出力します。

javascript:editor="textwell://replace?text=";p=pageContainer.innerHTML;p=p.replace(/&lt;\/div&gt;/g,"").replace(/&lt;span .+?&gt;/g,"").replace(/&lt;\/span&gt;/g,"\n");p=p.replace(/&lt;div class=\"(.+?)\"&gt;/g,"\t$1\n").replace(/&lt;div&gt;/g,"").replace(/\n+/g,"\n");p=p.replace(/&amp;lt;/g,"&lt;").replace(/&amp;gt;/g,"&gt;").replace(/&amp;amp;/g,"&amp;");s="";b=n=0;line=p.split("\n");for(i=0;i&lt;line.length;i++){c=line[i];switch(true){case /^\t(.+?)selected/.test(c):s="";b=1;n=0;break;case /^\tnotes/.test(c):n=1;break;case /^\tchildrenEnd/.test(c):b--;break;case /^\tchildren/.test(c):b++;n=0;break;case /^\t/.test(c):break;case b&lt;1:break;default: if(n){s+="&gt; ";}else{switch(b){case 1:s+="## ";break;case 2:s+="\n### ";break;case 3:break;default:for(j=4;j&lt;b;j++)s+="  ";s+="* ";}}c=c.replace(/&lt;a class=\"contentLink\"(.+?)&gt;(.+?)&lt;\/a&gt;/g,"$2");s+=c+"\n";if(n) s+="\n";}}s=s.replace(/\n([#\*])(.+?)\n([^\s\*])/g,"\n$1$2\n\n$3");location=editor+encodeURIComponent(marked(s));

iPadだと、ブックマークの「お気に入り」にフォルダを作ると、ブックマークバーにプルダウンメニューが付きます(設定アプリでブックマークバーをオンにすること)。すると、ブックマークレットの呼び出しが拡張機能のように扱える。「WorkFlowy」という名のフォルダを作り、関連ブックマークレットを集めてあります。


問題点

実はまだ太字やアンダーラインに対応していません。プレビューすると途中で改行してしまうようです。もう少し使い込んでから対応法を考えます。色付きにしたいところ。
それと今のSafariだと、行の移動で変なスクロールをします。とても使いにくい。これはWorkFlowy側で対応するか、iOSがバージョンアップすることで解消するかだろうから、手の打ちようがない。移動先を一度編集モードにすると、スクロールがそこまで飛んで、むしろ使いやすくなるときもあるけど。