JSFiddle - React, Tailwind, and code Playground
by dswitzer
CSS
.test-output {
white-space: pre-line;
font: 12px "Courier New";
}
JavaScript
function tokenReplacer(tokens, string){
/*
* This parsers the string looking for tokens in the format:
* {some}, {some.nested.variable}, {&some}, {&some.nested.variable}
*
* The expression:
* ([a-zA-Z_$][0-9a-zA-Z_$]*(\.[a-zA-Z_$][0-9a-zA-Z_$]*)*)
*
* Searches for any valid JS variable name.
*/
var regexParser = /\{\&?([a-zA-Z_$][0-9a-zA-Z_$]*(\.[a-zA-Z_$][0-9a-zA-Z_$]*)*)\}/g
, matches = string.match(regexParser)
, results = string;
function getToken(token){
// remove the { and } from the token
var keyPath = token.substring(1, token.length-1)
// if the token starts with "&" it means we URI encode the output
, isUriEncode = (keyPath.indexOf("&") === 0);
// if we have any special encoding commands, remove the encoding character
if( isUriEncode ){
keyPath = keyPath.substring(1);
}
// return the value found or an empty string
var value = getValueFromPath(tokens, keyPath) || "";
if( isUriEncode ){
value = encodeURIComponent(value);
}
console.log("%s = %o", keyPath, value);
return value;
}
function getValueFromPath(input, path) {
try {
var separator = '.';
return path
.replace('[', separator).replace(']','')
.split(separator)
.reduce(
function (obj, property) {
return obj[property];
}
, input
);
} catch (e) {
return;
}
}
console.log(matches);
if( matches ){
matches.forEach(function (match){
results = results.replace(match, getToken(match));
});
}
return results;
}
function test(tokens, string){
var output = document.createElement("div");
output.className = "test-output";
output.innerText = string + " -> " + tokenReplacer(tokens, string);
document.body.appendChild(output);
}
var tokens = {
widget: {title: "Hello World!"}
, item: {label: "My Label", value: 3, series: "Series Name"}
};
test(tokens, "{widget.title}: {item.label} -...