@lystech/sections 0.1.0 → 0.3.0
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.
- package/README.md +109 -55
- package/dist/SectionsProvider.d.ts +78 -0
- package/dist/SignatureLystech.d.ts +9 -0
- package/dist/editeur/Connexion.d.ts +6 -0
- package/dist/editeur/Editeur.d.ts +6 -0
- package/dist/editeur/TexteEnPlace.d.ts +7 -0
- package/dist/editeur/api.d.ts +39 -0
- package/dist/editeur/champs.d.ts +9 -0
- package/dist/editeur/index.d.ts +20 -0
- package/dist/editeur/pont.d.ts +28 -0
- package/dist/editeur/styles.d.ts +2 -0
- package/dist/editeur.js +1208 -0
- package/dist/index.d.ts +18 -108
- package/dist/index.js +259 -82
- package/dist/morceaux/sourceTexte-BMPMpNg9.js +71 -0
- package/dist/sourceTexte.d.ts +34 -0
- package/dist/types.d.ts +41 -0
- package/dist/useSection.d.ts +50 -0
- package/package.json +14 -6
- package/dist/index.umd.cjs +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,108 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
options?: string[];
|
|
20
|
-
/** Sous-champs d'une `list`. */
|
|
21
|
-
of?: ChampDeclare[];
|
|
22
|
-
/**
|
|
23
|
-
* Champ TRADUIT. La valeur stockée devient { fr: …, en: … } et le paquet
|
|
24
|
-
* rend celle de la langue courante.
|
|
25
|
-
*
|
|
26
|
-
* Le serveur ne connaît pas cette clé — il stocke la déclaration telle
|
|
27
|
-
* quelle. C'est voulu : ajouter une langue ne doit pas demander une
|
|
28
|
-
* migration côté plateforme.
|
|
29
|
-
*/
|
|
30
|
-
localized?: boolean;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
declare type Contexte = {
|
|
34
|
-
/** Sous-domaine de l'organisation dans Lystech. */
|
|
35
|
-
site: string;
|
|
36
|
-
/** Langue courante — décide quelle version d'un champ traduit est rendue. */
|
|
37
|
-
langue: string;
|
|
38
|
-
sections: SectionPubliee[];
|
|
39
|
-
etat: Etat;
|
|
40
|
-
recharger: () => void;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
declare type Etat = "chargement" | "pret" | "erreur";
|
|
44
|
-
|
|
45
|
-
export declare type ResultatSection<T> = {
|
|
46
|
-
/** Le contenu à afficher : publié si présent, défaut sinon. */
|
|
47
|
-
contenu: T;
|
|
48
|
-
/** Vrai quand le contenu vient du serveur, faux quand c'est le défaut. */
|
|
49
|
-
publie: boolean;
|
|
50
|
-
/** L'identifiant de la section — nécessaire à l'édition. */
|
|
51
|
-
UID: string | null;
|
|
52
|
-
chargement: boolean;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
/** Une section telle qu'elle revient du serveur. */
|
|
56
|
-
export declare type SectionPubliee = {
|
|
57
|
-
UID: string;
|
|
58
|
-
page: string;
|
|
59
|
-
blockType: string;
|
|
60
|
-
position: number;
|
|
61
|
-
data: Record<string, unknown> | null;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export declare function SectionsProvider({ site, page, langue, apiBaseUrl, children, }: {
|
|
65
|
-
/** Sous-domaine de l'organisation (ex. « armoise »). */
|
|
66
|
-
site: string;
|
|
67
|
-
/** La page dont on veut les sections (ex. « accueil »). */
|
|
68
|
-
page: string;
|
|
69
|
-
langue?: string;
|
|
70
|
-
apiBaseUrl?: string;
|
|
71
|
-
children: ReactNode;
|
|
72
|
-
}): JSX.Element;
|
|
73
|
-
|
|
74
|
-
export declare type TypeDeChamp = "text" | "richText" | "image" | "number" | "boolean" | "url" | "date" | "choice" | "list";
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Le contenu d'un type de bloc sur la page courante.
|
|
78
|
-
*
|
|
79
|
-
* Le cas visé est celui d'un site DÉJÀ DESSINÉ : un bloc par type et par page,
|
|
80
|
-
* dont on veut rendre les mots et les images modifiables — pas un constructeur
|
|
81
|
-
* de pages. Pour des blocs répétables, voir `useSectionList`.
|
|
82
|
-
*/
|
|
83
|
-
export declare function useSection<T extends object>(blockType: string, options: {
|
|
84
|
-
defaut: T;
|
|
85
|
-
}): ResultatSection<T>;
|
|
86
|
-
|
|
87
|
-
/** Plusieurs blocs du même type, dans l'ordre choisi par le client. */
|
|
88
|
-
export declare function useSectionList<T extends object>(blockType: string, options?: {
|
|
89
|
-
defaut?: T[];
|
|
90
|
-
}): {
|
|
91
|
-
items: Array<T & {
|
|
92
|
-
__uid: string;
|
|
93
|
-
}>;
|
|
94
|
-
publie: boolean;
|
|
95
|
-
chargement: boolean;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Le contexte, ou `null` HORS d'un fournisseur.
|
|
100
|
-
*
|
|
101
|
-
* On ne lève pas : un composant branché sur les sections doit rester
|
|
102
|
-
* utilisable dans une page qui n'en a pas (une maquette, un test, une page
|
|
103
|
-
* d'erreur). Il affichera son repli, ce qui est exactement le bon
|
|
104
|
-
* comportement.
|
|
105
|
-
*/
|
|
106
|
-
export declare function useSectionsContext(): Contexte | null;
|
|
107
|
-
|
|
108
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* @lystech/sections — le contenu d'un site, modifiable par son propriétaire.
|
|
3
|
+
*
|
|
4
|
+
* CE QUI EST EXPORTÉ ICI EST CE QU'UN VISITEUR TÉLÉCHARGE : la lecture, et
|
|
5
|
+
* rien d'autre. L'interface d'édition vivra dans un point d'entrée séparé,
|
|
6
|
+
* chargé à la demande. Un visiteur ne doit pas payer le poids d'un éditeur
|
|
7
|
+
* qu'il ne verra jamais.
|
|
8
|
+
*
|
|
9
|
+
* Le paquet ne dépend PAS de @lystech/core : une clinique qui veut modifier
|
|
10
|
+
* trois textes n'a aucune raison de charger un magasin, un panier et PayPal.
|
|
11
|
+
*/
|
|
12
|
+
export { SectionsProvider, useSectionsContext } from './SectionsProvider';
|
|
13
|
+
export { SignatureLystech } from './SignatureLystech';
|
|
14
|
+
export { adaptateurI18next, appliquerAuxTextes } from './sourceTexte';
|
|
15
|
+
export type { Dictionnaire, SourceTexte } from './sourceTexte';
|
|
16
|
+
export { useSection, useSectionList } from './useSection';
|
|
17
|
+
export type { BlocDeclare, ChampDeclare, SectionPubliee, TypeDeChamp, } from './types';
|
|
18
|
+
export type { AncrageEdition, ResultatSection } from './useSection';
|
package/dist/index.js
CHANGED
|
@@ -1,107 +1,284 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { jsx as S, jsxs as L, Fragment as F } from "react/jsx-runtime";
|
|
2
|
+
import { useState as h, useRef as P, useEffect as x, useCallback as O, useMemo as _, useContext as M, createContext as N } from "react";
|
|
3
|
+
import { appliquerAuxTextes as T } from "./morceaux/sourceTexte-BMPMpNg9.js";
|
|
4
|
+
import { adaptateurI18next as rt } from "./morceaux/sourceTexte-BMPMpNg9.js";
|
|
5
|
+
const d = "lystech-edit", k = N(null), q = "https://api.lystech.ca/api";
|
|
6
|
+
function H() {
|
|
7
|
+
if (typeof window > "u") return null;
|
|
8
|
+
const t = (n) => {
|
|
9
|
+
try {
|
|
10
|
+
window.sessionStorage.setItem(d, n);
|
|
11
|
+
} catch {
|
|
12
|
+
}
|
|
13
|
+
return n;
|
|
14
|
+
};
|
|
15
|
+
try {
|
|
16
|
+
const n = window.location.hash.replace(/^#/, "");
|
|
17
|
+
if (n.includes(d + "=")) {
|
|
18
|
+
const c = new URLSearchParams(n), o = c.get(d);
|
|
19
|
+
if (o) {
|
|
20
|
+
c.delete(d);
|
|
21
|
+
const i = c.toString();
|
|
22
|
+
return window.history.replaceState(
|
|
23
|
+
{},
|
|
24
|
+
"",
|
|
25
|
+
window.location.pathname + window.location.search + (i ? "#" + i : "")
|
|
26
|
+
), t(o);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const e = new URL(window.location.href), r = e.searchParams.get(d);
|
|
30
|
+
return r ? (e.searchParams.delete(d), window.history.replaceState({}, "", e.toString()), t(r)) : window.sessionStorage.getItem(d);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function X({
|
|
36
|
+
site: t,
|
|
37
|
+
page: n,
|
|
38
|
+
langue: e = "fr",
|
|
39
|
+
apiBaseUrl: r = q,
|
|
40
|
+
sectionsInitiales: c,
|
|
41
|
+
sourceTexte: o,
|
|
42
|
+
pagesPartagees: i,
|
|
43
|
+
children: m
|
|
10
44
|
}) {
|
|
11
|
-
const [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
45
|
+
const [u, g] = h(
|
|
46
|
+
c ?? []
|
|
47
|
+
), [w, p] = h(
|
|
48
|
+
c?.length ? "pret" : "chargement"
|
|
49
|
+
), [y, A] = h(0), [R, J] = h({}), [U, $] = h(!1), D = P(null);
|
|
50
|
+
x(() => {
|
|
51
|
+
if (!t || !n) return;
|
|
52
|
+
D.current?.abort();
|
|
53
|
+
const a = new AbortController();
|
|
54
|
+
D.current = a, p("chargement");
|
|
55
|
+
const f = r + "/site-sections/public/" + encodeURIComponent(t) + "/" + encodeURIComponent([n, ...i ?? []].join(","));
|
|
56
|
+
return fetch(f, { signal: a.signal }).then(
|
|
57
|
+
(s) => s.ok ? s.json() : Promise.reject(new Error(String(s.status)))
|
|
58
|
+
).then((s) => {
|
|
59
|
+
a.signal.aborted || (g(Array.isArray(s) ? s : []), p("pret"));
|
|
21
60
|
}).catch((s) => {
|
|
22
|
-
|
|
23
|
-
}), () =>
|
|
24
|
-
}, [
|
|
25
|
-
const
|
|
61
|
+
a.signal.aborted || s?.name === "AbortError" || p("erreur");
|
|
62
|
+
}), () => a.abort();
|
|
63
|
+
}, [t, n, r, y, (i ?? []).join(",")]);
|
|
64
|
+
const E = O(() => A((a) => a + 1), []);
|
|
65
|
+
x(() => {
|
|
66
|
+
!o || !u.length || T(u, o);
|
|
67
|
+
}, [u, o]);
|
|
68
|
+
const j = O(
|
|
69
|
+
(a, f) => J((s) => ({ ...s, [a]: f })),
|
|
70
|
+
[]
|
|
71
|
+
), l = P({
|
|
72
|
+
site: t,
|
|
73
|
+
page: n,
|
|
74
|
+
langue: e,
|
|
75
|
+
poserApercu: () => {
|
|
76
|
+
},
|
|
77
|
+
recharger: () => {
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
l.current.site = t, l.current.page = n, l.current.langue = e, l.current.poserApercu = j, l.current.sourceTexte = o, l.current.recharger = E, x(() => {
|
|
81
|
+
l.current.surChangementDePage?.(n);
|
|
82
|
+
}, [n]), x(() => {
|
|
83
|
+
const a = H();
|
|
84
|
+
if (!a) return;
|
|
85
|
+
let f = !0, s;
|
|
86
|
+
return import("@lystech/sections/editeur").then((b) => {
|
|
87
|
+
f && ($(!0), s = b.monterEditeur({
|
|
88
|
+
jeton: a,
|
|
89
|
+
site: t,
|
|
90
|
+
apiBaseUrl: r,
|
|
91
|
+
pont: l.current
|
|
92
|
+
}));
|
|
93
|
+
}).catch((b) => {
|
|
94
|
+
console.error("[lystech] éditeur indisponible:", b?.message ?? b);
|
|
95
|
+
}), () => {
|
|
96
|
+
f = !1, s?.();
|
|
97
|
+
};
|
|
98
|
+
}, [t, r]);
|
|
99
|
+
const z = _(
|
|
26
100
|
() => ({
|
|
27
|
-
site:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
101
|
+
site: t,
|
|
102
|
+
page: n,
|
|
103
|
+
langue: e,
|
|
104
|
+
apiBaseUrl: r,
|
|
105
|
+
sections: u,
|
|
106
|
+
etat: w,
|
|
107
|
+
recharger: E,
|
|
108
|
+
apercu: R,
|
|
109
|
+
poserApercu: j,
|
|
110
|
+
modeEdition: U
|
|
32
111
|
}),
|
|
33
|
-
[
|
|
112
|
+
[
|
|
113
|
+
t,
|
|
114
|
+
n,
|
|
115
|
+
e,
|
|
116
|
+
r,
|
|
117
|
+
u,
|
|
118
|
+
w,
|
|
119
|
+
E,
|
|
120
|
+
R,
|
|
121
|
+
j,
|
|
122
|
+
U
|
|
123
|
+
]
|
|
34
124
|
);
|
|
35
|
-
return /* @__PURE__ */
|
|
125
|
+
return /* @__PURE__ */ S(k.Provider, { value: z, children: m });
|
|
36
126
|
}
|
|
37
|
-
function
|
|
38
|
-
return
|
|
127
|
+
function I() {
|
|
128
|
+
return M(k);
|
|
39
129
|
}
|
|
40
|
-
|
|
41
|
-
|
|
130
|
+
const W = "https://api.lystech.ca/api", v = "lystech-edit";
|
|
131
|
+
function Y({
|
|
132
|
+
site: t,
|
|
133
|
+
apiBaseUrl: n,
|
|
134
|
+
className: e,
|
|
135
|
+
mention: r = "Réalisé avec Lystech",
|
|
136
|
+
connexion: c = "Connexion"
|
|
137
|
+
}) {
|
|
138
|
+
const o = I(), i = t ?? o?.site ?? "", m = n ?? o?.apiBaseUrl ?? W, [u, g] = h(!1);
|
|
139
|
+
if (!i) return null;
|
|
140
|
+
const w = async () => {
|
|
141
|
+
if (!u) {
|
|
142
|
+
g(!0);
|
|
143
|
+
try {
|
|
144
|
+
(await import("@lystech/sections/editeur")).monterConnexion({
|
|
145
|
+
site: i,
|
|
146
|
+
apiBaseUrl: m,
|
|
147
|
+
surJeton: (A) => {
|
|
148
|
+
try {
|
|
149
|
+
window.sessionStorage.setItem(v, A);
|
|
150
|
+
} catch {
|
|
151
|
+
window.location.hash = v + "=" + encodeURIComponent(A);
|
|
152
|
+
}
|
|
153
|
+
window.location.reload();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
} catch (y) {
|
|
157
|
+
console.error("[lystech] connexion indisponible:", y?.message ?? y);
|
|
158
|
+
} finally {
|
|
159
|
+
g(!1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}, p = {
|
|
163
|
+
color: "inherit",
|
|
164
|
+
font: "inherit",
|
|
165
|
+
background: "none",
|
|
166
|
+
border: 0,
|
|
167
|
+
padding: 0,
|
|
168
|
+
cursor: "pointer",
|
|
169
|
+
textDecoration: "underline",
|
|
170
|
+
textUnderlineOffset: "0.2em"
|
|
171
|
+
};
|
|
172
|
+
return /* @__PURE__ */ L(
|
|
173
|
+
"div",
|
|
174
|
+
{
|
|
175
|
+
className: e,
|
|
176
|
+
style: {
|
|
177
|
+
display: "flex",
|
|
178
|
+
flexWrap: "wrap",
|
|
179
|
+
alignItems: "center",
|
|
180
|
+
gap: "0.5em",
|
|
181
|
+
fontSize: "0.85em",
|
|
182
|
+
opacity: 0.7,
|
|
183
|
+
lineHeight: 1.5
|
|
184
|
+
},
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ S(
|
|
187
|
+
"a",
|
|
188
|
+
{
|
|
189
|
+
href: "https://lystech.ca",
|
|
190
|
+
target: "_blank",
|
|
191
|
+
rel: "noreferrer",
|
|
192
|
+
style: { color: "inherit" },
|
|
193
|
+
children: r
|
|
194
|
+
}
|
|
195
|
+
),
|
|
196
|
+
!o?.modeEdition && /* @__PURE__ */ L(F, { children: [
|
|
197
|
+
/* @__PURE__ */ S("span", { "aria-hidden": "true", children: "·" }),
|
|
198
|
+
/* @__PURE__ */ S("button", { type: "button", style: p, onClick: w, children: u ? "…" : c })
|
|
199
|
+
] })
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
);
|
|
42
203
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
if (I(e)) {
|
|
46
|
-
const t = e, o = r.slice(0, 2);
|
|
47
|
-
return t[r] ?? t[o] ?? Object.values(t).find((c) => c != null) ?? "";
|
|
48
|
-
}
|
|
49
|
-
if (e && typeof e == "object") {
|
|
50
|
-
const t = {};
|
|
51
|
-
for (const [o, n] of Object.entries(e))
|
|
52
|
-
t[o] = i(n, r);
|
|
53
|
-
return t;
|
|
54
|
-
}
|
|
55
|
-
return e;
|
|
204
|
+
function Z(t) {
|
|
205
|
+
return !!t && typeof t == "object" && !Array.isArray(t) && Object.keys(t).every((n) => /^[a-z]{2}(-[A-Za-z]{2})?$/.test(n));
|
|
56
206
|
}
|
|
57
|
-
function
|
|
58
|
-
if (
|
|
207
|
+
function C(t, n) {
|
|
208
|
+
if (Array.isArray(t)) return t.map((e) => C(e, n));
|
|
209
|
+
if (Z(t)) {
|
|
210
|
+
const e = t, r = n.slice(0, 2);
|
|
211
|
+
return e[n] ?? e[r] ?? Object.values(e).find((o) => o != null) ?? "";
|
|
212
|
+
}
|
|
213
|
+
if (t && typeof t == "object") {
|
|
214
|
+
const e = {};
|
|
215
|
+
for (const [r, c] of Object.entries(t))
|
|
216
|
+
e[r] = C(c, n);
|
|
59
217
|
return e;
|
|
60
|
-
|
|
61
|
-
for (const [o, n] of Object.entries(r))
|
|
62
|
-
n != null && (t[o] = n);
|
|
218
|
+
}
|
|
63
219
|
return t;
|
|
64
220
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
221
|
+
function G(t, n) {
|
|
222
|
+
if (!n || typeof n != "object" || Array.isArray(n))
|
|
223
|
+
return t;
|
|
224
|
+
const e = { ...t };
|
|
225
|
+
for (const [r, c] of Object.entries(n))
|
|
226
|
+
c != null && (e[r] = c);
|
|
227
|
+
return e;
|
|
228
|
+
}
|
|
229
|
+
function B(t, n) {
|
|
230
|
+
const e = I(), r = e?.apercu?.[t];
|
|
231
|
+
return _(() => {
|
|
232
|
+
const c = e?.sections.find(
|
|
233
|
+
(m) => m.blockType === t
|
|
234
|
+
), o = r ?? c?.data ?? null, i = o ? C(o, e?.langue ?? "fr") : null;
|
|
71
235
|
return {
|
|
72
|
-
contenu:
|
|
73
|
-
publie: !!
|
|
74
|
-
UID:
|
|
75
|
-
chargement:
|
|
236
|
+
contenu: G(n.defaut, i),
|
|
237
|
+
publie: !!c?.data,
|
|
238
|
+
UID: c?.UID ?? null,
|
|
239
|
+
chargement: e?.etat === "chargement",
|
|
240
|
+
ancrage: { "data-lystech-section": t }
|
|
76
241
|
};
|
|
77
|
-
}, [
|
|
242
|
+
}, [
|
|
243
|
+
e?.sections,
|
|
244
|
+
e?.langue,
|
|
245
|
+
e?.etat,
|
|
246
|
+
r,
|
|
247
|
+
t,
|
|
248
|
+
n.defaut
|
|
249
|
+
]);
|
|
78
250
|
}
|
|
79
|
-
function
|
|
80
|
-
const
|
|
81
|
-
return
|
|
82
|
-
const
|
|
83
|
-
(
|
|
251
|
+
function tt(t, n) {
|
|
252
|
+
const e = I();
|
|
253
|
+
return _(() => {
|
|
254
|
+
const r = { "data-lystech-section": t }, c = (e?.sections ?? []).filter(
|
|
255
|
+
(o) => o.blockType === t
|
|
84
256
|
);
|
|
85
|
-
return
|
|
86
|
-
items: (
|
|
87
|
-
...
|
|
88
|
-
__uid: `defaut-${
|
|
257
|
+
return c.length === 0 ? {
|
|
258
|
+
items: (n?.defaut ?? []).map((o, i) => ({
|
|
259
|
+
...o,
|
|
260
|
+
__uid: `defaut-${i}`
|
|
89
261
|
})),
|
|
90
262
|
publie: !1,
|
|
91
|
-
chargement:
|
|
263
|
+
chargement: e?.etat === "chargement",
|
|
264
|
+
ancrage: r
|
|
92
265
|
} : {
|
|
93
|
-
items:
|
|
94
|
-
...
|
|
95
|
-
__uid:
|
|
266
|
+
items: c.map((o) => ({
|
|
267
|
+
...C(o.data ?? {}, e?.langue ?? "fr"),
|
|
268
|
+
__uid: o.UID
|
|
96
269
|
})),
|
|
97
270
|
publie: !0,
|
|
98
|
-
chargement:
|
|
271
|
+
chargement: e?.etat === "chargement",
|
|
272
|
+
ancrage: r
|
|
99
273
|
};
|
|
100
|
-
}, [
|
|
274
|
+
}, [e?.sections, e?.langue, e?.etat, t, n?.defaut]);
|
|
101
275
|
}
|
|
102
276
|
export {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
277
|
+
X as SectionsProvider,
|
|
278
|
+
Y as SignatureLystech,
|
|
279
|
+
rt as adaptateurI18next,
|
|
280
|
+
T as appliquerAuxTextes,
|
|
281
|
+
B as useSection,
|
|
282
|
+
tt as useSectionList,
|
|
283
|
+
I as useSectionsContext
|
|
107
284
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function y(t, o) {
|
|
2
|
+
const e = t.split("."), r = {};
|
|
3
|
+
let n = r;
|
|
4
|
+
for (let s = 0; s < e.length - 1; s++) {
|
|
5
|
+
const c = e[s];
|
|
6
|
+
n[c] = {}, n = n[c];
|
|
7
|
+
}
|
|
8
|
+
return n[e[e.length - 1]] = o, r;
|
|
9
|
+
}
|
|
10
|
+
function l(t, o = "", e = {}) {
|
|
11
|
+
if (!t || typeof t != "object") return e;
|
|
12
|
+
for (const [r, n] of Object.entries(t)) {
|
|
13
|
+
const s = o ? o + "." + r : r;
|
|
14
|
+
typeof n == "string" ? e[s] = n : n && typeof n == "object" && !Array.isArray(n) && l(n, s, e);
|
|
15
|
+
}
|
|
16
|
+
return e;
|
|
17
|
+
}
|
|
18
|
+
function h(t) {
|
|
19
|
+
return {
|
|
20
|
+
langues: () => {
|
|
21
|
+
const o = t?.options?.supportedLngs, e = Array.isArray(o) ? o.filter((r) => r !== "cimode") : [];
|
|
22
|
+
return e.length ? e : [t?.language ?? "fr"];
|
|
23
|
+
},
|
|
24
|
+
langueCourante: () => String(t?.language ?? "fr").slice(0, 2),
|
|
25
|
+
dictionnaire: (o) => {
|
|
26
|
+
const e = Array.isArray(t?.options?.ns) ? t.options.ns : [t?.options?.defaultNS ?? "translation"], r = {};
|
|
27
|
+
for (const n of e) {
|
|
28
|
+
const s = t?.getResourceBundle?.(o, n);
|
|
29
|
+
s && (r[n] = l(s));
|
|
30
|
+
}
|
|
31
|
+
return r;
|
|
32
|
+
},
|
|
33
|
+
poser: (o, e, r, n) => {
|
|
34
|
+
t?.addResourceBundle?.(
|
|
35
|
+
o,
|
|
36
|
+
e,
|
|
37
|
+
y(r, n),
|
|
38
|
+
!0,
|
|
39
|
+
!0
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const d = /^i18n:([^:]+):(.*)$/;
|
|
45
|
+
function A(t, o) {
|
|
46
|
+
if (typeof t == "string") return t;
|
|
47
|
+
if (!t || typeof t != "object" || Array.isArray(t)) return null;
|
|
48
|
+
const e = t, r = o.slice(0, 2), n = e[o] ?? e[r];
|
|
49
|
+
return typeof n == "string" ? n : null;
|
|
50
|
+
}
|
|
51
|
+
function j(t, o) {
|
|
52
|
+
const e = o.langues();
|
|
53
|
+
let r = 0;
|
|
54
|
+
for (const n of t ?? []) {
|
|
55
|
+
const s = d.exec(n.blockType ?? "");
|
|
56
|
+
if (!s || !n.data) continue;
|
|
57
|
+
const c = s[1], u = s[2];
|
|
58
|
+
for (const [a, p] of Object.entries(n.data)) {
|
|
59
|
+
const g = u ? u + "." + a : a;
|
|
60
|
+
for (const f of e) {
|
|
61
|
+
const i = A(p, f);
|
|
62
|
+
i === null || i === "" || (o.poser(f, c, g, i), r++);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return r;
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
h as adaptateurI18next,
|
|
70
|
+
j as appliquerAuxTextes
|
|
71
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Un dictionnaire aplati : espace de noms → chemin pointé → texte. */
|
|
2
|
+
export type Dictionnaire = Record<string, Record<string, string>>;
|
|
3
|
+
export type SourceTexte = {
|
|
4
|
+
/** Les langues que le site sait rendre. */
|
|
5
|
+
langues: () => string[];
|
|
6
|
+
/** Celle qu'il affiche en ce moment. */
|
|
7
|
+
langueCourante: () => string;
|
|
8
|
+
/** Tout ce que le site sait dire, dans une langue. */
|
|
9
|
+
dictionnaire: (langue: string) => Dictionnaire;
|
|
10
|
+
/** Remplacer un texte. Le site doit se redessiner ensuite. */
|
|
11
|
+
poser: (langue: string, espace: string, chemin: string, valeur: string) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Branche une instance i18next.
|
|
15
|
+
*
|
|
16
|
+
* `bindI18nStore: "added"` doit être actif dans la configuration du site,
|
|
17
|
+
* sinon React ne se redessine pas quand on remplace un texte — la
|
|
18
|
+
* modification serait enregistrée mais invisible, ce qui est la pire des
|
|
19
|
+
* deux issues : la personne réécrit, republie, et finit par croire que rien
|
|
20
|
+
* ne fonctionne.
|
|
21
|
+
*/
|
|
22
|
+
export declare function adaptateurI18next(i18n: any): SourceTexte;
|
|
23
|
+
/**
|
|
24
|
+
* Applique des sections publiées à la source de textes du site.
|
|
25
|
+
*
|
|
26
|
+
* Utilisée à deux moments, et c'est ce qui rend le référencement juste :
|
|
27
|
+
* pendant le PRÉ-RENDU, pour que le HTML livré porte le bon texte et les
|
|
28
|
+
* bonnes balises ; puis dans le NAVIGATEUR, pour rattraper ce qui aurait été
|
|
29
|
+
* publié depuis la dernière reconstruction.
|
|
30
|
+
*/
|
|
31
|
+
export declare function appliquerAuxTextes(sections: Array<{
|
|
32
|
+
blockType: string;
|
|
33
|
+
data: Record<string, unknown> | null;
|
|
34
|
+
}>, source: SourceTexte): number;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type TypeDeChamp = "text" | "richText" | "image" | "number" | "boolean" | "url" | "date" | "choice" | "list";
|
|
2
|
+
export type ChampDeclare = {
|
|
3
|
+
key: string;
|
|
4
|
+
label: string;
|
|
5
|
+
type: TypeDeChamp;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
help?: string;
|
|
8
|
+
options?: string[];
|
|
9
|
+
/** Sous-champs d'une `list`. */
|
|
10
|
+
of?: ChampDeclare[];
|
|
11
|
+
/**
|
|
12
|
+
* Champ TRADUIT. La valeur stockée devient { fr: …, en: … } et le paquet
|
|
13
|
+
* rend celle de la langue courante.
|
|
14
|
+
*
|
|
15
|
+
* Le serveur ne connaît pas cette clé — il stocke la déclaration telle
|
|
16
|
+
* quelle. C'est voulu : ajouter une langue ne doit pas demander une
|
|
17
|
+
* migration côté plateforme.
|
|
18
|
+
*/
|
|
19
|
+
localized?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type BlocDeclare = {
|
|
22
|
+
blockType: string;
|
|
23
|
+
label: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
fields: ChampDeclare[];
|
|
26
|
+
pages?: string[] | null;
|
|
27
|
+
maxPerPage?: number | null;
|
|
28
|
+
};
|
|
29
|
+
/** Une section telle qu'elle revient du serveur. */
|
|
30
|
+
export type SectionPubliee = {
|
|
31
|
+
UID: string;
|
|
32
|
+
page: string;
|
|
33
|
+
blockType: string;
|
|
34
|
+
position: number;
|
|
35
|
+
data: Record<string, unknown> | null;
|
|
36
|
+
};
|
|
37
|
+
export type ValeurTraduite = {
|
|
38
|
+
[langue: string]: unknown;
|
|
39
|
+
};
|
|
40
|
+
/** Un champ traduit est un objet de langues ; on le reconnaît sans schéma. */
|
|
41
|
+
export declare function estTraduite(v: unknown): v is ValeurTraduite;
|