インデント毎に背景色を変える
※ Scrapbox研究会に一度投稿しましたが、カスタマイズコレクションに引っ越しました。
対訳を書いています。英文・和文をインデント(レベル)で区別して、背景色を変えるのが、よさそうです。
現在試用中
第1レベルは、英文
第2レベルは、和文(翻訳文)
直下のインデントレベルに翻訳結果を挿入するボタンが欲しい
第3レベルは、数式やコード
第4レベルは、メモ
その先の目論見(希望)
インデントレベル毎に可視・不可視を選べるボタンを作る
あるインデントレベルを表示すると、和訳のみ表示される、とか
和訳を textlint に喰わせる、とか
→ 快適な翻訳環境になると思う
動作例
原理
インデントレベル n
の行 ( .line
クラス) に .indent-level-n
というクラス名を追加する
.indent-level-n
の背景色を指定する
UserCSSを使う
参考
Scrapboxのインデントレベルを取得する
DOMやCSSセレクタで選択
jQuery 特定の子を持つ要素の親を取得する
.has( selector )
UserScript第1バージョンは、↑ こちら
style="margin-left: ___em;"
の値を読む
UserScript第3バージョンは、↑ こちら
.indent-mark span[class^="c-"]
の数を読む
UserScript第4バージョンは、↑ こちら
Scrapbox.Page.lines
をパースして取得
マッチする \s
の文字数でインデントレベルとする
UserScript第2バージョンは、↑ こちら
UserScript第4バージョン
基本は第3バージョンとほぼ同じ
.indent-mark span[class^="c-"]
の数でインデントレベルを調べている
任意の数のインデントレベルを取得できるようになった
UserScript第3バージョン
私の利用法には合わない →「マッチする \s
の文字数でインデントレベルとする」
\s
の文字数でインデントレベルを調べるのが
さんの利用法に合わない理由は何でしょうか?
\s
を数えると不都合が生じる場面が思いつかないので、純粋に疑問に感じました
単純にコーディングスタイルに合わないとか?
.indent-level-n
を付与する関数を書き換えた
style="margin-left: ___em;
でインデントレベルを調べる
さん方式
もう少しスマートに書きたいところ
.indent-level-n
を付与する関数:第3版
script.js// 参考 > https://scrapbox.io/api/code/customize/Hierarchy_Extension/script.js
function addIndentLevels() {
scrapbox.Page.lines.filter(l => {
return ! (document.getElementById(`L${l.id}`).querySelector('[class^="indent-level-"]'));
}).map(l => {
return {id: l.id, indent: l.text.match(/^\s+/)}
}).forEach((l) => {
let e;
e=document.getElementById(`L${l.id}`);
if (e.querySelector('[style="margin-left: 1.5em;"]')) {
e.classList.add(`indent-level-1`);
} else if (e.querySelector('[style="margin-left: 3em;"]')) {
e.classList.add(`indent-level-2`);
} else if (e.querySelector('[style="margin-left: 4.5em;"]')) {
e.classList.add(`indent-level-3`);
} else if (e.querySelector('[style="margin-left: 6em;"]')) {
e.classList.add(`indent-level-4`);
} else if (e.querySelector('[style="margin-left: 7.5em;"]')) {
e.classList.add(`indent-level-5`);
} else if (e.querySelector('[style="margin-left: 9em;"]')) {
e.classList.add(`indent-level-6`);
} else if (e.querySelector('[style="margin-left"]')) {
e.classList.add(`indent-level-7`);
} else {
e.classList.add(`indent-level-0`);
}
})
}
UserScript第2バージョン
.indent-level-n
を付与する関数を用意した
コード例をありがとうございます
.indent-level-n
が付与された行をスキップ する処理を追加した
セレクタの書き方が不安
さん、ヒントをありがとうございます
どういたしまして
変化を検出したら、上と同じ関数を呼び出して .indent-level-n
を再び付与する
行にカーソルをおくと .indent-level-n
が外れてしまう(ようだ)
でも、行を確定(?)すれば .indent-level-n
が再び付与される
ページ再読込は不要となった。うれしい
.indent-level-n
を付与する関数:第2版
script-2.js// 参考 > https://scrapbox.io/api/code/customize/Hierarchy_Extension/script.js
function addIndentLevels() {
scrapbox.Page.lines.filter(l => {
return ! (document.getElementById(`L${l.id}`).querySelector('[class^="indent-level-"]'));
}).map(l => {
return {id: l.id, indent: l.text.match(/^\s+/)}
}).forEach((l) => {
let indent;
if(l.indent == null) {
indent = 0;
} else {
indent = l.indent[0].length;
}
document.getElementById(`L${l.id}`).classList.add(`indent-level-${indent}`)
})
}
.indent-level-n
付与の実行とDOM変更の監視:第2版以降
script.js// DOM読み込み後の処理
addIndentLevels();
// DOM監視
(function () {
const target = document.getElementById('app-container')
const observer = new MutationObserver(records => addIndentLevels() )
observer.observe(target, {
childList: true,
subtree: true
})
})()
.indent-level-n
を付与する関数:第1版
script-1.js$('.line').has('.indent-mark .c-0').addClass("indent-level-0");
$('.line').has('.indent-mark .c-1').addClass("indent-level-1");
$('.line').has('.indent-mark .c-2').addClass("indent-level-2");
$('.line').has('.indent-mark .c-3').addClass("indent-level-3");
$('.line').has('.indent-mark .c-4').addClass("indent-level-4");
$('.line').has('.indent-mark .c-5').addClass("indent-level-5");
$('.line').has('.indent-mark .c-6').addClass("indent-level-6");
第1バージョンの問題点
まずは、動作確認的な扱いです。
行を編集すると背景色が消える(ページを更新すれば復活)
ページを新規作成時にしか、クラス名を付加しないので
編集中も動作するとうれしいです。
UserScriptの例が scrapbox.PopupMenu.addButton
や scrapbox.PopupMenu.addItem
を用いたものばかりなので、他の実例が見たい
ありがとうございます(VanillaJS初心者なので)
.line
クラスからではなくて
.text
クラスからを選択する方がよいかもしれない?
テキスト出現までの直近の主要構造が、次のようになっているので
.line
だと、テロメアも含んでしまう
page.html<div class="line">
<div class="teromere">...</div>
<span class="text">
<span>
<span class="indent-mark" style="width: 1.5em;"></span>
<span class="indent" style="margin-left: 1.5em;">
<span class="c-1">現</span>
<span class="c-2">在</span>
<span class="c-3">試</span>
</span>
</span>
</span>
</div>
.line
にCSSをあてる運用でよさそうです
テロメアを上書きしない
jQueryを使わずにCSSだけでも実現できそうです
.lineの中に入っている .indent
と .indent-mark
にインデントごとのstyleが属性がついているので、これを属性セレクタを使うことでこんな感じで選択することができます
ありがとうございます。
css.line .indent-mark[style^="width: 1.5em;"],
.line .indent[style^="margin-left: 1.5em;"] {
background: lightblue;
}
.indent-mark
のほうは height: 1rem;
が指定されていてテキストと高さが合わないので height: unset;
で解除しちゃうのがよさそうです
ただ .line
そのものではなくて子要素になってしまうので、折り返しがあったときに白い部分が出来てしまうのが少し気にはなりますが
CSSで .has
セレクタが早く使えるようになるとよいですね
CSSだとブラウザ側が処理してくれるので編集中もすぐ反映されるようになると思います
スタイルシートは、そのまま
style.css.indent-level-0 {
background-color: #FFFFBB; /* クリアな黄 */
}
.indent-level-1 {
background-color: #DDEEFF; /* 薄い青 */
}
.indent-level-2 {
background-color: #FFDDDD; /* 薄い赤 */
}
.indent-level-3 {
background-color: #DDEEAA; /* 透きとおった緑みの黄 */
}
.indent-level-4 {
background-color: #FFDDEE; /* 薄い赤紫 */
}
.indent-level-5 {
background-color: #AADDAA; /* 透きとおった緑 */
}
.indent-level-6 {
background-color: #FFBBBB; /* クリアな赤 */
}