New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

can-legacy-view-helpers

Package Overview
Dependencies
Maintainers
5
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

can-legacy-view-helpers - npm Package Compare versions

Comparing version 0.6.1 to 1.0.0

src/deferred.js

31

package.json
{
"name": "can-legacy-view-helpers",
"version": "0.6.1",
"version": "1.0.0",
"description": "Legacy view helpers used by can-ejs and can-mustache.",

@@ -22,3 +22,3 @@ "license": "MIT",

"testee": "testee test/test.html --browsers firefox",
"test": "npm run jshint && npm run testee",
"test": "npm run detect-cycle && npm run jshint && npm run testee",
"jshint": "jshint src/. --config",

@@ -29,3 +29,4 @@ "release:pre": "npm version pre && npm publish --tag=pre",

"release:major": "npm version major && npm publish",
"develop": "can-serve --static --develop --port 8080"
"develop": "can-serve --static --develop --port 8080",
"detect-cycle": "detect-cyclic-packages --ignore done-serve"
},

@@ -48,8 +49,21 @@ "main": "can-legacy-view-helpers",

"steal-tools"
]
],
"map": {
"can-legacy-view-helpers/deferred": "can-legacy-view-helpers/src/deferred",
"can-legacy-view-helpers/elements": "can-legacy-view-helpers/src/elements",
"can-legacy-view-helpers/live": "can-legacy-view-helpers/src/live",
"can-legacy-view-helpers/node_list": "can-legacy-view-helpers/src/node_list",
"can-legacy-view-helpers/render": "can-legacy-view-helpers/src/render",
"can-legacy-view-helpers/scanner": "can-legacy-view-helpers/src/scanner",
"can-legacy-view-helpers/view": "can-legacy-view-helpers/src/view"
}
},
"dependencies": {
"can-ajax": "^1.4.0",
"can-cid": "^1.0.3",
"can-compute": "^3.1.0",
"can-event": "^3.5.0",
"can-log": "^1.0.0",
"can-namespace": "^1.0.0",
"can-observation": "^3.3.5",
"can-util": "^3.9.0",

@@ -61,3 +75,6 @@ "can-view-callbacks": "^3.1.0",

"devDependencies": {
"documentjs": "^0.5.0",
"detect-cyclic-packages": "^1.1.0",
"documentjs": "^0.5.5",
"donejs-cli": "^1.0.1",
"generator-donejs": "^1.0.5",
"jshint": "^2.9.1",

@@ -67,6 +84,4 @@ "steal": "^1.5.2",

"steal-tools": "^1.3.3",
"testee": "^0.5.0",
"generator-donejs": "^1.0.5",
"donejs-cli": "^1.0.1"
"testee": "^0.8.0"
}
}
# can-legacy-view-helpers
[![Join the chat at https://gitter.im/canjs/canjs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/canjs/canjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join our Slack](https://img.shields.io/badge/slack-join%20chat-611f69.svg)](https://www.bitovi.com/community/slack?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join our Discourse](https://img.shields.io/discourse/https/forums.bitovi.com/posts.svg)](https://forums.bitovi.com/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/canjs/can-legacy-view-helpers/blob/master/LICENSE.md)

@@ -13,2 +14,6 @@ [![npm version](https://badge.fury.io/js/can-legacy-view-helpers.svg)](https://www.npmjs.com/package/can-legacy-view-helpers)

## Documentation
Read the [can-legacy-view-helpers API docs on CanJS.com](https://canjs.com/doc/can-legacy-view-helpers.html).
## Changelog

@@ -25,2 +30,1 @@

[MIT](https://github.com/canjs/can-legacy-view-helpers/blob/master/LICENSE.md)

@@ -10,2 +10,3 @@ var nodeLists = require("./node_list");

* @parent can.view
* @hide
*

@@ -23,2 +24,3 @@ * Provides helper methods for and information about the behavior

* @parent can.view.elements
* @hide
*

@@ -44,2 +46,3 @@ *

* @parent can.view.elements
* @hide
*

@@ -46,0 +49,0 @@ * A mapping of parent node names to child node names that can be inserted within

@@ -9,2 +9,3 @@ var view = require("./view");

* Helper(s)
* @hide
*/

@@ -11,0 +12,0 @@ var pendingHookups = [],

/**
* This module must be CJS format because is uses `with () { ... }`
* statements which will not work in ES6 since it forces strict mode.
* @hide
*/

@@ -13,2 +14,3 @@

* Helper(s)
* @hide
*/

@@ -88,2 +90,3 @@ var newLine = /(\r|\n)+/g,

* @constructor can.view.Scanner
* @hide
*

@@ -105,2 +108,3 @@ * can.view.Scanner is used to convert a template into a JavaScript function. That

* @typedef {{start: String, escape: String, scope: String, options: String}} can.view.Scanner.text
* @hide
*/

@@ -165,2 +169,3 @@ text: {},

* Extend can.View to add scanner support.
* @hide
*/

@@ -167,0 +172,0 @@ Scanner.prototype = {

@@ -14,4 +14,10 @@ // # can/view/view.js

each = require("can-util/js/each/each"),
can = require("can-namespace"),
Observation = require("can-observation"),
ajax = require("can-ajax/can-ajax"),
Deferred = require("./deferred"),
dev = require("can-log/dev/dev"),
// Used for hookup `id`s.
hookupId = 1;
hookupId = 1,
$view; // defined later

@@ -21,4 +27,173 @@ // internal utility methods

var isDeferred = function(maybeDeferred) {
return maybeDeferred instanceof Deferred;
};
var makeRenderer = function(textRenderer) {
if (textRenderer.renderType === "fragment") {
return textRenderer;
}
var renderer = function() {
return $view.frag(textRenderer.apply(this, arguments));
};
renderer.render = function() {
return textRenderer.apply(textRenderer, arguments);
};
return renderer;
};
// ##### checkText
// Makes sure there's a template, if not, have `steal` provide a warning.
var checkText = function (text, url) {
if (!text.length) {
// _removed if not used as a steal module_
//!steal-remove-start
dev.log("can/view/view.js: There is no template or an empty template at " + url);
//!steal-remove-end
throw new Error("can.view: No template or empty template:" + url);
}
};
// ##### get
// get a deferred renderer for provided url
/**
* @hide
* @function get
* @param {String | Object} obj url string or object with url property
* @param {Boolean} async If the ajax request should be asynchronous.
* @return {can.Deferred} a `view` renderer deferred.
*/
var getRenderer = function (obj, async) {
// If `obj` already is a renderer function just resolve a Deferred with it
if(isFunction(obj)) {
var def = Deferred();
return def.resolve(obj);
}
var url = typeof obj === 'string' ? obj : obj.url,
suffix = (obj.engine && '.' + obj.engine) || url.match(/\.[\w\d]+$/),
type,
// If we are reading a script element for the content of the template,
// `el` will be set to that script element.
el,
// A unique identifier for the view (used for caching).
// This is typically derived from the element id or
// the url for the template.
id;
//If the url has a #, we assume we want to use an inline template
//from a script element and not current page's HTML
if (url.match(/^#/)) {
url = url.substr(1);
}
// If we have an inline template, derive the suffix from the `text/???` part.
// This only supports `<script>` tags.
if (el = document.getElementById(url)) {
suffix = '.' + el.type.match(/\/(x\-)?(.+)/)[2];
}
// If there is no suffix, add one.
if (!suffix && !$view.cached[url]) {
url += suffix = $view.ext;
}
// if the suffix was derived from the .match() operation, pluck out the first value
if (Array.isArray(suffix)) {
suffix = suffix[0];
}
// Convert to a unique and valid id.
id = $view.toId(url);
// If an absolute path, use `steal`/`require` to get it.
// You should only be using `//` if you are using an AMD loader like `steal` or `require` (not almond).
if (url.match(/^\/\//)) {
url = url.substr(2);
url = !window.steal ?
url :
steal.config()
.root.mapJoin("" + steal.id(url));
}
// Localize for `require` (not almond)
if (window.require) {
if (require.toUrl) {
url = require.toUrl(url);
}
}
// Set the template engine type.
type = $view.types[suffix];
// If it is cached,
if ($view.cached[id]) {
// Return the cached deferred renderer.
return $view.cached[id];
// Otherwise if we are getting this from a `<script>` element.
} else if (el) {
// Resolve immediately with the element's `innerHTML`.
return $view.registerView(id, el.innerHTML, type);
} else {
// Make an ajax request for text.
var d = new Deferred();
ajax({
async: async,
url: url,
dataType: 'text',
error: function (jqXHR) {
checkText('', url);
d.reject(jqXHR);
},
success: function (text) {
// Make sure we got some text back.
checkText(text, url);
$view.registerView(id, text, type, d);
}
});
return d;
}
};
// ##### getDeferreds
// Gets an `array` of deferreds from an `object`.
// This only goes one level deep.
/**
* @hide
* @param {Object|can.Deferred} data
* @return {Array} deferred objects
*/
var getDeferreds = function (data) {
var deferreds = [];
// pull out deferreds
if (isDeferred(data)) {
return [data];
} else {
for (var prop in data) {
if (isDeferred(data[prop])) {
deferreds.push(data[prop]);
}
}
}
return deferreds;
};
// ##### usefulPart
// Gets the useful part of a resolved deferred.
// When a jQuery.when is resolved, it returns an array to each argument.
// Reference ($.when)[https://api.jquery.com/jQuery.when/]
// This is for `model`s and `can.ajax` that resolve to an `array`.
/**
* @hide
* @function usefulPart
* @param {Array|*} resolved
* @return {*}
*/
var usefulPart = function (resolved) {
return Array.isArray(resolved) && resolved[1] === 'success' ? resolved[0] : resolved;
};
// #### can.view

@@ -29,3 +204,3 @@ //defines $view for internal use, can.template for backwards compatibility

*/
var $view = function (view, data, helpers, callback) {
$view = function (view, data, helpers, callback) {
// If helpers is a `function`, it is actually a callback.

@@ -41,2 +216,5 @@ if (isFunction(helpers)) {

if (can.view) {
Object.assign($view, can.view);
}
// can.view methods

@@ -74,3 +252,3 @@ // --------------------------

// ##### toStr
// convert argument to a string
// convert argument to a string
toStr: function(txt){

@@ -157,4 +335,422 @@ return txt == null ? "" : ""+txt;

// cache view templates resolved via XHR on the client
/**
* @property {Boolean} can.view.cache cache
* @parent can.view.static
* By default, views are cached on the client. If you'd like the
* the views to reload from the server, you can set the `cache` attribute to `false`.
*
* //- Forces loads from server
* can.view.cache = false;
*
*/
cache: true,
// ##### register
// given an info object, register a template type
// different templating solutions produce strings or document fragments via their renderer function
/**
* @function can.view.register register
* @parent can.view.static
* @description Register a templating language.
* @signature `can.view.register(info)`
* @param {{}} info Information about the templating language.
* @option {String} plugin The location of the templating language's plugin.
* @option {String} suffix Files with this suffix will use this templating language's plugin by default.
* @option {function} renderer A function that returns a function that, given data, will render the template with that data.
* The __renderer__ function receives the id of the template and the text of the template.
* @option {function} script A function that returns the string form of the processed template.
*
* @body
* Registers a template engine to be used with
* view helpers and compression.
*
* ## Example
*
* ```
* can.View.register({
* suffix : "tmpl",
* plugin : "jquery/view/tmpl",
* renderer: function( id, text ) {
* return function(data){
* return jQuery.render( text, data );
* }
* },
* script: function( id, text ) {
* var tmpl = can.tmpl(text).toString();
* return "function(data){return ("+
* tmpl+
* ").call(jQuery, jQuery, data); }";
* }
* })
* ```
*/
register: function (info) {
this.types['.' + info.suffix] = info;
// _removed if not used as a steal module_
//!steal-remove-start
if ( typeof window !== "undefined" && window.steal && steal.type ) {
steal.type(info.suffix + " view js", function (options, success) {
var type = $view.types["." + options.type],
id = $view.toId(options.id + '');
options.text = type.script(id, options.text);
success();
});
}
//!steal-remove-end
can[info.suffix] = $view[info.suffix] = function (id, text) {
var renderer,
renderFunc;
// If there is no text, assume id is the template text, so return a nameless renderer.
if (!text) {
renderFunc = function(){
if(!renderer){
// if the template has a fragRenderer already, just return that.
if(info.fragRenderer) {
renderer = info.fragRenderer(null, id);
} else {
renderer = makeRenderer(info.renderer(null, id));
}
}
return renderer.apply(this, arguments);
};
renderFunc.render = function() {
var textRenderer = info.renderer(null, id);
return textRenderer.apply(textRenderer, arguments);
};
return renderFunc;
}
var registeredRenderer = function(){
if(!renderer){
if(info.fragRenderer) {
renderer = info.fragRenderer(id, text);
} else {
renderer = info.renderer(id, text);
}
}
return renderer.apply(this, arguments);
};
if(info.fragRenderer) {
return $view.preload( id, registeredRenderer );
} else {
return $view.preloadStringRenderer(id, registeredRenderer);
}
};
},
//registered view types
types: {},
/**
* @property {String} can.view.ext ext
* @parent can.view.static
* The default suffix to use if none is provided in the view's url.
* This is set to `.ejs` by default.
*
* // Changes view ext to 'txt'
* can.view.ext = 'txt';
*
*/
ext: ".ejs",
/**
* Returns the text from a script tag
* @hide
* @param {Object} type
* @param {Object} id
* @param {Object} src
*/
registerScript: function (type, id, src) {
return 'can.view.preloadStringRenderer(\'' + id + '\',' + $view.types['.' + type].script(id, src) + ');';
},
/**
* @hide
* Called by a production script to pre-load a fragment renderer function
* into the view cache.
* @param {String} id
* @param {Function} renderer
*/
preload: function (id, renderer) {
var def = $view.cached[id] = Deferred()
.resolve(function (data, helpers) {
return renderer.call(data, data, helpers);
});
// set cache references (otherwise preloaded recursive views won't recurse properly)
def.__view_id = id;
$view.cachedRenderers[id] = renderer;
return renderer;
},
/**
* @hide
* Called by a production script to pre-load a string renderer function
* into the view cache.
* @param id
* @param stringRenderer
* @return {*}
*/
preloadStringRenderer: function(id, stringRenderer) {
return this.preload(id, makeRenderer(stringRenderer) );
},
// #### renderers
// ---------------
// can.view's primary purpose is to load templates (from strings or filesystem) and render them
//
// can.view supports two different forms of rendering systems
//
// mustache templates return a string based rendering function
// stache (or other fragment based templating systems) return a document fragment, so 'hookup' steps are not required
//
// ##### render
//
/**
* @function can.view.render render
* @parent can.view.static
* @description Render a template.
* @signature `can.view.render(template[, callback])`
* @param {String|Object} view The path of the view template or a view object.
* @param {Function} [callback] A function executed after the template has been processed.
* @return {Function|can.Deferred} A renderer function to be called with data and helpers
* or a Deferred that resolves to a renderer function.
*
* @signature `can.view.render(template, data[, [helpers,] callback])`
* @param {String|Object} view The path of the view template or a view object.
* @param {Object} [data] The data to populate the template with.
* @param {Object.<String, function>} [helpers] Helper methods referenced in the template.
* @param {Function} [callback] A function executed after the template has been processed.
* @param {NodeList} nodelist parent nodelist to register partial template contents with
* @return {String|can.Deferred} The template with interpolated data in string form
* or a Deferred that resolves to the template with interpolated data.
*
* @body
* `can.view.render(view, [data], [helpers], callback)` returns the rendered markup produced by the corresponding template
* engine as String. If you pass a deferred object in as data, render returns
* a deferred resolving to the rendered markup.
*
* `can.view.render` is commonly used for sub-templates.
*
* ## Example
*
* _welcome.ejs_ looks like:
*
* <h1>Hello <%= hello %></h1>
*
* Render it to a string like:
*
* can.view.render("welcome.ejs",{hello: "world"})
* //-> <h1>Hello world</h1>
*
* ## Use as a Subtemplate
*
* If you have a template like:
*
* <ul>
* <% list(items, function(item){ %>
* <%== can.view.render("item.ejs",item) %>
* <% }) %>
* </ul>
*
* ## Using renderer functions
*
* If you only pass the view path, `can.view will return a renderer function that can be called with
* the data to render:
*
* var renderer = can.view.render("welcome.ejs");
* // Do some more things
* renderer({hello: "world"}) // -> Document Fragment
*
*/
//call `renderAs` with a hardcoded string, as view.render
// always operates against resolved template files or hardcoded strings
render: function (view, data, helpers, callback, nodelist) {
return $view.renderAs("string",view, data, helpers, callback, nodelist);
},
// ##### renderTo
//
/**
* @hide
* @function renderTo
* @param {String} format
* @param {Function} renderer
* @param data
* @param {Object} helpers helper methods for this template
* @param {NodeList} nodelist parent nodelist to register partial template contents with
* @return {*}
*/
renderTo: function(format, renderer, data, helpers, nodelist){
if (format === "string") {
if (renderer.renderAsString) {
renderer = renderer.renderAsString;
} else if (renderer.render) {
renderer = renderer.render;
}
}
return renderer(data, helpers, nodelist);
},
/**
* @hide
*
* @param format
* @param view
* @param data
* @param helpers
* @param callback
* @param nodelist
* @return {*}
*/
renderAs: function (format, view, data, helpers, callback, nodelist) {
// if callback has expression prop its actually the nodelist
if (callback !== undefined && typeof callback.expression === 'string') {
nodelist = callback;
callback = undefined;
}
// If helpers is a `function`, it is actually a callback.
if (isFunction(helpers)) {
callback = helpers;
helpers = undefined;
}
// give templates the can namespace:
helpers = Object.assign({ can: can }, helpers);
// See if we got passed any deferreds.
var deferreds = getDeferreds(data);
var deferred, dataCopy, async, response;
if (deferreds.length) {
// Does data contain any deferreds?
// The deferred that resolves into the rendered content...
deferred = new Deferred();
dataCopy = Object.assign({}, data);
// Add the view request to the list of deferreds.
deferreds.push(getRenderer(view, true));
// Wait for the view and all deferreds to finish...
Deferred.when.apply(can, deferreds)
.then(function (resolved) {
// Get all the resolved deferreds.
var objs = makeArray(arguments),
// Renderer is the last index of the data.
renderer = objs.pop(),
// The result of the template rendering with data.
result;
// Make data look like the resolved deferreds.
if (isDeferred(data)) {
dataCopy = usefulPart(resolved);
} else {
// Go through each prop in data again and
// replace the defferreds with what they resolved to.
for (var prop in data) {
if (isDeferred(data[prop])) {
dataCopy[prop] = usefulPart(objs.shift());
}
}
}
// Get the rendered result.
result = can.view.renderTo(format, renderer, dataCopy, helpers, nodelist);
// Resolve with the rendered view.
deferred.resolve(result, dataCopy);
// If there's a `callback`, call it back with the result.
if (callback) {
callback(result, dataCopy);
}
}, function () {
deferred.reject.apply(deferred, arguments);
});
// Return the deferred...
return deferred;
} else {
// If there's a `callback` function
async = isFunction(callback);
// get is called async but in
// ff will be async so we need to temporarily reset
deferred = Observation.ignore(getRenderer)(view, async);
// If we are `async`...
if (async) {
// Return the deferred
response = deferred;
// And fire callback with the rendered result.
deferred.then(function (renderer) {
callback(data ? $view.renderTo(format, renderer, data, helpers, nodelist) : renderer);
});
} else {
// if the deferred is resolved, call the cached renderer instead
// this is because it's possible, with recursive deferreds to
// need to render a view while its deferred is _resolving_. A _resolving_ deferred
// is a deferred that was just resolved and is calling back it's success callbacks.
// If a new success handler is called while resoliving, it does not get fired by
// jQuery's deferred system. So instead of adding a new callback
// we use the cached renderer.
// We also add __view_id on the deferred so we can look up it's cached renderer.
// In the future, we might simply store either a deferred or the cached result.
if (deferred.state() === 'resolved' && deferred.__view_id) {
var currentRenderer = $view.cachedRenderers[deferred.__view_id];
var result = data ? $view.renderTo(format, currentRenderer, data, helpers, nodelist) : currentRenderer;
return result;
} else {
// Otherwise, the deferred is complete, so
// set response to the result of the rendering.
deferred.then(function (renderer) {
response = data ? $view.renderTo(format, renderer, data, helpers, nodelist) : renderer;
});
}
}
return response;
}
},
/**
* @hide
* Registers a view with `cached` object. This is used
* internally by this class and Mustache to hookup views.
* @param {String} id
* @param {String} text
* @param {String} type
* @param {can.Deferred} def
*/
registerView: function (id, text, type, def) {
// Get the renderer function.
var info = (typeof type === "object" ? type : $view.types[type || $view.ext]),
renderer;
if(info.fragRenderer) {
renderer = info.fragRenderer(id, text);
} else {
renderer = makeRenderer( info.renderer(id, text) );
}
def = def || new Deferred();
// Cache if we are caching.
if ($view.cache) {
$view.cached[id] = def;
def.__view_id = id;
$view.cachedRenderers[id] = renderer;
}
// Return the objects for the response's `dataTypes`
// (in this case view).
return def.resolve(renderer);
},
// Returns a function that automatically converts all computes passed to it

@@ -178,3 +774,3 @@ simpleHelper: function(fn) {

module.exports = can.view = $view;
module.exports = $view;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc