Problem
I was inspired to write a BBCode to HTML converter as I’m currently learning functional programming. I wanted achieve functional cohesion. jsFiddle
I’d like feedback on:
- structuring of the code. Should the functions
getHtmlTag
andgetHtml
be contained withinbbTagToHtmlTag
since they are coupled through therules
variable? - any regex expressions that can reduce the code base
- any changes to the data model to reduce complexity
Below is the newer version of the code. This version is slightly less coupled compared to the original version and the functions are separated to allow for more reuse. This new version doesn’t involve any recursion, so it may be more efficient.
I suspect the cost of reuse is an increase in code base. Although, I’m sure there’s more regex magic that can be used to slim down the code base.
/* Escapes a string for use with regular expressions */
function escapeString(input) {
return input.replace(/([,!\^${}[]().*+?|<>-&])/g,
function(c){return "\" + c;});
}
/* replaces all */
function replaceAll(search, input, replacement, ignore) {
return input.replace(
new RegExp(escapeString(search), "g"+(ignore?"i":"")),
replacement);
};
/* Check if an index is event */
function isIndexEven(val, index, context) {
return (index % 2 === 0);
};
/* Sets the attributes on an HTML string given a set of attributes */
function setHtmlAttrs(htmlCode, attrs) {
return attrs.reduce(function(htmlCode, attr, index) {
var re = new RegExp('\$' + (index + 1), 'g');
return htmlCode.replace(re, attr);
}, htmlCode);
};
/* Gets the html tag(s) for a bbCode tag */
function eleFragsToHtml(isClosing, elementFragments) {
return '<' + elementFragments.map(function(frag) {
return (isClosing ? '/' + frag.join(' ') : frag.join(' '));
}).join('><') + '>';
};
/* Converts a single bbCode Tag to Html */
function bbTagToHtmlTag(rules, tag) {
var attrs = tag.replace(/[w+|]/g, '').trim().split(' ');
var key = tag.replace(/[/?| .+|]/g, '');
var isClosing = ///.test(tag);
var htmlTemplate = (isClosing ? rules[key].map(function(rule) {
return rule.filter(isIndexEven)
}).reverse()
: rules[key]);
var output = eleFragsToHtml(isClosing, htmlTemplate);
return setHtmlAttrs(output, attrs);
};
/* Converts bbCode to HTML */
function bbCodeToHtml(rules, bbCode) {
/* Creates the Regular Expression Search */
var regex = new RegExp( ['\[.?[',
Object.keys(rules).join('|'),
'].*?\]'].join(''), 'g' );
return bbCode.match(regex)
.reduce(function(htmlCode, tag) {
return replaceAll(tag,
htmlCode,
bbTagToHtmlTag(rules, tag));
}, bbCode);
};
Below is the test setup using the same rule set as the linked post.
var rules = {
'b': [ ['strong'] ],
'bg': [ ['span', 'style"background-color:$1""'] ]
Solution