bs-injular
Advanced tools
Comparing version 0.2.1 to 0.3.0
{ | ||
"extends": "eslint:recommended", | ||
"rules": { | ||
"block-scoped-var": "error", | ||
"curly": "error", | ||
"eqeqeq": ["error", "smart"], | ||
"indent": ["error", 2], | ||
"linebreak-style": ["error", "unix"], | ||
"no-empty-function": "error", | ||
"no-implicit-globals": "error", | ||
"semi": ["error", "always"] | ||
"extends": "./.eslintrc-common.json", | ||
"parserOptions": { | ||
"ecmaVersion": 6 | ||
}, | ||
"env": { | ||
"node": true | ||
} | ||
} |
{ | ||
"extends": "../.eslintrc.json", | ||
"extends": "../.eslintrc-common.json", | ||
"parserOptions": { | ||
@@ -4,0 +4,0 @@ "ecmaVersion": 3 |
@@ -5,3 +5,3 @@ | ||
var TEMPLATE_CHANGED_EVENT = 'injularTemplate:changed'; | ||
var CONTROLLER_CHANGED_EVENT = 'injularScript:changed'; | ||
var SCRIPT_CHANGED_EVENT = 'injularScript:changed'; | ||
var DIRECTIVE_SUFFIX = 'Directive'; | ||
@@ -12,10 +12,18 @@ | ||
sockets.on(TEMPLATE_CHANGED_EVENT, templateChangedListener); | ||
sockets.on(CONTROLLER_CHANGED_EVENT, scriptChangedListener); | ||
sockets.on(SCRIPT_CHANGED_EVENT, scriptChangedListener); | ||
function templateChangedListener(data) { | ||
try { | ||
tryTemplateChangedListener(data); | ||
} catch (err) { | ||
errorHandler(err); | ||
var $injector = getInjector(); | ||
var $templateCache = $injector.get('$templateCache'); | ||
var templateUrl = data.templateUrl; | ||
var template = data.template; | ||
replaceTemplateCache($templateCache, templateUrl, template); | ||
if (data.reloadRoute) { | ||
reloadRoute($injector); | ||
} else { | ||
var $compile = $injector.get('$compile'); | ||
replaceTemplateInDom($compile, templateUrl, template); | ||
} | ||
@@ -26,15 +34,11 @@ } | ||
function scriptChangedListener(data) { | ||
try { | ||
var $injector = getInjector(); | ||
var $injector = getInjector(); | ||
var localAngular = getLocalAngular($injector); | ||
localAngular._scriptUrl = data.scriptUrl; | ||
var jsInjector = new Function('angular', data.script); | ||
jsInjector(localAngular); | ||
removeDeletedDirectives($injector, data.scriptUrl); | ||
var localAngular = getLocalAngular($injector); | ||
localAngular._scriptUrl = data.scriptUrl; | ||
var jsInjector = new Function('angular', data.script); | ||
jsInjector(localAngular); | ||
removeDeletedDirectives($injector, data.scriptUrl); | ||
reloadRoute($injector); | ||
} catch (err) { | ||
errorHandler(err); | ||
} | ||
reloadRoute($injector); | ||
} | ||
@@ -64,2 +68,5 @@ | ||
var directivesByUrl = bsInjular.directivesByUrl; | ||
if (!directivesByUrl) { | ||
return; | ||
} | ||
var directivesByName = directivesByUrl[scriptUrl]; | ||
@@ -115,19 +122,2 @@ | ||
function tryTemplateChangedListener(data) { | ||
var $injector = getInjector(); | ||
var $templateCache = $injector.get('$templateCache'); | ||
var templateUrl = data.templateUrl; | ||
var template = data.template; | ||
replaceTemplateCache($templateCache, templateUrl, template); | ||
if (data.reloadRoute) { | ||
reloadRoute($injector); | ||
} else { | ||
var $compile = $injector.get('$compile'); | ||
replaceTemplateInDom($compile, templateUrl, template); | ||
} | ||
} | ||
function getAngular() { | ||
@@ -303,5 +293,16 @@ var angular = window.angular; | ||
app.directive = injularDirectiveRecipe; | ||
app.config = returnSelf; | ||
app.run = returnSelf; | ||
app.constant = returnSelf; | ||
app.value = returnSelf; | ||
app.provider = returnSelf; | ||
app.factory = returnSelf; | ||
app.service = returnSelf; | ||
return app; | ||
} | ||
function returnSelf() { | ||
return this; | ||
} | ||
function injularControllerRecipe() { | ||
@@ -331,6 +332,6 @@ if (!bsInjular.$controllerProvider) { | ||
if (angular.isString(name)) { | ||
injectDirectives(name, directiveFactory, directivesByName); | ||
injectDirective(name, directiveFactory, directivesByName); | ||
} else { | ||
angular.forEach(name, function(directiveFactory, name) { | ||
injectDirectives(name, directiveFactory, directivesByName); | ||
injectDirective(name, directiveFactory, directivesByName); | ||
}); | ||
@@ -345,3 +346,3 @@ } | ||
function injectDirectives(name, directiveFactory, directivesByName) { | ||
function injectDirective(name, directiveFactory, directivesByName) { | ||
var directiveList = directivesByName[name]; | ||
@@ -413,14 +414,5 @@ | ||
function errorHandler(err) { | ||
if (typeof err === 'string') { | ||
console.warn(err); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
function throwError(msg) { | ||
throw '[BS-Injular] ' + msg; | ||
throw new Error('[BS-Injular] ' + msg); | ||
} | ||
})(window.___browserSync___); |
// Karma configuration | ||
// Generated on Wed Apr 13 2016 23:13:43 GMT-0300 (ART) | ||
/* global module */ | ||
module.exports = function(config) { | ||
@@ -39,9 +37,19 @@ config.set({ | ||
preprocessors: { | ||
'client/**/*.js': ['coverage'] | ||
}, | ||
coverageReporter: { | ||
dir : 'coverage-client/', | ||
reporters : [ | ||
{type: 'json'}, | ||
{type: 'text-summary'} | ||
] | ||
}, | ||
// test results reporter to use | ||
// possible values: 'dots', 'progress' | ||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter | ||
reporters: ['progress'], | ||
reporters: ['progress', 'coverage'], | ||
@@ -48,0 +56,0 @@ |
{ | ||
"extends": "../.eslintrc.json", | ||
"extends": "../.eslintrc-common.json", | ||
"parserOptions": { | ||
@@ -4,0 +4,0 @@ "ecmaVersion": 6 |
'use strict'; | ||
/* global angular, window, document */ | ||
@@ -7,3 +6,4 @@ module.exports = { | ||
appendProvideGetter, | ||
appendAngularDirectivePatch | ||
appendAngularDirectivePatch, | ||
_appendAngularDirectivePatchFunction | ||
}; | ||
@@ -41,3 +41,3 @@ | ||
return body += ` | ||
;(${appendAngularDirectivePatchFunction})(); | ||
;(${_appendAngularDirectivePatchFunction})(angular, window, document); | ||
`; | ||
@@ -47,3 +47,3 @@ } | ||
var appendAngularDirectivePatchFunction = function() { | ||
function _appendAngularDirectivePatchFunction(angular, window, document) { | ||
var bsInjular = window.___bsInjular___; | ||
@@ -115,2 +115,2 @@ if (!bsInjular) { | ||
}; | ||
} |
@@ -7,3 +7,13 @@ const minimatch = require('minimatch'); | ||
function match(string, pattern) { | ||
return pattern && minimatch(string, pattern); | ||
if (!pattern) { | ||
return false; | ||
} | ||
if (Array.isArray(pattern)) { | ||
return pattern.some(p => | ||
minimatch(string, p) | ||
); | ||
} else { | ||
return minimatch(string, pattern); | ||
} | ||
} |
{ | ||
"name": "bs-injular", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"description": "Inject angular templates and controllers without reloading the page", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"test": "npm run lint && mocha && karma start --single-run", | ||
"lint": "eslint ." | ||
"test": "npm run lint && npm run test:server && npm run test:client && npm run test:merged", | ||
"lint": "eslint .", | ||
"test:server": "istanbul cover _mocha --dir coverage-server --report text-summary --report json -x test-server/**/* test-server", | ||
"test:client": "karma start --single-run", | ||
"test:merged": "istanbul report --dir coverage-merged lcov text-summary" | ||
}, | ||
@@ -37,4 +40,6 @@ "repository": { | ||
"immutable": "^3.7.4", | ||
"istanbul": "~0.4.3", | ||
"karma": "~0.13.22", | ||
"karma-chai-sinon": "~0.1.5", | ||
"karma-coverage": "~0.5.5", | ||
"karma-mocha": "~0.2.2", | ||
@@ -41,0 +46,0 @@ "karma-phantomjs-launcher": "~1.0.0", |
@@ -1,7 +0,8 @@ | ||
# Injular | ||
# Injular <sub><sup>(AngularJS 1.x hot reloading)</sup></sub> | ||
[](https://npmjs.org/package/bs-injular) | ||
[](https://travis-ci.org/tfoxy/bs-injular) | ||
[](https://codecov.io/gh/tfoxy/bs-injular) | ||
> Inject angular templates and controllers without reloading the page | ||
> Inject angular templates, controllers and directives without reloading the page | ||
@@ -27,3 +28,3 @@ This is a plugin for the awesome [BrowserSync](https://browsersync.io). | ||
Modify the `*.html` and `*.controller.js` files inside `src/app` | ||
Modify the `*.html`, `*.controller.js` and `*.directive.js` files inside `src/app` | ||
and watch the changes instantly. | ||
@@ -60,2 +61,4 @@ | ||
controllers: '**/app/**/*.controller.js', | ||
directives: '**/app/**/*.directive.js', | ||
angularFile: '/bower_components/angular/angular.js', | ||
moduleFile: '**/app/index.module.js', | ||
@@ -70,3 +73,3 @@ moduleName: 'fooApp' | ||
This supports template and controller injection. | ||
This supports template, controller and directive injection. | ||
@@ -96,6 +99,21 @@ | ||
The module file and module name are necessary in order to get the `$controllerProvider` | ||
in the config phase and inject the controllers later. | ||
in the config phase so that the controllers can be injected later. | ||
If you want to inject directives, you must provide the following properties: | ||
```js | ||
{ | ||
directives: '**/app/**/*.directive.js', | ||
angularFile: '/bower_components/angular/angular.js', | ||
moduleFile: '**/app/index.module.js', | ||
moduleName: 'fooApp' | ||
} | ||
``` | ||
The module file and module name are necessary in order to get the `$compileProvider` | ||
in the config phase so that the directives can be injected later. | ||
The angular file is necessary to keep track of the directives present in a file. | ||
**WARNING:** The controller files must retrieve the module using `angular.module()` | ||
and only use the `controller` recipe. | ||
and only use the `controller` recipe. The same applies to directives. | ||
@@ -112,3 +130,3 @@ ```js | ||
If there is a directive, a config block or any other angular recipe, it may work unexpectedly. | ||
If there is any other angular recipe, it will be ignored. | ||
@@ -130,8 +148,6 @@ | ||
* Support for inline templates and controllers | ||
* Show the file and line number when an error is thrown in an injected script. | ||
Currently, the script is evaluated using `Function`. | ||
* Show the file and line number when an error is thrown in an injected controller. | ||
Currently, the controller is evaluated using `Function`. | ||
## Resources | ||
@@ -138,0 +154,0 @@ |
{ | ||
"extends": "../.eslintrc.json", | ||
"extends": "../.eslintrc-common.json", | ||
"parserOptions": { | ||
@@ -4,0 +4,0 @@ "ecmaVersion": 3 |
@@ -43,3 +43,4 @@ 'use strict'; | ||
listener({ | ||
script: "angular.module('app').controller('fooCtrl', function(){})" | ||
script: "angular.module('app').controller('fooCtrl', function(){})", | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
@@ -65,3 +66,4 @@ | ||
listener({ | ||
script: '' | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
@@ -86,3 +88,4 @@ | ||
listener({ | ||
script: '' | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
@@ -98,13 +101,13 @@ | ||
it('should print a warning when window.___bsInjular___ is not found', function() { | ||
it('should throw an error when window.___bsInjular___ is not found', function() { | ||
var element = angular.element('<div ng-app="app"></div>'); | ||
rootElement.append(element); | ||
angular.bootstrap(element); | ||
console.warn = sinon.spy(); | ||
listener({ | ||
script: '' | ||
var fn = listener.bind(null, { | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('window.___bsInjular___'); | ||
expect(fn).to.throw('window.___bsInjular___'); | ||
}); | ||
@@ -118,9 +121,9 @@ | ||
window.___bsInjular___ = {}; | ||
console.warn = sinon.spy(); | ||
listener({ | ||
script: "angular.module('app').controller('fooCtrl', function(){})" | ||
var fn = listener.bind(null, { | ||
script: "angular.module('app').controller('fooCtrl', function(){})", | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('$controllerProvider'); | ||
expect(fn).to.throw('$controllerProvider'); | ||
}); | ||
@@ -146,9 +149,9 @@ | ||
window.___bsInjular___ = {$controllerProvider: {}}; | ||
console.warn = sinon.spy(); | ||
listener({ | ||
script: '' | ||
var fn = listener.bind(null, { | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('window.angular'); | ||
expect(fn).to.throw('window.angular'); | ||
}); | ||
@@ -163,11 +166,9 @@ | ||
rootElement.append(element); | ||
console.warn = sinon.spy(); | ||
listener({ | ||
template: '', | ||
templateUrl: '/app/foo.html' | ||
var fn = listener.bind(null, { | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('$injector'); | ||
expect(fn).to.throw('$injector'); | ||
}); | ||
@@ -181,14 +182,13 @@ | ||
angular.bootstrap(element); | ||
console.warn = sinon.spy(); | ||
listener({ | ||
template: '', | ||
templateUrl: '/app/foo.html' | ||
var fn = listener.bind(null, { | ||
script: '', | ||
scriptUrl: 'app/foo.controller.js' | ||
}); | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('$route'); | ||
expect(console.warn).to.have.been.calledWithMatch('$state'); | ||
expect(fn).to.throw(Error) | ||
.that.has.property('message') | ||
.that.contains('$state').and.contains('$route'); | ||
}); | ||
}); |
@@ -157,3 +157,2 @@ 'use strict'; | ||
it('should give a warning when directivesByUrl is not found', function() { | ||
console.warn = sinon.spy(); | ||
window.___bsInjular___ = {}; | ||
@@ -164,3 +163,3 @@ var element = angular.element('<div ng-app="app"></div>'); | ||
listener({ | ||
var fn = listener.bind(null, { | ||
scriptUrl: '/app/foo.directive.js', | ||
@@ -173,4 +172,3 @@ script: [ | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('directivesByUrl'); | ||
expect(fn).to.throw('directivesByUrl'); | ||
}); | ||
@@ -177,0 +175,0 @@ |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var listener = bs.__events[TEMPLATE_CHANGED_EVENT]; | ||
var rootElement, warn; | ||
var rootElement; | ||
@@ -14,5 +14,2 @@ before(function() { | ||
body.append(rootElement); | ||
warn = console.warn; | ||
console.warn = sinon.spy(); | ||
}); | ||
@@ -22,3 +19,2 @@ | ||
rootElement.children().remove(); | ||
console.warn.reset(); | ||
}); | ||
@@ -28,3 +24,2 @@ | ||
rootElement.remove(); | ||
console.warn = warn; | ||
}); | ||
@@ -56,3 +51,2 @@ | ||
expect(element.children()).to.have.length(1); | ||
expect(console.warn).to.have.callCount(0); | ||
}); | ||
@@ -84,3 +78,2 @@ | ||
expect(element.children()).to.have.length(1); | ||
expect(console.warn).to.have.callCount(0); | ||
}); | ||
@@ -102,3 +95,3 @@ | ||
it('should print a warning when querySelector is not found', function() { | ||
listener({ | ||
var fn = listener.bind(null, { | ||
template: '', | ||
@@ -108,4 +101,3 @@ templateUrl: '/app/foo.html' | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('querySelector'); | ||
expect(fn).to.throw('querySelector'); | ||
}); | ||
@@ -117,3 +109,3 @@ | ||
it('should print a warning when an [ng-app] element is not found', function() { | ||
listener({ | ||
var fn = listener.bind(null, { | ||
template: '', | ||
@@ -123,5 +115,5 @@ templateUrl: '/app/foo.html' | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('[ng-app]'); | ||
expect(console.warn).to.not.have.been.calledWithMatch('$injector'); | ||
expect(fn).to.throw(Error) | ||
.that.has.property('message') | ||
.that.contains('[ng-app]').and.not.contains('$injector'); | ||
}); | ||
@@ -134,3 +126,3 @@ | ||
listener({ | ||
var fn = listener.bind(null, { | ||
template: '', | ||
@@ -140,4 +132,3 @@ templateUrl: '/app/foo.html' | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('$injector'); | ||
expect(fn).to.throw('$injector'); | ||
}); | ||
@@ -151,3 +142,3 @@ | ||
listener({ | ||
var fn = listener.bind(null, { | ||
template: '', | ||
@@ -157,4 +148,3 @@ templateUrl: '/app/foo.html' | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('templateCache'); | ||
expect(fn).to.throw('templateCache'); | ||
}); | ||
@@ -177,3 +167,3 @@ | ||
listener({ | ||
var fn = listener.bind(null, { | ||
template: '', | ||
@@ -183,6 +173,5 @@ templateUrl: '/app/foo.html' | ||
expect(console.warn).to.have.callCount(1); | ||
expect(console.warn).to.have.been.calledWithMatch('bs-injular-end'); | ||
expect(fn).to.throw('bs-injular-end'); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
71904
32
1887
156
1
17