TEI Garage APIを使って、DOCX → TEI/XML 変換ツールをブラウザだけで作った

はじめに TEI (Text Encoding Initiative) は、人文学分野のテキストをデジタルで構造化するための国際標準です。図書館・博物館・学術研究などで利用されていますが、TEI/XML を直接書くにはマークアップの知識が必要で、導入のハードルが高いのが実情です。 そこで活用されるのが、Microsoft Word (.docx) から TEI/XML への変換ツールです。代表的なものに TEI Garage(旧 OxGarage)がありますが、多機能ゆえに UI がやや複雑です。今回、DOCX → TEI/XML の変換に特化した、シンプルなブラウザベースのツールを作成しました。 https://github.com/nakamura196/tei-converter デモサイト: https://tei-converter.pages.dev/ 仕組み TEI Garage は REST API を公開しており、以下のエンドポイントに DOCX ファイルを POST するだけで TEI/XML が返ってきます。 P O S d T T o E c I h x : t : t t a e p p x s p t : l : / i x / c m t a l e t / i i g o a n r : a v g n e d . . t o e p i e - n c x . m o l r f g r e m g a e t - s w - e o b f s f e i r c v e i d c o e c / u C m o e n n v t e . r w s o i r o d n p s r / o c e s s i n g m l . d o c u m e n t / 本ツールはこの API を呼び出すフロントエンドです。変換処理自体は TEI Consortium が運営するサーバ上で行われます。 ...

2026年3月1日 · 2 分 · Nakamura

はてなブログの記事を一括で非公開にする方法(AtomPub API)

はてなブログの記事を別サイトに移行した後、旧記事を一括で非公開にしたいケースがあります。 注意点:下書きには戻せない はてなブログのAtomPub APIでは、公開済みの記事を下書き(draft)に戻すことはできません。PUTリクエストで <app:draft>yes</app:draft> を送ると 400 Cannot Change into Draft エラーになります。 そのため、以下の2つの方法があります。 方法1:記事本文を「移転しました」に書き換える AtomPub APIのPUTで記事の <content> を書き換えることは可能です。 import requests import xml.etree.ElementTree as ET import time HATENA_ID = "your_hatena_id" BLOG_ID = "your_blog_id.hatenablog.com" API_KEY = "your_api_key" NEW_SITE_URL = "https://your-new-site.com" ATOM_NS = "http://www.w3.org/2005/Atom" def fetch_all_entries(): entries = [] url = f"https://blog.hatena.ne.jp/{HATENA_ID}/{BLOG_ID}/atom/entry" while url: resp = requests.get(url, auth=(HATENA_ID, API_KEY), timeout=30) resp.raise_for_status() root = ET.fromstring(resp.text) for entry in root.findall(f"{{{ATOM_NS}}}entry"): title_el = entry.find(f"{{{ATOM_NS}}}title") title = title_el.text or "" if title_el is not None else "" edit_link = entry.find(f"{{{ATOM_NS}}}link[@rel='edit']") edit_url = edit_link.get("href") if edit_link is not None else None if edit_url: entries.append({"title": title, "edit_url": edit_url}) next_el = root.find(f"{{{ATOM_NS}}}link[@rel='next']") url = next_el.get("href") if next_el is not None else None return entries def replace_content(entry): title = entry["title"] update_xml = f"""<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app"> <title>{title}</title> <content type="text/plain">この記事は {NEW_SITE_URL} に移転しました。</content> </entry>""" resp = requests.put( entry["edit_url"], auth=(HATENA_ID, API_KEY), data=update_xml.encode("utf-8"), headers={"Content-Type": "application/atom+xml; charset=utf-8"}, timeout=30, ) return resp.status_code entries = fetch_all_entries() print(f"Found {len(entries)} entries") for i, e in enumerate(entries): status = replace_content(e) print(f"[{i+1}/{len(entries)}] {status}: {e['title'][:50]}") time.sleep(0.5) 方法2:はてなブログの管理画面から一括削除 記事数が少なければ、管理画面の「記事の管理」から手動で削除する方法もあります。ただし一括選択機能がないため、大量の記事には向きません。 ...

2026年3月1日 · 1 分 · Nakamura

Hypothes.is APIでWebアノテーションをエクスポートしてTEI/XMLに変換する

