@trops/dash-core 0.1.644 → 0.1.646

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ var reactInstantsearchHooksWeb = require('react-instantsearch-hooks-web');
28
28
  var ReactDOM = require('react-dom');
29
29
  var reactRouterDom = require('react-router-dom');
30
30
  var marked = require('marked');
31
+ var DOMPurify = require('dompurify');
31
32
  var PropTypes = require('prop-types');
32
33
 
33
34
  function _interopNamespaceDefault(e) {
@@ -69054,6 +69055,58 @@ var ToolCallBlock = function ToolCallBlock(_ref) {
69054
69055
  });
69055
69056
  };
69056
69057
 
69058
+ /**
69059
+ * safeMarkdown.js
69060
+ *
69061
+ * Markdown → HTML that is safe to insert with dangerouslySetInnerHTML.
69062
+ *
69063
+ * AI replies are Markdown, and they can quote untrusted content (emails, web
69064
+ * pages, tool results). `marked` passes raw HTML through untouched, so a reply
69065
+ * containing `<img onerror=…>` or `<script>` would run in the app window —
69066
+ * which can reach window.mainApi. Every Markdown render of model or tool text
69067
+ * goes through here: `marked`, then DOMPurify.
69068
+ *
69069
+ * Kept: normal formatting (headings, emphasis, lists, code, tables, links).
69070
+ * Removed: scripts, event-handler attributes, javascript:/data: URLs,
69071
+ * iframes/objects/embeds/forms/styles, and inline style. Links get
69072
+ * rel="noopener noreferrer" (the app also blocks in-window navigation).
69073
+ */
69074
+ var FORBID_TAGS = ["style", "iframe", "object", "embed", "form", "input", "button", "textarea", "select", "link", "meta", "base"];
69075
+ var FORBID_ATTR = ["style"];
69076
+ // http(s), mailto, and in-page anchors only.
69077
+ var ALLOWED_URI_REGEXP = /^(?:(?:https?|mailto):|#)/i;
69078
+ var hooked = false;
69079
+ function ensureLinkHook() {
69080
+ if (hooked || typeof DOMPurify.addHook !== "function") return;
69081
+ DOMPurify.addHook("afterSanitizeAttributes", function (node) {
69082
+ if (node.tagName === "A" && node.hasAttribute("href")) {
69083
+ node.setAttribute("rel", "noopener noreferrer");
69084
+ node.setAttribute("target", "_blank");
69085
+ }
69086
+ });
69087
+ hooked = true;
69088
+ }
69089
+
69090
+ /**
69091
+ * @param {string} text Markdown (from a model, a tool, or a user)
69092
+ * @returns {string} sanitized HTML
69093
+ */
69094
+ function renderSafeMarkdown(text) {
69095
+ if (!text) return "";
69096
+ ensureLinkHook();
69097
+ var html = marked.marked(String(text), {
69098
+ breaks: true
69099
+ });
69100
+ return DOMPurify.sanitize(html, {
69101
+ USE_PROFILES: {
69102
+ html: true
69103
+ },
69104
+ FORBID_TAGS: FORBID_TAGS,
69105
+ FORBID_ATTR: FORBID_ATTR,
69106
+ ALLOWED_URI_REGEXP: ALLOWED_URI_REGEXP
69107
+ });
69108
+ }
69109
+
69057
69110
  function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
69058
69111
  function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
69059
69112
  function _createForOfIteratorHelper$4(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$4(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -69062,9 +69115,10 @@ function _arrayLikeToArray$4(r, a) { (null == a || a > r.length) && (a = r.lengt
69062
69115
  function AssistantTextContent(_ref) {
69063
69116
  var text = _ref.text;
69064
69117
  if (!text) return null;
69065
- var html = marked.marked(text, {
69066
- breaks: true
69067
- });
69118
+
69119
+ // Sanitized: replies can quote untrusted content (emails, web pages), and
69120
+ // this HTML is inserted into the app window.
69121
+ var html = renderSafeMarkdown(text);
69068
69122
  return /*#__PURE__*/jsxRuntime.jsx("div", {
69069
69123
  className: "prose prose-invert prose-sm max-w-none prose-p:my-2 prose-headings:my-3 prose-ul:my-2 prose-ol:my-2 prose-li:my-0.5 prose-pre:bg-black/40 prose-pre:text-gray-300 prose-code:text-indigo-300 prose-a:text-indigo-400 leading-relaxed",
69070
69124
  dangerouslySetInnerHTML: {
@@ -72008,6 +72062,7 @@ exports.renderGridLayout = renderGridLayout;
72008
72062
  exports.renderGridLayoutFlow = renderGridLayoutFlow;
72009
72063
  exports.renderLayout = _renderLayout;
72010
72064
  exports.renderLayoutMenu = renderLayoutMenu;
72065
+ exports.renderSafeMarkdown = renderSafeMarkdown;
72011
72066
  exports.replaceItemInLayout = replaceItemInLayout;
72012
72067
  exports.resolveGateWidgetId = resolveGateWidgetId;
72013
72068
  exports.resolveIcon = resolveIcon;