ScrapLua
code:template
ScrapLua
code:script.js
@CODE@
code:script.js
import fengari from "npm:fengari-web";
let calcLastExpr = null;
let calcLastResult = [];
const statusDomParent = document.createElement("div");
document.querySelector(".status-bar").appendChild(statusDomParent);
const statusDom = document.createElement("button");
const styleElem = document.createElement("style");
statusDom.type = "button";
statusDomParent.appendChild(statusDom);
statusDomParent.appendChild(styleElem);
statusDom.innerText = "ScrapLua:計算中...";
function scrapcalc_render() {
document
.querySelectorAll(
)
.forEach((e, i) => {
let span = document.createElement("span");
span.classList.add("scrapcalc_result");
span.classList.add("scraplua_result");
span.innerText = calcLastResulti; if (e.classList.contains("line")) {
let id = true;
let cbend = e;
while (id) {
const elem = cbend.nextSibling;
if (elem.querySelector(".code-block")) {
cbend = elem;
} else {
id = false;
}
}
cbend.appendChild(span);
} else {
e.parentNode.appendChild(span);
}
});
}
function scrapcalc_calc() {
const lua_state = fengari.lauxlib.luaL_newstate();
fengari.lualib.luaL_openlibs(lua_state);
globalThis.ScrapLuaResults = "";
fengari.lua.lua_pushcfunction(lua_state, function (lua_state) {
const nargs = fengari.lua.lua_gettop(lua_state);
for (let i = 1; i <= nargs; i++) {
if (i > 1) globalThis.ScrapLuaResults += "\t"; // 引数間にタブを追加
const t = fengari.lua.lua_type(lua_state, i);
switch (t) {
case fengari.lua.LUA_TSTRING:
case fengari.lua.LUA_TNUMBER:
globalThis.ScrapLuaResults += fengari.to_jsstring(
fengari.lua.lua_tostring(lua_state, i),
);
break;
case fengari.lua.LUA_TBOOLEAN:
globalThis.ScrapLuaResults += fengari.lua.lua_toboolean(
lua_state,
i,
)
? "true"
: "false";
break;
default:
globalThis.ScrapLuaResults += fengari.to_jsstring(fengari.lua.lua_typename(
lua_state,
t,
));
}
}
globalThis.ScrapLuaResults += "\n"; // 改行を追加
return 0;
});
fengari.lua.lua_setglobal(lua_state, "print");
calcLastResult = [];
for (const cbstart of document.querySelectorAll(
)) {
let text = "";
let cbend = cbstart;
if (cbstart.classList.contains("line")) {
let id = true;
while (id) {
const elem = cbend.nextSibling;
if (elem.querySelector(".code-block")) {
text += elem.querySelector(".code-block").innerText;
cbend = elem;
} else {
id = false;
}
}
} else {
text = cbstart.innerText
.replaceAll("[", "[")
.replaceAll("]", "]");
if (text.startsWith("[")) {
text = text.slice(4, -1);
}
}
globalThis.ScrapLuaResults = "";
console.log("lua run",text);
const calcerror = fengari.lauxlib.luaL_dostring(
lua_state,
fengari.to_luastring(text),
);
if (calcerror) {
calcLastResult.push("Error:" +
fengari.to_jsstring(
fengari.lua.lua_tostring(
lua_state,
fengari.lua.lua_gettop(lua_state),
),
));
fengari.lua.lua_settop(lua_state, 1);
} else {
if (globalThis.ScrapLuaResults == "") {
calcLastResult.push("No Output");
} else {
calcLastResult.push(
"Output:" + globalThis.ScrapLuaResults.trim(),
);
}
}
}
}
// force = "auto" | "cache" | "calc"
function scrapcalc_reload(force = "auto") {
for (let e of document.querySelectorAll(".scraplua_result")) {
e.remove();
}
if(force == "cache"){
scrapcalc_render();
return;
}
const calcExpr = Array.from(
document.querySelectorAll(
),
)
.map((cbstart) => {
let text = "";
let cbend = cbstart;
if (cbstart.classList.contains("line")) {
let id = true;
while (id) {
const elem = cbend.nextSibling;
if (elem.querySelector(".code-block")) {
text += elem.querySelector(".code-block").innerText;
cbend = elem;
} else {
id = false;
}
}
} else {
text = cbstart.innerText
.replaceAll("[", "[")
.replaceAll("]", "]");
if (text.startsWith("[")) {
text = text.slice(4, -1);
}
}
return text;
})
.join("\n");
if (calcLastExpr == calcExpr && force == "auto") {
scrapcalc_render();
} else {
styleElem.innerText = "*{cursor:wait !important;}";
statusDom.innerText = ScrapLua:計算中...;
setTimeout(()=>{
const start = Date.now();
calcLastExpr = calcExpr;
scrapcalc_calc();
styleElem.innerText = "";
scrapcalc_render();
statusDom.innerText = ScrapLua:${(Date.now() - start).toFixed()}ms;
},100)
}
}
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
scrapbox.on("page:changed", ()=>{scrapcalc_reload("calc");});
scrapbox.on("layout:changed", ()=>{scrapcalc_reload("calc");});
scrapbox.on("lines:changed", debounce(()=>{scrapcalc_reload();},1000));
statusDom.addEventListener("click",()=>{
styleElem.innerText = "*{cursor:wait !important;}";
scrapcalc_reload("calc");
});
function autoreload(){
// 計算結果のある行にカーソルを移動し、さらにほかの行にカーソルを移動すると計算結果が消えることの対処
if (
document.querySelectorAll(
).length != document.querySelectorAll(".scraplua_result").length
) {
scrapcalc_reload("cache");
}
window.requestAnimationFrame(autoreload);
}
scrapcalc_reload("calc");
window.requestAnimationFrame(autoreload);