scrapbox-embed-tweet
Xになってから定期的にTweet埋め込みが死ぬようになったのでしばらく借りる
公式フォーマットに近づけた
画像はまだよくわからない
script.jsimport {insertText} from '/api/code/takker/scrapbox-insert-text-2/script.js';
import {convertWholeText} from '../scrapbox-embed-tweet/convert.js';
scrapbox.PopupMenu.addButton({
title: text => /https:\/\/twitter\.com\S+\/status\/\d+/.test(text) ?
'X' : // Font Awesomeでないと文字化けします
'',
onClick: text => {
if (!/https:\/\/twitter\.com\S+\/status\/\d+/.test(text)) return; // URLがなければ何もしない
Promise.all(text.split('\n').map(line => {
const matches = line.match(/^\s+|.*/g);
const indent = /^\s+$/.test(matches[0])? matches[0] : '';
const content = /^\s+$/.test(matches[0])? matches[1] : matches[0];
console.log([indent,content]);
return convertWholeText(content, indent)
})).then(lines => insertText(lines.join('\n')));
// 入力しやすいよう選択範囲を先に消しておく
return '';
},
});
convert.jsimport {getTweetInfo} from '/api/code/takker/scrapbox-embed-tweet/getTweetInfo.js';
// 複数のURLを含んだテキストをまとめて変換する
export async function convertWholeText(text,indent) {
const tweetRegExp = /https:\/\/twitter\.com\S+\/status\/\d+(?:\?s=\d+)?/g;
const urls = text.match(tweetRegExp) ?? [];
if (urls.length === 0) return undefined;
const tweets = (await Promise.all(urls.map(url => getTweetInfo({tweetUrl: url}))))
.map(tweetInfo => convert({tweetInfo,indent,}));
console.log(tweets);
let map = {};
for (const originalUrl of urls) {
const i = urls.indexOf(originalUrl);
if (!tweets[i]) break;
map[originalUrl]= tweets[i];
}
//console.log(map);
const result = text.replace(tweetRegExp, match => map[match] ?? match);
//console.log(result);
return result;
}
convert.jsfunction convert({tweetInfo, indent}) {
return [...tweetInfo.content.map((text, i) => {
if(i===0) return `${indent}> [${tweetInfo.author.name} ${tweetInfo.date.href}]: ${text}`
return `> ${text}`
}
)].join('\n');
}