@@ -31,6 +31,108 @@ const OPTION_VALUES = [
31
31
] ;
32
32
const DEFAULT_CONFIG = { props : OPTION_NEVER , children : OPTION_NEVER , propElementValues : OPTION_IGNORE } ;
33
33
34
+ const HTML_ENTITY_REGEX = ( ) => / & [ A - Z a - z \d # ] + ; / g;
35
+
36
+ function containsLineTerminators ( rawStringValue ) {
37
+ return / [ \n \r \u2028 \u2029 ] / . test ( rawStringValue ) ;
38
+ }
39
+
40
+ function containsBackslash ( rawStringValue ) {
41
+ return arrayIncludes ( rawStringValue , '\\' ) ;
42
+ }
43
+
44
+ function containsHTMLEntity ( rawStringValue ) {
45
+ return HTML_ENTITY_REGEX ( ) . test ( rawStringValue ) ;
46
+ }
47
+
48
+ function containsOnlyHtmlEntities ( rawStringValue ) {
49
+ return rawStringValue . replace ( HTML_ENTITY_REGEX ( ) , '' ) . trim ( ) === '' ;
50
+ }
51
+
52
+ function containsDisallowedJSXTextChars ( rawStringValue ) {
53
+ return / [ { < > } ] / . test ( rawStringValue ) ;
54
+ }
55
+
56
+ function containsQuoteCharacters ( value ) {
57
+ return / [ ' " ] / . test ( value ) ;
58
+ }
59
+
60
+ function containsMultilineComment ( value ) {
61
+ return / \/ \* / . test ( value ) ;
62
+ }
63
+
64
+ function escapeDoubleQuotes ( rawStringValue ) {
65
+ return rawStringValue . replace ( / \\ " / g, '"' ) . replace ( / " / g, '\\"' ) ;
66
+ }
67
+
68
+ function escapeBackslashes ( rawStringValue ) {
69
+ return rawStringValue . replace ( / \\ / g, '\\\\' ) ;
70
+ }
71
+
72
+ function needToEscapeCharacterForJSX ( raw , node ) {
73
+ return (
74
+ containsBackslash ( raw )
75
+ || containsHTMLEntity ( raw )
76
+ || ( node . parent . type !== 'JSXAttribute' && containsDisallowedJSXTextChars ( raw ) )
77
+ ) ;
78
+ }
79
+
80
+ function containsWhitespaceExpression ( child ) {
81
+ if ( child . type === 'JSXExpressionContainer' ) {
82
+ const value = child . expression . value ;
83
+ return value ? jsxUtil . isWhiteSpaces ( value ) : false ;
84
+ }
85
+ return false ;
86
+ }
87
+
88
+ function isLineBreak ( text ) {
89
+ return containsLineTerminators ( text ) && text . trim ( ) === '' ;
90
+ }
91
+
92
+ function wrapNonHTMLEntities ( text ) {
93
+ const HTML_ENTITY = '<HTML_ENTITY>' ;
94
+ const withCurlyBraces = text . split ( HTML_ENTITY_REGEX ( ) ) . map ( ( word ) => (
95
+ word === '' ? '' : `{${ JSON . stringify ( word ) } }`
96
+ ) ) . join ( HTML_ENTITY ) ;
97
+
98
+ const htmlEntities = text . match ( HTML_ENTITY_REGEX ( ) ) ;
99
+ return htmlEntities . reduce ( ( acc , htmlEntity ) => (
100
+ acc . replace ( HTML_ENTITY , htmlEntity )
101
+ ) , withCurlyBraces ) ;
102
+ }
103
+
104
+ function wrapWithCurlyBraces ( rawText ) {
105
+ if ( ! containsLineTerminators ( rawText ) ) {
106
+ return `{${ JSON . stringify ( rawText ) } }` ;
107
+ }
108
+
109
+ return rawText . split ( '\n' ) . map ( ( line ) => {
110
+ if ( line . trim ( ) === '' ) {
111
+ return line ;
112
+ }
113
+ const firstCharIndex = line . search ( / [ ^ \s ] / ) ;
114
+ const leftWhitespace = line . slice ( 0 , firstCharIndex ) ;
115
+ const text = line . slice ( firstCharIndex ) ;
116
+
117
+ if ( containsHTMLEntity ( line ) ) {
118
+ return `${ leftWhitespace } ${ wrapNonHTMLEntities ( text ) } ` ;
119
+ }
120
+ return `${ leftWhitespace } {${ JSON . stringify ( text ) } }` ;
121
+ } ) . join ( '\n' ) ;
122
+ }
123
+
124
+ function isWhiteSpaceLiteral ( node ) {
125
+ return node . type && node . type === 'Literal' && node . value && jsxUtil . isWhiteSpaces ( node . value ) ;
126
+ }
127
+
128
+ function isStringWithTrailingWhiteSpaces ( value ) {
129
+ return / ^ \s | \s $ / . test ( value ) ;
130
+ }
131
+
132
+ function isLiteralWithTrailingWhiteSpaces ( node ) {
133
+ return node . type && node . type === 'Literal' && node . value && isStringWithTrailingWhiteSpaces ( node . value ) ;
134
+ }
135
+
34
136
// ------------------------------------------------------------------------------
35
137
// Rule Definition
36
138
// ------------------------------------------------------------------------------
@@ -74,100 +176,11 @@ module.exports = {
74
176
} ,
75
177
76
178
create ( context ) {
77
- const HTML_ENTITY_REGEX = ( ) => / & [ A - Z a - z \d # ] + ; / g;
78
179
const ruleOptions = context . options [ 0 ] ;
79
180
const userConfig = typeof ruleOptions === 'string'
80
181
? { props : ruleOptions , children : ruleOptions , propElementValues : OPTION_IGNORE }
81
182
: Object . assign ( { } , DEFAULT_CONFIG , ruleOptions ) ;
82
183
83
- function containsLineTerminators ( rawStringValue ) {
84
- return / [ \n \r \u2028 \u2029 ] / . test ( rawStringValue ) ;
85
- }
86
-
87
- function containsBackslash ( rawStringValue ) {
88
- return arrayIncludes ( rawStringValue , '\\' ) ;
89
- }
90
-
91
- function containsHTMLEntity ( rawStringValue ) {
92
- return HTML_ENTITY_REGEX ( ) . test ( rawStringValue ) ;
93
- }
94
-
95
- function containsOnlyHtmlEntities ( rawStringValue ) {
96
- return rawStringValue . replace ( HTML_ENTITY_REGEX ( ) , '' ) . trim ( ) === '' ;
97
- }
98
-
99
- function containsDisallowedJSXTextChars ( rawStringValue ) {
100
- return / [ { < > } ] / . test ( rawStringValue ) ;
101
- }
102
-
103
- function containsQuoteCharacters ( value ) {
104
- return / [ ' " ] / . test ( value ) ;
105
- }
106
-
107
- function containsMultilineComment ( value ) {
108
- return / \/ \* / . test ( value ) ;
109
- }
110
-
111
- function escapeDoubleQuotes ( rawStringValue ) {
112
- return rawStringValue . replace ( / \\ " / g, '"' ) . replace ( / " / g, '\\"' ) ;
113
- }
114
-
115
- function escapeBackslashes ( rawStringValue ) {
116
- return rawStringValue . replace ( / \\ / g, '\\\\' ) ;
117
- }
118
-
119
- function needToEscapeCharacterForJSX ( raw , node ) {
120
- return (
121
- containsBackslash ( raw )
122
- || containsHTMLEntity ( raw )
123
- || ( node . parent . type !== 'JSXAttribute' && containsDisallowedJSXTextChars ( raw ) )
124
- ) ;
125
- }
126
-
127
- function containsWhitespaceExpression ( child ) {
128
- if ( child . type === 'JSXExpressionContainer' ) {
129
- const value = child . expression . value ;
130
- return value ? jsxUtil . isWhiteSpaces ( value ) : false ;
131
- }
132
- return false ;
133
- }
134
-
135
- function isLineBreak ( text ) {
136
- return containsLineTerminators ( text ) && text . trim ( ) === '' ;
137
- }
138
-
139
- function wrapNonHTMLEntities ( text ) {
140
- const HTML_ENTITY = '<HTML_ENTITY>' ;
141
- const withCurlyBraces = text . split ( HTML_ENTITY_REGEX ( ) ) . map ( ( word ) => (
142
- word === '' ? '' : `{${ JSON . stringify ( word ) } }`
143
- ) ) . join ( HTML_ENTITY ) ;
144
-
145
- const htmlEntities = text . match ( HTML_ENTITY_REGEX ( ) ) ;
146
- return htmlEntities . reduce ( ( acc , htmlEntity ) => (
147
- acc . replace ( HTML_ENTITY , htmlEntity )
148
- ) , withCurlyBraces ) ;
149
- }
150
-
151
- function wrapWithCurlyBraces ( rawText ) {
152
- if ( ! containsLineTerminators ( rawText ) ) {
153
- return `{${ JSON . stringify ( rawText ) } }` ;
154
- }
155
-
156
- return rawText . split ( '\n' ) . map ( ( line ) => {
157
- if ( line . trim ( ) === '' ) {
158
- return line ;
159
- }
160
- const firstCharIndex = line . search ( / [ ^ \s ] / ) ;
161
- const leftWhitespace = line . slice ( 0 , firstCharIndex ) ;
162
- const text = line . slice ( firstCharIndex ) ;
163
-
164
- if ( containsHTMLEntity ( line ) ) {
165
- return `${ leftWhitespace } ${ wrapNonHTMLEntities ( text ) } ` ;
166
- }
167
- return `${ leftWhitespace } {${ JSON . stringify ( text ) } }` ;
168
- } ) . join ( '\n' ) ;
169
- }
170
-
171
184
/**
172
185
* Report and fix an unnecessary curly brace violation on a node
173
186
* @param {ASTNode } JSXExpressionNode - The AST node with an unnecessary JSX expression
@@ -233,18 +246,6 @@ module.exports = {
233
246
} ) ;
234
247
}
235
248
236
- function isWhiteSpaceLiteral ( node ) {
237
- return node . type && node . type === 'Literal' && node . value && jsxUtil . isWhiteSpaces ( node . value ) ;
238
- }
239
-
240
- function isStringWithTrailingWhiteSpaces ( value ) {
241
- return / ^ \s | \s $ / . test ( value ) ;
242
- }
243
-
244
- function isLiteralWithTrailingWhiteSpaces ( node ) {
245
- return node . type && node . type === 'Literal' && node . value && isStringWithTrailingWhiteSpaces ( node . value ) ;
246
- }
247
-
248
249
// Bail out if there is any character that needs to be escaped in JSX
249
250
// because escaping decreases readability and the original code may be more
250
251
// readable anyway or intentional for other specific reasons
0 commit comments