diff --git a/packages/draft-js-export-html/src/stateToHTML.js b/packages/draft-js-export-html/src/stateToHTML.js index 4b90501a..0e19e899 100644 --- a/packages/draft-js-export-html/src/stateToHTML.js +++ b/packages/draft-js-export-html/src/stateToHTML.js @@ -5,6 +5,7 @@ import normalizeAttributes from './helpers/normalizeAttributes'; import styleToCSS from './helpers/styleToCSS'; import { + isAllowedHref, getEntityRanges, BLOCK_TYPE, ENTITY_TYPE, @@ -84,7 +85,7 @@ const ENTITY_ATTR_MAP: {[entityType: string]: AttrMap} = { // Map entity data to element attributes. const DATA_TO_ATTR = { - [ENTITY_TYPE.LINK](entityType: string, entity: EntityInstance): Attributes { + [ENTITY_TYPE.LINK](entityType: string, entity: EntityInstance): ?Attributes { let attrMap = ENTITY_ATTR_MAP.hasOwnProperty(entityType) ? ENTITY_ATTR_MAP[entityType] : {}; @@ -94,6 +95,9 @@ const DATA_TO_ATTR = { let dataValue = data[dataKey]; if (attrMap.hasOwnProperty(dataKey)) { let attrKey = attrMap[dataKey]; + if (attrKey === 'href' && !isAllowedHref(dataValue)) { + return null; + } attrs[attrKey] = dataValue; } else if (DATA_ATTRIBUTE.test(dataKey)) { attrs[dataKey] = dataValue; @@ -101,7 +105,7 @@ const DATA_TO_ATTR = { } return attrs; }, - [ENTITY_TYPE.IMAGE](entityType: string, entity: EntityInstance): Attributes { + [ENTITY_TYPE.IMAGE](entityType: string, entity: EntityInstance): ?Attributes { let attrMap = ENTITY_ATTR_MAP.hasOwnProperty(entityType) ? ENTITY_ATTR_MAP[entityType] : {}; @@ -403,6 +407,9 @@ class MarkupGenerator { let attrs = DATA_TO_ATTR.hasOwnProperty(entityType) ? DATA_TO_ATTR[entityType](entityType, entity) : null; + if (attrs == null) { + return content; + } let attrString = stringifyAttrs(attrs); return `${content}`; } else if (entityType != null && entityType === ENTITY_TYPE.IMAGE) { diff --git a/packages/draft-js-export-html/test/test-cases.txt b/packages/draft-js-export-html/test/test-cases.txt index 4a73cd0e..45e89555 100644 --- a/packages/draft-js-export-html/test/test-cases.txt +++ b/packages/draft-js-export-html/test/test-cases.txt @@ -26,6 +26,10 @@ {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"url":"/","rel":null,"title":"hi","extra":"foo","data-id":42,"data-mutability":"mutable","data-False":"bad","data-":"no"}}},"blocks":[{"key":"8r91j","text":"a","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":1,"style":"ITALIC"}],"entityRanges":[{"offset":0,"length":1,"key":0}]}]}
+# Link as text if it has unsafe data URI +{"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"href":"data:text/html;base64,PHNjcmlwdD5hbGVydCgieHNzIik8L3NjcmlwdD4="}}},"blocks":[{"key":"33nh8","text":"x","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":0,"length":1,"key":0}]}]} +x
+ # Entity with inline style {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"url":"/"}}},"blocks":[{"key":"8r91j","text":"a","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":1,"style":"ITALIC"}],"entityRanges":[{"offset":0,"length":1,"key":0}]}]} diff --git a/packages/draft-js-export-markdown/src/stateToMarkdown.js b/packages/draft-js-export-markdown/src/stateToMarkdown.js index 02275d52..a039bdbe 100644 --- a/packages/draft-js-export-markdown/src/stateToMarkdown.js +++ b/packages/draft-js-export-markdown/src/stateToMarkdown.js @@ -1,6 +1,7 @@ // @flow import { + isAllowedHref, getEntityRanges, BLOCK_TYPE, ENTITY_TYPE, @@ -216,6 +217,9 @@ class MarkupGenerator { let entity = entityKey ? contentState.getEntity(entityKey) : null; if (entity != null && entity.getType() === ENTITY_TYPE.LINK) { let data = entity.getData(); + if (!isAllowedHref(data.url)) { + return content; + } let url = data.url || ''; let title = data.title ? ` "${escapeTitle(data.title)}"` : ''; return `[${content}](${encodeURL(url)}${title})`; diff --git a/packages/draft-js-export-markdown/test/test-cases.txt b/packages/draft-js-export-markdown/test/test-cases.txt index 799d13a0..394e47d7 100644 --- a/packages/draft-js-export-markdown/test/test-cases.txt +++ b/packages/draft-js-export-markdown/test/test-cases.txt @@ -38,6 +38,10 @@ Hello [World](/a). {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"url":"/a","title":"f\"oo"}}},"blocks":[{"key":"2m141","text":"Hello World.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":6,"length":5,"key":0}]}]} Hello [World](/a "f\"oo"). +>> Link as text if it has unsafe data URI +{"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"url":"data:text/html;base64,PHNjcmlwdD5hbGVydCgieHNzIik8L3NjcmlwdD4="}}},"blocks":[{"key":"2m141","text":"Hello World.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":6,"length":5,"key":0}]}]} +Hello World. + >> Ordered List {"entityMap":{},"blocks":[{"key":"33nh8","text":"An ordered list:","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[]},{"key":"8kinl","text":"One","type":"ordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[]},{"key":"ekll4","text":"Two","type":"ordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[]}]} An ordered list: diff --git a/packages/draft-js-import-element/src/stateFromElement.js b/packages/draft-js-import-element/src/stateFromElement.js index 3fac7735..da8f5c8f 100644 --- a/packages/draft-js-import-element/src/stateFromElement.js +++ b/packages/draft-js-import-element/src/stateFromElement.js @@ -3,7 +3,7 @@ import replaceTextWithMeta from './lib/replaceTextWithMeta'; import {CharacterMetadata, ContentBlock, ContentState, genKey} from 'draft-js'; import {List, Map, OrderedSet, Repeat, Seq} from 'immutable'; -import {BLOCK_TYPE, ENTITY_TYPE, INLINE_STYLE} from 'draft-js-utils'; +import {isAllowedHref, BLOCK_TYPE, ENTITY_TYPE, INLINE_STYLE} from 'draft-js-utils'; import {NODE_TYPE_ELEMENT, NODE_TYPE_TEXT} from 'synthetic-dom'; import { INLINE_ELEMENTS, @@ -86,7 +86,6 @@ type Options = { }; type DataMap