Reemplazar script de compilación con script en Zig
Squashed commit of the following: commitea51959ee8
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:56:30 2022 -0300 ci: Usar gcc No funciona con clang ya que no provee `cc` commitc152c8ec9f
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:54:27 2022 -0300 ci: Instalar clang Zig necesita un compilador de C para encontrar las librerías C commit0f360aaa10
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:52:42 2022 -0300 ci: No instalar cmark de terminal, instalar musl-dev commit24da2c684e
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:43:04 2022 -0300 ci: Agregar repo testing commit2163a9f71e
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:40:10 2022 -0300 ci: Usar edge para usar testing/zig commit259fad54e5
Author: Nulo <git@nulo.in> Date: Sat Jul 16 21:07:22 2022 -0300 Reemplazar script de compilación con script en Zig
This commit is contained in:
parent
76f9c2ff26
commit
b60e5850cf
5 changed files with 235 additions and 68 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
build/
|
build/
|
||||||
|
zig-cache/
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
pipeline:
|
pipeline:
|
||||||
build:
|
build:
|
||||||
image: docker.io/alpine:3.16
|
image: docker.io/alpine:edge
|
||||||
commands:
|
commands:
|
||||||
- apk add cmark git cmd:setup-timezone lua5.1
|
- echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
|
||||||
# Para generar las fechas bien
|
- apk add musl-dev cmark-dev lua5.1 zig gcc
|
||||||
- setup-timezone -z America/Argentina/Buenos_Aires
|
- zig run compilar.zig -lc -lcmark
|
||||||
- base_uri=https://nulo.in/ ./build.sh
|
|
||||||
deploy:
|
deploy:
|
||||||
image: docker.io/alpine:3.14
|
image: docker.io/alpine:3.14
|
||||||
commands:
|
commands:
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
Este es el README para [el repositorio del sitio](https://gitea.nulo.in/Nulo/sitio).
|
Este es el README para [el repositorio del sitio](https://gitea.nulo.in/Nulo/sitio).
|
||||||
|
|
||||||
Escuché [HOT DEMON B!TCHES NEAR U ! ! ! (de CORPSE y Night Lovell)](https://youtu.be/wqZnO71PBis) en loop para hacer la versión inicial del sitio.
|
## Compilar
|
||||||
|
|
||||||
|
Require [Zig](https://ziglang.org), shell, cmark (con cmark-dev) y Lua 5.1.
|
||||||
|
|
||||||
|
```
|
||||||
|
zig run compilar.zig -lc -lcmark
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
62
build.sh
62
build.sh
|
@ -1,62 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
template () {
|
|
||||||
echo "<!doctype html>"
|
|
||||||
echo "<meta charset=utf-8>"
|
|
||||||
echo "<meta name=viewport content='width=device-width, initial-scale=1.0'>"
|
|
||||||
echo "<meta name=author content=Nulo>"
|
|
||||||
echo "<meta property=og:title content='$1'>"
|
|
||||||
echo "<meta property=og:type content=website>"
|
|
||||||
if test -n "$base_uri"; then
|
|
||||||
echo "<meta property=og:url content='${base_uri}${1}.html'>"
|
|
||||||
fi
|
|
||||||
echo "<meta property=og:image content=cowboy.svg>"
|
|
||||||
echo "<link rel=stylesheet href=drip.css>"
|
|
||||||
echo "<link rel=icon href=cowboy.svg>"
|
|
||||||
echo "<title>$1</title>"
|
|
||||||
: "${inicio:=}"
|
|
||||||
if test "$mirror" = true; then
|
|
||||||
echo "<p style=color:darkred>Ojo: este sitio es un espejo (mirror). <a href=https://nulo.in>nulo.in</a> es la fuente.</p>"
|
|
||||||
fi
|
|
||||||
if test "$inicio" != true; then
|
|
||||||
echo "<a href=.>☚ Volver al inicio</a>"
|
|
||||||
fi
|
|
||||||
if test -n "$2"; then
|
|
||||||
echo "<header>"
|
|
||||||
echo "<h1>$1</h1>"
|
|
||||||
echo "<p><small>Último cambio: <time datetime='$(git log -1 --format=%ai "$2")'>$(date -d "@$(git log -1 --format=%at "$2")" '+%Y-%m-%d %H:%M')</time></small></p>"
|
|
||||||
echo "</header>"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
markdown () {
|
|
||||||
# TODO: hacky
|
|
||||||
cmark --unsafe "$1" \
|
|
||||||
| sed "s/<a h/<a rel='noopener noreferrer' h/gi" \
|
|
||||||
| sed 's/\[\[\(.*\)\]\]/<a href="\1.html">\1<\/a>/g'
|
|
||||||
}
|
|
||||||
|
|
||||||
outdir=build
|
|
||||||
mkdir -p $outdir
|
|
||||||
# Autocopiarnos :)
|
|
||||||
cp ./*.sh ./*.md ./*.css ./*.png ./*.jpg ./*.mp4 ./*.svg ./*.html "$outdir"
|
|
||||||
|
|
||||||
index="$outdir/index.html"
|
|
||||||
inicio=true header=false template "nulo.in" > "$index"
|
|
||||||
markdown index.md >> "$index"
|
|
||||||
|
|
||||||
for file in *.md; do
|
|
||||||
test "$(basename "$file")" = index.md && continue
|
|
||||||
title="$(basename "$file" .md)"
|
|
||||||
outfile="$outdir/$title.html"
|
|
||||||
template "$title" "$file" > "$outfile"
|
|
||||||
markdown "$file" >> "$outfile"
|
|
||||||
done
|
|
||||||
|
|
||||||
for file in *.gen; do
|
|
||||||
title="$(basename "$file" .gen)"
|
|
||||||
outfile="$outdir/$title.html"
|
|
||||||
template "$title" "$file" > "$outfile"
|
|
||||||
"./$file" >> "$outfile"
|
|
||||||
done
|
|
||||||
|
|
223
compilar.zig
Normal file
223
compilar.zig
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("cmark.h");
|
||||||
|
});
|
||||||
|
const endsWith = std.mem.endsWith;
|
||||||
|
|
||||||
|
fn stripExtension(file_name: []const u8) ![]const u8 {
|
||||||
|
const index = std.mem.lastIndexOfLinear(u8, file_name, ".");
|
||||||
|
if (index) |i| {
|
||||||
|
return file_name[0..i];
|
||||||
|
} else return error.NoExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HeaderOptions = struct {
|
||||||
|
// Si esto es true, se muestra un botón para volver al index.
|
||||||
|
ir_al_inicio: bool = true,
|
||||||
|
// Si esto es true, se muestra un <header>.
|
||||||
|
header: bool = true,
|
||||||
|
};
|
||||||
|
fn header(
|
||||||
|
writer: std.fs.File.Writer,
|
||||||
|
title: []const u8,
|
||||||
|
src_name: []const u8,
|
||||||
|
options: HeaderOptions,
|
||||||
|
) !void {
|
||||||
|
// TODO: deshardcodear base_uri
|
||||||
|
try writer.print(
|
||||||
|
\\<!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="{0s}">
|
||||||
|
\\<meta property=og:type content=website>
|
||||||
|
\\<meta property=og:url content="https://nulo.in/{1s}.html">
|
||||||
|
\\<meta property=og:image content=cowboy.svg>
|
||||||
|
\\<link rel=stylesheet href=drip.css>
|
||||||
|
\\<link rel=icon href=cowboy.svg>
|
||||||
|
\\<title>{0s}</title>
|
||||||
|
\\
|
||||||
|
, .{ title, src_name });
|
||||||
|
// if test "$mirror" = true; then
|
||||||
|
// echo "<p style=color:darkred>Ojo: este sitio es un espejo (mirror). <a href=https://nulo.in>nulo.in</a> es la fuente.</p>"
|
||||||
|
// fi
|
||||||
|
if (options.ir_al_inicio) {
|
||||||
|
try writer.writeAll("<a href=.>☚ Volver al inicio</a>\n");
|
||||||
|
}
|
||||||
|
if (options.header) {
|
||||||
|
try writer.print(
|
||||||
|
\\<header>
|
||||||
|
\\<h1>{s}</h1>
|
||||||
|
\\<a href="https://gitea.nulo.in/Nulo/sitio/commits/branch/ANTIFASCISTA/{s}">Historial</a>
|
||||||
|
\\</header>
|
||||||
|
\\
|
||||||
|
, .{ title, src_name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
defer _ = gpa.deinit();
|
||||||
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
var cwd = try std.fs.cwd().openDir(".", .{ .iterate = true });
|
||||||
|
defer cwd.close();
|
||||||
|
var cwd_iterator = cwd.iterate();
|
||||||
|
|
||||||
|
var build_dir = try cwd.makeOpenPath("build", .{});
|
||||||
|
defer build_dir.close();
|
||||||
|
|
||||||
|
while (try cwd_iterator.next()) |entry| {
|
||||||
|
if (entry.kind != .File) continue;
|
||||||
|
|
||||||
|
// Autocopiarnos :)
|
||||||
|
if (endsWith(u8, entry.name, ".sh") or
|
||||||
|
endsWith(u8, entry.name, ".md") or
|
||||||
|
endsWith(u8, entry.name, ".css") or
|
||||||
|
endsWith(u8, entry.name, ".png") or
|
||||||
|
endsWith(u8, entry.name, ".jpg") or
|
||||||
|
endsWith(u8, entry.name, ".mp4") or
|
||||||
|
endsWith(u8, entry.name, ".svg") or
|
||||||
|
endsWith(u8, entry.name, ".html"))
|
||||||
|
{
|
||||||
|
try cwd.copyFile(entry.name, build_dir, entry.name, .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endsWith(u8, entry.name, ".md"))
|
||||||
|
try generateMarkdown(allocator, cwd, entry.name, build_dir);
|
||||||
|
if (endsWith(u8, entry.name, ".gen"))
|
||||||
|
try generateExecutable(allocator, cwd, entry.name, build_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Writer = std.io.BufferedWriter(4096, std.fs.File.Writer).Writer;
|
||||||
|
|
||||||
|
fn hackilyTransformHtml(input: []const u8, writer: Writer) !void {
|
||||||
|
var iter = std.mem.split(u8, input, "\n");
|
||||||
|
while (iter.next()) |line| {
|
||||||
|
var index: usize = 0;
|
||||||
|
|
||||||
|
while (index < line.len) : (index += 1) {
|
||||||
|
const rest = line[index..];
|
||||||
|
|
||||||
|
const link_marker = "<a h";
|
||||||
|
if (std.ascii.startsWithIgnoreCase(rest, link_marker)) {
|
||||||
|
index += link_marker.len - 1;
|
||||||
|
try writer.writeAll("<a rel='noopener noreferrer' h");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.startsWith(u8, rest, "[[")) {
|
||||||
|
if (std.mem.indexOf(u8, rest, "]]")) |end| {
|
||||||
|
const name = rest[2..end];
|
||||||
|
index += 2 + name.len + 2 - 1;
|
||||||
|
try writer.print(
|
||||||
|
\\<a href="{0s}.html">{0s}</a>
|
||||||
|
, .{name});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try writer.writeByte(line[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try writer.writeByte('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generateMarkdown(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
cwd: std.fs.Dir,
|
||||||
|
src_name: []const u8,
|
||||||
|
build_dir: std.fs.Dir,
|
||||||
|
) !void {
|
||||||
|
var file = try cwd.openFile(src_name, .{});
|
||||||
|
defer file.close();
|
||||||
|
const markdown = try file.readToEndAllocOptions(
|
||||||
|
allocator,
|
||||||
|
69696969,
|
||||||
|
null,
|
||||||
|
@alignOf(u32),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
defer allocator.free(markdown);
|
||||||
|
const html = c.cmark_markdown_to_html(
|
||||||
|
markdown.ptr,
|
||||||
|
markdown.len,
|
||||||
|
c.CMARK_OPT_UNSAFE, //| c.CMARK_OPT_SMART,
|
||||||
|
);
|
||||||
|
defer std.c.free(html);
|
||||||
|
|
||||||
|
const output_file_name = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}.html",
|
||||||
|
.{try stripExtension(src_name)},
|
||||||
|
);
|
||||||
|
defer allocator.free(output_file_name);
|
||||||
|
|
||||||
|
const is_index = std.ascii.eqlIgnoreCase(src_name, "index.md");
|
||||||
|
|
||||||
|
const title = if (is_index)
|
||||||
|
"nulo.in"
|
||||||
|
else
|
||||||
|
try stripExtension(src_name);
|
||||||
|
|
||||||
|
var output = try build_dir.createFile(output_file_name, .{});
|
||||||
|
defer output.close();
|
||||||
|
try header(output.writer(), title, src_name, .{
|
||||||
|
.ir_al_inicio = !is_index,
|
||||||
|
.header = !is_index,
|
||||||
|
});
|
||||||
|
var buffered_writer = std.io.bufferedWriter(output.writer());
|
||||||
|
try hackilyTransformHtml(
|
||||||
|
std.mem.span(html),
|
||||||
|
buffered_writer.writer(),
|
||||||
|
);
|
||||||
|
try buffered_writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generateExecutable(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
cwd: std.fs.Dir,
|
||||||
|
src_name: []const u8,
|
||||||
|
build_dir: std.fs.Dir,
|
||||||
|
) !void {
|
||||||
|
_ = cwd;
|
||||||
|
const output_file_name = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}.html",
|
||||||
|
.{try stripExtension(src_name)},
|
||||||
|
);
|
||||||
|
defer allocator.free(output_file_name);
|
||||||
|
|
||||||
|
const title = try stripExtension(src_name);
|
||||||
|
|
||||||
|
var output = try build_dir.createFile(output_file_name, .{});
|
||||||
|
defer output.close();
|
||||||
|
try header(output.writer(), title, src_name, .{});
|
||||||
|
|
||||||
|
const executable_name = try std.fmt.allocPrint(allocator, "./{s}", .{src_name});
|
||||||
|
defer allocator.free(executable_name);
|
||||||
|
|
||||||
|
// const process = try std.ChildProcess.init(&.{executable_name}, allocator);
|
||||||
|
// defer process.deinit();
|
||||||
|
// process.stdout_behavior = .Ignore;
|
||||||
|
// process.stdout = output;
|
||||||
|
// const term = try process.spawnAndWait();
|
||||||
|
const result = try std.ChildProcess.exec(.{
|
||||||
|
.allocator = allocator,
|
||||||
|
.argv = &.{executable_name},
|
||||||
|
});
|
||||||
|
defer allocator.free(result.stdout);
|
||||||
|
defer allocator.free(result.stderr);
|
||||||
|
if (result.stderr.len > 0) {
|
||||||
|
std.log.err("{s} stderr: {s}", .{ src_name, result.stderr });
|
||||||
|
}
|
||||||
|
switch (result.term) {
|
||||||
|
.Exited => |status| {
|
||||||
|
if (status != 0) return error.ProcessFailed;
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
try output.writeAll(result.stdout);
|
||||||
|
}
|
Reference in a new issue