Created
January 22, 2015 23:42
-
-
Save bodia-uz/eabef29d40ea83cb8c00 to your computer and use it in GitHub Desktop.
// source http://jsbin.com/zuquno
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>JS Bin</title> | |
</head> | |
<body> | |
<script id="jsbin-javascript"> | |
function TextPattern(pattern){ | |
this.opener = '{'; | |
this.closer = '}'; | |
this.delimiter = '|'; | |
this.parse(pattern); | |
} | |
TextPattern.prototype = (function() { | |
var META_CHAR_PATTERN = /[-[\]{}()*+?.\\^$|,]/g; | |
var MARKUP_PATTERN = /{([^}]+)}/g; | |
var tmp = {}; | |
function random(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function sample(phrase, delimiter) { | |
var variants = phrase.split(delimiter); | |
var tries = variants.length; | |
var maxIndex = variants.length - 1; | |
var randomIndex = random(0, maxIndex); | |
// find not taken variant | |
while (tmp[phrase] && tmp[phrase][randomIndex] && tries--) { | |
randomIndex = randomIndex < maxIndex ? randomIndex + 1 : 0; | |
} | |
// if all variants taken, | |
// reset taken variants | |
// else save value as new one variant | |
tmp[phrase] = !tries ? {} : tmp[phrase] || {}; | |
tmp[phrase][randomIndex] = true; | |
return variants[randomIndex]; | |
} | |
function escape(string) { | |
return string.replace(META_CHAR_PATTERN, "\\$&"); | |
} | |
function wrap(string, opener, closer) { | |
return opener + string + closer; | |
} | |
function parse(string, opener, closer) { | |
/* Use an optimized regex when opener and closer are one character each */ | |
var iterator = new RegExp(escape(opener) + '|' + escape(closer), 'g'); | |
var results = []; | |
var openTokens; | |
var matchStartIndex; | |
var match; | |
do { | |
openTokens = 0; | |
while (match = iterator.exec(string)) { | |
if (match[0] == opener) { | |
if (!openTokens) | |
matchStartIndex = iterator.lastIndex; | |
openTokens++; | |
} else if (openTokens) { | |
openTokens--; | |
if (!openTokens) | |
results.push(string.slice(matchStartIndex, match.index)); | |
} | |
} | |
} while (openTokens && (iterator.lastIndex = matchStartIndex)); | |
return results; | |
} | |
function getGroups(pattern, opener, closer) { | |
var matches = parse(pattern, opener, closer); | |
return matches.map(function(match) { | |
var groups = getGroups(match, opener, closer) | |
return { | |
phrase: match, | |
groups: groups, | |
hasGroups: !!groups.length, | |
marker: function(phrase) { | |
return wrap(phrase || this.phrase, opener, closer); | |
} | |
}; | |
}); | |
} | |
function render(pattern, groups, delimiter) { | |
var result = pattern; | |
//console.log(phrases); | |
groups.forEach(function(group) { | |
var phrase = !group.hasGroups ? group.phrase : render(group.phrase, group.groups, delimiter); | |
var marker = group.marker(phrase); | |
if (group.hasGroups) { | |
result = result.replace(group.phrase, phrase); | |
} | |
result = result.replace(marker, sample(phrase, delimiter)); | |
}); | |
return result; | |
} | |
return { | |
parse: function(pattern) { | |
var self = this; | |
this.pattern = pattern; | |
this.groups = getGroups(pattern, this.opener, this.closer, this.delimiter); | |
}, | |
render: function() { | |
return render(this.pattern, this.groups, this.delimiter); | |
} | |
}; | |
})(); | |
var text = 'hello {world|bodia|zhup|{some|no|any}body}! Let\'s {go|play|cry|eat|sleep|do something}{!|?}'; | |
var pattern = new TextPattern(text); | |
console.log(pattern.render()); | |
console.log(pattern.render()); | |
console.log(pattern.render()); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">function TextPattern(pattern){ | |
this.opener = '{'; | |
this.closer = '}'; | |
this.delimiter = '|'; | |
this.parse(pattern); | |
} | |
TextPattern.prototype = (function() { | |
var META_CHAR_PATTERN = /[-[\]{}()*+?.\\^$|,]/g; | |
var MARKUP_PATTERN = /{([^}]+)}/g; | |
var tmp = {}; | |
function random(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function sample(phrase, delimiter) { | |
var variants = phrase.split(delimiter); | |
var tries = variants.length; | |
var maxIndex = variants.length - 1; | |
var randomIndex = random(0, maxIndex); | |
// find not taken variant | |
while (tmp[phrase] && tmp[phrase][randomIndex] && tries--) { | |
randomIndex = randomIndex < maxIndex ? randomIndex + 1 : 0; | |
} | |
// if all variants taken, | |
// reset taken variants | |
// else save value as new one variant | |
tmp[phrase] = !tries ? {} : tmp[phrase] || {}; | |
tmp[phrase][randomIndex] = true; | |
return variants[randomIndex]; | |
} | |
function escape(string) { | |
return string.replace(META_CHAR_PATTERN, "\\$&"); | |
} | |
function wrap(string, opener, closer) { | |
return opener + string + closer; | |
} | |
function parse(string, opener, closer) { | |
/* Use an optimized regex when opener and closer are one character each */ | |
var iterator = new RegExp(escape(opener) + '|' + escape(closer), 'g'); | |
var results = []; | |
var openTokens; | |
var matchStartIndex; | |
var match; | |
do { | |
openTokens = 0; | |
while (match = iterator.exec(string)) { | |
if (match[0] == opener) { | |
if (!openTokens) | |
matchStartIndex = iterator.lastIndex; | |
openTokens++; | |
} else if (openTokens) { | |
openTokens--; | |
if (!openTokens) | |
results.push(string.slice(matchStartIndex, match.index)); | |
} | |
} | |
} while (openTokens && (iterator.lastIndex = matchStartIndex)); | |
return results; | |
} | |
function getGroups(pattern, opener, closer) { | |
var matches = parse(pattern, opener, closer); | |
return matches.map(function(match) { | |
var groups = getGroups(match, opener, closer) | |
return { | |
phrase: match, | |
groups: groups, | |
hasGroups: !!groups.length, | |
marker: function(phrase) { | |
return wrap(phrase || this.phrase, opener, closer); | |
} | |
}; | |
}); | |
} | |
function render(pattern, groups, delimiter) { | |
var result = pattern; | |
//console.log(phrases); | |
groups.forEach(function(group) { | |
var phrase = !group.hasGroups ? group.phrase : render(group.phrase, group.groups, delimiter); | |
var marker = group.marker(phrase); | |
if (group.hasGroups) { | |
result = result.replace(group.phrase, phrase); | |
} | |
result = result.replace(marker, sample(phrase, delimiter)); | |
}); | |
return result; | |
} | |
return { | |
parse: function(pattern) { | |
var self = this; | |
this.pattern = pattern; | |
this.groups = getGroups(pattern, this.opener, this.closer, this.delimiter); | |
}, | |
render: function() { | |
return render(this.pattern, this.groups, this.delimiter); | |
} | |
}; | |
})(); | |
var text = 'hello {world|bodia|zhup|{some|no|any}body}! Let\'s {go|play|cry|eat|sleep|do something}{!|?}'; | |
var pattern = new TextPattern(text); | |
console.log(pattern.render()); | |
console.log(pattern.render()); | |
console.log(pattern.render());</script></body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function TextPattern(pattern){ | |
this.opener = '{'; | |
this.closer = '}'; | |
this.delimiter = '|'; | |
this.parse(pattern); | |
} | |
TextPattern.prototype = (function() { | |
var META_CHAR_PATTERN = /[-[\]{}()*+?.\\^$|,]/g; | |
var MARKUP_PATTERN = /{([^}]+)}/g; | |
var tmp = {}; | |
function random(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function sample(phrase, delimiter) { | |
var variants = phrase.split(delimiter); | |
var tries = variants.length; | |
var maxIndex = variants.length - 1; | |
var randomIndex = random(0, maxIndex); | |
// find not taken variant | |
while (tmp[phrase] && tmp[phrase][randomIndex] && tries--) { | |
randomIndex = randomIndex < maxIndex ? randomIndex + 1 : 0; | |
} | |
// if all variants taken, | |
// reset taken variants | |
// else save value as new one variant | |
tmp[phrase] = !tries ? {} : tmp[phrase] || {}; | |
tmp[phrase][randomIndex] = true; | |
return variants[randomIndex]; | |
} | |
function escape(string) { | |
return string.replace(META_CHAR_PATTERN, "\\$&"); | |
} | |
function wrap(string, opener, closer) { | |
return opener + string + closer; | |
} | |
function parse(string, opener, closer) { | |
/* Use an optimized regex when opener and closer are one character each */ | |
var iterator = new RegExp(escape(opener) + '|' + escape(closer), 'g'); | |
var results = []; | |
var openTokens; | |
var matchStartIndex; | |
var match; | |
do { | |
openTokens = 0; | |
while (match = iterator.exec(string)) { | |
if (match[0] == opener) { | |
if (!openTokens) | |
matchStartIndex = iterator.lastIndex; | |
openTokens++; | |
} else if (openTokens) { | |
openTokens--; | |
if (!openTokens) | |
results.push(string.slice(matchStartIndex, match.index)); | |
} | |
} | |
} while (openTokens && (iterator.lastIndex = matchStartIndex)); | |
return results; | |
} | |
function getGroups(pattern, opener, closer) { | |
var matches = parse(pattern, opener, closer); | |
return matches.map(function(match) { | |
var groups = getGroups(match, opener, closer) | |
return { | |
phrase: match, | |
groups: groups, | |
hasGroups: !!groups.length, | |
marker: function(phrase) { | |
return wrap(phrase || this.phrase, opener, closer); | |
} | |
}; | |
}); | |
} | |
function render(pattern, groups, delimiter) { | |
var result = pattern; | |
//console.log(phrases); | |
groups.forEach(function(group) { | |
var phrase = !group.hasGroups ? group.phrase : render(group.phrase, group.groups, delimiter); | |
var marker = group.marker(phrase); | |
if (group.hasGroups) { | |
result = result.replace(group.phrase, phrase); | |
} | |
result = result.replace(marker, sample(phrase, delimiter)); | |
}); | |
return result; | |
} | |
return { | |
parse: function(pattern) { | |
var self = this; | |
this.pattern = pattern; | |
this.groups = getGroups(pattern, this.opener, this.closer, this.delimiter); | |
}, | |
render: function() { | |
return render(this.pattern, this.groups, this.delimiter); | |
} | |
}; | |
})(); | |
var text = 'hello {world|bodia|zhup|{some|no|any}body}! Let\'s {go|play|cry|eat|sleep|do something}{!|?}'; | |
var pattern = new TextPattern(text); | |
console.log(pattern.render()); | |
console.log(pattern.render()); | |
console.log(pattern.render()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment