ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
DTS Viewer の改善 ― 複数 Citation Tree 対応・階層ナビゲーション・XML ブラウザ表示

DTS Viewer の改善 ― 複数 Citation Tree 対応・階層ナビゲーション・XML ブラウザ表示

はじめに 前回の記事で、校異源氏物語テキストDB用 DTS API を 1.0 仕様に対応させ、和歌(短歌)の Citation Tree を追加しました。 本記事では、そのAPIを利用するビューアアプリ「DTS Viewer」側で行った改善について紹介します。 主な改善点は以下の3つです。 複数 Citation Tree への対応 ― tree パラメータの正しい受け渡し ナビゲーション結果の階層表示 ― カード形式からテーブル形式への変更 XML のブラウザ内表示 ― mediaType パラメータの活用 1. 複数 Citation Tree への対応 問題 DTS 1.0 では、1つのリソースに複数の Citation Tree を定義できます。校異源氏物語では「ページ/行」と「和歌」の2つのツリーを持っています。 しかし、ビューアのナビゲーションリンクが tree パラメータを付与していなかったため、和歌ツリーのリンクをクリックしてもデフォルト(ページ/行)のナビゲーションが表示される問題がありました。 対応 Citation Tree の identifier を追跡し、ナビゲーション URL に &tree=${identifier} を付与するようにしました。 const getNavigationUrl = (navigation: string, url: string, level: number, tree?: string) => { navigation = decodeURIComponent(navigation); navigation = removeVars(navigation) + `&down=${level}`; if (tree) { navigation += `&tree=${tree}`; } const combined = getDomain(url) + navigation; return encodeURIComponent(combined); }; ツリー構造の視覚化 各 Citation Tree をツリー形式で表示し、description ラベルで区別できるようにしました。 リソース詳細ページ。「ページ・行による引用構造」と「和歌(短歌)による引用構造」が視覚的に分かれて表示されている。 ...

JavaScriptの演算子優先順位の罠 - Vercelビルドエラーの原因を探る

JavaScriptの演算子優先順位の罠 - Vercelビルドエラーの原因を探る

はじめに Next.jsアプリケーションをVercelにデプロイしようとしたところ、ローカルでは成功するのにVercelでは失敗するという問題に遭遇しました。エラーメッセージは曖昧で、原因の特定に苦労しました。 この記事では、問題の発見から解決までの過程を共有し、JavaScriptの演算子優先順位について学んだことをまとめます。 問題の症状 エラーメッセージ Error occurred prerendering page "/en/smells/22-03" [Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details.] 特徴的な現象 ローカルビルドは成功 するが、Vercelでは失敗 毎回異なるページ でエラーが発生(22-03、24-03、25-04など) エラーの詳細が本番ビルドでは隠される 原因の発見 複数のファイルを調査する中で、以下のコードパターンを発見しました: const origin = process.env.NEXT_PUBLIC_SITE_URL || '' + process.env.NEXT_PUBLIC_BASE_PATH || ''; 一見問題なさそうに見えますが、ここに演算子優先順位の罠 が潜んでいました。 演算子優先順位とは JavaScriptでは、演算子には優先順位があります。数学で「掛け算は足し算より先に計算する」のと同じです。 優先順位の例 // 数学と同じ 2 + 3 * 4 // → 2 + 12 → 14(3 * 4 が先) // 文字列連結 (+) と論理和 (||) の場合 // + の優先順位: 13 // || の優先順位: 5 // → + が先に評価される! 問題のコードを分解 const origin = process.env.NEXT_PUBLIC_SITE_URL || '' + process.env.NEXT_PUBLIC_BASE_PATH || ''; このコードは以下のように解釈されます: ...

@elastic/react-search-ui を React 19 + Next.js 15.5 で使う方法

@elastic/react-search-ui を React 19 + Next.js 15.5 で使う方法

はじめに React 19 と Next.js 15 を使用しているプロジェクトで @elastic/react-search-ui を使おうとすると、以下のような依存関係エラーに遭遇することがあります。 npm error ERESOLVE could not resolve npm error peer react@">= 16.8.0 < 19" from @elastic/react-search-ui@1.23.1 この記事では、この問題の原因と解決方法を詳しく解説します。 問題の原因 @elastic/react-search-ui@1.23.1 の peer dependency が react@">= 16.8.0 < 19" となっており、React 19 をサポートしていませんでした。 解決策 1. パッケージのアップグレード 2025年5月に PR #1162 がマージされ、React 19 がサポートされました。バージョン 1.24.2 以降を使用します。 // package.json { "dependencies": { - "@elastic/react-search-ui": "^1.23.1", - "@elastic/react-search-ui-views": "^1.23.1", - "@elastic/search-ui": "^1.23.1", + "@elastic/react-search-ui": "^1.24.2", + "@elastic/react-search-ui-views": "^1.24.2", + "@elastic/search-ui": "^1.24.2", - "next": "15.3.8", + "next": "15.5.9", } } 2. 型定義の変更への対応 1.24.2 では WithSearch コンポーネントの型定義が変更されました。SearchContextState の filters が Filter[] | undefined になっています。 ...

mirador-annotations を Mirador 4.x へ移行した記録

mirador-annotations を Mirador 4.x へ移行した記録

背景 mirador-annotations は、IIIF ビューア Mirador にアノテーション機能を追加するプラグインです。 従来のプロジェクトは以下の構成でした: ビルドツール : nwb (Create React App ベース) UI ライブラリ : Material-UI v4 Mirador : 3.x React : 17.x しかし、以下の問題が発生していました: nwb のメンテナンス停止 - nwb は長期間更新されておらず、依存関係の競合が頻発 npm install の失敗 - 古い依存関係により、新しい環境でのセットアップが困難に セキュリティ脆弱性 - 古いパッケージに多数の脆弱性警告 これらの問題を解決するため、以下への移行を決定しました: ビルドツール : Vite UI ライブラリ : MUI v7 Mirador : 4.x React : 18.x 移行作業の概要 1. ビルドツールの移行 (nwb → Vite) nwb の設定ファイルを削除し、vite.config.js を新規作成しました。 主なポイント: // vite.config.js export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ''); return { // draft-js が global を参照するため define: { global: 'globalThis', }, // 重複パッケージの解決 resolve: { dedupe: [ '@emotion/react', '@emotion/styled', 'react', 'react-dom', ], }, }; }); 2. Material-UI の移行 (v4 → v7) @material-ui/* を @mui/* に変更 makeStyles を sx prop に置き換え Grid コンポーネントの API 変更に対応 (item と xs props が size に統合) // 変更前 (MUI v4) Grid item xs={12}> // 変更後 (MUI v7) Grid size={12}> 3. Mirador 4.x への対応 Mirador 4.x では、アクションやセレクターのインポート方法が変更されました: ...

RAWGraphs 2.0 の日本語化

RAWGraphs 2.0 の日本語化

はじめに データ可視化ツール RAWGraphs を日本語化し、公開しました。 https://rawgraphs-ja.vercel.app/ RAWGraphsは、複雑なデータを美しいビジュアライゼーションに変換できるオープンソースのWebアプリケーションです。コーディング不要で、CSVやJSONデータをドラッグ&ドロップするだけで、様々なチャートを作成できます。 RAWGraphsとは RAWGraphsは、イタリアのDensityDesign Research Labが開発したデータ可視化ツールです。 https://www.rawgraphs.io/ 主な特徴: コーディング不要 : ブラウザ上でデータをペーストするだけ 多様なチャート : Alluvial Diagram、Treemap、Voronoi Tessellationなど30種類以上 SVGエクスポート : 作成したチャートをSVGやPNG形式でダウンロード可能 プライバシー保護 : データはサーバーに送信されず、ブラウザ内で処理 使用ライブラリ { "i18next": "^21.10.0", "react-i18next": "^11.18.6" } ! 最新版のi18nextではなく、互換性のある旧バージョンを使用しています。RAWGraphsのビルド環境(react-scripts 4.x)がオプショナルチェーニング(?.)構文を完全にサポートしていないためです。 実装手順 1. i18nの初期化 src/i18n.js を作成し、多言語対応の基盤を構築しました。 import i18n from 'i18next' import { initReactI18next } from 'react-i18next' import translationEN from './locales/en/translation.json' import translationJA from './locales/ja/translation.json' const resources = { en: { translation: translationEN }, ja: { translation: translationJA } } const savedLanguage = localStorage.getItem('i18nextLng') || 'ja' i18n .use(initReactI18next) .init({ resources, lng: savedLanguage, fallbackLng: 'en', interpolation: { escapeValue: false } }) i18n.on('languageChanged', (lng) => { localStorage.setItem('i18nextLng', lng) }) export default i18n 2. 翻訳ファイルの構造 src/locales/ ├── en/ │ └── translation.json └── ja/ └── translation.json 翻訳ファイルは、セクションごとに整理しました: ...

れきちずをNext.jsで使用する

れきちずをNext.jsで使用する

概要 れきちずをNext.jsで使用する方法を調べてみましたので、備忘録です。 背景 以下の記事で、「れきちず」の使い方を紹介しました。 そして、2025年4月4日に「全国版が公開」されたことを知りました。 https://rekichizu.jp/ そこでNext.jsを用いて作成したアプリケーションへの導入にあたり、その使い方を調べてみました。 デモアプリ 以下のようなアプリケーションを試作しました。 https://rekichizu-next.vercel.app/ja/ 使用方法の調査にあたり、公式サイトで提供されている地図の切り替えや重ね合わせ機能、および検索機能などを再現することを目的としました。この実装にあたり、以下のReactライブラリを使用しました。 https://visgl.github.io/react-maplibre/ 開発メモ 検索機能 検索機能には、GeoLODのAPIを利用させていただきました。なお、「れきちず」の公式サイトでは、専用の検索APIが用いられているようでした。 https://geolod.ex.nii.ac.jp/doc/api/ react-maplibre 本ライブラリを使用して、やりたいことの多くを実現できました。一方、TerrainControlではTerrainのON/OFFと合わせてピッチを変更することが難しい?、useMapではaddLayer/removeLayerが難しい?など、いくつか苦労した点もありました。 まとめ 「れきちず」およびNext.jsを用いたアプリケーション開発にあたり、参考になりましたら幸いです。 「れきちず」の開発に関わる方々に深く感謝いたします。

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

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

概要 任意の角度で画像を回転するMirador 4プラグインで、角度の初期値を設定できるようにしました。 リポジトリは以下です。 https://github.com/nakamura196/mirador-rotation-plugin デモページは以下です。角度および矩形を初期設定とともに、画像を回転させることができます。 https://nakamura196.github.io/mirador-rotation-plugin/ 背景 以下の記事で、本プラグインについて説明しています。 一方、課題として、角度の初期値を与えることができませんでした。 これに対して、以下の記事で紹介したように、Mirador 4の標準機能として、角度の初期値を与えることができるようでした。 合わせて、以下の「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のプラグイン開発にあたり、参考になりましたら幸いです。 ...

Next.js + CETEIcean + React TEI Routerを使ったビューア開発

Next.js + CETEIcean + React TEI Routerを使ったビューア開発

概要 Next.js、CETEIcean、React TEI Routerを組み合わせたTEI/XMLビューアの開発についての備忘録です。 背景 CETEIceanは、TEI/XML を HTML5 に変換する JavaScript ライブラリです。 https://github.com/TEIC/CETEIcean そして、React TEI Routerは、CETEIcean をベースに React コンポーネントで TEI/XML を構造化して表示できるライブラリです。以下のように説明されています。 https://github.com/pfefferniels/react-teirouter TEI for React using CETEIcean and routes これらを組み合わせることで、Next.js において TEI/XML をカスタマイズして表示できるビューア を作成しました。 リポジトリ 以下がサンプルリポジトリです。 https://github.com/nakamura196/next-ceteicean-router 実際に動作するデモも用意しています。 https://next-ceteicean-router.vercel.app/ 実装 Next.js のページコンポーネント (page.tsx) CETEIcean を利用して XML を変換し、カスタムコンポーネントで描画します。 import React from "react"; import Render from "@/components/tei"; export default function App() { const xmlContent = `<?xml version="1.0" encoding="UTF-8"?> <TEI xmlns="http://www.tei-c.org/ns/1.0"> <text> <body> <div type="original"> 私の名前は<persName corresp="#id1">田中太郎</persName>です。 </div> <div> <p style="color: green;">こんにちは</p> <p style="color: green;">こんばんは <seg style="color: blue;">xxx</seg> </p> </div> </body> </text> </TEI>`; return <Render xmlContent={xmlContent} />; } TEIレンダリングコンポーネント CETEIcean を使って XML を HTML5 に変換。 TEIRender + TEIRoute を使い、TEI 要素ごとにカスタムコンポーネントを適用。 import { TEIRender, TEIRoute } from "react-teirouter";を使用した上で、要素毎にコンポーネントを用意しています。 ...

Next.jsで多言語対応の静的サイトを構築する

Next.jsで多言語対応の静的サイトを構築する

はじめに この記事は、GPT-4oによって生成された内容です。Next.jsを使用して多言語対応の静的サイトを構築する方法について説明します。特に、メイン言語にはURLプレフィックスを付けず、その他の言語にはプレフィックスを付ける設定に焦点を当てます。GitHub Pagesを使用してデプロイする設定も含まれています。 プロジェクトのセットアップ まず、Next.jsのプロジェクトを作成します。create-next-appを使用してプロジェクトを初期化します。 npx create-next-app@latest next-intl-ssg 必要なパッケージのインストール 多言語対応のために、next-intlをインストールします。 npm install next-intl プロジェクト構成 プロジェクトのディレクトリ構成は以下の通りです。 src/app/[locale]/about/page.tsx src/app/about/page.tsx src/lib/i18n.ts src/components/I18nProvider.tsx src/i18n/ja.json src/i18n/en.json 多言語対応の実装 next-intlを使用して、言語ごとのメッセージを管理します。src/lib/i18n.tsでメッセージを取得する関数を定義しています。 export async function getMessages(locale: string) { return (await import(`@/i18n/${locale}.json`)).default; } I18nProviderコンポーネントを使用して、各ページでメッセージを提供します。 import { ReactNode } from 'react'; import { NextIntlClientProvider } from 'next-intl'; export default function I18nProvider({ children, locale, messages }: { children: ReactNode; locale: string; messages: Record<string, Record<string, string>>; }) { return ( <NextIntlClientProvider locale={locale} messages={messages}> {children} </NextIntlClientProvider> ); } SSGの設定 generateStaticParams関数を使用して、静的ページを生成する際のパラメータを設定します。メイン言語(日本語)にはプレフィックスを付けず、その他の言語にはプレフィックスを付けます。 // src/app/[locale]/about/page.tsx export function generateStaticParams() { return locales.filter(locale => locale !== 'ja').map(locale => ({ locale })); } GitHub Pagesへのデプロイ GitHub Actionsを使用して、GitHub Pagesにデプロイします。.github/workflows/deploy.ymlでデプロイの設定を行います。 name: Deploy to GitHub Pages on: push: branches: [main] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" - name: Install dependencies run: npm ci - name: Build run: npm run build - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./out deploy: environment: github-pages runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 リンク GitHubリポジトリ: next-intl-ssg GitHub Pages: next-intl-ssg まとめ このブログでは、Next.jsを使用して多言語対応の静的サイトを構築し、メイン言語にはプレフィックスを付けず、その他の言語にはプレフィックスを付ける方法を紹介しました。next-intlを活用することで、簡単に多言語対応が可能になります。ぜひ試してみてください。 ...

Mirador3のFirebase連携annotationsプラグインにおいて、メールアドレスによる登録を可能にしました。

Mirador3のFirebase連携annotationsプラグインにおいて、メールアドレスによる登録を可能にしました。

概要 Mirador3のFirebase連携annotationsプラグインを開発しています。 こちらについて、これまではGoogleアカウントによるログイン機能のみを提供していましたが、メールアドレスによるログイン機能を追加しました。 機能紹介 以下、ログインボタンを押した場合です。 メールアドレスによるログインの場合、アカウントの新規作成が可能です。 ログイン後、ユーザに関する情報を表示するようにしました。 アイコンをクリックすると、ログアウトボタンが表示されます。 まとめ IIIFを用いたアノテーションの作成と共有において、参考になりましたら幸いです。

Next 15(React 19 を使用)で、@react-three/fiberとdreiを使う

Next 15(React 19 を使用)で、@react-three/fiberとdreiを使う