はじめに Hypothes.isは、Webページ上にハイライトやコメントを付けられるオープンソースのアノテーションツールです。ブラウザ拡張やJavaScriptの埋め込みで手軽に使えますが、蓄積したアノテーションをバックアップしたい、あるいはTEI/XMLなど別の形式で活用したいケースもあります。 本記事では、Hypothes.is APIを使ってアノテーションをエクスポートし、TEI/XMLに変換する方法を紹介します。 APIキーの取得 Hypothes.isにログイン Developer settings にアクセス 「Generate your API token」でAPIキーを生成 取得したキーを.envファイルに保存します。 c # p . . e e n n v v . を e 編 x 集 a し m て p A l P e I キ . ー e を n 設 v 定 H Y P O T H E S I S _ A P I _ K E Y = x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x アノテーションのエクスポート APIの基本 Hypothes.is APIのベースURLは https://api.hypothes.is/api です。認証はAuthorization: Bearer <API_KEY>ヘッダーで行います。 ...

2026年2月28日 · 14 分 · Nakamura

OpenITI mARkdownからTEI XMLへの自動変換ツール「oitei」を試す

はじめに イスラーム圏の歴史テキストを扱う OpenITI(Open Islamicate Texts Initiative) プロジェクトでは、TEI/XMLの代わりに mARkdown という軽量記法でテキストをタグ付けできます。 TEI/XMLは構造化の国際規格として強力ですが、特にアラビア語のような右から左に書く言語(RTL)では、XMLタグとの混在でエディタ上の表示が乱れるという問題があります。mARkdownはこの課題を解決する記法です。 本記事では、mARkdownで書かれたテキストを TEI XMLに自動変換 するPythonツール oitei を実際に動かしてみます。 oiteiとは OpenITI mARkdown → TEI XML の変換ライブラリ(Python) OpenITI TEI Schema に準拠したXMLを出力 PyPIで公開されており pip install で導入可能 依存ライブラリ: oimdp(mARkdownパーサー)、lxml https://github.com/OpenITI/oitei インストール p i p i n s t a l l o i t e i Python 3.8以上が必要です。oimdp(OpenITI mARkdown Parser)と lxml が依存関係として自動インストールされます。 OpenITI mARkdownの記法 mARkdownファイルは以下の3部構成です。 マジックバリュー (1行目): ######OpenITI# メタデータ : #META# で始まる行 本文 : #META#Header#End# の後に記述 主なタグ 記法 意味 `### ` `### ### $ 伝記エントリ # 段落の開始 @P02 名前 人物名(後続2語を含む) @T11 地名 地名(後続1語を含む) @YB732 誕生年(ヒジュラ暦732年) @YD808 没年(ヒジュラ暦808年) %~% 詩行(hemistich)の区切り 固有表現タグ(@P, @T 等)の後ろの 2桁の数字 は、1桁目がエンティティ番号、2桁目が「後続する何単語を名前に含むか」を指定します。例えば @P02 Ibn Khaldun は「後続2語(Ibn Khaldun)を人名として含む」という意味です。 ...

2026年2月28日 · 15 分 · Nakamura

GakuNin RDM APIをNode.jsで操作する — プロジェクト作成からGitHub+Vercel自動デプロイまで

はじめに GakuNin RDMは、国立情報学研究所(NII)が提供する研究データ管理プラットフォームです。Open Science Framework(OSF)をベースに構築されており、APIを通じてプロジェクトの操作を自動化できます。 本記事では、Node.jsからGakuNin RDM APIを使って以下の操作を行う方法を紹介します。 プロジェクトの作成・設定 Wikiの作成・更新 メンバーの追加 GitHub連携 + Vercelによる自動デプロイ 事前準備 パーソナルアクセストークンの取得 GakuNin RDMにログイン 設定 > パーソナルアクセストークンに移動 新しいトークンを作成(スコープ:osf.full_read、osf.full_write) プロジェクトの初期化 m n n k p p d m m i r i i n n r i s d t t m a - l & y l & d c o d t e r n d v m .envファイルにトークンを保存します。 ...

2026年2月27日 · 12 分 · Nakamura

ethers.js v6 の日本語チュートリアルを作った

