From 23902023c4a5549ce37a8e8543ac4b9a20b6edca Mon Sep 17 00:00:00 2001 From: nzbr Date: Thu, 4 Jan 2024 19:58:22 +0100 Subject: [PATCH] web: add speechbubble post-processor --- package.json | 5 +- web/html-postprocessors/.gitignore | 1 + web/html-postprocessors/speechbubbles.ts | 79 ++++++++++++++++++++++++ web/html-postprocessors/tsconfig.json | 13 ++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 web/html-postprocessors/.gitignore create mode 100644 web/html-postprocessors/speechbubbles.ts create mode 100644 web/html-postprocessors/tsconfig.json diff --git a/package.json b/package.json index 3c13345..6cf3347 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,15 @@ }, "dependencies": { "@fontsource/jetbrains-mono": "^5.0.2", - "@fontsource/roboto-slab": "^5.0.2" + "@fontsource/roboto-slab": "^5.0.2", + "@nzbr/parcel-transformer-postprocess-html": "github:nzbr/parcel-transformer-postprocess-html" }, "peerDependencies": { "sharp": "^0.31.1" }, "devDependencies": { + "@types/node": "^20.10.6", + "typescript": "^5.3.3", "base16-builder": "^1.3.0" } } diff --git a/web/html-postprocessors/.gitignore b/web/html-postprocessors/.gitignore new file mode 100644 index 0000000..a6c7c28 --- /dev/null +++ b/web/html-postprocessors/.gitignore @@ -0,0 +1 @@ +*.js diff --git a/web/html-postprocessors/speechbubbles.ts b/web/html-postprocessors/speechbubbles.ts new file mode 100644 index 0000000..5b806c9 --- /dev/null +++ b/web/html-postprocessors/speechbubbles.ts @@ -0,0 +1,79 @@ +import * as path from 'path'; +import * as fs from 'fs'; +import type { StepInputs } from '@nzbr/parcel-transformer-postprocess-html/src'; +import { toPosixPath } from '@nzbr/parcel-transformer-postprocess-html/src'; + +export function generateSpeechbubbles({ $, asset, options }: StepInputs): void { + const root = toPosixPath(options.projectRoot); + const stickers = path.posix.join(root, 'src', 'stickers'); + + asset.invalidateOnFileCreate({ + glob: path.posix.join(stickers, '*'), + }); + + fs.readdirSync(stickers).forEach((character) => { + const characterDir = path.posix.join(stickers, character); + const cssClass = character.toLowerCase().trim().replaceAll(' ', '-'); + $(`.${cssClass}`).each((_, el) => { + asset.invalidateOnFileCreate({ + glob: path.posix.join(characterDir, '*'), + }); + + const stickers = fs + .readdirSync(characterDir) + .filter((file) => !file.endsWith('.txt')) + .map((file) => { + const stickerName = file.split('.').slice(0, -1).join('.'); + + return { + stickerName, + stickerFile: path.posix.join(characterDir, file), + stickerAltFile: path.posix.join(characterDir, stickerName + '.txt'), + stickerCssClass: stickerName.toLowerCase().trim().replaceAll(' ', '-'), + }; + }); + + const defaultSticker = stickers.find( + (sticker) => sticker.stickerName === character, + ); + const variants = stickers.filter((sticker) => sticker.stickerName !== character); + + const sticker = variants + .concat(defaultSticker ? [defaultSticker] : []) + .find((sticker) => $(el).hasClass(sticker.stickerCssClass)); + + if (!sticker) { + asset.invalidateOnFileCreate({ + glob: path.posix.join(characterDir, `${character}.*`), + }); + throw new Error(`No sticker found for ${character} in ${asset.filePath}`); + } + + if (!fs.existsSync(sticker.stickerAltFile)) { + asset.invalidateOnFileCreate({ + glob: path.posix.join(characterDir, `${sticker.stickerName}.txt`), + }); + throw new Error( + `No alt text found for ${sticker.stickerName} in ${asset.filePath}`, + ); + } + + asset.invalidateOnFileChange(sticker.stickerAltFile); + const alt = fs.readFileSync(sticker.stickerAltFile, 'utf-8').trim(); + + const url = asset.addURLDependency( + `/${path.posix.relative(root, sticker.stickerFile)}`, + {}, + ); + + $(el).addClass('speechbubble'); + $(el).html(` + ${alt} +
+ ${$(el).html() ?? ''} +
+ `); + // width=128 is a fallback for the reader mode, because it ignores the CSS + }); + }); +} diff --git a/web/html-postprocessors/tsconfig.json b/web/html-postprocessors/tsconfig.json new file mode 100644 index 0000000..4ab48f4 --- /dev/null +++ b/web/html-postprocessors/tsconfig.json @@ -0,0 +1,13 @@ +{ + "include": [ + "*.ts" + ], + "exclude": [], + "compilerOptions": { + "module": "CommonJS", + "outDir": ".", + "lib": [ + "ES2021" + ] + } +}