UNPKG

secst

Version:

SECST is a semantic, extensible, computational, styleable tagged markup language. You can use it to joyfully create compelling, interactive documents backed by HTML.

180 lines (163 loc) 6.37 kB
import fs from "fs/promises"; import url from "node:url"; import toArrayBuffer from "./src/to-array-buffer.js"; import { dirname } from 'path'; import { fileURLToPath } from 'url'; let __dirname = dirname(fileURLToPath(new URL(import.meta.url))).replace(/.*:/g,"").replace(/\\/g,"/"); console.log(__dirname) import JSON5 from "json5"; global.JSON5 = JSON5; import {init as initAutohelm,engage} from "@anywhichway/autohelm"; global.autohelm = { init: initAutohelm, engage } import {HighlightJS} from "highlight.js"; global.HighlightJS = HighlightJS; import { Window } from 'happy-dom'; global.window = new Window(), global.document = window.document; global.URL = URL; global.fetch = async (url,...args) => { if(url.startsWith(".")) { const mimeTypes = { png: "image/png", jpg: "image/jpg", gif: "image/gif", html: "text/html", htm: "text/plain", txt: "text/plain", css: "text/css" }, ext = (new URL(url,document.baseURI)).pathname.split(".").pop(), type = mimeTypes[ext] || "", data = await fs.readFile(url); return { status: 200, text() { return data.toString("utf-8") }, blob() { return { size: data.length, type, arrayBuffer() { return toArrayBuffer(data) } } } } } /*try { const response = await window.fetch((new URL(url,"http://localhost:63342/secst/")).href,...args); if(response.status===200) { return response; } } catch(e) { } return window.fetch((new URL(url, "https://sects.org/")).href,...args);*/ return window.fetch(url,...args); } global.Text = window.Text; global.MutationObserver = window.MutationObserver; global.DOMParser = window.DOMParser; global.FileReader = window.FileReader; global.Node = window.Node; Object.defineProperty(global.document,"baseURI",{configurable:true,writable:true,value:"http://localhost:63342/secst/"}); import * as all from "emoji-mart"; let { init, SearchIndex } = all; if(init==null) { init = all.default.init; SearchIndex = all.default.SearchIndex; } global.emojiMart = { init, SearchIndex } import toTagSpecs from "./src/to-tag-specs.js"; import resolveDataTemplate from "./src/resolve-data-template.js"; global.SECST = { resolveDataTemplate, tagSpecs: await (async () => { const {allTags} = await import("./src/tags/all-tags.js"); const specs = await toTagSpecs(allTags); //console.log(JSON.stringify(specs)) return await toTagSpecs(allTags); })() } import peg from "pegjs"; import {resolve} from "./src/resolve.js"; const globWithCallback = (await import("glob")).default, glob = async (pattern) => { return new Promise((resolve,reject) => { globWithCallback(pattern,(error,files) => { if(error) { reject(error) } else { resolve(files); } }) }) }; async function getPaths(target) { async function* _getPaths(path = `./`) { const entries = await fs.readdir(path, { withFileTypes: true }) for (let file of entries) { if (file.isDirectory()) { const fname = `${path}${file.name}/`; yield fname; yield* _getPaths(fname) } else { yield path + file.name; } } } const paths = []; for await(const path of _getPaths(target)) { paths.push(path); } return paths; } // this will work for file conversions at the moment, but SPD generation will require rework as a recursive function const {transform} = await import(__dirname + "/src/transform.js"), grammar = await fs.readFile(__dirname + "/src/secst.peg",{ encoding: 'utf8' }), runtime = await fs.readFile(__dirname + "/runtime.js",{encoding: 'utf8'}), parser = peg.generate(grammar); let [_,path,target="*.sct",...args] = process.argv; let isdir; try { isdir = (await fs.lstat(target)).isDirectory() } catch(e) { }; const paths = isdir ? await getPaths(target.endsWith("/") ? target : target + "/") : await glob(target); let spd = ""; for(const path of paths) { if(path.endsWith(".sct")) { const parts = path.split("."), level = path.split("/").length, text = await fs.readFile(path,{ encoding: 'utf8' }), section = isdir ? `:section({level:${level}})[${text}]` : text; spd += section + "\n"; const {dom,errors,parsed,transformed} = await transform(parser,section,{styleAllowed:true}); //dom.head.appendChild(script); await resolve(dom.body); parts.pop(); const fname = parts.join("."); await fs.writeFile(fname + ".html",`<!DOCTYPE html><html><head>${dom.head.innerHTML+document.head.innerHTML}<script async type="application/javascript">${runtime}</script></head><body>${dom.body.innerHTML}</body></html>`,{ encoding: 'utf8' }) if(args.includes("--writeAsTxt")) { await fs.writeFile(fname + ".txt",section,{ encoding: 'utf8' }) } console.log(errors); } } if(isdir) { const fname = target.endsWith("/") ? target.substring(0,target.length-1) : target; if(args.includes("--writeRootAsSCT")) { await fs.writeFile(fname + ".sct",spd,{encoding: 'utf8'} ); } if(args.includes("--writeRootAsTxt")) { await fs.writeFile(fname + ".txt",spd,{encoding: 'utf8'} ); } if(args.includes("--writeRootAsHTML")) { const {dom,errors,parsed,transformed} = await transform(parser,spd,{styleAllowed:"*"}); await resolve(dom.body); await fs.writeFile(fname + ".html",`<!DOCTYPE html><html><head>${dom.head.innerHTML}<script async type="application/javascript">${runtime}</script></head><body>${dom.body.innerHTML}</body></html>`,{ encoding: 'utf8' }) } }