html2sb
使い方
code:js
import {parse} from '/api/code/customize/html2sb/script.js';
const html = 'html形式のテキスト';
const text = parse({html: html});
引数
html: 変換対象のhtmlテキスト
config (optional): htmlの変換方法
書式はこう
code:ts
type Config = {
selector: string;
text?: (textContent: string, element: HTMLElement) => string;
processor?: (element: HTMLElement) => void;
}[];
selectorで指定したhtml要素をprocessorで変換する
単純にtextContentだけ変更すればいい場合はtextを使う
いずれの変換も指定されていない場合は、selectorに該当する要素を空にする
実装
forEach内の不要な中括弧を削除
DOMParserを使用しない
既知の問題
code stringみたいなやつを変換するとscrapbox記法がcodeの中に入ってしまう
configをいい感じに変えてやればなんとかなるかもしれない
箇条書きの変換に失敗している
/icons/hr.icon
Utilities
code:script.js
const format = text => text.split(/\n/).map(l => l.trim()).join('');
const ng = text => text.trim().replace(/[\\\n]/g, ' '); defaultのparsing設定
code:script.js
const defaultConfig = [
{
selector: 'pre',
text: code => 'code:code.*\n' + code.split('\n').map(l => ${l}).join('\n'),
},
{
selector: 'h3',
text: headline => [** ${format(headline)}],
},
{
selector: 'h2',
text: headline => [*** ${format(headline)}],
},
{
selector: 'h1',
text: headline => [**** ${format(headline)}],
},
{
selector: 'table',
processor: table => {
const title = table.getElementsByTagName('caption')?.0?.textContent ?? '*'; .map(column => column.textContent).join('\t')}`)
.join('\n');
table.outerHTML = <pre>table:${title}\n${body}</pre>;
},
},
{
selector: 'em, i',
text: text => [/ ${format(text)}],
},
{
selector: 'strong, b',
text: text => [* ${format(text)}],
},
{
processor: img => {
const a = img.closest('a');
a.outerHTML = [${img.src.trim()}#.png ${decodeURIComponent(a.href)}];
},
},
{
text: (_, a) => [${decodeURIComponent(a.href)} ${ng(a.text).trim()}],
},
{
processor: img => img.outerHTML = [${img.src.trim()}#.png],
},
{
processor: iframe =>
iframe.outerHTML =
[https://www.youtube.com/watch?v=${iframe.src.split('/embed/')[1].split('?')[0]}],
},
{
selector: 'code',
text: code => \`${code}\`,
},
];
code:script.js
function parse({html, config = defaultConfig} = {}) {
const dom = document.createElement('div');
dom.insertAdjacentHTML('beforeend', html);
// configに基づいてHTMLを変換する
for (const {selector,text,processor} of config) {
if (processor) {
dom.querySelectorAll(selector).forEach(element => processor(element));
continue;
}
if (text) {
dom.querySelectorAll(selector)
.forEach(element => element.textContent = text(element.textContent, element));
continue;
}
dom.querySelectorAll(selector).forEach(element => element.textContent = '');
}
// 箇条書きを変換する
let depth = -1;
const li = node => {
depth++;
node.querySelectorAll('li').forEach(n => li(n));
return node.innerHTML = '@sp@'.repeat(depth--) + node.innerHTML;
};
li(dom);
// DOMを実体化して、テキスト形式でコピペする
document.body.appendChild(dom);
const range = document.createRange();
range.selectNode(dom);
const text = dom.innerText;
document.body.removeChild(dom); // 後始末
return text.replace(/(\s*\n){3,}/g, '\n\n')
.replace(/@sp@/gi, ' '); // ここで箇条書きのインデントを復元している
}
export {defaultConfig, parse};
UserScript.icon