@agence-zef/astro 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* dans le cookie `zef-consent` (redemandé si les catégories changent). Google Analytics 4
|
|
7
7
|
* (`gaId`) n'est chargé qu'après accord sur « Mesure d'audience » ; un retrait efface ses
|
|
8
8
|
* cookies `_ga*` et recharge la page. Un élément `data-zef-cookies` (lien « Gérer les cookies »
|
|
9
|
-
* du footer) rouvre les préférences. Le choix est publié dans `window.zefConsent` et
|
|
9
|
+
* du footer) rouvre les préférences. Rien dans un cadre (aperçus du CMS). Le choix est publié dans `window.zefConsent` et
|
|
10
10
|
* l'événement `zef:consent`. À placer une fois dans le gabarit, avant `</body>`. Habillage :
|
|
11
11
|
* variables `--zef-*` (`@agence-zef/astro/styles.css`) ou `--cc-*` de vanilla-cookieconsent.
|
|
12
12
|
*/
|
|
@@ -187,6 +187,7 @@ const locale = Astro.currentLocale ?? "";
|
|
|
187
187
|
});
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
// Site ouvert dans un cadre (aperçus et vignettes du CMS) : pas de bandeau.
|
|
190
191
|
const root = document.querySelector<HTMLElement>("[data-zef-cookie-banner]");
|
|
191
|
-
if (root) start(root);
|
|
192
|
+
if (root && window.self === window.top) start(root);
|
|
192
193
|
</script>
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
---
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Texte riche saisi dans le CMS (paragraphes, titres autorisés, listes, liens), dans un `<div>`.
|
|
4
|
+
* `inline` : texte riche en ligne d'un titre ou d'un sous-titre (`f.richtext({ inline: true })` :
|
|
5
|
+
* gras, italique, souligné, surligné, lien, retours à la ligne), rendu sans enveloppe, à placer
|
|
6
|
+
* dans la balise du titre : `<h1><RichText html={titre} inline /></h1>`.
|
|
7
|
+
*/
|
|
8
|
+
import { inlineHtml } from "@agence-zef/schema";
|
|
9
|
+
|
|
3
10
|
interface Props {
|
|
4
|
-
html: string;
|
|
11
|
+
html: string | null | undefined;
|
|
5
12
|
class?: string;
|
|
13
|
+
inline?: boolean;
|
|
6
14
|
}
|
|
7
15
|
|
|
8
|
-
const { html, class: className } = Astro.props;
|
|
16
|
+
const { html, class: className, inline = false } = Astro.props;
|
|
9
17
|
---
|
|
10
18
|
|
|
11
|
-
{html && <div class={className} set:html={html} />}
|
|
19
|
+
{html && (inline ? <Fragment set:html={inlineHtml(html)} /> : <div class={className} set:html={html} />)}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Rendu à la demande (`rendering: "cached"`) : règles de cache des pages du CMS. Le CDN garde
|
|
3
|
-
* une page un an ; une publication l'invalide par le tag `zef`
|
|
4
|
-
*
|
|
3
|
+
* une page un an ; une publication l'invalide par le tag `zef` et la visite suivante reçoit la
|
|
4
|
+
* nouvelle version. Pas de `swr` : il faisait servir l'ancienne version une dernière fois après
|
|
5
|
+
* la publication (« Voir la page » montrait l'ancienne page jusqu'au rechargement).
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
/** Tag posé sur toutes les réponses du site rendues depuis le CMS. */
|
|
8
9
|
export const CACHE_TAG = "zef";
|
|
9
10
|
|
|
10
|
-
export const PAGE_CACHE = { maxAge: 60 * 60 * 24 * 365
|
|
11
|
+
export const PAGE_CACHE = { maxAge: 60 * 60 * 24 * 365 };
|
|
@@ -52,6 +52,8 @@ if (!site || !section) Astro.response.status = 404;
|
|
|
52
52
|
html { overflow: hidden; scrollbar-width: none; }
|
|
53
53
|
body { pointer-events: none; }
|
|
54
54
|
astro-dev-toolbar { display: none !important; }
|
|
55
|
+
/* Bandeau cookies et popups du gabarit : jamais dans une vignette. */
|
|
56
|
+
#cc-main, .zef-popup { display: none !important; }
|
|
55
57
|
</style>
|
|
56
58
|
<script>
|
|
57
59
|
// La section seule : tout ce qui l'entoure dans le gabarit (header, footer…) est masqué.
|
package/dist/overlay.d.ts
CHANGED
|
@@ -58,6 +58,14 @@ export type ToPreview = {
|
|
|
58
58
|
| {
|
|
59
59
|
zef: "locked";
|
|
60
60
|
fields: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Réduction de l'aperçu par le CMS (vue Ordinateur rendue plus large puis réduite) : l'overlay
|
|
64
|
+
* s'agrandit d'autant pour garder la taille de l'interface de l'éditeur.
|
|
65
|
+
*/
|
|
66
|
+
| {
|
|
67
|
+
zef: "scale";
|
|
68
|
+
value: number;
|
|
61
69
|
};
|
|
62
70
|
export type Pin = {
|
|
63
71
|
id: string;
|
package/dist/overlay.js
CHANGED
|
@@ -16,6 +16,8 @@ export function startOverlay() {
|
|
|
16
16
|
let pins = [];
|
|
17
17
|
let commentMode = false;
|
|
18
18
|
let locked = new Set();
|
|
19
|
+
/** Agrandissement de l'overlay (inverse de la réduction de l'aperçu par le CMS). */
|
|
20
|
+
let zoom = 1;
|
|
19
21
|
/** Image survolée pendant qu'on glisse un fichier. */
|
|
20
22
|
let dropTarget = null;
|
|
21
23
|
/* ---------- Repérage des champs ---------- */
|
|
@@ -37,6 +39,15 @@ export function startOverlay() {
|
|
|
37
39
|
element.remove();
|
|
38
40
|
element = container;
|
|
39
41
|
}
|
|
42
|
+
else if (element && [...element.children].some((c) => c.tagName !== "BR")) {
|
|
43
|
+
// Texte posé à côté d'autres éléments (pictogramme, image) : il reçoit son propre
|
|
44
|
+
// `<span>`, sinon l'édition et la saisie en direct remplaceraient aussi ses voisins.
|
|
45
|
+
// Les `<br>` d'un texte sur plusieurs lignes ne comptent pas.
|
|
46
|
+
const span = document.createElement("span");
|
|
47
|
+
node.before(span);
|
|
48
|
+
span.append(node);
|
|
49
|
+
element = span;
|
|
50
|
+
}
|
|
40
51
|
if (element && locations[0] && !element.hasAttribute(ATTR))
|
|
41
52
|
element.setAttribute(ATTR, locations[0]);
|
|
42
53
|
}
|
|
@@ -123,26 +134,26 @@ export function startOverlay() {
|
|
|
123
134
|
*, *::before, *::after { animation: none !important; transition: none !important; }
|
|
124
135
|
[${ATTR}] { cursor: pointer; }
|
|
125
136
|
[${ATTR}][contenteditable] { cursor: text; outline: none; }
|
|
126
|
-
#zef-overlay { position: fixed; inset: 0; pointer-events: none; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif; }
|
|
127
|
-
#zef-overlay .zef-frame { position: fixed; border: 1.5px solid #8c40f7; border-radius: 2px; }
|
|
137
|
+
#zef-overlay { --zef-zoom: 1; position: fixed; inset: 0; pointer-events: none; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif; }
|
|
138
|
+
#zef-overlay .zef-frame { position: fixed; border: calc(1.5px * var(--zef-zoom)) solid #8c40f7; border-radius: 2px; }
|
|
128
139
|
#zef-overlay .zef-frame.zef-section { border-style: dashed; border-color: #8c40f7aa; }
|
|
129
|
-
#zef-overlay .zef-frame.zef-selected { border-width: 2px; }
|
|
130
|
-
#zef-overlay .zef-frame.zef-field { border: 1.5px solid #8c40f7; border-radius: 3px; background: #8c40f70d; }
|
|
140
|
+
#zef-overlay .zef-frame.zef-selected { border-width: calc(2px * var(--zef-zoom)); }
|
|
141
|
+
#zef-overlay .zef-frame.zef-field { border: calc(1.5px * var(--zef-zoom)) solid #8c40f7; border-radius: 3px; background: #8c40f70d; }
|
|
131
142
|
#zef-overlay .zef-frame.zef-field .zef-tag { padding: 1px 5px; font-size: 10px; }
|
|
132
|
-
#zef-overlay .zef-tag { position: absolute; left: -1.5px; bottom: 100%; margin-bottom: 2px; padding: 2px 6px; border-radius: 4px; background: #8c40f7; color: #fff; white-space: nowrap; }
|
|
133
|
-
#zef-overlay .zef-compare { border: 2px solid #ea580c; }
|
|
134
|
-
#zef-overlay .zef-compare .zef-tag { left: 8px; top: 8px; bottom: auto; margin: 0; background: #fff7ed; color: #c2410c; }
|
|
143
|
+
#zef-overlay .zef-tag { position: absolute; left: -1.5px; bottom: 100%; margin-bottom: 2px; padding: 2px 6px; border-radius: 4px; background: #8c40f7; color: #fff; white-space: nowrap; transform: scale(var(--zef-zoom)); transform-origin: left bottom; }
|
|
144
|
+
#zef-overlay .zef-compare { border: calc(2px * var(--zef-zoom)) solid #ea580c; }
|
|
145
|
+
#zef-overlay .zef-compare .zef-tag { left: 8px; top: 8px; bottom: auto; margin: 0; background: #fff7ed; color: #c2410c; transform-origin: left top; }
|
|
135
146
|
#zef-overlay .zef-compare.zef-added { border-style: dashed; border-color: #16a34a; }
|
|
136
147
|
#zef-overlay .zef-compare.zef-added .zef-tag { background: #f0fdf4; color: #15803d; }
|
|
137
|
-
#zef-overlay .zef-pin { position: fixed; display: grid; place-items: center; width: 20px; height: 20px; border: 2px solid #fff; border-radius: 999px; background: #f97316; color: #fff; font: 600 10px/1 system-ui, sans-serif; box-shadow: 0 1px 4px rgb(0 0 0 / 0.25); cursor: pointer; pointer-events: auto; }
|
|
148
|
+
#zef-overlay .zef-pin { position: fixed; display: grid; place-items: center; width: 20px; height: 20px; border: 2px solid #fff; border-radius: 999px; background: #f97316; color: #fff; font: 600 10px/1 system-ui, sans-serif; box-shadow: 0 1px 4px rgb(0 0 0 / 0.25); cursor: pointer; pointer-events: auto; transform: scale(var(--zef-zoom)); }
|
|
138
149
|
html.zef-commenting, html.zef-commenting * { cursor: crosshair !important; }
|
|
139
|
-
#zef-overlay .zef-toolbar { position: fixed; display: flex; gap: 2px; padding: 3px; border: 1px solid #e4e4e7; border-radius: 8px; background: #fff; box-shadow: 0 4px 12px rgb(0 0 0 / 0.12); pointer-events: auto; }
|
|
150
|
+
#zef-overlay .zef-toolbar { position: fixed; display: flex; gap: 2px; padding: 3px; border: 1px solid #e4e4e7; border-radius: 8px; background: #fff; box-shadow: 0 4px 12px rgb(0 0 0 / 0.12); pointer-events: auto; transform: scale(var(--zef-zoom)); transform-origin: right top; }
|
|
140
151
|
#zef-overlay .zef-toolbar button { display: grid; place-items: center; width: 26px; height: 26px; border: 0; border-radius: 6px; background: transparent; color: #3f3f46; cursor: pointer; }
|
|
141
152
|
#zef-overlay .zef-toolbar button:hover { background: #f4f4f5; }
|
|
142
153
|
#zef-overlay .zef-toolbar button:disabled { opacity: 0.35; cursor: default; background: transparent; }
|
|
143
154
|
#zef-overlay .zef-toolbar button.zef-danger { color: #e11d48; }
|
|
144
|
-
#zef-overlay .zef-insert { position: fixed; height: 2px; margin-top: -1px; background: #8c40f7; }
|
|
145
|
-
#zef-overlay .zef-insert button { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; align-items: center; gap: 4px; padding: 4px 12px 4px 10px; border: 0; border-radius: 999px; background: #8c40f7; color: #fff; font: 500 12px/1.4 system-ui, sans-serif; white-space: nowrap; cursor: pointer; pointer-events: auto; }
|
|
155
|
+
#zef-overlay .zef-insert { position: fixed; height: calc(2px * var(--zef-zoom)); margin-top: calc(-1px * var(--zef-zoom)); background: #8c40f7; }
|
|
156
|
+
#zef-overlay .zef-insert button { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(var(--zef-zoom)); display: flex; align-items: center; gap: 4px; padding: 4px 12px 4px 10px; border: 0; border-radius: 999px; background: #8c40f7; color: #fff; font: 500 12px/1.4 system-ui, sans-serif; white-space: nowrap; cursor: pointer; pointer-events: auto; }
|
|
146
157
|
`;
|
|
147
158
|
document.head.append(style);
|
|
148
159
|
const layer = document.createElement("div");
|
|
@@ -162,8 +173,13 @@ export function startOverlay() {
|
|
|
162
173
|
span.className = "zef-tag";
|
|
163
174
|
span.textContent = tag;
|
|
164
175
|
// Cadre collé en haut de l'aperçu (header) : l'étiquette passe à l'intérieur.
|
|
165
|
-
if (r.top < 20)
|
|
166
|
-
Object.assign(span.style, {
|
|
176
|
+
if (r.top < 20 * zoom)
|
|
177
|
+
Object.assign(span.style, {
|
|
178
|
+
bottom: "auto",
|
|
179
|
+
top: "2px",
|
|
180
|
+
left: "2px",
|
|
181
|
+
transformOrigin: "left top",
|
|
182
|
+
});
|
|
167
183
|
div.append(span);
|
|
168
184
|
}
|
|
169
185
|
layer.append(div);
|
|
@@ -205,8 +221,12 @@ export function startOverlay() {
|
|
|
205
221
|
bar.append(button);
|
|
206
222
|
}
|
|
207
223
|
layer.append(bar);
|
|
208
|
-
const top = Math.max(r.top + 8, 8);
|
|
209
|
-
|
|
224
|
+
const top = Math.max(r.top + 8 * zoom, 8 * zoom);
|
|
225
|
+
// Agrandie depuis son coin haut droit : `offsetWidth` reste la largeur avant agrandissement.
|
|
226
|
+
Object.assign(bar.style, {
|
|
227
|
+
top: `${top}px`,
|
|
228
|
+
left: `${r.right - bar.offsetWidth - 8 * zoom}px`,
|
|
229
|
+
});
|
|
210
230
|
}
|
|
211
231
|
/** Ligne « + Ajouter une section » sous la section survolée. */
|
|
212
232
|
function insertLine(section, r) {
|
|
@@ -450,8 +470,10 @@ export function startOverlay() {
|
|
|
450
470
|
const element = fieldElement(section, path);
|
|
451
471
|
if (!element || element === editing)
|
|
452
472
|
return;
|
|
453
|
-
if (info(element)?.kind === "richtext")
|
|
454
|
-
|
|
473
|
+
if (info(element)?.kind === "richtext") {
|
|
474
|
+
// Espaces répétés (titre en ligne) : gardés comme une fois enregistrés.
|
|
475
|
+
element.innerHTML = value.replace(/(^|>)([^<]*)/g, (_, open, text) => open + text.replace(/ {2,}/g, (spaces) => ` ${" ".repeat(spaces.length - 1)}`));
|
|
476
|
+
}
|
|
455
477
|
else
|
|
456
478
|
element.textContent = value;
|
|
457
479
|
}
|
|
@@ -551,6 +573,10 @@ export function startOverlay() {
|
|
|
551
573
|
case "commentMode":
|
|
552
574
|
setCommentMode(message.on);
|
|
553
575
|
break;
|
|
576
|
+
case "scale":
|
|
577
|
+
zoom = message.value > 0 ? 1 / message.value : 1;
|
|
578
|
+
layer.style.setProperty("--zef-zoom", String(zoom));
|
|
579
|
+
break;
|
|
554
580
|
case "showPin": {
|
|
555
581
|
const pin = pins.find((p) => p.id === message.id);
|
|
556
582
|
const element = pin ? pinElement(pin) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agence-zef/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Intégration Astro du CMS ZEF : routes, rendu des sections, aperçu, composants réutilisables sans style.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"jiti": "^2.6.1",
|
|
88
88
|
"vanilla-cookieconsent": "3.1.0",
|
|
89
|
-
"@agence-zef/schema": "0.
|
|
90
|
-
"@agence-zef/sdk": "0.
|
|
89
|
+
"@agence-zef/schema": "0.9.0",
|
|
90
|
+
"@agence-zef/sdk": "0.9.0"
|
|
91
91
|
},
|
|
92
92
|
"homepage": "https://agence-zef.fr",
|
|
93
93
|
"scripts": {
|