@growth-labs/seo 0.1.3

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 (158) hide show
  1. package/README.md +80 -0
  2. package/dist/index.d.ts +8 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +162 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/middleware/seo.d.ts +5 -0
  7. package/dist/middleware/seo.d.ts.map +1 -0
  8. package/dist/middleware/seo.js +70 -0
  9. package/dist/middleware/seo.js.map +1 -0
  10. package/dist/options.d.ts +489 -0
  11. package/dist/options.d.ts.map +1 -0
  12. package/dist/options.js +118 -0
  13. package/dist/options.js.map +1 -0
  14. package/dist/routes/llms.d.ts +4 -0
  15. package/dist/routes/llms.d.ts.map +1 -0
  16. package/dist/routes/llms.js +11 -0
  17. package/dist/routes/llms.js.map +1 -0
  18. package/dist/routes/podcast-narration.d.ts +4 -0
  19. package/dist/routes/podcast-narration.d.ts.map +1 -0
  20. package/dist/routes/podcast-narration.js +36 -0
  21. package/dist/routes/podcast-narration.js.map +1 -0
  22. package/dist/routes/podcast.d.ts +4 -0
  23. package/dist/routes/podcast.d.ts.map +1 -0
  24. package/dist/routes/podcast.js +20 -0
  25. package/dist/routes/podcast.js.map +1 -0
  26. package/dist/routes/robots.d.ts +4 -0
  27. package/dist/routes/robots.d.ts.map +1 -0
  28. package/dist/routes/robots.js +11 -0
  29. package/dist/routes/robots.js.map +1 -0
  30. package/dist/routes/rss.d.ts +4 -0
  31. package/dist/routes/rss.d.ts.map +1 -0
  32. package/dist/routes/rss.js +19 -0
  33. package/dist/routes/rss.js.map +1 -0
  34. package/dist/routes/sitemap-articles.d.ts +4 -0
  35. package/dist/routes/sitemap-articles.d.ts.map +1 -0
  36. package/dist/routes/sitemap-articles.js +19 -0
  37. package/dist/routes/sitemap-articles.js.map +1 -0
  38. package/dist/routes/sitemap-index.d.ts +4 -0
  39. package/dist/routes/sitemap-index.d.ts.map +1 -0
  40. package/dist/routes/sitemap-index.js +77 -0
  41. package/dist/routes/sitemap-index.js.map +1 -0
  42. package/dist/routes/sitemap-pages.d.ts +4 -0
  43. package/dist/routes/sitemap-pages.d.ts.map +1 -0
  44. package/dist/routes/sitemap-pages.js +18 -0
  45. package/dist/routes/sitemap-pages.js.map +1 -0
  46. package/dist/routes/sitemap-products.d.ts +4 -0
  47. package/dist/routes/sitemap-products.d.ts.map +1 -0
  48. package/dist/routes/sitemap-products.js +18 -0
  49. package/dist/routes/sitemap-products.js.map +1 -0
  50. package/dist/routes/sitemap-videos.d.ts +4 -0
  51. package/dist/routes/sitemap-videos.d.ts.map +1 -0
  52. package/dist/routes/sitemap-videos.js +18 -0
  53. package/dist/routes/sitemap-videos.js.map +1 -0
  54. package/dist/state.d.ts +7 -0
  55. package/dist/state.d.ts.map +1 -0
  56. package/dist/state.js +18 -0
  57. package/dist/state.js.map +1 -0
  58. package/dist/types.d.ts +103 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils/aeo.d.ts +16 -0
  63. package/dist/utils/aeo.d.ts.map +1 -0
  64. package/dist/utils/aeo.js +38 -0
  65. package/dist/utils/aeo.js.map +1 -0
  66. package/dist/utils/discover.d.ts +18 -0
  67. package/dist/utils/discover.d.ts.map +1 -0
  68. package/dist/utils/discover.js +41 -0
  69. package/dist/utils/discover.js.map +1 -0
  70. package/dist/utils/hreflang.d.ts +3 -0
  71. package/dist/utils/hreflang.d.ts.map +1 -0
  72. package/dist/utils/hreflang.js +20 -0
  73. package/dist/utils/hreflang.js.map +1 -0
  74. package/dist/utils/index.d.ts +12 -0
  75. package/dist/utils/index.d.ts.map +1 -0
  76. package/dist/utils/index.js +12 -0
  77. package/dist/utils/index.js.map +1 -0
  78. package/dist/utils/json-ld/article.d.ts +4 -0
  79. package/dist/utils/json-ld/article.d.ts.map +1 -0
  80. package/dist/utils/json-ld/article.js +66 -0
  81. package/dist/utils/json-ld/article.js.map +1 -0
  82. package/dist/utils/json-ld/audio.d.ts +7 -0
  83. package/dist/utils/json-ld/audio.d.ts.map +1 -0
  84. package/dist/utils/json-ld/audio.js +25 -0
  85. package/dist/utils/json-ld/audio.js.map +1 -0
  86. package/dist/utils/json-ld/breadcrumb.d.ts +7 -0
  87. package/dist/utils/json-ld/breadcrumb.d.ts.map +1 -0
  88. package/dist/utils/json-ld/breadcrumb.js +20 -0
  89. package/dist/utils/json-ld/breadcrumb.js.map +1 -0
  90. package/dist/utils/json-ld/faq.d.ts +6 -0
  91. package/dist/utils/json-ld/faq.d.ts.map +1 -0
  92. package/dist/utils/json-ld/faq.js +15 -0
  93. package/dist/utils/json-ld/faq.js.map +1 -0
  94. package/dist/utils/json-ld/howto.d.ts +7 -0
  95. package/dist/utils/json-ld/howto.d.ts.map +1 -0
  96. package/dist/utils/json-ld/howto.js +19 -0
  97. package/dist/utils/json-ld/howto.js.map +1 -0
  98. package/dist/utils/json-ld/index.d.ts +13 -0
  99. package/dist/utils/json-ld/index.d.ts.map +1 -0
  100. package/dist/utils/json-ld/index.js +12 -0
  101. package/dist/utils/json-ld/index.js.map +1 -0
  102. package/dist/utils/json-ld/item-list.d.ts +5 -0
  103. package/dist/utils/json-ld/item-list.d.ts.map +1 -0
  104. package/dist/utils/json-ld/item-list.js +20 -0
  105. package/dist/utils/json-ld/item-list.js.map +1 -0
  106. package/dist/utils/json-ld/organization.d.ts +4 -0
  107. package/dist/utils/json-ld/organization.d.ts.map +1 -0
  108. package/dist/utils/json-ld/organization.js +36 -0
  109. package/dist/utils/json-ld/organization.js.map +1 -0
  110. package/dist/utils/json-ld/person.d.ts +6 -0
  111. package/dist/utils/json-ld/person.d.ts.map +1 -0
  112. package/dist/utils/json-ld/person.js +23 -0
  113. package/dist/utils/json-ld/person.js.map +1 -0
  114. package/dist/utils/json-ld/product.d.ts +5 -0
  115. package/dist/utils/json-ld/product.d.ts.map +1 -0
  116. package/dist/utils/json-ld/product.js +112 -0
  117. package/dist/utils/json-ld/product.js.map +1 -0
  118. package/dist/utils/json-ld/video.d.ts +3 -0
  119. package/dist/utils/json-ld/video.d.ts.map +1 -0
  120. package/dist/utils/json-ld/video.js +20 -0
  121. package/dist/utils/json-ld/video.js.map +1 -0
  122. package/dist/utils/json-ld/website.d.ts +4 -0
  123. package/dist/utils/json-ld/website.d.ts.map +1 -0
  124. package/dist/utils/json-ld/website.js +22 -0
  125. package/dist/utils/json-ld/website.js.map +1 -0
  126. package/dist/utils/llms.d.ts +7 -0
  127. package/dist/utils/llms.d.ts.map +1 -0
  128. package/dist/utils/llms.js +38 -0
  129. package/dist/utils/llms.js.map +1 -0
  130. package/dist/utils/meta.d.ts +7 -0
  131. package/dist/utils/meta.d.ts.map +1 -0
  132. package/dist/utils/meta.js +122 -0
  133. package/dist/utils/meta.js.map +1 -0
  134. package/dist/utils/podcast.d.ts +8 -0
  135. package/dist/utils/podcast.d.ts.map +1 -0
  136. package/dist/utils/podcast.js +94 -0
  137. package/dist/utils/podcast.js.map +1 -0
  138. package/dist/utils/robots.d.ts +3 -0
  139. package/dist/utils/robots.d.ts.map +1 -0
  140. package/dist/utils/robots.js +28 -0
  141. package/dist/utils/robots.js.map +1 -0
  142. package/dist/utils/rss.d.ts +4 -0
  143. package/dist/utils/rss.d.ts.map +1 -0
  144. package/dist/utils/rss.js +53 -0
  145. package/dist/utils/rss.js.map +1 -0
  146. package/dist/utils/sitemap.d.ts +13 -0
  147. package/dist/utils/sitemap.d.ts.map +1 -0
  148. package/dist/utils/sitemap.js +133 -0
  149. package/dist/utils/sitemap.js.map +1 -0
  150. package/dist/utils/validation.d.ts +18 -0
  151. package/dist/utils/validation.d.ts.map +1 -0
  152. package/dist/utils/validation.js +141 -0
  153. package/dist/utils/validation.js.map +1 -0
  154. package/dist/vite-plugin.d.ts +4 -0
  155. package/dist/vite-plugin.d.ts.map +1 -0
  156. package/dist/vite-plugin.js +22 -0
  157. package/dist/vite-plugin.js.map +1 -0
  158. package/package.json +59 -0
