commit
9401b91009
@ -0,0 +1,14 @@ |
||||
This is a Meteor application bundle. It has only one external dependency: |
||||
Node.js 0.10.36 or newer. To run the application: |
||||
|
||||
$ (cd programs/server && npm install) |
||||
$ export MONGO_URL='mongodb://user:password@host:port/databasename' |
||||
$ export ROOT_URL='http://example.com' |
||||
$ export MAIL_URL='smtp://user:password@mailhost:port/' |
||||
$ node main.js |
||||
|
||||
Use the PORT environment variable to set the port where the |
||||
application will listen. The default is 80, but that will require |
||||
root on most systems. |
||||
|
||||
Find out more about Meteor at meteor.com. |
@ -0,0 +1,9 @@ |
||||
|
||||
// The debugger pauses here when you run `meteor debug`, because this is
|
||||
// the very first code to be executed by the server process. If you have
|
||||
// not already added any `debugger` statements to your code, feel free to
|
||||
// do so now, wait for the server to restart, then reload this page and
|
||||
// click the |▶ button to continue.
|
||||
process.argv.splice(2, 0, 'program.json'); |
||||
process.chdir(require('path').join(__dirname, 'programs', 'server')); |
||||
require('./programs/server/boot.js'); |
@ -0,0 +1,28 @@ |
||||
<html {{htmlAttributes}}> |
||||
<head> |
||||
{{#each css}} <link rel="stylesheet" type="text/css" class="__meteor-css__" href="{{../bundledJsCssPrefix}}{{url}}">{{/each}} |
||||
|
||||
{{#if inlineScriptsAllowed}} |
||||
<script type='text/javascript'>__meteor_runtime_config__ = JSON.parse(decodeURIComponent({{meteorRuntimeConfig}}));</script> |
||||
{{else}} |
||||
<script type='text/javascript' src='{{rootUrlPathPrefix}}/meteor_runtime_config.js'></script> |
||||
{{/if}} |
||||
{{#each js}} <script type="text/javascript" src="{{../bundledJsCssPrefix}}{{url}}"></script> |
||||
{{/each}} |
||||
{{#each additionalStaticJs}} |
||||
{{#if ../inlineScriptsAllowed}} |
||||
<script type='text/javascript'> |
||||
{{contents}} |
||||
</script> |
||||
{{else}} |
||||
<script type='text/javascript' |
||||
src='{{rootUrlPathPrefix}}{{pathname}}'></script> |
||||
{{/if}} |
||||
{{/each}} |
||||
|
||||
{{{head}}} |
||||
</head> |
||||
<body> |
||||
{{{body}}} |
||||
</body> |
||||
</html> |
@ -0,0 +1,43 @@ |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta name="format-detection" content="telephone=no"> |
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height"> |
||||
<meta name="msapplication-tap-highlight" content="no"> |
||||
|
||||
{{#each css}} <link rel="stylesheet" type="text/css" class="__meteor-css__" href="{{../bundledJsCssPrefix}}{{url}}">{{/each}} |
||||
|
||||
<script type='text/javascript'> |
||||
__meteor_runtime_config__ = JSON.parse(decodeURIComponent({{meteorRuntimeConfig}})); |
||||
|
||||
if (/Android/i.test(navigator.userAgent)) { |
||||
// When Android app is emulated, it cannot connect to localhost, |
||||
// instead it should connect to 10.0.2.2 |
||||
// (unless we're using an http proxy; then it works!) |
||||
if (!__meteor_runtime_config__.httpProxyPort) { |
||||
__meteor_runtime_config__.ROOT_URL = (__meteor_runtime_config__.ROOT_URL || '').replace(/localhost/i, '10.0.2.2'); |
||||
__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL = (__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL || '').replace(/localhost/i, '10.0.2.2'); |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<script type="text/javascript" src="/cordova.js"></script> |
||||
{{#each js}} <script type="text/javascript" src="{{../bundledJsCssPrefix}}{{url}}"></script> |
||||
{{/each}} |
||||
{{#each additionalStaticJs}} |
||||
{{#if ../inlineScriptsAllowed}} |
||||
<script type='text/javascript'> |
||||
{{contents}} |
||||
</script> |
||||
{{else}} |
||||
<script type='text/javascript' |
||||
src='{{rootUrlPathPrefix}}{{pathname}}'></script> |
||||
{{/if}} |
||||
{{/each}} |
||||
{{{head}}} |
||||
</head> |
||||
|
||||
<body> |
||||
{{{body}}} |
||||
</body> |
||||
</html> |
@ -0,0 +1,7 @@ |
||||
// Separated from boot.js for testing.
|
||||
|
||||
// Check that we have a pid that looks like an integer (non-decimal
|
||||
// integer is okay).
|
||||
exports.validPid = function (pid) { |
||||
return ! isNaN(+pid); |
||||
}; |
@ -0,0 +1,263 @@ |
||||
var Fiber = require("fibers"); |
||||
var fs = require("fs"); |
||||
var path = require("path"); |
||||
var Future = require("fibers/future"); |
||||
var _ = require('underscore'); |
||||
var sourcemap_support = require('source-map-support'); |
||||
|
||||
var bootUtils = require('./boot-utils.js'); |
||||
var files = require('./mini-files.js'); |
||||
|
||||
// This code is duplicated in tools/main.js.
|
||||
var MIN_NODE_VERSION = 'v0.10.36'; |
||||
|
||||
if (require('semver').lt(process.version, MIN_NODE_VERSION)) { |
||||
process.stderr.write( |
||||
'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.\n'); |
||||
process.exit(1); |
||||
} |
||||
|
||||
// read our control files
|
||||
var serverJsonPath = path.resolve(process.argv[2]); |
||||
var serverDir = path.dirname(serverJsonPath); |
||||
var serverJson = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8')); |
||||
var configJson = |
||||
JSON.parse(fs.readFileSync(path.resolve(serverDir, 'config.json'), 'utf8')); |
||||
|
||||
// Set up environment
|
||||
__meteor_bootstrap__ = { |
||||
startupHooks: [], |
||||
serverDir: serverDir, |
||||
configJson: configJson }; |
||||
__meteor_runtime_config__ = { meteorRelease: configJson.meteorRelease }; |
||||
|
||||
|
||||
// connect (and some other NPM modules) use $NODE_ENV to make some decisions;
|
||||
// eg, if $NODE_ENV is not production, they send stack traces on error. connect
|
||||
// considers 'development' to be the default mode, but that's less safe than
|
||||
// assuming 'production' to be the default. If you really want development mode,
|
||||
// set it in your wrapper script (eg, run-app.js).
|
||||
if (!process.env.NODE_ENV) |
||||
process.env.NODE_ENV = 'production'; |
||||
|
||||
// Map from load path to its source map.
|
||||
var parsedSourceMaps = {}; |
||||
|
||||
// Read all the source maps into memory once.
|
||||
_.each(serverJson.load, function (fileInfo) { |
||||
if (fileInfo.sourceMap) { |
||||
var rawSourceMap = fs.readFileSync( |
||||
path.resolve(serverDir, fileInfo.sourceMap), 'utf8'); |
||||
// Parse the source map only once, not each time it's needed. Also remove
|
||||
// the anti-XSSI header if it's there.
|
||||
var parsedSourceMap = JSON.parse(rawSourceMap.replace(/^\)\]\}'/, '')); |
||||
// source-map-support doesn't ever look at the sourcesContent field, so
|
||||
// there's no point in keeping it in memory.
|
||||
delete parsedSourceMap.sourcesContent; |
||||
var url; |
||||
if (fileInfo.sourceMapRoot) { |
||||
// Add the specified root to any root that may be in the file.
|
||||
parsedSourceMap.sourceRoot = path.join( |
||||
fileInfo.sourceMapRoot, parsedSourceMap.sourceRoot || ''); |
||||
} |
||||
parsedSourceMaps[path.resolve(__dirname, fileInfo.path)] = parsedSourceMap; |
||||
} |
||||
}); |
||||
|
||||
var retrieveSourceMap = function (pathForSourceMap) { |
||||
if (_.has(parsedSourceMaps, pathForSourceMap)) |
||||
return { map: parsedSourceMaps[pathForSourceMap] }; |
||||
return null; |
||||
}; |
||||
|
||||
sourcemap_support.install({ |
||||
// Use the source maps specified in program.json instead of parsing source
|
||||
// code for them.
|
||||
retrieveSourceMap: retrieveSourceMap, |
||||
// For now, don't fix the source line in uncaught exceptions, because we
|
||||
// haven't fixed handleUncaughtExceptions in source-map-support to properly
|
||||
// locate the source files.
|
||||
handleUncaughtExceptions: false |
||||
}); |
||||
|
||||
// Only enabled by default in development.
|
||||
if (process.env.METEOR_SHELL_DIR) { |
||||
require('./shell-server.js').listen(process.env.METEOR_SHELL_DIR); |
||||
} |
||||
|
||||
// As a replacement to the old keepalives mechanism, check for a running
|
||||
// parent every few seconds. Exit if the parent is not running.
|
||||
//
|
||||
// Two caveats to this strategy:
|
||||
// * Doesn't catch the case where the parent is CPU-hogging (but maybe we
|
||||
// don't want to catch that case anyway, since the bundler not yielding
|
||||
// is what caused #2536).
|
||||
// * Could be fooled by pid re-use, i.e. if another process comes up and
|
||||
// takes the parent process's place before the child process dies.
|
||||
var startCheckForLiveParent = function (parentPid) { |
||||
if (parentPid) { |
||||
if (! bootUtils.validPid(parentPid)) { |
||||
console.error("METEOR_PARENT_PID must be a valid process ID."); |
||||
process.exit(1); |
||||
} |
||||
|
||||
setInterval(function () { |
||||
try { |
||||
process.kill(parentPid, 0); |
||||
} catch (err) { |
||||
console.error("Parent process is dead! Exiting."); |
||||
process.exit(1); |
||||
} |
||||
}, 3000); |
||||
} |
||||
}; |
||||
|
||||
|
||||
Fiber(function () { |
||||
_.each(serverJson.load, function (fileInfo) { |
||||
var code = fs.readFileSync(path.resolve(serverDir, fileInfo.path)); |
||||
|
||||
var Npm = { |
||||
/** |
||||
* @summary Require a package that was specified using |
||||
* `Npm.depends()`. |
||||
* @param {String} name The name of the package to require. |
||||
* @locus Server |
||||
* @memberOf Npm |
||||
*/ |
||||
require: function (name) { |
||||
if (! fileInfo.node_modules) { |
||||
return require(name); |
||||
} |
||||
|
||||
var nodeModuleBase = path.resolve(serverDir, |
||||
files.convertToOSPath(fileInfo.node_modules)); |
||||
var nodeModuleDir = path.resolve(nodeModuleBase, name); |
||||
|
||||
// If the user does `Npm.require('foo/bar')`, then we should resolve to
|
||||
// the package's node modules if `foo` was one of the modules we
|
||||
// installed. (`foo/bar` might be implemented as `foo/bar.js` so we
|
||||
// can't just naively see if all of nodeModuleDir exists.
|
||||
if (fs.existsSync(path.resolve(nodeModuleBase, name.split("/")[0]))) { |
||||
return require(nodeModuleDir); |
||||
} |
||||
|
||||
try { |
||||
return require(name); |
||||
} catch (e) { |
||||
// Try to guess the package name so we can print a nice
|
||||
// error message
|
||||
// fileInfo.path is a standard path, use files.pathSep
|
||||
var filePathParts = fileInfo.path.split(files.pathSep); |
||||
var packageName = filePathParts[1].replace(/\.js$/, ''); |
||||
|
||||
// XXX better message
|
||||
throw new Error( |
||||
"Can't find npm module '" + name + |
||||
"'. Did you forget to call 'Npm.depends' in package.js " + |
||||
"within the '" + packageName + "' package?"); |
||||
} |
||||
} |
||||
}; |
||||
var getAsset = function (assetPath, encoding, callback) { |
||||
var fut; |
||||
if (! callback) { |
||||
fut = new Future(); |
||||
callback = fut.resolver(); |
||||
} |
||||
// This assumes that we've already loaded the meteor package, so meteor
|
||||
// itself (and weird special cases like js-analyze) can't call
|
||||
// Assets.get*. (We could change this function so that it doesn't call
|
||||
// bindEnvironment if you don't pass a callback if we need to.)
|
||||
var _callback = Package.meteor.Meteor.bindEnvironment(function (err, result) { |
||||
if (result && ! encoding) |
||||
// Sadly, this copies in Node 0.10.
|
||||
result = new Uint8Array(result); |
||||
callback(err, result); |
||||
}, function (e) { |
||||
console.log("Exception in callback of getAsset", e.stack); |
||||
}); |
||||
|
||||
// Convert a DOS-style path to Unix-style in case the application code was
|
||||
// written on Windows.
|
||||
assetPath = files.convertToStandardPath(assetPath); |
||||
|
||||
if (!fileInfo.assets || !_.has(fileInfo.assets, assetPath)) { |
||||
_callback(new Error("Unknown asset: " + assetPath)); |
||||
} else { |
||||
var filePath = path.join(serverDir, fileInfo.assets[assetPath]); |
||||
fs.readFile(files.convertToOSPath(filePath), encoding, _callback); |
||||
} |
||||
if (fut) |
||||
return fut.wait(); |
||||
}; |
||||
|
||||
var Assets = { |
||||
getText: function (assetPath, callback) { |
||||
return getAsset(assetPath, "utf8", callback); |
||||
}, |
||||
getBinary: function (assetPath, callback) { |
||||
return getAsset(assetPath, undefined, callback); |
||||
} |
||||
}; |
||||
|
||||
// \n is necessary in case final line is a //-comment
|
||||
var wrapped = "(function(Npm, Assets){" + code + "\n})"; |
||||
|
||||
// It is safer to use the absolute path when source map is present as
|
||||
// different tooling, such as node-inspector, can get confused on relative
|
||||
// urls.
|
||||
|
||||
// fileInfo.path is a standard path, convert it to OS path to join with
|
||||
// __dirname
|
||||
var fileInfoOSPath = files.convertToOSPath(fileInfo.path); |
||||
var absoluteFilePath = path.resolve(__dirname, fileInfoOSPath); |
||||
|
||||
var scriptPath = |
||||
parsedSourceMaps[absoluteFilePath] ? absoluteFilePath : fileInfoOSPath; |
||||
// The final 'true' is an undocumented argument to runIn[Foo]Context that
|
||||
// causes it to print out a descriptive error message on parse error. It's
|
||||
// what require() uses to generate its errors.
|
||||
var func = require('vm').runInThisContext(wrapped, scriptPath, true); |
||||
func.call(global, Npm, Assets); // Coffeescript
|
||||
}); |
||||
|
||||
// run the user startup hooks. other calls to startup() during this can still
|
||||
// add hooks to the end.
|
||||
while (__meteor_bootstrap__.startupHooks.length) { |
||||
var hook = __meteor_bootstrap__.startupHooks.shift(); |
||||
hook(); |
||||
} |
||||
// Setting this to null tells Meteor.startup to call hooks immediately.
|
||||
__meteor_bootstrap__.startupHooks = null; |
||||
|
||||
// find and run main()
|
||||
// XXX hack. we should know the package that contains main.
|
||||
var mains = []; |
||||
var globalMain; |
||||
if ('main' in global) { |
||||
mains.push(main); |
||||
globalMain = main; |
||||
} |
||||
typeof Package !== 'undefined' && _.each(Package, function (p, n) { |
||||
if ('main' in p && p.main !== globalMain) { |
||||
mains.push(p.main); |
||||
} |
||||
}); |
||||
if (! mains.length) { |
||||
process.stderr.write("Program has no main() function.\n"); |
||||
process.exit(1); |
||||
} |
||||
if (mains.length > 1) { |
||||
process.stderr.write("Program has more than one main() function?\n"); |
||||
process.exit(1); |
||||
} |
||||
var exitCode = mains[0].call({}, process.argv.slice(3)); |
||||
// XXX hack, needs a better way to keep alive
|
||||
if (exitCode !== 'DAEMON') |
||||
process.exit(exitCode); |
||||
|
||||
if (process.env.METEOR_PARENT_PID) { |
||||
startCheckForLiveParent(process.env.METEOR_PARENT_PID); |
||||
} |
||||
}).run(); |
@ -0,0 +1,6 @@ |
||||
{ |
||||
"meteorRelease": "METEOR@1.1.0.2", |
||||
"clientPaths": { |
||||
"web.browser": "../web.browser/program.json" |
||||
} |
||||
} |
@ -0,0 +1,108 @@ |
||||
var _ = require("underscore"); |
||||
var os = require("os"); |
||||
var path = require("path"); |
||||
|
||||
// All of these functions are attached to files.js for the tool;
|
||||
// they live here because we need them in boot.js as well to avoid duplicating
|
||||
// a lot of the code.
|
||||
//
|
||||
// Note that this file does NOT contain any of the "perform I/O maybe
|
||||
// synchronously" functions from files.js; this is intentional, because we want
|
||||
// to make it very hard to accidentally use fs.*Sync functions in the app server
|
||||
// after bootup (since they block all concurrency!)
|
||||
var files = module.exports; |
||||
|
||||
var toPosixPath = function (p, partialPath) { |
||||
// Sometimes, you can have a path like \Users\IEUser on windows, and this
|
||||
// actually means you want C:\Users\IEUser
|
||||
if (p[0] === "\\" && (! partialPath)) { |
||||
p = process.env.SystemDrive + p; |
||||
} |
||||
|
||||
p = p.replace(/\\/g, '/'); |
||||
if (p[1] === ':' && ! partialPath) { |
||||
// transform "C:/bla/bla" to "/c/bla/bla"
|
||||
p = '/' + p[0] + p.slice(2); |
||||
} |
||||
|
||||
return p; |
||||
}; |
||||
|
||||
var toDosPath = function (p, partialPath) { |
||||
if (p[0] === '/' && ! partialPath) { |
||||
if (! /^\/[A-Za-z](\/|$)/.test(p)) |
||||
throw new Error("Surprising path: " + p); |
||||
// transform a previously windows path back
|
||||
// "/C/something" to "c:/something"
|
||||
p = p[1] + ":" + p.slice(2); |
||||
} |
||||
|
||||
p = p.replace(/\//g, '\\'); |
||||
return p; |
||||
}; |
||||
|
||||
|
||||
var convertToOSPath = function (standardPath, partialPath) { |
||||
if (process.platform === "win32") { |
||||
return toDosPath(standardPath, partialPath); |
||||
} |
||||
|
||||
return standardPath; |
||||
}; |
||||
|
||||
var convertToStandardPath = function (osPath, partialPath) { |
||||
if (process.platform === "win32") { |
||||
return toPosixPath(osPath, partialPath); |
||||
} |
||||
|
||||
return osPath; |
||||
} |
||||
|
||||
var convertToOSLineEndings = function (fileContents) { |
||||
return fileContents.replace(/\n/g, os.EOL); |
||||
}; |
||||
|
||||
var convertToStandardLineEndings = function (fileContents) { |
||||
// Convert all kinds of end-of-line chars to linuxy "\n".
|
||||
return fileContents.replace(new RegExp("\r\n", "g"), "\n") |
||||
.replace(new RegExp("\r", "g"), "\n"); |
||||
}; |
||||
|
||||
|
||||
// wrappings for path functions that always run as they were on unix (using
|
||||
// forward slashes)
|
||||
var wrapPathFunction = function (name, partialPaths) { |
||||
var f = path[name]; |
||||
return function (/* args */) { |
||||
if (process.platform === 'win32') { |
||||
var args = _.toArray(arguments); |
||||
args = _.map(args, function (p, i) { |
||||
// if partialPaths is turned on (for path.join mostly)
|
||||
// forget about conversion of absolute paths for Windows
|
||||
return toDosPath(p, partialPaths); |
||||
}); |
||||
return toPosixPath(f.apply(path, args), partialPaths); |
||||
} else { |
||||
return f.apply(path, arguments); |
||||
} |
||||
}; |
||||
}; |
||||
|
||||
files.pathJoin = wrapPathFunction("join", true); |
||||
files.pathNormalize = wrapPathFunction("normalize"); |
||||
files.pathRelative = wrapPathFunction("relative"); |
||||
files.pathResolve = wrapPathFunction("resolve"); |
||||
files.pathDirname = wrapPathFunction("dirname"); |
||||
files.pathBasename = wrapPathFunction("basename"); |
||||
files.pathExtname = wrapPathFunction("extname"); |
||||
files.pathSep = '/'; |
||||
files.pathDelimiter = ':'; |
||||
files.pathOsDelimiter = path.delimiter; |
||||
|
||||
files.convertToStandardPath = convertToStandardPath; |
||||
files.convertToOSPath = convertToOSPath; |
||||
files.convertToWindowsPath = toDosPath; |
||||
files.convertToPosixPath = toPosixPath; |
||||
|
||||
files.convertToStandardLineEndings = convertToStandardLineEndings; |
||||
files.convertToOSLineEndings = convertToOSLineEndings; |
@ -0,0 +1,40 @@ |
||||
{ |
||||
"name": "meteor-dev-bundle", |
||||
"version": "0.0.0", |
||||
"dependencies": { |
||||
"fibers": { |
||||
"version": "1.0.5", |
||||
"from": "fibers@1.0.5", |
||||
"resolved": "https://registry.npmjs.org/fibers/-/fibers-1.0.5.tgz" |
||||
}, |
||||
"semver": { |
||||
"version": "4.1.0", |
||||
"from": "semver@4.1.0", |
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-4.1.0.tgz" |
||||
}, |
||||
"source-map-support": { |
||||
"version": "0.2.8", |
||||
"from": "source-map-support@0.2.8", |
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.8.tgz", |
||||
"dependencies": { |
||||
"source-map": { |
||||
"version": "0.1.32", |
||||
"from": "source-map@0.1.32", |
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", |
||||
"dependencies": { |
||||
"amdefine": { |
||||
"version": "0.1.0", |
||||
"from": "amdefine@>=0.0.4", |
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"underscore": { |
||||
"version": "1.5.2", |
||||
"from": "underscore@1.5.2", |
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.5.2.tgz" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
{ |
||||
"name": "meteor-dev-bundle", |
||||
"version": "0.0.0", |
||||
"dependencies": { |
||||
"fibers": "1.0.5", |
||||
"underscore": "1.5.2", |
||||
"source-map-support": "0.2.8", |
||||
"semver": "4.1.0" |
||||
}, |
||||
"devDependencies": { |
||||
"eachline": "https://github.com/meteor/node-eachline/tarball/ff89722ff94e6b6a08652bf5f44c8fffea8a21da", |
||||
"chalk": "0.5.1" |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.autopublish = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=autopublish.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/autopublish.js"} |
@ -0,0 +1,237 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var WebApp = Package.webapp.WebApp; |
||||
var main = Package.webapp.main; |
||||
var WebAppInternals = Package.webapp.WebAppInternals; |
||||
var DDP = Package.ddp.DDP; |
||||
var DDPServer = Package.ddp.DDPServer; |
||||
var MongoInternals = Package.mongo.MongoInternals; |
||||
var Mongo = Package.mongo.Mongo; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var Autoupdate, ClientVersions; |
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/autoupdate/autoupdate_server.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Publish the current client versions to the client. When a client // 1
|
||||
// sees the subscription change and that there is a new version of the // 2
|
||||
// client available on the server, it can reload. // 3
|
||||
// // 4
|
||||
// By default there are two current client versions. The refreshable client // 5
|
||||
// version is identified by a hash of the client resources seen by the browser // 6
|
||||
// that are refreshable, such as CSS, while the non refreshable client version // 7
|
||||
// is identified by a hash of the rest of the client assets // 8
|
||||
// (the HTML, code, and static files in the `public` directory). // 9
|
||||
// // 10
|
||||
// If the environment variable `AUTOUPDATE_VERSION` is set it will be // 11
|
||||
// used as the client id instead. You can use this to control when // 12
|
||||
// the client reloads. For example, if you want to only force a // 13
|
||||
// reload on major changes, you can use a custom AUTOUPDATE_VERSION // 14
|
||||
// which you only change when something worth pushing to clients // 15
|
||||
// immediately happens. // 16
|
||||
// // 17
|
||||
// The server publishes a `meteor_autoupdate_clientVersions` // 18
|
||||
// collection. There are two documents in this collection, a document // 19
|
||||
// with _id 'version' which represnets the non refreshable client assets, // 20
|
||||
// and a document with _id 'version-refreshable' which represents the // 21
|
||||
// refreshable client assets. Each document has a 'version' field // 22
|
||||
// which is equivalent to the hash of the relevant assets. The refreshable // 23
|
||||
// document also contains a list of the refreshable assets, so that the client // 24
|
||||
// can swap in the new assets without forcing a page refresh. Clients can // 25
|
||||
// observe changes on these documents to detect when there is a new // 26
|
||||
// version available. // 27
|
||||
// // 28
|
||||
// In this implementation only two documents are present in the collection // 29
|
||||
// the current refreshable client version and the current nonRefreshable client // 30
|
||||
// version. Developers can easily experiment with different versioning and // 31
|
||||
// updating models by forking this package. // 32
|
||||
// 33
|
||||
var Future = Npm.require("fibers/future"); // 34
|
||||
// 35
|
||||
Autoupdate = {}; // 36
|
||||
// 37
|
||||
// The collection of acceptable client versions. // 38
|
||||
ClientVersions = new Mongo.Collection("meteor_autoupdate_clientVersions", // 39
|
||||
{ connection: null }); // 40
|
||||
// 41
|
||||
// The client hash includes __meteor_runtime_config__, so wait until // 42
|
||||
// all packages have loaded and have had a chance to populate the // 43
|
||||
// runtime config before using the client hash as our default auto // 44
|
||||
// update version id. // 45
|
||||
// 46
|
||||
// Note: Tests allow people to override Autoupdate.autoupdateVersion before // 47
|
||||
// startup. // 48
|
||||
Autoupdate.autoupdateVersion = null; // 49
|
||||
Autoupdate.autoupdateVersionRefreshable = null; // 50
|
||||
Autoupdate.autoupdateVersionCordova = null; // 51
|
||||
Autoupdate.appId = __meteor_runtime_config__.appId = process.env.APP_ID; // 52
|
||||
// 53
|
||||
var syncQueue = new Meteor._SynchronousQueue(); // 54
|
||||
// 55
|
||||
// updateVersions can only be called after the server has fully loaded. // 56
|
||||
var updateVersions = function (shouldReloadClientProgram) { // 57
|
||||
// Step 1: load the current client program on the server and update the // 58
|
||||
// hash values in __meteor_runtime_config__. // 59
|
||||
if (shouldReloadClientProgram) { // 60
|
||||
WebAppInternals.reloadClientPrograms(); // 61
|
||||
} // 62
|
||||
// 63
|
||||
// If we just re-read the client program, or if we don't have an autoupdate // 64
|
||||
// version, calculate it. // 65
|
||||
if (shouldReloadClientProgram || Autoupdate.autoupdateVersion === null) { // 66
|
||||
Autoupdate.autoupdateVersion = // 67
|
||||
process.env.AUTOUPDATE_VERSION || // 68
|
||||
WebApp.calculateClientHashNonRefreshable(); // 69
|
||||
} // 70
|
||||
// If we just recalculated it OR if it was set by (eg) test-in-browser, // 71
|
||||
// ensure it ends up in __meteor_runtime_config__. // 72
|
||||
__meteor_runtime_config__.autoupdateVersion = // 73
|
||||
Autoupdate.autoupdateVersion; // 74
|
||||
// 75
|
||||
Autoupdate.autoupdateVersionRefreshable = // 76
|
||||
__meteor_runtime_config__.autoupdateVersionRefreshable = // 77
|
||||
process.env.AUTOUPDATE_VERSION || // 78
|
||||
WebApp.calculateClientHashRefreshable(); // 79
|
||||
// 80
|
||||
Autoupdate.autoupdateVersionCordova = // 81
|
||||
__meteor_runtime_config__.autoupdateVersionCordova = // 82
|
||||
process.env.AUTOUPDATE_VERSION || // 83
|
||||
WebApp.calculateClientHashCordova(); // 84
|
||||
// 85
|
||||
// Step 2: form the new client boilerplate which contains the updated // 86
|
||||
// assets and __meteor_runtime_config__. // 87
|
||||
if (shouldReloadClientProgram) { // 88
|
||||
WebAppInternals.generateBoilerplate(); // 89
|
||||
} // 90
|
||||
// 91
|
||||
// XXX COMPAT WITH 0.8.3 // 92
|
||||
if (! ClientVersions.findOne({current: true})) { // 93
|
||||
// To ensure apps with version of Meteor prior to 0.9.0 (in // 94
|
||||
// which the structure of documents in `ClientVersions` was // 95
|
||||
// different) also reload. // 96
|
||||
ClientVersions.insert({current: true}); // 97
|
||||
} // 98
|
||||
// 99
|
||||
if (! ClientVersions.findOne({_id: "version"})) { // 100
|
||||
ClientVersions.insert({ // 101
|
||||
_id: "version", // 102
|
||||
version: Autoupdate.autoupdateVersion // 103
|
||||
}); // 104
|
||||
} else { // 105
|
||||
ClientVersions.update("version", { $set: { // 106
|
||||
version: Autoupdate.autoupdateVersion // 107
|
||||
}}); // 108
|
||||
} // 109
|
||||
// 110
|
||||
if (! ClientVersions.findOne({_id: "version-cordova"})) { // 111
|
||||
ClientVersions.insert({ // 112
|
||||
_id: "version-cordova", // 113
|
||||
version: Autoupdate.autoupdateVersionCordova, // 114
|
||||
refreshable: false // 115
|
||||
}); // 116
|
||||
} else { // 117
|
||||
ClientVersions.update("version-cordova", { $set: { // 118
|
||||
version: Autoupdate.autoupdateVersionCordova // 119
|
||||
}}); // 120
|
||||
} // 121
|
||||
// 122
|
||||
// Use `onListening` here because we need to use // 123
|
||||
// `WebAppInternals.refreshableAssets`, which is only set after // 124
|
||||
// `WebApp.generateBoilerplate` is called by `main` in webapp. // 125
|
||||
WebApp.onListening(function () { // 126
|
||||
if (! ClientVersions.findOne({_id: "version-refreshable"})) { // 127
|
||||
ClientVersions.insert({ // 128
|
||||
_id: "version-refreshable", // 129
|
||||
version: Autoupdate.autoupdateVersionRefreshable, // 130
|
||||
assets: WebAppInternals.refreshableAssets // 131
|
||||
}); // 132
|
||||
} else { // 133
|
||||
ClientVersions.update("version-refreshable", { $set: { // 134
|
||||
version: Autoupdate.autoupdateVersionRefreshable, // 135
|
||||
assets: WebAppInternals.refreshableAssets // 136
|
||||
}}); // 137
|
||||
} // 138
|
||||
}); // 139
|
||||
}; // 140
|
||||
// 141
|
||||
Meteor.publish( // 142
|
||||
"meteor_autoupdate_clientVersions", // 143
|
||||
function (appId) { // 144
|
||||
// `null` happens when a client doesn't have an appId and passes // 145
|
||||
// `undefined` to `Meteor.subscribe`. `undefined` is translated to // 146
|
||||
// `null` as JSON doesn't have `undefined. // 147
|
||||
check(appId, Match.OneOf(String, undefined, null)); // 148
|
||||
// 149
|
||||
// Don't notify clients using wrong appId such as mobile apps built with a // 150
|
||||
// different server but pointing at the same local url // 151
|
||||
if (Autoupdate.appId && appId && Autoupdate.appId !== appId) // 152
|
||||
return []; // 153
|
||||
// 154
|
||||
return ClientVersions.find(); // 155
|
||||
}, // 156
|
||||
{is_auto: true} // 157
|
||||
); // 158
|
||||
// 159
|
||||
Meteor.startup(function () { // 160
|
||||
updateVersions(false); // 161
|
||||
}); // 162
|
||||
// 163
|
||||
var fut = new Future(); // 164
|
||||
// 165
|
||||
// We only want 'refresh' to trigger 'updateVersions' AFTER onListen, // 166
|
||||
// so we add a queued task that waits for onListen before 'refresh' can queue // 167
|
||||
// tasks. Note that the `onListening` callbacks do not fire until after // 168
|
||||
// Meteor.startup, so there is no concern that the 'updateVersions' calls from // 169
|
||||
// 'refresh' will overlap with the `updateVersions` call from Meteor.startup. // 170
|
||||
// 171
|
||||
syncQueue.queueTask(function () { // 172
|
||||
fut.wait(); // 173
|
||||
}); // 174
|
||||
// 175
|
||||
WebApp.onListening(function () { // 176
|
||||
fut.return(); // 177
|
||||
}); // 178
|
||||
// 179
|
||||
var enqueueVersionsRefresh = function () { // 180
|
||||
syncQueue.queueTask(function () { // 181
|
||||
updateVersions(true); // 182
|
||||
}); // 183
|
||||
}; // 184
|
||||
// 185
|
||||
// Listen for the special {refresh: 'client'} message, which signals that a // 186
|
||||
// client asset has changed. // 187
|
||||
process.on('message', Meteor.bindEnvironment(function (m) { // 188
|
||||
if (m && m.refresh === 'client') { // 189
|
||||
enqueueVersionsRefresh(); // 190
|
||||
} // 191
|
||||
})); // 192
|
||||
// 193
|
||||
// Another way to tell the process to refresh: send SIGHUP signal // 194
|
||||
process.on('SIGHUP', Meteor.bindEnvironment(function () { // 195
|
||||
enqueueVersionsRefresh(); // 196
|
||||
})); // 197
|
||||
// 198
|
||||
// 199
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.autoupdate = { |
||||
Autoupdate: Autoupdate |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=autoupdate.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,175 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
/* Package-scope variables */ |
||||
var Base64; |
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/base64/base64.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Base 64 encoding // 1
|
||||
// 2
|
||||
var BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // 3
|
||||
// 4
|
||||
var BASE_64_VALS = {}; // 5
|
||||
// 6
|
||||
for (var i = 0; i < BASE_64_CHARS.length; i++) { // 7
|
||||
BASE_64_VALS[BASE_64_CHARS.charAt(i)] = i; // 8
|
||||
}; // 9
|
||||
// 10
|
||||
Base64 = {}; // 11
|
||||
// 12
|
||||
Base64.encode = function (array) { // 13
|
||||
// 14
|
||||
if (typeof array === "string") { // 15
|
||||
var str = array; // 16
|
||||
array = Base64.newBinary(str.length); // 17
|
||||
for (var i = 0; i < str.length; i++) { // 18
|
||||
var ch = str.charCodeAt(i); // 19
|
||||
if (ch > 0xFF) { // 20
|
||||
throw new Error( // 21
|
||||
"Not ascii. Base64.encode can only take ascii strings."); // 22
|
||||
} // 23
|
||||
array[i] = ch; // 24
|
||||
} // 25
|
||||
} // 26
|
||||
// 27
|
||||
var answer = []; // 28
|
||||
var a = null; // 29
|
||||
var b = null; // 30
|
||||
var c = null; // 31
|
||||
var d = null; // 32
|
||||
for (var i = 0; i < array.length; i++) { // 33
|
||||
switch (i % 3) { // 34
|
||||
case 0: // 35
|
||||
a = (array[i] >> 2) & 0x3F; // 36
|
||||
b = (array[i] & 0x03) << 4; // 37
|
||||
break; // 38
|
||||
case 1: // 39
|
||||
b = b | (array[i] >> 4) & 0xF; // 40
|
||||
c = (array[i] & 0xF) << 2; // 41
|
||||
break; // 42
|
||||
case 2: // 43
|
||||
c = c | (array[i] >> 6) & 0x03; // 44
|
||||
d = array[i] & 0x3F; // 45
|
||||
answer.push(getChar(a)); // 46
|
||||
answer.push(getChar(b)); // 47
|
||||
answer.push(getChar(c)); // 48
|
||||
answer.push(getChar(d)); // 49
|
||||
a = null; // 50
|
||||
b = null; // 51
|
||||
c = null; // 52
|
||||
d = null; // 53
|
||||
break; // 54
|
||||
} // 55
|
||||
} // 56
|
||||
if (a != null) { // 57
|
||||
answer.push(getChar(a)); // 58
|
||||
answer.push(getChar(b)); // 59
|
||||
if (c == null) // 60
|
||||
answer.push('='); // 61
|
||||
else // 62
|
||||
answer.push(getChar(c)); // 63
|
||||
if (d == null) // 64
|
||||
answer.push('='); // 65
|
||||
} // 66
|
||||
return answer.join(""); // 67
|
||||
}; // 68
|
||||
// 69
|
||||
var getChar = function (val) { // 70
|
||||
return BASE_64_CHARS.charAt(val); // 71
|
||||
}; // 72
|
||||
// 73
|
||||
var getVal = function (ch) { // 74
|
||||
if (ch === '=') { // 75
|
||||
return -1; // 76
|
||||
} // 77
|
||||
return BASE_64_VALS[ch]; // 78
|
||||
}; // 79
|
||||
// 80
|
||||
// XXX This is a weird place for this to live, but it's used both by // 81
|
||||
// this package and 'ejson', and we can't put it in 'ejson' without // 82
|
||||
// introducing a circular dependency. It should probably be in its own // 83
|
||||
// package or as a helper in a package that both 'base64' and 'ejson' // 84
|
||||
// use. // 85
|
||||
Base64.newBinary = function (len) { // 86
|
||||
if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') { // 87
|
||||
var ret = []; // 88
|
||||
for (var i = 0; i < len; i++) { // 89
|
||||
ret.push(0); // 90
|
||||
} // 91
|
||||
ret.$Uint8ArrayPolyfill = true; // 92
|
||||
return ret; // 93
|
||||
} // 94
|
||||
return new Uint8Array(new ArrayBuffer(len)); // 95
|
||||
}; // 96
|
||||
// 97
|
||||
Base64.decode = function (str) { // 98
|
||||
var len = Math.floor((str.length*3)/4); // 99
|
||||
if (str.charAt(str.length - 1) == '=') { // 100
|
||||
len--; // 101
|
||||
if (str.charAt(str.length - 2) == '=') // 102
|
||||
len--; // 103
|
||||
} // 104
|
||||
var arr = Base64.newBinary(len); // 105
|
||||
// 106
|
||||
var one = null; // 107
|
||||
var two = null; // 108
|
||||
var three = null; // 109
|
||||
// 110
|
||||
var j = 0; // 111
|
||||
// 112
|
||||
for (var i = 0; i < str.length; i++) { // 113
|
||||
var c = str.charAt(i); // 114
|
||||
var v = getVal(c); // 115
|
||||
switch (i % 4) { // 116
|
||||
case 0: // 117
|
||||
if (v < 0) // 118
|
||||
throw new Error('invalid base64 string'); // 119
|
||||
one = v << 2; // 120
|
||||
break; // 121
|
||||
case 1: // 122
|
||||
if (v < 0) // 123
|
||||
throw new Error('invalid base64 string'); // 124
|
||||
one = one | (v >> 4); // 125
|
||||
arr[j++] = one; // 126
|
||||
two = (v & 0x0F) << 4; // 127
|
||||
break; // 128
|
||||
case 2: // 129
|
||||
if (v >= 0) { // 130
|
||||
two = two | (v >> 2); // 131
|
||||
arr[j++] = two; // 132
|
||||
three = (v & 0x03) << 6; // 133
|
||||
} // 134
|
||||
break; // 135
|
||||
case 3: // 136
|
||||
if (v >= 0) { // 137
|
||||
arr[j++] = three | v; // 138
|
||||
} // 139
|
||||
break; // 140
|
||||
} // 141
|
||||
} // 142
|
||||
return arr; // 143
|
||||
}; // 144
|
||||
// 145
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.base64 = { |
||||
Base64: Base64 |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=base64.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["base64/base64.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mB;;AAEA,uF;;AAEA,sB;;AAEA,gD;AACA,4C;AACA,E;;AAEA,Y;;AAEA,kC;;AAEA,kC;AACA,oB;AACA,yC;AACA,0C;AACA,iC;AACA,sB;AACA,wB;AACA,mE;AACA,O;AACA,oB;AACA,K;AACA,G;;AAEA,kB;AACA,e;AACA,e;AACA,e;AACA,e;AACA,0C;AACA,oB;AACA,W;AACA,iC;AACA,iC;AACA,Y;AACA,W;AACA,oC;AACA,gC;AACA,Y;AACA,W;AACA,qC;AACA,0B;AACA,8B;AACA,8B;AACA,8B;AACA,8B;AACA,e;AACA,e;AACA,e;AACA,e;AACA,Y;AACA,K;AACA,G;AACA,kB;AACA,4B;AACA,4B;AACA,kB;AACA,uB;AACA,Q;AACA,8B;AACA,kB;AACA,uB;AACA,G;AACA,yB;AACA,E;;AAEA,8B;AACA,mC;AACA,E;;AAEA,4B;AACA,mB;AACA,c;AACA,G;AACA,0B;AACA,E;;AAEA,oE;AACA,mE;AACA,sE;AACA,qE;AACA,O;AACA,mC;AACA,gF;AACA,iB;AACA,mC;AACA,kB;AACA,K;AACA,mC;AACA,e;AACA,G;AACA,8C;AACA,E;;AAEA,gC;AACA,yC;AACA,0C;AACA,U;AACA,0C;AACA,Y;AACA,G;AACA,kC;;AAEA,iB;AACA,iB;AACA,mB;;AAEA,Y;;AAEA,wC;AACA,0B;AACA,sB;AACA,oB;AACA,W;AACA,gB;AACA,iD;AACA,mB;AACA,Y;AACA,W;AACA,gB;AACA,iD;AACA,2B;AACA,qB;AACA,4B;AACA,Y;AACA,W;AACA,mB;AACA,6B;AACA,uB;AACA,gC;AACA,O;AACA,Y;AACA,W;AACA,mB;AACA,6B;AACA,O;AACA,Y;AACA,K;AACA,G;AACA,a;AACA,E","file":"/packages/base64.js","sourcesContent":["// Base 64 encoding\n\nvar BASE_64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nvar BASE_64_VALS = {};\n\nfor (var i = 0; i < BASE_64_CHARS.length; i++) {\n BASE_64_VALS[BASE_64_CHARS.charAt(i)] = i;\n};\n\nBase64 = {};\n\nBase64.encode = function (array) {\n\n if (typeof array === \"string\") {\n var str = array;\n array = Base64.newBinary(str.length);\n for (var i = 0; i < str.length; i++) {\n var ch = str.charCodeAt(i);\n if (ch > 0xFF) {\n throw new Error(\n \"Not ascii. Base64.encode can only take ascii strings.\");\n }\n array[i] = ch;\n }\n }\n\n var answer = [];\n var a = null;\n var b = null;\n var c = null;\n var d = null;\n for (var i = 0; i < array.length; i++) {\n switch (i % 3) {\n case 0:\n a = (array[i] >> 2) & 0x3F;\n b = (array[i] & 0x03) << 4;\n break;\n case 1:\n b = b | (array[i] >> 4) & 0xF;\n c = (array[i] & 0xF) << 2;\n break;\n case 2:\n c = c | (array[i] >> 6) & 0x03;\n d = array[i] & 0x3F;\n answer.push(getChar(a));\n answer.push(getChar(b));\n answer.push(getChar(c));\n answer.push(getChar(d));\n a = null;\n b = null;\n c = null;\n d = null;\n break;\n }\n }\n if (a != null) {\n answer.push(getChar(a));\n answer.push(getChar(b));\n if (c == null)\n answer.push('=');\n else\n answer.push(getChar(c));\n if (d == null)\n answer.push('=');\n }\n return answer.join(\"\");\n};\n\nvar getChar = function (val) {\n return BASE_64_CHARS.charAt(val);\n};\n\nvar getVal = function (ch) {\n if (ch === '=') {\n return -1;\n }\n return BASE_64_VALS[ch];\n};\n\n// XXX This is a weird place for this to live, but it's used both by\n// this package and 'ejson', and we can't put it in 'ejson' without\n// introducing a circular dependency. It should probably be in its own\n// package or as a helper in a package that both 'base64' and 'ejson'\n// use.\nBase64.newBinary = function (len) {\n if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') {\n var ret = [];\n for (var i = 0; i < len; i++) {\n ret.push(0);\n }\n ret.$Uint8ArrayPolyfill = true;\n return ret;\n }\n return new Uint8Array(new ArrayBuffer(len));\n};\n\nBase64.decode = function (str) {\n var len = Math.floor((str.length*3)/4);\n if (str.charAt(str.length - 1) == '=') {\n len--;\n if (str.charAt(str.length - 2) == '=')\n len--;\n }\n var arr = Base64.newBinary(len);\n\n var one = null;\n var two = null;\n var three = null;\n\n var j = 0;\n\n for (var i = 0; i < str.length; i++) {\n var c = str.charAt(i);\n var v = getVal(c);\n switch (i % 4) {\n case 0:\n if (v < 0)\n throw new Error('invalid base64 string');\n one = v << 2;\n break;\n case 1:\n if (v < 0)\n throw new Error('invalid base64 string');\n one = one | (v >> 4);\n arr[j++] = one;\n two = (v & 0x0F) << 4;\n break;\n case 2:\n if (v >= 0) {\n two = two | (v >> 2);\n arr[j++] = two;\n three = (v & 0x03) << 6;\n }\n break;\n case 3:\n if (v >= 0) {\n arr[j++] = three | v;\n }\n break;\n }\n }\n return arr;\n};\n"]} |
@ -0,0 +1,369 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var IdMap = Package['id-map'].IdMap; |
||||
|
||||
/* Package-scope variables */ |
||||
var MaxHeap, MinHeap, MinMaxHeap; |
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/binary-heap/max-heap.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constructor of Heap // 1
|
||||
// - comparator - Function - given two items returns a number // 2
|
||||
// - options: // 3
|
||||
// - initData - Array - Optional - the initial data in a format: // 4
|
||||
// Object: // 5
|
||||
// - id - String - unique id of the item // 6
|
||||
// - value - Any - the data value // 7
|
||||
// each value is retained // 8
|
||||
// - IdMap - Constructor - Optional - custom IdMap class to store id->index // 9
|
||||
// mappings internally. Standard IdMap is used by default. // 10
|
||||
MaxHeap = function (comparator, options) { // 11
|
||||
if (! _.isFunction(comparator)) // 12
|
||||
throw new Error('Passed comparator is invalid, should be a comparison function'); // 13
|
||||
var self = this; // 14
|
||||
// 15
|
||||
// a C-style comparator that is given two values and returns a number, // 16
|
||||
// negative if the first value is less than the second, positive if the second // 17
|
||||
// value is greater than the first and zero if they are equal. // 18
|
||||
self._comparator = comparator; // 19
|
||||
// 20
|
||||
options = _.defaults(options || {}, { IdMap: IdMap }); // 21
|
||||
// 22
|
||||
// _heapIdx maps an id to an index in the Heap array the corresponding value // 23
|
||||
// is located on. // 24
|
||||
self._heapIdx = new options.IdMap; // 25
|
||||
// 26
|
||||
// The Heap data-structure implemented as a 0-based contiguous array where // 27
|
||||
// every item on index idx is a node in a complete binary tree. Every node can // 28
|
||||
// have children on indexes idx*2+1 and idx*2+2, except for the leaves. Every // 29
|
||||
// node has a parent on index (idx-1)/2; // 30
|
||||
self._heap = []; // 31
|
||||
// 32
|
||||
// If the initial array is passed, we can build the heap in linear time // 33
|
||||
// complexity (O(N)) compared to linearithmic time complexity (O(nlogn)) if // 34
|
||||
// we push elements one by one. // 35
|
||||
if (_.isArray(options.initData)) // 36
|
||||
self._initFromData(options.initData); // 37
|
||||
}; // 38
|
||||
// 39
|
||||
_.extend(MaxHeap.prototype, { // 40
|
||||
// Builds a new heap in-place in linear time based on passed data // 41
|
||||
_initFromData: function (data) { // 42
|
||||
var self = this; // 43
|
||||
// 44
|
||||
self._heap = _.map(data, function (o) { // 45
|
||||
return { id: o.id, value: o.value }; // 46
|
||||
}); // 47
|
||||
// 48
|
||||
_.each(data, function (o, i) { // 49
|
||||
self._heapIdx.set(o.id, i); // 50
|
||||
}); // 51
|
||||
// 52
|
||||
if (! data.length) // 53
|
||||
return; // 54
|
||||
// 55
|
||||
// start from the first non-leaf - the parent of the last leaf // 56
|
||||
for (var i = parentIdx(data.length - 1); i >= 0; i--) // 57
|
||||
self._downHeap(i); // 58
|
||||
}, // 59
|
||||
// 60
|
||||
_downHeap: function (idx) { // 61
|
||||
var self = this; // 62
|
||||
// 63
|
||||
while (leftChildIdx(idx) < self.size()) { // 64
|
||||
var left = leftChildIdx(idx); // 65
|
||||
var right = rightChildIdx(idx); // 66
|
||||
var largest = idx; // 67
|
||||
// 68
|
||||
if (left < self.size()) { // 69
|
||||
largest = self._maxIndex(largest, left); // 70
|
||||
} // 71
|
||||
if (right < self.size()) { // 72
|
||||
largest = self._maxIndex(largest, right); // 73
|
||||
} // 74
|
||||
// 75
|
||||
if (largest === idx) // 76
|
||||
break; // 77
|
||||
// 78
|
||||
self._swap(largest, idx); // 79
|
||||
idx = largest; // 80
|
||||
} // 81
|
||||
}, // 82
|
||||
// 83
|
||||
_upHeap: function (idx) { // 84
|
||||
var self = this; // 85
|
||||
// 86
|
||||
while (idx > 0) { // 87
|
||||
var parent = parentIdx(idx); // 88
|
||||
if (self._maxIndex(parent, idx) === idx) { // 89
|
||||
self._swap(parent, idx) // 90
|
||||
idx = parent; // 91
|
||||
} else { // 92
|
||||
break; // 93
|
||||
} // 94
|
||||
} // 95
|
||||
}, // 96
|
||||
// 97
|
||||
_maxIndex: function (idxA, idxB) { // 98
|
||||
var self = this; // 99
|
||||
var valueA = self._get(idxA); // 100
|
||||
var valueB = self._get(idxB); // 101
|
||||
return self._comparator(valueA, valueB) >= 0 ? idxA : idxB; // 102
|
||||
}, // 103
|
||||
// 104
|
||||
// Internal: gets raw data object placed on idxth place in heap // 105
|
||||
_get: function (idx) { // 106
|
||||
var self = this; // 107
|
||||
return self._heap[idx].value; // 108
|
||||
}, // 109
|
||||
// 110
|
||||
_swap: function (idxA, idxB) { // 111
|
||||
var self = this; // 112
|
||||
var recA = self._heap[idxA]; // 113
|
||||
var recB = self._heap[idxB]; // 114
|
||||
// 115
|
||||
self._heapIdx.set(recA.id, idxB); // 116
|
||||
self._heapIdx.set(recB.id, idxA); // 117
|
||||
// 118
|
||||
self._heap[idxA] = recB; // 119
|
||||
self._heap[idxB] = recA; // 120
|
||||
}, // 121
|
||||
// 122
|
||||
get: function (id) { // 123
|
||||
var self = this; // 124
|
||||
if (! self.has(id)) // 125
|
||||
return null; // 126
|
||||
return self._get(self._heapIdx.get(id)); // 127
|
||||
}, // 128
|
||||
set: function (id, value) { // 129
|
||||
var self = this; // 130
|
||||
// 131
|
||||
if (self.has(id)) { // 132
|
||||
if (self.get(id) === value) // 133
|
||||
return; // 134
|
||||
// 135
|
||||
var idx = self._heapIdx.get(id); // 136
|
||||
self._heap[idx].value = value; // 137
|
||||
// 138
|
||||
// Fix the new value's position // 139
|
||||
// Either bubble new value up if it is greater than its parent // 140
|
||||
self._upHeap(idx); // 141
|
||||
// or bubble it down if it is smaller than one of its children // 142
|
||||
self._downHeap(idx); // 143
|
||||
} else { // 144
|
||||
self._heapIdx.set(id, self._heap.length); // 145
|
||||
self._heap.push({ id: id, value: value }); // 146
|
||||
self._upHeap(self._heap.length - 1); // 147
|
||||
} // 148
|
||||
}, // 149
|
||||
remove: function (id) { // 150
|
||||
var self = this; // 151
|
||||
// 152
|
||||
if (self.has(id)) { // 153
|
||||
var last = self._heap.length - 1; // 154
|
||||
var idx = self._heapIdx.get(id); // 155
|
||||
// 156
|
||||
if (idx !== last) { // 157
|
||||
self._swap(idx, last); // 158
|
||||
self._heap.pop(); // 159
|
||||
self._heapIdx.remove(id); // 160
|
||||
// 161
|
||||
// Fix the swapped value's position // 162
|
||||
self._upHeap(idx); // 163
|
||||
self._downHeap(idx); // 164
|
||||
} else { // 165
|
||||
self._heap.pop(); // 166
|
||||
self._heapIdx.remove(id); // 167
|
||||
} // 168
|
||||
} // 169
|
||||
}, // 170
|
||||
has: function (id) { // 171
|
||||
var self = this; // 172
|
||||
return self._heapIdx.has(id); // 173
|
||||
}, // 174
|
||||
empty: function () { // 175
|
||||
var self = this; // 176
|
||||
return !self.size(); // 177
|
||||
}, // 178
|
||||
clear: function () { // 179
|
||||
var self = this; // 180
|
||||
self._heap = []; // 181
|
||||
self._heapIdx.clear(); // 182
|
||||
}, // 183
|
||||
// iterate over values in no particular order // 184
|
||||
forEach: function (iterator) { // 185
|
||||
var self = this; // 186
|
||||
_.each(self._heap, function (obj) { // 187
|
||||
return iterator(obj.value, obj.id); // 188
|
||||
}); // 189
|
||||
}, // 190
|
||||
size: function () { // 191
|
||||
var self = this; // 192
|
||||
return self._heap.length; // 193
|
||||
}, // 194
|
||||
setDefault: function (id, def) { // 195
|
||||
var self = this; // 196
|
||||
if (self.has(id)) // 197
|
||||
return self.get(id); // 198
|
||||
self.set(id, def); // 199
|
||||
return def; // 200
|
||||
}, // 201
|
||||
clone: function () { // 202
|
||||
var self = this; // 203
|
||||
var clone = new MaxHeap(self._comparator, self._heap); // 204
|
||||
return clone; // 205
|
||||
}, // 206
|
||||
// 207
|
||||
maxElementId: function () { // 208
|
||||
var self = this; // 209
|
||||
return self.size() ? self._heap[0].id : null; // 210
|
||||
}, // 211
|
||||
// 212
|
||||
_selfCheck: function () { // 213
|
||||
var self = this; // 214
|
||||
for (var i = 1; i < self._heap.length; i++) // 215
|
||||
if (self._maxIndex(parentIdx(i), i) !== parentIdx(i)) // 216
|
||||
throw new Error("An item with id " + self._heap[i].id + // 217
|
||||
" has a parent younger than it: " + // 218
|
||||
self._heap[parentIdx(i)].id); // 219
|
||||
} // 220
|
||||
}); // 221
|
||||
// 222
|
||||
function leftChildIdx (i) { return i * 2 + 1; } // 223
|
||||
function rightChildIdx (i) { return i * 2 + 2; } // 224
|
||||
function parentIdx (i) { return (i - 1) >> 1; } // 225
|
||||
// 226
|
||||
// 227
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/binary-heap/min-heap.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
MinHeap = function (comparator, options) { // 1
|
||||
var self = this; // 2
|
||||
MaxHeap.call(self, function (a, b) { // 3
|
||||
return -comparator(a, b); // 4
|
||||
}, options); // 5
|
||||
}; // 6
|
||||
// 7
|
||||
Meteor._inherits(MinHeap, MaxHeap); // 8
|
||||
// 9
|
||||
_.extend(MinHeap.prototype, { // 10
|
||||
maxElementId: function () { // 11
|
||||
throw new Error("Cannot call maxElementId on MinHeap"); // 12
|
||||
}, // 13
|
||||
minElementId: function () { // 14
|
||||
var self = this; // 15
|
||||
return MaxHeap.prototype.maxElementId.call(self); // 16
|
||||
} // 17
|
||||
}); // 18
|
||||
// 19
|
||||
// 20
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/binary-heap/min-max-heap.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This implementation of Min/Max-Heap is just a subclass of Max-Heap // 1
|
||||
// with a Min-Heap as an encapsulated property. // 2
|
||||
// // 3
|
||||
// Most of the operations are just proxy methods to call the same method on both // 4
|
||||
// heaps. // 5
|
||||
// // 6
|
||||
// This implementation takes 2*N memory but is fairly simple to write and // 7
|
||||
// understand. And the constant factor of a simple Heap is usually smaller // 8
|
||||
// compared to other two-way priority queues like Min/Max Heaps // 9
|
||||
// (http://www.cs.otago.ac.nz/staffpriv/mike/Papers/MinMaxHeaps/MinMaxHeaps.pdf) // 10
|
||||
// and Interval Heaps // 11
|
||||
// (http://www.cise.ufl.edu/~sahni/dsaac/enrich/c13/double.htm) // 12
|
||||
MinMaxHeap = function (comparator, options) { // 13
|
||||
var self = this; // 14
|
||||
// 15
|
||||
MaxHeap.call(self, comparator, options); // 16
|
||||
self._minHeap = new MinHeap(comparator, options); // 17
|
||||
}; // 18
|
||||
// 19
|
||||
Meteor._inherits(MinMaxHeap, MaxHeap); // 20
|
||||
// 21
|
||||
_.extend(MinMaxHeap.prototype, { // 22
|
||||
set: function (id, value) { // 23
|
||||
var self = this; // 24
|
||||
MaxHeap.prototype.set.apply(self, arguments); // 25
|
||||
self._minHeap.set(id, value); // 26
|
||||
}, // 27
|
||||
remove: function (id) { // 28
|
||||
var self = this; // 29
|
||||
MaxHeap.prototype.remove.apply(self, arguments); // 30
|
||||
self._minHeap.remove(id); // 31
|
||||
}, // 32
|
||||
clear: function () { // 33
|
||||
var self = this; // 34
|
||||
MaxHeap.prototype.clear.apply(self, arguments); // 35
|
||||
self._minHeap.clear(); // 36
|
||||
}, // 37
|
||||
setDefault: function (id, def) { // 38
|
||||
var self = this; // 39
|
||||
MaxHeap.prototype.setDefault.apply(self, arguments); // 40
|
||||
return self._minHeap.setDefault(id, def); // 41
|
||||
}, // 42
|
||||
clone: function () { // 43
|
||||
var self = this; // 44
|
||||
var clone = new MinMaxHeap(self._comparator, self._heap); // 45
|
||||
return clone; // 46
|
||||
}, // 47
|
||||
minElementId: function () { // 48
|
||||
var self = this; // 49
|
||||
return self._minHeap.minElementId(); // 50
|
||||
} // 51
|
||||
}); // 52
|
||||
// 53
|
||||
// 54
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['binary-heap'] = { |
||||
MaxHeap: MaxHeap, |
||||
MinHeap: MinHeap, |
||||
MinMaxHeap: MinMaxHeap |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=binary-heap.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,403 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var HTML = Package.htmljs.HTML; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var BlazeTools, toJSLiteral, toObjectLiteralKey, ToJSVisitor; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/blaze-tools/preamble.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
BlazeTools = {}; // 1
|
||||
// 2
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/blaze-tools/tokens.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 1
|
||||
// Adapted from source code of http://xregexp.com/plugins/#unicode // 2
|
||||
var unicodeCategories = { // 3
|
||||
Ll: "0061-007A00B500DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1D2B1D6B-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7B2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7FAFB00-FB06FB13-FB17FF41-FF5A", |
||||
Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D6A1D781D9B-1DBF2071207F2090-209C2C7C2C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A7F8A7F9A9CFAA70AADDAAF3AAF4FF70FF9EFF9F", |
||||
Lo: "00AA00BA01BB01C0-01C3029405D0-05EA05F0-05F20620-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150840-085808A008A2-08AC0904-0939093D09500958-09610972-09770979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA10FD-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF11CF51CF62135-21382D30-2D672D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCAAE0-AAEAAAF2AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", |
||||
Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", // 7
|
||||
Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A", |
||||
Mc: "0903093B093E-09400949-094C094E094F0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1BAC1BAD1BE71BEA-1BEC1BEE1BF21BF31C24-1C2B1C341C351CE11CF21CF3302E302FA823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BAAEBAAEEAAEFAAF5ABE3ABE4ABE6ABE7ABE9ABEAABEC", |
||||
Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0902093A093C0941-0948094D0951-095709620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F8D-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135D-135F1712-17141732-1734175217531772177317B417B517B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91BAB1BE61BE81BE91BED1BEF-1BF11C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF20D0-20DC20E120E5-20F02CEF-2CF12D7F2DE0-2DFF302A-302D3099309AA66FA674-A67DA69FA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAECAAEDAAF6ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", |
||||
Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19D91A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", |
||||
Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", // 12
|
||||
Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F" // 13
|
||||
}; // 14
|
||||
// 15
|
||||
var unicodeClass = function (abbrev) { // 16
|
||||
return '[' + // 17
|
||||
unicodeCategories[abbrev].replace(/[0-9A-F]{4}/ig, "\\u$&") + ']'; // 18
|
||||
}; // 19
|
||||
// 20
|
||||
// See ECMA-262 spec, 3rd edition, Section 7.6 // 21
|
||||
// Match one or more characters that can start an identifier. // 22
|
||||
// This is IdentifierStart+. // 23
|
||||
var rIdentifierPrefix = new RegExp( // 24
|
||||
"^([a-zA-Z$_]+|\\\\u[0-9a-fA-F]{4}|" + // 25
|
||||
[unicodeClass('Lu'), unicodeClass('Ll'), unicodeClass('Lt'), // 26
|
||||
unicodeClass('Lm'), unicodeClass('Lo'), unicodeClass('Nl')].join('|') + // 27
|
||||
")+"); // 28
|
||||
// Match one or more characters that can continue an identifier. // 29
|
||||
// This is (IdentifierPart and not IdentifierStart)+. // 30
|
||||
// To match a full identifier, match rIdentifierPrefix, then // 31
|
||||
// match rIdentifierMiddle followed by rIdentifierPrefix until they both fail. // 32
|
||||
var rIdentifierMiddle = new RegExp( // 33
|
||||
"^([0-9]|" + [unicodeClass('Mn'), unicodeClass('Mc'), unicodeClass('Nd'), // 34
|
||||
unicodeClass('Pc')].join('|') + ")+"); // 35
|
||||
// 36
|
||||
// 37
|
||||
// See ECMA-262 spec, 3rd edition, Section 7.8.3 // 38
|
||||
var rHexLiteral = /^0[xX][0-9a-fA-F]+(?!\w)/; // 39
|
||||
var rDecLiteral = // 40
|
||||
/^(((0|[1-9][0-9]*)(\.[0-9]*)?)|\.[0-9]+)([Ee][+-]?[0-9]+)?(?!\w)/; // 41
|
||||
// 42
|
||||
// Section 7.8.4 // 43
|
||||
var rStringQuote = /^["']/; // 44
|
||||
// Match one or more characters besides quotes, backslashes, or line ends // 45
|
||||
var rStringMiddle = /^(?=.)[^"'\\]+?((?!.)|(?=["'\\]))/; // 46
|
||||
// Match one escape sequence, including the backslash. // 47
|
||||
var rEscapeSequence = // 48
|
||||
/^\\(['"\\bfnrtv]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|(?=.)[^ux0-9])/; // 49
|
||||
// Match one ES5 line continuation // 50
|
||||
var rLineContinuation = // 51
|
||||
/^\\(\r\n|[\u000A\u000D\u2028\u2029])/; // 52
|
||||
// 53
|
||||
// 54
|
||||
BlazeTools.parseNumber = function (scanner) { // 55
|
||||
var startPos = scanner.pos; // 56
|
||||
// 57
|
||||
var isNegative = false; // 58
|
||||
if (scanner.peek() === '-') { // 59
|
||||
scanner.pos++; // 60
|
||||
isNegative = true; // 61
|
||||
} // 62
|
||||
// Note that we allow `"-0xa"`, unlike `Number(...)`. // 63
|
||||
// 64
|
||||
var rest = scanner.rest(); // 65
|
||||
var match = rDecLiteral.exec(rest) || rHexLiteral.exec(rest); // 66
|
||||
if (! match) { // 67
|
||||
scanner.pos = startPos; // 68
|
||||
return null; // 69
|
||||
} // 70
|
||||
var matchText = match[0]; // 71
|
||||
scanner.pos += matchText.length; // 72
|
||||
// 73
|
||||
var text = (isNegative ? '-' : '') + matchText; // 74
|
||||
var value = Number(matchText); // 75
|
||||
value = (isNegative ? -value : value); // 76
|
||||
return { text: text, value: value }; // 77
|
||||
}; // 78
|
||||
// 79
|
||||
BlazeTools.parseIdentifierName = function (scanner) { // 80
|
||||
var startPos = scanner.pos; // 81
|
||||
var rest = scanner.rest(); // 82
|
||||
var match = rIdentifierPrefix.exec(rest); // 83
|
||||
if (! match) // 84
|
||||
return null; // 85
|
||||
scanner.pos += match[0].length; // 86
|
||||
rest = scanner.rest(); // 87
|
||||
var foundMore = true; // 88
|
||||
// 89
|
||||
while (foundMore) { // 90
|
||||
foundMore = false; // 91
|
||||
// 92
|
||||
match = rIdentifierMiddle.exec(rest); // 93
|
||||
if (match) { // 94
|
||||
foundMore = true; // 95
|
||||
scanner.pos += match[0].length; // 96
|
||||
rest = scanner.rest(); // 97
|
||||
} // 98
|
||||
// 99
|
||||
match = rIdentifierPrefix.exec(rest); // 100
|
||||
if (match) { // 101
|
||||
foundMore = true; // 102
|
||||
scanner.pos += match[0].length; // 103
|
||||
rest = scanner.rest(); // 104
|
||||
} // 105
|
||||
} // 106
|
||||
// 107
|
||||
return scanner.input.substring(startPos, scanner.pos); // 108
|
||||
}; // 109
|
||||
// 110
|
||||
BlazeTools.parseStringLiteral = function (scanner) { // 111
|
||||
var startPos = scanner.pos; // 112
|
||||
var rest = scanner.rest(); // 113
|
||||
var match = rStringQuote.exec(rest); // 114
|
||||
if (! match) // 115
|
||||
return null; // 116
|
||||
// 117
|
||||
var quote = match[0]; // 118
|
||||
scanner.pos++; // 119
|
||||
rest = scanner.rest(); // 120
|
||||
// 121
|
||||
var jsonLiteral = '"'; // 122
|
||||
// 123
|
||||
while (match) { // 124
|
||||
match = rStringMiddle.exec(rest); // 125
|
||||
if (match) { // 126
|
||||
jsonLiteral += match[0]; // 127
|
||||
} else { // 128
|
||||
match = rEscapeSequence.exec(rest); // 129
|
||||
if (match) { // 130
|
||||
var esc = match[0]; // 131
|
||||
// Convert all string escapes to JSON-compatible string escapes, so we // 132
|
||||
// can use JSON.parse for some of the work. JSON strings are not the // 133
|
||||
// same as JS strings. They don't support `\0`, `\v`, `\'`, or hex // 134
|
||||
// escapes. // 135
|
||||
if (esc === '\\0') // 136
|
||||
jsonLiteral += '\\u0000'; // 137
|
||||
else if (esc === '\\v') // 138
|
||||
// Note: IE 8 doesn't correctly parse '\v' in JavaScript. // 139
|
||||
jsonLiteral += '\\u000b'; // 140
|
||||
else if (esc.charAt(1) === 'x') // 141
|
||||
jsonLiteral += '\\u00' + esc.slice(2); // 142
|
||||
else if (esc === '\\\'') // 143
|
||||
jsonLiteral += "'"; // 144
|
||||
else // 145
|
||||
jsonLiteral += esc; // 146
|
||||
} else { // 147
|
||||
match = rLineContinuation.exec(rest); // 148
|
||||
if (! match) { // 149
|
||||
match = rStringQuote.exec(rest); // 150
|
||||
if (match) { // 151
|
||||
var c = match[0]; // 152
|
||||
if (c !== quote) { // 153
|
||||
if (c === '"') // 154
|
||||
jsonLiteral += '\\'; // 155
|
||||
jsonLiteral += c; // 156
|
||||
} // 157
|
||||
} // 158
|
||||
} // 159
|
||||
} // 160
|
||||
} // 161
|
||||
if (match) { // 162
|
||||
scanner.pos += match[0].length; // 163
|
||||
rest = scanner.rest(); // 164
|
||||
if (match[0] === quote) // 165
|
||||
break; // 166
|
||||
} // 167
|
||||
} // 168
|
||||
// 169
|
||||
if (match[0] !== quote) // 170
|
||||
scanner.fatal("Unterminated string literal"); // 171
|
||||
// 172
|
||||
jsonLiteral += '"'; // 173
|
||||
var text = scanner.input.substring(startPos, scanner.pos); // 174
|
||||
var value = JSON.parse(jsonLiteral); // 175
|
||||
return { text: text, value: value }; // 176
|
||||
}; // 177
|
||||
// 178
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/blaze-tools/tojs.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 1
|
||||
BlazeTools.EmitCode = function (value) { // 2
|
||||
if (! (this instanceof BlazeTools.EmitCode)) // 3
|
||||
// called without `new` // 4
|
||||
return new BlazeTools.EmitCode(value); // 5
|
||||
// 6
|
||||
if (typeof value !== 'string') // 7
|
||||
throw new Error('BlazeTools.EmitCode must be constructed with a string'); // 8
|
||||
// 9
|
||||
this.value = value; // 10
|
||||
}; // 11
|
||||
BlazeTools.EmitCode.prototype.toJS = function (visitor) { // 12
|
||||
return this.value; // 13
|
||||
}; // 14
|
||||
// 15
|
||||
// Turns any JSONable value into a JavaScript literal. // 16
|
||||
toJSLiteral = function (obj) { // 17
|
||||
// See <http://timelessrepo.com/json-isnt-a-javascript-subset> for `\u2028\u2029`. // 18
|
||||
// Also escape Unicode surrogates. // 19
|
||||
return (JSON.stringify(obj) // 20
|
||||
.replace(/[\u2028\u2029\ud800-\udfff]/g, function (c) { // 21
|
||||
return '\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4); // 22
|
||||
})); // 23
|
||||
}; // 24
|
||||
BlazeTools.toJSLiteral = toJSLiteral; // 25
|
||||
// 26
|
||||
// 27
|
||||
// 28
|
||||
var jsReservedWordSet = (function (set) { // 29
|
||||
_.each("abstract else instanceof super boolean enum int switch break export interface synchronized byte extends let this case false long throw catch final native throws char finally new transient class float null true const for package try continue function private typeof debugger goto protected var default if public void delete implements return volatile do import short while double in static with".split(' '), function (w) { |
||||
set[w] = 1; // 31
|
||||
}); // 32
|
||||
return set; // 33
|
||||
})({}); // 34
|
||||
// 35
|
||||
toObjectLiteralKey = function (k) { // 36
|
||||
if (/^[a-zA-Z$_][a-zA-Z$0-9_]*$/.test(k) && jsReservedWordSet[k] !== 1) // 37
|
||||
return k; // 38
|
||||
return toJSLiteral(k); // 39
|
||||
}; // 40
|
||||
BlazeTools.toObjectLiteralKey = toObjectLiteralKey; // 41
|
||||
// 42
|
||||
var hasToJS = function (x) { // 43
|
||||
return x.toJS && (typeof (x.toJS) === 'function'); // 44
|
||||
}; // 45
|
||||
// 46
|
||||
ToJSVisitor = HTML.Visitor.extend(); // 47
|
||||
ToJSVisitor.def({ // 48
|
||||
visitNull: function (nullOrUndefined) { // 49
|
||||
return 'null'; // 50
|
||||
}, // 51
|
||||
visitPrimitive: function (stringBooleanOrNumber) { // 52
|
||||
return toJSLiteral(stringBooleanOrNumber); // 53
|
||||
}, // 54
|
||||
visitArray: function (array) { // 55
|
||||
var parts = []; // 56
|
||||
for (var i = 0; i < array.length; i++) // 57
|
||||
parts.push(this.visit(array[i])); // 58
|
||||
return '[' + parts.join(', ') + ']'; // 59
|
||||
}, // 60
|
||||
visitTag: function (tag) { // 61
|
||||
return this.generateCall(tag.tagName, tag.attrs, tag.children); // 62
|
||||
}, // 63
|
||||
visitComment: function (comment) { // 64
|
||||
return this.generateCall('HTML.Comment', null, [comment.value]); // 65
|
||||
}, // 66
|
||||
visitCharRef: function (charRef) { // 67
|
||||
return this.generateCall('HTML.CharRef', // 68
|
||||
{html: charRef.html, str: charRef.str}); // 69
|
||||
}, // 70
|
||||
visitRaw: function (raw) { // 71
|
||||
return this.generateCall('HTML.Raw', null, [raw.value]); // 72
|
||||
}, // 73
|
||||
visitObject: function (x) { // 74
|
||||
if (hasToJS(x)) { // 75
|
||||
return x.toJS(this); // 76
|
||||
} // 77
|
||||
// 78
|
||||
throw new Error("Unexpected object in HTMLjs in toJS: " + x); // 79
|
||||
}, // 80
|
||||
generateCall: function (name, attrs, children) { // 81
|
||||
var tagSymbol; // 82
|
||||
if (name.indexOf('.') >= 0) { // 83
|
||||
tagSymbol = name; // 84
|
||||
} else if (HTML.isTagEnsured(name)) { // 85
|
||||
tagSymbol = 'HTML.' + HTML.getSymbolName(name); // 86
|
||||
} else { // 87
|
||||
tagSymbol = 'HTML.getTag(' + toJSLiteral(name) + ')'; // 88
|
||||
} // 89
|
||||
// 90
|
||||
var attrsArray = null; // 91
|
||||
if (attrs) { // 92
|
||||
attrsArray = []; // 93
|
||||
var needsHTMLAttrs = false; // 94
|
||||
if (HTML.isArray(attrs)) { // 95
|
||||
var attrsArray = []; // 96
|
||||
for (var i = 0; i < attrs.length; i++) { // 97
|
||||
var a = attrs[i]; // 98
|
||||
if (hasToJS(a)) { // 99
|
||||
attrsArray.push(a.toJS(this)); // 100
|
||||
needsHTMLAttrs = true; // 101
|
||||
} else { // 102
|
||||
var attrsObjStr = this.generateAttrsDictionary(attrs[i]); // 103
|
||||
if (attrsObjStr !== null) // 104
|
||||
attrsArray.push(attrsObjStr); // 105
|
||||
} // 106
|
||||
} // 107
|
||||
} else if (hasToJS(attrs)) { // 108
|
||||
attrsArray.push(attrs.toJS(this)); // 109
|
||||
needsHTMLAttrs = true; // 110
|
||||
} else { // 111
|
||||
attrsArray.push(this.generateAttrsDictionary(attrs)); // 112
|
||||
} // 113
|
||||
} // 114
|
||||
var attrsStr = null; // 115
|
||||
if (attrsArray && attrsArray.length) { // 116
|
||||
if (attrsArray.length === 1 && ! needsHTMLAttrs) { // 117
|
||||
attrsStr = attrsArray[0]; // 118
|
||||
} else { // 119
|
||||
attrsStr = 'HTML.Attrs(' + attrsArray.join(', ') + ')'; // 120
|
||||
} // 121
|
||||
} // 122
|
||||
// 123
|
||||
var argStrs = []; // 124
|
||||
if (attrsStr !== null) // 125
|
||||
argStrs.push(attrsStr); // 126
|
||||
// 127
|
||||
if (children) { // 128
|
||||
for (var i = 0; i < children.length; i++) // 129
|
||||
argStrs.push(this.visit(children[i])); // 130
|
||||
} // 131
|
||||
// 132
|
||||
return tagSymbol + '(' + argStrs.join(', ') + ')'; // 133
|
||||
}, // 134
|
||||
generateAttrsDictionary: function (attrsDict) { // 135
|
||||
if (attrsDict.toJS && (typeof (attrsDict.toJS) === 'function')) { // 136
|
||||
// not an attrs dictionary, but something else! Like a template tag. // 137
|
||||
return attrsDict.toJS(this); // 138
|
||||
} // 139
|
||||
// 140
|
||||
var kvStrs = []; // 141
|
||||
for (var k in attrsDict) { // 142
|
||||
if (! HTML.isNully(attrsDict[k])) // 143
|
||||
kvStrs.push(toObjectLiteralKey(k) + ': ' + // 144
|
||||
this.visit(attrsDict[k])); // 145
|
||||
} // 146
|
||||
if (kvStrs.length) // 147
|
||||
return '{' + kvStrs.join(', ') + '}'; // 148
|
||||
return null; // 149
|
||||
} // 150
|
||||
}); // 151
|
||||
BlazeTools.ToJSVisitor = ToJSVisitor; // 152
|
||||
// 153
|
||||
BlazeTools.toJS = function (content) { // 154
|
||||
return (new ToJSVisitor).visit(content); // 155
|
||||
}; // 156
|
||||
// 157
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['blaze-tools'] = { |
||||
BlazeTools: BlazeTools |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=blaze-tools.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,141 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var SpacebarsCompiler = Package['spacebars-compiler'].SpacebarsCompiler; |
||||
var Spacebars = Package.spacebars.Spacebars; |
||||
var HTML = Package.htmljs.HTML; |
||||
var Blaze = Package.blaze.Blaze; |
||||
var UI = Package.blaze.UI; |
||||
var Handlebars = Package.blaze.Handlebars; |
||||
|
||||
/* Package-scope variables */ |
||||
var Boilerplate; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/boilerplate-generator/boilerplate-generator.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
var fs = Npm.require('fs'); // 1
|
||||
var path = Npm.require('path'); // 2
|
||||
// 3
|
||||
// Copied from webapp_server // 4
|
||||
var readUtf8FileSync = function (filename) { // 5
|
||||
return Meteor.wrapAsync(fs.readFile)(filename, 'utf8'); // 6
|
||||
}; // 7
|
||||
// 8
|
||||
Boilerplate = function (arch, manifest, options) { // 9
|
||||
var self = this; // 10
|
||||
options = options || {}; // 11
|
||||
self.template = _getTemplate(arch); // 12
|
||||
self.baseData = null; // 13
|
||||
self.func = null; // 14
|
||||
// 15
|
||||
self._generateBoilerplateFromManifestAndSource( // 16
|
||||
manifest, // 17
|
||||
self.template, // 18
|
||||
options // 19
|
||||
); // 20
|
||||
}; // 21
|
||||
// 22
|
||||
// The 'extraData' argument can be used to extend 'self.baseData'. Its // 23
|
||||
// purpose is to allow you to specify data that you might not know at // 24
|
||||
// the time that you construct the Boilerplate object. (e.g. it is used // 25
|
||||
// by 'webapp' to specify data that is only known at request-time). // 26
|
||||
Boilerplate.prototype.toHTML = function (extraData) { // 27
|
||||
var self = this; // 28
|
||||
// 29
|
||||
if (! self.baseData || ! self.func) // 30
|
||||
throw new Error('Boilerplate did not instantiate correctly.'); // 31
|
||||
// 32
|
||||
return "<!DOCTYPE html>\n" + // 33
|
||||
Blaze.toHTML(Blaze.With(_.extend(self.baseData, extraData), // 34
|
||||
self.func)); // 35
|
||||
}; // 36
|
||||
// 37
|
||||
// XXX Exported to allow client-side only changes to rebuild the boilerplate // 38
|
||||
// without requiring a full server restart. // 39
|
||||
// Produces an HTML string with given manifest and boilerplateSource. // 40
|
||||
// Optionally takes urlMapper in case urls from manifest need to be prefixed // 41
|
||||
// or rewritten. // 42
|
||||
// Optionally takes pathMapper for resolving relative file system paths. // 43
|
||||
// Optionally allows to override fields of the data context. // 44
|
||||
Boilerplate.prototype._generateBoilerplateFromManifestAndSource = // 45
|
||||
function (manifest, boilerplateSource, options) { // 46
|
||||
var self = this; // 47
|
||||
// map to the identity by default // 48
|
||||
var urlMapper = options.urlMapper || _.identity; // 49
|
||||
var pathMapper = options.pathMapper || _.identity; // 50
|
||||
// 51
|
||||
var boilerplateBaseData = { // 52
|
||||
css: [], // 53
|
||||
js: [], // 54
|
||||
head: '', // 55
|
||||
body: '', // 56
|
||||
meteorManifest: JSON.stringify(manifest) // 57
|
||||
}; // 58
|
||||
// 59
|
||||
// allow the caller to extend the default base data // 60
|
||||
_.extend(boilerplateBaseData, options.baseDataExtension); // 61
|
||||
// 62
|
||||
_.each(manifest, function (item) { // 63
|
||||
var urlPath = urlMapper(item.url); // 64
|
||||
var itemObj = { url: urlPath }; // 65
|
||||
// 66
|
||||
if (options.inline) { // 67
|
||||
itemObj.scriptContent = readUtf8FileSync( // 68
|
||||
pathMapper(item.path)); // 69
|
||||
itemObj.inline = true; // 70
|
||||
} // 71
|
||||
// 72
|
||||
if (item.type === 'css' && item.where === 'client') { // 73
|
||||
boilerplateBaseData.css.push(itemObj); // 74
|
||||
} // 75
|
||||
if (item.type === 'js' && item.where === 'client') { // 76
|
||||
boilerplateBaseData.js.push(itemObj); // 77
|
||||
} // 78
|
||||
if (item.type === 'head') { // 79
|
||||
boilerplateBaseData.head = // 80
|
||||
readUtf8FileSync(pathMapper(item.path)); // 81
|
||||
} // 82
|
||||
if (item.type === 'body') { // 83
|
||||
boilerplateBaseData.body = // 84
|
||||
readUtf8FileSync(pathMapper(item.path)); // 85
|
||||
} // 86
|
||||
}); // 87
|
||||
var boilerplateRenderCode = SpacebarsCompiler.compile( // 88
|
||||
boilerplateSource, { isBody: true }); // 89
|
||||
// 90
|
||||
// Note that we are actually depending on eval's local environment capture // 91
|
||||
// so that UI and HTML are visible to the eval'd code. // 92
|
||||
// XXX the template we are evaluating relies on the fact that UI is globally // 93
|
||||
// available. // 94
|
||||
global.UI = UI; // 95
|
||||
self.func = eval(boilerplateRenderCode); // 96
|
||||
self.baseData = boilerplateBaseData; // 97
|
||||
}; // 98
|
||||
// 99
|
||||
var _getTemplate = _.memoize(function (arch) { // 100
|
||||
var filename = 'boilerplate_' + arch + '.html'; // 101
|
||||
return Assets.getText(filename); // 102
|
||||
}); // 103
|
||||
// 104
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['boilerplate-generator'] = { |
||||
Boilerplate: Boilerplate |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=boilerplate-generator.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["boilerplate-generator/boilerplate-generator.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,2B;AACA,+B;;AAEA,4B;AACA,4C;AACA,yD;AACA,E;;AAEA,kD;AACA,kB;AACA,0B;AACA,qC;AACA,uB;AACA,mB;;AAEA,iD;AACA,a;AACA,kB;AACA,W;AACA,I;AACA,E;;AAEA,sE;AACA,qE;AACA,uE;AACA,mE;AACA,qD;AACA,kB;;AAEA,qC;AACA,kE;;AAEA,+B;AACA,+D;AACA,wC;AACA,E;;AAEA,4E;AACA,2C;AACA,qE;AACA,4E;AACA,gB;AACA,wE;AACA,4D;AACA,iE;AACA,mD;AACA,oB;AACA,qC;AACA,oD;AACA,sD;;AAEA,+B;AACA,c;AACA,a;AACA,e;AACA,e;AACA,8C;AACA,M;;AAEA,uD;AACA,6D;;AAEA,sC;AACA,wC;AACA,qC;;AAEA,2B;AACA,iD;AACA,iC;AACA,8B;AACA,O;;AAEA,2D;AACA,8C;AACA,O;AACA,0D;AACA,6C;AACA,O;AACA,iC;AACA,kC;AACA,kD;AACA,O;AACA,iC;AACA,kC;AACA,kD;AACA,O;AACA,O;AACA,0D;AACA,2C;;AAEA,8E;AACA,0D;AACA,gF;AACA,mB;AACA,mB;AACA,4C;AACA,wC;AACA,E;;AAEA,8C;AACA,iD;AACA,kC;AACA,G","file":"/packages/boilerplate-generator.js","sourcesContent":["var fs = Npm.require('fs');\nvar path = Npm.require('path');\n\n// Copied from webapp_server\nvar readUtf8FileSync = function (filename) {\n return Meteor.wrapAsync(fs.readFile)(filename, 'utf8');\n};\n\nBoilerplate = function (arch, manifest, options) {\n var self = this;\n options = options || {};\n self.template = _getTemplate(arch);\n self.baseData = null;\n self.func = null;\n\n self._generateBoilerplateFromManifestAndSource(\n manifest,\n self.template,\n options\n );\n};\n\n// The 'extraData' argument can be used to extend 'self.baseData'. Its\n// purpose is to allow you to specify data that you might not know at\n// the time that you construct the Boilerplate object. (e.g. it is used\n// by 'webapp' to specify data that is only known at request-time).\nBoilerplate.prototype.toHTML = function (extraData) {\n var self = this;\n\n if (! self.baseData || ! self.func)\n throw new Error('Boilerplate did not instantiate correctly.');\n\n return \"<!DOCTYPE html>\\n\" +\n Blaze.toHTML(Blaze.With(_.extend(self.baseData, extraData),\n self.func));\n};\n\n// XXX Exported to allow client-side only changes to rebuild the boilerplate\n// without requiring a full server restart.\n// Produces an HTML string with given manifest and boilerplateSource.\n// Optionally takes urlMapper in case urls from manifest need to be prefixed\n// or rewritten.\n// Optionally takes pathMapper for resolving relative file system paths.\n// Optionally allows to override fields of the data context.\nBoilerplate.prototype._generateBoilerplateFromManifestAndSource =\n function (manifest, boilerplateSource, options) {\n var self = this;\n // map to the identity by default\n var urlMapper = options.urlMapper || _.identity;\n var pathMapper = options.pathMapper || _.identity;\n\n var boilerplateBaseData = {\n css: [],\n js: [],\n head: '',\n body: '',\n meteorManifest: JSON.stringify(manifest)\n };\n\n // allow the caller to extend the default base data\n _.extend(boilerplateBaseData, options.baseDataExtension);\n\n _.each(manifest, function (item) {\n var urlPath = urlMapper(item.url);\n var itemObj = { url: urlPath };\n\n if (options.inline) {\n itemObj.scriptContent = readUtf8FileSync(\n pathMapper(item.path));\n itemObj.inline = true;\n }\n\n if (item.type === 'css' && item.where === 'client') {\n boilerplateBaseData.css.push(itemObj);\n }\n if (item.type === 'js' && item.where === 'client') {\n boilerplateBaseData.js.push(itemObj);\n }\n if (item.type === 'head') {\n boilerplateBaseData.head =\n readUtf8FileSync(pathMapper(item.path));\n }\n if (item.type === 'body') {\n boilerplateBaseData.body =\n readUtf8FileSync(pathMapper(item.path));\n }\n });\n var boilerplateRenderCode = SpacebarsCompiler.compile(\n boilerplateSource, { isBody: true });\n\n // Note that we are actually depending on eval's local environment capture\n // so that UI and HTML are visible to the eval'd code.\n // XXX the template we are evaluating relies on the fact that UI is globally\n // available.\n global.UI = UI;\n self.func = eval(boilerplateRenderCode);\n self.baseData = boilerplateBaseData;\n};\n\nvar _getTemplate = _.memoize(function (arch) {\n var filename = 'boilerplate_' + arch + '.html';\n return Assets.getText(filename);\n});\n"]} |
@ -0,0 +1,139 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var Hook; |
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/callback-hook/hook.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX This pattern is under development. Do not add more callsites // 1
|
||||
// using this package for now. See: // 2
|
||||
// https://meteor.hackpad.com/Design-proposal-Hooks-YxvgEW06q6f // 3
|
||||
// // 4
|
||||
// Encapsulates the pattern of registering callbacks on a hook. // 5
|
||||
// // 6
|
||||
// The `each` method of the hook calls its iterator function argument // 7
|
||||
// with each registered callback. This allows the hook to // 8
|
||||
// conditionally decide not to call the callback (if, for example, the // 9
|
||||
// observed object has been closed or terminated). // 10
|
||||
// // 11
|
||||
// Callbacks are bound with `Meteor.bindEnvironment`, so they will be // 12
|
||||
// called with the Meteor environment of the calling code that // 13
|
||||
// registered the callback. // 14
|
||||
// // 15
|
||||
// Registering a callback returns an object with a single `stop` // 16
|
||||
// method which unregisters the callback. // 17
|
||||
// // 18
|
||||
// The code is careful to allow a callback to be safely unregistered // 19
|
||||
// while the callbacks are being iterated over. // 20
|
||||
// // 21
|
||||
// If the hook is configured with the `exceptionHandler` option, the // 22
|
||||
// handler will be called if a called callback throws an exception. // 23
|
||||
// By default (if the exception handler doesn't itself throw an // 24
|
||||
// exception, or if the iterator function doesn't return a falsy value // 25
|
||||
// to terminate the calling of callbacks), the remaining callbacks // 26
|
||||
// will still be called. // 27
|
||||
// // 28
|
||||
// Alternatively, the `debugPrintExceptions` option can be specified // 29
|
||||
// as string describing the callback. On an exception the string and // 30
|
||||
// the exception will be printed to the console log with // 31
|
||||
// `Meteor._debug`, and the exception otherwise ignored. // 32
|
||||
// // 33
|
||||
// If an exception handler isn't specified, exceptions thrown in the // 34
|
||||
// callback will propagate up to the iterator function, and will // 35
|
||||
// terminate calling the remaining callbacks if not caught. // 36
|
||||
// 37
|
||||
Hook = function (options) { // 38
|
||||
var self = this; // 39
|
||||
options = options || {}; // 40
|
||||
self.nextCallbackId = 0; // 41
|
||||
self.callbacks = {}; // 42
|
||||
// 43
|
||||
if (options.exceptionHandler) // 44
|
||||
self.exceptionHandler = options.exceptionHandler; // 45
|
||||
else if (options.debugPrintExceptions) { // 46
|
||||
if (! _.isString(options.debugPrintExceptions)) // 47
|
||||
throw new Error("Hook option debugPrintExceptions should be a string"); // 48
|
||||
self.exceptionHandler = options.debugPrintExceptions; // 49
|
||||
} // 50
|
||||
}; // 51
|
||||
// 52
|
||||
_.extend(Hook.prototype, { // 53
|
||||
register: function (callback) { // 54
|
||||
var self = this; // 55
|
||||
// 56
|
||||
callback = Meteor.bindEnvironment( // 57
|
||||
callback, // 58
|
||||
self.exceptionHandler || function (exception) { // 59
|
||||
// Note: this relies on the undocumented fact that if bindEnvironment's // 60
|
||||
// onException throws, and you are invoking the callback either in the // 61
|
||||
// browser or from within a Fiber in Node, the exception is propagated. // 62
|
||||
throw exception; // 63
|
||||
} // 64
|
||||
); // 65
|
||||
// 66
|
||||
var id = self.nextCallbackId++; // 67
|
||||
self.callbacks[id] = callback; // 68
|
||||
// 69
|
||||
return { // 70
|
||||
stop: function () { // 71
|
||||
delete self.callbacks[id]; // 72
|
||||
} // 73
|
||||
}; // 74
|
||||
}, // 75
|
||||
// 76
|
||||
// For each registered callback, call the passed iterator function // 77
|
||||
// with the callback. // 78
|
||||
// // 79
|
||||
// The iterator function can choose whether or not to call the // 80
|
||||
// callback. (For example, it might not call the callback if the // 81
|
||||
// observed object has been closed or terminated). // 82
|
||||
// // 83
|
||||
// The iteration is stopped if the iterator function returns a falsy // 84
|
||||
// value or throws an exception. // 85
|
||||
// // 86
|
||||
each: function (iterator) { // 87
|
||||
var self = this; // 88
|
||||
// 89
|
||||
// Invoking bindEnvironment'd callbacks outside of a Fiber in Node doesn't // 90
|
||||
// run them to completion (and exceptions thrown from onException are not // 91
|
||||
// propagated), so we need to be in a Fiber. // 92
|
||||
Meteor._nodeCodeMustBeInFiber(); // 93
|
||||
// 94
|
||||
var ids = _.keys(self.callbacks); // 95
|
||||
for (var i = 0; i < ids.length; ++i) { // 96
|
||||
var id = ids[i]; // 97
|
||||
// check to see if the callback was removed during iteration // 98
|
||||
if (_.has(self.callbacks, id)) { // 99
|
||||
var callback = self.callbacks[id]; // 100
|
||||
// 101
|
||||
if (! iterator(callback)) // 102
|
||||
break; // 103
|
||||
} // 104
|
||||
} // 105
|
||||
} // 106
|
||||
}); // 107
|
||||
// 108
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['callback-hook'] = { |
||||
Hook: Hook |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=callback-hook.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["callback-hook/hook.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,mE;AACA,mC;AACA,+D;AACA,E;AACA,+D;AACA,E;AACA,qE;AACA,0D;AACA,sE;AACA,kD;AACA,E;AACA,qE;AACA,8D;AACA,2B;AACA,E;AACA,gE;AACA,yC;AACA,E;AACA,oE;AACA,+C;AACA,E;AACA,oE;AACA,mE;AACA,+D;AACA,sE;AACA,kE;AACA,wB;AACA,E;AACA,oE;AACA,qE;AACA,wD;AACA,wD;AACA,E;AACA,oE;AACA,gE;AACA,2D;;AAEA,2B;AACA,kB;AACA,0B;AACA,0B;AACA,sB;;AAEA,+B;AACA,qD;AACA,0C;AACA,mD;AACA,6E;AACA,yD;AACA,G;AACA,E;;AAEA,0B;AACA,iC;AACA,oB;;AAEA,sC;AACA,e;AACA,qD;AACA,+E;AACA,8E;AACA,+E;AACA,wB;AACA,O;AACA,M;;AAEA,mC;AACA,kC;;AAEA,Y;AACA,yB;AACA,kC;AACA,O;AACA,M;AACA,I;;AAEA,oE;AACA,uB;AACA,I;AACA,gE;AACA,mE;AACA,oD;AACA,I;AACA,sE;AACA,kC;AACA,I;AACA,6B;AACA,oB;;AAEA,8E;AACA,6E;AACA,gD;AACA,oC;;AAEA,qC;AACA,4C;AACA,sB;AACA,kE;AACA,sC;AACA,0C;;AAEA,iC;AACA,gB;AACA,O;AACA,K;AACA,G;AACA,G","file":"/packages/callback-hook.js","sourcesContent":["// XXX This pattern is under development. Do not add more callsites\n// using this package for now. See:\n// https://meteor.hackpad.com/Design-proposal-Hooks-YxvgEW06q6f\n//\n// Encapsulates the pattern of registering callbacks on a hook.\n//\n// The `each` method of the hook calls its iterator function argument\n// with each registered callback. This allows the hook to\n// conditionally decide not to call the callback (if, for example, the\n// observed object has been closed or terminated).\n//\n// Callbacks are bound with `Meteor.bindEnvironment`, so they will be\n// called with the Meteor environment of the calling code that\n// registered the callback.\n//\n// Registering a callback returns an object with a single `stop`\n// method which unregisters the callback.\n//\n// The code is careful to allow a callback to be safely unregistered\n// while the callbacks are being iterated over.\n//\n// If the hook is configured with the `exceptionHandler` option, the\n// handler will be called if a called callback throws an exception.\n// By default (if the exception handler doesn't itself throw an\n// exception, or if the iterator function doesn't return a falsy value\n// to terminate the calling of callbacks), the remaining callbacks\n// will still be called.\n//\n// Alternatively, the `debugPrintExceptions` option can be specified\n// as string describing the callback. On an exception the string and\n// the exception will be printed to the console log with\n// `Meteor._debug`, and the exception otherwise ignored.\n//\n// If an exception handler isn't specified, exceptions thrown in the\n// callback will propagate up to the iterator function, and will\n// terminate calling the remaining callbacks if not caught.\n\nHook = function (options) {\n var self = this;\n options = options || {};\n self.nextCallbackId = 0;\n self.callbacks = {};\n\n if (options.exceptionHandler)\n self.exceptionHandler = options.exceptionHandler;\n else if (options.debugPrintExceptions) {\n if (! _.isString(options.debugPrintExceptions))\n throw new Error(\"Hook option debugPrintExceptions should be a string\");\n self.exceptionHandler = options.debugPrintExceptions;\n }\n};\n\n_.extend(Hook.prototype, {\n register: function (callback) {\n var self = this;\n\n callback = Meteor.bindEnvironment(\n callback,\n self.exceptionHandler || function (exception) {\n // Note: this relies on the undocumented fact that if bindEnvironment's\n // onException throws, and you are invoking the callback either in the\n // browser or from within a Fiber in Node, the exception is propagated.\n throw exception;\n }\n );\n\n var id = self.nextCallbackId++;\n self.callbacks[id] = callback;\n\n return {\n stop: function () {\n delete self.callbacks[id];\n }\n };\n },\n\n // For each registered callback, call the passed iterator function\n // with the callback.\n //\n // The iterator function can choose whether or not to call the\n // callback. (For example, it might not call the callback if the\n // observed object has been closed or terminated).\n //\n // The iteration is stopped if the iterator function returns a falsy\n // value or throws an exception.\n //\n each: function (iterator) {\n var self = this;\n\n // Invoking bindEnvironment'd callbacks outside of a Fiber in Node doesn't\n // run them to completion (and exceptions thrown from onException are not\n // propagated), so we need to be in a Fiber.\n Meteor._nodeCodeMustBeInFiber();\n\n var ids = _.keys(self.callbacks);\n for (var i = 0; i < ids.length; ++i) {\n var id = ids[i];\n // check to see if the callback was removed during iteration\n if (_.has(self.callbacks, id)) {\n var callback = self.callbacks[id];\n\n if (! iterator(callback))\n break;\n }\n }\n }\n});\n"]} |
@ -0,0 +1,416 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var EJSON = Package.ejson.EJSON; |
||||
|
||||
/* Package-scope variables */ |
||||
var check, Match; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/check/match.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX docs // 1
|
||||
// 2
|
||||
// Things we explicitly do NOT support: // 3
|
||||
// - heterogenous arrays // 4
|
||||
// 5
|
||||
var currentArgumentChecker = new Meteor.EnvironmentVariable; // 6
|
||||
// 7
|
||||
/** // 8 |
||||
* @summary Check that a value matches a [pattern](#matchpatterns). // 9
|
||||
* If the value does not match the pattern, throw a `Match.Error`. // 10
|
||||
* // 11
|
||||
* Particularly useful to assert that arguments to a function have the right // 12
|
||||
* types and structure. // 13
|
||||
* @locus Anywhere // 14
|
||||
* @param {Any} value The value to check // 15
|
||||
* @param {MatchPattern} pattern The pattern to match // 16
|
||||
* `value` against // 17
|
||||
*/ // 18 |
||||
check = function (value, pattern) { // 19
|
||||
// Record that check got called, if somebody cared. // 20
|
||||
// // 21
|
||||
// We use getOrNullIfOutsideFiber so that it's OK to call check() // 22
|
||||
// from non-Fiber server contexts; the downside is that if you forget to // 23
|
||||
// bindEnvironment on some random callback in your method/publisher, // 24
|
||||
// it might not find the argumentChecker and you'll get an error about // 25
|
||||
// not checking an argument that it looks like you're checking (instead // 26
|
||||
// of just getting a "Node code must run in a Fiber" error). // 27
|
||||
var argChecker = currentArgumentChecker.getOrNullIfOutsideFiber(); // 28
|
||||
if (argChecker) // 29
|
||||
argChecker.checking(value); // 30
|
||||
try { // 31
|
||||
checkSubtree(value, pattern); // 32
|
||||
} catch (err) { // 33
|
||||
if ((err instanceof Match.Error) && err.path) // 34
|
||||
err.message += " in field " + err.path; // 35
|
||||
throw err; // 36
|
||||
} // 37
|
||||
}; // 38
|
||||
// 39
|
||||
/** // 40 |
||||
* @namespace Match // 41
|
||||
* @summary The namespace for all Match types and methods. // 42
|
||||
*/ // 43 |
||||
Match = { // 44
|
||||
Optional: function (pattern) { // 45
|
||||
return new Optional(pattern); // 46
|
||||
}, // 47
|
||||
OneOf: function (/*arguments*/) { // 48
|
||||
return new OneOf(_.toArray(arguments)); // 49
|
||||
}, // 50
|
||||
Any: ['__any__'], // 51
|
||||
Where: function (condition) { // 52
|
||||
return new Where(condition); // 53
|
||||
}, // 54
|
||||
ObjectIncluding: function (pattern) { // 55
|
||||
return new ObjectIncluding(pattern); // 56
|
||||
}, // 57
|
||||
ObjectWithValues: function (pattern) { // 58
|
||||
return new ObjectWithValues(pattern); // 59
|
||||
}, // 60
|
||||
// Matches only signed 32-bit integers // 61
|
||||
Integer: ['__integer__'], // 62
|
||||
// 63
|
||||
// XXX matchers should know how to describe themselves for errors // 64
|
||||
Error: Meteor.makeErrorType("Match.Error", function (msg) { // 65
|
||||
this.message = "Match error: " + msg; // 66
|
||||
// The path of the value that failed to match. Initially empty, this gets // 67
|
||||
// populated by catching and rethrowing the exception as it goes back up the // 68
|
||||
// stack. // 69
|
||||
// E.g.: "vals[3].entity.created" // 70
|
||||
this.path = ""; // 71
|
||||
// If this gets sent over DDP, don't give full internal details but at least // 72
|
||||
// provide something better than 500 Internal server error. // 73
|
||||
this.sanitizedError = new Meteor.Error(400, "Match failed"); // 74
|
||||
}), // 75
|
||||
// 76
|
||||
// Tests to see if value matches pattern. Unlike check, it merely returns true // 77
|
||||
// or false (unless an error other than Match.Error was thrown). It does not // 78
|
||||
// interact with _failIfArgumentsAreNotAllChecked. // 79
|
||||
// XXX maybe also implement a Match.match which returns more information about // 80
|
||||
// failures but without using exception handling or doing what check() // 81
|
||||
// does with _failIfArgumentsAreNotAllChecked and Meteor.Error conversion // 82
|
||||
// 83
|
||||
/** // 84 |
||||
* @summary Returns true if the value matches the pattern. // 85
|
||||
* @locus Anywhere // 86
|
||||
* @param {Any} value The value to check // 87
|
||||
* @param {MatchPattern} pattern The pattern to match `value` against // 88
|
||||
*/ // 89 |
||||
test: function (value, pattern) { // 90
|
||||
try { // 91
|
||||
checkSubtree(value, pattern); // 92
|
||||
return true; // 93
|
||||
} catch (e) { // 94
|
||||
if (e instanceof Match.Error) // 95
|
||||
return false; // 96
|
||||
// Rethrow other errors. // 97
|
||||
throw e; // 98
|
||||
} // 99
|
||||
}, // 100
|
||||
// 101
|
||||
// Runs `f.apply(context, args)`. If check() is not called on every element of // 102
|
||||
// `args` (either directly or in the first level of an array), throws an error // 103
|
||||
// (using `description` in the message). // 104
|
||||
// // 105
|
||||
_failIfArgumentsAreNotAllChecked: function (f, context, args, description) { // 106
|
||||
var argChecker = new ArgumentChecker(args, description); // 107
|
||||
var result = currentArgumentChecker.withValue(argChecker, function () { // 108
|
||||
return f.apply(context, args); // 109
|
||||
}); // 110
|
||||
// If f didn't itself throw, make sure it checked all of its arguments. // 111
|
||||
argChecker.throwUnlessAllArgumentsHaveBeenChecked(); // 112
|
||||
return result; // 113
|
||||
} // 114
|
||||
}; // 115
|
||||
// 116
|
||||
var Optional = function (pattern) { // 117
|
||||
this.pattern = pattern; // 118
|
||||
}; // 119
|
||||
// 120
|
||||
var OneOf = function (choices) { // 121
|
||||
if (_.isEmpty(choices)) // 122
|
||||
throw new Error("Must provide at least one choice to Match.OneOf"); // 123
|
||||
this.choices = choices; // 124
|
||||
}; // 125
|
||||
// 126
|
||||
var Where = function (condition) { // 127
|
||||
this.condition = condition; // 128
|
||||
}; // 129
|
||||
// 130
|
||||
var ObjectIncluding = function (pattern) { // 131
|
||||
this.pattern = pattern; // 132
|
||||
}; // 133
|
||||
// 134
|
||||
var ObjectWithValues = function (pattern) { // 135
|
||||
this.pattern = pattern; // 136
|
||||
}; // 137
|
||||
// 138
|
||||
var typeofChecks = [ // 139
|
||||
[String, "string"], // 140
|
||||
[Number, "number"], // 141
|
||||
[Boolean, "boolean"], // 142
|
||||
// While we don't allow undefined in EJSON, this is good for optional // 143
|
||||
// arguments with OneOf. // 144
|
||||
[undefined, "undefined"] // 145
|
||||
]; // 146
|
||||
// 147
|
||||
var checkSubtree = function (value, pattern) { // 148
|
||||
// Match anything! // 149
|
||||
if (pattern === Match.Any) // 150
|
||||
return; // 151
|
||||
// 152
|
||||
// Basic atomic types. // 153
|
||||
// Do not match boxed objects (e.g. String, Boolean) // 154
|
||||
for (var i = 0; i < typeofChecks.length; ++i) { // 155
|
||||
if (pattern === typeofChecks[i][0]) { // 156
|
||||
if (typeof value === typeofChecks[i][1]) // 157
|
||||
return; // 158
|
||||
throw new Match.Error("Expected " + typeofChecks[i][1] + ", got " + // 159
|
||||
typeof value); // 160
|
||||
} // 161
|
||||
} // 162
|
||||
if (pattern === null) { // 163
|
||||
if (value === null) // 164
|
||||
return; // 165
|
||||
throw new Match.Error("Expected null, got " + EJSON.stringify(value)); // 166
|
||||
} // 167
|
||||
// 168
|
||||
// Strings and numbers match literally. Goes well with Match.OneOf. // 169
|
||||
if (typeof pattern === "string" || typeof pattern === "number") { // 170
|
||||
if (value === pattern) // 171
|
||||
return; // 172
|
||||
throw new Match.Error("Expected " + pattern + ", got " + // 173
|
||||
EJSON.stringify(value)); // 174
|
||||
} // 175
|
||||
// 176
|
||||
// Match.Integer is special type encoded with array // 177
|
||||
if (pattern === Match.Integer) { // 178
|
||||
// There is no consistent and reliable way to check if variable is a 64-bit // 179
|
||||
// integer. One of the popular solutions is to get reminder of division by 1 // 180
|
||||
// but this method fails on really large floats with big precision. // 181
|
||||
// E.g.: 1.348192308491824e+23 % 1 === 0 in V8 // 182
|
||||
// Bitwise operators work consistantly but always cast variable to 32-bit // 183
|
||||
// signed integer according to JavaScript specs. // 184
|
||||
if (typeof value === "number" && (value | 0) === value) // 185
|
||||
return // 186
|
||||
throw new Match.Error("Expected Integer, got " // 187
|
||||
+ (value instanceof Object ? EJSON.stringify(value) : value)); // 188
|
||||
} // 189
|
||||
// 190
|
||||
// "Object" is shorthand for Match.ObjectIncluding({}); // 191
|
||||
if (pattern === Object) // 192
|
||||
pattern = Match.ObjectIncluding({}); // 193
|
||||
// 194
|
||||
// Array (checked AFTER Any, which is implemented as an Array). // 195
|
||||
if (pattern instanceof Array) { // 196
|
||||
if (pattern.length !== 1) // 197
|
||||
throw Error("Bad pattern: arrays must have one type element" + // 198
|
||||
EJSON.stringify(pattern)); // 199
|
||||
if (!_.isArray(value) && !_.isArguments(value)) { // 200
|
||||
throw new Match.Error("Expected array, got " + EJSON.stringify(value)); // 201
|
||||
} // 202
|
||||
// 203
|
||||
_.each(value, function (valueElement, index) { // 204
|
||||
try { // 205
|
||||
checkSubtree(valueElement, pattern[0]); // 206
|
||||
} catch (err) { // 207
|
||||
if (err instanceof Match.Error) { // 208
|
||||
err.path = _prependPath(index, err.path); // 209
|
||||
} // 210
|
||||
throw err; // 211
|
||||
} // 212
|
||||
}); // 213
|
||||
return; // 214
|
||||
} // 215
|
||||
// 216
|
||||
// Arbitrary validation checks. The condition can return false or throw a // 217
|
||||
// Match.Error (ie, it can internally use check()) to fail. // 218
|
||||
if (pattern instanceof Where) { // 219
|
||||
if (pattern.condition(value)) // 220
|
||||
return; // 221
|
||||
// XXX this error is terrible // 222
|
||||
throw new Match.Error("Failed Match.Where validation"); // 223
|
||||
} // 224
|
||||
// 225
|
||||
// 226
|
||||
if (pattern instanceof Optional) // 227
|
||||
pattern = Match.OneOf(undefined, pattern.pattern); // 228
|
||||
// 229
|
||||
if (pattern instanceof OneOf) { // 230
|
||||
for (var i = 0; i < pattern.choices.length; ++i) { // 231
|
||||
try { // 232
|
||||
checkSubtree(value, pattern.choices[i]); // 233
|
||||
// No error? Yay, return. // 234
|
||||
return; // 235
|
||||
} catch (err) { // 236
|
||||
// Other errors should be thrown. Match errors just mean try another // 237
|
||||
// choice. // 238
|
||||
if (!(err instanceof Match.Error)) // 239
|
||||
throw err; // 240
|
||||
} // 241
|
||||
} // 242
|
||||
// XXX this error is terrible // 243
|
||||
throw new Match.Error("Failed Match.OneOf or Match.Optional validation"); // 244
|
||||
} // 245
|
||||
// 246
|
||||
// A function that isn't something we special-case is assumed to be a // 247
|
||||
// constructor. // 248
|
||||
if (pattern instanceof Function) { // 249
|
||||
if (value instanceof pattern) // 250
|
||||
return; // 251
|
||||
throw new Match.Error("Expected " + (pattern.name || // 252
|
||||
"particular constructor")); // 253
|
||||
} // 254
|
||||
// 255
|
||||
var unknownKeysAllowed = false; // 256
|
||||
var unknownKeyPattern; // 257
|
||||
if (pattern instanceof ObjectIncluding) { // 258
|
||||
unknownKeysAllowed = true; // 259
|
||||
pattern = pattern.pattern; // 260
|
||||
} // 261
|
||||
if (pattern instanceof ObjectWithValues) { // 262
|
||||
unknownKeysAllowed = true; // 263
|
||||
unknownKeyPattern = [pattern.pattern]; // 264
|
||||
pattern = {}; // no required keys // 265
|
||||
} // 266
|
||||
// 267
|
||||
if (typeof pattern !== "object") // 268
|
||||
throw Error("Bad pattern: unknown pattern type"); // 269
|
||||
// 270
|
||||
// An object, with required and optional keys. Note that this does NOT do // 271
|
||||
// structural matches against objects of special types that happen to match // 272
|
||||
// the pattern: this really needs to be a plain old {Object}! // 273
|
||||
if (typeof value !== 'object') // 274
|
||||
throw new Match.Error("Expected object, got " + typeof value); // 275
|
||||
if (value === null) // 276
|
||||
throw new Match.Error("Expected object, got null"); // 277
|
||||
if (value.constructor !== Object) // 278
|
||||
throw new Match.Error("Expected plain object"); // 279
|
||||
// 280
|
||||
var requiredPatterns = {}; // 281
|
||||
var optionalPatterns = {}; // 282
|
||||
_.each(pattern, function (subPattern, key) { // 283
|
||||
if (subPattern instanceof Optional) // 284
|
||||
optionalPatterns[key] = subPattern.pattern; // 285
|
||||
else // 286
|
||||
requiredPatterns[key] = subPattern; // 287
|
||||
}); // 288
|
||||
// 289
|
||||
_.each(value, function (subValue, key) { // 290
|
||||
try { // 291
|
||||
if (_.has(requiredPatterns, key)) { // 292
|
||||
checkSubtree(subValue, requiredPatterns[key]); // 293
|
||||
delete requiredPatterns[key]; // 294
|
||||
} else if (_.has(optionalPatterns, key)) { // 295
|
||||
checkSubtree(subValue, optionalPatterns[key]); // 296
|
||||
} else { // 297
|
||||
if (!unknownKeysAllowed) // 298
|
||||
throw new Match.Error("Unknown key"); // 299
|
||||
if (unknownKeyPattern) { // 300
|
||||
checkSubtree(subValue, unknownKeyPattern[0]); // 301
|
||||
} // 302
|
||||
} // 303
|
||||
} catch (err) { // 304
|
||||
if (err instanceof Match.Error) // 305
|
||||
err.path = _prependPath(key, err.path); // 306
|
||||
throw err; // 307
|
||||
} // 308
|
||||
}); // 309
|
||||
// 310
|
||||
_.each(requiredPatterns, function (subPattern, key) { // 311
|
||||
throw new Match.Error("Missing key '" + key + "'"); // 312
|
||||
}); // 313
|
||||
}; // 314
|
||||
// 315
|
||||
var ArgumentChecker = function (args, description) { // 316
|
||||
var self = this; // 317
|
||||
// Make a SHALLOW copy of the arguments. (We'll be doing identity checks // 318
|
||||
// against its contents.) // 319
|
||||
self.args = _.clone(args); // 320
|
||||
// Since the common case will be to check arguments in order, and we splice // 321
|
||||
// out arguments when we check them, make it so we splice out from the end // 322
|
||||
// rather than the beginning. // 323
|
||||
self.args.reverse(); // 324
|
||||
self.description = description; // 325
|
||||
}; // 326
|
||||
// 327
|
||||
_.extend(ArgumentChecker.prototype, { // 328
|
||||
checking: function (value) { // 329
|
||||
var self = this; // 330
|
||||
if (self._checkingOneValue(value)) // 331
|
||||
return; // 332
|
||||
// Allow check(arguments, [String]) or check(arguments.slice(1), [String]) // 333
|
||||
// or check([foo, bar], [String]) to count... but only if value wasn't // 334
|
||||
// itself an argument. // 335
|
||||
if (_.isArray(value) || _.isArguments(value)) { // 336
|
||||
_.each(value, _.bind(self._checkingOneValue, self)); // 337
|
||||
} // 338
|
||||
}, // 339
|
||||
_checkingOneValue: function (value) { // 340
|
||||
var self = this; // 341
|
||||
for (var i = 0; i < self.args.length; ++i) { // 342
|
||||
// Is this value one of the arguments? (This can have a false positive if // 343
|
||||
// the argument is an interned primitive, but it's still a good enough // 344
|
||||
// check.) // 345
|
||||
// (NaN is not === to itself, so we have to check specially.) // 346
|
||||
if (value === self.args[i] || (_.isNaN(value) && _.isNaN(self.args[i]))) { // 347
|
||||
self.args.splice(i, 1); // 348
|
||||
return true; // 349
|
||||
} // 350
|
||||
} // 351
|
||||
return false; // 352
|
||||
}, // 353
|
||||
throwUnlessAllArgumentsHaveBeenChecked: function () { // 354
|
||||
var self = this; // 355
|
||||
if (!_.isEmpty(self.args)) // 356
|
||||
throw new Error("Did not check() all arguments during " + // 357
|
||||
self.description); // 358
|
||||
} // 359
|
||||
}); // 360
|
||||
// 361
|
||||
var _jsKeywords = ["do", "if", "in", "for", "let", "new", "try", "var", "case", // 362
|
||||
"else", "enum", "eval", "false", "null", "this", "true", "void", "with", // 363
|
||||
"break", "catch", "class", "const", "super", "throw", "while", "yield", // 364
|
||||
"delete", "export", "import", "public", "return", "static", "switch", // 365
|
||||
"typeof", "default", "extends", "finally", "package", "private", "continue", // 366
|
||||
"debugger", "function", "arguments", "interface", "protected", "implements", // 367
|
||||
"instanceof"]; // 368
|
||||
// 369
|
||||
// Assumes the base of path is already escaped properly // 370
|
||||
// returns key + base // 371
|
||||
var _prependPath = function (key, base) { // 372
|
||||
if ((typeof key) === "number" || key.match(/^[0-9]+$/)) // 373
|
||||
key = "[" + key + "]"; // 374
|
||||
else if (!key.match(/^[a-z_$][0-9a-z_$]*$/i) || _.contains(_jsKeywords, key)) // 375
|
||||
key = JSON.stringify([key]); // 376
|
||||
// 377
|
||||
if (base && base[0] !== "[") // 378
|
||||
return key + '.' + base; // 379
|
||||
return key + base; // 380
|
||||
}; // 381
|
||||
// 382
|
||||
// 383
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.check = { |
||||
check: check, |
||||
Match: Match |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=check.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['d3js:d3'] = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=d3js_d3.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/d3js:d3.js"} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,22 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Tracker = Package.tracker.Tracker; |
||||
var Deps = Package.tracker.Deps; |
||||
|
||||
/* Package-scope variables */ |
||||
var Tracker, Deps; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.deps = { |
||||
Tracker: Tracker, |
||||
Deps: Deps |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=deps.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;","file":"/packages/deps.js"} |
@ -0,0 +1,679 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var Base64 = Package.base64.Base64; |
||||
|
||||
/* Package-scope variables */ |
||||
var EJSON, EJSONTest; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ejson/ejson.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/** // 1 |
||||
* @namespace // 2
|
||||
* @summary Namespace for EJSON functions // 3
|
||||
*/ // 4 |
||||
EJSON = {}; // 5
|
||||
EJSONTest = {}; // 6
|
||||
// 7
|
||||
// 8
|
||||
// 9
|
||||
// Custom type interface definition // 10
|
||||
/** // 11 |
||||
* @class CustomType // 12
|
||||
* @instanceName customType // 13
|
||||
* @memberOf EJSON // 14
|
||||
* @summary The interface that a class must satisfy to be able to become an // 15
|
||||
* EJSON custom type via EJSON.addType. // 16
|
||||
*/ // 17 |
||||
// 18
|
||||
/** // 19 |
||||
* @function typeName // 20
|
||||
* @memberOf EJSON.CustomType // 21
|
||||
* @summary Return the tag used to identify this type. This must match the tag used to register this type with [`EJSON.addType`](#ejson_add_type). |
||||
* @locus Anywhere // 23
|
||||
* @instance // 24
|
||||
*/ // 25 |
||||
// 26
|
||||
/** // 27 |
||||
* @function toJSONValue // 28
|
||||
* @memberOf EJSON.CustomType // 29
|
||||
* @summary Serialize this instance into a JSON-compatible value. // 30
|
||||
* @locus Anywhere // 31
|
||||
* @instance // 32
|
||||
*/ // 33 |
||||
// 34
|
||||
/** // 35 |
||||
* @function clone // 36
|
||||
* @memberOf EJSON.CustomType // 37
|
||||
* @summary Return a value `r` such that `this.equals(r)` is true, and modifications to `r` do not affect `this` and vice versa. |
||||
* @locus Anywhere // 39
|
||||
* @instance // 40
|
||||
*/ // 41 |
||||
// 42
|
||||
/** // 43 |
||||
* @function equals // 44
|
||||
* @memberOf EJSON.CustomType // 45
|
||||
* @summary Return `true` if `other` has a value equal to `this`; `false` otherwise. // 46
|
||||
* @locus Anywhere // 47
|
||||
* @param {Object} other Another object to compare this to. // 48
|
||||
* @instance // 49
|
||||
*/ // 50 |
||||
// 51
|
||||
// 52
|
||||
var customTypes = {}; // 53
|
||||
// Add a custom type, using a method of your choice to get to and // 54
|
||||
// from a basic JSON-able representation. The factory argument // 55
|
||||
// is a function of JSON-able --> your object // 56
|
||||
// The type you add must have: // 57
|
||||
// - A toJSONValue() method, so that Meteor can serialize it // 58
|
||||
// - a typeName() method, to show how to look it up in our type table. // 59
|
||||
// It is okay if these methods are monkey-patched on. // 60
|
||||
// EJSON.clone will use toJSONValue and the given factory to produce // 61
|
||||
// a clone, but you may specify a method clone() that will be // 62
|
||||
// used instead. // 63
|
||||
// Similarly, EJSON.equals will use toJSONValue to make comparisons, // 64
|
||||
// but you may provide a method equals() instead. // 65
|
||||
/** // 66 |
||||
* @summary Add a custom datatype to EJSON. // 67
|
||||
* @locus Anywhere // 68
|
||||
* @param {String} name A tag for your custom type; must be unique among custom data types defined in your project, and must match the result of your type's `typeName` method. |
||||
* @param {Function} factory A function that deserializes a JSON-compatible value into an instance of your type. This should match the serialization performed by your type's `toJSONValue` method. |
||||
*/ // 71 |
||||
EJSON.addType = function (name, factory) { // 72
|
||||
if (_.has(customTypes, name)) // 73
|
||||
throw new Error("Type " + name + " already present"); // 74
|
||||
customTypes[name] = factory; // 75
|
||||
}; // 76
|
||||
// 77
|
||||
var isInfOrNan = function (obj) { // 78
|
||||
return _.isNaN(obj) || obj === Infinity || obj === -Infinity; // 79
|
||||
}; // 80
|
||||
// 81
|
||||
var builtinConverters = [ // 82
|
||||
{ // Date // 83
|
||||
matchJSONValue: function (obj) { // 84
|
||||
return _.has(obj, '$date') && _.size(obj) === 1; // 85
|
||||
}, // 86
|
||||
matchObject: function (obj) { // 87
|
||||
return obj instanceof Date; // 88
|
||||
}, // 89
|
||||
toJSONValue: function (obj) { // 90
|
||||
return {$date: obj.getTime()}; // 91
|
||||
}, // 92
|
||||
fromJSONValue: function (obj) { // 93
|
||||
return new Date(obj.$date); // 94
|
||||
} // 95
|
||||
}, // 96
|
||||
{ // NaN, Inf, -Inf. (These are the only objects with typeof !== 'object' // 97
|
||||
// which we match.) // 98
|
||||
matchJSONValue: function (obj) { // 99
|
||||
return _.has(obj, '$InfNaN') && _.size(obj) === 1; // 100
|
||||
}, // 101
|
||||
matchObject: isInfOrNan, // 102
|
||||
toJSONValue: function (obj) { // 103
|
||||
var sign; // 104
|
||||
if (_.isNaN(obj)) // 105
|
||||
sign = 0; // 106
|
||||
else if (obj === Infinity) // 107
|
||||
sign = 1; // 108
|
||||
else // 109
|
||||
sign = -1; // 110
|
||||
return {$InfNaN: sign}; // 111
|
||||
}, // 112
|
||||
fromJSONValue: function (obj) { // 113
|
||||
return obj.$InfNaN/0; // 114
|
||||
} // 115
|
||||
}, // 116
|
||||
{ // Binary // 117
|
||||
matchJSONValue: function (obj) { // 118
|
||||
return _.has(obj, '$binary') && _.size(obj) === 1; // 119
|
||||
}, // 120
|
||||
matchObject: function (obj) { // 121
|
||||
return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array // 122
|
||||
|| (obj && _.has(obj, '$Uint8ArrayPolyfill')); // 123
|
||||
}, // 124
|
||||
toJSONValue: function (obj) { // 125
|
||||
return {$binary: Base64.encode(obj)}; // 126
|
||||
}, // 127
|
||||
fromJSONValue: function (obj) { // 128
|
||||
return Base64.decode(obj.$binary); // 129
|
||||
} // 130
|
||||
}, // 131
|
||||
{ // Escaping one level // 132
|
||||
matchJSONValue: function (obj) { // 133
|
||||
return _.has(obj, '$escape') && _.size(obj) === 1; // 134
|
||||
}, // 135
|
||||
matchObject: function (obj) { // 136
|
||||
if (_.isEmpty(obj) || _.size(obj) > 2) { // 137
|
||||
return false; // 138
|
||||
} // 139
|
||||
return _.any(builtinConverters, function (converter) { // 140
|
||||
return converter.matchJSONValue(obj); // 141
|
||||
}); // 142
|
||||
}, // 143
|
||||
toJSONValue: function (obj) { // 144
|
||||
var newObj = {}; // 145
|
||||
_.each(obj, function (value, key) { // 146
|
||||
newObj[key] = EJSON.toJSONValue(value); // 147
|
||||
}); // 148
|
||||
return {$escape: newObj}; // 149
|
||||
}, // 150
|
||||
fromJSONValue: function (obj) { // 151
|
||||
var newObj = {}; // 152
|
||||
_.each(obj.$escape, function (value, key) { // 153
|
||||
newObj[key] = EJSON.fromJSONValue(value); // 154
|
||||
}); // 155
|
||||
return newObj; // 156
|
||||
} // 157
|
||||
}, // 158
|
||||
{ // Custom // 159
|
||||
matchJSONValue: function (obj) { // 160
|
||||
return _.has(obj, '$type') && _.has(obj, '$value') && _.size(obj) === 2; // 161
|
||||
}, // 162
|
||||
matchObject: function (obj) { // 163
|
||||
return EJSON._isCustomType(obj); // 164
|
||||
}, // 165
|
||||
toJSONValue: function (obj) { // 166
|
||||
var jsonValue = Meteor._noYieldsAllowed(function () { // 167
|
||||
return obj.toJSONValue(); // 168
|
||||
}); // 169
|
||||
return {$type: obj.typeName(), $value: jsonValue}; // 170
|
||||
}, // 171
|
||||
fromJSONValue: function (obj) { // 172
|
||||
var typeName = obj.$type; // 173
|
||||
if (!_.has(customTypes, typeName)) // 174
|
||||
throw new Error("Custom EJSON type " + typeName + " is not defined"); // 175
|
||||
var converter = customTypes[typeName]; // 176
|
||||
return Meteor._noYieldsAllowed(function () { // 177
|
||||
return converter(obj.$value); // 178
|
||||
}); // 179
|
||||
} // 180
|
||||
} // 181
|
||||
]; // 182
|
||||
// 183
|
||||
EJSON._isCustomType = function (obj) { // 184
|
||||
return obj && // 185
|
||||
typeof obj.toJSONValue === 'function' && // 186
|
||||
typeof obj.typeName === 'function' && // 187
|
||||
_.has(customTypes, obj.typeName()); // 188
|
||||
}; // 189
|
||||
// 190
|
||||
// 191
|
||||
// for both arrays and objects, in-place modification. // 192
|
||||
var adjustTypesToJSONValue = // 193
|
||||
EJSON._adjustTypesToJSONValue = function (obj) { // 194
|
||||
// Is it an atom that we need to adjust? // 195
|
||||
if (obj === null) // 196
|
||||
return null; // 197
|
||||
var maybeChanged = toJSONValueHelper(obj); // 198
|
||||
if (maybeChanged !== undefined) // 199
|
||||
return maybeChanged; // 200
|
||||
// 201
|
||||
// Other atoms are unchanged. // 202
|
||||
if (typeof obj !== 'object') // 203
|
||||
return obj; // 204
|
||||
// 205
|
||||
// Iterate over array or object structure. // 206
|
||||
_.each(obj, function (value, key) { // 207
|
||||
if (typeof value !== 'object' && value !== undefined && // 208
|
||||
!isInfOrNan(value)) // 209
|
||||
return; // continue // 210
|
||||
// 211
|
||||
var changed = toJSONValueHelper(value); // 212
|
||||
if (changed) { // 213
|
||||
obj[key] = changed; // 214
|
||||
return; // on to the next key // 215
|
||||
} // 216
|
||||
// if we get here, value is an object but not adjustable // 217
|
||||
// at this level. recurse. // 218
|
||||
adjustTypesToJSONValue(value); // 219
|
||||
}); // 220
|
||||
return obj; // 221
|
||||
}; // 222
|
||||
// 223
|
||||
// Either return the JSON-compatible version of the argument, or undefined (if // 224
|
||||
// the item isn't itself replaceable, but maybe some fields in it are) // 225
|
||||
var toJSONValueHelper = function (item) { // 226
|
||||
for (var i = 0; i < builtinConverters.length; i++) { // 227
|
||||
var converter = builtinConverters[i]; // 228
|
||||
if (converter.matchObject(item)) { // 229
|
||||
return converter.toJSONValue(item); // 230
|
||||
} // 231
|
||||
} // 232
|
||||
return undefined; // 233
|
||||
}; // 234
|
||||
// 235
|
||||
/** // 236 |
||||
* @summary Serialize an EJSON-compatible value into its plain JSON representation. // 237
|
||||
* @locus Anywhere // 238
|
||||
* @param {EJSON} val A value to serialize to plain JSON. // 239
|
||||
*/ // 240 |
||||
EJSON.toJSONValue = function (item) { // 241
|
||||
var changed = toJSONValueHelper(item); // 242
|
||||
if (changed !== undefined) // 243
|
||||
return changed; // 244
|
||||
if (typeof item === 'object') { // 245
|
||||
item = EJSON.clone(item); // 246
|
||||
adjustTypesToJSONValue(item); // 247
|
||||
} // 248
|
||||
return item; // 249
|
||||
}; // 250
|
||||
// 251
|
||||
// for both arrays and objects. Tries its best to just // 252
|
||||
// use the object you hand it, but may return something // 253
|
||||
// different if the object you hand it itself needs changing. // 254
|
||||
// // 255
|
||||
var adjustTypesFromJSONValue = // 256
|
||||
EJSON._adjustTypesFromJSONValue = function (obj) { // 257
|
||||
if (obj === null) // 258
|
||||
return null; // 259
|
||||
var maybeChanged = fromJSONValueHelper(obj); // 260
|
||||
if (maybeChanged !== obj) // 261
|
||||
return maybeChanged; // 262
|
||||
// 263
|
||||
// Other atoms are unchanged. // 264
|
||||
if (typeof obj !== 'object') // 265
|
||||
return obj; // 266
|
||||
// 267
|
||||
_.each(obj, function (value, key) { // 268
|
||||
if (typeof value === 'object') { // 269
|
||||
var changed = fromJSONValueHelper(value); // 270
|
||||
if (value !== changed) { // 271
|
||||
obj[key] = changed; // 272
|
||||
return; // 273
|
||||
} // 274
|
||||
// if we get here, value is an object but not adjustable // 275
|
||||
// at this level. recurse. // 276
|
||||
adjustTypesFromJSONValue(value); // 277
|
||||
} // 278
|
||||
}); // 279
|
||||
return obj; // 280
|
||||
}; // 281
|
||||
// 282
|
||||
// Either return the argument changed to have the non-json // 283
|
||||
// rep of itself (the Object version) or the argument itself. // 284
|
||||
// 285
|
||||
// DOES NOT RECURSE. For actually getting the fully-changed value, use // 286
|
||||
// EJSON.fromJSONValue // 287
|
||||
var fromJSONValueHelper = function (value) { // 288
|
||||
if (typeof value === 'object' && value !== null) { // 289
|
||||
if (_.size(value) <= 2 // 290
|
||||
&& _.all(value, function (v, k) { // 291
|
||||
return typeof k === 'string' && k.substr(0, 1) === '$'; // 292
|
||||
})) { // 293
|
||||
for (var i = 0; i < builtinConverters.length; i++) { // 294
|
||||
var converter = builtinConverters[i]; // 295
|
||||
if (converter.matchJSONValue(value)) { // 296
|
||||
return converter.fromJSONValue(value); // 297
|
||||
} // 298
|
||||
} // 299
|
||||
} // 300
|
||||
} // 301
|
||||
return value; // 302
|
||||
}; // 303
|
||||
// 304
|
||||
/** // 305 |
||||
* @summary Deserialize an EJSON value from its plain JSON representation. // 306
|
||||
* @locus Anywhere // 307
|
||||
* @param {JSONCompatible} val A value to deserialize into EJSON. // 308
|
||||
*/ // 309 |
||||
EJSON.fromJSONValue = function (item) { // 310
|
||||
var changed = fromJSONValueHelper(item); // 311
|
||||
if (changed === item && typeof item === 'object') { // 312
|
||||
item = EJSON.clone(item); // 313
|
||||
adjustTypesFromJSONValue(item); // 314
|
||||
return item; // 315
|
||||
} else { // 316
|
||||
return changed; // 317
|
||||
} // 318
|
||||
}; // 319
|
||||
// 320
|
||||
/** // 321 |
||||
* @summary Serialize a value to a string. // 322
|
||||
// 323
|
||||
For EJSON values, the serialization fully represents the value. For non-EJSON values, serializes the same way as `JSON.stringify`. |
||||
* @locus Anywhere // 325
|
||||
* @param {EJSON} val A value to stringify. // 326
|
||||
* @param {Object} [options] // 327
|
||||
* @param {Boolean | Integer | String} options.indent Indents objects and arrays for easy readability. When `true`, indents by 2 spaces; when an integer, indents by that number of spaces; and when a string, uses the string as the indentation pattern. |
||||
* @param {Boolean} options.canonical When `true`, stringifies keys in an object in sorted order. // 329
|
||||
*/ // 330 |
||||
EJSON.stringify = function (item, options) { // 331
|
||||
var json = EJSON.toJSONValue(item); // 332
|
||||
if (options && (options.canonical || options.indent)) { // 333
|
||||
return EJSON._canonicalStringify(json, options); // 334
|
||||
} else { // 335
|
||||
return JSON.stringify(json); // 336
|
||||
} // 337
|
||||
}; // 338
|
||||
// 339
|
||||
/** // 340 |
||||
* @summary Parse a string into an EJSON value. Throws an error if the string is not valid EJSON. // 341
|
||||
* @locus Anywhere // 342
|
||||
* @param {String} str A string to parse into an EJSON value. // 343
|
||||
*/ // 344 |
||||
EJSON.parse = function (item) { // 345
|
||||
if (typeof item !== 'string') // 346
|
||||
throw new Error("EJSON.parse argument should be a string"); // 347
|
||||
return EJSON.fromJSONValue(JSON.parse(item)); // 348
|
||||
}; // 349
|
||||
// 350
|
||||
/** // 351 |
||||
* @summary Returns true if `x` is a buffer of binary data, as returned from [`EJSON.newBinary`](#ejson_new_binary). // 352
|
||||
* @param {Object} x The variable to check. // 353
|
||||
* @locus Anywhere // 354
|
||||
*/ // 355 |
||||
EJSON.isBinary = function (obj) { // 356
|
||||
return !!((typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array) || // 357
|
||||
(obj && obj.$Uint8ArrayPolyfill)); // 358
|
||||
}; // 359
|
||||
// 360
|
||||
/** // 361 |
||||
* @summary Return true if `a` and `b` are equal to each other. Return false otherwise. Uses the `equals` method on `a` if present, otherwise performs a deep comparison. |
||||
* @locus Anywhere // 363
|
||||
* @param {EJSON} a // 364
|
||||
* @param {EJSON} b // 365
|
||||
* @param {Object} [options] // 366
|
||||
* @param {Boolean} options.keyOrderSensitive Compare in key sensitive order, if supported by the JavaScript implementation. For example, `{a: 1, b: 2}` is equal to `{b: 2, a: 1}` only when `keyOrderSensitive` is `false`. The default is `false`. |
||||
*/ // 368 |
||||
EJSON.equals = function (a, b, options) { // 369
|
||||
var i; // 370
|
||||
var keyOrderSensitive = !!(options && options.keyOrderSensitive); // 371
|
||||
if (a === b) // 372
|
||||
return true; // 373
|
||||
if (_.isNaN(a) && _.isNaN(b)) // 374
|
||||
return true; // This differs from the IEEE spec for NaN equality, b/c we don't want // 375
|
||||
// anything ever with a NaN to be poisoned from becoming equal to anything. // 376
|
||||
if (!a || !b) // if either one is falsy, they'd have to be === to be equal // 377
|
||||
return false; // 378
|
||||
if (!(typeof a === 'object' && typeof b === 'object')) // 379
|
||||
return false; // 380
|
||||
if (a instanceof Date && b instanceof Date) // 381
|
||||
return a.valueOf() === b.valueOf(); // 382
|
||||
if (EJSON.isBinary(a) && EJSON.isBinary(b)) { // 383
|
||||
if (a.length !== b.length) // 384
|
||||
return false; // 385
|
||||
for (i = 0; i < a.length; i++) { // 386
|
||||
if (a[i] !== b[i]) // 387
|
||||
return false; // 388
|
||||
} // 389
|
||||
return true; // 390
|
||||
} // 391
|
||||
if (typeof (a.equals) === 'function') // 392
|
||||
return a.equals(b, options); // 393
|
||||
if (typeof (b.equals) === 'function') // 394
|
||||
return b.equals(a, options); // 395
|
||||
if (a instanceof Array) { // 396
|
||||
if (!(b instanceof Array)) // 397
|
||||
return false; // 398
|
||||
if (a.length !== b.length) // 399
|
||||
return false; // 400
|
||||
for (i = 0; i < a.length; i++) { // 401
|
||||
if (!EJSON.equals(a[i], b[i], options)) // 402
|
||||
return false; // 403
|
||||
} // 404
|
||||
return true; // 405
|
||||
} // 406
|
||||
// fallback for custom types that don't implement their own equals // 407
|
||||
switch (EJSON._isCustomType(a) + EJSON._isCustomType(b)) { // 408
|
||||
case 1: return false; // 409
|
||||
case 2: return EJSON.equals(EJSON.toJSONValue(a), EJSON.toJSONValue(b)); // 410
|
||||
} // 411
|
||||
// fall back to structural equality of objects // 412
|
||||
var ret; // 413
|
||||
if (keyOrderSensitive) { // 414
|
||||
var bKeys = []; // 415
|
||||
_.each(b, function (val, x) { // 416
|
||||
bKeys.push(x); // 417
|
||||
}); // 418
|
||||
i = 0; // 419
|
||||
ret = _.all(a, function (val, x) { // 420
|
||||
if (i >= bKeys.length) { // 421
|
||||
return false; // 422
|
||||
} // 423
|
||||
if (x !== bKeys[i]) { // 424
|
||||
return false; // 425
|
||||
} // 426
|
||||
if (!EJSON.equals(val, b[bKeys[i]], options)) { // 427
|
||||
return false; // 428
|
||||
} // 429
|
||||
i++; // 430
|
||||
return true; // 431
|
||||
}); // 432
|
||||
return ret && i === bKeys.length; // 433
|
||||
} else { // 434
|
||||
i = 0; // 435
|
||||
ret = _.all(a, function (val, key) { // 436
|
||||
if (!_.has(b, key)) { // 437
|
||||
return false; // 438
|
||||
} // 439
|
||||
if (!EJSON.equals(val, b[key], options)) { // 440
|
||||
return false; // 441
|
||||
} // 442
|
||||
i++; // 443
|
||||
return true; // 444
|
||||
}); // 445
|
||||
return ret && _.size(b) === i; // 446
|
||||
} // 447
|
||||
}; // 448
|
||||
// 449
|
||||
/** // 450 |
||||
* @summary Return a deep copy of `val`. // 451
|
||||
* @locus Anywhere // 452
|
||||
* @param {EJSON} val A value to copy. // 453
|
||||
*/ // 454 |
||||
EJSON.clone = function (v) { // 455
|
||||
var ret; // 456
|
||||
if (typeof v !== "object") // 457
|
||||
return v; // 458
|
||||
if (v === null) // 459
|
||||
return null; // null has typeof "object" // 460
|
||||
if (v instanceof Date) // 461
|
||||
return new Date(v.getTime()); // 462
|
||||
// RegExps are not really EJSON elements (eg we don't define a serialization // 463
|
||||
// for them), but they're immutable anyway, so we can support them in clone. // 464
|
||||
if (v instanceof RegExp) // 465
|
||||
return v; // 466
|
||||
if (EJSON.isBinary(v)) { // 467
|
||||
ret = EJSON.newBinary(v.length); // 468
|
||||
for (var i = 0; i < v.length; i++) { // 469
|
||||
ret[i] = v[i]; // 470
|
||||
} // 471
|
||||
return ret; // 472
|
||||
} // 473
|
||||
// XXX: Use something better than underscore's isArray // 474
|
||||
if (_.isArray(v) || _.isArguments(v)) { // 475
|
||||
// For some reason, _.map doesn't work in this context on Opera (weird test // 476
|
||||
// failures). // 477
|
||||
ret = []; // 478
|
||||
for (i = 0; i < v.length; i++) // 479
|
||||
ret[i] = EJSON.clone(v[i]); // 480
|
||||
return ret; // 481
|
||||
} // 482
|
||||
// handle general user-defined typed Objects if they have a clone method // 483
|
||||
if (typeof v.clone === 'function') { // 484
|
||||
return v.clone(); // 485
|
||||
} // 486
|
||||
// handle other custom types // 487
|
||||
if (EJSON._isCustomType(v)) { // 488
|
||||
return EJSON.fromJSONValue(EJSON.clone(EJSON.toJSONValue(v)), true); // 489
|
||||
} // 490
|
||||
// handle other objects // 491
|
||||
ret = {}; // 492
|
||||
_.each(v, function (value, key) { // 493
|
||||
ret[key] = EJSON.clone(value); // 494
|
||||
}); // 495
|
||||
return ret; // 496
|
||||
}; // 497
|
||||
// 498
|
||||
/** // 499 |
||||
* @summary Allocate a new buffer of binary data that EJSON can serialize. // 500
|
||||
* @locus Anywhere // 501
|
||||
* @param {Number} size The number of bytes of binary data to allocate. // 502
|
||||
*/ // 503 |
||||
// EJSON.newBinary is the public documented API for this functionality, // 504
|
||||
// but the implementation is in the 'base64' package to avoid // 505
|
||||
// introducing a circular dependency. (If the implementation were here, // 506
|
||||
// then 'base64' would have to use EJSON.newBinary, and 'ejson' would // 507
|
||||
// also have to use 'base64'.) // 508
|
||||
EJSON.newBinary = Base64.newBinary; // 509
|
||||
// 510
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ejson/stringify.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Based on json2.js from https://github.com/douglascrockford/JSON-js // 1
|
||||
// // 2
|
||||
// json2.js // 3
|
||||
// 2012-10-08 // 4
|
||||
// // 5
|
||||
// Public Domain. // 6
|
||||
// // 7
|
||||
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. // 8
|
||||
// 9
|
||||
function quote(string) { // 10
|
||||
return JSON.stringify(string); // 11
|
||||
} // 12
|
||||
// 13
|
||||
var str = function (key, holder, singleIndent, outerIndent, canonical) { // 14
|
||||
// 15
|
||||
// Produce a string from holder[key]. // 16
|
||||
// 17
|
||||
var i; // The loop counter. // 18
|
||||
var k; // The member key. // 19
|
||||
var v; // The member value. // 20
|
||||
var length; // 21
|
||||
var innerIndent = outerIndent; // 22
|
||||
var partial; // 23
|
||||
var value = holder[key]; // 24
|
||||
// 25
|
||||
// What happens next depends on the value's type. // 26
|
||||
// 27
|
||||
switch (typeof value) { // 28
|
||||
case 'string': // 29
|
||||
return quote(value); // 30
|
||||
case 'number': // 31
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null. // 32
|
||||
return isFinite(value) ? String(value) : 'null'; // 33
|
||||
case 'boolean': // 34
|
||||
return String(value); // 35
|
||||
// If the type is 'object', we might be dealing with an object or an array or // 36
|
||||
// null. // 37
|
||||
case 'object': // 38
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object', // 39
|
||||
// so watch out for that case. // 40
|
||||
if (!value) { // 41
|
||||
return 'null'; // 42
|
||||
} // 43
|
||||
// Make an array to hold the partial results of stringifying this object value. // 44
|
||||
innerIndent = outerIndent + singleIndent; // 45
|
||||
partial = []; // 46
|
||||
// 47
|
||||
// Is the value an array? // 48
|
||||
if (_.isArray(value) || _.isArguments(value)) { // 49
|
||||
// 50
|
||||
// The value is an array. Stringify every element. Use null as a placeholder // 51
|
||||
// for non-JSON values. // 52
|
||||
// 53
|
||||
length = value.length; // 54
|
||||
for (i = 0; i < length; i += 1) { // 55
|
||||
partial[i] = str(i, value, singleIndent, innerIndent, canonical) || 'null'; // 56
|
||||
} // 57
|
||||
// 58
|
||||
// Join all of the elements together, separated with commas, and wrap them in // 59
|
||||
// brackets. // 60
|
||||
// 61
|
||||
if (partial.length === 0) { // 62
|
||||
v = '[]'; // 63
|
||||
} else if (innerIndent) { // 64
|
||||
v = '[\n' + innerIndent + partial.join(',\n' + innerIndent) + '\n' + outerIndent + ']'; // 65
|
||||
} else { // 66
|
||||
v = '[' + partial.join(',') + ']'; // 67
|
||||
} // 68
|
||||
return v; // 69
|
||||
} // 70
|
||||
// 71
|
||||
// 72
|
||||
// Iterate through all of the keys in the object. // 73
|
||||
var keys = _.keys(value); // 74
|
||||
if (canonical) // 75
|
||||
keys = keys.sort(); // 76
|
||||
_.each(keys, function (k) { // 77
|
||||
v = str(k, value, singleIndent, innerIndent, canonical); // 78
|
||||
if (v) { // 79
|
||||
partial.push(quote(k) + (innerIndent ? ': ' : ':') + v); // 80
|
||||
} // 81
|
||||
}); // 82
|
||||
// 83
|
||||
// 84
|
||||
// Join all of the member texts together, separated with commas, // 85
|
||||
// and wrap them in braces. // 86
|
||||
// 87
|
||||
if (partial.length === 0) { // 88
|
||||
v = '{}'; // 89
|
||||
} else if (innerIndent) { // 90
|
||||
v = '{\n' + innerIndent + partial.join(',\n' + innerIndent) + '\n' + outerIndent + '}'; // 91
|
||||
} else { // 92
|
||||
v = '{' + partial.join(',') + '}'; // 93
|
||||
} // 94
|
||||
return v; // 95
|
||||
} // 96
|
||||
} // 97
|
||||
// 98
|
||||
// If the JSON object does not yet have a stringify method, give it one. // 99
|
||||
// 100
|
||||
EJSON._canonicalStringify = function (value, options) { // 101
|
||||
// Make a fake root object containing our value under the key of ''. // 102
|
||||
// Return the result of stringifying the value. // 103
|
||||
options = _.extend({ // 104
|
||||
indent: "", // 105
|
||||
canonical: false // 106
|
||||
}, options); // 107
|
||||
if (options.indent === true) { // 108
|
||||
options.indent = " "; // 109
|
||||
} else if (typeof options.indent === 'number') { // 110
|
||||
var newIndent = ""; // 111
|
||||
for (var i = 0; i < options.indent; i++) { // 112
|
||||
newIndent += ' '; // 113
|
||||
} // 114
|
||||
options.indent = newIndent; // 115
|
||||
} // 116
|
||||
return str('', {'': value}, options.indent, "", options.canonical); // 117
|
||||
}; // 118
|
||||
// 119
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.ejson = { |
||||
EJSON: EJSON, |
||||
EJSONTest: EJSONTest |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=ejson.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,455 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
/* Package-scope variables */ |
||||
var GeoJSON, module; |
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/pre.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Define an object named exports. This will cause geojson-utils.js to put `gju` // 1
|
||||
// as a field on it, instead of in the global namespace. See also post.js. // 2
|
||||
module = {exports:{}}; // 3
|
||||
// 4
|
||||
// 5
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/geojson-utils.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
(function () { // 1
|
||||
var gju = {}; // 2
|
||||
// 3
|
||||
// Export the geojson object for **CommonJS** // 4
|
||||
if (typeof module !== 'undefined' && module.exports) { // 5
|
||||
module.exports = gju; // 6
|
||||
} // 7
|
||||
// 8
|
||||
// adapted from http://www.kevlindev.com/gui/math/intersection/Intersection.js // 9
|
||||
gju.lineStringsIntersect = function (l1, l2) { // 10
|
||||
var intersects = []; // 11
|
||||
for (var i = 0; i <= l1.coordinates.length - 2; ++i) { // 12
|
||||
for (var j = 0; j <= l2.coordinates.length - 2; ++j) { // 13
|
||||
var a1 = { // 14
|
||||
x: l1.coordinates[i][1], // 15
|
||||
y: l1.coordinates[i][0] // 16
|
||||
}, // 17
|
||||
a2 = { // 18
|
||||
x: l1.coordinates[i + 1][1], // 19
|
||||
y: l1.coordinates[i + 1][0] // 20
|
||||
}, // 21
|
||||
b1 = { // 22
|
||||
x: l2.coordinates[j][1], // 23
|
||||
y: l2.coordinates[j][0] // 24
|
||||
}, // 25
|
||||
b2 = { // 26
|
||||
x: l2.coordinates[j + 1][1], // 27
|
||||
y: l2.coordinates[j + 1][0] // 28
|
||||
}, // 29
|
||||
ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), // 30
|
||||
ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), // 31
|
||||
u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); // 32
|
||||
if (u_b != 0) { // 33
|
||||
var ua = ua_t / u_b, // 34
|
||||
ub = ub_t / u_b; // 35
|
||||
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { // 36
|
||||
intersects.push({ // 37
|
||||
'type': 'Point', // 38
|
||||
'coordinates': [a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)] // 39
|
||||
}); // 40
|
||||
} // 41
|
||||
} // 42
|
||||
} // 43
|
||||
} // 44
|
||||
if (intersects.length == 0) intersects = false; // 45
|
||||
return intersects; // 46
|
||||
} // 47
|
||||
// 48
|
||||
// Bounding Box // 49
|
||||
// 50
|
||||
function boundingBoxAroundPolyCoords (coords) { // 51
|
||||
var xAll = [], yAll = [] // 52
|
||||
// 53
|
||||
for (var i = 0; i < coords[0].length; i++) { // 54
|
||||
xAll.push(coords[0][i][1]) // 55
|
||||
yAll.push(coords[0][i][0]) // 56
|
||||
} // 57
|
||||
// 58
|
||||
xAll = xAll.sort(function (a,b) { return a - b }) // 59
|
||||
yAll = yAll.sort(function (a,b) { return a - b }) // 60
|
||||
// 61
|
||||
return [ [xAll[0], yAll[0]], [xAll[xAll.length - 1], yAll[yAll.length - 1]] ] // 62
|
||||
} // 63
|
||||
// 64
|
||||
gju.pointInBoundingBox = function (point, bounds) { // 65
|
||||
return !(point.coordinates[1] < bounds[0][0] || point.coordinates[1] > bounds[1][0] || point.coordinates[0] < bounds[0][1] || point.coordinates[0] > bounds[1][1])
|
||||
} // 67
|
||||
// 68
|
||||
// Point in Polygon // 69
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#Listing the Vertices // 70
|
||||
// 71
|
||||
function pnpoly (x,y,coords) { // 72
|
||||
var vert = [ [0,0] ] // 73
|
||||
// 74
|
||||
for (var i = 0; i < coords.length; i++) { // 75
|
||||
for (var j = 0; j < coords[i].length; j++) { // 76
|
||||
vert.push(coords[i][j]) // 77
|
||||
} // 78
|
||||
vert.push([0,0]) // 79
|
||||
} // 80
|
||||
// 81
|
||||
var inside = false // 82
|
||||
for (var i = 0, j = vert.length - 1; i < vert.length; j = i++) { // 83
|
||||
if (((vert[i][0] > y) != (vert[j][0] > y)) && (x < (vert[j][1] - vert[i][1]) * (y - vert[i][0]) / (vert[j][0] - vert[i][0]) + vert[i][1])) inside = !inside |
||||
} // 85
|
||||
// 86
|
||||
return inside // 87
|
||||
} // 88
|
||||
// 89
|
||||
gju.pointInPolygon = function (p, poly) { // 90
|
||||
var coords = (poly.type == "Polygon") ? [ poly.coordinates ] : poly.coordinates // 91
|
||||
// 92
|
||||
var insideBox = false // 93
|
||||
for (var i = 0; i < coords.length; i++) { // 94
|
||||
if (gju.pointInBoundingBox(p, boundingBoxAroundPolyCoords(coords[i]))) insideBox = true // 95
|
||||
} // 96
|
||||
if (!insideBox) return false // 97
|
||||
// 98
|
||||
var insidePoly = false // 99
|
||||
for (var i = 0; i < coords.length; i++) { // 100
|
||||
if (pnpoly(p.coordinates[1], p.coordinates[0], coords[i])) insidePoly = true // 101
|
||||
} // 102
|
||||
// 103
|
||||
return insidePoly // 104
|
||||
} // 105
|
||||
// 106
|
||||
gju.numberToRadius = function (number) { // 107
|
||||
return number * Math.PI / 180; // 108
|
||||
} // 109
|
||||
// 110
|
||||
gju.numberToDegree = function (number) { // 111
|
||||
return number * 180 / Math.PI; // 112
|
||||
} // 113
|
||||
// 114
|
||||
// written with help from @tautologe // 115
|
||||
gju.drawCircle = function (radiusInMeters, centerPoint, steps) { // 116
|
||||
var center = [centerPoint.coordinates[1], centerPoint.coordinates[0]], // 117
|
||||
dist = (radiusInMeters / 1000) / 6371, // 118
|
||||
// convert meters to radiant // 119
|
||||
radCenter = [gju.numberToRadius(center[0]), gju.numberToRadius(center[1])], // 120
|
||||
steps = steps || 15, // 121
|
||||
// 15 sided circle // 122
|
||||
poly = [[center[0], center[1]]]; // 123
|
||||
for (var i = 0; i < steps; i++) { // 124
|
||||
var brng = 2 * Math.PI * i / steps; // 125
|
||||
var lat = Math.asin(Math.sin(radCenter[0]) * Math.cos(dist) // 126
|
||||
+ Math.cos(radCenter[0]) * Math.sin(dist) * Math.cos(brng)); // 127
|
||||
var lng = radCenter[1] + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(radCenter[0]), // 128
|
||||
Math.cos(dist) - Math.sin(radCenter[0]) * Math.sin(lat)); // 129
|
||||
poly[i] = []; // 130
|
||||
poly[i][1] = gju.numberToDegree(lat); // 131
|
||||
poly[i][0] = gju.numberToDegree(lng); // 132
|
||||
} // 133
|
||||
return { // 134
|
||||
"type": "Polygon", // 135
|
||||
"coordinates": [poly] // 136
|
||||
}; // 137
|
||||
} // 138
|
||||
// 139
|
||||
// assumes rectangle starts at lower left point // 140
|
||||
gju.rectangleCentroid = function (rectangle) { // 141
|
||||
var bbox = rectangle.coordinates[0]; // 142
|
||||
var xmin = bbox[0][0], // 143
|
||||
ymin = bbox[0][1], // 144
|
||||
xmax = bbox[2][0], // 145
|
||||
ymax = bbox[2][1]; // 146
|
||||
var xwidth = xmax - xmin; // 147
|
||||
var ywidth = ymax - ymin; // 148
|
||||
return { // 149
|
||||
'type': 'Point', // 150
|
||||
'coordinates': [xmin + xwidth / 2, ymin + ywidth / 2] // 151
|
||||
}; // 152
|
||||
} // 153
|
||||
// 154
|
||||
// from http://www.movable-type.co.uk/scripts/latlong.html // 155
|
||||
gju.pointDistance = function (pt1, pt2) { // 156
|
||||
var lon1 = pt1.coordinates[0], // 157
|
||||
lat1 = pt1.coordinates[1], // 158
|
||||
lon2 = pt2.coordinates[0], // 159
|
||||
lat2 = pt2.coordinates[1], // 160
|
||||
dLat = gju.numberToRadius(lat2 - lat1), // 161
|
||||
dLon = gju.numberToRadius(lon2 - lon1), // 162
|
||||
a = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(gju.numberToRadius(lat1)) // 163
|
||||
* Math.cos(gju.numberToRadius(lat2)) * Math.pow(Math.sin(dLon / 2), 2), // 164
|
||||
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 165
|
||||
// Earth radius is 6371 km // 166
|
||||
return (6371 * c) * 1000; // returns meters // 167
|
||||
}, // 168
|
||||
// 169
|
||||
// checks if geometry lies entirely within a circle // 170
|
||||
// works with Point, LineString, Polygon // 171
|
||||
gju.geometryWithinRadius = function (geometry, center, radius) { // 172
|
||||
if (geometry.type == 'Point') { // 173
|
||||
return gju.pointDistance(geometry, center) <= radius; // 174
|
||||
} else if (geometry.type == 'LineString' || geometry.type == 'Polygon') { // 175
|
||||
var point = {}; // 176
|
||||
var coordinates; // 177
|
||||
if (geometry.type == 'Polygon') { // 178
|
||||
// it's enough to check the exterior ring of the Polygon // 179
|
||||
coordinates = geometry.coordinates[0]; // 180
|
||||
} else { // 181
|
||||
coordinates = geometry.coordinates; // 182
|
||||
} // 183
|
||||
for (var i in coordinates) { // 184
|
||||
point.coordinates = coordinates[i]; // 185
|
||||
if (gju.pointDistance(point, center) > radius) { // 186
|
||||
return false; // 187
|
||||
} // 188
|
||||
} // 189
|
||||
} // 190
|
||||
return true; // 191
|
||||
} // 192
|
||||
// 193
|
||||
// adapted from http://paulbourke.net/geometry/polyarea/javascript.txt // 194
|
||||
gju.area = function (polygon) { // 195
|
||||
var area = 0; // 196
|
||||
// TODO: polygon holes at coordinates[1] // 197
|
||||
var points = polygon.coordinates[0]; // 198
|
||||
var j = points.length - 1; // 199
|
||||
var p1, p2; // 200
|
||||
// 201
|
||||
for (var i = 0; i < points.length; j = i++) { // 202
|
||||
var p1 = { // 203
|
||||
x: points[i][1], // 204
|
||||
y: points[i][0] // 205
|
||||
}; // 206
|
||||
var p2 = { // 207
|
||||
x: points[j][1], // 208
|
||||
y: points[j][0] // 209
|
||||
}; // 210
|
||||
area += p1.x * p2.y; // 211
|
||||
area -= p1.y * p2.x; // 212
|
||||
} // 213
|
||||
// 214
|
||||
area /= 2; // 215
|
||||
return area; // 216
|
||||
}, // 217
|
||||
// 218
|
||||
// adapted from http://paulbourke.net/geometry/polyarea/javascript.txt // 219
|
||||
gju.centroid = function (polygon) { // 220
|
||||
var f, x = 0, // 221
|
||||
y = 0; // 222
|
||||
// TODO: polygon holes at coordinates[1] // 223
|
||||
var points = polygon.coordinates[0]; // 224
|
||||
var j = points.length - 1; // 225
|
||||
var p1, p2; // 226
|
||||
// 227
|
||||
for (var i = 0; i < points.length; j = i++) { // 228
|
||||
var p1 = { // 229
|
||||
x: points[i][1], // 230
|
||||
y: points[i][0] // 231
|
||||
}; // 232
|
||||
var p2 = { // 233
|
||||
x: points[j][1], // 234
|
||||
y: points[j][0] // 235
|
||||
}; // 236
|
||||
f = p1.x * p2.y - p2.x * p1.y; // 237
|
||||
x += (p1.x + p2.x) * f; // 238
|
||||
y += (p1.y + p2.y) * f; // 239
|
||||
} // 240
|
||||
// 241
|
||||
f = gju.area(polygon) * 6; // 242
|
||||
return { // 243
|
||||
'type': 'Point', // 244
|
||||
'coordinates': [y / f, x / f] // 245
|
||||
}; // 246
|
||||
}, // 247
|
||||
// 248
|
||||
gju.simplify = function (source, kink) { /* source[] array of geojson points */ // 249
|
||||
/* kink in metres, kinks above this depth kept */ // 250
|
||||
/* kink depth is the height of the triangle abc where a-b and b-c are two consecutive line segments */ // 251
|
||||
kink = kink || 20; // 252
|
||||
source = source.map(function (o) { // 253
|
||||
return { // 254
|
||||
lng: o.coordinates[0], // 255
|
||||
lat: o.coordinates[1] // 256
|
||||
} // 257
|
||||
}); // 258
|
||||
// 259
|
||||
var n_source, n_stack, n_dest, start, end, i, sig; // 260
|
||||
var dev_sqr, max_dev_sqr, band_sqr; // 261
|
||||
var x12, y12, d12, x13, y13, d13, x23, y23, d23; // 262
|
||||
var F = (Math.PI / 180.0) * 0.5; // 263
|
||||
var index = new Array(); /* aray of indexes of source points to include in the reduced line */ // 264
|
||||
var sig_start = new Array(); /* indices of start & end of working section */ // 265
|
||||
var sig_end = new Array(); // 266
|
||||
// 267
|
||||
/* check for simple cases */ // 268
|
||||
// 269
|
||||
if (source.length < 3) return (source); /* one or two points */ // 270
|
||||
// 271
|
||||
/* more complex case. initialize stack */ // 272
|
||||
// 273
|
||||
n_source = source.length; // 274
|
||||
band_sqr = kink * 360.0 / (2.0 * Math.PI * 6378137.0); /* Now in degrees */ // 275
|
||||
band_sqr *= band_sqr; // 276
|
||||
n_dest = 0; // 277
|
||||
sig_start[0] = 0; // 278
|
||||
sig_end[0] = n_source - 1; // 279
|
||||
n_stack = 1; // 280
|
||||
// 281
|
||||
/* while the stack is not empty ... */ // 282
|
||||
while (n_stack > 0) { // 283
|
||||
// 284
|
||||
/* ... pop the top-most entries off the stacks */ // 285
|
||||
// 286
|
||||
start = sig_start[n_stack - 1]; // 287
|
||||
end = sig_end[n_stack - 1]; // 288
|
||||
n_stack--; // 289
|
||||
// 290
|
||||
if ((end - start) > 1) { /* any intermediate points ? */ // 291
|
||||
// 292
|
||||
/* ... yes, so find most deviant intermediate point to // 293 |
||||
either side of line joining start & end points */ // 294 |
||||
// 295
|
||||
x12 = (source[end].lng() - source[start].lng()); // 296
|
||||
y12 = (source[end].lat() - source[start].lat()); // 297
|
||||
if (Math.abs(x12) > 180.0) x12 = 360.0 - Math.abs(x12); // 298
|
||||
x12 *= Math.cos(F * (source[end].lat() + source[start].lat())); /* use avg lat to reduce lng */ // 299
|
||||
d12 = (x12 * x12) + (y12 * y12); // 300
|
||||
// 301
|
||||
for (i = start + 1, sig = start, max_dev_sqr = -1.0; i < end; i++) { // 302
|
||||
// 303
|
||||
x13 = source[i].lng() - source[start].lng(); // 304
|
||||
y13 = source[i].lat() - source[start].lat(); // 305
|
||||
if (Math.abs(x13) > 180.0) x13 = 360.0 - Math.abs(x13); // 306
|
||||
x13 *= Math.cos(F * (source[i].lat() + source[start].lat())); // 307
|
||||
d13 = (x13 * x13) + (y13 * y13); // 308
|
||||
// 309
|
||||
x23 = source[i].lng() - source[end].lng(); // 310
|
||||
y23 = source[i].lat() - source[end].lat(); // 311
|
||||
if (Math.abs(x23) > 180.0) x23 = 360.0 - Math.abs(x23); // 312
|
||||
x23 *= Math.cos(F * (source[i].lat() + source[end].lat())); // 313
|
||||
d23 = (x23 * x23) + (y23 * y23); // 314
|
||||
// 315
|
||||
if (d13 >= (d12 + d23)) dev_sqr = d23; // 316
|
||||
else if (d23 >= (d12 + d13)) dev_sqr = d13; // 317
|
||||
else dev_sqr = (x13 * y12 - y13 * x12) * (x13 * y12 - y13 * x12) / d12; // solve triangle // 318
|
||||
if (dev_sqr > max_dev_sqr) { // 319
|
||||
sig = i; // 320
|
||||
max_dev_sqr = dev_sqr; // 321
|
||||
} // 322
|
||||
} // 323
|
||||
// 324
|
||||
if (max_dev_sqr < band_sqr) { /* is there a sig. intermediate point ? */ // 325
|
||||
/* ... no, so transfer current start point */ // 326
|
||||
index[n_dest] = start; // 327
|
||||
n_dest++; // 328
|
||||
} else { /* ... yes, so push two sub-sections on stack for further processing */ // 329
|
||||
n_stack++; // 330
|
||||
sig_start[n_stack - 1] = sig; // 331
|
||||
sig_end[n_stack - 1] = end; // 332
|
||||
n_stack++; // 333
|
||||
sig_start[n_stack - 1] = start; // 334
|
||||
sig_end[n_stack - 1] = sig; // 335
|
||||
} // 336
|
||||
} else { /* ... no intermediate points, so transfer current start point */ // 337
|
||||
index[n_dest] = start; // 338
|
||||
n_dest++; // 339
|
||||
} // 340
|
||||
} // 341
|
||||
// 342
|
||||
/* transfer last point */ // 343
|
||||
index[n_dest] = n_source - 1; // 344
|
||||
n_dest++; // 345
|
||||
// 346
|
||||
/* make return array */ // 347
|
||||
var r = new Array(); // 348
|
||||
for (var i = 0; i < n_dest; i++) // 349
|
||||
r.push(source[index[i]]); // 350
|
||||
// 351
|
||||
return r.map(function (o) { // 352
|
||||
return { // 353
|
||||
type: "Point", // 354
|
||||
coordinates: [o.lng, o.lat] // 355
|
||||
} // 356
|
||||
}); // 357
|
||||
} // 358
|
||||
// 359
|
||||
// http://www.movable-type.co.uk/scripts/latlong.html#destPoint // 360
|
||||
gju.destinationPoint = function (pt, brng, dist) { // 361
|
||||
dist = dist/6371; // convert dist to angular distance in radians // 362
|
||||
brng = gju.numberToRadius(brng); // 363
|
||||
// 364
|
||||
var lat1 = gju.numberToRadius(pt.coordinates[0]); // 365
|
||||
var lon1 = gju.numberToRadius(pt.coordinates[1]); // 366
|
||||
// 367
|
||||
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) + // 368
|
||||
Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) ); // 369
|
||||
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1), // 370
|
||||
Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2)); // 371
|
||||
lon2 = (lon2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º // 372
|
||||
// 373
|
||||
return { // 374
|
||||
'type': 'Point', // 375
|
||||
'coordinates': [gju.numberToDegree(lat2), gju.numberToDegree(lon2)] // 376
|
||||
}; // 377
|
||||
}; // 378
|
||||
// 379
|
||||
})(); // 380
|
||||
// 381
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/post.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This exports object was created in pre.js. Now copy the `exports` object // 1
|
||||
// from it into the package-scope variable `GeoJSON`, which will get exported. // 2
|
||||
GeoJSON = module.exports; // 3
|
||||
// 4
|
||||
// 5
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['geojson-utils'] = { |
||||
GeoJSON: GeoJSON |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=geojson-utils.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,28 @@ |
||||
/* Imports for global scope */ |
||||
|
||||
moment = Package['momentjs:moment'].moment; |
||||
lodash = Package['stevezhu:lodash'].lodash; |
||||
_ = Package.underscore._; |
||||
numeral = Package['numeral:numeral'].numeral; |
||||
topojson = Package['mrt:topojson'].topojson; |
||||
Meteor = Package.meteor.Meteor; |
||||
WebApp = Package.webapp.WebApp; |
||||
main = Package.webapp.main; |
||||
WebAppInternals = Package.webapp.WebAppInternals; |
||||
Log = Package.logging.Log; |
||||
Tracker = Package.deps.Tracker; |
||||
Deps = Package.deps.Deps; |
||||
DDP = Package.livedata.DDP; |
||||
DDPServer = Package.livedata.DDPServer; |
||||
MongoInternals = Package.mongo.MongoInternals; |
||||
Mongo = Package.mongo.Mongo; |
||||
Blaze = Package.ui.Blaze; |
||||
UI = Package.ui.UI; |
||||
Handlebars = Package.ui.Handlebars; |
||||
Spacebars = Package.spacebars.Spacebars; |
||||
check = Package.check.check; |
||||
Match = Package.check.Match; |
||||
Random = Package.random.Random; |
||||
EJSON = Package.ejson.EJSON; |
||||
HTML = Package.htmljs.HTML; |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,664 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Tracker = Package.tracker.Tracker; |
||||
var Deps = Package.tracker.Deps; |
||||
|
||||
/* Package-scope variables */ |
||||
var HTML, IDENTITY, SLICE; |
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/preamble.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
HTML = {}; // 1
|
||||
// 2
|
||||
IDENTITY = function (x) { return x; }; // 3
|
||||
SLICE = Array.prototype.slice; // 4
|
||||
// 5
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/visitors.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////// VISITORS // 1
|
||||
// 2
|
||||
// _assign is like _.extend or the upcoming Object.assign. // 3
|
||||
// Copy src's own, enumerable properties onto tgt and return // 4
|
||||
// tgt. // 5
|
||||
var _hasOwnProperty = Object.prototype.hasOwnProperty; // 6
|
||||
var _assign = function (tgt, src) { // 7
|
||||
for (var k in src) { // 8
|
||||
if (_hasOwnProperty.call(src, k)) // 9
|
||||
tgt[k] = src[k]; // 10
|
||||
} // 11
|
||||
return tgt; // 12
|
||||
}; // 13
|
||||
// 14
|
||||
HTML.Visitor = function (props) { // 15
|
||||
_assign(this, props); // 16
|
||||
}; // 17
|
||||
// 18
|
||||
HTML.Visitor.def = function (options) { // 19
|
||||
_assign(this.prototype, options); // 20
|
||||
}; // 21
|
||||
// 22
|
||||
HTML.Visitor.extend = function (options) { // 23
|
||||
var curType = this; // 24
|
||||
var subType = function HTMLVisitorSubtype(/*arguments*/) { // 25
|
||||
HTML.Visitor.apply(this, arguments); // 26
|
||||
}; // 27
|
||||
subType.prototype = new curType; // 28
|
||||
subType.extend = curType.extend; // 29
|
||||
subType.def = curType.def; // 30
|
||||
if (options) // 31
|
||||
_assign(subType.prototype, options); // 32
|
||||
return subType; // 33
|
||||
}; // 34
|
||||
// 35
|
||||
HTML.Visitor.def({ // 36
|
||||
visit: function (content/*, ...*/) { // 37
|
||||
if (content == null) // 38
|
||||
// null or undefined. // 39
|
||||
return this.visitNull.apply(this, arguments); // 40
|
||||
// 41
|
||||
if (typeof content === 'object') { // 42
|
||||
if (content.htmljsType) { // 43
|
||||
switch (content.htmljsType) { // 44
|
||||
case HTML.Tag.htmljsType: // 45
|
||||
return this.visitTag.apply(this, arguments); // 46
|
||||
case HTML.CharRef.htmljsType: // 47
|
||||
return this.visitCharRef.apply(this, arguments); // 48
|
||||
case HTML.Comment.htmljsType: // 49
|
||||
return this.visitComment.apply(this, arguments); // 50
|
||||
case HTML.Raw.htmljsType: // 51
|
||||
return this.visitRaw.apply(this, arguments); // 52
|
||||
default: // 53
|
||||
throw new Error("Unknown htmljs type: " + content.htmljsType); // 54
|
||||
} // 55
|
||||
} // 56
|
||||
// 57
|
||||
if (HTML.isArray(content)) // 58
|
||||
return this.visitArray.apply(this, arguments); // 59
|
||||
// 60
|
||||
return this.visitObject.apply(this, arguments); // 61
|
||||
// 62
|
||||
} else if ((typeof content === 'string') || // 63
|
||||
(typeof content === 'boolean') || // 64
|
||||
(typeof content === 'number')) { // 65
|
||||
return this.visitPrimitive.apply(this, arguments); // 66
|
||||
// 67
|
||||
} else if (typeof content === 'function') { // 68
|
||||
return this.visitFunction.apply(this, arguments); // 69
|
||||
} // 70
|
||||
// 71
|
||||
throw new Error("Unexpected object in htmljs: " + content); // 72
|
||||
// 73
|
||||
}, // 74
|
||||
visitNull: function (nullOrUndefined/*, ...*/) {}, // 75
|
||||
visitPrimitive: function (stringBooleanOrNumber/*, ...*/) {}, // 76
|
||||
visitArray: function (array/*, ...*/) {}, // 77
|
||||
visitComment: function (comment/*, ...*/) {}, // 78
|
||||
visitCharRef: function (charRef/*, ...*/) {}, // 79
|
||||
visitRaw: function (raw/*, ...*/) {}, // 80
|
||||
visitTag: function (tag/*, ...*/) {}, // 81
|
||||
visitObject: function (obj/*, ...*/) { // 82
|
||||
throw new Error("Unexpected object in htmljs: " + obj); // 83
|
||||
}, // 84
|
||||
visitFunction: function (obj/*, ...*/) { // 85
|
||||
throw new Error("Unexpected function in htmljs: " + obj); // 86
|
||||
} // 87
|
||||
}); // 88
|
||||
// 89
|
||||
HTML.TransformingVisitor = HTML.Visitor.extend(); // 90
|
||||
HTML.TransformingVisitor.def({ // 91
|
||||
visitNull: IDENTITY, // 92
|
||||
visitPrimitive: IDENTITY, // 93
|
||||
visitArray: function (array/*, ...*/) { // 94
|
||||
var argsCopy = SLICE.call(arguments); // 95
|
||||
var result = array; // 96
|
||||
for (var i = 0; i < array.length; i++) { // 97
|
||||
var oldItem = array[i]; // 98
|
||||
argsCopy[0] = oldItem; // 99
|
||||
var newItem = this.visit.apply(this, argsCopy); // 100
|
||||
if (newItem !== oldItem) { // 101
|
||||
// copy `array` on write // 102
|
||||
if (result === array) // 103
|
||||
result = array.slice(); // 104
|
||||
result[i] = newItem; // 105
|
||||
} // 106
|
||||
} // 107
|
||||
return result; // 108
|
||||
}, // 109
|
||||
visitComment: IDENTITY, // 110
|
||||
visitCharRef: IDENTITY, // 111
|
||||
visitRaw: IDENTITY, // 112
|
||||
visitObject: IDENTITY, // 113
|
||||
visitFunction: IDENTITY, // 114
|
||||
visitTag: function (tag/*, ...*/) { // 115
|
||||
var oldChildren = tag.children; // 116
|
||||
var argsCopy = SLICE.call(arguments); // 117
|
||||
argsCopy[0] = oldChildren; // 118
|
||||
var newChildren = this.visitChildren.apply(this, argsCopy); // 119
|
||||
// 120
|
||||
var oldAttrs = tag.attrs; // 121
|
||||
argsCopy[0] = oldAttrs; // 122
|
||||
var newAttrs = this.visitAttributes.apply(this, argsCopy); // 123
|
||||
// 124
|
||||
if (newAttrs === oldAttrs && newChildren === oldChildren) // 125
|
||||
return tag; // 126
|
||||
// 127
|
||||
var newTag = HTML.getTag(tag.tagName).apply(null, newChildren); // 128
|
||||
newTag.attrs = newAttrs; // 129
|
||||
return newTag; // 130
|
||||
}, // 131
|
||||
visitChildren: function (children/*, ...*/) { // 132
|
||||
return this.visitArray.apply(this, arguments); // 133
|
||||
}, // 134
|
||||
// Transform the `.attrs` property of a tag, which may be a dictionary, // 135
|
||||
// an array, or in some uses, a foreign object (such as // 136
|
||||
// a template tag). // 137
|
||||
visitAttributes: function (attrs/*, ...*/) { // 138
|
||||
if (HTML.isArray(attrs)) { // 139
|
||||
var argsCopy = SLICE.call(arguments); // 140
|
||||
var result = attrs; // 141
|
||||
for (var i = 0; i < attrs.length; i++) { // 142
|
||||
var oldItem = attrs[i]; // 143
|
||||
argsCopy[0] = oldItem; // 144
|
||||
var newItem = this.visitAttributes.apply(this, argsCopy); // 145
|
||||
if (newItem !== oldItem) { // 146
|
||||
// copy on write // 147
|
||||
if (result === attrs) // 148
|
||||
result = attrs.slice(); // 149
|
||||
result[i] = newItem; // 150
|
||||
} // 151
|
||||
} // 152
|
||||
return result; // 153
|
||||
} // 154
|
||||
// 155
|
||||
if (attrs && HTML.isConstructedObject(attrs)) { // 156
|
||||
throw new Error("The basic HTML.TransformingVisitor does not support " + // 157
|
||||
"foreign objects in attributes. Define a custom " + // 158
|
||||
"visitAttributes for this case."); // 159
|
||||
} // 160
|
||||
// 161
|
||||
var oldAttrs = attrs; // 162
|
||||
var newAttrs = oldAttrs; // 163
|
||||
if (oldAttrs) { // 164
|
||||
var attrArgs = [null, null]; // 165
|
||||
attrArgs.push.apply(attrArgs, arguments); // 166
|
||||
for (var k in oldAttrs) { // 167
|
||||
var oldValue = oldAttrs[k]; // 168
|
||||
attrArgs[0] = k; // 169
|
||||
attrArgs[1] = oldValue; // 170
|
||||
var newValue = this.visitAttribute.apply(this, attrArgs); // 171
|
||||
if (newValue !== oldValue) { // 172
|
||||
// copy on write // 173
|
||||
if (newAttrs === oldAttrs) // 174
|
||||
newAttrs = _assign({}, oldAttrs); // 175
|
||||
newAttrs[k] = newValue; // 176
|
||||
} // 177
|
||||
} // 178
|
||||
} // 179
|
||||
// 180
|
||||
return newAttrs; // 181
|
||||
}, // 182
|
||||
// Transform the value of one attribute name/value in an // 183
|
||||
// attributes dictionary. // 184
|
||||
visitAttribute: function (name, value, tag/*, ...*/) { // 185
|
||||
var args = SLICE.call(arguments, 2); // 186
|
||||
args[0] = value; // 187
|
||||
return this.visit.apply(this, args); // 188
|
||||
} // 189
|
||||
}); // 190
|
||||
// 191
|
||||
// 192
|
||||
HTML.ToTextVisitor = HTML.Visitor.extend(); // 193
|
||||
HTML.ToTextVisitor.def({ // 194
|
||||
visitNull: function (nullOrUndefined) { // 195
|
||||
return ''; // 196
|
||||
}, // 197
|
||||
visitPrimitive: function (stringBooleanOrNumber) { // 198
|
||||
var str = String(stringBooleanOrNumber); // 199
|
||||
if (this.textMode === HTML.TEXTMODE.RCDATA) { // 200
|
||||
return str.replace(/&/g, '&').replace(/</g, '<'); // 201
|
||||
} else if (this.textMode === HTML.TEXTMODE.ATTRIBUTE) { // 202
|
||||
// escape `&` and `"` this time, not `&` and `<` // 203
|
||||
return str.replace(/&/g, '&').replace(/"/g, '"'); // 204
|
||||
} else { // 205
|
||||
return str; // 206
|
||||
} // 207
|
||||
}, // 208
|
||||
visitArray: function (array) { // 209
|
||||
var parts = []; // 210
|
||||
for (var i = 0; i < array.length; i++) // 211
|
||||
parts.push(this.visit(array[i])); // 212
|
||||
return parts.join(''); // 213
|
||||
}, // 214
|
||||
visitComment: function (comment) { // 215
|
||||
throw new Error("Can't have a comment here"); // 216
|
||||
}, // 217
|
||||
visitCharRef: function (charRef) { // 218
|
||||
if (this.textMode === HTML.TEXTMODE.RCDATA || // 219
|
||||
this.textMode === HTML.TEXTMODE.ATTRIBUTE) { // 220
|
||||
return charRef.html; // 221
|
||||
} else { // 222
|
||||
return charRef.str; // 223
|
||||
} // 224
|
||||
}, // 225
|
||||
visitRaw: function (raw) { // 226
|
||||
return raw.value; // 227
|
||||
}, // 228
|
||||
visitTag: function (tag) { // 229
|
||||
// Really we should just disallow Tags here. However, at the // 230
|
||||
// moment it's useful to stringify any HTML we find. In // 231
|
||||
// particular, when you include a template within `{{#markdown}}`, // 232
|
||||
// we render the template as text, and since there's currently // 233
|
||||
// no way to make the template be *parsed* as text (e.g. `<template // 234
|
||||
// type="text">`), we hackishly support HTML tags in markdown // 235
|
||||
// in templates by parsing them and stringifying them. // 236
|
||||
return this.visit(this.toHTML(tag)); // 237
|
||||
}, // 238
|
||||
visitObject: function (x) { // 239
|
||||
throw new Error("Unexpected object in htmljs in toText: " + x); // 240
|
||||
}, // 241
|
||||
toHTML: function (node) { // 242
|
||||
return HTML.toHTML(node); // 243
|
||||
} // 244
|
||||
}); // 245
|
||||
// 246
|
||||
// 247
|
||||
// 248
|
||||
HTML.ToHTMLVisitor = HTML.Visitor.extend(); // 249
|
||||
HTML.ToHTMLVisitor.def({ // 250
|
||||
visitNull: function (nullOrUndefined) { // 251
|
||||
return ''; // 252
|
||||
}, // 253
|
||||
visitPrimitive: function (stringBooleanOrNumber) { // 254
|
||||
var str = String(stringBooleanOrNumber); // 255
|
||||
return str.replace(/&/g, '&').replace(/</g, '<'); // 256
|
||||
}, // 257
|
||||
visitArray: function (array) { // 258
|
||||
var parts = []; // 259
|
||||
for (var i = 0; i < array.length; i++) // 260
|
||||
parts.push(this.visit(array[i])); // 261
|
||||
return parts.join(''); // 262
|
||||
}, // 263
|
||||
visitComment: function (comment) { // 264
|
||||
return '<!--' + comment.sanitizedValue + '-->'; // 265
|
||||
}, // 266
|
||||
visitCharRef: function (charRef) { // 267
|
||||
return charRef.html; // 268
|
||||
}, // 269
|
||||
visitRaw: function (raw) { // 270
|
||||
return raw.value; // 271
|
||||
}, // 272
|
||||
visitTag: function (tag) { // 273
|
||||
var attrStrs = []; // 274
|
||||
// 275
|
||||
var tagName = tag.tagName; // 276
|
||||
var children = tag.children; // 277
|
||||
// 278
|
||||
var attrs = tag.attrs; // 279
|
||||
if (attrs) { // 280
|
||||
attrs = HTML.flattenAttributes(attrs); // 281
|
||||
for (var k in attrs) { // 282
|
||||
if (k === 'value' && tagName === 'textarea') { // 283
|
||||
children = [attrs[k], children]; // 284
|
||||
} else { // 285
|
||||
var v = this.toText(attrs[k], HTML.TEXTMODE.ATTRIBUTE); // 286
|
||||
attrStrs.push(' ' + k + '="' + v + '"'); // 287
|
||||
} // 288
|
||||
} // 289
|
||||
} // 290
|
||||
// 291
|
||||
var startTag = '<' + tagName + attrStrs.join('') + '>'; // 292
|
||||
// 293
|
||||
var childStrs = []; // 294
|
||||
var content; // 295
|
||||
if (tagName === 'textarea') { // 296
|
||||
// 297
|
||||
for (var i = 0; i < children.length; i++) // 298
|
||||
childStrs.push(this.toText(children[i], HTML.TEXTMODE.RCDATA)); // 299
|
||||
// 300
|
||||
content = childStrs.join(''); // 301
|
||||
if (content.slice(0, 1) === '\n') // 302
|
||||
// TEXTAREA will absorb a newline, so if we see one, add // 303
|
||||
// another one. // 304
|
||||
content = '\n' + content; // 305
|
||||
// 306
|
||||
} else { // 307
|
||||
for (var i = 0; i < children.length; i++) // 308
|
||||
childStrs.push(this.visit(children[i])); // 309
|
||||
// 310
|
||||
content = childStrs.join(''); // 311
|
||||
} // 312
|
||||
// 313
|
||||
var result = startTag + content; // 314
|
||||
// 315
|
||||
if (children.length || ! HTML.isVoidElement(tagName)) { // 316
|
||||
// "Void" elements like BR are the only ones that don't get a close // 317
|
||||
// tag in HTML5. They shouldn't have contents, either, so we could // 318
|
||||
// throw an error upon seeing contents here. // 319
|
||||
result += '</' + tagName + '>'; // 320
|
||||
} // 321
|
||||
// 322
|
||||
return result; // 323
|
||||
}, // 324
|
||||
visitObject: function (x) { // 325
|
||||
throw new Error("Unexpected object in htmljs in toHTML: " + x); // 326
|
||||
}, // 327
|
||||
toText: function (node, textMode) { // 328
|
||||
return HTML.toText(node, textMode); // 329
|
||||
} // 330
|
||||
}); // 331
|
||||
// 332
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/html.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 1
|
||||
// 2
|
||||
HTML.Tag = function () {}; // 3
|
||||
HTML.Tag.prototype.tagName = ''; // this will be set per Tag subclass // 4
|
||||
HTML.Tag.prototype.attrs = null; // 5
|
||||
HTML.Tag.prototype.children = Object.freeze ? Object.freeze([]) : []; // 6
|
||||
HTML.Tag.prototype.htmljsType = HTML.Tag.htmljsType = ['Tag']; // 7
|
||||
// 8
|
||||
// Given "p" create the function `HTML.P`. // 9
|
||||
var makeTagConstructor = function (tagName) { // 10
|
||||
// HTMLTag is the per-tagName constructor of a HTML.Tag subclass // 11
|
||||
var HTMLTag = function (/*arguments*/) { // 12
|
||||
// Work with or without `new`. If not called with `new`, // 13
|
||||
// perform instantiation by recursively calling this constructor. // 14
|
||||
// We can't pass varargs, so pass no args. // 15
|
||||
var instance = (this instanceof HTML.Tag) ? this : new HTMLTag; // 16
|
||||
// 17
|
||||
var i = 0; // 18
|
||||
var attrs = arguments.length && arguments[0]; // 19
|
||||
if (attrs && (typeof attrs === 'object')) { // 20
|
||||
// Treat vanilla JS object as an attributes dictionary. // 21
|
||||
if (! HTML.isConstructedObject(attrs)) { // 22
|
||||
instance.attrs = attrs; // 23
|
||||
i++; // 24
|
||||
} else if (attrs instanceof HTML.Attrs) { // 25
|
||||
var array = attrs.value; // 26
|
||||
if (array.length === 1) { // 27
|
||||
instance.attrs = array[0]; // 28
|
||||
} else if (array.length > 1) { // 29
|
||||
instance.attrs = array; // 30
|
||||
} // 31
|
||||
i++; // 32
|
||||
} // 33
|
||||
} // 34
|
||||
// 35
|
||||
// 36
|
||||
// If no children, don't create an array at all, use the prototype's // 37
|
||||
// (frozen, empty) array. This way we don't create an empty array // 38
|
||||
// every time someone creates a tag without `new` and this constructor // 39
|
||||
// calls itself with no arguments (above). // 40
|
||||
if (i < arguments.length) // 41
|
||||
instance.children = SLICE.call(arguments, i); // 42
|
||||
// 43
|
||||
return instance; // 44
|
||||
}; // 45
|
||||
HTMLTag.prototype = new HTML.Tag; // 46
|
||||
HTMLTag.prototype.constructor = HTMLTag; // 47
|
||||
HTMLTag.prototype.tagName = tagName; // 48
|
||||
// 49
|
||||
return HTMLTag; // 50
|
||||
}; // 51
|
||||
// 52
|
||||
// Not an HTMLjs node, but a wrapper to pass multiple attrs dictionaries // 53
|
||||
// to a tag (for the purpose of implementing dynamic attributes). // 54
|
||||
var Attrs = HTML.Attrs = function (/*attrs dictionaries*/) { // 55
|
||||
// Work with or without `new`. If not called with `new`, // 56
|
||||
// perform instantiation by recursively calling this constructor. // 57
|
||||
// We can't pass varargs, so pass no args. // 58
|
||||
var instance = (this instanceof Attrs) ? this : new Attrs; // 59
|
||||
// 60
|
||||
instance.value = SLICE.call(arguments); // 61
|
||||
// 62
|
||||
return instance; // 63
|
||||
}; // 64
|
||||
// 65
|
||||
////////////////////////////// KNOWN ELEMENTS // 66
|
||||
// 67
|
||||
HTML.getTag = function (tagName) { // 68
|
||||
var symbolName = HTML.getSymbolName(tagName); // 69
|
||||
if (symbolName === tagName) // all-caps tagName // 70
|
||||
throw new Error("Use the lowercase or camelCase form of '" + tagName + "' here"); // 71
|
||||
// 72
|
||||
if (! HTML[symbolName]) // 73
|
||||
HTML[symbolName] = makeTagConstructor(tagName); // 74
|
||||
// 75
|
||||
return HTML[symbolName]; // 76
|
||||
}; // 77
|
||||
// 78
|
||||
HTML.ensureTag = function (tagName) { // 79
|
||||
HTML.getTag(tagName); // don't return it // 80
|
||||
}; // 81
|
||||
// 82
|
||||
HTML.isTagEnsured = function (tagName) { // 83
|
||||
return HTML.isKnownElement(tagName); // 84
|
||||
}; // 85
|
||||
// 86
|
||||
HTML.getSymbolName = function (tagName) { // 87
|
||||
// "foo-bar" -> "FOO_BAR" // 88
|
||||
return tagName.toUpperCase().replace(/-/g, '_'); // 89
|
||||
}; // 90
|
||||
// 91
|
||||
HTML.knownElementNames = 'a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption center cite code col colgroup command data datagrid datalist dd del details dfn dir div dl dt em embed eventsource fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins isindex kbd keygen label legend li link main map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr'.split(' '); |
||||
// (we add the SVG ones below) // 93
|
||||
// 94
|
||||
HTML.knownSVGElementNames = 'altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform circle clipPath color-profile cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient marker mask metadata missing-glyph path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tref tspan use view vkern'.split(' '); |
||||
// Append SVG element names to list of known element names // 96
|
||||
HTML.knownElementNames = HTML.knownElementNames.concat(HTML.knownSVGElementNames); // 97
|
||||
// 98
|
||||
HTML.voidElementNames = 'area base br col command embed hr img input keygen link meta param source track wbr'.split(' '); |
||||
// 100
|
||||
// Speed up search through lists of known elements by creating internal "sets" // 101
|
||||
// of strings. // 102
|
||||
var YES = {yes:true}; // 103
|
||||
var makeSet = function (array) { // 104
|
||||
var set = {}; // 105
|
||||
for (var i = 0; i < array.length; i++) // 106
|
||||
set[array[i]] = YES; // 107
|
||||
return set; // 108
|
||||
}; // 109
|
||||
var voidElementSet = makeSet(HTML.voidElementNames); // 110
|
||||
var knownElementSet = makeSet(HTML.knownElementNames); // 111
|
||||
var knownSVGElementSet = makeSet(HTML.knownSVGElementNames); // 112
|
||||
// 113
|
||||
HTML.isKnownElement = function (tagName) { // 114
|
||||
return knownElementSet[tagName] === YES; // 115
|
||||
}; // 116
|
||||
// 117
|
||||
HTML.isKnownSVGElement = function (tagName) { // 118
|
||||
return knownSVGElementSet[tagName] === YES; // 119
|
||||
}; // 120
|
||||
// 121
|
||||
HTML.isVoidElement = function (tagName) { // 122
|
||||
return voidElementSet[tagName] === YES; // 123
|
||||
}; // 124
|
||||
// 125
|
||||
// 126
|
||||
// Ensure tags for all known elements // 127
|
||||
for (var i = 0; i < HTML.knownElementNames.length; i++) // 128
|
||||
HTML.ensureTag(HTML.knownElementNames[i]); // 129
|
||||
// 130
|
||||
// 131
|
||||
var CharRef = HTML.CharRef = function (attrs) { // 132
|
||||
if (! (this instanceof CharRef)) // 133
|
||||
// called without `new` // 134
|
||||
return new CharRef(attrs); // 135
|
||||
// 136
|
||||
if (! (attrs && attrs.html && attrs.str)) // 137
|
||||
throw new Error( // 138
|
||||
"HTML.CharRef must be constructed with ({html:..., str:...})"); // 139
|
||||
// 140
|
||||
this.html = attrs.html; // 141
|
||||
this.str = attrs.str; // 142
|
||||
}; // 143
|
||||
CharRef.prototype.htmljsType = CharRef.htmljsType = ['CharRef']; // 144
|
||||
// 145
|
||||
var Comment = HTML.Comment = function (value) { // 146
|
||||
if (! (this instanceof Comment)) // 147
|
||||
// called without `new` // 148
|
||||
return new Comment(value); // 149
|
||||
// 150
|
||||
if (typeof value !== 'string') // 151
|
||||
throw new Error('HTML.Comment must be constructed with a string'); // 152
|
||||
// 153
|
||||
this.value = value; // 154
|
||||
// Kill illegal hyphens in comment value (no way to escape them in HTML) // 155
|
||||
this.sanitizedValue = value.replace(/^-|--+|-$/g, ''); // 156
|
||||
}; // 157
|
||||
Comment.prototype.htmljsType = Comment.htmljsType = ['Comment']; // 158
|
||||
// 159
|
||||
var Raw = HTML.Raw = function (value) { // 160
|
||||
if (! (this instanceof Raw)) // 161
|
||||
// called without `new` // 162
|
||||
return new Raw(value); // 163
|
||||
// 164
|
||||
if (typeof value !== 'string') // 165
|
||||
throw new Error('HTML.Raw must be constructed with a string'); // 166
|
||||
// 167
|
||||
this.value = value; // 168
|
||||
}; // 169
|
||||
Raw.prototype.htmljsType = Raw.htmljsType = ['Raw']; // 170
|
||||
// 171
|
||||
// 172
|
||||
HTML.isArray = function (x) { // 173
|
||||
// could change this to use the more convoluted Object.prototype.toString // 174
|
||||
// approach that works when objects are passed between frames, but does // 175
|
||||
// it matter? // 176
|
||||
return (x instanceof Array); // 177
|
||||
}; // 178
|
||||
// 179
|
||||
HTML.isConstructedObject = function (x) { // 180
|
||||
return (x && (typeof x === 'object') && // 181
|
||||
(x.constructor !== Object) && // 182
|
||||
(! Object.prototype.hasOwnProperty.call(x, 'constructor'))); // 183
|
||||
}; // 184
|
||||
// 185
|
||||
HTML.isNully = function (node) { // 186
|
||||
if (node == null) // 187
|
||||
// null or undefined // 188
|
||||
return true; // 189
|
||||
// 190
|
||||
if (HTML.isArray(node)) { // 191
|
||||
// is it an empty array or an array of all nully items? // 192
|
||||
for (var i = 0; i < node.length; i++) // 193
|
||||
if (! HTML.isNully(node[i])) // 194
|
||||
return false; // 195
|
||||
return true; // 196
|
||||
} // 197
|
||||
// 198
|
||||
return false; // 199
|
||||
}; // 200
|
||||
// 201
|
||||
HTML.isValidAttributeName = function (name) { // 202
|
||||
return /^[:_A-Za-z][:_A-Za-z0-9.\-]*/.test(name); // 203
|
||||
}; // 204
|
||||
// 205
|
||||
// If `attrs` is an array of attributes dictionaries, combines them // 206
|
||||
// into one. Removes attributes that are "nully." // 207
|
||||
HTML.flattenAttributes = function (attrs) { // 208
|
||||
if (! attrs) // 209
|
||||
return attrs; // 210
|
||||
// 211
|
||||
var isArray = HTML.isArray(attrs); // 212
|
||||
if (isArray && attrs.length === 0) // 213
|
||||
return null; // 214
|
||||
// 215
|
||||
var result = {}; // 216
|
||||
for (var i = 0, N = (isArray ? attrs.length : 1); i < N; i++) { // 217
|
||||
var oneAttrs = (isArray ? attrs[i] : attrs); // 218
|
||||
if ((typeof oneAttrs !== 'object') || // 219
|
||||
HTML.isConstructedObject(oneAttrs)) // 220
|
||||
throw new Error("Expected plain JS object as attrs, found: " + oneAttrs); // 221
|
||||
for (var name in oneAttrs) { // 222
|
||||
if (! HTML.isValidAttributeName(name)) // 223
|
||||
throw new Error("Illegal HTML attribute name: " + name); // 224
|
||||
var value = oneAttrs[name]; // 225
|
||||
if (! HTML.isNully(value)) // 226
|
||||
result[name] = value; // 227
|
||||
} // 228
|
||||
} // 229
|
||||
// 230
|
||||
return result; // 231
|
||||
}; // 232
|
||||
// 233
|
||||
// 234
|
||||
// 235
|
||||
////////////////////////////// TOHTML // 236
|
||||
// 237
|
||||
HTML.toHTML = function (content) { // 238
|
||||
return (new HTML.ToHTMLVisitor).visit(content); // 239
|
||||
}; // 240
|
||||
// 241
|
||||
// Escaping modes for outputting text when generating HTML. // 242
|
||||
HTML.TEXTMODE = { // 243
|
||||
STRING: 1, // 244
|
||||
RCDATA: 2, // 245
|
||||
ATTRIBUTE: 3 // 246
|
||||
}; // 247
|
||||
// 248
|
||||
// 249
|
||||
HTML.toText = function (content, textMode) { // 250
|
||||
if (! textMode) // 251
|
||||
throw new Error("textMode required for HTML.toText"); // 252
|
||||
if (! (textMode === HTML.TEXTMODE.STRING || // 253
|
||||
textMode === HTML.TEXTMODE.RCDATA || // 254
|
||||
textMode === HTML.TEXTMODE.ATTRIBUTE)) // 255
|
||||
throw new Error("Unknown textMode: " + textMode); // 256
|
||||
// 257
|
||||
var visitor = new HTML.ToTextVisitor({textMode: textMode});; // 258
|
||||
return visitor.visit(content); // 259
|
||||
}; // 260
|
||||
// 261
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.htmljs = { |
||||
HTML: HTML |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=htmljs.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,110 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var EJSON = Package.ejson.EJSON; |
||||
|
||||
/* Package-scope variables */ |
||||
var IdMap; |
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/id-map/id-map.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
IdMap = function (idStringify, idParse) { // 1
|
||||
var self = this; // 2
|
||||
self._map = {}; // 3
|
||||
self._idStringify = idStringify || JSON.stringify; // 4
|
||||
self._idParse = idParse || JSON.parse; // 5
|
||||
}; // 6
|
||||
// 7
|
||||
// Some of these methods are designed to match methods on OrderedDict, since // 8
|
||||
// (eg) ObserveMultiplex and _CachingChangeObserver use them interchangeably. // 9
|
||||
// (Conceivably, this should be replaced with "UnorderedDict" with a specific // 10
|
||||
// set of methods that overlap between the two.) // 11
|
||||
// 12
|
||||
_.extend(IdMap.prototype, { // 13
|
||||
get: function (id) { // 14
|
||||
var self = this; // 15
|
||||
var key = self._idStringify(id); // 16
|
||||
return self._map[key]; // 17
|
||||
}, // 18
|
||||
set: function (id, value) { // 19
|
||||
var self = this; // 20
|
||||
var key = self._idStringify(id); // 21
|
||||
self._map[key] = value; // 22
|
||||
}, // 23
|
||||
remove: function (id) { // 24
|
||||
var self = this; // 25
|
||||
var key = self._idStringify(id); // 26
|
||||
delete self._map[key]; // 27
|
||||
}, // 28
|
||||
has: function (id) { // 29
|
||||
var self = this; // 30
|
||||
var key = self._idStringify(id); // 31
|
||||
return _.has(self._map, key); // 32
|
||||
}, // 33
|
||||
empty: function () { // 34
|
||||
var self = this; // 35
|
||||
return _.isEmpty(self._map); // 36
|
||||
}, // 37
|
||||
clear: function () { // 38
|
||||
var self = this; // 39
|
||||
self._map = {}; // 40
|
||||
}, // 41
|
||||
// Iterates over the items in the map. Return `false` to break the loop. // 42
|
||||
forEach: function (iterator) { // 43
|
||||
var self = this; // 44
|
||||
// don't use _.each, because we can't break out of it. // 45
|
||||
var keys = _.keys(self._map); // 46
|
||||
for (var i = 0; i < keys.length; i++) { // 47
|
||||
var breakIfFalse = iterator.call(null, self._map[keys[i]], // 48
|
||||
self._idParse(keys[i])); // 49
|
||||
if (breakIfFalse === false) // 50
|
||||
return; // 51
|
||||
} // 52
|
||||
}, // 53
|
||||
size: function () { // 54
|
||||
var self = this; // 55
|
||||
return _.size(self._map); // 56
|
||||
}, // 57
|
||||
setDefault: function (id, def) { // 58
|
||||
var self = this; // 59
|
||||
var key = self._idStringify(id); // 60
|
||||
if (_.has(self._map, key)) // 61
|
||||
return self._map[key]; // 62
|
||||
self._map[key] = def; // 63
|
||||
return def; // 64
|
||||
}, // 65
|
||||
// Assumes that values are EJSON-cloneable, and that we don't need to clone // 66
|
||||
// IDs (ie, that nobody is going to mutate an ObjectId). // 67
|
||||
clone: function () { // 68
|
||||
var self = this; // 69
|
||||
var clone = new IdMap(self._idStringify, self._idParse); // 70
|
||||
self.forEach(function (value, id) { // 71
|
||||
clone.set(id, EJSON.clone(value)); // 72
|
||||
}); // 73
|
||||
return clone; // 74
|
||||
} // 75
|
||||
}); // 76
|
||||
// 77
|
||||
// 78
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['id-map'] = { |
||||
IdMap: IdMap |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=id-map.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["id-map/id-map.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,yC;AACA,kB;AACA,iB;AACA,oD;AACA,wC;AACA,E;;AAEA,4E;AACA,6E;AACA,6E;AACA,gD;;AAEA,2B;AACA,sB;AACA,oB;AACA,oC;AACA,0B;AACA,I;AACA,6B;AACA,oB;AACA,oC;AACA,2B;AACA,I;AACA,yB;AACA,oB;AACA,oC;AACA,0B;AACA,I;AACA,sB;AACA,oB;AACA,oC;AACA,iC;AACA,I;AACA,sB;AACA,oB;AACA,gC;AACA,I;AACA,sB;AACA,oB;AACA,mB;AACA,I;AACA,0E;AACA,gC;AACA,oB;AACA,0D;AACA,iC;AACA,2C;AACA,gE;AACA,+D;AACA,iC;AACA,e;AACA,K;AACA,I;AACA,qB;AACA,oB;AACA,6B;AACA,I;AACA,kC;AACA,oB;AACA,oC;AACA,8B;AACA,4B;AACA,yB;AACA,e;AACA,I;AACA,6E;AACA,0D;AACA,sB;AACA,oB;AACA,4D;AACA,uC;AACA,wC;AACA,O;AACA,iB;AACA,G;AACA,G","file":"/packages/id-map.js","sourcesContent":["IdMap = function (idStringify, idParse) {\n var self = this;\n self._map = {};\n self._idStringify = idStringify || JSON.stringify;\n self._idParse = idParse || JSON.parse;\n};\n\n// Some of these methods are designed to match methods on OrderedDict, since\n// (eg) ObserveMultiplex and _CachingChangeObserver use them interchangeably.\n// (Conceivably, this should be replaced with \"UnorderedDict\" with a specific\n// set of methods that overlap between the two.)\n\n_.extend(IdMap.prototype, {\n get: function (id) {\n var self = this;\n var key = self._idStringify(id);\n return self._map[key];\n },\n set: function (id, value) {\n var self = this;\n var key = self._idStringify(id);\n self._map[key] = value;\n },\n remove: function (id) {\n var self = this;\n var key = self._idStringify(id);\n delete self._map[key];\n },\n has: function (id) {\n var self = this;\n var key = self._idStringify(id);\n return _.has(self._map, key);\n },\n empty: function () {\n var self = this;\n return _.isEmpty(self._map);\n },\n clear: function () {\n var self = this;\n self._map = {};\n },\n // Iterates over the items in the map. Return `false` to break the loop.\n forEach: function (iterator) {\n var self = this;\n // don't use _.each, because we can't break out of it.\n var keys = _.keys(self._map);\n for (var i = 0; i < keys.length; i++) {\n var breakIfFalse = iterator.call(null, self._map[keys[i]],\n self._idParse(keys[i]));\n if (breakIfFalse === false)\n return;\n }\n },\n size: function () {\n var self = this;\n return _.size(self._map);\n },\n setDefault: function (id, def) {\n var self = this;\n var key = self._idStringify(id);\n if (_.has(self._map, key))\n return self._map[key];\n self._map[key] = def;\n return def;\n },\n // Assumes that values are EJSON-cloneable, and that we don't need to clone\n // IDs (ie, that nobody is going to mutate an ObjectId).\n clone: function () {\n var self = this;\n var clone = new IdMap(self._idStringify, self._idParse);\n self.forEach(function (value, id) {\n clone.set(id, EJSON.clone(value));\n });\n return clone;\n }\n});\n\n"]} |
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.insecure = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=insecure.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/insecure.js"} |
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.jquery = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=jquery.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/jquery.js"} |
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.json = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=json.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/json.js"} |
@ -0,0 +1,23 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var DDP = Package.ddp.DDP; |
||||
var DDPServer = Package.ddp.DDPServer; |
||||
|
||||
/* Package-scope variables */ |
||||
var DDP, DDPServer, LivedataTest; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.livedata = { |
||||
DDP: DDP, |
||||
DDPServer: DDPServer, |
||||
LivedataTest: LivedataTest |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=livedata.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;","file":"/packages/livedata.js"} |
@ -0,0 +1,309 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var EJSON = Package.ejson.EJSON; |
||||
|
||||
/* Package-scope variables */ |
||||
var Log; |
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/logging/logging.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
Log = function () { // 1
|
||||
return Log.info.apply(this, arguments); // 2
|
||||
}; // 3
|
||||
// 4
|
||||
/// FOR TESTING // 5
|
||||
var intercept = 0; // 6
|
||||
var interceptedLines = []; // 7
|
||||
var suppress = 0; // 8
|
||||
// 9
|
||||
// Intercept the next 'count' calls to a Log function. The actual // 10
|
||||
// lines printed to the console can be cleared and read by calling // 11
|
||||
// Log._intercepted(). // 12
|
||||
Log._intercept = function (count) { // 13
|
||||
intercept += count; // 14
|
||||
}; // 15
|
||||
// 16
|
||||
// Suppress the next 'count' calls to a Log function. Use this to stop // 17
|
||||
// tests from spamming the console, especially with red errors that // 18
|
||||
// might look like a failing test. // 19
|
||||
Log._suppress = function (count) { // 20
|
||||
suppress += count; // 21
|
||||
}; // 22
|
||||
// 23
|
||||
// Returns intercepted lines and resets the intercept counter. // 24
|
||||
Log._intercepted = function () { // 25
|
||||
var lines = interceptedLines; // 26
|
||||
interceptedLines = []; // 27
|
||||
intercept = 0; // 28
|
||||
return lines; // 29
|
||||
}; // 30
|
||||
// 31
|
||||
// Either 'json' or 'colored-text'. // 32
|
||||
// // 33
|
||||
// When this is set to 'json', print JSON documents that are parsed by another // 34
|
||||
// process ('satellite' or 'meteor run'). This other process should call // 35
|
||||
// 'Log.format' for nice output. // 36
|
||||
// // 37
|
||||
// When this is set to 'colored-text', call 'Log.format' before printing. // 38
|
||||
// This should be used for logging from within satellite, since there is no // 39
|
||||
// other process that will be reading its standard output. // 40
|
||||
Log.outputFormat = 'json'; // 41
|
||||
// 42
|
||||
var LEVEL_COLORS = { // 43
|
||||
debug: 'green', // 44
|
||||
// leave info as the default color // 45
|
||||
warn: 'magenta', // 46
|
||||
error: 'red' // 47
|
||||
}; // 48
|
||||
// 49
|
||||
var META_COLOR = 'blue'; // 50
|
||||
// 51
|
||||
// XXX package // 52
|
||||
var RESTRICTED_KEYS = ['time', 'timeInexact', 'level', 'file', 'line', // 53
|
||||
'program', 'originApp', 'satellite', 'stderr']; // 54
|
||||
// 55
|
||||
var FORMATTED_KEYS = RESTRICTED_KEYS.concat(['app', 'message']); // 56
|
||||
// 57
|
||||
var logInBrowser = function (obj) { // 58
|
||||
var str = Log.format(obj); // 59
|
||||
// 60
|
||||
// XXX Some levels should be probably be sent to the server // 61
|
||||
var level = obj.level; // 62
|
||||
// 63
|
||||
if ((typeof console !== 'undefined') && console[level]) { // 64
|
||||
console[level](str); // 65
|
||||
} else { // 66
|
||||
// XXX Uses of Meteor._debug should probably be replaced by Log.debug or // 67
|
||||
// Log.info, and we should have another name for "do your best to // 68
|
||||
// call call console.log". // 69
|
||||
Meteor._debug(str); // 70
|
||||
} // 71
|
||||
}; // 72
|
||||
// 73
|
||||
// @returns {Object: { line: Number, file: String }} // 74
|
||||
Log._getCallerDetails = function () { // 75
|
||||
var getStack = function () { // 76
|
||||
// We do NOT use Error.prepareStackTrace here (a V8 extension that gets us a // 77
|
||||
// pre-parsed stack) since it's impossible to compose it with the use of // 78
|
||||
// Error.prepareStackTrace used on the server for source maps. // 79
|
||||
var err = new Error; // 80
|
||||
var stack = err.stack; // 81
|
||||
return stack; // 82
|
||||
}; // 83
|
||||
// 84
|
||||
var stack = getStack(); // 85
|
||||
// 86
|
||||
if (!stack) return {}; // 87
|
||||
// 88
|
||||
var lines = stack.split('\n'); // 89
|
||||
// 90
|
||||
// looking for the first line outside the logging package (or an // 91
|
||||
// eval if we find that first) // 92
|
||||
var line; // 93
|
||||
for (var i = 1; i < lines.length; ++i) { // 94
|
||||
line = lines[i]; // 95
|
||||
if (line.match(/^\s*at eval \(eval/)) { // 96
|
||||
return {file: "eval"}; // 97
|
||||
} // 98
|
||||
// 99
|
||||
if (!line.match(/packages\/(?:local-test:)?logging(?:\/|\.js)/)) // 100
|
||||
break; // 101
|
||||
} // 102
|
||||
// 103
|
||||
var details = {}; // 104
|
||||
// 105
|
||||
// The format for FF is 'functionName@filePath:lineNumber' // 106
|
||||
// The format for V8 is 'functionName (packages/logging/logging.js:81)' or // 107
|
||||
// 'packages/logging/logging.js:81' // 108
|
||||
var match = /(?:[@(]| at )([^(]+?):([0-9:]+)(?:\)|$)/.exec(line); // 109
|
||||
if (!match) // 110
|
||||
return details; // 111
|
||||
// in case the matched block here is line:column // 112
|
||||
details.line = match[2].split(':')[0]; // 113
|
||||
// 114
|
||||
// Possible format: https://foo.bar.com/scripts/file.js?random=foobar // 115
|
||||
// XXX: if you can write the following in better way, please do it // 116
|
||||
// XXX: what about evals? // 117
|
||||
details.file = match[1].split('/').slice(-1)[0].split('?')[0]; // 118
|
||||
// 119
|
||||
return details; // 120
|
||||
}; // 121
|
||||
// 122
|
||||
_.each(['debug', 'info', 'warn', 'error'], function (level) { // 123
|
||||
// @param arg {String|Object} // 124
|
||||
Log[level] = function (arg) { // 125
|
||||
if (suppress) { // 126
|
||||
suppress--; // 127
|
||||
return; // 128
|
||||
} // 129
|
||||
// 130
|
||||
var intercepted = false; // 131
|
||||
if (intercept) { // 132
|
||||
intercept--; // 133
|
||||
intercepted = true; // 134
|
||||
} // 135
|
||||
// 136
|
||||
var obj = (_.isObject(arg) && !_.isRegExp(arg) && !_.isDate(arg) ) ? // 137
|
||||
arg : {message: new String(arg).toString() }; // 138
|
||||
// 139
|
||||
_.each(RESTRICTED_KEYS, function (key) { // 140
|
||||
if (obj[key]) // 141
|
||||
throw new Error("Can't set '" + key + "' in log message"); // 142
|
||||
}); // 143
|
||||
// 144
|
||||
if (_.has(obj, 'message') && !_.isString(obj.message)) // 145
|
||||
throw new Error("The 'message' field in log objects must be a string"); // 146
|
||||
if (!obj.omitCallerDetails) // 147
|
||||
obj = _.extend(Log._getCallerDetails(), obj); // 148
|
||||
obj.time = new Date(); // 149
|
||||
obj.level = level; // 150
|
||||
// 151
|
||||
// XXX allow you to enable 'debug', probably per-package // 152
|
||||
if (level === 'debug') // 153
|
||||
return; // 154
|
||||
// 155
|
||||
if (intercepted) { // 156
|
||||
interceptedLines.push(EJSON.stringify(obj)); // 157
|
||||
} else if (Meteor.isServer) { // 158
|
||||
if (Log.outputFormat === 'colored-text') { // 159
|
||||
console.log(Log.format(obj, {color: true})); // 160
|
||||
} else if (Log.outputFormat === 'json') { // 161
|
||||
console.log(EJSON.stringify(obj)); // 162
|
||||
} else { // 163
|
||||
throw new Error("Unknown logging output format: " + Log.outputFormat); // 164
|
||||
} // 165
|
||||
} else { // 166
|
||||
logInBrowser(obj); // 167
|
||||
} // 168
|
||||
}; // 169
|
||||
}); // 170
|
||||
// 171
|
||||
// tries to parse line as EJSON. returns object if parse is successful, or null if not // 172
|
||||
Log.parse = function (line) { // 173
|
||||
var obj = null; // 174
|
||||
if (line && line.charAt(0) === '{') { // might be json generated from calling 'Log' // 175
|
||||
try { obj = EJSON.parse(line); } catch (e) {} // 176
|
||||
} // 177
|
||||
// 178
|
||||
// XXX should probably check fields other than 'time' // 179
|
||||
if (obj && obj.time && (obj.time instanceof Date)) // 180
|
||||
return obj; // 181
|
||||
else // 182
|
||||
return null; // 183
|
||||
}; // 184
|
||||
// 185
|
||||
// formats a log object into colored human and machine-readable text // 186
|
||||
Log.format = function (obj, options) { // 187
|
||||
obj = EJSON.clone(obj); // don't mutate the argument // 188
|
||||
options = options || {}; // 189
|
||||
// 190
|
||||
var time = obj.time; // 191
|
||||
if (!(time instanceof Date)) // 192
|
||||
throw new Error("'time' must be a Date object"); // 193
|
||||
var timeInexact = obj.timeInexact; // 194
|
||||
// 195
|
||||
// store fields that are in FORMATTED_KEYS since we strip them // 196
|
||||
var level = obj.level || 'info'; // 197
|
||||
var file = obj.file; // 198
|
||||
var lineNumber = obj.line; // 199
|
||||
var appName = obj.app || ''; // 200
|
||||
var originApp = obj.originApp; // 201
|
||||
var message = obj.message || ''; // 202
|
||||
var program = obj.program || ''; // 203
|
||||
var satellite = obj.satellite; // 204
|
||||
var stderr = obj.stderr || ''; // 205
|
||||
// 206
|
||||
_.each(FORMATTED_KEYS, function(key) { // 207
|
||||
delete obj[key]; // 208
|
||||
}); // 209
|
||||
// 210
|
||||
if (!_.isEmpty(obj)) { // 211
|
||||
if (message) message += " "; // 212
|
||||
message += EJSON.stringify(obj); // 213
|
||||
} // 214
|
||||
// 215
|
||||
var pad2 = function(n) { return n < 10 ? '0' + n : n.toString(); }; // 216
|
||||
var pad3 = function(n) { return n < 100 ? '0' + pad2(n) : n.toString(); }; // 217
|
||||
// 218
|
||||
var dateStamp = time.getFullYear().toString() + // 219
|
||||
pad2(time.getMonth() + 1 /*0-based*/) + // 220
|
||||
pad2(time.getDate()); // 221
|
||||
var timeStamp = pad2(time.getHours()) + // 222
|
||||
':' + // 223
|
||||
pad2(time.getMinutes()) + // 224
|
||||
':' + // 225
|
||||
pad2(time.getSeconds()) + // 226
|
||||
'.' + // 227
|
||||
pad3(time.getMilliseconds()); // 228
|
||||
// 229
|
||||
// eg in San Francisco in June this will be '(-7)' // 230
|
||||
var utcOffsetStr = '(' + (-(new Date().getTimezoneOffset() / 60)) + ')'; // 231
|
||||
// 232
|
||||
var appInfo = ''; // 233
|
||||
if (appName) appInfo += appName; // 234
|
||||
if (originApp && originApp !== appName) appInfo += ' via ' + originApp; // 235
|
||||
if (appInfo) appInfo = '[' + appInfo + '] '; // 236
|
||||
// 237
|
||||
var sourceInfoParts = []; // 238
|
||||
if (program) sourceInfoParts.push(program); // 239
|
||||
if (file) sourceInfoParts.push(file); // 240
|
||||
if (lineNumber) sourceInfoParts.push(lineNumber); // 241
|
||||
var sourceInfo = _.isEmpty(sourceInfoParts) ? // 242
|
||||
'' : '(' + sourceInfoParts.join(':') + ') '; // 243
|
||||
// 244
|
||||
if (satellite) // 245
|
||||
sourceInfo += ['[', satellite, ']'].join(''); // 246
|
||||
// 247
|
||||
var stderrIndicator = stderr ? '(STDERR) ' : ''; // 248
|
||||
// 249
|
||||
var metaPrefix = [ // 250
|
||||
level.charAt(0).toUpperCase(), // 251
|
||||
dateStamp, // 252
|
||||
'-', // 253
|
||||
timeStamp, // 254
|
||||
utcOffsetStr, // 255
|
||||
timeInexact ? '? ' : ' ', // 256
|
||||
appInfo, // 257
|
||||
sourceInfo, // 258
|
||||
stderrIndicator].join(''); // 259
|
||||
// 260
|
||||
var prettify = function (line, color) { // 261
|
||||
return (options.color && Meteor.isServer && color) ? // 262
|
||||
Npm.require('cli-color')[color](line) : line; // 263
|
||||
}; // 264
|
||||
// 265
|
||||
return prettify(metaPrefix, options.metaColor || META_COLOR) + // 266
|
||||
prettify(message, LEVEL_COLORS[level]); // 267
|
||||
}; // 268
|
||||
// 269
|
||||
// Turn a line of text into a loggable object. // 270
|
||||
// @param line {String} // 271
|
||||
// @param override {Object} // 272
|
||||
Log.objFromText = function (line, override) { // 273
|
||||
var obj = {message: line, level: "info", time: new Date(), timeInexact: true}; // 274
|
||||
return _.extend(obj, override); // 275
|
||||
}; // 276
|
||||
// 277
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.logging = { |
||||
Log: Log |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=logging.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,15 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Autoupdate = Package.autoupdate.Autoupdate; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['meteor-platform'] = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=meteor-platform.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;","file":"/packages/meteor-platform.js"} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['mquandalle:jade'] = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=mquandalle_jade.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/mquandalle_jade.js"} |
@ -0,0 +1,32 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
/* Package-scope variables */ |
||||
var topojson; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/mrt:topojson/meteor-topojson.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
topojson = Npm.require('topojson'); // 1
|
||||
// 2
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['mrt:topojson'] = { |
||||
topojson: topojson |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=mrt_topojson.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"file":"/packages/mrt:topojson.js","sources":["mrt:topojson/meteor-topojson.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mC","sourcesContent":["topojson = Npm.require('topojson');\n"]} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,384 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Tracker = Package.tracker.Tracker; |
||||
var Deps = Package.tracker.Deps; |
||||
var LocalCollection = Package.minimongo.LocalCollection; |
||||
var Minimongo = Package.minimongo.Minimongo; |
||||
var _ = Package.underscore._; |
||||
var Random = Package.random.Random; |
||||
|
||||
/* Package-scope variables */ |
||||
var ObserveSequence, seqChangedToEmpty, seqChangedToArray, seqChangedToCursor; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/observe-sequence/observe_sequence.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
var warn = function () { // 1
|
||||
if (ObserveSequence._suppressWarnings) { // 2
|
||||
ObserveSequence._suppressWarnings--; // 3
|
||||
} else { // 4
|
||||
if (typeof console !== 'undefined' && console.warn) // 5
|
||||
console.warn.apply(console, arguments); // 6
|
||||
// 7
|
||||
ObserveSequence._loggedWarnings++; // 8
|
||||
} // 9
|
||||
}; // 10
|
||||
// 11
|
||||
var idStringify = LocalCollection._idStringify; // 12
|
||||
var idParse = LocalCollection._idParse; // 13
|
||||
// 14
|
||||
ObserveSequence = { // 15
|
||||
_suppressWarnings: 0, // 16
|
||||
_loggedWarnings: 0, // 17
|
||||
// 18
|
||||
// A mechanism similar to cursor.observe which receives a reactive // 19
|
||||
// function returning a sequence type and firing appropriate callbacks // 20
|
||||
// when the value changes. // 21
|
||||
// // 22
|
||||
// @param sequenceFunc {Function} a reactive function returning a // 23
|
||||
// sequence type. The currently supported sequence types are: // 24
|
||||
// 'null', arrays and cursors. // 25
|
||||
// // 26
|
||||
// @param callbacks {Object} similar to a specific subset of // 27
|
||||
// callbacks passed to `cursor.observe` // 28
|
||||
// (http://docs.meteor.com/#observe), with minor variations to // 29
|
||||
// support the fact that not all sequences contain objects with // 30
|
||||
// _id fields. Specifically: // 31
|
||||
// // 32
|
||||
// * addedAt(id, item, atIndex, beforeId) // 33
|
||||
// * changedAt(id, newItem, oldItem, atIndex) // 34
|
||||
// * removedAt(id, oldItem, atIndex) // 35
|
||||
// * movedTo(id, item, fromIndex, toIndex, beforeId) // 36
|
||||
// // 37
|
||||
// @returns {Object(stop: Function)} call 'stop' on the return value // 38
|
||||
// to stop observing this sequence function. // 39
|
||||
// // 40
|
||||
// We don't make any assumptions about our ability to compare sequence // 41
|
||||
// elements (ie, we don't assume EJSON.equals works; maybe there is extra // 42
|
||||
// state/random methods on the objects) so unlike cursor.observe, we may // 43
|
||||
// sometimes call changedAt() when nothing actually changed. // 44
|
||||
// XXX consider if we *can* make the stronger assumption and avoid // 45
|
||||
// no-op changedAt calls (in some cases?) // 46
|
||||
// // 47
|
||||
// XXX currently only supports the callbacks used by our // 48
|
||||
// implementation of {{#each}}, but this can be expanded. // 49
|
||||
// // 50
|
||||
// XXX #each doesn't use the indices (though we'll eventually need // 51
|
||||
// a way to get them when we support `@index`), but calling // 52
|
||||
// `cursor.observe` causes the index to be calculated on every // 53
|
||||
// callback using a linear scan (unless you turn it off by passing // 54
|
||||
// `_no_indices`). Any way to avoid calculating indices on a pure // 55
|
||||
// cursor observe like we used to? // 56
|
||||
observe: function (sequenceFunc, callbacks) { // 57
|
||||
var lastSeq = null; // 58
|
||||
var activeObserveHandle = null; // 59
|
||||
// 60
|
||||
// 'lastSeqArray' contains the previous value of the sequence // 61
|
||||
// we're observing. It is an array of objects with '_id' and // 62
|
||||
// 'item' fields. 'item' is the element in the array, or the // 63
|
||||
// document in the cursor. // 64
|
||||
// // 65
|
||||
// '_id' is whichever of the following is relevant, unless it has // 66
|
||||
// already appeared -- in which case it's randomly generated. // 67
|
||||
// // 68
|
||||
// * if 'item' is an object: // 69
|
||||
// * an '_id' field, if present // 70
|
||||
// * otherwise, the index in the array // 71
|
||||
// // 72
|
||||
// * if 'item' is a number or string, use that value // 73
|
||||
// // 74
|
||||
// XXX this can be generalized by allowing {{#each}} to accept a // 75
|
||||
// general 'key' argument which could be a function, a dotted // 76
|
||||
// field name, or the special @index value. // 77
|
||||
var lastSeqArray = []; // elements are objects of form {_id, item} // 78
|
||||
var computation = Tracker.autorun(function () { // 79
|
||||
var seq = sequenceFunc(); // 80
|
||||
// 81
|
||||
Tracker.nonreactive(function () { // 82
|
||||
var seqArray; // same structure as `lastSeqArray` above. // 83
|
||||
// 84
|
||||
if (activeObserveHandle) { // 85
|
||||
// If we were previously observing a cursor, replace lastSeqArray with // 86
|
||||
// more up-to-date information. Then stop the old observe. // 87
|
||||
lastSeqArray = _.map(lastSeq.fetch(), function (doc) { // 88
|
||||
return {_id: doc._id, item: doc}; // 89
|
||||
}); // 90
|
||||
activeObserveHandle.stop(); // 91
|
||||
activeObserveHandle = null; // 92
|
||||
} // 93
|
||||
// 94
|
||||
if (!seq) { // 95
|
||||
seqArray = seqChangedToEmpty(lastSeqArray, callbacks); // 96
|
||||
} else if (seq instanceof Array) { // 97
|
||||
seqArray = seqChangedToArray(lastSeqArray, seq, callbacks); // 98
|
||||
} else if (isStoreCursor(seq)) { // 99
|
||||
var result /* [seqArray, activeObserveHandle] */ = // 100
|
||||
seqChangedToCursor(lastSeqArray, seq, callbacks); // 101
|
||||
seqArray = result[0]; // 102
|
||||
activeObserveHandle = result[1]; // 103
|
||||
} else { // 104
|
||||
throw badSequenceError(); // 105
|
||||
} // 106
|
||||
// 107
|
||||
diffArray(lastSeqArray, seqArray, callbacks); // 108
|
||||
lastSeq = seq; // 109
|
||||
lastSeqArray = seqArray; // 110
|
||||
}); // 111
|
||||
}); // 112
|
||||
// 113
|
||||
return { // 114
|
||||
stop: function () { // 115
|
||||
computation.stop(); // 116
|
||||
if (activeObserveHandle) // 117
|
||||
activeObserveHandle.stop(); // 118
|
||||
} // 119
|
||||
}; // 120
|
||||
}, // 121
|
||||
// 122
|
||||
// Fetch the items of `seq` into an array, where `seq` is of one of the // 123
|
||||
// sequence types accepted by `observe`. If `seq` is a cursor, a // 124
|
||||
// dependency is established. // 125
|
||||
fetch: function (seq) { // 126
|
||||
if (!seq) { // 127
|
||||
return []; // 128
|
||||
} else if (seq instanceof Array) { // 129
|
||||
return seq; // 130
|
||||
} else if (isStoreCursor(seq)) { // 131
|
||||
return seq.fetch(); // 132
|
||||
} else { // 133
|
||||
throw badSequenceError(); // 134
|
||||
} // 135
|
||||
} // 136
|
||||
}; // 137
|
||||
// 138
|
||||
var badSequenceError = function () { // 139
|
||||
return new Error("{{#each}} currently only accepts " + // 140
|
||||
"arrays, cursors or falsey values."); // 141
|
||||
}; // 142
|
||||
// 143
|
||||
var isStoreCursor = function (cursor) { // 144
|
||||
return cursor && _.isObject(cursor) && // 145
|
||||
_.isFunction(cursor.observe) && _.isFunction(cursor.fetch); // 146
|
||||
}; // 147
|
||||
// 148
|
||||
// Calculates the differences between `lastSeqArray` and // 149
|
||||
// `seqArray` and calls appropriate functions from `callbacks`. // 150
|
||||
// Reuses Minimongo's diff algorithm implementation. // 151
|
||||
var diffArray = function (lastSeqArray, seqArray, callbacks) { // 152
|
||||
var diffFn = Package.minimongo.LocalCollection._diffQueryOrderedChanges; // 153
|
||||
var oldIdObjects = []; // 154
|
||||
var newIdObjects = []; // 155
|
||||
var posOld = {}; // maps from idStringify'd ids // 156
|
||||
var posNew = {}; // ditto // 157
|
||||
var posCur = {}; // 158
|
||||
var lengthCur = lastSeqArray.length; // 159
|
||||
// 160
|
||||
_.each(seqArray, function (doc, i) { // 161
|
||||
newIdObjects.push({_id: doc._id}); // 162
|
||||
posNew[idStringify(doc._id)] = i; // 163
|
||||
}); // 164
|
||||
_.each(lastSeqArray, function (doc, i) { // 165
|
||||
oldIdObjects.push({_id: doc._id}); // 166
|
||||
posOld[idStringify(doc._id)] = i; // 167
|
||||
posCur[idStringify(doc._id)] = i; // 168
|
||||
}); // 169
|
||||
// 170
|
||||
// Arrays can contain arbitrary objects. We don't diff the // 171
|
||||
// objects. Instead we always fire 'changedAt' callback on every // 172
|
||||
// object. The consumer of `observe-sequence` should deal with // 173
|
||||
// it appropriately. // 174
|
||||
diffFn(oldIdObjects, newIdObjects, { // 175
|
||||
addedBefore: function (id, doc, before) { // 176
|
||||
var position = before ? posCur[idStringify(before)] : lengthCur; // 177
|
||||
// 178
|
||||
if (before) { // 179
|
||||
// If not adding at the end, we need to update indexes. // 180
|
||||
// XXX this can still be improved greatly! // 181
|
||||
_.each(posCur, function (pos, id) { // 182
|
||||
if (pos >= position) // 183
|
||||
posCur[id]++; // 184
|
||||
}); // 185
|
||||
} // 186
|
||||
// 187
|
||||
lengthCur++; // 188
|
||||
posCur[idStringify(id)] = position; // 189
|
||||
// 190
|
||||
callbacks.addedAt( // 191
|
||||
id, // 192
|
||||
seqArray[posNew[idStringify(id)]].item, // 193
|
||||
position, // 194
|
||||
before); // 195
|
||||
}, // 196
|
||||
movedBefore: function (id, before) { // 197
|
||||
if (id === before) // 198
|
||||
return; // 199
|
||||
// 200
|
||||
var oldPosition = posCur[idStringify(id)]; // 201
|
||||
var newPosition = before ? posCur[idStringify(before)] : lengthCur; // 202
|
||||
// 203
|
||||
// Moving the item forward. The new element is losing one position as it // 204
|
||||
// was removed from the old position before being inserted at the new // 205
|
||||
// position. // 206
|
||||
// Ex.: 0 *1* 2 3 4 // 207
|
||||
// 0 2 3 *1* 4 // 208
|
||||
// The original issued callback is "1" before "4". // 209
|
||||
// The position of "1" is 1, the position of "4" is 4. // 210
|
||||
// The generated move is (1) -> (3) // 211
|
||||
if (newPosition > oldPosition) { // 212
|
||||
newPosition--; // 213
|
||||
} // 214
|
||||
// 215
|
||||
// Fix up the positions of elements between the old and the new positions // 216
|
||||
// of the moved element. // 217
|
||||
// // 218
|
||||
// There are two cases: // 219
|
||||
// 1. The element is moved forward. Then all the positions in between // 220
|
||||
// are moved back. // 221
|
||||
// 2. The element is moved back. Then the positions in between *and* the // 222
|
||||
// element that is currently standing on the moved element's future // 223
|
||||
// position are moved forward. // 224
|
||||
_.each(posCur, function (elCurPosition, id) { // 225
|
||||
if (oldPosition < elCurPosition && elCurPosition < newPosition) // 226
|
||||
posCur[id]--; // 227
|
||||
else if (newPosition <= elCurPosition && elCurPosition < oldPosition) // 228
|
||||
posCur[id]++; // 229
|
||||
}); // 230
|
||||
// 231
|
||||
// Finally, update the position of the moved element. // 232
|
||||
posCur[idStringify(id)] = newPosition; // 233
|
||||
// 234
|
||||
callbacks.movedTo( // 235
|
||||
id, // 236
|
||||
seqArray[posNew[idStringify(id)]].item, // 237
|
||||
oldPosition, // 238
|
||||
newPosition, // 239
|
||||
before); // 240
|
||||
}, // 241
|
||||
removed: function (id) { // 242
|
||||
var prevPosition = posCur[idStringify(id)]; // 243
|
||||
// 244
|
||||
_.each(posCur, function (pos, id) { // 245
|
||||
if (pos >= prevPosition) // 246
|
||||
posCur[id]--; // 247
|
||||
}); // 248
|
||||
// 249
|
||||
delete posCur[idStringify(id)]; // 250
|
||||
lengthCur--; // 251
|
||||
// 252
|
||||
callbacks.removedAt( // 253
|
||||
id, // 254
|
||||
lastSeqArray[posOld[idStringify(id)]].item, // 255
|
||||
prevPosition); // 256
|
||||
} // 257
|
||||
}); // 258
|
||||
// 259
|
||||
_.each(posNew, function (pos, idString) { // 260
|
||||
var id = idParse(idString); // 261
|
||||
if (_.has(posOld, idString)) { // 262
|
||||
// specifically for primitive types, compare equality before // 263
|
||||
// firing the 'changedAt' callback. otherwise, always fire it // 264
|
||||
// because doing a deep EJSON comparison is not guaranteed to // 265
|
||||
// work (an array can contain arbitrary objects, and 'transform' // 266
|
||||
// can be used on cursors). also, deep diffing is not // 267
|
||||
// necessarily the most efficient (if only a specific subfield // 268
|
||||
// of the object is later accessed). // 269
|
||||
var newItem = seqArray[pos].item; // 270
|
||||
var oldItem = lastSeqArray[posOld[idString]].item; // 271
|
||||
// 272
|
||||
if (typeof newItem === 'object' || newItem !== oldItem) // 273
|
||||
callbacks.changedAt(id, newItem, oldItem, pos); // 274
|
||||
} // 275
|
||||
}); // 276
|
||||
}; // 277
|
||||
// 278
|
||||
seqChangedToEmpty = function (lastSeqArray, callbacks) { // 279
|
||||
return []; // 280
|
||||
}; // 281
|
||||
// 282
|
||||
seqChangedToArray = function (lastSeqArray, array, callbacks) { // 283
|
||||
var idsUsed = {}; // 284
|
||||
var seqArray = _.map(array, function (item, index) { // 285
|
||||
var id; // 286
|
||||
if (typeof item === 'string') { // 287
|
||||
// ensure not empty, since other layers (eg DomRange) assume this as well // 288
|
||||
id = "-" + item; // 289
|
||||
} else if (typeof item === 'number' || // 290
|
||||
typeof item === 'boolean' || // 291
|
||||
item === undefined) { // 292
|
||||
id = item; // 293
|
||||
} else if (typeof item === 'object') { // 294
|
||||
id = (item && item._id) || index; // 295
|
||||
} else { // 296
|
||||
throw new Error("{{#each}} doesn't support arrays with " + // 297
|
||||
"elements of type " + typeof item); // 298
|
||||
} // 299
|
||||
// 300
|
||||
var idString = idStringify(id); // 301
|
||||
if (idsUsed[idString]) { // 302
|
||||
if (typeof item === 'object' && '_id' in item) // 303
|
||||
warn("duplicate id " + id + " in", array); // 304
|
||||
id = Random.id(); // 305
|
||||
} else { // 306
|
||||
idsUsed[idString] = true; // 307
|
||||
} // 308
|
||||
// 309
|
||||
return { _id: id, item: item }; // 310
|
||||
}); // 311
|
||||
// 312
|
||||
return seqArray; // 313
|
||||
}; // 314
|
||||
// 315
|
||||
seqChangedToCursor = function (lastSeqArray, cursor, callbacks) { // 316
|
||||
var initial = true; // are we observing initial data from cursor? // 317
|
||||
var seqArray = []; // 318
|
||||
// 319
|
||||
var observeHandle = cursor.observe({ // 320
|
||||
addedAt: function (document, atIndex, before) { // 321
|
||||
if (initial) { // 322
|
||||
// keep track of initial data so that we can diff once // 323
|
||||
// we exit `observe`. // 324
|
||||
if (before !== null) // 325
|
||||
throw new Error("Expected initial data from observe in order"); // 326
|
||||
seqArray.push({ _id: document._id, item: document }); // 327
|
||||
} else { // 328
|
||||
callbacks.addedAt(document._id, document, atIndex, before); // 329
|
||||
} // 330
|
||||
}, // 331
|
||||
changedAt: function (newDocument, oldDocument, atIndex) { // 332
|
||||
callbacks.changedAt(newDocument._id, newDocument, oldDocument, // 333
|
||||
atIndex); // 334
|
||||
}, // 335
|
||||
removedAt: function (oldDocument, atIndex) { // 336
|
||||
callbacks.removedAt(oldDocument._id, oldDocument, atIndex); // 337
|
||||
}, // 338
|
||||
movedTo: function (document, fromIndex, toIndex, before) { // 339
|
||||
callbacks.movedTo( // 340
|
||||
document._id, document, fromIndex, toIndex, before); // 341
|
||||
} // 342
|
||||
}); // 343
|
||||
initial = false; // 344
|
||||
// 345
|
||||
return [seqArray, observeHandle]; // 346
|
||||
}; // 347
|
||||
// 348
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['observe-sequence'] = { |
||||
ObserveSequence: ObserveSequence |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=observe-sequence.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,241 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var OrderedDict; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ordered-dict/ordered_dict.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file defines an ordered dictionary abstraction that is useful for // 1
|
||||
// maintaining a dataset backed by observeChanges. It supports ordering items // 2
|
||||
// by specifying the item they now come before. // 3
|
||||
// 4
|
||||
// The implementation is a dictionary that contains nodes of a doubly-linked // 5
|
||||
// list as its values. // 6
|
||||
// 7
|
||||
// constructs a new element struct // 8
|
||||
// next and prev are whole elements, not keys. // 9
|
||||
var element = function (key, value, next, prev) { // 10
|
||||
return { // 11
|
||||
key: key, // 12
|
||||
value: value, // 13
|
||||
next: next, // 14
|
||||
prev: prev // 15
|
||||
}; // 16
|
||||
}; // 17
|
||||
OrderedDict = function (/* ... */) { // 18
|
||||
var self = this; // 19
|
||||
self._dict = {}; // 20
|
||||
self._first = null; // 21
|
||||
self._last = null; // 22
|
||||
self._size = 0; // 23
|
||||
var args = _.toArray(arguments); // 24
|
||||
self._stringify = function (x) { return x; }; // 25
|
||||
if (typeof args[0] === 'function') // 26
|
||||
self._stringify = args.shift(); // 27
|
||||
_.each(args, function (kv) { // 28
|
||||
self.putBefore(kv[0], kv[1], null); // 29
|
||||
}); // 30
|
||||
}; // 31
|
||||
// 32
|
||||
_.extend(OrderedDict.prototype, { // 33
|
||||
// the "prefix keys with a space" thing comes from here // 34
|
||||
// https://github.com/documentcloud/underscore/issues/376#issuecomment-2815649 // 35
|
||||
_k: function (key) { return " " + this._stringify(key); }, // 36
|
||||
// 37
|
||||
empty: function () { // 38
|
||||
var self = this; // 39
|
||||
return !self._first; // 40
|
||||
}, // 41
|
||||
size: function () { // 42
|
||||
var self = this; // 43
|
||||
return self._size; // 44
|
||||
}, // 45
|
||||
_linkEltIn: function (elt) { // 46
|
||||
var self = this; // 47
|
||||
if (!elt.next) { // 48
|
||||
elt.prev = self._last; // 49
|
||||
if (self._last) // 50
|
||||
self._last.next = elt; // 51
|
||||
self._last = elt; // 52
|
||||
} else { // 53
|
||||
elt.prev = elt.next.prev; // 54
|
||||
elt.next.prev = elt; // 55
|
||||
if (elt.prev) // 56
|
||||
elt.prev.next = elt; // 57
|
||||
} // 58
|
||||
if (self._first === null || self._first === elt.next) // 59
|
||||
self._first = elt; // 60
|
||||
}, // 61
|
||||
_linkEltOut: function (elt) { // 62
|
||||
var self = this; // 63
|
||||
if (elt.next) // 64
|
||||
elt.next.prev = elt.prev; // 65
|
||||
if (elt.prev) // 66
|
||||
elt.prev.next = elt.next; // 67
|
||||
if (elt === self._last) // 68
|
||||
self._last = elt.prev; // 69
|
||||
if (elt === self._first) // 70
|
||||
self._first = elt.next; // 71
|
||||
}, // 72
|
||||
putBefore: function (key, item, before) { // 73
|
||||
var self = this; // 74
|
||||
if (self._dict[self._k(key)]) // 75
|
||||
throw new Error("Item " + key + " already present in OrderedDict"); // 76
|
||||
var elt = before ? // 77
|
||||
element(key, item, self._dict[self._k(before)]) : // 78
|
||||
element(key, item, null); // 79
|
||||
if (elt.next === undefined) // 80
|
||||
throw new Error("could not find item to put this one before"); // 81
|
||||
self._linkEltIn(elt); // 82
|
||||
self._dict[self._k(key)] = elt; // 83
|
||||
self._size++; // 84
|
||||
}, // 85
|
||||
append: function (key, item) { // 86
|
||||
var self = this; // 87
|
||||
self.putBefore(key, item, null); // 88
|
||||
}, // 89
|
||||
remove: function (key) { // 90
|
||||
var self = this; // 91
|
||||
var elt = self._dict[self._k(key)]; // 92
|
||||
if (elt === undefined) // 93
|
||||
throw new Error("Item " + key + " not present in OrderedDict"); // 94
|
||||
self._linkEltOut(elt); // 95
|
||||
self._size--; // 96
|
||||
delete self._dict[self._k(key)]; // 97
|
||||
return elt.value; // 98
|
||||
}, // 99
|
||||
get: function (key) { // 100
|
||||
var self = this; // 101
|
||||
if (self.has(key)) // 102
|
||||
return self._dict[self._k(key)].value; // 103
|
||||
return undefined; // 104
|
||||
}, // 105
|
||||
has: function (key) { // 106
|
||||
var self = this; // 107
|
||||
return _.has(self._dict, self._k(key)); // 108
|
||||
}, // 109
|
||||
// Iterate through the items in this dictionary in order, calling // 110
|
||||
// iter(value, key, index) on each one. // 111
|
||||
// 112
|
||||
// Stops whenever iter returns OrderedDict.BREAK, or after the last element. // 113
|
||||
forEach: function (iter) { // 114
|
||||
var self = this; // 115
|
||||
var i = 0; // 116
|
||||
var elt = self._first; // 117
|
||||
while (elt !== null) { // 118
|
||||
var b = iter(elt.value, elt.key, i); // 119
|
||||
if (b === OrderedDict.BREAK) // 120
|
||||
return; // 121
|
||||
elt = elt.next; // 122
|
||||
i++; // 123
|
||||
} // 124
|
||||
}, // 125
|
||||
first: function () { // 126
|
||||
var self = this; // 127
|
||||
if (self.empty()) // 128
|
||||
return undefined; // 129
|
||||
return self._first.key; // 130
|
||||
}, // 131
|
||||
firstValue: function () { // 132
|
||||
var self = this; // 133
|
||||
if (self.empty()) // 134
|
||||
return undefined; // 135
|
||||
return self._first.value; // 136
|
||||
}, // 137
|
||||
last: function () { // 138
|
||||
var self = this; // 139
|
||||
if (self.empty()) // 140
|
||||
return undefined; // 141
|
||||
return self._last.key; // 142
|
||||
}, // 143
|
||||
lastValue: function () { // 144
|
||||
var self = this; // 145
|
||||
if (self.empty()) // 146
|
||||
return undefined; // 147
|
||||
return self._last.value; // 148
|
||||
}, // 149
|
||||
prev: function (key) { // 150
|
||||
var self = this; // 151
|
||||
if (self.has(key)) { // 152
|
||||
var elt = self._dict[self._k(key)]; // 153
|
||||
if (elt.prev) // 154
|
||||
return elt.prev.key; // 155
|
||||
} // 156
|
||||
return null; // 157
|
||||
}, // 158
|
||||
next: function (key) { // 159
|
||||
var self = this; // 160
|
||||
if (self.has(key)) { // 161
|
||||
var elt = self._dict[self._k(key)]; // 162
|
||||
if (elt.next) // 163
|
||||
return elt.next.key; // 164
|
||||
} // 165
|
||||
return null; // 166
|
||||
}, // 167
|
||||
moveBefore: function (key, before) { // 168
|
||||
var self = this; // 169
|
||||
var elt = self._dict[self._k(key)]; // 170
|
||||
var eltBefore = before ? self._dict[self._k(before)] : null; // 171
|
||||
if (elt === undefined) // 172
|
||||
throw new Error("Item to move is not present"); // 173
|
||||
if (eltBefore === undefined) { // 174
|
||||
throw new Error("Could not find element to move this one before"); // 175
|
||||
} // 176
|
||||
if (eltBefore === elt.next) // no moving necessary // 177
|
||||
return; // 178
|
||||
// remove from its old place // 179
|
||||
self._linkEltOut(elt); // 180
|
||||
// patch into its new place // 181
|
||||
elt.next = eltBefore; // 182
|
||||
self._linkEltIn(elt); // 183
|
||||
}, // 184
|
||||
// Linear, sadly. // 185
|
||||
indexOf: function (key) { // 186
|
||||
var self = this; // 187
|
||||
var ret = null; // 188
|
||||
self.forEach(function (v, k, i) { // 189
|
||||
if (self._k(k) === self._k(key)) { // 190
|
||||
ret = i; // 191
|
||||
return OrderedDict.BREAK; // 192
|
||||
} // 193
|
||||
return undefined; // 194
|
||||
}); // 195
|
||||
return ret; // 196
|
||||
}, // 197
|
||||
_checkRep: function () { // 198
|
||||
var self = this; // 199
|
||||
_.each(self._dict, function (k, v) { // 200
|
||||
if (v.next === v) // 201
|
||||
throw new Error("Next is a loop"); // 202
|
||||
if (v.prev === v) // 203
|
||||
throw new Error("Prev is a loop"); // 204
|
||||
}); // 205
|
||||
} // 206
|
||||
// 207
|
||||
}); // 208
|
||||
OrderedDict.BREAK = {"break": true}; // 209
|
||||
// 210
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['ordered-dict'] = { |
||||
OrderedDict: OrderedDict |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=ordered-dict.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,285 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var Random; |
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/random/random.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// We use cryptographically strong PRNGs (crypto.getRandomBytes() on the server, // 1
|
||||
// window.crypto.getRandomValues() in the browser) when available. If these // 2
|
||||
// PRNGs fail, we fall back to the Alea PRNG, which is not cryptographically // 3
|
||||
// strong, and we seed it with various sources such as the date, Math.random, // 4
|
||||
// and window size on the client. When using crypto.getRandomValues(), our // 5
|
||||
// primitive is hexString(), from which we construct fraction(). When using // 6
|
||||
// window.crypto.getRandomValues() or alea, the primitive is fraction and we use // 7
|
||||
// that to construct hex string. // 8
|
||||
// 9
|
||||
if (Meteor.isServer) // 10
|
||||
var nodeCrypto = Npm.require('crypto'); // 11
|
||||
// 12
|
||||
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript // 13
|
||||
// for a full discussion and Alea implementation. // 14
|
||||
var Alea = function () { // 15
|
||||
function Mash() { // 16
|
||||
var n = 0xefc8249d; // 17
|
||||
// 18
|
||||
var mash = function(data) { // 19
|
||||
data = data.toString(); // 20
|
||||
for (var i = 0; i < data.length; i++) { // 21
|
||||
n += data.charCodeAt(i); // 22
|
||||
var h = 0.02519603282416938 * n; // 23
|
||||
n = h >>> 0; // 24
|
||||
h -= n; // 25
|
||||
h *= n; // 26
|
||||
n = h >>> 0; // 27
|
||||
h -= n; // 28
|
||||
n += h * 0x100000000; // 2^32 // 29
|
||||
} // 30
|
||||
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 // 31
|
||||
}; // 32
|
||||
// 33
|
||||
mash.version = 'Mash 0.9'; // 34
|
||||
return mash; // 35
|
||||
} // 36
|
||||
// 37
|
||||
return (function (args) { // 38
|
||||
var s0 = 0; // 39
|
||||
var s1 = 0; // 40
|
||||
var s2 = 0; // 41
|
||||
var c = 1; // 42
|
||||
// 43
|
||||
if (args.length == 0) { // 44
|
||||
args = [+new Date]; // 45
|
||||
} // 46
|
||||
var mash = Mash(); // 47
|
||||
s0 = mash(' '); // 48
|
||||
s1 = mash(' '); // 49
|
||||
s2 = mash(' '); // 50
|
||||
// 51
|
||||
for (var i = 0; i < args.length; i++) { // 52
|
||||
s0 -= mash(args[i]); // 53
|
||||
if (s0 < 0) { // 54
|
||||
s0 += 1; // 55
|
||||
} // 56
|
||||
s1 -= mash(args[i]); // 57
|
||||
if (s1 < 0) { // 58
|
||||
s1 += 1; // 59
|
||||
} // 60
|
||||
s2 -= mash(args[i]); // 61
|
||||
if (s2 < 0) { // 62
|
||||
s2 += 1; // 63
|
||||
} // 64
|
||||
} // 65
|
||||
mash = null; // 66
|
||||
// 67
|
||||
var random = function() { // 68
|
||||
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 // 69
|
||||
s0 = s1; // 70
|
||||
s1 = s2; // 71
|
||||
return s2 = t - (c = t | 0); // 72
|
||||
}; // 73
|
||||
random.uint32 = function() { // 74
|
||||
return random() * 0x100000000; // 2^32 // 75
|
||||
}; // 76
|
||||
random.fract53 = function() { // 77
|
||||
return random() + // 78
|
||||
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 // 79
|
||||
}; // 80
|
||||
random.version = 'Alea 0.9'; // 81
|
||||
random.args = args; // 82
|
||||
return random; // 83
|
||||
// 84
|
||||
} (Array.prototype.slice.call(arguments))); // 85
|
||||
}; // 86
|
||||
// 87
|
||||
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz"; // 88
|
||||
var BASE64_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + // 89
|
||||
"0123456789-_"; // 90
|
||||
// 91
|
||||
// If seeds are provided, then the alea PRNG will be used, since cryptographic // 92
|
||||
// PRNGs (Node crypto and window.crypto.getRandomValues) don't allow us to // 93
|
||||
// specify seeds. The caller is responsible for making sure to provide a seed // 94
|
||||
// for alea if a csprng is not available. // 95
|
||||
var RandomGenerator = function (seedArray) { // 96
|
||||
var self = this; // 97
|
||||
if (seedArray !== undefined) // 98
|
||||
self.alea = Alea.apply(null, seedArray); // 99
|
||||
}; // 100
|
||||
// 101
|
||||
RandomGenerator.prototype.fraction = function () { // 102
|
||||
var self = this; // 103
|
||||
if (self.alea) { // 104
|
||||
return self.alea(); // 105
|
||||
} else if (nodeCrypto) { // 106
|
||||
var numerator = parseInt(self.hexString(8), 16); // 107
|
||||
return numerator * 2.3283064365386963e-10; // 2^-32 // 108
|
||||
} else if (typeof window !== "undefined" && window.crypto && // 109
|
||||
window.crypto.getRandomValues) { // 110
|
||||
var array = new Uint32Array(1); // 111
|
||||
window.crypto.getRandomValues(array); // 112
|
||||
return array[0] * 2.3283064365386963e-10; // 2^-32 // 113
|
||||
} else { // 114
|
||||
throw new Error('No random generator available'); // 115
|
||||
} // 116
|
||||
}; // 117
|
||||
// 118
|
||||
RandomGenerator.prototype.hexString = function (digits) { // 119
|
||||
var self = this; // 120
|
||||
if (nodeCrypto && ! self.alea) { // 121
|
||||
var numBytes = Math.ceil(digits / 2); // 122
|
||||
var bytes; // 123
|
||||
// Try to get cryptographically strong randomness. Fall back to // 124
|
||||
// non-cryptographically strong if not available. // 125
|
||||
try { // 126
|
||||
bytes = nodeCrypto.randomBytes(numBytes); // 127
|
||||
} catch (e) { // 128
|
||||
// XXX should re-throw any error except insufficient entropy // 129
|
||||
bytes = nodeCrypto.pseudoRandomBytes(numBytes); // 130
|
||||
} // 131
|
||||
var result = bytes.toString("hex"); // 132
|
||||
// If the number of digits is odd, we'll have generated an extra 4 bits // 133
|
||||
// of randomness, so we need to trim the last digit. // 134
|
||||
return result.substring(0, digits); // 135
|
||||
} else { // 136
|
||||
var hexDigits = []; // 137
|
||||
for (var i = 0; i < digits; ++i) { // 138
|
||||
hexDigits.push(self.choice("0123456789abcdef")); // 139
|
||||
} // 140
|
||||
return hexDigits.join(''); // 141
|
||||
} // 142
|
||||
}; // 143
|
||||
// 144
|
||||
RandomGenerator.prototype._randomString = function (charsCount, // 145
|
||||
alphabet) { // 146
|
||||
var self = this; // 147
|
||||
var digits = []; // 148
|
||||
for (var i = 0; i < charsCount; i++) { // 149
|
||||
digits[i] = self.choice(alphabet); // 150
|
||||
} // 151
|
||||
return digits.join(""); // 152
|
||||
}; // 153
|
||||
// 154
|
||||
RandomGenerator.prototype.id = function (charsCount) { // 155
|
||||
var self = this; // 156
|
||||
// 17 characters is around 96 bits of entropy, which is the amount of // 157
|
||||
// state in the Alea PRNG. // 158
|
||||
if (charsCount === undefined) // 159
|
||||
charsCount = 17; // 160
|
||||
// 161
|
||||
return self._randomString(charsCount, UNMISTAKABLE_CHARS); // 162
|
||||
}; // 163
|
||||
// 164
|
||||
RandomGenerator.prototype.secret = function (charsCount) { // 165
|
||||
var self = this; // 166
|
||||
// Default to 256 bits of entropy, or 43 characters at 6 bits per // 167
|
||||
// character. // 168
|
||||
if (charsCount === undefined) // 169
|
||||
charsCount = 43; // 170
|
||||
return self._randomString(charsCount, BASE64_CHARS); // 171
|
||||
}; // 172
|
||||
// 173
|
||||
RandomGenerator.prototype.choice = function (arrayOrString) { // 174
|
||||
var index = Math.floor(this.fraction() * arrayOrString.length); // 175
|
||||
if (typeof arrayOrString === "string") // 176
|
||||
return arrayOrString.substr(index, 1); // 177
|
||||
else // 178
|
||||
return arrayOrString[index]; // 179
|
||||
}; // 180
|
||||
// 181
|
||||
// instantiate RNG. Heuristically collect entropy from various sources when a // 182
|
||||
// cryptographic PRNG isn't available. // 183
|
||||
// 184
|
||||
// client sources // 185
|
||||
var height = (typeof window !== 'undefined' && window.innerHeight) || // 186
|
||||
(typeof document !== 'undefined' // 187
|
||||
&& document.documentElement // 188
|
||||
&& document.documentElement.clientHeight) || // 189
|
||||
(typeof document !== 'undefined' // 190
|
||||
&& document.body // 191
|
||||
&& document.body.clientHeight) || // 192
|
||||
1; // 193
|
||||
// 194
|
||||
var width = (typeof window !== 'undefined' && window.innerWidth) || // 195
|
||||
(typeof document !== 'undefined' // 196
|
||||
&& document.documentElement // 197
|
||||
&& document.documentElement.clientWidth) || // 198
|
||||
(typeof document !== 'undefined' // 199
|
||||
&& document.body // 200
|
||||
&& document.body.clientWidth) || // 201
|
||||
1; // 202
|
||||
// 203
|
||||
var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || ""; // 204
|
||||
// 205
|
||||
if (nodeCrypto || // 206
|
||||
(typeof window !== "undefined" && // 207
|
||||
window.crypto && window.crypto.getRandomValues)) // 208
|
||||
Random = new RandomGenerator(); // 209
|
||||
else // 210
|
||||
Random = new RandomGenerator([new Date(), height, width, agent, Math.random()]); // 211
|
||||
// 212
|
||||
Random.createWithSeeds = function () { // 213
|
||||
if (arguments.length === 0) { // 214
|
||||
throw new Error('No seeds were provided'); // 215
|
||||
} // 216
|
||||
return new RandomGenerator(arguments); // 217
|
||||
}; // 218
|
||||
// 219
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/random/deprecated.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Before this package existed, we used to use this Meteor.uuid() // 1
|
||||
// implementing the RFC 4122 v4 UUID. It is no longer documented // 2
|
||||
// and will go away. // 3
|
||||
// XXX COMPAT WITH 0.5.6 // 4
|
||||
Meteor.uuid = function () { // 5
|
||||
var HEX_DIGITS = "0123456789abcdef"; // 6
|
||||
var s = []; // 7
|
||||
for (var i = 0; i < 36; i++) { // 8
|
||||
s[i] = Random.choice(HEX_DIGITS); // 9
|
||||
} // 10
|
||||
s[14] = "4"; // 11
|
||||
s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1); // 12
|
||||
s[8] = s[13] = s[18] = s[23] = "-"; // 13
|
||||
// 14
|
||||
var uuid = s.join(""); // 15
|
||||
return uuid; // 16
|
||||
}; // 17
|
||||
// 18
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.random = { |
||||
Random: Random |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=random.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,129 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Tracker = Package.tracker.Tracker; |
||||
var Deps = Package.tracker.Deps; |
||||
|
||||
/* Package-scope variables */ |
||||
var ReactiveVar; |
||||
|
||||
(function () { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reactive-var/reactive-var.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/* // 1 |
||||
* ## [new] ReactiveVar(initialValue, [equalsFunc]) // 2
|
||||
* // 3
|
||||
* A ReactiveVar holds a single value that can be get and set, // 4
|
||||
* such that calling `set` will invalidate any Computations that // 5
|
||||
* called `get`, according to the usual contract for reactive // 6
|
||||
* data sources. // 7
|
||||
* // 8
|
||||
* A ReactiveVar is much like a Session variable -- compare `foo.get()` // 9
|
||||
* to `Session.get("foo")` -- but it doesn't have a global name and isn't // 10
|
||||
* automatically migrated across hot code pushes. Also, while Session // 11
|
||||
* variables can only hold JSON or EJSON, ReactiveVars can hold any value. // 12
|
||||
* // 13
|
||||
* An important property of ReactiveVars, which is sometimes the reason // 14
|
||||
* to use one, is that setting the value to the same value as before has // 15
|
||||
* no effect, meaning ReactiveVars can be used to absorb extra // 16
|
||||
* invalidations that wouldn't serve a purpose. However, by default, // 17
|
||||
* ReactiveVars are extremely conservative about what changes they // 18
|
||||
* absorb. Calling `set` with an object argument will *always* trigger // 19
|
||||
* invalidations, because even if the new value is `===` the old value, // 20
|
||||
* the object may have been mutated. You can change the default behavior // 21
|
||||
* by passing a function of two arguments, `oldValue` and `newValue`, // 22
|
||||
* to the constructor as `equalsFunc`. // 23
|
||||
* // 24
|
||||
* This class is extremely basic right now, but the idea is to evolve // 25
|
||||
* it into the ReactiveVar of Geoff's Lickable Forms proposal. // 26
|
||||
*/ // 27 |
||||
// 28
|
||||
/** // 29 |
||||
* @class // 30
|
||||
* @instanceName reactiveVar // 31
|
||||
* @summary Constructor for a ReactiveVar, which represents a single reactive variable. // 32
|
||||
* @locus Client // 33
|
||||
* @param {Any} initialValue The initial value to set. `equalsFunc` is ignored when setting the initial value. // 34
|
||||
* @param {Function} [equalsFunc] Optional. A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null. |
||||
*/ // 36 |
||||
ReactiveVar = function (initialValue, equalsFunc) { // 37
|
||||
if (! (this instanceof ReactiveVar)) // 38
|
||||
// called without `new` // 39
|
||||
return new ReactiveVar(initialValue, equalsFunc); // 40
|
||||
// 41
|
||||
this.curValue = initialValue; // 42
|
||||
this.equalsFunc = equalsFunc; // 43
|
||||
this.dep = new Tracker.Dependency; // 44
|
||||
}; // 45
|
||||
// 46
|
||||
ReactiveVar._isEqual = function (oldValue, newValue) { // 47
|
||||
var a = oldValue, b = newValue; // 48
|
||||
// Two values are "equal" here if they are `===` and are // 49
|
||||
// number, boolean, string, undefined, or null. // 50
|
||||
if (a !== b) // 51
|
||||
return false; // 52
|
||||
else // 53
|
||||
return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') || // 54
|
||||
(typeof a === 'string')); // 55
|
||||
}; // 56
|
||||
// 57
|
||||
/** // 58 |
||||
* @summary Returns the current value of the ReactiveVar, establishing a reactive dependency. // 59
|
||||
* @locus Client // 60
|
||||
*/ // 61 |
||||
ReactiveVar.prototype.get = function () { // 62
|
||||
if (Tracker.active) // 63
|
||||
this.dep.depend(); // 64
|
||||
// 65
|
||||
return this.curValue; // 66
|
||||
}; // 67
|
||||
// 68
|
||||
/** // 69 |
||||
* @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value. |
||||
* @locus Client // 71
|
||||
* @param {Any} newValue // 72
|
||||
*/ // 73 |
||||
ReactiveVar.prototype.set = function (newValue) { // 74
|
||||
var oldValue = this.curValue; // 75
|
||||
// 76
|
||||
if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue)) // 77
|
||||
// value is same as last time // 78
|
||||
return; // 79
|
||||
// 80
|
||||
this.curValue = newValue; // 81
|
||||
this.dep.changed(); // 82
|
||||
}; // 83
|
||||
// 84
|
||||
ReactiveVar.prototype.toString = function () { // 85
|
||||
return 'ReactiveVar{' + this.get() + '}'; // 86
|
||||
}; // 87
|
||||
// 88
|
||||
ReactiveVar.prototype._numListeners = function() { // 89
|
||||
// Tests want to know. // 90
|
||||
// Accesses a private field of Tracker.Dependency. // 91
|
||||
var count = 0; // 92
|
||||
for (var id in this.dep._dependentsById) // 93
|
||||
count++; // 94
|
||||
return count; // 95
|
||||
}; // 96
|
||||
// 97
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['reactive-var'] = { |
||||
ReactiveVar: ReactiveVar |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=reactive-var.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["reactive-var/reactive-var.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,E;AACA,mD;AACA,E;AACA,8D;AACA,gE;AACA,6D;AACA,gB;AACA,E;AACA,uE;AACA,yE;AACA,sE;AACA,0E;AACA,E;AACA,uE;AACA,wE;AACA,8D;AACA,qE;AACA,kE;AACA,uE;AACA,uE;AACA,yE;AACA,qE;AACA,sC;AACA,E;AACA,qE;AACA,8D;AACA,G;;AAEA,G;AACA,U;AACA,4B;AACA,uF;AACA,gB;AACA,+G;AACA,yU;AACA,G;AACA,mD;AACA,sC;AACA,2B;AACA,qD;;AAEA,+B;AACA,+B;AACA,oC;AACA,E;;AAEA,sD;AACA,iC;AACA,0D;AACA,iD;AACA,c;AACA,iB;AACA,M;AACA,0E;AACA,qC;AACA,E;;AAEA,G;AACA,6F;AACA,gB;AACA,G;AACA,yC;AACA,qB;AACA,sB;;AAEA,uB;AACA,E;;AAEA,G;AACA,qJ;AACA,gB;AACA,wB;AACA,G;AACA,iD;AACA,+B;;AAEA,oE;AACA,iC;AACA,W;;AAEA,2B;AACA,qB;AACA,E;;AAEA,8C;AACA,2C;AACA,E;;AAEA,kD;AACA,wB;AACA,oD;AACA,gB;AACA,0C;AACA,Y;AACA,e;AACA,E","file":"/packages/reactive-var.js","sourcesContent":["/*\n * ## [new] ReactiveVar(initialValue, [equalsFunc])\n *\n * A ReactiveVar holds a single value that can be get and set,\n * such that calling `set` will invalidate any Computations that\n * called `get`, according to the usual contract for reactive\n * data sources.\n *\n * A ReactiveVar is much like a Session variable -- compare `foo.get()`\n * to `Session.get(\"foo\")` -- but it doesn't have a global name and isn't\n * automatically migrated across hot code pushes. Also, while Session\n * variables can only hold JSON or EJSON, ReactiveVars can hold any value.\n *\n * An important property of ReactiveVars, which is sometimes the reason\n * to use one, is that setting the value to the same value as before has\n * no effect, meaning ReactiveVars can be used to absorb extra\n * invalidations that wouldn't serve a purpose. However, by default,\n * ReactiveVars are extremely conservative about what changes they\n * absorb. Calling `set` with an object argument will *always* trigger\n * invalidations, because even if the new value is `===` the old value,\n * the object may have been mutated. You can change the default behavior\n * by passing a function of two arguments, `oldValue` and `newValue`,\n * to the constructor as `equalsFunc`.\n *\n * This class is extremely basic right now, but the idea is to evolve\n * it into the ReactiveVar of Geoff's Lickable Forms proposal.\n */\n\n/**\n * @class \n * @instanceName reactiveVar\n * @summary Constructor for a ReactiveVar, which represents a single reactive variable.\n * @locus Client\n * @param {Any} initialValue The initial value to set. `equalsFunc` is ignored when setting the initial value.\n * @param {Function} [equalsFunc] Optional. A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null.\n */\nReactiveVar = function (initialValue, equalsFunc) {\n if (! (this instanceof ReactiveVar))\n // called without `new`\n return new ReactiveVar(initialValue, equalsFunc);\n\n this.curValue = initialValue;\n this.equalsFunc = equalsFunc;\n this.dep = new Tracker.Dependency;\n};\n\nReactiveVar._isEqual = function (oldValue, newValue) {\n var a = oldValue, b = newValue;\n // Two values are \"equal\" here if they are `===` and are\n // number, boolean, string, undefined, or null.\n if (a !== b)\n return false;\n else\n return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') ||\n (typeof a === 'string'));\n};\n\n/**\n * @summary Returns the current value of the ReactiveVar, establishing a reactive dependency.\n * @locus Client\n */\nReactiveVar.prototype.get = function () {\n if (Tracker.active)\n this.dep.depend();\n\n return this.curValue;\n};\n\n/**\n * @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value.\n * @locus Client\n * @param {Any} newValue\n */\nReactiveVar.prototype.set = function (newValue) {\n var oldValue = this.curValue;\n\n if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue))\n // value is same as last time\n return;\n\n this.curValue = newValue;\n this.dep.changed();\n};\n\nReactiveVar.prototype.toString = function () {\n return 'ReactiveVar{' + this.get() + '}';\n};\n\nReactiveVar.prototype._numListeners = function() {\n // Tests want to know.\n // Accesses a private field of Tracker.Dependency.\n var count = 0;\n for (var id in this.dep._dependentsById)\n count++;\n return count;\n};\n"]} |
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.reload = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=reload.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/reload.js"} |
@ -0,0 +1,97 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var Random = Package.random.Random; |
||||
|
||||
/* Package-scope variables */ |
||||
var Retry; |
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/retry/retry.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Retry logic with an exponential backoff. // 1
|
||||
// // 2
|
||||
// options: // 3
|
||||
// baseTimeout: time for initial reconnect attempt (ms). // 4
|
||||
// exponent: exponential factor to increase timeout each attempt. // 5
|
||||
// maxTimeout: maximum time between retries (ms). // 6
|
||||
// minCount: how many times to reconnect "instantly". // 7
|
||||
// minTimeout: time to wait for the first `minCount` retries (ms). // 8
|
||||
// fuzz: factor to randomize retry times by (to avoid retry storms). // 9
|
||||
// 10
|
||||
Retry = function (options) { // 11
|
||||
var self = this; // 12
|
||||
_.extend(self, _.defaults(_.clone(options || {}), { // 13
|
||||
baseTimeout: 1000, // 1 second // 14
|
||||
exponent: 2.2, // 15
|
||||
// The default is high-ish to ensure a server can recover from a // 16
|
||||
// failure caused by load. // 17
|
||||
maxTimeout: 5 * 60000, // 5 minutes // 18
|
||||
minTimeout: 10, // 19
|
||||
minCount: 2, // 20
|
||||
fuzz: 0.5 // +- 25% // 21
|
||||
})); // 22
|
||||
self.retryTimer = null; // 23
|
||||
}; // 24
|
||||
// 25
|
||||
_.extend(Retry.prototype, { // 26
|
||||
// 27
|
||||
// Reset a pending retry, if any. // 28
|
||||
clear: function () { // 29
|
||||
var self = this; // 30
|
||||
if (self.retryTimer) // 31
|
||||
clearTimeout(self.retryTimer); // 32
|
||||
self.retryTimer = null; // 33
|
||||
}, // 34
|
||||
// 35
|
||||
// Calculate how long to wait in milliseconds to retry, based on the // 36
|
||||
// `count` of which retry this is. // 37
|
||||
_timeout: function (count) { // 38
|
||||
var self = this; // 39
|
||||
// 40
|
||||
if (count < self.minCount) // 41
|
||||
return self.minTimeout; // 42
|
||||
// 43
|
||||
var timeout = Math.min( // 44
|
||||
self.maxTimeout, // 45
|
||||
self.baseTimeout * Math.pow(self.exponent, count)); // 46
|
||||
// fuzz the timeout randomly, to avoid reconnect storms when a // 47
|
||||
// server goes down. // 48
|
||||
timeout = timeout * ((Random.fraction() * self.fuzz) + // 49
|
||||
(1 - self.fuzz/2)); // 50
|
||||
return timeout; // 51
|
||||
}, // 52
|
||||
// 53
|
||||
// Call `fn` after a delay, based on the `count` of which retry this is. // 54
|
||||
retryLater: function (count, fn) { // 55
|
||||
var self = this; // 56
|
||||
var timeout = self._timeout(count); // 57
|
||||
if (self.retryTimer) // 58
|
||||
clearTimeout(self.retryTimer); // 59
|
||||
self.retryTimer = Meteor.setTimeout(fn, timeout); // 60
|
||||
return timeout; // 61
|
||||
} // 62
|
||||
// 63
|
||||
}); // 64
|
||||
// 65
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.retry = { |
||||
Retry: Retry |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=retry.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["retry/retry.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2C;AACA,E;AACA,W;AACA,yD;AACA,kE;AACA,kD;AACA,sD;AACA,mE;AACA,qE;;AAEA,4B;AACA,kB;AACA,qD;AACA,kC;AACA,kB;AACA,oE;AACA,8B;AACA,uC;AACA,mB;AACA,gB;AACA,uB;AACA,M;AACA,yB;AACA,E;;AAEA,2B;;AAEA,mC;AACA,sB;AACA,oB;AACA,wB;AACA,oC;AACA,2B;AACA,I;;AAEA,sE;AACA,oC;AACA,8B;AACA,oB;;AAEA,8B;AACA,6B;;AAEA,2B;AACA,sB;AACA,yD;AACA,kE;AACA,wB;AACA,0D;AACA,4C;AACA,mB;AACA,I;;AAEA,0E;AACA,oC;AACA,oB;AACA,uC;AACA,wB;AACA,oC;AACA,qD;AACA,mB;AACA,G;;AAEA,G","file":"/packages/retry.js","sourcesContent":["// Retry logic with an exponential backoff.\n//\n// options:\n// baseTimeout: time for initial reconnect attempt (ms).\n// exponent: exponential factor to increase timeout each attempt.\n// maxTimeout: maximum time between retries (ms).\n// minCount: how many times to reconnect \"instantly\".\n// minTimeout: time to wait for the first `minCount` retries (ms).\n// fuzz: factor to randomize retry times by (to avoid retry storms).\n\nRetry = function (options) {\n var self = this;\n _.extend(self, _.defaults(_.clone(options || {}), {\n baseTimeout: 1000, // 1 second\n exponent: 2.2,\n // The default is high-ish to ensure a server can recover from a\n // failure caused by load.\n maxTimeout: 5 * 60000, // 5 minutes\n minTimeout: 10,\n minCount: 2,\n fuzz: 0.5 // +- 25%\n }));\n self.retryTimer = null;\n};\n\n_.extend(Retry.prototype, {\n\n // Reset a pending retry, if any.\n clear: function () {\n var self = this;\n if (self.retryTimer)\n clearTimeout(self.retryTimer);\n self.retryTimer = null;\n },\n\n // Calculate how long to wait in milliseconds to retry, based on the\n // `count` of which retry this is.\n _timeout: function (count) {\n var self = this;\n\n if (count < self.minCount)\n return self.minTimeout;\n\n var timeout = Math.min(\n self.maxTimeout,\n self.baseTimeout * Math.pow(self.exponent, count));\n // fuzz the timeout randomly, to avoid reconnect storms when a\n // server goes down.\n timeout = timeout * ((Random.fraction() * self.fuzz) +\n (1 - self.fuzz/2));\n return timeout;\n },\n\n // Call `fn` after a delay, based on the `count` of which retry this is.\n retryLater: function (count, fn) {\n var self = this;\n var timeout = self._timeout(count);\n if (self.retryTimer)\n clearTimeout(self.retryTimer);\n self.retryTimer = Meteor.setTimeout(fn, timeout);\n return timeout;\n }\n\n});\n"]} |
@ -0,0 +1,161 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var RoutePolicy, RoutePolicyTest; |
||||
|
||||
(function () { |
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/routepolicy/routepolicy.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// In addition to listing specific files to be cached, the browser // 1
|
||||
// application cache manifest allows URLs to be designated as NETWORK // 2
|
||||
// (always fetched from the Internet) and FALLBACK (which we use to // 3
|
||||
// serve app HTML on arbitrary URLs). // 4
|
||||
// // 5
|
||||
// The limitation of the manifest file format is that the designations // 6
|
||||
// are by prefix only: if "/foo" is declared NETWORK then "/foobar" // 7
|
||||
// will also be treated as a network route. // 8
|
||||
// // 9
|
||||
// RoutePolicy is a low-level API for declaring the route type of URL prefixes: // 10
|
||||
// // 11
|
||||
// "network": for network routes that should not conflict with static // 12
|
||||
// resources. (For example, if "/sockjs/" is a network route, we // 13
|
||||
// shouldn't have "/sockjs/red-sock.jpg" as a static resource). // 14
|
||||
// // 15
|
||||
// "static-online": for static resources which should not be cached in // 16
|
||||
// the app cache. This is implemented by also adding them to the // 17
|
||||
// NETWORK section (as otherwise the browser would receive app HTML // 18
|
||||
// for them because of the FALLBACK section), but static-online routes // 19
|
||||
// don't need to be checked for conflict with static resources. // 20
|
||||
// 21
|
||||
// The route policy is a singleton in a running application, but we // 22
|
||||
// can't unit test the real singleton because messing with the real // 23
|
||||
// routes would break tinytest... so allow policy instances to be // 24
|
||||
// constructed for testing. // 25
|
||||
// 26
|
||||
RoutePolicyTest = {}; // 27
|
||||
// 28
|
||||
var RoutePolicyConstructor = RoutePolicyTest.Constructor = function () { // 29
|
||||
var self = this; // 30
|
||||
self.urlPrefixTypes = {}; // 31
|
||||
}; // 32
|
||||
// 33
|
||||
_.extend(RoutePolicyConstructor.prototype, { // 34
|
||||
// 35
|
||||
urlPrefixMatches: function (urlPrefix, url) { // 36
|
||||
return url.substr(0, urlPrefix.length) === urlPrefix; // 37
|
||||
}, // 38
|
||||
// 39
|
||||
checkType: function (type) { // 40
|
||||
if (! _.contains(['network', 'static-online'], type)) // 41
|
||||
return 'the route type must be "network" or "static-online"'; // 42
|
||||
return null; // 43
|
||||
}, // 44
|
||||
// 45
|
||||
checkUrlPrefix: function (urlPrefix, type) { // 46
|
||||
var self = this; // 47
|
||||
// 48
|
||||
if (urlPrefix.charAt(0) !== '/') // 49
|
||||
return 'a route URL prefix must begin with a slash'; // 50
|
||||
// 51
|
||||
if (urlPrefix === '/') // 52
|
||||
return 'a route URL prefix cannot be /'; // 53
|
||||
// 54
|
||||
var existingType = self.urlPrefixTypes[urlPrefix]; // 55
|
||||
if (existingType && existingType !== type) // 56
|
||||
return 'the route URL prefix ' + urlPrefix + ' has already been declared to be of type ' + existingType; // 57
|
||||
// 58
|
||||
return null; // 59
|
||||
}, // 60
|
||||
// 61
|
||||
checkForConflictWithStatic: function (urlPrefix, type, _testManifest) { // 62
|
||||
var self = this; // 63
|
||||
if (type === 'static-online') // 64
|
||||
return null; // 65
|
||||
if (!Package.webapp || !Package.webapp.WebApp // 66
|
||||
|| !Package.webapp.WebApp.clientPrograms // 67
|
||||
|| !Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest) { // 68
|
||||
// Hack: If we don't have a manifest, deal with it // 69
|
||||
// gracefully. This lets us load livedata into a nodejs // 70
|
||||
// environment that doesn't have a HTTP server (eg, a // 71
|
||||
// command-line tool). // 72
|
||||
return null; // 73
|
||||
} // 74
|
||||
var manifest = _testManifest || // 75
|
||||
Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest; // 76
|
||||
var conflict = _.find(manifest, function (resource) { // 77
|
||||
return (resource.type === 'static' && // 78
|
||||
resource.where === 'client' && // 79
|
||||
self.urlPrefixMatches(urlPrefix, resource.url)); // 80
|
||||
}); // 81
|
||||
if (conflict) // 82
|
||||
return ('static resource ' + conflict.url + ' conflicts with ' + // 83
|
||||
type + ' route ' + urlPrefix); // 84
|
||||
else // 85
|
||||
return null; // 86
|
||||
}, // 87
|
||||
// 88
|
||||
declare: function (urlPrefix, type) { // 89
|
||||
var self = this; // 90
|
||||
var problem = self.checkType(type) || // 91
|
||||
self.checkUrlPrefix(urlPrefix, type) || // 92
|
||||
self.checkForConflictWithStatic(urlPrefix, type); // 93
|
||||
if (problem) // 94
|
||||
throw new Error(problem); // 95
|
||||
// TODO overlapping prefixes, e.g. /foo/ and /foo/bar/ // 96
|
||||
self.urlPrefixTypes[urlPrefix] = type; // 97
|
||||
}, // 98
|
||||
// 99
|
||||
isValidUrl: function (url) { // 100
|
||||
return url.charAt(0) === '/'; // 101
|
||||
}, // 102
|
||||
// 103
|
||||
classify: function (url) { // 104
|
||||
var self = this; // 105
|
||||
if (url.charAt(0) !== '/') // 106
|
||||
throw new Error('url must be a relative URL: ' + url); // 107
|
||||
var prefix = _.find(_.keys(self.urlPrefixTypes), function (_prefix) { // 108
|
||||
return self.urlPrefixMatches(_prefix, url); // 109
|
||||
}); // 110
|
||||
if (prefix) // 111
|
||||
return self.urlPrefixTypes[prefix]; // 112
|
||||
else // 113
|
||||
return null; // 114
|
||||
}, // 115
|
||||
// 116
|
||||
urlPrefixesFor: function (type) { // 117
|
||||
var self = this; // 118
|
||||
var prefixes = []; // 119
|
||||
_.each(self.urlPrefixTypes, function (_type, _prefix) { // 120
|
||||
if (_type === type) // 121
|
||||
prefixes.push(_prefix); // 122
|
||||
}); // 123
|
||||
return prefixes.sort(); // 124
|
||||
} // 125
|
||||
}); // 126
|
||||
// 127
|
||||
RoutePolicy = new RoutePolicyConstructor(); // 128
|
||||
// 129
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.routepolicy = { |
||||
RoutePolicy: RoutePolicy, |
||||
RoutePolicyTest: RoutePolicyTest |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=routepolicy.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.session = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=session.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;","file":"/packages/session.js"} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,316 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var HTML = Package.htmljs.HTML; |
||||
var Tracker = Package.tracker.Tracker; |
||||
var Deps = Package.tracker.Deps; |
||||
var Blaze = Package.blaze.Blaze; |
||||
var UI = Package.blaze.UI; |
||||
var Handlebars = Package.blaze.Handlebars; |
||||
var ObserveSequence = Package['observe-sequence'].ObserveSequence; |
||||
var _ = Package.underscore._; |
||||
|
||||
/* Package-scope variables */ |
||||
var Spacebars; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/spacebars/spacebars-runtime.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
Spacebars = {}; // 1
|
||||
// 2
|
||||
var tripleEquals = function (a, b) { return a === b; }; // 3
|
||||
// 4
|
||||
Spacebars.include = function (templateOrFunction, contentFunc, elseFunc) { // 5
|
||||
if (! templateOrFunction) // 6
|
||||
return null; // 7
|
||||
// 8
|
||||
if (typeof templateOrFunction !== 'function') { // 9
|
||||
var template = templateOrFunction; // 10
|
||||
if (! Blaze.isTemplate(template)) // 11
|
||||
throw new Error("Expected template or null, found: " + template); // 12
|
||||
return templateOrFunction.constructView(contentFunc, elseFunc); // 13
|
||||
} // 14
|
||||
// 15
|
||||
var templateVar = Blaze.ReactiveVar(null, tripleEquals); // 16
|
||||
var view = Blaze.View('Spacebars.include', function () { // 17
|
||||
var template = templateVar.get(); // 18
|
||||
if (template === null) // 19
|
||||
return null; // 20
|
||||
// 21
|
||||
if (! Blaze.isTemplate(template)) // 22
|
||||
throw new Error("Expected template or null, found: " + template); // 23
|
||||
// 24
|
||||
return template.constructView(contentFunc, elseFunc); // 25
|
||||
}); // 26
|
||||
view.__templateVar = templateVar; // 27
|
||||
view.onViewCreated(function () { // 28
|
||||
this.autorun(function () { // 29
|
||||
templateVar.set(templateOrFunction()); // 30
|
||||
}); // 31
|
||||
}); // 32
|
||||
// 33
|
||||
return view; // 34
|
||||
}; // 35
|
||||
// 36
|
||||
// Executes `{{foo bar baz}}` when called on `(foo, bar, baz)`. // 37
|
||||
// If `bar` and `baz` are functions, they are called before // 38
|
||||
// `foo` is called on them. // 39
|
||||
// // 40
|
||||
// This is the shared part of Spacebars.mustache and // 41
|
||||
// Spacebars.attrMustache, which differ in how they post-process the // 42
|
||||
// result. // 43
|
||||
Spacebars.mustacheImpl = function (value/*, args*/) { // 44
|
||||
var args = arguments; // 45
|
||||
// if we have any arguments (pos or kw), add an options argument // 46
|
||||
// if there isn't one. // 47
|
||||
if (args.length > 1) { // 48
|
||||
var kw = args[args.length - 1]; // 49
|
||||
if (! (kw instanceof Spacebars.kw)) { // 50
|
||||
kw = Spacebars.kw(); // 51
|
||||
// clone arguments into an actual array, then push // 52
|
||||
// the empty kw object. // 53
|
||||
args = Array.prototype.slice.call(arguments); // 54
|
||||
args.push(kw); // 55
|
||||
} else { // 56
|
||||
// For each keyword arg, call it if it's a function // 57
|
||||
var newHash = {}; // 58
|
||||
for (var k in kw.hash) { // 59
|
||||
var v = kw.hash[k]; // 60
|
||||
newHash[k] = (typeof v === 'function' ? v() : v); // 61
|
||||
} // 62
|
||||
args[args.length - 1] = Spacebars.kw(newHash); // 63
|
||||
} // 64
|
||||
} // 65
|
||||
// 66
|
||||
return Spacebars.call.apply(null, args); // 67
|
||||
}; // 68
|
||||
// 69
|
||||
Spacebars.mustache = function (value/*, args*/) { // 70
|
||||
var result = Spacebars.mustacheImpl.apply(null, arguments); // 71
|
||||
// 72
|
||||
if (result instanceof Spacebars.SafeString) // 73
|
||||
return HTML.Raw(result.toString()); // 74
|
||||
else // 75
|
||||
// map `null`, `undefined`, and `false` to null, which is important // 76
|
||||
// so that attributes with nully values are considered absent. // 77
|
||||
// stringify anything else (e.g. strings, booleans, numbers including 0). // 78
|
||||
return (result == null || result === false) ? null : String(result); // 79
|
||||
}; // 80
|
||||
// 81
|
||||
Spacebars.attrMustache = function (value/*, args*/) { // 82
|
||||
var result = Spacebars.mustacheImpl.apply(null, arguments); // 83
|
||||
// 84
|
||||
if (result == null || result === '') { // 85
|
||||
return null; // 86
|
||||
} else if (typeof result === 'object') { // 87
|
||||
return result; // 88
|
||||
} else if (typeof result === 'string' && HTML.isValidAttributeName(result)) { // 89
|
||||
var obj = {}; // 90
|
||||
obj[result] = ''; // 91
|
||||
return obj; // 92
|
||||
} else { // 93
|
||||
throw new Error("Expected valid attribute name, '', null, or object"); // 94
|
||||
} // 95
|
||||
}; // 96
|
||||
// 97
|
||||
Spacebars.dataMustache = function (value/*, args*/) { // 98
|
||||
var result = Spacebars.mustacheImpl.apply(null, arguments); // 99
|
||||
// 100
|
||||
return result; // 101
|
||||
}; // 102
|
||||
// 103
|
||||
// Idempotently wrap in `HTML.Raw`. // 104
|
||||
// // 105
|
||||
// Called on the return value from `Spacebars.mustache` in case the // 106
|
||||
// template uses triple-stache (`{{{foo bar baz}}}`). // 107
|
||||
Spacebars.makeRaw = function (value) { // 108
|
||||
if (value == null) // null or undefined // 109
|
||||
return null; // 110
|
||||
else if (value instanceof HTML.Raw) // 111
|
||||
return value; // 112
|
||||
else // 113
|
||||
return HTML.Raw(value); // 114
|
||||
}; // 115
|
||||
// 116
|
||||
// If `value` is a function, called it on the `args`, after // 117
|
||||
// evaluating the args themselves (by calling them if they are // 118
|
||||
// functions). Otherwise, simply return `value` (and assert that // 119
|
||||
// there are no args). // 120
|
||||
Spacebars.call = function (value/*, args*/) { // 121
|
||||
if (typeof value === 'function') { // 122
|
||||
// evaluate arguments if they are functions (by calling them) // 123
|
||||
var newArgs = []; // 124
|
||||
for (var i = 1; i < arguments.length; i++) { // 125
|
||||
var arg = arguments[i]; // 126
|
||||
newArgs[i-1] = (typeof arg === 'function' ? arg() : arg); // 127
|
||||
} // 128
|
||||
// 129
|
||||
return value.apply(null, newArgs); // 130
|
||||
} else { // 131
|
||||
if (arguments.length > 1) // 132
|
||||
throw new Error("Can't call non-function: " + value); // 133
|
||||
// 134
|
||||
return value; // 135
|
||||
} // 136
|
||||
}; // 137
|
||||
// 138
|
||||
// Call this as `Spacebars.kw({ ... })`. The return value // 139
|
||||
// is `instanceof Spacebars.kw`. // 140
|
||||
Spacebars.kw = function (hash) { // 141
|
||||
if (! (this instanceof Spacebars.kw)) // 142
|
||||
// called without new; call with new // 143
|
||||
return new Spacebars.kw(hash); // 144
|
||||
// 145
|
||||
this.hash = hash || {}; // 146
|
||||
}; // 147
|
||||
// 148
|
||||
// Call this as `Spacebars.SafeString("some HTML")`. The return value // 149
|
||||
// is `instanceof Spacebars.SafeString` (and `instanceof Handlebars.SafeString). // 150
|
||||
Spacebars.SafeString = function (html) { // 151
|
||||
if (! (this instanceof Spacebars.SafeString)) // 152
|
||||
// called without new; call with new // 153
|
||||
return new Spacebars.SafeString(html); // 154
|
||||
// 155
|
||||
return new Handlebars.SafeString(html); // 156
|
||||
}; // 157
|
||||
Spacebars.SafeString.prototype = Handlebars.SafeString.prototype; // 158
|
||||
// 159
|
||||
// `Spacebars.dot(foo, "bar", "baz")` performs a special kind // 160
|
||||
// of `foo.bar.baz` that allows safe indexing of `null` and // 161
|
||||
// indexing of functions (which calls the function). If the // 162
|
||||
// result is a function, it is always a bound function (e.g. // 163
|
||||
// a wrapped version of `baz` that always uses `foo.bar` as // 164
|
||||
// `this`). // 165
|
||||
// // 166
|
||||
// In `Spacebars.dot(foo, "bar")`, `foo` is assumed to be either // 167
|
||||
// a non-function value or a "fully-bound" function wrapping a value, // 168
|
||||
// where fully-bound means it takes no arguments and ignores `this`. // 169
|
||||
// // 170
|
||||
// `Spacebars.dot(foo, "bar")` performs the following steps: // 171
|
||||
// // 172
|
||||
// * If `foo` is falsy, return `foo`. // 173
|
||||
// // 174
|
||||
// * If `foo` is a function, call it (set `foo` to `foo()`). // 175
|
||||
// // 176
|
||||
// * If `foo` is falsy now, return `foo`. // 177
|
||||
// // 178
|
||||
// * Return `foo.bar`, binding it to `foo` if it's a function. // 179
|
||||
Spacebars.dot = function (value, id1/*, id2, ...*/) { // 180
|
||||
if (arguments.length > 2) { // 181
|
||||
// Note: doing this recursively is probably less efficient than // 182
|
||||
// doing it in an iterative loop. // 183
|
||||
var argsForRecurse = []; // 184
|
||||
argsForRecurse.push(Spacebars.dot(value, id1)); // 185
|
||||
argsForRecurse.push.apply(argsForRecurse, // 186
|
||||
Array.prototype.slice.call(arguments, 2)); // 187
|
||||
return Spacebars.dot.apply(null, argsForRecurse); // 188
|
||||
} // 189
|
||||
// 190
|
||||
if (typeof value === 'function') // 191
|
||||
value = value(); // 192
|
||||
// 193
|
||||
if (! value) // 194
|
||||
return value; // falsy, don't index, pass through // 195
|
||||
// 196
|
||||
var result = value[id1]; // 197
|
||||
if (typeof result !== 'function') // 198
|
||||
return result; // 199
|
||||
// `value[id1]` (or `value()[id1]`) is a function. // 200
|
||||
// Bind it so that when called, `value` will be placed in `this`. // 201
|
||||
return function (/*arguments*/) { // 202
|
||||
return result.apply(value, arguments); // 203
|
||||
}; // 204
|
||||
}; // 205
|
||||
// 206
|
||||
// Spacebars.With implements the conditional logic of rendering // 207
|
||||
// the `{{else}}` block if the argument is falsy. It combines // 208
|
||||
// a Blaze.If with a Blaze.With (the latter only in the truthy // 209
|
||||
// case, since the else block is evaluated without entering // 210
|
||||
// a new data context). // 211
|
||||
Spacebars.With = function (argFunc, contentFunc, elseFunc) { // 212
|
||||
var argVar = new Blaze.ReactiveVar; // 213
|
||||
var view = Blaze.View('Spacebars_with', function () { // 214
|
||||
return Blaze.If(function () { return argVar.get(); }, // 215
|
||||
function () { return Blaze.With(function () { // 216
|
||||
return argVar.get(); }, contentFunc); }, // 217
|
||||
elseFunc); // 218
|
||||
}); // 219
|
||||
view.onViewCreated(function () { // 220
|
||||
this.autorun(function () { // 221
|
||||
argVar.set(argFunc()); // 222
|
||||
// 223
|
||||
// This is a hack so that autoruns inside the body // 224
|
||||
// of the #with get stopped sooner. It reaches inside // 225
|
||||
// our ReactiveVar to access its dep. // 226
|
||||
// 227
|
||||
Tracker.onInvalidate(function () { // 228
|
||||
argVar.dep.changed(); // 229
|
||||
}); // 230
|
||||
// 231
|
||||
// Take the case of `{{#with A}}{{B}}{{/with}}`. The goal // 232
|
||||
// is to not re-render `B` if `A` changes to become falsy // 233
|
||||
// and `B` is simultaneously invalidated. // 234
|
||||
// // 235
|
||||
// A series of autoruns are involved: // 236
|
||||
// // 237
|
||||
// 1. This autorun (argument to Spacebars.With) // 238
|
||||
// 2. Argument to Blaze.If // 239
|
||||
// 3. Blaze.If view re-render // 240
|
||||
// 4. Argument to Blaze.With // 241
|
||||
// 5. The template tag `{{B}}` // 242
|
||||
// // 243
|
||||
// When (3) is invalidated, it immediately stops (4) and (5) // 244
|
||||
// because of a Tracker.onInvalidate built into materializeView. // 245
|
||||
// (When a View's render method is invalidated, it immediately // 246
|
||||
// tears down all the subviews, via a Tracker.onInvalidate much // 247
|
||||
// like this one. // 248
|
||||
// // 249
|
||||
// Suppose `A` changes to become falsy, and `B` changes at the // 250
|
||||
// same time (i.e. without an intervening flush). // 251
|
||||
// Without the code above, this happens: // 252
|
||||
// // 253
|
||||
// - (1) and (5) are invalidated. // 254
|
||||
// - (1) runs, invalidating (2) and (4). // 255
|
||||
// - (5) runs. // 256
|
||||
// - (2) runs, invalidating (3), stopping (4) and (5). // 257
|
||||
// // 258
|
||||
// With the code above: // 259
|
||||
// // 260
|
||||
// - (1) and (5) are invalidated, invalidating (2) and (4). // 261
|
||||
// - (1) runs. // 262
|
||||
// - (2) runs, invalidating (3), stopping (4) and (5). // 263
|
||||
// // 264
|
||||
// If the re-run of (5) is originally enqueued before (1), all // 265
|
||||
// bets are off, but typically that doesn't seem to be the // 266
|
||||
// case. Anyway, doing this is always better than not doing it, // 267
|
||||
// because it might save a bunch of DOM from being updated // 268
|
||||
// needlessly. // 269
|
||||
}); // 270
|
||||
}); // 271
|
||||
// 272
|
||||
return view; // 273
|
||||
}; // 274
|
||||
// 275
|
||||
// XXX COMPAT WITH 0.9.0 // 276
|
||||
Spacebars.TemplateWith = Blaze._TemplateWith; // 277
|
||||
// 278
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.spacebars = { |
||||
Spacebars: Spacebars |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=spacebars.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,33 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
/* Package-scope variables */ |
||||
var lodash, _; |
||||
|
||||
(function () { |
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/stevezhu:lodash/server.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
_ = lodash = Npm.require('lodash'); // 1
|
||||
// 2
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package['stevezhu:lodash'] = { |
||||
lodash: lodash, |
||||
_: _ |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=stevezhu_lodash.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["stevezhu:lodash/server.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mC","file":"/packages/stevezhu_lodash.js","sourcesContent":["_ = lodash = Npm.require('lodash');\n"]} |
@ -0,0 +1,19 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var _ = Package.underscore._; |
||||
var Blaze = Package.blaze.Blaze; |
||||
var UI = Package.blaze.UI; |
||||
var Handlebars = Package.blaze.Handlebars; |
||||
var HTML = Package.htmljs.HTML; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.templating = {}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=templating.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;","file":"/packages/templating.js"} |
@ -0,0 +1,660 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
|
||||
/* Package-scope variables */ |
||||
var Tracker, Deps; |
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/tracker/tracker.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
///////////////////////////////////////////////////// // 1
|
||||
// Package docs at http://docs.meteor.com/#tracker // // 2
|
||||
///////////////////////////////////////////////////// // 3
|
||||
// 4
|
||||
/** // 5 |
||||
* @namespace Tracker // 6
|
||||
* @summary The namespace for Tracker-related methods. // 7
|
||||
*/ // 8 |
||||
Tracker = {}; // 9
|
||||
// 10
|
||||
// http://docs.meteor.com/#tracker_active // 11
|
||||
// 12
|
||||
/** // 13 |
||||
* @summary True if there is a current computation, meaning that dependencies on reactive data sources will be tracked and potentially cause the current computation to be rerun. |
||||
* @locus Client // 15
|
||||
* @type {Boolean} // 16
|
||||
*/ // 17 |
||||
Tracker.active = false; // 18
|
||||
// 19
|
||||
// http://docs.meteor.com/#tracker_currentcomputation // 20
|
||||
// 21
|
||||
/** // 22 |
||||
* @summary The current computation, or `null` if there isn't one. The current computation is the [`Tracker.Computation`](#tracker_computation) object created by the innermost active call to `Tracker.autorun`, and it's the computation that gains dependencies when reactive data sources are accessed. |
||||
* @locus Client // 24
|
||||
* @type {Tracker.Computation} // 25
|
||||
*/ // 26 |
||||
Tracker.currentComputation = null; // 27
|
||||
// 28
|
||||
// References to all computations created within the Tracker by id. // 29
|
||||
// Keeping these references on an underscore property gives more control to // 30
|
||||
// tooling and packages extending Tracker without increasing the API surface. // 31
|
||||
// These can used to monkey-patch computations, their functions, use // 32
|
||||
// computation ids for tracking, etc. // 33
|
||||
Tracker._computations = {}; // 34
|
||||
// 35
|
||||
var setCurrentComputation = function (c) { // 36
|
||||
Tracker.currentComputation = c; // 37
|
||||
Tracker.active = !! c; // 38
|
||||
}; // 39
|
||||
// 40
|
||||
var _debugFunc = function () { // 41
|
||||
// We want this code to work without Meteor, and also without // 42
|
||||
// "console" (which is technically non-standard and may be missing // 43
|
||||
// on some browser we come across, like it was on IE 7). // 44
|
||||
// // 45
|
||||
// Lazy evaluation because `Meteor` does not exist right away.(??) // 46
|
||||
return (typeof Meteor !== "undefined" ? Meteor._debug : // 47
|
||||
((typeof console !== "undefined") && console.error ? // 48
|
||||
function () { console.error.apply(console, arguments); } : // 49
|
||||
function () {})); // 50
|
||||
}; // 51
|
||||
// 52
|
||||
var _maybeSupressMoreLogs = function (messagesLength) { // 53
|
||||
// Sometimes when running tests, we intentionally supress logs on expected // 54
|
||||
// printed errors. Since the current implementation of _throwOrLog can log // 55
|
||||
// multiple separate log messages, supress all of them if at least one supress // 56
|
||||
// is expected as we still want them to count as one. // 57
|
||||
if (typeof Meteor !== "undefined") { // 58
|
||||
if (Meteor._supressed_log_expected()) { // 59
|
||||
Meteor._suppress_log(messagesLength - 1); // 60
|
||||
} // 61
|
||||
} // 62
|
||||
}; // 63
|
||||
// 64
|
||||
var _throwOrLog = function (from, e) { // 65
|
||||
if (throwFirstError) { // 66
|
||||
throw e; // 67
|
||||
} else { // 68
|
||||
var printArgs = ["Exception from Tracker " + from + " function:"]; // 69
|
||||
if (e.stack && e.message && e.name) { // 70
|
||||
var idx = e.stack.indexOf(e.message); // 71
|
||||
if (idx < 0 || idx > e.name.length + 2) { // check for "Error: " // 72
|
||||
// message is not part of the stack // 73
|
||||
var message = e.name + ": " + e.message; // 74
|
||||
printArgs.push(message); // 75
|
||||
} // 76
|
||||
} // 77
|
||||
printArgs.push(e.stack); // 78
|
||||
_maybeSupressMoreLogs(printArgs.length); // 79
|
||||
// 80
|
||||
for (var i = 0; i < printArgs.length; i++) { // 81
|
||||
_debugFunc()(printArgs[i]); // 82
|
||||
} // 83
|
||||
} // 84
|
||||
}; // 85
|
||||
// 86
|
||||
// Takes a function `f`, and wraps it in a `Meteor._noYieldsAllowed` // 87
|
||||
// block if we are running on the server. On the client, returns the // 88
|
||||
// original function (since `Meteor._noYieldsAllowed` is a // 89
|
||||
// no-op). This has the benefit of not adding an unnecessary stack // 90
|
||||
// frame on the client. // 91
|
||||
var withNoYieldsAllowed = function (f) { // 92
|
||||
if ((typeof Meteor === 'undefined') || Meteor.isClient) { // 93
|
||||
return f; // 94
|
||||
} else { // 95
|
||||
return function () { // 96
|
||||
var args = arguments; // 97
|
||||
Meteor._noYieldsAllowed(function () { // 98
|
||||
f.apply(null, args); // 99
|
||||
}); // 100
|
||||
}; // 101
|
||||
} // 102
|
||||
}; // 103
|
||||
// 104
|
||||
var nextId = 1; // 105
|
||||
// computations whose callbacks we should call at flush time // 106
|
||||
var pendingComputations = []; // 107
|
||||
// `true` if a Tracker.flush is scheduled, or if we are in Tracker.flush now // 108
|
||||
var willFlush = false; // 109
|
||||
// `true` if we are in Tracker.flush now // 110
|
||||
var inFlush = false; // 111
|
||||
// `true` if we are computing a computation now, either first time // 112
|
||||
// or recompute. This matches Tracker.active unless we are inside // 113
|
||||
// Tracker.nonreactive, which nullfies currentComputation even though // 114
|
||||
// an enclosing computation may still be running. // 115
|
||||
var inCompute = false; // 116
|
||||
// `true` if the `_throwFirstError` option was passed in to the call // 117
|
||||
// to Tracker.flush that we are in. When set, throw rather than log the // 118
|
||||
// first error encountered while flushing. Before throwing the error, // 119
|
||||
// finish flushing (from a finally block), logging any subsequent // 120
|
||||
// errors. // 121
|
||||
var throwFirstError = false; // 122
|
||||
// 123
|
||||
var afterFlushCallbacks = []; // 124
|
||||
// 125
|
||||
var requireFlush = function () { // 126
|
||||
if (! willFlush) { // 127
|
||||
// We want this code to work without Meteor, see debugFunc above // 128
|
||||
if (typeof Meteor !== "undefined") // 129
|
||||
Meteor._setImmediate(Tracker._runFlush); // 130
|
||||
else // 131
|
||||
setTimeout(Tracker._runFlush, 0); // 132
|
||||
willFlush = true; // 133
|
||||
} // 134
|
||||
}; // 135
|
||||
// 136
|
||||
// Tracker.Computation constructor is visible but private // 137
|
||||
// (throws an error if you try to call it) // 138
|
||||
var constructingComputation = false; // 139
|
||||
// 140
|
||||
// // 141
|
||||
// http://docs.meteor.com/#tracker_computation // 142
|
||||
// 143
|
||||
/** // 144 |
||||
* @summary A Computation object represents code that is repeatedly rerun // 145
|
||||
* in response to // 146
|
||||
* reactive data changes. Computations don't have return values; they just // 147
|
||||
* perform actions, such as rerendering a template on the screen. Computations // 148
|
||||
* are created using Tracker.autorun. Use stop to prevent further rerunning of a // 149
|
||||
* computation. // 150
|
||||
* @instancename computation // 151
|
||||
*/ // 152 |
||||
Tracker.Computation = function (f, parent, onError) { // 153
|
||||
if (! constructingComputation) // 154
|
||||
throw new Error( // 155
|
||||
"Tracker.Computation constructor is private; use Tracker.autorun"); // 156
|
||||
constructingComputation = false; // 157
|
||||
// 158
|
||||
var self = this; // 159
|
||||
// 160
|
||||
// http://docs.meteor.com/#computation_stopped // 161
|
||||
// 162
|
||||
/** // 163 |
||||
* @summary True if this computation has been stopped. // 164
|
||||
* @locus Client // 165
|
||||
* @memberOf Tracker.Computation // 166
|
||||
* @instance // 167
|
||||
* @name stopped // 168
|
||||
*/ // 169 |
||||
self.stopped = false; // 170
|
||||
// 171
|
||||
// http://docs.meteor.com/#computation_invalidated // 172
|
||||
// 173
|
||||
/** // 174 |
||||
* @summary True if this computation has been invalidated (and not yet rerun), or if it has been stopped. // 175
|
||||
* @locus Client // 176
|
||||
* @memberOf Tracker.Computation // 177
|
||||
* @instance // 178
|
||||
* @name invalidated // 179
|
||||
* @type {Boolean} // 180
|
||||
*/ // 181 |
||||
self.invalidated = false; // 182
|
||||
// 183
|
||||
// http://docs.meteor.com/#computation_firstrun // 184
|
||||
// 185
|
||||
/** // 186 |
||||
* @summary True during the initial run of the computation at the time `Tracker.autorun` is called, and false on subsequent reruns and at other times. |
||||
* @locus Client // 188
|
||||
* @memberOf Tracker.Computation // 189
|
||||
* @instance // 190
|
||||
* @name firstRun // 191
|
||||
* @type {Boolean} // 192
|
||||
*/ // 193 |
||||
self.firstRun = true; // 194
|
||||
// 195
|
||||
self._id = nextId++; // 196
|
||||
self._onInvalidateCallbacks = []; // 197
|
||||
// the plan is at some point to use the parent relation // 198
|
||||
// to constrain the order that computations are processed // 199
|
||||
self._parent = parent; // 200
|
||||
self._func = f; // 201
|
||||
self._onError = onError; // 202
|
||||
self._recomputing = false; // 203
|
||||
// 204
|
||||
// Register the computation within the global Tracker. // 205
|
||||
Tracker._computations[self._id] = self; // 206
|
||||
// 207
|
||||
var errored = true; // 208
|
||||
try { // 209
|
||||
self._compute(); // 210
|
||||
errored = false; // 211
|
||||
} finally { // 212
|
||||
self.firstRun = false; // 213
|
||||
if (errored) // 214
|
||||
self.stop(); // 215
|
||||
} // 216
|
||||
}; // 217
|
||||
// 218
|
||||
// http://docs.meteor.com/#computation_oninvalidate // 219
|
||||
// 220
|
||||
/** // 221 |
||||
* @summary Registers `callback` to run when this computation is next invalidated, or runs it immediately if the computation is already invalidated. The callback is run exactly once and not upon future invalidations unless `onInvalidate` is called again after the computation becomes valid again. |
||||
* @locus Client // 223
|
||||
* @param {Function} callback Function to be called on invalidation. Receives one argument, the computation that was invalidated. |
||||
*/ // 225 |
||||
Tracker.Computation.prototype.onInvalidate = function (f) { // 226
|
||||
var self = this; // 227
|
||||
// 228
|
||||
if (typeof f !== 'function') // 229
|
||||
throw new Error("onInvalidate requires a function"); // 230
|
||||
// 231
|
||||
if (self.invalidated) { // 232
|
||||
Tracker.nonreactive(function () { // 233
|
||||
withNoYieldsAllowed(f)(self); // 234
|
||||
}); // 235
|
||||
} else { // 236
|
||||
self._onInvalidateCallbacks.push(f); // 237
|
||||
} // 238
|
||||
}; // 239
|
||||
// 240
|
||||
// http://docs.meteor.com/#computation_invalidate // 241
|
||||
// 242
|
||||
/** // 243 |
||||
* @summary Invalidates this computation so that it will be rerun. // 244
|
||||
* @locus Client // 245
|
||||
*/ // 246 |
||||
Tracker.Computation.prototype.invalidate = function () { // 247
|
||||
var self = this; // 248
|
||||
if (! self.invalidated) { // 249
|
||||
// if we're currently in _recompute(), don't enqueue // 250
|
||||
// ourselves, since we'll rerun immediately anyway. // 251
|
||||
if (! self._recomputing && ! self.stopped) { // 252
|
||||
requireFlush(); // 253
|
||||
pendingComputations.push(this); // 254
|
||||
} // 255
|
||||
// 256
|
||||
self.invalidated = true; // 257
|
||||
// 258
|
||||
// callbacks can't add callbacks, because // 259
|
||||
// self.invalidated === true. // 260
|
||||
for(var i = 0, f; f = self._onInvalidateCallbacks[i]; i++) { // 261
|
||||
Tracker.nonreactive(function () { // 262
|
||||
withNoYieldsAllowed(f)(self); // 263
|
||||
}); // 264
|
||||
} // 265
|
||||
self._onInvalidateCallbacks = []; // 266
|
||||
} // 267
|
||||
}; // 268
|
||||
// 269
|
||||
// http://docs.meteor.com/#computation_stop // 270
|
||||
// 271
|
||||
/** // 272 |
||||
* @summary Prevents this computation from rerunning. // 273
|
||||
* @locus Client // 274
|
||||
*/ // 275 |
||||
Tracker.Computation.prototype.stop = function () { // 276
|
||||
if (! this.stopped) { // 277
|
||||
this.stopped = true; // 278
|
||||
this.invalidate(); // 279
|
||||
// Unregister from global Tracker. // 280
|
||||
delete Tracker._computations[this._id]; // 281
|
||||
} // 282
|
||||
}; // 283
|
||||
// 284
|
||||
Tracker.Computation.prototype._compute = function () { // 285
|
||||
var self = this; // 286
|
||||
self.invalidated = false; // 287
|
||||
// 288
|
||||
var previous = Tracker.currentComputation; // 289
|
||||
setCurrentComputation(self); // 290
|
||||
var previousInCompute = inCompute; // 291
|
||||
inCompute = true; // 292
|
||||
try { // 293
|
||||
withNoYieldsAllowed(self._func)(self); // 294
|
||||
} finally { // 295
|
||||
setCurrentComputation(previous); // 296
|
||||
inCompute = previousInCompute; // 297
|
||||
} // 298
|
||||
}; // 299
|
||||
// 300
|
||||
Tracker.Computation.prototype._needsRecompute = function () { // 301
|
||||
var self = this; // 302
|
||||
return self.invalidated && ! self.stopped; // 303
|
||||
}; // 304
|
||||
// 305
|
||||
Tracker.Computation.prototype._recompute = function () { // 306
|
||||
var self = this; // 307
|
||||
// 308
|
||||
self._recomputing = true; // 309
|
||||
try { // 310
|
||||
if (self._needsRecompute()) { // 311
|
||||
try { // 312
|
||||
self._compute(); // 313
|
||||
} catch (e) { // 314
|
||||
if (self._onError) { // 315
|
||||
self._onError(e); // 316
|
||||
} else { // 317
|
||||
_throwOrLog("recompute", e); // 318
|
||||
} // 319
|
||||
} // 320
|
||||
} // 321
|
||||
} finally { // 322
|
||||
self._recomputing = false; // 323
|
||||
} // 324
|
||||
}; // 325
|
||||
// 326
|
||||
// // 327
|
||||
// http://docs.meteor.com/#tracker_dependency // 328
|
||||
// 329
|
||||
/** // 330 |
||||
* @summary A Dependency represents an atomic unit of reactive data that a // 331
|
||||
* computation might depend on. Reactive data sources such as Session or // 332
|
||||
* Minimongo internally create different Dependency objects for different // 333
|
||||
* pieces of data, each of which may be depended on by multiple computations. // 334
|
||||
* When the data changes, the computations are invalidated. // 335
|
||||
* @class // 336
|
||||
* @instanceName dependency // 337
|
||||
*/ // 338 |
||||
Tracker.Dependency = function () { // 339
|
||||
this._dependentsById = {}; // 340
|
||||
}; // 341
|
||||
// 342
|
||||
// http://docs.meteor.com/#dependency_depend // 343
|
||||
// // 344
|
||||
// Adds `computation` to this set if it is not already // 345
|
||||
// present. Returns true if `computation` is a new member of the set. // 346
|
||||
// If no argument, defaults to currentComputation, or does nothing // 347
|
||||
// if there is no currentComputation. // 348
|
||||
// 349
|
||||
/** // 350 |
||||
* @summary Declares that the current computation (or `fromComputation` if given) depends on `dependency`. The computation will be invalidated the next time `dependency` changes. |
||||
// 352
|
||||
If there is no current computation and `depend()` is called with no arguments, it does nothing and returns false. // 353
|
||||
// 354
|
||||
Returns true if the computation is a new dependent of `dependency` rather than an existing one. // 355
|
||||
* @locus Client // 356
|
||||
* @param {Tracker.Computation} [fromComputation] An optional computation declared to depend on `dependency` instead of the current computation. |
||||
* @returns {Boolean} // 358
|
||||
*/ // 359 |
||||
Tracker.Dependency.prototype.depend = function (computation) { // 360
|
||||
if (! computation) { // 361
|
||||
if (! Tracker.active) // 362
|
||||
return false; // 363
|
||||
// 364
|
||||
computation = Tracker.currentComputation; // 365
|
||||
} // 366
|
||||
var self = this; // 367
|
||||
var id = computation._id; // 368
|
||||
if (! (id in self._dependentsById)) { // 369
|
||||
self._dependentsById[id] = computation; // 370
|
||||
computation.onInvalidate(function () { // 371
|
||||
delete self._dependentsById[id]; // 372
|
||||
}); // 373
|
||||
return true; // 374
|
||||
} // 375
|
||||
return false; // 376
|
||||
}; // 377
|
||||
// 378
|
||||
// http://docs.meteor.com/#dependency_changed // 379
|
||||
// 380
|
||||
/** // 381 |
||||
* @summary Invalidate all dependent computations immediately and remove them as dependents. // 382
|
||||
* @locus Client // 383
|
||||
*/ // 384 |
||||
Tracker.Dependency.prototype.changed = function () { // 385
|
||||
var self = this; // 386
|
||||
for (var id in self._dependentsById) // 387
|
||||
self._dependentsById[id].invalidate(); // 388
|
||||
}; // 389
|
||||
// 390
|
||||
// http://docs.meteor.com/#dependency_hasdependents // 391
|
||||
// 392
|
||||
/** // 393 |
||||
* @summary True if this Dependency has one or more dependent Computations, which would be invalidated if this Dependency were to change. |
||||
* @locus Client // 395
|
||||
* @returns {Boolean} // 396
|
||||
*/ // 397 |
||||
Tracker.Dependency.prototype.hasDependents = function () { // 398
|
||||
var self = this; // 399
|
||||
for(var id in self._dependentsById) // 400
|
||||
return true; // 401
|
||||
return false; // 402
|
||||
}; // 403
|
||||
// 404
|
||||
// http://docs.meteor.com/#tracker_flush // 405
|
||||
// 406
|
||||
/** // 407 |
||||
* @summary Process all reactive updates immediately and ensure that all invalidated computations are rerun. // 408
|
||||
* @locus Client // 409
|
||||
*/ // 410 |
||||
Tracker.flush = function (options) { // 411
|
||||
Tracker._runFlush({ finishSynchronously: true, // 412
|
||||
throwFirstError: options && options._throwFirstError }); // 413
|
||||
}; // 414
|
||||
// 415
|
||||
// Run all pending computations and afterFlush callbacks. If we were not called // 416
|
||||
// directly via Tracker.flush, this may return before they're all done to allow // 417
|
||||
// the event loop to run a little before continuing. // 418
|
||||
Tracker._runFlush = function (options) { // 419
|
||||
// XXX What part of the comment below is still true? (We no longer // 420
|
||||
// have Spark) // 421
|
||||
// // 422
|
||||
// Nested flush could plausibly happen if, say, a flush causes // 423
|
||||
// DOM mutation, which causes a "blur" event, which runs an // 424
|
||||
// app event handler that calls Tracker.flush. At the moment // 425
|
||||
// Spark blocks event handlers during DOM mutation anyway, // 426
|
||||
// because the LiveRange tree isn't valid. And we don't have // 427
|
||||
// any useful notion of a nested flush. // 428
|
||||
// // 429
|
||||
// https://app.asana.com/0/159908330244/385138233856 // 430
|
||||
if (inFlush) // 431
|
||||
throw new Error("Can't call Tracker.flush while flushing"); // 432
|
||||
// 433
|
||||
if (inCompute) // 434
|
||||
throw new Error("Can't flush inside Tracker.autorun"); // 435
|
||||
// 436
|
||||
options = options || {}; // 437
|
||||
// 438
|
||||
inFlush = true; // 439
|
||||
willFlush = true; // 440
|
||||
throwFirstError = !! options.throwFirstError; // 441
|
||||
// 442
|
||||
var recomputedCount = 0; // 443
|
||||
var finishedTry = false; // 444
|
||||
try { // 445
|
||||
while (pendingComputations.length || // 446
|
||||
afterFlushCallbacks.length) { // 447
|
||||
// 448
|
||||
// recompute all pending computations // 449
|
||||
while (pendingComputations.length) { // 450
|
||||
var comp = pendingComputations.shift(); // 451
|
||||
comp._recompute(); // 452
|
||||
if (comp._needsRecompute()) { // 453
|
||||
pendingComputations.unshift(comp); // 454
|
||||
} // 455
|
||||
// 456
|
||||
if (! options.finishSynchronously && ++recomputedCount > 1000) { // 457
|
||||
finishedTry = true; // 458
|
||||
return; // 459
|
||||
} // 460
|
||||
} // 461
|
||||
// 462
|
||||
if (afterFlushCallbacks.length) { // 463
|
||||
// call one afterFlush callback, which may // 464
|
||||
// invalidate more computations // 465
|
||||
var func = afterFlushCallbacks.shift(); // 466
|
||||
try { // 467
|
||||
func(); // 468
|
||||
} catch (e) { // 469
|
||||
_throwOrLog("afterFlush", e); // 470
|
||||
} // 471
|
||||
} // 472
|
||||
} // 473
|
||||
finishedTry = true; // 474
|
||||
} finally { // 475
|
||||
if (! finishedTry) { // 476
|
||||
// we're erroring due to throwFirstError being true. // 477
|
||||
inFlush = false; // needed before calling `Tracker.flush()` again // 478
|
||||
// finish flushing // 479
|
||||
Tracker._runFlush({ // 480
|
||||
finishSynchronously: options.finishSynchronously, // 481
|
||||
throwFirstError: false // 482
|
||||
}); // 483
|
||||
} // 484
|
||||
willFlush = false; // 485
|
||||
inFlush = false; // 486
|
||||
if (pendingComputations.length || afterFlushCallbacks.length) { // 487
|
||||
// We're yielding because we ran a bunch of computations and we aren't // 488
|
||||
// required to finish synchronously, so we'd like to give the event loop a // 489
|
||||
// chance. We should flush again soon. // 490
|
||||
if (options.finishSynchronously) { // 491
|
||||
throw new Error("still have more to do?"); // shouldn't happen // 492
|
||||
} // 493
|
||||
setTimeout(requireFlush, 10); // 494
|
||||
} // 495
|
||||
} // 496
|
||||
}; // 497
|
||||
// 498
|
||||
// http://docs.meteor.com/#tracker_autorun // 499
|
||||
// // 500
|
||||
// Run f(). Record its dependencies. Rerun it whenever the // 501
|
||||
// dependencies change. // 502
|
||||
// // 503
|
||||
// Returns a new Computation, which is also passed to f. // 504
|
||||
// // 505
|
||||
// Links the computation to the current computation // 506
|
||||
// so that it is stopped if the current computation is invalidated. // 507
|
||||
// 508
|
||||
/** // 509 |
||||
* @callback Tracker.ComputationFunction // 510
|
||||
* @param {Tracker.Computation} // 511
|
||||
*/ // 512 |
||||
/** // 513 |
||||
* @summary Run a function now and rerun it later whenever its dependencies // 514
|
||||
* change. Returns a Computation object that can be used to stop or observe the // 515
|
||||
* rerunning. // 516
|
||||
* @locus Client // 517
|
||||
* @param {Tracker.ComputationFunction} runFunc The function to run. It receives // 518
|
||||
* one argument: the Computation object that will be returned. // 519
|
||||
* @param {Object} [options] // 520
|
||||
* @param {Function} options.onError Optional. The function to run when an error // 521
|
||||
* happens in the Computation. The only argument it recieves is the Error // 522
|
||||
* thrown. Defaults to the error being logged to the console. // 523
|
||||
* @returns {Tracker.Computation} // 524
|
||||
*/ // 525 |
||||
Tracker.autorun = function (f, options) { // 526
|
||||
if (typeof f !== 'function') // 527
|
||||
throw new Error('Tracker.autorun requires a function argument'); // 528
|
||||
// 529
|
||||
options = options || {}; // 530
|
||||
// 531
|
||||
constructingComputation = true; // 532
|
||||
var c = new Tracker.Computation( // 533
|
||||
f, Tracker.currentComputation, options.onError); // 534
|
||||
// 535
|
||||
if (Tracker.active) // 536
|
||||
Tracker.onInvalidate(function () { // 537
|
||||
c.stop(); // 538
|
||||
}); // 539
|
||||
// 540
|
||||
return c; // 541
|
||||
}; // 542
|
||||
// 543
|
||||
// http://docs.meteor.com/#tracker_nonreactive // 544
|
||||
// // 545
|
||||
// Run `f` with no current computation, returning the return value // 546
|
||||
// of `f`. Used to turn off reactivity for the duration of `f`, // 547
|
||||
// so that reactive data sources accessed by `f` will not result in any // 548
|
||||
// computations being invalidated. // 549
|
||||
// 550
|
||||
/** // 551 |
||||
* @summary Run a function without tracking dependencies. // 552
|
||||
* @locus Client // 553
|
||||
* @param {Function} func A function to call immediately. // 554
|
||||
*/ // 555 |
||||
Tracker.nonreactive = function (f) { // 556
|
||||
var previous = Tracker.currentComputation; // 557
|
||||
setCurrentComputation(null); // 558
|
||||
try { // 559
|
||||
return f(); // 560
|
||||
} finally { // 561
|
||||
setCurrentComputation(previous); // 562
|
||||
} // 563
|
||||
}; // 564
|
||||
// 565
|
||||
// http://docs.meteor.com/#tracker_oninvalidate // 566
|
||||
// 567
|
||||
/** // 568 |
||||
* @summary Registers a new [`onInvalidate`](#computation_oninvalidate) callback on the current computation (which must exist), to be called immediately when the current computation is invalidated or stopped. |
||||
* @locus Client // 570
|
||||
* @param {Function} callback A callback function that will be invoked as `func(c)`, where `c` is the computation on which the callback is registered. |
||||
*/ // 572 |
||||
Tracker.onInvalidate = function (f) { // 573
|
||||
if (! Tracker.active) // 574
|
||||
throw new Error("Tracker.onInvalidate requires a currentComputation"); // 575
|
||||
// 576
|
||||
Tracker.currentComputation.onInvalidate(f); // 577
|
||||
}; // 578
|
||||
// 579
|
||||
// http://docs.meteor.com/#tracker_afterflush // 580
|
||||
// 581
|
||||
/** // 582 |
||||
* @summary Schedules a function to be called during the next flush, or later in the current flush if one is in progress, after all invalidated computations have been rerun. The function will be run once and not on subsequent flushes unless `afterFlush` is called again. |
||||
* @locus Client // 584
|
||||
* @param {Function} callback A function to call at flush time. // 585
|
||||
*/ // 586 |
||||
Tracker.afterFlush = function (f) { // 587
|
||||
afterFlushCallbacks.push(f); // 588
|
||||
requireFlush(); // 589
|
||||
}; // 590
|
||||
// 591
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () { |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/tracker/deprecated.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Deprecated functions. // 1
|
||||
// 2
|
||||
// These functions used to be on the Meteor object (and worked slightly // 3
|
||||
// differently). // 4
|
||||
// XXX COMPAT WITH 0.5.7 // 5
|
||||
Meteor.flush = Tracker.flush; // 6
|
||||
Meteor.autorun = Tracker.autorun; // 7
|
||||
// 8
|
||||
// We used to require a special "autosubscribe" call to reactively subscribe to // 9
|
||||
// things. Now, it works with autorun. // 10
|
||||
// XXX COMPAT WITH 0.5.4 // 11
|
||||
Meteor.autosubscribe = Tracker.autorun; // 12
|
||||
// 13
|
||||
// This Tracker API briefly existed in 0.5.8 and 0.5.9 // 14
|
||||
// XXX COMPAT WITH 0.5.9 // 15
|
||||
Tracker.depend = function (d) { // 16
|
||||
return d.depend(); // 17
|
||||
}; // 18
|
||||
// 19
|
||||
Deps = Tracker; // 20
|
||||
// 21
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this); |
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.tracker = { |
||||
Tracker: Tracker, |
||||
Deps: Deps |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=tracker.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,25 @@ |
||||
(function () { |
||||
|
||||
/* Imports */ |
||||
var Meteor = Package.meteor.Meteor; |
||||
var Blaze = Package.blaze.Blaze; |
||||
var UI = Package.blaze.UI; |
||||
var Handlebars = Package.blaze.Handlebars; |
||||
var HTML = Package.htmljs.HTML; |
||||
|
||||
/* Package-scope variables */ |
||||
var Blaze, UI, Handlebars; |
||||
|
||||
|
||||
|
||||
/* Exports */ |
||||
if (typeof Package === 'undefined') Package = {}; |
||||
Package.ui = { |
||||
Blaze: Blaze, |
||||
UI: UI, |
||||
Handlebars: Handlebars |
||||
}; |
||||
|
||||
})(); |
||||
|
||||
//# sourceMappingURL=ui.js.map
|
@ -0,0 +1 @@ |
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;","file":"/packages/ui.js"} |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue