babel-plugin-hyperstache
Advanced tools
Comparing version 0.0.1 to 0.1.0
@@ -1,1 +0,1 @@ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).hyperstache=n()}(this,(function(){function e(e){return"true"===e?e=!0:"false"===e?e=!1:"null"===e?e=null:"undefined"===e?e=void 0:isNaN(+e)||(e=+e),e}function n(e,n){return e[0]===n[0]&&e[e.length-1]===n[n.length-1]&&e.slice(1,-1)}var r=1,t=3,a=4,u=0,f=2;return function(i,s){var o=i.types;function c(e){for(var n,r=e.split("."),t=0;t<r.length;t++){var a=(u=r[t],o.isValidIdentifier(u)?o.identifier(u):o.stringLiteral(u));n=0===t?a:o.memberExpression(n,a)}var u;return n}function l(r){if(""===r)return o.stringLiteral(r);var t;switch("string"==typeof r&&(r=e(r)),typeof r){case"string":return(t=n(r,'"'))||(t=n(r,"'"))?o.stringLiteral(t):o.identifier(r);case"number":return o.numericLiteral(r);case"boolean":return o.booleanLiteral(r);default:return o.identifier(""+r)}}function v(r){switch("string"==typeof r&&(r=e(r)),typeof r){case"string":return n(r,'"')||n(r,"'"),o.stringLiteral(r);case"number":return o.numericLiteral(r);case"boolean":return o.booleanLiteral(r);default:return o.identifier(""+r)}}void 0===s&&(s={});var d=s.tag||"hbs",p=s.tagOut||"html";return{name:"hyperstache",visitor:{TaggedTemplateExpression:function(n){if(n.node.tag.name===d){var i=n.node.quasi.quasis.map((function(e){return e.value.raw})),s=[0].concat(n.node.quasi.expressions),h=function e(n,r){for(var t=[],a=[],u=1;u<n.length;u++){var f=n[u],i=n[++u];"number"==typeof f?a.push(r[f]):i>=4?function(){var e=n[++u],r=n[++u],t=l(f);if(o.isIdentifier(t)){var s=[o.stringLiteral(f),o.identifier("ctx")],d=[];e.length>0&&d.push(o.objectProperty(o.identifier("params"),o.arrayExpression(e.map(v)))),Object.keys(r).length>0&&d.push(o.objectProperty(o.identifier("hash"),o.objectExpression(Object.keys(r).map((function(e){return o.objectProperty(o.stringLiteral(e),l(r[e]))}))))),d.push(o.objectProperty(o.identifier("data"),o.identifier("data"),!1,!0));var p=o.objectExpression(d);s.push(p),t=o.callExpression(c("hys.expr"),s)}4===i&&(o.isCallExpression(t)||o.isStringLiteral(t))&&(t=o.callExpression(c("hys.escape"),[t])),a.push(t)}():1===i?function(){var n=f[1][1],r=f[1][3],t=f[1][4],u=f[2],i=[o.stringLiteral(n),o.identifier("ctx")],s=[o.objectProperty(o.identifier("fn"),e([0].concat(f[1].slice(5))))];u.length>1&&s.push(o.objectProperty(o.identifier("inverse"),e(u))),r.length>0&&s.push(o.objectProperty(o.identifier("params"),o.arrayExpression(r.map(v)))),Object.keys(t).length>0&&s.push(o.objectProperty(o.identifier("hash"),o.objectExpression(Object.keys(t).map((function(e){return o.objectProperty(o.stringLiteral(e),v(t[e]))}))))),s.push(o.objectProperty(o.identifier("data"),o.identifier("data"),!1,!0));var l=o.objectExpression(s);i.push(l);var d=o.callExpression(c("hys.block"),i);a.push(d)}():t.push(o.templateElement({raw:f,cooked:f}))}var s=[o.identifier("hys"),o.identifier("ctx"),o.identifier("data")],d=o.templateLiteral(t,a),h=o.taggedTemplateExpression(o.identifier(p),d);return o.callExpression(o.identifier("template"),[o.arrowFunctionExpression(s,h)])}(function(n){for(var i,s,o,c,l,v,d=r,p="",h="",m="",y=[0],b="}}",g=0;g<n.length;g++){i=""+n[g],g&&(d===r&&(O(),h||O("")),O(g));for(var x=0;x<i.length;x++)if(o=i[x],c=i.substr(x,"{{".length),l=i.substr(x,b.length),d===r)"{{"===c?(O(),h||O(""),s=4,d=t,x++):(s=void 0,p+=o);else if(m)o===m&&(m=""),p+=o;else if('"'===o||"'"===o)m=o,p+=o;else if(l===b&&"}"!==i[x+b.length])x+=b.length-1,6==s?(O(""),b="}}"):(O(),v=""),d=r;else if(6==s)"--"===(p+=o)&&(b="--}}");else if(" "===o||"\t"===o||"\n"===o||"\r"===o)s===f?(i="{{#/"+p+i.substr(x),d=r,x=-1,p=""):p&&(O(),v="");else if(!p&&"{"===o||"}"===o)s=5;else if(p||"!"!==o)if(p||"#"!==o)"="===o?(v=p,p=""):"/"===o?(y[0][3]&&(i="}}{{/"+i.substr(x+1),x=-1),d=y[0],(y=y[0][0]).push(d,1)):p+=o;else{var j=[y];y=j[1]=[j],j[2]=[j],j[3]="/"===i[x+1]&&++x,s=3,d=t}else s=6}return O(),h||O(""),y;function O(n){var i;null!=n?i=n:(p=p.replace(/^\s*\n\s*|\s*\n\s*$/g,""))&&(i=p),d===r&&null!=i?y.push(i,u):d>=t&&null!=i&&(d===t?"else"===p||"^"===p?(y=y[0][2],s=f,d=t):(y.push(i,s,[],{}),d=a):(y[y.length-3]=s,v?y[y.length-1][v]=e(i):y[y.length-2].push(e(i)))),h=p,p=""}}(i),s),m=o.variableDeclaration("const",[o.variableDeclarator(o.objectPattern([o.objectProperty(o.identifier("template"),o.identifier("template"),!1,!0)]),o.callExpression(o.identifier("require"),[o.stringLiteral("hyperstache/runtime")]))]);n.replaceWithMultiple([m,o.expressionStatement(h)])}}}}}})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).hyperstache=t()}(this,(function(){function e(e){return"true"===e?e=!0:"false"===e?e=!1:"null"===e?e=null:"undefined"===e?e=void 0:isNaN(+e)||(e=+e),e}function t(e,t){return e[0]===t[0]&&e[e.length-1]===t[t.length-1]&&e.slice(1,-1)}const n=0,s=1,r=2,f=0,o=2;function i(e,t){for(let n=e.length;n--;)for(let s=e[n].length;s>2;)if(t(e[n][--s],e[n][--s],s,e[n]))return}const u={tag:"hbs",tagOut:"html",runtime:"hyperstache/runtime"};return function({types:l},c={}){c={...u,...c};const a=(e,t,n)=>{const s=[],r=[];for(let n=1;n<e.length;n++){const f=e[n],o=e[++n];if("number"==typeof f)r.push(t[f]);else if(o>=4){const t=e[++n],s=e[++n];let i=p(f);if(l.isIdentifier(i)){const e=[l.stringLiteral(f),l.identifier("ctx")],n=[];t.length>0&&n.push(l.objectProperty(l.identifier("params"),l.arrayExpression(t.map(h)))),Object.keys(s).length>0&&n.push(l.objectProperty(l.identifier("hash"),l.objectExpression(Object.keys(s).map(e=>l.objectProperty(l.stringLiteral(e),p(s[e])))))),n.push(l.objectProperty(l.identifier("data"),l.identifier("data"),!1,!0)),n.push(l.objectProperty(l.identifier("depths"),l.identifier("depths"),!1,!0)),e.push(l.objectExpression(n)),i=l.callExpression(d("hys.expr"),e)}4===o&&(l.isCallExpression(i)||l.isStringLiteral(i))&&(i=l.callExpression(d("hys.escape"),[i])),r.push(i)}else if(1===o){const e=f[1][1],n=f[1][3],s=f[1][4],o=f[2],i=f[3],u=[l.stringLiteral(e),l.identifier("ctx")],c=[l.objectProperty(l.identifier("fn"),a([0].concat(f[1].slice(5)),t))];o.length>1&&c.push(l.objectProperty(l.identifier("inverse"),a(o,t))),n.length>0&&c.push(l.objectProperty(l.identifier("params"),l.arrayExpression(n.map(h)))),Object.keys(s).length>0&&c.push(l.objectProperty(l.identifier("hash"),l.objectExpression(Object.keys(s).map(e=>l.objectProperty(l.stringLiteral(e),h(s[e])))))),i&&c.push(l.objectProperty(l.identifier("inverted"),l.booleanLiteral(i))),c.push(l.objectProperty(l.identifier("data"),l.identifier("data"),!1,!0)),c.push(l.objectProperty(l.identifier("depths"),l.identifier("depths"),!1,!0)),u.push(l.objectExpression(c));let p=l.callExpression(d("hys.block"),u);r.push(p)}else s.push(l.templateElement({raw:f,cooked:f}))}const f=[];f.push(l.identifier("ctx")),f.push(l.identifier("data")),f.push(l.identifier("depths")),n&&f.push(l.identifier("hys"));const o=l.templateLiteral(s,r),i=l.taggedTemplateExpression(l.identifier(c.tagOut),o);return l.callExpression(l.identifier("template"),[l.arrowFunctionExpression(f,i)])};function d(e){const t=e.split(".");let n;for(let e=0;e<t.length;e++){const r=(s=t[e],l.isValidIdentifier(s)?l.identifier(s):l.stringLiteral(s));n=0===e?r:l.memberExpression(n,r)}var s;return n}function p(n){if(""===n)return l.stringLiteral(n);let s;switch("string"==typeof n&&(n=e(n)),typeof n){case"string":return(s=t(n,'"'))||(s=t(n,"'"))?l.stringLiteral(s):l.identifier(n);case"number":return l.numericLiteral(n);case"boolean":return l.booleanLiteral(n);default:return l.identifier(""+n)}}function h(n){switch("string"==typeof n&&(n=e(n)),typeof n){case"string":return t(n,'"')||t(n,"'"),l.stringLiteral(n);case"number":return l.numericLiteral(n);case"boolean":return l.booleanLiteral(n);default:return l.identifier(""+n)}}return{name:"hyperstache",visitor:{TaggedTemplateExpression:function(t){if(t.node.tag.name===c.tag){const u=t.node.quasi.quasis.map(e=>e.value.raw),d=[0,...t.node.quasi.expressions],p=function(t){let u,l,c,a,d,p,h,m,y,b,g,v=n,x="",$=[0],j=[$],O=j;for(let e=0;e<t.length;e++){u=t[e],e&&(v===n&&(w(),a||w("")),w(e));for(let e=0;e<u.length;e++)if(l=u[e],b=/\s/.test(l),v===n)"{"===l&&"{"===u[e+1]?(g=!1,w(),a||w(""),m=!0,c=4,v=s,e++):(b||(y=!0,g=!1),g&&b||(x+=l),"\n"===l&&(k(),O=O.concat(j),j=[$]),c=void 0);else if(p&&x!==p||"}"!==l||"}"!==u[e+1]||"}"===u[e+2])if(6===c)"--"===(x=u[e-1]+l)&&(p=x);else if(d)l===d&&(d=""),x+=l;else if('"'===l||"'"===l)d=l,x+=l;else if(b)c===o?(u=`{{#/${x}${u.substr(e)}`,v=n,e=-1,x=""):x&&(w(),h="");else if("~"===l&&"}"===u[e+1])g=!0;else if(x||"~"!==l)if((x||"{"!==l&&"&"!==l)&&"}"!==l)if(x||"!"!==l)if(x||"#"!==l&&"^"!==l)"="===l?(h=x,x=""):"/"===l?($[0][4]&&(u=`}}{{/${u.substr(e+1)}`,e=-1),v=$[0],($=$[0][0]).push(v,1),c=3):x+=l;else{const t=[$];$=t[1]=[t],j.push($),t[2]=[t],t[3]="^"===l,t[4]="/"===u[e+1]&&++e,c=3,v=s}else c=6;else c=5,y=!0;else i(O,(e,t,n,s)=>{if(e>f||e===f&&(s[n]=t.replace(/\s*$/,"")))return!0});else 4!==c&&5!==c||(y=!0),6===c?w(""):w(),p=!1,v=n,e++}return w(),a||w(""),k(),$;function w(t){v!==n||null==t&&!x?v>=s&&(null!=t||x)&&(v===s?"else"===x||"^"===x?($=$[0][2],j.push($),c=o,v=s):($.push(null!=t?t:x,c,[],{}),v=r):($[$.length-3]=c,h?$[$.length-1][h]=e(x):$[$.length-2].push(e(x)))):$.push(null!=t?t:x,f),a=x,x=""}function k(){m&&!y&&(x=x.replace(/\r?\n$/,""),i(j,(e,t,n,s)=>{if(e===f&&(s[n]=t.replace(/[^\S\n]*$/,"")))return!0})),y=!1,m=!1}}(u),h=a(p,d,!0),m=l.variableDeclaration("const",[l.variableDeclarator(l.objectPattern([l.objectProperty(l.identifier("template"),l.identifier("template"),!1,!0)]),l.callExpression(l.identifier("require"),[l.stringLiteral(c.runtime)]))]);t.replaceWithMultiple([m,l.expressionStatement(h)])}}}}}})); |
@@ -1,481 +0,1 @@ | ||
/* Some code from Handlebars - MIT License - Yehuda Katz */ | ||
function parseLiteral(value) { | ||
if (value === 'true') { | ||
value = true; | ||
} else if (value === 'false') { | ||
value = false; | ||
} else if (value === 'null') { | ||
value = null; | ||
} else if (value === 'undefined') { | ||
value = undefined; | ||
} else if (!isNaN(+value)) { | ||
value = +value; | ||
} | ||
return value; | ||
} | ||
function unwrap(str, adfix) { | ||
return ( | ||
str[0] === adfix[0] && | ||
str[str.length - 1] === adfix[adfix.length - 1] && | ||
str.slice(1, -1) | ||
); | ||
} | ||
/* Adapted from HTM - Apache License 2.0 - Jason Miller, Joachim Viide */ | ||
// const MODE_SLASH = 0; | ||
const MODE_TEXT = 1; | ||
// const MODE_WHITESPACE = 2; | ||
const MODE_EXPR_SET = 3; | ||
const MODE_EXPR_APPEND = 4; | ||
const CHILD_APPEND = 0; | ||
const CHILD_RECURSE = 1; | ||
const EXPR_INVERSE = 2; | ||
const EXPR_BLOCK = 3; | ||
const EXPR_VAR = 4; | ||
const EXPR_RAW = 5; | ||
const EXPR_COMMENT = 6; | ||
const build = function(statics) { | ||
let str; | ||
let mode = MODE_TEXT; | ||
let expr; | ||
let buffer = ''; | ||
let lastBuffer = ''; | ||
let quote = ''; | ||
let current = [0]; | ||
let char; | ||
let openTag = '{{'; | ||
let closeTag = '}}'; | ||
let openSlice; | ||
let closeSlice; | ||
let propName; | ||
// log('STATICS', statics); | ||
for (let i = 0; i < statics.length; i++) { | ||
// This can be a SafeString obj, convert to string. | ||
str = '' + statics[i]; | ||
if (i) { | ||
if (mode === MODE_TEXT) { | ||
commit(); | ||
if (!lastBuffer) { | ||
// Add a split if there is no content before the expression. | ||
commit(''); | ||
} | ||
} | ||
commit(i); | ||
} | ||
for (let j = 0; j < str.length; j++) { | ||
char = str[j]; | ||
openSlice = str.substr(j, openTag.length); | ||
closeSlice = str.substr(j, closeTag.length); | ||
if (mode === MODE_TEXT) { | ||
if (openSlice === openTag) { | ||
commit(); | ||
if (!lastBuffer) { | ||
// Add a split if there is no content before the expression. | ||
commit(''); | ||
} | ||
expr = EXPR_VAR; | ||
mode = MODE_EXPR_SET; | ||
j++; | ||
} else { | ||
expr = undefined; | ||
buffer += char; | ||
} | ||
} else if (quote) { | ||
if (char === quote) { | ||
quote = ''; | ||
} | ||
buffer += char; | ||
} else if (char === '"' || char === "'") { | ||
quote = char; | ||
buffer += char; | ||
} else if (closeSlice === closeTag && str[j + closeTag.length] !== '}') { | ||
j += closeTag.length - 1; | ||
if (expr == EXPR_COMMENT) { | ||
commit(''); | ||
closeTag = '}}'; | ||
} else { | ||
commit(); | ||
propName = ''; | ||
} | ||
mode = MODE_TEXT; | ||
} else if (expr == EXPR_COMMENT) { | ||
buffer += char; | ||
if (buffer === '--') { | ||
closeTag = '--}}'; | ||
} | ||
} else if ( | ||
char === ' ' || | ||
char === '\t' || | ||
char === '\n' || | ||
char === '\r' | ||
) { | ||
if (expr === EXPR_INVERSE) { | ||
// Add `else` chaining. | ||
// e.g. transforms {{else if }} into {{else}}{{#/if }} | ||
str = `{{#/${buffer}${str.substr(j)}`; // {{#/ autoclose | ||
mode = MODE_TEXT; | ||
j = -1; | ||
buffer = ''; | ||
} else { | ||
// Only commit if there is buffer, ignore spaces after `{{`. | ||
if (buffer) { | ||
commit(); | ||
propName = ''; | ||
} | ||
} | ||
} else if ((!buffer && char === '{') || char === '}') { | ||
// First `{` after opening expression `{{`. | ||
expr = EXPR_RAW; | ||
} else if (!buffer && char === '!') { | ||
expr = EXPR_COMMENT; | ||
} else if (!buffer && char === '#') { | ||
// First `#` after opening expression `{{`. | ||
// [1] is reserved for `if`, [2] for `else`. | ||
const block = [current]; | ||
current = block[1] = [block]; | ||
block[2] = [block]; | ||
block[3] = str[j + 1] === '/' && ++j; // autoclose | ||
expr = EXPR_BLOCK; | ||
mode = MODE_EXPR_SET; | ||
} else if (char === '=') { | ||
propName = buffer; | ||
buffer = ''; | ||
} else if (char === '/') { | ||
if (current[0][3]) { | ||
// autoclose | ||
str = `}}{{/${str.substr(j + 1)}`; | ||
j = -1; | ||
} | ||
mode = current[0]; | ||
(current = current[0][0]).push(mode, CHILD_RECURSE); | ||
// mode = MODE_SLASH; | ||
} else { | ||
buffer += char; | ||
} | ||
} | ||
} | ||
commit(); | ||
if (!lastBuffer) { | ||
// Add a split if there is no content before the expression. | ||
commit(''); | ||
} | ||
return current; | ||
function commit(field) { | ||
let value; | ||
if (field != null) { | ||
value = field; | ||
} else { | ||
buffer = buffer.replace(/^\s*\n\s*|\s*\n\s*$/g, ''); | ||
if (buffer) value = buffer; | ||
} | ||
if (mode === MODE_TEXT && value != null) { | ||
current.push(value, CHILD_APPEND); | ||
} else if (mode >= MODE_EXPR_SET && value != null) { | ||
if (mode === MODE_EXPR_SET) { | ||
if (buffer === 'else' || buffer === '^') { | ||
current = current[0][2]; | ||
expr = EXPR_INVERSE; | ||
mode = MODE_EXPR_SET; | ||
} else { | ||
// [..., (var|fn), EXPR, args, hash, ...] | ||
current.push(value, expr, [], {}); | ||
mode = MODE_EXPR_APPEND; | ||
} | ||
} else { | ||
current[current.length - 3] = expr; | ||
if (propName) { | ||
current[current.length - 1][propName] = parseLiteral(value); | ||
} else { | ||
current[current.length - 2].push(parseLiteral(value)); | ||
} | ||
} | ||
} | ||
lastBuffer = buffer; | ||
buffer = ''; | ||
} | ||
}; | ||
/** | ||
* @param {Babel} babel | ||
* @param {object} options | ||
* @param {string} [options.tag=hbs] The tagged template "tag" function name to process. | ||
* @param {string} [options.tagOut=html] The tagged template "tag" function name to output. | ||
*/ | ||
function hysBabelPlugin({ types: t }, options = {}) { | ||
function TaggedTemplateExpression(path) { | ||
const tag = path.node.tag.name; | ||
if (tag === hbsName) { | ||
const stats = path.node.quasi.quasis.map(e => e.value.raw); | ||
const fields = [0, ...path.node.quasi.expressions]; | ||
const built = build(stats); | ||
// log('BUILT', built); | ||
const node = evaluate(built, fields); | ||
// var _hys = require("hyperstache/runtime"); | ||
const runtimeTpl = t.variableDeclaration( | ||
'const', | ||
[ | ||
t.variableDeclarator( | ||
t.objectPattern([ | ||
t.objectProperty( | ||
t.identifier('template'), | ||
t.identifier('template'), | ||
false, | ||
true | ||
) | ||
]), | ||
t.callExpression( | ||
t.identifier('require'), | ||
[t.stringLiteral('hyperstache/runtime')] | ||
) | ||
) | ||
] | ||
); | ||
path.replaceWithMultiple([ | ||
runtimeTpl, | ||
t.expressionStatement(node) | ||
]); | ||
} | ||
} | ||
const evaluate = (built, fields) => { | ||
const statics = []; | ||
const exprs = []; | ||
// log('BUILT', built); | ||
for (let i = 1; i < built.length; i++) { | ||
const field = built[i]; | ||
// log('FIELD', field); | ||
const type = built[++i]; | ||
if (typeof field === 'number') { | ||
exprs.push(fields[field]); | ||
} else if (type >= EXPR_VAR) { | ||
const params = built[++i]; | ||
const hash = built[++i]; | ||
let expr = transform(field); | ||
// log('EXPR', expr); | ||
if (t.isIdentifier(expr)) { | ||
const args = [ | ||
t.stringLiteral(field), | ||
t.identifier('ctx') | ||
]; | ||
const properties = []; | ||
if (params.length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
)); | ||
} | ||
if (Object.keys(hash).length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression(Object.keys(hash).map((key) => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transform(hash[key]) | ||
); | ||
})) | ||
)); | ||
} | ||
properties.push(t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
)); | ||
const options = t.objectExpression(properties); | ||
args.push(options); | ||
expr = t.callExpression(dottedIdentifier('hys.expr'), args); | ||
} | ||
if (type === EXPR_VAR && (t.isCallExpression(expr) || t.isStringLiteral(expr))) { | ||
expr = t.callExpression(dottedIdentifier('hys.escape'), [expr]); | ||
} | ||
// log('EXPR', expr); | ||
exprs.push(expr); | ||
} else if (type === CHILD_RECURSE) { | ||
/** | ||
* field = [ | ||
* [parent], | ||
* [[parent], if, 5, ['@first'], { hash: param }, 'body', 3], // if block | ||
* [[parent], if, 5, ['@last'], {}, 'body', 3, 'End', 1] // else block | ||
* ] | ||
*/ | ||
const fnName = field[1][1]; | ||
const params = field[1][3]; | ||
const hash = field[1][4]; | ||
const inverse = field[2]; | ||
const args = [ | ||
t.stringLiteral(fnName), | ||
t.identifier('ctx') | ||
]; | ||
const properties = [ | ||
t.objectProperty( | ||
t.identifier('fn'), | ||
evaluate([0].concat(field[1].slice(5))) | ||
) | ||
]; | ||
if (inverse.length > 1) { | ||
properties.push(t.objectProperty( | ||
t.identifier('inverse'), | ||
evaluate(inverse) | ||
)); | ||
} | ||
if (params.length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
)); | ||
} | ||
if (Object.keys(hash).length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression(Object.keys(hash).map((key) => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transformParams(hash[key]) | ||
); | ||
})) | ||
)); | ||
} | ||
properties.push(t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
)); | ||
const options = t.objectExpression(properties); | ||
args.push(options); | ||
let expr = t.callExpression(dottedIdentifier('hys.block'), args); | ||
// log('EXPR', expr); | ||
exprs.push(expr); | ||
} else { | ||
// code === CHILD_APPEND | ||
statics.push(t.templateElement({ | ||
raw: field, | ||
cooked: field | ||
})); | ||
} | ||
} | ||
// log('EXPRS', exprs); | ||
const params = [t.identifier('hys'), t.identifier('ctx'), t.identifier('data')]; | ||
const quasi = t.templateLiteral(statics, exprs); | ||
const body = t.taggedTemplateExpression(t.identifier(htmlName), quasi); | ||
const node = t.callExpression( | ||
t.identifier('template'), | ||
[t.arrowFunctionExpression(params, body)] | ||
); | ||
return node; | ||
}; | ||
function dottedIdentifier(keypath) { | ||
const path = keypath.split('.'); | ||
let out; | ||
for (let i=0; i<path.length; i++) { | ||
const ident = propertyName(path[i]); | ||
out = i===0 ? ident : t.memberExpression(out, ident); | ||
} | ||
return out; | ||
} | ||
function propertyName(key) { | ||
if (t.isValidIdentifier(key)) { | ||
return t.identifier(key); | ||
} | ||
return t.stringLiteral(key); | ||
} | ||
function transform(value) { | ||
if (value === '') { | ||
return t.stringLiteral(value); | ||
} | ||
if (typeof value === 'string') { | ||
value = parseLiteral(value); | ||
} | ||
let str; | ||
switch (typeof value) { | ||
case 'string': | ||
if ((str = unwrap(value, '"')) || (str = unwrap(value, "'"))) { | ||
return t.stringLiteral(str); | ||
} | ||
return t.identifier(value); | ||
case 'number': | ||
return t.numericLiteral(value); | ||
case 'boolean': | ||
return t.booleanLiteral(value); | ||
default: | ||
return t.identifier('' + value); | ||
} | ||
} | ||
function transformParams(value) { | ||
if (typeof value === 'string') { | ||
value = parseLiteral(value); | ||
} | ||
switch (typeof value) { | ||
case 'string': | ||
if (unwrap(value, '"') || unwrap(value, "'")) { | ||
return t.stringLiteral(value); | ||
} | ||
return t.stringLiteral(value); | ||
case 'number': | ||
return t.numericLiteral(value); | ||
case 'boolean': | ||
return t.booleanLiteral(value); | ||
default: | ||
return t.identifier('' + value); | ||
} | ||
} | ||
// The tagged template tag function name we're looking for. | ||
// This is static because it's generally assigned via htm.bind(h), | ||
// which could be imported from elsewhere, making tracking impossible. | ||
const hbsName = options.tag || 'hbs'; | ||
const htmlName = options.tagOut || 'html'; | ||
return { | ||
name: 'hyperstache', | ||
visitor: { | ||
TaggedTemplateExpression | ||
} | ||
}; | ||
} | ||
export default hysBabelPlugin; | ||
function e(e){return"true"===e?e=!0:"false"===e?e=!1:"null"===e?e=null:"undefined"===e?e=void 0:isNaN(+e)||(e=+e),e}function t(e,t){return e[0]===t[0]&&e[e.length-1]===t[t.length-1]&&e.slice(1,-1)}const n=0,s=1,r=2,l=0,i=2;function o(e,t){for(let n=e.length;n--;)for(let s=e[n].length;s>2;)if(t(e[n][--s],e[n][--s],s,e[n]))return}const f={tag:"hbs",tagOut:"html",runtime:"hyperstache/runtime"};export default function({types:u},c={}){c={...f,...c};const a=(e,t,n)=>{const s=[],r=[];for(let n=1;n<e.length;n++){const l=e[n],i=e[++n];if("number"==typeof l)r.push(t[l]);else if(i>=4){const t=e[++n],s=e[++n];let o=h(l);if(u.isIdentifier(o)){const e=[u.stringLiteral(l),u.identifier("ctx")],n=[];t.length>0&&n.push(u.objectProperty(u.identifier("params"),u.arrayExpression(t.map(d)))),Object.keys(s).length>0&&n.push(u.objectProperty(u.identifier("hash"),u.objectExpression(Object.keys(s).map(e=>u.objectProperty(u.stringLiteral(e),h(s[e])))))),n.push(u.objectProperty(u.identifier("data"),u.identifier("data"),!1,!0)),n.push(u.objectProperty(u.identifier("depths"),u.identifier("depths"),!1,!0)),e.push(u.objectExpression(n)),o=u.callExpression(p("hys.expr"),e)}4===i&&(u.isCallExpression(o)||u.isStringLiteral(o))&&(o=u.callExpression(p("hys.escape"),[o])),r.push(o)}else if(1===i){const e=l[1][1],n=l[1][3],s=l[1][4],i=l[2],o=l[3],f=[u.stringLiteral(e),u.identifier("ctx")],c=[u.objectProperty(u.identifier("fn"),a([0].concat(l[1].slice(5)),t))];i.length>1&&c.push(u.objectProperty(u.identifier("inverse"),a(i,t))),n.length>0&&c.push(u.objectProperty(u.identifier("params"),u.arrayExpression(n.map(d)))),Object.keys(s).length>0&&c.push(u.objectProperty(u.identifier("hash"),u.objectExpression(Object.keys(s).map(e=>u.objectProperty(u.stringLiteral(e),d(s[e])))))),o&&c.push(u.objectProperty(u.identifier("inverted"),u.booleanLiteral(o))),c.push(u.objectProperty(u.identifier("data"),u.identifier("data"),!1,!0)),c.push(u.objectProperty(u.identifier("depths"),u.identifier("depths"),!1,!0)),f.push(u.objectExpression(c));let h=u.callExpression(p("hys.block"),f);r.push(h)}else s.push(u.templateElement({raw:l,cooked:l}))}const l=[];l.push(u.identifier("ctx")),l.push(u.identifier("data")),l.push(u.identifier("depths")),n&&l.push(u.identifier("hys"));const i=u.templateLiteral(s,r),o=u.taggedTemplateExpression(u.identifier(c.tagOut),i);return u.callExpression(u.identifier("template"),[u.arrowFunctionExpression(l,o)])};function p(e){const t=e.split(".");let n;for(let e=0;e<t.length;e++){const r=(s=t[e],u.isValidIdentifier(s)?u.identifier(s):u.stringLiteral(s));n=0===e?r:u.memberExpression(n,r)}var s;return n}function h(n){if(""===n)return u.stringLiteral(n);let s;switch("string"==typeof n&&(n=e(n)),typeof n){case"string":return(s=t(n,'"'))||(s=t(n,"'"))?u.stringLiteral(s):u.identifier(n);case"number":return u.numericLiteral(n);case"boolean":return u.booleanLiteral(n);default:return u.identifier(""+n)}}function d(n){switch("string"==typeof n&&(n=e(n)),typeof n){case"string":return t(n,'"')||t(n,"'"),u.stringLiteral(n);case"number":return u.numericLiteral(n);case"boolean":return u.booleanLiteral(n);default:return u.identifier(""+n)}}return{name:"hyperstache",visitor:{TaggedTemplateExpression:function(t){if(t.node.tag.name===c.tag){const f=t.node.quasi.quasis.map(e=>e.value.raw),p=[0,...t.node.quasi.expressions],h=function(t){let f,u,c,a,p,h,d,m,y,b,g,v=n,x="",$=[0],O=[$],j=O;for(let e=0;e<t.length;e++){f=t[e],e&&(v===n&&(w(),a||w("")),w(e));for(let e=0;e<f.length;e++)if(u=f[e],b=/\s/.test(u),v===n)"{"===u&&"{"===f[e+1]?(g=!1,w(),a||w(""),m=!0,c=4,v=s,e++):(b||(y=!0,g=!1),g&&b||(x+=u),"\n"===u&&(k(),j=j.concat(O),O=[$]),c=void 0);else if(h&&x!==h||"}"!==u||"}"!==f[e+1]||"}"===f[e+2])if(6===c)"--"===(x=f[e-1]+u)&&(h=x);else if(p)u===p&&(p=""),x+=u;else if('"'===u||"'"===u)p=u,x+=u;else if(b)c===i?(f=`{{#/${x}${f.substr(e)}`,v=n,e=-1,x=""):x&&(w(),d="");else if("~"===u&&"}"===f[e+1])g=!0;else if(x||"~"!==u)if((x||"{"!==u&&"&"!==u)&&"}"!==u)if(x||"!"!==u)if(x||"#"!==u&&"^"!==u)"="===u?(d=x,x=""):"/"===u?($[0][4]&&(f=`}}{{/${f.substr(e+1)}`,e=-1),v=$[0],($=$[0][0]).push(v,1),c=3):x+=u;else{const t=[$];$=t[1]=[t],O.push($),t[2]=[t],t[3]="^"===u,t[4]="/"===f[e+1]&&++e,c=3,v=s}else c=6;else c=5,y=!0;else o(j,(e,t,n,s)=>{if(e>l||e===l&&(s[n]=t.replace(/\s*$/,"")))return!0});else 4!==c&&5!==c||(y=!0),6===c?w(""):w(),h=!1,v=n,e++}return w(),a||w(""),k(),$;function w(t){v!==n||null==t&&!x?v>=s&&(null!=t||x)&&(v===s?"else"===x||"^"===x?($=$[0][2],O.push($),c=i,v=s):($.push(null!=t?t:x,c,[],{}),v=r):($[$.length-3]=c,d?$[$.length-1][d]=e(x):$[$.length-2].push(e(x)))):$.push(null!=t?t:x,l),a=x,x=""}function k(){m&&!y&&(x=x.replace(/\r?\n$/,""),o(O,(e,t,n,s)=>{if(e===l&&(s[n]=t.replace(/[^\S\n]*$/,"")))return!0})),y=!1,m=!1}}(f),d=a(h,p,!0),m=u.variableDeclaration("const",[u.variableDeclarator(u.objectPattern([u.objectProperty(u.identifier("template"),u.identifier("template"),!1,!0)]),u.callExpression(u.identifier("require"),[u.stringLiteral(c.runtime)]))]);t.replaceWithMultiple([m,u.expressionStatement(d)])}}}}} |
{ | ||
"name": "babel-plugin-hyperstache", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"description": "Babel plugin to pre-compile handlebars.", | ||
@@ -8,5 +8,5 @@ "main": "dist/babel-plugin-hyperstache.js", | ||
"files": [ | ||
"module", | ||
"dist", | ||
"src" | ||
"module", | ||
"dist", | ||
"src" | ||
], | ||
@@ -13,0 +13,0 @@ "author": "Wesley Luyten <me@wesleyluyten.com> (https://wesleyluyten.com)", |
@@ -7,1 +7,50 @@ # `babel-plugin-hyperstache` | ||
Basic usage: | ||
```js | ||
[ | ||
["hyperstache", { | ||
"tag": "hbs", | ||
"tagOut": "html", | ||
"runtime": "hyperstache/runtime" | ||
}] | ||
] | ||
``` | ||
```js | ||
// input: | ||
hbs`<div id=hello>{{fruit}}</div>`({ fruit: 'Apple' }); | ||
// output: | ||
const { template } = require("hyperstache/runtime"); | ||
template((hys,ctx,data) => html`<div id=hello>${ | ||
hys.escape(hys.expr("fruit",ctx,{data})) | ||
}</div>`)({ fruit: 'Apple' }); | ||
``` | ||
## options | ||
### `tag=hbs` | ||
By default, `babel-plugin-hyperstache` will process all Tagged Templates with a tag function named `hbs`. To use a different name, use the `tag` option in your Babel configuration: | ||
```js | ||
{"plugins":[ | ||
["babel-plugin-hyperstache", { | ||
"tag": "myCustomHbsFunction" | ||
}] | ||
]} | ||
``` | ||
### `tagOut=html` | ||
The output tag given to Tagged Templates for further processing. | ||
```js | ||
{"plugins":[ | ||
["babel-plugin-hyperstache", { | ||
"tagOut": "myCustomHtmlFunction" | ||
}] | ||
]} | ||
``` |
260
src/index.js
import { build, EXPR_VAR, CHILD_RECURSE } from '../../../src/build.js'; | ||
import { unwrap, parseLiteral, log } from '../../../src/utils.js'; | ||
const defaults = { | ||
tag: 'hbs', | ||
tagOut: 'html', | ||
runtime: 'hyperstache/runtime' | ||
} | ||
/** | ||
@@ -11,5 +17,7 @@ * @param {Babel} babel | ||
export default function hysBabelPlugin({ types: t }, options = {}) { | ||
options = { ...defaults, ...options }; | ||
function TaggedTemplateExpression(path) { | ||
const tag = path.node.tag.name; | ||
if (tag === hbsName) { | ||
if (tag === options.tag) { | ||
const stats = path.node.quasi.quasis.map(e => e.value.raw); | ||
@@ -21,33 +29,26 @@ const fields = [0, ...path.node.quasi.expressions]; | ||
const node = evaluate(built, fields); | ||
const node = evaluate(built, fields, true); | ||
// var _hys = require("hyperstache/runtime"); | ||
const runtimeTpl = t.variableDeclaration( | ||
'const', | ||
[ | ||
t.variableDeclarator( | ||
t.objectPattern([ | ||
t.objectProperty( | ||
t.identifier('template'), | ||
t.identifier('template'), | ||
false, | ||
true | ||
) | ||
]), | ||
t.callExpression( | ||
t.identifier('require'), | ||
[t.stringLiteral('hyperstache/runtime')] | ||
// const { template } = require("hyperstache/runtime"); | ||
const runtimeTpl = t.variableDeclaration('const', [ | ||
t.variableDeclarator( | ||
t.objectPattern([ | ||
t.objectProperty( | ||
t.identifier('template'), | ||
t.identifier('template'), | ||
false, | ||
true | ||
) | ||
) | ||
] | ||
); | ||
]), | ||
t.callExpression(t.identifier('require'), [ | ||
t.stringLiteral(options.runtime) | ||
]) | ||
) | ||
]); | ||
path.replaceWithMultiple([ | ||
runtimeTpl, | ||
t.expressionStatement(node) | ||
]); | ||
path.replaceWithMultiple([runtimeTpl, t.expressionStatement(node)]); | ||
} | ||
} | ||
const evaluate = (built, fields) => { | ||
const evaluate = (built, fields, root) => { | ||
const statics = []; | ||
@@ -71,41 +72,56 @@ const exprs = []; | ||
if (t.isIdentifier(expr)) { | ||
const args = [ | ||
t.stringLiteral(field), | ||
t.identifier('ctx') | ||
]; | ||
const args = [t.stringLiteral(field), t.identifier('ctx')]; | ||
const properties = []; | ||
if (params.length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
)) | ||
if (params.length > 0) { | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
) | ||
); | ||
} | ||
if (Object.keys(hash).length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression(Object.keys(hash).map((key) => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transform(hash[key]) | ||
); | ||
})) | ||
)); | ||
if (Object.keys(hash).length > 0) { | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression( | ||
Object.keys(hash).map(key => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transform(hash[key]) | ||
); | ||
}) | ||
) | ||
) | ||
); | ||
} | ||
properties.push(t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
)); | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
) | ||
); | ||
const options = t.objectExpression(properties); | ||
args.push(options); | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('depths'), | ||
t.identifier('depths'), | ||
false, // computed | ||
true // shorthand | ||
) | ||
); | ||
args.push(t.objectExpression(properties)); | ||
expr = t.callExpression(dottedIdentifier('hys.expr'), args); | ||
} | ||
if (type === EXPR_VAR && (t.isCallExpression(expr) || t.isStringLiteral(expr))) { | ||
if ( | ||
type === EXPR_VAR && | ||
(t.isCallExpression(expr) || t.isStringLiteral(expr)) | ||
) { | ||
expr = t.callExpression(dottedIdentifier('hys.escape'), [expr]); | ||
@@ -125,9 +141,7 @@ } | ||
const params = field[1][3]; | ||
const hash = field[1][4] | ||
const hash = field[1][4]; | ||
const inverse = field[2]; | ||
const inverted = field[3]; | ||
const args = [ | ||
t.stringLiteral(fnName), | ||
t.identifier('ctx') | ||
]; | ||
const args = [t.stringLiteral(fnName), t.identifier('ctx')]; | ||
@@ -137,3 +151,3 @@ const properties = [ | ||
t.identifier('fn'), | ||
evaluate([0].concat(field[1].slice(5))) | ||
evaluate([0].concat(field[1].slice(5)), fields) | ||
) | ||
@@ -143,37 +157,60 @@ ]; | ||
if (inverse.length > 1) { | ||
properties.push(t.objectProperty( | ||
t.identifier('inverse'), | ||
evaluate(inverse) | ||
)) | ||
properties.push( | ||
t.objectProperty(t.identifier('inverse'), evaluate(inverse, fields)) | ||
); | ||
} | ||
if (params.length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
)) | ||
if (params.length > 0) { | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('params'), | ||
t.arrayExpression(params.map(transformParams)) | ||
) | ||
); | ||
} | ||
if (Object.keys(hash).length > 0) { | ||
properties.push(t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression(Object.keys(hash).map((key) => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transformParams(hash[key]) | ||
); | ||
})) | ||
)); | ||
if (Object.keys(hash).length > 0) { | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('hash'), | ||
t.objectExpression( | ||
Object.keys(hash).map(key => { | ||
return t.objectProperty( | ||
t.stringLiteral(key), | ||
transformParams(hash[key]) | ||
); | ||
}) | ||
) | ||
) | ||
); | ||
} | ||
properties.push(t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
)); | ||
if (inverted) { | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('inverted'), | ||
t.booleanLiteral(inverted) | ||
) | ||
); | ||
} | ||
const options = t.objectExpression(properties); | ||
args.push(options); | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('data'), | ||
t.identifier('data'), | ||
false, // computed | ||
true // shorthand | ||
) | ||
); | ||
properties.push( | ||
t.objectProperty( | ||
t.identifier('depths'), | ||
t.identifier('depths'), | ||
false, // computed | ||
true // shorthand | ||
) | ||
); | ||
args.push(t.objectExpression(properties)); | ||
let expr = t.callExpression(dottedIdentifier('hys.block'), args); | ||
@@ -184,6 +221,8 @@ // log('EXPR', expr); | ||
// code === CHILD_APPEND | ||
statics.push(t.templateElement({ | ||
raw: field, | ||
cooked: field | ||
})); | ||
statics.push( | ||
t.templateElement({ | ||
raw: field, | ||
cooked: field | ||
}) | ||
); | ||
} | ||
@@ -193,12 +232,17 @@ } | ||
// log('EXPRS', exprs); | ||
const params = []; | ||
params.push(t.identifier('ctx')); | ||
params.push(t.identifier('data')); | ||
params.push(t.identifier('depths')); | ||
if (root) { | ||
params.push(t.identifier('hys')); | ||
} | ||
const params = [t.identifier('hys'), t.identifier('ctx'), t.identifier('data')]; | ||
const quasi = t.templateLiteral(statics, exprs); | ||
const body = t.taggedTemplateExpression(t.identifier(htmlName), quasi); | ||
const node = t.callExpression( | ||
t.identifier('template'), | ||
[t.arrowFunctionExpression(params, body)] | ||
); | ||
const body = t.taggedTemplateExpression(t.identifier(options.tagOut), quasi); | ||
const node = t.callExpression(t.identifier('template'), [ | ||
t.arrowFunctionExpression(params, body) | ||
]); | ||
return node; | ||
} | ||
}; | ||
@@ -208,5 +252,5 @@ function dottedIdentifier(keypath) { | ||
let out; | ||
for (let i=0; i<path.length; i++) { | ||
for (let i = 0; i < path.length; i++) { | ||
const ident = propertyName(path[i]); | ||
out = i===0 ? ident : t.memberExpression(out, ident); | ||
out = i === 0 ? ident : t.memberExpression(out, ident); | ||
} | ||
@@ -268,13 +312,11 @@ return out; | ||
// The tagged template tag function name we're looking for. | ||
// This is static because it's generally assigned via htm.bind(h), | ||
// which could be imported from elsewhere, making tracking impossible. | ||
const hbsName = options.tag || 'hbs'; | ||
const htmlName = options.tagOut || 'html'; | ||
return { | ||
name: 'hyperstache', | ||
visitor: { | ||
// The tagged template tag function name we're looking for. | ||
// This is static because it's generally assigned via hyperstache.bind(html), | ||
// which could be imported from elsewhere, making tracking impossible. | ||
return { | ||
name: 'hyperstache', | ||
visitor: { | ||
TaggedTemplateExpression | ||
} | ||
}; | ||
}; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56
20253
317
1