@studiotitta/studio-editori 0.1.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/dist/index.d.ts +2 -0
- package/dist/index.js +9 -0
- package/dist/komponentit/Editori.d.ts +1 -0
- package/dist/komponentit/Editori.js +29 -0
- package/dist/komponentit/Muokattava.d.ts +10 -0
- package/dist/komponentit/Muokattava.js +7 -0
- package/dist/komponentit/index.d.ts +2 -0
- package/dist/komponentit/index.js +5 -0
- package/dist/maarittely.d.ts +215 -0
- package/dist/maarittely.js +170 -0
- package/dist/palvelin/apurit.d.ts +26 -0
- package/dist/palvelin/apurit.js +70 -0
- package/dist/palvelin/asetukset.d.ts +26 -0
- package/dist/palvelin/asetukset.js +55 -0
- package/dist/palvelin/github/avain.d.ts +15 -0
- package/dist/palvelin/github/avain.js +121 -0
- package/dist/palvelin/github/tiedostot.d.ts +56 -0
- package/dist/palvelin/github/tiedostot.js +144 -0
- package/dist/palvelin/github/yhteys.d.ts +28 -0
- package/dist/palvelin/github/yhteys.js +89 -0
- package/dist/palvelin/index.d.ts +15 -0
- package/dist/palvelin/index.js +19 -0
- package/dist/palvelin/istunto.d.ts +34 -0
- package/dist/palvelin/istunto.js +86 -0
- package/dist/palvelin/kaannos.d.ts +12 -0
- package/dist/palvelin/kaannos.js +102 -0
- package/dist/palvelin/kaannosreitti.d.ts +9 -0
- package/dist/palvelin/kaannosreitti.js +42 -0
- package/dist/palvelin/kirjautuminen.d.ts +25 -0
- package/dist/palvelin/kirjautuminen.js +183 -0
- package/dist/palvelin/kuvat.d.ts +29 -0
- package/dist/palvelin/kuvat.js +130 -0
- package/dist/palvelin/kuvateksti.d.ts +15 -0
- package/dist/palvelin/kuvateksti.js +95 -0
- package/dist/palvelin/lue.d.ts +6 -0
- package/dist/palvelin/lue.js +41 -0
- package/dist/palvelin/posti.d.ts +9 -0
- package/dist/palvelin/posti.js +45 -0
- package/dist/palvelin/reitit.d.ts +10 -0
- package/dist/palvelin/reitit.js +71 -0
- package/dist/palvelin/tallennus.d.ts +18 -0
- package/dist/palvelin/tallennus.js +177 -0
- package/dist/palvelin/tila.d.ts +21 -0
- package/dist/palvelin/tila.js +116 -0
- package/dist/palvelin/tunnus.d.ts +30 -0
- package/dist/palvelin/tunnus.js +84 -0
- package/dist/palvelin/varasto.d.ts +18 -0
- package/dist/palvelin/varasto.js +87 -0
- package/dist/selain/EditorinPalkki.d.ts +1 -0
- package/dist/selain/EditorinPalkki.js +35 -0
- package/dist/selain/Muokkaustila.d.ts +3 -0
- package/dist/selain/Muokkaustila.js +646 -0
- package/dist/selain/PalkkiLataaja.d.ts +1 -0
- package/dist/selain/PalkkiLataaja.js +19 -0
- package/dist/selain/Paneeli.d.ts +44 -0
- package/dist/selain/Paneeli.js +259 -0
- package/dist/selain/index.d.ts +4 -0
- package/dist/selain/index.js +8 -0
- package/dist/selain/kieli.d.ts +10 -0
- package/dist/selain/kieli.js +14 -0
- package/dist/selain/kuva.d.ts +7 -0
- package/dist/selain/kuva.js +45 -0
- package/dist/selain/polku.d.ts +21 -0
- package/dist/selain/polku.js +108 -0
- package/dist/selain/tyypit.d.ts +22 -0
- package/dist/selain/tyypit.js +2 -0
- package/dist/tarkistus.d.ts +26 -0
- package/dist/tarkistus.js +324 -0
- package/package.json +59 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
const segmentoija = new Intl.Segmenter("fi", { granularity: "grapheme" });
|
|
2
|
+
/** Merkkien määrä niin kuin lukija ne näkee (esim. "é" tai emoji = 1). */
|
|
3
|
+
export function merkkimaara(teksti) {
|
|
4
|
+
let maara = 0;
|
|
5
|
+
for (const _ of segmentoija.segment(teksti))
|
|
6
|
+
maara++;
|
|
7
|
+
return maara;
|
|
8
|
+
}
|
|
9
|
+
function onTavallinenOlio(arvo) {
|
|
10
|
+
return typeof arvo === "object" && arvo !== null && !Array.isArray(arvo);
|
|
11
|
+
}
|
|
12
|
+
function onTyhja(arvo) {
|
|
13
|
+
if (arvo === undefined || arvo === null)
|
|
14
|
+
return true;
|
|
15
|
+
if (typeof arvo === "string")
|
|
16
|
+
return arvo.trim() === "";
|
|
17
|
+
if (Array.isArray(arvo))
|
|
18
|
+
return arvo.length === 0;
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
/** Onko kenttä sellainen, jonka arvo tallennetaan kielittäin? */
|
|
22
|
+
function onKaannettava(maaritys) {
|
|
23
|
+
return "kaannettava" in maaritys && maaritys.kaannettava === true;
|
|
24
|
+
}
|
|
25
|
+
/* ---- Yksittäiset tyypit -------------------------------------------------- */
|
|
26
|
+
function tarkistaTeksti(teksti, maaritys, kohde, kieli, tulos) {
|
|
27
|
+
const huomio = (viesti) => (kieli ? { kohde, kieli, viesti } : { kohde, viesti });
|
|
28
|
+
if (typeof teksti !== "string") {
|
|
29
|
+
tulos.virheet.push(huomio("Arvon pitää olla tekstiä."));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (maaritys.tyyppi === "teksti" && /[\r\n]/.test(teksti)) {
|
|
33
|
+
tulos.virheet.push(huomio("Tähän kenttään ei voi lisätä rivinvaihtoa."));
|
|
34
|
+
}
|
|
35
|
+
if (maaritys.pakollinen && teksti.trim() === "") {
|
|
36
|
+
tulos.virheet.push(huomio("Kenttä ei voi olla tyhjä."));
|
|
37
|
+
}
|
|
38
|
+
const suositus = "suositusPituus" in maaritys ? maaritys.suositusPituus : undefined;
|
|
39
|
+
if (suositus !== undefined) {
|
|
40
|
+
const yli = merkkimaara(teksti) - suositus;
|
|
41
|
+
if (yli > 0) {
|
|
42
|
+
tulos.varoitukset.push(huomio(`Teksti on ${yli} merkkiä pidempi kuin suunniteltu. Tarkista, miltä se näyttää puhelimella.`));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function tarkistaTekstilista(arvo, maaritys, kohde, kieli, tulos) {
|
|
47
|
+
const huomio = (viesti) => (kieli ? { kohde, kieli, viesti } : { kohde, viesti });
|
|
48
|
+
if (!Array.isArray(arvo)) {
|
|
49
|
+
tulos.virheet.push(huomio("Arvon pitää olla lista tekstejä."));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (maaritys.enintaan !== undefined && arvo.length > maaritys.enintaan) {
|
|
53
|
+
tulos.virheet.push(huomio(`Listassa voi olla enintään ${maaritys.enintaan} kohtaa.`));
|
|
54
|
+
}
|
|
55
|
+
if (maaritys.pakollinen && arvo.length === 0) {
|
|
56
|
+
tulos.virheet.push(huomio("Kenttä ei voi olla tyhjä."));
|
|
57
|
+
}
|
|
58
|
+
arvo.forEach((kohta, sija) => {
|
|
59
|
+
if (typeof kohta !== "string") {
|
|
60
|
+
tulos.virheet.push(huomio(`Kohta ${sija + 1} ei ole tekstiä.`));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!maaritys.monirivinen && /[\r\n]/.test(kohta)) {
|
|
64
|
+
tulos.virheet.push(huomio(`Kohtaan ${sija + 1} ei voi lisätä rivinvaihtoa.`));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function tarkistaLuku(arvo, maaritys, kohde, sisarukset, tulos) {
|
|
69
|
+
if (typeof arvo !== "number" || !Number.isFinite(arvo)) {
|
|
70
|
+
tulos.virheet.push({ kohde, viesti: "Arvon pitää olla luku." });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!Number.isInteger(arvo)) {
|
|
74
|
+
tulos.virheet.push({ kohde, viesti: "Luvun pitää olla kokonaisluku." });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (maaritys.pienin !== undefined && arvo < maaritys.pienin) {
|
|
78
|
+
tulos.virheet.push({ kohde, viesti: `Luku ei voi olla pienempi kuin ${maaritys.pienin}.` });
|
|
79
|
+
}
|
|
80
|
+
if (maaritys.suurin !== undefined && arvo > maaritys.suurin) {
|
|
81
|
+
tulos.virheet.push({ kohde, viesti: `Luku ei voi olla suurempi kuin ${maaritys.suurin}.` });
|
|
82
|
+
}
|
|
83
|
+
/* Vertailu toiseen kenttään: varatut paikat eivät voi ylittää ryhmäkokoa. */
|
|
84
|
+
if (maaritys.enintaanKuin) {
|
|
85
|
+
const raja = sisarukset[maaritys.enintaanKuin];
|
|
86
|
+
if (typeof raja === "number" && arvo > raja) {
|
|
87
|
+
tulos.virheet.push({
|
|
88
|
+
kohde,
|
|
89
|
+
viesti: `Luku ei voi olla suurempi kuin ${raja}.`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function tarkistaKuva(arvo, maaritys, kohde, tulos) {
|
|
95
|
+
if (!onTavallinenOlio(arvo)) {
|
|
96
|
+
tulos.virheet.push({ kohde, viesti: "Kuvan arvo on väärässä muodossa." });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const { src, alt } = arvo;
|
|
100
|
+
if (typeof src !== "string" || src === "") {
|
|
101
|
+
tulos.virheet.push({ kohde, viesti: "Kuvatiedosto puuttuu." });
|
|
102
|
+
}
|
|
103
|
+
else if (!src.startsWith("/") || src.includes("..")) {
|
|
104
|
+
/* Osoite tulee kuvien latauksesta; tämä estää sen, että käsin muokattu
|
|
105
|
+
tiedosto voisi osoittaa sivuston ulkopuolelle. */
|
|
106
|
+
tulos.virheet.push({ kohde, viesti: "Kuvan osoite ei kelpaa." });
|
|
107
|
+
}
|
|
108
|
+
if (typeof alt !== "string") {
|
|
109
|
+
tulos.virheet.push({ kohde, viesti: "Kuvan vaihtoehtoinen teksti on väärässä muodossa." });
|
|
110
|
+
}
|
|
111
|
+
else if (maaritys.pakollinenAlt !== false && alt.trim() === "") {
|
|
112
|
+
tulos.virheet.push({
|
|
113
|
+
kohde,
|
|
114
|
+
viesti: "Kerro sanoin, mitä kuvassa on. Sen lukee se, joka ei näe kuvaa.",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/* ---- Kentät ja kohteet --------------------------------------------------- */
|
|
119
|
+
function tarkistaKentta(kielet, maaritys, arvo, kohde, sisarukset, tulos) {
|
|
120
|
+
/* null on sama kuin tyhjä: sisältötiedostoissa sillä merkitään "ei vielä
|
|
121
|
+
tiedossa" (esimerkiksi maksulinkki, jota ei ole avattu). */
|
|
122
|
+
if (arvo === undefined || arvo === null) {
|
|
123
|
+
if (maaritys.pakollinen)
|
|
124
|
+
tulos.virheet.push({ kohde, viesti: "Kenttä ei voi olla tyhjä." });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (onKaannettava(maaritys)) {
|
|
128
|
+
if (!onTavallinenOlio(arvo)) {
|
|
129
|
+
tulos.virheet.push({ kohde, viesti: "Käännettävän kentän arvo on väärässä muodossa." });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const kieli of Object.keys(arvo)) {
|
|
133
|
+
if (!kielet.includes(kieli)) {
|
|
134
|
+
tulos.virheet.push({ kohde, kieli, viesti: `Sivustolla ei ole kieltä "${kieli}".` });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const oletuskieli = kielet[0];
|
|
138
|
+
for (const kieli of kielet) {
|
|
139
|
+
const kaannos = arvo[kieli];
|
|
140
|
+
if (onTyhja(kaannos)) {
|
|
141
|
+
/*
|
|
142
|
+
Pakollinen kenttä vaaditaan vain oletuskielellä. Keskeneräinen
|
|
143
|
+
käännös ei saa estää julkaisua: uusi kurssi kirjoitetaan ensin
|
|
144
|
+
suomeksi, ja englanti tulee perässä. Puuttuva käännös näkyy
|
|
145
|
+
varoituksena, jotta se ei myöskään unohdu.
|
|
146
|
+
*/
|
|
147
|
+
if (maaritys.pakollinen && kieli === oletuskieli) {
|
|
148
|
+
tulos.virheet.push({ kohde, kieli, viesti: "Kenttä ei voi olla tyhjä." });
|
|
149
|
+
}
|
|
150
|
+
else if (maaritys.pakollinen || Object.values(arvo).some((muu) => !onTyhja(muu))) {
|
|
151
|
+
tulos.varoitukset.push({ kohde, kieli, viesti: "Käännös puuttuu." });
|
|
152
|
+
}
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (maaritys.tyyppi === "tekstilista") {
|
|
156
|
+
tarkistaTekstilista(kaannos, maaritys, kohde, kieli, tulos);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
tarkistaTeksti(kaannos, maaritys, kohde, kieli, tulos);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
switch (maaritys.tyyppi) {
|
|
165
|
+
case "teksti":
|
|
166
|
+
case "tekstialue":
|
|
167
|
+
tarkistaTeksti(arvo, maaritys, kohde, undefined, tulos);
|
|
168
|
+
return;
|
|
169
|
+
case "tekstilista":
|
|
170
|
+
tarkistaTekstilista(arvo, maaritys, kohde, undefined, tulos);
|
|
171
|
+
return;
|
|
172
|
+
case "luku":
|
|
173
|
+
tarkistaLuku(arvo, maaritys, kohde, sisarukset, tulos);
|
|
174
|
+
return;
|
|
175
|
+
case "valinta":
|
|
176
|
+
if (typeof arvo !== "string" || !maaritys.vaihtoehdot.some((v) => v.arvo === arvo)) {
|
|
177
|
+
const sallitut = maaritys.vaihtoehdot.map((v) => v.arvo).join(", ");
|
|
178
|
+
tulos.virheet.push({ kohde, viesti: `Arvon pitää olla jokin näistä: ${sallitut}.` });
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
case "kytkin":
|
|
182
|
+
if (typeof arvo !== "boolean") {
|
|
183
|
+
tulos.virheet.push({ kohde, viesti: "Arvon pitää olla kyllä tai ei." });
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
case "aika":
|
|
187
|
+
if (typeof arvo !== "string" || Number.isNaN(new Date(arvo).getTime())) {
|
|
188
|
+
tulos.virheet.push({ kohde, viesti: "Aika ei kelpaa." });
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
case "kuva":
|
|
192
|
+
tarkistaKuva(arvo, maaritys, kohde, tulos);
|
|
193
|
+
return;
|
|
194
|
+
case "kielivalinta": {
|
|
195
|
+
if (!Array.isArray(arvo)) {
|
|
196
|
+
tulos.virheet.push({ kohde, viesti: "Arvon pitää olla lista kieliä." });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const kieli of arvo) {
|
|
200
|
+
if (typeof kieli !== "string" || !kielet.includes(kieli)) {
|
|
201
|
+
tulos.virheet.push({ kohde, viesti: `Sivustolla ei ole kieltä "${String(kieli)}".` });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (new Set(arvo).size !== arvo.length) {
|
|
205
|
+
tulos.virheet.push({ kohde, viesti: "Sama kieli on valittu kahdesti." });
|
|
206
|
+
}
|
|
207
|
+
if (maaritys.pakollinen && arvo.length === 0) {
|
|
208
|
+
tulos.virheet.push({ kohde, viesti: "Valitse vähintään yksi kieli." });
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
case "ryhma": {
|
|
213
|
+
if (!onTavallinenOlio(arvo)) {
|
|
214
|
+
tulos.virheet.push({ kohde, viesti: "Arvon pitää olla ryhmä kenttiä." });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
tarkistaJoukko(kielet, maaritys.kentat, arvo, kohde, tulos);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
case "kohdelista": {
|
|
221
|
+
if (!Array.isArray(arvo)) {
|
|
222
|
+
tulos.virheet.push({ kohde, viesti: "Arvon pitää olla lista." });
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const tunnukset = new Set();
|
|
226
|
+
arvo.forEach((kohta, sija) => {
|
|
227
|
+
if (!onTavallinenOlio(kohta)) {
|
|
228
|
+
tulos.virheet.push({ kohde: `${kohde}[${sija + 1}]`, viesti: "Kohde on väärässä muodossa." });
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const tunnus = kohta[maaritys.tunnus];
|
|
232
|
+
const nimi = typeof tunnus === "string" && tunnus !== "" ? tunnus : `${sija + 1}`;
|
|
233
|
+
if (typeof tunnus === "string" && tunnus !== "") {
|
|
234
|
+
if (tunnukset.has(tunnus)) {
|
|
235
|
+
tulos.virheet.push({
|
|
236
|
+
kohde: `${kohde}.${nimi}`,
|
|
237
|
+
viesti: `Tunnus "${tunnus}" on jo toisella kohteella.`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
tunnukset.add(tunnus);
|
|
241
|
+
}
|
|
242
|
+
tarkistaJoukko(kielet, maaritys.kentat, kohta, `${kohde}.${nimi}`, tulos);
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function tarkistaJoukko(kielet, kentat, data, polku, tulos) {
|
|
249
|
+
for (const avain of Object.keys(data)) {
|
|
250
|
+
if (!Object.hasOwn(kentat, avain)) {
|
|
251
|
+
tulos.virheet.push({ kohde: `${polku}.${avain}`, viesti: "Tätä kenttää ei ole sisältömallissa." });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (const [avain, maaritys] of Object.entries(kentat)) {
|
|
255
|
+
tarkistaKentta(kielet, maaritys, data[avain], `${polku}.${avain}`, data, tulos);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Tarkistaa yhden sivun sisällön sisältömallia vasten. `data` on mitä
|
|
260
|
+
* tahansa, esimerkiksi selaimelta tullut tallennuspyyntö, joten mitään ei
|
|
261
|
+
* oleteta etukäteen.
|
|
262
|
+
*/
|
|
263
|
+
export function tarkistaSivu(maarittely, sivunAvain, data) {
|
|
264
|
+
const tulos = { virheet: [], varoitukset: [] };
|
|
265
|
+
const sivu = maarittely.sivut[sivunAvain];
|
|
266
|
+
if (!sivu) {
|
|
267
|
+
tulos.virheet.push({ kohde: sivunAvain, viesti: "Tuntematon sivu." });
|
|
268
|
+
return tulos;
|
|
269
|
+
}
|
|
270
|
+
if (!onTavallinenOlio(data)) {
|
|
271
|
+
tulos.virheet.push({ kohde: sivunAvain, viesti: "Sivun sisältö on väärässä muodossa." });
|
|
272
|
+
return tulos;
|
|
273
|
+
}
|
|
274
|
+
tarkistaJoukko(maarittely.kielet, sivu.kentat, data, sivunAvain, tulos);
|
|
275
|
+
return tulos;
|
|
276
|
+
}
|
|
277
|
+
/* ---- Kielistys ----------------------------------------------------------- */
|
|
278
|
+
function kielistaArvo(maaritys, arvo, kielet, kieli) {
|
|
279
|
+
const oletuskieli = kielet[0] ?? kieli;
|
|
280
|
+
if (onKaannettava(maaritys)) {
|
|
281
|
+
const kaannokset = onTavallinenOlio(arvo) ? arvo : {};
|
|
282
|
+
const omalla = kaannokset[kieli];
|
|
283
|
+
const oletuksella = kaannokset[oletuskieli];
|
|
284
|
+
const valittu = !onTyhja(omalla) ? omalla : oletuksella;
|
|
285
|
+
if (maaritys.tyyppi === "tekstilista")
|
|
286
|
+
return Array.isArray(valittu) ? valittu : [];
|
|
287
|
+
return typeof valittu === "string" ? valittu : "";
|
|
288
|
+
}
|
|
289
|
+
switch (maaritys.tyyppi) {
|
|
290
|
+
case "teksti":
|
|
291
|
+
case "tekstialue":
|
|
292
|
+
return typeof arvo === "string" ? arvo : "";
|
|
293
|
+
case "tekstilista":
|
|
294
|
+
case "kielivalinta":
|
|
295
|
+
return Array.isArray(arvo) ? arvo : [];
|
|
296
|
+
case "kytkin":
|
|
297
|
+
return arvo === true;
|
|
298
|
+
case "ryhma":
|
|
299
|
+
return kielistaJoukko(maaritys.kentat, onTavallinenOlio(arvo) ? arvo : {}, kielet, kieli);
|
|
300
|
+
case "kohdelista":
|
|
301
|
+
return Array.isArray(arvo)
|
|
302
|
+
? arvo
|
|
303
|
+
.filter(onTavallinenOlio)
|
|
304
|
+
.map((kohta) => kielistaJoukko(maaritys.kentat, kohta, kielet, kieli))
|
|
305
|
+
: [];
|
|
306
|
+
default:
|
|
307
|
+
return arvo;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function kielistaJoukko(kentat, data, kielet, kieli) {
|
|
311
|
+
const tulos = {};
|
|
312
|
+
for (const [avain, maaritys] of Object.entries(kentat)) {
|
|
313
|
+
tulos[avain] = kielistaArvo(maaritys, data[avain], kielet, kieli);
|
|
314
|
+
}
|
|
315
|
+
return tulos;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Muuntaa tallennetun sivun yhdelle kielelle. Puuttuva käännös korvataan
|
|
319
|
+
* oletuskielellä: vieraskielinen rivi on julkisella sivulla parempi kuin
|
|
320
|
+
* tyhjä kohta, ja editori näyttää puuttuvat käännökset muokkaajalle.
|
|
321
|
+
*/
|
|
322
|
+
export function kielista(maarittely, sivu, data, kieli) {
|
|
323
|
+
return kielistaJoukko(sivu.kentat, data, maarittely.kielet, kieli);
|
|
324
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@studiotitta/studio-editori",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Studio Titan sisältöeditori asiakassivustoille: tekstit ja kuvat muokataan suoraan sivulla",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./palvelin": {
|
|
13
|
+
"types": "./dist/palvelin/index.d.ts",
|
|
14
|
+
"default": "./dist/palvelin/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./komponentit": {
|
|
17
|
+
"types": "./dist/komponentit/index.d.ts",
|
|
18
|
+
"default": "./dist/komponentit/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./selain": {
|
|
21
|
+
"types": "./dist/selain/index.d.ts",
|
|
22
|
+
"default": "./dist/selain/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
30
|
+
"tarkista": "tsc --noEmit",
|
|
31
|
+
"testit": "node --test \"testit/*.test.ts\"",
|
|
32
|
+
"prepublishOnly": "npm run tarkista && npm run testit && npm run build"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"next": ">=16.3.3",
|
|
36
|
+
"react": ">=19.0.0",
|
|
37
|
+
"react-dom": ">=19.0.0"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"registry": "https://registry.npmjs.org",
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/TittaWin/studio-editori.git"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^24.13.6",
|
|
49
|
+
"@types/react": "^19.3.0",
|
|
50
|
+
"@types/react-dom": "^19.3.0",
|
|
51
|
+
"next": "^16.3.6",
|
|
52
|
+
"react": "^19.2.8",
|
|
53
|
+
"react-dom": "^19.2.8",
|
|
54
|
+
"typescript": "^7.0.2"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@anthropic-ai/sdk": "^0.70.0"
|
|
58
|
+
}
|
|
59
|
+
}
|