関連ページリストにタグに応じて色やアイコンをつける
scrapbox-syncで、タグによってページの公開状態を決めているが、関連ページの公開状態を調べるのにいちいち見て回る必要があり面倒だったので作ったyosider.icon アイコン版のほうが、該当するタグが複数種類ついている場合にすべて表示できるので便利
色版でも頑張ればできそうだが
面白そうtakker.icon
例によってちょっと書き換えた
for文を減らした
デバッグしないで書き換えて放置というクソ迷惑なことしていますごめんなさい
ありがとうございますyosider.icon
むしろそれを期待して置いてるところあるw
色版
https://gyazo.com/e535292491956c67adf5b08d2d34919d
code:script1.js
const tagColorPairs = {
// for default-dark
'private': '#a95756',
'not-private': '#3c763d',
}
mark();
const observer = new MutationObserver(mark);
//observer.observe(document.querySelector('div.related-page-list.clearfix ul.grid'), { childList: true });
addObserver();
function addObserver() {
let elem = document.querySelector('div.related-page-list.clearfix ul.grid');
if (!elem) {
window.setTimeout(addObserver, 500);
return;
}
observer.observe(elem, { childList: true });
}
code:script1.js
if (match===' ') return '_'
else if (match==='"') return '\\"' // ahref='...'の中なので必要 else if (match==="'") return "\\'"
else return encodeURIComponent(match);
});
async function mark() {
if (!scrapbox.Page.title) return;
const {relatedPages: {links1hop}} = await (await fetch(/api/pages/${scrapbox.Project.name}/${scrapbox.Page.title})).json();
links1hop.forEach(({linksLc, title}) => {
const tag = Object.keys(tagColorPairs).find(tag => linksLc.includes(tag));
if (!tag) return;
const header = document.querySelector(.related-page-list .grid li.page-list-item a[href="/${scrapbox.Project.name}/${encode(title)}"] .header);
↑titleのエンコードを特殊な感じにしないといけないっぽい
/icons/fail.iconencodeURIComponent(title)
:はそのまま
(半角スペース)は_に置換
どう書けば良いのかわからない…誰か教えて下さいyosider.icon
title.replace(/ /g, '_').replace(/\/g, encodeURIComponent('/'))....みたいに列挙するしかない?
title.toLowerCase().replace(/ /g, '_')でいけると思いますtakker.icon
titleをtitleLcに変換できます
code:js
const header = document.querySelector(.related-page-list .grid li.page-list-item a[href="/${scrapbox.Project.name}/${title.toLowerCase().replace(/ /g, '_')}"] .header);
関連ページリストのカードを、hrefの値で取得しようとしているのですが、他にも/とか#とかencodeしないといけない文字があるようで、これだけではだめでしたyosider.icon
とりあえず以下でいけた
code:js
function _encode(match, offset, string) {
if (match===' ') return '_'
else if (match==="'") return "\\'" // ahref='...'の中なので必要 else if (match==='"') return '\\"' // 一応
else return encodeURIComponent(match);
}
code:script1.js
header.style.borderTop = ${tagColorPairs[tag]} solid 10px;
});
}
アイコン版
https://gyazo.com/17429297bea019940b91e949cac3499c
FontAwesomeアイコンを使う場合は、そのためのUserCSSも必要
code:style.css
.grid li {
font-family: "Roboto", Helvetica, Arial, "Hiragino Sans", sans-serif, FontAwesome;
}
.grid i {
font-style: normal;
}
code:script2.js
const tagIconPairs = {
// for default-dark
'private': <i class="fa fa-lock" style="color:#cd5c5c; margin-right:0.3em;"></i>,
'not-private': <i class="fas fa-unlock" style="color:#6fac63; margin-right:0.2em;"></i>,
}
mark();
const observer = new MutationObserver(mark);
addObserver();
function addObserver() {
let elem = document.querySelector('div.related-page-list.clearfix ul.grid');
if (!elem) {
window.setTimeout(addObserver, 500);
return;
}
observer.observe(elem, { childList: true });
}
if (match===' ') return '_'
else if (match==='"') return '\\"' // ahref='...'の中なので必要 else if (match==="'") return "\\'"
else return encodeURIComponent(match);
});
async function mark() {
if (!scrapbox.Page.title) return;
const {relatedPages: {links1hop}} = await (await fetch(/api/pages/${scrapbox.Project.name}/${scrapbox.Page.title})).json();
links1hop.forEach(({linksLc, title}) => {
const html = Object.keys(tagIconPairs)
.flatMap(tag => linksLc.includes(tag) ? [tagIconPairstag] : []) .join('');
const titleElem = document.querySelector(.related-page-list .grid li.page-list-item a[href="/${scrapbox.Project.name}/${encode(title)}"] .title);
//const temp = titleElem.textContent;
//titleElem.textContent = '';
//titleElem.textContent = temp;
titleElem.textContent = titleElem.textContent;
titleElem.insertAdjacentHTML('afterbegin', html);
});
}
https://gyazo.com/278b03d0243a3a6b0664d7555bd56b97
observerが発火する度にアイコンがふえる!
/icons/知らんかった.icontakker.icon
なるほど…?
なんか直感に反する動作だな…yosider.icon
testという1hop linkに対して、titleElem.textContentは"test"という文字列だけだが、titleElem.textContent = ''とするとアイコンと文字列両方が消える
titleElem.textContent = titleElem.textContent;だけでよさそう
なんだこの意味不明な行w
草takker.icon
違和感ありまくりだったのでいろいろ挟んでいたのですが、そんな事せずともA=Aで動くみたいですね
やっていることはtitleElem.setTextContent(titleElem.getTextContent())みたいな単なる関数呼び出しなので、まあ値が変化するのは当然といえば当然なのですが、いかんせん表記がA=Aなので、違和感を拭えませんね……
何もわからない。。
MDN.icon