Comparing version 0.1.0-next.1 to 0.1.0-next.2
@@ -1,5 +0,127 @@ | ||
const utils = require('tempura/utils'); | ||
const ESCAPE = /[&"<]/g, CHARS = { | ||
'"': '"', | ||
'&': '&', | ||
'<': '<', | ||
}; | ||
const ENDLINES = /[\r\n]+$/g; | ||
const CURLY = /{{{?\s*([\s\S]*?)\s*}}}?/g; | ||
const ARGS = /([a-zA-Z$_][^\s=]*)\s*=\s*((["`'])(?:(?=(\\?))\4.)*?\3|{[^}]*}|\[[^\]]*]|\S+)/g; | ||
// $$1 = escape() | ||
// $$2 = extra blocks | ||
// $$3 = template values | ||
function gen(input, options) { | ||
options = options || {}; | ||
let char, num, action, tmp; | ||
let last = CURLY.lastIndex = 0; | ||
let wip='', txt='', match, inner; | ||
let extra=options.blocks||{}, stack=[]; | ||
let initials = new Set(options.props||[]); | ||
function close() { | ||
if (wip.length > 0) { | ||
txt += (txt ? 'x+=' : '=') + '`' + wip + '`;'; | ||
} else if (txt.length === 0) { | ||
txt = '="";' | ||
} | ||
wip = ''; | ||
} | ||
while (match = CURLY.exec(input)) { | ||
wip += input.substring(last, match.index).replace(ENDLINES, ''); | ||
last = match.index + match[0].length; | ||
inner = match[1].trim(); | ||
char = inner.charAt(0); | ||
if (char === '!') { | ||
// comment, continue | ||
} else if (char === '#') { | ||
close(); | ||
[, action, inner] = /^#\s*(\w[\w\d]+)\s*([^]*)/.exec(inner); | ||
if (action === 'expect') { | ||
inner.split(/[\n\r\s\t]*,[\n\r\s\t]*/g).forEach(key => { | ||
initials.add(key); | ||
}); | ||
} else if (action === 'var') { | ||
num = inner.indexOf('='); | ||
tmp = inner.substring(0, num++).trim(); | ||
inner = inner.substring(num).trim().replace(/[;]$/, ''); | ||
txt += `var ${tmp}=${inner};`; | ||
} else if (action === 'each') { | ||
num = inner.indexOf(' as '); | ||
stack.push(action); | ||
if (!~num) { | ||
txt += `for(var i=0,$$a=${inner};i<$$a.length;i++){`; | ||
} else { | ||
tmp = inner.substring(0, num).trim(); | ||
inner = inner.substring(num + 4).trim(); | ||
let [item, idx='i'] = inner.replace(/[()\s]/g, '').split(','); // (item, idx?) | ||
txt += `for(var ${idx}=0,${item},$$a=${tmp};${idx}<$$a.length;${idx}++){${item}=$$a[${idx}];`; | ||
} | ||
} else if (action === 'if') { | ||
txt += `if(${inner}){`; | ||
stack.push(action); | ||
} else if (action === 'elif') { | ||
txt += `}else if(${inner}){`; | ||
} else if (action === 'else') { | ||
txt += `}else{`; | ||
} else if (extra[action]) { | ||
if (inner.length) { | ||
tmp = []; | ||
// parse arguments, `defer=true` -> `{ defer: true }` | ||
while (match = ARGS.exec(inner)) tmp.push(match[1] + ':' + match[2]); | ||
inner = tmp.length ? '{' + tmp.join() + '}' : ''; | ||
} | ||
tmp = (options.async) ? 'await ' : ''; | ||
wip += '${' + tmp + '$$2.' + action + '(' + inner + ')}'; | ||
} else { | ||
throw new Error(`Unknown "${action}" block`); | ||
} | ||
} else if (char === '/') { | ||
action = inner.substring(1); | ||
inner = stack.pop(); | ||
close(); | ||
if (action === inner) txt += '}'; | ||
else throw new Error(`Expected to close "${inner}" block; closed "${action}" instead`); | ||
} else if (match[0].charAt(2) === '{') { | ||
wip += '${' + inner + '}'; // {{{ raw }}} | ||
} else { | ||
wip += '${$$1(' + inner + ')}'; | ||
} | ||
} | ||
if (stack.length > 0) { | ||
throw new Error(`Unterminated "${stack.pop()}" block`); | ||
} | ||
if (last < input.length) { | ||
wip += input.substring(last).replace(ENDLINES, ''); | ||
} | ||
close(); | ||
tmp = initials.size ? `{${ [...initials].join() }}=$$3,x` : ' x'; | ||
return `var${tmp + txt}return x`; | ||
} | ||
function esc(value) { | ||
if (typeof value !== 'string') return value; | ||
let last=ESCAPE.lastIndex=0, tmp=0, out=''; | ||
while (ESCAPE.test(value)) { | ||
tmp = ESCAPE.lastIndex - 1; | ||
out += value.substring(last, tmp) + CHARS[value[tmp]]; | ||
last = tmp + 1; | ||
} | ||
return out + value.substring(last); | ||
} | ||
function compile(input, options={}) { | ||
return new Function('$$1', '$$2', '$$3', utils.gen(input, options)).bind(0, options.escape || utils.esc, options.blocks); | ||
return new (options.async ? (async()=>{}).constructor : Function)( | ||
'$$1', '$$2', '$$3', gen(input, options) | ||
).bind(0, options.escape || esc, options.blocks); | ||
} | ||
@@ -10,8 +132,11 @@ | ||
options.format === 'cjs' | ||
? 'var{esc:$$1}=require("tempura/utils");module.exports=' | ||
: 'import{esc as $$1}from"tempura/utils";export default ' | ||
) + 'function($$3,$$2){'+utils.gen(input, options)+'}'; | ||
? 'var $$1=require("tempura").esc;module.exports=' | ||
: 'import{esc as $$1}from"tempura";export default ' | ||
) + ( | ||
options.async ? 'async ' : '' | ||
) + 'function($$3,$$2){'+gen(input, options)+'}'; | ||
} | ||
exports.compile = compile; | ||
exports.esc = esc; | ||
exports.transform = transform; |
@@ -1,6 +0,14 @@ | ||
import type { Options } from 'tempura/utils'; | ||
import { esc } from 'tempura/utils'; | ||
export type Args = Record<string, any>; | ||
export type Block<T extends Args = Args> = (args: T) => string; | ||
export type Compiler = <T extends Record<string, any>> (data: T) => string; | ||
export type Compiler = <T extends Record<string, any>> (data: T) => string; | ||
export interface Options { | ||
props?: string[]; | ||
blocks?: Record<string, Block>; | ||
async?: boolean; | ||
} | ||
export function esc<T=unknown>(value: T): T|string; | ||
export function compile(input: string, options?: Options & { escape?: typeof esc; }): Compiler; | ||
export function transform(input: string, options?: Options & { format?: 'esm' | 'cjs' }): string; |
{ | ||
"name": "tempura", | ||
"version": "0.1.0-next.1", | ||
"version": "0.1.0-next.2", | ||
"repository": "lukeed/tempura", | ||
@@ -19,4 +19,4 @@ "description": "WIP", | ||
"scripts": { | ||
"build": "bundt", | ||
"test": "uvu -r esm -r module-alias/register test" | ||
"build": "node bin && bundt", | ||
"test": "uvu -r esm test" | ||
}, | ||
@@ -33,10 +33,5 @@ "files": [ | ||
}, | ||
"./utils": { | ||
"import": "./utils/index.mjs", | ||
"require": "./utils/index.js" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"modes": { | ||
"utils": "src/utils.js", | ||
"default": "src/index.js" | ||
@@ -46,10 +41,6 @@ }, | ||
"devDependencies": { | ||
"bundt": "1.1.3", | ||
"bundt": "1.1.5", | ||
"esm": "3.2.25", | ||
"module-alias": "2.2.2", | ||
"uvu": "0.5.1" | ||
}, | ||
"_moduleAliases": { | ||
"tempura/utils": "src/utils.js" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
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
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
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
14368
3
0
134
1
6