2007年8月6日月曜日

userchrome.js で「タイトルとURLをコピー」

前々から利用させていただいているSCRAPBLOG : [userChrome.js] Copy Title + URLにちょっとした変更を加えてみました。 変更点は以下の通り。

  • userchrome.js.xpiの話題 - alice0775のファイル置き場 を参考に、コンテキストメニューを日本語に変更
  • 改行コードを \r\n に変更 (一部のソフトで \n を改行として扱わないことがあるため)
  • URLテキストの一部記号をURLエスケープ
  • タイトルのHTMLエスケープ処理でシングルクォートもエスケープ
  • (個人的に使用している)li要素形式のコピーを追加
/**
 * A user script for userChrome.js extension.
 * @name タイトルとURLをコピー
 * @description 「タイトルとURLをコピー」コマンドをタブメニューに追加
 * @compatibility Firefox 2.0.0.6
 * @author Gomita, think
 * @lastUupdated 2007.09.10
 * @permalink http://thinkarc.blogspot.com/2007/08/userchromejs-url.html
 * @originallink http://www.xuldev.org/blog/?p=51
*/
(function()
{
	window.ucjs_copyTabInfo = function(copytype)
	{
		function htmlEscape(s) {
			s = s.replace(/</g, "&lt;");	// 小なり
			s = s.replace(/>/g, "&gt;");	// 大なり
			s = s.replace(/&/g, "&amp;");	// アンバサンド
			s = s.replace(/"/g, '&quot;');	// ダブルクォート
			s = s.replace(/'/g, '&#039;');	// シングルクォート

			return s;
		}

		function urlEscape(dat){
			dat = dat.replace(/%(?![\da-f]{2})/ig, '%25');	// パーセント
			dat = dat.replace(/ /g, '%20');					// 半角スペース
			dat = dat.replace(/\"/g, '%22');				// ダブルクオート
			dat = dat.replace(/(#[^#]*)#/, "$1%23");		// シャープ
			dat = dat.replace(/\'/g, '%27');				// シングルクオート
			dat = dat.replace(/\(/g, '%28');				// 左小括弧
			dat = dat.replace(/\)/g, '%29');				// 右小括弧
			dat = dat.replace(/\*/g, '%2a');				// アスタリスク
			dat = dat.replace(/,/g, '%2c');					// カンマ
			dat = dat.replace(/</g, '%3c');					// 小なり
			dat = dat.replace(/>/g, '%3e');					// 大なり
			dat = dat.replace(/\[/g, '%5b');				// 左大括弧
			dat = dat.replace(/\\/g, '%5c');				// 円記号
			dat = dat.replace(/]/g, '%5d');					// 右大括弧
			dat = dat.replace(/\^/g, '%5e');				// キャレット
			dat = dat.replace(/`/g, '%60');					// バッククォート
			dat = dat.replace(/{/g, '%7b');					// 左中括弧
			dat = dat.replace(/\|/g, '%7c');				// 縦棒
			dat = dat.replace(/}/g, '%7d');					// 右中括弧

			return dat;
		}

		var tab = document.popupNode;
		var url = gBrowser.getBrowserForTab(tab).contentWindow.location.href;
		var txt;

		switch (copytype){
			case 'text':
				txt = tab.label + "\r\n" + urlEscape(url);
				break;
			case 'anchor':
				txt = '<a href=\'' + htmlEscape(urlEscape(url)) + '\'>' + htmlEscape(tab.label) + '</a>';
				break;
			case 'list':
				txt = '<li><a href=\'' + htmlEscape(urlEscape(url)) + '\'>' + htmlEscape(tab.label) + '</a></li>';
				break;
		}

		if(txt){
			var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
			.getService(Components.interfaces.nsIClipboardHelper);
			clipboard.copyString(txt);
		}
    };

	var UI = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
	createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	UI.charset = 'UTF-8';
	var menuitem = Array();

/*
	menuitem の初期化処理を forEach で回したかったのですが、上手くいかず保留。
	多分、初歩的なミスだと思います…。

	var menuindex = 0;
	var menu_array = Array(
		'text': 'タイトルとURLをコピー',
		'anchor': 'タイトルとURLをa要素でコピー',
		'list': 'タイトルとURLをli要素でコピー'
	);

	function setLabel(element, index) {
		menuitem[menuindex] = document.createElement("menuitem");
		menuitem[menuindex].setAttribute("label", UI.ConvertToUnicode(element));
		menuitem[menuindex].setAttribute("oncommand", "ucjs_copyTabInfo(" + index + ");");
		menuindex++;
	}

	menu_array.forEach(setLabel);
*/

	menuitem[0] = document.createElement("menuitem");
	menuitem[0].setAttribute("label", UI.ConvertToUnicode("タイトルとURLをコピー"));
	menuitem[0].setAttribute("oncommand", "ucjs_copyTabInfo('text');");

	menuitem[1] = document.createElement("menuitem");
	menuitem[1].setAttribute("label", UI.ConvertToUnicode("タイトルとURLをa要素でコピー"));
	menuitem[1].setAttribute("oncommand", "ucjs_copyTabInfo('anchor');");

	menuitem[2] = document.createElement("menuitem");
	menuitem[2].setAttribute("label", UI.ConvertToUnicode("タイトルとURLをli要素でコピー"));
	menuitem[2].setAttribute("oncommand", "ucjs_copyTabInfo('list');");

	setTimeout(function()
	{
		gBrowser.mStrip.childNodes[1].appendChild(document.createElement("menuseparator"));

		for(var i=0, L=menuitem.length; i < L; i++){
			gBrowser.mStrip.childNodes[1].appendChild(menuitem[i]);
		}

	}, 0);
})();

ようは、Syleraスクリプトで使っていた処理を使い回しただけだったり。
URLエスケープは、Another HTML-lintで文法チェック時にエラーを返すURL文字をエスケープします。

いくつかエスケープ不要な文字が混じっていますが、これは掲示板にURLを投稿する状況を考慮しています。
ほとんどの掲示板は http:// から始まるURL文字列に自動的にリンクが貼られますが、一部の文字をURL文字として認識してくれないことがあります。
例えば、「アスタリスクや括弧があると、その手前でリンク化が止まう」というような状況。
それでは困るので、未対応と思われるマイナーな記号をパーセントエンコードして、正しくリンクさせようという試みです。

ラベル: ,

0 件のコメント:

コメントを投稿

登録 コメントの投稿 [Atom]

<< ホーム