catberry
Advanced tools
Comparing version 8.6.1 to 9.0.0
@@ -1,29 +0,9 @@ | ||
/** | ||
* This file is a template and it is used only for some string replaces | ||
* by BrowserBundleBuilder module. It does not work by itself. | ||
*/ | ||
'use strict'; | ||
const stores = [ | ||
const Catberry = require('./Catberry.js'); | ||
const BootstrapperBase = require('../lib/base/BootstrapperBase'); | ||
const StoreDispatcher = require('../lib/StoreDispatcher'); | ||
const ModuleApiProvider = require('./providers/ModuleApiProvider'); | ||
const CookieWrapper = require('./CookieWrapper'); | ||
/** __stores **/ | ||
]; | ||
const components = [ | ||
/** __components **/ | ||
]; | ||
const routeDefinitions = '__routeDefinitions' || []; | ||
const routeDescriptors = '__routes' || []; | ||
const Catberry = require('./node_modules/catberry/browser/Catberry.js'); | ||
const BootstrapperBase = require('./node_modules/catberry/lib/base/BootstrapperBase.js'); | ||
const StoreDispatcher = require('./node_modules/catberry/lib/StoreDispatcher'); | ||
const ModuleApiProvider = require('./node_modules/catberry/browser/providers/ModuleApiProvider'); | ||
const CookieWrapper = require('./node_modules/catberry/browser/CookieWrapper'); | ||
class Bootstrapper extends BootstrapperBase { | ||
@@ -51,12 +31,2 @@ | ||
locator.registerInstance('window', window); | ||
routeDefinitions.forEach(routeDefinition => | ||
locator.registerInstance('routeDefinition', routeDefinition)); | ||
routeDescriptors.forEach(routeDescriptor => | ||
locator.registerInstance('routeDescriptor', routeDescriptor)); | ||
stores.forEach(store => locator.registerInstance('store', store)); | ||
components.forEach(component => locator.registerInstance('component', component)); | ||
} | ||
@@ -63,0 +33,0 @@ } |
@@ -31,2 +31,15 @@ 'use strict'; | ||
wrapDocument() { | ||
const appDefinitions = require('appDefinitions'); | ||
appDefinitions.routeDefinitions | ||
.forEach(routeDefinition => this.locator.registerInstance('routeDefinition', routeDefinition)); | ||
appDefinitions.routeDescriptors | ||
.forEach(routeDescriptor => this.locator.registerInstance('routeDescriptor', routeDescriptor)); | ||
appDefinitions.stores | ||
.forEach(store => this.locator.registerInstance('store', store)); | ||
appDefinitions.components | ||
.forEach(component => this.locator.registerInstance('component', component)); | ||
this._router = this.locator.resolve('requestRouter'); | ||
@@ -33,0 +46,0 @@ } |
@@ -1014,4 +1014,2 @@ 'use strict'; | ||
}; | ||
componentContext.sendBroadcastAction = (name, args) => | ||
this._storeDispatcher.sendBroadcastAction(name, args); | ||
@@ -1018,0 +1016,0 @@ return Object.freeze(componentContext); |
'use strict'; | ||
const moduleHelper = require('../../lib/helpers/moduleHelper'); | ||
const templateHelper = require('../../lib/helpers/templateHelper'); | ||
const LoaderBase = require('../../lib/base/LoaderBase'); | ||
@@ -36,7 +37,8 @@ | ||
/** | ||
* Current template provider. | ||
* @type {TemplateProvider} | ||
* Current template provider map. | ||
* @type {Object} | ||
* @private | ||
*/ | ||
this._templateProvider = locator.resolve('templateProvider'); | ||
this._templateProvidersByNames = templateHelper | ||
.resolveTemplateProvidersByNames(locator); | ||
@@ -102,16 +104,13 @@ /** | ||
} | ||
component = transformed; | ||
this._templateProvider.registerCompiled( | ||
component.name, component.templateSource | ||
); | ||
component.template = { | ||
render: dataContext => this._templateProvider.render(component.name, dataContext) | ||
}; | ||
if (typeof (component.errorTemplateSource) === 'string') { | ||
const errorTemplateName = moduleHelper.getNameForErrorTemplate(component.name); | ||
this._templateProvider.registerCompiled(errorTemplateName, component.errorTemplateSource); | ||
component.errorTemplate = { | ||
render: dataContext => this._templateProvider.render(errorTemplateName, dataContext) | ||
}; | ||
component = Object.create(transformed); | ||
component.templateProvider = this._templateProvidersByNames[component.templateProviderName]; | ||
component.errorTemplateProvider = this._templateProvidersByNames[component.errorTemplateProviderName]; | ||
if (!component.templateProvider && | ||
(component.errorTemplateProviderName && !component.errorTemplateProvider)) { | ||
throw new Error(`Template provider required by the component "${component.name}" not found`); | ||
} | ||
templateHelper.registerTemplates(component); | ||
this._eventBus.emit('componentLoaded', component); | ||
@@ -118,0 +117,0 @@ return component; |
@@ -24,3 +24,3 @@ 'use strict'; | ||
*/ | ||
this.version = '8.6.1'; | ||
this.version = '9.0.0'; | ||
@@ -27,0 +27,0 @@ /** |
@@ -8,3 +8,3 @@ 'use strict'; | ||
const BrowserBundleBuilder = require('./builders/BrowserBundleBuilder'); | ||
const BootstrapperBuilder = require('./builders/BootstrapperBuilder'); | ||
const AppDefinitionsBuilder = require('./builders/AppDefinitionsBuilder'); | ||
const StoreFinder = require('./finders/StoreFinder'); | ||
@@ -46,3 +46,3 @@ const ComponentFinder = require('./finders/ComponentFinder'); | ||
locator.register('browserBundleBuilder', BrowserBundleBuilder, true); | ||
locator.register('bootstrapperBuilder', BootstrapperBuilder, true); | ||
locator.register('appDefinitionsBuilder', AppDefinitionsBuilder, true); | ||
locator.register('storeFinder', StoreFinder, true); | ||
@@ -49,0 +49,0 @@ locator.register('componentFinder', ComponentFinder, true); |
@@ -10,11 +10,14 @@ 'use strict'; | ||
const babelify = require('babelify'); | ||
const babelifyPreset = require('babel-preset-es2015-ie'); | ||
const babelEnv = require('babel-preset-env'); | ||
const babili = require('babel-preset-babili'); | ||
const browserify = require('browserify'); | ||
const hrTimeHelper = require('../helpers/hrTimeHelper'); | ||
const UglifyTransform = require('../streams/UglifyTransform'); | ||
const DEFAULT_PUBLIC_DIRECTORY = path.join(process.cwd(), 'public'); | ||
const TEMPORARY_BOOTSTRAPPER_FILENAME = '__BrowserBundle.js'; | ||
const WORKING_DIR = process.cwd(); | ||
const DEFAULT_PUBLIC_DIRECTORY = path.join(WORKING_DIR, 'public'); | ||
const TEMPORARY_APP_DEFINITIONS_FILENAME = '.appDefinitions.js'; | ||
const BROWSER_SCRIPT_FILENAME = 'browser.js'; | ||
const BUNDLE_FILENAME = 'bundle.js'; | ||
const APP_DEFAULT_FILENAME = 'app.js'; | ||
const EXTERNALS_DEFAULT_FILENAME = 'externals.js'; | ||
const APP_DEPENDENCY_ID_REGEXP = process.platform === 'win32' ? /^(\.|\w:)/ : /^[\/.]/; | ||
@@ -24,3 +27,3 @@ var packageDescriptionString = ''; | ||
try { | ||
const packageDescription = require(path.join(process.cwd(), 'package.json')); | ||
const packageDescription = require(path.join(WORKING_DIR, 'package.json')); | ||
if (packageDescription && | ||
@@ -68,16 +71,23 @@ packageDescription.name && | ||
/** | ||
* Current path to the bundle.js. | ||
* Current path to the application bundle file. | ||
* @type {string} | ||
* @private | ||
*/ | ||
this._bundlePath = path.join(this._publicPath, (config.bundleFilename || BUNDLE_FILENAME)); | ||
this._appPath = path.join(this._publicPath, (config.appBundleFilename || APP_DEFAULT_FILENAME)); | ||
/** | ||
* Current path to the __BrowserBundle.js. | ||
* Current path to the externals bunlde file. | ||
* @type {string} | ||
* @private | ||
*/ | ||
this._bootstrapperPath = path.join(process.cwd(), TEMPORARY_BOOTSTRAPPER_FILENAME); | ||
this._externalsPath = path.join(this._publicPath, (config.externalsBundleFilename || EXTERNALS_DEFAULT_FILENAME)); | ||
/** | ||
* Current path to the __appDefinitions.js. | ||
* @type {string} | ||
* @private | ||
*/ | ||
this._appDefinitionsPath = path.join(WORKING_DIR, TEMPORARY_APP_DEFINITIONS_FILENAME); | ||
/** | ||
* Current path to the browser.js. | ||
@@ -87,3 +97,3 @@ * @type {string} | ||
*/ | ||
this._entryPath = path.join(process.cwd(), BROWSER_SCRIPT_FILENAME); | ||
this._entryPath = path.join(WORKING_DIR, BROWSER_SCRIPT_FILENAME); | ||
@@ -105,7 +115,7 @@ /** | ||
/** | ||
* Current bootstrapper builder. | ||
* @type {BootstrapperBuilder} | ||
* Current app definitions builder. | ||
* @type {AppDefinitionsBuilder} | ||
* @private | ||
*/ | ||
this._bootstrapperBuilder = locator.resolve('bootstrapperBuilder'); | ||
this._appDefinitionsBuilder = locator.resolve('appDefinitionsBuilder'); | ||
@@ -163,14 +173,28 @@ /** | ||
/** | ||
* Current Browserify bundler. | ||
* Current Browserify app bundler. | ||
* @type {Browserify} | ||
* @private | ||
*/ | ||
this._bundler = null; | ||
this._appBundler = null; | ||
/** | ||
* Current bootstrapper cache. | ||
* Current Browserify externals bundler. | ||
* @type {Browserify} | ||
* @private | ||
*/ | ||
this._externalsBundler = null; | ||
/** | ||
* Current set of external modules. | ||
* @type {Object} | ||
* @private | ||
*/ | ||
this._externalModules = {}; | ||
/** | ||
* Current app definitions cache. | ||
* @type {string} | ||
* @private | ||
*/ | ||
this._bootstrapperCache = ''; | ||
this._appDefinitionsCache = ''; | ||
} | ||
@@ -185,4 +209,4 @@ | ||
.then(isExists => !isExists ? makeDirectory(this._publicPath) : null) | ||
.then(() => this._createBootstrapper()) | ||
.then(() => new Promise((fulfill, reject) => this._createBundler() | ||
.then(() => this._createAppDefinitions()) | ||
.then(() => new Promise((fulfill, reject) => this._createAppBundler() | ||
.once('error', reject) | ||
@@ -196,5 +220,15 @@ .once('bundle', bundleStream => bundleStream | ||
) | ||
.then(() => new Promise((fulfill, reject) => this._createExternalsBundler() | ||
.once('error', reject) | ||
.once('bundle', bundleStream => bundleStream | ||
.once('end', fulfill) | ||
.on('error', reject) | ||
) | ||
.bundle() | ||
) | ||
) | ||
.then(() => this._doPostBuildActions()) | ||
.then(() => this._isRelease ? | ||
pfs.unlink(this._bootstrapperPath) : | ||
pfs.unlink(this._appDefinitionsPath) : | ||
this._watch() | ||
@@ -206,7 +240,7 @@ ) | ||
/** | ||
* Creates a bootstrapper file for the bundler. | ||
* Creates a app definitions file for the bundler. | ||
* @returns {Promise} The promise for finished work. | ||
* @private | ||
*/ | ||
_createBootstrapper() { | ||
_createAppDefinitions() { | ||
return Promise.all([ | ||
@@ -216,9 +250,9 @@ this._storeFinder.find(), | ||
]) | ||
.then(found => this._bootstrapperBuilder.build(found[0], found[1])) | ||
.then(realBootstrapper => { | ||
if (realBootstrapper === this._bootstrapperCache) { | ||
.then(found => this._appDefinitionsBuilder.build(found[0], found[1])) | ||
.then(realAppDefinitions => { | ||
if (realAppDefinitions === this._appDefinitionsCache) { | ||
return null; | ||
} | ||
this._bootstrapperCache = realBootstrapper; | ||
return pfs.writeFile(this._bootstrapperPath, realBootstrapper); | ||
this._appDefinitionsCache = realAppDefinitions; | ||
return pfs.writeFile(this._appDefinitionsPath, realAppDefinitions); | ||
}); | ||
@@ -228,56 +262,50 @@ } | ||
/** | ||
* Creates the browserify bundler or re-uses the existing one. | ||
* Creates the browserify bundler for the app or re-uses the existing one. | ||
* @returns {Browserify} The browserify instance. | ||
* @private | ||
*/ | ||
_createBundler() { | ||
if (this._bundler) { | ||
return this._bundler; | ||
_createAppBundler() { | ||
if (this._appBundler) { | ||
return this._appBundler; | ||
} | ||
this._bundler = browserify([this._entryPath], { | ||
this._appBundler = browserify(this._entryPath, { | ||
cache: {}, | ||
packageCache: {}, | ||
debug: !this._isRelease | ||
}) | ||
.transform(babelify, { | ||
global: true, | ||
ast: false, | ||
comments: false, | ||
sourceMap: !this._isRelease, | ||
presets: [babelifyPreset] | ||
}); | ||
debug: !this._isRelease, | ||
filter: id => { | ||
if (APP_DEPENDENCY_ID_REGEXP.test(id)) { | ||
return true; | ||
} | ||
this._externalModules[id] = true; | ||
return false; | ||
} | ||
}); | ||
this._appBundler.require( | ||
this._appDefinitionsPath, {expose: 'appDefinitions'} | ||
); | ||
this._appBundler.external('catberry'); | ||
if (!this._isRelease) { | ||
this._bundler.plugin(watchify); | ||
this._eventBus.emit('info', 'Watching files for changes to rebuild the bundle...'); | ||
} else { | ||
this._bundler.transform(file => { | ||
if (path.extname(file) !== '.js') { | ||
return new stream.PassThrough(); | ||
} | ||
this._eventBus.emit('trace', `Minifying code of the file "${file}"...`); | ||
return new UglifyTransform(); | ||
}, { | ||
global: true | ||
}); | ||
this._appBundler.plugin(watchify); | ||
this._eventBus.emit('info', 'Watching files for changes to rebuild the app bundle...'); | ||
} | ||
this._setTransformations(); | ||
this._setPlugins(); | ||
this._attachExtensionsToBundler(this._appBundler); | ||
var startTime; | ||
const resetHandler = () => { | ||
this._eventBus.emit('info', `Building browser script bundle at "${this._bundlePath}"...`); | ||
this._eventBus.emit('info', `Building browser script bundle for the app at "${this._appPath}"...`); | ||
startTime = hrTimeHelper.get(); | ||
}; | ||
this._bundler | ||
this._appBundler | ||
.on('update', ids => { | ||
this._eventBus.emit('bundleChanged', { | ||
path: this._bundlePath, | ||
this._eventBus.emit('appBundleChanged', { | ||
path: this._appPath, | ||
changedFiles: ids | ||
}); | ||
this._bundler.bundle(); | ||
this._appBundler.bundle(); | ||
}) | ||
@@ -287,3 +315,3 @@ .on('error', error => this._eventBus.emit('error', error)) | ||
.on('bundle', sourceStream => { | ||
const outputStream = fs.createWriteStream(this._bundlePath); | ||
const outputStream = fs.createWriteStream(this._appPath); | ||
if (this._isRelease) { | ||
@@ -294,4 +322,4 @@ outputStream.write(packageDescriptionString); | ||
const hrTime = hrTimeHelper.get(startTime); | ||
this._eventBus.emit('bundleBuilt', { | ||
path: this._bundlePath, | ||
this._eventBus.emit('appBundleBuilt', { | ||
path: this._appPath, | ||
hrTime, | ||
@@ -305,6 +333,81 @@ time: hrTimeHelper.toMilliseconds(hrTime) | ||
resetHandler(); // to set startTime universally. | ||
return this._bundler; | ||
return this._appBundler; | ||
} | ||
/** | ||
* Creates the browserify bundler for externals or re-uses the existing one. | ||
* @returns {Browserify} The browserify instances. | ||
* @private | ||
*/ | ||
_createExternalsBundler() { | ||
if (this._externalsBundler) { | ||
return this._externalsBundler; | ||
} | ||
this._externalsBundler = browserify({ | ||
cache: {}, | ||
packageCache: {}, | ||
debug: !this._isRelease | ||
}); | ||
this._externalsBundler.require(Object.keys(this._externalModules)); | ||
this._externalsBundler.external('appDefinitions'); | ||
this._attachExtensionsToBundler(this._externalsBundler); | ||
const startTime = hrTimeHelper.get(); | ||
this._eventBus.emit('info', `Building browser script bundle for externals at "${this._externalsPath}"...`); | ||
this._externalsBundler | ||
.on('error', error => this._eventBus.emit('error', error)) | ||
.on('bundle', sourceStream => { | ||
const outputStream = fs.createWriteStream(this._externalsPath); | ||
outputStream.once('finish', () => { | ||
const hrTime = hrTimeHelper.get(startTime); | ||
this._eventBus.emit('externalsBundleBuilt', { | ||
path: this._externalsPath, | ||
hrTime, | ||
time: hrTimeHelper.toMilliseconds(hrTime) | ||
}); | ||
}); | ||
sourceStream.pipe(outputStream); | ||
}); | ||
return this._externalsBundler; | ||
} | ||
/** | ||
* Attaches necessary plugins and transformations to the bundle. | ||
* @param {Browserify} bundler The bundler to attach extensions. | ||
*/ | ||
_attachExtensionsToBundler(bundler) { | ||
const isDebug = !this._isRelease; | ||
const presets = [[ | ||
babelEnv, { | ||
targets: { | ||
browsers: [ | ||
'last 2 versions', | ||
'not ie <= 10' | ||
] | ||
}, | ||
debug: isDebug | ||
} | ||
]]; | ||
if (this._isRelease) { | ||
presets.push(babili); | ||
} | ||
bundler.transform(babelify, { | ||
global: true, | ||
ast: false, | ||
comments: false, | ||
presets, | ||
sourceMap: isDebug | ||
}); | ||
this._setTransformations(bundler); | ||
this._setPlugins(bundler); | ||
} | ||
/** | ||
* Does all the registered post build actions. | ||
@@ -345,3 +448,3 @@ * @param {number?} index Current action index for recursive calls. | ||
_watch() { | ||
const watchHandler = this._createBootstrapper.bind(this); | ||
const watchHandler = this._createAppDefinitions.bind(this); | ||
this._componentFinder.watch(); | ||
@@ -375,3 +478,3 @@ this._componentFinder | ||
} | ||
this._bundler.transform( | ||
this._appBundler.transform( | ||
currentTransformation.transform, currentTransformation.options | ||
@@ -397,3 +500,3 @@ ); | ||
} | ||
this._bundler.plugin( | ||
this._appBundler.plugin( | ||
currentPlugin.plugin, currentPlugin.options | ||
@@ -400,0 +503,0 @@ ); |
@@ -21,3 +21,3 @@ 'use strict'; | ||
${userAgent || 'Unknown browser'};<br/> | ||
Catberry@8.6.1 ( | ||
Catberry@9.0.0 ( | ||
<a href="https://github.com/catberry/catberry/issues" target="_blank"> | ||
@@ -24,0 +24,0 @@ report an issue |
@@ -6,2 +6,4 @@ 'use strict'; | ||
const moduleHelper = require('../helpers/moduleHelper'); | ||
const loadHelper = require('../helpers/loadHelper'); | ||
const templateHelper = require('../helpers/templateHelper'); | ||
const path = require('path'); | ||
@@ -36,7 +38,7 @@ const LoaderBase = require('../base/LoaderBase'); | ||
/** | ||
* Current template provider. | ||
* @type {TemplateProvider} | ||
* Current template provider list. | ||
* @type {Array<TemplateProvider>} | ||
* @private | ||
*/ | ||
this._templateProvider = locator.resolve('templateProvider'); | ||
this._templateProviders = templateHelper.resolveTemplateProviders(locator); | ||
@@ -151,11 +153,12 @@ /** | ||
return this._loadTemplateSources(component) | ||
.then(() => this._compileTemplates(component)) | ||
.then(compiledTemplates => this._applyTransforms(component) | ||
return loadHelper.loadTemplateSources(component) | ||
.then(() => loadHelper.assignTemplateProviders(component, this._templateProviders)) | ||
.then(() => loadHelper.compileTemplates(component)) | ||
.then(() => this._applyTransforms(component) | ||
.then(transformed => { | ||
if (!transformed) { | ||
throw new Error(`Transformation for the "${componentDetails.name}" component returned a bad result`); | ||
throw new Error(`Transformation for the "${component.name}" component returned a bad result`); | ||
} | ||
component = transformed; | ||
return this._registerTemplates(component, compiledTemplates); | ||
return templateHelper.registerTemplates(component); | ||
}) | ||
@@ -204,98 +207,2 @@ ) | ||
/** | ||
* Loads template sources from the files. | ||
* @param {Object} component The component. | ||
* @returns {Promise} The promise for finished work. | ||
* @private | ||
*/ | ||
_loadTemplateSources(component) { | ||
const templateSourcePromise = Promise.resolve() | ||
.then(() => { | ||
const templatePath = path.resolve( | ||
path.dirname(component.path), | ||
component.properties.template | ||
); | ||
return fs.readFile(templatePath) | ||
.then(source => { | ||
component.templateSource = source.toString(); | ||
}); | ||
}); | ||
const errorTemplateSourcePromise = Promise.resolve() | ||
.then(() => { | ||
component.errorTemplateSource = null; | ||
const relativePath = component.properties.errorTemplate; | ||
if (typeof (relativePath) !== 'string') { | ||
return null; | ||
} | ||
const templatePath = path.resolve( | ||
path.dirname(component.path), | ||
component.properties.errorTemplate | ||
); | ||
return fs.readFile(templatePath) | ||
.then(source => { | ||
component.errorTemplateSource = source.toString(); | ||
}); | ||
}); | ||
return Promise.all([ | ||
templateSourcePromise, errorTemplateSourcePromise | ||
]); | ||
} | ||
/** | ||
* Compiles template sources of the component. | ||
* @param {Object} component The component. | ||
* @returns {Promise} The promise for finished work. | ||
* @private | ||
*/ | ||
_compileTemplates(component) { | ||
const templateCompilePromise = Promise.resolve() | ||
.then(() => this._templateProvider.compile(component.templateSource, component.name)); | ||
const errorTemplateName = moduleHelper.getNameForErrorTemplate(component.name); | ||
const errorTemplateCompilePromise = Promise.resolve() | ||
.then(() => { | ||
if (!component.errorTemplateSource) { | ||
return null; | ||
} | ||
return this._templateProvider.compile(component.errorTemplateSource, errorTemplateName); | ||
}); | ||
return Promise.all([ | ||
templateCompilePromise, | ||
errorTemplateCompilePromise | ||
]) | ||
.then(compiledTemplates => ({ | ||
template: compiledTemplates[0], | ||
errorTemplate: compiledTemplates[1] || null | ||
})); | ||
} | ||
/** | ||
* Registers templates into the component and template providers. | ||
* @param {Object} component The component. | ||
* @param {{template: string, errorTemplate: string}} templates | ||
* The compiled templates. | ||
* @private | ||
*/ | ||
_registerTemplates(component, templates) { | ||
this._templateProvider.registerCompiled(component.name, templates.template); | ||
component.template = { | ||
render: context => this._templateProvider.render(component.name, context) | ||
}; | ||
if (!templates.errorTemplate) { | ||
return; | ||
} | ||
const errorTemplateName = moduleHelper.getNameForErrorTemplate(component.name); | ||
this._templateProvider.registerCompiled(errorTemplateName, templates.errorTemplate); | ||
component.errorTemplate = { | ||
render: context => this._templateProvider.render(errorTemplateName, context) | ||
}; | ||
} | ||
/** | ||
* Gets an absolute path to the component's logic file. | ||
@@ -302,0 +209,0 @@ * @param {Object} componentDetails The component details object. |
@@ -12,7 +12,4 @@ 'use strict'; | ||
/* eslint prefer-rest-params:0 */ | ||
/* eslint no-invalid-this:0 */ | ||
// TODO rewrite this when Spread operator and Rest parameters will be supported | ||
return function() { | ||
const args = Array.prototype.slice.call(arguments); | ||
return function(...args) { | ||
return new Promise((fulfill, reject) => { | ||
@@ -19,0 +16,0 @@ args.push((error, result) => { |
@@ -163,26 +163,2 @@ 'use strict'; | ||
/** | ||
* Sends an action to every store that has a "handle" method for such action. | ||
* @param {string} actionName Name of the action. | ||
* @param {Object} arg Action arguments. | ||
* @returns {Promise<Array<*>>} Promise for the action handling result. | ||
*/ | ||
sendBroadcastAction(actionName, arg) { | ||
const promises = []; | ||
const storesByNames = this._storeLoader.getStoresByNames(); | ||
const methodName = moduleHelper.getCamelCaseName('handle', actionName); | ||
Object.keys(storesByNames) | ||
.forEach(storeName => { | ||
const store = storesByNames[storeName]; | ||
const protoMethod = store.constructor.prototype[methodName]; | ||
if (typeof (protoMethod) !== 'function') { | ||
return; | ||
} | ||
const sendActionPromise = this.sendAction(store.name, actionName, arg); | ||
promises.push(sendActionPromise); | ||
}); | ||
return Promise.all(promises); | ||
} | ||
/** | ||
* Sets a new state to the store dispatcher and invokes the "changed" method for all | ||
@@ -325,3 +301,2 @@ * stores which state has been changed. | ||
storeContext.sendAction = (storeName, name, args) => this.sendAction(storeName, name, args); | ||
storeContext.sendBroadcastAction = (name, args) => this.sendBroadcastAction(name, args); | ||
@@ -328,0 +303,0 @@ return storeContext; |
@@ -22,3 +22,3 @@ 'use strict'; | ||
/** | ||
* Creates q new instance of the parser duplex stream. | ||
* Creates a new instance of the parser duplex stream. | ||
* @param {Object} context Rendering parameters. | ||
@@ -100,4 +100,8 @@ * @param {Object?} options Stream options. | ||
attributes: Object.create(null) | ||
}) | ||
.then(html => this.renderHTML(html)); | ||
}); | ||
if (this._processingFoundTagPromise) { | ||
this._processingFoundTagPromise = this._processingFoundTagPromise | ||
.then(html => this.renderHTML(html)); | ||
} | ||
} | ||
@@ -400,4 +404,2 @@ | ||
(name, args) => context.storeDispatcher.sendAction(storeName, name, args); | ||
componentContext.sendBroadcastAction = | ||
(name, args) => context.storeDispatcher.sendBroadcastAction(name, args); | ||
@@ -404,0 +406,0 @@ return Object.freeze(componentContext); |
{ | ||
"name": "catberry", | ||
"version": "8.6.1", | ||
"version": "9.0.0", | ||
"author": { | ||
@@ -73,3 +73,3 @@ "name": "Denis Rechkunov", | ||
"browser": { | ||
"./lib/Bootstrapper.js": "__BrowserBundle.js", | ||
"./lib/Bootstrapper.js": "./browser/Bootstrapper.js", | ||
"./lib/Catberry.js": "./browser/Catberry.js", | ||
@@ -87,29 +87,29 @@ "./lib/CookieWrapper.js": "./browser/CookieWrapper.js", | ||
"mkdirp": "~0.5.1", | ||
"glob": "^7.0.0", | ||
"chokidar": "^1.4.3", | ||
"catberry-locator": "^2.1.0", | ||
"catberry-uri": "^3.1.0", | ||
"pretty-hrtime": "^1.0.2", | ||
"glob": "^7.1.1", | ||
"chokidar": "^1.6.1", | ||
"catberry-locator": "^2.2.1", | ||
"catberry-uri": "^3.2.2", | ||
"pretty-hrtime": "^1.0.3", | ||
"browser-process-hrtime": "~0.1.2", | ||
"entities": "^1.1.1", | ||
"watchify": "^3.7.0", | ||
"babelify": "^7.2.0", | ||
"babel-preset-es2015-ie": "^6.6.1", | ||
"uglify-js": "^2.6.2", | ||
"browserify": "^13.0.0", | ||
"watchify": "^3.9.0", | ||
"babelify": "^7.3.0", | ||
"babel-preset-babili": "~0.0.12", | ||
"babel-preset-env": "^1.2.2", | ||
"browserify": "^14.1.0", | ||
"promise": "^7.1.1", | ||
"morphdom": "~2.2.0", | ||
"uuid": "^2.0.1" | ||
"uuid": "^3.0.1" | ||
}, | ||
"devDependencies": { | ||
"istanbul": "~0.4.2", | ||
"codecov": "^1.0.1", | ||
"jsdom": "^9.4.2", | ||
"mocha": "^3.0.2", | ||
"eslint": "^3.3.1", | ||
"istanbul": "~0.4.5", | ||
"codecov": "^2.1.0", | ||
"jsdom": "^9.12.0", | ||
"mocha": "^3.2.0", | ||
"eslint": "^3.18.0", | ||
"ncp": "^2.0.0", | ||
"rimraf": "^2.5.4" | ||
"rimraf": "^2.6.1" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
"node": ">=6.10" | ||
}, | ||
@@ -116,0 +116,0 @@ "scripts": { |
@@ -12,3 +12,3 @@ # Catberry | ||
Catberry was developed to help create ["isomorphic/Universal" Web applications](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#isomorphicuniversal-applications). | ||
Catberry was developed to help create ["isomorphic/Universal" Web applications](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#isomorphicuniversal-applications). | ||
@@ -45,5 +45,5 @@ Long story short, isomorphic/universal applications are apps that use the same codebase on both the server and client environments to render what the client would see as a "[Single Page Application](http://en.wikipedia.org/wiki/Single_Page_Application)". | ||
* [Catberry Documentation](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md) | ||
* [Get Started Guide](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#get-started) | ||
* [Plugins and Tools](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#plugins-and-tools) | ||
* [Catberry Documentation](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md) | ||
* [Get Started Guide](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#get-started) | ||
* [Plugins and Tools](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#plugins-and-tools) | ||
* [Catberry's homepage](http://catberry.org) and its [source code](https://github.com/catberry/catberry-homepage) | ||
@@ -57,4 +57,4 @@ * [Todo application](https://github.com/catberry/catberry-todomvc) | ||
* The entire architecture of the framework is built using the [Service Locator](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#service-locator) pattern – which helps to manage module dependencies and [create plugins](https://github.com/catberry/catberry/) – and [Flux](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#flux), for the data layer | ||
* [Cat-components](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#cat-components) – similar to [web-components](http://webcomponents.org/) but organized as directories, can be rendered on the server and published/installed as NPM packages | ||
* The entire architecture of the framework is built using the [Service Locator](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#service-locator) pattern – which helps to manage module dependencies and [create plugins](https://github.com/catberry/catberry/) – and [Flux](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#flux), for the data layer | ||
* [Cat-components](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#cat-components) – similar to [web-components](http://webcomponents.org/) but organized as directories, can be rendered on the server and published/installed as NPM packages | ||
* Catberry builds a bundle for running the application in a browser as a [Single Page Application](http://en.wikipedia.org/wiki/Single_Page_Application) | ||
@@ -71,6 +71,6 @@ * [ES2015/ES6 support](https://nodejs.org/en/docs/es6/) – native on the server/Node.js and using [Babel](http://babeljs.io/) for a browser | ||
* [Handlebars](https://github.com/catberry/catberry-handlebars), [Dust](https://github.com/catberry/catberry-dust) and | ||
[Jade](https://github.com/catberry/catberry-jade) template engines are [officially supported](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md#template-engines) (and you can implement your own provider to support any other) | ||
[Pug](https://github.com/catberry/catberry-pug) template engines are [officially supported](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md#template-engines) (and you can implement your own provider to support any other) | ||
* Efficient DOM event listening using [event delegation](http://davidwalsh.name/event-delegate) | ||
For more details please proceed to [Catberry Documentation](https://github.com/catberry/catberry/blob/8.6.1/docs/index.md). | ||
For more details please proceed to [Catberry Documentation](https://github.com/catberry/catberry/blob/9.0.0/docs/index.md). | ||
@@ -108,4 +108,4 @@ ### Typical Cat-component example | ||
return { | ||
// CSS selector | ||
'.clickable': () => window.alert('Ouch!'); | ||
// CSS selector | ||
'.clickable': () => window.alert('Ouch!'); | ||
} | ||
@@ -191,19 +191,4 @@ } | ||
All supported browsers are listed below: | ||
Catberry supports 2 last versions of modern browsers and IE 11. It depends on Babel [babel-preset-env](https://github.com/babel/babel-preset-env) preset which config you can override putting a `.babelrc` file in your project. | ||
| Browser | Version | | ||
|-------------|-----------| | ||
| IE | 9 (partial non-[SPA](http://en.wikipedia.org/wiki/Single-page_application)), 10+ | | ||
| IE Mobile | 10+ | | ||
| Firefox | 4+ | | ||
| Firefox Android | 29+ | | ||
| Chrome | 19+ | | ||
| Chrome Android | 35+ | | ||
| Android Browser | 2.2+, 4.2+ | | ||
| Safari | 6+ | | ||
| iOS Safari | 5+ | | ||
| Opera | 12+ | | ||
| Opera Mobile | 11.1+ | | ||
| Blackberry Browser| 7+ | | ||
## Contributing | ||
@@ -216,5 +201,5 @@ | ||
* [Submit a bug or a feature request](https://github.com/catberry/catberry/issues) | ||
* [Submit a PR](https://github.com/catberry/catberry/blob/8.6.1/CONTRIBUTING.md) | ||
* [Submit a PR](https://github.com/catberry/catberry/blob/9.0.0/CONTRIBUTING.md) | ||
* If you like the logo, you might want to buy a Catberry [T-Shirt](http://www.redbubble.com/people/catberryjs/works/14439373-catberry-js-framework-logo?p=t-shirt) or a [sticker](http://www.redbubble.com/people/catberryjs/works/14439373-catberry-js-framework-logo?p=sticker) | ||
Denis Rechkunov <denis.rechkunov@gmail.com> |
@@ -29,7 +29,9 @@ 'use strict'; | ||
logic: './logic.js', | ||
errorTemplate: './templates/error.html', | ||
template: './templates/template.html' | ||
errorTemplate: './templates/error.html1', | ||
template: './templates/template.html1' | ||
}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: 'Error occurs :(' | ||
templateProviderName: 'html1', | ||
errorTemplateProviderName: 'html1', | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: 'Error occurs :(' | ||
}, | ||
@@ -41,10 +43,44 @@ second: { | ||
logic: './index.js', | ||
template: './template.html' | ||
template: './template.html2' | ||
}, | ||
templateSource: 'Hello from second!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html2', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello from second!', | ||
compiledErrorTemplate: null | ||
}, | ||
third: { | ||
constructor: componentMocks.AsyncComponent, | ||
name: 'third', | ||
properties: { | ||
logic: './index.js', | ||
template: './template.html1', | ||
errorTemplate: './error.html2' | ||
}, | ||
templateProviderName: 'html1', | ||
errorTemplateProviderName: 'html2', | ||
compiledTemplate: 'Hello from third!', | ||
compiledErrorTemplate: 'Error from third!' | ||
} | ||
}; | ||
registerComponents(components); | ||
locator.unregister('templateProvider'); | ||
const templates = {}; | ||
locator.registerInstance('templateProvider', { | ||
getName: () => 'html1', | ||
render: name => Promise.resolve(`html1: ${templates[name]}`), | ||
registerCompiled: (name, source) => { | ||
templates[name] = source; | ||
} | ||
}); | ||
locator.registerInstance('templateProvider', { | ||
getName: () => 'html2', | ||
render: name => Promise.resolve(`html2: ${templates[name]}`), | ||
registerCompiled: (name, source) => { | ||
templates[name] = source; | ||
} | ||
}); | ||
const loader = locator.resolve('componentLoader'); | ||
@@ -57,3 +93,3 @@ | ||
// can't use deepEqual because of templates | ||
assert.strictEqual(Object.keys(loadedComponents).length, 2); | ||
assert.strictEqual(Object.keys(loadedComponents).length, 3); | ||
Object.keys(loadedComponents).forEach(key => { | ||
@@ -68,5 +104,7 @@ const actual = loadedComponents[key]; | ||
const expected = [ | ||
'Hello, world!', | ||
'Error occurs :(', | ||
'Hello from second!' | ||
'html1: Hello, world!', | ||
'html1: Error occurs :(', | ||
'html2: Hello from second!', | ||
'html1: Hello from third!', | ||
'html2: Error from third!' | ||
]; | ||
@@ -76,3 +114,5 @@ return Promise.all([ | ||
loadedComponents['first-cool'].errorTemplate.render(), | ||
loadedComponents.second.template.render() | ||
loadedComponents.second.template.render(), | ||
loadedComponents.third.template.render(), | ||
loadedComponents.third.errorTemplate.render() | ||
]) | ||
@@ -91,4 +131,6 @@ .then(rendered => assert.deepEqual(rendered, expected)); | ||
properties: {}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: 'Error occurs :(' | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: 'html', | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: 'Error occurs :(' | ||
} | ||
@@ -98,3 +140,3 @@ }; | ||
registerComponents(components); | ||
locator.unregister('remplateProvider'); | ||
locator.unregister('templateProvider'); | ||
locator.registerInstance('templateProvider', { | ||
@@ -112,2 +154,57 @@ register: () => Promise.reject(new Error('TestError')) | ||
it('should not load component if there is no template provider', function(done) { | ||
const components = { | ||
'first-cool': { | ||
constructor: componentMocks.SyncComponent, | ||
name: 'first-cool', | ||
properties: {}, | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: 'html', | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: 'Error occurs :(' | ||
} | ||
}; | ||
registerComponents(components); | ||
locator.unregister('templateProvider'); | ||
const loader = locator.resolve('componentLoader'); | ||
loader | ||
.load() | ||
.then(loadedComponents => assert.deepEqual(loadedComponents, {})) | ||
.then(done) | ||
.catch(done); | ||
}); | ||
it('should not load component if there is no suitable template provider', function(done) { | ||
const components = { | ||
'first-cool': { | ||
constructor: componentMocks.SyncComponent, | ||
name: 'first-cool', | ||
properties: {}, | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: 'html', | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: 'Error occurs :(' | ||
} | ||
}; | ||
registerComponents(components); | ||
locator.unregister('templateProvider'); | ||
locator.registerInstance('templateProvider', { | ||
getName: () => 'wrong', | ||
registerCompiled: () => {}, | ||
render: () => {} | ||
}); | ||
const loader = locator.resolve('componentLoader'); | ||
loader | ||
.load() | ||
.then(loadedComponents => assert.deepEqual(loadedComponents, {})) | ||
.then(done) | ||
.catch(done); | ||
}); | ||
it('should load nothing if no components are registered', function(done) { | ||
@@ -146,4 +243,6 @@ registerComponents({}); | ||
properties: {}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: 'html', | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: null | ||
}, | ||
@@ -154,4 +253,6 @@ second: { | ||
properties: {}, | ||
templateSource: 'Hello from second!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello from second!', | ||
compiledErrorTemplate: null | ||
} | ||
@@ -192,4 +293,6 @@ }; | ||
properties: {}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: null | ||
}, | ||
@@ -200,4 +303,6 @@ second: { | ||
properties: {}, | ||
templateSource: 'Hello from second!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello from second!', | ||
compiledErrorTemplate: null | ||
} | ||
@@ -239,4 +344,6 @@ }; | ||
properties: {}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: null | ||
} | ||
@@ -267,4 +374,6 @@ }; | ||
properties: {}, | ||
templateSource: 'Hello, world!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello, world!', | ||
compiledErrorTemplate: null | ||
}, | ||
@@ -275,4 +384,6 @@ second: { | ||
properties: {}, | ||
templateSource: 'Hello from second!', | ||
errorTemplateSource: null | ||
templateProviderName: 'html', | ||
errorTemplateProviderName: null, | ||
compiledTemplate: 'Hello from second!', | ||
compiledErrorTemplate: null | ||
} | ||
@@ -326,2 +437,3 @@ }; | ||
templates: {}, | ||
getName: () => 'html', | ||
render: name => Promise.resolve(templateProvider[name]), | ||
@@ -328,0 +440,0 @@ registerCompiled: (name, source) => { |
@@ -11,3 +11,3 @@ { | ||
"logic": "./logic.js", | ||
"errorTemplate": "./templates/error.html", | ||
"errorTemplate": "./templates/error.htm", | ||
"template": "./templates/template.html" | ||
@@ -27,7 +27,7 @@ } | ||
"expectedTemplates": [ | ||
"Hello, world!", | ||
"Hello from second!" | ||
"HTML: Hello, world!", | ||
"HTML: Hello from second!" | ||
], | ||
"expectedErrorTemplates": [ | ||
"Error occurs :(", | ||
"HTM: Error occurs :(", | ||
null | ||
@@ -51,2 +51,26 @@ ] | ||
{ | ||
"name": "should not load if component has a unsupported template", | ||
"components": { | ||
"error5": { | ||
"name": "error5", | ||
"path": "test/cases/lib/loaders/ComponentLoader/Error5/error5.json", | ||
"properties": { | ||
"logic": "./index.js", | ||
"template": "./template.wrong" | ||
} | ||
}, | ||
"error6": { | ||
"name": "error6", | ||
"path": "test/cases/lib/loaders/ComponentLoader/Error6/error6.json", | ||
"properties": { | ||
"logic": "./index.js", | ||
"template": "./template.html", | ||
"errorTemplate": "./error.wrong" | ||
} | ||
} | ||
}, | ||
"expectedCount": 0 | ||
}, | ||
{ | ||
"name": "should not load if component has wrong path in \"template\" field", | ||
@@ -53,0 +77,0 @@ "components": { |
@@ -141,14 +141,28 @@ 'use strict'; | ||
const templateProvider = { | ||
templates: {}, | ||
const HTMLTemplates = {}; | ||
const HTMLTemplateProvider = { | ||
getName: () => 'html', | ||
isTemplateSupported: filename => /html$/.test(filename), | ||
compile: str => Promise.resolve(str), | ||
render: name => Promise.resolve(templateProvider[name]), | ||
render: name => Promise.resolve(`HTML: ${HTMLTemplates[name]}`), | ||
registerCompiled: (name, source) => { | ||
templateProvider[name] = source; | ||
HTMLTemplates[name] = source; | ||
} | ||
}; | ||
const HTMTemplates = {}; | ||
const HTMTemplateProvider = { | ||
getName: () => 'htm', | ||
isTemplateSupported: filename => /htm$/.test(filename), | ||
compile: str => Promise.resolve(str), | ||
render: name => Promise.resolve(`HTM: ${HTMTemplates[name]}`), | ||
registerCompiled: (name, source) => { | ||
HTMTemplates[name] = source; | ||
} | ||
}; | ||
locator.registerInstance('eventBus', eventBus); | ||
locator.registerInstance('componentFinder', new ComponentFinder(components)); | ||
locator.registerInstance('templateProvider', templateProvider); | ||
locator.registerInstance('templateProvider', HTMLTemplateProvider); | ||
locator.registerInstance('templateProvider', HTMTemplateProvider); | ||
locator.register('contextFactory', ContextFactory); | ||
@@ -155,0 +169,0 @@ locator.register('moduleApiProvider', ModuleApiProvider); |
@@ -730,93 +730,2 @@ 'use strict'; | ||
describe('#sendBroadcastAction', function() { | ||
it('should send action to all stores with handlers', function(done) { | ||
class Store { | ||
handleSomeAction(args) { | ||
return { | ||
args, | ||
result: this.$context.name | ||
}; | ||
} | ||
} | ||
const stores = { | ||
store1: { | ||
name: 'store1', | ||
constructor: Store | ||
}, | ||
store2: { | ||
name: 'store2', | ||
constructor: storeMocks.SyncDataStore | ||
}, | ||
store3: { | ||
name: 'store3', | ||
constructor: Store | ||
} | ||
}; | ||
const actionParameters = {}; | ||
const locator = createLocator(stores); | ||
const dispatcher = locator.resolve('storeDispatcher'); | ||
dispatcher.setState({}, {}); | ||
dispatcher.sendBroadcastAction( | ||
'some-action', actionParameters | ||
) | ||
.then(results => { | ||
assert.strictEqual(results.length, 2); | ||
assert.strictEqual(results[0].args, actionParameters); | ||
assert.strictEqual(results[0].result, 'store1'); | ||
assert.strictEqual(results[1].args, actionParameters); | ||
assert.strictEqual(results[1].result, 'store3'); | ||
}) | ||
.then(done) | ||
.catch(done); | ||
}); | ||
it('should send action to all stores with handlers from $context', function(done) { | ||
class Store1 { | ||
handleSome(name) { | ||
return this.$context.sendBroadcastAction('action', name); | ||
} | ||
} | ||
class Store2 { | ||
handleAction(name) { | ||
return `hello from store2, ${name}`; | ||
} | ||
} | ||
class Store3 { | ||
handleAction(name) { | ||
return `hello from store3, ${name}`; | ||
} | ||
} | ||
const stores = { | ||
store1: { | ||
name: 'store1', | ||
constructor: Store1 | ||
}, | ||
store2: { | ||
name: 'store2', | ||
constructor: Store2 | ||
}, | ||
store3: { | ||
name: 'store3', | ||
constructor: Store3 | ||
} | ||
}; | ||
const locator = createLocator(stores); | ||
const dispatcher = locator.resolve('storeDispatcher'); | ||
dispatcher.setState({}, {}); | ||
dispatcher.sendAction('store1', 'some', 'catberry') | ||
.then(results => { | ||
assert.strictEqual(results.length, 2); | ||
assert.strictEqual(results[0], 'hello from store2, catberry'); | ||
assert.strictEqual(results[1], 'hello from store3, catberry'); | ||
}) | ||
.then(done) | ||
.catch(done); | ||
}); | ||
}); | ||
}); | ||
@@ -823,0 +732,0 @@ |
@@ -42,2 +42,21 @@ 'use strict'; | ||
}); | ||
describe('#renderDocument', function() { | ||
it('renders nothing when there is no document', function(done) { | ||
const parser = new ComponentReadable(createContext()); | ||
parser.renderDocument(); | ||
var concat = ''; | ||
parser | ||
.on('data', function(chunk) { | ||
concat += chunk; | ||
}) | ||
.on('end', function() { | ||
assert.strictEqual(concat, '', 'Wrong HTML content'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -47,2 +66,3 @@ | ||
return { | ||
components: Object.create(null), | ||
routingContext: { | ||
@@ -49,0 +69,0 @@ middleware: { |
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
500169
204
16520
199
+ Addedbabel-preset-babili@~0.0.12
+ Addedbabel-preset-env@^1.2.2
+ Addedbabel-helper-builder-binary-assignment-operator-visitor@6.24.1(transitive)
+ Addedbabel-helper-evaluate-path@0.0.3(transitive)
+ Addedbabel-helper-explode-assignable-expression@6.24.1(transitive)
+ Addedbabel-helper-flip-expressions@0.0.2(transitive)
+ Addedbabel-helper-is-nodes-equiv@0.0.1(transitive)
+ Addedbabel-helper-is-void-0@0.0.1(transitive)
+ Addedbabel-helper-mark-eval-scopes@0.0.30.1.1(transitive)
+ Addedbabel-helper-remap-async-to-generator@6.24.1(transitive)
+ Addedbabel-helper-remove-or-void@0.1.1(transitive)
+ Addedbabel-helper-to-multiple-sequence-expressions@0.0.4(transitive)
+ Addedbabel-plugin-minify-builtins@0.0.2(transitive)
+ Addedbabel-plugin-minify-constant-folding@0.0.4(transitive)
+ Addedbabel-plugin-minify-dead-code-elimination@0.1.7(transitive)
+ Addedbabel-plugin-minify-flip-comparisons@0.0.2(transitive)
+ Addedbabel-plugin-minify-guarded-expressions@0.0.4(transitive)
+ Addedbabel-plugin-minify-infinity@0.0.3(transitive)
+ Addedbabel-plugin-minify-mangle-names@0.0.8(transitive)
+ Addedbabel-plugin-minify-numeric-literals@0.0.1(transitive)
+ Addedbabel-plugin-minify-replace@0.0.1(transitive)
+ Addedbabel-plugin-minify-simplify@0.0.8(transitive)
+ Addedbabel-plugin-minify-type-constructors@0.0.4(transitive)
+ Addedbabel-plugin-syntax-async-functions@6.13.0(transitive)
+ Addedbabel-plugin-syntax-exponentiation-operator@6.13.0(transitive)
+ Addedbabel-plugin-syntax-trailing-function-commas@6.22.0(transitive)
+ Addedbabel-plugin-transform-async-to-generator@6.24.1(transitive)
+ Addedbabel-plugin-transform-es2015-modules-amd@6.24.1(transitive)
+ Addedbabel-plugin-transform-es2015-modules-systemjs@6.24.1(transitive)
+ Addedbabel-plugin-transform-es2015-modules-umd@6.24.1(transitive)
+ Addedbabel-plugin-transform-exponentiation-operator@6.24.1(transitive)
+ Addedbabel-plugin-transform-inline-consecutive-adds@0.0.2(transitive)
+ Addedbabel-plugin-transform-member-expression-literals@6.9.4(transitive)
+ Addedbabel-plugin-transform-merge-sibling-variables@6.9.5(transitive)
+ Addedbabel-plugin-transform-minify-booleans@6.9.4(transitive)
+ Addedbabel-plugin-transform-property-literals@6.9.4(transitive)
+ Addedbabel-plugin-transform-regexp-constructors@0.0.6(transitive)
+ Addedbabel-plugin-transform-remove-console@6.9.4(transitive)
+ Addedbabel-plugin-transform-remove-debugger@6.9.4(transitive)
+ Addedbabel-plugin-transform-remove-undefined@0.0.5(transitive)
+ Addedbabel-plugin-transform-simplify-comparison-operators@6.9.4(transitive)
+ Addedbabel-plugin-transform-undefined-to-void@6.9.4(transitive)
+ Addedbabel-preset-babili@0.0.12(transitive)
+ Addedbabel-preset-env@1.7.0(transitive)
+ Addedbrowserify@14.5.0(transitive)
+ Addedbrowserslist@3.2.8(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedcaniuse-lite@1.0.30001621(transitive)
+ Addedelectron-to-chromium@1.4.783(transitive)
+ Addedjsesc@2.5.2(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.some@4.6.0(transitive)
+ Addedsemver@5.7.2(transitive)
+ Addedstring_decoder@1.0.3(transitive)
+ Addeduuid@3.4.0(transitive)
- Removedbabel-preset-es2015-ie@^6.6.1
- Removeduglify-js@^2.6.2
- Removedalign-text@0.1.4(transitive)
- Removedbabel-plugin-transform-object-assign@6.22.0(transitive)
- Removedbabel-plugin-transform-proto-to-assign@6.26.0(transitive)
- Removedbabel-preset-es2015-ie@6.7.0(transitive)
- Removedbrowserify@13.3.0(transitive)
- Removedbrowserify-zlib@0.1.4(transitive)
- Removedbuffer@4.9.2(transitive)
- Removedcamelcase@1.2.1(transitive)
- Removedcenter-align@0.1.3(transitive)
- Removedcliui@2.1.0(transitive)
- Removeddecamelize@1.2.0(transitive)
- Removedhttps-browserify@0.0.1(transitive)
- Removedlazy-cache@1.0.4(transitive)
- Removedlongest@1.0.1(transitive)
- Removedos-browserify@0.1.2(transitive)
- Removedpako@0.2.9(transitive)
- Removedright-align@0.1.3(transitive)
- Removeduglify-js@2.8.29(transitive)
- Removeduglify-to-browserify@1.0.2(transitive)
- Removeduuid@2.0.3(transitive)
- Removedwindow-size@0.1.0(transitive)
- Removedwordwrap@0.0.2(transitive)
- Removedyargs@3.10.0(transitive)
Updatedbabelify@^7.3.0
Updatedbrowserify@^14.1.0
Updatedcatberry-locator@^2.2.1
Updatedcatberry-uri@^3.2.2
Updatedchokidar@^1.6.1
Updatedglob@^7.1.1
Updatedpretty-hrtime@^1.0.3
Updateduuid@^3.0.1
Updatedwatchify@^3.9.0