Files
mastodon/config/vite/plugin-assets-manifest.ts
jcoffey-dev 319ed76dbd
Crowdin / Upload translations / upload-translations (push) Skipped
Historical data migration test / test (14-alpine) (push) Canceled after 0s
Historical data migration test / test (15-alpine) (push) Canceled after 0s
Historical data migration test / test (16-alpine) (push) Canceled after 0s
Historical data migration test / test (17-alpine) (push) Canceled after 0s
Bundler Audit / security (push) Canceled after 0s
Haml Linting / lint (push) Canceled after 0s
JavaScript Linting / lint (push) Canceled after 0s
Ruby Linting / lint (push) Canceled after 0s
JavaScript Testing / test (push) Canceled after 0s
Ruby Testing / build (production) (push) Canceled after 0s
Ruby Testing / test (.ruby-version) (push) Canceled after 0s
Ruby Testing / test (3.3) (push) Canceled after 0s
Ruby Testing / test (3.4) (push) Canceled after 0s
Ruby Testing / End to End testing (.ruby-version) (push) Canceled after 0s
Ruby Testing / End to End testing (3.3) (push) Canceled after 0s
Ruby Testing / End to End testing (3.4) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check i18n / check-i18n (push) Canceled after 0s
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (javascript) (push) Canceled after 0s
CodeQL / Analyze (ruby) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.4, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check formatting / lint (push) Canceled after 0s
CSS Linting / lint (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.19.2) (push) Canceled after 0s
Chromatic / Check for relevant changes (push) Canceled after 0s
Chromatic / Run Chromatic (push) Canceled after 0s
Import Mastodon v4.7.3
Snapshot of upstream tag v4.7.3 (commit 8ff11c2bb7b9f0714e947b10fa3629c6542c7121) from
https://github.com/mastodon/mastodon, unmodified.
2026-10-05 22:03:13 -07:00

85 lines
2.4 KiB
TypeScript

// Heavily inspired by https://github.com/ElMassimo/vite_ruby
import { createHash } from 'node:crypto';
import fs from 'node:fs/promises';
import path from 'node:path';
import glob from 'fast-glob';
import type { Plugin } from 'vite';
interface AssetManifestChunk {
file: string;
integrity: string;
}
const ALGORITHM = 'sha384';
export function MastodonAssetsManifest(): Plugin {
let manifest: string | boolean = true;
let jsRoot = '';
return {
name: 'mastodon-assets-manifest',
applyToEnvironment(environment) {
return !!environment.config.build.manifest;
},
configResolved(resolvedConfig) {
manifest = resolvedConfig.build.manifest;
jsRoot = resolvedConfig.root;
},
async generateBundle() {
// Glob all assets and return an array of absolute paths.
const assetPaths = await glob('{fonts,icons,images}/**/*', {
cwd: jsRoot,
absolute: true,
});
const assetManifest: Record<string, AssetManifestChunk> = {};
const excludeExts = ['', '.md'];
for (const file of assetPaths) {
// Exclude files like markdown or README files with no extension.
const ext = path.extname(file);
if (excludeExts.includes(ext)) {
continue;
}
// Read the file and emit it as an asset.
const contents = await fs.readFile(file);
const ref = this.emitFile({
name: path.basename(file),
type: 'asset',
source: contents,
});
const hashedFilename = this.getFileName(ref);
// With the emitted file information, hash the contents and store in manifest.
const name = path.relative(jsRoot, file);
const hash = createHash(ALGORITHM)
.update(contents)
.digest()
.toString('base64');
assetManifest[name] = {
file: hashedFilename,
integrity: `${ALGORITHM}-${hash}`,
};
}
if (Object.keys(assetManifest).length === 0) {
console.warn('Asset manifest is empty');
return;
}
// Get manifest location and emit the manifest.
const manifestDir =
typeof manifest === 'string' ? path.dirname(manifest) : '.vite';
const fileName = `${manifestDir}/manifest-assets.json`;
this.emitFile({
fileName,
type: 'asset',
source: JSON.stringify(assetManifest, null, 2),
});
},
};
}