@gaulatti/giorgia 0.1.57

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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/carousels.d.ts +1 -0
  4. package/dist/carousels.js +65 -0
  5. package/dist/components/live-program/LiveProgram.d.ts +9 -0
  6. package/dist/components/live-program/LiveProgram.js +751 -0
  7. package/dist/components/live-program/assets.d.ts +14 -0
  8. package/dist/components/live-program/assets.js +14 -0
  9. package/dist/components/live-program/components/Marquee.d.ts +16 -0
  10. package/dist/components/live-program/components/Marquee.js +88 -0
  11. package/dist/components/live-program/components/MarqueeCurtain.d.ts +5 -0
  12. package/dist/components/live-program/components/MarqueeCurtain.js +30 -0
  13. package/dist/components/live-program/components/WorldClocks.d.ts +19 -0
  14. package/dist/components/live-program/components/WorldClocks.js +101 -0
  15. package/dist/components/live-program/components/slides/ArticleSlide.d.ts +14 -0
  16. package/dist/components/live-program/components/slides/ArticleSlide.js +32 -0
  17. package/dist/components/live-program/components/slides/CallsignSlide.d.ts +6 -0
  18. package/dist/components/live-program/components/slides/CallsignSlide.js +49 -0
  19. package/dist/components/live-program/components/slides/LiveEventSlide.d.ts +9 -0
  20. package/dist/components/live-program/components/slides/LiveEventSlide.js +86 -0
  21. package/dist/components/live-program/components/slides/slideStyles.d.ts +1 -0
  22. package/dist/components/live-program/components/slides/slideStyles.js +64 -0
  23. package/dist/components/live-program/events.d.ts +34 -0
  24. package/dist/components/live-program/events.js +167 -0
  25. package/dist/components/live-program/hooks/useSSE.d.ts +11 -0
  26. package/dist/components/live-program/hooks/useSSE.js +107 -0
  27. package/dist/components/live-program/i18n.d.ts +4 -0
  28. package/dist/components/live-program/i18n.js +305 -0
  29. package/dist/components/live-program/segments/ArticlesSegment.d.ts +6 -0
  30. package/dist/components/live-program/segments/ArticlesSegment.js +160 -0
  31. package/dist/components/live-program/segments/EarthquakeSegment.d.ts +16 -0
  32. package/dist/components/live-program/segments/EarthquakeSegment.js +130 -0
  33. package/dist/components/live-program/segments/LiveEventSegment.d.ts +4 -0
  34. package/dist/components/live-program/segments/LiveEventSegment.js +27 -0
  35. package/dist/components/live-program/segments/MarketsSegment.d.ts +12 -0
  36. package/dist/components/live-program/segments/MarketsSegment.js +76 -0
  37. package/dist/components/live-program/segments/WeatherSegment.d.ts +15 -0
  38. package/dist/components/live-program/segments/WeatherSegment.js +119 -0
  39. package/dist/components/live-program/segments/fetchLiveEvents.d.ts +20 -0
  40. package/dist/components/live-program/segments/fetchLiveEvents.js +76 -0
  41. package/dist/components/live-program/segments/index.d.ts +8 -0
  42. package/dist/components/live-program/segments/index.js +8 -0
  43. package/dist/components/live-program/segments/types.d.ts +23 -0
  44. package/dist/components/live-program/segments/types.js +1 -0
  45. package/dist/components/live-program/segments/usePlaylistEngine.d.ts +9 -0
  46. package/dist/components/live-program/segments/usePlaylistEngine.js +108 -0
  47. package/dist/components/live-program/utils/broadcastTime.d.ts +12 -0
  48. package/dist/components/live-program/utils/broadcastTime.js +33 -0
  49. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGD_jZtU.ttf +0 -0
  50. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGFPjZtU.ttf +0 -0
  51. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGGHiZtU.ttf +0 -0
  52. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGGHjZtU.ttf +0 -0
  53. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGIbkZtU.ttf +0 -0
  54. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGL_kZtU.ttf +0 -0
  55. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGMjkZtU.ttf +0 -0
  56. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGOHjZtU.ttf +0 -0
  57. package/dist/fonts/LDIcapOFNxEwR-Bd1O9uYNmnUQomAgE25imKSbHhROjLsZBWTSrQGOHkZtU.ttf +0 -0
  58. package/dist/fonts/SlGDmQSNjdsmc35JDF1K5E55YMjF_7DPuGi-2fRUAw.ttf +0 -0
  59. package/dist/fonts/SlGDmQSNjdsmc35JDF1K5E55YMjF_7DPuGi-6_RUAw.ttf +0 -0
  60. package/dist/fonts/SlGDmQSNjdsmc35JDF1K5E55YMjF_7DPuGi-DPNUAw.ttf +0 -0
  61. package/dist/fonts/SlGDmQSNjdsmc35JDF1K5E55YMjF_7DPuGi-NfNUAw.ttf +0 -0
  62. package/dist/fonts/SlGDmQSNjdsmc35JDF1K5E55YMjF_7DPuGi-a_NUAw.ttf +0 -0
  63. package/dist/fonts/SlGFmQSNjdsmc35JDF1K5GRwUjcdlttVFm-rI7c8R496.ttf +0 -0
  64. package/dist/fonts/SlGFmQSNjdsmc35JDF1K5GRwUjcdlttVFm-rI7dbR496.ttf +0 -0
  65. package/dist/fonts/SlGFmQSNjdsmc35JDF1K5GRwUjcdlttVFm-rI7diR496.ttf +0 -0
  66. package/dist/fonts/SlGFmQSNjdsmc35JDF1K5GRwUjcdlttVFm-rI7e8QI96.ttf +0 -0
  67. package/dist/fonts/SlGFmQSNjdsmc35JDF1K5GRwUjcdlttVFm-rI7eOQI96.ttf +0 -0
  68. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs13FvgUE.ttf +0 -0
  69. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs169vgUE.ttf +0 -0
  70. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs18NvgUE.ttf +0 -0
  71. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs1_FvgUE.ttf +0 -0
  72. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs1xZogUE.ttf +0 -0
  73. package/dist/fonts/TK3_WkUHHAIjg75cFRf3bXL8LICs1y9ogUE.ttf +0 -0
  74. package/dist/fonts/fonts.css +378 -0
  75. package/dist/fonts/j8_16_LD37rqfuwxyIuaZhE6cRXOLtm2gfTGgQ.ttf +0 -0
  76. package/dist/fonts/j8_46_LD37rqfuwxyIuaZhE6cRXOLtm2gfT-BYipBw.ttf +0 -0
  77. package/dist/fonts/j8_46_LD37rqfuwxyIuaZhE6cRXOLtm2gfT-IYmpBw.ttf +0 -0
  78. package/dist/fonts/j8_46_LD37rqfuwxyIuaZhE6cRXOLtm2gfT-PYqpBw.ttf +0 -0
  79. package/dist/fonts/j8_46_LD37rqfuwxyIuaZhE6cRXOLtm2gfT-WYupBw.ttf +0 -0
  80. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oYiRNDM.ttf +0 -0
  81. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oZ8RNDM.ttf +0 -0
  82. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oZ8RdDM.ttf +0 -0
  83. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oZORNDM.ttf +0 -0
  84. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oabQ9DM.ttf +0 -0
  85. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05oaiQ9DM.ttf +0 -0
  86. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05ob8Q9DM.ttf +0 -0
  87. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05ob8RNDM.ttf +0 -0
  88. package/dist/fonts/jizMREVItHgc8qDIbSTKq4XkRiUawTk7f45UM9y05obVQ9DM.ttf +0 -0
  89. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduh8MKUBw.ttf +0 -0
  90. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhHMWUBw.ttf +0 -0
  91. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhLsSUBw.ttf +0 -0
  92. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhLsWUBw.ttf +0 -0
  93. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhcMWUBw.ttf +0 -0
  94. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhh8KUBw.ttf +0 -0
  95. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhrsKUBw.ttf +0 -0
  96. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhrsWUBw.ttf +0 -0
  97. package/dist/fonts/jizOREVItHgc8qDIbSTKq4XkRg8T88bjFuXOnduhycKUBw.ttf +0 -0
  98. package/dist/homepage-distributor.d.ts +55 -0
  99. package/dist/homepage-distributor.js +68 -0
  100. package/dist/instagram-image-template.d.ts +9 -0
  101. package/dist/instagram-image-template.js +51 -0
  102. package/dist/live-program/main.d.ts +1 -0
  103. package/dist/live-program/main.js +10 -0
  104. package/dist/live-program-page/fifthbell/audio/pipes.ogg +0 -0
  105. package/dist/live-program-page/fifthbell/images/berlin.jpg +0 -0
  106. package/dist/live-program-page/fifthbell/images/fifthbell.png +0 -0
  107. package/dist/live-program-page/fifthbell/images/nyc.jpg +0 -0
  108. package/dist/live-program-page/fifthbell/images/nyse.jpg +0 -0
  109. package/dist/live-program-page/fifthbell/images/santiago.jpg +0 -0
  110. package/dist/live-program-page/fifthbell/images/seismograph.jpg +0 -0
  111. package/dist/live-program-page/fifthbell/images/tokyo.jpg +0 -0
  112. package/dist/live-program-page/index.html +16 -0
  113. package/dist/live-program-page/live-program.css +3 -0
  114. package/dist/live-program-page/live-program.js +76 -0
  115. package/dist/outlet-config.d.ts +29 -0
  116. package/dist/outlet-config.js +29 -0
  117. package/dist/renderer.browser.d.ts +2 -0
  118. package/dist/renderer.browser.js +132 -0
  119. package/dist/renderer.core.d.ts +9 -0
  120. package/dist/renderer.core.js +354 -0
  121. package/dist/renderer.d.ts +6 -0
  122. package/dist/renderer.js +4 -0
  123. package/dist/renderer.node.d.ts +16 -0
  124. package/dist/renderer.node.js +166 -0
  125. package/dist/types/canonical-article.d.ts +249 -0
  126. package/dist/types/canonical-article.js +236 -0
  127. package/dist/utils/sofascore.d.ts +3 -0
  128. package/dist/utils/sofascore.js +31 -0
  129. package/dist/version.d.ts +1 -0
  130. package/dist/version.js +4 -0
  131. package/package.json +89 -0
  132. package/src/partial-deps.json +53 -0
  133. package/src/styles/compiled.css +2 -0
  134. package/src/templates/layouts/404.hbs +5 -0
  135. package/src/templates/layouts/article-page.hbs +5 -0
  136. package/src/templates/layouts/category-page.hbs +5 -0
  137. package/src/templates/layouts/homepage.hbs +5 -0
  138. package/src/templates/layouts/link-in-bio.hbs +226 -0
  139. package/src/templates/layouts/live-story.hbs +5 -0
  140. package/src/templates/layouts/media-page.hbs +5 -0
  141. package/src/templates/layouts/search-page.hbs +5 -0
  142. package/src/templates/partials/blocks/audio.hbs +12 -0
  143. package/src/templates/partials/blocks/data-table.hbs +23 -0
  144. package/src/templates/partials/blocks/divider.hbs +1 -0
  145. package/src/templates/partials/blocks/heading.hbs +9 -0
  146. package/src/templates/partials/blocks/image.hbs +6 -0
  147. package/src/templates/partials/blocks/info-box.hbs +8 -0
  148. package/src/templates/partials/blocks/instagram.hbs +28 -0
  149. package/src/templates/partials/blocks/key-points.hbs +8 -0
  150. package/src/templates/partials/blocks/list.hbs +13 -0
  151. package/src/templates/partials/blocks/live-update.hbs +24 -0
  152. package/src/templates/partials/blocks/pull-quote.hbs +6 -0
  153. package/src/templates/partials/blocks/rich-text.hbs +1 -0
  154. package/src/templates/partials/blocks/tiktok.hbs +15 -0
  155. package/src/templates/partials/blocks/x.hbs +74 -0
  156. package/src/templates/partials/blocks/youtube.hbs +12 -0
  157. package/src/templates/partials/components/article-main.hbs +159 -0
  158. package/src/templates/partials/components/breaking-news/live-updates-column.hbs +29 -0
  159. package/src/templates/partials/components/breaking-news.hbs +56 -0
  160. package/src/templates/partials/components/category/header.hbs +5 -0
  161. package/src/templates/partials/components/category/main-grid.hbs +55 -0
  162. package/src/templates/partials/components/category/main.hbs +7 -0
  163. package/src/templates/partials/components/category/more-grid.hbs +26 -0
  164. package/src/templates/partials/components/editorial-hero.hbs +73 -0
  165. package/src/templates/partials/components/headline.hbs +15 -0
  166. package/src/templates/partials/components/hero-editorial.hbs +1 -0
  167. package/src/templates/partials/components/hero.hbs +1 -0
  168. package/src/templates/partials/components/home/landing.hbs +111 -0
  169. package/src/templates/partials/components/home/main.hbs +63 -0
  170. package/src/templates/partials/components/home/more-stories.hbs +23 -0
  171. package/src/templates/partials/components/home/must-read.hbs +77 -0
  172. package/src/templates/partials/components/live-story/main.hbs +229 -0
  173. package/src/templates/partials/components/media/main.hbs +220 -0
  174. package/src/templates/partials/components/not-found/main.hbs +28 -0
  175. package/src/templates/partials/components/search/main.hbs +420 -0
  176. package/src/templates/partials/components/snack.hbs +92 -0
  177. package/src/templates/partials/components/spotlight-hero.hbs +59 -0
  178. package/src/templates/partials/components/trending.hbs +14 -0
  179. package/src/templates/partials/components/ui/accordion.hbs +30 -0
  180. package/src/templates/partials/components/ui/breadcrumb.hbs +16 -0
  181. package/src/templates/partials/components/ui/icon-button.hbs +19 -0
  182. package/src/templates/partials/components/ui/loading-spinner.hbs +27 -0
  183. package/src/templates/partials/components/ui/pagination.hbs +56 -0
  184. package/src/templates/partials/components/ui/scroll-area.hbs +12 -0
  185. package/src/templates/partials/components/ui/status-badge.hbs +21 -0
  186. package/src/templates/partials/footers/footer-full.hbs +79 -0
  187. package/src/templates/partials/footers/footer-minimal.hbs +5 -0
  188. package/src/templates/partials/headers/header-main.hbs +400 -0
  189. package/src/templates/partials/headers/header-minimal.hbs +16 -0
  190. package/src/templates/partials/nav/nav-categories.hbs +5 -0
  191. package/src/templates/partials/shell/doc-end.hbs +282 -0
  192. package/src/templates/partials/shell/doc-start-404.hbs +41 -0
  193. package/src/templates/partials/shell/doc-start-standard.hbs +86 -0
  194. package/src/templates/templates/instagram-image.hbs +175 -0
