Spaces:
Build error
Build error
Claude commited on
rename: Scriptorium AI → IIIF Studio across entire codebase
Browse filesReplace all variants (Scriptorium AI, scriptorium-ai, ScriptoriumAI,
scriptorium.db, scriptoriumProcessing) with their IIIF Studio equivalents
(IIIF Studio, iiif-studio, IIIFStudio, iiif_studio.db, iiifStudioProcessing)
across 21 files. All 477 tests pass.
https://claude.ai/code/session_01WWohTtw2CxGRawmpH1tyrY
- .github/workflows/deploy-hf.yml +1 -1
- .huggingface/README.md +1 -1
- CLAUDE.md +4 -4
- Dockerfile +2 -2
- README.md +4 -4
- backend/app/api/v1/ingest.py +2 -2
- backend/app/config.py +1 -1
- backend/app/main.py +3 -3
- backend/app/services/export/alto.py +1 -1
- backend/app/services/export/iiif.py +1 -1
- backend/app/services/export/mets.py +4 -4
- backend/app/services/ingest/iiif_fetcher.py +2 -2
- backend/pyproject.toml +2 -2
- backend/tests/test_export_alto.py +2 -2
- backend/tests/test_export_iiif.py +1 -1
- backend/tests/test_export_mets.py +1 -1
- backend/tests/test_image_pipeline.py +2 -2
- frontend/index.html +1 -1
- frontend/package.json +1 -1
- frontend/src/lib/api.ts +1 -1
- frontend/src/pages/Home.tsx +1 -1
.github/workflows/deploy-hf.yml
CHANGED
|
@@ -35,5 +35,5 @@ jobs:
|
|
| 35 |
run: |
|
| 36 |
git config user.email "github-actions[bot]@users.noreply.github.com"
|
| 37 |
git config user.name "github-actions[bot]"
|
| 38 |
-
git remote add hf https://Ma-Ri-Ba-Ku:${HF_TOKEN}@huggingface.co/spaces/Ma-Ri-Ba-Ku/
|
| 39 |
git push hf main --force
|
|
|
|
| 35 |
run: |
|
| 36 |
git config user.email "github-actions[bot]@users.noreply.github.com"
|
| 37 |
git config user.name "github-actions[bot]"
|
| 38 |
+
git remote add hf https://Ma-Ri-Ba-Ku:${HF_TOKEN}@huggingface.co/spaces/Ma-Ri-Ba-Ku/iiif-studio
|
| 39 |
git push hf main --force
|
.huggingface/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 📜
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: yellow
|
|
|
|
| 1 |
---
|
| 2 |
+
title: IIIF Studio
|
| 3 |
emoji: 📜
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: yellow
|
CLAUDE.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
-
#
|
| 2 |
## Version 2.0 — mise à jour Sprint 2
|
| 3 |
|
| 4 |
---
|
| 5 |
|
| 6 |
## 1. Contexte du projet
|
| 7 |
|
| 8 |
-
|
| 9 |
pour documents patrimoniaux numérisés : manuscrits médiévaux, incunables, cartulaires,
|
| 10 |
archives, chartes, papyri — tout type de document, toute époque, toute langue.
|
| 11 |
|
|
@@ -38,7 +38,7 @@ latin carolingien, XIe siècle). Le Beatus est un profil parmi d'autres — pas
|
|
| 38 |
|
| 39 |
```toml
|
| 40 |
[project]
|
| 41 |
-
name = "
|
| 42 |
version = "0.1.0"
|
| 43 |
requires-python = ">=3.11"
|
| 44 |
|
|
@@ -73,7 +73,7 @@ asyncio_mode = "auto"
|
|
| 73 |
## 3. Arborescence du repo — structure canonique
|
| 74 |
|
| 75 |
```
|
| 76 |
-
|
| 77 |
│
|
| 78 |
├── CLAUDE.md ← CE FICHIER — ne pas modifier sans instruction
|
| 79 |
├── STATUS.md ← état courant (mis à jour avant chaque session)
|
|
|
|
| 1 |
+
# IIIF Studio — Instructions permanentes pour Claude Code
|
| 2 |
## Version 2.0 — mise à jour Sprint 2
|
| 3 |
|
| 4 |
---
|
| 5 |
|
| 6 |
## 1. Contexte du projet
|
| 7 |
|
| 8 |
+
IIIF Studio est une **plateforme générique** de génération d'éditions savantes augmentées
|
| 9 |
pour documents patrimoniaux numérisés : manuscrits médiévaux, incunables, cartulaires,
|
| 10 |
archives, chartes, papyri — tout type de document, toute époque, toute langue.
|
| 11 |
|
|
|
|
| 38 |
|
| 39 |
```toml
|
| 40 |
[project]
|
| 41 |
+
name = "iiif-studio"
|
| 42 |
version = "0.1.0"
|
| 43 |
requires-python = ">=3.11"
|
| 44 |
|
|
|
|
| 73 |
## 3. Arborescence du repo — structure canonique
|
| 74 |
|
| 75 |
```
|
| 76 |
+
iiif-studio/
|
| 77 |
│
|
| 78 |
├── CLAUDE.md ← CE FICHIER — ne pas modifier sans instruction
|
| 79 |
├── STATUS.md ← état courant (mis à jour avant chaque session)
|
Dockerfile
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
-
#
|
| 2 |
# Ce fichier est utilisé par HuggingFace Spaces (SDK docker, détection automatique).
|
| 3 |
# Source unique — le fichier infra/Dockerfile a été supprimé pour éviter la divergence.
|
| 4 |
#
|
| 5 |
# Build depuis la racine du dépôt :
|
| 6 |
-
# docker build -t
|
| 7 |
|
| 8 |
# ── Stage 1 : build du frontend React ────────────────────────────────────────
|
| 9 |
FROM node:20-slim AS frontend-builder
|
|
|
|
| 1 |
+
# IIIF Studio — image de production (multi-stage)
|
| 2 |
# Ce fichier est utilisé par HuggingFace Spaces (SDK docker, détection automatique).
|
| 3 |
# Source unique — le fichier infra/Dockerfile a été supprimé pour éviter la divergence.
|
| 4 |
#
|
| 5 |
# Build depuis la racine du dépôt :
|
| 6 |
+
# docker build -t iiif-studio .
|
| 7 |
|
| 8 |
# ── Stage 1 : build du frontend React ────────────────────────────────────────
|
| 9 |
FROM node:20-slim AS frontend-builder
|
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 📜
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: yellow
|
|
@@ -8,7 +8,7 @@ app_port: 7860
|
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
-
#
|
| 12 |
|
| 13 |
Plateforme générique de génération d'éditions savantes augmentées pour documents
|
| 14 |
patrimoniaux numérisés : manuscrits médiévaux, incunables, cartulaires, archives,
|
|
@@ -19,7 +19,7 @@ chartes, papyri — tout type de document, toute époque, toute langue.
|
|
| 19 |
## Structure du dépôt
|
| 20 |
|
| 21 |
```
|
| 22 |
-
|
| 23 |
├── backend/ # API FastAPI + pipeline Python
|
| 24 |
│ ├── app/
|
| 25 |
│ │ ├── api/v1/ # endpoints REST (/api/v1/...)
|
|
@@ -41,7 +41,7 @@ scriptorium-ai/
|
|
| 41 |
|
| 42 |
```bash
|
| 43 |
# 1. Cloner le dépôt
|
| 44 |
-
git clone https://github.com/<org>/
|
| 45 |
|
| 46 |
# 2. Définir les variables d'environnement
|
| 47 |
cp .env.example .env # puis renseigner les clés dans .env
|
|
|
|
| 1 |
---
|
| 2 |
+
title: IIIF Studio
|
| 3 |
emoji: 📜
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: yellow
|
|
|
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
+
# IIIF Studio
|
| 12 |
|
| 13 |
Plateforme générique de génération d'éditions savantes augmentées pour documents
|
| 14 |
patrimoniaux numérisés : manuscrits médiévaux, incunables, cartulaires, archives,
|
|
|
|
| 19 |
## Structure du dépôt
|
| 20 |
|
| 21 |
```
|
| 22 |
+
iiif-studio/
|
| 23 |
├── backend/ # API FastAPI + pipeline Python
|
| 24 |
│ ├── app/
|
| 25 |
│ │ ├── api/v1/ # endpoints REST (/api/v1/...)
|
|
|
|
| 41 |
|
| 42 |
```bash
|
| 43 |
# 1. Cloner le dépôt
|
| 44 |
+
git clone https://github.com/<org>/iiif-studio && cd iiif-studio
|
| 45 |
|
| 46 |
# 2. Définir les variables d'environnement
|
| 47 |
cp .env.example .env # puis renseigner les clés dans .env
|
backend/app/api/v1/ingest.py
CHANGED
|
@@ -159,8 +159,8 @@ async def _create_page(
|
|
| 159 |
|
| 160 |
_MANIFEST_HEADERS = {
|
| 161 |
"User-Agent": (
|
| 162 |
-
"Mozilla/5.0 (compatible;
|
| 163 |
-
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/
|
| 164 |
),
|
| 165 |
"Accept": "application/ld+json,application/json,*/*",
|
| 166 |
"Referer": "https://gallica.bnf.fr/",
|
|
|
|
| 159 |
|
| 160 |
_MANIFEST_HEADERS = {
|
| 161 |
"User-Agent": (
|
| 162 |
+
"Mozilla/5.0 (compatible; IIIFStudio/1.0; "
|
| 163 |
+
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/iiif-studio)"
|
| 164 |
),
|
| 165 |
"Accept": "application/ld+json,application/json,*/*",
|
| 166 |
"Referer": "https://gallica.bnf.fr/",
|
backend/app/config.py
CHANGED
|
@@ -41,7 +41,7 @@ class Settings(BaseSettings):
|
|
| 41 |
prompts_dir: Path = _REPO_ROOT / "prompts"
|
| 42 |
|
| 43 |
# ── Base de données ───────────────────────────────────────────────────────
|
| 44 |
-
database_url: str = "sqlite+aiosqlite:///./
|
| 45 |
|
| 46 |
# ── Fournisseurs IA (R06 — clés depuis l'environnement uniquement) ────────
|
| 47 |
# Chaque clé est optionnelle. Le backend détecte automatiquement quels
|
|
|
|
| 41 |
prompts_dir: Path = _REPO_ROOT / "prompts"
|
| 42 |
|
| 43 |
# ── Base de données ───────────────────────────────────────────────────────
|
| 44 |
+
database_url: str = "sqlite+aiosqlite:///./iiif_studio.db"
|
| 45 |
|
| 46 |
# ── Fournisseurs IA (R06 — clés depuis l'environnement uniquement) ────────
|
| 47 |
# Chaque clé est optionnelle. Le backend détecte automatiquement quels
|
backend/app/main.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
"""
|
| 2 |
-
Application FastAPI — point d'entrée de
|
| 3 |
|
| 4 |
Tous les endpoints sont sous /api/v1/ (R10).
|
| 5 |
CORS ouvert pour le développement local (origins=["*"]).
|
|
@@ -32,7 +32,7 @@ async def lifespan(application: FastAPI):
|
|
| 32 |
# Ces logs apparaissent dans la console HuggingFace et permettent de
|
| 33 |
# diagnostiquer instantanément tout problème de chemin en production.
|
| 34 |
logger.info(
|
| 35 |
-
"Démarrage
|
| 36 |
extra={
|
| 37 |
"profiles_dir": str(settings.profiles_dir),
|
| 38 |
"profiles_dir_ok": settings.profiles_dir.is_dir(),
|
|
@@ -59,7 +59,7 @@ async def lifespan(application: FastAPI):
|
|
| 59 |
|
| 60 |
|
| 61 |
app = FastAPI(
|
| 62 |
-
title="
|
| 63 |
description="Plateforme générique de génération d'éditions savantes augmentées",
|
| 64 |
version="0.1.0",
|
| 65 |
lifespan=lifespan,
|
|
|
|
| 1 |
"""
|
| 2 |
+
Application FastAPI — point d'entrée de IIIF Studio.
|
| 3 |
|
| 4 |
Tous les endpoints sont sous /api/v1/ (R10).
|
| 5 |
CORS ouvert pour le développement local (origins=["*"]).
|
|
|
|
| 32 |
# Ces logs apparaissent dans la console HuggingFace et permettent de
|
| 33 |
# diagnostiquer instantanément tout problème de chemin en production.
|
| 34 |
logger.info(
|
| 35 |
+
"Démarrage IIIF Studio — chemins configurés",
|
| 36 |
extra={
|
| 37 |
"profiles_dir": str(settings.profiles_dir),
|
| 38 |
"profiles_dir_ok": settings.profiles_dir.is_dir(),
|
|
|
|
| 59 |
|
| 60 |
|
| 61 |
app = FastAPI(
|
| 62 |
+
title="IIIF Studio",
|
| 63 |
description="Plateforme générique de génération d'éditions savantes augmentées",
|
| 64 |
version="0.1.0",
|
| 65 |
lifespan=lifespan,
|
backend/app/services/export/alto.py
CHANGED
|
@@ -170,7 +170,7 @@ def generate_alto(master: PageMaster) -> str:
|
|
| 170 |
master.processing.processed_at.isoformat()
|
| 171 |
)
|
| 172 |
software = etree.SubElement(step, _a("processingSoftware"))
|
| 173 |
-
etree.SubElement(software, _a("softwareCreator")).text = "
|
| 174 |
etree.SubElement(software, _a("softwareName")).text = (
|
| 175 |
master.processing.model_display_name
|
| 176 |
)
|
|
|
|
| 170 |
master.processing.processed_at.isoformat()
|
| 171 |
)
|
| 172 |
software = etree.SubElement(step, _a("processingSoftware"))
|
| 173 |
+
etree.SubElement(software, _a("softwareCreator")).text = "IIIF Studio"
|
| 174 |
etree.SubElement(software, _a("softwareName")).text = (
|
| 175 |
master.processing.model_display_name
|
| 176 |
)
|
backend/app/services/export/iiif.py
CHANGED
|
@@ -51,7 +51,7 @@ def generate_manifest(
|
|
| 51 |
Optionnelles : language (str), repository (str), shelfmark (str),
|
| 52 |
date_label (str), institution (str)
|
| 53 |
base_url: URL de base de la plateforme, sans slash final
|
| 54 |
-
(ex. "https://
|
| 55 |
|
| 56 |
Returns:
|
| 57 |
dict sérialisable en JSON contenant le Manifest IIIF 3.0.
|
|
|
|
| 51 |
Optionnelles : language (str), repository (str), shelfmark (str),
|
| 52 |
date_label (str), institution (str)
|
| 53 |
base_url: URL de base de la plateforme, sans slash final
|
| 54 |
+
(ex. "https://iiif-studio.hf.space").
|
| 55 |
|
| 56 |
Returns:
|
| 57 |
dict sérialisable en JSON contenant le Manifest IIIF 3.0.
|
backend/app/services/export/mets.py
CHANGED
|
@@ -128,7 +128,7 @@ def generate_mets(
|
|
| 128 |
# ── 1. metsHdr ──────────────────────────────────────────────────────────
|
| 129 |
hdr = _el(root, f"{_M}metsHdr", {"CREATEDATE": now_iso})
|
| 130 |
agent = _el(hdr, f"{_M}agent", {"ROLE": "CREATOR", "TYPE": "ORGANIZATION"})
|
| 131 |
-
_el(agent, f"{_M}name", text="
|
| 132 |
|
| 133 |
# ── 2. dmdSec — Dublin Core ─────────────────────────────────────────────
|
| 134 |
dmd = _el(root, f"{_M}dmdSec", {"ID": "DMD_1"})
|
|
@@ -152,15 +152,15 @@ def generate_mets(
|
|
| 152 |
# ── 3. amdSec — techMD global ───────────────────────────────────────────
|
| 153 |
amd = _el(root, f"{_M}amdSec")
|
| 154 |
tech = _el(amd, f"{_M}techMD", {"ID": "AMD_1"})
|
| 155 |
-
amd_wrap = _el(tech, f"{_M}mdWrap", {"MDTYPE": "OTHER", "OTHERMDTYPE": "
|
| 156 |
amd_data = _el(amd_wrap, f"{_M}xmlData")
|
| 157 |
|
| 158 |
# Premier processing trouvé parmi les pages
|
| 159 |
first_processing = next(
|
| 160 |
(m.processing for m in pages if m.processing is not None), None
|
| 161 |
)
|
| 162 |
-
amd_root = etree.SubElement(amd_data, "
|
| 163 |
-
_el(amd_root, "generator", text="
|
| 164 |
_el(amd_root, "pageCount", text=str(len(pages)))
|
| 165 |
_el(amd_root, "corpusSlug", text=corpus_slug)
|
| 166 |
if first_processing:
|
|
|
|
| 128 |
# ── 1. metsHdr ──────────────────────────────────────────────────────────
|
| 129 |
hdr = _el(root, f"{_M}metsHdr", {"CREATEDATE": now_iso})
|
| 130 |
agent = _el(hdr, f"{_M}agent", {"ROLE": "CREATOR", "TYPE": "ORGANIZATION"})
|
| 131 |
+
_el(agent, f"{_M}name", text="IIIF Studio")
|
| 132 |
|
| 133 |
# ── 2. dmdSec — Dublin Core ─────────────────────────────────────────────
|
| 134 |
dmd = _el(root, f"{_M}dmdSec", {"ID": "DMD_1"})
|
|
|
|
| 152 |
# ── 3. amdSec — techMD global ───────────────────────────────────────────
|
| 153 |
amd = _el(root, f"{_M}amdSec")
|
| 154 |
tech = _el(amd, f"{_M}techMD", {"ID": "AMD_1"})
|
| 155 |
+
amd_wrap = _el(tech, f"{_M}mdWrap", {"MDTYPE": "OTHER", "OTHERMDTYPE": "IIIFStudio"})
|
| 156 |
amd_data = _el(amd_wrap, f"{_M}xmlData")
|
| 157 |
|
| 158 |
# Premier processing trouvé parmi les pages
|
| 159 |
first_processing = next(
|
| 160 |
(m.processing for m in pages if m.processing is not None), None
|
| 161 |
)
|
| 162 |
+
amd_root = etree.SubElement(amd_data, "iiifStudioProcessing")
|
| 163 |
+
_el(amd_root, "generator", text="IIIF Studio")
|
| 164 |
_el(amd_root, "pageCount", text=str(len(pages)))
|
| 165 |
_el(amd_root, "corpusSlug", text=corpus_slug)
|
| 166 |
if first_processing:
|
backend/app/services/ingest/iiif_fetcher.py
CHANGED
|
@@ -13,8 +13,8 @@ _DEFAULT_TIMEOUT = 60.0 # secondes — les images IIIF haute résolution peuven
|
|
| 13 |
|
| 14 |
_HEADERS = {
|
| 15 |
"User-Agent": (
|
| 16 |
-
"Mozilla/5.0 (compatible;
|
| 17 |
-
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/
|
| 18 |
),
|
| 19 |
"Accept": "image/jpeg,image/png,image/*,*/*",
|
| 20 |
}
|
|
|
|
| 13 |
|
| 14 |
_HEADERS = {
|
| 15 |
"User-Agent": (
|
| 16 |
+
"Mozilla/5.0 (compatible; IIIFStudio/1.0; "
|
| 17 |
+
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/iiif-studio)"
|
| 18 |
),
|
| 19 |
"Accept": "image/jpeg,image/png,image/*,*/*",
|
| 20 |
}
|
backend/pyproject.toml
CHANGED
|
@@ -3,9 +3,9 @@ requires = ["setuptools>=61", "wheel"]
|
|
| 3 |
build-backend = "setuptools.build_meta"
|
| 4 |
|
| 5 |
[project]
|
| 6 |
-
name = "
|
| 7 |
version = "0.2.0"
|
| 8 |
-
description = "Backend
|
| 9 |
requires-python = ">=3.11"
|
| 10 |
dependencies = [
|
| 11 |
"fastapi>=0.111",
|
|
|
|
| 3 |
build-backend = "setuptools.build_meta"
|
| 4 |
|
| 5 |
[project]
|
| 6 |
+
name = "iiif-studio-backend"
|
| 7 |
version = "0.2.0"
|
| 8 |
+
description = "Backend IIIF Studio — plateforme générique d'éditions savantes augmentées"
|
| 9 |
requires-python = ">=3.11"
|
| 10 |
dependencies = [
|
| 11 |
"fastapi>=0.111",
|
backend/tests/test_export_alto.py
CHANGED
|
@@ -459,10 +459,10 @@ def test_ocr_processing_absent_without_processing_info():
|
|
| 459 |
assert len(_xpath(root, "//a:OCRProcessing")) == 0
|
| 460 |
|
| 461 |
|
| 462 |
-
def
|
| 463 |
root = _parse(generate_alto(master_text_only))
|
| 464 |
creator = _one(root, "//a:processingSoftware/a:softwareCreator")
|
| 465 |
-
assert creator.text == "
|
| 466 |
|
| 467 |
|
| 468 |
# ---------------------------------------------------------------------------
|
|
|
|
| 459 |
assert len(_xpath(root, "//a:OCRProcessing")) == 0
|
| 460 |
|
| 461 |
|
| 462 |
+
def test_software_creator_is_iiif_studio(master_text_only):
|
| 463 |
root = _parse(generate_alto(master_text_only))
|
| 464 |
creator = _one(root, "//a:processingSoftware/a:softwareCreator")
|
| 465 |
+
assert creator.text == "IIIF Studio"
|
| 466 |
|
| 467 |
|
| 468 |
# ---------------------------------------------------------------------------
|
backend/tests/test_export_iiif.py
CHANGED
|
@@ -30,7 +30,7 @@ import pytest
|
|
| 30 |
from app.schemas.page_master import EditorialInfo, EditorialStatus, OCRResult, PageMaster, ProcessingInfo
|
| 31 |
from app.services.export.iiif import generate_manifest, write_manifest
|
| 32 |
|
| 33 |
-
_BASE_URL = "https://
|
| 34 |
_IIIF_CONTEXT = "http://iiif.io/api/presentation/3/context.json"
|
| 35 |
|
| 36 |
|
|
|
|
| 30 |
from app.schemas.page_master import EditorialInfo, EditorialStatus, OCRResult, PageMaster, ProcessingInfo
|
| 31 |
from app.services.export.iiif import generate_manifest, write_manifest
|
| 32 |
|
| 33 |
+
_BASE_URL = "https://iiif-studio.example.com"
|
| 34 |
_IIIF_CONTEXT = "http://iiif.io/api/presentation/3/context.json"
|
| 35 |
|
| 36 |
|
backend/tests/test_export_mets.py
CHANGED
|
@@ -252,7 +252,7 @@ def test_metsHdr_agent_creator(beatus_pages, beatus_meta):
|
|
| 252 |
root = _parse(generate_mets(beatus_pages, beatus_meta))
|
| 253 |
agent = _one(root, "m:metsHdr/m:agent[@ROLE='CREATOR']")
|
| 254 |
name = _one(agent, "m:name")
|
| 255 |
-
assert name.text == "
|
| 256 |
|
| 257 |
|
| 258 |
def test_metsHdr_has_createdate(beatus_pages, beatus_meta):
|
|
|
|
| 252 |
root = _parse(generate_mets(beatus_pages, beatus_meta))
|
| 253 |
agent = _one(root, "m:metsHdr/m:agent[@ROLE='CREATOR']")
|
| 254 |
name = _one(agent, "m:name")
|
| 255 |
+
assert name.text == "IIIF Studio"
|
| 256 |
|
| 257 |
|
| 258 |
def test_metsHdr_has_createdate(beatus_pages, beatus_meta):
|
backend/tests/test_image_pipeline.py
CHANGED
|
@@ -274,8 +274,8 @@ def test_fetch_iiif_image_success():
|
|
| 274 |
"https://example.com/image.jpg",
|
| 275 |
headers={
|
| 276 |
"User-Agent": (
|
| 277 |
-
"Mozilla/5.0 (compatible;
|
| 278 |
-
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/
|
| 279 |
),
|
| 280 |
"Accept": "image/jpeg,image/png,image/*,*/*",
|
| 281 |
},
|
|
|
|
| 274 |
"https://example.com/image.jpg",
|
| 275 |
headers={
|
| 276 |
"User-Agent": (
|
| 277 |
+
"Mozilla/5.0 (compatible; IIIFStudio/1.0; "
|
| 278 |
+
"+https://huggingface.co/spaces/Ma-Ri-Ba-Ku/iiif-studio)"
|
| 279 |
),
|
| 280 |
"Accept": "image/jpeg,image/png,image/*,*/*",
|
| 281 |
},
|
frontend/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
-
<title>
|
| 7 |
</head>
|
| 8 |
<body>
|
| 9 |
<div id="root"></div>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>IIIF Studio</title>
|
| 7 |
</head>
|
| 8 |
<body>
|
| 9 |
<div id="root"></div>
|
frontend/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"name": "
|
| 3 |
"version": "0.1.0",
|
| 4 |
"private": true,
|
| 5 |
"scripts": {
|
|
|
|
| 1 |
{
|
| 2 |
+
"name": "iiif-studio-frontend",
|
| 3 |
"version": "0.1.0",
|
| 4 |
"private": true,
|
| 5 |
"scripts": {
|
frontend/src/lib/api.ts
CHANGED
|
@@ -2,7 +2,7 @@ const BASE_URL: string = import.meta.env.VITE_API_URL ?? ''
|
|
| 2 |
|
| 3 |
if (!BASE_URL && import.meta.env.PROD) {
|
| 4 |
console.warn(
|
| 5 |
-
'[
|
| 6 |
'Les appels API utiliseront des chemins relatifs, ce qui peut échouer ' +
|
| 7 |
'si le frontend n\'est pas servi par le même domaine que le backend.'
|
| 8 |
)
|
|
|
|
| 2 |
|
| 3 |
if (!BASE_URL && import.meta.env.PROD) {
|
| 4 |
console.warn(
|
| 5 |
+
'[IIIF-Studio] VITE_API_URL non défini en production. ' +
|
| 6 |
'Les appels API utiliseront des chemins relatifs, ce qui peut échouer ' +
|
| 7 |
'si le frontend n\'est pas servi par le même domaine que le backend.'
|
| 8 |
)
|
frontend/src/pages/Home.tsx
CHANGED
|
@@ -68,7 +68,7 @@ export default function Home({ onOpenManuscript, onOpenPage, onAdmin }: Props) {
|
|
| 68 |
<div className="min-h-screen bg-stone-50">
|
| 69 |
<header className="bg-stone-900 text-stone-100 px-8 py-6 flex items-start justify-between">
|
| 70 |
<div>
|
| 71 |
-
<h1 className="text-2xl font-semibold tracking-tight">
|
| 72 |
<p className="text-stone-400 text-sm mt-1">
|
| 73 |
Plateforme de génération d'éditions savantes augmentées
|
| 74 |
</p>
|
|
|
|
| 68 |
<div className="min-h-screen bg-stone-50">
|
| 69 |
<header className="bg-stone-900 text-stone-100 px-8 py-6 flex items-start justify-between">
|
| 70 |
<div>
|
| 71 |
+
<h1 className="text-2xl font-semibold tracking-tight">IIIF Studio</h1>
|
| 72 |
<p className="text-stone-400 text-sm mt-1">
|
| 73 |
Plateforme de génération d'éditions savantes augmentées
|
| 74 |
</p>
|