@flamingo-stack/openframe-frontend-core 0.0.533 → 0.0.534

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 (99) hide show
  1. package/dist/{chunk-XN4JKIJY.js → chunk-2ALT6CTY.js} +2 -2
  2. package/dist/{chunk-4ZRHVOEB.cjs → chunk-2YJ2CVRC.cjs} +31 -31
  3. package/dist/{chunk-4ZRHVOEB.cjs.map → chunk-2YJ2CVRC.cjs.map} +1 -1
  4. package/dist/{chunk-NAV4FRNL.cjs → chunk-67MWXMNT.cjs} +26 -26
  5. package/dist/{chunk-NAV4FRNL.cjs.map → chunk-67MWXMNT.cjs.map} +1 -1
  6. package/dist/{chunk-4QKXNWH5.js → chunk-BSE2UT6L.js} +2 -2
  7. package/dist/{chunk-2XGHEJZK.js → chunk-BUVD2OAI.js} +4 -4
  8. package/dist/{chunk-6W3ULZ4X.js → chunk-D62VYSTL.js} +6 -6
  9. package/dist/{chunk-J4BE4FIR.cjs → chunk-EBSZWSC5.cjs} +4 -4
  10. package/dist/{chunk-J4BE4FIR.cjs.map → chunk-EBSZWSC5.cjs.map} +1 -1
  11. package/dist/{chunk-U555TMPC.js → chunk-H4W4LENJ.js} +5 -5
  12. package/dist/{chunk-DFQLUK75.cjs → chunk-JELZAWSM.cjs} +3 -3
  13. package/dist/{chunk-DFQLUK75.cjs.map → chunk-JELZAWSM.cjs.map} +1 -1
  14. package/dist/{chunk-6YXN5RHW.js → chunk-KZ6PWFHK.js} +2 -2
  15. package/dist/{chunk-JDW2IL7A.cjs → chunk-LBZEPB4Y.cjs} +11 -11
  16. package/dist/{chunk-JDW2IL7A.cjs.map → chunk-LBZEPB4Y.cjs.map} +1 -1
  17. package/dist/{chunk-UPHN2VRZ.cjs → chunk-LYRGM25P.cjs} +750 -946
  18. package/dist/chunk-LYRGM25P.cjs.map +1 -0
  19. package/dist/{chunk-GNOK5J34.cjs → chunk-M5ODB6RQ.cjs} +37 -37
  20. package/dist/{chunk-GNOK5J34.cjs.map → chunk-M5ODB6RQ.cjs.map} +1 -1
  21. package/dist/{chunk-ENPGPZIB.cjs → chunk-MLILEBJU.cjs} +61 -61
  22. package/dist/{chunk-ENPGPZIB.cjs.map → chunk-MLILEBJU.cjs.map} +1 -1
  23. package/dist/{chunk-46FKXLNE.js → chunk-MTCU5MQN.js} +2 -2
  24. package/dist/{chunk-2MYDGLJS.cjs → chunk-NCUKKJRG.cjs} +87 -87
  25. package/dist/{chunk-2MYDGLJS.cjs.map → chunk-NCUKKJRG.cjs.map} +1 -1
  26. package/dist/{chunk-LIUARTOZ.js → chunk-O6VJZX2N.js} +56 -252
  27. package/dist/{chunk-LIUARTOZ.js.map → chunk-O6VJZX2N.js.map} +1 -1
  28. package/dist/{chunk-LE3BJ5H2.js → chunk-ONIYUMTO.js} +2 -2
  29. package/dist/{chunk-2TUOBFPK.js → chunk-POFCTXNH.js} +2 -2
  30. package/dist/{chunk-OLOKQQAP.cjs → chunk-RHKH4YUY.cjs} +5 -5
  31. package/dist/{chunk-OLOKQQAP.cjs.map → chunk-RHKH4YUY.cjs.map} +1 -1
  32. package/dist/{chunk-Z3NOI7X7.cjs → chunk-UMDGRL6A.cjs} +26 -26
  33. package/dist/{chunk-Z3NOI7X7.cjs.map → chunk-UMDGRL6A.cjs.map} +1 -1
  34. package/dist/{chunk-RKITTO5V.cjs → chunk-UWB33C6R.cjs} +14 -14
  35. package/dist/{chunk-RKITTO5V.cjs.map → chunk-UWB33C6R.cjs.map} +1 -1
  36. package/dist/{chunk-MVGL5NNJ.js → chunk-VYOGAQLM.js} +2 -2
  37. package/dist/{chunk-5U67WTAS.js → chunk-W4MXOBEW.js} +2 -2
  38. package/dist/{chunk-YLB6XXO6.js → chunk-WBYRBTAS.js} +2 -2
  39. package/dist/{chunk-KMB66NYX.cjs → chunk-YW2ZU7LC.cjs} +7 -7
  40. package/dist/{chunk-KMB66NYX.cjs.map → chunk-YW2ZU7LC.cjs.map} +1 -1
  41. package/dist/{chunk-QZ2NAPLF.cjs → chunk-ZKQXE2P4.cjs} +9 -9
  42. package/dist/{chunk-QZ2NAPLF.cjs.map → chunk-ZKQXE2P4.cjs.map} +1 -1
  43. package/dist/{chunk-6SMLYZLH.js → chunk-ZLLXYE2G.js} +4 -4
  44. package/dist/components/case-studies/index.cjs +8 -8
  45. package/dist/components/case-studies/index.js +2 -2
  46. package/dist/components/chat/index.cjs +2 -2
  47. package/dist/components/chat/index.js +1 -1
  48. package/dist/components/contact/index.cjs +3 -3
  49. package/dist/components/contact/index.js +2 -2
  50. package/dist/components/docs/index.cjs +5 -5
  51. package/dist/components/docs/index.js +4 -4
  52. package/dist/components/embeds/index.cjs +3 -3
  53. package/dist/components/embeds/index.js +2 -2
  54. package/dist/components/faq/index.cjs +3 -3
  55. package/dist/components/faq/index.js +2 -2
  56. package/dist/components/features/index.cjs +2 -2
  57. package/dist/components/features/index.js +1 -1
  58. package/dist/components/help-center-pages/index.cjs +22 -22
  59. package/dist/components/help-center-pages/index.js +13 -13
  60. package/dist/components/index.cjs +132 -132
  61. package/dist/components/index.js +11 -11
  62. package/dist/components/meeting-scheduler/index.cjs +34 -34
  63. package/dist/components/meeting-scheduler/index.js +3 -3
  64. package/dist/components/navigation/index.cjs +2 -2
  65. package/dist/components/navigation/index.js +1 -1
  66. package/dist/components/onboarding-guides/index.cjs +5 -5
  67. package/dist/components/onboarding-guides/index.js +4 -4
  68. package/dist/components/related-content/index.cjs +3 -3
  69. package/dist/components/related-content/index.js +2 -2
  70. package/dist/components/tickets/index.cjs +6 -6
  71. package/dist/components/tickets/index.js +5 -5
  72. package/dist/components/ui/index.cjs +2 -2
  73. package/dist/components/ui/index.js +1 -1
  74. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -1
  75. package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +1 -1
  76. package/dist/index.cjs +2 -2
  77. package/dist/index.js +1 -1
  78. package/dist/utils/social-embed-cache.d.ts +16 -16
  79. package/dist/utils/social-embed-cache.d.ts.map +1 -1
  80. package/package.json +1 -1
  81. package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +1 -5
  82. package/src/components/ui/markdown/rich/__tests__/shortcodes.test.ts +58 -0
  83. package/src/components/ui/markdown/rich/embed-overrides.tsx +13 -7
  84. package/src/components/ui/markdown/rich/shortcodes.ts +15 -0
  85. package/src/utils/social-embed-cache.ts +63 -336
  86. package/dist/chunk-UPHN2VRZ.cjs.map +0 -1
  87. /package/dist/{chunk-XN4JKIJY.js.map → chunk-2ALT6CTY.js.map} +0 -0
  88. /package/dist/{chunk-4QKXNWH5.js.map → chunk-BSE2UT6L.js.map} +0 -0
  89. /package/dist/{chunk-2XGHEJZK.js.map → chunk-BUVD2OAI.js.map} +0 -0
  90. /package/dist/{chunk-6W3ULZ4X.js.map → chunk-D62VYSTL.js.map} +0 -0
  91. /package/dist/{chunk-U555TMPC.js.map → chunk-H4W4LENJ.js.map} +0 -0
  92. /package/dist/{chunk-6YXN5RHW.js.map → chunk-KZ6PWFHK.js.map} +0 -0
  93. /package/dist/{chunk-46FKXLNE.js.map → chunk-MTCU5MQN.js.map} +0 -0
  94. /package/dist/{chunk-LE3BJ5H2.js.map → chunk-ONIYUMTO.js.map} +0 -0
  95. /package/dist/{chunk-2TUOBFPK.js.map → chunk-POFCTXNH.js.map} +0 -0
  96. /package/dist/{chunk-MVGL5NNJ.js.map → chunk-VYOGAQLM.js.map} +0 -0
  97. /package/dist/{chunk-5U67WTAS.js.map → chunk-W4MXOBEW.js.map} +0 -0
  98. /package/dist/{chunk-YLB6XXO6.js.map → chunk-WBYRBTAS.js.map} +0 -0
  99. /package/dist/{chunk-6SMLYZLH.js.map → chunk-ZLLXYE2G.js.map} +0 -0
