* Substitute values from an object into a string and optionally formats them using d3-format, * or fallback to associated labels. * * Examples: * Lib.templateFormatString({ template 'name: %{trace}', labels: {trace: 'asdf'} }) --> 'name: asdf' * Lib.templateFormatString({ template: 'name: %{t
({ data = [], locale, fallback, labels = {}, opts, template })
| 1131 | * @return {string} templated string |
| 1132 | */ |
| 1133 | function templateFormatString({ data = [], locale, fallback, labels = {}, opts, template }) { |
| 1134 | return template.replace(lib.TEMPLATE_STRING_REGEX, (match, key, format) => { |
| 1135 | const isOther = ['xother', 'yother'].includes(key); |
| 1136 | const isSpaceOther = ['_xother', '_yother'].includes(key); |
| 1137 | const isSpaceOtherSpace = ['_xother_', '_yother_'].includes(key); |
| 1138 | const isOtherSpace = ['xother_', 'yother_'].includes(key); |
| 1139 | const hasOther = isOther || isSpaceOther || isOtherSpace || isSpaceOtherSpace; |
| 1140 | |
| 1141 | // Remove underscores from key |
| 1142 | if (isSpaceOther || isSpaceOtherSpace) key = key.substring(1); |
| 1143 | if (isOtherSpace || isSpaceOtherSpace) key = key.substring(0, key.length - 1); |
| 1144 | |
| 1145 | let parsedOp = null; |
| 1146 | let parsedNumber = null; |
| 1147 | if (opts.parseMultDiv) { |
| 1148 | var _match = multDivParser(key); |
| 1149 | key = _match.key; |
| 1150 | parsedOp = _match.op; |
| 1151 | parsedNumber = _match.number; |
| 1152 | } |
| 1153 | |
| 1154 | let value = undefined; |
| 1155 | if (hasOther) { |
| 1156 | // 'other' specifiers that are undefined return an empty string by design |
| 1157 | if (labels[key] === undefined) return ''; |
| 1158 | value = labels[key]; |
| 1159 | } else { |
| 1160 | for (const obj of data) { |
| 1161 | if (!obj) continue; |
| 1162 | if (obj.hasOwnProperty(key)) { |
| 1163 | value = obj[key]; |
| 1164 | break; |
| 1165 | } |
| 1166 | |
| 1167 | if (!SIMPLE_PROPERTY_REGEX.test(key)) { |
| 1168 | // true here means don't convert null to undefined |
| 1169 | value = lib.nestedProperty(obj, key).get(true); |
| 1170 | } |
| 1171 | if (value !== undefined) break; |
| 1172 | } |
| 1173 | } |
| 1174 | |
| 1175 | if (value === undefined) { |
| 1176 | const { count, max, name } = opts; |
| 1177 | const fallbackValue = fallback === false ? match : fallback; |
| 1178 | if (count < max) { |
| 1179 | lib.warn( |
| 1180 | [ |
| 1181 | `Variable '${key}' in ${name} could not be found!`, |
| 1182 | 'Please verify that the template is correct.', |
| 1183 | `Using value: '${fallbackValue}'.` |
| 1184 | ].join(' ') |
| 1185 | ); |
| 1186 | } |
| 1187 | if (count === max) lib.warn(`Too many '${name}' warnings - additional warnings will be suppressed.`); |
| 1188 | opts.count++; |
| 1189 | |
| 1190 | return fallbackValue; |
no test coverage detected
searching dependent graphs…