はじめに Ethereum の JavaScript ライブラリである ethers.js の日本語チュートリアルを作成しました。 https://github.com/nakamura196/ethers-ja-tutorial VitePress で静的サイトとしても公開しています。 https://nakamura196.github.io/ethers-ja-tutorial/ 作った背景 ethers.js は Ethereum 開発において最も広く使われているライブラリの一つです。v6 に関する日本語記事は v5 からのマイグレーション解説が中心で、初心者がゼロから学べる体系的なチュートリアルは見当たりませんでした。公式ドキュメントも英語のみのため、日本語で基礎から順を追って学べるチュートリアルを作成しました。 チュートリアルの内容 全 8 章構成で、基礎から実践的な内容までカバーしています。 章 テーマ 内容 1 環境構築 Node.js と ethers.js のインストール 2 プロバイダー Ethereum ネットワークへの接続 3 ウォレット ウォレットの作成と管理 4 ブロックチェーンの読み取り 残高確認・ブロック情報の取得 5 トランザクション送信 ETH の送金 6 スマートコントラクト コントラクトとのやり取り 7 イベント イベントのリスニング 8 ユーティリティ 単位変換・ハッシュなどの便利機能 特徴 すぐに動くサンプルコード付き examples/ ディレクトリに実行可能なサンプルコードを用意しています。 g c n n i d p o t m d e e c t i l h n e o e s x n r t a e s a m - l p h j l l t a e t - s p t / s u 0 : t 1 / - r c g i o i a n t l n h e u c b t . . c m o j m s / n a k a m u r a 1 9 6 / e t h e r s - j a - t u t o r i a l . g i t たとえば 01-connect.mjs を実行すると、Ethereum メインネットの最新ブロック番号やガス価格が取得できます。 ...

2026年2月25日 · 3 分 · Nakamura

Annotoriousの描画モードがproduction buildでだけ壊れる

はじめに ある日、Vercelにデプロイした IIIF アノテーションエディタで、アノテーションが一切付与できなくなっていることに気づきました。ローカルの開発サーバーでは正常に動作するのに、本番環境でだけ描画モードに入れない。コンソールエラーも出ない。UIのボタンは正しく切り替わるのに、画像上でドラッグしても何も起きない——。 原因は、package.json のキャレット指定(^)による Annotorious の自動アップグレードと、v3.7.13 での状態管理ライブラリ移行が webpack の production build で引き起こす不具合でした。 この記事では、調査過程から根本原因の特定、そして得られた教訓までをまとめます。 環境 フレームワーク : Next.js 15 (App Router) 画像ビューア : OpenSeadragon 5 アノテーション : Annotorious v3 (@annotorious/react + @annotorious/openseadragon) バンドラ : webpack(Next.js 内蔵) デプロイ先 : Vercel 症状 本番環境(Vercel)で以下の症状が発生しました。 矩形・ポリゴンの描画ツールボタンをクリックすると、UIの状態は正しく切り替わる (React の state 更新は正常) しかし Annotorious が描画モードに入らない ——カーソルが crosshair に変わらず auto のまま 画像上でクリック&ドラッグしてもアノテーションが作成されない コンソールにエラーは一切表示されない Annotorious のアノテーションレイヤー要素(a9s-gl-canvas)自体は DOM 上に正しく描画されている ローカルの next dev では完全に正常動作するため、再現が困難な状況でした。 調査過程 1. Playwright による自動テスト まず Playwright を使って、デプロイ済みサイトに対する自動テストを実施しました。 ...

2026年2月25日 · 7 分 · Nakamura

GakuNin RDM Search API (`/api/v1/search/`) 調査メモ

調査日 : 2026-02-24 対象 : GakuNin RDM (GRDM) の Search API ソースコード : RCOSDP/RDM-osf.io(website/search/ ディレクトリ) 開発者ガイド : RCOSDP/RDM-developer-guide 注意 : Search API の公式ドキュメントは確認できませんでした。本稿は API の実際の挙動とソースコードの両方に基づく調査記録です。 概要 GakuNin RDM は OSF (Open Science Framework) のフォークであり、ソースコードは GitHub (RCOSDP/RDM-osf.io) で公開されています。検索機能の実装は website/search/ ディレクトリにあり、主に以下のファイルで構成されています。 ファイル 役割 elastic_search.py インデックスのマッピング定義、ドキュメントの登録・更新 views.py API エンドポイントのハンドラ util.py build_private_search_query() 等のクエリ構築 search.py 上位インターフェース P A O u S t T h o h r t i t z p a s t : i / n r : d m B . e n a i r i e . r a c < . パ j ー p ソ / ナ a ル p ア i ク / セ v ス 1 ト / ー s ク e ン a > r c h / 日本語環境では Elasticsearch の kuromoji_analyzer が使用されています(ソースコードで確認)。 ...

