@pixelated-tech/components 3.13.14 → 3.13.16

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 (68) hide show
  1. package/dist/components/general/schema.functions.js +114 -0
  2. package/dist/components/general/schema.js +662 -0
  3. package/dist/components/general/sitemap.js +74 -31
  4. package/dist/components/general/utilities.js +38 -0
  5. package/dist/components/integrations/spotify.components.js +43 -0
  6. package/dist/components/integrations/spotify.functions.js +111 -0
  7. package/dist/components/integrations/wordpress.components.js +2 -2
  8. package/dist/config/pixelated.config.json.enc +1 -1
  9. package/dist/index.js +7 -13
  10. package/dist/index.server.js +3 -1
  11. package/dist/scripts/release.sh +9 -15
  12. package/dist/scripts/update.sh +45 -8
  13. package/dist/types/components/general/schema.d.ts +266 -0
  14. package/dist/types/components/general/schema.d.ts.map +1 -0
  15. package/dist/types/components/general/schema.functions.d.ts +77 -0
  16. package/dist/types/components/general/schema.functions.d.ts.map +1 -0
  17. package/dist/types/components/general/sitemap.d.ts +4 -4
  18. package/dist/types/components/general/sitemap.d.ts.map +1 -1
  19. package/dist/types/components/general/utilities.d.ts +2 -0
  20. package/dist/types/components/general/utilities.d.ts.map +1 -1
  21. package/dist/types/components/integrations/spotify.components.d.ts +27 -0
  22. package/dist/types/components/integrations/spotify.components.d.ts.map +1 -0
  23. package/dist/types/components/integrations/spotify.functions.d.ts +57 -0
  24. package/dist/types/components/integrations/spotify.functions.d.ts.map +1 -0
  25. package/dist/types/index.d.ts +7 -13
  26. package/dist/types/index.server.d.ts +3 -1
  27. package/dist/types/stories/general/schema.stories.d.ts +1 -1
  28. package/dist/types/stories/general/schema.stories.d.ts.map +1 -1
  29. package/dist/types/stories/integrations/loremipsum.stories.d.ts +1 -1
  30. package/dist/types/stories/integrations/schema-podcast.stories.d.ts +45 -0
  31. package/dist/types/stories/integrations/schema-podcast.stories.d.ts.map +1 -0
  32. package/dist/types/stories/integrations/spotify.stories.d.ts +19 -0
  33. package/dist/types/stories/integrations/spotify.stories.d.ts.map +1 -0
  34. package/dist/types/tests/schema-podcast.test.d.ts +2 -0
  35. package/dist/types/tests/schema-podcast.test.d.ts.map +1 -0
  36. package/dist/types/tests/spotify.test.d.ts +2 -0
  37. package/dist/types/tests/spotify.test.d.ts.map +1 -0
  38. package/package.json +46 -42
  39. package/dist/components/general/schema-blogposting.functions.js +0 -44
  40. package/dist/components/general/schema-blogposting.js +0 -18
  41. package/dist/components/general/schema-breadcrumb.js +0 -78
  42. package/dist/components/general/schema-faq.js +0 -38
  43. package/dist/components/general/schema-localbusiness.js +0 -125
  44. package/dist/components/general/schema-product.js +0 -51
  45. package/dist/components/general/schema-recipe.js +0 -58
  46. package/dist/components/general/schema-review.js +0 -47
  47. package/dist/components/general/schema-services.js +0 -79
  48. package/dist/components/general/schema-website.js +0 -148
  49. package/dist/types/components/general/schema-blogposting.d.ts +0 -10
  50. package/dist/types/components/general/schema-blogposting.d.ts.map +0 -1
  51. package/dist/types/components/general/schema-blogposting.functions.d.ts +0 -27
  52. package/dist/types/components/general/schema-blogposting.functions.d.ts.map +0 -1
  53. package/dist/types/components/general/schema-breadcrumb.d.ts +0 -14
  54. package/dist/types/components/general/schema-breadcrumb.d.ts.map +0 -1
  55. package/dist/types/components/general/schema-faq.d.ts +0 -10
  56. package/dist/types/components/general/schema-faq.d.ts.map +0 -1
  57. package/dist/types/components/general/schema-localbusiness.d.ts +0 -53
  58. package/dist/types/components/general/schema-localbusiness.d.ts.map +0 -1
  59. package/dist/types/components/general/schema-product.d.ts +0 -38
  60. package/dist/types/components/general/schema-product.d.ts.map +0 -1
  61. package/dist/types/components/general/schema-recipe.d.ts +0 -33
  62. package/dist/types/components/general/schema-recipe.d.ts.map +0 -1
  63. package/dist/types/components/general/schema-review.d.ts +0 -34
  64. package/dist/types/components/general/schema-review.d.ts.map +0 -1
  65. package/dist/types/components/general/schema-services.d.ts +0 -36
  66. package/dist/types/components/general/schema-services.d.ts.map +0 -1
  67. package/dist/types/components/general/schema-website.d.ts +0 -40
  68. package/dist/types/components/general/schema-website.d.ts.map +0 -1
@@ -1,7 +1,8 @@
1
1
  import PropTypes from "prop-types";
2
+ import { encode } from 'html-entities';
2
3
  import { getAllRoutes } from "./metadata.functions";
3
4
  import { getWordPressItems, getWordPressItemImages } from "../integrations/wordpress.functions";
4
- import { getContentfulFieldValues, getContentfulAssetURLs } from "../integrations/contentful.delivery";
5
+ import { getContentfulFieldValues, getContentfulAssets } from "../integrations/contentful.delivery";
5
6
  import { getEbayAppToken, getEbayItemsSearch } from "../shoppingcart/ebay.functions";
6
7
  import { getFullPixelatedConfig } from '../config/config';
7
8
  import { CacheManager } from '../general/cache-manager';
