generated at
meganii

メーカ系SE


script.js
scrapbox.TimeStamp.removeAllFormats() scrapbox.TimeStamp.addFormat('YYYY-MM-DD') scrapbox.TimeStamp.addFormat('YYYY-MM-DD HH:mm:ss')

script.js
await import("/files/659a85f33276650023c439bf.js") console.log()

クリックでON/OFFできるチェックボックス
js
setTimeout(() => { // チェックボックスとして使用する文字のリスト const checkBoxList = ['⬜', '✅']; // const checkBoxList = ['🔲', '☑️']; const textArea = document.getElementById('text-input'); const keydownEvent = { event: document.createEvent('Event'), dispatch: function(keycode, withShift = false, withCommand = false) { this.event.keyCode = keycode; this.event.shiftKey = withShift; this.event.metaKey = withCommand; textArea.dispatchEvent(this.event); } }; keydownEvent.event.initEvent('keydown', true, true); const inputEvent = { event: document.createEvent('Event'), dispatch: function(string) { textArea.value = string; textArea.dispatchEvent(this.event); } }; inputEvent.event.initEvent('input', true, true); const boxHtmlReg = new RegExp('<span class="c-\\d">(' + checkBoxList.join('|') + ')<\/span>'); const startsWithBoxReg = new RegExp('^\\s*(' + checkBoxList.join('|') + ')'); // ボックスクリックでオンオフする $('.lines').off('click.toggleCheckBox'); $('.lines').on('click.toggleCheckBox', ev => { const target = ev.target; if (!isFirstElementChild(target) || !boxHtmlReg.test(target.outerHTML)) return; setTimeout(() => { let lineString; try { lineString = getCursorLineString(); } catch(err) { console.log(err); return; } if (!startsWithBoxReg.test(lineString)) return; const targetX = target.getBoundingClientRect().left; const cursorX = document.getElementsByClassName('cursor')[0].getBoundingClientRect().left; if (cursorX <= targetX) { keydownEvent.dispatch(39); // → } keydownEvent.dispatch(8); // Delete const newBox = (() => { const trimmedLineString = lineString.trim(); for (let i = 0; i < checkBoxList.length; i++) { if (trimmedLineString.startsWith(checkBoxList[i])) { if (i + 1 < checkBoxList.length) { return checkBoxList[i + 1]; } else { return checkBoxList[0]; } } } return checkBoxList[0]; })(); inputEvent.dispatch(newBox); // この下のコメントアウトを解除すると、checked時に取消線を入れて時刻を追記します // Mac、Porterでのみ動作します /* if (/Mobile/.test(navigator.userAgent) || newBox === checkBoxList[0]) return; setTimeout(() => { keydownEvent.dispatch(39, true, true); // shift + command + → inputEvent.dispatch('-'); keydownEvent.dispatch(39, false, true); // command + → const now = moment().format('HH:mm'); inputEvent.dispatch(` ${now}`); }, 50); */ }, 50); }); // ボックス行で改行するとボックス自動配置 $('#text-input').off('keydown.autoInsertCheckBox'); $('#text-input').on('keydown.autoInsertCheckBox', ev => { switch (ev.key) { case 'Enter': let lineString; try { lineString = getCursorLineString(); } catch(err) { console.log(err); return; } if (!startsWithBoxReg.test(lineString)) return; setTimeout(() => { let lineString; try { lineString = getCursorLineString(); } catch(err) { console.log(err); return; } if (startsWithBoxReg.test(lineString)) return; inputEvent.dispatch(checkBoxList[0]); }, 50); return; default: return; } }); function isFirstElementChild(elem) { return elem.parentNode.firstElementChild === elem; } function getCursorLineString() { return document.querySelector('.lines div.line.cursor-line').textContent; } }, 1500);

style.css
.presentation .line.section-title { color: #39ac86; /* green */ }

script.js.old
var O=()=>{let e=document.createElement("style");e.textContent=".bottom-bar{position:fixed;display:flex;flex-direction:column;align-items:flex-end;z-index:300;bottom:0;width:100%}div.status-bar{position:relative}.edit-bar{position:relative;border-top:var(--edit-bar-border);display:grid;grid-auto-flow:row;grid-template-columns:repeat(auto-fill,48px);grid-templete-rows:auto;width:100%;overflow-x:auto;overflow-y:hidden;background-color:#0000001a;--edit-bar-border: 1px solid var(--tool-light-color, #a9aaaf)}.edit-bar>div{border:var(--edit-bar-border);background-color:var(--body-bg, #dcdde0);color:var(--tool-text-color, #666874);font-size:16px;height:34px;line-height:28px;text-align:center;vertical-align:middle;cursor:pointer}.edit-bar>div:first-child{border-top-left-radius:unset}.edit-bar>div:last-child{border-top-right-radius:unset}",document.head.append(e);let t=document.createElement("div");t.classList.add("edit-bar");let n=document.createElement("div");n.classList.add("bottom-bar");let i=document.querySelector(".status-bar");return document.querySelector(".app").append(n),n.append(i),n.append(t),t},R=O(),w=()=>{let e=document.createElement("div");R.append(e);let t;return{render:n=>{e.textContent="",t&&e.removeEventListener("click",t),t=n.onClick,e.classList.add("eb-"+n.name);let i=_(n);i&&(t&&e.addEventListener("click",t),e.append(i))},dispose:()=>e.remove()}},_=e=>{switch(e.type){case"icon":return F(...e.iconClass);case"text":return P(e.text)}},P=e=>{let t=document.createElement("span");return t.classList.add("item"),t.append(e),t},F=(...e)=>{let t=document.createElement("span");return e.join("")!=""&&t.classList.add(...e),t};var u=e=>e==null,l=e=>typeof e=="string",d=e=>typeof e=="number";var y=(e,t)=>{if(!Array.isArray(e))throw new TypeError(`"${t}" must be an array but actual is "${e}"`)};var T=(e,t)=>{if(!(e instanceof HTMLTextAreaElement))throw new TypeError(`"${t}" must be HTMLTextAreaElement but actual is "${e}"`)};var s=()=>{let e=document.getElementById("text-input");if(!!e)return T(e,"textarea#text-input"),e};function U(e){if(u(e))return;if(d(e))return m(e)?.id;if(l(e))return e.startsWith("L")?e.slice(1):e;if(e.classList.contains("line"))return e.id.slice(1);let t=e.closest(".line");if(t)return t.id.slice(1)}function m(e){if(u(e))return;if(d(e))return h()[e];let t=U(e);return t?h().find(n=>n.id===t):void 0}function $(e){return e instanceof HTMLDivElement&&e.classList.contains("line")}function h(){return y(scrapbox.Page.lines,"scrapbox.Page.lines"),scrapbox.Page.lines}function p(e){if(u(e))return;if(d(e)||l(e))return m(e)?.text;if(!(e instanceof HTMLElement))return;if($(e))return m(e)?.text;if(e.classList.contains("char-index"))return e.textContent??void 0;if(e.classList.contains("line")||e.getElementsByClassName("lines")?.[0])return h().map(({text:i})=>i).join(` `);let t=[],n=m(e);if(!u(n)){for(let i of Y(e))t.push(j(i));return n.text.slice(Math.min(...t),Math.max(...t)+1)}}function*Y(e){let t=e.getElementsByClassName("char-index");for(let n=0;n<t.length;n++)yield t[0]}function X(e){return e instanceof HTMLSpanElement&&e.classList.contains("char-index")}function j(e){if(!X(e))throw Error("A char DOM is required.");let t=e.className.match(/c-(\d+)/)?.[1];if(u(t))throw Error('.char-index must have ".c-{\\d}"');return parseInt(t)}function r(e,t){let{noModifiedKeys:n=!1,...i}=t??{},b={bubbles:!0,cancelable:!0,keyCode:V[e],...n?{}:{...i}},x=s();if(!x)throw Error("#text-input must exist.");x.dispatchEvent(new KeyboardEvent("keydown",b)),x.dispatchEvent(new KeyboardEvent("keyup",b))}var V={Backspace:8,Tab:9,Enter:13,Delete:46,Escape:27," ":32,PageUp:33,PageDown:34,End:35,Home:36,ArrowLeft:37,ArrowUp:38,ArrowRight:39,ArrowDown:40,a:65,A:65,b:66,B:66,c:67,C:67,d:68,D:68,e:69,E:69,f:70,F:70,g:71,G:71,h:72,H:72,i:73,I:73,j:74,J:74,k:75,K:75,l:76,L:76,m:77,M:77,n:78,N:78,o:79,O:79,p:80,P:80,q:81,Q:81,r:82,R:82,s:83,S:83,t:84,T:84,u:85,U:85,v:86,V:86,w:87,W:87,x:88,X:88,y:89,Y:89,z:90,Z:90,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,F1:113,F2:114,F3:115,F4:116,F5:117,F6:118,F7:119,F8:120,F9:121,F10:122,F11:123,F12:124,":":186,"*":186,";":187,"+":187,"-":189,"=":189,".":190,">":190,"/":191,"?":191,"@":192,"`":192,"[":219,"{":219,"\\":220,"|":220,"]":221,"}":221,"^":222,"~":222,_:226};var E=e=>new Promise(t=>setTimeout(()=>t(),e));function a(){let e=s();if(!e)throw Error("#text-input is not found.");let t=Object.keys(e).find(n=>n.startsWith("__reactFiber"));if(!t)throw Error('div.cursor must has the property whose name starts with "__reactFiber"');return e[t].return.return.stateNode.props}function*o(e,t){for(let n=e;n<t;n++)yield n}function L(e=1){for(let t of o(0,e))r("z",{ctrlKey:!0})}function k(e=1){for(let t of o(0,e))r("z",{shiftKey:!0,ctrlKey:!0})}function M(e=1){for(let t of o(0,e))r("ArrowRight",{ctrlKey:!0})}function v(e=1){for(let t of o(0,e))r("ArrowLeft",{ctrlKey:!0})}function H(e=1){for(let t of o(0,e))r("ArrowUp",{ctrlKey:!0})}function C(e=1){for(let t of o(0,e))r("ArrowDown",{ctrlKey:!0})}function I(e=1){for(let t of o(0,e))r("ArrowRight",{altKey:!0})}function B(e=1){for(let t of o(0,e))r("ArrowLeft",{altKey:!0})}function D(e=1){for(let t of o(0,e))r("ArrowUp",{altKey:!0})}function A(e=1){for(let t of o(0,e))r("ArrowDown",{altKey:!0})}async function K(e){let t=s();if(!t)throw Error("#text-input is not ditected.");t.focus(),t.value=e;let n=new InputEvent("input",{bubbles:!0});t.dispatchEvent(n),await E(1)}var f=()=>{let e=s();if(!e)throw Error("#text-input is not found.");let t=Object.keys(e).find(n=>n.startsWith("__reactFiber"));if(!t)throw Error('#text-input must has the property whose name starts with "__reactFiber"');return e[t].return.return.stateNode._stores};var S=()=>{for(let e of f())if("goByAction"in e)return e;throw Error('#text-input must has a "Cursor" store.')};var N=()=>{for(let e of f())if("hasSelection"in e)return e;throw Error('#text-input must has a "Selection" store.')};function q(e){switch(e){case"spinner":return["fa","fa-spinner"];case"check-circle":return["kamon","kamon-check-circle"];case"exclamation-triangle":case"caret-up":case"caret-down":case"caret-left":case"caret-right":case"cut":case"expand":case"i-cursor":case"undo":case"redo":return["fas",`fa-${e}`];case"copy":case"clipboard":return["far",`fa-${e}`];default:return[""]}}var g=N(),c=S(),J=[{name:"caret-left",onClick:()=>{c.focus(),a().selectedText===""?B():v()}},{name:"caret-right",onClick:()=>{c.focus(),a().selectedText===""?I():M()}},{name:"caret-up",onClick:()=>{c.focus(),a().selectedText===""?D():H()}},{name:"caret-down",onClick:()=>{c.focus(),a().selectedText===""?A():C()}},{name:"copy",onClick:async()=>{try{let{position:e,selectedText:t}=a(),n=t||p(e.line);if(!n)return;await navigator.clipboard.writeText(n)}catch(e){console.error(e),alert(`Faild to copy:${JSON.stringify(e)}`)}}},{name:"cut",onClick:async()=>{try{let e=g.hasSelection(),t=g.getRange().start.line,n=e?g.getSelectedText():p(t);if(!n)return;await navigator.clipboard.writeText(n),e||g.setRange({start:{line:t,char:0},end:{line:t,char:n.length}}),c.focus(),r("Delete")}catch(e){console.error(e),alert(`Faild to cut:${JSON.stringify(e)}`)}}},{name:"clipboard",onClick:async()=>{try{let e=await navigator.clipboard.readText();if(!e)return;c.focus(),await K(e)}catch(e){console.error(e),alert(`Faild to paste:${JSON.stringify(e)}`)}}},{name:"undo",onClick:()=>L()},{name:"redo",onClick:()=>k()},{name:"i-cursor",onClick:()=>{c.getVisible()&&c.hide()}}];if(/mobile/i.test(navigator.userAgent))for(let{name:e,onClick:t}of J){let{render:n}=w();n({type:"icon",name:e,iconClass:q(e),onClick:t})}