@studiotitta/studio-editori 0.1.5 → 0.1.6
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/dist/maarittely.d.ts +7 -4
- package/dist/selain/Muokkaustila.js +11 -0
- package/dist/selain/Paneeli.js +16 -1
- package/dist/selain/polku.d.ts +7 -1
- package/dist/selain/polku.js +34 -11
- package/package.json +1 -1
package/dist/maarittely.d.ts
CHANGED
|
@@ -118,9 +118,9 @@ export interface TekstilistaKentta<K extends boolean = boolean> extends KentanPe
|
|
|
118
118
|
* Editorissa se näkyy omana lohkonaan, jotta sivun kentät eivät sekoitu
|
|
119
119
|
* hakukoneteksteihin.
|
|
120
120
|
*/
|
|
121
|
-
export interface RyhmaKentta extends KentanPerus {
|
|
121
|
+
export interface RyhmaKentta<R extends Record<string, Kentta> = Record<string, Kentta>> extends KentanPerus {
|
|
122
122
|
tyyppi: "ryhma";
|
|
123
|
-
kentat:
|
|
123
|
+
kentat: R;
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
126
|
* Lista samanlaisia kohteita, esimerkiksi kurssit.
|
|
@@ -167,7 +167,7 @@ export declare function kielivalinta(asetukset?: Omit<KielivalintaKentta, "tyypp
|
|
|
167
167
|
export declare function tekstilista<K extends boolean = false>(asetukset?: Omit<TekstilistaKentta<K>, "tyyppi" | "kaannettava"> & {
|
|
168
168
|
kaannettava?: K;
|
|
169
169
|
}): TekstilistaKentta<K>;
|
|
170
|
-
export declare function ryhma(asetukset: Omit<RyhmaKentta
|
|
170
|
+
export declare function ryhma<R extends Record<string, Kentta>>(asetukset: Omit<RyhmaKentta<R>, "tyyppi">): RyhmaKentta<R>;
|
|
171
171
|
export declare function kohdelista(asetukset: Omit<KohdelistaKentta, "tyyppi">): KohdelistaKentta;
|
|
172
172
|
export interface SivunMaarittely {
|
|
173
173
|
/** Nimi, jonka muokkaaja näkee editorissa. Oletuksena sivun avain. */
|
|
@@ -209,7 +209,10 @@ export type KentanArvo<K extends Kentta> = K extends {
|
|
|
209
209
|
tyyppi: "kohdelista";
|
|
210
210
|
} ? Record<string, unknown>[] : K extends {
|
|
211
211
|
tyyppi: "ryhma";
|
|
212
|
-
|
|
212
|
+
kentat: infer R extends Record<string, Kentta>;
|
|
213
|
+
} ? {
|
|
214
|
+
[A in keyof R]: KentanArvo<R[A]>;
|
|
215
|
+
} : string;
|
|
213
216
|
/** Kentän arvo sellaisena kuin se on tiedostossa. */
|
|
214
217
|
type TallennettuArvo<K extends Kentta, L extends string> = K extends {
|
|
215
218
|
kaannettava: true;
|
|
@@ -464,6 +464,13 @@ export function Muokkaustila() {
|
|
|
464
464
|
}
|
|
465
465
|
continue;
|
|
466
466
|
}
|
|
467
|
+
/* Sivun oma ryhmä: kentät ovat ryhmän sisällä, eivät sivun juuressa. */
|
|
468
|
+
if (kenttä.tyyppi === "ryhma") {
|
|
469
|
+
for (const [ryhmanKentta, ryhmanMaaritys] of Object.entries(kenttä.kentat)) {
|
|
470
|
+
tutki({ sivu: sivunAvain, kentta: avain, alikentta: ryhmanKentta }, ryhmanMaaritys);
|
|
471
|
+
}
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
467
474
|
tutki({ sivu: sivunAvain, kentta: avain }, kenttä);
|
|
468
475
|
}
|
|
469
476
|
return loydot;
|
|
@@ -677,6 +684,10 @@ function kentanMaaritys(sisalto, polku) {
|
|
|
677
684
|
return undefined;
|
|
678
685
|
if (polku.alikentta === undefined)
|
|
679
686
|
return kentta;
|
|
687
|
+
/* Ilman tunnusta alikenttä on sivun oman ryhmän kenttä. */
|
|
688
|
+
if (polku.tunnus === undefined) {
|
|
689
|
+
return kentta.tyyppi === "ryhma" ? kentta.kentat[polku.alikentta] : undefined;
|
|
690
|
+
}
|
|
680
691
|
if (kentta.tyyppi !== "kohdelista")
|
|
681
692
|
return undefined;
|
|
682
693
|
const [ensimmainen, ryhmanKentta] = polku.alikentta.split(".");
|
package/dist/selain/Paneeli.js
CHANGED
|
@@ -151,6 +151,14 @@ function virheenKohde(tiedot, kohde) {
|
|
|
151
151
|
const maaritys = kentta ? tiedot.malli.kentat[kentta] : undefined;
|
|
152
152
|
if (!maaritys)
|
|
153
153
|
return { nimi: osat.at(-1) ?? kohde, sivulla: false };
|
|
154
|
+
if (maaritys.tyyppi === "ryhma") {
|
|
155
|
+
const ryhmanKentta = osat[2];
|
|
156
|
+
const sisempi = ryhmanKentta ? maaritys.kentat[ryhmanKentta] : undefined;
|
|
157
|
+
return {
|
|
158
|
+
nimi: sisempi?.nimi ?? ryhmanKentta ?? maaritys.nimi ?? kentta,
|
|
159
|
+
sivulla: tiedot.sivullaNakyvat.has(`${tiedot.sivu}.${kentta}.${ryhmanKentta}`),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
154
162
|
if (maaritys.tyyppi !== "kohdelista") {
|
|
155
163
|
return {
|
|
156
164
|
nimi: maaritys.nimi ?? kentta,
|
|
@@ -183,13 +191,20 @@ export function Paneeli(tiedot) {
|
|
|
183
191
|
/* Kielivalinta on turha, jos sivustolla on vain yksi kieli. */
|
|
184
192
|
if (maaritys.tyyppi === "kielivalinta" && tiedot.kielet.length < 2)
|
|
185
193
|
return false;
|
|
194
|
+
/* Ryhmä, jonka jokainen kenttä muokataan jo sivulla, ei kuulu paneeliin:
|
|
195
|
+
tyhjä otsikko näyttäisi siltä, että jotain puuttuu. */
|
|
196
|
+
if (maaritys.tyyppi === "ryhma") {
|
|
197
|
+
return Object.keys(maaritys.kentat).some((ryhmanKentta) => !tiedot.sivullaNakyvat.has(`${tiedot.sivu}.${avain}.${ryhmanKentta}`));
|
|
198
|
+
}
|
|
186
199
|
return !tiedot.sivullaNakyvat.has(`${tiedot.sivu}.${avain}`);
|
|
187
200
|
};
|
|
188
201
|
const omat = kentat.filter(([avain, maaritys]) => maaritys.tyyppi !== "kohdelista" && nayta([avain, maaritys]));
|
|
189
202
|
return (_jsxs("aside", { className: "paneeli", "aria-label": "Sis\u00E4ll\u00F6n tiedot", children: [tiedot.virheet && tiedot.virheet.length > 0 ? (_jsxs("section", { className: "virheet", role: "alert", children: [_jsx("h2", { children: "Tallennus pys\u00E4htyi" }), _jsx("ul", { children: tiedot.virheet.slice(0, 6).map((virhe) => {
|
|
190
203
|
const tiedot_ = virheenKohde(tiedot, virhe.kohde);
|
|
191
204
|
return (_jsxs("li", { children: [_jsx("strong", { children: tiedot_.nimi }), " ", virhe.viesti, tiedot_.kohteenNimi ? (_jsx("button", { type: "button", className: "linkki", onClick: () => tiedot_.tunnus && tiedot.valitse(tiedot_.tunnus), children: tiedot_.kohteenNimi })) : null, tiedot_.sivulla ? _jsx("span", { className: "merkki", children: " Muokataan sivulla." }) : null] }, `${virhe.kohde}-${virhe.viesti}`));
|
|
192
|
-
}) })] })) : null, omat.length > 0 || tiedot.kaannettavia.sivu.length > 0 ? (_jsxs("section", { children: [_jsx("h2", { children: tiedot.malli.nimi }), omat.map(([avain, maaritys]) => (
|
|
205
|
+
}) })] })) : null, omat.length > 0 || tiedot.kaannettavia.sivu.length > 0 ? (_jsxs("section", { children: [_jsx("h2", { children: tiedot.malli.nimi }), omat.map(([avain, maaritys]) => maaritys.tyyppi === "ryhma" ? (_jsxs("div", { className: "ryhma", children: [_jsx("h3", { children: maaritys.nimi ?? avain }), maaritys.ohje ? _jsx("p", { className: "ohje", children: maaritys.ohje }) : null, Object.entries(maaritys.kentat)
|
|
206
|
+
.filter(([ryhmanKentta]) => !tiedot.sivullaNakyvat.has(`${tiedot.sivu}.${avain}.${ryhmanKentta}`))
|
|
207
|
+
.map(([ryhmanKentta, ryhmanMaaritys]) => (_jsx(Kentta_, { polku: { sivu: tiedot.sivu, kentta: avain, alikentta: ryhmanKentta }, maaritys: ryhmanMaaritys, tiedot: tiedot }, ryhmanKentta)))] }, avain)) : (_jsx(Kentta_, { polku: { sivu: tiedot.sivu, kentta: avain }, maaritys: maaritys, tiedot: tiedot }, avain))), tiedot.kielet.length > 1 ? _jsx(Kaannos, { tiedot: tiedot, mihin: "sivu" }) : null] })) : null, lista ? _jsx(Kohteet, { avain: lista[0], maaritys: lista[1], tiedot: tiedot }) : null] }));
|
|
193
208
|
}
|
|
194
209
|
const KIELELLE = {
|
|
195
210
|
fi: "suomeksi",
|
package/dist/selain/polku.d.ts
CHANGED
|
@@ -3,7 +3,13 @@ export interface Kentanpolku {
|
|
|
3
3
|
kentta: string;
|
|
4
4
|
/** Kohteen tunnus, jos kenttä on listan sisällä. */
|
|
5
5
|
tunnus?: string;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Kentän nimi ryhmän sisällä.
|
|
8
|
+
*
|
|
9
|
+
* Ilman tunnusta tämä on sivun oman ryhmän kenttä ("hero.otsikko" →
|
|
10
|
+
* kentta "hero", alikenttä "otsikko"). Tunnuksen kanssa se on kohteen
|
|
11
|
+
* kenttä, joka voi olla myös kohteen ryhmässä ("meta.title").
|
|
12
|
+
*/
|
|
7
13
|
alikentta?: string;
|
|
8
14
|
}
|
|
9
15
|
export declare function lueKentanpolku(polku: string): Kentanpolku | null;
|
package/dist/selain/polku.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
Sivulla oleva merkintä kertoo, mitä kohtaa sisällöstä elementti näyttää:
|
|
5
5
|
|
|
6
6
|
kurssit.otsikko sivun oma kenttä
|
|
7
|
+
etusivu.hero.otsikko kenttä sivun ryhmässä
|
|
7
8
|
kurssit.lista[joogaretriitti].nimi yhden kohteen kenttä listassa
|
|
8
9
|
|
|
9
10
|
Hakasulkeissa on kohteen tunnus, ei järjestysnumero. Näin muokkaus osuu
|
|
@@ -13,23 +14,31 @@
|
|
|
13
14
|
Tämä tiedosto on tarkoituksella pelkkää logiikkaa ilman selainta, jotta
|
|
14
15
|
sen voi testata suoraan.
|
|
15
16
|
========================================================================== */
|
|
16
|
-
/*
|
|
17
|
-
|
|
17
|
+
/* Kolme muotoa: sivun kenttä, sivun ryhmän kenttä ja kohteen kenttä
|
|
18
|
+
listassa. Kohteen kenttä voi olla vielä kohteen oman ryhmän sisällä:
|
|
19
|
+
"kurssit.lista[tunnus].meta.title". */
|
|
20
|
+
const MUOTO = /^([a-zA-Z][a-zA-Z0-9]*)\.([a-zA-Z][a-zA-Z0-9]*)(?:\[([^\]]+)\]\.([a-zA-Z][a-zA-Z0-9]*(?:\.[a-zA-Z][a-zA-Z0-9]*)?)|\.([a-zA-Z][a-zA-Z0-9]*))?$/;
|
|
18
21
|
export function lueKentanpolku(polku) {
|
|
19
22
|
const osuma = MUOTO.exec(polku.trim());
|
|
20
23
|
if (!osuma)
|
|
21
24
|
return null;
|
|
22
|
-
const [, sivu, kentta, tunnus,
|
|
25
|
+
const [, sivu, kentta, tunnus, kohteenKentta, ryhmanKentta] = osuma;
|
|
23
26
|
if (!sivu || !kentta)
|
|
24
27
|
return null;
|
|
25
|
-
if (tunnus !== undefined
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
if (tunnus !== undefined) {
|
|
29
|
+
if (!kohteenKentta)
|
|
30
|
+
return null;
|
|
31
|
+
return { sivu, kentta, tunnus, alikentta: kohteenKentta };
|
|
32
|
+
}
|
|
33
|
+
return ryhmanKentta === undefined ? { sivu, kentta } : { sivu, kentta, alikentta: ryhmanKentta };
|
|
28
34
|
}
|
|
29
35
|
export function kirjoitaKentanpolku(polku) {
|
|
30
|
-
|
|
36
|
+
if (polku.tunnus !== undefined) {
|
|
37
|
+
return `${polku.sivu}.${polku.kentta}[${polku.tunnus}].${polku.alikentta}`;
|
|
38
|
+
}
|
|
39
|
+
return polku.alikentta === undefined
|
|
31
40
|
? `${polku.sivu}.${polku.kentta}`
|
|
32
|
-
: `${polku.sivu}.${polku.kentta}
|
|
41
|
+
: `${polku.sivu}.${polku.kentta}.${polku.alikentta}`;
|
|
33
42
|
}
|
|
34
43
|
/* ---- Arvon asettaminen --------------------------------------------------- */
|
|
35
44
|
function onOlio(arvo) {
|
|
@@ -49,7 +58,17 @@ export function asetaArvo(sivunData, polku, arvo, kieli, tunnusKentta = "tunnus"
|
|
|
49
58
|
return { ...pohja, [kieli]: arvo };
|
|
50
59
|
};
|
|
51
60
|
if (polku.tunnus === undefined) {
|
|
52
|
-
|
|
61
|
+
if (polku.alikentta === undefined) {
|
|
62
|
+
return { ...sivunData, [polku.kentta]: yhdista(sivunData[polku.kentta]) };
|
|
63
|
+
}
|
|
64
|
+
/* Sivun ryhmä: muut ryhmän kentät säilyvät ennallaan. */
|
|
65
|
+
const ryhma = onOlio(sivunData[polku.kentta])
|
|
66
|
+
? sivunData[polku.kentta]
|
|
67
|
+
: {};
|
|
68
|
+
return {
|
|
69
|
+
...sivunData,
|
|
70
|
+
[polku.kentta]: { ...ryhma, [polku.alikentta]: yhdista(ryhma[polku.alikentta]) },
|
|
71
|
+
};
|
|
53
72
|
}
|
|
54
73
|
const lista = Array.isArray(sivunData[polku.kentta]) ? [...sivunData[polku.kentta]] : [];
|
|
55
74
|
const sija = lista.findIndex((kohde) => onOlio(kohde) && kohde[tunnusKentta] === polku.tunnus);
|
|
@@ -73,8 +92,12 @@ export function asetaArvo(sivunData, polku, arvo, kieli, tunnusKentta = "tunnus"
|
|
|
73
92
|
}
|
|
74
93
|
/** Lukee yhden arvon sivun sisällöstä. */
|
|
75
94
|
export function lueArvo(sivunData, polku, tunnusKentta = "tunnus") {
|
|
76
|
-
if (polku.tunnus === undefined)
|
|
77
|
-
|
|
95
|
+
if (polku.tunnus === undefined) {
|
|
96
|
+
const arvo = sivunData[polku.kentta];
|
|
97
|
+
if (polku.alikentta === undefined)
|
|
98
|
+
return arvo;
|
|
99
|
+
return onOlio(arvo) ? arvo[polku.alikentta] : undefined;
|
|
100
|
+
}
|
|
78
101
|
const lista = sivunData[polku.kentta];
|
|
79
102
|
if (!Array.isArray(lista))
|
|
80
103
|
return undefined;
|
package/package.json
CHANGED