diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2023-02-05 09:35:20 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-05 09:35:20 -0400 |
commit | f71136f0a03d7f3c36651918af2dc18527dd47be (patch) | |
tree | 6df9bba79901eed7cc7d1f16eba0375a21f10280 /src | |
parent | f0af4edfa87e9518703b7c9ab35244911f0a3ac2 (diff) | |
parent | 7c668d5cc6a107b3613e6bc1ab20c9005590b3cf (diff) |
Merge pull request #152 from hsmusic/skeleton-support
Better support "skeleton" and minimal-content wikis
Diffstat (limited to 'src')
-rw-r--r-- | src/data/yaml.js | 62 | ||||
-rw-r--r-- | src/page/album.js | 8 | ||||
-rw-r--r-- | src/page/group.js | 25 | ||||
-rw-r--r-- | src/util/io.js | 4 |
4 files changed, 72 insertions, 27 deletions
diff --git a/src/data/yaml.js b/src/data/yaml.js index b00d68ee..13b746f7 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -4,7 +4,7 @@ import * as path from 'path'; import yaml from 'js-yaml'; -import {readFile} from 'fs/promises'; +import {readFile, stat} from 'fs/promises'; import {inspect as nodeInspect} from 'util'; import T from './things/index.js'; @@ -241,7 +241,7 @@ export const processTrackGroupDocument = makeProcessDocument(T.TrackGroup, { export const processTrackDocument = makeProcessDocument(T.Track, { fieldTransformations: { - 'Duration': getDurationInSeconds, + 'Duration': parseDuration, 'Date First Released': (value) => new Date(value), 'Cover Art Date': (value) => new Date(value), @@ -447,13 +447,9 @@ export function processHomepageLayoutRowDocument(document) { // --> Utilities shared across document parsing functions -export function getDurationInSeconds(string) { - if (typeof string === 'number') { - return string; - } - +export function parseDuration(string) { if (typeof string !== 'string') { - throw new TypeError(`Expected a string or number, got ${string}`); + return string; } const parts = string.split(':').map((n) => parseInt(n)); @@ -467,7 +463,6 @@ export function getDurationInSeconds(string) { } export function parseAdditionalFiles(array) { - if (!array) return null; if (!Array.isArray(array)) { // Error will be caught when validating against whatever this value is return array; @@ -493,8 +488,11 @@ export function parseCommentary(text) { } export function parseContributors(contributors) { - if (!contributors) { - return null; + // If this isn't something we can parse, just return it as-is. + // The Thing object's validators will handle the data error better + // than we're able to here. + if (!Array.isArray(contributors)) { + return contributors; } if (contributors.length === 1 && contributors[0].startsWith('<i>')) { @@ -528,8 +526,11 @@ export function parseContributors(contributors) { } function parseDimensions(string) { - if (!string) { - return null; + // It's technically possible to pass an array like [30, 40] through here. + // That's not really an issue because if it isn't of the appropriate shape, + // the Thing object's validators will handle the error. + if (typeof string !== 'string') { + return string; } const parts = string.split(/[x,* ]+/g); @@ -945,6 +946,30 @@ export async function loadAndProcessDataDocuments({dataPath}) { ? await callAsync(dataStep.file, dataPath) : dataStep.file); + const statResult = await callAsync(() => + stat(file).then( + () => true, + error => { + if (error.code === 'ENOENT') { + return false; + } else { + throw error; + } + })); + + if (statResult === false) { + const saveResult = call(dataStep.save, { + [documentModes.allInOne]: [], + [documentModes.oneDocumentTotal]: {}, + }[documentMode]); + + if (!saveResult) return; + + Object.assign(wikiDataResult, saveResult); + + return; + } + const readResult = await callAsync(readFile, file, 'utf-8'); if (!readResult) { @@ -992,7 +1017,16 @@ export async function loadAndProcessDataDocuments({dataPath}) { let files = ( typeof dataStep.files === 'function' - ? await callAsync(dataStep.files, dataPath) + ? await callAsync(() => + dataStep.files(dataPath).then( + files => files, + error => { + if (error.code === 'ENOENT') { + return []; + } else { + throw error; + } + })) : dataStep.files ); diff --git a/src/page/album.js b/src/page/album.js index 1fc74520..80397065 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -53,7 +53,7 @@ export function write(album, {wikiData}) { const displayTrackGroups = album.trackGroups && (album.trackGroups.length > 1 || - !album.trackGroups[0].isDefaultTrackGroup); + !album.trackGroups[0]?.isDefaultTrackGroup); const listTag = getAlbumListTag(album); @@ -301,6 +301,7 @@ export function write(album, {wikiData}) { })), displayTrackGroups && + !empty(album.trackGroups) && html.tag('dl', {class: 'album-group-list'}, album.trackGroups.flatMap(({ @@ -323,6 +324,7 @@ export function write(album, {wikiData}) { ])), !displayTrackGroups && + !empty(album.tracks) && html.tag(listTag, album.tracks.map(trackToListItem)), @@ -759,6 +761,10 @@ export function generateAlbumNavLinks(album, currentTrack, { randomLink, ].filter(Boolean); + if (empty(allLinks)) { + return ''; + } + return `(${language.formatUnitList(allLinks)})`; } diff --git a/src/page/group.js b/src/page/group.js index 6bfd1532..f9af8e80 100644 --- a/src/page/group.js +++ b/src/page/group.js @@ -16,8 +16,7 @@ export function targets({wikiData}) { export function write(group, {wikiData}) { const {listingSpec, wikiInfo} = wikiData; - const {albums} = group; - const tracks = albums.flatMap((album) => album.tracks); + const tracks = group.albums.flatMap((album) => album.tracks); const totalDuration = getTotalDuration(tracks, {originalReleasesOnly: true}); const albumLines = group.albums.map((album) => ({ @@ -65,7 +64,7 @@ export function write(group, {wikiData}) { transformMultiline(group.description)), ...html.fragment( - group.albums && [ + !empty(group.albums) && [ html.tag('h2', {class: ['content-heading']}, language.$('groupInfoPage.albumList.title')), @@ -123,7 +122,7 @@ export function write(group, {wikiData}) { }), }; - const galleryPage = { + const galleryPage = !empty(group.albums) && { type: 'page', path: ['groupGallery', group.directory], page: ({ @@ -165,7 +164,7 @@ export function write(group, {wikiData}) { unit: true, })), albums: html.tag('b', - language.countAlbums(albums.length, { + language.countAlbums(group.albums.length, { unit: true, })), time: html.tag('b', @@ -222,7 +221,7 @@ export function write(group, {wikiData}) { }), }; - return [infoPage, galleryPage]; + return [infoPage, galleryPage].filter(Boolean); } // Utility functions @@ -240,8 +239,6 @@ function generateGroupSidebar(currentGroup, isGallery, { return null; } - const linkKey = isGallery ? 'groupGallery' : 'groupInfo'; - return { content: [ html.tag('h1', @@ -260,15 +257,21 @@ function generateGroupSidebar(currentGroup, isGallery, { category: `<span class="group-name">${category.name}</span>`, })), html.tag('ul', - category.groups.map((group) => - html.tag('li', + category.groups.map((group) => { + const linkKey = ( + isGallery && !empty(group.albums) + ? 'groupGallery' + : 'groupInfo'); + + return html.tag('li', { class: group === currentGroup && 'current', style: getLinkThemeString(group.color), }, language.$('groupSidebar.groupList.item', { group: link[linkKey](group), - })))), + })); + })), ])), ], }; diff --git a/src/util/io.js b/src/util/io.js index 6cc89b56..12e87f4d 100644 --- a/src/util/io.js +++ b/src/util/io.js @@ -12,7 +12,9 @@ export async function findFiles(dataPath, { try { files = await readdir(dataPath); } catch (error) { - throw new AggregateError([error], `Failed to list files from ${dataPath}`); + throw Object.assign( + new AggregateError([error], `Failed to list files from ${dataPath}`), + {code: error.code}); } return files |