react-safe-html-parser
Version:
A secure, lightweight HTML parser for React with XSS protection and SSR support
12 lines (11 loc) • 19.9 kB
JavaScript
;Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");function r(){if("undefined"!=typeof window&&"undefined"!=typeof DOMParser)return{parseHTML:e=>({document:(new DOMParser).parseFromString(e,"text/html"),window:window})};try{const{parseHTML:e}=require("linkedom");return{parseHTML:r=>e(r)}}catch(e){throw new Error("DOM parser not available. Please install linkedom for Node.js environments.")}}const t=r();function n(e){try{const{document:r}=t.parseHTML(e);return r}catch(e){throw new Error(`Failed to parse HTML: ${e instanceof Error?e.message:"Unknown error"}`)}}const o={dangerousAttributes:["onabort","onbeforeunload","onerror","onhashchange","onmessage","onoffline","ononline","onpagehide","onpageshow","onpopstate","onresize","onstorage","onunload","onblur","onchange","oncontextmenu","onfocus","oninput","oninvalid","onreset","onsearch","onselect","onsubmit","onkeydown","onkeypress","onkeyup","onclick","ondblclick","onmousedown","onmouseenter","onmouseleave","onmousemove","onmouseout","onmouseover","onmouseup","onwheel","oncopy","oncut","onpaste","onabort","onbeforecopy","onbeforecut","onbeforepaste","onload","onerror","onunload","onbeforeunload","onresize","onmessage","onerror","onabort","onbeforeunload","onerror","onhashchange","onmessage","onoffline","ononline","onpagehide","onpageshow","onpopstate","onresize","onstorage","onunload"],dangerousProtocols:["javascript:","vbscript:","data:","mocha:","livescript:"],dangerousTags:["script","object","embed","form","input","textarea","button","select","option","optgroup","fieldset","legend","label"],allowedAttributesByTag:{a:["href","title","target","rel"],img:["src","alt","title","width","height"],div:["class","id","style"],span:["class","id","style"],p:["class","id","style"],h1:["class","id","style"],h2:["class","id","style"],h3:["class","id","style"],h4:["class","id","style"],h5:["class","id","style"],h6:["class","id","style"],ul:["class","id","style"],ol:["class","id","style"],li:["class","id","style"],table:["class","id","style"],tr:["class","id","style"],td:["class","id","style","colspan","rowspan"],th:["class","id","style","colspan","rowspan"],strong:["class","id","style"],em:["class","id","style"],b:["class","id","style"],i:["class","id","style"],u:["class","id","style"],code:["class","id","style"],pre:["class","id","style"],blockquote:["class","id","style"],br:[],hr:["class","id","style"]}};function s(e){const r=e.toLowerCase().trim();return o.dangerousProtocols.some(e=>r.startsWith(e))}function a(e){return o.dangerousAttributes.includes(e.toLowerCase())}function l(e){return o.dangerousTags.includes(e.toLowerCase())}function i(e,r,t={}){const n={},l=t.allowedAttributes||Object.keys(o.allowedAttributesByTag[r]||{});for(const[r,t]of Object.entries(e)){const e=r.toLowerCase();if(a(e))continue;if(!l.includes(e))continue;if(("href"===e||"src"===e)&&s(t))continue;n["class"===e?"className":e]=t}return n}function c(e,r={}){const t={},n=r.allowedStyles||["color","background-color","font-size","font-weight","text-align","margin","padding","border","width","height","display","position"],o=e.split(";");for(const e of o){const[r,o]=e.split(":").map(e=>e.trim());if(!r||!o)continue;const s=r.toLowerCase();if(!n.includes(s))continue;t[s.replace(/-([a-z])/g,(e,r)=>r.toUpperCase())]=o}return t}function u(e){const r={"&":"&","<":"<",">":">",""":'"',"'":"'","'":"'"," ":" ","©":"©","®":"®","™":"™","…":"…","—":"—","–":"–","‘":"'","’":"'","“":'"',"”":'"'};return e.replace(/&[a-zA-Z0-9#]+;/g,e=>r[e]||e)}function p(r,t,n,o){const{components:s,transform:a,sanitize:p,decodeHtmlEntities:d=!0,parseStyle:y=!0}=t;if(r.nodeType===Node.TEXT_NODE){let e=r.textContent||"";return d&&(e=u(e)),e.trim()?e:null}if(r.nodeType===Node.COMMENT_NODE)return null;if(r.nodeType===Node.ELEMENT_NODE){const u=r,d=u.tagName.toLowerCase();if(l(d))return null;const m={};for(let e=0;e<u.attributes.length;e++){const r=u.attributes[e];if(!r)continue;const t=r.name;let n=r.value;if("style"===t&&y){const e=c(n,p);Object.keys(e).length>0&&(m.style=e);continue}m[t]=n}const h=i(m,d,p),g=s?.[d];if(g)return e.createElement(g,{...h,key:n,children:f(u,t)});const b=f(u,t),v={...h,key:n},w={type:"element",tagName:d,attributes:h,children:[],nodeType:r.nodeType};if(a){const r=a(w,n,o);if(null===r)return null;if("string"==typeof r)return r;if(e.isValidElement(r))return e.cloneElement(r,{key:n})}return e.createElement(d,v,b)}return null}function f(e,r){const t=[];let n=0;for(let o=0;o<e.childNodes.length;o++){const s=e.childNodes[o];if(!s)continue;const a=p(s,r,n);null!==a&&(t.push(a),n++)}return t}function d(r,t={}){const o=[],s=[];try{if(!r||"string"!=typeof r)return{elements:[],errors:[new Error("Invalid HTML input")],success:!1};const a=n(r),l=a.body||a,i=[];let c=0;for(let e=0;e<l.childNodes.length;e++){const r=l.childNodes[e];if(!r)continue;const n=p(r,t,c);null!==n&&(i.push(n),c++)}for(const r of i)e.isValidElement(r)?s.push(r):"string"==typeof r&&r.trim()&&s.push(e.createElement("span",{key:`text-${c}`},r));return{elements:s,errors:o,success:!0}}catch(e){return o.push(e instanceof Error?e:new Error("Unknown parsing error")),{elements:[],errors:o,success:!1}}}function y(r,t={}){const n=d(r,t);return n.success&&0!==n.elements.length?1===n.elements.length?n.elements[0]||null:e.createElement(e.Fragment,{},...n.elements):null}var m,h={exports:{}},g={};var b,v={};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/"production"===process.env.NODE_ENV?h.exports=function(){if(m)return g;m=1;var r=e,t=Symbol.for("react.element"),n=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,s=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,a={key:!0,ref:!0,__self:!0,__source:!0};function l(e,r,n){var l,i={},c=null,u=null;for(l in void 0!==n&&(c=""+n),void 0!==r.key&&(c=""+r.key),void 0!==r.ref&&(u=r.ref),r)o.call(r,l)&&!a.hasOwnProperty(l)&&(i[l]=r[l]);if(e&&e.defaultProps)for(l in r=e.defaultProps)void 0===i[l]&&(i[l]=r[l]);return{$$typeof:t,type:e,key:c,ref:u,props:i,_owner:s.current}}return g.Fragment=n,g.jsx=l,g.jsxs=l,g}():h.exports=(b||(b=1,"production"!==process.env.NODE_ENV&&function(){var r,t=e,n=Symbol.for("react.element"),o=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),l=Symbol.for("react.profiler"),i=Symbol.for("react.provider"),c=Symbol.for("react.context"),u=Symbol.for("react.forward_ref"),p=Symbol.for("react.suspense"),f=Symbol.for("react.suspense_list"),d=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),m=Symbol.for("react.offscreen"),h=Symbol.iterator,g=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;function b(e){for(var r=arguments.length,t=new Array(r>1?r-1:0),n=1;n<r;n++)t[n-1]=arguments[n];!function(e,r,t){var n=g.ReactDebugCurrentFrame.getStackAddendum();""!==n&&(r+="%s",t=t.concat([n]));var o=t.map(function(e){return String(e)});o.unshift("Warning: "+r),Function.prototype.apply.call(console[e],console,o)}("error",e,t)}function w(e){return e.displayName||"Context"}function k(e){if(null==e)return null;if("number"==typeof e.tag&&b("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),"function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case s:return"Fragment";case o:return"Portal";case l:return"Profiler";case a:return"StrictMode";case p:return"Suspense";case f:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case c:return w(e)+".Consumer";case i:return w(e._context)+".Provider";case u:return function(e,r,t){var n=e.displayName;if(n)return n;var o=r.displayName||r.name||"";return""!==o?t+"("+o+")":t}(e,e.render,"ForwardRef");case d:var r=e.displayName||null;return null!==r?r:k(e.type)||"Memo";case y:var t=e,n=t._payload,m=t._init;try{return k(m(n))}catch(e){return null}}return null}r=Symbol.for("react.module.reference");var _,E,j,x,O,S,T,R=Object.assign,P=0;function N(){}N.__reactDisabledLog=!0;var D,C=g.ReactCurrentDispatcher;function F(e,r,t){if(void 0===D)try{throw Error()}catch(e){var n=e.stack.trim().match(/\n( *(at )?)/);D=n&&n[1]||""}return"\n"+D+e}var $,L=!1,H="function"==typeof WeakMap?WeakMap:Map;function M(e,r){if(!e||L)return"";var t,n=$.get(e);if(void 0!==n)return n;L=!0;var o,s=Error.prepareStackTrace;Error.prepareStackTrace=void 0,o=C.current,C.current=null,function(){if(0===P){_=console.log,E=console.info,j=console.warn,x=console.error,O=console.group,S=console.groupCollapsed,T=console.groupEnd;var e={configurable:!0,enumerable:!0,value:N,writable:!0};Object.defineProperties(console,{info:e,log:e,warn:e,error:e,group:e,groupCollapsed:e,groupEnd:e})}P++}();try{if(r){var a=function(){throw Error()};if(Object.defineProperty(a.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(a,[])}catch(e){t=e}Reflect.construct(e,[],a)}else{try{a.call()}catch(e){t=e}e.call(a.prototype)}}else{try{throw Error()}catch(e){t=e}e()}}catch(r){if(r&&t&&"string"==typeof r.stack){for(var l=r.stack.split("\n"),i=t.stack.split("\n"),c=l.length-1,u=i.length-1;c>=1&&u>=0&&l[c]!==i[u];)u--;for(;c>=1&&u>=0;c--,u--)if(l[c]!==i[u]){if(1!==c||1!==u)do{if(c--,--u<0||l[c]!==i[u]){var p="\n"+l[c].replace(" at new "," at ");return e.displayName&&p.includes("<anonymous>")&&(p=p.replace("<anonymous>",e.displayName)),"function"==typeof e&&$.set(e,p),p}}while(c>=1&&u>=0);break}}}finally{L=!1,C.current=o,function(){if(0===--P){var e={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:R({},e,{value:_}),info:R({},e,{value:E}),warn:R({},e,{value:j}),error:R({},e,{value:x}),group:R({},e,{value:O}),groupCollapsed:R({},e,{value:S}),groupEnd:R({},e,{value:T})})}P<0&&b("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}(),Error.prepareStackTrace=s}var f=e?e.displayName||e.name:"",d=f?F(f):"";return"function"==typeof e&&$.set(e,d),d}function I(e,r,t){if(null==e)return"";if("function"==typeof e)return M(e,!(!(n=e.prototype)||!n.isReactComponent));var n;if("string"==typeof e)return F(e);switch(e){case p:return F("Suspense");case f:return F("SuspenseList")}if("object"==typeof e)switch(e.$$typeof){case u:return M(e.render,!1);case d:return I(e.type,r,t);case y:var o=e,s=o._payload,a=o._init;try{return I(a(s),r,t)}catch(e){}}return""}$=new H;var A=Object.prototype.hasOwnProperty,z={},U=g.ReactDebugCurrentFrame;function W(e){if(e){var r=e._owner,t=I(e.type,e._source,r?r.type:null);U.setExtraStackFrame(t)}else U.setExtraStackFrame(null)}var q=Array.isArray;function Y(e){return q(e)}function B(e){return""+e}function V(e){if(function(e){try{return B(e),!1}catch(e){return!0}}(e))return b("The provided key is an unsupported type %s. This value must be coerced to a string before before using it here.",function(e){return"function"==typeof Symbol&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object"}(e)),B(e)}var X,J,K=g.ReactCurrentOwner,G={key:!0,ref:!0,__self:!0,__source:!0};function Z(e,r,t,o,s){var a,l={},i=null,c=null;for(a in void 0!==t&&(V(t),i=""+t),function(e){if(A.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return void 0!==e.key}(r)&&(V(r.key),i=""+r.key),function(e){if(A.call(e,"ref")){var r=Object.getOwnPropertyDescriptor(e,"ref").get;if(r&&r.isReactWarning)return!1}return void 0!==e.ref}(r)&&(c=r.ref,function(e){"string"==typeof e.ref&&K.current}(r)),r)A.call(r,a)&&!G.hasOwnProperty(a)&&(l[a]=r[a]);if(e&&e.defaultProps){var u=e.defaultProps;for(a in u)void 0===l[a]&&(l[a]=u[a])}if(i||c){var p="function"==typeof e?e.displayName||e.name||"Unknown":e;i&&function(e,r){var t=function(){X||(X=!0,b("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",r))};t.isReactWarning=!0,Object.defineProperty(e,"key",{get:t,configurable:!0})}(l,p),c&&function(e,r){var t=function(){J||(J=!0,b("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",r))};t.isReactWarning=!0,Object.defineProperty(e,"ref",{get:t,configurable:!0})}(l,p)}return function(e,r,t,o,s,a,l){var i={$$typeof:n,type:e,key:r,ref:t,props:l,_owner:a,_store:{}};return Object.defineProperty(i._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(i,"_self",{configurable:!1,enumerable:!1,writable:!1,value:o}),Object.defineProperty(i,"_source",{configurable:!1,enumerable:!1,writable:!1,value:s}),Object.freeze&&(Object.freeze(i.props),Object.freeze(i)),i}(e,i,c,s,o,K.current,l)}var Q,ee=g.ReactCurrentOwner,re=g.ReactDebugCurrentFrame;function te(e){if(e){var r=e._owner,t=I(e.type,e._source,r?r.type:null);re.setExtraStackFrame(t)}else re.setExtraStackFrame(null)}function ne(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}function oe(){if(ee.current){var e=k(ee.current.type);if(e)return"\n\nCheck the render method of `"+e+"`."}return""}Q=!1;var se={};function ae(e,r){if(e._store&&!e._store.validated&&null==e.key){e._store.validated=!0;var t=function(e){var r=oe();if(!r){var t="string"==typeof e?e:e.displayName||e.name;t&&(r="\n\nCheck the top-level render call using <"+t+">.")}return r}(r);if(!se[t]){se[t]=!0;var n="";e&&e._owner&&e._owner!==ee.current&&(n=" It was passed a child from "+k(e._owner.type)+"."),te(e),b('Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.',t,n),te(null)}}}function le(e,r){if("object"==typeof e)if(Y(e))for(var t=0;t<e.length;t++){var n=e[t];ne(n)&&ae(n,r)}else if(ne(e))e._store&&(e._store.validated=!0);else if(e){var o=function(e){if(null===e||"object"!=typeof e)return null;var r=h&&e[h]||e["@@iterator"];return"function"==typeof r?r:null}(e);if("function"==typeof o&&o!==e.entries)for(var s,a=o.call(e);!(s=a.next()).done;)ne(s.value)&&ae(s.value,r)}}function ie(e){var r,t=e.type;if(null!=t&&"string"!=typeof t){if("function"==typeof t)r=t.propTypes;else{if("object"!=typeof t||t.$$typeof!==u&&t.$$typeof!==d)return;r=t.propTypes}if(r){var n=k(t);!function(e,r,t,n,o){var s=Function.call.bind(A);for(var a in e)if(s(e,a)){var l=void 0;try{if("function"!=typeof e[a]){var i=Error((n||"React class")+": "+t+" type `"+a+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof e[a]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw i.name="Invariant Violation",i}l=e[a](r,a,n,t,null,"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED")}catch(e){l=e}!l||l instanceof Error||(W(o),b("%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).",n||"React class",t,a,typeof l),W(null)),l instanceof Error&&!(l.message in z)&&(z[l.message]=!0,W(o),b("Failed %s type: %s",t,l.message),W(null))}}(r,e.props,"prop",n,e)}else void 0===t.PropTypes||Q||(Q=!0,b("Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?",k(t)||"Unknown"));"function"!=typeof t.getDefaultProps||t.getDefaultProps.isReactClassApproved||b("getDefaultProps is only used on classic React.createClass definitions. Use a static property named `defaultProps` instead.")}}var ce={};function ue(e,t,o,h,g,v){var w=function(e){return"string"==typeof e||"function"==typeof e||e===s||e===l||e===a||e===p||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===y||e.$$typeof===d||e.$$typeof===i||e.$$typeof===c||e.$$typeof===u||e.$$typeof===r||void 0!==e.getModuleId)}(e);if(!w){var _,E="";(void 0===e||"object"==typeof e&&null!==e&&0===Object.keys(e).length)&&(E+=" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports."),E+=oe(),null===e?_="null":Y(e)?_="array":void 0!==e&&e.$$typeof===n?(_="<"+(k(e.type)||"Unknown")+" />",E=" Did you accidentally export a JSX literal instead of a component?"):_=typeof e,b("React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",_,E)}var j=Z(e,t,o,g,v);if(null==j)return j;if(w){var x=t.children;if(void 0!==x)if(h)if(Y(x)){for(var O=0;O<x.length;O++)le(x[O],e);Object.freeze&&Object.freeze(x)}else b("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else le(x,e)}if(A.call(t,"key")){var S=k(e),T=Object.keys(t).filter(function(e){return"key"!==e}),R=T.length>0?"{key: someKey, "+T.join(": ..., ")+": ...}":"{key: someKey}";ce[S+R]||(b('A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',R,S,T.length>0?"{"+T.join(": ..., ")+": ...}":"{}",S),ce[S+R]=!0)}return e===s?function(e){for(var r=Object.keys(e.props),t=0;t<r.length;t++){var n=r[t];if("children"!==n&&"key"!==n){te(e),b("Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.",n),te(null);break}}null!==e.ref&&(te(e),b("Invalid attribute `ref` supplied to `React.Fragment`."),te(null))}(j):ie(j),j}var pe=function(e,r,t){return ue(e,r,t,!1)},fe=function(e,r,t){return ue(e,r,t,!0)};v.Fragment=s,v.jsx=pe,v.jsxs=fe}()),v);var w=h.exports;const k=({html:r,options:t={},className:n,style:o,fallback:s=null,showErrors:a=!1})=>{const l=e.useMemo(()=>{try{return y(r,t)}catch(e){return a&&console.error("HtmlParser error:",e),null}},[r,t,a]);return l?n||o?w.jsx("div",{className:n,style:o,children:l}):w.jsx(w.Fragment,{children:l}):w.jsx(w.Fragment,{children:s})};exports.AsyncHtmlParser=r=>w.jsx(e.Suspense,{fallback:r.fallback||w.jsx("div",{children:"Loading..."}),children:w.jsx(k,{...r})}),exports.DEFAULT_SECURITY_CONFIG=o,exports.HtmlParser=k,exports.HtmlParserStatic=({html:e,options:r={},className:t,style:n,fallback:o=null,showErrors:s=!1})=>{let a=null;try{a=y(e,r)}catch(e){s&&console.error("HtmlParserStatic error:",e)}return a?t||n?w.jsx("div",{className:t,style:n,children:a}):w.jsx(w.Fragment,{children:a}):w.jsx(w.Fragment,{children:o})},exports.SSRHtmlParser=({html:e,options:r={},className:t,style:n,fallback:o=null,showErrors:s=!1})=>{let a=null;try{a=y(e,r)}catch(e){s&&console.error("SSRHtmlParser error:",e)}return a?t||n?w.jsx("div",{className:t,style:n,children:a}):w.jsx(w.Fragment,{children:a}):w.jsx(w.Fragment,{children:o})},exports.createIsomorphicDOMParser=r,exports.decodeHtmlEntities=u,exports.default=k,exports.isDangerousAttribute=a,exports.isDangerousTag=l,exports.isDangerousUrl=s,exports.isomorphicDOMParser=t,exports.parseHTML=n,exports.parseHtmlToElement=y,exports.parseHtmlToReact=d,exports.parseHtmlToReactElement=function(e,r={}){try{return y(e,r)}catch(e){return console.error("parseHtmlToReactElement error:",e),null}},exports.parseHtmlToReactElements=function(e,r={}){try{const t=y(e,r);return t?[t]:[]}catch(e){return console.error("parseHtmlToReactElements error:",e),[]}},exports.sanitizeAttributes=i,exports.sanitizeStyles=c;
//# sourceMappingURL=index.min.js.map