From b85404e0b438a0c014b26b9cbfd12475cea6cb33 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 10:36:25 -0300 Subject: content: linkThing: sanitize name before passing to linkTemplate --- src/content/dependencies/linkThing.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/dependencies/linkThing.js b/src/content/dependencies/linkThing.js index 643bf4b..e661ca7 100644 --- a/src/content/dependencies/linkThing.js +++ b/src/content/dependencies/linkThing.js @@ -1,6 +1,6 @@ export default { contentDependencies: ['linkTemplate'], - extraDependencies: ['html'], + extraDependencies: ['html', 'language'], relations(relation) { return { @@ -41,7 +41,7 @@ export default { hash: {type: 'string'}, }, - generate(data, relations, slots, {html}) { + generate(data, relations, slots, {html, language}) { const path = [data.pathKey, data.directory]; const name = @@ -51,7 +51,7 @@ export default { const content = (html.isBlank(slots.content) - ? name + ? language.sanitize(name) : slots.content); let color = null; -- cgit 1.3.0-6-gf8a5 From 72c29f7dfee2bdd7ded4113f0bbccc74d9ea60f9 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 10:36:45 -0300 Subject: test: linkThing: basic tests (snapshot) --- tap-snapshots/test/snapshot/linkThing.js.test.cjs | 35 +++++++++++ test/snapshot/linkThing.js | 76 +++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 tap-snapshots/test/snapshot/linkThing.js.test.cjs create mode 100644 test/snapshot/linkThing.js diff --git a/tap-snapshots/test/snapshot/linkThing.js.test.cjs b/tap-snapshots/test/snapshot/linkThing.js.test.cjs new file mode 100644 index 0000000..2e52d0a --- /dev/null +++ b/tap-snapshots/test/snapshot/linkThing.js.test.cjs @@ -0,0 +1,35 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > basic behavior 1`] = ` +Cool track! +` + +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > color 1`] = ` +Showtime (Piano Refrain) +Showtime (Piano Refrain) +Showtime (Piano Refrain) +` + +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > preferShortName 1`] = ` +Five +` + +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > tags in name escaped 1`] = ` +<a href="SNOOPING">AS USUAL</a> I SEE +<b>boldface</b> +>Exile< +<3 +` + +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > tooltip & content 1`] = ` +Beyond Canon +Beyond Canon +Next +Banana +Banana +` diff --git a/test/snapshot/linkThing.js b/test/snapshot/linkThing.js new file mode 100644 index 0000000..f76b17d --- /dev/null +++ b/test/snapshot/linkThing.js @@ -0,0 +1,76 @@ +import t from 'tap'; +import * as html from '#html'; +import {testContentFunctions} from '#test-lib'; + +testContentFunctions(t, 'linkThing (snapshot)', async (t, evaluate) => { + await evaluate.load(); + + const quickSnapshot = (message, oneOrMultiple) => + evaluate.snapshot(message, + (Array.isArray(oneOrMultiple) + ? {name: 'linkThing', multiple: oneOrMultiple} + : {name: 'linkThing', ...oneOrMultiple})); + + quickSnapshot('basic behavior', { + args: ['localized.track', { + directory: 'foo', + color: '#abcdef', + name: `Cool track!`, + }], + }); + + quickSnapshot('preferShortName', { + args: ['localized.tag', { + directory: 'five-oceanfalls', + name: 'Five (Oceanfalls)', + nameShort: 'Five', + }], + slots: {preferShortName: true}, + }); + + quickSnapshot('tooltip & content', { + args: ['localized.album', { + directory: 'beyond-canon', + name: 'Beyond Canon', + }], + multiple: [ + {slots: {tooltip: false}}, + {slots: {tooltip: true}}, + {slots: {tooltip: true, content: 'Next'}}, + {slots: {tooltip: 'Apple', content: 'Banana'}}, + {slots: {content: 'Banana'}}, + ], + }); + + quickSnapshot('color', { + args: ['localized.track', { + directory: 'showtime-piano-refrain', + name: 'Showtime (Piano Refrain)', + color: '#38f43d', + }], + multiple: [ + {slots: {color: false}}, + {slots: {color: true}}, + {slots: {color: '#aaccff'}}, + ], + }); + + quickSnapshot('tags in name escaped', [ + {args: ['localized.track', { + directory: 'foo', + name: `AS USUAL I SEE`, + }]}, + {args: ['localized.track', { + directory: 'bar', + name: `boldface`, + }]}, + {args: ['localized.album', { + directory: 'exile', + name: '>Exile<', + }]}, + {args: ['localized.track', { + directory: 'heart', + name: '<3', + }]}, + ]); +}); -- cgit 1.3.0-6-gf8a5 From fcb00a7afd8c70586d645a7072fc84fa5de074b3 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 10:43:27 -0300 Subject: test: linkThing: specifically test tag stripping --- tap-snapshots/test/snapshot/linkThing.js.test.cjs | 4 ++++ test/snapshot/linkThing.js | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/tap-snapshots/test/snapshot/linkThing.js.test.cjs b/tap-snapshots/test/snapshot/linkThing.js.test.cjs index 2e52d0a..1a98cfd 100644 --- a/tap-snapshots/test/snapshot/linkThing.js.test.cjs +++ b/tap-snapshots/test/snapshot/linkThing.js.test.cjs @@ -15,6 +15,10 @@ exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > color 1`] = ` Showtime (Piano Refrain) ` +exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > nested links in content stripped 1`] = ` +Oooo! Very spooky. +` + exports[`test/snapshot/linkThing.js TAP linkThing (snapshot) > preferShortName 1`] = ` Five ` diff --git a/test/snapshot/linkThing.js b/test/snapshot/linkThing.js index f76b17d..195d8c0 100644 --- a/test/snapshot/linkThing.js +++ b/test/snapshot/linkThing.js @@ -73,4 +73,15 @@ testContentFunctions(t, 'linkThing (snapshot)', async (t, evaluate) => { name: '<3', }]}, ]); + + quickSnapshot('nested links in content stripped', { + args: ['localized.staticPage', {directory: 'foo', name: 'Foo'}], + slots: { + content: + html.tag('b', {[html.joinChildren]: ''}, [ + html.tag('a', {href: 'bar'}, `Oooo!`), + ` Very spooky.`, + ]), + }, + }); }); -- cgit 1.3.0-6-gf8a5 From 368092b78d87efd4d85b73be90ab9bba3e02ecc3 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 12:32:13 -0300 Subject: readme updates --- README.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 62dd64d..a7fc582 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ $ git clone https://github.com/hsmusic/hsmusic-wiki code Cloning into 'code'... $ git clone https://github.com/hsmusic/hsmusic-data data Cloning into 'data'... -$ git clone https://nebula.ed1.club/git/hsmusic-media media +$ git clone https://github.com/hsmusic/hsmusic-media media Cloning into 'media'... ``` @@ -106,7 +106,7 @@ HSMusic works using a number of repositories in tandem: - This repo covers albums, tracks, artists, groups, and a variety of other things which make up the content of a music wiki. - The data repo also contains all the metadata which makes one wiki unique from another: layout info, static pages (like "About & Credits"), whether or not certain site features are enabled (like "Flashes & Games" or UI for browsing groups), and so on. - All data is written and accessed in the YAML format, and every file follows a specific structure described within this (code) repository. See below and the `src/data` directory for details. -- [`hsmusic-media`][ed1-media]: The media repository, holding all album, track, and layout media used across the site in one place. Media and organization directly corresponds to entries in the data repository; generally the data and media repositories go together and are swapped out for another together. +- [`hsmusic-media`][github-media]: The media repository, holding all album, track, and layout media used across the site in one place. Media and organization directly corresponds to entries in the data repository; generally the data and media repositories go together and are swapped out for another together. - *Language repo:* The language repository, holding up-to-date strings and other localization info for HSMusic. NB: This repo isn't currently online as its structure and tooling haven't been polished or properly put together yet, but it's not required for building the site. - Strings and language info are stored in top-level JSON files within this repository. They're based off the `src/strings-default.json` file within the code repo (and don't need to provide translations for all strings to be used for site building). @@ -139,16 +139,18 @@ The source code for HSMusic is divided across a number of source files, loosely - `src/` - `data/` - - `cacheable-object.js`: Backbone of how data objects (colloquially "things") store, share, and compute their properties - - `things.js`: Descriptors for all "thing" classes used across the wiki: albums, tracks, artists, groups, etc - - `validators.js`: Convenient error-throwing utilities which help ensure properties set on things follow the right format - - `yaml.js`: Mappings from YAML documents (the format used in `hsmusic-data`) to things (actual data objects), and a full set of utilities used to actually load that data from scratch - - `page/` - - All page templates (HTML content and layout metadata) are kept in source files under this directory - - `static/` - - Purely client-side files are kept here, e.g. site CSS, icon SVGs, and client-side JS - - `util/` - - Common utilities which generally may be accessed from both Node.js or the client (web browser) + - `things/`: Descriptors for individual types of data objects used across the wiki, notably including: + - `cacheable-object.js`: Backbone of how data objects (colloquially "things") store, share, and compute their properties + - `thing.js`: Common superclass for most data objects, with a bunch of utilities and common behavior + - `validators.js`: Convenient error-throwing utilities which help ensure properties set on data objects follow the right format + - `yaml.js`: Mappings from YAML documents (the format used in `hsmusic-data`) to things (actual data objects), and a full suite of utilities used to actually load that data from scratch + - `content/`: Functions which generate HTML content; these go from bite-sized, commonly reused utilities (like `linkTemplate`) all the way up to entire page definitions (like `generateArtistInfoPage`) + - `page/`: Definitions for page paths, mapping data objects to paths served over an HTTP server (or written to an output folder) and to the functions which actually generate those pages' content + - `write/`: Common utilities and output methods for controlling what hsmusic does to turn data and media into something you actually visit; these each define a variety of command-line arguments and are basically the interchangeable "second half" of upd8.js + - `live-dev-server.js`: Gets the site available for viewing as quickly as possible, generating and serving pages as they are requested from a local HTTP server; reacts live to code changes in the `content` directory + - `static-build.js`: Builds the entire site at once, writing all the output to one self-contained folder which can be uploaded to a static file server + - `static/`: Purely client-side files are kept here, e.g. site CSS, icon SVGs, and client-side JS + - `util/`: Common utilities which generally may be accessed from both Node.js or the client (web browser) - `upd8.js`: Main entry point which controls and directs site generation from start to finish - `gen-thumbs.js`: Standalone utility also called every time HSMusic is run (unless `--skip-thumbs` is provided) which keeps a persistent cache of media MD5s and (re)generates thumbnails for new or updated image files - `repl.js`: Standalone utility for loading all wiki data and providing a convenient REPL to run filters and transformations on data objects right from the Node.js command line @@ -165,16 +167,16 @@ hsmusic is a relatively generic music wiki software, so you're more than encoura As mentioned, part of the focus of the hsmusic.wiki release, as well as most development since, has been to create a more modular and developer-friendly repository. So, on the curious chance anyone would like to contribute code to the repo, that's more possible now than it used to be! -Still, for larger additions, we encourage you to [drop the main dev an email][feedback] or, better yet, [pop by the Discord][discord] before writing all the implementation code: besides code tips which might make your life a bit easier (questions are welcome), we also love to discuss feature designs and values while they're still being brainstormed! That way, nobody has to tell you there are fundamental ideas or implementation details that should be rebuilt from the ground up - the last thing we want is anyone putting hours into code that has to be replaced by another implementation before it ever ends up part of the wiki! +Still, for larger additions, we encourage you to [drop the main devs an email][feedback] or, better yet, [pop by the Discord][discord] before writing all the implementation code: besides code tips which might make your life a bit easier (questions are welcome), we also love to discuss feature designs and values while they're still being brainstormed! That way, nobody has to tell you there are fundamental ideas or implementation details that should be rebuilt from the ground up - the last thing we want is anyone putting hours into code that has to be replaced by another implementation before it ever ends up part of the wiki! As ever, feedback is always welcome, and may be shared via the usual links. Thank you for checking the repository out! - [ed1-media]: https://nebula.ed1.club/git/hsmusic-media/ [discord]: https://hsmusic.wiki/discord/ [fandom]: https://homestuck-and-mspa-music.fandom.com/wiki/Homestuck_and_MSPA_Music_Wiki [feedback]: https://hsmusic.wiki/feedback/ [github]: https://github.com/hsmusic/hsmusic-wiki [github-code]: https://github.com/hsmusic/hsmusic-wiki [github-data]: https://github.com/hsmusic/hsmusic-data + [github-media]: https://github.com/hsmusic/hsmusic-media [hsmusic]: https://hsmusic.wiki [nsnd]: https://homestuck.net/music/references.html -- cgit 1.3.0-6-gf8a5 From 2099c258fc1833ac459c8a43ca0cae9ae6150ad0 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 12:41:20 -0300 Subject: content: listTracksWithExtra: handle dateless albums cleanly --- src/content/dependencies/listTracksWithExtra.js | 12 ++++++++---- src/strings-default.json | 9 ++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/content/dependencies/listTracksWithExtra.js b/src/content/dependencies/listTracksWithExtra.js index 73d25e3..c9f80f3 100644 --- a/src/content/dependencies/listTracksWithExtra.js +++ b/src/content/dependencies/listTracksWithExtra.js @@ -65,10 +65,14 @@ export default { stitchArrays({ albumLink: relations.albumLinks, date: data.dates, - }).map(({albumLink, date}) => ({ - album: albumLink, - date: language.formatDate(date), - })), + }).map(({albumLink, date}) => + (date + ? { + stringsKey: 'withDate', + album: albumLink, + date: language.formatDate(date), + } + : {album: albumLink})), chunkRows: relations.trackLinks diff --git a/src/strings-default.json b/src/strings-default.json index b5e39e9..0ad7a51 100644 --- a/src/strings-default.json +++ b/src/strings-default.json @@ -437,15 +437,18 @@ "listingPage.listTracks.inFlashes.byFlash.chunk.item": "{TRACK} (from {ALBUM})", "listingPage.listTracks.withLyrics.title": "Tracks - with Lyrics", "listingPage.listTracks.withLyrics.title.short": "...with Lyrics", - "listingPage.listTracks.withLyrics.chunk.title": "{ALBUM} ({DATE})", + "listingPage.listTracks.withLyrics.chunk.title": "{ALBUM}", + "listingPage.listTracks.withLyrics.chunk.title.withDate": "{ALBUM} ({DATE})", "listingPage.listTracks.withLyrics.chunk.item": "{TRACK}", "listingPage.listTracks.withSheetMusicFiles.title": "Tracks - with Sheet Music Files", "listingPage.listTracks.withSheetMusicFiles.title.short": "...with Sheet Music Files", - "listingPage.listTracks.withSheetMusicFiles.chunk.title": "{ALBUM} ({DATE})", + "listingPage.listTracks.withSheetMusicFiles.chunk.title": "{ALBUM}", + "listingPage.listTracks.withSheetMusicFiles.chunk.title.withDate": "{ALBUM} ({DATE})", "listingPage.listTracks.withSheetMusicFiles.chunk.item": "{TRACK}", "listingPage.listTracks.withMidiProjectFiles.title": "Tracks - with MIDI & Project Files", "listingPage.listTracks.withMidiProjectFiles.title.short": "...with MIDI & Project Files", - "listingPage.listTracks.withMidiProjectFiles.chunk.title": "{ALBUM} ({DATE})", + "listingPage.listTracks.withMidiProjectFiles.chunk.title": "{ALBUM}", + "listingPage.listTracks.withMidiProjectFiles.chunk.title.withDate": "{ALBUM} ({DATE})", "listingPage.listTracks.withMidiProjectFiles.chunk.item": "{TRACK}", "listingPage.listTags.byName.title": "Tags - by Name", "listingPage.listTags.byName.title.short": "...by Name", -- cgit 1.3.0-6-gf8a5 From 0e613cf94a3fade7050fc2e50e8bfbab8d532ad2 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 13:21:08 -0300 Subject: thumbs: probably fix using wrong convert command?? --- src/gen-thumbs.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gen-thumbs.js b/src/gen-thumbs.js index 18d1964..65f0a4d 100644 --- a/src/gen-thumbs.js +++ b/src/gen-thumbs.js @@ -250,7 +250,11 @@ async function getImageMagickVersion(binary) { allData += data.toString(); }); - await promisifyProcess(proc, false); + try { + await promisifyProcess(proc, false); + } catch (error) { + return null; + } if (!allData.match(/ImageMagick/i)) { return null; -- cgit 1.3.0-6-gf8a5 From 9745cf89d808bc2e4698af346ddbc53e1ae08a2c Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 13:25:49 -0300 Subject: SO A BIT EMBARRASSING --- src/gen-thumbs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gen-thumbs.js b/src/gen-thumbs.js index 65f0a4d..34eed9c 100644 --- a/src/gen-thumbs.js +++ b/src/gen-thumbs.js @@ -286,7 +286,7 @@ async function getSpawnMagick(tool) { } if (fn === null && await commandExists('magick')) { - version = await getImageMagickVersion(fn); + version = await getImageMagickVersion('magick'); if (version !== null) { fn = (args) => spawn('magick', [tool, ...args]); description = `magick ${tool}`; -- cgit 1.3.0-6-gf8a5 From a53d53e1f95d84b23cffb9a5d43f1a70a412b6fe Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 17:23:05 -0300 Subject: page: don't generate redirect from directory to same directory --- src/page/artist-alias.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/page/artist-alias.js b/src/page/artist-alias.js index 1da2af4..d230522 100644 --- a/src/page/artist-alias.js +++ b/src/page/artist-alias.js @@ -7,6 +7,12 @@ export function targets({wikiData}) { export function pathsForTarget(aliasArtist) { const {aliasedArtist} = aliasArtist; + // Don't generate a redirect page if this aliased name resolves to the same + // directory as the original artist! See issue #280. + if (aliasArtist.directory === aliasedArtist.directory) { + return []; + } + return [ { type: 'redirect', -- cgit 1.3.0-6-gf8a5