@@ -23109,9 +23109,8 @@ function useRichMarkdownRuntime() {
23109
23109
  import { useState as useState50, useEffect as useEffect41, useRef as useRef33 } from "react";
23110
23110
 
23111
23111
  // src/utils/social-embed-cache.ts
23112
- var cachingRequests = /* @__PURE__ */ new Map();
23113
23112
  var dataCache = /* @__PURE__ */ new Map();
23114
- var refreshTimestamps = /* @__PURE__ */ new Map();
23113
+ var inflightRequests = /* @__PURE__ */ new Map();
23115
23114
  var SocialEmbedCache = class _SocialEmbedCache {
23116
23115
  static getInstance() {
23117
23116
  if (!_SocialEmbedCache.instance) {
@@ -23119,269 +23118,64 @@ var SocialEmbedCache = class _SocialEmbedCache {
23119
23118
  }
23120
23119
  return _SocialEmbedCache.instance;
23121
23120
  }
23122
- // Check if data exists in memory cache
23123
23121
  getFromMemory(url) {
23124
23122
  return dataCache.get(url) || null;
23125
23123
  }
23126
- // Store data in memory cache
23127
23124
  setInMemory(url, data) {
23128
23125
  dataCache.set(url, data);
23129
23126
  }
23130
- // Check server cache (cache-only mode)
23131
- async getFromServer(options) {
23132
- try {
23133
- console.log(`\u{1F50D} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Checking server cache for: ${options.url}`);
23134
- const response = await fetch(`${options.apiEndpoint}?url=${encodeURIComponent(options.url)}&cache-only=true`);
23135
- if (response.ok) {
23136
- const data = await response.json();
23137
- console.log(`\u2705 [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Server cache hit: ${options.url}`);
23138
- return data;
23139
- } else if (response.status === 404) {
23140
- console.log(`\u{1F4A8} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] No server cache available for: ${options.url}`);
23141
- return null;
23142
- }
23143
- } catch (error) {
23144
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Server cache check failed for: ${options.url}`, error);
23145
- }
23146
- return null;
23147
- }
23148
- // Helper method to update server cache asynchronously
23149
- async updateServerCache(apiEndpoint, url, data) {
23150
- try {
23151
- console.log(`\u{1F4BE} [Cache] Updating server cache for: ${url}`);
23152
- await fetch(`${apiEndpoint}?url=${encodeURIComponent(url)}`, {
23153
- method: "POST",
23154
- headers: { "Content-Type": "application/json" },
23155
- body: JSON.stringify(data)
23156
- });
23157
- console.log(`\u2705 [Cache] Server cache updated for: ${url}`);
23158
- } catch (error) {
23159
- console.log(`\u274C [Cache] Server cache update failed for: ${url}`, error);
23160
- }
23161
- }
23162
- // Store data in server cache (with deduplication)
23163
- async setInServer(options, data) {
23164
- const cacheKey = `${options.platform}-${options.url}`;
23165
- if (cachingRequests.has(cacheKey)) {
23166
- console.log(`\u23ED\uFE0F [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Server cache update skipped (already in progress): ${options.url}`);
23167
- return;
23168
- }
23169
- console.log(`\u{1F4BE} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Updating server cache for: ${options.url}`);
23170
- const cachePromise = fetch(`${options.apiEndpoint}?url=${encodeURIComponent(options.url)}`, {
23171
- method: "POST",
23172
- headers: { "Content-Type": "application/json" },
23173
- body: JSON.stringify(data)
23174
- }).then(() => {
23175
- console.log(`\u2705 [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Server cache updated successfully: ${options.url}`);
23176
- cachingRequests.delete(cacheKey);
23177
- }).catch((error) => {
23178
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Cache] Server cache update failed: ${options.url}`, error);
23179
- cachingRequests.delete(cacheKey);
23180
- });
23181
- cachingRequests.set(cacheKey, cachePromise);
23182
- await cachePromise;
23183
- }
23184
- // Direct fetch with platform-specific logic
23185
- async fetchDirect(options) {
23186
- try {
23187
- console.log(`\u{1F504} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Direct] Fetching content: ${options.url}`);
23188
- const result = await options.directFetcher();
23189
- console.log(`\u2705 [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Direct] Fetch successful: ${options.url}`);
23190
- return result;
23191
- } catch (error) {
23192
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Direct] Fetch failed: ${options.url}`, error);
23193
- return null;
23194
- }
23195
- }
23196
- // Unified cache hierarchy: Memory → Server → Direct
23127
+ /**
23128
+ * Memory → proxy. Kept the historical name so the embed clients'
23129
+ * call sites are unchanged.
23130
+ */
23197
23131
  async fetchWithHierarchy(options) {
23198
- const { url, platform, onDataUpdate, onError, onLoading, dataValidator } = options;
23199
- const platformName = platform.charAt(0).toUpperCase() + platform.slice(1);
23200
- this.scheduleAsyncRefresh(platform, url, dataValidator, options.apiEndpoint);
23201
- console.log(`\u{1F50D} [${platformName} Cache] Checking memory cache for: ${url}`);
23132
+ const { url, platform, apiEndpoint, dataValidator, onDataUpdate, onError, onLoading } = options;
23202
23133
  const memoryData = this.getFromMemory(url);
23203
23134
  if (memoryData && dataValidator(memoryData)) {
23204
- console.log(`\u{1F48E} [${platformName} Cache] Memory cache hit for: ${url}`);
23205
23135
  onDataUpdate(memoryData);
23206
23136
  onLoading(false);
23207
23137
  return;
23208
23138
  }
23209
- console.log(`\u{1F50D} [${platformName} Cache] No memory cache, checking server cache for: ${url}`);
23210
- const serverCacheData = await this.getFromServer(options);
23211
- if (serverCacheData && dataValidator(serverCacheData)) {
23212
- console.log(`\u{1F3AF} [${platformName} Cache] Server cache hit (cached data) for: ${url}`);
23213
- onDataUpdate(serverCacheData);
23214
- this.setInMemory(url, serverCacheData);
23215
- onLoading(false);
23216
- return;
23217
- }
23218
- console.log(`\u{1F50D} [${platformName} Cache] No server cache, attempting direct fetch for: ${url}`);
23219
- if (platform === "reddit") {
23220
- try {
23221
- const directResponse = await fetch(url, {
23222
- method: "GET",
23223
- headers: {
23224
- "Accept": "application/json"
23225
- },
23226
- signal: AbortSignal.timeout(1e4)
23227
- });
23228
- if (directResponse.ok) {
23229
- const directData = await directResponse.json();
23230
- if (directData && dataValidator(directData)) {
23231
- console.log(`\u2705 [${platformName} Direct] Browser direct fetch successful for: ${url}`);
23232
- onDataUpdate(directData);
23233
- this.setInMemory(url, directData);
23234
- onLoading(false);
23235
- setTimeout(() => {
23236
- this.updateServerCache(options.apiEndpoint, url, directData);
23237
- }, 0);
23238
- return;
23239
- }
23240
- }
23241
- console.log(`\u{1F4A8} [${platformName} Direct] Browser direct fetch failed (${directResponse.status}), trying server proxy...`);
23242
- } catch (directError) {
23243
- console.log(`\u{1F4A8} [${platformName} Direct] Browser direct fetch failed, trying server proxy...`, directError);
23244
- }
23245
- }
23246
- console.log(`\u{1F50D} [${platformName} Cache] Trying server proxy for: ${url}`);
23247
23139
  try {
23248
- const response = await fetch(`${options.apiEndpoint}?url=${encodeURIComponent(url)}`);
23249
- if (response.ok) {
23250
- const serverData = await response.json();
23251
- if (serverData && dataValidator(serverData)) {
23252
- const cacheStatus = response.headers.get("x-cache") || "UNKNOWN";
23253
- if (cacheStatus === "HIT") {
23254
- console.log(`\u{1F3AF} [${platformName} Proxy] Server cache hit (cached data) for: ${url}`);
23255
- } else if (cacheStatus === "MISS-FETCHED") {
23256
- console.log(`\u{1F504} [${platformName} Proxy] Server processed fresh fetch (now cached) for: ${url}`);
23257
- } else {
23258
- console.log(`\u2705 [${platformName} Proxy] Server returned data (${cacheStatus}) for: ${url}`);
23259
- }
23260
- onDataUpdate(serverData);
23261
- this.setInMemory(url, serverData);
23262
- onLoading(false);
23263
- return;
23264
- } else {
23265
- console.log(`\u26A0\uFE0F [${platformName} Proxy] Server returned data but validation failed for: ${url}`);
23266
- throw new Error("Server proxy returned invalid data shape");
23267
- }
23268
- } else {
23269
- let errorData = null;
23270
- try {
23271
- errorData = await response.json();
23272
- } catch {
23273
- }
23274
- if (response.status === 404 && errorData?.error && errorData?.message) {
23275
- console.log(`\u{1F6AB} [${platformName} Proxy] Content unavailable: ${errorData.message}`);
23276
- onError(errorData.message);
23277
- onLoading(false);
23278
- return;
23279
- }
23280
- if (errorData?.error) {
23281
- throw new Error(`Server error: ${errorData.error}`);
23282
- }
23283
- throw new Error(`Server proxy failed: ${response.status}`);
23140
+ const data = await this.fetchFromProxy(url, apiEndpoint, dataValidator);
23141
+ if (data) {
23142
+ this.setInMemory(url, data);
23143
+ onDataUpdate(data);
23144
+ onLoading(false);
23145
+ return;
23284
23146
  }
23147
+ onError(`This ${platform === "reddit" ? "Reddit post" : "tweet"} could not be loaded.`);
23285
23148
  } catch (error) {
23286
- console.log(`\u274C [${platformName} Cache] All fetch attempts failed for: ${url}`, error);
23149
+ console.log(`\u274C [${platform} embed] Proxy fetch failed for: ${url}`, error);
23287
23150
  onError(`Unable to load ${platform} content`);
23288
- onLoading(false);
23289
23151
  }
23152
+ onLoading(false);
23290
23153
  }
23291
- // Schedule async background refresh (runs once, 1 second after load)
23292
- //
23293
- // The hub's old version hard-coded `/api/blog/{reddit,twitter}-proxy`. We
23294
- // now require `apiEndpoint` so embedders can route through their own
23295
- // reverse proxy (e.g. `/content/api/blog/...`).
23296
- scheduleAsyncRefresh(platform, url, dataValidator, apiEndpoint) {
23297
- setTimeout(() => {
23298
- const platformName = platform.charAt(0).toUpperCase() + platform.slice(1);
23299
- console.log(`\u{1F504} [${platformName} Async] Background refresh starting for: ${url}`);
23300
- fetch(`${apiEndpoint}?url=${encodeURIComponent(url)}`).then((response) => {
23301
- if (response.ok) {
23302
- return response.json();
23303
- } else {
23304
- console.log(`\u274C [${platformName} Async] Background refresh failed (${response.status}) for: ${url}`);
23305
- return null;
23306
- }
23307
- }).then((data) => {
23308
- if (data && dataValidator(data)) {
23309
- this.setInMemory(url, data);
23310
- console.log(`\u2705 [${platformName} Async] Background refresh completed for: ${url}`);
23311
- } else if (data) {
23312
- console.log(`\u274C [${platformName} Async] Background refresh failed (invalid data) for: ${url}`);
23313
- }
23314
- }).catch((error) => console.log(`\u274C [${platformName} Async] Background refresh failed for: ${url}`, error));
23315
- }, 1e3);
23316
- }
23317
- // Background refresh to keep cache fresh (with request deduplication)
23318
- async backgroundRefresh(options, currentData) {
23319
- const refreshKey = `refresh-${options.platform}-${options.url}`;
23320
- const now = Date.now();
23321
- const lastRefresh = refreshTimestamps.get(refreshKey);
23322
- if (lastRefresh && now - lastRefresh < 3e4) {
23323
- console.log(`\u23ED\uFE0F [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Refresh skipped (recent refresh): ${options.url}`);
23324
- return;
23325
- }
23326
- if (cachingRequests.has(refreshKey)) {
23327
- console.log(`\u23ED\uFE0F [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Refresh skipped (already in progress): ${options.url}`);
23328
- return;
23329
- }
23330
- const refreshPromise = (async () => {
23331
- try {
23332
- console.log(`\u{1F504} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Starting background refresh for: ${options.url}`);
23333
- refreshTimestamps.set(refreshKey, now);
23334
- const freshData = await this.fetchDirect(options);
23335
- if (freshData && options.dataValidator(freshData)) {
23336
- this.setInMemory(options.url, freshData);
23337
- await this.setInServer(options, freshData);
23338
- console.log(`\u2705 [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Background refresh completed for: ${options.url}`);
23339
- } else {
23340
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Background refresh failed (invalid data) for: ${options.url}`);
23341
- }
23342
- } catch (error) {
23343
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Background] Background refresh failed for: ${options.url}`, error);
23344
- } finally {
23345
- cachingRequests.delete(refreshKey);
23154
+ /**
23155
+ * Returns the validated payload, `null` for a structured "content
23156
+ * unavailable" 404, and throws for everything else. Concurrent calls for
23157
+ * the same URL share one request.
23158
+ */
23159
+ fetchFromProxy(url, apiEndpoint, dataValidator) {
23160
+ const inflight = inflightRequests.get(url);
23161
+ if (inflight) return inflight;
23162
+ const request = (async () => {
23163
+ const response = await fetch(`${apiEndpoint}?url=${encodeURIComponent(url)}`, {
23164
+ signal: AbortSignal.timeout(15e3)
23165
+ });
23166
+ if (response.ok) {
23167
+ const data = await response.json();
23168
+ if (data && dataValidator(data)) return data;
23169
+ throw new Error("Server proxy returned invalid data shape");
23346
23170
  }
23171
+ if (response.status === 404) return null;
23172
+ throw new Error(`Server proxy failed: ${response.status}`);
23347
23173
  })();
23348
- cachingRequests.set(refreshKey, refreshPromise);
23349
- await refreshPromise;
23350
- }
23351
- // Silent background refresh for UI-sensitive components
23352
- silentBackgroundRefresh(options) {
23353
- const refreshKey = `silent-refresh-${options.platform}-${options.url}`;
23354
- const now = Date.now();
23355
- const lastRefresh = refreshTimestamps.get(refreshKey);
23356
- if (lastRefresh && now - lastRefresh < 3e5) {
23357
- console.log(`\u23ED\uFE0F [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Silent refresh skipped (recent refresh): ${options.url}`);
23358
- return;
23359
- }
23360
- if (cachingRequests.has(refreshKey)) {
23361
- console.log(`\u23ED\uFE0F [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Silent refresh skipped (already in progress): ${options.url}`);
23362
- return;
23363
- }
23364
- setTimeout(() => {
23365
- const refreshPromise = (async () => {
23366
- try {
23367
- console.log(`\u{1F504} [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Starting silent background refresh for: ${options.url}`);
23368
- refreshTimestamps.set(refreshKey, now);
23369
- const freshData = await this.fetchDirect(options);
23370
- if (freshData && options.dataValidator(freshData)) {
23371
- this.setInMemory(options.url, freshData);
23372
- await this.setInServer(options, freshData);
23373
- console.log(`\u2705 [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Silent refresh completed for: ${options.url}`);
23374
- } else {
23375
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Silent refresh failed (invalid data) for: ${options.url}`);
23376
- }
23377
- } catch (error) {
23378
- console.log(`\u274C [${options.platform.charAt(0).toUpperCase() + options.platform.slice(1)} Silent] Silent refresh failed for: ${options.url}`, error);
23379
- } finally {
23380
- cachingRequests.delete(refreshKey);
23381
- }
23382
- })();
23383
- cachingRequests.set(refreshKey, refreshPromise);
23384
- }, 0);
23174
+ inflightRequests.set(
23175
+ url,
23176
+ request.finally(() => inflightRequests.delete(url))
23177
+ );
23178
+ return inflightRequests.get(url);
23385
23179
  }
23386
23180
  };
23387
23181
  var socialCache = SocialEmbedCache.getInstance();
@@ -25019,13 +24813,15 @@ function buildRichEmbedOverrides({
25019
24813
  }
25020
24814
  return standard.div(divProps);
25021
24815
  },
25022
- // Reddit's OWN embed markup lives in 58 published blog posts as
25023
- // `<blockquote class="reddit-embed-bq">…<a href="post-url">` paired with
25024
- // a `<script src="embed.reddit.com/widgets.js">` loader. The sanitize
25025
- // stack strips the script (correctly), so the composition rehydrates the
25026
- // blockquote itself: extract the post URL from the first reddit link and
25027
- // render the RedditEmbedClient SSOT. Non-reddit blockquotes fall through
25028
- // to the engine's base blockquote.
24816
+ // Pasted-from-the-platform embed markup lives in published blog posts as
24817
+ // `<blockquote class="reddit-embed-bq">…<a href="post-url">` (58 blocks
24818
+ // across 9 posts) and Twitter's equivalent is
24819
+ // `<blockquote class="twitter-tweet">…<a href="status-url">`. Each pair
24820
+ // ships a `widgets.js` loader script, which `processShortcodes` strips
24821
+ // from the source text (Step 1.5). The composition rehydrates the
24822
+ // blockquote itself: extract the post URL from the first matching link
24823
+ // and render the platform's embed-client SSOT. Other blockquotes fall
24824
+ // through to the engine's base blockquote.
25029
24825
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
25030
24826
  blockquote: (bqProps) => {
25031
24827
  const { node, className } = bqProps;
@@ -25034,6 +24830,10 @@ function buildRichEmbedOverrides({
25034
24830
  const postUrl = findFirstHref(node, /reddit\.com/);
25035
24831
  if (postUrl) return /* @__PURE__ */ jsx169(RedditEmbedClient, { url: postUrl });
25036
24832
  }
24833
+ if (classNames.includes("twitter-tweet")) {
24834
+ const tweetUrl = findFirstHref(node, /(?:twitter\.com|x\.com)\/[^/]+\/status\//);
24835
+ if (tweetUrl) return /* @__PURE__ */ jsx169(TwitterEmbedClient, { url: tweetUrl });
24836
+ }
25037
24837
  return standard.blockquote(bqProps);
25038
24838
  },
25039
24839
  // In-article images: MarkdownImage reads `transformImageSrc` from the
@@ -25120,6 +24920,10 @@ var processShortcodes = (content) => {
25120
24920
  codeBlocks.push(match2);
25121
24921
  return placeholder;
25122
24922
  });
24923
+ processedContent = processedContent.replace(
24924
+ /<script\b[^>]{0,2000}>[\s\S]{0,20000}?<\/script\s{0,10}>/gi,
24925
+ ""
24926
+ );
25123
24927
  const markdownLinks = [];
25124
24928
  processedContent = processedContent.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match2) => {
25125
24929
  const placeholder = `__MARKDOWN_LINK_${markdownLinks.length}__`;
@@ -62267,4 +62071,4 @@ export {
62267
62071
  LogsList,
62268
62072
  assets
62269
62073
  };
62270
- //# sourceMappingURL=chunk-LIUARTOZ.js.map
62074
+ //# sourceMappingURL=chunk-O6VJZX2N.js.map