選択範囲をAAに最適化するブックマークレット

まとめブログを見ていると、AAがメイリオで表示されたりすることがあったので作ってみました。
選択範囲をAAに最適化します。

javascript:(function(){function fmt(n){if(n.nodeType==1){n.style.fontFamily="MS PGothic";n.style.fontSize="12pt";n.style.lineHeight="1.2";n.style.fontWeight="normal";}if(n.nodeType==3){var s=document.createElement("span");fmt(s);n.parentNode.insertBefore(s,n);n.parentNode.removeChild(n);s.appendChild(n);}}function trace(n,r){var nr=document.createRange();while(true){nr.selectNode(n);if(nr.compareBoundaryPoints(Range.START_TO_END,r)>-1){if(nr.compareBoundaryPoints(Range.END_TO_START,r)>0)return;else fmt(n);}if(n.hasChildNodes())n=n.firstChild;else{while(!n.nextSibling){n=n.parentNode;if(!n)return;}n=n.nextSibling;}}}var p,r,c;var s=window.getSelection();for(var i=0;i<s.rangeCount;i++){r=s.getRangeAt(i);if(r.startContainer==r.endContainer){p=document.createElement("span");r.surroundContents(p);fmt(p);c=p.getElementsByTagName("*");for(var i=0;i<c.length;i++)fmt(c[i]);}else{var t=document.createRange();t.setStart(r.startContainer,r.startOffset);t.setEndAfter(r.startContainer);t.insertNode(t.extractContents());t.setEnd(r.endContainer,r.endOffset);t.setStartBefore(r.endContainer);t.insertNode(t.extractContents());t.detach();trace(r.startContainer,r);}}})();

なっげー。

Firefoxのみで動作確認しています。他で動くかは分かりません。あと、選択範囲の前後のフォントも変わってしまう不具合あり。
今日はもうこれ作っただけで疲れたからまた今度直します。

整形したソースは以下の通り。

javascript:
(function(){
  function fmt(n){
    if(n.nodeType==1){
      n.style.fontFamily="MS PGothic";
      n.style.fontSize="12pt";
      n.style.lineHeight="1.2";
      n.style.fontWeight="normal";
    }
    if(n.nodeType==3){
      var s=document.createElement("span");
      fmt(s);
      n.parentNode.insertBefore(s,n);
      n.parentNode.removeChild(n);
      s.appendChild(n);
    }
  }
  function trace(n,r){
    var nr=document.createRange();
    while(true){
      nr.selectNode(n);
      if(nr.compareBoundaryPoints(Range.START_TO_END,r)>-1){
        if(nr.compareBoundaryPoints(Range.END_TO_START,r)>0)
          return;
        else
          fmt(n);
      }
      if(n.hasChildNodes())
        n=n.firstChild;
      else{
        while(!n.nextSibling){
          n=n.parentNode;
          if(!n)
            return;
        }
        n=n.nextSibling;
      }
    }
  }
  var p,r,c;
  var s=window.getSelection();
  for(var i=0;i<s.rangeCount;i++){
    r=s.getRangeAt(i);
    if(r.startContainer==r.endContainer){
      p=document.createElement("span");
      r.surroundContents(p);
      fmt(p);
      c=p.getElementsByTagName("*");
      for(var i=0;i<c.length;i++)
        fmt(c[i]);
    }
    else{
      var t=document.createRange();
      t.setStart(r.startContainer,r.startOffset);
      t.setEndAfter(r.startContainer);
      t.insertNode(t.extractContents());
      t.setEnd(r.endContainer,r.endOffset);
      t.setStartBefore(r.endContainer);
      t.insertNode(t.extractContents());
      t.detach();
      trace(r.startContainer,r);
    }
  }
}
)();

このあたりを参考にしました。

これを作るに当たってBookmarklet Builderを活用しました。