概要 Next 15(React 19 を使用)で、@react-three/fiberを使う際、以下のように説明されています。 R3F v8 is not compatible with React 19 or Next 15, which uses React 19. Use the R3F v9 RC instead which can be installed with @react-three/fiber@rc. (日本語訳)R3F v8 は React 19 や Next 15(React 19 を使用)と互換性がありません。代わりに R3F v9 RC を使用してください。インストールするには @react-three/fiber@rc を使用してください。 一方、マウス操作を行うために以下を追加しましたが、@react-three/fiber@rcとは相性が悪いようでした。 https://www.npmjs.com/package/@react-three/drei この問題に対する対処法の備忘録です。 方法 本記事執筆時点(2025-02-06)の情報です。 まず、@react-three/fiber@rcではなく、@react-three/fiber@alphaをインストールする必要がありました。(@betaでもよいかもしれません。) そして、dreiについては、@react-three/drei@10.0.0-rc.1をインストールしました。結果、以下のような組み合わせでは、無事にインストールすることができました。 "@react-three/drei": "^10.0.0-rc.1", "@react-three/fiber": "^9.0.0-alpha.8", まとめ 考慮が不十分な点があるかもしれませんが、参考になりましたら幸いです。

aleph-r3fを試す

aleph-r3fを試す

概要 以下の記事で、Aleph 3D viewerを紹介しました。 その後調べた結果、以下のリポジトリの存在も知りました。 https://github.com/aleph-viewer/aleph-r3f 以下のように説明されており、react-three-fiberとshadcn/uiを使用している点に違いがあるようでした。 Aleph is a 3D object viewer and annotation/measurement tool built with react-three-fiber and shadcn/ui 以下のように、アノテーション付与機能なども改良されているようでした。 今回の記事でも、菊池市デジタルアーカイブで公開されている「石淵家地球儀」の3Dデータを使用します。 https://adeac.jp/kikuchi-city/catalog/e0001 使い方 以下で閲覧いただけます。 https://iiif-aleph-r3f.vercel.app/ アノテーションタブで、アノテーションの付与を行うことができました。 アノテーションデータのインポート/エクスポートを行うことができ、JSON形式でのエクスポート結果は以下でした。 [ { "position": { "x": -0.06690392681702004, "y": 0.6256817352784154, "z": -0.7424544387001097 }, "normal": { "x": -0.11627753958254597, "y": 0.6430031011979032, "z": -0.7569851687044529 }, "cameraPosition": { "x": -0.15922188799592055, "y": 1.1767071158114843, "z": -1.4378842144444104 }, "cameraTarget": { "x": -0.0023649930953979492, "y": -0.0009789466857910165, "z": -0.011684000492095947 }, "rotation": { "isEuler": true, "_x": 0, "_y": 0, "_z": 0, "_order": "XYZ" }, "label": "大西洋", "description": "初めてのアノテーション" } ] カスタマイズ 「石淵家地球儀」を表示するにあたり、以下のようにソースコードを編集する必要がありました。 import './App.css'; import { useEffect, useRef } from 'react'; ... const [{ src }, _setLevaControls] = useControls(() => ({ src: { options: { // 'Measurement Cube': { // url: 'https://cdn.glitch.global/afd88411-0206-477e-b65f-3d1f201de994/measurement_cube.glb?v=1710500461208', // label: 'Measurement Cube', // }, 石淵家地球儀: 'https://sukilam.aws.ldas.jp/files/original/253efdf34478459954ae04f6b3befa5f3822ed59.glb', 'Flight Helmet': 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/FlightHelmet/glTF/FlightHelmet.gltf', ... また、Vercelへのデプロイにあたり、以下のように、tailwind.config.jsを修正する必要がありました。 ...

Mirador3プラグイン開発: ウインドウをコピーする

Mirador3プラグイン開発: ウインドウをコピーする

