Zenn
🦁

Mirador 4プラグイン開発:任意の角度で画像を回転するプラグインで、角度の初期値を設定できるようにしました。

2025/03/26に公開

概要

任意の角度で画像を回転するMirador 4プラグインで、角度の初期値を設定できるようにしました。

リポジトリは以下です。

https://github.com/nakamura196/mirador-rotation-plugin

デモページは以下です。角度および矩形を初期設定とともに、画像を回転させることができます。

https://nakamura196.github.io/mirador-rotation-plugin/

背景

以下の記事で、本プラグインについて説明しています。

https://zenn.dev/nakamura196/articles/de5a391597b8a5

一方、課題として、角度の初期値を与えることができませんでした。

これに対して、以下の記事で紹介したように、Mirador 4の標準機能として、角度の初期値を与えることができるようでした。

https://zenn.dev/nakamura196/articles/9e70d8f8af0283

合わせて、以下の「mirador-image-tools」プラグインについて、webpackからViteに変更されていたので、この変更を「mirador-rotation-plugin」にも反映することにしました。

https://github.com/ProjectMirador/mirador-image-tools

GitHub Pagesでの公開

GitHub Pagesでの公開にあたり、「mirador-image-tools」のvite.config.jsを以下のように変更しています。これで、npm run build:demoにより、GitHub Pagesで公開するためのディレクトリを作成することができるようになりました。

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(),
    // カスタムプラグインを追加してディレクトリ構造を修正
    {
      name: 'fix-output-structure',
      closeBundle: async () => {
        if (process.env.GITHUB_PAGES) {
          const distDir = path.resolve('dist');
          const demoSrcDir = path.resolve(distDir, 'demo', 'src');
          
          // demo/src/ディレクトリが存在するか確認
          try {
            const demoSrcStats = await fs.stat(demoSrcDir);
            if (demoSrcStats.isDirectory()) {
              console.log('Moving files from demo/src to root directory...');
              
              // demo/src内のファイルリストを取得
              const files = await fs.readdir(demoSrcDir);
              
              // 各ファイルをルートディレクトリに移動
              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.');
              
              // demo/src階層を削除(オプション)
              // 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',
  },
});

まとめ

Mirador 4のプラグイン開発にあたり、参考になりましたら幸いです。

なお、Mirador 4がReact 19への対応を進めており、今後プラグインのほうも19に対応する必要がありそうです。

https://github.com/ProjectMirador/mirador/releases/tag/v4.0.0-alpha.16

Miradorやmirador-image-toolsプラグインの開発が進んだら、本モジュールもReact 19への対応を行いたいと思います。

Discussion

ログインするとコメントできます