Hatena::ブログ(Diary)

奇妙に、そしてささやかに。 このページをアンテナに追加 RSSフィード

2007-10-22

Firefox Add-on :: Make Link 機能追加版

下記の機能追加版は本家に統合されました。詳しくは

Make Link 8.06をお使いください。 - 奇妙に、そしてささやかに。
http://d.hatena.ne.jp/bizarre_sprout/20080609/makelink806

をご覧下さい。(6/10追記)

作者にメールしたら丁寧に「忙しいからフォーラムで質問してみて!」って言われた。フォーラムで質問するのが面倒なので、勉強して直してみた。


ちなみにこのアドオンの便利さについては

Make Linkが完全体に - 奇妙に、そしてささやかに。
http://d.hatena.ne.jp/bizarre_sprout/20070330/1175258531

に書いてます。


便利なんだけど、引用をHTMLでやる時に改行が全て半角スペースにされるのは困っていたので直してみた。

従来の%text%に加え、改行をそのまま反映する%text_n%と<br>として反映する%text_br%という変数を付け加えた形だ。

ブログでの引用などに便利だと思う。

ファイルは>ここを左クリックでファイルを開いてインストール


ちなみに今まで使ってた人は、リンク規則の情報はプロファイルフォルダのpref.jsに入っていて、前のアドオンを消して上のアドオンで上書きしても保持されます。心配ならば、perf.jsで"net.soylentred.makelink"で検索をかけてバックアップをとっておくと良い。


参考までに以下に拡張機能の直し方を書いておく。


プログラムソースへアクセス

プロファイルフォルダのextensionsのフォルダから探した。"{0B6B0D55-DFAC-4006-AEE6-25667F55A2A8}"って名前のフォルダだった。chromeの中のmakelink.jarは実体はzipファイルなのでLhaPlusかなんかで解凍。中身が見える。


JavaScriptを直す

JavaScriptの知識はあるので、ちゃっちゃか直す。

jarの中身のcontent/makelink/にあるmakelink.jsとlib.jsが対象。

lib.jsは

function getSelectedText( node )

function getSelectedText( node , what_n )

にし、

// collapse white space:
selection = selection.replace(/[ \n\r\t]+/g, " ");

// collapse white space:
selection = selection.replace(/[ \r\t]+/g, " ");
// replace \n to what_n:
selection = selection.replace(/(\n)/g, what_n);

に直すだけ。文字列を取ってきて整形する関数を引数から"\n"の整形に関して指定するようにしている。

makelink.jsは詳細は省くけど、

case "text":
copyText += info['text'];
inVar = false;
break;

をコピーして%text_n%,%text_br%の分を作り、その内容を下の方で定義している。

if ( ( selection = getSelectedText( target , " " ) ) != "" ) {
// some text is selected:
info['text'] = selection;
info['text_n'] = getSelectedText( target , "\n" );
info['text_br'] = getSelectedText( target , "<br>\n" );
info['url'] = window.content.document.location.href;
info['title'] = window.content.document.title;
}

みたいな感じで。もともとのgetSelectedTextの引数を2つに増やすのもお忘れなく。

これは選択文字列のあるケースだけど他のケースは%text%と同じになるようにした。


作ったものを確認

contentとlocaleをzip圧縮してmakelink.jarに名前を変えて置き換える。

挙動を確認。上手く動いたのでめでたしめでたし。


ついでにヘルプの追加と日本語localeの追加

helpはcontent/makelink/help/defininglinktypes.htmlなので適当に直した。

localeはlocaleフォルダの中のen-USをコピーしてja-JPに変更し、中のrdfファイルもs/en-US/ja-JP/する。

dtdファイルは適宜訳した。


それからchrome.manifestに

locale makelink ja-JP jar:chrome/makelink.jar!/locale/ja-JP/makelink/

