X-Git-Url: https://git.ladys.computer/Beorn/blobdiff_plain/7bea148d7f7b13878c590a9105af1829870fa7e7..HEAD:/build.js?ds=sidebyside diff --git a/build.js b/build.js index 4c26518..7299dc0 100755 --- a/build.js +++ b/build.js @@ -467,7 +467,8 @@ const applyMetadata = (node, metadata) => { default: { // The property describes (potentially rich) text. if (value == null) { - // The property has no value; skip appending it to the node. + // The property has no value; skip appending it to the + // node. continue; } else if (Object(value) instanceof String) { // The property has a string value. @@ -511,31 +512,63 @@ const basePath = `./${Deno.args[0] ?? ""}`; * * - "literal": This is a plaintext field. */ -const context = { - author: { namespace: DC11, localName: "creator", type: "person" }, +const context = Object.freeze({ + author: Object.freeze({ + namespace: DC11, + localName: "creator", + type: "person", + }), // category is not supported at this time - content: { namespace: SIOC, localName: "content", type: "text" }, - contributor: { + content: Object.freeze({ + namespace: SIOC, + localName: "content", + type: "text", + }), + contributor: Object.freeze({ namespace: DC11, localName: "contributor", type: "person", - }, + }), // generator is provided by the build script - icon: { namespace: AWOL, localName: "icon", type: "literal" }, + icon: Object.freeze({ + namespace: AWOL, + localName: "icon", + type: "node", + }), // link is provided by the build script - logo: { namespace: AWOL, localName: "logo", type: "literal" }, - published: { + logo: Object.freeze({ + namespace: AWOL, + localName: "logo", + type: "node", + }), + published: Object.freeze({ namespace: DC11, localName: "date", type: "literal", - }, - rights: { namespace: DC11, localName: "rights", type: "text" }, + }), + rights: Object.freeze({ + namespace: DC11, + localName: "rights", + type: "text", + }), // source is not supported at this time - subtitle: { namespace: RDFS, localName: "label", type: "text" }, - summary: { namespace: DC11, localName: "abstract", type: "text" }, - title: { namespace: DC11, localName: "title", type: "text" }, + subtitle: Object.freeze({ + namespace: RDFS, + localName: "label", + type: "text", + }), + summary: Object.freeze({ + namespace: DC11, + localName: "abstract", + type: "text", + }), + title: Object.freeze({ + namespace: DC11, + localName: "title", + type: "text", + }), // updated is provided by the build script -}; +}); const { /** @@ -769,6 +802,10 @@ const metadataFromDocument = ( const { [name]: existing } = result; const content = (() => { switch (type) { + case "node": { + // The node points to another node. + return node.getAttributeNS(RDF, "resource"); + } case "person": { // The node describes a person. const base = @@ -929,6 +966,7 @@ const validateMetadata = (metadata, type) => { globalThis.Lemon = Lemon; globalThis.Bjørn = { addContent, + context, getLanguage, setLanguage, }; @@ -978,90 +1016,82 @@ await (async () => { // this is the run script const feedEntries = feedTemplate.createDocumentFragment(); // Process entries and save the resulting index files. - for await ( - const { name: date, isDirectory } of Deno.readDir( - `${basePath}/`, + for ( + const { name: date } of Array.from( + Deno.readDirSync(`${basePath}/`), + ).filter(({ name: date, isDirectory }) => + // Exclude non‐dated directories. + isDirectory && /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/u.test(date) + ).sort(({ name: a }, { name: b }) => + // Sort the directories. + a < b ? 1 : a > b ? -1 : 0 ) ) { - // Iterate over each directory and process the ones which are - // dates. - if (!isDirectory || !/[0-9]{4}-[0-9]{2}-[0-9]{2}/u.test(date)) { - // This isn’t a dated directory. - continue; - } else { - // This is a dated directory. - for ( - const { name: entryName, isDirectory } of Array.from( - Deno.readDirSync(`${basePath}/${date}/`), - ).sort(({ name: a }, { name: b }) => - a < b ? -1 : a > b ? 1 : 0 - ) - ) { - // Iterate over each directory and process the ones which look - // like entries. - if ( - !isDirectory || - //deno-lint-ignore no-control-regex - /[\x00-\x20\x22#%/<>?\\^\x60{|}\x7F]/u.test(entryName) - ) { - // This isn’t an entry directory. - continue; - } else { - // Process the entry. - const entry = document.createElement("entry"); - const entryPath = - `${basePath}/${date}/${entryName}/#entry.rdf`; - const entryDocument = parser.parseFromString( - await Deno.readTextFile(entryPath), - "application/xml", - ); - const { documentElement: entryRoot } = entryDocument; - entryDocument.lastModified = - (await Deno.lstat(entryPath)).mtime; - if (!entryRoot.hasAttributeNS(RDF, "about")) { - // The entry doesn’t have an identifier; let’s give it one. - entryRoot.setAttributeNS( - RDF, - "about", - new URL(`./${date}/${entryName}/`, feedURI), - ); - } else { - // The entry already has an identifier. - /* do nothing */ - } - const entryMetadata = metadataFromDocument(entryDocument); - if (entryMetadata.author.length == 0) { - // The entry metadata did not supply an author. - entryMetadata.author = feedMetadata.author; - } else { - // The entry metadata supplied its own author. - /* do nothing */ - } - const entryTemplate = await documentFromTemplate("entry"); - const { documentElement: templateRoot } = entryTemplate; - const lang = getLanguage(entryRoot); - if (lang && !getLanguage(templateRoot)) { - // The root element of the template does not have an - // assigned language, but the entry does. - setLanguage(templateRoot, lang); - } else { - // Either the template root already has a language, or the - // entry doesn’t either. - /* do nothing */ - } - writes.push( - Deno.writeTextFile( - `${basePath}/${date}/${entryName}/index.xhtml`, - serializer.serializeToString( - applyMetadata(entryTemplate, entryMetadata), - ) + "\n", - ), - ); - applyMetadata(entry, entryMetadata); - applyMetadata(feedEntries, entryMetadata); - feed.appendChild(entry); - } + // Iterate over each dated directory and process its entries. + for ( + const { name: entryName } of Array.from( + Deno.readDirSync(`${basePath}/${date}/`), + ).filter(({ name: entryName, isDirectory }) => + // Exclude non‐entry directories. + isDirectory && + //deno-lint-ignore no-control-regex + !/[\x00-\x20\x22#%/<>?\\^\x60{|}\x7F]/u.test(entryName) + ).sort(({ name: a }, { name: b }) => + // Sort the directories. + a < b ? 1 : a > b ? -1 : 0 + ) + ) { + // Iterate over each entry directory and process its contents. + const entry = document.createElement("entry"); + const entryPath = `${basePath}/${date}/${entryName}/#entry.rdf`; + const entryDocument = parser.parseFromString( + await Deno.readTextFile(entryPath), + "application/xml", + ); + const { documentElement: entryRoot } = entryDocument; + entryDocument.lastModified = (await Deno.lstat(entryPath)).mtime; + if (!entryRoot.hasAttributeNS(RDF, "about")) { + // The entry doesn’t have an identifier; let’s give it one. + entryRoot.setAttributeNS( + RDF, + "about", + new URL(`./${date}/${entryName}/`, feedURI), + ); + } else { + // The entry already has an identifier. + /* do nothing */ } + const entryMetadata = metadataFromDocument(entryDocument); + if (entryMetadata.author.length == 0) { + // The entry metadata did not supply an author. + entryMetadata.author = feedMetadata.author; + } else { + // The entry metadata supplied its own author. + /* do nothing */ + } + const entryTemplate = await documentFromTemplate("entry"); + const { documentElement: templateRoot } = entryTemplate; + const lang = getLanguage(entryRoot); + if (lang && !getLanguage(templateRoot)) { + // The root element of the template does not have an + // assigned language, but the entry does. + setLanguage(templateRoot, lang); + } else { + // Either the template root already has a language, or the + // entry doesn’t either. + /* do nothing */ + } + writes.push( + Deno.writeTextFile( + `${basePath}/${date}/${entryName}/index.xhtml`, + serializer.serializeToString( + applyMetadata(entryTemplate, entryMetadata), + ) + "\n", + ), + ); + applyMetadata(entry, entryMetadata); + applyMetadata(feedEntries, entryMetadata); + feed.appendChild(entry); } }