@@ -0,0 +1,29 @@
1
+ export declare const outletConfig: {
2
+ readonly siteName: "fifthbell";
3
+ readonly publicSiteUrl: "https://fifthbell.com";
4
+ readonly cdnUrl: "https://cdn.fifthbell.com";
5
+ readonly contentPath: "/content";
6
+ readonly inventoryFilename: "cronkite-inventory.json";
7
+ readonly defaultLanguage: "en";
8
+ readonly supportedLanguages: readonly ["en", "es", "it"];
9
+ readonly prefixDefaultLocale: false;
10
+ readonly defaultAuthor: {
11
+ readonly name: "Fifthbell Newsroom";
12
+ readonly slug: "fifthbell-newsroom";
13
+ };
14
+ readonly defaultCategory: {
15
+ readonly name: "Top Stories";
16
+ readonly slug: "top-stories";
17
+ };
18
+ readonly linkInBioRoute: "/instagram";
19
+ readonly searchTitle: "Search";
20
+ readonly searchDescriptions: {
21
+ readonly en: "Search stories from Fifthbell.";
22
+ readonly es: "Busca noticias de Fifthbell.";
23
+ readonly it: "Cerca notizie Fifthbell.";
24
+ };
25
+ readonly socialLanguages: readonly ["en"];
26
+ readonly socialUserAgent: "Cronkite/1.0";
27
+ readonly socialImageExport: "buildInstagramImageHtml";
28
+ readonly hashtagServiceBaseUrl: "http://192.168.0.99:8000";
29
+ };
@@ -0,0 +1,29 @@
1
+ export const outletConfig = {
2
+ siteName: 'fifthbell',
3
+ publicSiteUrl: 'https://fifthbell.com',
4
+ cdnUrl: 'https://cdn.fifthbell.com',
5
+ contentPath: '/content',
6
+ inventoryFilename: 'cronkite-inventory.json',
7
+ defaultLanguage: 'en',
8
+ supportedLanguages: ['en', 'es', 'it'],
9
+ prefixDefaultLocale: false,
10
+ defaultAuthor: {
11
+ name: 'Fifthbell Newsroom',
12
+ slug: 'fifthbell-newsroom'
13
+ },
14
+ defaultCategory: {
15
+ name: 'Top Stories',
16
+ slug: 'top-stories'
17
+ },
18
+ linkInBioRoute: '/instagram',
19
+ searchTitle: 'Search',
20
+ searchDescriptions: {
21
+ en: 'Search stories from Fifthbell.',
22
+ es: 'Busca noticias de Fifthbell.',
23
+ it: 'Cerca notizie Fifthbell.'
24
+ },
25
+ socialLanguages: ['en'],
26
+ socialUserAgent: 'Cronkite/1.0',
27
+ socialImageExport: 'buildInstagramImageHtml',
28
+ hashtagServiceBaseUrl: 'http://192.168.0.99:8000'
29
+ };
@@ -0,0 +1,2 @@
1
+ import type { CanonicalDocument } from './types/canonical-article.js';
2
+ export declare function render(document: CanonicalDocument): string;
@@ -0,0 +1,132 @@
1
+ import articleLayoutHbs from './templates/layouts/article-page.hbs?raw';
2
+ import homepageLayoutHbs from './templates/layouts/homepage.hbs?raw';
3
+ import categoryLayoutHbs from './templates/layouts/category-page.hbs?raw';
4
+ import searchLayoutHbs from './templates/layouts/search-page.hbs?raw';
5
+ import notFoundLayoutHbs from './templates/layouts/404.hbs?raw';
6
+ import liveStoryLayoutHbs from './templates/layouts/live-story.hbs?raw';
7
+ import linkInBioLayoutHbs from './templates/layouts/link-in-bio.hbs?raw';
8
+ import mediaPageLayoutHbs from './templates/layouts/media-page.hbs?raw';
9
+ import headerMainHbs from './templates/partials/headers/header-main.hbs?raw';
10
+ import headerMinimalHbs from './templates/partials/headers/header-minimal.hbs?raw';
11
+ import footerFullHbs from './templates/partials/footers/footer-full.hbs?raw';
12
+ import footerMinimalHbs from './templates/partials/footers/footer-minimal.hbs?raw';
13
+ import navCategoriesHbs from './templates/partials/nav/nav-categories.hbs?raw';
14
+ import shellDocStartStandardHbs from './templates/partials/shell/doc-start-standard.hbs?raw';
15
+ import shellDocStart404Hbs from './templates/partials/shell/doc-start-404.hbs?raw';
16
+ import shellDocEndHbs from './templates/partials/shell/doc-end.hbs?raw';
17
+ import blockRichTextHbs from './templates/partials/blocks/rich-text.hbs?raw';
18
+ import blockHeadingHbs from './templates/partials/blocks/heading.hbs?raw';
19
+ import blockImageHbs from './templates/partials/blocks/image.hbs?raw';
20
+ import blockListHbs from './templates/partials/blocks/list.hbs?raw';
21
+ import blockDividerHbs from './templates/partials/blocks/divider.hbs?raw';
22
+ import blockInfoBoxHbs from './templates/partials/blocks/info-box.hbs?raw';
23
+ import blockKeyPointsHbs from './templates/partials/blocks/key-points.hbs?raw';
24
+ import blockDataTableHbs from './templates/partials/blocks/data-table.hbs?raw';
25
+ import blockLiveUpdateHbs from './templates/partials/blocks/live-update.hbs?raw';
26
+ import blockAudioHbs from './templates/partials/blocks/audio.hbs?raw';
27
+ import blockYoutubeHbs from './templates/partials/blocks/youtube.hbs?raw';
28
+ import blockXHbs from './templates/partials/blocks/x.hbs?raw';
29
+ import blockInstagramHbs from './templates/partials/blocks/instagram.hbs?raw';
30
+ import blockTikTokHbs from './templates/partials/blocks/tiktok.hbs?raw';
31
+ import blockPullQuoteHbs from './templates/partials/blocks/pull-quote.hbs?raw';
32
+ import componentArticleMainHbs from './templates/partials/components/article-main.hbs?raw';
33
+ import componentBreakingNewsHbs from './templates/partials/components/breaking-news.hbs?raw';
34
+ import componentBreakingNewsLiveUpdatesColumnHbs from './templates/partials/components/breaking-news/live-updates-column.hbs?raw';
35
+ import componentSnackHbs from './templates/partials/components/snack.hbs?raw';
36
+ import componentHeadlineHbs from './templates/partials/components/headline.hbs?raw';
37
+ import componentHeroHbs from './templates/partials/components/hero.hbs?raw';
38
+ import componentHeroEditorialHbs from './templates/partials/components/hero-editorial.hbs?raw';
39
+ import componentSpotlightHeroHbs from './templates/partials/components/spotlight-hero.hbs?raw';
40
+ import componentEditorialHeroHbs from './templates/partials/components/editorial-hero.hbs?raw';
41
+ import componentTrendingHbs from './templates/partials/components/trending.hbs?raw';
42
+ import componentHomeMainHbs from './templates/partials/components/home/main.hbs?raw';
43
+ import componentHomeLandingHbs from './templates/partials/components/home/landing.hbs?raw';
44
+ import componentHomeMustReadHbs from './templates/partials/components/home/must-read.hbs?raw';
45
+ import componentHomeMoreStoriesHbs from './templates/partials/components/home/more-stories.hbs?raw';
46
+ import componentCategoryMainHbs from './templates/partials/components/category/main.hbs?raw';
47
+ import componentCategoryHeaderHbs from './templates/partials/components/category/header.hbs?raw';
48
+ import componentCategoryMainGridHbs from './templates/partials/components/category/main-grid.hbs?raw';
49
+ import componentCategoryMoreGridHbs from './templates/partials/components/category/more-grid.hbs?raw';
50
+ import componentSearchMainHbs from './templates/partials/components/search/main.hbs?raw';
51
+ import componentNotFoundMainHbs from './templates/partials/components/not-found/main.hbs?raw';
52
+ import componentLiveStoryMainHbs from './templates/partials/components/live-story/main.hbs?raw';
53
+ import componentMediaMainHbs from './templates/partials/components/media/main.hbs?raw';
54
+ import componentUiAccordionHbs from './templates/partials/components/ui/accordion.hbs?raw';
55
+ import componentUiBreadcrumbHbs from './templates/partials/components/ui/breadcrumb.hbs?raw';
56
+ import componentUiIconButtonHbs from './templates/partials/components/ui/icon-button.hbs?raw';
57
+ import componentUiLoadingSpinnerHbs from './templates/partials/components/ui/loading-spinner.hbs?raw';
58
+ import componentUiPaginationHbs from './templates/partials/components/ui/pagination.hbs?raw';
59
+ import componentUiScrollAreaHbs from './templates/partials/components/ui/scroll-area.hbs?raw';
60
+ import componentUiStatusBadgeHbs from './templates/partials/components/ui/status-badge.hbs?raw';
61
+ import styles from './styles/compiled.css?raw';
62
+ import { renderWithAssets } from './renderer.core.js';
63
+ const assets = {
64
+ layouts: {
65
+ 'article-page': articleLayoutHbs,
66
+ homepage: homepageLayoutHbs,
67
+ 'category-page': categoryLayoutHbs,
68
+ 'search-page': searchLayoutHbs,
69
+ '404': notFoundLayoutHbs,
70
+ 'live-story': liveStoryLayoutHbs,
71
+ 'link-in-bio': linkInBioLayoutHbs,
72
+ 'media-page': mediaPageLayoutHbs
73
+ },
74
+ partials: {
75
+ 'headers/header-main': headerMainHbs,
76
+ 'headers/header-minimal': headerMinimalHbs,
77
+ 'footers/footer-full': footerFullHbs,
78
+ 'footers/footer-minimal': footerMinimalHbs,
79
+ 'nav/nav-categories': navCategoriesHbs,
80
+ 'shell/doc-start-standard': shellDocStartStandardHbs,
81
+ 'shell/doc-start-404': shellDocStart404Hbs,
82
+ 'shell/doc-end': shellDocEndHbs,
83
+ 'blocks/rich-text': blockRichTextHbs,
84
+ 'blocks/heading': blockHeadingHbs,
85
+ 'blocks/image': blockImageHbs,
86
+ 'blocks/list': blockListHbs,
87
+ 'blocks/divider': blockDividerHbs,
88
+ 'blocks/info-box': blockInfoBoxHbs,
89
+ 'blocks/key-points': blockKeyPointsHbs,
90
+ 'blocks/data-table': blockDataTableHbs,
91
+ 'blocks/live-update': blockLiveUpdateHbs,
92
+ 'blocks/audio': blockAudioHbs,
93
+ 'blocks/youtube': blockYoutubeHbs,
94
+ 'blocks/x': blockXHbs,
95
+ 'blocks/instagram': blockInstagramHbs,
96
+ 'blocks/tiktok': blockTikTokHbs,
97
+ 'blocks/pull-quote': blockPullQuoteHbs,
98
+ 'components/article-main': componentArticleMainHbs,
99
+ 'components/breaking-news': componentBreakingNewsHbs,
100
+ 'components/breaking-news/live-updates-column': componentBreakingNewsLiveUpdatesColumnHbs,
101
+ 'components/snack': componentSnackHbs,
102
+ 'components/headline': componentHeadlineHbs,
103
+ 'components/spotlight-hero': componentSpotlightHeroHbs,
104
+ 'components/editorial-hero': componentEditorialHeroHbs,
105
+ 'components/hero': componentHeroHbs,
106
+ 'components/hero-editorial': componentHeroEditorialHbs,
107
+ 'components/trending': componentTrendingHbs,
108
+ 'components/home/main': componentHomeMainHbs,
109
+ 'components/home/landing': componentHomeLandingHbs,
110
+ 'components/home/must-read': componentHomeMustReadHbs,
111
+ 'components/home/more-stories': componentHomeMoreStoriesHbs,
112
+ 'components/category/main': componentCategoryMainHbs,
113
+ 'components/category/header': componentCategoryHeaderHbs,
114
+ 'components/category/main-grid': componentCategoryMainGridHbs,
115
+ 'components/category/more-grid': componentCategoryMoreGridHbs,
116
+ 'components/search/main': componentSearchMainHbs,
117
+ 'components/not-found/main': componentNotFoundMainHbs,
118
+ 'components/live-story/main': componentLiveStoryMainHbs,
119
+ 'components/media/main': componentMediaMainHbs,
120
+ 'components/ui/accordion': componentUiAccordionHbs,
121
+ 'components/ui/breadcrumb': componentUiBreadcrumbHbs,
122
+ 'components/ui/icon-button': componentUiIconButtonHbs,
123
+ 'components/ui/loading-spinner': componentUiLoadingSpinnerHbs,
124
+ 'components/ui/pagination': componentUiPaginationHbs,
125
+ 'components/ui/scroll-area': componentUiScrollAreaHbs,
126
+ 'components/ui/status-badge': componentUiStatusBadgeHbs
127
+ },
128
+ styles
129
+ };
130
+ export function render(document) {
131
+ return renderWithAssets(document, assets);
132
+ }
@@ -0,0 +1,9 @@
1
+ import { type CanonicalDocument } from './types/canonical-article.js';
2
+ export type LayoutName = CanonicalDocument['layout'];
3
+ export type RendererAssets = {
4
+ layouts: Record<LayoutName, string>;
5
+ partials: Record<string, string>;
6
+ styles: string;
7
+ };
8
+ export declare function initializeHandlebars(assets: RendererAssets): void;
9
+ export declare function renderWithAssets(doc: CanonicalDocument, assets: RendererAssets): string;
@@ -0,0 +1,354 @@
1
+ import Handlebars from 'handlebars';
2
+ import { canonicalArticleSchema } from './types/canonical-article.js';
3
+ import { distributeHomepageArticles } from './homepage-distributor.js';
4
+ import { buildSofascoreAttackMomentumUrl, buildSofascoreMatchUrl } from './utils/sofascore.js';
5
+ let initialized = false;
6
+ const layoutCache = new Map();
7
+ let runtimeStyles = '';
8
+ const removedBlockTypes = new Set(['truthSocial', 'truthsocial', 'truth-social', 'truth_social']);
9
+ const siteTitlesByLanguage = {
10
+ en: 'fifthbell - Breaking News & Current Events',
11
+ es: 'fifthbell - Noticias de última hora y actualidad',
12
+ it: 'fifthbell - Ultime notizie e attualità'
13
+ };
14
+ function normalizePathInput(value) {
15
+ if (typeof value !== 'string')
16
+ return '';
17
+ const trimmed = value.trim();
18
+ if (!trimmed)
19
+ return '';
20
+ try {
21
+ if (/^https?:\/\//i.test(trimmed)) {
22
+ const parsed = new URL(trimmed);
23
+ const normalizedAbsolute = `/${(parsed.pathname || '').replace(/^\/+/, '')}`.replace(/\/{2,}/g, '/');
24
+ if (normalizedAbsolute !== '/' && normalizedAbsolute.endsWith('/')) {
25
+ return normalizedAbsolute.slice(0, -1);
26
+ }
27
+ return normalizedAbsolute || '/';
28
+ }
29
+ }
30
+ catch {
31
+ // Fall back to raw string normalization below.
32
+ }
33
+ const withoutQueryOrHash = trimmed.split('#')[0].split('?')[0];
34
+ const normalized = `/${withoutQueryOrHash.replace(/^\/+/, '')}`.replace(/\/{2,}/g, '/');
35
+ if (normalized !== '/' && normalized.endsWith('/')) {
36
+ return normalized.slice(0, -1);
37
+ }
38
+ return normalized;
39
+ }
40
+ function cleanPathSegment(value) {
41
+ if (typeof value !== 'string')
42
+ return '';
43
+ return value.trim().replace(/^\/+|\/+$/g, '');
44
+ }
45
+ function buildLocalePath(path, language) {
46
+ const normalizedLanguage = language === 'es' || language === 'it' ? language : 'en';
47
+ if (!path)
48
+ return normalizedLanguage === 'en' ? '/' : `/${normalizedLanguage}`;
49
+ const normalized = String(path).startsWith('/') ? String(path) : `/${path}`;
50
+ if (normalized.startsWith('/es/') || normalized.startsWith('/it/')) {
51
+ return normalized;
52
+ }
53
+ if (normalizedLanguage === 'en') {
54
+ return normalized;
55
+ }
56
+ return `/${normalizedLanguage}${normalized}`;
57
+ }
58
+ function resolveArticleUrl(input) {
59
+ const explicitUrl = normalizePathInput(input.url);
60
+ if (explicitUrl && explicitUrl !== '/') {
61
+ return buildLocalePath(explicitUrl, input.language);
62
+ }
63
+ const canonicalUrl = normalizePathInput(input.canonicalUrl);
64
+ if (canonicalUrl && canonicalUrl !== '/') {
65
+ return buildLocalePath(canonicalUrl, input.language);
66
+ }
67
+ const slugRaw = typeof input.slug === 'string' ? input.slug : '';
68
+ const normalizedSlugPath = normalizePathInput(slugRaw);
69
+ const slugSegments = normalizedSlugPath.split('/').filter(Boolean);
70
+ if (slugSegments.length > 1) {
71
+ return buildLocalePath(normalizedSlugPath, input.language);
72
+ }
73
+ const slugSegment = cleanPathSegment(slugRaw);
74
+ const categories = Array.isArray(input.categories) ? input.categories : [];
75
+ const primaryCategorySlug = cleanPathSegment(categories[0]?.slug) || cleanPathSegment(input.category?.slug);
76
+ if (slugSegment && primaryCategorySlug) {
77
+ return buildLocalePath(`/${primaryCategorySlug}/${slugSegment}`, input.language);
78
+ }
79
+ if (slugSegment) {
80
+ return buildLocalePath(`/${slugSegment}`, input.language);
81
+ }
82
+ return buildLocalePath('/', input.language);
83
+ }
84
+ function normalizeDocument(doc) {
85
+ const rawBody = doc.body;
86
+ if (!Array.isArray(rawBody))
87
+ return doc;
88
+ return {
89
+ ...doc,
90
+ body: rawBody.filter((block) => {
91
+ if (!block || typeof block !== 'object')
92
+ return true;
93
+ const type = block.type;
94
+ return typeof type !== 'string' || !removedBlockTypes.has(type);
95
+ })
96
+ };
97
+ }
98
+ function registerHelpers() {
99
+ Handlebars.registerHelper('eq', (a, b) => a === b);
100
+ Handlebars.registerHelper('add', (a, b) => Number(a) + Number(b));
101
+ Handlebars.registerHelper('slice', (items, start, end) => {
102
+ if (!Array.isArray(items))
103
+ return [];
104
+ return items.slice(start, end);
105
+ });
106
+ Handlebars.registerHelper('uppercase', (value) => String(value ?? '').toUpperCase());
107
+ Handlebars.registerHelper('coalesce', (...args) => {
108
+ const values = args.slice(0, -1);
109
+ for (const value of values) {
110
+ if (value === null || value === undefined)
111
+ continue;
112
+ if (typeof value === 'string' && value.trim().length === 0)
113
+ continue;
114
+ if (Array.isArray(value) && value.length === 0)
115
+ continue;
116
+ return value;
117
+ }
118
+ return '';
119
+ });
120
+ Handlebars.registerHelper('articleUrl', (...args) => {
121
+ const options = args[args.length - 1];
122
+ const hash = options?.hash;
123
+ const root = options?.data?.root;
124
+ return resolveArticleUrl({
125
+ url: hash?.url,
126
+ canonicalUrl: hash?.canonicalUrl,
127
+ slug: hash?.slug,
128
+ categories: hash?.categories,
129
+ category: hash?.category,
130
+ language: hash?.language ?? root?.language
131
+ });
132
+ });
133
+ Handlebars.registerHelper('formatDate', (isoString) => {
134
+ if (!isoString)
135
+ return '';
136
+ try {
137
+ const date = new Date(isoString);
138
+ const now = new Date();
139
+ const isWithin24h = now.getTime() - date.getTime() < 24 * 60 * 60 * 1000;
140
+ if (isWithin24h) {
141
+ return date.toLocaleTimeString('en-US', {
142
+ hour: 'numeric',
143
+ minute: '2-digit',
144
+ hour12: true,
145
+ timeZone: 'America/New_York'
146
+ });
147
+ }
148
+ else {
149
+ return date.toLocaleDateString('en-US', {
150
+ year: 'numeric',
151
+ month: 'long',
152
+ day: 'numeric',
153
+ timeZone: 'America/New_York'
154
+ });
155
+ }
156
+ }
157
+ catch {
158
+ return isoString;
159
+ }
160
+ });
161
+ Handlebars.registerHelper('xStatusUrl', (url) => {
162
+ if (!url)
163
+ return '';
164
+ try {
165
+ const parsed = new URL(url);
166
+ if (parsed.hostname === 'x.com' || parsed.hostname === 'www.x.com') {
167
+ return `https://twitter.com${parsed.pathname}`;
168
+ }
169
+ return url;
170
+ }
171
+ catch {
172
+ return url;
173
+ }
174
+ });
175
+ Handlebars.registerHelper('xEmbedUrl', (url) => {
176
+ if (!url)
177
+ return '';
178
+ const buildEmbedUrl = (tweetId) => `https://platform.twitter.com/embed/Tweet.html?id=${tweetId}&dnt=true`;
179
+ const idFromRaw = url.match(/status\/(\d+)/)?.[1];
180
+ try {
181
+ const parsed = new URL(url);
182
+ const host = parsed.hostname.replace(/^www\./, '');
183
+ if (host === 'x.com' || host === 'twitter.com') {
184
+ const tweetId = parsed.pathname.match(/\/[^/]+\/status\/(\d+)/)?.[1];
185
+ if (tweetId)
186
+ return buildEmbedUrl(tweetId);
187
+ }
188
+ return idFromRaw ? buildEmbedUrl(idFromRaw) : '';
189
+ }
190
+ catch {
191
+ return idFromRaw ? buildEmbedUrl(idFromRaw) : '';
192
+ }
193
+ });
194
+ Handlebars.registerHelper('xTweetId', (url) => {
195
+ if (!url)
196
+ return '';
197
+ const idFromRaw = url.match(/status\/(\d+)/)?.[1];
198
+ if (idFromRaw)
199
+ return idFromRaw;
200
+ try {
201
+ const parsed = new URL(url);
202
+ const host = parsed.hostname.replace(/^www\./, '');
203
+ if (host === 'x.com' || host === 'twitter.com') {
204
+ return parsed.pathname.match(/\/[^/]+\/status\/(\d+)/)?.[1] ?? '';
205
+ }
206
+ return '';
207
+ }
208
+ catch {
209
+ return '';
210
+ }
211
+ });
212
+ Handlebars.registerHelper('instagramEmbedUrl', (url) => {
213
+ if (!url)
214
+ return '';
215
+ const normalized = url.endsWith('/') ? url : `${url}/`;
216
+ return `${normalized}embed/`;
217
+ });
218
+ Handlebars.registerHelper('tiktokEmbedUrl', (url) => {
219
+ if (!url)
220
+ return '';
221
+ const match = url.match(/\/video\/(\d+)/);
222
+ if (!match)
223
+ return url;
224
+ return `https://www.tiktok.com/embed/v2/${match[1]}`;
225
+ });
226
+ Handlebars.registerHelper('sofascoreWidgetUrl', (id) => buildSofascoreAttackMomentumUrl(id));
227
+ Handlebars.registerHelper('sofascoreMatchUrl', (id) => buildSofascoreMatchUrl(id));
228
+ Handlebars.registerHelper('jsonString', (value) => {
229
+ if (value === undefined)
230
+ return 'null';
231
+ return JSON.stringify(value);
232
+ });
233
+ Handlebars.registerHelper('resolveHeadTitle', (doc) => {
234
+ if (!doc || typeof doc !== 'object')
235
+ return 'fifthbell';
236
+ const page = doc;
237
+ if (page.layout === 'homepage') {
238
+ const language = page.language === 'es' || page.language === 'it' ? page.language : 'en';
239
+ return siteTitlesByLanguage[language];
240
+ }
241
+ if (page.layout === 'category-page') {
242
+ const categoryName = page.categories?.[0]?.name?.trim();
243
+ const baseTitle = categoryName || page.title?.trim() || 'Category';
244
+ return `${baseTitle} | fifthbell`;
245
+ }
246
+ if (page.layout === 'search-page') {
247
+ return 'Search | fifthbell';
248
+ }
249
+ if (page.layout === 'article-page') {
250
+ const baseTitle = page.title?.trim() || 'Article';
251
+ return `${baseTitle} | fifthbell`;
252
+ }
253
+ if (page.layout === '404') {
254
+ return '404 - Page Not Found | fifthbell';
255
+ }
256
+ if (page.layout === 'live-story') {
257
+ const baseTitle = page.title?.trim() || 'Live Story';
258
+ return `${baseTitle} | fifthbell`;
259
+ }
260
+ if (page.layout === 'link-in-bio') {
261
+ const baseTitle = page.title?.trim() || 'Top Stories';
262
+ return `${baseTitle} | fifthbell`;
263
+ }
264
+ const seoTitle = page.seo?.metaTitle?.trim();
265
+ if (seoTitle)
266
+ return seoTitle;
267
+ const baseTitle = page.title?.trim() || 'fifthbell';
268
+ return `${baseTitle} | fifthbell`;
269
+ });
270
+ Handlebars.registerHelper('socialImageUrl', (value) => {
271
+ if (typeof value !== 'string')
272
+ return '';
273
+ const raw = value.trim();
274
+ if (!raw)
275
+ return '';
276
+ const normalizePath = (pathname) => pathname.replace(/\.avif$/i, '.jpg');
277
+ try {
278
+ const parsed = new URL(raw);
279
+ parsed.pathname = normalizePath(parsed.pathname);
280
+ return parsed.toString();
281
+ }
282
+ catch {
283
+ // Support relative URLs in template data.
284
+ return normalizePath(raw);
285
+ }
286
+ });
287
+ }
288
+ function registerPartials(partials) {
289
+ for (const [name, template] of Object.entries(partials)) {
290
+ Handlebars.registerPartial(name, template);
291
+ }
292
+ const bodyAliases = {
293
+ richText: 'blocks/rich-text',
294
+ heading: 'blocks/heading',
295
+ image: 'blocks/image',
296
+ list: 'blocks/list',
297
+ divider: 'blocks/divider',
298
+ infoBox: 'blocks/info-box',
299
+ keyPoints: 'blocks/key-points',
300
+ dataTable: 'blocks/data-table',
301
+ liveUpdate: 'blocks/live-update',
302
+ audio: 'blocks/audio',
303
+ youtube: 'blocks/youtube',
304
+ x: 'blocks/x',
305
+ instagram: 'blocks/instagram',
306
+ tiktok: 'blocks/tiktok',
307
+ pullQuote: 'blocks/pull-quote'
308
+ };
309
+ for (const [alias, partialName] of Object.entries(bodyAliases)) {
310
+ const source = partials[partialName];
311
+ if (source) {
312
+ Handlebars.registerPartial(alias, source);
313
+ }
314
+ }
315
+ }
316
+ function compileLayouts(layouts) {
317
+ for (const [name, source] of Object.entries(layouts)) {
318
+ layoutCache.set(name, Handlebars.compile(source));
319
+ }
320
+ }
321
+ export function initializeHandlebars(assets) {
322
+ if (initialized)
323
+ return;
324
+ registerHelpers();
325
+ registerPartials(assets.partials);
326
+ compileLayouts(assets.layouts);
327
+ runtimeStyles = assets.styles;
328
+ initialized = true;
329
+ }
330
+ export function renderWithAssets(doc, assets) {
331
+ if (!initialized) {
332
+ initializeHandlebars(assets);
333
+ }
334
+ const requestedLayout = doc.layout;
335
+ if (!requestedLayout || !layoutCache.has(requestedLayout)) {
336
+ throw new Error(`Unknown layout "${requestedLayout ?? 'undefined'}". Expected one of: article-page, homepage, category-page, search-page, 404, live-story, link-in-bio, media-page`);
337
+ }
338
+ const parsed = canonicalArticleSchema.parse(normalizeDocument(doc));
339
+ const template = layoutCache.get(parsed.layout);
340
+ if (!template) {
341
+ throw new Error(`Layout template missing for \"${parsed.layout}\"`);
342
+ }
343
+ // Build the template context, enriching homepage renders with pre-distributed
344
+ // article slots so templates do not need to perform index arithmetic.
345
+ const docExtra = doc;
346
+ const showBreakingNews = parsed.layout === 'homepage' && Boolean(parsed.breakingNews) && docExtra['showBreakingNews'] !== false;
347
+ const homepageSlots = parsed.layout === 'homepage' ? distributeHomepageArticles(parsed.articles ?? [], new Date(), showBreakingNews) : undefined;
348
+ return template({
349
+ ...parsed,
350
+ ...(homepageSlots !== undefined ? { homepageSlots } : {}),
351
+ styles: runtimeStyles,
352
+ logoLink: parsed.language === 'en' ? '/' : `/${parsed.language}`
353
+ });
354
+ }
@@ -0,0 +1,6 @@
1
+ export { render, liveProgramPageHtml, liveProgramPageAsset, liveProgramPageFiles, fontFiles } from './renderer.node.js';
2
+ export type { LiveProgramFileEntry, FontFileEntry } from './renderer.node.js';
3
+ export { buildInstagramImageHtml, registerInstagramImageHelpers, type InstagramImageTemplateParams } from './instagram-image-template.js';
4
+ export { outletConfig } from './outlet-config.js';
5
+ export { version } from './version.js';
6
+ export type { CanonicalDocument } from './types/canonical-article.js';
@@ -0,0 +1,4 @@
1
+ export { render, liveProgramPageHtml, liveProgramPageAsset, liveProgramPageFiles, fontFiles } from './renderer.node.js';
2
+ export { buildInstagramImageHtml, registerInstagramImageHelpers } from './instagram-image-template.js';
3
+ export { outletConfig } from './outlet-config.js';
4
+ export { version } from './version.js';
@@ -0,0 +1,16 @@
1
+ import type { CanonicalDocument } from './types/canonical-article.js';
2
+ export declare function render(document: CanonicalDocument): string;
3
+ export declare function liveProgramPageHtml(): string;
4
+ export type FontFileEntry = {
5
+ key: string;
6
+ body: Buffer;
7
+ contentType: string;
8
+ };
9
+ export declare function fontFiles(): FontFileEntry[];
10
+ export declare function liveProgramPageAsset(filename: string): string;
11
+ export type LiveProgramFileEntry = {
12
+ key: string;
13
+ body: Buffer;
14
+ contentType: string;
15
+ };
16
+ export declare function liveProgramPageFiles(): LiveProgramFileEntry[];