@@ -2,8 +2,9 @@ import config from './config'
2
2
import * as string from './util/string'
3
3
import * as nodeType from './node-type'
4
4
import * as quotes from './quotes'
5
+ import { isPlainTextBlock } from './block'
5
6
6
- let allowedElements , requiredAttributes , transformElements , blockLevelElements , replaceQuotes
7
+ let allowedElements , allowedPlainTextElements , requiredAttributes , transformElements , blockLevelElements , replaceQuotes
7
8
let splitIntoBlocks , blacklistedElements
8
9
const whitespaceOnly = / ^ \s * $ /
9
10
const blockPlaceholder = '<!-- BLOCK -->'
@@ -13,6 +14,7 @@ updateConfig(config)
13
14
export function updateConfig ( conf ) {
14
15
const rules = conf . pastedHtmlRules
15
16
allowedElements = rules . allowedElements || { }
17
+ allowedPlainTextElements = rules . allowedPlainTextElements || { }
16
18
requiredAttributes = rules . requiredAttributes || { }
17
19
transformElements = rules . transformElements || { }
18
20
blacklistedElements = rules . blacklistedElements || [ ]
@@ -25,9 +27,9 @@ export function updateConfig (conf) {
25
27
rules . splitIntoBlocks . forEach ( ( name ) => { splitIntoBlocks [ name ] = true } )
26
28
}
27
29
28
- export function paste ( element , cursor , clipboardContent ) {
29
- const document = element . ownerDocument
30
- element . setAttribute ( config . pastingAttribute , true )
30
+ export function paste ( block , cursor , clipboardContent ) {
31
+ const document = block . ownerDocument
32
+ block . setAttribute ( config . pastingAttribute , true )
31
33
32
34
if ( cursor . isSelection ) {
33
35
cursor = cursor . deleteExactSurroundingTags ( )
@@ -39,9 +41,10 @@ export function paste (element, cursor, clipboardContent) {
39
41
const pasteHolder = document . createElement ( 'div' )
40
42
pasteHolder . innerHTML = clipboardContent
41
43
42
- const blocks = parseContent ( pasteHolder )
44
+ const isPlainText = isPlainTextBlock ( block )
45
+ const blocks = parseContent ( pasteHolder , { plainText : isPlainText } )
43
46
44
- element . removeAttribute ( config . pastingAttribute )
47
+ block . removeAttribute ( config . pastingAttribute )
45
48
return { blocks, cursor}
46
49
}
47
50
@@ -55,30 +58,35 @@ export function paste (element, cursor, clipboardContent) {
55
58
* @param {DOM node } A container where the pasted content is located.
56
59
* @returns {Array of Strings } An array of cleaned innerHTML like strings.
57
60
*/
58
- export function parseContent ( element ) {
61
+ export function parseContent ( element , { plainText = false } = { } ) {
62
+ const options = {
63
+ allowedElements : plainText ? allowedPlainTextElements : allowedElements ,
64
+ keepInternalRelativeLinks : plainText ? false : keepInternalRelativeLinks
65
+ }
66
+
59
67
// Filter pasted content
60
- return filterHtmlElements ( element )
68
+ return filterHtmlElements ( element , options )
61
69
// Handle Blocks
62
70
. split ( blockPlaceholder )
63
71
. map ( ( entry ) => string . trim ( cleanWhitespace ( replaceAllQuotes ( entry ) ) ) )
64
72
. filter ( ( entry ) => ! whitespaceOnly . test ( entry ) )
65
73
}
66
74
67
- export function filterHtmlElements ( elem ) {
75
+ function filterHtmlElements ( elem , options ) {
68
76
return Array . from ( elem . childNodes ) . reduce ( ( content , child ) => {
69
77
if ( blacklistedElements . indexOf ( child . nodeName . toLowerCase ( ) ) !== - 1 ) {
70
78
return ''
71
79
}
72
80
73
81
// Keep internal relative links relative (on paste).
74
- if ( keepInternalRelativeLinks && child . nodeName === 'A' && child . href ) {
82
+ if ( options . keepInternalRelativeLinks && child . nodeName === 'A' && child . href ) {
75
83
const stripInternalHost = child . getAttribute ( 'href' ) . replace ( window . location . origin , '' )
76
84
child . setAttribute ( 'href' , stripInternalHost )
77
85
}
78
86
79
87
if ( child . nodeType === nodeType . elementNode ) {
80
- const childContent = filterHtmlElements ( child )
81
- return content + conditionalNodeWrap ( child , childContent )
88
+ const childContent = filterHtmlElements ( child , options )
89
+ return content + conditionalNodeWrap ( child , childContent , options )
82
90
}
83
91
84
92
// Escape HTML characters <, > and &
@@ -87,11 +95,11 @@ export function filterHtmlElements (elem) {
87
95
} , '' )
88
96
}
89
97
90
- export function conditionalNodeWrap ( child , content ) {
98
+ function conditionalNodeWrap ( child , content , options ) {
91
99
let nodeName = child . nodeName . toLowerCase ( )
92
100
nodeName = transformNodeName ( nodeName )
93
101
94
- if ( shouldKeepNode ( nodeName , child ) ) {
102
+ if ( shouldKeepNode ( nodeName , child , options ) ) {
95
103
const attributes = filterAttributes ( nodeName , child )
96
104
97
105
if ( nodeName === 'br' ) return `<${ nodeName + attributes } >`
@@ -115,7 +123,7 @@ export function conditionalNodeWrap (child, content) {
115
123
}
116
124
117
125
// returns string of concatenated attributes e.g. 'target="_blank" rel="nofollow" href="/test.com"'
118
- export function filterAttributes ( nodeName , node ) {
126
+ function filterAttributes ( nodeName , node ) {
119
127
return Array . from ( node . attributes ) . reduce ( ( attributes , { name, value} ) => {
120
128
if ( allowedElements [ nodeName ] [ name ] && value ) {
121
129
return `${ attributes } ${ name } ="${ value } "`
@@ -124,22 +132,22 @@ export function filterAttributes (nodeName, node) {
124
132
} , '' )
125
133
}
126
134
127
- export function transformNodeName ( nodeName ) {
135
+ function transformNodeName ( nodeName ) {
128
136
return transformElements [ nodeName ] || nodeName
129
137
}
130
138
131
- export function hasRequiredAttributes ( nodeName , node ) {
139
+ function hasRequiredAttributes ( nodeName , node ) {
132
140
const requiredAttrs = requiredAttributes [ nodeName ]
133
141
if ( ! requiredAttrs ) return true
134
142
135
143
return ! requiredAttrs . some ( ( name ) => ! node . getAttribute ( name ) )
136
144
}
137
145
138
- export function shouldKeepNode ( nodeName , node ) {
139
- return allowedElements [ nodeName ] && hasRequiredAttributes ( nodeName , node )
146
+ function shouldKeepNode ( nodeName , node , options ) {
147
+ return options . allowedElements [ nodeName ] && hasRequiredAttributes ( nodeName , node )
140
148
}
141
149
142
- export function cleanWhitespace ( str ) {
150
+ function cleanWhitespace ( str ) {
143
151
return str
144
152
. replace ( / \n / g, ' ' )
145
153
. replace ( / { 2 , } / g, ' ' )
@@ -149,7 +157,7 @@ export function cleanWhitespace (str) {
149
157
) )
150
158
}
151
159
152
- export function replaceAllQuotes ( str ) {
160
+ function replaceAllQuotes ( str ) {
153
161
if ( replaceQuotes . quotes || replaceQuotes . singleQuotes || replaceQuotes . apostrophe ) {
154
162
return quotes . replaceAllQuotes ( str , replaceQuotes )
155
163
}
0 commit comments