@jjlmoya/utils-tabletop 1.20.0 → 1.22.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/package.json +1 -1
- package/src/category/index.ts +2 -0
- package/src/entries.ts +4 -0
- package/src/index.ts +1 -0
- package/src/tests/locale_completeness.test.ts +1 -1
- package/src/tests/seo_translation_completeness.test.ts +69 -0
- package/src/tests/spanish_leakage.test.ts +25 -3
- package/src/tests/tool_validation.test.ts +1 -1
- package/src/tool/decision-wheel/i18n/de.ts +10 -10
- package/src/tool/decision-wheel/i18n/es.ts +10 -10
- package/src/tool/decision-wheel/i18n/fr.ts +10 -10
- package/src/tool/decision-wheel/i18n/id.ts +10 -10
- package/src/tool/decision-wheel/i18n/it.ts +10 -10
- package/src/tool/decision-wheel/i18n/ja.ts +10 -10
- package/src/tool/decision-wheel/i18n/ko.ts +10 -10
- package/src/tool/decision-wheel/i18n/nl.ts +10 -10
- package/src/tool/decision-wheel/i18n/pl.ts +10 -10
- package/src/tool/decision-wheel/i18n/pt.ts +10 -10
- package/src/tool/decision-wheel/i18n/sv.ts +10 -10
- package/src/tool/decision-wheel/i18n/tr.ts +10 -10
- package/src/tool/decision-wheel/i18n/zh.ts +10 -10
- package/src/tool/dungeon-map-generator/bibliography.astro +16 -0
- package/src/tool/dungeon-map-generator/bibliography.ts +12 -0
- package/src/tool/dungeon-map-generator/component.astro +134 -0
- package/src/tool/dungeon-map-generator/controller.ts +242 -0
- package/src/tool/dungeon-map-generator/document.ts +72 -0
- package/src/tool/dungeon-map-generator/dom-views.ts +139 -0
- package/src/tool/dungeon-map-generator/editor.ts +57 -0
- package/src/tool/dungeon-map-generator/entry.ts +28 -0
- package/src/tool/dungeon-map-generator/evaluator.ts +40 -0
- package/src/tool/dungeon-map-generator/i18n/de.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/en.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/es.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/fr.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/id.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/it.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/ja.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/ko.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/nl.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/pl.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/pt.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/ru.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/sv.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/tr.ts +172 -0
- package/src/tool/dungeon-map-generator/i18n/zh.ts +172 -0
- package/src/tool/dungeon-map-generator/index.ts +11 -0
- package/src/tool/dungeon-map-generator/logic.test.ts +75 -0
- package/src/tool/dungeon-map-generator/logic.ts +255 -0
- package/src/tool/dungeon-map-generator/random-dungeon-map-generator.css +678 -0
- package/src/tool/dungeon-map-generator/seo.astro +16 -0
- package/src/tool/dungeon-map-generator/storage.ts +18 -0
- package/src/tool/dungeon-map-generator/ui.ts +53 -0
- package/src/tool/dungeon-map-generator/validation.ts +40 -0
- package/src/tool/hidden-role-dealer/i18n/de.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/id.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/it.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/ja.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/ko.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/nl.ts +6 -6
- package/src/tool/hidden-role-dealer/i18n/pl.ts +7 -7
- package/src/tool/hidden-role-dealer/i18n/pt.ts +7 -7
- package/src/tool/hidden-role-dealer/i18n/ru.ts +7 -7
- package/src/tool/hidden-role-dealer/i18n/sv.ts +7 -7
- package/src/tool/hidden-role-dealer/i18n/tr.ts +7 -7
- package/src/tool/hidden-role-dealer/i18n/zh.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/de.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/es.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/fr.ts +12 -12
- package/src/tool/scatter-direction-selector/i18n/id.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/it.ts +11 -11
- package/src/tool/scatter-direction-selector/i18n/ja.ts +8 -8
- package/src/tool/scatter-direction-selector/i18n/ko.ts +8 -8
- package/src/tool/scatter-direction-selector/i18n/nl.ts +9 -10
- package/src/tool/scatter-direction-selector/i18n/pl.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/pt.ts +12 -12
- package/src/tool/scatter-direction-selector/i18n/ru.ts +7 -7
- package/src/tool/scatter-direction-selector/i18n/sv.ts +9 -9
- package/src/tool/scatter-direction-selector/i18n/tr.ts +8 -8
- package/src/tool/scatter-direction-selector/i18n/zh.ts +11 -11
- package/src/tools.ts +2 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { DungeonMapGeneratorLocaleContent, DungeonMapGeneratorUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: DungeonMapGeneratorUI = {
|
|
6
|
+
intro: 'Kies een seed, stel het raster in en kies een stijl. Genereer een verbonden kaart voor je notities, afdruk of virtual tabletop.',
|
|
7
|
+
seedLabel: 'Kaart seed',
|
|
8
|
+
seedHint: 'Hergebruik dezelfde seed met dezelfde instellingen om exact dezelfde kaart te maken.',
|
|
9
|
+
randomSeed: 'Nieuwe seed',
|
|
10
|
+
sizeLabel: 'Expeditiegrootte',
|
|
11
|
+
sizeCompact: 'Eenmalig avontuur (One-shot)',
|
|
12
|
+
sizeSession: 'Standaard sessie',
|
|
13
|
+
sizeStronghold: 'Grote vestiging',
|
|
14
|
+
fineTuneGrid: 'Fijnafstemming raster en dichtheid',
|
|
15
|
+
columnsLabel: 'Kolommen',
|
|
16
|
+
rowsLabel: 'Rijen',
|
|
17
|
+
densityLabel: 'Kamerdichtheid',
|
|
18
|
+
densityHint: 'Hogere dichtheid voegt meer kamers en bruikbare vloer toe.',
|
|
19
|
+
styleLabel: 'Architectuurstijl',
|
|
20
|
+
dungeonStyle: 'Dungeon',
|
|
21
|
+
dungeonStyleHint: 'Stenen kamers met enkele gangen.',
|
|
22
|
+
cavernStyle: 'Grot',
|
|
23
|
+
cavernStyleHint: 'Natuurlijke kamers met afgeronde randen.',
|
|
24
|
+
scifiStyle: 'Sci-Fi',
|
|
25
|
+
scifiStyleHint: 'Brede modules met dubbele gangen.',
|
|
26
|
+
generate: 'Tekengeneratie',
|
|
27
|
+
mapRegionLabel: 'Gegenereerde dungeonkaart en exportknoppen',
|
|
28
|
+
connectedBadge: 'Alle kamers verbonden',
|
|
29
|
+
roomsLabel: 'Kamers',
|
|
30
|
+
doorsLabel: 'Deuren',
|
|
31
|
+
floorLabel: 'Vloerdekking',
|
|
32
|
+
legendFloor: 'Begaanbare vloer',
|
|
33
|
+
legendWall: 'Massieve muur',
|
|
34
|
+
legendDoor: 'Deur of luchtsluis',
|
|
35
|
+
editHint: 'Rechtermuisklik op een cel om te bewerken',
|
|
36
|
+
editCell: 'Bewerk deze cel',
|
|
37
|
+
paintFloor: 'Vloer',
|
|
38
|
+
paintWall: 'Muur',
|
|
39
|
+
paintDoor: 'Deur',
|
|
40
|
+
mapData: 'Kaartgegevens',
|
|
41
|
+
copyLink: 'Kopieer kaartlink',
|
|
42
|
+
linkCopied: 'Link gekopieerd',
|
|
43
|
+
exportPng: 'Download PNG',
|
|
44
|
+
exportSvg: 'Download SVG',
|
|
45
|
+
exportJson: 'Opslaan als JSON',
|
|
46
|
+
importJson: 'Open JSON',
|
|
47
|
+
importError: 'Dit bestand bevat geen geldige dungeoninstellingen.',
|
|
48
|
+
compactMap: 'Spannende verkenning',
|
|
49
|
+
balancedMap: 'Gebalanceerde expeditie',
|
|
50
|
+
sprawlingMap: 'Open vestiging',
|
|
51
|
+
compactHint: 'Langere gangen laten meer onbekende ruimte tussen kamers.',
|
|
52
|
+
balancedHint: 'Kamers en gangen verdelen de ruimte gebalanceerd.',
|
|
53
|
+
sprawlingHint: 'Veel vloeroppervlak bevordert gevechten en snelle beweging.',
|
|
54
|
+
mapReady: 'Kaartlegenda',
|
|
55
|
+
dimensionsUnit: 'rastercellen',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const faq = [
|
|
59
|
+
{
|
|
60
|
+
question: 'Genereert dezelfde seed altijd dezelfde dungeonkaart?',
|
|
61
|
+
answer: 'Ja. De seed, rasterafmetingen, dichtheid en stijl vormen een deterministische configuratie. Het hergebruiken van alle instellingen levert exact dezelfde kaart op.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
question: 'Zijn alle gegenereerde kamers bereikbaar?',
|
|
65
|
+
answer: 'Ja. Kamers worden na plaatsing via een hoofdroute verbonden, zodat elk begaanbaar gebied tot één verbonden kaart behoort.',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
question: 'Wat is het verschil tussen dungeon-, grot- en Sci-Fi-stijlen?',
|
|
69
|
+
answer: 'Dungeon gebruikt regelmatige stenen kamers. Grotten vormen onregelmatige ronde kamers. Sci-Fi gebruikt brede modules met dubbele gangen.',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
question: 'Welk formaat moet ik exporteren voor een virtual tabletop (VTT)?',
|
|
73
|
+
answer: 'PNG is de makkelijkste optie voor de meeste VTTs. SVG blijft scherp op elke schaal en is eenvoudig te bewerken in vectorsoftware.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
question: 'Kan iemand anders mijn willekeurige dungeonkaart maken?',
|
|
77
|
+
answer: 'Ja. Kopieer de kaartlink of stuur het JSON-bestand. De ontvanger kan direct dezelfde kaart laden.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
question: 'Voegt deze generator monsters, valstrikken of schatten toe?',
|
|
81
|
+
answer: 'Nee. Het maakt een neutrale plattegrond die je zelf kunt inrichten voor elk spelsysteem.',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const howTo = [
|
|
86
|
+
{
|
|
87
|
+
name: 'Stel rasterafmetingen in',
|
|
88
|
+
text: 'Kies het aantal kolommen en rijen passend voor je notities of VTT-scène.',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Kies een stijl',
|
|
92
|
+
text: 'Kies dungeon, grot of Sci-Fi en pas de dichtheid aan.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Genereer en bekijk',
|
|
96
|
+
text: 'Voer een seed in, genereer de kaart en bekijk het overzicht.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Exporteer of deel',
|
|
100
|
+
text: 'Download PNG of SVG om te spelen, of bewaar de instellingen via link of JSON.',
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
105
|
+
'@context': 'https://schema.org',
|
|
106
|
+
'@type': 'FAQPage',
|
|
107
|
+
mainEntity: faq.map((item) => ({
|
|
108
|
+
'@type': 'Question',
|
|
109
|
+
name: item.question,
|
|
110
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
111
|
+
})),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
115
|
+
'@context': 'https://schema.org',
|
|
116
|
+
'@type': 'SoftwareApplication',
|
|
117
|
+
name: 'Willekeurige Dungeonkaart Generator',
|
|
118
|
+
operatingSystem: 'All',
|
|
119
|
+
applicationCategory: 'UtilitiesApplication',
|
|
120
|
+
description: 'Een deterministische generator voor dungeonkaarten met verbonden kamers, deuren en lokale exports.',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const howToSchema: WithContext<HowTo> = {
|
|
124
|
+
'@context': 'https://schema.org',
|
|
125
|
+
'@type': 'HowTo',
|
|
126
|
+
name: 'Hoe genereer je een verbonden dungeonkaart',
|
|
127
|
+
step: howTo.map((item) => ({
|
|
128
|
+
'@type': 'HowToStep',
|
|
129
|
+
name: item.name,
|
|
130
|
+
text: item.text,
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const content: DungeonMapGeneratorLocaleContent = {
|
|
135
|
+
slug: 'willekeurige-dungeonkaart-generator',
|
|
136
|
+
title: 'Willekeurige Dungeonkaart Generator voor RPGs',
|
|
137
|
+
description: 'Maak herbruikbare kaarten voor dungeons, grotten en Sci-Fi met verbonden kamers, deuren en PNG/SVG export.',
|
|
138
|
+
ui,
|
|
139
|
+
seo: [
|
|
140
|
+
{ type: 'title', text: 'Maak een Speelbare Dungeonkaart met een Herbruikbare Seed', level: 2 },
|
|
141
|
+
{ type: 'paragraph', html: 'Een nuttige willekeurige dungeonkaart heeft meer nodig dan alleen willekeurige visuele ruis. Elke kamer moet bereikbaar zijn via verbonden gangen, het raster moet passen op het speeloppervlak en het resultaat moet op elk moment hersteld kunnen worden op elk apparaat. Deze generator behandelt de seed en instellingen als een compacte en deterministische kaartspecificatie. Als je dezelfde seed, kolommen, rijen, dichtheid en architectuurstijl behoudt, wordt exact dezelfde plattegrond later opnieuw opgebouwd.' },
|
|
142
|
+
{ type: 'title', text: 'Kies Rasterafmetingen voor Afdruk en Virtual Tabletops', level: 2 },
|
|
143
|
+
{ type: 'paragraph', html: 'Het instellen van het raster is de eerste praktische stap bij het plannen van een sessie. Een klein raster is eenvoudig af te drukken op papier voor korte avonturen of eenmalige locaties, terwijl een grote kaart uitgebreide ruimte biedt voor complexe verkenningen, tactische ontmoetingen en meerdere facties. De geëxporteerde afbeelding behoudt perfect vierkante cellen zodat deze naadloos uitlijnt met de rasterinstellingen in virtuele tabletop-software (VTT).' },
|
|
144
|
+
{
|
|
145
|
+
type: 'table',
|
|
146
|
+
headers: ['Rastergrootte', 'Typisch gebruik', 'Begindichtheid', 'Planningsnotitie'],
|
|
147
|
+
rows: [
|
|
148
|
+
['20 bij 16 cellen', 'Kort avontuur (One-shot)', '35 tot 45', 'Makkelijk af te drukken en snel visueel leesbaar op papier'],
|
|
149
|
+
['36 bij 26 cellen', 'Standaard sessie', '45 tot 55', 'Gebalanceerd ritme tussen kamers en gangen'],
|
|
150
|
+
['52 bij 38 cellen', 'Groot complex', '50 tot 65', 'Veel ruimte voor meerdere facties en optionele routes'],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{ type: 'tip', title: 'Stem de Kaart af op de Gevechtsschaal', html: 'Bereken de benodigde ruimte voor grote gevechten voordat je de totale grootte kiest. Een grote dungeon met piepkleine kamers voelt benauwd aan, terwijl een compacte kaart met één royale centrale kamer gedenkwaardige scènes mogelijk maakt.' },
|
|
154
|
+
{ type: 'title', text: 'Lees Vloerdekking als Tempo-Indicator', level: 2 },
|
|
155
|
+
{ type: 'paragraph', html: 'Vloerdekking geeft het percentage van het rechthoekige canvas aan dat begaanbaar is. Lage dekking benadrukt spanning, isolatie en onbekende ruimtes tussen de kamers. Middelgrote dekking ondersteunt een gestaag expeditieritme. Hoge dekking creëert een vesting of faciliteit waar gevechten en patrouilles zich snel kunnen uitbreiden naar aangrenzende ruimtes.' },
|
|
156
|
+
{
|
|
157
|
+
type: 'list',
|
|
158
|
+
items: [
|
|
159
|
+
'<strong>Spannende verkenning:</strong> gebruik lege ruimte om isolatie of geheime gangen te suggereren.',
|
|
160
|
+
'<strong>Gebalanceerde expeditie:</strong> afwisseling van onderzoekskamers, gangen en gevechten.',
|
|
161
|
+
'<strong>Open vestiging:</strong> bereid zichtlijnen, patrouilleroutes en onderling verbonden ontmoetingen voor.',
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{ type: 'title', text: 'Van Neutrale Plattegrond naar Avontuurlocatie', level: 2 },
|
|
165
|
+
{ type: 'paragraph', html: 'De gegenereerde kaart biedt bewust alleen de basisarchitectuur. Wijs een verhalende rol toe aan elke belangrijke kamer en plaats aanwijzingen, valstrikken, wezens en schatten volgens dat doel. Gebruik deuren als strategische beslismomenten voor je spelers.' },
|
|
166
|
+
{ type: 'tip', title: 'Bewaar Instellingen voor het Toevoegen van Notities', html: 'Kopieer de link of bewaar het JSON-bestand voordat je ontmoetingsnotities toevoegt om een schone kaart aan spelers te geven zonder spelleidergeheimen te onthullen.' },
|
|
167
|
+
],
|
|
168
|
+
faq,
|
|
169
|
+
bibliography,
|
|
170
|
+
howTo,
|
|
171
|
+
schemas: [faqSchema, appSchema, howToSchema] as unknown as Record<string, unknown>[],
|
|
172
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { DungeonMapGeneratorLocaleContent, DungeonMapGeneratorUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: DungeonMapGeneratorUI = {
|
|
6
|
+
intro: 'Wybierz ziarno (seed), ustaw siatkę i wybierz styl architektoniczny. Wygeneruj połączoną mapę do notatek, druku lub wirtualnego stołu (VTT).',
|
|
7
|
+
seedLabel: 'Ziarno mapy (Seed)',
|
|
8
|
+
seedHint: 'Użyj tego samego ziarna przy tych samych ustawieniach, aby odtworzyć dokładnie tę samą mapę.',
|
|
9
|
+
randomSeed: 'Nowe ziarno',
|
|
10
|
+
sizeLabel: 'Rozmiar ekspedycji',
|
|
11
|
+
sizeCompact: 'Jednorazowa sesja (One-shot)',
|
|
12
|
+
sizeSession: 'Zwykła sesja',
|
|
13
|
+
sizeStronghold: 'Duża twierdza',
|
|
14
|
+
fineTuneGrid: 'Precyzyjne strojenie siatki i gęstości',
|
|
15
|
+
columnsLabel: 'Kolumny',
|
|
16
|
+
rowsLabel: 'Wiersze',
|
|
17
|
+
densityLabel: 'Gęstość pomieszczeń',
|
|
18
|
+
densityHint: 'Wyższa gęstość dodaje więcej komnat i powierzchni użytkowej.',
|
|
19
|
+
styleLabel: 'Architektura mapy',
|
|
20
|
+
dungeonStyle: 'Lochy (Dungeon)',
|
|
21
|
+
dungeonStyleHint: 'Kamienne komnaty z wąskimi korytarzami.',
|
|
22
|
+
cavernStyle: 'Jaskinia (Cavern)',
|
|
23
|
+
cavernStyleHint: 'Nieregularne komory o zaokrąglonych krawędziach.',
|
|
24
|
+
scifiStyle: 'Sci-Fi',
|
|
25
|
+
scifiStyleHint: 'Szerokie moduły z podwójnymi korytarzami.',
|
|
26
|
+
generate: 'Rysuj mapę',
|
|
27
|
+
mapRegionLabel: 'Wygenerowana mapa lochów i opcje eksportu',
|
|
28
|
+
connectedBadge: 'Wszystkie komnaty połączone',
|
|
29
|
+
roomsLabel: 'Pokoje',
|
|
30
|
+
doorsLabel: 'Drzwi',
|
|
31
|
+
floorLabel: 'Pokrycie podłogi',
|
|
32
|
+
legendFloor: 'Podłoga do chodzenia',
|
|
33
|
+
legendWall: 'Lita ściana',
|
|
34
|
+
legendDoor: 'Drzwi lub śluza',
|
|
35
|
+
editHint: 'Prawy przycisk myszy na komórce, aby edytować',
|
|
36
|
+
editCell: 'Edytuj tę komórkę',
|
|
37
|
+
paintFloor: 'Podłoga',
|
|
38
|
+
paintWall: 'Ściana',
|
|
39
|
+
paintDoor: 'Drzwi',
|
|
40
|
+
mapData: 'Dane mapy',
|
|
41
|
+
copyLink: 'Kopiuj link do mapy',
|
|
42
|
+
linkCopied: 'Link skopiowany',
|
|
43
|
+
exportPng: 'Pobierz PNG',
|
|
44
|
+
exportSvg: 'Pobierz SVG',
|
|
45
|
+
exportJson: 'Zapisz JSON',
|
|
46
|
+
importJson: 'Otwórz JSON',
|
|
47
|
+
importError: 'Ten plik nie zawiera prawidłowej konfiguracji mapy lochów.',
|
|
48
|
+
compactMap: 'Napięta eksploracja',
|
|
49
|
+
balancedMap: 'Zrównoważona ekspedycja',
|
|
50
|
+
sprawlingMap: 'Otwarta twierdza',
|
|
51
|
+
compactHint: 'Dłuższe przejścia pozostawiają więcej nieznanego obszaru między komnatami.',
|
|
52
|
+
balancedHint: 'Komnaty i korytarze dzielą przestrzeń w sposób zrównoważony.',
|
|
53
|
+
sprawlingHint: 'Duża powierzchnia podłogi sprzyja walkom i szybkiemu przemieszczaniu się.',
|
|
54
|
+
mapReady: 'Legenda mapy',
|
|
55
|
+
dimensionsUnit: 'komórki siatki',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const faq = [
|
|
59
|
+
{
|
|
60
|
+
question: 'Czy to samo ziarno zawsze tworzy tę samą mapę?',
|
|
61
|
+
answer: 'Tak. Ziarno, wymiary siatki, gęstość i styl tworzą konfigurację deterministyczną. Ponowne użycie tych samych ustawień generuje identyczną mapę.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
question: 'Czy wszystkie wygenerowane komnaty są ze sobą połączone?',
|
|
65
|
+
answer: 'Tak. Wszystkie pomieszczenia są łączone w trasę główną, dzięki czemu cała podłoga tworzy jedną połączoną mapę.',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
question: 'Czym różnią się style lochów, jaskini i Sci-Fi?',
|
|
69
|
+
answer: 'Style lochów używają regularnych kamiennych komnat. Jaskinie tworzą nieregularne zaokrąglone komory. Style Sci-Fi wykorzystują szerokie moduły i podwójne śluzy.',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
question: 'Jaki format wyeksportować do wirtualnego stołu (VTT)?',
|
|
73
|
+
answer: 'Format PNG jest najprostszym wyborem dla większości programów VTT. Format SVG zachowuje ostrość w każdej skali i ułatwia edycję wektorową.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
question: 'Czy inna osoba może odtworzyć moją mapę?',
|
|
77
|
+
answer: 'Tak. Skopiuj link do mapy lub prześlij plik JSON. Odbiorca może natychmiast załadować tę samą konfigurację.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
question: 'Czy ten generator dodaje potwory, pułapki lub skarby?',
|
|
81
|
+
answer: 'Nie. Tworzy neutralny plan architektoniczny, który Mistrz Gry może samodzielnie uzupełnić według własnych zasad.',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const howTo = [
|
|
86
|
+
{
|
|
87
|
+
name: 'Ustaw wymiary siatki',
|
|
88
|
+
text: 'Wybierz liczbę kolumn i wierszy dopasowaną do Twoich notatek lub sceny VTT.',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Wybierz architekturę',
|
|
92
|
+
text: 'Wybierz lochy, jaskinię lub Sci-Fi i dostosuj gęstość pomieszczeń.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Wygeneruj i sprawdź',
|
|
96
|
+
text: 'Wpisz ziarno, wygeneruj mapę i przejrzyj podsumowanie pomieszczeń i drzwi.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Eksportuj lub udostępnij',
|
|
100
|
+
text: 'Pobierz PNG lub SVG do gry albo zapisz konfigurację przez link lub plik JSON.',
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
105
|
+
'@context': 'https://schema.org',
|
|
106
|
+
'@type': 'FAQPage',
|
|
107
|
+
mainEntity: faq.map((item) => ({
|
|
108
|
+
'@type': 'Question',
|
|
109
|
+
name: item.question,
|
|
110
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
111
|
+
})),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
115
|
+
'@context': 'https://schema.org',
|
|
116
|
+
'@type': 'SoftwareApplication',
|
|
117
|
+
name: 'Generator Losowych Map Lochów',
|
|
118
|
+
operatingSystem: 'All',
|
|
119
|
+
applicationCategory: 'UtilitiesApplication',
|
|
120
|
+
description: 'Deterministyczny generator map lochów z połączonymi komnatami, drzwiami i eksportem lokalnym.',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const howToSchema: WithContext<HowTo> = {
|
|
124
|
+
'@context': 'https://schema.org',
|
|
125
|
+
'@type': 'HowTo',
|
|
126
|
+
name: 'Jak wygenerować połączoną mapę lochów',
|
|
127
|
+
step: howTo.map((item) => ({
|
|
128
|
+
'@type': 'HowToStep',
|
|
129
|
+
name: item.name,
|
|
130
|
+
text: item.text,
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const content: DungeonMapGeneratorLocaleContent = {
|
|
135
|
+
slug: 'generator-losowych-map-lochow',
|
|
136
|
+
title: 'Generator Losowych Map Lochów do Gier RPG',
|
|
137
|
+
description: 'Twórz odtwarzalne mapy lochów, jaskiń i Sci-Fi z połączonymi komnatami, drzwiami oraz eksportem PNG/SVG.',
|
|
138
|
+
ui,
|
|
139
|
+
seo: [
|
|
140
|
+
{ type: 'title', text: 'Wygeneruj funkcjonalną mapę lochów za pomocą powtarzalnego ziarna', level: 2 },
|
|
141
|
+
{ type: 'paragraph', html: 'Użyteczna mapa lochów wymaga czegoś więcej niż przypadkowego szumu wizualnego. Każda komnata musi być dostępna przez połączone korytarze, siatka musi pasować do powierzchni gry, a wynik musi dawać się łatwo odtworzyć w dowolnym momencie na każdym urządzeniu. Ten generator traktuje ziarno i ustawienia jako zwartą i deterministyczną specyfikację mapy. Zachowując to samo ziarno, kolumny, wiersze, gęstość i styl architektury, w późniejszym czasie odtworzysz dokładnie ten sam plan.' },
|
|
142
|
+
{ type: 'title', text: 'Wymiary siatki do druku i wirtualnych stołów (VTT)', level: 2 },
|
|
143
|
+
{ type: 'paragraph', html: 'Ustawienie rozmiaru siatki to pierwszy krok praktyczny podczas planowania sesji. Mała siatka jest łatwa do wydrukowania na papierze na krótką przygodę lub jednorazową lokację, podczas gdy duża mapa daje przestrzeń na skomplikowaną eksplorację, starcia taktyczne i wiele frakcji. Wyeksportowany obraz zachowuje idealnie kwadratowe komórki, co ułatwia dopasowanie go do siatki w programach wirtualnego stołu (VTT).' },
|
|
144
|
+
{
|
|
145
|
+
type: 'table',
|
|
146
|
+
headers: ['Rozmiar siatki', 'Typowe zastosowanie', 'Gęstość początkowa', 'Uwaga planistyczna'],
|
|
147
|
+
rows: [
|
|
148
|
+
['20 na 16 komórek', 'Jednorazowa sesja (One-shot)', '35 do 45', 'Łatwy druk i szybki odczyt wizualny na papierze'],
|
|
149
|
+
['36 na 26 komórek', 'Sesyjny loch', '45 do 55', 'Zrównoważony rytm komnat i korytarzy'],
|
|
150
|
+
['52 na 38 komórek', 'Duży kompleks', '50 do 65', 'Dużo miejsca na frakcje i drogi opcjonalne'],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{ type: 'tip', title: 'Dopasuj mapę do skali starć', html: 'Oblicz komórki potrzebne na kluczowe walki przed wybraniem całkowitego rozmiaru. Duży loch z ciasnymi pokojami sprawi wrażenie dusznego, podczas gdy kompaktowa mapa z jedną dużą salą główną sprzyja zapamiętywalnym scenom.' },
|
|
154
|
+
{ type: 'title', text: 'Interpretuj pokrycie podłogi jako tempo rozgrywki', level: 2 },
|
|
155
|
+
{ type: 'paragraph', html: 'Pokrycie podłogi wskazuje procent powierzchni prostokątnego płótna przeznaczonej do chodzenia. Niska gęstość buduje napięcie, izolację i niepewność między pomieszczeniami. Średnie pokrycie wspiera stały rytm ekspedycji. Wysoka gęstość tworzy kompleks twierdzy, w którym starcia i patrole mogą szybko rozprzestrzeniać się na sąsiednie komnaty.' },
|
|
156
|
+
{
|
|
157
|
+
type: 'list',
|
|
158
|
+
items: [
|
|
159
|
+
'<strong>Napięta eksploracja:</strong> wykorzystaj wolną przestrzeń do sugerowania tajemnic lub ukrytych przejść.',
|
|
160
|
+
'<strong>Zrównoważona ekspedycja:</strong> przeplataj komnaty badawcze korytarzami i salami walki.',
|
|
161
|
+
'<strong>Otwarta twierdza:</strong> przygotuj proste linie wzroku i połączone trasy patroli.',
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{ type: 'title', text: 'Zmień neutralny plan w miejsce przygody', level: 2 },
|
|
165
|
+
{ type: 'paragraph', html: 'Wygenerowana mapa daje celowo tylko podstawową architekturę. Przypisz rolę fabularną do każdego ważnego pomieszczenia i rozmieść wskazówki, pułapki, stwory i skarby zgodnie z tym celem. Używaj drzwi jako strategicznych punktów decyzyjnych dla graczy.' },
|
|
166
|
+
{ type: 'tip', title: 'Zapisz konfigurację przed dodaniem notatek', html: 'Skopiuj link lub zapisz JSON przed zanotowaniem szczegółów, aby zachować czystą wersję dla graczy bez ujawniania sekretów Mistrza Gry.' },
|
|
167
|
+
],
|
|
168
|
+
faq,
|
|
169
|
+
bibliography,
|
|
170
|
+
howTo,
|
|
171
|
+
schemas: [faqSchema, appSchema, howToSchema] as unknown as Record<string, unknown>[],
|
|
172
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import { bibliography } from '../bibliography';
|
|
3
|
+
import type { DungeonMapGeneratorLocaleContent, DungeonMapGeneratorUI } from '../entry';
|
|
4
|
+
|
|
5
|
+
const ui: DungeonMapGeneratorUI = {
|
|
6
|
+
intro: 'Escolha uma semente, ajuste a grade e selecione um estilo arquitetônico. Gere um mapa conectado para suas notas, impressão ou mesa virtual.',
|
|
7
|
+
seedLabel: 'Semente do mapa',
|
|
8
|
+
seedHint: 'Reutilize a mesma semente com as mesmas configurações para reconstruir exatamente o mesmo mapa.',
|
|
9
|
+
randomSeed: 'Nova semente',
|
|
10
|
+
sizeLabel: 'Tamanho da expedição',
|
|
11
|
+
sizeCompact: 'Sessão única (One-shot)',
|
|
12
|
+
sizeSession: 'Sessão padrão',
|
|
13
|
+
sizeStronghold: 'Fortaleza',
|
|
14
|
+
fineTuneGrid: 'Ajuste fino de grade e densidade',
|
|
15
|
+
columnsLabel: 'Colunas',
|
|
16
|
+
rowsLabel: 'Linhas',
|
|
17
|
+
densityLabel: 'Densidade de salas',
|
|
18
|
+
densityHint: 'Densidade mais alta adiciona mais salas e área útil de piso.',
|
|
19
|
+
styleLabel: 'Arquitetura do mapa',
|
|
20
|
+
dungeonStyle: 'Masmorra',
|
|
21
|
+
dungeonStyleHint: 'Salas de pedra com corredores de largura única.',
|
|
22
|
+
cavernStyle: 'Caverna',
|
|
23
|
+
cavernStyleHint: 'Câmaras irregulares com bordas suavizadas.',
|
|
24
|
+
scifiStyle: 'Ficção Científica',
|
|
25
|
+
scifiStyleHint: 'Módulos amplos com corredores de largura dupla.',
|
|
26
|
+
generate: 'Desenhar mapa',
|
|
27
|
+
mapRegionLabel: 'Mapa de masmorra gerado e controles de exportação',
|
|
28
|
+
connectedBadge: 'Todas as salas conectadas',
|
|
29
|
+
roomsLabel: 'Salas',
|
|
30
|
+
doorsLabel: 'Portas',
|
|
31
|
+
floorLabel: 'Cobertura de piso',
|
|
32
|
+
legendFloor: 'Piso caminhável',
|
|
33
|
+
legendWall: 'Parede sólida',
|
|
34
|
+
legendDoor: 'Porta ou escotilha',
|
|
35
|
+
editHint: 'Clique com o botão direito em uma célula para editar',
|
|
36
|
+
editCell: 'Editar esta célula',
|
|
37
|
+
paintFloor: 'Piso',
|
|
38
|
+
paintWall: 'Parede',
|
|
39
|
+
paintDoor: 'Porta',
|
|
40
|
+
mapData: 'Dados do mapa',
|
|
41
|
+
copyLink: 'Copiar link do mapa',
|
|
42
|
+
linkCopied: 'Link copiado',
|
|
43
|
+
exportPng: 'Baixar PNG',
|
|
44
|
+
exportSvg: 'Baixar SVG',
|
|
45
|
+
exportJson: 'Salvar JSON',
|
|
46
|
+
importJson: 'Abrir JSON',
|
|
47
|
+
importError: 'Este arquivo não contém uma configuração válida de mapa de masmorra.',
|
|
48
|
+
compactMap: 'Exploração tensa',
|
|
49
|
+
balancedMap: 'Expedição equilibrada',
|
|
50
|
+
sprawlingMap: 'Fortaleza aberta',
|
|
51
|
+
compactHint: 'Corredores mais longos deixam mais espaço desconhecido entre as salas.',
|
|
52
|
+
balancedHint: 'Salas e corredores dividem o espaço de forma equilibrada.',
|
|
53
|
+
sprawlingHint: 'Maior cobertura de piso favorece combates e movimentação rápida.',
|
|
54
|
+
mapReady: 'Legenda do mapa',
|
|
55
|
+
dimensionsUnit: 'células de grade',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const faq = [
|
|
59
|
+
{
|
|
60
|
+
question: 'A mesma semente sempre cria o mesmo mapa de masmorra?',
|
|
61
|
+
answer: 'Sim. A semente, as dimensões da grade, a densidade e o estilo formam uma configuração determinística. Reutilizar os quatro parâmetros recria exatamente as mesmas salas e portas.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
question: 'Todas as salas geradas são conectadas?',
|
|
65
|
+
answer: 'Sim. As salas são conectadas por uma rota principal após o reposicionamento, garantindo que toda a área de piso pertença a um único mapa conectado.',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
question: 'Qual a diferença entre os estilos masmorra, caverna e ficção científica?',
|
|
69
|
+
answer: 'Masmorra usa salas regulares de pedra. Cavernas criam câmaras irregulares e arredondadas. Ficção científica usa módulos amplos e portas duplas.',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
question: 'Qual formato exportar para uma mesa virtual (VTT)?',
|
|
73
|
+
answer: 'PNG é a opção mais simples para a maioria das mesas virtuais. SVG permanece nítido em qualquer escala e é fácil de editar em softwares vetoriais.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
question: 'Outra pessoa pode regenerar meu mapa aleatório?',
|
|
77
|
+
answer: 'Sim. Copie o link do mapa para incluir a configuração na URL ou envie o arquivo JSON. O destinatário carregará o mesmo mapa instantaneamente.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
question: 'Este gerador adiciona monstros, armadilhas ou tesouros?',
|
|
81
|
+
answer: 'Não. Ele cria um plano arquitetônico neutro para que você possa adaptá-lo a qualquer sistema de jogo. A criação de encontros fica a cargo do Mestre.',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const howTo = [
|
|
86
|
+
{
|
|
87
|
+
name: 'Ajuste as dimensões da grade',
|
|
88
|
+
text: 'Escolha o número de colunas e linhas adequado às suas anotações ou mesa virtual.',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Escolha a arquitetura',
|
|
92
|
+
text: 'Selecione masmorra, caverna ou ficção científica e ajuste a densidade de salas.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Gere e inspecione',
|
|
96
|
+
text: 'Insira uma semente, gere o mapa e revise o resumo de salas, portas e cobertura de piso.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Exporte ou compartilhe',
|
|
100
|
+
text: 'Baixe em PNG ou SVG para jogar, ou salve a configuração via link ou arquivo JSON.',
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
105
|
+
'@context': 'https://schema.org',
|
|
106
|
+
'@type': 'FAQPage',
|
|
107
|
+
mainEntity: faq.map((item) => ({
|
|
108
|
+
'@type': 'Question',
|
|
109
|
+
name: item.question,
|
|
110
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
111
|
+
})),
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
115
|
+
'@context': 'https://schema.org',
|
|
116
|
+
'@type': 'SoftwareApplication',
|
|
117
|
+
name: 'Gerador de Mapas de Masmorra Aleatórios',
|
|
118
|
+
operatingSystem: 'All',
|
|
119
|
+
applicationCategory: 'UtilitiesApplication',
|
|
120
|
+
description: 'Um gerador determinístico de mapas de masmorra com salas conectadas, portas e exportações locais.',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const howToSchema: WithContext<HowTo> = {
|
|
124
|
+
'@context': 'https://schema.org',
|
|
125
|
+
'@type': 'HowTo',
|
|
126
|
+
name: 'Como gerar um mapa de masmorra conectado',
|
|
127
|
+
step: howTo.map((item) => ({
|
|
128
|
+
'@type': 'HowToStep',
|
|
129
|
+
name: item.name,
|
|
130
|
+
text: item.text,
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const content: DungeonMapGeneratorLocaleContent = {
|
|
135
|
+
slug: 'gerador-mapas-masmorra-aleatorios',
|
|
136
|
+
title: 'Gerador de Mapas de Masmorra Aleatórios para RPG',
|
|
137
|
+
description: 'Crie mapas reproduzíveis de masmorras, cavernas e ficção científica com salas conectadas, portas e exportação PNG/SVG.',
|
|
138
|
+
ui,
|
|
139
|
+
seo: [
|
|
140
|
+
{ type: 'title', text: 'Gere um Mapa de Masmorra Jogável com uma Semente Reutilizável', level: 2 },
|
|
141
|
+
{ type: 'paragraph', html: 'Um gerador de mapas de masmorra útil precisa ir além do ruído visual aleatório. Cada câmara deve ser acessível por corredores conectados, a grade deve se ajustar à superfície de jogo e o resultado deve poder ser recuperado a qualquer momento em qualquer dispositivo. Este gerador trata a semente e os controles como uma especificação de mapa compacta e determinística. Manter a mesma semente, colunas, linhas, densidade e estilo arquitetônico garante a reconstituição de exatamente o mesmo plano mais tarde.' },
|
|
142
|
+
{ type: 'title', text: 'Dimensões de Grade para Impressão e Mesas Virtuais', level: 2 },
|
|
143
|
+
{ type: 'paragraph', html: 'Configurar o tamanho da grade é o primeiro passo prático ao planejar uma sessão. Uma grade pequena é fácil de imprimir em papel para aventuras curtas ou locais pontuais, enquanto um mapa amplo deixa espaço para explorações complexas, encontros táticos e várias facções. A imagem exportada preserva células perfeitamente quadradas para alinhar perfeitamente com a grade em softwares de mesa virtual (VTT).' },
|
|
144
|
+
{
|
|
145
|
+
type: 'table',
|
|
146
|
+
headers: ['Tamanho da grade', 'Uso típico', 'Densidade inicial', 'Nota de planejamento'],
|
|
147
|
+
rows: [
|
|
148
|
+
['20 por 16 células', 'Aventura curta (One-shot)', '35 a 45', 'Fácil de imprimir e leitura visual rápida no papel'],
|
|
149
|
+
['36 por 26 células', 'Masmorra de sessão', '45 a 55', 'Ritmo equilibrado entre salas e corredores'],
|
|
150
|
+
['52 por 38 células', 'Complexo multi-sessão', '50 a 65', 'Espaço amplo para várias facções e caminhos opcionais'],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{ type: 'tip', title: 'Adapte o Mapa à Escala dos Combates', html: 'Calcule as células necessárias para seus encontros principais antes de definir o tamanho total. Uma grande masmorra com salas minúsculas parecerá apertada, enquanto um plano compacto com uma sala principal espaçosa favorece encontros marcantes.' },
|
|
154
|
+
{ type: 'title', text: 'Interprete a Cobertura de Piso como Ritmo de Jogo', level: 2 },
|
|
155
|
+
{ type: 'paragraph', html: 'A cobertura de piso indica a porcentagem da área retangular do mapa que é caminhável. Baixa cobertura enfatiza mistério, isolamento e tensão entre as salas. Cobertura média suporta um ritmo constante de expedição. Alta cobertura cria complexos fortificados onde combates e patrulhas podem se espalhar para salas adjacentes.' },
|
|
156
|
+
{
|
|
157
|
+
type: 'list',
|
|
158
|
+
items: [
|
|
159
|
+
'<strong>Exploração tensa:</strong> use o espaço vazio para sugerir isolamento ou passagens secretas.',
|
|
160
|
+
'<strong>Expedição equilibrada:</strong> alterne salas de investigação com corredores e áreas de combate.',
|
|
161
|
+
'<strong>Fortaleza aberta:</strong> planeje linhas de visão claras, rotas de patrulha e encontros interconectados.',
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{ type: 'title', text: 'Transforme um Plano Neutro em um Local de Aventura', level: 2 },
|
|
165
|
+
{ type: 'paragraph', html: 'O mapa gerado fornece intencionalmente apenas a arquitetura básica. Atribua um papel narrativo a cada sala principal e adicione pistas, armadilhas, criaturas e tesouros de acordo com esse propósito. Use as portas como pontos de decisão estratégica para os jogadores.' },
|
|
166
|
+
{ type: 'tip', title: 'Salve a Configuração antes de Adicionar Notas', html: 'Copie o link do mapa ou salve o arquivo JSON antes de anotar os encontros para manter uma cópia limpa para os jogadores sem revelar os segredos do Mestre.' },
|
|
167
|
+
],
|
|
168
|
+
faq,
|
|
169
|
+
bibliography,
|
|
170
|
+
howTo,
|
|
171
|
+
schemas: [faqSchema, appSchema, howToSchema] as unknown as Record<string, unknown>[],
|
|
172
|
+
};
|