@@ -81,7 +82,7 @@ export async function generateSitemap(cfg = {}, originInput) {
81
82
  const useWPImages = cfg.createWordPressImageURLs ?? false;
82
83
  const useImageJSON = cfg.createImageURLsFromJSON ?? true;
83
84
  const useContentful = cfg.createContentfulURLs ?? false;
84
- const useContentfulImages = cfg.createContentfulImageURLs ?? false;
85
+ const useContentfulAssets = cfg.createContentfulAssetURLs ?? false;
85
86
  const usePageBuilder = cfg.createPageBuilderURLs ?? false;
86
87
  const useEbay = cfg.createEbayItemURLs ?? false;
87
88
  // Pages
@@ -103,9 +104,9 @@ export async function generateSitemap(cfg = {}, originInput) {
103
104
  if (useContentful && cfg.contentful) {
104
105
  sitemapEntries.push(...(await createContentfulURLs({ apiProps: cfg.contentful, origin })));
105
106
  }
106
- // Contentful images
107
- if (useContentfulImages && cfg.contentful) {
108
- sitemapEntries.push(...(await createContentfulImageURLs({ apiProps: cfg.contentful, origin })));
107
+ // Contentful assets (images and videos)
108
+ if (useContentfulAssets && cfg.contentful) {
109
+ sitemapEntries.push(...(await createContentfulAssetURLs({ apiProps: cfg.contentful, origin })));
109
110
  }
110
111
  // Page Builder (existing helper in package not always present)
111
112
  if (usePageBuilder && cfg.contentful) {
@@ -300,17 +301,17 @@ export async function createContentfulPageBuilderURLs(props) {
300
301
  return sitemap;
301
302
  }
302
303
  /**
303
- * createContentfulImageURLs — Fetch Contentful assets and generate absolute image URLs for the sitemap.
304
+ * createContentfulAssetURLs — Fetch Contentful assets and generate absolute image and video URLs for the sitemap.
304
305
  *
305
306
  * @param {shape} [props.apiProps] - Contentful API props (proxyURL optional, base_url, space_id, environment, access_token).
306
- * @param {string} [props.proxyURL] - Optional proxy base URL to route image requests through.
307
+ * @param {string} [props.proxyURL] - Optional proxy base URL to route asset requests through.
307
308
  * @param {string} [props.base_url] - Contentful base API URL.
308
309
  * @param {string} [props.space_id] - Contentful space id.
309
310
  * @param {string} [props.environment] - Contentful environment.
310
311
  * @param {string} [props.access_token] - Access token to read assets from Contentful.
311
- * @param {string} [props.origin] - Origin used to convert relative image paths to absolute URLs.
312
+ * @param {string} [props.origin] - Origin used to convert relative asset paths to absolute URLs.
312
313
  */
313
- createContentfulImageURLs.propTypes = {
314
+ createContentfulAssetURLs.propTypes = {
314
315
  /** Contentful API properties */
315
316
  apiProps: PropTypes.shape({
316
317
  /** Optional proxy URL */
@@ -327,37 +328,79 @@ createContentfulImageURLs.propTypes = {
327
328
  /** Origin used to convert relative URLs to absolute */
328
329
  origin: PropTypes.string.isRequired,
329
330
  };
330
- export async function createContentfulImageURLs(props) {
331
+ export async function createContentfulAssetURLs(props) {
331
332
  const sitemap = [];
332
333
  const providerContentfulApiProps = getFullPixelatedConfig()?.contentful;
333
334
  // Changed order: provider config overrides apiProps for security (tokens)
334
335
  const mergedApiProps = { ...props.apiProps, ...providerContentfulApiProps };
335
- // const mergedApiProps = { ...providerContentfulApiProps, ...props.apiProps }; // Old: apiProps overrode provider
336
336
  try {
337
- const assets = await getContentfulAssetURLs({ apiProps: mergedApiProps });
338
- if (!Array.isArray(assets) || assets.length === 0)
337
+ const rawAssets = await getContentfulAssets({ apiProps: mergedApiProps });
338
+ if (!Array.isArray(rawAssets?.items) || rawAssets.items.length === 0) {
339
339
  return sitemap;
340
- const newImages = assets.map((a) => {
341
- let i = a.image || '';
342
- if (!i)
343
- return ''; // Filter out empty images before processing
344
- if (i.startsWith('//'))
345
- i = `https:${i}`;
346
- else if (i.startsWith('/'))
347
- i = `${props.origin}${i}`;
348
- else if (!i.startsWith('http://') && !i.startsWith('https://'))
349
- i = `${props.origin}/${i}`; // Handle relative URLs
350
- return i;
351
- }).filter(Boolean);
352
- sitemap.push({
353
- url: `${props.origin}/images`,
354
- images: newImages,
355
- lastModified: new Date(),
356
- });
340
+ }
341
+ // Process assets into images and videos by content type
342
+ const imageAssets = rawAssets.items.filter((a) => a.fields?.file?.contentType?.startsWith('image/'));
343
+ // Process image assets
344
+ if (imageAssets.length > 0) {
345
+ const imageURLs = imageAssets.map((a) => {
346
+ let url = a.fields?.file?.url || '';
347
+ if (!url)
348
+ return '';
349
+ if (url.startsWith('//'))
350
+ url = `https:${url}`;
351
+ else if (url.startsWith('/'))
352
+ url = `${props.origin}${url}`;
353
+ else if (!url.startsWith('http://') && !url.startsWith('https://'))
354
+ url = `${props.origin}/${url}`;
355
+ return encode(url);
356
+ }).filter(Boolean);
357
+ if (imageURLs.length > 0) {
358
+ sitemap.push({
359
+ url: `${props.origin}/images`,
360
+ lastModified: new Date(),
361
+ changeFrequency: 'always',
362
+ priority: 1.0,
363
+ images: imageURLs,
364
+ });
365
+ }
366
+ }
367
+ const videoAssets = rawAssets.items.filter((a) => a.fields?.file?.contentType?.startsWith('video/'));
368
+ // Process video assets
369
+ if (videoAssets.length > 0) {
370
+ console.log("Video Assets", videoAssets);
371
+ sitemap.push({
372
+ url: `${props.origin}/videos`,
373
+ lastModified: new Date(),
374
+ changeFrequency: 'always',
375
+ priority: 1.0,
376
+ // videos: videoURLs,
377
+ videos: videoAssets.map((a) => {
378
+ let url = a.fields?.file?.url || '';
379
+ if (!url)
380
+ return null;
381
+ if (url.startsWith('//'))
382
+ url = `https:${url}`;
383
+ else if (url.startsWith('/'))
384
+ url = `${props.origin}${url}`;
385
+ else if (!url.startsWith('http://') && !url.startsWith('https://'))
386
+ url = `${props.origin}/${url}`;
387
+ return {
388
+ title: a.fields?.title || 'Untitled Video',
389
+ thumbnail_loc: `${props.origin}/images/placeholder.png`,
390
+ description: a.fields?.description || 'No description available',
391
+ publication_date: a.sys?.createdAt || new Date().toISOString(),
392
+ content_loc: encode(url),
393
+ player_loc: encode(url),
394
+ family_friendly: 'yes',
395
+ // duration: 600,
396
+ };
397
+ })
398
+ });
399
+ }
357
400
  }
358
401
  catch (e) {
359
402
  if (typeof console !== 'undefined')
360
- console.warn('createContentfulImageURLs failed', e);
403
+ console.warn('createContentfulAssetURLs failed', e);
361
404
  }
362
405
  return sitemap;
363
406
  }
@@ -203,3 +203,41 @@ export const SERVER_ONLY_PATTERNS = [
203
203
  // /\bNextRequest\b/,
204
204
  // /\bNextResponse\b/
205
205
  ];
206
+ export function stringTo1337_v1(str) {
207
+ return str
208
+ .replace(/o/gi, '0')
209
+ // .replace(/i/gi, '1')
210
+ .replace(/l/gi, '1')
211
+ .replace(/r/gi, '2')
212
+ .replace(/e/gi, '3')
213
+ .replace(/a/gi, '4')
214
+ .replace(/s/gi, '5')
215
+ .replace(/g/gi, '6')
216
+ .replace(/t/gi, '7')
217
+ .replace(/b/gi, '8')
218
+ .replace(/g/gi, '9');
219
+ }
220
+ export function stringTo1337(str) {
221
+ //converts lowercase non consecutive, non number characters (and doublets) to leet speak numbers
222
+ const leetMap = {
223
+ 'o': '0', 'l': '1', 'z': '2', 'e': '3',
224
+ 'a': '4', 's': '5', 'b': '6', 't': '7',
225
+ 'g': '9'
226
+ };
227
+ let result = '';
228
+ for (const char of str) {
229
+ const leet = leetMap[char];
230
+ const last = result.slice(-1);
231
+ const lastIsNumber = /[0-9]/.test(last);
232
+ // Convert if:
233
+ // 1. There is a mapping
234
+ // 2. AND (the last char isn't a leet number OR it's matches for a doublet)
235
+ if (leet && (!lastIsNumber || last === leet)) {
236
+ result += leet;
237
+ }
238
+ else {
239
+ result += char;
240
+ }
241
+ }
242
+ return result;
243
+ }
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import PropTypes from "prop-types";
3
+ import { PageGridItem } from '@pixelated-tech/components';
4
+ import { BlogPostSummary } from '@pixelated-tech/components';
5
+ function getFirstSentences(str, minLength = 300) {
6
+ if (!str)
7
+ return '';
8
+ const firstPeriodIndex = str.indexOf('.', minLength);
9
+ if (firstPeriodIndex !== -1) {
10
+ return str.slice(0, firstPeriodIndex + 1);
11
+ }
12
+ return str;
13
+ }
14
+ /**
15
+ * Component to display a list of podcast episodes.
16
+ * @param props - The properties for the component, including an array of podcast episodes.
17
+ * @returns A React component that renders a list of podcast episodes.
18
+ */
19
+ PodcastEpisodeList.propTypes = {
20
+ episodes: PropTypes.arrayOf(PropTypes.shape({
21
+ title: PropTypes.string.isRequired,
22
+ description: PropTypes.string.isRequired,
23
+ link: PropTypes.string.isRequired,
24
+ guid: PropTypes.string.isRequired,
25
+ creator: PropTypes.string.isRequired,
26
+ pubDate: PropTypes.string.isRequired,
27
+ enclosure: PropTypes.shape({
28
+ url: PropTypes.string.isRequired,
29
+ type: PropTypes.string.isRequired,
30
+ length: PropTypes.string.isRequired,
31
+ }).isRequired,
32
+ summary: PropTypes.string.isRequired,
33
+ explicit: PropTypes.bool.isRequired,
34
+ duration: PropTypes.string.isRequired,
35
+ image: PropTypes.string.isRequired,
36
+ episode: PropTypes.string.isRequired,
37
+ episodeType: PropTypes.string.isRequired,
38
+ }).isRequired).isRequired
39
+ };
40
+ export function PodcastEpisodeList(props) {
41
+ const { episodes } = props;
42
+ return (_jsx(_Fragment, { children: episodes.map((episode) => (_jsx(PageGridItem, { children: _jsx(BlogPostSummary, { ID: episode.guid, title: episode.title, date: episode.pubDate, excerpt: getFirstSentences(episode.summary), URL: episode.link, featured_image: episode.image, showCategories: false }) }, episode.guid))) }));
43
+ }
@@ -0,0 +1,111 @@
1
+ import PropTypes from "prop-types";
2
+ function SpotifyRSSSeriesToJson(data) {
3
+ const parser = new DOMParser();
4
+ const xml = parser.parseFromString(data, 'application/xml');
5
+ const channel = xml.querySelectorAll('channel');
6
+ if (channel.length > 0) {
7
+ const item = channel[0];
8
+ return {
9
+ title: item.querySelector('title')?.textContent,
10
+ description: item.querySelector('description')?.textContent,
11
+ link: item.querySelector('link')?.textContent,
12
+ generator: item.querySelector('generator')?.textContent,
13
+ lastBuildDate: item.querySelector('lastBuildDate')?.textContent,
14
+ author: item.querySelector('author')?.textContent,
15
+ copyright: item.querySelector('copyright')?.textContent,
16
+ language: item.querySelector('language')?.textContent,
17
+ iTunesAuthor: item.querySelector('author')?.textContent,
18
+ summary: item.querySelector('summary')?.textContent,
19
+ type: item.querySelector('type')?.textContent,
20
+ owner: {
21
+ name: item.querySelector('owner')?.querySelector('name')?.textContent,
22
+ email: item.querySelector('owner')?.querySelector('email')?.textContent,
23
+ },
24
+ explicit: item.querySelector('explicit')?.textContent,
25
+ category: item.querySelector('category')?.textContent,
26
+ image: item.querySelector('image')?.getAttribute('href') || '',
27
+ /*
28
+ <atom:link href="https://anchor.fm/s/10fc04b98/podcast/rss" rel="self" type="application/rss+xml"/>
29
+ <atom:link rel="hub" href="https://pubsubhubbub.appspot.com/"/>
30
+ */
31
+ };
32
+ }
33
+ else {
34
+ return {};
35
+ }
36
+ }
37
+ /**
38
+ * getSpotifySeries — Fetch series information from the Spotify API for a given podcast.
39
+ *
40
+ * @param {string} [props.rssURL] - RSS feed URL of the podcast.
41
+ */
42
+ getSpotifySeries.propTypes = {
43
+ /** RSS feed URL of the podcast */
44
+ rssURL: PropTypes.string.isRequired,
45
+ };
46
+ export async function getSpotifySeries(props) {
47
+ const { rssURL } = props;
48
+ try {
49
+ const response = await fetch(rssURL);
50
+ const data = await response.text();
51
+ let rssJSON = SpotifyRSSSeriesToJson(data);
52
+ return rssJSON;
53
+ }
54
+ catch (error) {
55
+ console.error("Error fetching Spotify series data via RSS:", error);
56
+ return;
57
+ }
58
+ }
59
+ function SpotifyRSSItemsToJson(data) {
60
+ const parser = new DOMParser();
61
+ const xml = parser.parseFromString(data, 'application/xml');
62
+ let items;
63
+ if (xml.querySelectorAll('item').length > 0) {
64
+ items = Array.from(xml.querySelectorAll('item')).map(item => {
65
+ return {
66
+ title: item.querySelector('title')?.textContent,
67
+ description: item.querySelector('description')?.textContent,
68
+ link: item.querySelector('link')?.textContent,
69
+ guid: item.querySelector('guid')?.textContent,
70
+ creator: item.querySelector('creator')?.textContent,
71
+ pubDate: item.querySelector('pubDate')?.textContent,
72
+ enclosure: {
73
+ url: item.querySelector('enclosure')?.getAttribute('url') || '',
74
+ type: item.querySelector('enclosure')?.getAttribute('type') || '',
75
+ length: item.querySelector('enclosure')?.getAttribute('length') || '',
76
+ },
77
+ summary: item.querySelector('summary')?.textContent,
78
+ explicit: item.querySelector('explicit')?.textContent,
79
+ duration: item.querySelector('duration')?.textContent,
80
+ image: item.querySelector('image')?.getAttribute('href') || '',
81
+ episode: item.querySelector('episode')?.textContent,
82
+ episodeType: item.querySelector('episodeType')?.textContent,
83
+ };
84
+ });
85
+ }
86
+ return (items);
87
+ }
88
+ /**
89
+ * getSpotifyEpisodes — Fetch episodes from the Spotify API for a given podcast.
90
+ *
91
+ * @param {string} [props.rssURL] - RSS feed URL of the podcast.
92
+ */
93
+ getSpotifyEpisodes.propTypes = {
94
+ /** RSS feed URL of the podcast */
95
+ rssURL: PropTypes.string.isRequired,
96
+ };
97
+ export async function getSpotifyEpisodes(props) {
98
+ const { rssURL } = props;
99
+ try {
100
+ const response = await fetch(rssURL);
101
+ const data = await response.text();
102
+ let rssJSON = SpotifyRSSItemsToJson(data);
103
+ if (rssJSON)
104
+ rssJSON = rssJSON.sort((a, b) => ((a.pubDate ?? '') < (b.pubDate ?? '')) ? 1 : -1);
105
+ return rssJSON;
106
+ }
107
+ catch (error) {
108
+ console.error("Error fetching Spotify episodes via RSS:", error);
109
+ return;
110
+ }
111
+ }
@@ -9,8 +9,8 @@ import { getWordPressItems, getWordPressLastModified } from './wordpress.functio
9
9
  import { Loading, ToggleLoading } from '../general/loading';
10
10
  import { CacheManager } from "../general/cache-manager";
11
11
  import "./wordpress.css";
12
- import { SchemaBlogPosting } from '../general/schema-blogposting';
13
- import { mapWordPressToBlogPosting } from '../general/schema-blogposting.functions';
12
+ import { SchemaBlogPosting } from '../general/schema';
13
+ import { mapWordPressToBlogPosting } from '../general/schema.functions';
14
14
  // https://microformats.org/wiki/h-entry
15
15
  function decodeString(str) {
16
16
  const textarea = document.createElement('textarea');
@@ -1 +1 @@
1
- pxl:v1:0ea7358faf9202bb60545a38:41b21ffbdb5cae26290f4bb92ae63bc4:a1017f34fcc52a595990b19a92ea5c6a2d6e9e3fa34d83104950ece2f89b75693721aa678144396168af698e6f4e0eaae9388c26dbf390503176d96f13805fedf1e3e2e70a839bf8ecf3b9ba2dbecfb8005943ba313c6274c2ee70fc2dca552f3e7348b3dc362302036f847fffdf25e8bb0a283497be568b06ef3901117b5714e1ec34682a9d04bc6aa9af4d4991a5d1199ec55434fd83e9fc09d4348dfd01ccfbb1527169006ce35e98d52e4a2c4edcfa9245edfdef351b3fdbdd79e512476218544dc9b83c36e4a6eb7eb92bccb0befa3009006fec2cb0e6e68e4d5416c89fc0fc5db02c1d2dc646cf446edfbc5fd0bb14e854589bd78f6c61544ea2d03af9449e56a613d28422a4e3157d6e83f8fd335a38da0a9235ff78884f0dddf664fcc9bc42631dc8afb436dd423704812883b88b134ca067760a87af43263c1286be69ca2bcee1ec3c3e97b7d6d829f8aa3e5027777de3f0f0624c83312506e716d02fcf0c6f906347aa09afc2856e54e2a29acf9cb91a43adde0b260b02bcaa9030054ad91513afd71f4e501ada65455b29d94bc91f15786b07f2f4d38f459686fd676fd151a821f69bce450462231e9602954dc1dd1f842b6966dff2074e1cb9c9f198582c692e4f1ef962bee0d24bfe86d455a483999649db7e54e5cc67e1fe59505fd3ad051a3cd4d2ca401df3aca192ba0ee560879f7245e8666eac98af4c913593fc822c37aec67c38183312d11185a959ff425b24d8a658023a2f6da93c2c71bd11381b148e3fd33313c7585b3b53747128e05333e7407165a504bd9b337fa6b11ae76de1c74fe57e80c05e261fb968cd2c91ad023962ea37fb66420365caab1bea9e27ec783200b4f932c698b2e5f814f7403102906e06eef4ca02d24b5ccf9d5b06995527a6fcd26999ae48859a03d17f2cedc169541f1ce8f5d087720dd7b62a612bcc3748974f5249f148cfe53faa8cd59a756dbc442fb8f825ad402fe7fea959ddd8509a721a7c2253c78350b767b9f186e508b73a3de58d6c90492b3d8837f7002a10c190cc83c095db131173ce4ae546b10b0eeab7aa805fd42c33788e9971decd631cfaea9a5fde1b4db41b97c34d149c9d887b0162fdbe946100bf87d50a28c97cc1b5a043bf71b178ebf8edb8a03c024eb74d1e985c6f3b88645b38a21d1395359a4aa10c584febbd5f7ccf3c01418f9bee5dbc930ac18fed045dbd10fb43322d6f9a9092576d6f2937626cf05cf18a9b14daee20743333953f858dc5aabe22d3522809b42454a7818a27fea0adb89e4457def259ce8510f1cc3958fc6572550cae28f9570747351abd2906fad62083cc06e3f80577a3b62c2eccd0649485a5656078bc9d7624c174b04ec1dff3c7162ff1a6b66ed16b28570c2986be3abd80add81a656a91aea1293950f56540c5ca155eb869f6cd6979e9c682333ca0ef939d1325ea62dcd96ee5c5aa0277ba83bbff63a2a888639095fdf148116b6259d5415691dc6b7a4b6940ba12a93017c1aca3d98e40044e52a1c97a1d8bd4d1028c1e602f529e5d5edb47d948f3057ad21d8259053052402729104f22d4da4674d8b6ad8751b31fd5c5db55b79c627e5fc6f4a17e03ef31f9ca0949f7521c887c222e07fb5067efee0cc96c6ea7a273d31ba3ddc06ce2d36915b6819083c43de1f916a72bef34ed70ad6b1c15885be1065e83b8056d2b8c9c6fde3415439c2903787e5e41e15bf5f4bd428b5b549352ab4c6d4b027bf5c84fec5862da1176fb652715b0e20a6286f17d5a16aba429fa331a90e6d6fe357a120a872824c6426afaa448f9cbe8ae1d41c1cf44cbf9646325bdc181435deabc5b9c7d67fe5f6f2ff3ee41adcfbe29325121006f7714af6e671e6ae374c9a89b456a0fff452f5a6939c3a4387330fe599080876084ee5432cfc8d073c5db098b2d522ee31a9d9c1790c1787a28bfdb98130b1bf24def2a5579d9ddb5cdf929e51071fa392c0663efaab5785a41ab8ae7f19754352d8f394b79f36ed64ab4c63681dfdddb20e15a4c2f3837480bb50d7538aead3d19e58cc2677b6ad3a2acbb0cda0338f944b3e7a6da40bd85cd6bc2b8358b76e85b327ad5349eb40804155791e20293e00122d33393fe812358e35757cc81c80a380faccbdf4a9db17c71c4595084d4cef7b435cc05fa5bf9364b9d46be4ecc79a06b92d6976d4a3e889adbd01a20b936ceb0d9866a8869758735457da6c6fa0955752682929b032135b063aae10a9638a1142f8e22211de33d784c0d4a944098e2edd31c2c9c2beaa853978eb0d38891d6e9cef523490408573479ea5a1726463e2fc8d5652b53599d310e22557bc22e45ccb406925e9ec2f22530f55f691ecb80fae5660d9ab5e2f16b31393f82fcfd793591c9403df6ef0ee157ea604ef94389503b9eeeeb97cd805e1250266cd45760608e006b7a6af235ebda3d8e55d9a0fb8384ac66777f81e0af8b5ca3eb28f27133b50294c1294439dfd762153357a8e697e87a597979f3c3670b33e2c7e956cff5d4fd691612bde8a2fa45deecc738c5dc16b4a501ac7bd56e2a11780506f459457157ef878af605be160ae0b79a6336f2ac6c463a7cca653cf45049fe87bbc7e494bbbca6e2fab73faa35db282da16c845d867338d122768dc32eaaa2325593410cdbc1d99b3e9433a970001ec1e28d743c6403ac62a18c333cc71349839bd23683e6efb80026b469034aaf9c2cb45c89ed6cbb95bf516e8f63a01fe9344086e9ed163c9ce5e0a7d796bd50e781dd15128506981d6b2d9a313f39fdcdf96f2ba9f9e40115ce797276cca266be78808600238dd0b615f6e95863f3cb48dbcfa074681d69ef15743c060697318d26396b8147e0807712352d83b921c9d4a9b02ee13c14ad9a1625973edcce01a220c6f267bc18b757f7f04109dd859c895683e29035acf4c1e5625e6a7d86bef3b8e0cb9e3eb4b4658678d53a90d4ef01ab1063158725c5a16447105ddc78a42772ba9fbb8fbd98cf6c649ae4ead6fc18a48ca2303855810c2c291f33d28377726f728e6e2eb08752842afe9d7ec887fe0d8b6c520c068c99f0c6a43e00831d9743126a96c9b12491ef7e9d12f7b21b519c7a8e2bebe23bcb36fe9cbd5b43f919e1597123e94e97d2c8b9fc3843fc4ec06b5c5fa393d8e9d1e3c8ab67c649735d00d78ab26f501e8d7b8b11a53736ecef15b3ec4252c57b64a4163d88c7cd63cc92b5db732dfe3ce412ffc5c54bdb7b889a45943125e641ec2be103c03ab8c54bfddf6d17396eaf5cd19a93a8cb45a5865d27ffdc09130d63500d6e1c9dc83b987be204fe258431af4275a6df25f68c06168433666f569c5e73127f4468a1e18e4d7983456e52c41b842b806c242c990bc7b0acf97ba8f00706f7fc29c9ec608b65de147cfd25f8efeb6ef8eaa0809880098c9e4b4e149187dd8224d0f9538ab6bc7b8113ca7ead03c5465e622e978603ff2d0eb780a30370a99e15e1d71f4c17c6570309dfcaf2cc4bb38c0a889c0fbddc0ed7047d3f95a1c0262631e05d799b88455b2f7e2d92ad9a55e729de7ae71ba18ea6c0219a7c1f4a2b08c3bf5fbc165f8a6caaf456edb4d0fb562834596ca029d0cc15ff748fa403af721a1195457616720c1d7772c76b325f64a447f1fd7000ab6efa84532bb9790b0ee99f1780e11de6bc1c685bec050a91ce6ddcd7d0dce00686a9d2a0d2367da4788df398a973623f8afd3dc21ef3c4c8e676a90e9aea0e2bfee396cb16c6197ee42663a2c52c5dbdad7bdbc2e85e05f599d34560dc790cffa647532852a406edbba22ecf5f28d95f6c3fc52988bccf67879e0448332e0d36a21351c02f3426bbfa093e1dffc8c29c16bb6c7a1a9bfb87819bcd49b8d004bb0563ddbb128833c123886c220ff27fa45ad80011dd6a7c614219a638c079560be2e8cd61fbe0ee53c875cea305f9d1f9256a0d5c3fff4baa6353c956a101de27f518ba70cf7753775cc6ce95b8f5a2e53d0bf3989eed0b7722844d70e512dfa3afcf63976c06eef282bc3275830a95f27f5154bf7e0aca120ffce4e30c71120ec7ec55148c2ff5fe13226353ebdee6c4e95d4f9e42887f5a3ce9688a1b0b2b29843c27eb4dd7d25266b2e5bef768d2676e56e7e425dbc8abe355f348cd81bcd7884176e4a28440a8fd2de1eca0cafc03a2d81f9239677574aaed133e88c77d0e9dcb8b77e757268d3fedfe1a0bbc5b59d39eff72fbc4a636669e26cef4de347c351cd0f939229df8fd03ad4db01c0168aa94fa3cabeb8b4ac198cb68e8d8a5eaf61537c942e1c57e5249ceb5aaf242cb67aab10a93fadb49635bb4208f28fbd52a10741f40d85c15c7ad177b6f0aefd205bcf415f1d5898b9f090bca6d32ad0d04dd26c31e5eeb169e69a4d2c6c6fc94ed038daf3e5cb7161506c98938fc1714bd7fb8e9dc597b47d21bcc00abcd6b0bc682bf26bbaa677fd9e032e6cda762303109f7face898c4fda344ee919b5cc3ff9ef2668112e14866e4c9c2dcc1d68daf789c59750588940cc7cf484b8fff986be92bb3c7c0228b2e478a93560602860a178a21abd86bdb687d854c1315452248a84821c95652c1214122cc49f539f6827dfa6d5fe9cb87b667f8079b1b154e94b0ad46cc2b9f5457bcc424b39e0560f0db042839365207910b6b63b12f2a4b381aca3a1551fc01a43015941530310841d0b00e0d58d30fdd04db383c2f0d7ac2a4e86ffc1585aa212819061cfce2d6a09bd31fe184586f685009ca05621a34d5121561e458681bc0192e625f351d3001c5e0db9c6e56816a08067648e84c6c109e4e6aa3c918184121e44468d5da9dbe8499dc27642a02a3298cc7389730aece4af2ab7accde38568132fff0e3c2b8cc08919af1f5a921e274ef5480c5714ce51dbe5c8abc849b1c7f58a869bce26520d1ba6ef70adcc487db04fda3b9824d5d94322b430695fcad899b4fe41284e9267dffcb241b5409351e843d64d2aaa25730e0da1fcb1de14d0e2a9c3967d4c7543b8b3277026a2aea1b9fd74f554f874b870e7105a0025f3f2d1e613e18531cc6f81b0e00745af8dd2a3502cd206427c6d5b774f9a5eefadd77d0c977ef2eea90f2abf361685b4973ba302891b540b75eba593b92c9f75557b2a9e0ca2ec075dc5bef273d8113cc0d0479858
1
+ pxl:v1:944e61c3a894b694470bac88:f6779781197b20e03d028b7ef7b9e0d1:7d4f34021a97d9ddc6abc9eafd6fc8ab3331521a2d2778d03e3fd73b7a43e7d876b4abe146b08a1f6434ad5eca758902efc9fdee70d2a714d03ceeca56ccc927882baf25169bcbec791f9d556c461e175c4fc7476b413a933a5b2456dc02cbe1844b628fee57147b9e323db61c157f3719e1b9dadfa8d0fbaf182b147f7fecab03490ddc56e244511d043d56222c51ef0978bd0e0f97a226c7f9e4e5db26d502a8409474646b8af27b6b3951b448881d456d650b1620cccfcf20b2d6291d929c1d0501fb2c7285d57f161d7b8ba6bdeed2a86f3e2973faa4a2ba7ee0acad5591c19421377cdc3db453566d8ee351957298bf5bbfe5e8b65f3b92bb87edb9f81867e682b7fb939750771abfb78554b8dae1835bf2601f0e853154bc8c1ad4dd13f1d8cd62aa51970e00a99793ad9e211110e1616513be5d767938cb6e25c779fa759fb00fbd420abe655f22639048abcc6a64971fd17045e4910d9970c5b1283df77ec3a791b334f73b969c0c11e042cf951912cbe75fe575ad89fa8aa07a5a5e8ddc82037791eec89cde965fcbb34ad942f6f6e83ad6b945c1b19d67f3552a11d5234b4d146bb6548ddcce1028cc403e3931bf2690edb6ca664b529f147546ba2472714e7da565cd65b605fa8c63670f8273d6cdccd6d68cd3aaed2b31537e68e03fa9a714e25abaa5495063791550473b0e302591249af671d34fca96bb570580341c4bbe354eac0d49c884d597b768e3dd0ac613eb4de1918043076423a0659467d6a27cbd1e9b36af0af4ebdf8ab66f0525b864cdecc7ffd051b14292399abff2ea947d43f67ea52f918c97f456cf551a772562ffdc3c1a69e51d47662add62b98f96c293deb611900e15cb4cd32c542b4dcd3fb74b86b860107461fc513292a862e1baf8d4d886cc8a38de5250ee0df338910086eda61ed71b20dbbc2ea2215f4de83cd0909b2018782c454165b61734d6a62097aa86c833ea83ddb0202201f8d3f6db442aa5b9fc8f511e33733cdc4105bac41a089f79f477b6d16eab14e2017214553bf024c8a12779ac8f2ab18a771c6fda2a32e4497cb9ad9aa85cd1d9d3d4d0904492cf15b9fce1fad21821976b996b1046a6c2a47af2f1b011fe7fe98f5c21fe16566405baa865a859416dd0fea83309acdfb48be864cddfb0567a4a04e6b921d88b23542fd0eca913ef5ea41448c743e033bb6c8bd7ee68cf610c8c118b2e62b06d74a8ebd84f494b3e18000260c087d7dba662862657d03115da55700c992163e8ac4ac0677ccd4ddb013910e64bb0ec26c4d0b10fc2fc0f32f54b7f98d9bf9f2df9778713cfae5a1af74380f5c089f42c2a76385f979fa899249e42e4552817e1333f10d2864a194e6069edd843077b607a9ae27e3b4ec6cd1a9d46905b3c82dbd15804f37629d5fc833f78f007b58f20561766c062a3e9f919560b6e385fa2a04014af8d576ebe020d6bf3909dde72174346bba7cad0f419289caf4b5a78ccb46b505c78c275ceac24c9288e290c3b78861525bd1c366f19dfd60b6dade33e1d89e2ccb8c0d4153939daea7deb0eb618f7d9080b9b92572fbf7989169248b96c9e8c796d197cbb33a29e277488c2d0f29003c30ceaceb4f18bdf7ce5af3841ba41d6a2387361ce318d944591429141ff1571f800065ca70a118384dd5ed7bdc1998e77f130e6f6962ed957baf8e842db91dbea612c444cb3e4de3c05c1cddfa4003a4415ec994390c02d07f4fb3759b3dccaa518e866293aeda8aafcf12257ab5fd04f32af299d07dfe94d8a9f2620cdfb7da421a91e4c19f072c3eb154f09d90631b3b7923f1a8b188ce76a11b6a9fcdc925bc4d13105c0e917c31ef33ce23092ceb95c3f675df2cff9ff1dc2ee011a096fbde4815135cc1a937266ab75f3e763e4d2f115de29ffa1bf613ae7d450719e1608f3f401bb7a613be93175893f7f6add200fb43e186b7e7946d02cc4472e408448ec89461711bacba747304c8d0b5836db2ac307f46d4f5b18c43f7188b2afcfaab16d2c55acf6209984745ac341b27ba2ee816f30ebbe1b6585deabc553e6368b8bb9e82952372385ce7e8198b76a750bd45b1371bbf7daa94c057e5c6d1855d6bdb404c1c56b0f2ceed9e9d90f80793b2b994d4d5ee1f8c330d93613f2ea8cbe5cf54065a3d8f990f61d0f366bacf02f8f14a45dc809c2fd07f7afdc9eda7e8dc4114491f303abccc22a352ef9ce6d3fe496c979757e2166da62535c71cf37b9dfe855c38dc4c7221c99c0863558dbff39793e9e5ec93a59d279b29c4b4361f22186cad0d70c7aee82b717eca7dbfeafbfae4ad88d8f1f3ff720974ad3fde16165b323557c901521cf36a7c177beab3fce4473aaf4b9f73276ff2ac9a8bce40419ad8d7657531ea593f7d50d459bd15dd8c180f4cdca9fcd255010386bbebadd07edf6598b2ba597d541ae8b822c2f37c296f42e651684c62b90beff18795eb0636102bdfb59b282f4596b9479c44dbaf4f6e3a5f3f97cf819c580d697317f78e4b97f1188879221e7bcdfebe98d6622304ed58067c8d3092d4b9fcc4e6c7ab511865054efaa2a3158995f6c9552bd9092d7a13b6df9ef0d1aba0458323a06fde15f0f0ace038620e017bc4d9f7b39a4d437b58cf09f96ba19b3238eec550e4ce3938a368b765ddf99c5188e06295611166db68057d9d40037c4951eb244e5ca44cea74a0961177056fb3daf789c7bd00ad4975f1aa5acfe0007216e7b89793891191cd2b269c334f8b03d6420f0f05741e43d3c1f73d79c2ba3665f7dee1940569747bddf7951071496164542bc4e4a06f1a5a524b52a20904dc5138959dbe9dfe80cd373dc85fc38ecfa01ae274dd7b237355773f852336b420a5c7014211762c9c3e0d8178fc3de2756387e601636af9abc1e502baeda567d863257461f8131d58f2b8c6dfc5e9dd4ef9c0311ae24e98ff7323905cdf5b0041396e25b00284a7335867ac8a3effcf1963a1f98d11445bc6529fa1ef790bb5654300a95a042eb912c8d3baee66af768bf5f168bf373fd535ea6b24aed2d8fb6e99be1fcf07dc03e2b065a2b2b63ec4164d33603f252b2500b1104f761387fa5768c9441cf96dc7ddcffa130480aba07b816a4123ef9e13e13c4c02d6418264d178a1f059d919703ced2d0e85046c649f249baf5cf69333f720168ab9015cfe2c8959ef5df19d982a22d58c97768d0519db911dbb62f1b7d0aea0035dd1618be2ba6a0c31d0f64bbe139fb3c847c28051bd10994db9f645dbec726858e1b93fdb351a1e7f826a2f336c76fac898023e6608792e9507cbbf8f5c700dac02faccf15cc76e4edfc6dbfb1a94a44006a7d75aca791fa60729191072ea6ddbfecf63ae1efc5b60c5172b6f358d97eb337dc0cfdb4749754b24c56760a59e63fcd1ffac6f067a593bb3fdd25981b40abfaf1349d486d5baa3469ba7723b9d5f795ccad47e8f742a3520cc27a27e410be3fadbd29a9aed21f38b8687c41e5b61f27c8720a44721942ccfe8115921746ebd3967d1959d6c318e79e3bf6242cbde0b2bcf6f9ee9bcc416f7f2de108950740c7a15353ab4f9beda7ffd34e835a3a96480f50753384303f72ec5086ee068e19a1b92f6f9a440b31df44574a25e1fb3d646941e3ffbc61efbdadbd60b0790f251fe76e3d4a4c36d56e573ca4ed9a3f273fecb5673fbef83bb0aeb4b84b06eea730bc70f8531400570ba1f5852710b5622b13691bce5b75bf52973b81d997f925f5947e1e3ff5dc8a1689f4914726ae5d8399c5e9bd4397cc2a538ad609a4db37ac1de7dfc729c9d68d5921bb1bcf4e26e46763d5184fee8cba8260c96d8c8e6919164ea6a5956010bb70a42975000e4a4310f57e5bcc9b5ae37d4379d0e429c7ca85b95af872dc53ff7c0051ccfa403a96ccea339ae7f93463d18a3e25fd4fa2431b0e42a1a7a8fd9fe0e16063d8bad5fe5ce6dd4d77f4273822f3d1701d5a2df96117739867277d987ca9acfc1cec6ac423c92577efc8ed64b59e19908b7b6516d2171e75f92ffac643a660c9462b66dcc5e495f0734d18c7ed551d60fbb94582c9854bf7f64be60552d50454587c474f55bef32dce91e32e438b652e4fe510ae64b9edc3aad012ce3a246fc660356b6d08f479114d767515b6287599257332af996a7f1e2d3f802899beded1b2ce4cef4fb82360905dccf7c36d5cdd81c2fc3ad9e2824ace66169aaaff65412b3a2b50e9268063a6224d4218b6a148429466223fdb6be4f9d4e0cb5af5d49d968db89f5978e2e3b36426652d7a21e5b37a46f706168a4d6efe7446cb479af9a77b67cc960917c03c5a8e9409608d73de415daad4f5cbc826795251502a3a2c5015f2e6432ff6e9a56fe357a027e354389ff5e94ba86400a509b374a504385dbed27be82eeee376b45226717c4731f77d2955cf9127dfa3e96676a4eea53f3feadc5dc72c8c6a44636d208eec756680a0b3e77fd68a67600761bb7fb40e32182b9540c4f166bc141cbc65e3d6d33895c1e5dddddbfe758fb574f851aa92fd24a5704cea302c5e250af273cd5ec567dc3de4101bbb20532881bf519b4d4f806cacc7b3b541d2c3b2a8e4707e175120d34d6f4bd9d25a9b7106abcf1fdad303081cbb9a19543b0e3d279fdc92c0fe9d6fdab1d6c031c85cb3c8ff58282c63bc629b03096aef20b62966ea977e93cdcf81a64c04e3a1bcbd7ed6c5c11a891a58d38ef11141d5c0bff17870e1196c9dfc6f996f3e092dfbf1d13b815731846033c6f0dc8f69f079c296b02dbf4fcbdea3a8d8b44569cd4861aa26903b7bbb83893125e3b67936c3e25978c2238a9adb7b7f560be5e946fe4f780efda5cc474f10854016fdeed26d22cae0d66dcf7c0a3271f6d3dff102700b46089cd151b169415482eabe33eea7c4e7be28a137503f51a22982c0673bcf3c990c4af558adcee7d6c4277d4266b90a1acc2d31fb48b8e6004af095507c4fe609ed96c5e215b7bd3f3faeb8240705e72bda4ce846b1a715c63ce9861b52cbae58e57488614ef6eb3f5b1e7eea3b6567d38fa2e7f70407a107e8d9a718197092943c46668e0110f14ba001dd47d3f1cbd3a7c928b47e8dde47467e0e7682dcd520bf747bb038acfc1a96cb6593af32bba76656167f7496e91fac8feb8c9f1293ec4853969d6197
package/dist/index.js CHANGED
@@ -29,16 +29,8 @@ export * from './components/general/modal';
29
29
  export * from './components/general/nerdjoke';
30
30
  export * from './components/general/recipe';
31
31
  export * from './components/general/resume';
32
- export * from './components/general/schema-blogposting';
33
- export * from './components/general/schema-blogposting.functions';
34
- export * from './components/general/schema-breadcrumb';
35
- export * from './components/general/schema-faq';
36
- export * from './components/general/schema-localbusiness';
37
- export * from './components/general/schema-product';
38
- export * from './components/general/schema-recipe';
39
- export * from './components/general/schema-review';
40
- export * from './components/general/schema-services';
41
- export * from './components/general/schema-website';
32
+ export * from './components/general/schema';
33
+ export * from './components/general/schema.functions';
42
34
  export * from './components/general/semantic';
43
35
  export * from './components/general/sidepanel';
44
36
  export * from './components/general/sitemap';
@@ -54,12 +46,11 @@ export * from './components/general/tiles';
54
46
  export * from './components/general/timeline';
55
47
  export * from './components/integrations/calendly';
56
48
  export * from './components/integrations/cloudinary';
57
- export * from './components/integrations/lipsum';
58
- export * from './components/integrations/loremipsum';
59
49
  export * from './components/integrations/contentful.delivery';
60
50
  export * from './components/integrations/contentful.items.components';
61
51
  export * from './components/integrations/contentful.management';
62
52
  export * from './components/integrations/flickr';
53
+ export * from './components/integrations/gemini-api.client';
63
54
  export * from './components/integrations/google.reviews.components';
64
55
  export * from './components/integrations/google.reviews.functions';
65
56
  export * from './components/integrations/googleanalytics';
@@ -70,8 +61,11 @@ export * from './components/integrations/gravatar.functions';
70
61
  export * from './components/integrations/hubspot.components';
71
62
  export * from './components/integrations/instagram.components';
72
63
  export * from './components/integrations/instagram.functions';
64
+ export * from './components/integrations/lipsum';
65
+ export * from './components/integrations/loremipsum';
73
66
  export * from './components/integrations/socialcard';
74
- export * from './components/integrations/gemini-api.client';
67
+ export * from './components/integrations/spotify.components';
68
+ export * from './components/integrations/spotify.functions';
75
69
  export * from './components/integrations/wordpress.components';
76
70
  export * from './components/integrations/wordpress.functions';
77
71
  export * from './components/integrations/yelp';
@@ -12,7 +12,7 @@ export * from './components/general/manifest';
12
12
  export * from './components/general/metadata.functions';
13
13
  export * from './components/general/proxy-handler';
14
14
  export * from './components/general/resume';
15
- export * from './components/general/schema-blogposting.functions';
15
+ export * from './components/general/schema.functions';
16
16
  export * from './components/general/sitemap';
17
17
  export * from './components/general/skeleton';
18
18
  export * from './components/general/well-known';
@@ -26,6 +26,8 @@ export * from './components/integrations/google.reviews.functions';
26
26
  export * from './components/integrations/gravatar.functions';
27
27
  export * from './components/integrations/instagram.functions';
28
28
  export * from './components/integrations/lipsum';
29
+ export * from './components/integrations/spotify.components';
30
+ export * from './components/integrations/spotify.functions';
29
31
  export * from './components/integrations/wordpress.functions';
30
32
  export * from './components/shoppingcart/ebay.functions';
31
33
  export * from './components/sitebuilder/config/ConfigEngine';
@@ -164,21 +164,15 @@ fi
164
164
  echo ""
165
165
  echo "📦 Step $((STEP_COUNT++)): Updating dependencies (all sections)..."
166
166
  echo "================================================="
167
- # iterate through prod/dev/optional sections, only bumping same-major versions
168
- for scope in "" dev optional; do
169
- flag=$([ "$scope" ] && echo "--$scope" || echo "")
170
- save=$([ "$scope" ] && echo "--save-$scope" || echo "--save")
171
- pkgs=$(npm outdated $flag --parseable --long | awk -F: '{ split($2,c,"@"); split($4,l,"@"); split(c[2],cv,"\\."); split(l[2],lv,"\\."); if(cv[1]==lv[1]) print $4 }')
172
- if [ -n "$pkgs" ]; then
173
- echo "Updating $scope packages: $pkgs"
174
- echo "$pkgs" | xargs npm install --force $save 2>/dev/null || true
175
- else
176
- echo "✅ No $scope updates needed"
177
- fi
178
- done
179
- # report peer deps separately
180
- peers=$(npm outdated --parseable --long --peer | awk -F: '{print $4}')
181
- printf "peer deps (manual): %s\n" "$peers"
167
+ if [ -f "src/scripts/update.sh" ]; then
168
+ bash src/scripts/update.sh
169
+ elif [ -f "scripts/update.sh" ]; then
170
+ bash scripts/update.sh
171
+ elif command -v npm &> /dev/null; then
172
+ npm run update 2>/dev/null || echo "⚠️ No update script found; skipping dependency update"
173
+ else
174
+ echo "⚠️ Could not find update.sh; skipping dependency update"
175
+ fi
182
176
 
183
177
 
184
178
 
@@ -4,15 +4,25 @@ set -euo pipefail
4
4
  # update.sh - refresh dependencies across all sections
5
5
  # usage: bash src/scripts/update.sh
6
6
 
7
- for type in "" --dev --optional --peer; do
7
+ # Dynamically build skip list from packages with pinned versions (no ^, ~, or *)
8
+ if command -v jq &> /dev/null; then
9
+ SKIP_PACKAGES=$(jq -r '.devDependencies // {} | to_entries[] | select(.value | test("^[0-9]")) | .key' package.json 2>/dev/null | paste -sd '|' - || echo "")
10
+ else
11
+ SKIP_PACKAGES=""
12
+ fi
13
+
14
+ for type in "" --dev --optional; do
8
15
  case $type in
9
16
  "") flag=""; installArgs="--save" ;;
10
- --dev) flag=--dev; installArgs="--save-dev" ;;
11
- --optional) flag=--optional; installArgs="--save-optional" ;;
12
- --peer) flag=--peer; installArgs="" ;;
17
+ --dev) flag="--include=dev"; installArgs="--save-dev" ;;
18
+ --optional) flag="--include=optional"; installArgs="--save-optional" ;;
13
19
  esac
14
20
 
15
- UPDATES=$(npm outdated $flag | awk 'NR>1 {print $1"@"$3}' || true)
21
+ if [ -n "$SKIP_PACKAGES" ]; then
22
+ UPDATES=$(npm outdated $flag | awk 'NR>1 {print $1"@"$4}' | grep -vE "^($SKIP_PACKAGES)@" || true)
23
+ else
24
+ UPDATES=$(npm outdated $flag | awk 'NR>1 {print $1"@"$4}' || true)
25
+ fi
16
26
  if [ -n "$UPDATES" ]; then
17
27
  echo "Updating $type packages: $UPDATES"
18
28
  if [ "$type" = "--peer" ]; then
@@ -26,8 +36,35 @@ for type in "" --dev --optional --peer; do
26
36
  fi
27
37
  done
28
38
 
29
- # print peer dependencies that need manual update
30
- peers=$(npm outdated --parseable --long --peer | awk -F: '{print $4}')
31
- printf "peer deps (manual): %s\n" "$peers"
39
+ # Handle peer dependencies
40
+ echo ""
41
+ echo "Checking peer dependencies for updates..."
42
+ if command -v jq &> /dev/null; then
43
+ peers=$(jq -r '.peerDependencies // {} | to_entries[] | "\(.key)=\(.value)"' package.json 2>/dev/null)
44
+ if [ -n "$peers" ]; then
45
+ while IFS='=' read -r pkgname current_constraint; do
46
+ if [ -n "$pkgname" ]; then
47
+ # Extract installed version from node_modules
48
+ installed=$(npm ls "$pkgname" --depth=0 2>/dev/null | grep "$pkgname" | sed 's/.*@\([0-9.]*\).*/\1/' | head -1)
49
+ # Get latest version
50
+ latest=$(npm view "$pkgname" version 2>/dev/null)
51
+ if [ -n "$latest" ] && [ -n "$installed" ]; then
52
+ # Only update if installed version is different from latest
53
+ if [ "$latest" != "$installed" ]; then
54
+ echo "📦 Updating peer dependency: $pkgname from $installed to $latest"
55
+ npm install "$pkgname@$latest" --save-peer 2>/dev/null || npm install "$pkgname@$latest" --save-dev 2>/dev/null || true
56
+ else
57
+ echo "✅ $pkgname is up to date ($latest)"
58
+ fi
59
+ fi
60
+ fi
61
+ done <<< "$peers"
62
+ else
63
+ echo "✅ No peer dependencies to update"
64
+ fi
65
+ else
66
+ echo "⚠️ jq not found - skipping peer dependency updates"
67
+ echo " Run 'npm ls --peer' to check peer dependencies manually"
68
+ fi
32
69
 
33
70
  npm audit fix 2>/dev/null || true