Skip to content

Commit 5f3670f

Browse files
committed
Add fallback value for template strings
1 parent 75b157f commit 5f3670f

File tree

1 file changed

+31
-45
lines changed

1 file changed

+31
-45
lines changed

src/lib/index.js

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,23 +1074,19 @@ lib.templateString = function (string, obj) {
10741074
});
10751075
};
10761076

1077-
var hovertemplateWarnings = {
1077+
const hovertemplateWarnings = {
10781078
max: 10,
10791079
count: 0,
10801080
name: 'hovertemplate'
10811081
};
1082-
lib.hovertemplateString = function () {
1083-
return templateFormatString.apply(hovertemplateWarnings, arguments);
1084-
};
1082+
lib.hovertemplateString = (params) => templateFormatString({ ...params, opts: hovertemplateWarnings });
10851083

1086-
var texttemplateWarnings = {
1084+
const texttemplateWarnings = {
10871085
max: 10,
10881086
count: 0,
10891087
name: 'texttemplate'
10901088
};
1091-
lib.texttemplateString = function () {
1092-
return templateFormatString.apply(texttemplateWarnings, arguments);
1093-
};
1089+
lib.texttemplateString = (params) => templateFormatString({ ...params, opts: texttemplateWarnings });
10941090

10951091
// Regex for parsing multiplication and division operations applied to a template key
10961092
// Used for shape.label.texttemplate
@@ -1108,66 +1104,57 @@ var texttemplateWarningsForShapes = {
11081104
name: 'texttemplate',
11091105
parseMultDiv: true
11101106
};
1111-
lib.texttemplateStringForShapes = function () {
1112-
return templateFormatString.apply(texttemplateWarningsForShapes, arguments);
1113-
};
1107+
lib.texttemplateStringForShapes = (params) => templateFormatString({ ...params, opts: texttemplateWarningsForShapes });
11141108

11151109
var TEMPLATE_STRING_FORMAT_SEPARATOR = /^[:|\|]/;
11161110
/**
11171111
* Substitute values from an object into a string and optionally formats them using d3-format,
11181112
* or fallback to associated labels.
11191113
*
11201114
* Examples:
1121-
* Lib.hovertemplateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf'
1122-
* Lib.hovertemplateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf'
1123-
* Lib.hovertemplateString('price: %{y:$.2f}', {y: 1}) --> 'price: $1.00'
1115+
* Lib.hovertemplateString({ string 'name: %{trace}', labels: {trace: 'asdf'} }) --> 'name: asdf'
1116+
* Lib.hovertemplateString({ string: 'name: %{trace[0].name}', labels: { trace: [{ name: 'asdf' }] } }) --> 'name: asdf'
1117+
* Lib.hovertemplateString({ string: 'price: %{y:$.2f}', labels: { y: 1 } }) --> 'price: $1.00'
11241118
*
1125-
* @param {string} input string containing %{...:...} template strings
1126-
* @param {obj} data object containing fallback text when no formatting is specified, ex.: {yLabel: 'formattedYValue'}
1127-
* @param {obj} d3 locale
1128-
* @param {obj} data objects containing substitution values
1119+
* @param {object} options - Configuration object
1120+
* @param {array} options.args - Data objects containing substitution values
1121+
* @param {object} options.d3locale - D3 locale for formatting
1122+
* @param {string} options.fallback - Fallback value when substitution fails
1123+
* @param {object} options.labels - Data object containing fallback text when no formatting is specified, ex.: {yLabel: 'formattedYValue'}
1124+
* @param {object} options.opts - Additional options
1125+
* @param {string} options.string - Input string containing %{...:...} template strings
11291126
*
11301127
* @return {string} templated string
11311128
*/
1132-
function templateFormatString(string, labels, d3locale) {
1133-
var opts = this;
1134-
var args = arguments;
1135-
if (!labels) labels = {};
1136-
1137-
return string.replace(lib.TEMPLATE_STRING_REGEX, function (match, rawKey, format) {
1138-
var isOther = rawKey === 'xother' || rawKey === 'yother';
1139-
1140-
var isSpaceOther = rawKey === '_xother' || rawKey === '_yother';
1141-
1142-
var isSpaceOtherSpace = rawKey === '_xother_' || rawKey === '_yother_';
1143-
1144-
var isOtherSpace = rawKey === 'xother_' || rawKey === 'yother_';
1145-
1146-
var hasOther = isOther || isSpaceOther || isOtherSpace || isSpaceOtherSpace;
1147-
1148-
var key = rawKey;
1129+
function templateFormatString({ args = [], d3locale, fallback, labels = {}, opts, string }) {
1130+
return string.replace(lib.TEMPLATE_STRING_REGEX, (_, rawKey, format) => {
1131+
const isOther = ['xother', 'yother'].includes(rawKey);
1132+
const isSpaceOther = ['_xother', '_yother'].includes(rawKey);
1133+
const isSpaceOtherSpace = ['_xother_', '_yother_'].includes(rawKey);
1134+
const isOtherSpace = ['xother_', 'yother_'].includes(rawKey);
1135+
const hasOther = isOther || isSpaceOther || isOtherSpace || isSpaceOtherSpace;
1136+
1137+
let key = rawKey;
11491138
if (isSpaceOther || isSpaceOtherSpace) key = key.substring(1);
11501139
if (isOtherSpace || isSpaceOtherSpace) key = key.substring(0, key.length - 1);
11511140

11521141
// Shape labels support * and / operators in template string
11531142
// Parse these if the parseMultDiv param is set to true
1154-
var parsedOp = null;
1155-
var parsedNumber = null;
1143+
let parsedOp = null;
1144+
let parsedNumber = null;
11561145
if (opts.parseMultDiv) {
11571146
var _match = multDivParser(key);
11581147
key = _match.key;
11591148
parsedOp = _match.op;
11601149
parsedNumber = _match.number;
11611150
}
11621151

1163-
var value;
1152+
let value;
11641153
if (hasOther) {
1154+
if (labels[key] === undefined) return '';
11651155
value = labels[key];
1166-
if (value === undefined) return '';
11671156
} else {
1168-
var obj, i;
1169-
for (i = 3; i < args.length; i++) {
1170-
obj = args[i];
1157+
for (const obj of args) {
11711158
if (!obj) continue;
11721159
if (obj.hasOwnProperty(key)) {
11731160
value = obj[key];
@@ -1184,12 +1171,11 @@ function templateFormatString(string, labels, d3locale) {
11841171

11851172
if (value === undefined) {
11861173
const { count, max, name } = opts;
1187-
if (count < max) lib.warn(`Variable '${key}' in ${name} could not be found!`);
1174+
if (count < max) lib.warn(`Variable '${key}' in ${name} could not be found! Using fallback value.`);
11881175
if (count === max) lib.warn(`Too many '${name}' warnings - additional warnings will be suppressed`);
11891176
opts.count++;
11901177

1191-
// TODO: Make return valuable configurable with a reasonable default (like 'N/A')
1192-
return '';
1178+
return fallback;
11931179
}
11941180

11951181
if (parsedOp === '*') value *= parsedNumber;

0 commit comments

Comments
 (0)