jsimport {parse} from '/api/code/customize/html2sb/script.js';
const html = 'html形式のテキスト';
const text = parse({html: html});
html
: 変換対象のhtmlテキスト config
(optional): htmlの変換方法tstype 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
をいい感じに変えてやればなんとかなるかもしれないscript.jsconst format = text => text.split(/\n/).map(l => l.trim()).join('');
const ng = text => text.trim().replace(/[\[\]\n]/g, ' ');
script.jsconst 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 ?? '*';
const body = [...table.getElementsByTagName('tr')]
.map(row => ` ${[...row.querySelectorAll('th, td')]
.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)}]`,
},
{
selector: 'a[href] img[src]',
processor: img => {
const a = img.closest('a');
a.outerHTML = `[${img.src.trim()}#.png ${decodeURIComponent(a.href)}]`;
},
},
{
selector: 'a[href]',
text: (_, a) => `[${decodeURIComponent(a.href)} ${ng(a.text).trim()}]`,
},
{
selector: 'img[src]',
processor: img => img.outerHTML = `[${img.src.trim()}#.png]`,
},
{
selector: 'iframe[src*="//www.youtube.com/embed/"]',
processor: iframe =>
iframe.outerHTML =
`[https://www.youtube.com/watch?v=${iframe.src.split('/embed/')[1].split('?')[0]}]`,
},
{
selector: 'code',
text: code => `\`${code}\``,
},
];
script.jsfunction 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};