Compare commits

..

2 commits

Author SHA1 Message Date
3aaceb9080 refactor + agregar <time> para microdata
All checks were successful
repro-run Corre repro-run.json
2023-03-09 11:58:29 -03:00
60c0a04fc9 parsear fechas de títulos y usar para todo 2023-03-09 11:09:27 -03:00
4 changed files with 134 additions and 23 deletions

View file

@ -19,6 +19,10 @@ import {
ul, ul,
h2, h2,
raw, raw,
p,
VirtualElement,
time,
article,
} from "@nulo/html.js"; } from "@nulo/html.js";
const execFile = promisify(execFileCallback); const execFile = promisify(execFileCallback);
@ -26,6 +30,13 @@ const execFile = promisify(execFileCallback);
const reader = new commonmark.Parser({ smart: true }); const reader = new commonmark.Parser({ smart: true });
const writer = new commonmark.HtmlRenderer({ safe: false, smart: true }); const writer = new commonmark.HtmlRenderer({ safe: false, smart: true });
const dateFormatter = new Intl.DateTimeFormat("es-AR", {
weekday: "long",
day: "numeric",
month: "long",
year: "numeric",
});
const wikilinkExp = /\[\[(.+?)\]\]/giu; const wikilinkExp = /\[\[(.+?)\]\]/giu;
const compilers: { const compilers: {
@ -85,18 +96,21 @@ async function compileFile(name: string) {
async function compilePage(config: Config, sourceFileName: string) { async function compilePage(config: Config, sourceFileName: string) {
const name = basename(sourceFileName, extname(sourceFileName)); const name = basename(sourceFileName, extname(sourceFileName));
const isIndex = name === "index"; const isIndex = name === "index";
const title = isIndex ? "nulo.in" : name; const title = isIndex ? "nulo.in" : formatNameToPlainText(name);
const fileConnections = connections.filter(({ linked }) => linked === name); const fileConnections = connections.filter(({ linked }) => linked === name);
const contentHtml = await compileContentHtml(config, sourceFileName); const contentHtml = await compileContentHtml(config, sourceFileName);
const html = render( const html = render(
...generateHead(title, name), ...generateHead(title, name),
...(isIndex article(
? [] { itemscope: "", itemtype: "https://schema.org/CreativeWork" },
: generateHeader(title, sourceFileName, fileConnections.length > 0)), ...(isIndex
raw(contentHtml), ? []
...generateConnectionsSection(fileConnections) : generateHeader(name, sourceFileName, fileConnections.length > 0)),
raw(contentHtml),
...generateConnectionsSection(fileConnections)
)
); );
const outputPath = join(config.buildPath, name + ".html"); const outputPath = join(config.buildPath, name + ".html");
@ -185,15 +199,112 @@ function generateHead(titlee: string, outputName: string): Renderable[] {
]; ];
} }
function formatDate(dateish: Dateish, upper: boolean = false): string {
const date = new Date(dateish.year, dateish.month - 1, dateish.day);
const formatted = dateFormatter.format(date);
if (upper) {
// no le digan a la policía del unicode!
return formatted[0].toUpperCase() + formatted.slice(1);
} else return formatted;
}
interface Dateish {
year: number;
month: number;
day: number;
}
function dateishToString({ year, month, day }: Dateish): string {
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(
2,
"0"
)}`;
}
type TitleMetadata =
| {
// title puede tener length == 0 y por lo tanto ser falseish
title: string;
date?: Dateish;
}
| { date: Dateish };
function parseName(name: string): TitleMetadata {
const titleWithDate =
/^((?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}))? ?(?<title>.*)$/;
const found = name.match(titleWithDate);
if (!found || !found.groups) throw new Error("Algo raro pasó");
const { title } = found.groups;
const date =
(found.groups.year && {
year: parseInt(found.groups.year),
month: parseInt(found.groups.month),
day: parseInt(found.groups.day),
}) ||
undefined;
// no definir title si es length == 0
if (!title && date) return { date };
return { title, date };
}
function dateishToElement(
dateish: Dateish,
{ itemprop, upper }: { itemprop?: string; upper?: boolean } = {}
): VirtualElement {
return time(
{ datetime: dateishToString(dateish), ...(itemprop ? { itemprop } : {}) },
formatDate(dateish, upper)
);
}
function formatNameToInline(name: string): Renderable[] {
const parsed = parseName(name);
if ("title" in parsed) {
const { title, date } = parsed;
return [title, ...(date ? [` (`, dateishToElement(date), `)`] : [])];
} else {
return [dateishToElement(parsed.date, { upper: true })];
}
}
function formatNameToPlainText(name: string): string {
const parsed = parseName(name);
if ("title" in parsed) {
const { title, date } = parsed;
return title + (date ? ` (${formatDate(date)})` : "");
} else {
return formatDate(parsed.date, true);
}
}
function generateHeader( function generateHeader(
title: string, name: string,
sourceCodePath: string, sourceCodePath: string,
linkConexiones = false linkConexiones = false
): Renderable[] { ): Renderable[] {
const parsedTitle = parseName(name);
return [ return [
a({ href: "." }, "☚ Volver al inicio"), a({ href: "." }, "☚ Volver al inicio"),
header( header(
h1(title), ...("title" in parsedTitle
? [
h1(parsedTitle.title),
...(parsedTitle.date
? [
dateishToElement(parsedTitle.date, {
itemprop: "datePublished",
}),
" / ",
]
: []),
]
: [
h1(
dateishToElement(parsedTitle.date, {
itemprop: "datePublished",
upper: true,
})
),
]),
a( a(
{ {
href: `https://gitea.nulo.in/Nulo/sitio/commits/branch/ANTIFASCISTA/${sourceCodePath}`, href: `https://gitea.nulo.in/Nulo/sitio/commits/branch/ANTIFASCISTA/${sourceCodePath}`,
@ -215,11 +326,7 @@ function generateConnectionsSection(
section( section(
{ id: "conexiones" }, { id: "conexiones" },
h2(`⥆ Conexiones (${fileConnections.length})`), h2(`⥆ Conexiones (${fileConnections.length})`),
ul( ul(...fileConnections.map(({ linker }) => li(internalLink(linker))))
...fileConnections.map(({ linker }) =>
li(a({ href: internalLink(linker) }, linker))
)
)
), ),
] ]
: []; : [];
@ -234,7 +341,7 @@ async function compilePageList(config: Config, pageList: string[]) {
ul( ul(
...pageList ...pageList
.sort((a, b) => a.localeCompare(b, "es", { sensitivity: "base" })) .sort((a, b) => a.localeCompare(b, "es", { sensitivity: "base" }))
.map((name) => li(a({ href: internalLink(name) }, name))) .map((name) => li(internalLink(name)))
) )
); );
await writeFile(outputPath, html); await writeFile(outputPath, html);
@ -277,7 +384,7 @@ function renderMarkdown(markdown: string) {
async function hackilyTransformHtml(html: string): Promise<string> { async function hackilyTransformHtml(html: string): Promise<string> {
html = html html = html
.replaceAll("<a h", '<a rel="noopener noreferrer" h') .replaceAll("<a h", '<a rel="noopener noreferrer" h')
.replaceAll(wikilinkExp, (_, l) => render(a({ href: internalLink(l) }, l))); .replaceAll(wikilinkExp, (_, l) => render(internalLink(l)));
for (const [match, archivo] of html.matchAll( for (const [match, archivo] of html.matchAll(
/<nulo-sitio-reemplazar-con archivo="(.+?)" \/>/g /<nulo-sitio-reemplazar-con archivo="(.+?)" \/>/g
)) { )) {
@ -290,6 +397,7 @@ async function hackilyTransformHtml(html: string): Promise<string> {
// Linking // Linking
// ============================================== // ==============================================
function internalLink(path: string) { function internalLink(path: string): VirtualElement {
return encodeURI(`./${path}.html`); const href = encodeURI(`./${path}.html`);
return a({ href }, ...formatNameToInline(path));
} }

View file

@ -15,10 +15,13 @@ body {
padding: 1rem; padding: 1rem;
} }
header { article header {
margin: 2rem 0; margin: 2rem 0;
text-align: center; text-align: center;
} }
article h1 {
font-size: 32px;
}
h2 { h2 {
border-bottom: var(--foreground) solid 1px; border-bottom: var(--foreground) solid 1px;

View file

@ -19,7 +19,7 @@
"typescript": "^4.9.4" "typescript": "^4.9.4"
}, },
"dependencies": { "dependencies": {
"@nulo/html.js": "^0.0.7", "@nulo/html.js": "^0.0.8",
"commonmark": "^0.30.0" "commonmark": "^0.30.0"
} }
} }

View file

@ -1,7 +1,7 @@
lockfileVersion: 5.4 lockfileVersion: 5.4
specifiers: specifiers:
'@nulo/html.js': ^0.0.7 '@nulo/html.js': ^0.0.8
'@types/commonmark': ^0.27.5 '@types/commonmark': ^0.27.5
'@types/node': ^18.11.18 '@types/node': ^18.11.18
commonmark: ^0.30.0 commonmark: ^0.30.0
@ -9,7 +9,7 @@ specifiers:
typescript: ^4.9.4 typescript: ^4.9.4
dependencies: dependencies:
'@nulo/html.js': 0.0.7 '@nulo/html.js': 0.0.8
commonmark: 0.30.0 commonmark: 0.30.0
devDependencies: devDependencies:
@ -218,8 +218,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nulo/html.js/0.0.7: /@nulo/html.js/0.0.8:
resolution: {integrity: sha512-4xzxbrovLRlS36RrQx9AtEc6OQZSIOK1cWuda7AYQFv3aQSkGAIuEgJK3FvvtgHMIi9AOcQuD/T9c9VpK4NAkA==, tarball: https://gitea.nulo.in/api/packages/Nulo/npm/%40nulo%2Fhtml.js/-/0.0.7/html.js-0.0.7.tgz} resolution: {integrity: sha512-fi2VrrdTx2ivWPyUuZpnuBxelGoxWzbvyo/iki222AfYlPa9/xMwAXz+9q8vdtHOP5/3E/z30YDp+Sq5TkRZhg==, tarball: https://gitea.nulo.in/api/packages/Nulo/npm/%40nulo%2Fhtml.js/-/0.0.8/html.js-0.0.8.tgz}
dev: false dev: false
/@types/commonmark/0.27.5: /@types/commonmark/0.27.5: