Overview
I enabled initial angle settings in the Mirador 4 plugin for rotating images at arbitrary angles.
The repository is here.
https://github.com/nakamura196/mirador-rotation-plugin
The demo page is here. You can rotate images with initial settings for angle and bounding box.
https://nakamura196.github.io/mirador-rotation-plugin/

Background
The following article explains this plugin.
However, there was an issue where initial angle values could not be provided.
As introduced in the following article, it appeared that Mirador 4’s standard functionality allows providing initial angle values.
Additionally, since the “mirador-image-tools” plugin had been changed from webpack to Vite, I decided to reflect this change in “mirador-rotation-plugin” as well.
https://github.com/ProjectMirador/mirador-image-tools
Publishing on GitHub Pages
For publishing on GitHub Pages, I modified the vite.config.js from “mirador-image-tools” as follows. This allows creating a directory for GitHub Pages deployment using npm run build:demo.
https://github.com/nakamura196/mirador-rotation-plugin/blob/main/vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import fs from 'fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'url';
import { globSync } from 'glob';
import pkg from './package.json';
/**
* Vite configuration
*/
export default defineConfig({
base: process.env.GITHUB_PAGES ? (process.env.BASE_PATH || '/mirador-rotation-plugin/') : '/',
...(
process.env.GITHUB_PAGES ? {
build: {
outDir: 'dist',
emptyOutDir: true,
rollupOptions: {
external: ['__tests__/*', '__mocks__/*'],
input: fileURLToPath(new URL('./demo/src/index.html', import.meta.url)),
},
sourcemap: true,
},
} :
{
build: {
lib: {
entry: './src/index.js',
fileName: (format) => (format === 'umd' ? 'mirador-rotation.js' : 'mirador-rotation.es.js'),
formats: ['es', 'umd'],
name: 'MiradorDlPlugin',
},
rollupOptions: {
external: [...Object.keys(pkg.peerDependencies || {}), '__tests__/*', '__mocks__/*'],
output: {
assetFileNames: 'mirador-rotation.[ext]',
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
sourcemap: true,
},
}
),
esbuild: {
exclude: [],
// Matches .js and .jsx in __tests__ and .jsx in src
include: [/__tests__\/.*\.(js|jsx)$/, /src\/.*\.jsx?$/],
loader: 'jsx',
},
optimizeDeps: {
esbuildOptions: {
plugins: [
{
name: 'load-js-files-as-jsx',
// TODO: rename all our files to .jsx ...
setup(build) {
build.onLoad({ filter: /(src|__tests__)\/.*\.js$/ }, async (args) => ({
contents: await fs.readFile(args.path, 'utf8'),
loader: 'jsx',
}));
},
},
],
},
},
plugins: [
react(),
// Add custom plugin to fix directory structure
{
name: 'fix-output-structure',
closeBundle: async () => {
if (process.env.GITHUB_PAGES) {
const distDir = path.resolve('dist');
const demoSrcDir = path.resolve(distDir, 'demo', 'src');
// Check if demo/src/ directory exists
try {
const demoSrcStats = await fs.stat(demoSrcDir);
if (demoSrcStats.isDirectory()) {
console.log('Moving files from demo/src to root directory...');
// Get file list in demo/src
const files = await fs.readdir(demoSrcDir);
// Move each file to root directory
for (const file of files) {
const srcPath = path.join(demoSrcDir, file);
const destPath = path.join(distDir, file);
const stats = await fs.stat(srcPath);
if (stats.isFile()) {
await fs.copyFile(srcPath, destPath);
console.log(`Copied: ${srcPath} -> ${destPath}`);
}
}
console.log('Files moved successfully.');
// Remove demo/src hierarchy (optional)
// await fs.rm(demoSrcDir, { recursive: true, force: true });
// await fs.rm(path.resolve(distDir, 'demo'), { recursive: true, force: true });
// console.log('Removed original directory structure.');
}
} catch (err) {
if (err.code !== 'ENOENT') {
console.error('Error processing output files:', err);
}
}
}
}
}
],
resolve: {
alias: {
'@tests/': fileURLToPath(new URL('./__tests__', import.meta.url)),
},
},
server: {
open: '/demo/src/index.html',
port: '4446',
},
});
Summary
We hope this is helpful for Mirador 4 plugin development.
Note that Mirador 4 is progressing toward React 19 support, and the plugin will also need to be updated for React 19 in the future.
https://github.com/ProjectMirador/mirador/releases/tag/v4.0.0-alpha.16
Once development of Mirador and the mirador-image-tools plugin advances, I would like to update this module for React 19 support as well.