Adds npm for managing client-side dependencies

- Includes a package.json file with build and CI scripts
- Includes shrinkwrap file for locking dependency version
- Includes Gulp for running build tasks
- Includes a 'build' task for copying library files from node_modules to thirdparty
- Includes a 'sanity' task for makes sure library files in thirdparty match what's in node_modules
- Includes updates to .travis.yml (new JS_SANITY_CHECK flag) to run the sanity task
This commit is contained in:
David Craig 2016-01-06 16:06:47 +13:00
parent 066dff4123
commit 254b942737
17 changed files with 241 additions and 652 deletions

5
.gitignore vendored
View File

@ -1,10 +1,9 @@
.sass-cache
.DS_Store
npm-debug.log
/.buildpath
/.project
/.settings
css/GridField_print.css
admin/thirdparty/chosen/node_modules
node_modules/

View File

@ -9,6 +9,7 @@ addons:
env:
global:
- TRAVIS_NODE_VERSION="4.2.0"
- CORE_RELEASE=master
- "ARTIFACTS_AWS_REGION=us-east-1"
- "ARTIFACTS_S3_BUCKET=silverstripe-travis-artifacts"
@ -26,7 +27,7 @@ matrix:
- php: 5.6
env: DB=MYSQL PDO=1
- php: 5.6
env: DB=MYSQL BEHAT_TEST=1
env: DB=MYSQL BEHAT_TEST=1 JS_SANITY_CHECK=1
before_script:
# Until http://pecl.php.net/package/imagick is working again
@ -36,6 +37,7 @@ before_script:
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
- "if [ \"$BEHAT_TEST\" = \"\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss; fi"
- "if [ \"$BEHAT_TEST\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/behat-extension; fi"
- "if [ \"JS_SANITY_CHECK\" = \"1\" ]; then nvm install $TRAVIS_NODE_VERSION && npm install; fi"
- cd ~/builds/ss
- php ~/travis-support/travis_setup_selenium.php --if-env BEHAT_TEST
- php ~/travis-support/travis_setup_php54_webserver.php --if-env BEHAT_TEST
@ -44,6 +46,7 @@ script:
- "if [ \"$BEHAT_TEST\" = \"\" ]; then vendor/bin/phpunit framework/tests; fi"
- "if [ \"$BEHAT_TEST\" = \"\" ]; then vendor/bin/phpunit framework/admin/tests; fi"
- "if [ \"$BEHAT_TEST\" = \"1\" ]; then vendor/bin/behat @framework; fi"
- "if [ \"JS_SANITY_CHECK\" = \"1\" ]; then npm run sanity; fi"
after_failure:
- php ~/travis-support/travis_upload_artifacts.php --if-env BEHAT_TEST,ARTIFACTS_AWS_SECRET_ACCESS_KEY --target-path $TRAVIS_REPO_SLUG/$TRAVIS_BUILD_ID/$TRAVIS_JOB_ID --artifacts-base-url https://s3.amazonaws.com/$ARTIFACTS_S3_BUCKET/

11
admin/thirdparty/jsizes/lib/jquery.sizes.js vendored Normal file → Executable file
View File

@ -7,6 +7,7 @@
*/
/*global jQuery*/
(function ($) {
'use strict';
var num = function (value) {
return parseInt(value, 10) || 0;
};
@ -25,9 +26,7 @@
if (value.height !== undefined) {
this.css(name + '-height', value.height);
}
return this;
}
else {
} else {
width = this.css(name + '-width');
height = this.css(name + '-height');
// Apparently:
@ -36,6 +35,7 @@
return {'width': (name === 'max' && (width === undefined || width === 'none' || num(width) === -1) && Number.MAX_VALUE) || num(width),
'height': (name === 'max' && (height === undefined || height === 'none' || num(height) === -1) && Number.MAX_VALUE) || num(height)};
}
return this;
};
});
@ -64,14 +64,13 @@
if (value.right !== undefined) {
this.css(name + '-right' + (name === 'border' ? '-width' : ''), value.right);
}
return this;
}
else {
} else {
return {top: num(this.css(name + '-top' + (name === 'border' ? '-width' : ''))),
bottom: num(this.css(name + '-bottom' + (name === 'border' ? '-width' : ''))),
left: num(this.css(name + '-left' + (name === 'border' ? '-width' : ''))),
right: num(this.css(name + '-right' + (name === 'border' ? '-width' : '')))};
}
return this;
};
});
}(jQuery));

