tweetの埋め込みのフォーマットを変更するscript
scrapbox標準のフォーマットはこんな感じ:
@discord: stay warm this holiday season with the gift of baked beans https://pbs.twimg.com/media/Fkmcw75WAAEHHvz.jpg
format.jsに使える文字
url
tweetのURL
screenName
tweetのユーザーの表示名
userName
tweetのユーザーのID名
使えなくなってましたwogikaze.icon
description
tweet内容
images
画像
PopupMenuに追加される(twitterのリンク以外の時は非表示になってます)
公式のTweetのフォーマット
code:format.js
export const format = [
].join("\n")
code:import.ts
import { format } from "./format.js"
const condition = /https:\/\/twitter\.com\/.*?\/status\/\d+/;
scrapbox.PopupMenu.addButton({
title: (text) => text.split("\n").some(
(line) => condition.test(line.trim())
) ? 'Embed Tweet' : "",
onClick: urltext => {
Promise.all(urltext.split('\n').map(line => {
if (!condition.test(line.trim())) return line
var tweetlink = line.match(condition);
var indent = /\s+/.test(line) ? line.match(/\s+/) : "";
console.log(line)
return getTweetInfo(tweetlink).then(res => indent + format.replace("url", line.trim())
.replace("screenName", res.value.screenName)
.replace("userName", res.value.userName)
.replace("description", res.value.description.replace(/\n/g, \n>))
.replace("images", res.value.images.join("]["))
.replace(/\n/g,\n${indent})
.replace(/\n.*?\\/g,"") /*何か+[]のみの行を削除*/ )
})).then(lines => insertText(lines.join('\n')));
return "" // 空白にしておく
}
});
テスト用jsコード
code:test.js
2個リンクがあったとき、空白があったときに対応できてない
画像がないときに>[]を削除する
自分用format&code
code:format-yuyasurarin.js
export const format = [
].join("\n")
code:script.js
var u=e=>{let{fetch:t=globalThis.fetch,hostName:r="scrapbox.io",...o}=e;return{fetch:t,hostName:r,...o}};var d=class extends Error{constructor(t){super(${t.status} ${t.statusText} when fetching ${t.path.toString()});this.name="UnexpectedResponseError";this.status=t.status,this.statusText=t.statusText,this.body=t.body,this.path=t.path,Error.captureStackTrace&&Error.captureStackTrace(this,d)}};var T=async e=>{let{sid:t,hostName:r,fetch:o}=u(e??{}),n=https://${r}/api/users/me,s=await o(n,t?{headers:{Cookie:l(t)}}:void 0);if(!s.ok)throw new d({path:new URL(n),...s,body:await s.text()});return await s.json()};var l=e=>connect.sid=${e},y=async e=>window._csrf?window._csrf:(await T(e)).csrfToken;var W=e=>typeof e=="object"&&e!==null,G=e=>W(e)?(e.name===void 0||typeof e.name=="string")&&typeof e.message=="string":!1,f=e=>{try{let t=typeof e=="string"?JSON.parse(e):e;return G(t)?t:!1}catch(t){if(t instanceof SyntaxError)return!1;throw t}};var R=async(e,t)=>{let{sid:r,hostName:o,fetch:n,csrf:s}=u(t??{}),i=https://${o}/api/embed-text/twitter?url=${encodeURIComponent(e.toString())},c=await n(i,{method:"POST",headers:{"Content-Type":"application/json;charset=utf-8","X-CSRF-TOKEN":s??await y(t),...r?{Cookie:l(r)}:{}},body:JSON.stringify({timeout:3e3})});if(!c.ok){if(c.status===422)return{ok:!1,value:{name:"InvalidURLError",message:(await c.json()).message}};let g=await c.text(),h=f(g);if(!h)throw new d({path:new URL(i),...c,body:g});return{ok:!1,value:h}}let m=await c.json();return{ok:!0,value:m}};var O=(e,t)=>{if(!(e instanceof HTMLTextAreaElement))throw new TypeError("${t}" must be HTMLTextAreaElement but actual is "${e}")};var E=()=>{let e=document.getElementById("text-input");if(!!e)return O(e,"textarea#text-input"),e};var I=e=>new Promise(t=>setTimeout(()=>t(),e));var U=async e=>{let t=E();if(!t)throw Error("#text-input is not ditected.");t.focus(),t.value=e;let r=new InputEvent("input",{bubbles:!0});t.dispatchEvent(r),await I(1)};var Kn=new Map;var a=(e,{parseOnNested:t,parseOnQuoted:r,patterns:o})=>(n,s,i)=>{var c,m,g,h,k,L;if(!t&&s.nested)return(c=i?.())!==null&&c!==void 0?c:[];if(!r&&s.quoted)return(m=i?.())!==null&&m!==void 0?m:[];for(let _ of o){let w=_.exec(n);if(w===null)continue;let K=n.substring(0,w.index),q=n.substring(w.index+((h=(g=w0)===null||g===void 0?void 0:g.length)!==null&&h!==void 0?h:0)),z=e((k=w0)!==null&&k!==void 0?k:"",s);return...x(K,s),...z,...x(q,s)}return(L=i?.())!==null&&L!==void 0?L:[]},p=e=>{type:"plain",raw:e,text:e},ee=a(p,{parseOnNested:!0,parseOnQuoted:!0,patterns:/^()(.*)()$/}),te=/^>.*$/,re=(e,t)=>t.context==="table"?p(e,t):{type:"quote",raw:e,nodes:x(e.substring(1),{...t,quoted:!0})},oe=a(re,{parseOnNested:!1,parseOnQuoted:!1,patterns:te}),ne=/^\? .+$/,se=(e,t)=>t.context==="table"?p(e,t):{type:"helpfeel",raw:e,text:e.substring(2)},ie=a(se,{parseOnNested:!1,parseOnQuoted:!1,patterns:ne}),ae=/\[\[https?:\/\/^\s\]+\.(?:png|jpe?g|gif|svg)\]\]/i,ce=/\[\[https?:\/\/(?:0-9a-z-+\.)?gyazo\.com\/0-9a-f{32}\]\]/,pe=(e,t)=>{if(t.context==="table")return p(e,t);let r=e.substring(2,e.length-2),o=/^https?:\/\/(0-9a-z-\.)?gyazo\.com\/0-9a-f{32}$/.test(r);return[{type:"strongImage",raw:e,src:o?${r}/thumb/1000:r}]},de=a(pe,{parseOnNested:!1,parseOnQuoted:!0,patterns:ae,ce}),ue=/\^[\*\.icon(?:\*1-9\d*)?\]/;function j(e){return(t,r)=>{if(e==="strongIcon"&&r.context==="table")return p(t,r);let o=e==="icon"?t.substring(1,t.length-1):t.substring(2,t.length-2),n=o.lastIndexOf(".icon"),s=o.substring(0,n),i=s.startsWith("/")?"root":"relative",c=o.substring(n+5,o.length),m=c.startsWith("*")?parseInt(c.substring(1),10):1;return new Array(m).fill({}).map(()=>({path:s,pathType:i,type:e,raw:t}))}}var le=j("icon"),me=a(le,{parseOnNested:!0,parseOnQuoted:!0,patterns:ue}),fe=/\[\^[\*\.icon(?:\*\d+)?\]\]/,ge=j("strongIcon"),he=a(ge,{parseOnNested:!1,parseOnQuoted:!0,patterns:fe}),xe=/\[\[(?:[^[]|\^[]).*?\]*\]\]/,we=(e,t)=>t.context==="table"?p(e,t):{type:"strong",raw:e,nodes:x(e.substring(2,e.length-2),{...t,nested:!0})},ye=a(we,{parseOnNested:!1,parseOnQuoted:!0,patterns:xe}),Ee=/\\$ .+? \/,be=/\[\$ [^\+\]/,ve=(e,t)=>t.context==="table"?p(e,t):{type:"formula",raw:e,formula:e.substring(3,e.length-(e.endsWith(" ")?2:1))}],ke=a(ve,{parseOnNested:!1,parseOnQuoted:!0,patterns:Ee,be}),Le=/\!"#%&'()*+,\-./{|}<>_~]+ (?:\[[^[\+\]|^\])+\]/,Te=(e,t)=>{if(t.context==="table")return p(e,t);let r=e.indexOf(" "),o=e.substring(1,r),n=e.substring(r+1,e.length-1),s=new Set(o);if(s.has("*")){let i=o.split("*").length-1;s.delete("*"),s.add(*-${Math.min(i,10)})}return{type:"decoration",raw:e,rawDecos:o,decos:Array.from(s),nodes:x(n,{...t,nested:!0})}},Ie=a(Te,{parseOnNested:!1,parseOnQuoted:!0,patterns:Le}),Ne=/.*?/,Pe=(e,t)=>t.context==="table"?p(e,t):{type:"code",raw:e,text:e.substring(1,e.length-1)},Me=a(Pe,{parseOnNested:!1,parseOnQuoted:!0,patterns:Ne}),Se=/^$% .+$/,Ce=(e,t)=>{var r;if(t.context==="table")return p(e,t);let o=(r=e0)!==null&&r!==void 0?r:"",n=e.substring(2);return{type:"commandLine",raw:e,symbol:o,text:n}},Re=a(Ce,{parseOnNested:!1,parseOnQuoted:!1,patterns:Se}),Oe=/\\s+\/,De=(e,t)=>t.context==="table"?p(e,t):{type:"blank",raw:e,text:e.substring(1,e.length-1)},Ue=a(De,{parseOnNested:!1,parseOnQuoted:!0,patterns:Oe}),je=/\[https?:\/\/^\s\]+\.(?:png|jpe?g|gif|svg)(?:\?^\\s]+)?(?:\s+https?:\/\/^\s\]+)?\]/i,He=/\[https?:\/\/^\s\]+\s+https?:\/\/^\s\]+\.(?:png|jpe?g|gif|svg)(?:\?^\\s]+)?\]/i,$e=/\[https?:\/\/(?:0-9a-z-+\.)?gyazo\.com\/0-9a-f{32}(?:\/raw)?(?:\s+https?:\/\/^\s\]+)?\]/,Be=/\[https?:\/\/^\s\]+\s+https?:\/\/(?:0-9a-z-+\.)?gyazo\.com\/0-9a-f{32}(?:\/raw)?\]/,Fe=e=>/^https?:\/\/^\s\]+\.(png|jpe?g|gif|svg)(\?^\\s]+)?$/i.test(e)||Ae(e),Ae=e=>/^https?:\/\/(0-9a-z-\.)?gyazo\.com\/0-9a-f{32}(\/raw)?$/.test(e),_e=(e,t)=>{if(t.context==="table")return p(e,t);let r=e.search(/\s/),o=r!==-1?e.substring(1,r):e.substring(1,e.length-1),n=r!==-1?e.substring(r,e.length-1).trimLeft():"",s,i=Fe(n)?n,o:o,n;return[{type:"image",raw:e,src:/^https?:\/\/(0-9a-z-\.)?gyazo\.com\/0-9a-f{32}$/.test(s)?${s}/thumb/1000:s,link:i}]},Ke=a(_e,{parseOnNested:!0,parseOnQuoted:!0,patterns:je,He,$e,Be}),qe=/\[https?:\/\/^\s\]+\s+^\]*^\s\]/,ze=/\^[\*^\s\s+https?:\/\/^\s\]+\]/,We=/\[https?:\/\/^\s\]+\]/,Ge=/https?:\/\/^\s+/,Qe=(e,t)=>{if(t.context==="table")return p(e,t);let r=e.startsWith("")&&e.endsWith("")?e.substring(1,e.length-1):e,o=/^https?:\/\/^\s\]/.test(r),n=(o?/^https?:\/\/^\s\]+/:/https?:\/\/^\s\]+$/).exec(r);if(n?.0===void 0)return[];let s=o?r.substring(n0.length):r.substring(0,n.index-1);return[{type:"link",raw:e,pathType:"absolute",href:n0,content:s.trim()}]},Ye=a(Qe,{parseOnNested:!0,parseOnQuoted:!0,patterns:qe,ze,We,Ge}),H=/\[(^\]*^\s)\s+(NS\d+(?:\.\d+)?,EW\d+(?:\.\d+)?(?:,Z\d+)?)\]/,$=/\[(NS\d+(?:\.\d+)?,EW\d+(?:\.\d+)?(?:,Z\d+)?)(?:\s+(^\]*^\s))?\]/,Xe=e=>{lett="",r="",o=""=e.split(","),n=parseFloat(t.replace(/^N/,"").replace(/^S/,"-")),s=parseFloat(r.replace(/^E/,"").replace(/^W/,"-")),i=/^Z\d+$/.test(o)?parseInt(o.replace(/^Z/,""),10):14;return{latitude:n,longitude:s,zoom:i}},Je=(e,t)=>{var r;if(t.context==="table")return p(e,t);let o=(r=e.match(H))!==null&&r!==void 0?r:e.match($);if(o===null)return[];let n=e.startsWith("[N")||e.startsWith("[S"),,s="",i=""=n?o:[o0,o2,o1],{latitude:c,longitude:m,zoom:g}=Xe(s),h=i!==""?https://www.google.com/maps/place/${encodeURIComponent(i)}/@${c},${m},${g}z:https://www.google.com/maps/@${c},${m},${g}z;return{type:"googleMap",raw:e,latitude:c,longitude:m,zoom:g,place:i,url:h}},Ve=a(Je,{parseOnNested:!1,parseOnQuoted:!0,patterns:H,$}),Ze=/\[\/?[^\]+\]/,et=e=>{let t=e.substring(1,e.length-1);return{type:"link",raw:e,pathType:t.startsWith("/")?"root":"relative",href:t,content:""}},tt=a(et,{parseOnNested:!0,parseOnQuoted:!0,patterns:Ze}),rt=/(?:^|\s)#\S+/,ot=(e,t)=>{if(t.context==="table")return p(e,t);if(e.startsWith("#"))return{type:"hashTag",raw:e,href:e.substring(1)};let r=e.substring(0,1),o=e.substring(1);return...p(r,t),{type:"hashTag",raw:o,href:o.substring(1)}},nt=a(ot,{parseOnNested:!0,parseOnQuoted:!0,patterns:rt}),st=/^0-9+\. .*$/,it=(e,t)=>{if(t.context==="table")return p(e,t);let r=e.indexOf(" "),o=e.substring(0,r-1),n=parseInt(o,10),s=e.substring(r+1,e.length);return{type:"numberList",raw:e,rawNumber:o,number:n,nodes:x(s,{...t,nested:!0})}},at=a(it,{parseOnNested:!1,parseOnQuoted:!1,patterns:st}),ct=(e,t,r)=>{var o;return e===""?[]:(o=r?.())!==null&&o!==void 0?o:[]},pt=(...e)=>(t,r)=>e.reduceRight((o,n)=>()=>n(t,r,o),()=>ee(t,r))(),x=pt(ct,oe,ie,Me,Re,ke,Ue,Ie,de,he,ye,Ke,Ye,me,Ve,tt,nt,at);var A=[">description url screenName",">images"].join(\n);var C=/https:\/\/twitter\.com\/.*?\/status\/\d+/;scrapbox.PopupMenu.addButton({title:e=>e.split(\n).some(t=>C.test(t.trim()))?"Embed Tweet":"",onClick:e=>(Promise.all(e.split(\n).map(t=>{if(!C.test(t.trim()))return t;var r=t.match(C),o=/\s+/.test(t)?t.match(/\s+/):"";return console.log(t),R(r).then(n=>o+A.replace("url",t.trim()).replace("screenName",n.value.screenName).replace("userName",n.value.userName).replace("description",n.value.description.replace(/\n/g,\n>)).replace("images",n.value.images.join("][")).replace(/\n/g,\n${o}).replace(/\n.*?\\/g,""))})).then(t=>U(t.join(\n))),"")});