Ubuntu日本語フォーラム
ログインしていません。
/* 自ら新規トピックをたてるのは,フォーラムにユーザ登録した直後以来です.*/
「引用」クリックでリンクが自動付記されるシステムにしていただきたいですへのスクリプト投稿以降も,
FireFox の拡張機能 greasemonkey を使って「Ubuntu日本語フォーラム」をユーザサイドで改造するスクリプトをいくつか作成しました.
UJFHack-disable-smilies : 「スマイリーを表示しない」にチェックを入れる
UJFHack-draggable-form : クイック投稿の返信フォームを上下にドラッグ可能にする
UJFHack-keep-draft : 投稿入力フォームに入力中の文章をログアウトまで保持する
UJFHack-linked-quote : 「引用」のリンククリックで挿入される BBCode をリンク付きにする*
UJFHack-page-button : 25超の投稿を1頁に読み込んで表示する*
UJFHack-privacy : 本名等のうっかり投稿をブロックする
UJFHack-quick-preview : クイック投稿の返信フォームにプレビューボタンをつける*
UJFHack-quick-quote : クイック投稿の返信フォームに様々な書式の引用を挿入する*
UJFHack-reverse-review : 返信投稿のページのレビューの順序を逆順にする
UJFHack-scrollable-view : 投稿表示エリアにスクロールバーをつける
UJFHack-search-result : サイト内検索結果を新たなタブに表示する
一部* は以前 ubuntu-ja-* として投稿したもので,リファクタリングの結果 プレフィックスを UJFHack に変更しました.
greasemonkey についてはUbuntuフォーラムをGreasemonkeyで便利に使っちゃおう!(by kiyopさん)を,
また,スクリプト作成の動機や経緯については前述のトピックの#44, #50を参照して下さい.
そこに書いたように対象は「自らカスタマイズできるユーザ」です.ユーザフレンドリーなエラー処理は組み込んでありません.
// つまり,エラーは「ツール→エラーコンソール」で対処しなくてはなりませんが,それでも使ってみようという方はいらっしゃるのでしょうか?
1 回につき 1 ファイルのペースで,とりあえず,一番短いスクリプトから,投稿を始めます.
一覧のスクリプトの投稿が終わる(または,途中で挫けるか,何/誰かに止められる)まで続けたいと思っています.
オフライン
UJFHack-search-result : サイト内検索結果を新たなタブに表示
ページ右上の「サイト内検索」には,
- 検索結果が現在のページを置き換えてしまう.
- 投稿番号 #25 近くを読んでいるときには,検索ボックスは遥か上に消えてしまい,いちいちスクロールするのが面倒.
の不満を持っていました.
そこで,ごくごく簡単なスクリプトを書きました.
1. 検索結果が新しいタブで開くようにする.
2. スクロール位置に関係なく,検索ボックスが常に右上隅に表示されるようにする.
// ==UserScript== // @name UJFHack-search-result // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Search Result in New Tab $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/* // ==/UserScript== var form = document.getElementById('cse-search-box'); if (!form) return; form.target = '_blank'; var searchbox = form.parentNode; var style = searchbox.style; style.top = '-2em'; style.zIndex = 50; style.position = 'fixed'; searchbox.previousSibling.previousSibling.style.zIndex = 75;
2. だけなら Stylish 等による stylesheet のカスタマイズでも実現可能です.
// 検索ボックスが常に目に入る位置に有れば,検索せずに投稿する人が減らないかな…?
オフライン
yama さん,hir0 さん,コメントをありがとうございます.
スクリプトをダウンロード可能なサイトに置くと,最短 2 クリック(=ソースコードを確認しない場合)でインストール出来ます.
確かに導入は簡単になりますが,greasemonkey スクリプトはセキュリティ上危険な操作も可能なので,
そういう「ソースコードが目に触れないことが一般的である方法」で自作スクリプトを他人に奨めることは避けたいと考えています.
// 仮令コードを読めない人が大半であるとしても,読める人の目に触れる確率を高くしておきたい.
そもそも私自身が userscripts.org にあるスクリプトをインストールしようと思ったことがありません.
他人のスクリプトを警戒して使おうと思わない人間が,他人に自作のスクリプトを奨めるとはどういうつもりなのか?
と問われると返答に窮してしまいます.弁明を考え始めると…シリーズ途中で挫けるかもしれません.
動機的には奨めるよりも,「ユーザ側でもここまではできるぞ」というデモンストレーションの意味合いが強いのですが…
次ではスクリプトを投稿します.
オフライン
(==) ← 次に投稿するスクリプトのテスト
自らトピックをたてたのは,実験場が欲しかったという面もあります.
オフライン
UJFHack-disable-smilies : 「スマイリーを表示しない」をチェック
フォーラムに不慣れな人が貼り付けた Xorg.0.log の (==) が絵文字に化けるのを見る度に,
スマイリーはデフォルトで OFF にして,使いたい人だけが ON にするべきではと感じます.
私自身は,-- どのシークエンスが絵文字になるのか全く覚えていないので --,間違っても絵文字化けさせないため,
投稿の際には必ずチェックを入れるようにしていました.それを自動化するスクリプトです.
// ==UserScript== // @name UJFHack-disable-smilies // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Disable Smilies $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== if (location.pathname === '/post.php') { document.getElementsByName('hide_smilies')[0].checked = true; } else { var formsent = document.getElementsByName('form_sent')[0]; if (!formsent) return; var hide = document.createElement('input'); hide.type = 'hidden'; hide.name = 'hide_smilies'; hide.value = 1; formsent.parentNode.insertBefore(hide, formsent); }
// ニーズは無いかな?
フォームのデフォルト値を弄るのは greasemonkey の典型的な使用法でしょう.
オフライン
einundzwanzighundertsechs さん
試しに、Trixie+IE8 という環境でユーザスクリプトを試してみたところ、下記のようになってしまいました。
↓こちらで紹介していただいたスクリプト。
https://forums.ubuntulinux.jp/viewtopic.php?pid=55639#p55639
~さんの投稿 #x というのが上手く解釈出来ないようで文字化けしてしまいます。
いつかすごく時間が出来たときで結構ですので、Trixie でも上手く動くようにしていただけると、色々な意味で敷居がグンと下がると思うので、TODO の一番最後にでもメモしていただけるとありがたいかと。
あ、私自身が欲しい機能ではないので、お願いするだけの説得力にやや欠けるのですが…。
einundzwanzighundertsechs ����̓��e:
/* 自ら新規トピックをたてるのは,フォーラムにユーザ登録した直後以来です.*/
「引用」クリックでリンクが自動付記されるシステムにしていただきたいですへのスクリプト投稿以降も,
FireFox の拡張機能 greasemonkey を使って「Ubuntu日本語フォーラム」をユーザサイドで改造するスクリプトをいくつか作成しました.
……
……
オフライン
petitbootang さんによる投稿 (#8):
↓こちらで紹介していただいたスクリプト。
https://forums.ubuntulinux.jp/viewtopic.php?pid=55639#p55639
~さんの投稿 #x というのが上手く解釈出来ないようで文字化けしてしまいます。
確認のために、スクリプトファイルの文字コードを UTF-8 (BOM無し) で保存して、もう一度試してみてください
小生も最初は Shift-JIS で保存してしまい FireFox で文字化けを起こしました
オフライン
ry さん、ありがとうございます。
utf-8 LF で保存し直したら、正常に表示されるようになりました。
einundzwanzighundertsechs さん、お騒がせいたしました。
これから、ほかのスクリプトも色々試してみます。
petitbootang さんによる投稿 (#8):
↓こちらで紹介していただいたスクリプト。
https://forums.ubuntulinux.jp/viewtopic.php?pid=55639#p55639
~さんの投稿 #x というのが上手く解釈出来ないようで文字化けしてしまいます。確認のために、スクリプトファイルの文字コードを UTF-8 (BOM無し) で保存して、もう一度試してみてください
小生も最初は Shift-JIS で保存してしまい FireFox で文字化けを起こしました
オフライン
petitbootang さん,ry さん,こんばんわ.留守にしている間に問題は解決したようで良かったです.
===================================================
「引用」クリックでリンクが自動付記されるシステムにしていただきたいです #61に投稿したubuntu-ja-quick-quote では,
UJFHack-page-button/-quick-quote の機能を1つのスクリプトに詰め込む,All in One 指向でした.
機能を限定して,ファイルサイズを小さくし,コードの目的をはっきりさせれば,怪しい操作は紛れ込ませ難くなります.
今回の UJFHack-* では,原則として 「1 スクリプト = 1 機能」 となるようにファイルを分けました.
「ダウンロード&インストール」ではなく「ソースコード投稿による配布」を選択した以上,ファイル分割は不可避となりました.
* メリット:
バグフィックスでは当該のファイルのみ訂正・投稿すれば良く,コードの保守がしやすい.必要な機能のみインストールでき,機能毎の ON/OFF が容易になる.
* デメリット:
複数のファイルを管理する必要がある.インストール手順が多少複雑になり,スクリプトの実行順に注意しなければならない.
次から4回続けて,#1の一覧に挙げなかったスクリプト
UJFHack-BEGIN
UJFHack-Post
UJFHack-ViewTopic
UJFHack-END
を投稿します.
これらは個々の機能を実現するスクリプトが連携するための「枠組み」を構成するものです.
// スタートしていきなりの大きな曲がり角です.
オフライン
UJFHack-BEGIN : ルートオブジェクト
スクリプト間の仲介役となるグローバルオブジェクトを作成し,
頻繁に使う XPath 検索関数と最後に実行する関数を登録するフックを定義します.
このスクリプトは以降に投稿するスクリプトに先んじて実行されなければなりません.
greasemonkey の「ユーザスクリプトの管理」でリストの先頭へと持っていきます.
// ==UserScript== // @name UJFHack-BEGIN // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Root Object $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/* // ==/UserScript== function find(xpath, node, result) { return document.evaluate(xpath, node, null, result, null); }; unsafeWindow.UJFHack = { findFirst : function(xpath, node) { return find(xpath, node, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue; }, findAll : function(xpath, node) { return find(xpath, node, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); }, findString : function(xpath, node) { return find(xpath, node, XPathResult.STRING_TYPE).stringValue; }, findNumber : function(xpath, node) { return find(xpath, node, XPathResult.NUMBER_TYPE).numberValue; }, hooks : [] };
オフライン
UJFHack-END : フック関数を実行
他のスクリプトより実行を遅らせたい関数は,フックに登録してこのスクリプトで実行します.
「ユーザスクリプトの管理」でリストの最後に置きます.
// ==UserScript== // @name UJFHack-END // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Run Hooks $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/* // ==/UserScript== var hooks = unsafeWindow.UJFHack.hooks; for (var i = 0; i < hooks.length; ++ i) { hooks[i](); }
// onload イベントに引っ掛けたのでは,ページロード直後の表示の乱れが目立つので独自のフックを導入しました.
オフライン
UJFHack-Post : Post オブジェクト
投稿フォームを操作するオブジェクトと関数を定義します.
// ==UserScript== // @name UJFHack-Post // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum : Object for Post $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== var Post = unsafeWindow.UJFHack.Post = { message : document.getElementsByName('req_message')[0], }; var submit = document.getElementsByName('submit')[0]; if (submit) { var anchor = submit.nextSibling; var index = submit.tabIndex; var parent = submit.parentNode; Post.addInput = function(input) { input.tabIndex = ++ index; parent.insertBefore(input, anchor); } }
オフライン
UJFHack-ViewTopic : ViewTopic オブジェクト
投稿を表示するビュー(div 要素)を下準備します.
// ==UserScript== // @name UJFHack-ViewTopic // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Object for View Topic $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // ==/UserScript== var UJFHack = unsafeWindow.UJFHack; var ViewTopic = UJFHack.ViewTopic = { createButton : function (name, func) { var button = document.createElement('input'); button.type = 'button'; button.value = name; button.addEventListener('click', func, false); return button; }, pageRevisor : [], revisePage : function (page) { var list = ViewTopic.pageRevisor; for (var i = 0; i < list.length; ++ i) { list[i](page); } }, }; var punviewtopic = ViewTopic.punviewtopic = document.getElementById('punviewtopic'); var thePage = ViewTopic.thePage = document.createElement('div'); ViewTopic.inbox = UJFHack.findFirst('div[@class="linkst"]/div[@class="inbox"]', punviewtopic); var list = UJFHack.findAll('div[starts-with(@class,"blockpost")]', punviewtopic); punviewtopic.insertBefore(thePage, list.snapshotItem(0)); for (var i = 0; i < list.snapshotLength; ++ i) { thePage.appendChild(list.snapshotItem(i)); } ViewTopic.pageView = thePage;
オフライン
#14, #15のUJFHack-Post/-ViewTopic のスクリプトは「ユーザスクリプトの管理」で UJFHack-BEGIN の直後に挿入します.
これ以降に投稿する#1の一覧のスクリプトはさらにその後に挿入します.
推奨のスクリプト実行順
UJFHack-BEGIN
UJFHack-Post
UJFHack-ViewTopic
UJFHack-小文字スクリプト
UJFHack-END
小文字スクリプトの実行順が動作に深刻な影響を与え無いように「枠組み」を設計したつもりです.
スクリプトの実行順がおかしい場合には,JavaScript のエラーがエラーコンソールに記録されます.
UJFHack-Post/-ViewTopic の順は逆でも構いません.
UJFHack-search-result/-disable-smilies はこの枠組みに依存していないので,実際はどこに置いてもOKです.
UJFHack-disable-smilies : 修整版 1.1(旧版→#7)
この数回の投稿で,UJFHack-disable-smilies がエラーを吐いていることに気づきました.
投稿後リダイレクトの直前のページに対象の要素が無いのが原因です.
動作には問題は有りませんが,深刻ではないエラーがコンソールに残るとデバッグに差し支えるので修正します.
// ==UserScript== // @name UJFHack-disable-smilies // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Disable Smilies $Revision: 1.1 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== if (location.pathname === '/post.php') { hide = document.getElementsByName('hide_smilies')[0]; if (! hide) return; hide.checked = true; } else { var formsent = document.getElementsByName('form_sent')[0]; if (!formsent) return; var hide = document.createElement('input'); hide.type = 'hidden'; hide.name = 'hide_smilies'; hide.value = 1; formsent.parentNode.insertBefore(hide, formsent); }
まずは,これで一段落です.
オフライン
UJFHack-quick-preview : クイック投稿にプレビューボタン追加 -- まずは「枠組み」のインストールテストとして --
「引用」クリックでリンクが自動付記されるシステムにしていただきたいです #44に投稿した ubuntu-ja-quick-preview の UJFHack 版です.
前々から greasemonkey で実現できると判っていたものの,コーディングは「クイック投稿」とプレビューがポストされたのを見てからでした.
#16に述べた位置に本スクリプトを挿入すれば,クイック投稿にプレビューボタンが追加されるはずです.
// ==UserScript== // @name UJFHack-quick-preview // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Preview Button in Quick Post $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // ==/UserScript== var UJFHack = unsafeWindow.UJFHack; var addInput = UJFHack.Post.addInput; if (! addInput) return; var preview = document.createElement('input'); preview.type = 'submit'; preview.accessKey = 'p'; preview.value = 'プレビュー'; preview.name = 'preview'; UJFHack.hooks.push(function() { addInput(preview); });
フックを使ったのは投稿予定の他のスクリプトが追加するボタンよりも後にプレビューボタンを追加して,「クイック投稿」と「返事を投稿」でのボタンの並びを同じにするためです.
//#1の一覧で数えるとこれでやっと3本目…
=================================
UJFHack-disable-smilies : 修整版 1.1#16では var をつけ忘れたのだけれど,FireFox の実装によるものか,エラーにならないらしいです.diff を貼ります.
--- ujfhack-disable-smilies.user.js 2010/04/19 14:56:51 1.1 +++ ujfhack-disable-smilies.user.js 2010/04/19 15:41:19 1.2 @@ -1,13 +1,13 @@ // ==UserScript== // @name UJFHack-disable-smilies // @namespace http://localhost/ -// @description Hack for Ubuntu Japanese Forum: Disable Smilies $Revision: 1.1 $ +// @description Hack for Ubuntu Japanese Forum: Disable Smilies $Revision: 1.2 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== if (location.pathname === '/post.php') { - hide = document.getElementsByName('hide_smilies')[0]; + var hide = document.getElementsByName('hide_smilies')[0]; if (! hide) return; hide.checked = true; }
オフライン
UJFHack-keep-draft : 入力中の文章をログアウトまで保持
この機能は
「クイック投稿」とプレビュー の funatogawa さんの投稿:
一番困ったのは、入力途中で他のURLを参照にいって、戻ると、入力した文章がなくなっており、『前のページに戻る』キーでも文章は戻ってこず、最初から入れ直しになってしまうことです。分かっていながらついやってしまい、後悔の連続です。
がきっかけです.想像以上に有用だったスクリプトです.本トピックを新しく投稿したときの体験では--(以下は引用では有りません)
「Tutorial & Tips」の「新しいトピックの投稿」で入力開始,途中で「Japanese Wiki & フォーラム」のトピックに移動,
投稿予定の機能「クイック引用」でリンクをいくつか挿入して,投稿済みの機能「クイックプレビュー」で確認,
「戻る」のリンクでトピックビューに戻り文章を完成させる.
ここで「送信」すると「Japanese Wiki & フォーラム」のトピックへの返信扱いになるので,
もう一度「Tutorial & Tips」の「新しいトピックの投稿」から入力フォームを表示させ「送信」をクリックした.
この間,ページ遷移を跨いで編集中の文章は保持され,メッセージ欄の有るページを開く度にそれまでに入力済みの文章が自動的に挿入されました.
// 最初に入力したトピックタイトルは失われていて,かえってこの機能が強力な事が実感出来ました.
保持した文章はログアウトか,送信に成功したときに廃棄されます.他のサイトに移動してもフォーラムの login.php を踏まない限り文章は残ります.
// ==UserScript== // @name UJFHack-keep-draft // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Keep Message Draft $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // @include https://forums.ubuntulinux.jp/login.php?* // ==/UserScript== if (location.pathname === '/login.php') { GM_setValue('message', ''); return; } var Post = unsafeWindow.UJFHack.Post; var message = Post.message; if (!message) return; var revert; if (message.value === '') { message.value = revert = GM_getValue('message', ''); GM_setValue('message', ''); } else { revert = message.value; } function saveMessage () { GM_setValue('message', message.value); } unsafeWindow.addEventListener('unload', saveMessage, false); var process_form = unsafeWindow.process_form; unsafeWindow.process_form = function(form) { if (process_form(form)) { unsafeWindow.removeEventListener('unload', saveMessage, false); return true; } return false; }; var reset = document.createElement('input'); reset.accessKey = 'r'; reset.value = 'リセット'; reset.type = 'button'; reset.addEventListener('click', function () { message.value = revert; }, false); Post.addInput(reset); var clear = document.createElement('input'); clear.accessKey = 'c'; clear.value = 'クリア'; clear.type = 'button'; clear.addEventListener('click', function () { message.value = ''; }, false); Post.addInput(clear);
リセットボタンは現在のページに移動してきたときのメッセージ欄の文章(=保持文書)に戻し,
クリアボタンはメッセージ欄の文章を消去しますが,リセットで保持文書が復活します.
メッセージ欄を消去してページを離れると保持文書が空となり,結果として保持文書を廃棄することになります.
// お薦めの機能なので挫折しないうちに投稿!!
オフライン
※規約違反により追放されたユーザの投稿は、ログインユーザにのみ表示されます。
オフライン
// kiyop さんの言葉ですっかり説明を抜かしていたことに気づきました.
UJFHack-keep-draft #18はUbuntu 日本語フォーラムが送ってきた HTML ソースに含まれる JavaScript の process_form 関数を呼び出しています.
セキュリティに不安のある方はこの部分を自分で改変して使用してください.
======================================
kiyop さん,こんばんは.Wiki への掲載は OK ですが,注意書きは 「NO」 に近い「保留」です.理由は説明しだすと取り留めがなくなるので
- 何も書かなくてよいは思わないけれど,セキュリティ問題に対する啓蒙的な意味で,何を書けば効果的,あるいは逆効果なのか,わからない.→「保留」の理由
- 通り一遍の文言だけでは何かあった時の言い訳(「だから言ったのに…」)に役立つぐらいの意味しか無いだろう.→「NO」の理由
と言うことで,ごめんなさい.
オフライン
※規約違反により追放されたユーザの投稿は、ログインユーザにのみ表示されます。
オフライン
UJFHack-privacy : 個人情報の簡易保護
正規表現としてハードコードしたNGワードが投稿文に含まれていたら,送信をブロックします.
投稿では ubuntu を対象にしています.「保護」ボタンでNGワードを伏せ字に置換します.
また,「本当に送信しますか(Yes/No)?」の確認ダイアログでは,間違って Yes を押してしまうことが心配なので,
アラートを表示して有無を言わさずブロックする仕様にしました.
// 確認ダイアログではわたしの「うっかり」は防ぎきれない
// ==UserScript== // @name UJFHack-privacy // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Protect Privacy $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== var Post = unsafeWindow.UJFHack.Post; var addInput = Post.addInput; if (! addInput) return; var message = Post.message; var regexp = /ubuntu/; var ellipsis = '………'; var protect = document.createElement('input'); protect.type = 'button'; protect.value = '保護'; protect.addEventListener('click', function () { message.value = message.value.replace(regexp, ellipsis); }, false); addInput(protect); var process_form = unsafeWindow.process_form; unsafeWindow.process_form = function(form) { if (regexp.test(message.value)) { alert('個人情報が保護されていません'); return false; } return process_form(form); };
質問者にコマンド実行例を提示するとき,私のユーザ名は本名なので,出力を sed s/$USER/xxx/g にパイプしてから貼り付けています.
それでも送信ボタンを押すときには置換漏れがないか気になるので,ブラウザにも一役買ってもらおうと作成した機能です.
UJFHack-keep-draft#18と同じく,HTMLソースの process_form 関数を呼び出しています.セキュリティが心配の方はこの部分を自分で改変して使用してください.
オフライン
インターミッション:
そもそもどんなプログラムの実行も全て潜在的に危険であり,警戒は程度の差こそあれ常に必要です.
#18や#22のスクリプトにセキュリティ上の注意書きを添えましたが,これは他のスクリプトにセキュリティの問題が全く無いと言う意味では決してありません.
このような文書を付けなかったことで,被害の補償を求めれては確かに困るので,契約書やライセンスには免責事項を明記しなくてはならないと思うけれど,
Wiki やフォーラムでは,自己責任が原則としてそんなことは書かなくても当然であるべき,--- と言うか,
表面的な注意喚起(=責任回避の免罪符)で「正しい知識・正しい意識」が防衛の基本であることが霞んでしまう気がするのです.
だからと言って注意書きが無くて良いとは全然思わないのだけど,良い書き方が思いつかない…
オフライン
UJFHack-linked-quote : リンク付き引用
// 新機能の説明に疲れたので,過去の改訂版の投稿でお茶を濁します.
「引用」クリックでリンクが自動付記されるシステムにしていただきたいですの#38に投稿した ubuntu-ja-linked-quote の UJFHack 版です.
基本的に,「枠組み」が取得したHTML要素を使用するようにしただけで,「枠組み」に依存しないので旧版の方が使い良いかもしれません.
「引用にリンクを付けてほしい」という要望をとても短いコードで実現できて,greasemonkey の力を再認識したスクリプトでした.
現在私はより高機能の UJFHack-quick-quote を使っています.
// ==UserScript== // @name UJFHack-linked-quote // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Insert Linked Quote $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/post.php?* // ==/UserScript== var qid = /&qid=(\d+)$/.exec(location.search); if (!qid) return; qid = qid[1]; var message = unsafeWindow.UJFHack.Post.message; var url = 'url=' + location.protocol + '//' + location.host + '/viewtopic.php?pid=' + qid + '#p' + qid; function quote(match, user) { user += user === 'einundzwanzighundertsechs' ? ' ' : ' さん'; return '[quote][' + url + ']' + user + 'の投稿[/url]:\n\n'; } message.value = message.value.replace(/^\[quote=([^\]]+)\]/, quote);
特定の一人を除いて,HNの後に敬称「さん」を付ける仕組みになっています.
私が嫌っているのは自ら書いたの文章に他の方を呼び捨てにしている部分が混じることですので,そのまま使って頂いても私は気にしません.
オフライン
UJFHack-quick-quote : クイック投稿での引用機能
「引用」クリックでリンクが自動付記されるシステムにしていただきたいです の petitbootang さんの投稿に触発されて
同トピックの #51にに投稿した ubuntu-ja-quick-quote の UJFHack 版です.
引用パターンを選択出来る機能を追加しました.// 中には引用ではないものも入ってます.
引用パターンの変更,追加,削除はソースを皆さんで編集して下さい.
UJFHack-linked-quote と同じく,特定の一人にだけ,「さん」を付けないコードにしています.
// ==UserScript== // @name UJFHack-quick-quote // @namespace http://localhost/ // @description Hack for Ubuntu Japanese Forum: Add Quick Quote Functions $Revision: 1.0 $ // @include https://forums.ubuntulinux.jp/viewtopic.php?* // ==/UserScript== var UJFHack = unsafeWindow.UJFHack; var ViewTopic = UJFHack.ViewTopic; var punviewtopic = ViewTopic.punviewtopic; var createButton = ViewTopic.createButton; var findString = UJFHack.findString; var findAll = UJFHack.findAll; var findFirst = UJFHack.findFirst; var topic = findString('ul/li[position()=last()]', ViewTopic.inbox).slice(3); var message = UJFHack.Post.message; if (message) { var list = findAll('div/div[@class="inbox"]/p[@class="postlink conr"]/a', punviewtopic); var i = 0; var reply = list.snapshotItem(0); var url = location.protocol + '//' + location.host + location.pathname + '?id=' + reply.href.replace(/.*=/, ''); var title = '[' + 'url=' + url + ']' + topic + '[/url]'; function appendTitle() { message.value += title; } do { reply.parentNode.appendChild(createButton('タイトル引用', appendTitle)); } while (reply = list.snapshotItem(++ i)); } function sliceQuote(html) { var b = html.indexOf(']', html.indexOf('name="req_message"')) + 1; var e = html.indexOf('</textarea>', b) - 1; return html.slice(b, e); } function quickQuote(blockpost) { if (blockpost.nodeType !== unsafeWindow.Node.ELEMENT_NODE) return; var inbox = findFirst('div[@class="box"]/div[@class="inbox"]', blockpost); var user = findString('div[@class="postleft"]/dl/dt/strong/a', inbox); var nbsp = String.fromCharCode(160); if (! user) return; user += user === 'einundzwanzighundertsechs' ? nbsp : nbsp + 'さん'; var postfootright = inbox.lastChild.previousSibling; var conr = findFirst('h2/span/span[@class="conr"]', blockpost); var post = conr.textContent.slice(0, -1); var link = '[' + 'url=' + conr.nextSibling.href + ']'; if (! message) { postfootright.textContent = link + user + 'の投稿' + nbsp + post + '[/url]'; return; } var postquote = findFirst('ul/li[@class="postquote"]/a[starts-with(@href,"post.php")]', postfootright).href; function appendLink(text) { return function () { message.value += link + text + '[/url]'; }; } function appendQuote(func) { return function () { GM_xmlhttpRequest({method : 'GET', url : postquote, onload : func}); } } function withoutLink(text) { return function (detail) { message.value += '[quote' + text + ']' + sliceQuote(detail.responseText) + '\n'; } } function withLink(text) { return function (detail) { message.value += '[quote]' + link + text + '[/url]:\n\n' + sliceQuote(detail.responseText) + '\n'; } } var menu = [ { text:'クイック引用' }, { text:'Q', exec:appendQuote(withoutLink('')) }, { text:'T', exec:appendLink(topic) }, { text:'#', exec:appendLink(post) }, { text:'T#', exec:appendLink(topic + nbsp + post) }, { text:'U#', exec:appendLink(user + 'の投稿' + nbsp + post) }, { text:'QU', exec:appendQuote(withoutLink('=' + user)) }, { text:'TU', exec:appendLink(topic + ' の ' + user + 'の投稿') }, { text:'TU#', exec:appendLink(topic + ' の ' + user + 'の投稿' + nbsp + post) }, { text:'QT#', exec:appendQuote(withLink(topic + nbsp + post)) }, { text:'QU#', exec:appendQuote(withLink(user + 'の投稿' + nbsp + post)) }, { text:'QTU', exec:appendQuote(withLink(topic + ' の ' + user + 'の投稿')) }, { text:'QTU#', exec:appendQuote(withLink(topic + ' の ' + user + 'の投稿' + nbsp + post)) }, ]; var select = document.createElement('select'); for (var i = 0; i < menu.length; ++ i) { var option = document.createElement('option'); option.textContent = menu[i].text; select.appendChild(option); } select.addEventListener('change', function() { menu[this.selectedIndex].exec(); this.selectedIndex = 0; }, false); conr.appendChild(select); } function addQuoteButton(node) { for (var i = 0; i < node.childNodes.length; ++ i) { quickQuote(node.childNodes[i]); } } addQuoteButton(ViewTopic.thePage); ViewTopic.pageRevisor.push(addQuoteButton);
このスクリプトでは GM_xmlhttpRequest でフォーラムから引用文を GET しています.
セキュリティが気になる方は GM_xmlhttpRequest の引数を精査して下さい.
オフライン