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,50 @@
1
+ import type { VotingRecord, VotingPattern, VotingAnomaly, MotionsQuestion, CoalitionIntelligence, AdoptedTextFeedItem } from '../types/index.js';
2
+ /** Marker string used in all fallback/placeholder data to indicate MCP data is unavailable */
3
+ export declare const PLACEHOLDER_MARKER = "DATA_UNAVAILABLE (placeholder)";
4
+ /**
5
+ * Get fallback data for motions article
6
+ *
7
+ * @param dateStr - Current date string
8
+ * @param dateFromStr - Start date string
9
+ * @returns Object with all fallback data arrays
10
+ */
11
+ export declare function getMotionsFallbackData(dateStr: string, dateFromStr: string): {
12
+ votingRecords: VotingRecord[];
13
+ votingPatterns: VotingPattern[];
14
+ anomalies: VotingAnomaly[];
15
+ questions: MotionsQuestion[];
16
+ };
17
+ /**
18
+ * Generate HTML content for motions article
19
+ *
20
+ * @param dateFromStr - Start date
21
+ * @param dateStr - End date
22
+ * @param votingRecords - Voting records data
23
+ * @param votingPatterns - Voting patterns data
24
+ * @param anomalies - Anomalies data
25
+ * @param questions - Questions data
26
+ * @param lang - Language code for editorial strings (default: 'en')
27
+ * @returns HTML content string
28
+ */
29
+ export declare function generateMotionsContent(dateFromStr: string, dateStr: string, votingRecords: VotingRecord[], votingPatterns: VotingPattern[], anomalies: VotingAnomaly[], questions: MotionsQuestion[], lang?: string): string;
30
+ /**
31
+ * Build political alignment analysis section for motions, showing how
32
+ * voting records map to coalition cohesion and cross-party dynamics.
33
+ * Returns an empty string when both input arrays are empty or yield no items.
34
+ *
35
+ * @param votingRecords - Voting records to analyse
36
+ * @param coalitions - Coalition intelligence data from MCP
37
+ * @param language - BCP 47 language code used as the section lang attribute
38
+ * @returns HTML string for the political alignment section
39
+ */
40
+ export declare function buildPoliticalAlignmentSection(votingRecords: VotingRecord[], coalitions: CoalitionIntelligence[], language: string): string;
41
+ /**
42
+ * Build an HTML section listing recently adopted texts from EP feed data.
43
+ * Groups texts by adoption date and renders them as a structured list.
44
+ *
45
+ * @param adoptedTexts - Adopted text feed items
46
+ * @param language - BCP 47 language code
47
+ * @returns HTML section string, or empty string if no texts
48
+ */
49
+ export declare function buildAdoptedTextsSection(adoptedTexts: readonly AdoptedTextFeedItem[], language: string): string;
50
+ //# sourceMappingURL=motions-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motions-content.d.ts","sourceRoot":"","sources":["../../src/generators/motions-content.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAE3B,8FAA8F;AAC9F,eAAO,MAAM,kBAAkB,mCAAmC,CAAC;AAEnE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB;IACD,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B,CAmDA;AAgDD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,YAAY,EAAE,EAC7B,cAAc,EAAE,aAAa,EAAE,EAC/B,SAAS,EAAE,aAAa,EAAE,EAC1B,SAAS,EAAE,eAAe,EAAE,EAC5B,IAAI,SAAO,GACV,MAAM,CAkHR;AAmDD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,YAAY,EAAE,EAC7B,UAAU,EAAE,qBAAqB,EAAE,EACnC,QAAQ,EAAE,MAAM,GACf,MAAM,CAYR;AAwDD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,SAAS,mBAAmB,EAAE,EAC5C,QAAQ,EAAE,MAAM,GACf,MAAM,CA2CR"}
@@ -0,0 +1,391 @@
1
+ // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * @module Generators/MotionsContent
5
+ * @description Pure functions for building motions article HTML and
6
+ * generating placeholder/fallback data when MCP is unavailable.
7
+ */
8
+ import { escapeHTML } from '../utils/file-utils.js';
9
+ import { getLocalizedString, EDITORIAL_STRINGS, MOTIONS_STRINGS } from '../constants/languages.js';
10
+ /** Marker string used in all fallback/placeholder data to indicate MCP data is unavailable */
11
+ export const PLACEHOLDER_MARKER = 'DATA_UNAVAILABLE (placeholder)';
12
+ /**
13
+ * Get fallback data for motions article
14
+ *
15
+ * @param dateStr - Current date string
16
+ * @param dateFromStr - Start date string
17
+ * @returns Object with all fallback data arrays
18
+ */
19
+ export function getMotionsFallbackData(dateStr, dateFromStr) {
20
+ return {
21
+ votingRecords: [
22
+ {
23
+ title: 'Example motion (placeholder – data unavailable)',
24
+ date: dateStr,
25
+ result: PLACEHOLDER_MARKER,
26
+ votes: { for: 0, against: 0, abstain: 0 },
27
+ },
28
+ {
29
+ title: 'Example amendment (placeholder – data unavailable)',
30
+ date: dateFromStr,
31
+ result: PLACEHOLDER_MARKER,
32
+ votes: { for: 0, against: 0, abstain: 0 },
33
+ },
34
+ ],
35
+ votingPatterns: [
36
+ {
37
+ group: 'Example group A (placeholder)',
38
+ cohesion: 0.0,
39
+ participation: 0.0,
40
+ },
41
+ {
42
+ group: 'Example group B (placeholder)',
43
+ cohesion: 0.0,
44
+ participation: 0.0,
45
+ },
46
+ ],
47
+ anomalies: [
48
+ {
49
+ type: 'Placeholder example',
50
+ description: 'No real anomaly data available from MCP – this is illustrative placeholder content only.',
51
+ severity: 'LOW',
52
+ },
53
+ ],
54
+ questions: [
55
+ {
56
+ author: 'Placeholder MEP 1',
57
+ topic: 'Placeholder parliamentary question on energy security (MCP data unavailable)',
58
+ date: dateStr,
59
+ status: PLACEHOLDER_MARKER,
60
+ },
61
+ {
62
+ author: 'Placeholder MEP 2',
63
+ topic: 'Placeholder parliamentary question on migration policy (MCP data unavailable)',
64
+ date: dateFromStr,
65
+ status: PLACEHOLDER_MARKER,
66
+ },
67
+ ],
68
+ };
69
+ }
70
+ /**
71
+ * Returns true when there is no real roll-call data: either the records
72
+ * array is empty or every voting record carries the placeholder marker,
73
+ * indicating no real roll-call data was retrieved from MCP.
74
+ *
75
+ * @param records - Voting records to test
76
+ * @returns `true` if the array is empty or all records are placeholder-only data
77
+ */
78
+ function isPlaceholderVotingRecords(records) {
79
+ return records.length === 0 || records.every((r) => r.result === PLACEHOLDER_MARKER);
80
+ }
81
+ /**
82
+ * Returns true when there is no real voting pattern data: either the patterns
83
+ * array is empty or every voting pattern is placeholder/fallback data
84
+ * (groups whose name contains the word "placeholder" — case-insensitive).
85
+ *
86
+ * @param patterns - Voting patterns to test
87
+ * @returns `true` if the array is empty or all patterns are placeholder-only data
88
+ */
89
+ function isPlaceholderVotingPatterns(patterns) {
90
+ return patterns.length === 0 || patterns.every((p) => /placeholder/i.test(p.group));
91
+ }
92
+ /**
93
+ * Returns true when there is no real anomaly data: either the array is empty
94
+ * or every anomaly type contains the word "placeholder" (case-insensitive).
95
+ *
96
+ * @param anomalies - Anomalies to test
97
+ * @returns `true` if the array is empty or all anomalies are placeholder-only data
98
+ */
99
+ function isPlaceholderAnomalies(anomalies) {
100
+ return anomalies.length === 0 || anomalies.every((a) => /placeholder/i.test(a.type));
101
+ }
102
+ /**
103
+ * Returns true when there is no real questions data: either the array is empty
104
+ * or every question carries the placeholder marker in its status field.
105
+ *
106
+ * @param questions - Parliamentary questions to test
107
+ * @returns `true` if the array is empty or all questions are placeholder-only data
108
+ */
109
+ function isPlaceholderQuestions(questions) {
110
+ return questions.length === 0 || questions.every((q) => q.status === PLACEHOLDER_MARKER);
111
+ }
112
+ /**
113
+ * Generate HTML content for motions article
114
+ *
115
+ * @param dateFromStr - Start date
116
+ * @param dateStr - End date
117
+ * @param votingRecords - Voting records data
118
+ * @param votingPatterns - Voting patterns data
119
+ * @param anomalies - Anomalies data
120
+ * @param questions - Questions data
121
+ * @param lang - Language code for editorial strings (default: 'en')
122
+ * @returns HTML content string
123
+ */
124
+ export function generateMotionsContent(dateFromStr, dateStr, votingRecords, votingPatterns, anomalies, questions, lang = 'en') {
125
+ const editorial = getLocalizedString(EDITORIAL_STRINGS, lang);
126
+ const strings = getLocalizedString(MOTIONS_STRINGS, lang);
127
+ const ledeAnalysisRaw = strings.ledeAnalysis
128
+ .replace('{DATE_FROM}', dateFromStr)
129
+ .replace('{DATE_TO}', dateStr);
130
+ const showVotingResults = !isPlaceholderVotingRecords(votingRecords);
131
+ const showVotingPatterns = !isPlaceholderVotingPatterns(votingPatterns);
132
+ const showAnomalies = !isPlaceholderAnomalies(anomalies);
133
+ const showQuestions = !isPlaceholderQuestions(questions);
134
+ return `
135
+ <div class="article-content">
136
+ <section class="lede">
137
+ <p>${escapeHTML(strings.lede)} ${escapeHTML(editorial.sourceAttribution)}, ${escapeHTML(ledeAnalysisRaw)}</p>
138
+ </section>
139
+ ${showVotingResults
140
+ ? `
141
+ <section class="voting-results">
142
+ <h2>${escapeHTML(strings.votingRecordsHeading)}</h2>
143
+ ${votingRecords
144
+ .filter((r) => r.result !== PLACEHOLDER_MARKER)
145
+ .map((record) => `
146
+ <div class="vote-item">
147
+ <h3>${escapeHTML(record.title)}</h3>
148
+ <p class="vote-date">${escapeHTML(strings.dateLabel)}: ${escapeHTML(record.date)}</p>
149
+ <p class="vote-result"><strong>${escapeHTML(strings.resultLabel)}:</strong> ${escapeHTML(record.result)}</p>
150
+ <div class="vote-breakdown">
151
+ <span class="vote-for">${escapeHTML(strings.forLabel)}: ${escapeHTML(String(record.votes.for))}</span>
152
+ <span class="vote-against">${escapeHTML(strings.againstLabel)}: ${escapeHTML(String(record.votes.against))}</span>
153
+ <span class="vote-abstain">${escapeHTML(strings.abstainLabel)}: ${escapeHTML(String(record.votes.abstain))}</span>
154
+ </div>
155
+ </div>
156
+ `)
157
+ .join('')}
158
+ </section>`
159
+ : ''}
160
+ ${showVotingPatterns
161
+ ? `
162
+ <section class="voting-patterns">
163
+ <h2>${escapeHTML(strings.partyCohesionHeading)}</h2>
164
+ <p>${escapeHTML(editorial.parliamentaryContext)}: Analysis of voting behavior reveals varying levels of party discipline across political groups:</p>
165
+ ${votingPatterns
166
+ .filter((p) => !/placeholder/i.test(p.group))
167
+ .map((pattern) => `
168
+ <div class="pattern-item">
169
+ <h3>${escapeHTML(pattern.group)}</h3>
170
+ <p><strong>${escapeHTML(strings.cohesionLabel)}:</strong> ${escapeHTML(String((pattern.cohesion * 100).toFixed(1)))}%</p>
171
+ <p><strong>${escapeHTML(strings.participationLabel)}:</strong> ${escapeHTML(String((pattern.participation * 100).toFixed(1)))}%</p>
172
+ </div>
173
+ `)
174
+ .join('')}
175
+ </section>`
176
+ : ''}
177
+ ${showAnomalies
178
+ ? `
179
+ <section class="anomalies">
180
+ <h2>${escapeHTML(strings.anomaliesHeading)}</h2>
181
+ <p>${escapeHTML(editorial.analysisNote)}: Unusual voting patterns that deviate from typical party lines:</p>
182
+ ${anomalies
183
+ .filter((a) => !/placeholder/i.test(a.type))
184
+ .map((anomaly) => {
185
+ const rawSeverity = anomaly.severity ?? 'unknown';
186
+ const severityDisplay = typeof rawSeverity === 'string' ? rawSeverity : String(rawSeverity);
187
+ const severityClass = severityDisplay.toLowerCase();
188
+ return `
189
+ <div class="anomaly-item severity-${escapeHTML(severityClass)}">
190
+ <h3>${escapeHTML(anomaly.type)}</h3>
191
+ <p>${escapeHTML(anomaly.description)}</p>
192
+ <p class="severity">${escapeHTML(strings.severityLabel)}: ${escapeHTML(severityDisplay)}</p>
193
+ </div>
194
+ `;
195
+ })
196
+ .join('')}
197
+ </section>`
198
+ : ''}
199
+ ${showQuestions
200
+ ? `
201
+ <section class="questions">
202
+ <h2>${escapeHTML(strings.questionsHeading)}</h2>
203
+ ${questions
204
+ .filter((q) => q.status !== PLACEHOLDER_MARKER)
205
+ .map((question) => `
206
+ <div class="question-item">
207
+ <p class="question-author">${escapeHTML(question.author)}</p>
208
+ <p class="question-topic"><strong>${escapeHTML(question.topic)}</strong></p>
209
+ <p class="question-meta">${escapeHTML(strings.dateLabel)}: ${escapeHTML(question.date)} | ${escapeHTML(strings.statusLabel)}: ${escapeHTML(question.status)}</p>
210
+ </div>
211
+ `)
212
+ .join('')}
213
+ </section>`
214
+ : ''}
215
+
216
+ <section class="why-this-matters">
217
+ <h2>${escapeHTML(editorial.whyThisMatters)}</h2>
218
+ <p>${escapeHTML(editorial.keyTakeaway)}: ${escapeHTML(strings.keyTakeawayText)}</p>
219
+ </section>
220
+ <!-- /article-content -->
221
+ </div>
222
+ `;
223
+ }
224
+ // ─── Political Alignment section ──────────────────────────────────────────────
225
+ /**
226
+ * Build HTML list items for voting record alignment rows
227
+ *
228
+ * @param records - Voting records to render
229
+ * @returns HTML list items string
230
+ */
231
+ function buildVoteAlignmentHtml(records) {
232
+ if (records.length === 0)
233
+ return '';
234
+ const realRecords = records.filter((r) => r.result !== PLACEHOLDER_MARKER);
235
+ if (realRecords.length === 0)
236
+ return '';
237
+ const items = realRecords
238
+ .map((r) => {
239
+ const forVotes = escapeHTML(String(r.votes.for));
240
+ const againstVotes = escapeHTML(String(r.votes.against));
241
+ const abstainVotes = escapeHTML(String(r.votes.abstain));
242
+ return (`<li class="alignment-vote">` +
243
+ `<strong>${escapeHTML(r.title)}</strong> — ` +
244
+ `${escapeHTML(r.result)} ` +
245
+ `(${forVotes}&#43; / ${againstVotes}&#8722; / ${abstainVotes} abstain)` +
246
+ `</li>`);
247
+ })
248
+ .join('\n ');
249
+ return `<ul class="alignment-votes">\n ${items}\n </ul>`;
250
+ }
251
+ /**
252
+ * Build HTML list items for coalition alignment rows
253
+ *
254
+ * @param coalitions - Coalition intelligence items to render
255
+ * @returns HTML list items string
256
+ */
257
+ function buildCoalitionAlignmentHtml(coalitions) {
258
+ if (coalitions.length === 0)
259
+ return '';
260
+ const items = coalitions
261
+ .map((c) => `<li class="alignment-coalition alignment-${escapeHTML(c.riskLevel)}">` +
262
+ `${escapeHTML(c.groups.join(', '))} — ` +
263
+ `cohesion: ${escapeHTML(String(Math.round(c.cohesionScore * 100)))}% ` +
264
+ `(${escapeHTML(c.alignmentTrend)})</li>`)
265
+ .join('\n ');
266
+ return `<ul class="alignment-coalitions">\n ${items}\n </ul>`;
267
+ }
268
+ /**
269
+ * Build political alignment analysis section for motions, showing how
270
+ * voting records map to coalition cohesion and cross-party dynamics.
271
+ * Returns an empty string when both input arrays are empty or yield no items.
272
+ *
273
+ * @param votingRecords - Voting records to analyse
274
+ * @param coalitions - Coalition intelligence data from MCP
275
+ * @param language - BCP 47 language code used as the section lang attribute
276
+ * @returns HTML string for the political alignment section
277
+ */
278
+ export function buildPoliticalAlignmentSection(votingRecords, coalitions, language) {
279
+ if (votingRecords.length === 0 && coalitions.length === 0)
280
+ return '';
281
+ const recordsHtml = buildVoteAlignmentHtml(votingRecords);
282
+ const coalitionsHtml = buildCoalitionAlignmentHtml(coalitions);
283
+ if (!recordsHtml && !coalitionsHtml)
284
+ return '';
285
+ const strings = getLocalizedString(MOTIONS_STRINGS, language);
286
+ return `
287
+ <section class="political-alignment" lang="${escapeHTML(language)}">
288
+ <h2>${escapeHTML(strings.politicalAlignmentHeading)}</h2>
289
+ ${recordsHtml}
290
+ ${coalitionsHtml}
291
+ </section>`;
292
+ }
293
+ /** Localized headings for the adopted texts feed section */
294
+ const ADOPTED_TEXTS_HEADINGS = {
295
+ en: 'Recently Adopted Texts',
296
+ sv: 'Nyligen Antagna Texter',
297
+ da: 'Nyligt Vedtagne Tekster',
298
+ no: 'Nylig Vedtatte Tekster',
299
+ fi: 'Äskettäin Hyväksytyt Tekstit',
300
+ de: 'Kürzlich Angenommene Texte',
301
+ fr: 'Textes Récemment Adoptés',
302
+ es: 'Textos Recientemente Adoptados',
303
+ nl: 'Recent Aangenomen Teksten',
304
+ ar: 'النصوص المعتمدة مؤخراً',
305
+ he: 'טקסטים שאומצו לאחרונה',
306
+ ja: '最近採択されたテキスト',
307
+ ko: '최근 채택된 텍스트',
308
+ zh: '最近通过的文本',
309
+ };
310
+ /** Localized fallback label for items with no adoption date */
311
+ const ADOPTED_TEXTS_DATE_UNKNOWN_STRINGS = {
312
+ en: 'Unknown',
313
+ sv: 'Okänt',
314
+ da: 'Ukendt',
315
+ no: 'Ukjent',
316
+ fi: 'Tuntematon',
317
+ de: 'Unbekannt',
318
+ fr: 'Inconnu',
319
+ es: 'Desconocido',
320
+ nl: 'Onbekend',
321
+ ar: 'غير معروف',
322
+ he: 'לא ידוע',
323
+ ja: '不明',
324
+ ko: '알 수 없음',
325
+ zh: '未知',
326
+ };
327
+ /** Localized count descriptions for the adopted texts feed section */
328
+ const ADOPTED_TEXTS_COUNT_STRINGS = {
329
+ en: (n) => `${n} texts adopted in recent plenary sessions:`,
330
+ sv: (n) => `${n} texter antagna i nyliga plenarsammanträden:`,
331
+ da: (n) => `${n} tekster vedtaget i seneste plenarmøder:`,
332
+ no: (n) => `${n} tekster vedtatt i nylige plenumsmøter:`,
333
+ fi: (n) => `${n} tekstiä hyväksytty viimeisimmissä täysistunnoissa:`,
334
+ de: (n) => `${n} Texte in jüngsten Plenarsitzungen angenommen:`,
335
+ fr: (n) => `${n}\u00a0textes adoptés lors des récentes sessions plénières\u00a0:`,
336
+ es: (n) => `${n} textos adoptados en recientes sesiones plenarias:`,
337
+ nl: (n) => `${n} teksten aangenomen in recente plenaire vergaderingen:`,
338
+ ar: (n) => `تم اعتماد ${n} نصاً في جلسات البرلمان الأخيرة:`,
339
+ he: (n) => `${n} טקסטים אומצו בישיבות המליאה האחרונות:`,
340
+ ja: (n) => `最近の本会議セッションで ${n} 件のテキストが採択されました:`,
341
+ ko: (n) => `최근 전체 회의에서 ${n}개의 텍스트가 채택되었습니다:`,
342
+ zh: (n) => `最近全体会议共通过了 ${n} 份文本:`,
343
+ };
344
+ /**
345
+ * Build an HTML section listing recently adopted texts from EP feed data.
346
+ * Groups texts by adoption date and renders them as a structured list.
347
+ *
348
+ * @param adoptedTexts - Adopted text feed items
349
+ * @param language - BCP 47 language code
350
+ * @returns HTML section string, or empty string if no texts
351
+ */
352
+ export function buildAdoptedTextsSection(adoptedTexts, language) {
353
+ if (adoptedTexts.length === 0)
354
+ return '';
355
+ const heading = ADOPTED_TEXTS_HEADINGS[language] ?? ADOPTED_TEXTS_HEADINGS['en'] ?? 'Recently Adopted Texts';
356
+ const countFn = ADOPTED_TEXTS_COUNT_STRINGS[language] ?? ADOPTED_TEXTS_COUNT_STRINGS['en'];
357
+ const countText = countFn(adoptedTexts.length);
358
+ const unknownDate = ADOPTED_TEXTS_DATE_UNKNOWN_STRINGS[language] ?? ADOPTED_TEXTS_DATE_UNKNOWN_STRINGS['en'];
359
+ // Group by date, sort most recent first
360
+ const byDate = new Map();
361
+ for (const item of adoptedTexts) {
362
+ const date = item.date || unknownDate;
363
+ const group = byDate.get(date) ?? [];
364
+ group.push(item);
365
+ byDate.set(date, group);
366
+ }
367
+ const sortedDates = [...byDate.keys()].sort().reverse();
368
+ let itemsHtml = '';
369
+ for (const date of sortedDates) {
370
+ const items = byDate.get(date) ?? [];
371
+ for (const item of items) {
372
+ const ref = item.identifier ?? item.id;
373
+ const title = item.title || ref;
374
+ itemsHtml += `
375
+ <li class="adopted-text-item">
376
+ <strong>${escapeHTML(title)}</strong>
377
+ <span class="feed-label">${escapeHTML(ref)}</span>
378
+ <span class="feed-date">${escapeHTML(date)}</span>
379
+ </li>`;
380
+ }
381
+ }
382
+ return `
383
+ <section class="adopted-texts-feed" lang="${escapeHTML(language)}">
384
+ <h2>${escapeHTML(heading)}</h2>
385
+ <p>${escapeHTML(countText)}</p>
386
+ <ul class="adopted-texts-list">
387
+ ${itemsHtml}
388
+ </ul>
389
+ </section>`;
390
+ }
391
+ //# sourceMappingURL=motions-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motions-content.js","sourceRoot":"","sources":["../../src/generators/motions-content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { parsePlenarySessions, parseEPEvents, parseCommitteeMeetings, parseLegislativeDocuments, parseLegislativePipeline, parseParliamentaryQuestions, buildWeekAheadContent, buildKeywords, PLACEHOLDER_EVENTS, buildWhatToWatchSection, buildStakeholderImpactMatrix, computeWeekPoliticalTemperature } from './week-ahead-content.js';
3
+ import { buildBreakingNewsContent, scoreBreakingNewsSignificance, SIGNIFICANCE_THRESHOLD } from './breaking-content.js';
4
+ import { applyCommitteeInfo, applyDocuments, applyEffectiveness, FEATURED_COMMITTEES } from './committee-helpers.js';
5
+ import { PLACEHOLDER_MARKER, getMotionsFallbackData, generateMotionsContent, buildPoliticalAlignmentSection } from './motions-content.js';
6
+ import { buildPropositionsContent } from './propositions-content.js';
7
+ import type { PipelineData } from './propositions-content.js';
8
+ export { parsePlenarySessions, parseEPEvents, parseCommitteeMeetings, parseLegislativeDocuments, parseLegislativePipeline, parseParliamentaryQuestions, buildWeekAheadContent, buildKeywords, PLACEHOLDER_EVENTS, buildWhatToWatchSection, buildStakeholderImpactMatrix, computeWeekPoliticalTemperature, };
9
+ export { buildBreakingNewsContent, scoreBreakingNewsSignificance, SIGNIFICANCE_THRESHOLD };
10
+ export { applyCommitteeInfo, applyDocuments, applyEffectiveness, FEATURED_COMMITTEES };
11
+ export { PLACEHOLDER_MARKER, getMotionsFallbackData, generateMotionsContent, buildPoliticalAlignmentSection, };
12
+ export { buildPropositionsContent };
13
+ export type { PipelineData };
14
+ //# sourceMappingURL=news-enhanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"news-enhanced.d.ts","sourceRoot":"","sources":["../../src/generators/news-enhanced.ts"],"names":[],"mappings":";AAiEA,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,4BAA4B,EAC5B,+BAA+B,EAChC,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,8BAA8B,EAC/B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI9D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,4BAA4B,EAC5B,+BAA+B,GAChC,CAAC;AACF,OAAO,EAAE,wBAAwB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;AACvF,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,8BAA8B,GAC/B,CAAC;AACF,OAAO,EAAE,wBAAwB,EAAE,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ /**
5
+ * @module Generators/NewsEnhanced
6
+ * @description CLI orchestrator for European Parliament news generation.
7
+ *
8
+ * Coordinates the three-stage pipeline (fetch → generate → output)
9
+ * via dedicated pipeline-stage modules and a strategy registry. Each article
10
+ * type is handled by its own {@link ArticleStrategy} implementation.
11
+ *
12
+ * Pipeline stages:
13
+ * - {@link module:Generators/Pipeline/FetchStage}
14
+ * - {@link module:Generators/Pipeline/GenerateStage}
15
+ * - {@link module:Generators/Pipeline/OutputStage}
16
+ *
17
+ * Article strategies:
18
+ * - {@link module:Generators/Strategies/WeekAheadStrategy}
19
+ * - {@link module:Generators/Strategies/MonthAheadStrategy}
20
+ * - {@link module:Generators/Strategies/BreakingNewsStrategy}
21
+ * - {@link module:Generators/Strategies/CommitteeReportsStrategy}
22
+ * - {@link module:Generators/Strategies/PropositionsStrategy}
23
+ * - {@link module:Generators/Strategies/MotionsStrategy}
24
+ * - {@link module:Generators/Strategies/WeeklyReviewStrategy}
25
+ * - {@link module:Generators/Strategies/MonthlyReviewStrategy}
26
+ *
27
+ * Bounded-context content modules (re-exported for backward compatibility):
28
+ * - {@link module:Generators/WeekAheadContent}
29
+ * - {@link module:Generators/BreakingContent}
30
+ * - {@link module:Generators/CommitteeHelpers}
31
+ * - {@link module:Generators/MotionsContent}
32
+ * - {@link module:Generators/PropositionsContent}
33
+ */
34
+ import path, { resolve } from 'path';
35
+ import { pathToFileURL } from 'url';
36
+ import { NEWS_DIR, METADATA_DIR, VALID_ARTICLE_CATEGORIES, ARTICLE_TYPE_WEEK_AHEAD, ARG_SEPARATOR, } from '../constants/config.js';
37
+ import { ALL_LANGUAGES, LANGUAGE_PRESETS, isSupportedLanguage } from '../constants/languages.js';
38
+ import { closeEPMCPClient } from '../mcp/ep-mcp-client.js';
39
+ import { ensureDirectoryExists } from '../utils/file-utils.js';
40
+ // ─── Pipeline-stage imports ───────────────────────────────────────────────────
41
+ import { initializeMCPClient } from './pipeline/fetch-stage.js';
42
+ import { createStrategyRegistry, generateArticleForStrategy } from './pipeline/generate-stage.js';
43
+ import { writeGenerationMetadata } from './pipeline/output-stage.js';
44
+ // ─── Content-module imports (bounded contexts) ───────────────────────────────
45
+ import { parsePlenarySessions, parseEPEvents, parseCommitteeMeetings, parseLegislativeDocuments, parseLegislativePipeline, parseParliamentaryQuestions, buildWeekAheadContent, buildKeywords, PLACEHOLDER_EVENTS, buildWhatToWatchSection, buildStakeholderImpactMatrix, computeWeekPoliticalTemperature, } from './week-ahead-content.js';
46
+ import { buildBreakingNewsContent, scoreBreakingNewsSignificance, SIGNIFICANCE_THRESHOLD, } from './breaking-content.js';
47
+ import { applyCommitteeInfo, applyDocuments, applyEffectiveness, FEATURED_COMMITTEES, } from './committee-helpers.js';
48
+ import { PLACEHOLDER_MARKER, getMotionsFallbackData, generateMotionsContent, buildPoliticalAlignmentSection, } from './motions-content.js';
49
+ import { buildPropositionsContent } from './propositions-content.js';
50
+ // ─── Re-exports for backward compatibility (tests import from this module) ───
51
+ export { parsePlenarySessions, parseEPEvents, parseCommitteeMeetings, parseLegislativeDocuments, parseLegislativePipeline, parseParliamentaryQuestions, buildWeekAheadContent, buildKeywords, PLACEHOLDER_EVENTS, buildWhatToWatchSection, buildStakeholderImpactMatrix, computeWeekPoliticalTemperature, };
52
+ export { buildBreakingNewsContent, scoreBreakingNewsSignificance, SIGNIFICANCE_THRESHOLD };
53
+ export { applyCommitteeInfo, applyDocuments, applyEffectiveness, FEATURED_COMMITTEES };
54
+ export { PLACEHOLDER_MARKER, getMotionsFallbackData, generateMotionsContent, buildPoliticalAlignmentSection, };
55
+ export { buildPropositionsContent };
56
+ // ─── CLI argument parsing ─────────────────────────────────────────────────────
57
+ const useMCP = process.env['USE_EP_MCP'] !== 'false';
58
+ const args = process.argv.slice(2);
59
+ const typesArg = args.find((arg) => arg.startsWith('--types='));
60
+ const languagesArg = args.find((arg) => arg.startsWith('--languages='));
61
+ const feedDataArg = args.find((arg) => arg.startsWith('--feed-data='));
62
+ const dryRunArg = args.includes('--dry-run');
63
+ const skipExistingArg = args.includes('--skip-existing');
64
+ /** Path to a JSON file containing pre-fetched EP feed data (optional). */
65
+ const feedDataPath = feedDataArg?.startsWith('--feed-data=')
66
+ ? feedDataArg.slice('--feed-data='.length).trim()
67
+ : '';
68
+ const articleTypes = typesArg
69
+ ? (typesArg.split(ARG_SEPARATOR)[1] ?? '').split(',').map((t) => t.trim())
70
+ : [ARTICLE_TYPE_WEEK_AHEAD];
71
+ let languagesInput = languagesArg
72
+ ? (languagesArg.split(ARG_SEPARATOR)[1] ?? '').trim().toLowerCase()
73
+ : 'en';
74
+ // Expand presets
75
+ if (LANGUAGE_PRESETS[languagesInput]) {
76
+ languagesInput = LANGUAGE_PRESETS[languagesInput].join(',');
77
+ }
78
+ const languages = languagesInput
79
+ .split(',')
80
+ .map((l) => l.trim())
81
+ .filter((l) => isSupportedLanguage(l));
82
+ if (languages.length === 0) {
83
+ console.error('❌ No valid language codes provided. Valid codes:', ALL_LANGUAGES.join(', '));
84
+ process.exit(1);
85
+ }
86
+ // Validate article types
87
+ const invalidTypes = articleTypes.filter((t) => !VALID_ARTICLE_CATEGORIES.includes(t.trim()));
88
+ if (invalidTypes.length > 0) {
89
+ console.warn(`⚠️ Unknown article types ignored: ${invalidTypes.join(', ')}`);
90
+ }
91
+ console.log('📰 Enhanced News Generation Script');
92
+ console.log('Article types:', articleTypes.join(', '));
93
+ console.log('Languages:', languages.join(', '));
94
+ console.log('Dry run:', dryRunArg ? 'Yes (no files written)' : 'No');
95
+ console.log('Skip existing:', skipExistingArg ? 'Yes' : 'No');
96
+ if (feedDataPath) {
97
+ console.log('Feed data file:', feedDataPath);
98
+ }
99
+ // Ensure directories exist
100
+ ensureDirectoryExists(METADATA_DIR);
101
+ ensureDirectoryExists(NEWS_DIR);
102
+ // Generation statistics
103
+ const stats = {
104
+ generated: 0,
105
+ skipped: 0,
106
+ dryRun: 0,
107
+ errors: 0,
108
+ articles: [],
109
+ timestamp: new Date().toISOString(),
110
+ };
111
+ // ─── Main orchestration ───────────────────────────────────────────────────────
112
+ /**
113
+ * Main execution: initialise the MCP client, iterate over requested article
114
+ * types, delegate to the appropriate strategy, then persist metadata.
115
+ */
116
+ async function main() {
117
+ console.log('');
118
+ console.log('🚀 Starting news generation...');
119
+ console.log('');
120
+ // When --feed-data is provided, expose the path via env so strategies can
121
+ // load pre-fetched data without requiring a live MCP connection.
122
+ if (feedDataPath) {
123
+ process.env['EP_FEED_DATA_FILE'] = feedDataPath;
124
+ console.log(`📂 Pre-fetched feed data will be loaded from: ${feedDataPath}`);
125
+ }
126
+ const client = await initializeMCPClient(useMCP);
127
+ const outputOptions = {
128
+ dryRun: dryRunArg,
129
+ skipExisting: skipExistingArg,
130
+ newsDir: path.resolve(NEWS_DIR),
131
+ };
132
+ const registry = createStrategyRegistry();
133
+ try {
134
+ const results = [];
135
+ for (const articleType of articleTypes) {
136
+ if (!VALID_ARTICLE_CATEGORIES.includes(articleType)) {
137
+ console.log(`⏭️ Skipping unknown article type: ${articleType}`);
138
+ continue;
139
+ }
140
+ const strategy = registry.get(articleType);
141
+ if (!strategy) {
142
+ console.log(`⏭️ Article type "${articleType}" not yet implemented`);
143
+ continue;
144
+ }
145
+ results.push(await generateArticleForStrategy(strategy, client, languages, outputOptions, stats));
146
+ }
147
+ console.log('');
148
+ console.log('📊 Generation Summary:');
149
+ console.log(` ✅ Generated: ${stats.generated} articles`);
150
+ console.log(` ⏭️ Skipped: ${stats.skipped} articles`);
151
+ if (dryRunArg)
152
+ console.log(` 🔍 Dry run: ${stats.dryRun} articles`);
153
+ console.log(` ❌ Errors: ${stats.errors}`);
154
+ console.log('');
155
+ writeGenerationMetadata(stats, results, client !== null, METADATA_DIR, dryRunArg);
156
+ }
157
+ finally {
158
+ if (client) {
159
+ console.log('🔌 Closing MCP client connection...');
160
+ await closeEPMCPClient();
161
+ }
162
+ }
163
+ process.exit(stats.errors > 0 ? 1 : 0);
164
+ }
165
+ // Only run main when executed directly (not when imported)
166
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
167
+ main();
168
+ }
169
+ //# sourceMappingURL=news-enhanced.js.map