compilar: Portear a Node.js
This commit is contained in:
parent
507c2239f2
commit
c14875b10b
6 changed files with 259 additions and 15 deletions
|
@ -1,13 +1,15 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
build/
|
||||
zig-cache/
|
||||
node_modules/
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
pipeline:
|
||||
build:
|
||||
image: docker.io/alpine:edge
|
||||
image: docker.io/alpine:3.17
|
||||
commands:
|
||||
- echo "172.17.0.1 alpine.proxy.coso" >> /etc/hosts
|
||||
- echo "http://alpine.proxy.coso/alpine/edge/main" > /etc/apk/repositories
|
||||
- echo "http://alpine.proxy.coso/alpine/edge/community" >> /etc/apk/repositories
|
||||
- echo "http://alpine.proxy.coso/alpine/edge/testing" >> /etc/apk/repositories
|
||||
- apk add musl-dev cmark-dev lua5.1 zig gcc
|
||||
- echo "http://alpine.proxy.coso/alpine/v3.17/main" > /etc/apk/repositories
|
||||
- echo "http://alpine.proxy.coso/alpine/v3.17/community" >> /etc/apk/repositories
|
||||
- apk add curl nodejs npm lua5.1
|
||||
- curl -fsSL "https://github.com/pnpm/pnpm/releases/latest/download/pnpm-linuxstatic-x64" -o /bin/pnpm; chmod +x /bin/pnpm
|
||||
|
||||
- pnpm set registry http://npm.proxy.coso
|
||||
- pnpm install
|
||||
- node compilar.js
|
||||
|
||||
- zig run compilar.zig -lc -lcmark
|
||||
deploy:
|
||||
image: docker.io/alpine:3.16
|
||||
commands:
|
||||
- echo "172.17.0.1 alpine.proxy.coso" >> /etc/hosts
|
||||
- echo "http://alpine.proxy.coso/alpine/v3.16/main" > /etc/apk/repositories
|
||||
- echo "http://alpine.proxy.coso/alpine/v3.16/community" >> /etc/apk/repositories
|
||||
- apk add rsync openssh-client-default
|
||||
|
||||
- eval $(ssh-agent -s)
|
||||
|
|
176
compilar.js
Normal file
176
compilar.js
Normal file
|
@ -0,0 +1,176 @@
|
|||
import { copyFile, mkdir, opendir, readFile, writeFile } from "fs/promises";
|
||||
import { basename, extname, join } from "path";
|
||||
import { execFile as execFileCallback } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import * as commonmark from "commonmark";
|
||||
|
||||
const execFile = promisify(execFileCallback);
|
||||
|
||||
const reader = new commonmark.Parser({ smart: true });
|
||||
const writer = new commonmark.HtmlRenderer({ safe: false, smart: true });
|
||||
|
||||
const config = {
|
||||
sourcePath: ".",
|
||||
buildPath: "build",
|
||||
};
|
||||
|
||||
function head(title, outputName) {
|
||||
// TODO: deshardcodear og:url
|
||||
return `<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1.0">
|
||||
<meta name=author content=Nulo>
|
||||
<meta property=og:title content="${title}">
|
||||
<meta property=og:type content=website>
|
||||
<meta property=og:url content="https://nulo.in/${outputName}.html">
|
||||
<meta property=og:image content=cowboy.svg>
|
||||
<link rel=stylesheet href=drip.css>
|
||||
<link rel=icon href=cowboy.svg>
|
||||
<title>${title}</title>
|
||||
`;
|
||||
}
|
||||
|
||||
function header(title, sourceCodePath, linkConexiones = false) {
|
||||
return (
|
||||
`<a href=.>☚ Volver al inicio</a>` +
|
||||
`<header>
|
||||
<h1>${title}</h1>
|
||||
<a href="https://gitea.nulo.in/Nulo/sitio/commits/branch/ANTIFASCISTA/${sourceCodePath}">Historial</a>${
|
||||
linkConexiones
|
||||
? ` /
|
||||
<a href="#conexiones">Conexiones</a>`
|
||||
: ""
|
||||
}
|
||||
</header>`
|
||||
);
|
||||
}
|
||||
const wikilinkExp = /\[\[(.+?)\]\]/giu;
|
||||
|
||||
async function scanForConnections(sourcePath) {
|
||||
const dir = await opendir(sourcePath);
|
||||
let connections = [];
|
||||
for await (const entry of dir) {
|
||||
const extension = extname(entry.name);
|
||||
if (extension === ".md") {
|
||||
const name = basename(entry.name, ".md");
|
||||
const file = await readFile(join(config.sourcePath, entry.name), "utf-8");
|
||||
for (const [, linked] of file.matchAll(wikilinkExp)) {
|
||||
connections.push({ linked, linker: name });
|
||||
}
|
||||
}
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
function hackilyTransformHtml(html) {
|
||||
return html
|
||||
.replaceAll("<a h", '<a rel="noopener noreferrer" h')
|
||||
.replaceAll(wikilinkExp, `<a href="$1.html">$1</a>`);
|
||||
}
|
||||
|
||||
const connections = await scanForConnections(config.sourcePath);
|
||||
|
||||
await mkdir(config.buildPath, { recursive: true });
|
||||
|
||||
const dir = await opendir(config.sourcePath);
|
||||
let pageList = [];
|
||||
let promises = [];
|
||||
for await (const entry of dir) {
|
||||
if (!entry.isFile()) continue;
|
||||
promises.push(compileFile(entry.name));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
await compilePageList(config, pageList);
|
||||
|
||||
async function compileFile(name) {
|
||||
const extension = extname(name);
|
||||
if (
|
||||
[".js", ".md", ".css", ".png", ".jpg", ".mp4", ".svg", ".html"].includes(
|
||||
extension
|
||||
)
|
||||
) {
|
||||
await copyFile(join(config.sourcePath, name), join(config.buildPath, name));
|
||||
}
|
||||
if ([".md", ".gen"].includes(extension)) {
|
||||
pageList.push(basename(name, extension));
|
||||
}
|
||||
|
||||
if (extension === ".md") await compileMarkdown(config, name);
|
||||
else if (extension === ".gen") await compileExecutable(config, name);
|
||||
}
|
||||
|
||||
async function compilePageList(config, pageList) {
|
||||
const name = "Lista de páginas";
|
||||
const outputPath = join(config.buildPath, name + ".html");
|
||||
const html =
|
||||
head(name, name) +
|
||||
header(name, "compilar.js") +
|
||||
`<ul>
|
||||
${pageList
|
||||
.map((name) => `<li><a href="${name}.html">${name}</a></li>`)
|
||||
.join("\n")}
|
||||
</ul>
|
||||
`;
|
||||
await writeFile(outputPath, html);
|
||||
}
|
||||
async function compileMarkdown(config, sourceFileName) {
|
||||
const name = basename(sourceFileName, ".md");
|
||||
const markdown = await readFile(
|
||||
join(config.sourcePath, sourceFileName),
|
||||
"utf-8"
|
||||
);
|
||||
const markdownHtml = renderMarkdown(markdown);
|
||||
|
||||
const fileConnections = connections.filter(({ linked }) => linked === name);
|
||||
|
||||
const isIndex = sourceFileName === "index.md";
|
||||
const title = isIndex ? "nulo.in" : name;
|
||||
const html =
|
||||
head(title, sourceFileName) +
|
||||
(isIndex ? "" : header(title, sourceFileName, fileConnections.length > 0)) +
|
||||
hackilyTransformHtml(markdownHtml) +
|
||||
(fileConnections.length > 0
|
||||
? `
|
||||
<section id=conexiones>
|
||||
<h2>⥆ Conexiones (${fileConnections.length})</h2>
|
||||
<ul>
|
||||
${fileConnections
|
||||
.map(({ linker }) => `<li><a href="${linker}.html">${linker}</a></li>`)
|
||||
.join("\n")}
|
||||
</ul>
|
||||
</section>`
|
||||
: "");
|
||||
|
||||
const outputPath = join(
|
||||
config.buildPath,
|
||||
basename(sourceFileName, ".md") + ".html"
|
||||
);
|
||||
await writeFile(outputPath, html);
|
||||
}
|
||||
|
||||
async function compileExecutable(config, sourceFileName) {
|
||||
const name = basename(sourceFileName, ".gen");
|
||||
|
||||
const { stdout, stderr } = await execFile(
|
||||
"./" + join(config.sourcePath, sourceFileName)
|
||||
);
|
||||
if (stderr.length > 0) console.error(`${sourceFileName} stderr: ${stderr}`);
|
||||
|
||||
const html = head(name, name) + header(name, sourceFileName) + stdout;
|
||||
|
||||
const outputPath = join(
|
||||
config.buildPath,
|
||||
basename(sourceFileName, ".gen") + ".html"
|
||||
);
|
||||
await writeFile(outputPath, html);
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// Markdown utils
|
||||
// ==============================================
|
||||
|
||||
function renderMarkdown(markdown) {
|
||||
const parsed = reader.parse(markdown);
|
||||
return writer.render(parsed);
|
||||
}
|
20
package.json
Normal file
20
package.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "sitio",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/commonmark": "^0.27.5",
|
||||
"@types/node": "^18.11.17"
|
||||
},
|
||||
"dependencies": {
|
||||
"commonmark": "^0.30.0"
|
||||
}
|
||||
}
|
49
pnpm-lock.yaml
Normal file
49
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,49 @@
|
|||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@types/commonmark': ^0.27.5
|
||||
'@types/node': ^18.11.17
|
||||
commonmark: ^0.30.0
|
||||
|
||||
dependencies:
|
||||
commonmark: 0.30.0
|
||||
|
||||
devDependencies:
|
||||
'@types/commonmark': 0.27.5
|
||||
'@types/node': 18.11.17
|
||||
|
||||
packages:
|
||||
|
||||
/@types/commonmark/0.27.5:
|
||||
resolution: {integrity: sha512-vIqgmHyLsc8Or3EWLz6QkhI8/v61FNeH0yxRupA7VqSbA2eFMoHHJAhZSHudplAV89wqg1CKSmShE016ziRXuw==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.11.17:
|
||||
resolution: {integrity: sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==}
|
||||
dev: true
|
||||
|
||||
/commonmark/0.30.0:
|
||||
resolution: {integrity: sha512-j1yoUo4gxPND1JWV9xj5ELih0yMv1iCWDG6eEQIPLSWLxzCXiFoyS7kvB+WwU+tZMf4snwJMMtaubV0laFpiBA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
entities: 2.0.3
|
||||
mdurl: 1.0.1
|
||||
minimist: 1.2.7
|
||||
string.prototype.repeat: 0.2.0
|
||||
dev: false
|
||||
|
||||
/entities/2.0.3:
|
||||
resolution: {integrity: sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==}
|
||||
dev: false
|
||||
|
||||
/mdurl/1.0.1:
|
||||
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
|
||||
dev: false
|
||||
|
||||
/minimist/1.2.7:
|
||||
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
|
||||
dev: false
|
||||
|
||||
/string.prototype.repeat/0.2.0:
|
||||
resolution: {integrity: sha512-1BH+X+1hSthZFW+X+JaUkjkkUPwIlLEMJBLANN3hOob3RhEk5snLWNECDnYbgn/m5c5JV7Ersu1Yubaf+05cIA==}
|
||||
dev: false
|
Reference in a new issue