@@ -13,7 +13,7 @@ const { defaultOptions, defaultTime } = D;
13
13
import G from './Globals.js' ;
14
14
const { doc } = G ;
15
15
import U from './Utilities.js' ;
16
- const { extend, getNestedProperty, isArray, isNumber, isObject, pick, ucfirst } = U ;
16
+ const { extend, getNestedProperty, isArray, isNumber, isObject, isString , pick, ucfirst } = U ;
17
17
const helpers = {
18
18
// Built-in helpers
19
19
add : ( a , b ) => a + b ,
@@ -48,6 +48,8 @@ const numberFormatCache = {};
48
48
* Functions
49
49
*
50
50
* */
51
+ // Internal convenience function
52
+ const isQuotedString = ( str ) => / ^ [ " ' ] .+ [ " ' ] $ / . test ( str ) ;
51
53
/**
52
54
* Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a
53
55
* human readable date string. The format is a subset of the formats for PHP's
@@ -125,11 +127,11 @@ function dateFormat(format, timestamp, upperCaseFirst) {
125
127
* The formatted string.
126
128
*/
127
129
function format ( str = '' , ctx , chart ) {
128
- const regex = / \{ ( [ \p{ L} \d : \. , ; \- \/ < > \[ \] % _ @ " ' ’ = # \( \) ] + ) \} / gu,
130
+ const regex = / \{ ( [ \p{ L} \d : \. , ; \- \/ < > \[ \] % _ @ + " ' ’ = # \( \) ] + ) \} / gu,
129
131
// The sub expression regex is the same as the top expression regex,
130
132
// but except parens and block helpers (#), and surrounded by parens
131
133
// instead of curly brackets.
132
- subRegex = / \( ( [ \p{ L} \d : \. , ; \- \/ < > \[ \] % _ @ " ' = ] + ) \) / gu, matches = [ ] , floatRegex = / f $ / , decRegex = / \. ( \d ) / , lang = chart ?. options . lang || defaultOptions . lang , time = chart && chart . time || defaultTime , numberFormatter = chart && chart . numberFormatter || numberFormat ;
134
+ subRegex = / \( ( [ \p{ L} \d : \. , ; \- \/ < > \[ \] % _ @ + " ' = ] + ) \) / gu, matches = [ ] , floatRegex = / f $ / , decRegex = / \. ( \d ) / , lang = chart ?. options . lang || defaultOptions . lang , time = chart && chart . time || defaultTime , numberFormatter = chart && chart . numberFormatter || numberFormat ;
133
135
/*
134
136
* Get a literal or variable value inside a template expression. May be
135
137
* extended with other types like string or null if needed, but keep it
@@ -147,7 +149,7 @@ function format(str = '', ctx, chart) {
147
149
if ( ( n = Number ( key ) ) . toString ( ) === key ) {
148
150
return n ;
149
151
}
150
- if ( / ^ [ " ' ] . + [ " ' ] $ / . test ( key ) ) {
152
+ if ( isQuotedString ( key ) ) {
151
153
return key . slice ( 1 , - 1 ) ;
152
154
}
153
155
// Variables and constants
@@ -260,7 +262,8 @@ function format(str = '', ctx, chart) {
260
262
// Simple variable replacement
261
263
}
262
264
else {
263
- const valueAndFormat = expression . split ( ':' ) ;
265
+ const valueAndFormat = isQuotedString ( expression ) ?
266
+ [ expression ] : expression . split ( ':' ) ;
264
267
replacement = resolveProperty ( valueAndFormat . shift ( ) || '' ) ;
265
268
// Format the replacement
266
269
if ( valueAndFormat . length && typeof replacement === 'number' ) {
@@ -273,13 +276,14 @@ function format(str = '', ctx, chart) {
273
276
}
274
277
else {
275
278
replacement = time . dateFormat ( segment , replacement ) ;
276
- // Use string literal in order to be preserved in the outer
277
- // expression
278
- if ( hasSub ) {
279
- replacement = `"${ replacement } "` ;
280
- }
281
279
}
282
280
}
281
+ // Use string literal in order to be preserved in the outer
282
+ // expression
283
+ subRegex . lastIndex = 0 ;
284
+ if ( subRegex . test ( match . find ) && isString ( replacement ) ) {
285
+ replacement = `"${ replacement } "` ;
286
+ }
283
287
}
284
288
str = str . replace ( match . find , pick ( replacement , '' ) ) ;
285
289
} ) ;
0 commit comments