scrapboxのページカードを作成するscript_old
scrapbox-parserを使ったver.を作った
以下は、独自の簡易parserを使った方法
scrapboxの実装をほぼそのまま使う
説明文の実装
1行づつ <p>
で囲む
↓構文解析が面倒なのでパス
リンクは <span class="page-link">
を使う
外部リンクは <span class="link">
を使う
アイコン記法は <img class="inline-icon" src='...'>
を使う
src
は読み込み元のprojectに合わせる
インラインコードは <code>
を使う
script.jsexport function createPageCard(project,titleLc,descriptions,imageUrl = null) {
const wrapper = document.createElement('a');
wrapper.href = `/${project}/${titleLc}`;
wrapper.rel = 'route';
const hover = document.createElement('div');
hover.classList.add('hover');
wrapper.appendChild(hover);
const content = document.createElement('div');
content.classList.add('content');
wrapper.appendChild(content);
// titleを入れる
const title = document.createElement('div');
title.classList.add('title');
title.textContent = decodeURIComponent(titleLc);
const header = document.createElement('div');
header.classList.add('header');
header.appendChild(title);
content.appendChild(header);
// thumbnail imageがある場合
if (imageUrl !== null) {
const image = document.createElement('img');
image.loading = 'lazy';
image.src= imageUrl;
const icon = document.createElement('div');
icon.classList.add('icon');
icon.appendChild(image);
content.appendChild(icon);
} else {
const text = document.createElement('div');
text.classList.add('description');
descriptions.forEach(description => {
const line = document.createElement('p');
line.appendChild(parseLine(description, project));
text.appendChild(line);
});
content.appendChild(text);
}
const card = document.createElement('li');
card.classList.add('page-list-item', 'grid-style-item');
card.appendChild(wrapper);
return card;
}
function parseLine(line, project) {
// []記法を探す
const reg = /(\[[^\s!"#%&'()\*\+,\-\.\{\|\}<>_~[\]]+[^[\]]*\])/u;
const words = line.split(reg).filter(word => word !== '');
let fragment = document.createDocumentFragment();
for (const word of words) {
if(!reg.test(word)) {
fragment.appendChild(document.createTextNode(word));
continue;
}
const content = word.replace(/\[(.+)\]/,'$1');
// 外部リンクかどうか
if(/(?:^https*:\/\/)|(?:\shttps*:\/\/[^\s]+$)/.test(content)) {
const link = document.createElement('span');
link.classList.add('link');
link.textContent = content.replace(/(?:^https*:\/\/[^\s]+\s)|(?:\shttps*:\/\/[^\s]+$).*/,'');
fragment.appendChild(link);
continue;
}
// 記法によって分岐する
if(/\.icon$/.test(content)) {
const img = document.createElement('img');
img.classList.add('inline-icon');
const link = content.replace(/(.+)\.icon$/,'$1');
// 外部projectかどうか
const isExternalLink = /^\/[a-zA-z\-]+(?:\/|$)/.test(content);
if(isExternalLink) {
img.src = `/api/pages${link}/icon`;
} else {
img.src = `/api/pages/${project}/${link}/icon`;
}
fragment.appendChild(img);
continue;
}
const link = document.createElement('span');
link.classList.add('page-link');
link.textContent = content;
fragment.appendChild(link);
}
return fragment;
}