can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
247 lines (246 loc) • 12 kB
JavaScript
/*!
* CanJS - 2.3.34
* http://canjs.com/
* Copyright (c) 2018 Bitovi
* Mon, 30 Apr 2018 20:56:51 GMT
* Licensed MIT
*/
/*can@2.3.34#view/stache/mustache_core*/
define([
'can/util/library',
'can/view/utils',
'can/view/mustache_helpers',
'can/view/expression',
'can/view/live',
'can/elements',
'can/view/scope',
'can/view/node_lists'
], function (can, utils, mustacheHelpers, expression, live, elements, Scope, nodeLists) {
live = live || can.view.live;
elements = elements || can.view.elements;
Scope = Scope || can.view.Scope;
nodeLists = nodeLists || can.view.nodeLists;
var mustacheLineBreakRegExp = /(?:(?:^|(\r?)\n)(\s*)(\{\{([^\}]*)\}\}\}?)([^\S\n\r]*)($|\r?\n))|(\{\{([^\}]*)\}\}\}?)/g, getItemsStringContent = function (items, isObserveList, helperOptions, options) {
var txt = '';
for (var i = 0, len = items.length; i < len; i++) {
txt += helperOptions.fn(isObserveList ? items.attr('' + i) : items[i], options);
}
return txt;
}, k = function () {
};
var core = {
expression: expression,
makeEvaluator: function (scope, helperOptions, nodeList, mode, exprData, truthyRenderer, falseyRenderer, stringOnly) {
if (mode === '^') {
var temp = truthyRenderer;
truthyRenderer = falseyRenderer;
falseyRenderer = temp;
}
var value, helperOptionArg;
if (exprData instanceof expression.Call) {
helperOptionArg = {
fn: function () {
},
inverse: function () {
},
context: scope.attr('.'),
scope: scope,
nodeList: nodeList,
exprData: exprData,
helpersScope: helperOptions
};
utils.convertToScopes(helperOptionArg, scope, helperOptions, nodeList, truthyRenderer, falseyRenderer, stringOnly);
value = exprData.value(scope, helperOptions, helperOptionArg);
if (exprData.isHelper) {
return value;
}
} else {
var readOptions = {
isArgument: true,
args: [
scope.attr('.'),
scope
],
asCompute: true
};
var helperAndValue = exprData.helperAndValue(scope, helperOptions, readOptions, nodeList, truthyRenderer, falseyRenderer, stringOnly);
var helper = helperAndValue.helper;
value = helperAndValue.value;
if (helper) {
return exprData.evaluator(helper, scope, helperOptions, readOptions, nodeList, truthyRenderer, falseyRenderer, stringOnly);
}
}
if (!mode) {
if (value && value.isComputed) {
return value;
} else {
return function () {
return '' + (value != null ? value : '');
};
}
} else if (mode === '#' || mode === '^') {
helperOptionArg = {
fn: function () {
},
inverse: function () {
}
};
utils.convertToScopes(helperOptionArg, scope, helperOptions, nodeList, truthyRenderer, falseyRenderer, stringOnly);
return function () {
var finalValue;
if (can.isFunction(value) && value.isComputed) {
finalValue = value();
} else {
finalValue = value;
}
if (typeof finalValue === 'function') {
return finalValue;
} else if (utils.isArrayLike(finalValue)) {
var isObserveList = utils.isObserveLike(finalValue);
if (isObserveList ? finalValue.attr('length') : finalValue.length) {
if (stringOnly) {
return getItemsStringContent(finalValue, isObserveList, helperOptionArg, helperOptions);
} else {
return can.frag(utils.getItemsFragContent(finalValue, helperOptionArg, scope));
}
} else {
return helperOptionArg.inverse(scope, helperOptions);
}
} else {
return finalValue ? helperOptionArg.fn(finalValue || scope, helperOptions) : helperOptionArg.inverse(scope, helperOptions);
}
};
} else {
}
},
makeLiveBindingPartialRenderer: function (partialName, state) {
partialName = can.trim(partialName);
return function (scope, options, parentSectionNodeList) {
var nodeList = [this];
nodeList.expression = '>' + partialName;
nodeLists.register(nodeList, null, parentSectionNodeList || true, state.directlyNested);
var partialFrag = can.compute(function () {
var localPartialName = partialName;
var partial = options.attr('partials.' + localPartialName), renderer;
if (partial) {
renderer = function () {
return partial.render ? partial.render(scope, options, nodeList) : partial(scope, options);
};
} else {
var scopePartialName = scope.read(localPartialName, { isArgument: true }).value;
if (scopePartialName === null || !scopePartialName && localPartialName[0] === '*') {
return can.frag('');
}
if (scopePartialName) {
localPartialName = scopePartialName;
}
renderer = function () {
return can.isFunction(localPartialName) ? localPartialName(scope, options, nodeList) : can.view.render(localPartialName, scope, options, nodeList);
};
}
var res = can.__notObserve(renderer)();
return can.frag(res);
});
partialFrag.computeInstance.setPrimaryDepth(nodeList.nesting);
live.html(this, partialFrag, this.parentNode, nodeList);
};
},
makeStringBranchRenderer: function (mode, expressionString) {
var exprData = core.expression.parse(expressionString), fullExpression = mode + expressionString;
if (!(exprData instanceof expression.Helper) && !(exprData instanceof expression.Call)) {
exprData = new expression.Helper(exprData, [], {});
}
return function branchRenderer(scope, options, truthyRenderer, falseyRenderer) {
var evaluator = scope.__cache[fullExpression];
if (mode || !evaluator) {
evaluator = makeEvaluator(scope, options, null, mode, exprData, truthyRenderer, falseyRenderer, true);
if (!mode) {
scope.__cache[fullExpression] = evaluator;
}
}
var res = evaluator();
return res == null ? '' : '' + res;
};
},
makeLiveBindingBranchRenderer: function (mode, expressionString, state) {
var exprData = core.expression.parse(expressionString);
if (!(exprData instanceof expression.Helper) && !(exprData instanceof expression.Call)) {
exprData = new expression.Helper(exprData, [], {});
}
return function branchRenderer(scope, options, parentSectionNodeList, truthyRenderer, falseyRenderer) {
var nodeList = [this];
nodeList.expression = expressionString;
nodeLists.register(nodeList, null, parentSectionNodeList || true, state.directlyNested);
var evaluator = makeEvaluator(scope, options, nodeList, mode, exprData, truthyRenderer, falseyRenderer, state.tag);
var gotCompute = evaluator.isComputed, compute;
if (gotCompute) {
compute = evaluator;
} else {
compute = can.compute(evaluator, null, false);
}
compute.computeInstance.setPrimaryDepth(nodeList.nesting);
compute.computeInstance.bind('change', k);
var value = compute();
if (typeof value === 'function') {
can.__notObserve(value)(this);
} else if (gotCompute || compute.computeInstance.hasDependencies) {
if (state.attr) {
live.simpleAttribute(this, state.attr, compute);
} else if (state.tag) {
live.attributes(this, compute);
} else if (state.text && typeof value !== 'object') {
live.text(this, compute, this.parentNode, nodeList);
} else {
live.html(this, compute, this.parentNode, nodeList);
}
} else {
if (state.attr) {
can.attr.set(this, state.attr, value);
} else if (state.tag) {
live.setAttributes(this, value);
} else if (state.text && typeof value === 'string') {
this.nodeValue = value;
} else if (value != null) {
elements.replace([this], can.frag(value, this.ownerDocument));
}
}
compute.computeInstance.unbind('change', k);
};
},
splitModeFromExpression: function (expression, state) {
expression = can.trim(expression);
var mode = expression.charAt(0);
if ('#/{&^>!'.indexOf(mode) >= 0) {
expression = can.trim(expression.substr(1));
} else {
mode = null;
}
if (mode === '{' && state.node) {
mode = null;
}
return {
mode: mode,
expression: expression
};
},
cleanLineEndings: function (template) {
return template.replace(mustacheLineBreakRegExp, function (whole, returnBefore, spaceBefore, special, expression, spaceAfter, returnAfter, spaceLessSpecial, spaceLessExpression, matchIndex) {
spaceAfter = spaceAfter || '';
returnBefore = returnBefore || '';
spaceBefore = spaceBefore || '';
var modeAndExpression = splitModeFromExpression(expression || spaceLessExpression, {});
if (spaceLessSpecial || '>{'.indexOf(modeAndExpression.mode) >= 0) {
return whole;
} else if ('^#!/'.indexOf(modeAndExpression.mode) >= 0) {
return special + (matchIndex !== 0 && returnAfter.length ? returnBefore + '\n' : '');
} else {
return spaceBefore + special + spaceAfter + (spaceBefore.length || matchIndex !== 0 ? returnBefore + '\n' : '');
}
});
},
Options: utils.Options
};
var makeEvaluator = core.makeEvaluator, splitModeFromExpression = core.splitModeFromExpression;
can.view.mustacheCore = core;
return core;
});