Permalink
Browse files

Added NPM package

  • Loading branch information...
1 parent 16099c1 commit df91e3ff9d7912d004dd7e5c01cb1da405e86450 Oliver Morgan committed Sep 9, 2011
Showing with 216 additions and 0 deletions.
  1. +12 −0 README.md
  2. +13 −0 package.json
  3. +191 −0 parrot.js
View
@@ -17,6 +17,18 @@ All feedback is welcome.
## Installation
+### NPM (Node Package Manager)
+
+The easiest way to install parrot is by using NPM as follows:
+
+ npm install parrot
+
+Or globally by:
+
+ npm install -g parrot
+
+### Alternatively
+
Open up your project folder, create a folder called 'lib/parrot' if it doesn't exist already. Navigate to that folder and place the parrot index.js within that folder. The url to download the parrot files can be found here:
http://github.com/ollym/parrot/zipball/master
View
@@ -0,0 +1,13 @@
+{
+ "name" : "parrot",
+ "description" : "A lightning fast and lightweight templating engine for Node.js.",
+ "keywords" : ["template"],
+ "homepage" : "https://github.com/ollym/parrot",
+ "version" : "0.3.0",
+ "author" : "Oliver Morgan <ollym@me.com>",
+ "contributors" : [],
+ "dependencies" : [],
+ "repository" : { "type": "git", "url": "git://github.com/ollym/parrot.git" },
+ "main" : "parrot.js" ,
+ "engines" : { "node": ">= 0.4.9 < 0.7.0" }
+}
View
191 parrot.js
@@ -0,0 +1,191 @@
+/**
+ * License Information (MIT)
+ *
+ * Copyright (c) 2010 Oliver Morgan (oliver.morgan@kohark.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+var crypto = require('crypto'),
+ Script = process.binding('evals').Script,
+ cache = { };
+
+// Defines parrot's version
+exports.version = '0.3.0';
+
+// Global configuration
+exports.config = {
+ sandbox: {},
+ cache: 5,
+ buffer: true,
+ tags: {
+ start: '<%',
+ end: '%>'
+ }
+};
+
+/**
+ * Clear's parrots internal cache
+ *
+ * @return undefined
+ */
+exports.clearCache = function() {
+
+ cache = {};
+}
+
+/**
+ * Renders a template
+ *
+ * @param data string The input data
+ * @param config object Any optional configuration options
+ * @return The rendered template
+ */
+exports.render = function(data, config, onprint) {
+
+ // If config is given as a function
+ if (typeof config === 'function') {
+
+ // Swap the parameters
+ onprint = config;
+ config = undefined;
+ }
+
+ if (config === undefined) {
+
+ // Use the global defaults
+ config = exports.config;
+ }
+ else {
+
+ // Set the cache and buffer configuration if none is defiend
+ config.cache = config.cache || exports.config.cache;
+ config.buffer = config.buffer || exports.config.buffer;
+
+ if (config.tags === undefined) {
+
+ // Default to the global tags
+ config.tags = exports.config.tags;
+ }
+ else {
+
+ // Default to the global tags if they aren't set
+ config.tags.start = config.tags.start || exports.config.tags.start;
+ config.tags.end = config.tags.end || exports.config.tags.end;
+ }
+
+ if (config.sandbox === undefined) {
+
+ // Set the sandbox defaults
+ config.sandbox = exports.config.sandbox;
+ }
+ else {
+
+ // Default to the global sandbox
+ var sandbox = exports.config.sandbox;
+
+ // Loop through each item in the sandbox
+ for (var key in config.sandbox) {
+
+ // And overwrite any existing sandbox item
+ sandbox[key] = config.sandbox[key];
+ }
+
+ // Replace the merged sandbox
+ config.sandbox = sandbox;
+ }
+ }
+
+ // Short forms for the start and end tags and get the parent callee
+ var et = config.tags.end,
+ st = config.tags.start,
+ ident = crypto.createHash('md5').update(data).digest('base64'),
+ output = '';
+
+ // Override the print function
+ config.sandbox.print = function(chunk) {
+
+ // We can only accept strings
+ chunk = chunk.toString();
+
+ // If the buffer configuration was set to false and the user defined a function
+ if ( ! config.buffer && typeof onprint === 'function') {
+
+ // Call the function with the data chunk
+ onprint(chunk);
+ }
+
+ // Append any data to the output buffer
+ output += chunk;
+ }
+
+ // If the output is already cached
+ if (cache[ident] !== undefined) {
+
+ // Print the entire output
+ config.sandbox.print(cache[ident]);
+
+ // And return the output
+ return output;
+ }
+
+ // Parrot can only process strings
+ data = data.toString();
+
+ // Escape double quoted strings and default to print
+ data = 'print("' + data.replace(/"/gm, '\\"') + '");';
+
+ // Compile the input into executable javascript
+ data = data
+ .replace(new RegExp(':\\s*' + et, ['g', 'm']), '{ %>')
+ .replace(new RegExp(st + '=(.+)' + et, ['g', 'm']), '"); print($1); print("')
+ .replace(new RegExp(st + '\\s*end(if|while|for|switch);*\\s*' + et, ['g', 'm', 'i']), '"); } print("')
+ .replace(new RegExp(st + '(.+)' + et, ['g', 'm']), '"); $1 print("')
+ .replace(new RegExp('\n', ['g', 'm']), '\\n')
+ .replace(new RegExp('\r', ['g', 'm']), '\\r')
+ .replace(new RegExp('\t', ['g', 'm']), '\\t');
+
+ // Execute the script, rendering the template
+ Script.runInNewContext(data, config.sandbox);
+
+ // If we have a valid cache amount
+ if (config.cache > 0) {
+
+ // Cache the output
+ cache[ident] = output;
+
+ // Set a timeout of the time
+ setTimeout(function() {
+
+ // Delete the cache entry
+ delete cache[ident];
+
+ }, config.cache);
+ }
+
+ // If we have been buffering the output and onprint is a function
+ if (config.buffer && typeof onprint == 'function') {
+
+ // Return the output value
+ return onprint(output);
+ }
+
+ // Return the output
+ return output;
+};

0 comments on commit df91e3f

Please sign in to comment.