From e4308c9321095be1c149b6f16ba41ae3e5594208 Mon Sep 17 00:00:00 2001 From: maciej-ka Date: Wed, 17 Jan 2018 20:20:55 +0100 Subject: [PATCH] feat: allow regexps in singleTags option --- README.md | 5 +++-- lib/posthtml-render.js | 21 +++++++++++++++++++-- posthtml-render.min.js | 2 +- test/test.js | 4 ++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d3da618..bd1397d 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,11 @@ __In Browser__ ## Options ### singleTags -Array tags for extend default list single tags +Array tags for extend default list single tags. Values can be strings or regular expressions. __Default__: `[]` -*Options* `{ singleTags: ['rect', 'custom'] }` +*Options* `{ singleTags: ['rect', 'custom', /^%.*%$/] }` ```html ... @@ -65,6 +65,7 @@ __Default__: `[]` ... + <%=title%> ``` diff --git a/lib/posthtml-render.js b/lib/posthtml-render.js index 052b49b..e183245 100644 --- a/lib/posthtml-render.js +++ b/lib/posthtml-render.js @@ -25,6 +25,7 @@ function postHTMLRender(tree, options) { var SINGLE_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; var singleTags = {}; + var regexpSingleTags = []; for (var i = 0, leni = SINGLE_TAGS.length; i < leni; i++) { singleTags[SINGLE_TAGS[i]] = 1; @@ -32,7 +33,11 @@ function postHTMLRender(tree, options) { if (optSingleTags) { for (var j = 0, lenj = optSingleTags.length; j < lenj; j++) { - singleTags[optSingleTags[j]] = 1; + if (optSingleTags[j] instanceof RegExp) { + regexpSingleTags.push(optSingleTags[j]); + } else { + singleTags[optSingleTags[j]] = 1; + } } } @@ -60,7 +65,7 @@ function postHTMLRender(tree, options) { } var tag = node.tag || 'div'; - if (singleTags[tag]) { + if (isSingleTag(tag, singleTags, regexpSingleTags)) { buf += '<'+ tag + attrs(node.attrs); switch (closingSingleTag) { case 'slash': @@ -107,6 +112,18 @@ function traverse(tree, cb) { return tree; } +function isSingleTag(tag, strings, regexps) { + if (strings[tag]) { + return true; + } + for (var i = 0; i < regexps.length; i++) { + if (tag.match(regexps[i])) { + return true; + } + } + return false; +} + var defineAsGlobal = true; /* istanbul ignore next */ diff --git a/posthtml-render.min.js b/posthtml-render.min.js index 98f60ca..04f4e12 100644 --- a/posthtml-render.min.js +++ b/posthtml-render.min.js @@ -1 +1 @@ -!function(global){function postHTMLRender(tree,options){for(var optSingleTags=(options=options||{}).singleTags,closingSingleTag=options.closingSingleTag,SINGLE_TAGS=["area","base","br","col","command","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"],singleTags={},i=0,leni=SINGLE_TAGS.length;i";break;case"tag":buf+=">";break;default:buf+=">"}else buf+="<"+tag+(node.attrs?attrs(node.attrs):"")+">"+(node.content?html(node.content):"")+""}}else buf+=node});return buf;function attrs(obj){var attr="";for(var key in obj)"boolean"==typeof obj[key]&&obj[key]?attr+=" "+key:"string"!=typeof obj[key]&&"number"!=typeof obj[key]||(attr+=" "+key+'="'+obj[key]+'"');return attr}}(tree)}var defineAsGlobal=!0;"object"==typeof module&&"object"==typeof module.exports&&(module.exports=postHTMLRender,defineAsGlobal=!1),"object"==typeof modules&&"function"==typeof modules.define&&(modules.define("postHTMLRender",function(provide){provide(postHTMLRender)}),defineAsGlobal=!1),"function"==typeof define&&(define(function(require,exports,module){module.exports=postHTMLRender}),defineAsGlobal=!1),defineAsGlobal&&(global.postHTMLRender=postHTMLRender)}("undefined"!=typeof window?window:global); \ No newline at end of file +!function(global){function postHTMLRender(tree,options){function html(tree){function attrs(obj){var attr="";for(var key in obj)"boolean"==typeof obj[key]&&obj[key]?attr+=" "+key:"string"!=typeof obj[key]&&"number"!=typeof obj[key]||(attr+=" "+key+'="'+obj[key]+'"');return attr}var buf="";return traverse([].concat(tree),function(node){if(node){if("string"==typeof node||"number"==typeof node)return void(buf+=node);if("boolean"==typeof node.tag&&!node.tag)return"object"!=typeof node.content&&(buf+=node.content),node.content;if(Array.isArray(node))return void(buf+=html(node));var tag=node.tag||"div";if(isSingleTag(tag,singleTags,regexpSingleTags))switch(buf+="<"+tag+attrs(node.attrs),closingSingleTag){case"slash":buf+=" />";break;case"tag":buf+=">";break;default:buf+=">"}else buf+="<"+tag+(node.attrs?attrs(node.attrs):"")+">"+(node.content?html(node.content):"")+""}}),buf}options=options||{};for(var optSingleTags=options.singleTags,closingSingleTag=options.closingSingleTag,SINGLE_TAGS=["area","base","br","col","command","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"],singleTags={},regexpSingleTags=[],i=0,leni=SINGLE_TAGS.length;i'); }); + it('use regexp', function() { + expect(render({ tag: '%=title%' }, { singleTags: [/^%.*%$/] })).to.eql('<%=title%>'); + }); + it('safe attrs', function() { expect(render({ tag: 'rect', attrs: { id: 'id' } }, { singleTags: ['rect'] })).to.eql(''); });