euparliamentmonitor 0.8.4

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 (276) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1005 -0
  3. package/SECURITY.md +151 -0
  4. package/package.json +131 -0
  5. package/scripts/constants/committee-indicator-map.d.ts +199 -0
  6. package/scripts/constants/committee-indicator-map.d.ts.map +1 -0
  7. package/scripts/constants/committee-indicator-map.js +1224 -0
  8. package/scripts/constants/committee-indicator-map.js.map +1 -0
  9. package/scripts/constants/config.d.ts +38 -0
  10. package/scripts/constants/config.d.ts.map +1 -0
  11. package/scripts/constants/config.js +66 -0
  12. package/scripts/constants/config.js.map +1 -0
  13. package/scripts/constants/language-articles.d.ts +84 -0
  14. package/scripts/constants/language-articles.d.ts.map +1 -0
  15. package/scripts/constants/language-articles.js +6771 -0
  16. package/scripts/constants/language-articles.js.map +1 -0
  17. package/scripts/constants/language-core.d.ts +38 -0
  18. package/scripts/constants/language-core.d.ts.map +1 -0
  19. package/scripts/constants/language-core.js +90 -0
  20. package/scripts/constants/language-core.js.map +1 -0
  21. package/scripts/constants/language-ui.d.ts +82 -0
  22. package/scripts/constants/language-ui.d.ts.map +1 -0
  23. package/scripts/constants/language-ui.js +889 -0
  24. package/scripts/constants/language-ui.js.map +1 -0
  25. package/scripts/constants/languages.d.ts +14 -0
  26. package/scripts/constants/languages.d.ts.map +1 -0
  27. package/scripts/constants/languages.js +15 -0
  28. package/scripts/constants/languages.js.map +1 -0
  29. package/scripts/generators/analysis-builders.d.ts +266 -0
  30. package/scripts/generators/analysis-builders.d.ts.map +1 -0
  31. package/scripts/generators/analysis-builders.js +2903 -0
  32. package/scripts/generators/analysis-builders.js.map +1 -0
  33. package/scripts/generators/breaking-content.d.ts +45 -0
  34. package/scripts/generators/breaking-content.d.ts.map +1 -0
  35. package/scripts/generators/breaking-content.js +530 -0
  36. package/scripts/generators/breaking-content.js.map +1 -0
  37. package/scripts/generators/committee-helpers.d.ts +54 -0
  38. package/scripts/generators/committee-helpers.d.ts.map +1 -0
  39. package/scripts/generators/committee-helpers.js +154 -0
  40. package/scripts/generators/committee-helpers.js.map +1 -0
  41. package/scripts/generators/dashboard-content.d.ts +95 -0
  42. package/scripts/generators/dashboard-content.d.ts.map +1 -0
  43. package/scripts/generators/dashboard-content.js +630 -0
  44. package/scripts/generators/dashboard-content.js.map +1 -0
  45. package/scripts/generators/deep-analysis-content.d.ts +23 -0
  46. package/scripts/generators/deep-analysis-content.d.ts.map +1 -0
  47. package/scripts/generators/deep-analysis-content.js +831 -0
  48. package/scripts/generators/deep-analysis-content.js.map +1 -0
  49. package/scripts/generators/mindmap-content.d.ts +55 -0
  50. package/scripts/generators/mindmap-content.d.ts.map +1 -0
  51. package/scripts/generators/mindmap-content.js +512 -0
  52. package/scripts/generators/mindmap-content.js.map +1 -0
  53. package/scripts/generators/motions-content.d.ts +50 -0
  54. package/scripts/generators/motions-content.d.ts.map +1 -0
  55. package/scripts/generators/motions-content.js +391 -0
  56. package/scripts/generators/motions-content.js.map +1 -0
  57. package/scripts/generators/news-enhanced.d.ts +14 -0
  58. package/scripts/generators/news-enhanced.d.ts.map +1 -0
  59. package/scripts/generators/news-enhanced.js +169 -0
  60. package/scripts/generators/news-enhanced.js.map +1 -0
  61. package/scripts/generators/news-indexes.d.ts +31 -0
  62. package/scripts/generators/news-indexes.d.ts.map +1 -0
  63. package/scripts/generators/news-indexes.js +410 -0
  64. package/scripts/generators/news-indexes.js.map +1 -0
  65. package/scripts/generators/pipeline/fetch-stage.d.ts +352 -0
  66. package/scripts/generators/pipeline/fetch-stage.d.ts.map +1 -0
  67. package/scripts/generators/pipeline/fetch-stage.js +1522 -0
  68. package/scripts/generators/pipeline/fetch-stage.js.map +1 -0
  69. package/scripts/generators/pipeline/generate-stage.d.ts +43 -0
  70. package/scripts/generators/pipeline/generate-stage.d.ts.map +1 -0
  71. package/scripts/generators/pipeline/generate-stage.js +204 -0
  72. package/scripts/generators/pipeline/generate-stage.js.map +1 -0
  73. package/scripts/generators/pipeline/output-stage.d.ts +48 -0
  74. package/scripts/generators/pipeline/output-stage.d.ts.map +1 -0
  75. package/scripts/generators/pipeline/output-stage.js +145 -0
  76. package/scripts/generators/pipeline/output-stage.js.map +1 -0
  77. package/scripts/generators/pipeline/transform-stage.d.ts +57 -0
  78. package/scripts/generators/pipeline/transform-stage.d.ts.map +1 -0
  79. package/scripts/generators/pipeline/transform-stage.js +111 -0
  80. package/scripts/generators/pipeline/transform-stage.js.map +1 -0
  81. package/scripts/generators/propositions-content.d.ts +29 -0
  82. package/scripts/generators/propositions-content.d.ts.map +1 -0
  83. package/scripts/generators/propositions-content.js +90 -0
  84. package/scripts/generators/propositions-content.js.map +1 -0
  85. package/scripts/generators/sankey-content.d.ts +45 -0
  86. package/scripts/generators/sankey-content.d.ts.map +1 -0
  87. package/scripts/generators/sankey-content.js +227 -0
  88. package/scripts/generators/sankey-content.js.map +1 -0
  89. package/scripts/generators/sitemap.d.ts +66 -0
  90. package/scripts/generators/sitemap.d.ts.map +1 -0
  91. package/scripts/generators/sitemap.js +562 -0
  92. package/scripts/generators/sitemap.js.map +1 -0
  93. package/scripts/generators/strategies/article-strategy.d.ts +146 -0
  94. package/scripts/generators/strategies/article-strategy.d.ts.map +1 -0
  95. package/scripts/generators/strategies/article-strategy.js +4 -0
  96. package/scripts/generators/strategies/article-strategy.js.map +1 -0
  97. package/scripts/generators/strategies/breaking-news-strategy.d.ts +64 -0
  98. package/scripts/generators/strategies/breaking-news-strategy.d.ts.map +1 -0
  99. package/scripts/generators/strategies/breaking-news-strategy.js +246 -0
  100. package/scripts/generators/strategies/breaking-news-strategy.js.map +1 -0
  101. package/scripts/generators/strategies/committee-reports-strategy.d.ts +93 -0
  102. package/scripts/generators/strategies/committee-reports-strategy.d.ts.map +1 -0
  103. package/scripts/generators/strategies/committee-reports-strategy.js +447 -0
  104. package/scripts/generators/strategies/committee-reports-strategy.js.map +1 -0
  105. package/scripts/generators/strategies/month-ahead-strategy.d.ts +60 -0
  106. package/scripts/generators/strategies/month-ahead-strategy.d.ts.map +1 -0
  107. package/scripts/generators/strategies/month-ahead-strategy.js +175 -0
  108. package/scripts/generators/strategies/month-ahead-strategy.js.map +1 -0
  109. package/scripts/generators/strategies/monthly-review-strategy.d.ts +66 -0
  110. package/scripts/generators/strategies/monthly-review-strategy.d.ts.map +1 -0
  111. package/scripts/generators/strategies/monthly-review-strategy.js +204 -0
  112. package/scripts/generators/strategies/monthly-review-strategy.js.map +1 -0
  113. package/scripts/generators/strategies/motions-strategy.d.ts +61 -0
  114. package/scripts/generators/strategies/motions-strategy.d.ts.map +1 -0
  115. package/scripts/generators/strategies/motions-strategy.js +215 -0
  116. package/scripts/generators/strategies/motions-strategy.js.map +1 -0
  117. package/scripts/generators/strategies/propositions-strategy.d.ts +60 -0
  118. package/scripts/generators/strategies/propositions-strategy.d.ts.map +1 -0
  119. package/scripts/generators/strategies/propositions-strategy.js +257 -0
  120. package/scripts/generators/strategies/propositions-strategy.js.map +1 -0
  121. package/scripts/generators/strategies/week-ahead-strategy.d.ts +57 -0
  122. package/scripts/generators/strategies/week-ahead-strategy.d.ts.map +1 -0
  123. package/scripts/generators/strategies/week-ahead-strategy.js +178 -0
  124. package/scripts/generators/strategies/week-ahead-strategy.js.map +1 -0
  125. package/scripts/generators/strategies/weekly-review-strategy.d.ts +63 -0
  126. package/scripts/generators/strategies/weekly-review-strategy.d.ts.map +1 -0
  127. package/scripts/generators/strategies/weekly-review-strategy.js +211 -0
  128. package/scripts/generators/strategies/weekly-review-strategy.js.map +1 -0
  129. package/scripts/generators/swot-content.d.ts +42 -0
  130. package/scripts/generators/swot-content.d.ts.map +1 -0
  131. package/scripts/generators/swot-content.js +366 -0
  132. package/scripts/generators/swot-content.js.map +1 -0
  133. package/scripts/generators/week-ahead-content.d.ts +103 -0
  134. package/scripts/generators/week-ahead-content.d.ts.map +1 -0
  135. package/scripts/generators/week-ahead-content.js +610 -0
  136. package/scripts/generators/week-ahead-content.js.map +1 -0
  137. package/scripts/index.d.ts +40 -0
  138. package/scripts/index.d.ts.map +1 -0
  139. package/scripts/index.js +53 -0
  140. package/scripts/index.js.map +1 -0
  141. package/scripts/mcp/ep-mcp-client.d.ts +471 -0
  142. package/scripts/mcp/ep-mcp-client.d.ts.map +1 -0
  143. package/scripts/mcp/ep-mcp-client.js +734 -0
  144. package/scripts/mcp/ep-mcp-client.js.map +1 -0
  145. package/scripts/mcp/mcp-connection.d.ts +264 -0
  146. package/scripts/mcp/mcp-connection.d.ts.map +1 -0
  147. package/scripts/mcp/mcp-connection.js +790 -0
  148. package/scripts/mcp/mcp-connection.js.map +1 -0
  149. package/scripts/mcp/mcp-health.d.ts +75 -0
  150. package/scripts/mcp/mcp-health.d.ts.map +1 -0
  151. package/scripts/mcp/mcp-health.js +78 -0
  152. package/scripts/mcp/mcp-health.js.map +1 -0
  153. package/scripts/mcp/mcp-retry.d.ts +94 -0
  154. package/scripts/mcp/mcp-retry.d.ts.map +1 -0
  155. package/scripts/mcp/mcp-retry.js +127 -0
  156. package/scripts/mcp/mcp-retry.js.map +1 -0
  157. package/scripts/mcp/wb-mcp-client.d.ts +38 -0
  158. package/scripts/mcp/wb-mcp-client.d.ts.map +1 -0
  159. package/scripts/mcp/wb-mcp-client.js +112 -0
  160. package/scripts/mcp/wb-mcp-client.js.map +1 -0
  161. package/scripts/templates/article-template.d.ts +9 -0
  162. package/scripts/templates/article-template.d.ts.map +1 -0
  163. package/scripts/templates/article-template.js +378 -0
  164. package/scripts/templates/article-template.js.map +1 -0
  165. package/scripts/templates/section-builders.d.ts +28 -0
  166. package/scripts/templates/section-builders.d.ts.map +1 -0
  167. package/scripts/templates/section-builders.js +142 -0
  168. package/scripts/templates/section-builders.js.map +1 -0
  169. package/scripts/types/analysis.d.ts +115 -0
  170. package/scripts/types/analysis.d.ts.map +1 -0
  171. package/scripts/types/analysis.js +4 -0
  172. package/scripts/types/analysis.js.map +1 -0
  173. package/scripts/types/common.d.ts +584 -0
  174. package/scripts/types/common.d.ts.map +1 -0
  175. package/scripts/types/common.js +96 -0
  176. package/scripts/types/common.js.map +1 -0
  177. package/scripts/types/generation.d.ts +104 -0
  178. package/scripts/types/generation.d.ts.map +1 -0
  179. package/scripts/types/generation.js +4 -0
  180. package/scripts/types/generation.js.map +1 -0
  181. package/scripts/types/index.d.ts +24 -0
  182. package/scripts/types/index.d.ts.map +1 -0
  183. package/scripts/types/index.js +16 -0
  184. package/scripts/types/index.js.map +1 -0
  185. package/scripts/types/intelligence.d.ts +129 -0
  186. package/scripts/types/intelligence.d.ts.map +1 -0
  187. package/scripts/types/intelligence.js +4 -0
  188. package/scripts/types/intelligence.js.map +1 -0
  189. package/scripts/types/mcp.d.ts +418 -0
  190. package/scripts/types/mcp.d.ts.map +1 -0
  191. package/scripts/types/mcp.js +4 -0
  192. package/scripts/types/mcp.js.map +1 -0
  193. package/scripts/types/parliament.d.ts +388 -0
  194. package/scripts/types/parliament.d.ts.map +1 -0
  195. package/scripts/types/parliament.js +4 -0
  196. package/scripts/types/parliament.js.map +1 -0
  197. package/scripts/types/quality.d.ts +114 -0
  198. package/scripts/types/quality.d.ts.map +1 -0
  199. package/scripts/types/quality.js +4 -0
  200. package/scripts/types/quality.js.map +1 -0
  201. package/scripts/types/stakeholder.d.ts +88 -0
  202. package/scripts/types/stakeholder.d.ts.map +1 -0
  203. package/scripts/types/stakeholder.js +16 -0
  204. package/scripts/types/stakeholder.js.map +1 -0
  205. package/scripts/types/visualization.d.ts +708 -0
  206. package/scripts/types/visualization.d.ts.map +1 -0
  207. package/scripts/types/visualization.js +4 -0
  208. package/scripts/types/visualization.js.map +1 -0
  209. package/scripts/types/world-bank.d.ts +85 -0
  210. package/scripts/types/world-bank.d.ts.map +1 -0
  211. package/scripts/types/world-bank.js +4 -0
  212. package/scripts/types/world-bank.js.map +1 -0
  213. package/scripts/utils/article-category.d.ts +18 -0
  214. package/scripts/utils/article-category.d.ts.map +1 -0
  215. package/scripts/utils/article-category.js +49 -0
  216. package/scripts/utils/article-category.js.map +1 -0
  217. package/scripts/utils/article-quality-scorer.d.ts +87 -0
  218. package/scripts/utils/article-quality-scorer.d.ts.map +1 -0
  219. package/scripts/utils/article-quality-scorer.js +1048 -0
  220. package/scripts/utils/article-quality-scorer.js.map +1 -0
  221. package/scripts/utils/content-metadata.d.ts +34 -0
  222. package/scripts/utils/content-metadata.d.ts.map +1 -0
  223. package/scripts/utils/content-metadata.js +249 -0
  224. package/scripts/utils/content-metadata.js.map +1 -0
  225. package/scripts/utils/content-validator.d.ts +94 -0
  226. package/scripts/utils/content-validator.d.ts.map +1 -0
  227. package/scripts/utils/content-validator.js +489 -0
  228. package/scripts/utils/content-validator.js.map +1 -0
  229. package/scripts/utils/copy-test-reports.d.ts +9 -0
  230. package/scripts/utils/copy-test-reports.d.ts.map +1 -0
  231. package/scripts/utils/copy-test-reports.js +508 -0
  232. package/scripts/utils/copy-test-reports.js.map +1 -0
  233. package/scripts/utils/file-utils.d.ts +144 -0
  234. package/scripts/utils/file-utils.d.ts.map +1 -0
  235. package/scripts/utils/file-utils.js +374 -0
  236. package/scripts/utils/file-utils.js.map +1 -0
  237. package/scripts/utils/fix-articles.d.ts +27 -0
  238. package/scripts/utils/fix-articles.d.ts.map +1 -0
  239. package/scripts/utils/fix-articles.js +510 -0
  240. package/scripts/utils/fix-articles.js.map +1 -0
  241. package/scripts/utils/generate-docs-index.d.ts +8 -0
  242. package/scripts/utils/generate-docs-index.d.ts.map +1 -0
  243. package/scripts/utils/generate-docs-index.js +275 -0
  244. package/scripts/utils/generate-docs-index.js.map +1 -0
  245. package/scripts/utils/html-sanitize.d.ts +18 -0
  246. package/scripts/utils/html-sanitize.d.ts.map +1 -0
  247. package/scripts/utils/html-sanitize.js +57 -0
  248. package/scripts/utils/html-sanitize.js.map +1 -0
  249. package/scripts/utils/intelligence-analysis.d.ts +173 -0
  250. package/scripts/utils/intelligence-analysis.d.ts.map +1 -0
  251. package/scripts/utils/intelligence-analysis.js +936 -0
  252. package/scripts/utils/intelligence-analysis.js.map +1 -0
  253. package/scripts/utils/intelligence-index.d.ts +126 -0
  254. package/scripts/utils/intelligence-index.d.ts.map +1 -0
  255. package/scripts/utils/intelligence-index.js +731 -0
  256. package/scripts/utils/intelligence-index.js.map +1 -0
  257. package/scripts/utils/metadata-utils.d.ts +14 -0
  258. package/scripts/utils/metadata-utils.d.ts.map +1 -0
  259. package/scripts/utils/metadata-utils.js +18 -0
  260. package/scripts/utils/metadata-utils.js.map +1 -0
  261. package/scripts/utils/news-metadata.d.ts +47 -0
  262. package/scripts/utils/news-metadata.d.ts.map +1 -0
  263. package/scripts/utils/news-metadata.js +259 -0
  264. package/scripts/utils/news-metadata.js.map +1 -0
  265. package/scripts/utils/validate-articles.d.ts +2 -0
  266. package/scripts/utils/validate-articles.d.ts.map +1 -0
  267. package/scripts/utils/validate-articles.js +284 -0
  268. package/scripts/utils/validate-articles.js.map +1 -0
  269. package/scripts/utils/validate-ep-api.d.ts +51 -0
  270. package/scripts/utils/validate-ep-api.d.ts.map +1 -0
  271. package/scripts/utils/validate-ep-api.js +160 -0
  272. package/scripts/utils/validate-ep-api.js.map +1 -0
  273. package/scripts/utils/world-bank-data.d.ts +84 -0
  274. package/scripts/utils/world-bank-data.d.ts.map +1 -0
  275. package/scripts/utils/world-bank-data.js +311 -0
  276. package/scripts/utils/world-bank-data.js.map +1 -0
