popupに数式を出してみる
jsimport('/api/code/programming-notes/popupに数式を出してみる/script.js');
2021-05-21 00:49:43 テストのつもりが完成してしまった……
Preact楽すぎだろ
features
[$ ]
内でTeXを打つと、どんな数式になるかpreviewしてくれるよ
こんな感じでE=mc^2
数式にミスが有ると、どこにミスが有るのか教えてくれるよ
{aligned}
とかもちゃんと表示できるよ
\begin{aligned}\int\sin\theta\mathrm{d}\theta=&\int\mathrm{d}(-\cos\theta)\\=&-\cos\theta+C\quad.\mathrm{for}\exist C\in\Bbb{R}\end{aligned}
script.jsimport {html} from '../htm@3.0.4%2Fpreact/script.js';
import {useKaTeX} from '../use-KaTeX/script.js';
import {useState} from '../preact@10.5.13/hooks.js';
import {PopupContainer, CSS} from '../popup-container@0.1.0/script.js';
import register from '../preact-custom-element@4.2.1/script.js';
import {scrapboxDOM} from '../scrapbox-dom-accessor/script.js';
import {useMutationObserver} from '../useMutationObserver/script.js';
import {throttle} from '../custom-throttle/script.js';
const App = ({formula}) => {
const {ref, error, setFormula} = useKaTeX(formula); // 数式rendering用hook
const [open, setOpen] = useState(false); // popupの開閉
const [cursorPosition, setCursorPosition] = useState({
styleTop: 0,
styleLeft: 0,
}); // cursorの位置
// .formula内にcursorが来たらpreviewを開始する
// 負荷低減のために、throttleで少し間引いている
const callback = throttle((mutation) => {
const cursor = mutation.target;
const {top, left} = cursor.getBoundingClientRect();
const elements = document.elementsFromPoint(left, top);
const formulaDOM = elements.find(element => element.matches('.formula'));
if (!formulaDOM) {
setOpen(false);
return;
}
setOpen(true);
setFormula(formulaDOM.textContent.slice(3, -1));
setCursorPosition({
styleTop: +cursor.style.top.slice(0, -2),
styleLeft: +cursor.style.left.slice(0, -2),
});
}, 100);
useMutationObserver([{current: scrapboxDOM.cursor}], ([mutation]) => callback(mutation), {attributes: true});
return html`
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.12.0/katex.min.css" />
<${CSS} />
<style>
.error {color:#fd7373; }
.katex-display {color: #eee;}
</style>
<${PopupContainer} cursorPosition="${cursorPosition}" open="${open}">
${error && html`<span class="error">${error}</span>`}
<span class="katex-display" ref="${ref}" />
<//>
`;
};
register(App, 'userscript-katex-test', ['formula'], {shadow: true});
document.getElementById('editor')
.insertAdjacentHTML('beforeend', '<userscript-katex-test formula="E=mc^2"></userscript-katex-test>');