@agent-cms/agentcms 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +143 -0
  2. package/README.md +1119 -2
  3. package/changelog.json +31 -0
  4. package/dist/admin/admin-files.json +48 -0
  5. package/dist/admin/assets/CodeEditor-Wx1WlF3h.js +24 -0
  6. package/dist/admin/assets/flexweg-logo-CdtuqAFA.png +0 -0
  7. package/dist/admin/assets/index-DFVZw8E0.js +5460 -0
  8. package/dist/admin/assets/index-DMcGogR2.css +1 -0
  9. package/dist/admin/assets/sql-wasm-Bfkbn6Oa.js +2 -0
  10. package/dist/admin/assets/sql-wasm-C1U8OeUW.wasm +0 -0
  11. package/dist/admin/assets/sql-wasm-V5jTDcrT.js +1 -0
  12. package/dist/admin/config.js +11 -0
  13. package/dist/admin/external.default.json +72 -0
  14. package/dist/admin/index.html +116 -0
  15. package/dist/admin/plugins/core-seo/bundle.js +55 -0
  16. package/dist/admin/plugins/core-seo/manifest.json +7 -0
  17. package/dist/admin/plugins/flexweg-archives/bundle.js +1414 -0
  18. package/dist/admin/plugins/flexweg-archives/manifest.json +7 -0
  19. package/dist/admin/plugins/flexweg-multilang/bundle.js +1187 -0
  20. package/dist/admin/plugins/flexweg-multilang/manifest.json +7 -0
  21. package/dist/admin/plugins/flexweg-rss/bundle.js +1354 -0
  22. package/dist/admin/plugins/flexweg-rss/manifest.json +7 -0
  23. package/dist/admin/plugins/flexweg-search/bundle.js +1243 -0
  24. package/dist/admin/plugins/flexweg-search/manifest.json +7 -0
  25. package/dist/admin/plugins/flexweg-sitemaps/bundle.js +1293 -0
  26. package/dist/admin/plugins/flexweg-sitemaps/manifest.json +7 -0
  27. package/dist/admin/runtime/cms-runtime.js +164 -0
  28. package/dist/admin/runtime/react-dom-client.js +13 -0
  29. package/dist/admin/runtime/react-dom.js +16 -0
  30. package/dist/admin/runtime/react-i18next.js +21 -0
  31. package/dist/admin/runtime/react-jsx-runtime.js +17 -0
  32. package/dist/admin/runtime/react.js +55 -0
  33. package/dist/admin/themes/corporate/bundle.js +14465 -0
  34. package/dist/admin/themes/corporate/manifest.json +7 -0
  35. package/dist/admin/themes/corporate/theme.css +2 -0
  36. package/dist/admin/themes/magazine/bundle.js +10229 -0
  37. package/dist/admin/themes/magazine/manifest.json +7 -0
  38. package/dist/admin/themes/magazine/theme.css +2 -0
  39. package/dist/admin/themes/marketplace-core/bundle.js +11213 -0
  40. package/dist/admin/themes/marketplace-core/manifest.json +7 -0
  41. package/dist/admin/themes/marketplace-core/theme.css +1613 -0
  42. package/dist/admin/themes/portfolio/bundle.js +9195 -0
  43. package/dist/admin/themes/portfolio/manifest.json +7 -0
  44. package/dist/admin/themes/portfolio/theme.css +2 -0
  45. package/dist/admin/themes/storefront/bundle.js +13172 -0
  46. package/dist/admin/themes/storefront/manifest.json +7 -0
  47. package/dist/admin/themes/storefront/theme.css +2 -0
  48. package/dist/agent/agentcms.mjs +1711 -0
  49. package/dist/agent/chunks/hosting-BftlDdsL.mjs +117 -0
  50. package/dist/agent/chunks/index-BG05qslv.mjs +3608 -0
  51. package/dist/agent/chunks/install-DnmgOT3F.mjs +577 -0
  52. package/dist/agent/chunks/plan-BrM8ztEp.mjs +245 -0
  53. package/dist/agent/chunks/registry-C9TSnZ77.mjs +53517 -0
  54. package/dist/agent/chunks/siteAdd-BcXhN9fk.mjs +118 -0
  55. package/dist/agent/chunks/sql-wasm-GjJDiefO.mjs +10 -0
  56. package/dist/agent/chunks/sqljs-DjSCStJ0.mjs +20 -0
  57. package/dist/agent/vendor/sql-wasm.cjs +188 -0
  58. package/dist/theme-assets/corporate-menu.js +266 -0
  59. package/dist/theme-assets/corporate-posts.js +571 -0
  60. package/dist/theme-assets/corporate.css +2 -0
  61. package/dist/theme-assets/default-menu.js +266 -0
  62. package/dist/theme-assets/default-posts.js +378 -0
  63. package/dist/theme-assets/default.css +1 -0
  64. package/dist/theme-assets/magazine-menu.js +227 -0
  65. package/dist/theme-assets/magazine-posts.js +361 -0
  66. package/dist/theme-assets/magazine.css +2 -0
  67. package/dist/theme-assets/portfolio-filters.js +104 -0
  68. package/dist/theme-assets/portfolio-menu.js +240 -0
  69. package/dist/theme-assets/portfolio-posts.js +358 -0
  70. package/dist/theme-assets/portfolio.css +2 -0
  71. package/dist/theme-assets/storefront-catalog.js +504 -0
  72. package/dist/theme-assets/storefront-menu.js +239 -0
  73. package/dist/theme-assets/storefront-posts.js +404 -0
  74. package/dist/theme-assets/storefront.css +2 -0
  75. package/dist/version.json +9 -0
  76. package/package.json +101 -4
  77. package/plugin/.claude-plugin/plugin.json +16 -0
  78. package/plugin/skills/agentcms-install/SKILL.md +110 -0
  79. package/plugin/skills/agentcms-install/references/cloudflare.md +15 -0
  80. package/plugin/skills/agentcms-install/references/flexweg.md +11 -0
  81. package/plugin/skills/agentcms-install/references/github.md +67 -0
  82. package/plugin/skills/agentcms-install/references/gitlab.md +15 -0
  83. package/plugin/skills/agentcms-install/references/s3.md +81 -0
  84. package/plugin/skills/agentcms-manage/SKILL.md +92 -0
@@ -0,0 +1,1293 @@
1
+ import { pickPublicLocale as re, deleteFile as M, uploadFile as A, pathToPublicUrl as v, applyFiltersSync as X, applyFilters as de, buildPostUrl as pe, useCmsData as ce, toast as L, fetchAllPosts as W } from "@flexweg/cms-runtime";
2
+ import { jsxs as u, jsx as d } from "react/jsx-runtime";
3
+ import { forwardRef as K, createElement as G, useState as C, useEffect as me } from "react";
4
+ import { useTranslation as ue } from "react-i18next";
5
+ const ge = {
6
+ title: "Sitemaps",
7
+ description: "Generates sitemaps/sitemap-<year>.xml files, a sitemaps/sitemap-index.xml referencing them, an optional sitemaps/sitemap-news.xml, and a customizable robots.txt at the site root.",
8
+ regenerationTarget: {
9
+ label: "Sitemaps",
10
+ description: "Yearly + index sitemaps under /sitemaps/, robots.txt, XSL stylesheets"
11
+ },
12
+ sections: {
13
+ general: "General",
14
+ robots: "robots.txt",
15
+ actions: "Regeneration"
16
+ },
17
+ xsl: {
18
+ help: "XSL stylesheets style the sitemaps when opened in a browser. Re-upload after changing the public site language.",
19
+ upload: "Upload stylesheets",
20
+ uploading: "Uploading…",
21
+ uploaded: "Uploaded {{count}} stylesheet(s).",
22
+ failed: "Stylesheet upload failed."
23
+ },
24
+ contentTypes: {
25
+ label: "Content types in sitemaps",
26
+ posts: "Posts only",
27
+ postsPages: "Posts and pages"
28
+ },
29
+ news: {
30
+ enabled: "Generate sitemap-news.xml",
31
+ enabledHelp: "Enable to publish a Google News sitemap alongside the index.",
32
+ windowDays: "News window (days)",
33
+ windowDaysHelp: "Articles modified within this many days appear in sitemap-news.xml. Google recommends 2."
34
+ },
35
+ robots: {
36
+ label: "robots.txt content",
37
+ help: "Leave empty to use a generated default that points to your sitemaps/sitemap-index.xml (and sitemaps/sitemap-news.xml when News is enabled).",
38
+ resetDefault: "Insert default",
39
+ saveAndRegenerate: "Save & regenerate robots.txt",
40
+ saving: "Saving…",
41
+ saved: "robots.txt saved and regenerated."
42
+ },
43
+ saveSettings: "Save settings",
44
+ saved: "Settings saved.",
45
+ forceRegenerate: "Force regenerate sitemaps",
46
+ forceRegenerating: "Regenerating…",
47
+ regenerated: "Sitemaps regenerated.",
48
+ regenerateFailed: "Sitemap regeneration failed.",
49
+ baseUrlMissing: "Set the public site URL in Settings → General before regenerating sitemaps.",
50
+ uploaded: "Uploaded {{count}} files."
51
+ }, he = {
52
+ title: "Sitemaps",
53
+ description: "Génère les fichiers sitemaps/sitemap-<année>.xml, un sitemaps/sitemap-index.xml qui les référence, un sitemaps/sitemap-news.xml optionnel, et un robots.txt personnalisable à la racine du site.",
54
+ regenerationTarget: {
55
+ label: "Sitemaps",
56
+ description: "Sitemaps annuels + index sous /sitemaps/, robots.txt, feuilles XSL"
57
+ },
58
+ sections: {
59
+ general: "Général",
60
+ robots: "robots.txt",
61
+ actions: "Régénération"
62
+ },
63
+ xsl: {
64
+ help: "Les feuilles de style XSL habillent les sitemaps quand on les ouvre dans un navigateur. À ré-envoyer après un changement de langue du site public.",
65
+ upload: "Envoyer les feuilles de style",
66
+ uploading: "Envoi…",
67
+ uploaded: "{{count}} feuille(s) de style envoyée(s).",
68
+ failed: "Échec de l'envoi des feuilles de style."
69
+ },
70
+ contentTypes: {
71
+ label: "Types de contenu dans les sitemaps",
72
+ posts: "Articles uniquement",
73
+ postsPages: "Articles et pages"
74
+ },
75
+ news: {
76
+ enabled: "Générer sitemap-news.xml",
77
+ enabledHelp: "Activez pour publier un sitemap Google News à côté de l'index.",
78
+ windowDays: "Fenêtre News (jours)",
79
+ windowDaysHelp: "Les articles modifiés dans cet intervalle apparaissent dans sitemap-news.xml. Google recommande 2."
80
+ },
81
+ robots: {
82
+ label: "Contenu de robots.txt",
83
+ help: "Laissez vide pour utiliser un robots.txt par défaut généré, qui pointe vers votre sitemaps/sitemap-index.xml (et sitemaps/sitemap-news.xml si News est activé).",
84
+ resetDefault: "Insérer le défaut",
85
+ saveAndRegenerate: "Enregistrer & régénérer robots.txt",
86
+ saving: "Enregistrement…",
87
+ saved: "robots.txt enregistré et régénéré."
88
+ },
89
+ saveSettings: "Enregistrer les réglages",
90
+ saved: "Réglages enregistrés.",
91
+ forceRegenerate: "Forcer la régénération",
92
+ forceRegenerating: "Régénération…",
93
+ regenerated: "Sitemaps régénérés.",
94
+ regenerateFailed: "Échec de la régénération des sitemaps.",
95
+ baseUrlMissing: "Définissez l'URL publique du site dans Réglages → Général avant de régénérer les sitemaps.",
96
+ uploaded: "{{count}} fichiers envoyés."
97
+ }, fe = {
98
+ title: "Sitemaps",
99
+ description: "Erzeugt sitemaps/sitemap-<Jahr>.xml-Dateien, eine sitemaps/sitemap-index.xml, die darauf verweist, eine optionale sitemaps/sitemap-news.xml und eine anpassbare robots.txt im Site-Root.",
100
+ regenerationTarget: {
101
+ label: "Sitemaps",
102
+ description: "Jährliche + Index-Sitemaps unter /sitemaps/, robots.txt, XSL-Stylesheets"
103
+ },
104
+ sections: {
105
+ general: "Allgemein",
106
+ robots: "robots.txt",
107
+ actions: "Neuerzeugung"
108
+ },
109
+ xsl: {
110
+ help: "XSL-Stylesheets stylen die Sitemaps, wenn sie im Browser geöffnet werden. Nach Änderung der öffentlichen Website-Sprache erneut hochladen.",
111
+ upload: "Stylesheets hochladen",
112
+ uploading: "Lädt hoch…",
113
+ uploaded: "{{count}} Stylesheet(s) hochgeladen.",
114
+ failed: "Stylesheet-Upload fehlgeschlagen."
115
+ },
116
+ contentTypes: {
117
+ label: "Inhaltstypen in Sitemaps",
118
+ posts: "Nur Artikel",
119
+ postsPages: "Artikel und Seiten"
120
+ },
121
+ news: {
122
+ enabled: "sitemap-news.xml erzeugen",
123
+ enabledHelp: "Aktivieren, um eine Google-News-Sitemap neben dem Index zu veröffentlichen.",
124
+ windowDays: "News-Fenster (Tage)",
125
+ windowDaysHelp: "Artikel, die innerhalb dieser Anzahl von Tagen geändert wurden, erscheinen in sitemap-news.xml. Google empfiehlt 2."
126
+ },
127
+ robots: {
128
+ label: "Inhalt der robots.txt",
129
+ help: "Leer lassen, um eine erzeugte Standard-Datei zu verwenden, die auf Ihre sitemaps/sitemap-index.xml (und sitemaps/sitemap-news.xml bei aktivierter News-Sitemap) verweist.",
130
+ resetDefault: "Standard einfügen",
131
+ saveAndRegenerate: "Speichern & robots.txt neu erzeugen",
132
+ saving: "Speichert…",
133
+ saved: "robots.txt gespeichert und neu erzeugt."
134
+ },
135
+ saveSettings: "Einstellungen speichern",
136
+ saved: "Einstellungen gespeichert.",
137
+ forceRegenerate: "Sitemaps zwangsweise neu erzeugen",
138
+ forceRegenerating: "Neu erzeugen…",
139
+ regenerated: "Sitemaps neu erzeugt.",
140
+ regenerateFailed: "Sitemap-Neuerzeugung fehlgeschlagen.",
141
+ baseUrlMissing: "Legen Sie die öffentliche Website-URL unter Einstellungen → Allgemein fest, bevor Sie Sitemaps neu erzeugen.",
142
+ uploaded: "{{count}} Dateien hochgeladen."
143
+ }, we = {
144
+ title: "Sitemaps",
145
+ description: "Genera archivos sitemaps/sitemap-<año>.xml, un sitemaps/sitemap-index.xml que los referencia, un sitemaps/sitemap-news.xml opcional y un robots.txt personalizable en la raíz del sitio.",
146
+ regenerationTarget: {
147
+ label: "Sitemaps",
148
+ description: "Sitemaps anuales + índice bajo /sitemaps/, robots.txt, hojas XSL"
149
+ },
150
+ sections: {
151
+ general: "General",
152
+ robots: "robots.txt",
153
+ actions: "Regeneración"
154
+ },
155
+ xsl: {
156
+ help: "Las hojas de estilo XSL dan formato a los sitemaps cuando se abren en un navegador. Vuelve a subirlas tras cambiar el idioma del sitio público.",
157
+ upload: "Subir hojas de estilo",
158
+ uploading: "Subiendo…",
159
+ uploaded: "Subidas {{count}} hoja(s) de estilo.",
160
+ failed: "Error al subir las hojas de estilo."
161
+ },
162
+ contentTypes: {
163
+ label: "Tipos de contenido en sitemaps",
164
+ posts: "Solo entradas",
165
+ postsPages: "Entradas y páginas"
166
+ },
167
+ news: {
168
+ enabled: "Generar sitemap-news.xml",
169
+ enabledHelp: "Actívalo para publicar un sitemap de Google News junto al índice.",
170
+ windowDays: "Ventana News (días)",
171
+ windowDaysHelp: "Los artículos modificados en este número de días aparecen en sitemap-news.xml. Google recomienda 2."
172
+ },
173
+ robots: {
174
+ label: "Contenido de robots.txt",
175
+ help: "Déjalo vacío para usar un valor por defecto generado que apunta a tu sitemaps/sitemap-index.xml (y a sitemaps/sitemap-news.xml si News está activado).",
176
+ resetDefault: "Insertar por defecto",
177
+ saveAndRegenerate: "Guardar y regenerar robots.txt",
178
+ saving: "Guardando…",
179
+ saved: "robots.txt guardado y regenerado."
180
+ },
181
+ saveSettings: "Guardar ajustes",
182
+ saved: "Ajustes guardados.",
183
+ forceRegenerate: "Forzar regeneración",
184
+ forceRegenerating: "Regenerando…",
185
+ regenerated: "Sitemaps regenerados.",
186
+ regenerateFailed: "La regeneración de sitemaps falló.",
187
+ baseUrlMissing: "Define la URL pública del sitio en Ajustes → General antes de regenerar los sitemaps.",
188
+ uploaded: "{{count}} archivos subidos."
189
+ }, be = {
190
+ title: "Sitemaps",
191
+ description: "Genereert sitemaps/sitemap-<jaar>.xml-bestanden, een sitemaps/sitemap-index.xml die ernaar verwijst, een optionele sitemaps/sitemap-news.xml en een aanpasbare robots.txt in de site-root.",
192
+ regenerationTarget: {
193
+ label: "Sitemaps",
194
+ description: "Jaarlijkse + index-sitemaps onder /sitemaps/, robots.txt, XSL-stylesheets"
195
+ },
196
+ sections: {
197
+ general: "Algemeen",
198
+ robots: "robots.txt",
199
+ actions: "Regeneratie"
200
+ },
201
+ xsl: {
202
+ help: "XSL-stylesheets geven sitemaps stijl wanneer ze in een browser worden geopend. Upload opnieuw na het wijzigen van de publieke sitetaal.",
203
+ upload: "Stylesheets uploaden",
204
+ uploading: "Uploaden…",
205
+ uploaded: "{{count}} stylesheet(s) geüpload.",
206
+ failed: "Stylesheet-upload mislukt."
207
+ },
208
+ contentTypes: {
209
+ label: "Inhoudstypes in sitemaps",
210
+ posts: "Alleen berichten",
211
+ postsPages: "Berichten en pagina's"
212
+ },
213
+ news: {
214
+ enabled: "sitemap-news.xml genereren",
215
+ enabledHelp: "Inschakelen om een Google News-sitemap naast de index te publiceren.",
216
+ windowDays: "News-venster (dagen)",
217
+ windowDaysHelp: "Artikelen die binnen dit aantal dagen zijn gewijzigd verschijnen in sitemap-news.xml. Google adviseert 2."
218
+ },
219
+ robots: {
220
+ label: "Inhoud van robots.txt",
221
+ help: "Laat leeg om een gegenereerde standaard te gebruiken die wijst naar je sitemaps/sitemap-index.xml (en sitemaps/sitemap-news.xml wanneer News is ingeschakeld).",
222
+ resetDefault: "Standaard invoegen",
223
+ saveAndRegenerate: "Opslaan & robots.txt opnieuw genereren",
224
+ saving: "Opslaan…",
225
+ saved: "robots.txt opgeslagen en opnieuw gegenereerd."
226
+ },
227
+ saveSettings: "Instellingen opslaan",
228
+ saved: "Instellingen opgeslagen.",
229
+ forceRegenerate: "Sitemaps forceren te regenereren",
230
+ forceRegenerating: "Regenereren…",
231
+ regenerated: "Sitemaps geregenereerd.",
232
+ regenerateFailed: "Sitemap-regeneratie mislukt.",
233
+ baseUrlMissing: "Stel de publieke site-URL in via Instellingen → Algemeen voordat je sitemaps regenereert.",
234
+ uploaded: "{{count}} bestanden geüpload."
235
+ }, xe = {
236
+ title: "Sitemaps",
237
+ description: "Gera ficheiros sitemaps/sitemap-<ano>.xml, um sitemaps/sitemap-index.xml que os referencia, um sitemaps/sitemap-news.xml opcional e um robots.txt personalizável na raiz do site.",
238
+ regenerationTarget: {
239
+ label: "Sitemaps",
240
+ description: "Sitemaps anuais + índice em /sitemaps/, robots.txt, folhas XSL"
241
+ },
242
+ sections: {
243
+ general: "Geral",
244
+ robots: "robots.txt",
245
+ actions: "Regeneração"
246
+ },
247
+ xsl: {
248
+ help: "As folhas de estilo XSL formatam os sitemaps quando abertos num browser. Reenviar após alterar o idioma do site público.",
249
+ upload: "Enviar folhas de estilo",
250
+ uploading: "A enviar…",
251
+ uploaded: "Enviadas {{count}} folha(s) de estilo.",
252
+ failed: "Falha ao enviar folhas de estilo."
253
+ },
254
+ contentTypes: {
255
+ label: "Tipos de conteúdo nos sitemaps",
256
+ posts: "Apenas artigos",
257
+ postsPages: "Artigos e páginas"
258
+ },
259
+ news: {
260
+ enabled: "Gerar sitemap-news.xml",
261
+ enabledHelp: "Ativa para publicar um sitemap Google News ao lado do índice.",
262
+ windowDays: "Janela News (dias)",
263
+ windowDaysHelp: "Os artigos modificados neste número de dias aparecem em sitemap-news.xml. O Google recomenda 2."
264
+ },
265
+ robots: {
266
+ label: "Conteúdo do robots.txt",
267
+ help: "Deixa vazio para usar um valor predefinido gerado que aponta para o teu sitemaps/sitemap-index.xml (e sitemaps/sitemap-news.xml quando o News está ativo).",
268
+ resetDefault: "Inserir predefinido",
269
+ saveAndRegenerate: "Guardar e regenerar robots.txt",
270
+ saving: "A guardar…",
271
+ saved: "robots.txt guardado e regenerado."
272
+ },
273
+ saveSettings: "Guardar definições",
274
+ saved: "Definições guardadas.",
275
+ forceRegenerate: "Forçar regeneração",
276
+ forceRegenerating: "A regenerar…",
277
+ regenerated: "Sitemaps regenerados.",
278
+ regenerateFailed: "Falha na regeneração de sitemaps.",
279
+ baseUrlMissing: "Define o URL público do site em Definições → Geral antes de regenerar sitemaps.",
280
+ uploaded: "{{count}} ficheiros enviados."
281
+ }, ye = {
282
+ title: "사이트맵",
283
+ description: "sitemaps/sitemap-<연도>.xml 파일, 이를 참조하는 sitemaps/sitemap-index.xml, 선택적 sitemaps/sitemap-news.xml 및 사이트 루트의 사용자 정의 가능한 robots.txt를 생성합니다.",
284
+ regenerationTarget: {
285
+ label: "사이트맵",
286
+ description: "/sitemaps/ 아래의 연도별 + 인덱스 사이트맵, robots.txt, XSL 스타일시트"
287
+ },
288
+ sections: {
289
+ general: "일반",
290
+ robots: "robots.txt",
291
+ actions: "재생성"
292
+ },
293
+ xsl: {
294
+ help: "XSL 스타일시트는 브라우저에서 사이트맵을 열 때 스타일을 적용합니다. 공개 사이트 언어를 변경한 후 다시 업로드하세요.",
295
+ upload: "스타일시트 업로드",
296
+ uploading: "업로드 중…",
297
+ uploaded: "{{count}}개의 스타일시트를 업로드했습니다.",
298
+ failed: "스타일시트 업로드에 실패했습니다."
299
+ },
300
+ contentTypes: {
301
+ label: "사이트맵에 포함할 콘텐츠 유형",
302
+ posts: "게시물만",
303
+ postsPages: "게시물 및 페이지"
304
+ },
305
+ news: {
306
+ enabled: "sitemap-news.xml 생성",
307
+ enabledHelp: "활성화하면 인덱스 옆에 Google News 사이트맵을 게시합니다.",
308
+ windowDays: "News 기간 (일)",
309
+ windowDaysHelp: "지정한 일수 내에 수정된 기사는 sitemap-news.xml에 포함됩니다. Google은 2일을 권장합니다."
310
+ },
311
+ robots: {
312
+ label: "robots.txt 내용",
313
+ help: "비워 두면 sitemaps/sitemap-index.xml(및 News가 활성화된 경우 sitemaps/sitemap-news.xml)을 가리키는 기본값이 사용됩니다.",
314
+ resetDefault: "기본값 삽입",
315
+ saveAndRegenerate: "저장 및 robots.txt 재생성",
316
+ saving: "저장 중…",
317
+ saved: "robots.txt가 저장되고 재생성되었습니다."
318
+ },
319
+ saveSettings: "설정 저장",
320
+ saved: "설정이 저장되었습니다.",
321
+ forceRegenerate: "사이트맵 강제 재생성",
322
+ forceRegenerating: "재생성 중…",
323
+ regenerated: "사이트맵이 재생성되었습니다.",
324
+ regenerateFailed: "사이트맵 재생성에 실패했습니다.",
325
+ baseUrlMissing: "사이트맵을 재생성하기 전에 설정 → 일반에서 공개 사이트 URL을 설정하세요.",
326
+ uploaded: "{{count}}개의 파일을 업로드했습니다."
327
+ }, F = "sitemaps/sitemap.xsl", U = "sitemaps/sitemap-news.xsl", Z = {
328
+ en: {
329
+ pageTitle: "XML Sitemap",
330
+ heading: "XML Sitemap",
331
+ meta: "This XML sitemap is meant for consumption by search engines.",
332
+ indexCountBefore: "This index references ",
333
+ indexCountAfter: " sitemaps.",
334
+ urlCountBefore: "This sitemap contains ",
335
+ urlCountAfter: " URLs.",
336
+ newsCountBefore: "This News sitemap contains ",
337
+ newsCountAfter: " articles.",
338
+ newsHeading: "XML News Sitemap",
339
+ newsPageTitle: "XML News Sitemap",
340
+ columnSitemap: "Sitemap URL",
341
+ columnUrl: "URL",
342
+ columnLastmod: "Last modified",
343
+ columnTitle: "Title",
344
+ columnPubdate: "Publication date"
345
+ },
346
+ fr: {
347
+ pageTitle: "Plan du site XML",
348
+ heading: "Plan du site XML",
349
+ meta: "Ce sitemap XML est destiné aux moteurs de recherche.",
350
+ indexCountBefore: "Cet index référence ",
351
+ indexCountAfter: " sitemaps.",
352
+ urlCountBefore: "Ce sitemap contient ",
353
+ urlCountAfter: " URLs.",
354
+ newsCountBefore: "Ce sitemap News contient ",
355
+ newsCountAfter: " articles.",
356
+ newsHeading: "Plan du site XML News",
357
+ newsPageTitle: "Plan du site XML News",
358
+ columnSitemap: "URL du sitemap",
359
+ columnUrl: "URL",
360
+ columnLastmod: "Dernière modification",
361
+ columnTitle: "Titre",
362
+ columnPubdate: "Date de publication"
363
+ },
364
+ de: {
365
+ pageTitle: "XML-Sitemap",
366
+ heading: "XML-Sitemap",
367
+ meta: "Diese XML-Sitemap ist für Suchmaschinen bestimmt.",
368
+ indexCountBefore: "Dieser Index verweist auf ",
369
+ indexCountAfter: " Sitemaps.",
370
+ urlCountBefore: "Diese Sitemap enthält ",
371
+ urlCountAfter: " URLs.",
372
+ newsCountBefore: "Diese News-Sitemap enthält ",
373
+ newsCountAfter: " Artikel.",
374
+ newsHeading: "XML News-Sitemap",
375
+ newsPageTitle: "XML News-Sitemap",
376
+ columnSitemap: "Sitemap-URL",
377
+ columnUrl: "URL",
378
+ columnLastmod: "Zuletzt geändert",
379
+ columnTitle: "Titel",
380
+ columnPubdate: "Veröffentlichungsdatum"
381
+ },
382
+ es: {
383
+ pageTitle: "Sitemap XML",
384
+ heading: "Sitemap XML",
385
+ meta: "Este sitemap XML está destinado a los motores de búsqueda.",
386
+ indexCountBefore: "Este índice referencia ",
387
+ indexCountAfter: " sitemaps.",
388
+ urlCountBefore: "Este sitemap contiene ",
389
+ urlCountAfter: " URLs.",
390
+ newsCountBefore: "Este sitemap News contiene ",
391
+ newsCountAfter: " artículos.",
392
+ newsHeading: "Sitemap XML News",
393
+ newsPageTitle: "Sitemap XML News",
394
+ columnSitemap: "URL del sitemap",
395
+ columnUrl: "URL",
396
+ columnLastmod: "Última modificación",
397
+ columnTitle: "Título",
398
+ columnPubdate: "Fecha de publicación"
399
+ },
400
+ nl: {
401
+ pageTitle: "XML-sitemap",
402
+ heading: "XML-sitemap",
403
+ meta: "Deze XML-sitemap is bedoeld voor gebruik door zoekmachines.",
404
+ indexCountBefore: "Deze index verwijst naar ",
405
+ indexCountAfter: " sitemaps.",
406
+ urlCountBefore: "Deze sitemap bevat ",
407
+ urlCountAfter: " URLs.",
408
+ newsCountBefore: "Deze News-sitemap bevat ",
409
+ newsCountAfter: " artikelen.",
410
+ newsHeading: "XML News-sitemap",
411
+ newsPageTitle: "XML News-sitemap",
412
+ columnSitemap: "Sitemap-URL",
413
+ columnUrl: "URL",
414
+ columnLastmod: "Laatst gewijzigd",
415
+ columnTitle: "Titel",
416
+ columnPubdate: "Publicatiedatum"
417
+ },
418
+ pt: {
419
+ pageTitle: "Sitemap XML",
420
+ heading: "Sitemap XML",
421
+ meta: "Este sitemap XML destina-se aos motores de busca.",
422
+ indexCountBefore: "Este índice referencia ",
423
+ indexCountAfter: " sitemaps.",
424
+ urlCountBefore: "Este sitemap contém ",
425
+ urlCountAfter: " URLs.",
426
+ newsCountBefore: "Este sitemap News contém ",
427
+ newsCountAfter: " artigos.",
428
+ newsHeading: "Sitemap XML News",
429
+ newsPageTitle: "Sitemap XML News",
430
+ columnSitemap: "URL do sitemap",
431
+ columnUrl: "URL",
432
+ columnLastmod: "Última modificação",
433
+ columnTitle: "Título",
434
+ columnPubdate: "Data de publicação"
435
+ },
436
+ ko: {
437
+ pageTitle: "XML 사이트맵",
438
+ heading: "XML 사이트맵",
439
+ meta: "이 XML 사이트맵은 검색 엔진을 위한 것입니다.",
440
+ indexCountBefore: "이 인덱스는 ",
441
+ indexCountAfter: "개의 사이트맵을 참조합니다.",
442
+ urlCountBefore: "이 사이트맵에는 ",
443
+ urlCountAfter: "개의 URL이 포함되어 있습니다.",
444
+ newsCountBefore: "이 News 사이트맵에는 ",
445
+ newsCountAfter: "개의 기사가 포함되어 있습니다.",
446
+ newsHeading: "XML News 사이트맵",
447
+ newsPageTitle: "XML News 사이트맵",
448
+ columnSitemap: "사이트맵 URL",
449
+ columnUrl: "URL",
450
+ columnLastmod: "마지막 수정일",
451
+ columnTitle: "제목",
452
+ columnPubdate: "게시일"
453
+ }
454
+ };
455
+ function Q(t) {
456
+ return re(t);
457
+ }
458
+ const ee = `
459
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; color: #1f2937; margin: 0; padding: 32px 16px; background: #ffffff; }
460
+ main { max-width: 1024px; margin: 0 auto; }
461
+ h1 { font-size: 22px; margin: 0 0 8px; font-weight: 600; }
462
+ .meta { color: #6b7280; font-size: 13px; margin: 0 0 24px; }
463
+ .count { color: #6b7280; font-size: 13px; margin: 0 0 16px; }
464
+ table { width: 100%; border-collapse: collapse; font-size: 13px; }
465
+ th { text-align: left; padding: 10px 12px; background: #f3f4f6; border-bottom: 1px solid #e5e7eb; font-weight: 600; color: #1f2937; }
466
+ td { padding: 10px 12px; border-bottom: 1px solid #f3f4f6; vertical-align: top; }
467
+ tr:nth-child(even) td { background: #fafafa; }
468
+ tr:hover td { background: #f3f4f6; }
469
+ a { color: #2563eb; text-decoration: none; }
470
+ a:hover { text-decoration: underline; }
471
+ .url { word-break: break-all; }
472
+ .lastmod, .pubdate { white-space: nowrap; color: #4b5563; width: 220px; }
473
+ `;
474
+ function ve(t) {
475
+ const s = Q(t), e = Z[s];
476
+ return `<?xml version="1.0" encoding="UTF-8"?>
477
+ <xsl:stylesheet version="1.0"
478
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
479
+ xmlns:s="http://www.sitemaps.org/schemas/sitemap/0.9"
480
+ exclude-result-prefixes="s">
481
+ <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"
482
+ doctype-system="about:legacy-compat"/>
483
+ <xsl:template match="/">
484
+ <html lang="${s}">
485
+ <head>
486
+ <title>${e.pageTitle}</title>
487
+ <meta charset="utf-8"/>
488
+ <meta name="robots" content="noindex,follow"/>
489
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
490
+ <style type="text/css">${ee}</style>
491
+ </head>
492
+ <body>
493
+ <main>
494
+ <h1>${e.heading}</h1>
495
+ <p class="meta">${e.meta}</p>
496
+ <xsl:choose>
497
+ <xsl:when test="s:sitemapindex">
498
+ <p class="count">${e.indexCountBefore}<xsl:value-of select="count(s:sitemapindex/s:sitemap)"/>${e.indexCountAfter}</p>
499
+ <table>
500
+ <thead><tr><th>${e.columnSitemap}</th><th>${e.columnLastmod}</th></tr></thead>
501
+ <tbody>
502
+ <xsl:for-each select="s:sitemapindex/s:sitemap">
503
+ <tr>
504
+ <td class="url"><a href="{s:loc}"><xsl:value-of select="s:loc"/></a></td>
505
+ <td class="lastmod"><xsl:value-of select="s:lastmod"/></td>
506
+ </tr>
507
+ </xsl:for-each>
508
+ </tbody>
509
+ </table>
510
+ </xsl:when>
511
+ <xsl:when test="s:urlset">
512
+ <p class="count">${e.urlCountBefore}<xsl:value-of select="count(s:urlset/s:url)"/>${e.urlCountAfter}</p>
513
+ <table>
514
+ <thead><tr><th>${e.columnUrl}</th><th>${e.columnLastmod}</th></tr></thead>
515
+ <tbody>
516
+ <xsl:for-each select="s:urlset/s:url">
517
+ <tr>
518
+ <td class="url"><a href="{s:loc}"><xsl:value-of select="s:loc"/></a></td>
519
+ <td class="lastmod"><xsl:value-of select="s:lastmod"/></td>
520
+ </tr>
521
+ </xsl:for-each>
522
+ </tbody>
523
+ </table>
524
+ </xsl:when>
525
+ </xsl:choose>
526
+ </main>
527
+ </body>
528
+ </html>
529
+ </xsl:template>
530
+ </xsl:stylesheet>`;
531
+ }
532
+ function Se(t) {
533
+ const s = Q(t), e = Z[s];
534
+ return `<?xml version="1.0" encoding="UTF-8"?>
535
+ <xsl:stylesheet version="1.0"
536
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
537
+ xmlns:s="http://www.sitemaps.org/schemas/sitemap/0.9"
538
+ xmlns:n="http://www.google.com/schemas/sitemap-news/0.9"
539
+ exclude-result-prefixes="s n">
540
+ <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"
541
+ doctype-system="about:legacy-compat"/>
542
+ <xsl:template match="/">
543
+ <html lang="${s}">
544
+ <head>
545
+ <title>${e.newsPageTitle}</title>
546
+ <meta charset="utf-8"/>
547
+ <meta name="robots" content="noindex,follow"/>
548
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
549
+ <style type="text/css">${ee}</style>
550
+ </head>
551
+ <body>
552
+ <main>
553
+ <h1>${e.newsHeading}</h1>
554
+ <p class="meta">${e.meta}</p>
555
+ <p class="count">${e.newsCountBefore}<xsl:value-of select="count(s:urlset/s:url)"/>${e.newsCountAfter}</p>
556
+ <table>
557
+ <thead><tr><th>${e.columnTitle}</th><th>${e.columnPubdate}</th></tr></thead>
558
+ <tbody>
559
+ <xsl:for-each select="s:urlset/s:url">
560
+ <tr>
561
+ <td class="url"><a href="{s:loc}"><xsl:value-of select="n:news/n:title"/></a></td>
562
+ <td class="pubdate"><xsl:value-of select="n:news/n:publication_date"/></td>
563
+ </tr>
564
+ </xsl:for-each>
565
+ </tbody>
566
+ </table>
567
+ </main>
568
+ </body>
569
+ </html>
570
+ </xsl:template>
571
+ </xsl:stylesheet>`;
572
+ }
573
+ const te = {
574
+ newsEnabled: !1,
575
+ newsWindowDays: 2,
576
+ contentTypes: "posts-pages",
577
+ robotsTxt: ""
578
+ }, O = "sitemaps", z = `${O}/sitemap-index.xml`, R = `${O}/sitemap-news.xml`, Le = "robots.txt";
579
+ function se(t) {
580
+ return `${O}/sitemap-${t}.xml`;
581
+ }
582
+ const ae = [
583
+ "sitemap-index.xml",
584
+ "sitemap-news.xml",
585
+ "sitemap.xsl",
586
+ "sitemap-news.xsl"
587
+ ];
588
+ function Te(t) {
589
+ return `sitemap-${t}.xml`;
590
+ }
591
+ function j(t, s) {
592
+ const e = ["User-agent: *", "Allow: /", "Disallow: /admin/", ""];
593
+ return t && (e.push(`Sitemap: ${v(t, z)}`), s && e.push(`Sitemap: ${v(t, R)}`)), e.join(`
594
+ `) + `
595
+ `;
596
+ }
597
+ function Y(t, s) {
598
+ var n, a, o, l, p, g;
599
+ let e;
600
+ try {
601
+ const m = t.primaryTermId ? s.find((w) => w.id === t.primaryTermId) : void 0;
602
+ e = pe({ post: t, primaryTerm: m });
603
+ } catch {
604
+ return null;
605
+ }
606
+ const i = ((a = (n = t.createdAt) == null ? void 0 : n.toMillis) == null ? void 0 : a.call(n)) ?? ((l = (o = t.publishedAt) == null ? void 0 : o.toMillis) == null ? void 0 : l.call(o)) ?? Date.now(), r = ((g = (p = t.updatedAt) == null ? void 0 : p.toMillis) == null ? void 0 : g.call(p)) ?? i;
607
+ return {
608
+ path: e,
609
+ createdAtMs: i,
610
+ updatedAtMs: r,
611
+ title: t.title || t.slug,
612
+ sourcePost: t
613
+ };
614
+ }
615
+ function Ae(t, s, e, i) {
616
+ const r = [];
617
+ for (const n of t) {
618
+ if (n.status !== "online") continue;
619
+ const a = Y(n, e);
620
+ a && r.push(a);
621
+ }
622
+ if (i.contentTypes === "posts-pages")
623
+ for (const n of s) {
624
+ if (n.status !== "online") continue;
625
+ const a = Y(n, e);
626
+ a && r.push(a);
627
+ }
628
+ return r;
629
+ }
630
+ function Re(t) {
631
+ const s = /* @__PURE__ */ new Map();
632
+ for (const e of t) {
633
+ const i = new Date(e.createdAtMs).getUTCFullYear(), r = s.get(i) ?? [];
634
+ r.push(e), s.set(i, r);
635
+ }
636
+ return s;
637
+ }
638
+ function x(t) {
639
+ return t.replace(/[&<>"']/g, (s) => {
640
+ switch (s) {
641
+ case "&":
642
+ return "&amp;";
643
+ case "<":
644
+ return "&lt;";
645
+ case ">":
646
+ return "&gt;";
647
+ case '"':
648
+ return "&quot;";
649
+ default:
650
+ return "&apos;";
651
+ }
652
+ });
653
+ }
654
+ function Ne(t) {
655
+ return new Date(t).toISOString();
656
+ }
657
+ function k(t) {
658
+ return new Date(t).toISOString().slice(0, 10);
659
+ }
660
+ function _(t) {
661
+ return [
662
+ '<?xml version="1.0" encoding="UTF-8"?>',
663
+ `<?xml-stylesheet type="text/xsl" href="${x(t)}"?>`
664
+ ].join(`
665
+ `);
666
+ }
667
+ function Ce(t, s, e, i) {
668
+ const r = X(
669
+ "sitemap.urlset.namespaces",
670
+ {},
671
+ { kind: "year", baseUrl: s }
672
+ ), n = Object.entries(r).map(([o, l]) => ` ${x(o)}="${x(l)}"`).join(""), a = [
673
+ _(e),
674
+ `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"${n}>`
675
+ ];
676
+ for (const o of t) {
677
+ const l = X(
678
+ "sitemap.url.entry",
679
+ "",
680
+ { entity: o.sourcePost, baseUrl: s, path: o.path, lastmodMs: o.updatedAtMs }
681
+ );
682
+ a.push(" <url>"), a.push(` <loc>${x(v(s, o.path))}</loc>`), a.push(` <lastmod>${k(o.updatedAtMs)}</lastmod>`), l && a.push(l), a.push(" </url>");
683
+ }
684
+ for (const o of i) {
685
+ const l = o.lastmodMs ?? Date.now();
686
+ a.push(" <url>"), a.push(` <loc>${x(v(s, o.path))}</loc>`), a.push(` <lastmod>${k(l)}</lastmod>`), o.extraInnerXml && a.push(o.extraInnerXml), a.push(" </url>");
687
+ }
688
+ return a.push("</urlset>"), a.join(`
689
+ `);
690
+ }
691
+ function Ue(t, s, e, i, r, n) {
692
+ const a = [
693
+ _(r),
694
+ '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
695
+ ], o = k(i);
696
+ for (const l of [...t].sort((p, g) => p - g))
697
+ a.push(" <sitemap>"), a.push(` <loc>${x(v(e, se(l)))}</loc>`), a.push(` <lastmod>${o}</lastmod>`), a.push(" </sitemap>");
698
+ s && (a.push(" <sitemap>"), a.push(` <loc>${x(v(e, R))}</loc>`), a.push(` <lastmod>${o}</lastmod>`), a.push(" </sitemap>"));
699
+ for (const l of n) {
700
+ const p = l.lastmodMs ?? i;
701
+ a.push(" <sitemap>"), a.push(` <loc>${x(v(e, l.path))}</loc>`), a.push(` <lastmod>${k(p)}</lastmod>`), a.push(" </sitemap>");
702
+ }
703
+ return a.push("</sitemapindex>"), a.join(`
704
+ `);
705
+ }
706
+ function V(t, s, e, i, r, n) {
707
+ const a = Date.now() - r * 24 * 60 * 60 * 1e3, o = t.filter((m) => m.updatedAtMs >= a).sort((m, w) => w.updatedAtMs - m.updatedAtMs), l = [
708
+ _(n),
709
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"',
710
+ ' xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">'
711
+ ], p = x(s || "Site"), g = x((e || "en").split("-")[0] || "en");
712
+ for (const m of o)
713
+ l.push(" <url>"), l.push(` <loc>${x(v(i, m.path))}</loc>`), l.push(" <news:news>"), l.push(" <news:publication>"), l.push(` <news:name>${p}</news:name>`), l.push(` <news:language>${g}</news:language>`), l.push(" </news:publication>"), l.push(` <news:publication_date>${Ne(m.updatedAtMs)}</news:publication_date>`), l.push(` <news:title>${x(m.title)}</news:title>`), l.push(" </news:news>"), l.push(" </url>");
714
+ return l.push("</urlset>"), l.join(`
715
+ `);
716
+ }
717
+ async function q(t) {
718
+ const { posts: s, pages: e, terms: i, settings: r, config: n, scope: a } = t, o = (r.baseUrl || "").replace(/\/+$/, "");
719
+ if (!o) throw new Error("baseUrl is empty — cannot build sitemap URLs.");
720
+ const l = Ae(s, e, i, n), p = Re(l), g = [...p.keys()], m = (a == null ? void 0 : a.years) ?? g, w = [], S = [];
721
+ if (!a) {
722
+ const y = [
723
+ ...ae,
724
+ ...g.map((h) => Te(h))
725
+ ];
726
+ for (const h of y)
727
+ try {
728
+ await M(h), S.push(h);
729
+ } catch {
730
+ }
731
+ }
732
+ const N = v(o, F), T = v(o, U);
733
+ for (const y of m) {
734
+ const h = p.get(y) ?? [], f = X(
735
+ "sitemap.urls.extra",
736
+ [],
737
+ { posts: s, pages: e, terms: i, settings: r, year: y, scope: "year" }
738
+ ), b = se(y);
739
+ if (h.length === 0 && f.length === 0) {
740
+ try {
741
+ await M(b), S.push(b);
742
+ } catch {
743
+ }
744
+ continue;
745
+ }
746
+ const $ = Ce(h, o, N, f);
747
+ await A({ path: b, content: $ }), w.push(b);
748
+ }
749
+ if ((a == null ? void 0 : a.index) !== !1) {
750
+ const y = [...p.entries()].filter(([, b]) => b.length > 0).map(([b]) => b), h = X(
751
+ "sitemap.index.extra",
752
+ [],
753
+ { settings: r }
754
+ ), f = Ue(
755
+ y,
756
+ n.newsEnabled,
757
+ o,
758
+ Date.now(),
759
+ N,
760
+ h
761
+ );
762
+ await A({ path: z, content: f }), w.push(z);
763
+ }
764
+ if ((a == null ? void 0 : a.news) !== !1)
765
+ if (n.newsEnabled) {
766
+ const y = V(
767
+ l,
768
+ r.title,
769
+ r.language,
770
+ o,
771
+ n.newsWindowDays,
772
+ T
773
+ );
774
+ await A({ path: R, content: y }), w.push(R);
775
+ const h = await de(
776
+ "sitemap.news.locales",
777
+ [],
778
+ { posts: s, pages: e, terms: i, settings: r, config: n }
779
+ );
780
+ for (const f of h) {
781
+ if (!f.path || !f.language) continue;
782
+ const b = V(
783
+ f.entities,
784
+ r.title,
785
+ f.language,
786
+ o,
787
+ n.newsWindowDays,
788
+ T
789
+ );
790
+ await A({ path: f.path, content: b }), w.push(f.path);
791
+ }
792
+ } else
793
+ try {
794
+ await M(R), S.push(R);
795
+ } catch {
796
+ }
797
+ return { uploaded: w, deleted: S };
798
+ }
799
+ async function H(t) {
800
+ const s = (t.baseUrl || "").replace(/\/+$/, "");
801
+ let e;
802
+ t.discourageIndexing ? e = `User-agent: *
803
+ Disallow: /
804
+ ` : t.config.robotsTxt && t.config.robotsTxt.trim().length > 0 ? e = t.config.robotsTxt : e = j(s, t.config.newsEnabled), await A({ path: Le, content: e });
805
+ }
806
+ async function B(t) {
807
+ const s = [], e = [];
808
+ for (const i of ae)
809
+ try {
810
+ await M(i), e.push(i);
811
+ } catch {
812
+ }
813
+ if (await A({
814
+ path: F,
815
+ content: ve(t.settings.language)
816
+ }), s.push(F), t.config.newsEnabled)
817
+ await A({
818
+ path: U,
819
+ content: Se(t.settings.language)
820
+ }), s.push(U);
821
+ else
822
+ try {
823
+ await M(U), e.push(U);
824
+ } catch {
825
+ }
826
+ return { uploaded: s, deleted: e };
827
+ }
828
+ async function Me(t) {
829
+ var i, r, n, a, o, l;
830
+ const s = ((r = (i = t.post.createdAt) == null ? void 0 : i.toMillis) == null ? void 0 : r.call(i)) ?? ((a = (n = t.post.publishedAt) == null ? void 0 : n.toMillis) == null ? void 0 : a.call(n)) ?? ((l = (o = t.post.updatedAt) == null ? void 0 : o.toMillis) == null ? void 0 : l.call(o)) ?? Date.now(), e = new Date(s).getUTCFullYear();
831
+ return q({
832
+ posts: t.posts,
833
+ pages: t.pages,
834
+ terms: t.terms,
835
+ settings: t.settings,
836
+ config: t.config,
837
+ scope: { years: [e] }
838
+ });
839
+ }
840
+ /**
841
+ * @license lucide-react v0.460.0 - ISC
842
+ *
843
+ * This source code is licensed under the ISC license.
844
+ * See the LICENSE file in the root directory of this source tree.
845
+ */
846
+ const De = (t) => t.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), ne = (...t) => t.filter((s, e, i) => !!s && s.trim() !== "" && i.indexOf(s) === e).join(" ").trim();
847
+ /**
848
+ * @license lucide-react v0.460.0 - ISC
849
+ *
850
+ * This source code is licensed under the ISC license.
851
+ * See the LICENSE file in the root directory of this source tree.
852
+ */
853
+ var Xe = {
854
+ xmlns: "http://www.w3.org/2000/svg",
855
+ width: 24,
856
+ height: 24,
857
+ viewBox: "0 0 24 24",
858
+ fill: "none",
859
+ stroke: "currentColor",
860
+ strokeWidth: 2,
861
+ strokeLinecap: "round",
862
+ strokeLinejoin: "round"
863
+ };
864
+ /**
865
+ * @license lucide-react v0.460.0 - ISC
866
+ *
867
+ * This source code is licensed under the ISC license.
868
+ * See the LICENSE file in the root directory of this source tree.
869
+ */
870
+ const ke = K(
871
+ ({
872
+ color: t = "currentColor",
873
+ size: s = 24,
874
+ strokeWidth: e = 2,
875
+ absoluteStrokeWidth: i,
876
+ className: r = "",
877
+ children: n,
878
+ iconNode: a,
879
+ ...o
880
+ }, l) => G(
881
+ "svg",
882
+ {
883
+ ref: l,
884
+ ...Xe,
885
+ width: s,
886
+ height: s,
887
+ stroke: t,
888
+ strokeWidth: i ? Number(e) * 24 / Number(s) : e,
889
+ className: ne("lucide", r),
890
+ ...o
891
+ },
892
+ [
893
+ ...a.map(([p, g]) => G(p, g)),
894
+ ...Array.isArray(n) ? n : [n]
895
+ ]
896
+ )
897
+ );
898
+ /**
899
+ * @license lucide-react v0.460.0 - ISC
900
+ *
901
+ * This source code is licensed under the ISC license.
902
+ * See the LICENSE file in the root directory of this source tree.
903
+ */
904
+ const P = (t, s) => {
905
+ const e = K(
906
+ ({ className: i, ...r }, n) => G(ke, {
907
+ ref: n,
908
+ iconNode: s,
909
+ className: ne(`lucide-${De(t)}`, i),
910
+ ...r
911
+ })
912
+ );
913
+ return e.displayName = `${t}`, e;
914
+ };
915
+ /**
916
+ * @license lucide-react v0.460.0 - ISC
917
+ *
918
+ * This source code is licensed under the ISC license.
919
+ * See the LICENSE file in the root directory of this source tree.
920
+ */
921
+ const Pe = P("FileCode2", [
922
+ ["path", { d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4", key: "1pf5j1" }],
923
+ ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
924
+ ["path", { d: "m5 12-3 3 3 3", key: "oke12k" }],
925
+ ["path", { d: "m9 18 3-3-3-3", key: "112psh" }]
926
+ ]);
927
+ /**
928
+ * @license lucide-react v0.460.0 - ISC
929
+ *
930
+ * This source code is licensed under the ISC license.
931
+ * See the LICENSE file in the root directory of this source tree.
932
+ */
933
+ const D = P("LoaderCircle", [
934
+ ["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
935
+ ]);
936
+ /**
937
+ * @license lucide-react v0.460.0 - ISC
938
+ *
939
+ * This source code is licensed under the ISC license.
940
+ * See the LICENSE file in the root directory of this source tree.
941
+ */
942
+ const $e = P("RefreshCw", [
943
+ ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
944
+ ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
945
+ ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
946
+ ["path", { d: "M8 16H3v5", key: "1cv678" }]
947
+ ]);
948
+ /**
949
+ * @license lucide-react v0.460.0 - ISC
950
+ *
951
+ * This source code is licensed under the ISC license.
952
+ * See the LICENSE file in the root directory of this source tree.
953
+ */
954
+ const J = P("Save", [
955
+ [
956
+ "path",
957
+ {
958
+ d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",
959
+ key: "1c8476"
960
+ }
961
+ ],
962
+ ["path", { d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7", key: "1ydtos" }],
963
+ ["path", { d: "M7 3v4a1 1 0 0 0 1 1h7", key: "t51u73" }]
964
+ ]);
965
+ function Ee({ config: t, save: s }) {
966
+ const { t: e } = ue("flexweg-sitemaps"), { settings: i, terms: r } = ce(), [n, a] = C(t);
967
+ me(() => a(t), [t]);
968
+ const [o, l] = C(!1), [p, g] = C(!1), [m, w] = C(!1), [S, N] = C(!1);
969
+ function T(c) {
970
+ a((E) => ({ ...E, ...c }));
971
+ }
972
+ async function y() {
973
+ l(!0);
974
+ try {
975
+ await s(n), L.success(e("saved"));
976
+ } finally {
977
+ l(!1);
978
+ }
979
+ }
980
+ async function h() {
981
+ if (!i.baseUrl) {
982
+ L.error(e("baseUrlMissing"));
983
+ return;
984
+ }
985
+ g(!0);
986
+ try {
987
+ await s(n), await H({
988
+ config: n,
989
+ baseUrl: i.baseUrl,
990
+ discourageIndexing: i.discourageIndexing === !0
991
+ }), L.success(e("robots.saved"));
992
+ } finally {
993
+ g(!1);
994
+ }
995
+ }
996
+ async function f() {
997
+ if (!i.baseUrl) {
998
+ L.error(e("baseUrlMissing"));
999
+ return;
1000
+ }
1001
+ w(!0);
1002
+ try {
1003
+ await s(n);
1004
+ const c = await B({ settings: i, config: n }), [E, oe] = await Promise.all([
1005
+ W({ type: "post" }),
1006
+ W({ type: "page" })
1007
+ ]), le = await q({
1008
+ posts: E,
1009
+ pages: oe,
1010
+ terms: r,
1011
+ settings: i,
1012
+ config: n
1013
+ });
1014
+ await H({
1015
+ config: n,
1016
+ baseUrl: i.baseUrl,
1017
+ discourageIndexing: i.discourageIndexing === !0
1018
+ }), L.success(
1019
+ e("uploaded", { count: c.uploaded.length + le.uploaded.length + 1 })
1020
+ );
1021
+ } catch (c) {
1022
+ console.error("[flexweg-sitemaps] regeneration failed:", c), L.error(e("regenerateFailed"));
1023
+ } finally {
1024
+ w(!1);
1025
+ }
1026
+ }
1027
+ async function b() {
1028
+ if (!i.baseUrl) {
1029
+ L.error(e("baseUrlMissing"));
1030
+ return;
1031
+ }
1032
+ N(!0);
1033
+ try {
1034
+ await s(n);
1035
+ const c = await B({ settings: i, config: n });
1036
+ L.success(e("xsl.uploaded", { count: c.uploaded.length }));
1037
+ } catch (c) {
1038
+ console.error("[flexweg-sitemaps] xsl upload failed:", c), L.error(e("xsl.failed"));
1039
+ } finally {
1040
+ N(!1);
1041
+ }
1042
+ }
1043
+ function $() {
1044
+ T({ robotsTxt: j(i.baseUrl, n.newsEnabled) });
1045
+ }
1046
+ return /* @__PURE__ */ u("div", { className: "space-y-6", children: [
1047
+ /* @__PURE__ */ d("p", { className: "text-sm text-surface-600 dark:text-surface-300", children: e("description") }),
1048
+ /* @__PURE__ */ u("section", { className: "card p-4 space-y-4", children: [
1049
+ /* @__PURE__ */ d("h2", { className: "font-semibold", children: e("sections.general") }),
1050
+ /* @__PURE__ */ u("div", { children: [
1051
+ /* @__PURE__ */ d("label", { className: "label", children: e("contentTypes.label") }),
1052
+ /* @__PURE__ */ u(
1053
+ "select",
1054
+ {
1055
+ className: "input max-w-xs",
1056
+ value: n.contentTypes,
1057
+ onChange: (c) => T({ contentTypes: c.target.value }),
1058
+ children: [
1059
+ /* @__PURE__ */ d("option", { value: "posts", children: e("contentTypes.posts") }),
1060
+ /* @__PURE__ */ d("option", { value: "posts-pages", children: e("contentTypes.postsPages") })
1061
+ ]
1062
+ }
1063
+ )
1064
+ ] }),
1065
+ /* @__PURE__ */ u("div", { children: [
1066
+ /* @__PURE__ */ u("label", { className: "flex items-center gap-2", children: [
1067
+ /* @__PURE__ */ d(
1068
+ "input",
1069
+ {
1070
+ type: "checkbox",
1071
+ checked: n.newsEnabled,
1072
+ onChange: (c) => T({ newsEnabled: c.target.checked })
1073
+ }
1074
+ ),
1075
+ /* @__PURE__ */ d("span", { className: "text-sm font-medium", children: e("news.enabled") })
1076
+ ] }),
1077
+ /* @__PURE__ */ d("p", { className: "text-xs text-surface-500 mt-1 dark:text-surface-400", children: e("news.enabledHelp") })
1078
+ ] }),
1079
+ n.newsEnabled && /* @__PURE__ */ u("div", { children: [
1080
+ /* @__PURE__ */ d("label", { className: "label", children: e("news.windowDays") }),
1081
+ /* @__PURE__ */ d(
1082
+ "input",
1083
+ {
1084
+ className: "input max-w-xs",
1085
+ type: "number",
1086
+ min: 1,
1087
+ max: 30,
1088
+ value: n.newsWindowDays,
1089
+ onChange: (c) => T({
1090
+ newsWindowDays: Math.max(1, Math.min(30, Number.parseInt(c.target.value, 10) || 2))
1091
+ })
1092
+ }
1093
+ ),
1094
+ /* @__PURE__ */ d("p", { className: "text-xs text-surface-500 mt-1 dark:text-surface-400", children: e("news.windowDaysHelp") })
1095
+ ] }),
1096
+ /* @__PURE__ */ u(
1097
+ "button",
1098
+ {
1099
+ type: "button",
1100
+ className: "btn-primary",
1101
+ onClick: y,
1102
+ disabled: o,
1103
+ children: [
1104
+ /* @__PURE__ */ d(D, { className: o ? "h-4 w-4 animate-spin" : "hidden" }),
1105
+ /* @__PURE__ */ d(J, { className: o ? "hidden" : "h-4 w-4" }),
1106
+ /* @__PURE__ */ d("span", { children: e(o ? "robots.saving" : "saveSettings") })
1107
+ ]
1108
+ }
1109
+ )
1110
+ ] }),
1111
+ /* @__PURE__ */ u("section", { className: "card p-4 space-y-3", children: [
1112
+ /* @__PURE__ */ u("div", { className: "flex items-center justify-between gap-3", children: [
1113
+ /* @__PURE__ */ d("h2", { className: "font-semibold", children: e("sections.robots") }),
1114
+ /* @__PURE__ */ d("button", { type: "button", className: "btn-ghost", onClick: $, children: e("robots.resetDefault") })
1115
+ ] }),
1116
+ /* @__PURE__ */ d("p", { className: "text-xs text-surface-500 dark:text-surface-400", children: e("robots.help") }),
1117
+ /* @__PURE__ */ d(
1118
+ "textarea",
1119
+ {
1120
+ className: "input font-mono text-xs min-h-[180px]",
1121
+ value: n.robotsTxt,
1122
+ onChange: (c) => T({ robotsTxt: c.target.value }),
1123
+ placeholder: j(i.baseUrl, n.newsEnabled)
1124
+ }
1125
+ ),
1126
+ /* @__PURE__ */ u(
1127
+ "button",
1128
+ {
1129
+ type: "button",
1130
+ className: "btn-primary",
1131
+ onClick: h,
1132
+ disabled: p,
1133
+ children: [
1134
+ /* @__PURE__ */ d(D, { className: p ? "h-4 w-4 animate-spin" : "hidden" }),
1135
+ /* @__PURE__ */ d(J, { className: p ? "hidden" : "h-4 w-4" }),
1136
+ /* @__PURE__ */ d("span", { children: e(p ? "robots.saving" : "robots.saveAndRegenerate") })
1137
+ ]
1138
+ }
1139
+ )
1140
+ ] }),
1141
+ /* @__PURE__ */ u("section", { className: "card p-4 space-y-3", children: [
1142
+ /* @__PURE__ */ d("h2", { className: "font-semibold", children: e("sections.actions") }),
1143
+ /* @__PURE__ */ d("p", { className: "text-xs text-surface-500 dark:text-surface-400", children: e("xsl.help") }),
1144
+ /* @__PURE__ */ u("div", { className: "flex flex-wrap gap-2", children: [
1145
+ /* @__PURE__ */ d(
1146
+ "button",
1147
+ {
1148
+ type: "button",
1149
+ className: "btn-ghost",
1150
+ onClick: b,
1151
+ disabled: S,
1152
+ children: /* @__PURE__ */ u("span", { className: "inline-flex items-center justify-center gap-1.5", children: [
1153
+ /* @__PURE__ */ d(D, { className: "h-4 w-4 animate-spin " + (S ? "" : "hidden") }),
1154
+ /* @__PURE__ */ d(Pe, { className: "h-4 w-4 " + (S ? "hidden" : "") }),
1155
+ /* @__PURE__ */ d("span", { children: e(S ? "xsl.uploading" : "xsl.upload") })
1156
+ ] })
1157
+ }
1158
+ ),
1159
+ /* @__PURE__ */ d(
1160
+ "button",
1161
+ {
1162
+ type: "button",
1163
+ className: "btn-secondary",
1164
+ onClick: f,
1165
+ disabled: m,
1166
+ children: /* @__PURE__ */ u("span", { className: "inline-flex items-center justify-center gap-1.5", children: [
1167
+ /* @__PURE__ */ d(D, { className: "h-4 w-4 animate-spin " + (m ? "" : "hidden") }),
1168
+ /* @__PURE__ */ d($e, { className: "h-4 w-4 " + (m ? "hidden" : "") }),
1169
+ /* @__PURE__ */ d("span", { children: e(m ? "forceRegenerating" : "forceRegenerate") })
1170
+ ] })
1171
+ }
1172
+ )
1173
+ ] })
1174
+ ] })
1175
+ ] });
1176
+ }
1177
+ const Ie = `# Flexweg Sitemaps
1178
+
1179
+ Generates and maintains XML sitemaps for search engine discovery. Also produces a customizable \`robots.txt\` so crawlers know what they can index.
1180
+
1181
+ ## What it does
1182
+
1183
+ Every time a post or page is published, unpublished or deleted, the plugin **incrementally** regenerates only the sitemap files affected by the change — never the whole catalog. Output files (uploaded to your Flexweg site, all sitemap XML/XSL files grouped under \`/sitemaps/\` for tidiness; \`robots.txt\` stays at the site root because that's where crawlers expect it):
1184
+
1185
+ - **\`sitemaps/sitemap-<year>.xml\`** — one per year, listing every published URL whose \`createdAt\` falls in that year.
1186
+ - **\`sitemaps/sitemap-index.xml\`** — top-level index referencing every yearly sitemap. This is the URL you submit to Google Search Console.
1187
+ - **\`sitemaps/sitemap-news.xml\`** — optional Google News sitemap, scoped to posts published in a configurable rolling window (default: last 2 days).
1188
+ - **\`robots.txt\`** (at site root) — editable text file pointing crawlers at the sitemap index.
1189
+ - **\`sitemaps/sitemap.xsl\` / \`sitemaps/sitemap-news.xsl\`** — XSLT stylesheets that turn the raw XML into a styled HTML table when a human opens the URL directly. Invisible to crawlers.
1190
+
1191
+ When a yearly sitemap empties out (every post in that year gets deleted or unpublished), the file is removed from your Flexweg site so the index never points at a 404.
1192
+
1193
+ ### Migration from the previous root-level layout
1194
+
1195
+ Earlier versions of this plugin uploaded every sitemap file to the site root (\`sitemap-index.xml\`, \`sitemap-<year>.xml\`, …). On the next **Force regenerate** the plugin sweeps those legacy paths and deletes them silently — old files are removed, new ones land under \`/sitemaps/\`. The sweep is idempotent (404 is treated as already-gone). After migration, re-submit \`https://your-site.com/sitemaps/sitemap-index.xml\` in Google Search Console; the old URL will deindex naturally as Google sees the 404.
1196
+
1197
+ ## Settings
1198
+
1199
+ Reachable via **Plugins → Configure** when the plugin is enabled.
1200
+
1201
+ - **Content scope** — choose between *Posts only* (default) or *Posts and pages*. Pages-as-content sites usually want both; blogs typically just posts.
1202
+ - **News sitemap** — enable / disable. When enabled, set the rolling window (in days). A 2–3 day window matches Google News' own crawl horizon.
1203
+ - **\`robots.txt\`** — free-form text editor with an *Insert default* button that generates a sensible starting point referencing your sitemap index.
1204
+ - **Upload stylesheets** — manual button to push the XSL files. Run this once per site setup; the lifecycle hooks deliberately don't re-upload XSL on every publish to save bandwidth.
1205
+ - **Force regenerate** — rebuilds every sitemap, the index and the robots.txt from scratch. Useful after a bulk content move, a base URL change, or when the auto-incremental state drifts.
1206
+
1207
+ ## Requirements
1208
+
1209
+ The plugin needs \`Settings → Site → Public site URL\` to be set — sitemap entries require an absolute origin. With the field empty, the plugin no-ops silently rather than upload sitemaps with relative URLs.
1210
+
1211
+ ## When to disable it
1212
+
1213
+ Disable if you maintain sitemaps externally (e.g. a separate static-site generator running alongside Flexweg) or if your site is private and you don't want it indexed. Disabling stops new generation but does **not** delete already-uploaded sitemap files — clean those up by hand on Flexweg if needed.
1214
+ `;
1215
+ function ie(t) {
1216
+ var e;
1217
+ const s = (e = t.settings.pluginConfigs) == null ? void 0 : e["flexweg-sitemaps"];
1218
+ return { ...te, ...s ?? {} };
1219
+ }
1220
+ async function I(t, s) {
1221
+ if (!s.settings.baseUrl) {
1222
+ console.warn("[flexweg-sitemaps] skipping regeneration — baseUrl not configured");
1223
+ return;
1224
+ }
1225
+ try {
1226
+ await Me({
1227
+ post: t,
1228
+ posts: s.posts,
1229
+ pages: s.pages,
1230
+ terms: s.terms,
1231
+ settings: s.settings,
1232
+ config: ie(s)
1233
+ });
1234
+ } catch (e) {
1235
+ console.error("[flexweg-sitemaps] regeneration failed:", e);
1236
+ }
1237
+ }
1238
+ const He = {
1239
+ id: "flexweg-sitemaps",
1240
+ name: "Flexweg Sitemaps",
1241
+ version: "1.0.0",
1242
+ author: "Flexweg",
1243
+ description: "Generates sitemap-index.xml, per-year sitemaps, an optional Google News sitemap, and a robots.txt that points to them.",
1244
+ readme: Ie,
1245
+ i18n: { en: ge, fr: he, de: fe, es: we, nl: be, pt: xe, ko: ye },
1246
+ settings: {
1247
+ navLabelKey: "title",
1248
+ defaultConfig: te,
1249
+ component: Ee
1250
+ },
1251
+ register(t) {
1252
+ t.addAction("publish.complete", async (s, e) => {
1253
+ await I(s, e);
1254
+ }), t.addAction("post.unpublished", async (s, e) => {
1255
+ await I(s, e);
1256
+ }), t.addAction("post.deleted", async (s, e) => {
1257
+ await I(s, e);
1258
+ }), t.registerRegenerationTarget({
1259
+ id: "flexweg-sitemaps",
1260
+ labelKey: "regenerationTarget.label",
1261
+ descriptionKey: "regenerationTarget.description",
1262
+ priority: 200,
1263
+ run: async (s, e) => {
1264
+ if (!s.settings.baseUrl) {
1265
+ e({ level: "warn", message: "[flexweg-sitemaps] skipped — site URL not set." });
1266
+ return;
1267
+ }
1268
+ const i = ie(s);
1269
+ e({ level: "info", message: "Regenerating sitemap stylesheets…" });
1270
+ const r = await B({ settings: s.settings, config: i });
1271
+ e({ level: "info", message: "Regenerating sitemaps…" });
1272
+ const n = await q({
1273
+ posts: s.posts,
1274
+ pages: s.pages,
1275
+ terms: s.terms,
1276
+ settings: s.settings,
1277
+ config: i
1278
+ });
1279
+ e({ level: "info", message: "Regenerating robots.txt…" }), await H({
1280
+ config: i,
1281
+ baseUrl: s.settings.baseUrl,
1282
+ discourageIndexing: s.settings.discourageIndexing === !0
1283
+ }), e({
1284
+ level: "success",
1285
+ message: `Sitemaps: ${r.uploaded.length + n.uploaded.length + 1} file(s) uploaded.`
1286
+ });
1287
+ }
1288
+ });
1289
+ }
1290
+ };
1291
+ export {
1292
+ He as manifest
1293
+ };