@flamingo-stack/openframe-frontend-core 0.0.744 → 0.0.746

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 (118) hide show
  1. package/dist/build/export-map.json +1 -1
  2. package/dist/{chunk-LJ46XYYP.cjs → chunk-2ZVNXD74.cjs} +24 -24
  3. package/dist/{chunk-FTYQS6VI.cjs → chunk-3AUTORMB.cjs} +13 -13
  4. package/dist/{chunk-2JRCJV3M.cjs → chunk-3KVB5FQZ.cjs} +5 -5
  5. package/dist/{chunk-2UBR53AN.cjs → chunk-3OAACQQG.cjs} +4 -4
  6. package/dist/{chunk-QSO56JZ2.cjs → chunk-5X3F2KL7.cjs} +90 -90
  7. package/dist/{chunk-AT6ZI4CO.cjs → chunk-7AKFKPBV.cjs} +12 -12
  8. package/dist/{chunk-4N7KGOBS.cjs → chunk-B24U6KNJ.cjs} +3 -3
  9. package/dist/{chunk-H62FNZGG.cjs → chunk-DJ4YDVBF.cjs} +18 -18
  10. package/dist/{chunk-QZYF2YQ3.cjs → chunk-FAN73OTP.cjs} +6 -6
  11. package/dist/{chunk-HJ4KGA2M.cjs → chunk-GPSHFEF2.cjs} +1084 -890
  12. package/dist/{chunk-OC2LBQQJ.cjs → chunk-GSFANY2L.cjs} +80 -80
  13. package/dist/{chunk-URVIPSAJ.cjs → chunk-HNLI4OU5.cjs} +14 -14
  14. package/dist/{chunk-PYWHDPVC.cjs → chunk-IRKUFXVV.cjs} +38 -38
  15. package/dist/{chunk-ABLUMGCI.cjs → chunk-JHQNUWFM.cjs} +83 -33
  16. package/dist/{chunk-4A6OF4HI.cjs → chunk-KVPSV4ZI.cjs} +44 -44
  17. package/dist/{chunk-UY6A6TEY.cjs → chunk-L2IQESTQ.cjs} +2 -2
  18. package/dist/{chunk-YIOWV7LS.cjs → chunk-NZMQIAQC.cjs} +2 -2
  19. package/dist/{chunk-YJRMCFX3.cjs → chunk-O4J4NIMB.cjs} +7 -7
  20. package/dist/{chunk-GAGNKWOC.cjs → chunk-OWABNVDV.cjs} +2 -2
  21. package/dist/{chunk-HTQJYN47.cjs → chunk-PLBJ3XVC.cjs} +32 -32
  22. package/dist/{chunk-OWGLRE74.cjs → chunk-PSIKUDUV.cjs} +8 -8
  23. package/dist/{chunk-NURAL5HD.cjs → chunk-SDDZHPVK.cjs} +24 -24
  24. package/dist/{chunk-HHL23RFC.cjs → chunk-SLODGX6D.cjs} +35 -35
  25. package/dist/{chunk-7YDF3QBN.cjs → chunk-TILK7SC4.cjs} +320 -207
  26. package/dist/{chunk-U2O5YQRP.cjs → chunk-U6XWGK53.cjs} +33 -33
  27. package/dist/{chunk-JGZEHBBD.cjs → chunk-VZGCSVH7.cjs} +10 -10
  28. package/dist/{chunk-35IQLGV3.cjs → chunk-X4Y74M5K.cjs} +74 -74
  29. package/dist/{chunk-HMSUYWSB.cjs → chunk-XQJOYPPN.cjs} +4 -4
  30. package/dist/{chunk-65LJNDR2.cjs → chunk-YKF66VQY.cjs} +20 -20
  31. package/dist/{chunk-5TCIRWHL.cjs → chunk-YRULLK7N.cjs} +5 -5
  32. package/dist/{cloud-tenants-JPXAXSPE.cjs → cloud-tenants-OKUFSNPW.cjs} +13 -13
  33. package/dist/components/case-studies/index.cjs +25 -25
  34. package/dist/components/chat/index.cjs +9 -9
  35. package/dist/components/contact/index.cjs +14 -14
  36. package/dist/components/docs/index.cjs +17 -17
  37. package/dist/components/embeds/index.cjs +14 -14
  38. package/dist/components/embeds/reddit-embed-client.d.ts +3 -1
  39. package/dist/components/embeds/reddit-embed-client.d.ts.map +1 -1
  40. package/dist/components/embeds/reddit-embed-client.js +5 -3
  41. package/dist/components/embeds/twitter-embed-client.d.ts +3 -1
  42. package/dist/components/embeds/twitter-embed-client.d.ts.map +1 -1
  43. package/dist/components/embeds/twitter-embed-client.js +5 -3
  44. package/dist/components/faq/index.cjs +15 -15
  45. package/dist/components/features/index.cjs +13 -13
  46. package/dist/components/help-center-pages/index.cjs +116 -116
  47. package/dist/components/index.cjs +123 -125
  48. package/dist/components/meeting-scheduler/index.cjs +63 -63
  49. package/dist/components/navigation/index.cjs +16 -16
  50. package/dist/components/onboarding-guides/index.cjs +16 -16
  51. package/dist/components/product-demo/index.cjs +9 -9
  52. package/dist/components/related-content/index.cjs +7 -7
  53. package/dist/components/tickets/index.cjs +19 -19
  54. package/dist/components/ui/filter-checkbox-item.d.ts +8 -2
  55. package/dist/components/ui/filter-checkbox-item.d.ts.map +1 -1
  56. package/dist/components/ui/filter-checkbox-item.js +14 -4
  57. package/dist/components/ui/index.cjs +17 -13
  58. package/dist/components/ui/index.d.ts +1 -0
  59. package/dist/components/ui/index.d.ts.map +1 -1
  60. package/dist/components/ui/index.js +1 -0
  61. package/dist/components/ui/markdown/base-components.d.ts.map +1 -1
  62. package/dist/components/ui/markdown/base-components.js +3 -2
  63. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -1
  64. package/dist/components/ui/markdown/rich/embed-overrides.js +11 -8
  65. package/dist/components/ui/markdown-editor.d.ts.map +1 -1
  66. package/dist/components/ui/markdown-editor.js +4 -0
  67. package/dist/components/ui/markdown-link-command.d.ts +37 -0
  68. package/dist/components/ui/markdown-link-command.d.ts.map +1 -0
  69. package/dist/components/ui/markdown-link-command.js +180 -0
  70. package/dist/components/unified-filter-logic.js +1 -1
  71. package/dist/components/vendor-tag.d.ts +12 -0
  72. package/dist/components/vendor-tag.d.ts.map +1 -1
  73. package/dist/components/vendor-tag.js +50 -47
  74. package/dist/{devices-ONC4JOVH.cjs → devices-URCDMYFU.cjs} +14 -14
  75. package/dist/{embeddable-chat-7ZEGCDVF.cjs → embeddable-chat-B35GB5B6.cjs} +80 -80
  76. package/dist/index.cjs +36 -18
  77. package/dist/{knowledge-G7XU5YST.cjs → knowledge-5MW2PREQ.cjs} +14 -14
  78. package/dist/{logs-5B7NY4G6.cjs → logs-LJJK5CK4.cjs} +21 -21
  79. package/dist/{policies-OYR3SLJN.cjs → policies-6TCEWQYG.cjs} +17 -17
  80. package/dist/{remote-session-N4PJB5FW.cjs → remote-session-IYT4LWJC.cjs} +7 -7
  81. package/dist/{scripts-6CWHTY6U.cjs → scripts-ABB2P6PT.cjs} +20 -20
  82. package/dist/{software-update-AJPIY4SQ.cjs → software-update-4427ZRMO.cjs} +17 -17
  83. package/dist/{tickets-board-O753S4ZB.cjs → tickets-board-4MT6ZB4F.cjs} +8 -8
  84. package/dist/utils/format.d.ts.map +1 -1
  85. package/dist/utils/format.js +2 -3
  86. package/dist/utils/index.cjs +193 -28
  87. package/dist/utils/index.d.ts +2 -1
  88. package/dist/utils/index.d.ts.map +1 -1
  89. package/dist/utils/index.js +9 -6
  90. package/dist/utils/markdown-link.d.ts +44 -0
  91. package/dist/utils/markdown-link.d.ts.map +1 -0
  92. package/dist/utils/markdown-link.js +83 -0
  93. package/dist/utils/markdown-to-plain.d.ts +3 -16
  94. package/dist/utils/markdown-to-plain.d.ts.map +1 -1
  95. package/dist/utils/markdown-to-plain.js +33 -3
  96. package/dist/utils/vendor-classification.d.ts +43 -17
  97. package/dist/utils/vendor-classification.d.ts.map +1 -1
  98. package/dist/utils/vendor-classification.js +73 -22
  99. package/package.json +3 -1
  100. package/src/components/embeds/reddit-embed-client.tsx +7 -3
  101. package/src/components/embeds/twitter-embed-client.tsx +7 -3
  102. package/src/components/ui/filter-checkbox-item.tsx +21 -5
  103. package/src/components/ui/index.ts +1 -0
  104. package/src/components/ui/markdown/base-components.tsx +5 -2
  105. package/src/components/ui/markdown/rich/embed-overrides.tsx +12 -9
  106. package/src/components/ui/markdown-editor.tsx +6 -0
  107. package/src/components/ui/markdown-link-command.tsx +252 -0
  108. package/src/components/unified-filter-logic.tsx +1 -1
  109. package/src/components/vendor-tag.tsx +73 -69
  110. package/src/utils/format.ts +2 -3
  111. package/src/utils/index.ts +8 -5
  112. package/src/utils/markdown-link.ts +148 -0
  113. package/src/utils/markdown-to-plain.ts +64 -22
  114. package/src/utils/vendor-classification.ts +113 -34
  115. package/dist/utils/format-text-stub.d.ts +0 -5
  116. package/dist/utils/format-text-stub.d.ts.map +0 -1
  117. package/dist/utils/format-text-stub.js +0 -20
  118. package/src/utils/format-text-stub.ts +0 -17