概要 Mirador3のプラグインとして、ウインドウをコピーするプラグインを作成しました。 なお本機能は以下のプラグインですでに提供されているものです。 https://github.com/ProjectMirador/mirador-plugin-demos そのため、本プラグインはプラグインの開発手順を学ぶために作成しています。そのような観点で、本プラグインが参考になりましたら幸いです。 画面例は以下です。 ソースコードは以下です。 https://github.com/nakamura196/mirador-copy-window-plugin デモサイトは以下です。 https://nakamura196.github.io/mirador-copy-window-plugin/ 開発メモ 本プラグインの開発にあたり、まず以下のリポジトリをcloneし、変更を加えていきました。 https://github.com/ProjectMirador/mirador-dl-plugin src/index.js まず以下のファイルについて、miradorDownloadをMiradorCopyWindowに書き換えました。 https://github.com/nakamura196/mirador-copy-window-plugin/blob/main/src/index.js src/MiradorCopyWindow.js 以下のファイルが主に編集するファイルです。 https://github.com/nakamura196/mirador-copy-window-plugin/blob/main/src/MiradorCopyWindow.js 本ファイルは、まず以下のファイルの内容をコピーしました。 https://github.com/ProjectMirador/mirador-plugin-demos/blob/master/src/plugins/copy-window.js まず末尾の以下の記述から説明します。 export default { target: 'WindowTopMenu', mode: 'add', component: CopyWindowComponent, mapDispatchToProps: mapDispatchToProps, mapStateToProps: mapStateToProps, } targetとmode targetはコンポーネントを設置する場所を指定します。またmodeはコンポーネントの追加方法を指定します。modeについては、addやwrapという選択肢があるようでした。 以下、targetの値の例です。 WindowTopMenu 各ウインドウ上部のメニューの部分です。 WorkspaceControlPanelButtons ワークスペースのパネル部分です。 AnnotationSettings アノテーションの設定画面です。 最後のAnnotationSettingsおよびmodeにwrapが指定されているプラグインとして、以下のMiradorのアノテーション付与モジュールがありました。 https://github.com/ProjectMirador/mirador-annotations/blob/master/src/plugins/miradorAnnotationPlugin.js mapDispatchToPropsとmapStateToProps これがはじめ理解しづらかった(そしてまだ適切に説明できるほど理解できていない)のですが、propsに渡すdispathとstateを定めた変数を指定します。 dispatchについては、以下の変数を与えてます。 const mapDispatchToProps = (dispatch, { windowId }) => ({ copyWindow: () => dispatch(copyWindowAction(windowId)), }); copyWindowActionの具体的な内容は以下です。既存のwindowを取得して(1)、不要な変数を削除した上でwindowをコピーして(2)、それをaddWindow(3)しています。 const copyWindowAction = (windowId) => (dispatch, getState) => { const window = getState().windows[windowId]; // 1 const cleanedWindow = omit(window, [ 'id', 'companionWindowIds', 'thumbnailNavigationId', ]); // 2 dispatch(mirador.actions.addWindow(cleanedWindow)); // 3 }; stateについては、以下の変数を与えています。以下の例は少し特殊で、stateをすべてpropsに渡す設定となっています。他のプラグインでは、必要な値のみをstateから抽出して、propsに渡しているようでした。 const mapStateToProps = (state) => ({ state: state, }); 実際、本プラグインでは、mapStateToPropsでpropsに渡された値は使用されていないため、この記述はなくてもよいはずです。そのため、以下でもmapStateToPropsの記述は省略しています。 https://github.com/nakamura196/mirador-copy-window-plugin/blob/main/src/MiradorCopyWindow.js component 最後にcomponentです。以下のように、コンポーネントで表示する内容を記述しています。 ...

onClose propを使用する

onClose propを使用する

MUIのDialogコンポーネントにおいてonBackdropClickを使用したところ、以下の警告が発生しました。 Warning: Failed prop type: The prop `onBackdropClick` of `ForwardRef(Dialog)` is deprecated. Use the onClose prop with the `reason` argument to handle the `backdropClick` events. 警告メッセージは、Dialogコンポーネントの非推奨のprop onBackdropClickに関するものです。これは、このpropがあなたのコードのどこかで使用されているが、もはやサポートされていないか、使用が推奨されていないことを意味します。警告は代わりにonClose propを使用するように提案しています。 これを解決する方法は以下の通りです: 以前は、コードに以下のようなものがあったかもしれません: <Dialog open={isOpen} onBackdropClick={handleBackdropClick} > { /* ダイアログの内容 */ } </Dialog> 警告に従って、これをonClose propを使用するように更新する必要があります: <Dialog open={isOpen} onClose={(event, reason) => { if (reason === 'backdropClick') { handleBackdropClick(); } }} > { /* ダイアログの内容 */ } </Dialog> 上記のコードでは、onClose propは関数を取り、eventとreasonという2つの引数を受け取ります。reasonは’backdropClick’、’escapeKeyDown’、またはundefinedになる可能性があります。reasonが’backdropClick’かどうかをチェックすることで、ユーザーがダイアログボックスの外側をクリックしたときに関数handleBackdropClick()を実行できます。 以上のようにコードを更新すると、警告は表示されなくなりました。 ...