refactor: rename 'recit' to 'narrative' for English code naming
- Rename store: recit.js → narrative.js (useRecitStore → useNarrativeStore) - Rename templates: recit.php/json.php → narrative.php/json.php - Rename blueprint: recit.yml → narrative.yml - Update all imports and references in Vue/JS files - Update PHP template references and data attributes - Update CLAUDE.md documentation - Create comprehensive README.md with English-French dictionary The dictionary section maps English code terms to French content terms for easier navigation between codebase and CMS content. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ea0994ed45
commit
af788ad1e0
12 changed files with 267 additions and 66 deletions
202
public/site/templates/narrative.json.php
Normal file
202
public/site/templates/narrative.json.php
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
<?php
|
||||
/**
|
||||
* JSON template to expose narrative data
|
||||
* Accessible via /projet/narrative.json or /projet/narrative?format=json
|
||||
*/
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/**
|
||||
* Résout les références de fichiers Kirby en URLs absolues
|
||||
*/
|
||||
function resolveFileUrl($field, $page) {
|
||||
if (!$field || $field->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file = $field->toFile();
|
||||
if ($file) {
|
||||
return $file->url();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Résout les images dans le contenu HTML
|
||||
*/
|
||||
function resolveImagesInHtml($html, $page) {
|
||||
if (!$html) return $html;
|
||||
|
||||
// Remplacer les références file:// par les URLs réelles
|
||||
return preg_replace_callback(
|
||||
'/file:\/\/([a-z0-9]+)/i',
|
||||
function($matches) use ($page) {
|
||||
$uuid = $matches[1];
|
||||
$file = $page->file("file://{$uuid}");
|
||||
if (!$file) {
|
||||
// Chercher dans les fichiers du site
|
||||
$file = site()->file("file://{$uuid}");
|
||||
}
|
||||
return $file ? $file->url() : $matches[0];
|
||||
},
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse les blocks Kirby en structure JSON
|
||||
*/
|
||||
function parseBlocks($blocksField, $page) {
|
||||
if (!$blocksField || $blocksField->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$blocks = [];
|
||||
foreach ($blocksField->toBlocks() as $block) {
|
||||
$blockData = [
|
||||
'id' => $block->id(),
|
||||
'type' => $block->type(),
|
||||
'isHidden' => $block->isHidden(),
|
||||
];
|
||||
|
||||
switch ($block->type()) {
|
||||
case 'text':
|
||||
$blockData['content'] = [
|
||||
'text' => resolveImagesInHtml($block->text()->value(), $page)
|
||||
];
|
||||
break;
|
||||
|
||||
case 'heading':
|
||||
$blockData['content'] = [
|
||||
'level' => $block->level()->value() ?? 'h2',
|
||||
'text' => $block->text()->value()
|
||||
];
|
||||
break;
|
||||
|
||||
case 'image':
|
||||
$image = $block->image()->toFile();
|
||||
$blockData['content'] = [
|
||||
'url' => $image ? $image->url() : null,
|
||||
'alt' => $block->alt()->value() ?? '',
|
||||
'caption' => $block->caption()->value() ?? '',
|
||||
'width' => $block->width()->value() ?? '100%',
|
||||
'position' => $block->position()->value() ?? 'auto'
|
||||
];
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
$blockData['content'] = [
|
||||
'text' => $block->text()->value()
|
||||
];
|
||||
break;
|
||||
|
||||
case 'quote':
|
||||
$blockData['content'] = [
|
||||
'text' => $block->text()->value(),
|
||||
'citation' => $block->citation()->value() ?? ''
|
||||
];
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
$blockData['content'] = [
|
||||
'url' => $block->url()->value(),
|
||||
'caption' => $block->caption()->value() ?? ''
|
||||
];
|
||||
break;
|
||||
|
||||
case 'map':
|
||||
$blockData['content'] = [
|
||||
'map' => $block->map()->value()
|
||||
];
|
||||
break;
|
||||
|
||||
default:
|
||||
$blockData['content'] = $block->content()->toArray();
|
||||
}
|
||||
|
||||
$blocks[] = $blockData;
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse un chapitre
|
||||
*/
|
||||
function parseChapitre($chapitre) {
|
||||
return [
|
||||
'id' => $chapitre->id(),
|
||||
'uuid' => $chapitre->uuid()->toString(),
|
||||
'template' => 'chapitre',
|
||||
'title' => $chapitre->title()->value(),
|
||||
'slug' => $chapitre->slug(),
|
||||
'blocks' => parseBlocks($chapitre->text(), $chapitre)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse une carte
|
||||
*/
|
||||
function parseCarte($carte) {
|
||||
return [
|
||||
'id' => $carte->id(),
|
||||
'uuid' => $carte->uuid()->toString(),
|
||||
'template' => 'carte',
|
||||
'title' => $carte->title()->value(),
|
||||
'slug' => $carte->slug(),
|
||||
'tags' => $carte->tags()->isNotEmpty() ? $carte->tags()->split() : [],
|
||||
'text' => resolveImagesInHtml($carte->text()->value(), $carte)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse un geoformat
|
||||
*/
|
||||
function parseGeoformat($geoformat) {
|
||||
$chapitres = [];
|
||||
foreach ($geoformat->children()->listed() as $child) {
|
||||
if ($child->intendedTemplate()->name() === 'chapitre') {
|
||||
$chapitres[] = parseChapitre($child);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $geoformat->id(),
|
||||
'uuid' => $geoformat->uuid()->toString(),
|
||||
'template' => 'geoformat',
|
||||
'title' => $geoformat->title()->value(),
|
||||
'slug' => $geoformat->slug(),
|
||||
'subtitle' => $geoformat->subtitle()->value() ?? '',
|
||||
'tags' => $geoformat->tags()->isNotEmpty() ? $geoformat->tags()->split() : [],
|
||||
'cover' => resolveFileUrl($geoformat->cover(), $geoformat),
|
||||
'text' => resolveImagesInHtml($geoformat->text()->value(), $geoformat),
|
||||
'children' => $chapitres
|
||||
];
|
||||
}
|
||||
|
||||
// Build JSON response
|
||||
$data = [
|
||||
'id' => $page->id(),
|
||||
'uuid' => $page->uuid()->toString(),
|
||||
'template' => 'narrative',
|
||||
'title' => $page->title()->value(),
|
||||
'slug' => $page->slug(),
|
||||
'author' => $page->author()->value() ?? '',
|
||||
'cover' => resolveFileUrl($page->cover(), $page),
|
||||
'introduction' => resolveImagesInHtml($page->introduction()->value(), $page),
|
||||
'children' => []
|
||||
];
|
||||
|
||||
// Parse children (geoformats and maps)
|
||||
foreach ($page->children()->listed() as $child) {
|
||||
$template = $child->intendedTemplate()->name();
|
||||
|
||||
if ($template === 'geoformat') {
|
||||
$data['children'][] = parseGeoformat($child);
|
||||
} elseif ($template === 'carte') {
|
||||
$data['children'][] = parseCarte($child);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
Loading…
Add table
Add a link
Reference in a new issue