View File

@ -262,6 +262,38 @@ Helpful hint: You can always edit your last commit message by using:
$ git commit --amend
## Working with client-side dependencies
From time to time client-side dependencies like jQuery need to be upgraded, added, or removed. We have some tools for dealing with that. Note this only applies to core SilverStripe dependencies, you're free to to manage dependencies in your project codebase however you like.
### Node.js
The [Node.js](https://nodejs.org) JavaScript runtime is the foundation of our client-side build tool chain. If you want to do things like upgrade, add, or remove libraries, you'll need Node installed on your dev environment. Our build tooling supports the v4.2.x (LTS) version of Node.
### npm
[npm](https://www.npmjs.com/) is the package manager we use for JavaScript libraries. It comes bundled with Node.js so should already have it installed if you have Node.
The configuration for an npm package goes in `package.json`. You'll see one in the root directory of `framework`. As well as being used for defining dependencies and basic package information, the `package.json` file has some handy scripts.
```
$ npm run build
```
This script copies JavaScript files from the `node_modules` directory into the `thirdparty` directory. The `node_modules` directory is not part of source control, so you'll need to run this command if you have upgraded, or added a module.
```
$ npm run sanity
```
This script makes sure files in `thirdparty` match files copied from `node_modules`. You should never commit custom changes to a library file. This script will catch them if you do :smile:
Of course to run these scripts, you'll need to get the dependencies, so run a `npm install` from the root directory to get started.
### Gulp
[Gulp](http://gulpjs.com/) is the build system which gets invoked when you run npm scripts in SilverStripe. All npm scripts have a corresponding Gulp task which you can find in `gulpfile.js`.
## Some gotchas
Be careful not to commit any of your configuration files, logs, or throwaway test files to your GitHub repo. These files can contain information you wouldn't want publicly viewable and they will make it impossible to merge your contributions into the main development trunk.

100
gulpfile.js Normal file
View File

@ -0,0 +1,100 @@
var gulp = require('gulp'),
diff = require('gulp-diff'),
path = require('path'),
semver = require('semver'),
packageJson = require('./package.json');
var paths = {
modules: './node_modules/',
frameworkThirdparty: './thirdparty/',
adminThirdparty: './admin/thirdparty/'
};
var blueimpFileUploadConfig = {
src: paths.modules + 'blueimp-file-upload/',
dest: paths.frameworkThirdparty + 'jquery-fileupload/',
files: [
'cors/jquery.postmessage-transport.js',
'cors/jquery.xdr-transport.js',
'jquery.fileupload-ui.js',
'jquery.fileupload.js',
'jquery.iframe-transport.js'
]
};
var blueimpLoadImageConfig = {
src: paths.modules + 'blueimp-load-image/',
dest: paths.frameworkThirdparty + 'javascript-loadimage/',
files: ['load-image.js']
};
var blueimpTmplConfig = {
src: paths.modules + 'blueimp-tmpl/',
dest: paths.frameworkThirdparty + 'javascript-templates/',
files: ['tmpl.js']
};
var jquerySizesConfig = {
src: paths.modules + 'jquery-sizes/',
dest: paths.adminThirdparty + 'jsizes/',
files: ['lib/jquery.sizes.js']
};
/**
* Copies files from a source directory to a destination directory.
*
* @param object libConfig
* @param string libConfig.src - The source directory
* @param string libConfig.dest - The destination directory
* @param array libConfig.files - The list of files to copy from the source to the destination directory
*/
function copyFiles(libConfig) {
libConfig.files.forEach(function (file) {
var dir = path.parse(file).dir;
gulp.src(libConfig.src + file)
.pipe(gulp.dest(libConfig.dest + dir));
});
}
/**
* Diffs files in a source directory against a destination directory.
*
* @param object libConfig
* @param string libConfig.src - The source directory
* @param string libConfig.dest - The destination directory
* @param array libConfig.files - The list of files to copy from the source to the destination directory
*/
function diffFiles(libConfig) {
libConfig.files.forEach(function (file) {
var dir = path.parse(file).dir;
gulp.src(libConfig.src + file)
.pipe(diff(libConfig.dest + dir))
.pipe(diff.reporter({ fail: true, quiet: true }))
.on('error', function (error) {
console.error(new Error('Sanity check failed. \'' + libConfig.dest + file + '\' has been modified.'));
process.exit(1);
});
});
}
// Make sure the version of Node being used is valid.
if (!semver.satisfies(process.versions.node, packageJson.engines.node)) {
console.error('Invalid Node.js version. You need to be using ' + packageJson.engines.node + '. If you want to manage multiple Node.js versions try https://github.com/creationix/nvm');
process.exit(1);
}
gulp.task('build', function () {
copyFiles(blueimpFileUploadConfig);
copyFiles(blueimpLoadImageConfig);
copyFiles(blueimpTmplConfig);
copyFiles(jquerySizesConfig);
});
gulp.task('sanity', function () {
diffFiles(blueimpFileUploadConfig);
diffFiles(blueimpLoadImageConfig);
diffFiles(blueimpTmplConfig);
diffFiles(jquerySizesConfig);
});

55
npm-shrinkwrap.json generated Normal file
View File

@ -0,0 +1,55 @@
{
"name": "silverstripe-framework",
"version": "4.0.0",
"dependencies": {
"blueimp-file-upload": {
"version": "6.0.3",
"from": "blueimp-file-upload@6.0.3",
"resolved": "https://registry.npmjs.org/blueimp-file-upload/-/blueimp-file-upload-6.0.3.tgz",
"dependencies": {
"jquery": {
"version": "2.1.4",
"from": "jquery@>=1.6.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.1.4.tgz"
},
"jquery.ui.widget": {
"version": "1.10.3",
"from": "jquery.ui.widget@>=1.8.0",
"resolved": "https://registry.npmjs.org/jquery.ui.widget/-/jquery.ui.widget-1.10.3.tgz"
},
"blueimp-load-image": {
"version": "2.1.0",
"from": "blueimp-load-image@>=1.1.3",
"resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-2.1.0.tgz"
},
"blueimp-tmpl": {
"version": "3.1.0",
"from": "blueimp-tmpl@>=1.0.2",
"resolved": "https://registry.npmjs.org/blueimp-tmpl/-/blueimp-tmpl-3.1.0.tgz"
}
}
},
"blueimp-load-image": {
"version": "1.1.3",
"from": "blueimp-load-image@1.1.3",
"resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-1.1.3.tgz"
},
"blueimp-tmpl": {
"version": "1.0.2",
"from": "blueimp-tmpl@1.0.2",
"resolved": "https://registry.npmjs.org/blueimp-tmpl/-/blueimp-tmpl-1.0.2.tgz"
},
"jquery-sizes": {
"version": "0.33.0",
"from": "jquery-sizes@0.33.0",
"resolved": "https://registry.npmjs.org/jquery-sizes/-/jquery-sizes-0.33.0.tgz",
"dependencies": {
"jquery": {
"version": "2.1.4",
"from": "jquery@latest",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.1.4.tgz"
}
}
}
}
}

41
package.json Normal file
View File

@ -0,0 +1,41 @@
{
"name": "silverstripe-framework",
"version": "4.0.0",
"description": "The SilverStripe framework",
"directories": {
"doc": "docs",
"test": "tests"
},
"engines": {
"node": "~4.2.0"
},
"scripts": {
"build": "gulp build",
"sanity": "gulp sanity"
},
"repository": {
"type": "git",
"url": "git://github.com/silverstripe/silverstripe-framework.git"
},
"keywords": [
"silverstripe",
"framework"
],
"author": "SilverStripe Ltd",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/silverstripe/silverstripe-framework/issues"
},
"homepage": "https://github.com/silverstripe/silverstripe-framework#readme",
"devDependencies": {
"gulp": "^3.9.0",
"gulp-diff": "^1.0.0",
"semver": "^5.1.0"
},
"dependencies": {
"blueimp-file-upload": "^6.0.3",
"blueimp-load-image": "^1.1.3",
"blueimp-tmpl": "^1.0.2",
"jquery-sizes": "^0.33.0"
}
}

View File

@ -1,112 +0,0 @@
# JavaScript Load Image
## Demo
[JavaScript Load Image Demo](http://blueimp.github.com/JavaScript-Load-Image/)
## Usage
Include the (minified) JavaScript Load Image script in your HTML markup:
```html
<script src="load-image.min.js"></script>
```
In your application code, use the **loadImage()** function like this:
```js
document.getElementById('file-input').onchange = function (e) {
window.loadImage(
e.target.files[0],
function (img) {
document.body.appendChild(img);
},
{maxWidth: 600}
);
};
```
## Requirements
The JavaScript Load Image function has zero dependencies.
## API
The **loadImage()** function accepts a [File](https://developer.mozilla.org/en/DOM/File) or [Blob](https://developer.mozilla.org/en/DOM/Blob) object or a simple image URL (e.g. "http://example.org/image.png") as first argument.
If a [File](https://developer.mozilla.org/en/DOM/File) or [Blob](https://developer.mozilla.org/en/DOM/Blob) is passed as parameter, it returns a HTML **img** element if the browser supports the [URL](https://developer.mozilla.org/en/DOM/window.URL) API or a [FileReader](https://developer.mozilla.org/en/DOM/FileReader) object if supported, or **false**.
It always returns a HTML **img** element when passing an image URL:
```js
document.getElementById('file-input').onchange = function (e) {
var loadingImage = window.loadImage(
e.target.files[0],
function (img) {
document.body.appendChild(img);
},
{maxWidth: 600}
);
if (!loadingImage) {
// Alternative code ...
}
};
```
The **img** element or [FileReader](https://developer.mozilla.org/en/DOM/FileReader) object returned by the **loadImage()** function allows to abort the loading process by setting the **onload** and **onerror** event handlers to null:
```js
document.getElementById('file-input').onchange = function (e) {
var loadingImage = window.loadImage(
e.target.files[0],
function (img) {
document.body.appendChild(img);
},
{maxWidth: 600}
);
loadingImage.onload = loadingImage.onerror = null;
};
```
The second argument must be a **callback** function, which is called when the image has been loaded or an error occurred while loading the image. The callback function is passed one argument, which is either a HTML **img** element, a [canvas](https://developer.mozilla.org/en/HTML/Canvas) element, or an [Event](https://developer.mozilla.org/en/DOM/event) object of type "**error**":
```js
var imageUrl = "http://example.org/image.png";
window.loadImage(
imageUrl,
function (img) {
if(img.type === "error") {
console.log("Error loading image " + imageUrl);
} else {
document.body.appendChild(img);
}
},
{maxWidth: 600}
);
```
The optional third argument is a map of options:
* **maxWidth**: Defines the maximum width of the img/canvas element.
* **maxHeight**: Defines the maximum height of the img/canvas element.
* **minWidth**: Defines the minimum width of the img/canvas element.
* **minHeight**: Defines the minimum height of the img/canvas element.
* **canvas**: Defines if the returned element should be a [canvas](https://developer.mozilla.org/en/HTML/Canvas) element.
They can be used the following way:
```js
window.loadImage(
fileOrBlobOrUrl,
function (img) {
document.body.appendChild(img);
},
{
maxWidth: 600,
maxHeight: 300,
minWidth: 100,
minHeight: 50,
canvas: true
}
);
```
All options are optional. By default, the image is returned as HTML **img** element without any image size restrictions.
## License
The JavaScript Load Image script is released under the [MIT license](http://www.opensource.org/licenses/MIT).

View File

@ -1,3 +0,0 @@
(function(h){var e=function(a,c,d){var b=document.createElement("img"),g,f;window.Blob&&a instanceof Blob?(g=e.createObjectURL(a),f=!0):g=a;b.onerror=c;b.onload=function(){f&&e.revokeObjectURL(g);c(e.scale(b,d))};return g?(b.src=g,b):e.readFile(a,function(a){b.src=a})},f=window.createObjectURL&&window||window.URL&&URL||window.webkitURL&&webkitURL;e.scale=function(a,c){var c=c||{},d=document.createElement("canvas"),b=Math.max((c.minWidth||a.width)/a.width,(c.minHeight||a.height)/a.height);if(1<b)a.width=
parseInt(a.width*b,10),a.height=parseInt(a.height*b,10);b=Math.min((c.maxWidth||a.width)/a.width,(c.maxHeight||a.height)/a.height);if(1>b)a.width=parseInt(a.width*b,10),a.height=parseInt(a.height*b,10);if(!c.canvas||!d.getContext)return a;d.width=a.width;d.height=a.height;d.getContext("2d").drawImage(a,0,0,a.width,a.height);return d};e.createObjectURL=function(a){return f?f.createObjectURL(a):!1};e.revokeObjectURL=function(a){return f?f.revokeObjectURL(a):!1};e.readFile=function(a,c){if(window.FileReader&&
FileReader.prototype.readAsDataURL){var d=new FileReader;d.onload=function(a){c(a.target.result)};d.readAsDataURL(a);return d}return!1};"undefined"!==typeof define&&define.amd?define("loadImage",function(){return e}):h.loadImage=e})(this);

View File

@ -1,45 +0,0 @@
{
"name": "blueimp-load-image",
"version": "1.1.3",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a function to load images provided as File or Blob objects or via URL. It returns an optionally scaled HTML img or canvas element.",
"keywords": [
"javascript",
"load",
"loading",
"image",
"file",
"blob",
"url",
"scale",
"scaling",
"img",
"canvas"
],
"homepage": "https://github.com/blueimp/JavaScript-Load-Image",
"author": {
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
],
"repository": {
"type": "git",
"url": "git://github.com/blueimp/JavaScript-Load-Image.git"
},
"bugs": "https://github.com/blueimp/JavaScript-Load-Image/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"files": [
"load-image.js"
],
"main": "load-image.js"
}

View File

@ -1,309 +0,0 @@
# JavaScript Templates
## Demo
[JavaScript Templates Demo](http://blueimp.github.com/JavaScript-Templates/)
## Usage
### Client-side
Include the (minified) JavaScript Templates script in your HTML markup:
```html
<script src="tmpl.min.js"></script>
```
Add a script section with type **"text/html"** and your template definition as content:
```html
<script type="text/html" id="tmpl-demo">
<h3>{%=o.title%}</h3>
<p>Released under the
<a href="{%=o.license.url%}">{%=o.license.name%}</a>.</p>
<h4>Features</h4>
<ul>
{% for (var i=0; i<o.features.length; i++) { %}
<li>{%=o.features[i]%}</li>
{% } %}
</ul>
</script>
```
**"o"** (the lowercase letter) is a reference to the data parameter of the template function (see the API section on how to modify this identifier).
In your application code, create a JavaScript object to use as data for the template:
```js
var data = {
"title": "JavaScript Templates",
"license": {
"name": "MIT license",
"url": "http://www.opensource.org/licenses/MIT"
},
"features": [
"lightweight & fast",
"powerful",
"zero dependencies"
]
};
```
In a real application, this data could be the result of retrieving a [JSON](http://json.org/) resource.
Render the result by calling the **tmpl()** method with the id of the template and the data object as arguments:
```js
document.getElementById("result").innerHTML = tmpl("tmpl-demo", data);
```
### Server-side
The following is an example how to use the JavaScript Templates engine on the server-side with [node.js](http://nodejs.org/).
Create a new directory and add the **tmpl.js** file. Or alternatively, install the **blueimp-tmpl** package with [npm](http://npmjs.org/):
```sh
npm install blueimp-tmpl
```
Add a file **template.html** with the following content:
```html
<!DOCTYPE HTML>
<title>{%=o.title%}</title>
<h3><a href="{%=o.url%}">{%=o.title%}</a></h3>
<h4>Features</h4>
<ul>
{% for (var i=0; i<o.features.length; i++) { %}
<li>{%=o.features[i]%}</li>
{% } %}
</ul>
```
Add a file **server.js** with the following content:
```js
require("http").createServer(function (req, res) {
var fs = require("fs"),
// The tmpl module exports the tmpl() function:
tmpl = require("./tmpl").tmpl,
// Use the following version if you installed the package with npm:
// tmpl = require("blueimp-tmpl").tmpl,
// Sample data:
data = {
"title": "JavaScript Templates",
"url": "https://github.com/blueimp/JavaScript-Templates",
"features": [
"lightweight & fast",
"powerful",
"zero dependencies"
]
};
// Override the template loading method:
tmpl.load = function (id) {
var filename = id + ".html";
console.log("Loading " + filename);
return fs.readFileSync(filename, "utf8");
};
res.writeHead(200, {"Content-Type": "text/html"});
// Render the content:
res.end(tmpl("template", data));
}).listen(8080, "localhost");
console.log("Server running at http://localhost:8080/");
```
Run the application with the following command:
```sh
node server.js
```
## Requirements
The JavaScript Templates script has zero dependencies.
## API
### tmpl() function
The **tmpl()** function is added to the global **window** object and can be called as global function:
```js
var result = tmpl("tmpl-demo", data);
```
The **tmpl()** function can be called with the id of a template, or with a template string:
```js
var result = tmpl("<h3>{%=o.title%}</h3>", data);
```
If called without second argument, **tmpl()** returns a reusable template function:
```js
var func = tmpl("<h3>{%=o.title%}</h3>");
document.getElementById("result").innerHTML = func(data);
```
### Templates cache
Templates loaded by id are cached in the map **tmpl.cache**, which can be modified:
```js
var func = tmpl("tmpl-demo");
var cached = typeof tmpl.cache["tmpl-demo"] === "function"; // true
tmpl.cache["tmpl-demo"] = tmpl("<h3>{%=o.title%}</h3>");
var result = tmpl("tmpl-demo", {title: "JS"}); // Renders "<h3>JS</h3>"
```
### Output encoding
The method **tmpl.encode** is used to escape HTML special characters in template output:
```js
var output = tmpl.encode("<>&\"\x00"); // Renders "&lt;&gt;&amp;&quot;"
```
**tmpl.encode** makes use of the regular expression **tmpl.encReg** and the encoding map **tmpl.encMap** to match and replace special characters, which can be modified to change the behavior of the output encoding:
```js
// Add single quotes to the encoding rules:
tmpl.encReg = /[<>&"'\x00]/g;
tmpl.encMap["'"] = "&#39;";
var output = tmpl.encode("<>&\"'\x00"); // Renders "&lt;&gt;&amp;&quot;&#39;"
```
### Local helper variables
The local variables available inside the templates are the following:
* **o**: The data object given as parameter to the template function (see the next section on how to modify the parameter name).
* **_s**: The string for the rendered result content.
* **_t**: A reference to the **tmpl** function object.
* **_e**: A reference to the **tmpl.encode** method.
* **print**: Function to add content to the rendered result string.
* **include**: Function to include the return value of a different template in the result.
To introduce additional local helper variables, the string **tmpl.helper** can be extended. The following adds a convenience function for *console.log* and a streaming function, that streams the template rendering result back to the callback argument (note the comma at the beginning of each variable declaration):
```js
tmpl.helper += ",log=function(){console.log.apply(console, arguments)}" +
",st='',stream=function(cb){var l=st.length;st=_s;cb( _s.slice(l));}";
```
Those new helper functions could be used to stream the template contents to the console output:
```html
<script type="text/html" id="tmpl-demo">
<h3>{%=o.title%}</h3>
{% stream(log); %}
<p>Released under the
<a href="{%=o.license.url%}">{%=o.license.name%}</a>.</p>
{% stream(log); %}
<h4>Features</h4>
<ul>
{% stream(log); %}
{% for (var i=0; i<o.features.length; i++) { %}
<li>{%=o.features[i]%}</li>
{% stream(log); %}
{% } %}
</ul>
{% stream(log); %}
</script>
```
### Template function argument
The generated template functions accept one argument, which is the data object given to the **tmpl(id, data)** function. This argument is available inside the template definitions as parameter **o** (the lowercase letter).
The argument name can be modified by overriding **tmpl.arg**:
```js
tmpl.arg = "p";
// Renders "<h3>JavaScript Templates</h3>":
var result = tmpl("<h3>{%=p.title%}</h3>", {title: "JavaScript Templates"});
```
### Template parsing
The template contents are matched and replaced using the regular expression **tmpl.regexp** and the replacement function **tmpl.func**. The replacement function operates based on the [parenthesized submatch strings](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter).
To use different tags for the template syntax, override **tmpl.regexp** with a modified regular expression, by exchanging all occurrences of "**\\{%**" and "**%\\}**", e.g. with "**\\[%**" and "**%\\]**":
```js
tmpl.regexp = /(\s+)|('|\\)(?![^%]*%\])|(?:\[%(=|#)(.+?)%\])|(\[%)|(%\])/g;
```
## Templates syntax
### Interpolation
Print variable with HTML special characters escaped:
```html
<h3>{%=o.title%}</h3>
```
Print variable without escaping:
```html
<h3>{%#o.user_id%}</h3>
```
Print output of function calls:
```html
<a href="{%=encodeURI(o.url)%}">Website</a>
```
Use dot notation to print nested properties:
```html
<strong>{%=o.author.name%}</strong>
```
Note that the JavaScript Templates engine prints **falsy** values as empty strings.
That is, **undefined**, **null**, **false**, **0** and **NaN** will all be converted to **''**.
To be able to print e.g. the number 0, convert it to a String before using it as an output variable:
```html
<h3>{%=0+''%}</h3>
```
### Evaluation
Use **print(str)** to add escaped content to the output:
```html
<span>Year: {% var d=new Date(); print(d.getFullYear()); %}</span>
```
Use **print(str, true)** to add unescaped content to the output:
```html
<span>{% print("Fast &amp; powerful", true); %}</span>
```
Use **include(str, obj)** to include content from a different template:
```html
<div>
{% include('tmpl-link', {name: "Website", url: "http://example.org"}); %}
</div>
```
If else condition:
```html
{% if (o.author.url) { %}
<a href="{%=encodeURI(o.author.url)%}">{%=o.author.name%}</a>
{% } else { %}
<em>No author url.</em>
{% } %}
```
For loop:
```html
<ul>
{% for (var i=0; i<o.features.length; i++) { %}
<li>{%=o.features[i]%}</li>
{% } %}
</ul>
```
## License
The JavaScript Templates script is released under the [MIT license](http://www.opensource.org/licenses/MIT).

View File

@ -1,40 +0,0 @@
{
"name": "blueimp-tmpl",
"version": "1.0.2",
"title": "JavaScript Templates",
"description": "< 1KB lightweight, fast & powerful JavaScript templating engine with zero dependencies. Compatible with server-side environments like node.js, module loaders like RequireJS and all web browsers.",
"keywords": [
"javascript",
"templates",
"templating"
],
"homepage": "https://github.com/blueimp/JavaScript-Templates",
"author": {
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
],
"repository": {
"type": "git",
"url": "git://github.com/blueimp/JavaScript-Templates.git"
},
"bugs": "https://github.com/blueimp/JavaScript-Templates/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"scripts": {
"test": "node ./test/test.js"
},
"files": [
"tmpl.js"
],
"main": "tmpl.js"
}

View File

@ -75,8 +75,7 @@
",print=function(s,e){_s+=e&&(s||'')||_e(s);}" +
",include=function(s,d){_s+=_t(s,d);}";
if (typeof define === "function" && define.amd) {
// Register as an AMD module:
define("tmpl", function () {
define(function () {
return tmpl;
});
} else {

View File

@ -1,2 +0,0 @@
(function(e){var a=function(b,d){var c=!/[^\-\w]/.test(b)?a.cache[b]=a.cache[b]||a(a.load(b)):new Function(a.arg,("var _s=''"+a.helper+";_s+='"+b.replace(a.regexp,a.func)+"';return _s;").split("_s+='';").join(""));c.tmpl=c.tmpl||a;return d?c(d):c};a.cache={};a.load=function(a){return document.getElementById(a).innerHTML};a.regexp=/(\s+)|('|\\)(?![^%]*%\})|(?:\{%(=|#)(.+?)%\})|(\{%)|(%\})/g;a.func=function(a,d,c,f,g,e,i,h,j){if(d)return h&&h+a.length!==j.length?" ":"";if(c)return"\\"+a;if(f)return"="===
f?"'+_e("+g+")+'":"'+("+g+"||'')+'";if(e)return"';";if(i)return"_s+='"};a.encReg=/[<>&"\x00]/g;a.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","\x00":""};a.encode=function(b){return(""+(b||"")).replace(a.encReg,function(b){return a.encMap[b]})};a.arg="o";a.helper=",_t=arguments.callee.tmpl,_e=_t.encode,print=function(s,e){_s+=e&&(s||'')||_e(s);},include=function(s,d){_s+=_t(s,d);}";"function"===typeof define&&define.amd?define("tmpl",function(){return a}):e.tmpl=a})(this);

View File

@ -1,68 +0,0 @@
# jQuery File Upload Plugin
## Demo
[Demo File Upload](http://blueimp.github.com/jQuery-File-Upload/)
## Setup instructions
* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
## Features
* **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
* **Drag & Drop support:**
Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
* **Upload progress bar:**
Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
* **Cancelable uploads:**
Individual file uploads can be canceled to stop the upload progress.
* **Resumable uploads:**
Aborted uploads can be resumed with browsers supporting the Blob API.
* **Chunked uploads:**
Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
* **Preview images:**
A preview of image files can be displayed before uploading with browsers supporting the required HTML5 APIs.
* **No browser plugins (e.g. Adobe Flash) required:**
The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
* **Graceful fallback for legacy browsers:**
Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
* **HTML file upload form fallback:**
Shows a standard HTML file upload form if JavaScript is disabled.
* **Cross-site file uploads:**
Supports uploading files to a different domain with Cross-site XMLHttpRequests.
* **Multiple plugin instances:**
Allows to use multiple plugin instances on the same webpage.
* **Customizable and extensible:**
Provides an API to set individual options and define callBack methods for various upload events.
* **Multipart and file contents stream uploads:**
Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
* **Compatible with any server-side application platform:**
Works with Google App Engine (Python, Java), Ruby on Rails, PHP and any other platform that supports HTTP file uploads.
## Requirements
* [jQuery](http://jquery.com/) v. 1.6+
* [jQuery UI widget factory](http://wiki.jqueryui.com/w/page/12138135/Widget%20factory) v. 1.8.16+
* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/jquery.iframe-transport.js) (included)
* [JavaScript Load Image function](http://blueimp.github.com/JavaScript-Load-Image) v. 1.1.3+ (optional)
* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 1.0.2+ (optional)
The jQuery UI widget factory is a requirement for the basic File Upload plugin, but very lightweight without any other dependencies.
The UI version of the File Upload plugin also requires the JavaScript Templates engine and the JavaScript Load Image function (for the upload image previews). These dependencies are marked as optional, as the basic File Upload plugin can be used without them and the UI version of the plugin can be extended to override these dependencies with alternative solutions.
The repository also includes the [jQuery XDomainRequest Transport Plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/jquery.xdr-transport.js), which is required for Cross-domain AJAX requests in Microsoft Internet Explorer >= 8. It is only included for the [Demo](http://blueimp.github.com/jQuery-File-Upload/), which makes use of Cross-domain DELETE requests (GET requests for IE) to delete uploaded files from the Demo File Upload service.
[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The example implementation makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as redirect page. See also the example code in [application.js](https://github.com/blueimp/jQuery-File-Upload/blob/master/application.js) as well as the explanation of all [files in the repository](https://github.com/blueimp/jQuery-File-Upload/wiki/Plugin-files).
## Browser Support (tested versions)
* Google Chrome - 7.0+
* Apple Safari - 4.0+
* Mozilla Firefox - 3.0+
* Opera - 10.0+
* Microsoft Internet Explorer 6.0+
Drag & Drop is only supported on Google Chrome, Firefox 4.0+ and Safari 5.0+.
Microsoft Internet Explorer has no support for multiple file selection or upload progress.
[Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
## License
Released under the [MIT license](http://www.opensource.org/licenses/MIT).

View File

@ -31,7 +31,7 @@
// The maximum allowed file size:
maxFileSize: undefined,
// The minimum allowed file size:
minFileSize: 0,
minFileSize: 1,
// The regular expression for allowed file types, matches
// against either file type or file name:
acceptFileTypes: /.+$/i,

View File

@ -1,60 +0,0 @@
{
"name": "blueimp-file-upload",
"version": "6.0.3",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"keywords": [
"file",
"upload",
"widget",
"multiple",
"selection",
"drag",
"drop",
"progress",
"preview",
"cross-domain",
"cross-site",
"chunked",
"resume",
"gae",
"go",
"python",
"php"
],
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
"author": {
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
],
"repository": {
"type": "git",
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
},
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"dependencies": {
"jquery": ">=1.6",
"jquery.ui.widget": ">=1.8",
"blueimp-load-image": ">=1.1.3",
"blueimp-tmpl": ">=1.0.2"
},
"files": [
"jquery.iframe-transport.js",
"jquery.fileupload.js",
"jquery.fileupload-ui.js",
"jquery.fileupload-ui.css",
"progressbar.gif"
]
}