@dsaplatform/content-sdk 1.0.0 → 1.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.
- package/dist/headless.d.mts +101 -0
- package/dist/headless.d.ts +101 -0
- package/dist/headless.js +2 -0
- package/dist/headless.js.map +1 -0
- package/dist/headless.mjs +2 -0
- package/dist/headless.mjs.map +1 -0
- package/dist/index.d.mts +30 -20
- package/dist/index.d.ts +30 -20
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +4 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +1 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full article response from Content Engine
|
|
3
|
+
*/
|
|
4
|
+
interface Article {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
excerpt: string | null;
|
|
9
|
+
content_html: string;
|
|
10
|
+
content_json: any | null;
|
|
11
|
+
h1: string | null;
|
|
12
|
+
meta_title: string | null;
|
|
13
|
+
meta_description: string | null;
|
|
14
|
+
canonical_url?: string | null;
|
|
15
|
+
target_keyword: string | null;
|
|
16
|
+
secondary_keywords: string[];
|
|
17
|
+
headings: ArticleHeading[];
|
|
18
|
+
faq: FaqItem[];
|
|
19
|
+
internal_links: InternalLink[];
|
|
20
|
+
schema_json: any | null;
|
|
21
|
+
featured_image_url: string | null;
|
|
22
|
+
featured_image_alt: string | null;
|
|
23
|
+
publish_status: string;
|
|
24
|
+
published_at: string | null;
|
|
25
|
+
updated_at?: string | null;
|
|
26
|
+
word_count: number | null;
|
|
27
|
+
reading_time_minutes: number | null;
|
|
28
|
+
seo_score: number | null;
|
|
29
|
+
pillar_name?: string;
|
|
30
|
+
cluster_name?: string;
|
|
31
|
+
content_type?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Article heading (from H1-H6 tags)
|
|
35
|
+
*/
|
|
36
|
+
interface ArticleHeading {
|
|
37
|
+
level: number;
|
|
38
|
+
text: string;
|
|
39
|
+
id: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* FAQ item
|
|
43
|
+
*/
|
|
44
|
+
interface FaqItem {
|
|
45
|
+
question: string;
|
|
46
|
+
answer: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Internal link reference
|
|
50
|
+
*/
|
|
51
|
+
interface InternalLink {
|
|
52
|
+
slug: string;
|
|
53
|
+
anchor_text: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Headless utilities — data transformers with zero UI / zero inline styles.
|
|
58
|
+
* Use these to build your own components with shadcn/Tailwind/custom CSS.
|
|
59
|
+
*
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { buildTocData, buildFaqSchema, normalizeArticle } from '@dsaplatform/content-sdk/headless';
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/** TOC entry with indentation level for rendering */
|
|
66
|
+
interface TocEntry {
|
|
67
|
+
id: string;
|
|
68
|
+
text: string;
|
|
69
|
+
level: number;
|
|
70
|
+
/** Depth relative to minimum heading level (0-based) */
|
|
71
|
+
depth: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build TOC data from article headings.
|
|
75
|
+
* Normalizes depth so the shallowest heading is depth=0.
|
|
76
|
+
*/
|
|
77
|
+
declare function buildTocData(headings: ArticleHeading[]): TocEntry[];
|
|
78
|
+
/**
|
|
79
|
+
* Build Schema.org FAQPage JSON-LD object from FAQ items.
|
|
80
|
+
* Returns the object (not stringified) — you inject it into <script type="application/ld+json">.
|
|
81
|
+
*/
|
|
82
|
+
declare function buildFaqSchema(items: FaqItem[]): Record<string, any> | null;
|
|
83
|
+
/**
|
|
84
|
+
* Build Schema.org Article JSON-LD object.
|
|
85
|
+
*/
|
|
86
|
+
declare function buildArticleSchema(article: Article, siteUrl?: string): Record<string, any>;
|
|
87
|
+
/**
|
|
88
|
+
* Normalize an article response — ensures all array fields are arrays, never null.
|
|
89
|
+
*/
|
|
90
|
+
declare function normalizeArticle(article: Article): Article;
|
|
91
|
+
/**
|
|
92
|
+
* Extract plain text from content_html (strip tags).
|
|
93
|
+
* Useful for excerpts, search indexing, reading time calculation.
|
|
94
|
+
*/
|
|
95
|
+
declare function htmlToPlainText(html: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Calculate reading time from HTML content.
|
|
98
|
+
*/
|
|
99
|
+
declare function calculateReadingTime(html: string, wordsPerMinute?: number): number;
|
|
100
|
+
|
|
101
|
+
export { type Article, type ArticleHeading, type FaqItem, type TocEntry, buildArticleSchema, buildFaqSchema, buildTocData, calculateReadingTime, htmlToPlainText, normalizeArticle };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full article response from Content Engine
|
|
3
|
+
*/
|
|
4
|
+
interface Article {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
excerpt: string | null;
|
|
9
|
+
content_html: string;
|
|
10
|
+
content_json: any | null;
|
|
11
|
+
h1: string | null;
|
|
12
|
+
meta_title: string | null;
|
|
13
|
+
meta_description: string | null;
|
|
14
|
+
canonical_url?: string | null;
|
|
15
|
+
target_keyword: string | null;
|
|
16
|
+
secondary_keywords: string[];
|
|
17
|
+
headings: ArticleHeading[];
|
|
18
|
+
faq: FaqItem[];
|
|
19
|
+
internal_links: InternalLink[];
|
|
20
|
+
schema_json: any | null;
|
|
21
|
+
featured_image_url: string | null;
|
|
22
|
+
featured_image_alt: string | null;
|
|
23
|
+
publish_status: string;
|
|
24
|
+
published_at: string | null;
|
|
25
|
+
updated_at?: string | null;
|
|
26
|
+
word_count: number | null;
|
|
27
|
+
reading_time_minutes: number | null;
|
|
28
|
+
seo_score: number | null;
|
|
29
|
+
pillar_name?: string;
|
|
30
|
+
cluster_name?: string;
|
|
31
|
+
content_type?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Article heading (from H1-H6 tags)
|
|
35
|
+
*/
|
|
36
|
+
interface ArticleHeading {
|
|
37
|
+
level: number;
|
|
38
|
+
text: string;
|
|
39
|
+
id: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* FAQ item
|
|
43
|
+
*/
|
|
44
|
+
interface FaqItem {
|
|
45
|
+
question: string;
|
|
46
|
+
answer: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Internal link reference
|
|
50
|
+
*/
|
|
51
|
+
interface InternalLink {
|
|
52
|
+
slug: string;
|
|
53
|
+
anchor_text: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Headless utilities — data transformers with zero UI / zero inline styles.
|
|
58
|
+
* Use these to build your own components with shadcn/Tailwind/custom CSS.
|
|
59
|
+
*
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { buildTocData, buildFaqSchema, normalizeArticle } from '@dsaplatform/content-sdk/headless';
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/** TOC entry with indentation level for rendering */
|
|
66
|
+
interface TocEntry {
|
|
67
|
+
id: string;
|
|
68
|
+
text: string;
|
|
69
|
+
level: number;
|
|
70
|
+
/** Depth relative to minimum heading level (0-based) */
|
|
71
|
+
depth: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build TOC data from article headings.
|
|
75
|
+
* Normalizes depth so the shallowest heading is depth=0.
|
|
76
|
+
*/
|
|
77
|
+
declare function buildTocData(headings: ArticleHeading[]): TocEntry[];
|
|
78
|
+
/**
|
|
79
|
+
* Build Schema.org FAQPage JSON-LD object from FAQ items.
|
|
80
|
+
* Returns the object (not stringified) — you inject it into <script type="application/ld+json">.
|
|
81
|
+
*/
|
|
82
|
+
declare function buildFaqSchema(items: FaqItem[]): Record<string, any> | null;
|
|
83
|
+
/**
|
|
84
|
+
* Build Schema.org Article JSON-LD object.
|
|
85
|
+
*/
|
|
86
|
+
declare function buildArticleSchema(article: Article, siteUrl?: string): Record<string, any>;
|
|
87
|
+
/**
|
|
88
|
+
* Normalize an article response — ensures all array fields are arrays, never null.
|
|
89
|
+
*/
|
|
90
|
+
declare function normalizeArticle(article: Article): Article;
|
|
91
|
+
/**
|
|
92
|
+
* Extract plain text from content_html (strip tags).
|
|
93
|
+
* Useful for excerpts, search indexing, reading time calculation.
|
|
94
|
+
*/
|
|
95
|
+
declare function htmlToPlainText(html: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Calculate reading time from HTML content.
|
|
98
|
+
*/
|
|
99
|
+
declare function calculateReadingTime(html: string, wordsPerMinute?: number): number;
|
|
100
|
+
|
|
101
|
+
export { type Article, type ArticleHeading, type FaqItem, type TocEntry, buildArticleSchema, buildFaqSchema, buildTocData, calculateReadingTime, htmlToPlainText, normalizeArticle };
|
package/dist/headless.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var i=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var u=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},c=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of a(t))!l.call(e,r)&&r!==n&&i(e,r,{get:()=>t[r],enumerable:!(o=d(t,r))||o.enumerable});return e};var p=e=>c(i({},"__esModule",{value:!0}),e);var f={};u(f,{buildArticleSchema:()=>_,buildFaqSchema:()=>g,buildTocData:()=>m,calculateReadingTime:()=>h,htmlToPlainText:()=>s,normalizeArticle:()=>y});module.exports=p(f);function m(e){if(!e||e.length===0)return[];let t=Math.min(...e.map(n=>n.level));return e.map(n=>({id:n.id,text:n.text,level:n.level,depth:n.level-t}))}function g(e){return!e||e.length===0?null:{"@context":"https://schema.org","@type":"FAQPage",mainEntity:e.map(t=>({"@type":"Question",name:t.question,acceptedAnswer:{"@type":"Answer",text:t.answer}}))}}function _(e,t){if(e.schema_json&&Object.keys(e.schema_json).length>0)return e.schema_json;let n=t?`${t.replace(/\/+$/,"")}/blog/${e.slug}`:void 0;return{"@context":"https://schema.org","@type":"Article",headline:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",datePublished:e.published_at||void 0,dateModified:e.updated_at||e.published_at||void 0,...e.featured_image_url?{image:e.featured_image_url}:{},...n?{url:n}:{},...e.target_keyword?{keywords:[e.target_keyword,...e.secondary_keywords||[]].join(", ")}:{}}}function y(e){return{...e,headings:e.headings??[],faq:e.faq??[],internal_links:e.internal_links??[],secondary_keywords:e.secondary_keywords??[],schema_json:e.schema_json??null,content_json:e.content_json??null}}function s(e){return e.replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim()}function h(e,t=200){let o=s(e).split(/\s+/).filter(Boolean).length;return Math.max(1,Math.ceil(o/t))}0&&(module.exports={buildArticleSchema,buildFaqSchema,buildTocData,calculateReadingTime,htmlToPlainText,normalizeArticle});
|
|
2
|
+
//# sourceMappingURL=headless.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/headless.ts"],"sourcesContent":["/**\n * Headless utilities — data transformers with zero UI / zero inline styles.\n * Use these to build your own components with shadcn/Tailwind/custom CSS.\n *\n * ```ts\n * import { buildTocData, buildFaqSchema, normalizeArticle } from '@dsaplatform/content-sdk/headless';\n * ```\n */\nimport type { Article, ArticleHeading, FaqItem } from './types';\n\nexport type { Article, ArticleHeading, FaqItem };\n\n/** TOC entry with indentation level for rendering */\nexport interface TocEntry {\n id: string;\n text: string;\n level: number;\n /** Depth relative to minimum heading level (0-based) */\n depth: number;\n}\n\n/**\n * Build TOC data from article headings.\n * Normalizes depth so the shallowest heading is depth=0.\n */\nexport function buildTocData(headings: ArticleHeading[]): TocEntry[] {\n if (!headings || headings.length === 0) return [];\n const minLevel = Math.min(...headings.map((h) => h.level));\n return headings.map((h) => ({\n id: h.id,\n text: h.text,\n level: h.level,\n depth: h.level - minLevel,\n }));\n}\n\n/**\n * Build Schema.org FAQPage JSON-LD object from FAQ items.\n * Returns the object (not stringified) — you inject it into <script type=\"application/ld+json\">.\n */\nexport function buildFaqSchema(items: FaqItem[]): Record<string, any> | null {\n if (!items || items.length === 0) return null;\n return {\n '@context': 'https://schema.org',\n '@type': 'FAQPage',\n mainEntity: items.map((item) => ({\n '@type': 'Question',\n name: item.question,\n acceptedAnswer: { '@type': 'Answer', text: item.answer },\n })),\n };\n}\n\n/**\n * Build Schema.org Article JSON-LD object.\n */\nexport function buildArticleSchema(\n article: Article,\n siteUrl?: string,\n): Record<string, any> {\n if (article.schema_json && Object.keys(article.schema_json).length > 0) {\n return article.schema_json;\n }\n const url = siteUrl\n ? `${siteUrl.replace(/\\/+$/, '')}/blog/${article.slug}`\n : undefined;\n return {\n '@context': 'https://schema.org',\n '@type': 'Article',\n headline: article.meta_title || article.title,\n description: article.meta_description || article.excerpt || '',\n datePublished: article.published_at || undefined,\n dateModified: article.updated_at || article.published_at || undefined,\n ...(article.featured_image_url ? { image: article.featured_image_url } : {}),\n ...(url ? { url } : {}),\n ...(article.target_keyword\n ? { keywords: [article.target_keyword, ...(article.secondary_keywords || [])].join(', ') }\n : {}),\n };\n}\n\n/**\n * Normalize an article response — ensures all array fields are arrays, never null.\n */\nexport function normalizeArticle(article: Article): Article {\n return {\n ...article,\n headings: article.headings ?? [],\n faq: article.faq ?? [],\n internal_links: article.internal_links ?? [],\n secondary_keywords: article.secondary_keywords ?? [],\n schema_json: article.schema_json ?? null,\n content_json: article.content_json ?? null,\n };\n}\n\n/**\n * Extract plain text from content_html (strip tags).\n * Useful for excerpts, search indexing, reading time calculation.\n */\nexport function htmlToPlainText(html: string): string {\n return html.replace(/<[^>]+>/g, '').replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Calculate reading time from HTML content.\n */\nexport function calculateReadingTime(html: string, wordsPerMinute = 200): number {\n const text = htmlToPlainText(html);\n const words = text.split(/\\s+/).filter(Boolean).length;\n return Math.max(1, Math.ceil(words / wordsPerMinute));\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wBAAAE,EAAA,mBAAAC,EAAA,iBAAAC,EAAA,yBAAAC,EAAA,oBAAAC,EAAA,qBAAAC,IAAA,eAAAC,EAAAR,GAyBO,SAASI,EAAaK,EAAwC,CACnE,GAAI,CAACA,GAAYA,EAAS,SAAW,EAAG,MAAO,CAAC,EAChD,IAAMC,EAAW,KAAK,IAAI,GAAGD,EAAS,IAAKE,GAAMA,EAAE,KAAK,CAAC,EACzD,OAAOF,EAAS,IAAKE,IAAO,CAC1B,GAAIA,EAAE,GACN,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,MAAOA,EAAE,MAAQD,CACnB,EAAE,CACJ,CAMO,SAASP,EAAeS,EAA8C,CAC3E,MAAI,CAACA,GAASA,EAAM,SAAW,EAAU,KAClC,CACL,WAAY,qBACZ,QAAS,UACT,WAAYA,EAAM,IAAKC,IAAU,CAC/B,QAAS,WACT,KAAMA,EAAK,SACX,eAAgB,CAAE,QAAS,SAAU,KAAMA,EAAK,MAAO,CACzD,EAAE,CACJ,CACF,CAKO,SAASX,EACdY,EACAC,EACqB,CACrB,GAAID,EAAQ,aAAe,OAAO,KAAKA,EAAQ,WAAW,EAAE,OAAS,EACnE,OAAOA,EAAQ,YAEjB,IAAME,EAAMD,EACR,GAAGA,EAAQ,QAAQ,OAAQ,EAAE,CAAC,SAASD,EAAQ,IAAI,GACnD,OACJ,MAAO,CACL,WAAY,qBACZ,QAAS,UACT,SAAUA,EAAQ,YAAcA,EAAQ,MACxC,YAAaA,EAAQ,kBAAoBA,EAAQ,SAAW,GAC5D,cAAeA,EAAQ,cAAgB,OACvC,aAAcA,EAAQ,YAAcA,EAAQ,cAAgB,OAC5D,GAAIA,EAAQ,mBAAqB,CAAE,MAAOA,EAAQ,kBAAmB,EAAI,CAAC,EAC1E,GAAIE,EAAM,CAAE,IAAAA,CAAI,EAAI,CAAC,EACrB,GAAIF,EAAQ,eACR,CAAE,SAAU,CAACA,EAAQ,eAAgB,GAAIA,EAAQ,oBAAsB,CAAC,CAAE,EAAE,KAAK,IAAI,CAAE,EACvF,CAAC,CACP,CACF,CAKO,SAASP,EAAiBO,EAA2B,CAC1D,MAAO,CACL,GAAGA,EACH,SAAUA,EAAQ,UAAY,CAAC,EAC/B,IAAKA,EAAQ,KAAO,CAAC,EACrB,eAAgBA,EAAQ,gBAAkB,CAAC,EAC3C,mBAAoBA,EAAQ,oBAAsB,CAAC,EACnD,YAAaA,EAAQ,aAAe,KACpC,aAAcA,EAAQ,cAAgB,IACxC,CACF,CAMO,SAASR,EAAgBW,EAAsB,CACpD,OAAOA,EAAK,QAAQ,WAAY,EAAE,EAAE,QAAQ,OAAQ,GAAG,EAAE,KAAK,CAChE,CAKO,SAASZ,EAAqBY,EAAcC,EAAiB,IAAa,CAE/E,IAAMC,EADOb,EAAgBW,CAAI,EACd,MAAM,KAAK,EAAE,OAAO,OAAO,EAAE,OAChD,OAAO,KAAK,IAAI,EAAG,KAAK,KAAKE,EAAQD,CAAc,CAAC,CACtD","names":["headless_exports","__export","buildArticleSchema","buildFaqSchema","buildTocData","calculateReadingTime","htmlToPlainText","normalizeArticle","__toCommonJS","headings","minLevel","h","items","item","article","siteUrl","url","html","wordsPerMinute","words"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function i(e){if(!e||e.length===0)return[];let n=Math.min(...e.map(t=>t.level));return e.map(t=>({id:t.id,text:t.text,level:t.level,depth:t.level-n}))}function s(e){return!e||e.length===0?null:{"@context":"https://schema.org","@type":"FAQPage",mainEntity:e.map(n=>({"@type":"Question",name:n.question,acceptedAnswer:{"@type":"Answer",text:n.answer}}))}}function d(e,n){if(e.schema_json&&Object.keys(e.schema_json).length>0)return e.schema_json;let t=n?`${n.replace(/\/+$/,"")}/blog/${e.slug}`:void 0;return{"@context":"https://schema.org","@type":"Article",headline:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",datePublished:e.published_at||void 0,dateModified:e.updated_at||e.published_at||void 0,...e.featured_image_url?{image:e.featured_image_url}:{},...t?{url:t}:{},...e.target_keyword?{keywords:[e.target_keyword,...e.secondary_keywords||[]].join(", ")}:{}}}function a(e){return{...e,headings:e.headings??[],faq:e.faq??[],internal_links:e.internal_links??[],secondary_keywords:e.secondary_keywords??[],schema_json:e.schema_json??null,content_json:e.content_json??null}}function o(e){return e.replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim()}function l(e,n=200){let r=o(e).split(/\s+/).filter(Boolean).length;return Math.max(1,Math.ceil(r/n))}export{d as buildArticleSchema,s as buildFaqSchema,i as buildTocData,l as calculateReadingTime,o as htmlToPlainText,a as normalizeArticle};
|
|
2
|
+
//# sourceMappingURL=headless.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/headless.ts"],"sourcesContent":["/**\n * Headless utilities — data transformers with zero UI / zero inline styles.\n * Use these to build your own components with shadcn/Tailwind/custom CSS.\n *\n * ```ts\n * import { buildTocData, buildFaqSchema, normalizeArticle } from '@dsaplatform/content-sdk/headless';\n * ```\n */\nimport type { Article, ArticleHeading, FaqItem } from './types';\n\nexport type { Article, ArticleHeading, FaqItem };\n\n/** TOC entry with indentation level for rendering */\nexport interface TocEntry {\n id: string;\n text: string;\n level: number;\n /** Depth relative to minimum heading level (0-based) */\n depth: number;\n}\n\n/**\n * Build TOC data from article headings.\n * Normalizes depth so the shallowest heading is depth=0.\n */\nexport function buildTocData(headings: ArticleHeading[]): TocEntry[] {\n if (!headings || headings.length === 0) return [];\n const minLevel = Math.min(...headings.map((h) => h.level));\n return headings.map((h) => ({\n id: h.id,\n text: h.text,\n level: h.level,\n depth: h.level - minLevel,\n }));\n}\n\n/**\n * Build Schema.org FAQPage JSON-LD object from FAQ items.\n * Returns the object (not stringified) — you inject it into <script type=\"application/ld+json\">.\n */\nexport function buildFaqSchema(items: FaqItem[]): Record<string, any> | null {\n if (!items || items.length === 0) return null;\n return {\n '@context': 'https://schema.org',\n '@type': 'FAQPage',\n mainEntity: items.map((item) => ({\n '@type': 'Question',\n name: item.question,\n acceptedAnswer: { '@type': 'Answer', text: item.answer },\n })),\n };\n}\n\n/**\n * Build Schema.org Article JSON-LD object.\n */\nexport function buildArticleSchema(\n article: Article,\n siteUrl?: string,\n): Record<string, any> {\n if (article.schema_json && Object.keys(article.schema_json).length > 0) {\n return article.schema_json;\n }\n const url = siteUrl\n ? `${siteUrl.replace(/\\/+$/, '')}/blog/${article.slug}`\n : undefined;\n return {\n '@context': 'https://schema.org',\n '@type': 'Article',\n headline: article.meta_title || article.title,\n description: article.meta_description || article.excerpt || '',\n datePublished: article.published_at || undefined,\n dateModified: article.updated_at || article.published_at || undefined,\n ...(article.featured_image_url ? { image: article.featured_image_url } : {}),\n ...(url ? { url } : {}),\n ...(article.target_keyword\n ? { keywords: [article.target_keyword, ...(article.secondary_keywords || [])].join(', ') }\n : {}),\n };\n}\n\n/**\n * Normalize an article response — ensures all array fields are arrays, never null.\n */\nexport function normalizeArticle(article: Article): Article {\n return {\n ...article,\n headings: article.headings ?? [],\n faq: article.faq ?? [],\n internal_links: article.internal_links ?? [],\n secondary_keywords: article.secondary_keywords ?? [],\n schema_json: article.schema_json ?? null,\n content_json: article.content_json ?? null,\n };\n}\n\n/**\n * Extract plain text from content_html (strip tags).\n * Useful for excerpts, search indexing, reading time calculation.\n */\nexport function htmlToPlainText(html: string): string {\n return html.replace(/<[^>]+>/g, '').replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Calculate reading time from HTML content.\n */\nexport function calculateReadingTime(html: string, wordsPerMinute = 200): number {\n const text = htmlToPlainText(html);\n const words = text.split(/\\s+/).filter(Boolean).length;\n return Math.max(1, Math.ceil(words / wordsPerMinute));\n}\n"],"mappings":"AAyBO,SAASA,EAAaC,EAAwC,CACnE,GAAI,CAACA,GAAYA,EAAS,SAAW,EAAG,MAAO,CAAC,EAChD,IAAMC,EAAW,KAAK,IAAI,GAAGD,EAAS,IAAKE,GAAMA,EAAE,KAAK,CAAC,EACzD,OAAOF,EAAS,IAAKE,IAAO,CAC1B,GAAIA,EAAE,GACN,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,MAAOA,EAAE,MAAQD,CACnB,EAAE,CACJ,CAMO,SAASE,EAAeC,EAA8C,CAC3E,MAAI,CAACA,GAASA,EAAM,SAAW,EAAU,KAClC,CACL,WAAY,qBACZ,QAAS,UACT,WAAYA,EAAM,IAAKC,IAAU,CAC/B,QAAS,WACT,KAAMA,EAAK,SACX,eAAgB,CAAE,QAAS,SAAU,KAAMA,EAAK,MAAO,CACzD,EAAE,CACJ,CACF,CAKO,SAASC,EACdC,EACAC,EACqB,CACrB,GAAID,EAAQ,aAAe,OAAO,KAAKA,EAAQ,WAAW,EAAE,OAAS,EACnE,OAAOA,EAAQ,YAEjB,IAAME,EAAMD,EACR,GAAGA,EAAQ,QAAQ,OAAQ,EAAE,CAAC,SAASD,EAAQ,IAAI,GACnD,OACJ,MAAO,CACL,WAAY,qBACZ,QAAS,UACT,SAAUA,EAAQ,YAAcA,EAAQ,MACxC,YAAaA,EAAQ,kBAAoBA,EAAQ,SAAW,GAC5D,cAAeA,EAAQ,cAAgB,OACvC,aAAcA,EAAQ,YAAcA,EAAQ,cAAgB,OAC5D,GAAIA,EAAQ,mBAAqB,CAAE,MAAOA,EAAQ,kBAAmB,EAAI,CAAC,EAC1E,GAAIE,EAAM,CAAE,IAAAA,CAAI,EAAI,CAAC,EACrB,GAAIF,EAAQ,eACR,CAAE,SAAU,CAACA,EAAQ,eAAgB,GAAIA,EAAQ,oBAAsB,CAAC,CAAE,EAAE,KAAK,IAAI,CAAE,EACvF,CAAC,CACP,CACF,CAKO,SAASG,EAAiBH,EAA2B,CAC1D,MAAO,CACL,GAAGA,EACH,SAAUA,EAAQ,UAAY,CAAC,EAC/B,IAAKA,EAAQ,KAAO,CAAC,EACrB,eAAgBA,EAAQ,gBAAkB,CAAC,EAC3C,mBAAoBA,EAAQ,oBAAsB,CAAC,EACnD,YAAaA,EAAQ,aAAe,KACpC,aAAcA,EAAQ,cAAgB,IACxC,CACF,CAMO,SAASI,EAAgBC,EAAsB,CACpD,OAAOA,EAAK,QAAQ,WAAY,EAAE,EAAE,QAAQ,OAAQ,GAAG,EAAE,KAAK,CAChE,CAKO,SAASC,EAAqBD,EAAcE,EAAiB,IAAa,CAE/E,IAAMC,EADOJ,EAAgBC,CAAI,EACd,MAAM,KAAK,EAAE,OAAO,OAAO,EAAE,OAChD,OAAO,KAAK,IAAI,EAAG,KAAK,KAAKG,EAAQD,CAAc,CAAC,CACtD","names":["buildTocData","headings","minLevel","h","buildFaqSchema","items","item","buildArticleSchema","article","siteUrl","url","normalizeArticle","htmlToPlainText","html","calculateReadingTime","wordsPerMinute","words"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -56,10 +56,14 @@ interface ArticleListItem {
|
|
|
56
56
|
excerpt: string | null;
|
|
57
57
|
featured_image_url: string | null;
|
|
58
58
|
featured_image_alt: string | null;
|
|
59
|
+
target_keyword: string | null;
|
|
59
60
|
published_at: string | null;
|
|
60
61
|
pillar_name?: string;
|
|
61
62
|
cluster_name?: string;
|
|
62
63
|
content_type?: string;
|
|
64
|
+
funnel_stage?: string;
|
|
65
|
+
intent?: string;
|
|
66
|
+
word_count: number | null;
|
|
63
67
|
reading_time_minutes: number | null;
|
|
64
68
|
}
|
|
65
69
|
/**
|
|
@@ -183,6 +187,8 @@ declare class ContentClient {
|
|
|
183
187
|
private revalidateSeconds?;
|
|
184
188
|
constructor(config: DsaContentConfig);
|
|
185
189
|
private request;
|
|
190
|
+
/** Normalize article array fields to guarantee they're never null/undefined */
|
|
191
|
+
private normalizeArticle;
|
|
186
192
|
/** Get paginated list of published articles */
|
|
187
193
|
getArticles(filters?: ArticleFilters): Promise<PaginatedResponse<ArticleListItem>>;
|
|
188
194
|
/** Get a single article by slug */
|
|
@@ -266,16 +272,20 @@ interface ArticleFeedProps {
|
|
|
266
272
|
showMeta?: boolean;
|
|
267
273
|
onArticleClick?: (slug: string) => void;
|
|
268
274
|
className?: string;
|
|
275
|
+
/** "light" | "dark" | "inherit" — sets CSS variable defaults. Use "inherit" to control via your own CSS vars. */
|
|
276
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
269
277
|
renderArticle?: (article: ArticleListItem) => React.ReactNode;
|
|
270
278
|
}
|
|
271
279
|
/**
|
|
272
280
|
* Renders a grid or list of article cards.
|
|
281
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
273
282
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
283
|
+
* CSS variables (override in your own CSS for full control):
|
|
284
|
+
* --dsa-text, --dsa-text-muted, --dsa-text-faint,
|
|
285
|
+
* --dsa-card-bg, --dsa-card-border,
|
|
286
|
+
* --dsa-badge-bg, --dsa-badge-text, --dsa-hover-shadow
|
|
277
287
|
*/
|
|
278
|
-
declare function ArticleFeed({ articles, layout, columns, showExcerpt, showImage, showMeta, onArticleClick, className, renderArticle, }: ArticleFeedProps): react_jsx_runtime.JSX.Element;
|
|
288
|
+
declare function ArticleFeed({ articles, layout, columns, showExcerpt, showImage, showMeta, onArticleClick, className, theme, renderArticle, }: ArticleFeedProps): react_jsx_runtime.JSX.Element;
|
|
279
289
|
|
|
280
290
|
interface ArticlePageProps {
|
|
281
291
|
article: Article;
|
|
@@ -286,6 +296,8 @@ interface ArticlePageProps {
|
|
|
286
296
|
relatedArticles?: ArticleListItem[];
|
|
287
297
|
onRelatedClick?: (slug: string) => void;
|
|
288
298
|
className?: string;
|
|
299
|
+
/** "light" | "dark" | "inherit" — sets CSS variable defaults */
|
|
300
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
289
301
|
components?: {
|
|
290
302
|
H1?: React.ComponentType<{
|
|
291
303
|
children: React.ReactNode;
|
|
@@ -299,13 +311,13 @@ interface ArticlePageProps {
|
|
|
299
311
|
};
|
|
300
312
|
}
|
|
301
313
|
/**
|
|
302
|
-
*
|
|
314
|
+
* Full article page with optional TOC, FAQ, related articles, and JSON-LD.
|
|
315
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
303
316
|
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* ```
|
|
317
|
+
* CSS variables: --dsa-text, --dsa-text-muted, --dsa-toc-bg, --dsa-card-border,
|
|
318
|
+
* --dsa-badge-bg, --dsa-badge-text, --dsa-content-text, --dsa-divider
|
|
307
319
|
*/
|
|
308
|
-
declare function ArticlePage({ article, showFaq, showTableOfContents, showMeta, showRelated, relatedArticles, onRelatedClick, className, components, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
|
|
320
|
+
declare function ArticlePage({ article, showFaq, showTableOfContents, showMeta, showRelated, relatedArticles, onRelatedClick, className, theme, components, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
|
|
309
321
|
|
|
310
322
|
interface FaqBlockProps {
|
|
311
323
|
items: FaqItem[];
|
|
@@ -313,15 +325,14 @@ interface FaqBlockProps {
|
|
|
313
325
|
defaultOpen?: boolean;
|
|
314
326
|
className?: string;
|
|
315
327
|
title?: string;
|
|
328
|
+
/** "light" | "dark" | "inherit" */
|
|
329
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
316
330
|
}
|
|
317
331
|
/**
|
|
318
|
-
* FAQ block with
|
|
319
|
-
*
|
|
320
|
-
* ```tsx
|
|
321
|
-
* <FaqBlock items={article.faq} collapsible />
|
|
322
|
-
* ```
|
|
332
|
+
* FAQ block with Schema.org FAQPage markup.
|
|
333
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
323
334
|
*/
|
|
324
|
-
declare function FaqBlock({ items, collapsible, defaultOpen, className, title, }: FaqBlockProps): react_jsx_runtime.JSX.Element | null;
|
|
335
|
+
declare function FaqBlock({ items, collapsible, defaultOpen, className, title, theme, }: FaqBlockProps): react_jsx_runtime.JSX.Element | null;
|
|
325
336
|
|
|
326
337
|
interface RelatedArticlesProps {
|
|
327
338
|
articles: ArticleListItem[];
|
|
@@ -329,15 +340,14 @@ interface RelatedArticlesProps {
|
|
|
329
340
|
limit?: number;
|
|
330
341
|
onArticleClick?: (slug: string) => void;
|
|
331
342
|
className?: string;
|
|
343
|
+
/** "light" | "dark" | "inherit" */
|
|
344
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
332
345
|
}
|
|
333
346
|
/**
|
|
334
347
|
* Related articles widget.
|
|
335
|
-
*
|
|
336
|
-
* ```tsx
|
|
337
|
-
* <RelatedArticles articles={related} onArticleClick={(slug) => router.push(`/blog/${slug}`)} />
|
|
338
|
-
* ```
|
|
348
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
339
349
|
*/
|
|
340
|
-
declare function RelatedArticles({ articles, title, limit, onArticleClick, className, }: RelatedArticlesProps): react_jsx_runtime.JSX.Element | null;
|
|
350
|
+
declare function RelatedArticles({ articles, title, limit, onArticleClick, className, theme, }: RelatedArticlesProps): react_jsx_runtime.JSX.Element | null;
|
|
341
351
|
|
|
342
352
|
/**
|
|
343
353
|
* Generate Next.js App Router Metadata object from an Article.
|
package/dist/index.d.ts
CHANGED
|
@@ -56,10 +56,14 @@ interface ArticleListItem {
|
|
|
56
56
|
excerpt: string | null;
|
|
57
57
|
featured_image_url: string | null;
|
|
58
58
|
featured_image_alt: string | null;
|
|
59
|
+
target_keyword: string | null;
|
|
59
60
|
published_at: string | null;
|
|
60
61
|
pillar_name?: string;
|
|
61
62
|
cluster_name?: string;
|
|
62
63
|
content_type?: string;
|
|
64
|
+
funnel_stage?: string;
|
|
65
|
+
intent?: string;
|
|
66
|
+
word_count: number | null;
|
|
63
67
|
reading_time_minutes: number | null;
|
|
64
68
|
}
|
|
65
69
|
/**
|
|
@@ -183,6 +187,8 @@ declare class ContentClient {
|
|
|
183
187
|
private revalidateSeconds?;
|
|
184
188
|
constructor(config: DsaContentConfig);
|
|
185
189
|
private request;
|
|
190
|
+
/** Normalize article array fields to guarantee they're never null/undefined */
|
|
191
|
+
private normalizeArticle;
|
|
186
192
|
/** Get paginated list of published articles */
|
|
187
193
|
getArticles(filters?: ArticleFilters): Promise<PaginatedResponse<ArticleListItem>>;
|
|
188
194
|
/** Get a single article by slug */
|
|
@@ -266,16 +272,20 @@ interface ArticleFeedProps {
|
|
|
266
272
|
showMeta?: boolean;
|
|
267
273
|
onArticleClick?: (slug: string) => void;
|
|
268
274
|
className?: string;
|
|
275
|
+
/** "light" | "dark" | "inherit" — sets CSS variable defaults. Use "inherit" to control via your own CSS vars. */
|
|
276
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
269
277
|
renderArticle?: (article: ArticleListItem) => React.ReactNode;
|
|
270
278
|
}
|
|
271
279
|
/**
|
|
272
280
|
* Renders a grid or list of article cards.
|
|
281
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
273
282
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
283
|
+
* CSS variables (override in your own CSS for full control):
|
|
284
|
+
* --dsa-text, --dsa-text-muted, --dsa-text-faint,
|
|
285
|
+
* --dsa-card-bg, --dsa-card-border,
|
|
286
|
+
* --dsa-badge-bg, --dsa-badge-text, --dsa-hover-shadow
|
|
277
287
|
*/
|
|
278
|
-
declare function ArticleFeed({ articles, layout, columns, showExcerpt, showImage, showMeta, onArticleClick, className, renderArticle, }: ArticleFeedProps): react_jsx_runtime.JSX.Element;
|
|
288
|
+
declare function ArticleFeed({ articles, layout, columns, showExcerpt, showImage, showMeta, onArticleClick, className, theme, renderArticle, }: ArticleFeedProps): react_jsx_runtime.JSX.Element;
|
|
279
289
|
|
|
280
290
|
interface ArticlePageProps {
|
|
281
291
|
article: Article;
|
|
@@ -286,6 +296,8 @@ interface ArticlePageProps {
|
|
|
286
296
|
relatedArticles?: ArticleListItem[];
|
|
287
297
|
onRelatedClick?: (slug: string) => void;
|
|
288
298
|
className?: string;
|
|
299
|
+
/** "light" | "dark" | "inherit" — sets CSS variable defaults */
|
|
300
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
289
301
|
components?: {
|
|
290
302
|
H1?: React.ComponentType<{
|
|
291
303
|
children: React.ReactNode;
|
|
@@ -299,13 +311,13 @@ interface ArticlePageProps {
|
|
|
299
311
|
};
|
|
300
312
|
}
|
|
301
313
|
/**
|
|
302
|
-
*
|
|
314
|
+
* Full article page with optional TOC, FAQ, related articles, and JSON-LD.
|
|
315
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
303
316
|
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* ```
|
|
317
|
+
* CSS variables: --dsa-text, --dsa-text-muted, --dsa-toc-bg, --dsa-card-border,
|
|
318
|
+
* --dsa-badge-bg, --dsa-badge-text, --dsa-content-text, --dsa-divider
|
|
307
319
|
*/
|
|
308
|
-
declare function ArticlePage({ article, showFaq, showTableOfContents, showMeta, showRelated, relatedArticles, onRelatedClick, className, components, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
|
|
320
|
+
declare function ArticlePage({ article, showFaq, showTableOfContents, showMeta, showRelated, relatedArticles, onRelatedClick, className, theme, components, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
|
|
309
321
|
|
|
310
322
|
interface FaqBlockProps {
|
|
311
323
|
items: FaqItem[];
|
|
@@ -313,15 +325,14 @@ interface FaqBlockProps {
|
|
|
313
325
|
defaultOpen?: boolean;
|
|
314
326
|
className?: string;
|
|
315
327
|
title?: string;
|
|
328
|
+
/** "light" | "dark" | "inherit" */
|
|
329
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
316
330
|
}
|
|
317
331
|
/**
|
|
318
|
-
* FAQ block with
|
|
319
|
-
*
|
|
320
|
-
* ```tsx
|
|
321
|
-
* <FaqBlock items={article.faq} collapsible />
|
|
322
|
-
* ```
|
|
332
|
+
* FAQ block with Schema.org FAQPage markup.
|
|
333
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
323
334
|
*/
|
|
324
|
-
declare function FaqBlock({ items, collapsible, defaultOpen, className, title, }: FaqBlockProps): react_jsx_runtime.JSX.Element | null;
|
|
335
|
+
declare function FaqBlock({ items, collapsible, defaultOpen, className, title, theme, }: FaqBlockProps): react_jsx_runtime.JSX.Element | null;
|
|
325
336
|
|
|
326
337
|
interface RelatedArticlesProps {
|
|
327
338
|
articles: ArticleListItem[];
|
|
@@ -329,15 +340,14 @@ interface RelatedArticlesProps {
|
|
|
329
340
|
limit?: number;
|
|
330
341
|
onArticleClick?: (slug: string) => void;
|
|
331
342
|
className?: string;
|
|
343
|
+
/** "light" | "dark" | "inherit" */
|
|
344
|
+
theme?: 'light' | 'dark' | 'inherit';
|
|
332
345
|
}
|
|
333
346
|
/**
|
|
334
347
|
* Related articles widget.
|
|
335
|
-
*
|
|
336
|
-
* ```tsx
|
|
337
|
-
* <RelatedArticles articles={related} onArticleClick={(slug) => router.push(`/blog/${slug}`)} />
|
|
338
|
-
* ```
|
|
348
|
+
* Supports theme="light" | "dark" | "inherit" via CSS variables.
|
|
339
349
|
*/
|
|
340
|
-
declare function RelatedArticles({ articles, title, limit, onArticleClick, className, }: RelatedArticlesProps): react_jsx_runtime.JSX.Element | null;
|
|
350
|
+
declare function RelatedArticles({ articles, title, limit, onArticleClick, className, theme, }: RelatedArticlesProps): react_jsx_runtime.JSX.Element | null;
|
|
341
351
|
|
|
342
352
|
/**
|
|
343
353
|
* Generate Next.js App Router Metadata object from an Article.
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var W=Object.create;var R=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var J=(e,t)=>{for(var r in t)R(e,r,{get:t[r],enumerable:!0})},q=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of K(t))!G.call(e,a)&&a!==r&&R(e,a,{get:()=>t[a],enumerable:!(i=O(t,a))||i.enumerable});return e};var Q=(e,t,r)=>(r=e!=null?W(j(e)):{},q(t||!e||!e.__esModule?R(r,"default",{value:e,enumerable:!0}):r,e)),X=e=>q(R({},"__esModule",{value:!0}),e);var ee={};J(ee,{ArticleFeed:()=>w,ArticlePage:()=>k,ContentClient:()=>C,DsaContentProvider:()=>T,FaqBlock:()=>x,RelatedArticles:()=>P,SeoMetaBridge:()=>I,generateArticleMetadata:()=>F,useArticle:()=>U,useArticles:()=>E,useCategories:()=>B,useDsaContent:()=>b,useRelatedArticles:()=>z});module.exports=X(ee);var C=class{constructor(t){this.apiUrl=t.apiUrl.replace(/\/+$/,""),this.apiKey=t.apiKey,this.cacheStrategy=t.cacheStrategy==="revalidate"?"default":t.cacheStrategy==="force-cache"?"force-cache":"no-cache",this.revalidateSeconds=t.revalidateSeconds}async request(t,r){let i=new URL(`${this.apiUrl}${t}`);r&&Object.entries(r).forEach(([n,p])=>{p!=null&&p!==""&&i.searchParams.set(n,String(p))}),i.searchParams.set("site_key",this.apiKey);let a={method:"GET",headers:{"X-API-Key":this.apiKey},cache:this.cacheStrategy};this.revalidateSeconds&&this.cacheStrategy!=="no-cache"&&(a.next={revalidate:this.revalidateSeconds});let o=await fetch(i.toString(),a);if(!o.ok){let n=await o.text().catch(()=>"");throw new Error(`DSA Content API error ${o.status}: ${n||o.statusText}`)}return o.json()}async getArticles(t){return this.request("/api/public/articles",{page:t?.page,per_page:t?.per_page,pillar:t?.pillar,cluster:t?.cluster,content_type:t?.content_type,search:t?.search})}async getArticleBySlug(t){return this.request(`/api/public/articles/${encodeURIComponent(t)}`)}async getRelatedArticles(t,r=3){return this.request(`/api/public/articles/${encodeURIComponent(t)}/related`,{limit:r})}async getCategories(){return this.request("/api/public/categories")}async getSitemap(){return this.request("/api/public/sitemap")}};var _=require("react");var D=require("react/jsx-runtime"),L=(0,_.createContext)(null);function T({config:e,children:t}){let r=(0,_.useMemo)(()=>new C(e),[e.apiUrl,e.apiKey]);return(0,D.jsx)(L.Provider,{value:r,children:t})}function b(){let e=(0,_.useContext)(L);if(!e)throw new Error("useDsaContent() must be used inside <DsaContentProvider>");return e}var l=require("react");function E(e){let t=b(),[r,i]=(0,l.useState)({articles:[],loading:!0,error:null,pagination:{page:1,per_page:10,total:0,total_pages:0}}),a=(0,l.useCallback)(()=>{i(o=>({...o,loading:!0,error:null})),t.getArticles(e).then(o=>i({articles:o.items,loading:!1,error:null,pagination:{page:o.page,per_page:o.per_page,total:o.total,total_pages:o.total_pages}})).catch(o=>i(n=>({...n,loading:!1,error:o instanceof Error?o:new Error(String(o))})))},[t,e?.page,e?.per_page,e?.pillar,e?.cluster,e?.content_type,e?.search]);return(0,l.useEffect)(()=>{a()},[a]),{...r,refetch:a}}function U(e){let t=b(),[r,i]=(0,l.useState)({article:null,loading:!0,error:null}),a=(0,l.useCallback)(()=>{if(!e){i({article:null,loading:!1,error:null});return}i(o=>({...o,loading:!0,error:null})),t.getArticleBySlug(e).then(o=>i({article:o,loading:!1,error:null})).catch(o=>i({article:null,loading:!1,error:o instanceof Error?o:new Error(String(o))}))},[t,e]);return(0,l.useEffect)(()=>{a()},[a]),{...r,refetch:a}}function z(e,t=3){let r=b(),[i,a]=(0,l.useState)({articles:[],loading:!0,error:null}),o=(0,l.useCallback)(()=>{if(!e){a({articles:[],loading:!1,error:null});return}a(n=>({...n,loading:!0,error:null})),r.getRelatedArticles(e,t).then(n=>a({articles:n,loading:!1,error:null})).catch(n=>a({articles:[],loading:!1,error:n instanceof Error?n:new Error(String(n))}))},[r,e,t]);return(0,l.useEffect)(()=>{o()},[o]),{...i,refetch:o}}function B(){let e=b(),[t,r]=(0,l.useState)({categories:[],loading:!0,error:null}),i=(0,l.useCallback)(()=>{r(a=>({...a,loading:!0,error:null})),e.getCategories().then(a=>r({categories:a,loading:!1,error:null})).catch(a=>r({categories:[],loading:!1,error:a instanceof Error?a:new Error(String(a))}))},[e]);return(0,l.useEffect)(()=>{i()},[i]),{...t,refetch:i}}var v=Q(require("react")),c=require("react/jsx-runtime"),g={grid:{display:"grid",gap:"1.5rem"},card:{border:"1px solid #e5e7eb",borderRadius:"0.75rem",overflow:"hidden",background:"#fff",cursor:"pointer",transition:"box-shadow 0.2s"},cardHover:{boxShadow:"0 4px 12px rgba(0,0,0,0.08)"},image:{width:"100%",height:"200px",objectFit:"cover",display:"block"},body:{padding:"1.25rem"},title:{margin:"0 0 0.5rem",fontSize:"1.125rem",fontWeight:600,lineHeight:1.3,color:"#111827"},excerpt:{margin:"0 0 0.75rem",fontSize:"0.875rem",color:"#6b7280",lineHeight:1.5},meta:{display:"flex",gap:"0.75rem",fontSize:"0.75rem",color:"#9ca3af",flexWrap:"wrap"},badge:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"#f3f4f6",fontSize:"0.75rem",color:"#4b5563"},listCard:{display:"flex",border:"1px solid #e5e7eb",borderRadius:"0.75rem",overflow:"hidden",background:"#fff",cursor:"pointer",transition:"box-shadow 0.2s"},listImage:{width:"240px",minHeight:"160px",objectFit:"cover",flexShrink:0},listBody:{padding:"1.25rem",flex:1}};function V({article:e,layout:t,showExcerpt:r,showImage:i,showMeta:a,onClick:o}){let n=t==="grid",[p,f]=v.default.useState(!1);return(0,c.jsxs)("article",{style:{...n?g.card:g.listCard,...p?g.cardHover:{}},onMouseEnter:()=>f(!0),onMouseLeave:()=>f(!1),onClick:o,role:"link",tabIndex:0,onKeyDown:A=>A.key==="Enter"&&o?.(),children:[i&&e.featured_image_url&&(0,c.jsx)("img",{src:e.featured_image_url,alt:e.featured_image_alt||e.title,style:n?g.image:g.listImage,loading:"lazy"}),(0,c.jsxs)("div",{style:n?g.body:g.listBody,children:[(0,c.jsx)("h3",{style:g.title,children:e.title}),r&&e.excerpt&&(0,c.jsx)("p",{style:g.excerpt,children:e.excerpt}),a&&(0,c.jsxs)("div",{style:g.meta,children:[e.pillar_name&&(0,c.jsx)("span",{style:g.badge,children:e.pillar_name}),e.content_type&&(0,c.jsx)("span",{style:g.badge,children:e.content_type.replace(/_/g," ")}),e.reading_time_minutes&&(0,c.jsxs)("span",{children:[e.reading_time_minutes," min read"]}),e.published_at&&(0,c.jsx)("span",{children:new Date(e.published_at).toLocaleDateString()})]})]})]})}function w({articles:e,layout:t="grid",columns:r=3,showExcerpt:i=!0,showImage:a=!0,showMeta:o=!0,onArticleClick:n,className:p,renderArticle:f}){let A=t==="grid"?`repeat(${r}, 1fr)`:"1fr";return(0,c.jsx)("div",{className:p,style:{...g.grid,gridTemplateColumns:A},children:e.map(S=>f?(0,c.jsx)(v.default.Fragment,{children:f(S)},S.id):(0,c.jsx)(V,{article:S,layout:t,showExcerpt:i,showImage:a,showMeta:o,onClick:()=>n?.(S.slug)},S.id))})}var H=require("react"),d=require("react/jsx-runtime"),y={wrapper:{marginTop:"1rem"},title:{fontSize:"1.5rem",fontWeight:700,color:"#111827",margin:"0 0 1rem"},item:{borderBottom:"1px solid #e5e7eb",padding:"0.75rem 0"},question:{display:"flex",justifyContent:"space-between",alignItems:"center",cursor:"pointer",background:"none",border:"none",width:"100%",textAlign:"left",padding:"0.5rem 0",fontSize:"1rem",fontWeight:600,color:"#1f2937",fontFamily:"inherit"},questionStatic:{fontSize:"1rem",fontWeight:600,color:"#1f2937",margin:"0 0 0.5rem"},chevron:{flexShrink:0,marginLeft:"1rem",transition:"transform 0.2s",fontSize:"1.25rem",color:"#9ca3af"},answer:{fontSize:"0.9375rem",color:"#4b5563",lineHeight:1.6,paddingTop:"0.5rem"}};function Y({item:e,collapsible:t,defaultOpen:r}){let[i,a]=(0,H.useState)(r);return t?(0,d.jsxs)("div",{style:y.item,children:[(0,d.jsxs)("button",{style:y.question,onClick:()=>a(!i),"aria-expanded":i,children:[(0,d.jsx)("span",{children:e.question}),(0,d.jsx)("span",{style:{...y.chevron,transform:i?"rotate(180deg)":"rotate(0deg)"},children:"\u25BC"})]}),i&&(0,d.jsx)("div",{style:y.answer,children:e.answer})]}):(0,d.jsxs)("div",{style:y.item,children:[(0,d.jsx)("p",{style:y.questionStatic,children:e.question}),(0,d.jsx)("div",{style:y.answer,children:e.answer})]})}function x({items:e,collapsible:t=!0,defaultOpen:r=!1,className:i,title:a="Frequently Asked Questions"}){if(!e||e.length===0)return null;let o={"@context":"https://schema.org","@type":"FAQPage",mainEntity:e.map(n=>({"@type":"Question",name:n.question,acceptedAnswer:{"@type":"Answer",text:n.answer}}))};return(0,d.jsxs)("section",{className:i,style:y.wrapper,children:[(0,d.jsx)("h2",{style:y.title,children:a}),e.map((n,p)=>(0,d.jsx)(Y,{item:n,collapsible:t,defaultOpen:r},p)),(0,d.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(o)}})]})}var u=require("react/jsx-runtime"),h={wrapper:{marginTop:"1rem"},title:{fontSize:"1.25rem",fontWeight:700,color:"#111827",margin:"0 0 1rem"},grid:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(250px, 1fr))",gap:"1rem"},card:{border:"1px solid #e5e7eb",borderRadius:"0.5rem",overflow:"hidden",cursor:"pointer",transition:"box-shadow 0.2s",background:"#fff"},image:{width:"100%",height:"140px",objectFit:"cover",display:"block"},body:{padding:"1rem"},cardTitle:{fontSize:"0.9375rem",fontWeight:600,color:"#111827",margin:0,lineHeight:1.3},excerpt:{fontSize:"0.8125rem",color:"#6b7280",marginTop:"0.5rem",lineHeight:1.4}};function P({articles:e,title:t="Related Articles",limit:r=3,onArticleClick:i,className:a}){let o=e.slice(0,r);return o.length===0?null:(0,u.jsxs)("section",{className:a,style:h.wrapper,children:[(0,u.jsx)("h3",{style:h.title,children:t}),(0,u.jsx)("div",{style:h.grid,children:o.map(n=>(0,u.jsxs)("div",{style:h.card,onClick:()=>i?.(n.slug),role:"link",tabIndex:0,onKeyDown:p=>p.key==="Enter"&&i?.(n.slug),children:[n.featured_image_url&&(0,u.jsx)("img",{src:n.featured_image_url,alt:n.featured_image_alt||n.title,style:h.image,loading:"lazy"}),(0,u.jsxs)("div",{style:h.body,children:[(0,u.jsx)("h4",{style:h.cardTitle,children:n.title}),n.excerpt&&(0,u.jsx)("p",{style:h.excerpt,children:n.excerpt})]})]},n.id))})]})}var s=require("react/jsx-runtime"),m={wrapper:{maxWidth:"48rem",margin:"0 auto",fontFamily:"system-ui, -apple-system, sans-serif"},meta:{display:"flex",gap:"1rem",flexWrap:"wrap",fontSize:"0.875rem",color:"#6b7280",marginBottom:"1.5rem"},badge:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"#eff6ff",color:"#2563eb",fontSize:"0.75rem"},h1:{fontSize:"2.25rem",fontWeight:700,lineHeight:1.2,color:"#111827",margin:"0 0 1rem"},image:{width:"100%",borderRadius:"0.75rem",marginBottom:"2rem"},toc:{background:"#f9fafb",border:"1px solid #e5e7eb",borderRadius:"0.75rem",padding:"1.25rem",marginBottom:"2rem"},tocTitle:{fontSize:"0.875rem",fontWeight:600,color:"#374151",margin:"0 0 0.75rem",textTransform:"uppercase",letterSpacing:"0.05em"},tocList:{listStyle:"none",padding:0,margin:0},tocItem:{padding:"0.25rem 0"},tocLink:{color:"#4b5563",textDecoration:"none",fontSize:"0.875rem"},content:{lineHeight:1.75,color:"#374151",fontSize:"1.0625rem"},divider:{border:"none",borderTop:"1px solid #e5e7eb",margin:"2.5rem 0"}};function Z({headings:e}){return!e||e.length===0?null:(0,s.jsxs)("nav",{style:m.toc,children:[(0,s.jsx)("p",{style:m.tocTitle,children:"Table of Contents"}),(0,s.jsx)("ul",{style:m.tocList,children:e.map((t,r)=>(0,s.jsx)("li",{style:{...m.tocItem,paddingLeft:`${(t.level-2)*1}rem`},children:(0,s.jsx)("a",{href:`#${t.id}`,style:m.tocLink,children:t.text})},r))})]})}function k({article:e,showFaq:t=!0,showTableOfContents:r=!0,showMeta:i=!0,showRelated:a=!1,relatedArticles:o,onRelatedClick:n,className:p,components:f}){let A=f?.H1||(({children:N})=>(0,s.jsx)("h1",{style:m.h1,children:N})),S=f?.Toc||Z,$=f?.Faq||x;return(0,s.jsxs)("article",{className:p,style:m.wrapper,children:[i&&(0,s.jsxs)("div",{style:m.meta,children:[e.pillar_name&&(0,s.jsx)("span",{style:m.badge,children:e.pillar_name}),e.content_type&&(0,s.jsx)("span",{style:{...m.badge,background:"#f0fdf4",color:"#16a34a"},children:e.content_type.replace(/_/g," ")}),e.reading_time_minutes&&(0,s.jsxs)("span",{children:[e.reading_time_minutes," min read"]}),e.published_at&&(0,s.jsx)("span",{children:new Date(e.published_at).toLocaleDateString()})]}),(0,s.jsx)(A,{children:e.h1||e.title}),e.featured_image_url&&(0,s.jsx)("img",{src:e.featured_image_url,alt:e.featured_image_alt||e.title,style:m.image}),r&&e.headings?.length>0&&(0,s.jsx)(S,{headings:e.headings}),(0,s.jsx)("div",{style:m.content,dangerouslySetInnerHTML:{__html:e.content_html}}),t&&e.faq?.length>0&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("hr",{style:m.divider}),(0,s.jsx)($,{items:e.faq})]}),e.schema_json&&(0,s.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(e.schema_json)}}),a&&o&&o.length>0&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("hr",{style:m.divider}),(0,s.jsx)(P,{articles:o,onArticleClick:n})]})]})}var M=require("react/jsx-runtime");function F(e,t){let r=t?`${t.replace(/\/+$/,"")}/blog/${e.slug}`:void 0;return{title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",openGraph:{title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",type:"article",publishedTime:e.published_at||void 0,modifiedTime:e.updated_at||void 0,...r?{url:r}:{},...e.featured_image_url?{images:[{url:e.featured_image_url,alt:e.featured_image_alt||e.title}]}:{}},twitter:{card:"summary_large_image",title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",...e.featured_image_url?{images:[e.featured_image_url]}:{}},...e.canonical_url?{alternates:{canonical:e.canonical_url}}:r?{alternates:{canonical:r}}:{}}}function I({article:e,siteUrl:t}){let r=e.schema_json||{"@context":"https://schema.org","@type":"Article",headline:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",datePublished:e.published_at||void 0,dateModified:e.updated_at||e.published_at||void 0,...e.featured_image_url?{image:e.featured_image_url}:{},...t?{url:`${t.replace(/\/+$/,"")}/blog/${e.slug}`}:{},...e.target_keyword?{keywords:[e.target_keyword,...e.secondary_keywords||[]].join(", ")}:{}};return(0,M.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(r)}})}0&&(module.exports={ArticleFeed,ArticlePage,ContentClient,DsaContentProvider,FaqBlock,RelatedArticles,SeoMetaBridge,generateArticleMetadata,useArticle,useArticles,useCategories,useDsaContent,useRelatedArticles});
|
|
2
|
+
"use strict";var $=Object.create;var A=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var W=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var r in t)A(e,r,{get:t[r],enumerable:!0})},F=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of j(t))!O.call(e,n)&&n!==r&&A(e,n,{get:()=>t[n],enumerable:!(o=N(t,n))||o.enumerable});return e};var V=(e,t,r)=>(r=e!=null?$(W(e)):{},F(t||!e||!e.__esModule?A(r,"default",{value:e,enumerable:!0}):r,e)),G=e=>F(A({},"__esModule",{value:!0}),e);var re={};K(re,{ArticleFeed:()=>w,ArticlePage:()=>k,ContentClient:()=>y,DsaContentProvider:()=>I,FaqBlock:()=>v,RelatedArticles:()=>_,SeoMetaBridge:()=>P,generateArticleMetadata:()=>R,useArticle:()=>D,useArticles:()=>L,useCategories:()=>E,useDsaContent:()=>h,useRelatedArticles:()=>z});module.exports=G(re);var y=class{constructor(t){this.apiUrl=t.apiUrl.replace(/\/+$/,""),this.apiKey=t.apiKey,this.cacheStrategy=t.cacheStrategy==="revalidate"?"default":t.cacheStrategy==="force-cache"?"force-cache":"no-cache",this.revalidateSeconds=t.revalidateSeconds}async request(t,r){let o=new URL(`${this.apiUrl}${t}`);r&&Object.entries(r).forEach(([i,p])=>{p!=null&&p!==""&&o.searchParams.set(i,String(p))}),o.searchParams.set("site_key",this.apiKey);let n={method:"GET",headers:{"X-API-Key":this.apiKey},cache:this.cacheStrategy};this.revalidateSeconds&&this.cacheStrategy!=="no-cache"&&(n.next={revalidate:this.revalidateSeconds});let a=await fetch(o.toString(),n);if(!a.ok){let i=await a.text().catch(()=>"");throw new Error(`DSA Content API error ${a.status}: ${i||a.statusText}`)}return a.json()}normalizeArticle(t){return{...t,headings:t.headings??[],faq:t.faq??[],internal_links:t.internal_links??[],secondary_keywords:t.secondary_keywords??[],schema_json:t.schema_json??null,content_json:t.content_json??null}}async getArticles(t){let r=await this.request("/api/public/articles",{page:t?.page,per_page:t?.per_page,pillar:t?.pillar,cluster:t?.cluster,content_type:t?.content_type,search:t?.search});return{items:r.items??r.data??[],total:r.total??0,page:r.page??1,per_page:r.per_page??20,total_pages:r.total_pages??r.pages??1}}async getArticleBySlug(t){let r=await this.request(`/api/public/articles/${encodeURIComponent(t)}`);return this.normalizeArticle(r)}async getRelatedArticles(t,r=3){let o=await this.request(`/api/public/articles/${encodeURIComponent(t)}/related`,{limit:r});return o.items??(Array.isArray(o)?o:[])}async getCategories(){let t=await this.request("/api/public/categories");return t.items??(Array.isArray(t)?t:[])}async getSitemap(){let t=await this.request("/api/public/sitemap");return t.items??(Array.isArray(t)?t:[])}};var b=require("react");var T=require("react/jsx-runtime"),q=(0,b.createContext)(null);function I({config:e,children:t}){let r=(0,b.useMemo)(()=>new y(e),[e.apiUrl,e.apiKey]);return(0,T.jsx)(q.Provider,{value:r,children:t})}function h(){let e=(0,b.useContext)(q);if(!e)throw new Error("useDsaContent() must be used inside <DsaContentProvider>");return e}var l=require("react");function L(e){let t=h(),[r,o]=(0,l.useState)({articles:[],loading:!0,error:null,pagination:{page:1,per_page:10,total:0,total_pages:0}}),n=(0,l.useCallback)(()=>{o(a=>({...a,loading:!0,error:null})),t.getArticles(e).then(a=>o({articles:a.items,loading:!1,error:null,pagination:{page:a.page,per_page:a.per_page,total:a.total,total_pages:a.total_pages}})).catch(a=>o(i=>({...i,loading:!1,error:a instanceof Error?a:new Error(String(a))})))},[t,e?.page,e?.per_page,e?.pillar,e?.cluster,e?.content_type,e?.search]);return(0,l.useEffect)(()=>{n()},[n]),{...r,refetch:n}}function D(e){let t=h(),[r,o]=(0,l.useState)({article:null,loading:!0,error:null}),n=(0,l.useCallback)(()=>{if(!e){o({article:null,loading:!1,error:null});return}o(a=>({...a,loading:!0,error:null})),t.getArticleBySlug(e).then(a=>o({article:a,loading:!1,error:null})).catch(a=>o({article:null,loading:!1,error:a instanceof Error?a:new Error(String(a))}))},[t,e]);return(0,l.useEffect)(()=>{n()},[n]),{...r,refetch:n}}function z(e,t=3){let r=h(),[o,n]=(0,l.useState)({articles:[],loading:!0,error:null}),a=(0,l.useCallback)(()=>{if(!e){n({articles:[],loading:!1,error:null});return}n(i=>({...i,loading:!0,error:null})),r.getRelatedArticles(e,t).then(i=>n({articles:i,loading:!1,error:null})).catch(i=>n({articles:[],loading:!1,error:i instanceof Error?i:new Error(String(i))}))},[r,e,t]);return(0,l.useEffect)(()=>{a()},[a]),{...o,refetch:a}}function E(){let e=h(),[t,r]=(0,l.useState)({categories:[],loading:!0,error:null}),o=(0,l.useCallback)(()=>{r(n=>({...n,loading:!0,error:null})),e.getCategories().then(n=>r({categories:n,loading:!1,error:null})).catch(n=>r({categories:[],loading:!1,error:n instanceof Error?n:new Error(String(n))}))},[e]);return(0,l.useEffect)(()=>{o()},[o]),{...t,refetch:o}}var C=V(require("react")),c=require("react/jsx-runtime"),J={light:{"--dsa-text":"#111827","--dsa-text-muted":"#6b7280","--dsa-text-faint":"#9ca3af","--dsa-card-bg":"#fff","--dsa-card-border":"#e5e7eb","--dsa-badge-bg":"#f3f4f6","--dsa-badge-text":"#4b5563","--dsa-hover-shadow":"0 4px 12px rgba(0,0,0,0.08)"},dark:{"--dsa-text":"#f3f4f6","--dsa-text-muted":"#9ca3af","--dsa-text-faint":"#6b7280","--dsa-card-bg":"#1f2937","--dsa-card-border":"#374151","--dsa-badge-bg":"#374151","--dsa-badge-text":"#d1d5db","--dsa-hover-shadow":"0 4px 12px rgba(0,0,0,0.3)"}};function Q({article:e,layout:t,showExcerpt:r,showImage:o,showMeta:n,onClick:a}){let i=t==="grid",[p,d]=C.default.useState(!1),m={...i?{border:"1px solid var(--dsa-card-border)",borderRadius:"0.75rem",overflow:"hidden",background:"var(--dsa-card-bg)",cursor:"pointer",transition:"box-shadow 0.2s"}:{display:"flex",border:"1px solid var(--dsa-card-border)",borderRadius:"0.75rem",overflow:"hidden",background:"var(--dsa-card-bg)",cursor:"pointer",transition:"box-shadow 0.2s"},...p?{boxShadow:"var(--dsa-hover-shadow)"}:{}};return(0,c.jsxs)("article",{style:m,onMouseEnter:()=>d(!0),onMouseLeave:()=>d(!1),onClick:a,role:"link",tabIndex:0,onKeyDown:x=>x.key==="Enter"&&a?.(),children:[o&&e.featured_image_url&&(0,c.jsx)("img",{src:e.featured_image_url,alt:e.featured_image_alt||e.title,style:i?{width:"100%",height:"200px",objectFit:"cover",display:"block"}:{width:"240px",minHeight:"160px",objectFit:"cover",flexShrink:0},loading:"lazy"}),(0,c.jsxs)("div",{style:i?{padding:"1.25rem"}:{padding:"1.25rem",flex:1},children:[(0,c.jsx)("h3",{style:{margin:"0 0 0.5rem",fontSize:"1.125rem",fontWeight:600,lineHeight:1.3,color:"var(--dsa-text)"},children:e.title}),r&&e.excerpt&&(0,c.jsx)("p",{style:{margin:"0 0 0.75rem",fontSize:"0.875rem",color:"var(--dsa-text-muted)",lineHeight:1.5},children:e.excerpt}),n&&(0,c.jsxs)("div",{style:{display:"flex",gap:"0.75rem",fontSize:"0.75rem",color:"var(--dsa-text-faint)",flexWrap:"wrap"},children:[e.pillar_name&&(0,c.jsx)("span",{style:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"var(--dsa-badge-bg)",fontSize:"0.75rem",color:"var(--dsa-badge-text)"},children:e.pillar_name}),e.content_type&&(0,c.jsx)("span",{style:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"var(--dsa-badge-bg)",fontSize:"0.75rem",color:"var(--dsa-badge-text)"},children:e.content_type.replace(/_/g," ")}),e.reading_time_minutes&&(0,c.jsxs)("span",{children:[e.reading_time_minutes," min read"]}),e.published_at&&(0,c.jsx)("span",{children:new Date(e.published_at).toLocaleDateString()})]})]})]})}function w({articles:e,layout:t="grid",columns:r=3,showExcerpt:o=!0,showImage:n=!0,showMeta:a=!0,onArticleClick:i,className:p,theme:d="light",renderArticle:m}){let x=t==="grid"?`repeat(${r}, 1fr)`:"1fr",S=d!=="inherit"?J[d]:{};return(0,c.jsx)("div",{className:p,style:{display:"grid",gap:"1.5rem",gridTemplateColumns:x,...S},children:(e??[]).map(f=>m?(0,c.jsx)(C.default.Fragment,{children:m(f)},f.id):(0,c.jsx)(Q,{article:f,layout:t,showExcerpt:o,showImage:n,showMeta:a,onClick:()=>i?.(f.slug)},f.id))})}var U=require("react"),g=require("react/jsx-runtime"),X={light:{"--dsa-text":"#111827","--dsa-text-muted":"#4b5563","--dsa-text-faint":"#9ca3af","--dsa-divider":"#e5e7eb"},dark:{"--dsa-text":"#f3f4f6","--dsa-text-muted":"#d1d5db","--dsa-text-faint":"#6b7280","--dsa-divider":"#374151"}};function Y({item:e,collapsible:t,defaultOpen:r}){let[o,n]=(0,U.useState)(r);return t?(0,g.jsxs)("div",{style:{borderBottom:"1px solid var(--dsa-divider)",padding:"0.75rem 0"},children:[(0,g.jsxs)("button",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",cursor:"pointer",background:"none",border:"none",width:"100%",textAlign:"left",padding:"0.5rem 0",fontSize:"1rem",fontWeight:600,color:"var(--dsa-text)",fontFamily:"inherit"},onClick:()=>n(!o),"aria-expanded":o,children:[(0,g.jsx)("span",{children:e.question}),(0,g.jsx)("span",{style:{flexShrink:0,marginLeft:"1rem",transition:"transform 0.2s",fontSize:"1.25rem",color:"var(--dsa-text-faint)",transform:o?"rotate(180deg)":"rotate(0deg)"},children:"\u25BC"})]}),o&&(0,g.jsx)("div",{style:{fontSize:"0.9375rem",color:"var(--dsa-text-muted)",lineHeight:1.6,paddingTop:"0.5rem"},children:e.answer})]}):(0,g.jsxs)("div",{style:{borderBottom:"1px solid var(--dsa-divider)",padding:"0.75rem 0"},children:[(0,g.jsx)("p",{style:{fontSize:"1rem",fontWeight:600,color:"var(--dsa-text)",margin:"0 0 0.5rem"},children:e.question}),(0,g.jsx)("div",{style:{fontSize:"0.9375rem",color:"var(--dsa-text-muted)",lineHeight:1.6},children:e.answer})]})}function v({items:e,collapsible:t=!0,defaultOpen:r=!1,className:o,title:n="Frequently Asked Questions",theme:a="light"}){if(!e||e.length===0)return null;let i=a!=="inherit"?X[a]:{},p={"@context":"https://schema.org","@type":"FAQPage",mainEntity:e.map(d=>({"@type":"Question",name:d.question,acceptedAnswer:{"@type":"Answer",text:d.answer}}))};return(0,g.jsxs)("section",{className:o,style:{marginTop:"1rem",...i},children:[(0,g.jsx)("h2",{style:{fontSize:"1.5rem",fontWeight:700,color:"var(--dsa-text)",margin:"0 0 1rem"},children:n}),e.map((d,m)=>(0,g.jsx)(Y,{item:d,collapsible:t,defaultOpen:r},m)),(0,g.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(p)}})]})}var u=require("react/jsx-runtime"),Z={light:{"--dsa-text":"#111827","--dsa-text-muted":"#6b7280","--dsa-card-bg":"#fff","--dsa-card-border":"#e5e7eb"},dark:{"--dsa-text":"#f3f4f6","--dsa-text-muted":"#9ca3af","--dsa-card-bg":"#1f2937","--dsa-card-border":"#374151"}};function _({articles:e,title:t="Related Articles",limit:r=3,onArticleClick:o,className:n,theme:a="light"}){let i=(e??[]).slice(0,r);if(i.length===0)return null;let p=a!=="inherit"?Z[a]:{};return(0,u.jsxs)("section",{className:n,style:{marginTop:"1rem",...p},children:[(0,u.jsx)("h3",{style:{fontSize:"1.25rem",fontWeight:700,color:"var(--dsa-text)",margin:"0 0 1rem"},children:t}),(0,u.jsx)("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(250px, 1fr))",gap:"1rem"},children:i.map(d=>(0,u.jsxs)("div",{style:{border:"1px solid var(--dsa-card-border)",borderRadius:"0.5rem",overflow:"hidden",cursor:"pointer",transition:"box-shadow 0.2s",background:"var(--dsa-card-bg)"},onClick:()=>o?.(d.slug),role:"link",tabIndex:0,onKeyDown:m=>m.key==="Enter"&&o?.(d.slug),children:[d.featured_image_url&&(0,u.jsx)("img",{src:d.featured_image_url,alt:d.featured_image_alt||d.title,style:{width:"100%",height:"140px",objectFit:"cover",display:"block"},loading:"lazy"}),(0,u.jsxs)("div",{style:{padding:"1rem"},children:[(0,u.jsx)("h4",{style:{fontSize:"0.9375rem",fontWeight:600,color:"var(--dsa-text)",margin:0,lineHeight:1.3},children:d.title}),d.excerpt&&(0,u.jsx)("p",{style:{fontSize:"0.8125rem",color:"var(--dsa-text-muted)",marginTop:"0.5rem",lineHeight:1.4},children:d.excerpt})]})]},d.id))})]})}var s=require("react/jsx-runtime"),ee={light:{"--dsa-text":"#111827","--dsa-text-muted":"#6b7280","--dsa-text-faint":"#9ca3af","--dsa-card-bg":"#fff","--dsa-card-border":"#e5e7eb","--dsa-toc-bg":"#f9fafb","--dsa-badge-bg":"#eff6ff","--dsa-badge-text":"#2563eb","--dsa-badge-alt-bg":"#f0fdf4","--dsa-badge-alt-text":"#16a34a","--dsa-content-text":"#374151","--dsa-divider":"#e5e7eb"},dark:{"--dsa-text":"#f3f4f6","--dsa-text-muted":"#9ca3af","--dsa-text-faint":"#6b7280","--dsa-card-bg":"#1f2937","--dsa-card-border":"#374151","--dsa-toc-bg":"#111827","--dsa-badge-bg":"#1e3a5f","--dsa-badge-text":"#93c5fd","--dsa-badge-alt-bg":"#14532d","--dsa-badge-alt-text":"#86efac","--dsa-content-text":"#d1d5db","--dsa-divider":"#374151"}};function te({headings:e}){return!e||e.length===0?null:(0,s.jsxs)("nav",{style:{background:"var(--dsa-toc-bg, #f9fafb)",border:"1px solid var(--dsa-card-border, #e5e7eb)",borderRadius:"0.75rem",padding:"1.25rem",marginBottom:"2rem"},children:[(0,s.jsx)("p",{style:{fontSize:"0.875rem",fontWeight:600,color:"var(--dsa-text-muted, #374151)",margin:"0 0 0.75rem",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Table of Contents"}),(0,s.jsx)("ul",{style:{listStyle:"none",padding:0,margin:0},children:e.map((t,r)=>(0,s.jsx)("li",{style:{padding:"0.25rem 0",paddingLeft:`${(t.level-2)*1}rem`},children:(0,s.jsx)("a",{href:`#${t.id}`,style:{color:"var(--dsa-text-muted, #4b5563)",textDecoration:"none",fontSize:"0.875rem"},children:t.text})},r))})]})}function k({article:e,showFaq:t=!0,showTableOfContents:r=!0,showMeta:o=!0,showRelated:n=!1,relatedArticles:a,onRelatedClick:i,className:p,theme:d="light",components:m}){let x=m?.H1||(({children:M})=>(0,s.jsx)("h1",{style:{fontSize:"2.25rem",fontWeight:700,lineHeight:1.2,color:"var(--dsa-text)",margin:"0 0 1rem"},children:M})),S=m?.Toc||te,f=m?.Faq||v,H=d!=="inherit"?ee[d]:{};return(0,s.jsxs)("article",{className:p,style:{maxWidth:"48rem",margin:"0 auto",fontFamily:"system-ui, -apple-system, sans-serif",...H},children:[o&&(0,s.jsxs)("div",{style:{display:"flex",gap:"1rem",flexWrap:"wrap",fontSize:"0.875rem",color:"var(--dsa-text-muted)",marginBottom:"1.5rem"},children:[e.pillar_name&&(0,s.jsx)("span",{style:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"var(--dsa-badge-bg)",color:"var(--dsa-badge-text)",fontSize:"0.75rem"},children:e.pillar_name}),e.content_type&&(0,s.jsx)("span",{style:{display:"inline-block",padding:"0.125rem 0.5rem",borderRadius:"9999px",background:"var(--dsa-badge-alt-bg, var(--dsa-badge-bg))",color:"var(--dsa-badge-alt-text, var(--dsa-badge-text))",fontSize:"0.75rem"},children:e.content_type.replace(/_/g," ")}),e.reading_time_minutes&&(0,s.jsxs)("span",{children:[e.reading_time_minutes," min read"]}),e.published_at&&(0,s.jsx)("span",{children:new Date(e.published_at).toLocaleDateString()})]}),(0,s.jsx)(x,{children:e.h1||e.title}),e.featured_image_url&&(0,s.jsx)("img",{src:e.featured_image_url,alt:e.featured_image_alt||e.title,style:{width:"100%",borderRadius:"0.75rem",marginBottom:"2rem"}}),r&&(e.headings??[]).length>0&&(0,s.jsx)(S,{headings:e.headings}),(0,s.jsx)("div",{style:{lineHeight:1.75,color:"var(--dsa-content-text)",fontSize:"1.0625rem"},dangerouslySetInnerHTML:{__html:e.content_html}}),t&&(e.faq??[]).length>0&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("hr",{style:{border:"none",borderTop:"1px solid var(--dsa-divider)",margin:"2.5rem 0"}}),(0,s.jsx)(f,{items:e.faq})]}),e.schema_json&&(0,s.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(e.schema_json)}}),n&&a&&a.length>0&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("hr",{style:{border:"none",borderTop:"1px solid var(--dsa-divider)",margin:"2.5rem 0"}}),(0,s.jsx)(_,{articles:a,onArticleClick:i,theme:d})]})]})}var B=require("react/jsx-runtime");function R(e,t){let r=t?`${t.replace(/\/+$/,"")}/blog/${e.slug}`:void 0;return{title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",openGraph:{title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",type:"article",publishedTime:e.published_at||void 0,modifiedTime:e.updated_at||void 0,...r?{url:r}:{},...e.featured_image_url?{images:[{url:e.featured_image_url,alt:e.featured_image_alt||e.title}]}:{}},twitter:{card:"summary_large_image",title:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",...e.featured_image_url?{images:[e.featured_image_url]}:{}},...e.canonical_url?{alternates:{canonical:e.canonical_url}}:r?{alternates:{canonical:r}}:{}}}function P({article:e,siteUrl:t}){let r=e.schema_json||{"@context":"https://schema.org","@type":"Article",headline:e.meta_title||e.title,description:e.meta_description||e.excerpt||"",datePublished:e.published_at||void 0,dateModified:e.updated_at||e.published_at||void 0,...e.featured_image_url?{image:e.featured_image_url}:{},...t?{url:`${t.replace(/\/+$/,"")}/blog/${e.slug}`}:{},...e.target_keyword?{keywords:[e.target_keyword,...e.secondary_keywords||[]].join(", ")}:{}};return(0,B.jsx)("script",{type:"application/ld+json",dangerouslySetInnerHTML:{__html:JSON.stringify(r)}})}0&&(module.exports={ArticleFeed,ArticlePage,ContentClient,DsaContentProvider,FaqBlock,RelatedArticles,SeoMetaBridge,generateArticleMetadata,useArticle,useArticles,useCategories,useDsaContent,useRelatedArticles});
|
|
3
3
|
//# sourceMappingURL=index.js.map
|