2026年2月24日 · 5 分 · Nakamura

Google Workspace 管理者権限なしで Google Groups のメンバーを API で一括管理する

Google Groups のメンバーを定期的に入れ替える運用をしている組織は多いと思います。手作業での登録・削除は手間がかかるため、API で自動化したいところです。 Google Groups のメンバーを API で管理する方法としては、Admin SDK (Directory API) がよく紹介されています。一方で、Admin SDK は Google Workspace の管理者権限が必要であり、利用できる場面が限られます。 本記事では、管理者権限がない環境でも利用できる Cloud Identity Groups API を使って、Google Groups のメンバーを一括管理する方法を紹介します。 API の選択肢 Google Groups のメンバーを API で管理するには、主に以下の 2 つの方法があります。 Admin SDK (Directory API) もっとも広く紹介されている方法です。 s s e e r r v v i i c c e e . = m e b m u b i e l r d s ( ( ' ) a . d l m i i s n t ' ( , g r ' o d u i p r K e e c y t = o ' r g y r _ o v u 1 p ' @ , e x c a r m e p d l e e n . t c i o a m l ' s ) = . c e r x e e d c s u ) t e ( ) 利用するには、以下のいずれかが必要です: ...

2026年2月18日 · 12 分 · Nakamura

Archivematica における非DCメタデータの登録検証 ── source-metadata.csv を使ったEADの組み込み

Archivematica では、Dublin Core(DC)以外のメタデータスキーマもAIPのMETS.xmlに組み込むことができます。本ガイドでは、source-metadata.csv を使って EAD や MODS などの非DCメタデータをTransferに含め、AIPに正しく格納されるかをAPI経由で検証します。 目次 背景と目的 source-metadata.csv の仕組み XML Validation 機能 検証1: MODS単独でのメタデータ登録 検証2: EAD + MODS の同時登録 METS.xml における非DCメタデータの格納形式 検証3: Reingest によるメタデータ追加 まとめ 背景と目的 Archivematica の標準的な Transfer では、metadata/metadata.csv に記述した Dublin Core メタデータが METS.xml に <dmdSec> として格納されます。しかし、実際のデジタルアーカイブ運用では、以下のようなユースケースで DC 以外のメタデータスキーマを扱う必要があります。 EAD(Encoded Archival Description) : アーカイブズの階層記述で広く使われる標準 MODS(Metadata Object Description Schema) : 図書館資料の詳細記述に使われるスキーマ LIDO : 博物館・美術館資料の記述標準 MARC21 : 図書館の目録データフォーマット Archivematica は source-metadata.csv というCSVファイルを通じて、任意の XML メタデータを Transfer に紐付け、AIP の METS.xml に <dmdSec> として格納する機能を提供しています。本ガイドでは、この機能を API 経由で実際に検証します。 ...

2026年2月17日 · 24 分 · Nakamura

AtoM REST APIによるデジタルアーカイブ構築の検証

はじめに AtoM (Access to Memory) は、アーカイブ機関向けのオープンソースWebアプリケーションです。世界中の図書館・文書館・博物館で、資料記述の管理に利用されています。 AtoMの操作は通常Web UIから行いますが、REST APIを使えば外部システムとの連携やバッチ処理が可能になります。本記事では、現実的な業務シナリオ に沿ってAPIを一通り試し、Web UIでの反映も確認していきます。 APIプラグインの開発経緯や実装の詳細は、別記事 AtoMのREST APIを拡張するプラグインを開発した話 をご覧ください。 利用するAPI arRestApiPlugin (AtoM標準): 資料記述(Information Object)のCRUD arExtendedApiPlugin (独自開発): 所蔵機関・典拠レコード・受入記録・タクソノミー・機能記述・デジタルオブジェクトの操作 全28エンドポイントの一覧は開発記事を参照してください。 事前準備 # e # e x x A p A p t o P o o r I r M t キ t の ー U A ( A R T A P L O d I ( M m _ 環 _ i K 境 U n E に R Y 合 L > = わ = " せ " S y て h e o 変 t t u 更 t t r ) p i - : n a / g p / s i l - o > k c e a G y l l - h o h o b e s a r t l e : " 6 > 3 0 A 0 P 1 I " k e y で 設 定 ) APIキーはAtoMの管理画面(Settings > Global)で設定・確認できます。 ...

2026年2月15日 · 32 分 · Nakamura

AtoMのREST APIを拡張するプラグインを開発した話

はじめに AtoM (Access to Memory) は、アーカイブ機関向けのオープンソースWebアプリケーションです。ISAD(G)、ISAAR(CPF)、ISDFなどの国際標準に準拠した記述管理機能を提供しており、世界中の図書館・文書館・博物館で利用されています。 AtoMには arRestApiPlugin という標準のREST APIプラグインが同梱されていますが、以下の制約があります: 情報オブジェクト(資料記述)のCRUD が中心で、カバー範囲が限定的 所蔵機関(Repository) 、典拠レコード(Actor) 、受入記録(Accession) のAPIがない タクソノミー (分類語彙)の操作APIがない デジタルオブジェクト のアップロードAPIが実用的でない 機能記述(Function) のAPIがない これでは、外部システムとの連携やバッチ処理による大量登録といった業務ニーズに応えられません。 本記事では、これらの課題を解決するために開発した arExtendedApiPlugin の実装について解説します。 このプラグインを使って実際に業務シナリオを実行した記事もあります:APIで構築する図書館デジタルアーカイブ — AtoM業務シナリオ実践ガイド arExtendedApiPlugin の概要 エンドポイント一覧(全28エンドポイント) リソース メソッド エンドポイント 説明 サマリー GET /api/summary 各エンティティの件数 所蔵機関 GET /api/repositories 一覧(検索・ページネーション) GET /api/repositories/:slug 詳細取得 POST /api/repositories 新規作成 PUT /api/repositories/:slug 更新 DELETE /api/repositories/:slug 削除 POST /api/repositories/:slug/logo ロゴアップロード DELETE /api/repositories/:slug/logo ロゴ削除 典拠レコード GET /api/actors 一覧 GET /api/actors/:slug 詳細取得 POST /api/actors 新規作成 PUT /api/actors/:slug 更新 DELETE /api/actors/:slug 削除 受入記録 GET /api/accessions 一覧 GET /api/accessions/:slug 詳細取得 POST /api/accessions 新規作成 PUT /api/accessions/:slug 更新 DELETE /api/accessions/:slug 削除 タクソノミー GET /api/taxonomies 全タクソノミー一覧 POST /api/taxonomies/:id/terms 用語追加 PUT /api/taxonomies/terms/:id 用語更新 DELETE /api/taxonomies/terms/:id 用語削除 機能記述 GET /api/functions 一覧 GET /api/functions/:slug 詳細取得 POST /api/functions 新規作成 PUT /api/functions/:slug 更新 DELETE /api/functions/:slug 削除 デジタルオブジェクト POST /api/informationobjects/:slug/digitalobject アップロード Note : 資料記述(Information Object)のCRUDは、既存の arRestApiPlugin が提供する POST/GET /api/informationobjects を使用します。 ...

2026年2月15日 · 15 分 · Nakamura

AlfrescoをDockerで起動し、REST APIでレコード管理のライフサイクルを体験する

概要 本記事では、Alfresco Governance Services Community Edition(以下AGS)の最新版(25.3.0)をDockerで起動し、REST APIを使ってレコード管理の一連のライフサイクルを体験します。 具体的には、以下の業務シナリオを想定します。 シナリオ: 契約書管理 業務部門が契約書を作成・登録する レコード管理者がレコードとして宣言し、ファイルプランに分類する 保持スケジュール(Retention Schedule)を設定する 契約終了後、カットオフ(現用→非現用)を実行する 保持期間(3年)の経過後、廃棄する 訴訟対応が発生した場合、ホールド(凍結)により廃棄を停止する 以下の前回の記事をベースに、最新版での構築手順とAPIの使い方を紹介します。 環境 acs-deployment: v10.2.0(2026年2月リリース) Alfresco Governance Repository Community: 25.3.0 Alfresco Governance Share Community: 25.3.0 Alfresco Search Services: 2.0.17 Traefik: 3.6 PostgreSQL: 16.5 セットアップ リポジトリのクローン g c g c i d i d t t a d c c c o l s h c o - e k n d c e e e k r p o - h l u c t o t o t y m p m v p s e 1 o : n 0 s / t . e / 2 g . i 0 t h u b . c o m / A l f r e s c o / a c s - d e p l o y m e n t compose fileの作成 community-compose.yamlをベースに、Governance Services用のcompose fileを作成します。変更点は以下の3つです。 ...

2026年2月15日 · 252 分 · Nakamura

IIIFマニフェストを用いたテキスト比較ツールの開発

はじめに 古典籍のデジタル化が進む中、異なる写本や校訂本のテキストを比較・分析するニーズが高まっています。本稿では、IIIF(International Image Interoperability Framework)マニフェストを活用し、2つの資料の画像とテキストを並べて比較できるWebアプリケーション「Text Comparison Tool」を紹介します。 デモサイト : https://iiif-text.vercel.app/ 背景と課題 デジタルアーカイブで公開されている古典籍には、IIIFマニフェストにテキストアノテーションが付与されているものがあります。しかし、2つの資料のテキストを並べて比較する手軽なツールは多くありません。 例えば、ある作品の校訂本と写本を比較する場合、以下のような作業が必要です: 画像を並べて目視で比較する テキストの差異を一文字ずつ確認する どの程度類似しているかを定量的に把握する これらを1つのツールで実現することを目指しました。 3つの比較モード 本ツールは、3つのモードで資料を比較できます。 1. 画像比較 OpenSeadragonを用いた高精細画像ビューアで、2つの資料の画像を左右に並べて表示します。ズーム・パン・回転に対応し、ページ送りも可能です。 2. テキスト差分(Diff) IIIFマニフェストに含まれるテキストアノテーションを抽出し、文字単位での差分をハイライト表示します。追加箇所は緑色、削除箇所は赤色の取り消し線で表示されます。 3. 編集距離(Levenshtein Distance) レーベンシュタイン距離に基づき、行単位でのテキスト類似度を算出します。結果はネットワークグラフとして可視化され、類似度の高い行同士がエッジで結ばれます。閾値スライダーにより、表示するエッジの最低類似度を調整できます。 技術スタック カテゴリ 技術 フレームワーク Next.js(App Router / Static Export) 言語 TypeScript スタイリング Tailwind CSS v4 UIコンポーネント Radix UI 画像ビューア OpenSeadragon ネットワーク可視化 vis-network 状態管理 Zustand 国際化 next-intl(日本語 / English) 差分検出 diff アーキテクチャ データフロー I f C Z 各 I e o u 比 I ↓ t ↓ m ↓ s ↓ 較 F c p t コ マ h a a ン ニ M r n ポ フ a i d ー ェ n s ネ ス i o S ン ト f n t ト U e V o が R s a r 消 L t l e 費 ( u ・ ) e — 描 画 — — ア プ マ 画 リ ニ 像 ケ フ U ー ェ R シ ス L ョ ト 群 ン 取 、 状 得 テ 態 ・ キ と パ ス し ー ト て ス 配 保 列 持 、 メ タ デ ー タ fetchManifest()関数がIIIF Presentation API v3のマニフェストをパースし、各キャンバスの画像URLとテキストアノテーションを抽出します。抽出されたデータはZustandストアに格納され、各コンポーネントがリアクティブに参照します。 ...

2026年2月13日 · 3 分 · Nakamura

Drupal の GitHub Webhook モジュールを改善しました。

Drupal の管理画面から GitHub Actions をトリガーするカスタムモジュール「GitHub Webhook」を改善しました。 https://github.com/nakamura196/Drupal-module-github_webhook 元は複数リポジトリ対応の基本的なモジュールでしたが、UI のタブ分離、権限の細分化、ワークフローステータス表示、自動トリガーなどの機能を追加しています。 改善前のモジュール 元のモジュールは、以下のような構成でした。 ファイル数 : 5ファイル(info.yml、routing.yml、links.menu.yml、permissions.yml、SettingsForm.php) 対応バージョン : Drupal 10 のみ リポジトリ : 複数対応済み(AJAX で動的追加・削除) 画面 : 設定とトリガーが同一画面(アコーディオン2つ) 権限 : access github webhook settings の1権限のみ(設定もトリガーも同じ権限) トークン管理 : パスワードフィールドに #default_value を設定(HTML ソースに平文で出力される) HTTP クライアント : new \GuzzleHttp\Client() を直接インスタンス化 例外クラス : use 文なしで catch ブロックに記述(名前空間の解決が不正) $ ] f ; o ' ' ' 改 r # # # 善 m t t d 前 [ y i e : ' p t f s e l a ト e ' e u ー t ' l ク t = t ン i > = _ が n > v g ' a # s p $ l d ' a t u e ] s h e f [ s i ' a ' w s u g o - = l i r > > t t d t _ h ' ( $ v u , ' c a b G o l _ i n u t t f e o H i k u g に e b - 設 n > 定 ' T g さ ] o e れ k t て = e ( い n ' た [ ' g ) i , t h u b _ t o k e n ' ) , H T M L に 平 文 出 力 さ れ る $ c l 改 i 善 e 前 n : t G = u z n z e l w e \ ク G ラ u イ z ア z ン l ト e を H 直 t 接 t p n \ e C w l i し e て n い t た ( ) ; 変更の全体像 改善前後のファイル構成の比較です。* は変更、+ は新規追加を示します。 ...

2026年2月11日 · 39 分 · Nakamura

Netlify CLIを使って不要なサイトを一括削除する

大量のNetlifyサイトが溜まってきたので、CLIを使って一括削除した際の手順をまとめます。 背景 開発やテストで作成したNetlifyサイトが41個まで増えていました。現在使用しているサイトは数個だけだったため、古いサイトをまとめて削除することにしました。 環境 macOS Node.js netlify-cli v23.15.1 手順 1. Netlify CLIのインストール n p m i n s t a l l - g n e t l i f y - c l i 2. ログイン n e t l i f y l o g i n ブラウザが開き、Netlifyの認証画面が表示されます。認証を許可するとCLIにトークンが保存されます。 3. サイト一覧の取得 n e t l i f y s i t e s : l i s t JSON形式で取得する場合は --json オプションを付けます。 ...

2026年2月10日 · 6 分 · Nakamura

Drupal 10 の管理画面からモジュール更新とコアアップデートを行う

共用サーバー上の Drupal 10.6.1 で、Backup and Migrate によるバックアップと Automatic Updates によるモジュール・コアの自動更新を設定した手順をまとめる。 現状確認 管理画面の「レポート > サイトの状態」を確認すると、3つの警告が出ていた。 Drupal コアの更新状況:期限切れ(バージョン 10.6.3 が入手可能) PHP APCu available caching:メモリ使用量が75%超え モジュールとテーマの更新状況:期限切れ 「レポート > 利用可能なアップデート」を見ると、以下のモジュールに更新があった。 Consumers 8.x-1.22 Geofield 8.x-1.66 Geofield Map 11.1.1 Leaflet 10.3.11 Backup and Migrate のインストール 更新作業の前に、まずバックアップ手段を用意する。 c o m p o s e r . p h a r r e q u i r e ' d r u p a l / b a c k u p _ m i g r a t e : ^ 5 . 1 ' v e n d o r / b i n / d r u s h e n b a c k u p _ m i g r a t e v e n d o r / b i n / d r u s h c r インストール後、「管理 > 環境設定 > 開発 > バックアップと移動」からクイックバックアップが実行できるようになる。バックアップ元に「デフォルト Drupal データベース」、バックアップ保存先に「ダウンロード」を選択して「今すぐバックアップ」を押すと、データベースのバックアップファイルがダウンロードされる。 ...

2026年2月10日 · 4 分 · Nakamura

Mirador 4 で外部マニフェストのウィンドウタイトルだけを差し替える

背景 Mirador は IIIF 対応の画像ビューアで、複数の IIIF マニフェストを並べて比較閲覧できる。複数機関が公開するマニフェストを一画面に並べて表示する際、各ウィンドウのタイトルにはマニフェストの label がそのまま表示される。 しかし、自プロジェクト独自の名称をウィンドウタイトルとして表示したいケースがある。例えば、マニフェストの label が個別の冊次情報を含む長い文字列であるのに対し、資料群を示す短い名称で表示したい場合などである。 制約:マニフェストの中身は変えてはいけない 他機関が公開している IIIF マニフェストを読み込んで表示する以上、その中身を改変して表示することは避けたい。fetch のインターセプトや Mirador 内部状態の書き換えでマニフェスト JSON の label を差し替える方法もあるが、これは実質的にマニフェストの改変にあたる。 変更すべきは Mirador が画面上に描画したウィンドウのタイトル表示(DOM)だけ であり、マニフェストのデータ自体はオリジナルのまま保持したい。 試したアプローチと結果 1. Mirador.actions.receiveManifest による内部状態の書き換え s } t ) o v i } ; M r a f i e r v u s r . ( v a p t a s s m e r d o d u t a r a r o b a n r u t e r s t i i p e . c e f d d d d の r e d a J i i = s e t s s s b t n e o p t e s s [ d n a o ( t [ m J . t r f o m a s l c e u r a n o a h n e n i n b ( を c . i f e M 監 t g f e = l i 視 i e e s r し o t s t J = a 、 n S t I S d マ t I d O c o ニ a d ] N u r フ t ] . s . ェ e = p t a ス { ( & a o c ト ) & t r m t 読 ; r s T i み m u e i o 込 a e ( t n み n ; J l s 後 i S e . に f O ; r e N e l s . c a t s e b s t i e [ r v l m i e a n M を n g a 書 i i n き f f i 換 e y f え s ( e t m s I a t d n ( ] i m . f a j e n s s i o t f n s e [ s & m t & a I n d ! i , o f v e u e s p r t d r I a i d t d ] e d . d e j J n s s [ o o m n n a ) ) n ) ) i ; ; f e s t I d ] ) { 結果:動作しない。 unpkg から配信される Mirador 4 の UMD ビルドでは Mirador.actions が undefined であり、この API は利用できなかった。 ...

2026年2月8日 · 13 分 · Nakamura

Next.js 15 で発生する `localStorage.getItem is not a function` エラーの原因と対処法

Node.js 25 + Next.js 15 で発生する localStorage.getItem is not a function エラーの原因と対処法 はじめに Next.js 15 のプロジェクトで npm run dev を実行したところ、以下のエラーが発生して開発サーバーが正常に動作しなくなりました。 ⨯ } [ ( T ⨯ n [ d y o T i p [ d y g e T e p e E y : e s r p 2 E t r e 4 r : o E 0 r r r 5 o ' : r ) r 2 o : 8 l r W 9 o : a l 2 c r o 7 a l n c 0 l o i a 3 S c n l 8 t a g S 7 o l : t 9 r S o ' a t ` r g o - a e r - g . a l e g g o . e e c g t . a e I g l t t e s I e t t t m I o e t r m i e a s m g i e s n i - o s f n t i o n l t a o e t ` a f u a w f n a u c f s n t u c i n p t o c r i n t o o ] i v n o i ] n d ] e { d { w p i a t g h e o : u t / a j a v ' a l } i d p a t h コード上で localStorage を直接呼び出している箇所はなく、原因の特定に時間がかかりました。本記事では、このエラーの根本原因と対処法を解説します。 ...

2026年2月8日 · 10 分 · Nakamura

SPARQL クライアントを Apache Jena Fuseki に対応させるときにハマった 3 つのこと

Virtuoso / Dydra 向けに作られた SPARQL Explorer「Snorql」を Apache Jena Fuseki でも動くようにしました。SPARQL は W3C 標準ですが、エンドポイント実装ごとの挙動差は意外と大きいです。Fuseki 対応で直面した 3 つの問題と、その解決方法を記録します。 開発環境 Docker で Fuseki を起動し、ローカルで検証しました。 # s e o d r f l f o v u u u c i s i c p e m s k c e m o o n o e e e e k a n r - v - - l - s k r s i g t t i u : i - : : e a s " r A F m f - c : i : 3 o D U e u d o n 0 n M S s s a m s e 3 m I E : e t p t r 0 e N K k a o a _ : n _ I i : s i n 3 t P _ - e n a 0 : A D d . / m 3 S A a y j e 0 S T t m e : " W A a l n O S : a f R E / - u D T f f s = _ u u e a 1 s s k d = e e i m t k k i e i i n s t d # c o u c テ r - k ス l H - e ト d r デ - ' a ー X C t c タ o a o 投 P n - m 入 O t b p S e i o T n n s t a e ' - r h T y u t y p t p @ p e t - : : e d / s / t t l e d o x a c t t a / a l t . h u t o r t s t l t l : e 3 ' 0 3 0 / t e s t / d a t a ' 1. DESCRIBE のレスポンス形式が違う 症状 Fuseki に DESCRIBE クエリを投げると、結果が画面に表示されません。コンソールには JSON パースエラーが出ていました。 ...

2026年2月8日 · 14 分 · Nakamura