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
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = tab
|
|
||||||
tab_width = 4
|
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 4
|
||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
||||||
build/
|
build/
|
||||||
zig-cache/
|
node_modules/
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
pipeline:
|
pipeline:
|
||||||
build:
|
build:
|
||||||
image: docker.io/alpine:edge
|
image: docker.io/alpine:3.17
|
||||||
commands:
|
commands:
|
||||||
- echo "172.17.0.1 alpine.proxy.coso" >> /etc/hosts
|
- 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/v3.17/main" > /etc/apk/repositories
|
||||||
- echo "http://alpine.proxy.coso/alpine/edge/community" >> /etc/apk/repositories
|
- echo "http://alpine.proxy.coso/alpine/v3.17/community" >> /etc/apk/repositories
|
||||||
- echo "http://alpine.proxy.coso/alpine/edge/testing" >> /etc/apk/repositories
|
- apk add curl nodejs npm lua5.1
|
||||||
- apk add musl-dev cmark-dev lua5.1 zig gcc
|
- 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
|
- apk add rsync openssh-client-default
|
||||||
|
|
||||||
- eval $(ssh-agent -s)
|
- 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