@@ -0,0 +1,447 @@
1
+ // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { ArticleCategory } from '../../types/index.js';
4
+ import { COMMITTEE_REPORTS_TITLES, COMMITTEE_ANALYSIS_CONTENT_STRINGS, getLocalizedString, } from '../../constants/languages.js';
5
+ import { computeRollingDateRange, fetchCommitteeData, fetchEPFeedData, } from '../pipeline/fetch-stage.js';
6
+ import { FEATURED_COMMITTEES, isPlaceholderCommitteeData, PLACEHOLDER_CHAIR, PLACEHOLDER_MEMBERS, } from '../committee-helpers.js';
7
+ import { escapeHTML } from '../../utils/file-utils.js';
8
+ import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
9
+ import { buildCommitteeAnalysis, buildCommitteeSwot, buildCommitteeDashboard, buildCommitteeMindmap, } from '../analysis-builders.js';
10
+ import { buildSwotSection } from '../swot-content.js';
11
+ import { buildDashboardSection } from '../dashboard-content.js';
12
+ import { buildIntelligenceMindmapSection } from '../mindmap-content.js';
13
+ import { pl } from '../../utils/metadata-utils.js';
14
+ /** European Parliament home-page URL used as source reference */
15
+ const EP_SOURCE_URL = 'https://www.europarl.europa.eu';
16
+ /** European Parliament display name for source titles and article lede */
17
+ const EP_DISPLAY_NAME = 'European Parliament';
18
+ /** Base keywords shared by all Committee Reports articles */
19
+ const COMMITTEE_REPORTS_BASE_KEYWORDS = ['committee', 'EU Parliament', 'legislation'];
20
+ /** Source reference included in every committee reports article */
21
+ const COMMITTEE_REPORTS_SOURCES = [
22
+ { title: EP_DISPLAY_NAME, url: EP_SOURCE_URL },
23
+ ];
24
+ /**
25
+ * Extract content-aware keywords from committee data and feed data.
26
+ *
27
+ * Includes committee abbreviations, names, document types, and adopted-text
28
+ * themes for richer SEO coverage.
29
+ *
30
+ * @param committeeDataList - Fetched committee data
31
+ * @param feedData - EP feed data (may be undefined)
32
+ * @returns Deduplicated keyword array
33
+ */
34
+ function buildCommitteeKeywords(committeeDataList, feedData) {
35
+ const keywords = [...COMMITTEE_REPORTS_BASE_KEYWORDS];
36
+ // Add committee abbreviations and names
37
+ for (const c of committeeDataList) {
38
+ if (c.abbreviation)
39
+ keywords.push(c.abbreviation);
40
+ if (c.name)
41
+ keywords.push(c.name);
42
+ }
43
+ // Add adopted text themes from feed
44
+ if (feedData?.adoptedTexts) {
45
+ for (const text of feedData.adoptedTexts.slice(0, 5)) {
46
+ if (text.title) {
47
+ const theme = categorizeAdoptedText(text.title);
48
+ if (theme !== 'OTHER')
49
+ keywords.push(theme);
50
+ }
51
+ }
52
+ }
53
+ return [...new Set(keywords)];
54
+ }
55
+ /**
56
+ * Build a content-aware description from committee data.
57
+ * Summarises the number of active committees, document counts, and
58
+ * effectiveness highlights when available.
59
+ *
60
+ * @param committeeDataList - Fetched committee data
61
+ * @param feedData - EP feed data (may be undefined)
62
+ * @returns SEO-friendly description (≤ 200 chars)
63
+ */
64
+ function buildCommitteeDescription(committeeDataList, feedData) {
65
+ const activeCount = committeeDataList.filter((c) => c.chair !== PLACEHOLDER_CHAIR).length;
66
+ const totalDocs = committeeDataList.reduce((sum, c) => sum + c.documents.length, 0);
67
+ const adoptedCount = feedData?.adoptedTexts?.length ?? 0;
68
+ const parts = [];
69
+ if (activeCount > 0)
70
+ parts.push(`${pl(activeCount, 'committee', 'committees')} reporting`);
71
+ if (totalDocs > 0)
72
+ parts.push(pl(totalDocs, 'recent document', 'recent documents'));
73
+ if (adoptedCount > 0)
74
+ parts.push(pl(adoptedCount, 'adopted text', 'adopted texts'));
75
+ const abbrs = committeeDataList
76
+ .filter((c) => c.chair !== PLACEHOLDER_CHAIR)
77
+ .map((c) => c.abbreviation)
78
+ .join(', ');
79
+ if (abbrs)
80
+ parts.push(`covering ${abbrs}`);
81
+ if (parts.length === 0) {
82
+ return 'Analysis of recent legislative output, effectiveness metrics, and key committee activities';
83
+ }
84
+ const desc = `EP committee activity: ${parts.join('; ')}.`;
85
+ return desc.length > 200 ? desc.slice(0, 197) + '...' : desc;
86
+ }
87
+ /**
88
+ * Build a content-aware title suffix from committee data counts.
89
+ *
90
+ * @param committeeDataList - Fetched committee data
91
+ * @param feedData - EP feed data (may be undefined)
92
+ * @returns Short suffix for the title, or empty string
93
+ */
94
+ function buildCommitteeTitleSuffix(committeeDataList, feedData) {
95
+ const activeCount = committeeDataList.filter((c) => c.chair !== PLACEHOLDER_CHAIR).length;
96
+ const totalDocs = committeeDataList.reduce((sum, c) => sum + c.documents.length, 0);
97
+ const adoptedCount = feedData?.adoptedTexts?.length ?? 0;
98
+ const parts = [];
99
+ if (totalDocs > 0)
100
+ parts.push(pl(totalDocs, 'Document', 'Documents'));
101
+ if (adoptedCount > 0)
102
+ parts.push(pl(adoptedCount, 'Adopted Text', 'Adopted Texts'));
103
+ if (activeCount > 0 && parts.length === 0) {
104
+ parts.push(pl(activeCount, 'Active Committee', 'Active Committees'));
105
+ }
106
+ return parts.join(', ');
107
+ }
108
+ // Keyword lists are pre-normalized to lowercase so that each call to
109
+ // categorizeAdoptedText only needs to lowercase the title once.
110
+ //
111
+ // LIBE is checked before AFET so that human-rights and human-trafficking
112
+ // titles are correctly classified under civil liberties even when the title
113
+ // also mentions a country (e.g. "Ukraine") that would match AFET.
114
+ // Both LIBE and AFET are checked before AGRI so that person-name false
115
+ // positives (e.g. "Bobi Wine" matching the agricultural keyword "wine")
116
+ // are avoided.
117
+ // AGRI is then checked before ENVI so that titles containing 'agri-food' are
118
+ // not incorrectly captured by ENVI's broader 'food' keyword.
119
+ /** Lowercase keywords that map an adopted-text title to the AFET theme group */
120
+ export const AFET_KEYWORDS = [
121
+ 'foreign affairs',
122
+ 'foreign policy',
123
+ 'security policy',
124
+ 'security cooperation',
125
+ 'defence',
126
+ 'defense',
127
+ 'sanctions',
128
+ 'magnitsky',
129
+ 'ukraine',
130
+ 'aggression',
131
+ 'peace agreement',
132
+ 'peace process',
133
+ 'peace mission',
134
+ 'peace operation',
135
+ 'post-election',
136
+ 'opposition leader',
137
+ 'threats against',
138
+ ];
139
+ /** Lowercase keywords that map an adopted-text title to the LIBE theme group */
140
+ export const LIBE_KEYWORDS = [
141
+ 'civil liberties',
142
+ 'civil rights',
143
+ 'justice and home affairs',
144
+ 'justice cooperation',
145
+ 'criminal justice',
146
+ 'fundamental rights',
147
+ 'human rights',
148
+ 'human trafficking',
149
+ "workers' rights",
150
+ 'safe countries',
151
+ 'safe third',
152
+ 'asylum',
153
+ 'migration',
154
+ ];
155
+ /** Lowercase keywords that map an adopted-text title to the AGRI theme group */
156
+ export const AGRI_KEYWORDS = [
157
+ 'agriculture',
158
+ 'wine',
159
+ 'agri-food',
160
+ 'mercosur',
161
+ 'rural',
162
+ 'farming',
163
+ 'fisheries',
164
+ ];
165
+ /** Lowercase keywords that map an adopted-text title to the ENVI theme group */
166
+ export const ENVI_KEYWORDS = [
167
+ 'environment',
168
+ 'climate',
169
+ 'emission',
170
+ 'health',
171
+ 'food',
172
+ 'medicinal',
173
+ 'detergent',
174
+ 'gmo',
175
+ 'genetically',
176
+ 'cancer',
177
+ ];
178
+ /** Lowercase keywords that map an adopted-text title to the ECON theme group */
179
+ export const ECON_KEYWORDS = [
180
+ 'economic',
181
+ 'financial',
182
+ 'central bank',
183
+ 'monetary',
184
+ 'fiscal',
185
+ '28th regime',
186
+ ];
187
+ /**
188
+ * Categorize an adopted-text title into a committee theme group.
189
+ *
190
+ * LIBE is tested before AFET so that human-rights and human-trafficking
191
+ * titles are classified under civil liberties even when they also mention
192
+ * an AFET country keyword (e.g. "Ukraine"). Both are tested before AGRI
193
+ * to avoid person-name false positives (e.g. "Bobi Wine").
194
+ *
195
+ * @param title - Adopted text title to categorize
196
+ * @returns Committee theme key — one of `'ENVI'` | `'ECON'` | `'AFET'` | `'LIBE'` | `'AGRI'` | `'OTHER'`
197
+ */
198
+ export function categorizeAdoptedText(title) {
199
+ const t = title.toLowerCase();
200
+ if (LIBE_KEYWORDS.some((k) => t.includes(k)))
201
+ return 'LIBE';
202
+ if (AFET_KEYWORDS.some((k) => t.includes(k)))
203
+ return 'AFET';
204
+ if (AGRI_KEYWORDS.some((k) => t.includes(k)))
205
+ return 'AGRI';
206
+ if (ENVI_KEYWORDS.some((k) => t.includes(k)))
207
+ return 'ENVI';
208
+ if (ECON_KEYWORDS.some((k) => t.includes(k)))
209
+ return 'ECON';
210
+ return 'OTHER';
211
+ }
212
+ // ─── Feed data enrichment ─────────────────────────────────────────────────────
213
+ /**
214
+ * Build an HTML section from adopted texts feed data.
215
+ * Groups texts by thematic area and provides committee-relevant context.
216
+ *
217
+ * @param feedData - EP feed data with adopted texts
218
+ * @param lang - Language code for localized strings
219
+ * @returns HTML string, or empty string when no feed data
220
+ */
221
+ function buildAdoptedTextsSection(feedData, lang) {
222
+ if (!feedData?.adoptedTexts?.length)
223
+ return '';
224
+ const texts = feedData.adoptedTexts;
225
+ const s = getLocalizedString(COMMITTEE_ANALYSIS_CONTENT_STRINGS, lang);
226
+ const grouped = {};
227
+ for (const text of texts) {
228
+ const cat = categorizeAdoptedText(text.title);
229
+ const bucket = grouped[cat] ?? [];
230
+ bucket.push(text);
231
+ grouped[cat] = bucket;
232
+ }
233
+ const committeeNames = {
234
+ ENVI: s.committeeNameENVI,
235
+ ECON: s.committeeNameECON,
236
+ AFET: s.committeeNameAFET,
237
+ LIBE: s.committeeNameLIBE,
238
+ AGRI: s.committeeNameAGRI,
239
+ OTHER: s.committeeNameOTHER,
240
+ };
241
+ const sectionLabel = s.adoptedTextsSectionHeading;
242
+ const summary = texts.length === 1
243
+ ? s.adoptedTextsSummarySingular
244
+ : s.adoptedTextsSummary.replace('{count}', String(texts.length));
245
+ const displayOrder = ['ENVI', 'ECON', 'AFET', 'LIBE', 'AGRI', 'OTHER'];
246
+ const sections = displayOrder
247
+ .filter((cat) => grouped[cat]?.length)
248
+ .map((cat) => {
249
+ const items = grouped[cat];
250
+ const listItems = items
251
+ .map((item) => `<li class="adopted-text-item"><strong>${escapeHTML(item.title)}</strong> <span class="document-date">(${escapeHTML(item.date)})</span></li>`)
252
+ .join('\n ');
253
+ return `
254
+ <div class="committee-theme-group">
255
+ <h4>${escapeHTML(committeeNames[cat] ?? cat)}</h4>
256
+ <ul class="adopted-texts-list">${listItems}</ul>
257
+ </div>`;
258
+ })
259
+ .join('');
260
+ if (!sections)
261
+ return '';
262
+ return `
263
+ <section class="adopted-texts-overview">
264
+ <h3>${escapeHTML(sectionLabel)}</h3>
265
+ <p>${escapeHTML(summary)}</p>
266
+ ${sections}
267
+ </section>`;
268
+ }
269
+ // ─── HTML builders ────────────────────────────────────────────────────────────
270
+ /**
271
+ * Build the HTML body for a committee reports article.
272
+ *
273
+ * @param committeeDataList - Pre-fetched committee data
274
+ * @param lang - Language code for localized strings
275
+ * @returns Article HTML body
276
+ */
277
+ function buildCommitteeReportsHTML(committeeDataList, lang) {
278
+ const s = getLocalizedString(COMMITTEE_ANALYSIS_CONTENT_STRINGS, lang);
279
+ const committeeSections = committeeDataList
280
+ .map((committee) => {
281
+ // Render an unavailable notice for individual placeholder committee entries
282
+ if (committee.chair === PLACEHOLDER_CHAIR &&
283
+ committee.members === PLACEHOLDER_MEMBERS &&
284
+ committee.documents.length === 0) {
285
+ return `
286
+ <section class="committee-card committee-card--unavailable">
287
+ <h3 class="committee-name">${escapeHTML(committee.name)} (${escapeHTML(committee.abbreviation)})</h3>
288
+ <p class="committee-metadata-unavailable">${escapeHTML(s.committeeMetadataUnavailable)}</p>
289
+ </section>`;
290
+ }
291
+ const docItems = committee.documents.length > 0
292
+ ? committee.documents
293
+ .map((doc) => `
294
+ <li class="document-item">
295
+ <span class="document-type">${escapeHTML(doc.type)}</span>
296
+ <span class="document-title">${escapeHTML(doc.title)}</span>
297
+ ${doc.date ? `<span class="document-date">${escapeHTML(doc.date)}</span>` : ''}
298
+ </li>`)
299
+ .join('')
300
+ : `<li>${escapeHTML(s.noRecentDocs)}</li>`;
301
+ const effectivenessHtml = committee.effectiveness
302
+ ? `<p class="effectiveness-score">${escapeHTML(committee.effectiveness)}</p>`
303
+ : '';
304
+ return `
305
+ <section class="committee-card">
306
+ <h3 class="committee-name">${escapeHTML(committee.name)} (${escapeHTML(committee.abbreviation)})</h3>
307
+ <div class="committee-meta">
308
+ <span class="committee-chair">${escapeHTML(s.chairLabel)} ${escapeHTML(committee.chair)}</span>
309
+ <span class="committee-members">${committee.members} ${escapeHTML(s.membersLabel)}</span>
310
+ </div>
311
+ <section class="recent-activity">
312
+ <ul class="document-list">${docItems}</ul>
313
+ </section>
314
+ <section class="effectiveness-metrics">${effectivenessHtml}</section>
315
+ </section>`;
316
+ })
317
+ .join('');
318
+ return `
319
+ <div class="article-content">
320
+ <section class="committee-overview">
321
+ <p class="lede">${escapeHTML(s.lede)}</p>
322
+ </section>
323
+ <section class="committee-reports">${committeeSections}</section>
324
+ </div>`;
325
+ }
326
+ // ─── Strategy implementation ──────────────────────────────────────────────────
327
+ /**
328
+ * Article strategy for {@link ArticleCategory.COMMITTEE_REPORTS}.
329
+ * Fetches info, documents and effectiveness data for the featured committees
330
+ * then renders an activity overview.
331
+ */
332
+ export class CommitteeReportsStrategy {
333
+ type = ArticleCategory.COMMITTEE_REPORTS;
334
+ requiredMCPTools = [
335
+ 'get_committee_info',
336
+ 'search_documents',
337
+ 'analyze_legislative_effectiveness',
338
+ 'get_committee_documents_feed',
339
+ ];
340
+ /**
341
+ * Fetch committee data for all featured committees in parallel.
342
+ *
343
+ * @param client - MCP client or null
344
+ * @param date - ISO 8601 publication date
345
+ * @returns Populated committee reports data payload
346
+ */
347
+ async fetchData(client, date) {
348
+ const feedDateRange = computeRollingDateRange(date, 30, 'committee feed window');
349
+ // Fetch individual committee data and EP feeds in parallel
350
+ const [committeeDataRaw, feedData] = await Promise.all([
351
+ Promise.all(FEATURED_COMMITTEES.map((abbr) => fetchCommitteeData(client, abbr).catch((error) => {
352
+ const message = error instanceof Error ? error.message : String(error);
353
+ console.error(` ⚠️ Failed to fetch data for committee ${abbr}:`, message);
354
+ return null;
355
+ }))),
356
+ fetchEPFeedData(client, 'one-month', feedDateRange),
357
+ ]);
358
+ const committeeDataList = committeeDataRaw.filter((committee) => committee !== null);
359
+ return { date, committeeDataList, feedData };
360
+ }
361
+ /**
362
+ * Build the committee reports HTML body.
363
+ *
364
+ * @param data - Committee reports data payload
365
+ * @param lang - Language code for localized content
366
+ * @returns Article HTML body
367
+ */
368
+ buildContent(data, lang) {
369
+ const base = buildCommitteeReportsHTML(data.committeeDataList, lang);
370
+ const feedSection = buildAdoptedTextsSection(data.feedData, lang);
371
+ const analysis = buildCommitteeAnalysis(data.committeeDataList, data.date, lang);
372
+ const deepSection = buildDeepAnalysisSection(analysis, lang);
373
+ const mindmapData = buildCommitteeMindmap(data.committeeDataList, lang);
374
+ const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
375
+ const swotData = buildCommitteeSwot(data.committeeDataList, lang);
376
+ const swotSection = buildSwotSection(swotData, lang);
377
+ const dashboardData = buildCommitteeDashboard(data.committeeDataList, lang);
378
+ const dashboardSection = buildDashboardSection(dashboardData, lang);
379
+ const injection = feedSection + deepSection + mindmapSection + swotSection + dashboardSection;
380
+ // Inject before the closing </div> of .article-content
381
+ if (injection) {
382
+ const closingTag = '</div>';
383
+ const lastIdx = base.lastIndexOf(closingTag);
384
+ if (lastIdx !== -1) {
385
+ return base.slice(0, lastIdx) + injection + '\n' + base.slice(lastIdx);
386
+ }
387
+ }
388
+ return base;
389
+ }
390
+ /**
391
+ * Return language-specific metadata for the committee reports article.
392
+ *
393
+ * @param data - Committee reports data payload
394
+ * @param lang - Target language code
395
+ * @returns Localised metadata
396
+ */
397
+ getMetadata(data, lang) {
398
+ const committeeLabel = FEATURED_COMMITTEES.join(', ');
399
+ const titleFn = getLocalizedString(COMMITTEE_REPORTS_TITLES, lang);
400
+ const { title: baseTitle, subtitle: baseSubtitle } = titleFn(committeeLabel);
401
+ const suffix = lang === 'en' ? buildCommitteeTitleSuffix(data.committeeDataList, data.feedData) : '';
402
+ const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
403
+ const subtitle = lang === 'en'
404
+ ? buildCommitteeDescription(data.committeeDataList, data.feedData) || baseSubtitle
405
+ : baseSubtitle;
406
+ return {
407
+ title,
408
+ subtitle,
409
+ keywords: buildCommitteeKeywords(data.committeeDataList, data.feedData),
410
+ category: ArticleCategory.COMMITTEE_REPORTS,
411
+ sources: COMMITTEE_REPORTS_SOURCES,
412
+ };
413
+ }
414
+ /**
415
+ * Skip generation when no real data is available.
416
+ *
417
+ * Skips when:
418
+ * - All committee fetches failed (empty committeeDataList), or
419
+ * - All fetched committee data is placeholder AND no feed data is available.
420
+ * When EP feed data contains adopted texts or other items, the article can still
421
+ * provide valuable content even if individual committee metadata is sparse.
422
+ *
423
+ * @param data - Committee reports data payload
424
+ * @returns `true` when there is no usable data at all
425
+ */
426
+ shouldSkip(data) {
427
+ const { committeeDataList, feedData } = data;
428
+ if (committeeDataList.length === 0) {
429
+ return true;
430
+ }
431
+ // If feed data has any items, generate even with placeholder committees
432
+ if (feedData) {
433
+ const feedItemCount = (feedData.adoptedTexts?.length ?? 0) +
434
+ (feedData.committeeDocuments?.length ?? 0) +
435
+ (feedData.plenaryDocuments?.length ?? 0) +
436
+ (feedData.documents?.length ?? 0) +
437
+ (feedData.procedures?.length ?? 0);
438
+ if (feedItemCount > 0) {
439
+ return false;
440
+ }
441
+ }
442
+ return isPlaceholderCommitteeData(committeeDataList);
443
+ }
444
+ }
445
+ /** Singleton instance for use by the strategy registry */
446
+ export const committeeReportsStrategy = new CommitteeReportsStrategy();
447
+ //# sourceMappingURL=committee-reports-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"committee-reports-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/committee-reports-strategy.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,sCAAsC;AAUtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EACL,wBAAwB,EACxB,kCAAkC,EAClC,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AAGxE,OAAO,EAAE,EAAE,EAAE,MAAM,+BAA+B,CAAC;AAEnD,iEAAiE;AACjE,MAAM,aAAa,GAAG,gCAAgC,CAAC;AAEvD,0EAA0E;AAC1E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,6DAA6D;AAC7D,MAAM,+BAA+B,GAAG,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,CAAU,CAAC;AAE/F,mEAAmE;AACnE,MAAM,yBAAyB,GAA6B;IAC1D,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,aAAa,EAAE;CAC/C,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAS,sBAAsB,CAC7B,iBAA2C,EAC3C,QAAiC;IAEjC,MAAM,QAAQ,GAAa,CAAC,GAAG,+BAA+B,CAAC,CAAC;IAEhE,wCAAwC;IACxC,KAAK,MAAM,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,YAAY;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,CAAC,CAAC,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,oCAAoC;IACpC,IAAI,QAAQ,EAAE,YAAY,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACrD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChD,IAAI,KAAK,KAAK,OAAO;oBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,yBAAyB,CAChC,iBAA2C,EAC3C,QAAiC;IAEjC,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC,MAAM,CAAC;IAC1F,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,YAAY,GAAG,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAC3F,IAAI,SAAS,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACpF,IAAI,YAAY,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;IAEpF,MAAM,KAAK,GAAG,iBAAiB;SAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC;SAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;SAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;IAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,4FAA4F,CAAC;IACtG,CAAC;IAED,MAAM,IAAI,GAAG,0BAA0B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC3D,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC;AAED;;;;;;GAMG;AACH,SAAS,yBAAyB,CAChC,iBAA2C,EAC3C,QAAiC;IAEjC,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC,MAAM,CAAC;IAC1F,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,YAAY,GAAG,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,IAAI,YAAY,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;IACpF,IAAI,WAAW,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAoBD,qEAAqE;AACrE,gEAAgE;AAChE,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,kEAAkE;AAClE,uEAAuE;AACvE,wEAAwE;AACxE,eAAe;AACf,6EAA6E;AAC7E,6DAA6D;AAE7D,gFAAgF;AAChF,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,sBAAsB;IACtB,SAAS;IACT,SAAS;IACT,WAAW;IACX,WAAW;IACX,SAAS;IACT,YAAY;IACZ,iBAAiB;IACjB,eAAe;IACf,eAAe;IACf,iBAAiB;IACjB,eAAe;IACf,mBAAmB;IACnB,iBAAiB;CAClB,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,iBAAiB;IACjB,cAAc;IACd,0BAA0B;IAC1B,qBAAqB;IACrB,kBAAkB;IAClB,oBAAoB;IACpB,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,gBAAgB;IAChB,YAAY;IACZ,QAAQ;IACR,WAAW;CACZ,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,aAAa;IACb,MAAM;IACN,WAAW;IACX,UAAU;IACV,OAAO;IACP,SAAS;IACT,WAAW;CACZ,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,aAAa;IACb,SAAS;IACT,UAAU;IACV,QAAQ;IACR,MAAM;IACN,WAAW;IACX,WAAW;IACX,KAAK;IACL,aAAa;IACb,QAAQ;CACT,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,UAAU;IACV,WAAW;IACX,cAAc;IACd,UAAU;IACV,QAAQ;IACR,aAAa;CACd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iFAAiF;AAEjF;;;;;;;GAOG;AACH,SAAS,wBAAwB,CAAC,QAAgC,EAAE,IAAkB;IACpF,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC;IACpC,MAAM,CAAC,GAAG,kBAAkB,CAAC,kCAAkC,EAAE,IAAI,CAAC,CAAC;IAEvE,MAAM,OAAO,GAET,EAAE,CAAC;IACP,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,MAAM,cAAc,GAAmC;QACrD,IAAI,EAAE,CAAC,CAAC,iBAAiB;QACzB,IAAI,EAAE,CAAC,CAAC,iBAAiB;QACzB,IAAI,EAAE,CAAC,CAAC,iBAAiB;QACzB,IAAI,EAAE,CAAC,CAAC,iBAAiB;QACzB,IAAI,EAAE,CAAC,CAAC,iBAAiB;QACzB,KAAK,EAAE,CAAC,CAAC,kBAAkB;KAC5B,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,CAAC,0BAA0B,CAAC;IAClD,MAAM,OAAO,GACX,KAAK,CAAC,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,2BAA2B;QAC/B,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;IAEhF,MAAM,QAAQ,GAAG,YAAY;SAC1B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;SACrC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,KAAK;aACpB,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CACP,yCAAyC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,0CAA0C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAChJ;aACA,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,OAAO;;oBAEO,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;+CACX,SAAS;mBACrC,CAAC;IAChB,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzB,OAAO;;kBAES,UAAU,CAAC,YAAY,CAAC;iBACzB,UAAU,CAAC,OAAO,CAAC;cACtB,QAAQ;qBACD,CAAC;AACtB,CAAC;AAED,iFAAiF;AAEjF;;;;;;GAMG;AACH,SAAS,yBAAyB,CAChC,iBAA2C,EAC3C,IAAkB;IAElB,MAAM,CAAC,GAAG,kBAAkB,CAAC,kCAAkC,EAAE,IAAI,CAAC,CAAC;IAEvE,MAAM,iBAAiB,GAAG,iBAAiB;SACxC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QACjB,4EAA4E;QAC5E,IACE,SAAS,CAAC,KAAK,KAAK,iBAAiB;YACrC,SAAS,CAAC,OAAO,KAAK,mBAAmB;YACzC,SAAS,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAChC,CAAC;YACD,OAAO;;qCAEsB,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;oDAClD,UAAU,CAAC,CAAC,CAAC,4BAA4B,CAAC;iBAC7E,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GACZ,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAC5B,CAAC,CAAC,SAAS,CAAC,SAAS;iBAChB,GAAG,CACF,CAAC,GAAG,EAAE,EAAE,CAAC;;gDAEuB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;iDACnB,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;oBAClD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;sBAC1E,CACP;iBACA,IAAI,CAAC,EAAE,CAAC;YACb,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC;QAE/C,MAAM,iBAAiB,GAAG,SAAS,CAAC,aAAa;YAC/C,CAAC,CAAC,kCAAkC,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM;YAC7E,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;;qCAEwB,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;;0CAE5D,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;4CACrD,SAAS,CAAC,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;;;sCAGrD,QAAQ;;iDAEG,iBAAiB;iBACjD,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO;;;0BAGiB,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;;2CAED,iBAAiB;WACjD,CAAC;AACZ,CAAC;AAED,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,OAAO,wBAAwB;IAC1B,IAAI,GAAG,eAAe,CAAC,iBAAiB,CAAC;IAEzC,gBAAgB,GAAG;QAC1B,oBAAoB;QACpB,kBAAkB;QAClB,mCAAmC;QACnC,8BAA8B;KACtB,CAAC;IAEX;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CACb,MAA0C,EAC1C,IAAY;QAEZ,MAAM,aAAa,GAAG,uBAAuB,CAAC,IAAI,EAAE,EAAE,EAAE,uBAAuB,CAAC,CAAC;QAEjF,2DAA2D;QAC3D,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACrD,OAAO,CAAC,GAAG,CACT,mBAAmB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/B,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO,CAAC,KAAK,CAAC,2CAA2C,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;gBAC3E,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CACH,CACF;YACD,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,CAAC;SACpD,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,MAAM,CAC/C,CAAC,SAAS,EAA8B,EAAE,CAAC,SAAS,KAAK,IAAI,CAC9D,CAAC;QAEF,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;IAC/C,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,IAAiC,EAAE,IAAkB;QAChE,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,wBAAwB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjF,MAAM,WAAW,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,+BAA+B,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,uBAAuB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC5E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACpE,MAAM,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,GAAG,gBAAgB,CAAC;QAC9F,uDAAuD;QACvD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,UAAU,GAAG,QAAQ,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;gBACnB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,WAAW,CAAC,IAAiC,EAAE,IAAkB;QAC/D,MAAM,cAAc,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,kBAAkB,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;QACnE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;QAC7E,MAAM,MAAM,GACV,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,MAAM,QAAQ,GACZ,IAAI,KAAK,IAAI;YACX,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,YAAY;YAClF,CAAC,CAAC,YAAY,CAAC;QACnB,OAAO;YACL,KAAK;YACL,QAAQ;YACR,QAAQ,EAAE,sBAAsB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC;YACvE,QAAQ,EAAE,eAAe,CAAC,iBAAiB;YAC3C,OAAO,EAAE,yBAAyB;SACnC,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,IAAiC;QAC1C,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAE7C,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wEAAwE;QACxE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,aAAa,GACjB,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC;gBACpC,CAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,IAAI,CAAC,CAAC;gBAC1C,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,IAAI,CAAC,CAAC;gBACxC,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;gBACjC,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;YACrC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,0BAA0B,CAAC,iBAAiB,CAAC,CAAC;IACvD,CAAC;CACF;AAED,0DAA0D;AAC1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @module Generators/Strategies/MonthAheadStrategy
3
+ * @description Article strategy for the Month Ahead article type.
4
+ * Fetches plenary sessions, committee meetings, documents, and legislative
5
+ * pipeline data for the upcoming 30 days, then renders a forward-looking
6
+ * strategic outlook article.
7
+ */
8
+ import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
9
+ import { ArticleCategory } from '../../types/index.js';
10
+ import type { LanguageCode, DateRange, WeekAheadData, EPFeedData } from '../../types/index.js';
11
+ import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
12
+ /** Data fetched and pre-processed by {@link MonthAheadStrategy} */
13
+ export interface MonthAheadArticleData extends ArticleData {
14
+ /** Month-ahead date range (30 days) */
15
+ readonly dateRange: DateRange;
16
+ /** Aggregated month-ahead domain data */
17
+ readonly monthData: WeekAheadData;
18
+ /** SEO keywords derived from the data */
19
+ readonly keywords: readonly string[];
20
+ /** Display label for the target month */
21
+ readonly monthLabel: string;
22
+ /** EP feed data for enrichment (when available) */
23
+ readonly feedData?: EPFeedData | undefined;
24
+ }
25
+ /**
26
+ * Article strategy for {@link ArticleCategory.MONTH_AHEAD}.
27
+ * Fetches plenary, committee, document, and pipeline data then builds
28
+ * a forward-looking 30-day strategic outlook of parliamentary activity.
29
+ */
30
+ export declare class MonthAheadStrategy implements ArticleStrategy<MonthAheadArticleData> {
31
+ readonly type = ArticleCategory.MONTH_AHEAD;
32
+ readonly requiredMCPTools: readonly ["get_plenary_sessions", "get_committee_info", "search_documents", "monitor_legislative_pipeline", "get_parliamentary_questions", "get_events", "get_events_feed", "get_adopted_texts_feed", "get_procedures_feed"];
33
+ /**
34
+ * Fetch month-ahead data from MCP.
35
+ *
36
+ * @param client - MCP client or null
37
+ * @param date - ISO 8601 publication date
38
+ * @returns Populated month-ahead data payload
39
+ */
40
+ fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<MonthAheadArticleData>;
41
+ /**
42
+ * Build the month-ahead HTML body for the specified language.
43
+ *
44
+ * @param data - Month-ahead data payload
45
+ * @param lang - Target language code used for editorial strings
46
+ * @returns Article HTML body
47
+ */
48
+ buildContent(data: MonthAheadArticleData, lang: LanguageCode): string;
49
+ /**
50
+ * Return language-specific metadata for the month-ahead article.
51
+ *
52
+ * @param data - Month-ahead data payload
53
+ * @param lang - Target language code
54
+ * @returns Localised metadata
55
+ */
56
+ getMetadata(data: MonthAheadArticleData, lang: LanguageCode): ArticleMetadata;
57
+ }
58
+ /** Singleton instance for use by the strategy registry */
59
+ export declare const monthAheadStrategy: MonthAheadStrategy;
60
+ //# sourceMappingURL=month-ahead-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"month-ahead-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/month-ahead-strategy.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAc/F,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK3F,mEAAmE;AACnE,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AA8FD;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,eAAe,CAAC,qBAAqB,CAAC;IAC/E,QAAQ,CAAC,IAAI,+BAA+B;IAE5C,QAAQ,CAAC,gBAAgB,+NAUd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,CAAC;IAejC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAgBrE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAiB9E;AAED,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}