tripartite
Advanced tools
Comparing version 1.0.16 to 1.1.0
{ | ||
"name": "tripartite", | ||
"version": "1.0.16", | ||
"version": "1.1.0", | ||
"description": "A simple and fast javascript templating library", | ||
@@ -26,6 +26,20 @@ "main": "tripartite.js", | ||
"devDependencies": { | ||
"browserify": "^17.0.0", | ||
"chai": "^4.1.2", | ||
"mocha": "^3.4.2", | ||
"mocha": "^10.2.0", | ||
"stream-buffers": "^3.0.1" | ||
} | ||
,"files": [ | ||
"active-element.js" | ||
,"browserify-transform.js" | ||
,"calculate-relative-path.js" | ||
,"evaluate-in-context.js" | ||
,"execution-context.js" | ||
,"resolve-data-path.js" | ||
,"tripartite.js" | ||
,"webpack-loader.mjs" | ||
,"helpers" | ||
,"README" | ||
] | ||
} |
var calculateRelativePath = require('./calculate-relative-path') | ||
if(typeof String.prototype.trim !== 'function') { | ||
String.prototype.trim = function() { | ||
return this.replace(/^\s+|\s+$/g, ''); | ||
} | ||
} | ||
function cloneArray(ar) { | ||
var consumed = [] | ||
for(var i = 0; i < ar.length; i++) { | ||
consumed.push(ar[i]) | ||
if (typeof String.prototype.trim !== 'function') { | ||
String.prototype.trim = function () { | ||
return this.replace(/^\s+|\s+$/g, ''); | ||
} | ||
return consumed | ||
} | ||
var stackDepth = 0; | ||
function callCallback(callback) { | ||
if(callback) { | ||
if(stackDepth < 10) { | ||
stackDepth++ | ||
return callback() | ||
} | ||
else { | ||
stackDepth = 0; | ||
if(process && process.nextTick) { | ||
process.nextTick(callback) | ||
} | ||
else { | ||
setTimeout(callback) | ||
} | ||
} | ||
} | ||
function isStream(stream) { | ||
return stream !== null | ||
&& typeof stream === 'object' | ||
&& typeof stream.pipe === 'function'; | ||
} | ||
var Tripartite = function() { | ||
this.templates = { | ||
defaultTemplate: function(thedata) { | ||
return '' + thedata; | ||
} | ||
function isTemplate(obj) { | ||
if (!obj) { | ||
return false | ||
} | ||
this.templates.defaultTemplate.write = function(thedata, stream, callback) { | ||
stream.write('' + thedata) | ||
callCallback(callback) | ||
if (typeof obj !== 'function') { | ||
return false | ||
} | ||
this.constants = { | ||
templateBoundary: '__', | ||
templateNameBoundary: '##' | ||
if (!obj.write) { | ||
return false | ||
} | ||
// This object (if set) will receive the template functions parsed from a script | ||
// I want to be able to call my templates as global functions, so I've set it | ||
// to be the window object | ||
this.secondaryTemplateFunctionObject = null | ||
this.loaders = [] | ||
this.dataFunctions = {} | ||
if (!obj.parts) { | ||
return false | ||
} | ||
if (!obj.templateMeta) { | ||
return false | ||
} | ||
return true | ||
} | ||
var t = Tripartite | ||
let ExecutionContext = require('./execution-context') | ||
let ActiveElement = require('./active-element') | ||
t.prototype.addTemplate = function(name, template) { | ||
if(typeof template !== 'function') { | ||
template = this.pt(template); | ||
} | ||
if(!template.write) { | ||
var oldFun = template | ||
template = function(cc, globalData) { | ||
if(arguments.length > 1 && arguments[1] && arguments[1].write) { | ||
template.write.apply(this, arguments) | ||
} | ||
else { | ||
return oldFun(cc, globalData) | ||
} | ||
class Tripartite { | ||
constructor(options = {}) { | ||
this.templates = { | ||
defaultTemplate: this._makeTemplate(function (thedata) { | ||
return '' + thedata; | ||
}) | ||
} | ||
template.write = function(cc, stream, callback) { | ||
stream.write(oldFun(cc)) | ||
callCallback(callback) | ||
} | ||
} | ||
this.templates[name] = template; | ||
template.templateMeta = template.templateMeta || {} | ||
template.templateMeta.name = name | ||
return template; | ||
}; | ||
let { constants = { | ||
templateBoundary: '__', | ||
templateNameBoundary: '##' | ||
} } = options | ||
this.constants = constants | ||
t.prototype.createBlank = function() { | ||
return new Tripartite() | ||
} | ||
// This object (if set) will receive the template functions parsed from a script | ||
// I want to be able to call my templates as global functions, so I've set it | ||
// to be the window object | ||
this.secondaryTemplateFunctionObject = options.secondaryTemplateFunctionObject | ||
t.prototype.getTemplate = function(name) { | ||
return this.templates[name] | ||
} | ||
this.loaders = options.loaders || [] | ||
t.prototype.loadTemplate = function(name, callback) { | ||
if(name in this.templates) { | ||
callback(this.templates[name]) | ||
this.dataFunctions = options.dataFunction || {} | ||
} | ||
else { | ||
var tri = this | ||
var count = this.loaders.length | ||
var done = false | ||
var self = this | ||
for(var i = 0; i < this.loaders.length; i++) { | ||
this.loaders[i](name, function(template) { | ||
if(done) { | ||
return | ||
_makeTemplate(transformationFunction) { | ||
if (isTemplate(transformationFunction)) { | ||
return transformationFunction | ||
} | ||
let tri = this | ||
let f = function (thedata) { | ||
let stream = null | ||
let options = null | ||
let callback = null | ||
for (let i = 1; i < arguments.length; i++) { | ||
let arg = arguments[i] | ||
if (isStream(arg)) { | ||
stream = arg | ||
} | ||
count-- | ||
if(template) { | ||
done = true | ||
tri.addTemplate(name, template) | ||
callback(tri.getTemplate(name)) | ||
else if(typeof arg === 'function') { | ||
callback = arg | ||
} | ||
else if(count == 0) { | ||
self.templates[name] = null | ||
callback(null) | ||
else if(typeof arg === 'object') { | ||
options = arg | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
t.prototype.parseTemplateScript = function(tx) { | ||
var tks = this.tts(tx); | ||
/* current template name */ | ||
var ctn = null; | ||
for(var i = 0; i < tks.length; i++) { | ||
var token = tks[i]; | ||
if(token.active) { | ||
ctn = token.content; | ||
return f.write(thedata, stream, callback, options) | ||
} | ||
else { | ||
if(ctn) { | ||
var template = this.addTemplate(ctn, this.stw(token.content)); | ||
if(this.secondaryTemplateFunctionObject) { | ||
this.secondaryTemplateFunctionObject[ctn] = template; | ||
} | ||
ctn = null; | ||
f.write = function (thedata, stream, callback, options = {}) { | ||
if(transformationFunction && transformationFunction.write) { | ||
// if it's not a template, but has a write method, invoke the right method directly | ||
return transformationFunction.write.apply(transformationFunction, arguments) | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
let dest = stream || '' | ||
/* strip template whitespace */ | ||
t.prototype.stw = function(txt) { | ||
var i = txt.indexOf('\n'); | ||
if(i > -1 && txt.substring(0, i).trim() == '') { | ||
txt = txt.substring(i + 1); | ||
} | ||
i = txt.lastIndexOf('\n'); | ||
if(i > -1 && txt.substring(i).trim() == '') { | ||
txt = txt.substring(0, i); | ||
} | ||
return txt; | ||
}; | ||
let context = new ExecutionContext(tri, f, thedata, dest, tri.dataFunctions) | ||
if (options && 'continueOnTripartiteError' in options) { | ||
context.continueOnTripartiteError = options.continueOnTripartiteError | ||
} | ||
t.prototype.ActiveElement = function(/* the conditional */cd, data, hd, tripartite) { | ||
/* assign the conditional expression */ | ||
this.ce = cd; | ||
/* assign the data selector expression */ | ||
this.dse = data; | ||
this.tripartite = tripartite | ||
/* assign the hd expression */ | ||
if(hd) { | ||
this.he = hd; | ||
} | ||
else { | ||
this.he = 'defaultTemplate'; | ||
} | ||
/* evaluated data */ | ||
this.ed = null; | ||
}; | ||
var ae = t.prototype.ActiveElement; | ||
/* SimpleTemplate */ | ||
t.prototype.st = function(/* conditional expression */ cd, data, /* handling expression */ hd, tripartite, templateMeta) { | ||
this.tripartite = tripartite | ||
var el = new ae(cd, data, hd, tripartite); | ||
el.templateMeta = templateMeta | ||
var f = function(cc, globalData) { | ||
if(arguments.length > 1 && arguments[1] && arguments[1].write) { | ||
el.write.apply(el, arguments) | ||
return context.run(callback) | ||
} | ||
} | ||
else { | ||
return el.run(cc, globalData); | ||
f.parts = [] | ||
if (transformationFunction && typeof transformationFunction === 'function') { | ||
f.parts.push(transformationFunction) | ||
} | ||
f.templateMeta = {} | ||
return f | ||
} | ||
f.templateMeta = templateMeta | ||
f.write = function(cc, stream, callback, globalData) { | ||
el.write(cc, stream, callback, globalData) | ||
} | ||
return f | ||
}; | ||
ae.prototype.run = function(/* current context */cc, globalData) { | ||
/* run template */ | ||
var rt = false; | ||
/* evaluated data */ | ||
this.ed = this.edse(cc, globalData); | ||
if(this.ce) { | ||
rt = this.eic(cc, this.ce, globalData); | ||
} | ||
else { | ||
if(this.ed instanceof Array) { | ||
if(this.ed.length > 0) { | ||
rt = true; | ||
} | ||
addTemplate(name, template) { | ||
if (typeof template === 'string') { | ||
template = this.parseTemplate(template); | ||
} | ||
else { | ||
if(this.ed) { | ||
rt = true; | ||
} | ||
else if(!this.dse) { | ||
rt = true | ||
this.ed = cc | ||
} | ||
else if (typeof template === 'function') { | ||
template = this._makeTemplate(template) | ||
} | ||
this.templates[name] = template; | ||
template.templateMeta = template.templateMeta || {} | ||
template.templateMeta.name = name | ||
return template; | ||
} | ||
var at = this.he; | ||
if(at.charAt(0) == '$') { | ||
at = this.eic(cc, at.substring(1), globalData); | ||
createBlank() { | ||
return new Tripartite() | ||
} | ||
if(!at) { | ||
at = 'defaultTemplate'; | ||
getTemplate(name) { | ||
return this.templates[name] | ||
} | ||
// resolve relative template paths | ||
if(at.indexOf('./') == 0 || at.indexOf('../') == 0) { | ||
at = calculateRelativePath(this.templateMeta.name, at) | ||
} | ||
if(rt) { | ||
if(this.ed instanceof Array) { | ||
var r = ''; | ||
for(var i = 0; i < this.ed.length; i++) { | ||
r += this.getTemplate(at)(this.ed[i], globalData || cc); | ||
} | ||
return r; | ||
loadTemplate(name, callback) { | ||
if (name in this.templates) { | ||
callback(this.templates[name]) | ||
} | ||
else { | ||
return this.getTemplate(at)(this.ed, globalData || cc); | ||
} | ||
} | ||
return ''; | ||
}; | ||
let tri = this | ||
let count = this.loaders.length | ||
let done = false | ||
ae.prototype.write = function(/* current context */cc, stream, callback, globalData) { | ||
/* run template */ | ||
var rt = false; | ||
/* evaluated data */ | ||
this.ed = this.edse(cc, globalData); | ||
if(this.ce) { | ||
rt = this.eic(cc, this.ce, globalData); | ||
} | ||
else { | ||
if(this.ed instanceof Array) { | ||
if(this.ed.length > 0) { | ||
rt = true; | ||
if (count == 0) { | ||
tri.templates[name] = null | ||
callback(tri.getTemplate(name)) | ||
} | ||
} | ||
else { | ||
if(this.ed) { | ||
rt = true; | ||
else { | ||
this.loaders.forEach(loader => { | ||
if (done) { | ||
return | ||
} | ||
loader(name, template => { | ||
if (done) { | ||
return | ||
} | ||
count-- | ||
if (template) { | ||
done = true | ||
tri.addTemplate(name, template) | ||
} | ||
else if (count == 0) { | ||
done = true | ||
tri.templates[name] = null | ||
} | ||
if (done) { | ||
callback(tri.getTemplate(name)) | ||
} | ||
}) | ||
}) | ||
} | ||
else if(!this.dse) { | ||
rt = true | ||
this.ed = cc | ||
} | ||
} | ||
} | ||
var at = this.he; | ||
if(at.charAt(0) == '$') { | ||
at = this.eic(cc, at.substring(1), globalData); | ||
} | ||
if(!at) { | ||
at = 'defaultTemplate'; | ||
} | ||
// resolve relative template paths | ||
if(at.indexOf('./') == 0 || at.indexOf('../') == 0) { | ||
at = calculateRelativePath(this.templateMeta.name, at) | ||
} | ||
var self = this | ||
if(rt) { | ||
this.tripartite.loadTemplate(at, function(template) { | ||
var consumed | ||
if(self.ed instanceof Array) { | ||
consumed = cloneArray(self.ed) | ||
parseTemplateScript(tx) { | ||
var tks = this.tokenizeTemplateScript(tx); | ||
/* current template name */ | ||
var ctn = null; | ||
for (var i = 0; i < tks.length; i++) { | ||
var token = tks[i]; | ||
if (token.active) { | ||
ctn = token.content; | ||
} | ||
else { | ||
consumed = [self.ed] | ||
} | ||
var procConsumed = function() { | ||
if(template) { | ||
template.write(consumed.shift(), stream, function() { | ||
if(consumed.length > 0) { | ||
procConsumed() | ||
} | ||
else if(callback) { | ||
callCallback(callback) | ||
} | ||
}, globalData || cc) | ||
} | ||
else { | ||
if(callback) { | ||
var err = new Error('Cound not load template: ' + at) | ||
err.templateName = at | ||
err.type = 'missing template' | ||
callback(err) | ||
if (ctn) { | ||
var template = this.addTemplate(ctn, this.stripTemplateWhitespace(token.content)); | ||
if (this.secondaryTemplateFunctionObject) { | ||
this.secondaryTemplateFunctionObject[ctn] = template; | ||
} | ||
else { | ||
console.error('Cound not load template: ' + at) | ||
} | ||
ctn = null; | ||
} | ||
} | ||
if(consumed.length > 0) { | ||
procConsumed() | ||
} | ||
else { | ||
callCallback(callback) | ||
} | ||
}) | ||
} | ||
} | ||
else { | ||
callCallback(callback) | ||
stripTemplateWhitespace(txt) { | ||
var i = txt.indexOf('\n'); | ||
if (i > -1 && txt.substring(0, i).trim() == '') { | ||
txt = txt.substring(i + 1); | ||
} | ||
i = txt.lastIndexOf('\n'); | ||
if (i > -1 && txt.substring(i).trim() == '') { | ||
txt = txt.substring(0, i); | ||
} | ||
return txt; | ||
} | ||
}; | ||
ae.prototype.getTemplate = function(name) { | ||
return this.tripartite.getTemplate(name) | ||
} | ||
/* evaluate data selector expression */ | ||
ae.prototype.edse = function(cc, globalData) { | ||
if(!this.dse) { | ||
return null; | ||
/* simple template */ | ||
_createActiveElement(/* conditional expression */ cd, data, /* handling expression */ hd, tripartite, templateMeta) { | ||
let el = new ActiveElement(cd, data, hd, tripartite); | ||
el.templateMeta = templateMeta | ||
return el | ||
} | ||
if(this.dse === '$this') { | ||
return cc; | ||
pt(tx) { | ||
return this.parseTemplate(tx) | ||
} | ||
return this.eic(cc, this.dse, globalData); | ||
}; | ||
/* parse template */ | ||
parseTemplate(tx) { | ||
var tks = this.tokenizeTemplate(tx); | ||
let t = this._makeTemplate() | ||
var templateMeta = t.templateMeta | ||
/* evaluate in context */ | ||
ae.prototype.eic = function(cc, ex, globalData) { | ||
cc = cc || {}; | ||
return this.eicwt.call(cc, cc, ex, this.tripartite.dataFunctions, globalData); | ||
}; | ||
/* Evaluate in context having been called so that this === cc (current context */ | ||
ae.prototype.eicwt = function(cc, ex, dataFunctions, globalData) { | ||
dataFunctions = dataFunctions || {} | ||
globalData = globalData || cc || {} | ||
with ({ | ||
'$globals': globalData | ||
}) { | ||
with (dataFunctions) { | ||
with (cc) { | ||
try { | ||
return eval(ex); | ||
} catch(e) { | ||
return null; | ||
} | ||
for (let tk of tks) { | ||
if (tk.active) { | ||
t.parts.push(this.tokenizeActivePart(tk.content, templateMeta)); | ||
} | ||
else if (tk.content) { | ||
t.parts.push(tk.content); | ||
} | ||
} | ||
return t | ||
} | ||
}; | ||
/* parse template */ | ||
t.prototype.pt = function(tx) { | ||
var tks = this.tt(tx); | ||
var pt = []; | ||
var templateMeta = {} | ||
for(var i = 0; i < tks.length; i++) { | ||
var tk = tks[i]; | ||
if(tk.active) { | ||
pt.push(this.tap(tk.content, templateMeta)); | ||
tokenizeActivePart(tx, templateMeta) { | ||
var con = null; | ||
var dat = null; | ||
var han = null; | ||
/* condition index */ | ||
var ci = tx.indexOf('??'); | ||
if (ci > -1) { | ||
con = tx.substring(0, ci); | ||
ci += 2; | ||
} | ||
else { | ||
if(tk.content) { | ||
pt.push(tk.content); | ||
} | ||
ci = 0; | ||
} | ||
} | ||
var t = function(cc, globalData) { | ||
if(arguments.length > 1 && arguments[1] && arguments[1].write) { | ||
t.write.apply(t, arguments) | ||
/* handler index */ | ||
var hi = tx.indexOf('::'); | ||
if (hi > -1) { | ||
dat = tx.substring(ci, hi); | ||
han = tx.substring(hi + 2); | ||
} | ||
else { | ||
var r = ''; | ||
for(var i = 0; i < pt.length; i++) { | ||
if(typeof pt[i] === 'string') { | ||
r += pt[i]; | ||
} | ||
else { | ||
r += pt[i](cc, globalData); | ||
} | ||
} | ||
return r; | ||
dat = tx.substring(ci); | ||
} | ||
return this._createActiveElement(con, dat, han, this, templateMeta); | ||
} | ||
t.templateMeta = templateMeta | ||
t.write = function(cc, stream, callback, globalData) { | ||
var consumed = cloneArray(pt) | ||
var lastError | ||
var procConsumed = function() { | ||
var unit = consumed.shift() | ||
if(typeof unit === 'string') { | ||
stream.write(unit) | ||
if(consumed.length > 0) { | ||
procConsumed() | ||
} | ||
else if(callback) { | ||
callCallback(callback) | ||
} | ||
} | ||
else { | ||
unit.write(cc, stream, function(err) { | ||
if(err && stream.continueOnTripartiteError) { | ||
lastError = err | ||
} | ||
if(err && callback && !stream.continueOnTripartiteError) { | ||
callback(err) | ||
} | ||
else if(consumed.length > 0) { | ||
procConsumed() | ||
} | ||
else if(callback) { | ||
if(lastError) { | ||
callback(lastError) | ||
} | ||
else { | ||
callCallback(callback) | ||
} | ||
} | ||
}, globalData) | ||
} | ||
} | ||
if(consumed.length > 0) { | ||
procConsumed() | ||
} | ||
tokenizeTemplate(tx) { | ||
return this.tokenizeActiveAndInactiveBlocks(tx, this.constants.templateBoundary); | ||
} | ||
return t | ||
}; | ||
/* tokenize active part */ | ||
t.prototype.tokenizeActivePart = function(tx, templateMeta) { | ||
var con = null; | ||
var dat = null; | ||
var han = null; | ||
/* condition index */ | ||
var ci = tx.indexOf('??'); | ||
if(ci > -1) { | ||
con = tx.substring(0, ci); | ||
ci += 2; | ||
/** tokenize template script */ | ||
tokenizeTemplateScript(tx) { | ||
return this.tokenizeActiveAndInactiveBlocks(tx, this.constants.templateNameBoundary); | ||
} | ||
else { | ||
ci = 0; | ||
} | ||
/* handler index */ | ||
var hi = tx.indexOf('::'); | ||
if(hi > -1) { | ||
dat = tx.substring(ci, hi); | ||
han = tx.substring(hi + 2); | ||
} | ||
else { | ||
dat = tx.substring(ci); | ||
} | ||
return new this.st(con, dat, han, this, templateMeta); | ||
} | ||
t.prototype.tap = t.prototype.tokenizeActivePart | ||
/* tokenize active and inactive blocks */ | ||
tokenizeActiveAndInactiveBlocks(text, /*Active Region Boundary */ boundary) { | ||
/* whole length */ | ||
let length = text.length | ||
/* tokenize template */ | ||
t.prototype.tokenizeTemplate = function(tx) { | ||
return this.taib(tx, this.constants.templateBoundary); | ||
} | ||
/* current position */ | ||
let position = 0 | ||
t.prototype.tt = t.prototype.tokenizeTemplate | ||
/* are we in an active region */ | ||
let act = false | ||
/** tokenize template script */ | ||
t.prototype.tts = function(tx) { | ||
return this.taib(tx, this.constants.templateNameBoundary); | ||
} | ||
let tokens = [] | ||
/* tokenize active and inactive blocks */ | ||
t.prototype.taib = function(tx, /*Active Region Boundary */ bnd) { | ||
/* whole length */ | ||
var l = tx.length; | ||
/* current position */ | ||
var p = 0; | ||
/* are we in an active region */ | ||
var act = false; | ||
var tks = []; | ||
while(p < l) { | ||
var i = tx.indexOf(bnd, p); | ||
if(i == -1) { | ||
i = l; | ||
while (position < length) { | ||
let i = text.indexOf(boundary, position); | ||
if (i == -1) { | ||
i = length; | ||
} | ||
var tk = { active: act, content: text.substring(position, i) }; | ||
tokens.push(tk); | ||
position = i + boundary.length; | ||
act = !act; | ||
} | ||
var tk = { active: act, content: tx.substring(p, i)}; | ||
tks.push(tk); | ||
p = i + 2; | ||
act = !act; | ||
return tokens; | ||
} | ||
return tks; | ||
} | ||
var tripartiteInstance = new Tripartite() | ||
if(typeof window != 'undefined') { | ||
if (typeof window != 'undefined') { | ||
tripartiteInstance.secondaryTemplateFunctionObject = window | ||
} | ||
function addCallbackToPromise(promise, callback) { | ||
if(callback) { | ||
promise = promise.then((obj) => { | ||
callback(null, obj) | ||
}).catch((err) => { | ||
callback(err) | ||
}) | ||
} | ||
return promise | ||
} | ||
if(module) { | ||
if (typeof module !== 'undefined') { | ||
module.exports = tripartiteInstance | ||
@@ -571,7 +313,7 @@ } | ||
if(global) { | ||
if(!global.Tripartite) { | ||
if (typeof global != 'undefined') { | ||
if (!global.Tripartite) { | ||
global.Tripartite = Tripartite | ||
} | ||
if(!global.tripartite) { | ||
if (!global.tripartite) { | ||
global.tripartite = tripartiteInstance | ||
@@ -578,0 +320,0 @@ } |
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
21467
4
11
739
2