@@ -64,9 +64,17 @@ function isSafeUrl(url) {
6464 }
6565}
6666
67+ function isExternalHttpUrl ( url ) {
68+ try {
69+ const parsed = new URL ( url , window . location . href ) ;
70+ return [ "http:" , "https:" ] . includes ( parsed . protocol ) && parsed . origin !== window . location . origin ;
71+ } catch ( e ) {
72+ return false ;
73+ }
74+ }
75+
6776function sanitizeHtml ( html ) {
68- const template = document . createElement ( "template" ) ;
69- template . innerHTML = html ;
77+ const parsedHtml = new DOMParser ( ) . parseFromString ( String ( html || "" ) , "text/html" ) ;
7078
7179 const sanitizeNode = node => {
7280 if ( node . nodeType === Node . TEXT_NODE ) {
@@ -91,7 +99,7 @@ function sanitizeHtml(html) {
9199
92100 Array . from ( node . attributes ) . forEach ( attr => {
93101 const attrName = attr . name . toLowerCase ( ) ;
94- if ( ! allowedAttrs . has ( attr . name ) ) {
102+ if ( ! allowedAttrs . has ( attrName ) ) {
95103 return ;
96104 }
97105
@@ -103,8 +111,11 @@ function sanitizeHtml(html) {
103111 } ) ;
104112
105113 if ( tagName === "A" && clean . hasAttribute ( "href" ) ) {
106- clean . setAttribute ( "rel" , "noopener noreferrer" ) ;
107- clean . setAttribute ( "target" , "_blank" ) ;
114+ const href = clean . getAttribute ( "href" ) ;
115+ if ( isExternalHttpUrl ( href ) ) {
116+ clean . setAttribute ( "rel" , "noopener noreferrer" ) ;
117+ clean . setAttribute ( "target" , "_blank" ) ;
118+ }
108119 }
109120
110121 Array . from ( node . childNodes ) . forEach ( child => {
@@ -115,7 +126,7 @@ function sanitizeHtml(html) {
115126 } ;
116127
117128 const fragment = document . createDocumentFragment ( ) ;
118- Array . from ( template . content . childNodes ) . forEach ( child => {
129+ Array . from ( parsedHtml . body . childNodes ) . forEach ( child => {
119130 fragment . appendChild ( sanitizeNode ( child ) ) ;
120131 } ) ;
121132 return fragment ;
@@ -725,7 +736,7 @@ function render() {
725736 const app = document . getElementById ( "app" ) ;
726737 if ( ! app ) return ;
727738
728- app . innerHTML = "" ;
739+ app . replaceChildren ( ) ;
729740
730741 const currentId = state . currentNodeId || treeConfig . root ;
731742 const nodeRaw = treeConfig . nodes [ currentId ] ;
0 commit comments