@sonordev/site-kit 8.0.1 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/agent-manifest.json +1 -1
  3. package/dist/{AnalyticsProvider-EGCZ2MVM.js → AnalyticsProvider-6TAA3XYB.js} +4 -4
  4. package/dist/{ArticleViewTracker-ATNVMT45.js → ArticleViewTracker-H4N7YCLC.js} +3 -3
  5. package/dist/{BlocksPopup-F636XNO4.js → BlocksPopup-FJT5YQD3.js} +4 -4
  6. package/dist/{ChatWidget-EQTLKPJX.js → ChatWidget-THQHHTAA.js} +5 -5
  7. package/dist/{FileField-BUD2YGN5.js → FileField-OZXXJGUM.js} +3 -3
  8. package/dist/{FormSpotlight-NGH56TGC.js → FormSpotlight-MLDJS246.js} +1 -1
  9. package/dist/{FormStage-XZRC54SY.js → FormStage-6RVY7M3R.js} +1 -1
  10. package/dist/{ManagedForm-CQDQ4CUN.js → ManagedForm-3VV54RVH.js} +6 -6
  11. package/dist/{ManagedNewsletterForm-KCN3BTKA.js → ManagedNewsletterForm-RTJDGMGG.js} +4 -4
  12. package/dist/{SignalCore-RDQPM2L2.js → SignalCore-T7ZOCA44.js} +3 -3
  13. package/dist/{SiteChat-QBDOQ5ZZ.js → SiteChat-JSHPGAE3.js} +1 -1
  14. package/dist/{SiteDesignReporter-426TUCUF.js → SiteDesignReporter-L2JBAKKK.js} +5 -5
  15. package/dist/{SitePopups-KLUD6XIE.js → SitePopups-K6ADAWFK.js} +4 -4
  16. package/dist/{SitemapSync-QOIMV5GO.js → SitemapSync-VV2YSMIW.js} +4 -4
  17. package/dist/_client/booking-widget.js +5 -5
  18. package/dist/affiliates/index.js +3 -3
  19. package/dist/analytics/index.js +4 -4
  20. package/dist/{article-styles-6CM5FUMV.js → article-styles-GFXJJDLE.js} +2 -0
  21. package/dist/articles/article-photos.d.ts +9 -0
  22. package/dist/articles/index.d.ts +1 -0
  23. package/dist/articles/index.js +1 -1
  24. package/dist/articles/server-core.d.ts +2 -0
  25. package/dist/articles/server-ui.d.ts +2 -0
  26. package/dist/articles/server-ui.js +7 -5
  27. package/dist/articles/server.d.ts +2 -0
  28. package/dist/articles/server.js +2 -1
  29. package/dist/articles/types.d.ts +17 -0
  30. package/dist/chat/index.js +6 -6
  31. package/dist/{chunk-IY6G67EF.js → chunk-3EU6S5YC.js} +1 -1
  32. package/dist/{chunk-M62U7TJF.js → chunk-575L73NT.js} +1 -1
  33. package/dist/{chunk-OE3NXEOF.js → chunk-57K4GW3D.js} +1 -1
  34. package/dist/{chunk-6KUCA5HG.js → chunk-5ZCY36TY.js} +1 -1
  35. package/dist/{chunk-Z6PVFZRI.js → chunk-66G47P5C.js} +1 -1
  36. package/dist/{chunk-55JLUMAC.js → chunk-727R7C5R.js} +2 -2
  37. package/dist/{chunk-6BXUSAOJ.js → chunk-7FSB2EXS.js} +1 -1
  38. package/dist/{chunk-VQQV7FOX.js → chunk-BQZPHICL.js} +1 -1
  39. package/dist/{chunk-OCKGB734.js → chunk-EBILJHUF.js} +1 -1
  40. package/dist/{chunk-XPTJRVL2.js → chunk-FQUGGPBM.js} +3 -2
  41. package/dist/{chunk-B7QRRLTU.js → chunk-FVXFLVXF.js} +2 -2
  42. package/dist/{chunk-7BSC6HF3.js → chunk-GWP2VBFH.js} +3 -3
  43. package/dist/{chunk-CAF53GKN.js → chunk-H4R2GPAB.js} +1 -1
  44. package/dist/chunk-HUBMKTPW.js +131 -0
  45. package/dist/{chunk-EE6IG5GK.js → chunk-I6QFPSUU.js} +8 -8
  46. package/dist/{chunk-NKFRW2VB.js → chunk-JBEUZJS3.js} +2 -2
  47. package/dist/{chunk-JCFQGEG7.js → chunk-JC2VS2SB.js} +1 -1
  48. package/dist/{chunk-AGJODJ4V.js → chunk-NNEIBXGU.js} +1 -1
  49. package/dist/{chunk-S5G3A7OZ.js → chunk-Q72M5KBS.js} +1 -1
  50. package/dist/{chunk-GMXY2OOY.js → chunk-SMYX3AAO.js} +1 -1
  51. package/dist/{chunk-J6N5DCGW.js → chunk-WBC5B3JD.js} +2 -2
  52. package/dist/{chunk-FIGIJK5F.js → chunk-WK3N3Y7V.js} +1 -1
  53. package/dist/{chunk-5GB2HHVJ.js → chunk-WSNG2K3T.js} +2 -2
  54. package/dist/{chunk-Z4MK4VOG.js → chunk-WYZ4OUON.js} +1 -1
  55. package/dist/{chunk-DWNS6ZJM.js → chunk-X7VKRHFF.js} +1 -1
  56. package/dist/{chunk-YGXWG54S.js → chunk-XWIRU6UT.js} +1 -1
  57. package/dist/{chunk-3222QBUS.js → chunk-YBAFUM3Z.js} +1 -1
  58. package/dist/{chunk-H3SDOSVU.js → chunk-ZM2FNWIQ.js} +1 -1
  59. package/dist/client/index.js +3 -3
  60. package/dist/contracts/editorial-media.d.ts +39 -0
  61. package/dist/contracts/entries.d.ts +1 -1
  62. package/dist/fleet/index.js +4 -4
  63. package/dist/forms/index.js +7 -7
  64. package/dist/forms/server.js +2 -2
  65. package/dist/images/index.js +4 -4
  66. package/dist/index.js +1 -1
  67. package/dist/layout/client.js +7 -7
  68. package/dist/layout/index.js +8 -8
  69. package/dist/llms/index.js +4 -4
  70. package/dist/maps/index.js +3 -3
  71. package/dist/mcp/sonor.js +11 -9
  72. package/dist/revalidate/index.js +2 -2
  73. package/dist/runtime/index.js +3 -3
  74. package/dist/seo/client.js +4 -4
  75. package/dist/seo/index.js +4 -4
  76. package/dist/seo/llms.js +4 -4
  77. package/dist/seo/register-sitemap-cli.js +1 -1
  78. package/dist/seo/sitemap.js +2 -2
  79. package/dist/server/index.js +2 -2
  80. package/dist/shared/version.d.ts +1 -1
  81. package/dist/signal/index.js +2 -2
  82. package/dist/sitemap/index.js +2 -2
  83. package/dist/sync/index.js +5 -5
  84. package/dist/website/images.js +4 -4
  85. package/dist/website/index.js +5 -5
  86. package/dist/website/popups.js +4 -4
  87. package/dist/{writeLLMsTxt-UZGN6IBU.js → writeLLMsTxt-DGKLYXIW.js} +1 -1
  88. package/package.json +1 -1
  89. package/src/articles/README.md +33 -0
  90. /package/dist/{chunk-TZ5RTANX.js → chunk-WACWV5EP.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @sonordev/site-kit Changelog
2
2
 
3
+ ## 8.2.0
4
+
5
+ - Article photo placement uses the same pure contract as Sonor's editor and preview: exact section anchors, missing prose diagnostics, duplicate detection, and independent website placement.
6
+ - A saved heading ID keeps its image attached when that heading's wording changes; stale anchors are skipped rather than guessed.
7
+
8
+
9
+ ## 8.1.0
10
+
11
+ - **Supporting article photos.** The default `Article` server component places approved photo snapshots after the introduction or the opening paragraph of an exact section heading. Figures include descriptions, optional credit captions, intrinsic dimensions, and lazy loading. Missing or ambiguous headings are skipped; existing inline images aren't duplicated. Older articles render unchanged.
12
+ - **Custom publications and feeds.** `insertArticlePhotos`, `articlePhotoCss`, and `ArticleEditorialPhoto` are exported from the article entries. Custom renderers can apply the same placement contract to their HTML. RSS and Atom include the approved photos; the public `get_article` MCP tool exposes their descriptions and placements without private planning data.
13
+ - **Sonor owns the photo plan.** The authenticated app and MCP save source selection, image briefs, focal points, and readiness. Sites consume only `editorial_photos` from the public article response. This release doesn't add public write tools.
14
+
3
15
  ## 8.0.1
4
16
 
5
17
  - **`server-only` is a dependency.** The entries that run only on the server (`@sonordev/site-kit/server`, `/seo/server`, `/forms/server` and the others that import the `server-only` marker) didn't list it. A Next build never noticed, because Next supplies its own copy, but a Node script or a test that imported one of those entries from a pnpm install failed with `ERR_MODULE_NOT_FOUND`. site-kit now depends on `server-only` ^0.0.1, so the import resolves anywhere. Inside a build Next still uses its own copy, so nothing changes for a site. Outside Next, load a server entry under the `react-server` condition (`node --conditions=react-server`), the way a server component loads it; without that condition, `server-only` stops the import on purpose.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@sonordev/site-kit",
4
- "version": "8.0.1",
4
+ "version": "8.2.0",
5
5
  "description": "Machine-readable manifest for coding agents integrating a site with Sonor. See AGENTS.md (shipped) and docs/SITE-KIT-AGENT-NATIVE.md.",
6
6
  "env": {
7
7
  "required": [
@@ -1,4 +1,4 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-OCKGB734.js';
1
+ export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-EBILJHUF.js';
2
2
  import './chunk-LCDVPAMR.js';
3
3
  import './chunk-ZKADJNR2.js';
4
4
  import './chunk-L2V5PUFN.js';
@@ -7,7 +7,7 @@ import './chunk-GJWI74ZZ.js';
7
7
  import './chunk-CAH4Y4PY.js';
8
8
  import './chunk-EKBEOXTH.js';
9
9
  import './chunk-3G7YABRA.js';
10
- import './chunk-55JLUMAC.js';
11
- import './chunk-IY6G67EF.js';
12
- import './chunk-S5G3A7OZ.js';
10
+ import './chunk-727R7C5R.js';
11
+ import './chunk-3EU6S5YC.js';
12
+ import './chunk-Q72M5KBS.js';
13
13
  import './chunk-PKBMQBKP.js';
@@ -4,9 +4,9 @@ import { withSiteBody } from './chunk-MJP63SSS.js';
4
4
  import './chunk-FESKKJAS.js';
5
5
  import './chunk-A4CC4ZG3.js';
6
6
  import { readPublishedApiConfig } from './chunk-3G7YABRA.js';
7
- import { sonorFetch } from './chunk-55JLUMAC.js';
8
- import './chunk-IY6G67EF.js';
9
- import './chunk-S5G3A7OZ.js';
7
+ import { sonorFetch } from './chunk-727R7C5R.js';
8
+ import './chunk-3EU6S5YC.js';
9
+ import './chunk-Q72M5KBS.js';
10
10
  import './chunk-PKBMQBKP.js';
11
11
  import { useEffect } from 'react';
12
12
 
@@ -1,14 +1,14 @@
1
1
  'use client';
2
- import { getSiteDesignTokens } from './chunk-J6N5DCGW.js';
2
+ import { getSiteDesignTokens } from './chunk-WBC5B3JD.js';
3
3
  import { DEFAULT_POPUP_TOKENS, PopupBlocks } from './chunk-BF7TZYC3.js';
4
4
  import { normalizePopupBlocks, toHexColor, readableOn } from './chunk-IHG36STL.js';
5
5
  import './chunk-S22FSH7C.js';
6
6
  import './chunk-CAH4Y4PY.js';
7
7
  import './chunk-EKBEOXTH.js';
8
8
  import './chunk-3G7YABRA.js';
9
- import './chunk-55JLUMAC.js';
10
- import './chunk-IY6G67EF.js';
11
- import './chunk-S5G3A7OZ.js';
9
+ import './chunk-727R7C5R.js';
10
+ import './chunk-3EU6S5YC.js';
11
+ import './chunk-Q72M5KBS.js';
12
12
  import './chunk-PKBMQBKP.js';
13
13
  import { useState } from 'react';
14
14
  import { jsx } from 'react/jsx-runtime';
@@ -1,8 +1,8 @@
1
- export { ChatWidget, EchoChat, isChatEnabled } from './chunk-B7QRRLTU.js';
1
+ export { ChatWidget, EchoChat, isChatEnabled } from './chunk-FVXFLVXF.js';
2
2
  import './chunk-6T6CQVNL.js';
3
3
  import './chunk-JE4A5S4F.js';
4
4
  import './chunk-27FISYK4.js';
5
- import './chunk-3222QBUS.js';
5
+ import './chunk-YBAFUM3Z.js';
6
6
  import './chunk-Q6E4OPGG.js';
7
7
  import './chunk-5ROTTMBL.js';
8
8
  import './chunk-C2FZBUSS.js';
@@ -14,7 +14,7 @@ import './chunk-L2V5PUFN.js';
14
14
  import './chunk-5TM3WPCI.js';
15
15
  import './chunk-GJWI74ZZ.js';
16
16
  import './chunk-3G7YABRA.js';
17
- import './chunk-55JLUMAC.js';
18
- import './chunk-IY6G67EF.js';
19
- import './chunk-S5G3A7OZ.js';
17
+ import './chunk-727R7C5R.js';
18
+ import './chunk-3EU6S5YC.js';
19
+ import './chunk-Q72M5KBS.js';
20
20
  import './chunk-PKBMQBKP.js';
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { getClientApiConfig } from './chunk-3G7YABRA.js';
3
- import { sonorFetch } from './chunk-55JLUMAC.js';
4
- import './chunk-IY6G67EF.js';
5
- import './chunk-S5G3A7OZ.js';
3
+ import { sonorFetch } from './chunk-727R7C5R.js';
4
+ import './chunk-3EU6S5YC.js';
5
+ import './chunk-Q72M5KBS.js';
6
6
  import './chunk-PKBMQBKP.js';
7
7
  import React from 'react';
8
8
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { StageStyles, SummaryTick } from './chunk-3YKQLC7J.js';
3
- import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-JCFQGEG7.js';
3
+ import { stageFirstName, useFieldControls, stageViews, stageEstimate, AUTO_ADVANCE_TYPES } from './chunk-JC2VS2SB.js';
4
4
  import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
5
5
  import { isEmptyValue, unseenControlValues, isDisplayOnly } from './chunk-C2FZBUSS.js';
6
6
  import { FormField } from './chunk-TYAVHRWH.js';
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { StageStyles, SummaryTick } from './chunk-3YKQLC7J.js';
3
- import { useFieldControls, stageViews, stageFirstName, stageEstimate, formatAnswer, AUTO_ADVANCE_TYPES } from './chunk-JCFQGEG7.js';
3
+ import { useFieldControls, stageViews, stageFirstName, stageEstimate, formatAnswer, AUTO_ADVANCE_TYPES } from './chunk-JC2VS2SB.js';
4
4
  import { readAgentSubmit, formToolAttributes } from './chunk-Q6E4OPGG.js';
5
5
  import { isEmptyValue, unseenControlValues } from './chunk-C2FZBUSS.js';
6
6
  import { FormField } from './chunk-TYAVHRWH.js';
@@ -1,6 +1,6 @@
1
- export { ManagedForm } from './chunk-7BSC6HF3.js';
2
- import './chunk-JCFQGEG7.js';
3
- import './chunk-3222QBUS.js';
1
+ export { ManagedForm } from './chunk-GWP2VBFH.js';
2
+ import './chunk-JC2VS2SB.js';
3
+ import './chunk-YBAFUM3Z.js';
4
4
  import './chunk-Q6E4OPGG.js';
5
5
  import './chunk-5ROTTMBL.js';
6
6
  import './chunk-C2FZBUSS.js';
@@ -13,7 +13,7 @@ import './chunk-L2V5PUFN.js';
13
13
  import './chunk-5TM3WPCI.js';
14
14
  import './chunk-GJWI74ZZ.js';
15
15
  import './chunk-3G7YABRA.js';
16
- import './chunk-55JLUMAC.js';
17
- import './chunk-IY6G67EF.js';
18
- import './chunk-S5G3A7OZ.js';
16
+ import './chunk-727R7C5R.js';
17
+ import './chunk-3EU6S5YC.js';
18
+ import './chunk-Q72M5KBS.js';
19
19
  import './chunk-PKBMQBKP.js';
@@ -1,4 +1,4 @@
1
- import { useForm } from './chunk-3222QBUS.js';
1
+ import { useForm } from './chunk-YBAFUM3Z.js';
2
2
  import './chunk-Q6E4OPGG.js';
3
3
  import './chunk-5ROTTMBL.js';
4
4
  import './chunk-C2FZBUSS.js';
@@ -11,9 +11,9 @@ import './chunk-L2V5PUFN.js';
11
11
  import './chunk-5TM3WPCI.js';
12
12
  import './chunk-GJWI74ZZ.js';
13
13
  import './chunk-3G7YABRA.js';
14
- import './chunk-55JLUMAC.js';
15
- import './chunk-IY6G67EF.js';
16
- import './chunk-S5G3A7OZ.js';
14
+ import './chunk-727R7C5R.js';
15
+ import './chunk-3EU6S5YC.js';
16
+ import './chunk-Q72M5KBS.js';
17
17
  import './chunk-PKBMQBKP.js';
18
18
  import { jsx } from 'react/jsx-runtime';
19
19
 
@@ -4,9 +4,9 @@ import { onPageLeave } from './chunk-L2V5PUFN.js';
4
4
  import './chunk-5TM3WPCI.js';
5
5
  import './chunk-GJWI74ZZ.js';
6
6
  import { getClientApiConfig } from './chunk-3G7YABRA.js';
7
- import { sonorFetch } from './chunk-55JLUMAC.js';
8
- import { getFreshCredential, isSiteToken } from './chunk-IY6G67EF.js';
9
- import './chunk-S5G3A7OZ.js';
7
+ import { sonorFetch } from './chunk-727R7C5R.js';
8
+ import { getFreshCredential, isSiteToken } from './chunk-3EU6S5YC.js';
9
+ import './chunk-Q72M5KBS.js';
10
10
  import './chunk-PKBMQBKP.js';
11
11
  import { useState, useRef, useEffect, useCallback } from 'react';
12
12
 
@@ -1,4 +1,4 @@
1
- export { SiteChat } from './chunk-AGJODJ4V.js';
1
+ export { SiteChat } from './chunk-NNEIBXGU.js';
2
2
  import './chunk-27FISYK4.js';
3
3
  import './chunk-CAH4Y4PY.js';
4
4
  import './chunk-EKBEOXTH.js';
@@ -1,12 +1,12 @@
1
- export { SiteDesignReporter } from './chunk-CAF53GKN.js';
2
- import './chunk-J6N5DCGW.js';
1
+ export { SiteDesignReporter } from './chunk-H4R2GPAB.js';
2
+ import './chunk-WBC5B3JD.js';
3
3
  import './chunk-IHG36STL.js';
4
4
  import './chunk-YC7ELZS3.js';
5
5
  import './chunk-S22FSH7C.js';
6
6
  import './chunk-CAH4Y4PY.js';
7
7
  import './chunk-EKBEOXTH.js';
8
8
  import './chunk-3G7YABRA.js';
9
- import './chunk-55JLUMAC.js';
10
- import './chunk-IY6G67EF.js';
11
- import './chunk-S5G3A7OZ.js';
9
+ import './chunk-727R7C5R.js';
10
+ import './chunk-3EU6S5YC.js';
11
+ import './chunk-Q72M5KBS.js';
12
12
  import './chunk-PKBMQBKP.js';
@@ -1,4 +1,4 @@
1
- export { SitePopups } from './chunk-NKFRW2VB.js';
1
+ export { SitePopups } from './chunk-JBEUZJS3.js';
2
2
  import './chunk-27FISYK4.js';
3
3
  import './chunk-5ROTTMBL.js';
4
4
  import './chunk-ZKADJNR2.js';
@@ -7,7 +7,7 @@ import './chunk-GJWI74ZZ.js';
7
7
  import './chunk-CAH4Y4PY.js';
8
8
  import './chunk-EKBEOXTH.js';
9
9
  import './chunk-3G7YABRA.js';
10
- import './chunk-55JLUMAC.js';
11
- import './chunk-IY6G67EF.js';
12
- import './chunk-S5G3A7OZ.js';
10
+ import './chunk-727R7C5R.js';
11
+ import './chunk-3EU6S5YC.js';
12
+ import './chunk-Q72M5KBS.js';
13
13
  import './chunk-PKBMQBKP.js';
@@ -1,9 +1,9 @@
1
- export { SitemapSync } from './chunk-FIGIJK5F.js';
1
+ export { SitemapSync } from './chunk-WK3N3Y7V.js';
2
2
  import './chunk-YVKRYQRG.js';
3
3
  import './chunk-CAH4Y4PY.js';
4
4
  import './chunk-EKBEOXTH.js';
5
5
  import './chunk-3G7YABRA.js';
6
- import './chunk-55JLUMAC.js';
7
- import './chunk-IY6G67EF.js';
8
- import './chunk-S5G3A7OZ.js';
6
+ import './chunk-727R7C5R.js';
7
+ import './chunk-3EU6S5YC.js';
8
+ import './chunk-Q72M5KBS.js';
9
9
  import './chunk-PKBMQBKP.js';
@@ -1,8 +1,8 @@
1
1
  'use client';
2
- export { BookingWidget, BookingWidget_default as default } from '../chunk-Z6PVFZRI.js';
3
- import '../chunk-YGXWG54S.js';
2
+ export { BookingWidget, BookingWidget_default as default } from '../chunk-66G47P5C.js';
3
+ import '../chunk-XWIRU6UT.js';
4
4
  import '../chunk-3G7YABRA.js';
5
- import '../chunk-55JLUMAC.js';
6
- import '../chunk-IY6G67EF.js';
7
- import '../chunk-S5G3A7OZ.js';
5
+ import '../chunk-727R7C5R.js';
6
+ import '../chunk-3EU6S5YC.js';
7
+ import '../chunk-Q72M5KBS.js';
8
8
  import '../chunk-PKBMQBKP.js';
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { getClientApiConfig } from '../chunk-3G7YABRA.js';
3
- import { sonorFetch } from '../chunk-55JLUMAC.js';
4
- import '../chunk-IY6G67EF.js';
5
- import '../chunk-S5G3A7OZ.js';
3
+ import { sonorFetch } from '../chunk-727R7C5R.js';
4
+ import '../chunk-3EU6S5YC.js';
5
+ import '../chunk-Q72M5KBS.js';
6
6
  import '../chunk-PKBMQBKP.js';
7
7
  import { useState, useEffect } from 'react';
8
8
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-OCKGB734.js';
2
+ export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-EBILJHUF.js';
3
3
  import { trackConversion } from '../chunk-LCDVPAMR.js';
4
4
  export { trackConversion, trackEvent } from '../chunk-LCDVPAMR.js';
5
5
  import '../chunk-ZKADJNR2.js';
@@ -9,9 +9,9 @@ import '../chunk-GJWI74ZZ.js';
9
9
  export { isCrossOriginFrame, isFramed, isTopFrameSameOrigin } from '../chunk-CAH4Y4PY.js';
10
10
  import '../chunk-EKBEOXTH.js';
11
11
  import '../chunk-3G7YABRA.js';
12
- import '../chunk-55JLUMAC.js';
13
- import '../chunk-IY6G67EF.js';
14
- import '../chunk-S5G3A7OZ.js';
12
+ import '../chunk-727R7C5R.js';
13
+ import '../chunk-3EU6S5YC.js';
14
+ import '../chunk-Q72M5KBS.js';
15
15
  import '../chunk-PKBMQBKP.js';
16
16
  import { useCallback, useEffect } from 'react';
17
17
 
@@ -1,3 +1,4 @@
1
+ import { articlePhotoCss } from './chunk-HUBMKTPW.js';
1
2
  import { articleTableCss } from './chunk-Y3INC4QJ.js';
2
3
  import './chunk-PKBMQBKP.js';
3
4
 
@@ -6,6 +7,7 @@ var articleCss = (
6
7
  /* css */
7
8
  `
8
9
  ${articleTableCss}
10
+ ${articlePhotoCss}
9
11
  /* ===== Layout ===== */
10
12
  .sk-article {
11
13
  --_sk-primary: var(--sk-primary, #2563eb);
@@ -0,0 +1,9 @@
1
+ import type { ArticleEditorialPhoto } from './types';
2
+ /**
3
+ * Inserts approved public photo snapshots at explicitly authored placements.
4
+ * Missing/duplicate headings, unmatched sections and photos already in the body
5
+ * are skipped. Never changes the author's paragraphs, headings or other markup.
6
+ * This is a layout transform, not a sanitizer for the original article HTML.
7
+ */
8
+ export declare function insertArticlePhotos(html: string, photos?: ArticleEditorialPhoto[] | null): string;
9
+ export declare const articlePhotoCss = "\n.sk-article-photo { margin: 2em 0; max-width: 100%; }\n.sk-article-photo img { display: block; width: 100%; max-width: 100%; height: auto; border-radius: var(--sk-radius, 0.75rem); }\n.sk-article-photo figcaption { margin-top: 0.65em; color: var(--sk-text-secondary, inherit); font-size: 0.875em; line-height: 1.5; overflow-wrap: anywhere; }\n";
@@ -51,6 +51,7 @@ export { TableOfContents } from './TableOfContents';
51
51
  export { ServiceCallout, ServiceCallouts } from './ServiceCallout';
52
52
  export type { ServiceCalloutProps } from './ServiceCallout';
53
53
  export { ArticleFAQ } from './ArticleFAQ';
54
+ export type { ArticleEditorialPhoto } from './types';
54
55
  export type { ArticleFAQProps, FaqItem } from './ArticleFAQ';
55
56
  export { ClusterNavigation } from './ClusterNavigation';
56
57
  export type { ClusterNavigationProps } from './ClusterNavigation';
@@ -15,7 +15,7 @@ import '../chunk-PKBMQBKP.js';
15
15
  import React, { useState, Suspense, useEffect } from 'react';
16
16
  import { jsx, jsxs } from 'react/jsx-runtime';
17
17
 
18
- var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-KCN3BTKA.js'));
18
+ var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-RTJDGMGG.js'));
19
19
  function NewsletterWidget({
20
20
  title = "Subscribe to Our Newsletter",
21
21
  description = "Get the latest posts delivered straight to your inbox.",
@@ -455,5 +455,7 @@ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolv
455
455
  export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
456
456
  export { resolveArticleArtwork } from './artwork';
457
457
  export { wrapArticleTables, articleTableCss } from './article-tables';
458
+ export { insertArticlePhotos, articlePhotoCss } from './article-photos';
459
+ export type { ArticleEditorialPhoto } from './types';
458
460
  export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, buildNewsSitemapXml, cdata, recentNewsPosts } from './news-sitemap';
459
461
  export type { NewsSitemapOptions, NewsSitemapPost } from './news-sitemap';
@@ -26,3 +26,5 @@ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolv
26
26
  export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
27
27
  export { resolveArticleArtwork } from './artwork';
28
28
  export { wrapArticleTables, articleTableCss } from './article-tables';
29
+ export { insertArticlePhotos, articlePhotoCss } from './article-photos';
30
+ export type { ArticleEditorialPhoto } from './types';
@@ -2,7 +2,9 @@ import { readingTimeMinutes, ServiceCallouts, ClusterNavigation, getAuthorSocial
2
2
  export { ClusterNavigation } from '../chunk-FV2VD7WM.js';
3
3
  import { widgetStyle, widgetTitleStyle } from '../chunk-GYF2ULVO.js';
4
4
  import { resolvePublicationSiteUrl, addExternalLinkTargets } from '../chunk-L5UOHS6E.js';
5
- import { fetchArticleBySlug, fetchRelatedArticles, fetchArticleCategories, getTopicCluster } from '../chunk-XPTJRVL2.js';
5
+ import { fetchArticleBySlug, fetchRelatedArticles, fetchArticleCategories, getTopicCluster } from '../chunk-FQUGGPBM.js';
6
+ import { insertArticlePhotos } from '../chunk-HUBMKTPW.js';
7
+ export { articlePhotoCss, insertArticlePhotos } from '../chunk-HUBMKTPW.js';
6
8
  export { articleTableCss, wrapArticleTables } from '../chunk-Y3INC4QJ.js';
7
9
  import { resolveArticleArtwork, articleArtworkImageStyle } from '../chunk-QXMIKDOL.js';
8
10
  export { resolveArticleArtwork } from '../chunk-QXMIKDOL.js';
@@ -107,7 +109,7 @@ async function Article({
107
109
  }
108
110
  const [post, { articleCss }, { wrapArticleTables: wrapArticleTables2 }] = await Promise.all([
109
111
  fetchArticleBySlug({ apiUrl, apiKey, site }, slug),
110
- unstyled ? Promise.resolve({ articleCss: "" }) : import('../article-styles-6CM5FUMV.js'),
112
+ unstyled ? Promise.resolve({ articleCss: "" }) : import('../article-styles-GFXJJDLE.js'),
111
113
  import('../article-tables-AXSZOGNW.js')
112
114
  ]);
113
115
  if (!post) {
@@ -124,7 +126,7 @@ async function Article({
124
126
  const rawContent = post.content_html || post.content || "";
125
127
  const content = ensureHtml(rawContent);
126
128
  const siteUrlResolved = resolvePublicationSiteUrl(siteUrl);
127
- const contentWithExternalTargets = wrapArticleTables2(addExternalLinkTargets(content, siteUrlResolved));
129
+ const contentWithExternalTargets = wrapArticleTables2(addExternalLinkTargets(insertArticlePhotos(content, post.editorial_photos), siteUrlResolved));
128
130
  const artwork = resolveArticleArtwork(post, "article");
129
131
  const tableOfContents = showToc ? generateTableOfContents(content) : [];
130
132
  const relatedPosts = showRelated ? await fetchRelatedArticles({ apiUrl, apiKey, site }, post.id, relatedCount, { revalidate: 300 }) : [];
@@ -133,7 +135,7 @@ async function Article({
133
135
  ...item,
134
136
  answer: addExternalLinkTargets(item.answer || "", siteUrlResolved)
135
137
  })) ?? faqRaw;
136
- const { ArticleViewTracker } = await import('../ArticleViewTracker-ATNVMT45.js');
138
+ const { ArticleViewTracker } = await import('../ArticleViewTracker-H4N7YCLC.js');
137
139
  if (children) {
138
140
  return /* @__PURE__ */ jsxs(Fragment, { children: [
139
141
  /* @__PURE__ */ jsx(ArticleViewTracker, { slug: post.slug, site }),
@@ -407,7 +409,7 @@ async function ArticleList({
407
409
  const [articleData, categories, { articleListCss }] = await Promise.all([
408
410
  fetchArticleList({ apiUrl, apiKey, category, tag, author, featured, search, cluster, page, perPage, orderBy, order, site }),
409
411
  showCategoryFilter ? fetchArticleCategories({ apiUrl, apiKey, site }) : Promise.resolve([]),
410
- unstyled || children ? Promise.resolve({ articleListCss: "" }) : import('../article-styles-6CM5FUMV.js')
412
+ unstyled || children ? Promise.resolve({ articleListCss: "" }) : import('../article-styles-GFXJJDLE.js')
411
413
  ]);
412
414
  if (children) {
413
415
  return children({ posts: articleData.posts, pagination: articleData.pagination, categories });
@@ -455,5 +455,7 @@ export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolv
455
455
  export type { ArticleRoutePost, PublicationRoutingOptions } from './routes';
456
456
  export { resolveArticleArtwork } from './artwork';
457
457
  export { wrapArticleTables, articleTableCss } from './article-tables';
458
+ export { insertArticlePhotos, articlePhotoCss } from './article-photos';
459
+ export type { ArticleEditorialPhoto } from './types';
458
460
  export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, buildNewsSitemapXml, cdata, recentNewsPosts } from './news-sitemap';
459
461
  export type { NewsSitemapOptions, NewsSitemapPost } from './news-sitemap';
@@ -1,4 +1,5 @@
1
- export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, SEO_LIMITS, buildNewsSitemapXml, cdata, generateAllArticleSchemas, generateArticleCategoryMetadata, generateArticleListSchema, generateArticleMetadata, generateArticleSchema, generateArticleSitemap, generateArticleStaticParams, generateAtomFeed, generateAuthorPageMetadata, generateAuthorStaticParams, generateBreadcrumbSchema, generateCategoryStaticParams, generateClusterArticleSchema, generateClusterBreadcrumbSchema, generateClusterItemListSchema, generateClusterLandingSchema, generateClusterPageMetadata, generateFaqSchema, generateHowToSchema, generateNewsSitemap, generatePublicationMetadata, generateRssFeed, getAllArticleSlugs, getAllArticles, getAllAuthorSlugs, getArticle, getArticleCategories, getAuthorBySlug, getAuthorPosts, getClusterNavigation, getPostsByCategory, getRelatedInsights, getTopicCluster, getTopicClusters, recentNewsPosts, requireArticle, sanitizeExcerpt, validateArticleSeo, validateMetaDescription, validateSeoTitle } from '../chunk-XPTJRVL2.js';
1
+ export { FEED_DEFAULT_ITEMS, NEWS_SITEMAP_MAX_URLS, NEWS_SITEMAP_WINDOW_MS, SEO_LIMITS, buildNewsSitemapXml, cdata, generateAllArticleSchemas, generateArticleCategoryMetadata, generateArticleListSchema, generateArticleMetadata, generateArticleSchema, generateArticleSitemap, generateArticleStaticParams, generateAtomFeed, generateAuthorPageMetadata, generateAuthorStaticParams, generateBreadcrumbSchema, generateCategoryStaticParams, generateClusterArticleSchema, generateClusterBreadcrumbSchema, generateClusterItemListSchema, generateClusterLandingSchema, generateClusterPageMetadata, generateFaqSchema, generateHowToSchema, generateNewsSitemap, generatePublicationMetadata, generateRssFeed, getAllArticleSlugs, getAllArticles, getAllAuthorSlugs, getArticle, getArticleCategories, getAuthorBySlug, getAuthorPosts, getClusterNavigation, getPostsByCategory, getRelatedInsights, getTopicCluster, getTopicClusters, recentNewsPosts, requireArticle, sanitizeExcerpt, validateArticleSeo, validateMetaDescription, validateSeoTitle } from '../chunk-FQUGGPBM.js';
2
+ export { articlePhotoCss, insertArticlePhotos } from '../chunk-HUBMKTPW.js';
2
3
  export { articleTableCss, wrapArticleTables } from '../chunk-Y3INC4QJ.js';
3
4
  export { authorEntityId, generateArticleAuthorNode, generateAuthorPersonSchema, generateAuthorSchema, resolveArticleArtwork, withArticleAuthorIdentity } from '../chunk-QXMIKDOL.js';
4
5
  export { articleCategorySlug, createPublicationRoutes, resolveArticleUrl, resolvePublicationUrl } from '../chunk-WMVK77ND.js';
@@ -2,6 +2,21 @@
2
2
  * @sonordev/site-kit/articles - Type definitions
3
3
  */
4
4
  import type { PublicationRoutingOptions } from './routes';
5
+ /** Public, approved photo snapshot. Planning briefs and private source metadata stay in Sonor. */
6
+ export interface ArticleEditorialPhoto {
7
+ url: string;
8
+ alt: string;
9
+ caption?: string;
10
+ width: number;
11
+ height: number;
12
+ placement: {
13
+ kind: 'after_intro';
14
+ } | {
15
+ kind: 'after_heading';
16
+ heading: string;
17
+ headingId?: string;
18
+ };
19
+ }
5
20
  export interface Article {
6
21
  id: string;
7
22
  project_id: string;
@@ -23,6 +38,8 @@ export interface Article {
23
38
  /** Dedicated index frame from Sonor's atmosphere + content-stage renderer. */
24
39
  index_image?: string;
25
40
  index_image_alt?: string;
41
+ /** Supporting photos placed deliberately in the article body; optional on older APIs. */
42
+ editorial_photos?: ArticleEditorialPhoto[];
26
43
  /** Author - can be string or object depending on API response */
27
44
  author_id?: string;
28
45
  author?: ArticleAuthor | string;
@@ -1,10 +1,10 @@
1
1
  'use client';
2
- export { ChatWidget, DEFAULT_LAUNCHER_OFFSET_BOTTOM, EchoChat, chatLauncherStyles, isChatEnabled } from '../chunk-B7QRRLTU.js';
3
- export { SiteChat } from '../chunk-AGJODJ4V.js';
2
+ export { ChatWidget, DEFAULT_LAUNCHER_OFFSET_BOTTOM, EchoChat, chatLauncherStyles, isChatEnabled } from '../chunk-FVXFLVXF.js';
3
+ export { SiteChat } from '../chunk-NNEIBXGU.js';
4
4
  import '../chunk-6T6CQVNL.js';
5
5
  import '../chunk-JE4A5S4F.js';
6
6
  import '../chunk-27FISYK4.js';
7
- import '../chunk-3222QBUS.js';
7
+ import '../chunk-YBAFUM3Z.js';
8
8
  import '../chunk-Q6E4OPGG.js';
9
9
  import '../chunk-5ROTTMBL.js';
10
10
  import '../chunk-C2FZBUSS.js';
@@ -18,9 +18,9 @@ import '../chunk-GJWI74ZZ.js';
18
18
  import '../chunk-CAH4Y4PY.js';
19
19
  import '../chunk-EKBEOXTH.js';
20
20
  import '../chunk-3G7YABRA.js';
21
- import '../chunk-55JLUMAC.js';
22
- import '../chunk-IY6G67EF.js';
23
- import '../chunk-S5G3A7OZ.js';
21
+ import '../chunk-727R7C5R.js';
22
+ import '../chunk-3EU6S5YC.js';
23
+ import '../chunk-Q72M5KBS.js';
24
24
  import '../chunk-PKBMQBKP.js';
25
25
 
26
26
  // src/chat/echo-config.ts
@@ -1,4 +1,4 @@
1
- import { SITE_KIT_VERSION } from './chunk-S5G3A7OZ.js';
1
+ import { SITE_KIT_VERSION } from './chunk-Q72M5KBS.js';
2
2
 
3
3
  // src/shared/siteToken.ts
4
4
  var SITE_TOKEN_PREFIX = "st1.";
@@ -1,4 +1,4 @@
1
- import { generateLLMsTxt, generateLLMsFullTxt, appendAgentAccessSection } from './chunk-TZ5RTANX.js';
1
+ import { generateLLMsTxt, generateLLMsFullTxt, appendAgentAccessSection } from './chunk-WACWV5EP.js';
2
2
  import { createHash } from 'crypto';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import { join } from 'path';
@@ -1,4 +1,4 @@
1
- import { writeLLMsTxtToPublic } from './chunk-TZ5RTANX.js';
1
+ import { writeLLMsTxtToPublic } from './chunk-WACWV5EP.js';
2
2
  import { getSiteConfig } from './chunk-Z22QVHT4.js';
3
3
  import { buildFetch } from './chunk-UAYAJPEP.js';
4
4
  import { findAppDirForDiscovery } from './chunk-ZEGVKVD5.js';
@@ -1,5 +1,5 @@
1
1
  import { resolveSiteHost } from './chunk-FESKKJAS.js';
2
- import { configureSiteCredential, currentCredential } from './chunk-IY6G67EF.js';
2
+ import { configureSiteCredential, currentCredential } from './chunk-3EU6S5YC.js';
3
3
 
4
4
  // src/shared/publishCredential.ts
5
5
  function publishSiteCredential({
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { detectTimezone, releaseSlotHold, fetchBookingTypeDetails, fetchBookingTypes, fetchAvailability, createSlotHold, createBooking, formatDuration, formatDate, formatTime, prepareMeeting } from './chunk-YGXWG54S.js';
2
+ import { detectTimezone, releaseSlotHold, fetchBookingTypeDetails, fetchBookingTypes, fetchAvailability, createSlotHold, createBooking, formatDuration, formatDate, formatTime, prepareMeeting } from './chunk-XWIRU6UT.js';
3
3
  import { readPublishedApiConfig, DEFAULT_SONOR_API_URL } from './chunk-3G7YABRA.js';
4
4
  import { useState, useRef, useMemo, useCallback, useEffect, useId } from 'react';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
- import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-IY6G67EF.js';
2
- import { SITE_KIT_VERSION } from './chunk-S5G3A7OZ.js';
1
+ import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-3EU6S5YC.js';
2
+ import { SITE_KIT_VERSION } from './chunk-Q72M5KBS.js';
3
3
 
4
4
  // src/shared/fetchWithRetry.ts
5
5
  function backoffDelay(attempt, response) {
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-55JLUMAC.js';
2
+ import { sonorFetch } from './chunk-727R7C5R.js';
3
3
  import { useState, useCallback, useEffect } from 'react';
4
4
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -1,4 +1,4 @@
1
- import { FormEnhancer } from './chunk-GMXY2OOY.js';
1
+ import { FormEnhancer } from './chunk-SMYX3AAO.js';
2
2
  import { StaticForm } from './chunk-LNSF6BJC.js';
3
3
  import { serverApiFetch } from './chunk-C7TLGL3R.js';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -3,7 +3,7 @@ import { registerAnalyticsDispatcher } from './chunk-LCDVPAMR.js';
3
3
  import { getOrCreateVisitorId, getOrCreateSessionId } from './chunk-ZKADJNR2.js';
4
4
  import { onPageLeave } from './chunk-L2V5PUFN.js';
5
5
  import { resolveAnalyticsTarget } from './chunk-CAH4Y4PY.js';
6
- import { sonorFetch, sonorBeacon } from './chunk-55JLUMAC.js';
6
+ import { sonorFetch, sonorBeacon } from './chunk-727R7C5R.js';
7
7
  import { createContext, useRef, useEffect, useState, useMemo, useCallback, useContext } from 'react';
8
8
  import { usePathname } from 'next/navigation';
9
9
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,3 +1,4 @@
1
+ import { insertArticlePhotos } from './chunk-HUBMKTPW.js';
1
2
  import { generateArticleAuthorNode, resolveArticleArtwork, withArticleAuthorIdentity } from './chunk-QXMIKDOL.js';
2
3
  import { resolveArticleUrl, createPublicationRoutes, resolvePublicationUrl, articleCategorySlug } from './chunk-WMVK77ND.js';
3
4
  import { withoutSchemaPlaceholders } from './chunk-VWWITFWM.js';
@@ -599,7 +600,7 @@ async function generateRssFeed(options) {
599
600
  const postUrl = resolveArticleUrl(post, { ...options, siteUrl });
600
601
  const pubDate = post.published_at ? new Date(post.published_at).toUTCString() : now;
601
602
  const author = typeof post.author === "string" ? post.author : post.author?.name || "Unknown";
602
- const fullContent = post.content_html || post.content || "";
603
+ const fullContent = insertArticlePhotos(post.content_html || post.content || "", post.editorial_photos);
603
604
  const description2 = sanitizeExcerpt(post.excerpt, 300) || stripHtml(fullContent).substring(0, 300) + "...";
604
605
  rss += ` <item>
605
606
  <title>${escapeXml(post.title)}</title>
@@ -662,7 +663,7 @@ async function generateAtomFeed(options) {
662
663
  const updated = post.updated_at || post.published_at || now;
663
664
  const published = post.published_at || now;
664
665
  const author = typeof post.author === "string" ? post.author : post.author?.name || "Unknown";
665
- const fullContent = post.content_html || post.content || "";
666
+ const fullContent = insertArticlePhotos(post.content_html || post.content || "", post.editorial_photos);
666
667
  atom += ` <entry>
667
668
  <title>${escapeXml(post.title)}</title>
668
669
  <link href="${escapeXml(postUrl)}"/>
@@ -2,10 +2,10 @@
2
2
  import { VISUAL_VIEWPORT_GAP_PROPERTY } from './chunk-6T6CQVNL.js';
3
3
  import { GlassStyles } from './chunk-JE4A5S4F.js';
4
4
  import { DEFAULT_WIDGET_Z_INDEX } from './chunk-27FISYK4.js';
5
- import { useForm } from './chunk-3222QBUS.js';
5
+ import { useForm } from './chunk-YBAFUM3Z.js';
6
6
  import { parseColor, relativeLuminance, DARK_LUMINANCE, contrastRatio } from './chunk-S22FSH7C.js';
7
7
  import { readPublishedApiConfig } from './chunk-3G7YABRA.js';
8
- import { sonorFetch } from './chunk-55JLUMAC.js';
8
+ import { sonorFetch } from './chunk-727R7C5R.js';
9
9
  import { useState, useEffect, useRef, useLayoutEffect, useCallback, Fragment as Fragment$1 } from 'react';
10
10
  import { lexer } from 'marked';
11
11
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';