を追加。(参考:Chrome Registration - MDC

install.rdfからem:locale="locale/en-US/makelink/"を削除。


完成

localeも変えたしjarを作り直して、xpiもフォルダの中のをzip圧縮→xpiに名前変更して完成。

著者情報とか何にも入れてないけどね。


僕はblosxomのブログでの引用に

<dl><dt>%TITLE%</dt>
<dd><a href="%URL%">%URL%</a>
<blockquote><p>%text_br%</p></blockquote>
</dd></dl>

を良く使ってます。

大きな引用はこれで、小さな引用はシンプルなAタグで。



本当は著者情報とかバージョンとか直すべきかも知んないけど良くわかんないからとりあえず。

ciacia 2008/05/15 02:29 makelink本体がfirefox3に向けてバージョンアップしましたが、未だにそのままの仕様みたいですね。

bizarre_sproutbizarre_sprout 2008/05/15 19:44 そうですね、今度時間が空けば新バージョンをいじって作者にメールしてみようと思います。ご報告ありがとうございます〜

bizarre_sproutbizarre_sprout 2008/05/30 18:15 変更後拙い英語でメールしてみました。メールが返ってきたら顛末含めエントリにしますが、取り急ぎ8.04の機能追加版を
http://www.geocities.jp/storage_of_cm3/makelink_8_04_plus.xpi
に上げておきます、お急ぎなら使ってみて下さい。

bizarre_sproutbizarre_sprout 2008/06/10 23:54 本家に統合していただきましたので、Make Link 8.06をお使いください。 http://d.hatena.ne.jp/bizarre_sprout/20080609/makelink806

kmnykmny 2009/01/12 13:49 「CopyURL+」と比べ、使いにくい箇所(動作)を修正

■改良
(1) PRE要素で囲んだところをgetSelectionで選択すると改行がないことへの対応

補足:少しでも、他の要素が範囲に含まれているとPRE要素の箇所も改行が含まれる

場所:function mlGetSelectedText( node , n_alt ) の135行の最後のelse文の上

下記のコードを追加

else if ( nodeLocalName == "PRE" )
{
selection = node.textContent;
}

(2) サンプルソースコードの引用のため-1
場所:「// collapse white space:」の箇所

selection = selection.replace(/[ \r\t]+/g, " ");

// 最短マッチングの繰り返し
selection = selection.replace(/[ \r\t]+?/g, " ");

(3) サンプルソースコードの引用のため -2
・行末に半角スペースが残ることへの対応
・先頭の空白は残す。「\s」を用いると、改行のみの行が消えることへの対応

場所:「// trim white space:」の箇所

selection = selection.replace(/(^\s+)|(\s+$)/, "");

// 行末のタブ, CR, LF, 半角空白, 全角空白 の除去
selection = selection.replace(/([\t\r\f  ]+$)/mg, "");

kmnykmny 2009/01/12 14:27 「CopyURL+」と比べ、使いにくい箇所(動作)を修正-2

■改良:makelink.js
(1) %TITLE% で得られる情報の変更
・引用した文書のタイトルを得るるために用います。

▽場所:makeSelectionLink: function(event, format, useEntities)の「// look to see if there's selected text:」の「var selection;」の次

下記のコードを追加

var focusedWindow = document.commandDispatcher.focusedWindow;

変更

info['title'] = window.content.document.title;

info['title'] = focusedWindow.document.title;


(2) %LOCAL_TIME%, %UTC_TIME% の追加
・引用した日時を得るために用います。

▽場所-1:makeLink: function(format, info, copyAsHtml) のswitch文のdefault文の上

下記のコードを追加

case "utc_time":
copyText += info['utc_time'];
inVar = false;
break;
case "local_time":
copyText += info['local_time'];
inVar = false;
break;

▽場所-1:makeSelectionLink: function(event, format, useEntities)の「// array to store link info:」の箇所

下記のコードを追加
補足:now.toLocaleString() は日本の表記になるので使わない

var now = new Date();

var local_year = now.getYear();
var local_month = now.getMonth() + 1;
var local_day = now.getDate();
var local_hour = now.getHours();
var local_min = now.getMinutes();
var local_sec = now.getSeconds();

if(local_year < 2000) { local_year += 1900; }

// 0-padding
if(local_month < 10) { local_month = "0" + local_month; }
if(local_day < 10) { local_day = "0" + local_day; }
if(local_hour < 10) { local_hour = "0" + local_hour; }
if(local_min < 10) { local_min = "0" + local_min; }
if(local_sec < 10) { local_sec = "0" + local_sec; }

info['utc_time'] = now.toUTCString();
//info['local_time'] = now.toLocaleString();
info['local_time'] = local_year + "/" + local_month + "/" + local_day + " " + local_hour + ":" + local_min + ":" + local_sec;

kmnykmny 2009/01/12 14:52 ■改良をベースとしたMake Linkの利用例(定義例)
・TiddlyWiki用
・先の改良を施して初めて使いやすくなります

▽TW Link
・Name:TW Link
・Format:
[[%TITLE%|%URL%]]

▽TWLink & Selection
・Name: TWLink & Selection
・Format:
<<<
%TEXT_N%

Source: [[%TITLE%|%URL%]] (%LOCAL_TIME%)
<<<

▽補足
・私には、デフォルトのMake Link の出力は使いにくいです。(なぜか、みなさんMake Linkを絶賛ですが...)
・CopyURL+がFF3をサポートしないので、今回の修整を行いました。
・定義のしやすさを除けば、CopyRUL+ の出力動作(機能)は、私好みです。

kmnykmny 2009/01/13 21:00 ■補足:『「CopyURL+」と比べ、使いにくい箇所(動作)を修正』の記事について
いずれも、Make Link 8.12 に対する修正記事です。
・最初の改良記事は「lib.js」の修正
・二番目の改良記事は「makelink.js」の修正
です。

mikkunmikkun 2009/01/19 07:18 8.12の機能修正版を上げてもらえませんか。

bizarre_sproutbizarre_sprout 2009/01/23 03:06 ちょっと修士論文締め切り間近につき対応できませんが、とりいそぎ返信まで。

>kmnyさん
ありがとうございます。置換の表現とか言われて見ればなるほどな感じで。Make Linkの作者さんも忙しそうなので、どういう形になるか分かりませんがご指摘活用させていただきたいです。(もし本家への取り込みをご希望なら、直接コンタクトをとってもらった方が早いかもしれません)

>mikkunさん
8.06以降は機能修正が反映されていると思うのですが、どうでしょうか?僕の手元では8.12で%text_br%とか使えてます。

mikkunmikkun 2009/01/23 13:56 >bizarre_sproutさん
問題なく8.12で%text_br%とか使えてます。

kmnyさんの『「CopyURL+」と比べ、使いにくい箇所(動作)を修正』の記事に対しての要望でした。勘違いをしました。御免なさい。

修士論文がんばってください。

kmnykmny 2010/06/12 01:21 MakeLink 9.11 makelink.jarに含まれる
page_info.js の修正版
----------
net.soylentred.makelink.PageInfo = function() {
this.logger_ =
new net.soylentred.makelink.Logger('net.soylentred.makelink.PageInfo');
this.logger_.logCall('<init>', arguments);
};

/**
* Gets the {@code src} URL of an image.
* TODO: Resolve relative URLs.
*
* @param node The image node.
* @return The {@code src} URL of the image if present, or the empty string.
*/
net.soylentred.makelink.PageInfo.prototype.getImageUrl = function(node) {
this.logger_.logCall('getImageUrl', arguments);
var nodeType = node.nodeName.toLowerCase();
if (nodeType != 'img') {
throw 'Unexpected node type in getImageUrl: ' + nodeType;
}
return node.src || '';
};

/**
* Gets the text content of an element and its sub-elements as a string.
* Only text content is preserved (i.e., there are no tags), and images are
* replaced by their {@code alt} attributes.
*
* @param element The element to get the text of.
* @return The complete text of the element and its children.
*/
net.soylentred.makelink.PageInfo.prototype.getElementText =
function(element) {
this.logger_.logCall('getElementText', arguments);
var text = '';
for (var i = 0; i < element.childNodes.length; i++) {
var child = element.childNodes[i];
if (child.nodeValue != null) {
// It's a text node.
text += child.nodeValue;
} else if (child.tagName.toLowerCase() == "img") {
text += child.alt;
} else {
text += this.getElementText(child);
}
}
return text.replace(/[ \n\r\t]+/g, ' ');
};

/**
* Get the selected text on a page.
* TODO: Determine why it's necessary to pass a node as an argument.
* TODO: Leave the n_alt repacement up to the caller.
*/
net.soylentred.makelink.PageInfo.prototype.getSelectedText =
function(node, n_alt) {
this.logger_.logCall('getSelectedText', arguments);
var selection = '';
var nodeLocalName = node.localName.toUpperCase();
if (nodeLocalName == "TEXTAREA" || nodeLocalName == "INPUT" &&
(node.type == "text" || node.type == "password")) {
selection = node.value.substring(node.selectionStart, node.selectionEnd);
} else if (nodeLocalName == "OPTION") {
var parentSelect = node.parentNode;
if (parentSelect.localName.toUpperCase() == "SELECT") {
if (parentSelect.multiple) {
var anOption;
for (var i = 0; i < parentSelect.options.length; i++ ) {
anOption = parentSelect.options[i];
if (anOption.selected) {
selection += " " + anOption.value;
}
}
} else {
selection = node.value;
}
}
} else if (nodeLocalName == "SELECT") {
// TODO: determine if this works correctly for multiple select.
selection = node.options[node.selected].value;
//---------------------------------------------------------- @A2A begin
} else if ( nodeLocalName == "PRE" ) {

// MEMO: 2009/01/12
// * PRE要素で囲んだところをgetSelectionで選択すると改行がない
// * また、PRE要素内の文字を変更する際、改行コードの扱いが各ブラウザで異なる
// source: http://d.hatena.ne.jp/brazil/20060917/1158465641
// * CODE要素は問題なさそう

// MEMO: 2010/06/11
// ☆ この箇所は改善の余地あり
selection = node.textContent;
//---------------------------------------------------------- @A2A end
} else {
var focusedWindow = document.commandDispatcher.focusedWindow;
selection = focusedWindow.getSelection().toString();
}
selection = selection.toString();
// collapse white space:

// MEMO: 最短マッチングの繰り返しにする。サンプルソースコードの引用のため @A1A
//@A1D selection = selection.replace(/[ \r\t]+/g, " ");
selection = selection.replace(/[ \r\t]+?/g, " "); //@A1A

// replace \n with n_alt:
selection = selection.replace(/\n/g, n_alt);

// trim white space:

// MEMO1: 行末に半角スペースが残るので修正 @A1A
//@A1D selection = selection.replace(/(^\s+)|(\s+$)/, "");
// MEMO2: 先頭の空白は残す。「\s」を用いると、改行のみの行が消える。 @A1A
// \s は、空白文字(スペース, タブ, 改行 など) つまり [\t\n\r\f ] or [\t\n\x11\f\r ] と同じ
//@A2D selection = selection.replace(/([\t\x11\f\r  ]+$)/mg, ""); //@A1A
selection = selection.replace(/([\t\r\f  ]+$)/mg, ""); //@A2A

return selection;
};

/**
* Gets the value of the {@code content} attribute of the first {@code meta}
* element with a {@code name} attribute of 'description'.
*
* @return The description of the page according to the first
* {@code <meta name='description'>} element, or the empty string if no
* such element exists or if it is missing the {@code content} attribute.
*/
net.soylentred.makelink.PageInfo.prototype.getPageDescription =
function(document) {
this.logger_.logCall('getPageDescription', arguments);
var metas = document.getElementsByTagName('meta');
for (var i = 0; i < metas.length; i++) {
var name = metas[i].getAttribute('name');
if (name && name.toLowerCase() == 'description') {
return metas[i].getAttribute('content') || '';
}
}
return 'desc';
};

/**
* Finds the nearest ancestor link ({@code a} element with a {@code href}
* attribute) or block level element containing the given node.
*
* @param node The node to check.
* @return The nearest ancestor block-level element or link or the node.
*/
net.soylentred.makelink.PageInfo.prototype.getCorrectTarget = function(node) {
this.logger_.logCall('getCorrectTarget', arguments);
while (!this.isBlockLevel(node) && !this.isLink(node) && node.parentNode) {
node = node.parentNode;
}
return node;
};

/**
* Checks if the given node is an {@code a} element with an {@code href}
* attribute.
*
* @param node The node to check.
* @return true iff the node is an {@code a} element with an {@code href}
* attribute.
*/
net.soylentred.makelink.PageInfo.prototype.isLink = function(node) {
this.logger_.logCall('isLink', arguments);
return node.href && node.localName.toLowerCase() == 'a';
};

/**
* Checks if the given node is a block-level element.
*
* @param node The node to check.
* @return true iff the node is block-level.
*/
net.soylentred.makelink.PageInfo.prototype.isBlockLevel = function(node) {
this.logger_.logCall('isBlockLevel', arguments);
var blocks = ['html', 'body', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul',
'ol', 'dir', 'menu', 'li', 'dl', 'dt', 'dd', 'p', 'pre', 'blockquote',
'address', 'div', 'center', 'form', 'table', 'tr', 'td'];
return blocks.indexOf(node.localName.toLowerCase()) >= 0;
};

kmnykmny 2010/06/12 01:25 MakeLink 9.11 makelink.jarに含まれる
link_maker.js の修正版
----------
net.soylentred.makelink.LinkMaker = function() {
this.prefs_ = net.soylentred.makelink.getPrefs();
this.logger_ =
new net.soylentred.makelink.Logger('net.soylentred.makelink.LinkMaker');
this.logger_.logCall('<init>', arguments);
this.linkTypeSource_ = new net.soylentred.makelink.LinkTypeSource();
this.urlShortener_ = new net.soylentred.makelink.UrlShortener();
this.pageInfo_ = new net.soylentred.makelink.PageInfo();
};

net.soylentred.makelink.LinkMaker.prototype.startUp = function() {
this.logger_.logCall('startUp', arguments);
this.prefs_.addObserver('', this, false);
this.rebuildMenu_();
};

net.soylentred.makelink.LinkMaker.prototype.shutDown = function() {
this.logger_.logCall('shutDown', arguments);
this.prefs_.removeObserver('', this);
};

net.soylentred.makelink.LinkMaker.prototype.makeSelectionLink = function(
event, format, useEntities) {
this.logger_.logCall('makeSelectionLink', arguments);
// What element was clicked on:
var target = document.popupNode;

var info = {};
if (target.nodeName.toLowerCase() == 'img') {
info['imgurl'] = this.pageInfo_.getImageUrl(target);
}

//----------------------------------------------------- @A2A begin
var now = new Date();

var local_year = now.getYear();
var local_month = now.getMonth() + 1;
var local_day = now.getDate();
var local_hour = now.getHours();
var local_min = now.getMinutes();
var local_sec = now.getSeconds();

if(local_year < 2000) { local_year += 1900; }

// 0-padding
if(local_month < 10) { local_month = "0" + local_month; }
if(local_day < 10) { local_day = "0" + local_day; }
if(local_hour < 10) { local_hour = "0" + local_hour; }
if(local_min < 10) { local_min = "0" + local_min; }
if(local_sec < 10) { local_sec = "0" + local_sec; }

info['utc_time'] = now.toUTCString();
//info['local_time'] = now.toLocaleString();
info['local_time'] = local_year + "/" + local_month + "/" + local_day + " " + local_hour + ":" + local_min + ":" + local_sec;
//----------------------------------------------------- @A2A end

// move up the DOM tree to a link or block level element:
target = this.pageInfo_.getCorrectTarget(target);

// look to see if there's selected text:
var selection;
var focusedWindow = document.commandDispatcher.focusedWindow; //@A1A
if ((selection = this.pageInfo_.getSelectedText(target, ' ')) != '') {
info['text'] = selection;
info['text_n'] = this.pageInfo_.getSelectedText(target, '\n');
info['text_br'] = this.pageInfo_.getSelectedText(target , '<br />\n');
info['url'] = window.content.document.location.href;
info['title'] = window.content.document.title;
}
// or if it's a link:
else if (this.pageInfo_.isLink(target)) {
// get anchor text/URL:
info['text'] = this.pageInfo_.getElementText(target);
info['text_n'] = this.pageInfo_.getElementText(target);
info['text_br'] = this.pageInfo_.getElementText(target);
info['url'] = target.href;
info['title'] = target.title || '';
} else {
// not an anchor (get page title/URL):
info['text'] = window.content.document.title;
info['text_n'] = window.content.document.title;
info['text_br'] = window.content.document.title;
info['url'] = window.content.document.location.href;
//@A1D info['title'] =
//@A1D this.pageInfo_.getPageDescription(window.content.document);
info['title'] = focusedWindow.document.title; //@A1A
}

if (useEntities) {
for (i in info) {
info[i] = info[i].replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\"/g, '"');
}
}
// make the link:
return this.makeLink_(format, info, useEntities);
};

net.soylentred.makelink.LinkMaker.prototype.openOptions = function() {
this.logger_.logCall('openOptions', arguments);
var features = 'chrome,titlebar,toolbar,centerscreen,resizable';
window.openDialog('chrome://makelink/content/options/options.xul',
'makelinkoptions', features);
};

net.soylentred.makelink.LinkMaker.prototype.observe = function(
subject, topic, data) {
this.logger_.logCall('observe', arguments);
if (topic == 'nsPref:changed') {
this.rebuildMenu_();
}
};

net.soylentred.makelink.LinkMaker.prototype.makeLink_ = function(
format, info, copyAsHtml) {
this.logger_.logCall('makeLink_', arguments);
// split into pieces on %:
var piece = format.split('%');
// flag to record if the current piece is potentially a makelink variable:
var inVar = false;

var copyText = '';
for (var i = 0; i < piece.length; i++) {
// if it's not a makelink variable...:
if (!inVar) {
// just add it as it is:
copyText += piece[i];
// next piece could be a variable:
inVar = true;
} else {
inVar = false;
switch (piece[i].toLowerCase()) {
case 'text':
copyText += info['text'];
break;
case 'text_n':
copyText += info['text_n'];
break;
case 'text_br':
copyText += info['text_br'];
break;
case 'url':
copyText += info['url'];
break;
case 'imgurl':
copyText += info['imgurl'];
break;
case 'title':
copyText += info['title'];
break;
case 'tinyurl':
var shortenedUrl = this.urlShortener_.getShortenedUrl(info['url']);
if (!shortenedUrl) {
this.logger_.warning('Failed to fetch shortened URL');
return false;
}
copyText += shortenedUrl;
break;
case 'input':
copyText += prompt(format +
'\n\nPlease enter the %input% text for\n--\n' +
format + '\n--');
break;
//--------------------------------------- @A2A begin
case "utc_time":
copyText += info['utc_time'];
inVar = false;
break;
case "local_time":
copyText += info['local_time'];
inVar = false;
break;
//--------------------------------------- @A2A end
// default (not actually a make link variable) means inVar
// is still true for the next piece
default:
inVar = true;
copyText += '%' + piece[i];
}
}
}

if (copyAsHtml) {
var mimeTypes = ['text/html', 'text/unicode'];
} else {
var mimeTypes = ['text/unicode'];
}
return this.copyToClipboard_(copyText, mimeTypes);
};

net.soylentred.makelink.LinkMaker.prototype.copyToClipboard_ = function(
copyText, mimeTypes) {
this.logger_.logCall('copyToClipboard_', arguments);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var string = Components.classes['@mozilla.org/supports-string;1']
.createInstance(Components.interfaces.nsISupportsString);
if (!string) {
this.logger_.warning('Failed to create nsISupportsString');
return false;
}
var transferable = Components.classes['@mozilla.org/widget/transferable;1']
.createInstance(Components.interfaces.nsITransferable);
if (!transferable) {
this.logger_.warning('Failed to create nsITransferable');
return false;
}
var clipboard = Components.classes['@mozilla.org/widget/clipboard;1']
.getService(Components.interfaces.nsIClipboard);
if (!clipboard) {
this.logger_.warning('Failed to get service nsIClipboard');
return false;
}

string.data = copyText;
for (var i = 0; i < mimeTypes.length; i++) {
transferable.addDataFlavor(mimeTypes[i]);
transferable.setTransferData(mimeTypes[i], string, copyText.length * 2);
}
clipboard.setData(transferable, null,
Components.interfaces.nsIClipboard.kGlobalClipboard);
return true;
};

net.soylentred.makelink.LinkMaker.prototype.rebuildMenu_ = function() {
this.logger_.logCall('rebuildMenu_', arguments);
var menu = document.getElementById('makelink-submenu');
var config = menu.lastChild;
if (!this.menuHasBeenBuilt_) {
config.addEventListener('command',
net.soylentred.makelink.bind(this, this.openOptions),
false);
this.menuHasBeenBuilt_ = true;
};
var types = this.linkTypeSource_.getLinkTypes();
// Remove all children of the menu:
while (menu.firstChild != config) {
menu.removeChild(menu.firstChild);
}
// For each link type, add a menu item:
for (var i = 0; i < types.length; i++) {
var menuitem = document.createElement('menuitem');
menuitem.setAttribute('label', types[i]['title']);
menuitem.setAttribute('format', types[i]['format']);
menuitem.setAttribute('useentities',
types[i]['useentities'] ? 'true' : 'false');
menuitem.setAttribute('class', 'makelink-linktype');
var linkMaker = this;
menuitem.addEventListener('command',
function(e) {
linkMaker.makeSelectionLink(e, this.getAttribute('format'),
this.getAttribute('useentities') == 'true');
}, false);
menu.insertBefore(menuitem, config);
}
// Add a separator (only if there's at least one link type):
if (menu.firstChild != config) {
menu.insertBefore(document.createElement('menuseparator'), config);
}
};

(function(){
var linkMaker = new net.soylentred.makelink.LinkMaker();
window.addEventListener('load',
net.soylentred.makelink.bind(linkMaker, linkMaker.startUp),
false);
window.addEventListener('unload',
net.soylentred.makelink.bind(linkMaker, linkMaker.shutDown),
false);
})();

kmnykmny 2010/06/12 01:40 ■修正
▽追加変数
・LOCAL_TIME: ローカルタイム
 形式: YYYY/MM/DD hh:mm:ss
 toLocaleString()は用いない

・UTC_TIME: UTCタイム
 形式: toUTCString()の出力

▽機能変更
・TITLE
 content.document → document.title

・TEXT, TEXT_N
 空白部分を半角スペース1文字に置き換え
 → 最短マッチングの繰り返しにする (サンプルソースコードの引用のため)

・TEXT_N
 文頭と文末の半角スペースのトリム
 → 行末に半角スペースが残るのを修正
  引用文に複数の改行が含まれることを想定、複数の行末のについて処理

 追加: 2009/01/12
 PRE要素で囲んだところをgetSelectionで選択すると改行がなくなる。CODE要素は問題なさそう
 (PRE要素内の文字を変更する際、改行コードの扱いが各ブラウザで異なる)
 → node.localName を用いて、PRE要素かどうかを見る。改行が含まれる textContent 利用

■TiddlyWiki用MakeLink定義例
▽TW Link
[[%TITLE%|%URL%]]

▽TWLink & Selection
<<<
%TEXT_N%

Source: [[%TITLE%|%URL%]] (%LOCAL_TIME%)
<<<

■補足
* MakeLink 9.11のmakelink.jarに含まている、makelink.jsは使われていない (Ver 8.x のころのもの)。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証