fix 1.2.1 : cache index.md, H1 rendu, scroll wizard, titre Modifier
- ArticleManager : invalider le cache si index.md est plus récent que meta.json - migration_001 : touch(meta.json) après maj index.md pour forcer l'invalidation - post_view.php : masquer le H1 initial du contenu (déjà affiché par le template) - step1.php : en-tête "Modifier" sans le titre de l'article - wizard.js : retirer scrollToCursor (erroné sur auto-resize) ; Ctrl+Home/End via scrollIntoView Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,17 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag
|
||||
|
||||
---
|
||||
|
||||
## [1.2.1] - 2026-05-14
|
||||
|
||||
### Corrigé
|
||||
- Cache article invalidé si `index.md` est plus récent que `meta.json` (migration de contenu ne se reflétait pas)
|
||||
- Migration 001 : `touch(meta.json)` après écriture de `index.md` pour invalider le cache
|
||||
- `post_view.php` : le `# Titre` Markdown est retiré du rendu (déjà affiché par le template)
|
||||
- Wizard étape 1 : en-tête affiche « Modifier » sans répéter le titre de l'article
|
||||
- `wizard.js` : suppression de `scrollToCursor` (calcul erroné sur textarea auto-resize) ; Ctrl+Home / Ctrl+End scrollent correctement via `scrollIntoView`
|
||||
|
||||
---
|
||||
|
||||
## [1.2.0] - 2026-05-14
|
||||
|
||||
### Ajouté
|
||||
|
||||
@@ -13,20 +13,13 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
ta.addEventListener('input', resizeTa);
|
||||
resizeTa();
|
||||
|
||||
function scrollToCursor() {
|
||||
var lineH = parseFloat(getComputedStyle(ta).lineHeight) || 20;
|
||||
var padT = parseFloat(getComputedStyle(ta).paddingTop) || 8;
|
||||
var lines = ta.value.substr(0, ta.selectionStart).split('\n').length;
|
||||
var cursorY = ta.getBoundingClientRect().top + padT + lines * lineH;
|
||||
var margin = lineH * 3;
|
||||
if (cursorY > window.innerHeight - margin) {
|
||||
window.scrollBy({ top: cursorY - window.innerHeight + margin, behavior: 'instant' });
|
||||
} else if (cursorY < margin) {
|
||||
window.scrollBy({ top: cursorY - margin, behavior: 'instant' });
|
||||
}
|
||||
}
|
||||
ta.addEventListener('keyup', scrollToCursor);
|
||||
ta.addEventListener('click', scrollToCursor);
|
||||
// Ctrl+Home / Ctrl+End : scroller la fenêtre vers le début/fin du textarea
|
||||
ta.addEventListener('keydown', function (e) {
|
||||
if (!(e.ctrlKey || e.metaKey) || (e.key !== 'Home' && e.key !== 'End')) return;
|
||||
requestAnimationFrame(function () {
|
||||
ta.scrollIntoView({ block: e.key === 'Home' ? 'start' : 'end', behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Ctrl+Enter soumet le formulaire ────────────────────────────────────
|
||||
@@ -61,12 +54,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
var data = await res.json();
|
||||
if (data.ok) {
|
||||
indicator.textContent = 'Sauvegardé à ' + data.time;
|
||||
// Mettre à jour le titre de la page si le serveur l'a extrait
|
||||
var pageTitle = document.getElementById('wz-page-title');
|
||||
if (pageTitle && data.title) {
|
||||
var prefix = pageTitle.dataset.prefix || '';
|
||||
pageTitle.textContent = prefix ? prefix + data.title : data.title;
|
||||
}
|
||||
} else {
|
||||
indicator.textContent = 'Erreur de sauvegarde';
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.2.0
|
||||
1.2.1
|
||||
|
||||
@@ -43,6 +43,7 @@ foreach (glob($dataDir . '/*/meta.json') as $metaPath) {
|
||||
}
|
||||
|
||||
file_put_contents($mdPath, '# ' . $title . "\n\n" . ltrim($content));
|
||||
touch($metaPath);
|
||||
$updated++;
|
||||
}
|
||||
|
||||
|
||||
@@ -1164,8 +1164,9 @@ class ArticleManager
|
||||
$uuid = basename($dir);
|
||||
$cachePath = $this->articleCachePath($uuid);
|
||||
|
||||
// Utiliser le cache si plus récent que meta.json
|
||||
if (file_exists($cachePath) && filemtime($cachePath) >= filemtime($metaPath)) {
|
||||
// Utiliser le cache si plus récent que meta.json ET index.md
|
||||
$contentMtime = file_exists($dir . '/index.md') ? filemtime($dir . '/index.md') : 0;
|
||||
if (file_exists($cachePath) && filemtime($cachePath) >= filemtime($metaPath) && filemtime($cachePath) >= $contentMtime) {
|
||||
$cached = json_decode((string) file_get_contents($cachePath), true);
|
||||
if (is_array($cached) && !empty($cached['uuid'])) {
|
||||
return $cached;
|
||||
|
||||
@@ -9,6 +9,8 @@ $_accentMap = [
|
||||
];
|
||||
$_tocItems = [];
|
||||
$_tocSeen = [];
|
||||
// Le titre H1 est déjà affiché par le template ; on le retire du rendu.
|
||||
$_rawForRender = preg_replace('/^\s*# [^\n]*\n*/u', '', $rawContent);
|
||||
$_renderedContent = preg_replace_callback(
|
||||
'/<(h[23])>(.+?)<\/h[23]>/i',
|
||||
function ($m) use (&$_tocItems, &$_tocSeen, $_accentMap) {
|
||||
@@ -31,7 +33,7 @@ $_renderedContent = preg_replace_callback(
|
||||
$_tocItems[] = ['level' => $level, 'text' => $plain, 'id' => $id];
|
||||
return "<{$tag} id=\"" . htmlspecialchars($id) . "\">{$inner}</{$tag}>";
|
||||
},
|
||||
$Parsedown->text($rawContent)
|
||||
$Parsedown->text($_rawForRender)
|
||||
);
|
||||
|
||||
ob_start();
|
||||
|
||||
@@ -19,8 +19,7 @@ $_hasUuid = $_wizUuid !== '';
|
||||
<!-- En-tête avec boutons ────────────────────────────────────────────────── -->
|
||||
<div class="d-flex align-items-center justify-content-between gap-3 mb-4 flex-wrap">
|
||||
<div>
|
||||
<h1 class="h4 mb-0" id="wz-page-title"
|
||||
data-prefix="<?= $mode === 'edit' ? 'Modifier — ' : '' ?>"><?= $mode === 'create' ? 'Nouvel article' : htmlspecialchars('Modifier — ' . ($article['title'] ?? '')) ?></h1>
|
||||
<h1 class="h4 mb-0" id="wz-page-title"><?= $mode === 'create' ? 'Nouvel article' : 'Modifier' ?></h1>
|
||||
<?php if ($_hasUuid): ?>
|
||||
<span id="autosave-indicator" class="text-muted small"></span>
|
||||
<?php endif; ?>
|
||||
@@ -44,7 +43,8 @@ $_hasUuid = $_wizUuid !== '';
|
||||
<div class="mb-3">
|
||||
<label for="wz-content" class="form-label fw-semibold">Contenu <small class="text-muted fw-normal">(Markdown)</small></label>
|
||||
<textarea class="form-control font-monospace" id="wz-content" name="content" rows="18"
|
||||
style="min-height:320px"><?= htmlspecialchars($content ?? '') ?></textarea>
|
||||
style="min-height:320px"
|
||||
placeholder="# Titre de l'article Votre contenu ici…"><?= htmlspecialchars($content ?? '') ?></textarea>
|
||||
</div>
|
||||
|
||||
</div><!-- /col-lg-9 -->
|
||||
|
||||
Reference in New Issue
Block a user