@@ -6,10 +6,21 @@ var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var libphonenumberJs = require('libphonenumber-js');
8
8
  var lucideReact = require('lucide-react');
9
+ var hastUtilToText = require('hast-util-to-text');
10
+ var rehypeRaw = require('rehype-raw');
11
+ var remark = require('remark');
12
+ var remarkBreaks = require('remark-breaks');
13
+ var remarkGfm = require('remark-gfm');
14
+ var remarkRehype = require('remark-rehype');
15
+ var unistUtilVisit = require('unist-util-visit');
9
16
 
10
17
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
18
 
12
19
  var React__default = /*#__PURE__*/_interopDefault(React);
20
+ var rehypeRaw__default = /*#__PURE__*/_interopDefault(rehypeRaw);
21
+ var remarkBreaks__default = /*#__PURE__*/_interopDefault(remarkBreaks);
22
+ var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
23
+ var remarkRehype__default = /*#__PURE__*/_interopDefault(remarkRehype);
13
24
 
14
25
  var __defProp = Object.defineProperty;
15
26
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -80131,35 +80142,85 @@ if (_orderIdx("flamingo") > _orderIdx("universal") || getPlatformByHostname("fla
80131
80142
  }
80132
80143
 
80133
80144
  // src/utils/vendor-classification.ts
80134
- var VENDOR_CLASSIFICATIONS = [
80135
- "open_source",
80136
- "commercial",
80137
- "openframe_selected",
80138
- "openframe_shipped",
80139
- "openframe_connect"
80140
- ];
80141
- var OPENFRAME_CLASSIFICATIONS = {
80145
+ var VENDOR_CLASSIFICATION_COPY = {
80142
80146
  openframe_selected: {
80143
- word: "Selected",
80144
80147
  label: "OpenFrame Selected",
80145
- description: "OpenFrame is a unified platform that integrates multiple open-source IT and security tools into a single dashboard for MSPs. This filter shows vendors selected by our team for their excellence, community support, and MSP-specific value."
80148
+ word: "Selected",
80149
+ description: "OpenFrame is a unified platform that integrates multiple open-source IT and security tools into a single dashboard for MSPs. This filter shows vendors selected by our team for their excellence, community support, and MSP-specific value.",
80150
+ group: "openframe",
80151
+ icon: { name: "openframe-logo", tone: "accent" }
80152
+ },
80153
+ openframe_connect: {
80154
+ label: "OpenFrame Connect",
80155
+ word: "Connect",
80156
+ description: "Services OpenFrame connects to and manages for every client, such as Microsoft 365 and Google Workspace, beside devices and tickets.",
80157
+ group: "openframe",
80158
+ icon: { name: "openframe-logo", tone: "accent" }
80146
80159
  },
80147
80160
  openframe_shipped: {
80148
- word: "Shipped",
80149
80161
  label: "OpenFrame Shipped",
80150
- description: "Tools and OpenFrame products that are in the released OpenFrame product today, not on the roadmap."
80162
+ word: "Shipped",
80163
+ description: "Tools and OpenFrame products that are in the released OpenFrame product today, not on the roadmap.",
80164
+ group: "openframe",
80165
+ icon: { name: "openframe-logo", tone: "accent" }
80151
80166
  },
80152
- openframe_connect: {
80153
- word: "Connect",
80154
- label: "OpenFrame Connect",
80155
- description: "Services OpenFrame connects to and manages for every client, such as Microsoft 365 and Google Workspace, beside devices and tickets."
80167
+ open_source: {
80168
+ label: "Open Source",
80169
+ description: "Released under an OSI-approved open-source license.",
80170
+ group: "license",
80171
+ icon: { name: "code", tone: "accent" }
80172
+ },
80173
+ source_available: {
80174
+ label: "Source-available",
80175
+ description: "The source code is public, but the license restricts how it may be used (for example SSPL, BSL, the Elastic License, or limits on company size or on offering it as a service).",
80176
+ group: "license",
80177
+ icon: { name: "file-code", tone: "neutral" }
80178
+ },
80179
+ commercial: {
80180
+ label: "Commercial",
80181
+ description: "Proprietary software sold by the vendor.",
80182
+ group: "license",
80183
+ icon: { name: "dollar", tone: "neutral" }
80184
+ },
80185
+ end_of_life: {
80186
+ label: "End of life",
80187
+ description: "The vendor has discontinued or retired the product. No new releases.",
80188
+ group: "lifecycle",
80189
+ icon: { name: "alert-triangle", tone: "warning" }
80190
+ },
80191
+ end_of_support: {
80192
+ label: "End of support",
80193
+ description: "The vendor no longer provides support or security fixes, though the product can still be obtained.",
80194
+ group: "lifecycle",
80195
+ icon: { name: "clock", tone: "warning" }
80196
+ },
80197
+ unmaintained: {
80198
+ label: "Unmaintained",
80199
+ description: "No release for years and no official end-of-life notice.",
80200
+ group: "lifecycle",
80201
+ icon: { name: "pause-circle", tone: "warning" }
80156
80202
  }
80157
80203
  };
80158
- function isVendorClassification(value) {
80159
- return VENDOR_CLASSIFICATIONS.includes(value);
80204
+ function vendorClassificationCopy(value) {
80205
+ if (!value || !Object.prototype.hasOwnProperty.call(VENDOR_CLASSIFICATION_COPY, value)) return void 0;
80206
+ return VENDOR_CLASSIFICATION_COPY[value];
80207
+ }
80208
+ function vendorClassificationGroup(value) {
80209
+ return vendorClassificationCopy(value)?.group;
80160
80210
  }
80161
80211
  function isOpenFrameClassification(value) {
80162
- return !!value && Object.prototype.hasOwnProperty.call(OPENFRAME_CLASSIFICATIONS, value);
80212
+ return vendorClassificationGroup(value) === "openframe";
80213
+ }
80214
+ var DISPLAY_ORDER = Object.keys(VENDOR_CLASSIFICATION_COPY);
80215
+ function compareVendorClassifications(a, b) {
80216
+ const ia = DISPLAY_ORDER.indexOf(a);
80217
+ const ib = DISPLAY_ORDER.indexOf(b);
80218
+ if (ia !== -1 || ib !== -1) {
80219
+ if (ia === -1) return 1;
80220
+ if (ib === -1) return -1;
80221
+ return ia - ib;
80222
+ }
80223
+ return a.localeCompare(b);
80163
80224
  }
80164
80225
 
80165
80226
  // src/utils/format.ts
@@ -80557,8 +80618,7 @@ function stripHtml(html) {
80557
80618
  return noTags.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&#x27;/g, "'").replace(/&apos;/g, "'").replace(/&amp;/g, "&").replace(/\s+/g, " ").trim();
80558
80619
  }
80559
80620
  function formatClassification(classification) {
80560
- if (isOpenFrameClassification(classification)) return OPENFRAME_CLASSIFICATIONS[classification].label;
80561
- return formatUnderscoreText(classification);
80621
+ return vendorClassificationCopy(classification)?.label ?? formatUnderscoreText(classification);
80562
80622
  }
80563
80623
  function formatPricingModel(pricingModel) {
80564
80624
  const customMappings = {
@@ -85228,18 +85288,116 @@ function buildDocumentTree(docs, mapFn, getParentPath, getPath) {
85228
85288
  return sortTreeChildren(rootNodes);
85229
85289
  }
85230
85290
 
85231
- // src/utils/markdown-to-plain.ts
85291
+ // src/utils/markdown-link.ts
85292
+ var AUTHORED_LINK_REL_TOKENS = ["nofollow", "ugc", "sponsored"];
85293
+ var NEW_TAB_REL = "noopener noreferrer";
85294
+ function authoredRelTokens(rel) {
85295
+ if (!rel) return [];
85296
+ const given = new Set(
85297
+ (typeof rel === "string" ? rel.split(/\s+/) : rel).map((token) => token.trim().toLowerCase()).filter(Boolean)
85298
+ );
85299
+ return AUTHORED_LINK_REL_TOKENS.filter((token) => given.has(token));
85300
+ }
85301
+ function isNofollowRel(rel) {
85302
+ return authoredRelTokens(rel).includes("nofollow");
85303
+ }
85304
+ function renderedLinkRel(authoredRel, opensInNewTab) {
85305
+ const tokens = authoredRelTokens(authoredRel);
85306
+ if (opensInNewTab) tokens.push(NEW_TAB_REL);
85307
+ return tokens.length > 0 ? tokens.join(" ") : void 0;
85308
+ }
85309
+ var MARKDOWN_LINK_RE = /(?<!!)\[((?:\\.|[^\]\\])*)\]\(\s*<?([^\s)>]*)>?(?:\s+"[^"]*")?\s*\)/g;
85310
+ var HTML_LINK_RE = /<a\s([^>]*)>([\s\S]*?)<\/a\s*>/gi;
85311
+ function htmlAttribute(attributes, name) {
85312
+ const match = new RegExp(`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'>]+))`, "i").exec(attributes);
85313
+ if (!match) return null;
85314
+ return match[1] ?? match[2] ?? match[3] ?? "";
85315
+ }
85316
+ function decodeHtmlEntities(value) {
85317
+ return value.replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
85318
+ }
85319
+ function escapeHtmlAttribute(value) {
85320
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
85321
+ }
85322
+ function escapeHtmlText(value) {
85323
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
85324
+ }
85325
+ function escapeMarkdownLinkText(value) {
85326
+ return value.replace(/([\\[\]<])/g, "\\$1");
85327
+ }
85328
+ function unescapeMarkdownLinkText(value) {
85329
+ return value.replace(/\\([\\[\]<])/g, "$1");
85330
+ }
85331
+ function encodeMarkdownUrl(url) {
85332
+ return url.replace(/\s/g, (match) => encodeURIComponent(match)).replace(/[()]/g, (match) => encodeURIComponent(match));
85333
+ }
85334
+ function findMarkdownLinkAt(text, selectionStart, selectionEnd = selectionStart) {
85335
+ const from = Math.min(selectionStart, selectionEnd);
85336
+ const to = Math.max(selectionStart, selectionEnd);
85337
+ const contains = (start, end) => start <= from && to <= end;
85338
+ for (const match of text.matchAll(HTML_LINK_RE)) {
85339
+ const start = match.index ?? 0;
85340
+ const end = start + match[0].length;
85341
+ if (!contains(start, end)) continue;
85342
+ const attributes = match[1] ?? "";
85343
+ return {
85344
+ start,
85345
+ end,
85346
+ text: decodeHtmlEntities(match[2] ?? ""),
85347
+ url: decodeHtmlEntities(htmlAttribute(attributes, "href") ?? ""),
85348
+ rel: authoredRelTokens(htmlAttribute(attributes, "rel"))
85349
+ };
85350
+ }
85351
+ for (const match of text.matchAll(MARKDOWN_LINK_RE)) {
85352
+ const start = match.index ?? 0;
85353
+ const end = start + match[0].length;
85354
+ if (!contains(start, end)) continue;
85355
+ return { start, end, text: unescapeMarkdownLinkText(match[1] ?? ""), url: match[2] ?? "", rel: [] };
85356
+ }
85357
+ return null;
85358
+ }
85359
+ function formatMarkdownLink({ text, url, rel }) {
85360
+ const label = text.length > 0 ? text : url;
85361
+ const tokens = authoredRelTokens(rel);
85362
+ if (tokens.length > 0) {
85363
+ return `<a href="${escapeHtmlAttribute(url)}" rel="${tokens.join(" ")}">${escapeHtmlText(label)}</a>`;
85364
+ }
85365
+ return `[${escapeMarkdownLinkText(label)}](${encodeMarkdownUrl(url)})`;
85366
+ }
85232
85367
  function stripInlineMarkdown(s) {
85233
85368
  return s.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1");
85234
85369
  }
85370
+ var toHtmlTree = remark.remark().use(remarkGfm__default.default).use(remarkBreaks__default.default).use(remarkRehype__default.default, { allowDangerousHtml: true }).use(rehypeRaw__default.default);
85371
+ var NOT_PROSE = /* @__PURE__ */ new Set(["pre", "img"]);
85372
+ var TABLE_SECTIONS = /* @__PURE__ */ new Set(["thead", "tbody", "tfoot"]);
85373
+ function proseTree(markdown) {
85374
+ const tree = toHtmlTree.runSync(toHtmlTree.parse(markdown));
85375
+ unistUtilVisit.visit(tree, "element", (node, index, parent) => {
85376
+ if (NOT_PROSE.has(node.tagName) && parent && index !== void 0) {
85377
+ parent.children.splice(index, 1);
85378
+ return [unistUtilVisit.SKIP, index];
85379
+ }
85380
+ if (TABLE_SECTIONS.has(node.tagName) && parent && index !== void 0) {
85381
+ const followedBySection = parent.children.slice(index + 1).some((sibling) => sibling.type === "element" && TABLE_SECTIONS.has(sibling.tagName));
85382
+ const rows = node.children.filter(
85383
+ (child) => child.type === "element" && child.tagName === "tr"
85384
+ );
85385
+ const lastRow = rows[rows.length - 1];
85386
+ if (followedBySection && lastRow) {
85387
+ lastRow.children.push({ type: "element", tagName: "br", properties: {}, children: [] });
85388
+ }
85389
+ }
85390
+ return void 0;
85391
+ });
85392
+ return tree;
85393
+ }
85235
85394
  function markdownToPlainText(markdown, options = {}) {
85236
85395
  const { mode = "article", maxChars } = options;
85237
- let out = markdown.replace(/```[\s\S]*?```/g, "").replace(/!\[[^\]]*\]\([^)]+\)/g, "");
85238
- out = stripInlineMarkdown(out).replace(/^#+\s*/gm, "").replace(/^\s*[-*+]\s+/gm, "");
85396
+ let out = hastUtilToText.toText(proseTree(markdown));
85239
85397
  if (mode === "preview") {
85240
85398
  out = out.replace(/\s+/g, " ").trim();
85241
85399
  } else {
85242
- out = out.replace(/\n{3,}/g, "\n\n").trim();
85400
+ out = out.replace(/[^\S\n]*\n[^\S\n]*/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
85243
85401
  }
85244
85402
  if (maxChars != null && out.length > maxChars) {
85245
85403
  out = out.slice(0, maxChars);
@@ -85913,6 +86071,7 @@ function identityTint(accent) {
85913
86071
  exports.ACTIVE_ANCHOR_ATTRIBUTE = ACTIVE_ANCHOR_ATTRIBUTE;
85914
86072
  exports.AI_PROVIDERS = AI_PROVIDERS;
85915
86073
  exports.ANTHROPIC_SUPPORTED_IMAGE_MIME = ANTHROPIC_SUPPORTED_IMAGE_MIME;
86074
+ exports.AUTHORED_LINK_REL_TOKENS = AUTHORED_LINK_REL_TOKENS;
85916
86075
  exports.AUTO_CONTINUATION_DIRECTIVE_PREFIX = AUTO_CONTINUATION_DIRECTIVE_PREFIX;
85917
86076
  exports.BADGE_PALETTE = BADGE_PALETTE;
85918
86077
  exports.BITE_ID_RE = BITE_ID_RE;
@@ -85972,7 +86131,6 @@ exports.ODS_SPACING_TOKENS = ODS_SPACING_TOKENS;
85972
86131
  exports.ODS_SPACING_TOKEN_PATTERN = ODS_SPACING_TOKEN_PATTERN;
85973
86132
  exports.ODS_STEM_CLASSES = ODS_STEM_CLASSES;
85974
86133
  exports.ODS_STEM_TOKENS = ODS_STEM_TOKENS;
85975
- exports.OPENFRAME_CLASSIFICATIONS = OPENFRAME_CLASSIFICATIONS;
85976
86134
  exports.OPENFRAME_DEV_SECTIONS = OPENFRAME_DEV_SECTIONS;
85977
86135
  exports.OS_PLATFORMS = OS_PLATFORMS;
85978
86136
  exports.PAGE_PARAM_LIMITS = PAGE_PARAM_LIMITS;
@@ -85998,7 +86156,7 @@ exports.TICKET_OPEN_PARAM = TICKET_OPEN_PARAM;
85998
86156
  exports.TICKET_STATUS_OPTIONS = TICKET_STATUS_OPTIONS;
85999
86157
  exports.TOKEN_RATE_EMPTY = TOKEN_RATE_EMPTY;
86000
86158
  exports.TRIAL_TERMS = TRIAL_TERMS;
86001
- exports.VENDOR_CLASSIFICATIONS = VENDOR_CLASSIFICATIONS;
86159
+ exports.VENDOR_CLASSIFICATION_COPY = VENDOR_CLASSIFICATION_COPY;
86002
86160
  exports.VIEWER_TIMEZONE = VIEWER_TIMEZONE;
86003
86161
  exports.WALKTHROUGH_OPEN_QUERY_PARAM = WALKTHROUGH_OPEN_QUERY_PARAM;
86004
86162
  exports.WALKTHROUGH_VIDEO_DISMISS_KEY = WALKTHROUGH_VIDEO_DISMISS_KEY;
@@ -86006,6 +86164,7 @@ exports.aiProvider = aiProvider;
86006
86164
  exports.analyzeImageColor = analyzeImageColor;
86007
86165
  exports.announcementDismissCookieName = announcementDismissCookieName;
86008
86166
  exports.applyProxyAuth = applyProxyAuth;
86167
+ exports.authoredRelTokens = authoredRelTokens;
86009
86168
  exports.brandMarkDataUri = brandMarkDataUri;
86010
86169
  exports.buildAutoContinuationDirective = buildAutoContinuationDirective;
86011
86170
  exports.buildChatAttachmentViewUrl = buildChatAttachmentViewUrl;
@@ -86032,6 +86191,7 @@ exports.clearLegacyAnnouncementCache = clearLegacyAnnouncementCache;
86032
86191
  exports.clearWalkthroughDismissal = clearWalkthroughDismissal;
86033
86192
  exports.clickupTaskUrl = clickupTaskUrl;
86034
86193
  exports.cn = cn;
86194
+ exports.compareVendorClassifications = compareVendorClassifications;
86035
86195
  exports.complianceStandardForName = complianceStandardForName;
86036
86196
  exports.consumeAccessCode = consumeAccessCode;
86037
86197
  exports.copyrightLine = copyrightLine;
@@ -86080,6 +86240,7 @@ exports.filledRescueFields = filledRescueFields;
86080
86240
  exports.findAnchorElementByNormalizedId = findAnchorElementByNormalizedId;
86081
86241
  exports.findDocNodeByPath = findDocNodeByPath;
86082
86242
  exports.findHoneypotCopySource = findHoneypotCopySource;
86243
+ exports.findMarkdownLinkAt = findMarkdownLinkAt;
86083
86244
  exports.firstParamValue = firstParamValue;
86084
86245
  exports.flattenAssistantContent = flattenAssistantContent;
86085
86246
  exports.formatAbbreviatedNumber = formatAbbreviatedNumber;
@@ -86114,6 +86275,7 @@ exports.formatEntryMonthUTC = formatEntryMonthUTC;
86114
86275
  exports.formatFileSize = formatFileSize;
86115
86276
  exports.formatLargeNumber = formatLargeNumber;
86116
86277
  exports.formatLegalDate = formatLegalDate;
86278
+ exports.formatMarkdownLink = formatMarkdownLink;
86117
86279
  exports.formatNumber = formatNumber;
86118
86280
  exports.formatPercent = formatPercent;
86119
86281
  exports.formatPhoneE164 = formatPhoneE164;
@@ -86224,6 +86386,7 @@ exports.isImageMedia = isImageMedia;
86224
86386
  exports.isLegalDocumentType = isLegalDocumentType;
86225
86387
  exports.isListedSchedulingName = isListedSchedulingName;
86226
86388
  exports.isLocalUrl = isLocalUrl;
86389
+ exports.isNofollowRel = isNofollowRel;
86227
86390
  exports.isOSPlatform = isOSPlatform;
86228
86391
  exports.isOpenFrameClassification = isOpenFrameClassification;
86229
86392
  exports.isOrderedRange = isOrderedRange;
@@ -86236,7 +86399,6 @@ exports.isValidEmailDomain = isValidEmailDomain;
86236
86399
  exports.isValidPathPattern = isValidPathPattern;
86237
86400
  exports.isValidSchedulingSlug = isValidSchedulingSlug;
86238
86401
  exports.isValidToolType = isValidToolType;
86239
- exports.isVendorClassification = isVendorClassification;
86240
86402
  exports.isVideoMedia = isVideoMedia;
86241
86403
  exports.isWalkthroughDismissed = isWalkthroughDismissed;
86242
86404
  exports.isWithinMinutes = isWithinMinutes;
@@ -86298,6 +86460,7 @@ exports.readDismissCookie = readDismissCookie;
86298
86460
  exports.readLeadingDecisionFrame = readLeadingDecisionFrame;
86299
86461
  exports.recordCountLabel = recordCountLabel;
86300
86462
  exports.releaseTypeToBadgeColor = releaseTypeToBadgeColor;
86463
+ exports.renderedLinkRel = renderedLinkRel;
86301
86464
  exports.replaceLocationHash = replaceLocationHash;
86302
86465
  exports.rescueCompletionPct = rescueCompletionPct;
86303
86466
  exports.resolveContentFetchPath = resolveContentFetchPath;
@@ -86357,6 +86520,8 @@ exports.validateAndConsumeAccessCode = validateAndConsumeAccessCode;
86357
86520
  exports.validateEmailDomain = validateEmailDomain;
86358
86521
  exports.validateEmailDomainList = validateEmailDomainList;
86359
86522
  exports.validatePhoneNumber = validatePhoneNumber;
86523
+ exports.vendorClassificationCopy = vendorClassificationCopy;
86524
+ exports.vendorClassificationGroup = vendorClassificationGroup;
86360
86525
  exports.walkthroughDismissCookieName = walkthroughDismissCookieName;
86361
86526
  exports.webinarTiming = webinarTiming;
86362
86527
  exports.withFirstTouchAttribution = withFirstTouchAttribution;
@@ -4,7 +4,7 @@ export { formatDate, formatNumber, formatPrice, formatBytes, formatUrlForDisplay
4
4
  export * from './ai-providers';
5
5
  export * from './model-token-rates';
6
6
  export { TRIAL_TERMS, trialLabels, trialLengthLabel } from './trial';
7
- export { VENDOR_CLASSIFICATIONS, OPENFRAME_CLASSIFICATIONS, isVendorClassification, isOpenFrameClassification, type VendorClassificationValue, type OpenFrameClassification, type OpenFrameClassificationCopy, } from './vendor-classification';
7
+ export { VENDOR_CLASSIFICATION_COPY, vendorClassificationCopy, vendorClassificationGroup, compareVendorClassifications, isOpenFrameClassification, type VendorClassificationValue, type VendorClassificationGroup, type VendorClassificationCopy, type VendorClassificationIconConfig, } from './vendor-classification';
8
8
  export { PLAY_ICON_PATH } from '../components/icons-v2-generated/media-playback/play-icon';
9
9
  export { getPlatformAccentColor, getCurrentPlatform, getPlatformConfig, usePlatformColors, switchPlatformTheme, getSemanticColor, type ColorCategory, HEX_PATTERN, getReadableTextColor, hexToRgb, rgbToHex, deriveHoverColor, deriveActiveColor, } from './ods-color-utils';
10
10
  export { errorMessage, delay, generateRandomString, truncateString, deepClone, getSlackCommunityJoinUrl, serializeJsonLd, clamp, pick, NO_CLIENT_CACHE, } from './common';
@@ -78,6 +78,7 @@ export * from './doc-path-utils';
78
78
  export * from './doc-tree-nav';
79
79
  export * from './tree-builder';
80
80
  export * from './markdown-heading-id';
81
+ export * from './markdown-link';
81
82
  export * from './markdown-section-extractor';
82
83
  export * from './markdown-to-plain';
83
84
  export * from './embed-url-converters';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
@@ -13,9 +13,10 @@ export * from "./ai-providers.js";
13
13
  export * from "./model-token-rates.js";
14
14
  import { TRIAL_TERMS, trialLabels, trialLengthLabel } from "./trial.js";
15
15
  import {
16
- VENDOR_CLASSIFICATIONS,
17
- OPENFRAME_CLASSIFICATIONS,
18
- isVendorClassification,
16
+ VENDOR_CLASSIFICATION_COPY,
17
+ vendorClassificationCopy,
18
+ vendorClassificationGroup,
19
+ compareVendorClassifications,
19
20
  isOpenFrameClassification
20
21
  } from "./vendor-classification.js";
21
22
  import { PLAY_ICON_PATH } from "../components/icons-v2-generated/media-playback/play-icon.js";
@@ -236,6 +237,7 @@ export * from "./doc-path-utils.js";
236
237
  export * from "./doc-tree-nav.js";
237
238
  export * from "./tree-builder.js";
238
239
  export * from "./markdown-heading-id.js";
240
+ export * from "./markdown-link.js";
239
241
  export * from "./markdown-section-extractor.js";
240
242
  export * from "./markdown-to-plain.js";
241
243
  export * from "./embed-url-converters.js";
@@ -285,7 +287,6 @@ export {
285
287
  ICON_REGISTRY,
286
288
  LOCATION_HASH_SYNC_EVENT,
287
289
  NO_CLIENT_CACHE,
288
- OPENFRAME_CLASSIFICATIONS,
289
290
  PLAY_ICON_PATH,
290
291
  PROGRAM_META_RENDERERS,
291
292
  SCROLL_ANCHOR,
@@ -297,7 +298,7 @@ export {
297
298
  STICKY_HEADER_OFFSET_PX,
298
299
  TICKET_OPEN_PARAM,
299
300
  TRIAL_TERMS,
300
- VENDOR_CLASSIFICATIONS,
301
+ VENDOR_CLASSIFICATION_COPY,
301
302
  VIEWER_TIMEZONE,
302
303
  applyProxyAuth,
303
304
  buildAutoContinuationDirective,
@@ -313,6 +314,7 @@ export {
313
314
  clearEmbedProxyAuth,
314
315
  clickupTaskUrl,
315
316
  cn,
317
+ compareVendorClassifications,
316
318
  copyrightLine,
317
319
  createSseSubscription,
318
320
  createUTCTimestamp,
@@ -414,7 +416,6 @@ export {
414
416
  isOrderedRange,
415
417
  isScrollSyncedHash,
416
418
  isToday,
417
- isVendorClassification,
418
419
  isWithinMinutes,
419
420
  makeComposeContentUrl,
420
421
  nameInitials,
@@ -457,5 +458,7 @@ export {
457
458
  truncateString,
458
459
  urlPathLooksLikeSvg,
459
460
  usePlatformColors,
461
+ vendorClassificationCopy,
462
+ vendorClassificationGroup,
460
463
  webinarTiming
461
464
  };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * One link format for the markdown editors and one `rel` rule for the renderers.
3
+ *
4
+ * A FOLLOWED link is written as markdown, `[text](url)`, exactly as the editors always wrote it.
5
+ * A link with an authored `rel` (nofollow, sponsored or ugc, the values Google reads) is written as
6
+ * an HTML anchor, `<a href="url" rel="sponsored">text</a>`: markdown has no attribute syntax, and
7
+ * an HTML anchor is what stored content already uses for links that carry attributes (the
8
+ * sanitizer keeps `rel` on `a`). Reading back accepts both forms, so a link can be switched either
9
+ * way. Nothing is rewritten unless an editor changes a link.
10
+ *
11
+ * Server-safe: no React, no DOM.
12
+ */
13
+ /** The `rel` tokens an author may set on a link. Search engines read these; nothing else is kept. */
14
+ export declare const AUTHORED_LINK_REL_TOKENS: readonly ["nofollow", "ugc", "sponsored"];
15
+ export type AuthoredLinkRel = (typeof AUTHORED_LINK_REL_TOKENS)[number];
16
+ /** The authored SEO tokens in a `rel` value, in their canonical order. */
17
+ export declare function authoredRelTokens(rel: string | readonly string[] | null | undefined): AuthoredLinkRel[];
18
+ /** Whether an authored `rel` asks search engines not to follow the link. */
19
+ export declare function isNofollowRel(rel: string | readonly string[] | null | undefined): boolean;
20
+ /**
21
+ * The `rel` a renderer writes for a link: the author's SEO tokens, plus `noopener noreferrer` when
22
+ * the link opens in a new tab. `undefined` when there is nothing to write.
23
+ */
24
+ export declare function renderedLinkRel(authoredRel: string | readonly string[] | null | undefined, opensInNewTab: boolean): string | undefined;
25
+ /** A link as the editor's dialog edits it. */
26
+ export interface MarkdownLinkFields {
27
+ text: string;
28
+ url: string;
29
+ /** The authored `rel` values. Empty = a followed link. */
30
+ rel: AuthoredLinkRel[];
31
+ }
32
+ /** A link found in the editor's text, with the range it occupies. */
33
+ export interface MarkdownLinkMatch extends MarkdownLinkFields {
34
+ start: number;
35
+ end: number;
36
+ }
37
+ /**
38
+ * The link the selection `[selectionStart, selectionEnd]` is in or on, if any: a markdown link or an
39
+ * HTML anchor that contains the whole selection (a caret counts when it touches the link).
40
+ */
41
+ export declare function findMarkdownLinkAt(text: string, selectionStart: number, selectionEnd?: number): MarkdownLinkMatch | null;
42
+ /** The text that writes a link: markdown when followed, an HTML anchor when it carries a `rel`. */
43
+ export declare function formatMarkdownLink({ text, url, rel }: MarkdownLinkFields): string;
44
+ //# sourceMappingURL=markdown-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-link.d.ts","sourceRoot":"","sources":["../../src/utils/markdown-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qGAAqG;AACrG,eAAO,MAAM,wBAAwB,2CAA4C,CAAC;AAElF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAKxE,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,EAAE,CAMvG;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAC1D,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAIpB;AAED,8CAA8C;AAC9C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,GAAG,EAAE,eAAe,EAAE,CAAC;CACxB;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AA4CD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,YAAY,GAAE,MAAuB,GACpC,iBAAiB,GAAG,IAAI,CAyB1B;AAED,mGAAmG;AACnG,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,kBAAkB,GAAG,MAAM,CAOjF"}
@@ -0,0 +1,83 @@
1
+ const AUTHORED_LINK_REL_TOKENS = ["nofollow", "ugc", "sponsored"];
2
+ const NEW_TAB_REL = "noopener noreferrer";
3
+ function authoredRelTokens(rel) {
4
+ if (!rel) return [];
5
+ const given = new Set(
6
+ (typeof rel === "string" ? rel.split(/\s+/) : rel).map((token) => token.trim().toLowerCase()).filter(Boolean)
7
+ );
8
+ return AUTHORED_LINK_REL_TOKENS.filter((token) => given.has(token));
9
+ }
10
+ function isNofollowRel(rel) {
11
+ return authoredRelTokens(rel).includes("nofollow");
12
+ }
13
+ function renderedLinkRel(authoredRel, opensInNewTab) {
14
+ const tokens = authoredRelTokens(authoredRel);
15
+ if (opensInNewTab) tokens.push(NEW_TAB_REL);
16
+ return tokens.length > 0 ? tokens.join(" ") : void 0;
17
+ }
18
+ const MARKDOWN_LINK_RE = /(?<!!)\[((?:\\.|[^\]\\])*)\]\(\s*<?([^\s)>]*)>?(?:\s+"[^"]*")?\s*\)/g;
19
+ const HTML_LINK_RE = /<a\s([^>]*)>([\s\S]*?)<\/a\s*>/gi;
20
+ function htmlAttribute(attributes, name) {
21
+ const match = new RegExp(`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'>]+))`, "i").exec(attributes);
22
+ if (!match) return null;
23
+ return match[1] ?? match[2] ?? match[3] ?? "";
24
+ }
25
+ function decodeHtmlEntities(value) {
26
+ return value.replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
27
+ }
28
+ function escapeHtmlAttribute(value) {
29
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
30
+ }
31
+ function escapeHtmlText(value) {
32
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
33
+ }
34
+ function escapeMarkdownLinkText(value) {
35
+ return value.replace(/([\\[\]<])/g, "\\$1");
36
+ }
37
+ function unescapeMarkdownLinkText(value) {
38
+ return value.replace(/\\([\\[\]<])/g, "$1");
39
+ }
40
+ function encodeMarkdownUrl(url) {
41
+ return url.replace(/\s/g, (match) => encodeURIComponent(match)).replace(/[()]/g, (match) => encodeURIComponent(match));
42
+ }
43
+ function findMarkdownLinkAt(text, selectionStart, selectionEnd = selectionStart) {
44
+ const from = Math.min(selectionStart, selectionEnd);
45
+ const to = Math.max(selectionStart, selectionEnd);
46
+ const contains = (start, end) => start <= from && to <= end;
47
+ for (const match of text.matchAll(HTML_LINK_RE)) {
48
+ const start = match.index ?? 0;
49
+ const end = start + match[0].length;
50
+ if (!contains(start, end)) continue;
51
+ const attributes = match[1] ?? "";
52
+ return {
53
+ start,
54
+ end,
55
+ text: decodeHtmlEntities(match[2] ?? ""),
56
+ url: decodeHtmlEntities(htmlAttribute(attributes, "href") ?? ""),
57
+ rel: authoredRelTokens(htmlAttribute(attributes, "rel"))
58
+ };
59
+ }
60
+ for (const match of text.matchAll(MARKDOWN_LINK_RE)) {
61
+ const start = match.index ?? 0;
62
+ const end = start + match[0].length;
63
+ if (!contains(start, end)) continue;
64
+ return { start, end, text: unescapeMarkdownLinkText(match[1] ?? ""), url: match[2] ?? "", rel: [] };
65
+ }
66
+ return null;
67
+ }
68
+ function formatMarkdownLink({ text, url, rel }) {
69
+ const label = text.length > 0 ? text : url;
70
+ const tokens = authoredRelTokens(rel);
71
+ if (tokens.length > 0) {
72
+ return `<a href="${escapeHtmlAttribute(url)}" rel="${tokens.join(" ")}">${escapeHtmlText(label)}</a>`;
73
+ }
74
+ return `[${escapeMarkdownLinkText(label)}](${encodeMarkdownUrl(url)})`;
75
+ }
76
+ export {
77
+ AUTHORED_LINK_REL_TOKENS,
78
+ authoredRelTokens,
79
+ findMarkdownLinkAt,
80
+ formatMarkdownLink,
81
+ isNofollowRel,
82
+ renderedLinkRel
83
+ };
@@ -1,17 +1,3 @@
1
- /**
2
- * Convert markdown source to plain text. Used by both the SEO server component
3
- * (article-body echo in JSON-LD) and chat entity-card preview (clamped previews
4
- * inside chat cards).
5
- *
6
- * The two consumers differ only in pre/post processing — `mode: 'article'`
7
- * strips code blocks + images + headings + list bullets and preserves paragraph
8
- * breaks; `mode: 'preview'` collapses everything to a single line. Both share
9
- * the same inline-marker strip (link / bold / italic / inline-code).
10
- *
11
- * All regex patterns are linear (negated character classes, non-greedy with
12
- * bounded targets) — no nested quantifiers, no catastrophic backtracking on
13
- * pathological input.
14
- */
15
1
  export interface MarkdownToPlainOptions {
16
2
  /**
17
3
  * - `'article'` (default): preserve paragraph structure (`\n\n` as separator),
@@ -25,8 +11,9 @@ export interface MarkdownToPlainOptions {
25
11
  /** Optional max-character cap. Truncates with no ellipsis (caller-decided). */
26
12
  maxChars?: number;
27
13
  }
28
- /** Strip inline markdown markers (bold, italic, inline-code, links). Shared
29
- * by `extractSections`'s `stripFormattingMarkers` and `markdownToPlainText`. */
14
+ /** Strip inline markdown markers (bold, italic, inline-code, links) from ONE line of text.
15
+ * Shared by `extractSections`'s `stripFormattingMarkers` and the heading ids, whose output is
16
+ * an anchor: it stays a fixed, regex-only rule so no heading id ever moves. */
30
17
  export declare function stripInlineMarkdown(s: string): string;
31
18
  export declare function markdownToPlainText(markdown: string, options?: MarkdownToPlainOptions): string;
32
19
  //# sourceMappingURL=markdown-to-plain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-to-plain.d.ts","sourceRoot":"","sources":["../../src/utils/markdown-to-plain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;iFACiF;AACjF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CA0BlG"}
1
+ {"version":3,"file":"markdown-to-plain.d.ts","sourceRoot":"","sources":["../../src/utils/markdown-to-plain.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;gFAEgF;AAChF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrD;AAyCD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAmBlG"}