@@ -0,0 +1,112 @@
1
+ const AVAILABILITY_MAP = {
2
+ InStock: 'https://schema.org/InStock',
3
+ OutOfStock: 'https://schema.org/OutOfStock',
4
+ PreOrder: 'https://schema.org/PreOrder',
5
+ Discontinued: 'https://schema.org/Discontinued',
6
+ };
7
+ function buildOffer(price, currency, availability, url, condition, hasReturnPolicy) {
8
+ const offer = {
9
+ '@type': 'Offer',
10
+ price,
11
+ priceCurrency: currency,
12
+ availability: AVAILABILITY_MAP[availability] ?? `https://schema.org/${availability}`,
13
+ url,
14
+ };
15
+ if (condition) {
16
+ offer.itemCondition = `https://schema.org/${condition}`;
17
+ }
18
+ if (hasReturnPolicy) {
19
+ offer.hasMerchantReturnPolicy = { '@id': '#return-policy' };
20
+ }
21
+ return offer;
22
+ }
23
+ function buildVariantProduct(variant, url, productCurrency, hasReturnPolicy) {
24
+ const currency = variant.currency ?? productCurrency;
25
+ const v = {
26
+ '@type': 'Product',
27
+ name: variant.name,
28
+ offers: buildOffer(variant.price, currency, variant.availability, url, undefined, hasReturnPolicy),
29
+ };
30
+ if (variant.sku)
31
+ v.sku = variant.sku;
32
+ if (variant.image)
33
+ v.image = variant.image;
34
+ return v;
35
+ }
36
+ export function generateProductJsonLd(product, url, options) {
37
+ const hasReturnPolicy = !!(options.commerce?.enabled && options.commerce.returnPolicy);
38
+ const result = {
39
+ '@context': 'https://schema.org',
40
+ '@type': 'Product',
41
+ name: product.name,
42
+ description: product.description,
43
+ image: product.images,
44
+ offers: buildOffer(product.price, product.currency, product.availability, url, product.condition, hasReturnPolicy),
45
+ };
46
+ if (product.sku)
47
+ result.sku = product.sku;
48
+ if (product.gtin)
49
+ result.gtin = product.gtin;
50
+ if (product.mpn)
51
+ result.mpn = product.mpn;
52
+ if (product.brand) {
53
+ result.brand = {
54
+ '@type': 'Brand',
55
+ name: product.brand,
56
+ };
57
+ }
58
+ if (product.rating) {
59
+ result.aggregateRating = {
60
+ '@type': 'AggregateRating',
61
+ ratingValue: product.rating.value,
62
+ reviewCount: product.rating.count,
63
+ ...(product.rating.bestRating !== undefined ? { bestRating: product.rating.bestRating } : {}),
64
+ };
65
+ }
66
+ if (product.reviews?.length) {
67
+ result.review = product.reviews.map((review) => {
68
+ const r = {
69
+ '@type': 'Review',
70
+ author: { '@type': 'Person', name: review.author },
71
+ reviewRating: {
72
+ '@type': 'Rating',
73
+ ratingValue: review.rating,
74
+ },
75
+ };
76
+ if (review.body)
77
+ r.reviewBody = review.body;
78
+ if (review.datePublished)
79
+ r.datePublished = review.datePublished;
80
+ return r;
81
+ });
82
+ }
83
+ return result;
84
+ }
85
+ export function generateProductGroupJsonLd(product, url, options) {
86
+ const hasReturnPolicy = !!(options.commerce?.enabled && options.commerce.returnPolicy);
87
+ const variants = product.variants ?? [];
88
+ const result = {
89
+ '@context': 'https://schema.org',
90
+ '@type': 'ProductGroup',
91
+ name: product.name,
92
+ description: product.description,
93
+ image: product.images,
94
+ hasVariant: variants.map((v) => buildVariantProduct(v, url, product.currency, hasReturnPolicy)),
95
+ };
96
+ if (product.brand) {
97
+ result.brand = {
98
+ '@type': 'Brand',
99
+ name: product.brand,
100
+ };
101
+ }
102
+ if (product.rating) {
103
+ result.aggregateRating = {
104
+ '@type': 'AggregateRating',
105
+ ratingValue: product.rating.value,
106
+ reviewCount: product.rating.count,
107
+ ...(product.rating.bestRating !== undefined ? { bestRating: product.rating.bestRating } : {}),
108
+ };
109
+ }
110
+ return result;
111
+ }
112
+ //# sourceMappingURL=product.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.js","sourceRoot":"","sources":["../../../src/utils/json-ld/product.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ContentItem, JsonLdObject } from '../../types.js';
2
+ export declare function generateVideoJsonLd(item: ContentItem): JsonLdObject;
3
+ //# sourceMappingURL=video.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/utils/json-ld/video.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAiBnE"}
@@ -0,0 +1,20 @@
1
+ export function generateVideoJsonLd(item) {
2
+ const video = item.video;
3
+ const result = {
4
+ '@context': 'https://schema.org',
5
+ '@type': 'VideoObject',
6
+ name: item.title,
7
+ thumbnailUrl: video.thumbnailUrl,
8
+ duration: video.duration,
9
+ };
10
+ if (item.description)
11
+ result.description = item.description;
12
+ if (video.contentUrl)
13
+ result.contentUrl = video.contentUrl;
14
+ if (video.embedUrl)
15
+ result.embedUrl = video.embedUrl;
16
+ if (item.datePublished)
17
+ result.uploadDate = item.datePublished;
18
+ return result;
19
+ }
20
+ //# sourceMappingURL=video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.js","sourceRoot":"","sources":["../../../src/utils/json-ld/video.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CAAC,IAAiB;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAM,CAAA;IAEzB,MAAM,MAAM,GAAiB;QAC5B,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,aAAa;QACtB,IAAI,EAAE,IAAI,CAAC,KAAK;QAChB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACxB,CAAA;IAED,IAAI,IAAI,CAAC,WAAW;QAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;IAC3D,IAAI,KAAK,CAAC,UAAU;QAAE,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAA;IAC1D,IAAI,KAAK,CAAC,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IACpD,IAAI,IAAI,CAAC,aAAa;QAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAA;IAE9D,OAAO,MAAM,CAAA;AACd,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ResolvedSeoOptions } from '../../options.js';
2
+ import type { JsonLdObject } from '../../types.js';
3
+ export declare function generateWebSiteJsonLd(options: ResolvedSeoOptions): JsonLdObject;
4
+ //# sourceMappingURL=website.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website.d.ts","sourceRoot":"","sources":["../../../src/utils/json-ld/website.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,YAAY,CAuB/E"}
@@ -0,0 +1,22 @@
1
+ export function generateWebSiteJsonLd(options) {
2
+ const { site, organization, locales } = options;
3
+ const result = {
4
+ '@context': 'https://schema.org',
5
+ '@type': 'WebSite',
6
+ name: organization.name,
7
+ url: site,
8
+ potentialAction: {
9
+ '@type': 'SearchAction',
10
+ target: {
11
+ '@type': 'EntryPoint',
12
+ urlTemplate: `${site}/?q={search_term_string}`,
13
+ },
14
+ 'query-input': 'required name=search_term_string',
15
+ },
16
+ };
17
+ if (locales?.length) {
18
+ result.inLanguage = locales.map((l) => l.lang);
19
+ }
20
+ return result;
21
+ }
22
+ //# sourceMappingURL=website.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website.js","sourceRoot":"","sources":["../../../src/utils/json-ld/website.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,qBAAqB,CAAC,OAA2B;IAChE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAE/C,MAAM,MAAM,GAAiB;QAC5B,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,GAAG,EAAE,IAAI;QACT,eAAe,EAAE;YAChB,OAAO,EAAE,cAAc;YACvB,MAAM,EAAE;gBACP,OAAO,EAAE,YAAY;gBACrB,WAAW,EAAE,GAAG,IAAI,0BAA0B;aAC9C;YACD,aAAa,EAAE,kCAAkC;SACjD;KACD,CAAA;IAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAC/C,CAAC;IAED,OAAO,MAAM,CAAA;AACd,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ResolvedSeoOptions } from '../options.js';
2
+ /**
3
+ * Generate llms.txt per the llmstxt.org spec
4
+ * Format: # Title, > description, ## sections with links, ## Optional links
5
+ */
6
+ export declare function generateLlmsTxt(options: ResolvedSeoOptions): string;
7
+ //# sourceMappingURL=llms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llms.d.ts","sourceRoot":"","sources":["../../src/utils/llms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAEvD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAsCnE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Generate llms.txt per the llmstxt.org spec
3
+ * Format: # Title, > description, ## sections with links, ## Optional links
4
+ */
5
+ export function generateLlmsTxt(options) {
6
+ const { organization, llmsContent } = options;
7
+ const lines = [];
8
+ // Title
9
+ lines.push(`# ${organization.name}`);
10
+ lines.push('');
11
+ if (llmsContent) {
12
+ // Description block
13
+ if (llmsContent.description) {
14
+ lines.push(`> ${llmsContent.description}`);
15
+ lines.push('');
16
+ }
17
+ // Sections with links
18
+ for (const section of llmsContent.sections) {
19
+ lines.push(`## ${section.heading}`);
20
+ lines.push('');
21
+ for (const link of section.links) {
22
+ lines.push(`- [${link.title}](${link.url}): ${link.description}`);
23
+ }
24
+ lines.push('');
25
+ }
26
+ // Optional links
27
+ if (llmsContent.optionalLinks?.length) {
28
+ lines.push('## Optional');
29
+ lines.push('');
30
+ for (const link of llmsContent.optionalLinks) {
31
+ lines.push(`- [${link.title}](${link.url})`);
32
+ }
33
+ lines.push('');
34
+ }
35
+ }
36
+ return `${lines.join('\n').trimEnd()}\n`;
37
+ }
38
+ //# sourceMappingURL=llms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llms.js","sourceRoot":"","sources":["../../src/utils/llms.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAA2B;IAC1D,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IAE7C,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,QAAQ;IACR,KAAK,CAAC,IAAI,CAAC,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC,CAAA;IACpC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,IAAI,WAAW,EAAE,CAAC;QACjB,oBAAoB;QACpB,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,WAAW,EAAE,CAAC,CAAA;YAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACf,CAAC;QAED,sBAAsB;QACtB,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACd,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;YAClE,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACf,CAAC;QAED,iBAAiB;QACjB,IAAI,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACd,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;gBAC9C,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,CAAA;YAC7C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACf,CAAC;IACF,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,CAAA;AACzC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ResolvedSeoOptions } from '../options.js';
2
+ import type { CanonicalLink, ContentItem, MetaTag } from '../types.js';
3
+ export type OgVariant = 'article' | 'product' | 'website';
4
+ export declare function applyTrailingSlash(url: string, policy: string): string;
5
+ export declare function generateCanonical(url: string, options: ResolvedSeoOptions): CanonicalLink;
6
+ export declare function generateMeta(item: ContentItem, variant: OgVariant, options: ResolvedSeoOptions): MetaTag[];
7
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/utils/meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAEtE,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAEzD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAmCtE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAKzF;AAED,wBAAgB,YAAY,CAC3B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,kBAAkB,GACzB,OAAO,EAAE,CA+FX"}
@@ -0,0 +1,122 @@
1
+ export function applyTrailingSlash(url, policy) {
2
+ if (policy === 'never') {
3
+ // Strip trailing slash but preserve root slash
4
+ if (url.endsWith('/') && url !== '/') {
5
+ try {
6
+ const parsed = new URL(url);
7
+ if (parsed.pathname !== '/') {
8
+ parsed.pathname = parsed.pathname.replace(/\/+$/, '');
9
+ return parsed.toString();
10
+ }
11
+ return url;
12
+ }
13
+ catch {
14
+ return url.endsWith('/') && url.length > 1 ? url.slice(0, -1) : url;
15
+ }
16
+ }
17
+ return url;
18
+ }
19
+ if (policy === 'always') {
20
+ if (!url.endsWith('/')) {
21
+ try {
22
+ const parsed = new URL(url);
23
+ // Don't add slash if there's a query string or hash
24
+ if (!parsed.search && !parsed.hash) {
25
+ parsed.pathname = parsed.pathname.replace(/\/*$/, '/');
26
+ return parsed.toString();
27
+ }
28
+ return url;
29
+ }
30
+ catch {
31
+ return `${url}/`;
32
+ }
33
+ }
34
+ return url;
35
+ }
36
+ // ignore
37
+ return url;
38
+ }
39
+ export function generateCanonical(url, options) {
40
+ return {
41
+ rel: 'canonical',
42
+ href: applyTrailingSlash(url, options.trailingSlash),
43
+ };
44
+ }
45
+ export function generateMeta(item, variant, options) {
46
+ const tags = [];
47
+ const { defaults, organization } = options;
48
+ const canonicalUrl = applyTrailingSlash(item.url, options.trailingSlash);
49
+ const image = item.image ?? defaults.defaultImage ?? '';
50
+ const ogType = variant === 'article' ? 'article' : variant === 'product' ? 'og:product' : 'website';
51
+ // og:type
52
+ tags.push({ property: 'og:type', content: ogType });
53
+ // og:title
54
+ tags.push({ property: 'og:title', content: item.title });
55
+ // og:description
56
+ if (item.description) {
57
+ tags.push({ property: 'og:description', content: item.description });
58
+ }
59
+ // og:url
60
+ tags.push({ property: 'og:url', content: canonicalUrl });
61
+ // og:image
62
+ if (image) {
63
+ tags.push({ property: 'og:image', content: image });
64
+ tags.push({ property: 'og:image:width', content: '1200' });
65
+ tags.push({ property: 'og:image:height', content: '630' });
66
+ }
67
+ // og:site_name
68
+ tags.push({ property: 'og:site_name', content: organization.name });
69
+ // og:locale
70
+ const locale = item.locale ?? defaults.locale;
71
+ tags.push({ property: 'og:locale', content: locale });
72
+ // og:locale:alternate
73
+ if (item.alternateLocales?.length) {
74
+ for (const alt of item.alternateLocales) {
75
+ tags.push({ property: 'og:locale:alternate', content: alt.lang });
76
+ }
77
+ }
78
+ // twitter:card
79
+ tags.push({ name: 'twitter:card', content: defaults.twitterCardType });
80
+ // twitter:site
81
+ if (defaults.twitterSite) {
82
+ tags.push({ name: 'twitter:site', content: defaults.twitterSite });
83
+ }
84
+ // twitter:title
85
+ tags.push({ name: 'twitter:title', content: item.title });
86
+ // twitter:description
87
+ if (item.description) {
88
+ tags.push({ name: 'twitter:description', content: item.description });
89
+ }
90
+ // twitter:image
91
+ if (image) {
92
+ tags.push({ name: 'twitter:image', content: image });
93
+ }
94
+ // robots
95
+ tags.push({ name: 'robots', content: 'max-image-preview:large' });
96
+ // Article-specific
97
+ if (variant === 'article') {
98
+ if (item.datePublished) {
99
+ tags.push({ property: 'article:published_time', content: item.datePublished });
100
+ }
101
+ if (item.dateModified) {
102
+ tags.push({ property: 'article:modified_time', content: item.dateModified });
103
+ }
104
+ if (item.authors?.length) {
105
+ for (const author of item.authors) {
106
+ tags.push({ property: 'article:author', content: author.url ?? author.name });
107
+ }
108
+ }
109
+ }
110
+ // Product-specific
111
+ if (variant === 'product' && item.product) {
112
+ const p = item.product;
113
+ tags.push({ property: 'product:price:amount', content: String(p.price) });
114
+ tags.push({ property: 'product:price:currency', content: p.currency });
115
+ tags.push({ property: 'product:availability', content: p.availability });
116
+ if (p.brand) {
117
+ tags.push({ property: 'product:brand', content: p.brand });
118
+ }
119
+ }
120
+ return tags;
121
+ }
122
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/utils/meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ResolvedSeoOptions } from '../options.js';
2
+ import type { ContentItem } from '../types.js';
3
+ /**
4
+ * Convert ISO 8601 duration (e.g. PT8M30S, PT1H2M3S) to M:SS or H:MM:SS
5
+ */
6
+ export declare function convertIso8601Duration(duration: string): string;
7
+ export declare function generatePodcastFeed(episodes: ContentItem[], options: ResolvedSeoOptions): string;
8
+ //# sourceMappingURL=podcast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"podcast.d.ts","sourceRoot":"","sources":["../../src/utils/podcast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAW9C;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAe/D;AAMD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAwEhG"}
@@ -0,0 +1,94 @@
1
+ function escapeXml(str) {
2
+ return str
3
+ .replace(/&/g, '&')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;')
7
+ .replace(/'/g, '&apos;');
8
+ }
9
+ /**
10
+ * Convert ISO 8601 duration (e.g. PT8M30S, PT1H2M3S) to M:SS or H:MM:SS
11
+ */
12
+ export function convertIso8601Duration(duration) {
13
+ const match = duration.match(/^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/);
14
+ if (!match)
15
+ return duration;
16
+ const hours = parseInt(match[1] ?? '0', 10);
17
+ const minutes = parseInt(match[2] ?? '0', 10);
18
+ const seconds = parseInt(match[3] ?? '0', 10);
19
+ if (hours > 0) {
20
+ const mm = String(minutes).padStart(2, '0');
21
+ const ss = String(seconds).padStart(2, '0');
22
+ return `${hours}:${mm}:${ss}`;
23
+ }
24
+ const ss = String(seconds).padStart(2, '0');
25
+ return `${minutes}:${ss}`;
26
+ }
27
+ function toRfc822(dateStr) {
28
+ return new Date(dateStr).toUTCString();
29
+ }
30
+ export function generatePodcastFeed(episodes, options) {
31
+ const { site, organization } = options;
32
+ const podcast = options.podcast;
33
+ // Use podcast config if available, fall back to organization
34
+ const author = podcast?.author ?? organization.name;
35
+ const podcastTitle = podcast?.title ?? organization.name;
36
+ const podcastDescription = podcast?.description ?? '';
37
+ const podcastImage = podcast?.image ?? organization.logo;
38
+ const podcastCategory = podcast?.category ?? 'Technology';
39
+ const podcastLanguage = podcast?.language ?? 'en';
40
+ const podcastExplicit = podcast?.explicit ?? false;
41
+ const podcastType = podcast?.type ?? 'episodic';
42
+ const ownerEmail = podcast?.email ?? '';
43
+ const episodesXml = episodes
44
+ .map((item) => {
45
+ const pubDate = item.datePublished ? toRfc822(item.datePublished) : '';
46
+ const pubDateTag = pubDate ? `\n <pubDate>${escapeXml(pubDate)}</pubDate>` : '';
47
+ const descTag = item.description
48
+ ? `\n <description>${escapeXml(item.description)}</description>`
49
+ : '';
50
+ const enclosureTag = item.audio
51
+ ? `\n <enclosure url="${escapeXml(item.audio.url)}" type="audio/mpeg" length="0"/>`
52
+ : '';
53
+ const durationTag = item.audio?.duration
54
+ ? `\n <itunes:duration>${escapeXml(convertIso8601Duration(item.audio.duration))}</itunes:duration>`
55
+ : '';
56
+ const ep = item.podcastEpisode;
57
+ const episodeTag = ep?.episodeNumber != null
58
+ ? `\n <itunes:episode>${ep.episodeNumber}</itunes:episode>`
59
+ : '';
60
+ const seasonTag = ep?.seasonNumber != null ? `\n <itunes:season>${ep.seasonNumber}</itunes:season>` : '';
61
+ const episodeTypeTag = ep?.episodeType
62
+ ? `\n <itunes:episodeType>${escapeXml(ep.episodeType)}</itunes:episodeType>`
63
+ : '';
64
+ return ` <item>
65
+ <title>${escapeXml(item.title)}</title>
66
+ <link>${escapeXml(item.url)}</link>
67
+ <guid isPermaLink="true">${escapeXml(item.url)}</guid>${pubDateTag}${descTag}${enclosureTag}${durationTag}${episodeTag}${seasonTag}${episodeTypeTag}
68
+ </item>`;
69
+ })
70
+ .join('\n');
71
+ return `<?xml version="1.0" encoding="UTF-8"?>
72
+ <rss version="2.0"
73
+ xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
74
+ xmlns:podcast="https://podcastindex.org/namespace/1.0"
75
+ xmlns:atom="http://www.w3.org/2005/Atom">
76
+ <channel>
77
+ <title>${escapeXml(podcastTitle)}</title>
78
+ <description>${escapeXml(podcastDescription)}</description>
79
+ <link>${escapeXml(site)}</link>
80
+ <language>${escapeXml(podcastLanguage)}</language>
81
+ <itunes:author>${escapeXml(author)}</itunes:author>
82
+ <itunes:owner>
83
+ <itunes:name>${escapeXml(author)}</itunes:name>
84
+ <itunes:email>${escapeXml(ownerEmail)}</itunes:email>
85
+ </itunes:owner>
86
+ <itunes:image href="${escapeXml(podcastImage)}"/>
87
+ <itunes:category text="${escapeXml(podcastCategory)}"/>
88
+ <itunes:explicit>${podcastExplicit ? 'true' : 'false'}</itunes:explicit>
89
+ <itunes:type>${escapeXml(podcastType)}</itunes:type>
90
+ ${episodesXml}
91
+ </channel>
92
+ </rss>`;
93
+ }
94
+ //# sourceMappingURL=podcast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"podcast.js","sourceRoot":"","sources":["../../src/utils/podcast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ResolvedSeoOptions } from '../options.js';
2
+ export declare function generateRobotsTxt(options: ResolvedSeoOptions): string;
3
+ //# sourceMappingURL=robots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../../src/utils/robots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAGvD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA4BrE"}
@@ -0,0 +1,28 @@
1
+ import { SITEMAP_INDEX_PATH } from './sitemap.js';
2
+ export function generateRobotsTxt(options) {
3
+ const { site, robots } = options;
4
+ const lines = [];
5
+ // Default rules
6
+ lines.push('User-agent: *');
7
+ lines.push('Allow: /');
8
+ lines.push(`Sitemap: ${new URL(SITEMAP_INDEX_PATH, site).toString()}`);
9
+ // Additional rules
10
+ if (robots.additionalRules?.length) {
11
+ for (const rule of robots.additionalRules) {
12
+ lines.push('');
13
+ lines.push(`User-agent: ${rule.userAgent}`);
14
+ if (rule.allow?.length) {
15
+ for (const path of rule.allow) {
16
+ lines.push(`Allow: ${path}`);
17
+ }
18
+ }
19
+ if (rule.disallow?.length) {
20
+ for (const path of rule.disallow) {
21
+ lines.push(`Disallow: ${path}`);
22
+ }
23
+ }
24
+ }
25
+ }
26
+ return `${lines.join('\n')}\n`;
27
+ }
28
+ //# sourceMappingURL=robots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.js","sourceRoot":"","sources":["../../src/utils/robots.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC5D,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAChC,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,gBAAgB;IAChB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACtB,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;IAEtE,mBAAmB;IACnB,IAAI,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACd,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;YAC3C,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;gBACxB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC/B,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAA;gBAC7B,CAAC;YACF,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClC,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;gBAChC,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ResolvedSeoOptions } from '../options.js';
2
+ import type { ContentItem } from '../types.js';
3
+ export declare function generateRssFeed(items: ContentItem[], options: ResolvedSeoOptions, description?: string): string;
4
+ //# sourceMappingURL=rss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rss.d.ts","sourceRoot":"","sources":["../../src/utils/rss.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAe9C,wBAAgB,eAAe,CAC9B,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,EAAE,kBAAkB,EAC3B,WAAW,CAAC,EAAE,MAAM,GAClB,MAAM,CA2CR"}
@@ -0,0 +1,53 @@
1
+ function escapeXml(str) {
2
+ return str
3
+ .replace(/&/g, '&amp;')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;')
7
+ .replace(/'/g, '&apos;');
8
+ }
9
+ function toRfc822(dateStr) {
10
+ return new Date(dateStr).toUTCString();
11
+ }
12
+ export function generateRssFeed(items, options, description) {
13
+ const { site, organization, defaults } = options;
14
+ const feedDescription = description ?? organization.name;
15
+ const language = defaults.locale.replace('_', '-').toLowerCase();
16
+ const lastBuildDate = new Date().toUTCString();
17
+ const itemsXml = items
18
+ .map((item) => {
19
+ const pubDate = item.datePublished ? toRfc822(item.datePublished) : '';
20
+ const pubDateTag = pubDate ? `\n <pubDate>${escapeXml(pubDate)}</pubDate>` : '';
21
+ const descTag = item.description
22
+ ? `\n <description>${escapeXml(item.description)}</description>`
23
+ : '';
24
+ const creatorsXml = (item.authors ?? [])
25
+ .map((a) => `\n <dc:creator>${escapeXml(a.name)}</dc:creator>`)
26
+ .join('');
27
+ const enclosureTag = item.audio
28
+ ? `\n <enclosure url="${escapeXml(item.audio.url)}" type="audio/mpeg" length="0"/>`
29
+ : '';
30
+ return ` <item>
31
+ <title>${escapeXml(item.title)}</title>
32
+ <link>${escapeXml(item.url)}</link>
33
+ <guid isPermaLink="true">${escapeXml(item.url)}</guid>${pubDateTag}${descTag}${creatorsXml}${enclosureTag}
34
+ </item>`;
35
+ })
36
+ .join('\n');
37
+ return `<?xml version="1.0" encoding="UTF-8"?>
38
+ <rss version="2.0"
39
+ xmlns:atom="http://www.w3.org/2005/Atom"
40
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
41
+ xmlns:content="http://purl.org/rss/1.0/modules/content/">
42
+ <channel>
43
+ <title>${escapeXml(organization.name)}</title>
44
+ <description>${escapeXml(feedDescription)}</description>
45
+ <link>${escapeXml(site)}</link>
46
+ <language>${escapeXml(language)}</language>
47
+ <atom:link href="${escapeXml(`${site}/feed.xml`)}" rel="self" type="application/rss+xml"/>
48
+ <lastBuildDate>${lastBuildDate}</lastBuildDate>
49
+ ${itemsXml}
50
+ </channel>
51
+ </rss>`;
52
+ }
53
+ //# sourceMappingURL=rss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rss.js","sourceRoot":"","sources":["../../src/utils/rss.ts"],"names":[],"mappings":"AAGA,SAAS,SAAS,CAAC,GAAW;IAC7B,OAAO,GAAG;SACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe;IAChC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAC9B,KAAoB,EACpB,OAA2B,EAC3B,WAAoB;IAEpB,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAChD,MAAM,eAAe,GAAG,WAAW,IAAI,YAAY,CAAC,IAAI,CAAA;IACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IAChE,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAE9C,MAAM,QAAQ,GAAG,KAAK;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACtE,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,oBAAoB,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;QACpF,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW;YAC/B,CAAC,CAAC,wBAAwB,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB;YACrE,CAAC,CAAC,EAAE,CAAA;QACL,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;aACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;aACnE,IAAI,CAAC,EAAE,CAAC,CAAA;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK;YAC9B,CAAC,CAAC,2BAA2B,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC;YACxF,CAAC,CAAC,EAAE,CAAA;QAEL,OAAO;eACK,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;cACtB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;iCACA,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,YAAY;YACnG,CAAA;IACV,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO;;;;;;aAMK,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC;mBACtB,SAAS,CAAC,eAAe,CAAC;YACjC,SAAS,CAAC,IAAI,CAAC;gBACX,SAAS,CAAC,QAAQ,CAAC;uBACZ,SAAS,CAAC,GAAG,IAAI,WAAW,CAAC;qBAC/B,aAAa;EAChC,QAAQ;;OAEH,CAAA;AACP,CAAC"}