Commit 25d03849 authored by Robert Knight's avatar Robert Knight

Require templates with require() in components

Include Angular component templates as strings in the app bundle using
the stringify Browserify transform and use them from directives using
'template' instead of 'templateUrl'.

This is faster, because it avoids going through the async $http
machinery to load templates, but it is also synchronous, which generally
means fewer surprises due to async template loading and specifically in
the context of the <excerpt> directive will be useful as it will make it
possible for the <excerpt> directive to measure the height of its
content in the link function, because all components inside the
exercept's content will have been fully resolved at that point.
parent 17e6556c
...@@ -60,25 +60,27 @@ function configureLocation($locationProvider) { ...@@ -60,25 +60,27 @@ function configureLocation($locationProvider) {
} }
// @ngInject // @ngInject
var VIEWER_TEMPLATE = require('../../templates/client/viewer.html');
function configureRoutes($routeProvider) { function configureRoutes($routeProvider) {
$routeProvider.when('/a/:id', $routeProvider.when('/a/:id',
{ {
controller: 'AnnotationViewerController', controller: 'AnnotationViewerController',
templateUrl: 'viewer.html', template: VIEWER_TEMPLATE,
reloadOnSearch: false, reloadOnSearch: false,
resolve: resolve resolve: resolve
}); });
$routeProvider.when('/viewer', $routeProvider.when('/viewer',
{ {
controller: 'WidgetController', controller: 'WidgetController',
templateUrl: 'viewer.html', template: VIEWER_TEMPLATE,
reloadOnSearch: false, reloadOnSearch: false,
resolve: resolve resolve: resolve
}); });
$routeProvider.when('/stream', $routeProvider.when('/stream',
{ {
controller: 'StreamController', controller: 'StreamController',
templateUrl: 'viewer.html', template: VIEWER_TEMPLATE,
reloadOnSearch: false, reloadOnSearch: false,
resolve: resolve resolve: resolve
}); });
...@@ -112,6 +114,15 @@ function processAppOpts() { ...@@ -112,6 +114,15 @@ function processAppOpts() {
} }
} }
// @ngInject
function setupTemplateCache($templateCache) {
// 'thread.html' is used via ng-include so it needs to be added
// to the template cache. Other components just require() templates
// directly as strings.
$templateCache.put('thread.html',
require('../../templates/client/thread.html'));
}
module.exports = angular.module('h', [ module.exports = angular.module('h', [
// Angular addons which export the Angular module name // Angular addons which export the Angular module name
// via module.exports // via module.exports
...@@ -202,6 +213,7 @@ module.exports = angular.module('h', [ ...@@ -202,6 +213,7 @@ module.exports = angular.module('h', [
.config(configureRoutes) .config(configureRoutes)
.run(setupCrossFrame) .run(setupCrossFrame)
.run(setupHttp); .run(setupHttp)
.run(setupTemplateCache);
processAppOpts(); processAppOpts();
...@@ -784,7 +784,7 @@ function annotation($document) { ...@@ -784,7 +784,7 @@ function annotation($document) {
onReplyCountClick: '&', onReplyCountClick: '&',
replyCount: '<', replyCount: '<',
}, },
templateUrl: 'annotation.html' template: require('../../../templates/client/annotation.html'),
}; };
} }
......
...@@ -26,6 +26,6 @@ module.exports = function () { ...@@ -26,6 +26,6 @@ module.exports = function () {
onClick: '&', onClick: '&',
onToggleDropdown: '&', onToggleDropdown: '&',
}, },
templateUrl: 'dropdown_menu_btn.html' template: require('../../../templates/client/dropdown_menu_btn.html'),
}; };
}; };
...@@ -145,7 +145,7 @@ function excerpt() { ...@@ -145,7 +145,7 @@ function excerpt() {
}, },
restrict: 'E', restrict: 'E',
transclude: true, transclude: true,
templateUrl: 'excerpt.html', template: require('../../../templates/client/excerpt.html'),
}; };
} }
......
...@@ -39,7 +39,7 @@ function groupList( $window, groups, settings) { ...@@ -39,7 +39,7 @@ function groupList( $window, groups, settings) {
scope: { scope: {
auth: '<' auth: '<'
}, },
templateUrl: 'group_list.html' template: require('../../../templates/client/group_list.html'),
}; };
}; };
......
...@@ -15,6 +15,6 @@ module.exports = function () { ...@@ -15,6 +15,6 @@ module.exports = function () {
*/ */
onLogin: '&', onLogin: '&',
}, },
templateUrl: 'loggedout_message.html', template: require('../../../templates/client/loggedout_message.html'),
}; };
}; };
...@@ -102,7 +102,7 @@ module.exports = { ...@@ -102,7 +102,7 @@ module.exports = {
scope: { scope: {
onClose: '&', onClose: '&',
}, },
templateUrl: 'login_form.html', template: require('../../../templates/client/login_form.html'),
}; };
}, },
Controller: Controller, Controller: Controller,
......
...@@ -262,6 +262,6 @@ module.exports = function($filter, $sanitize, $sce) { ...@@ -262,6 +262,6 @@ module.exports = function($filter, $sanitize, $sce) {
readOnly: '<', readOnly: '<',
required: '@' required: '@'
}, },
templateUrl: 'markdown.html' template: require('../../../templates/client/markdown.html'),
}; };
}; };
...@@ -36,6 +36,6 @@ module.exports = function () { ...@@ -36,6 +36,6 @@ module.exports = function () {
onSave: '&', onSave: '&',
onSetPrivacy: '&' onSetPrivacy: '&'
}, },
templateUrl: 'publish_annotation_btn.html' template: require('../../../templates/client/publish_annotation_btn.html'),
}; };
} }
...@@ -12,6 +12,6 @@ module.exports = function () { ...@@ -12,6 +12,6 @@ module.exports = function () {
selectionCount: '<', selectionCount: '<',
totalCount: '<', totalCount: '<',
}, },
templateUrl: 'search_status_bar.html', template: require('../../../templates/client/search_status_bar.html'),
}; };
}; };
...@@ -31,5 +31,5 @@ module.exports = ['crossframe', (crossframe) -> ...@@ -31,5 +31,5 @@ module.exports = ['crossframe', (crossframe) ->
scope.viaPageLink = 'https://via.hypothes.is/' + frames[0].uri scope.viaPageLink = 'https://via.hypothes.is/' + frames[0].uri
restrict: 'E' restrict: 'E'
templateUrl: 'share_dialog.html' template: require('../../../templates/client/share_dialog.html')
] ]
...@@ -33,7 +33,7 @@ module.exports = { ...@@ -33,7 +33,7 @@ module.exports = {
controllerAs: 'vm', controllerAs: 'vm',
restrict: 'E', restrict: 'E',
scope: {}, scope: {},
templateUrl: 'sidebar_tutorial.html' template: require('../../../templates/client/sidebar_tutorial.html'),
}; };
}, },
Controller: SidebarTutorialController Controller: SidebarTutorialController
......
...@@ -29,6 +29,6 @@ module.exports = function () { ...@@ -29,6 +29,6 @@ module.exports = function () {
*/ */
newStyle: '<', newStyle: '<',
}, },
templateUrl: 'signin_control.html', template: require('../../../templates/client/signin_control.html'),
}; };
}; };
...@@ -13,6 +13,6 @@ module.exports = function () { ...@@ -13,6 +13,6 @@ module.exports = function () {
/** Called when the user changes the current sort criteria. */ /** Called when the user changes the current sort criteria. */
onChangeSortBy: '&', onChangeSortBy: '&',
}, },
templateUrl: 'sort_dropdown.html', template: require('../../../templates/client/sort_dropdown.html'),
} }
} }
...@@ -984,7 +984,6 @@ describe('annotation', function() { ...@@ -984,7 +984,6 @@ describe('annotation', function() {
createDirective(annotation); createDirective(annotation);
$scope.$digest(); $scope.$digest();
$scope.$destroy(); $scope.$destroy();
$timeout.flush();
$timeout.verifyNoPendingTasks(); $timeout.verifyNoPendingTasks();
}); });
}); });
......
...@@ -15,6 +15,6 @@ module.exports = function () { ...@@ -15,6 +15,6 @@ module.exports = function () {
sortOptions: '<', sortOptions: '<',
onChangeSortBy: '&', onChangeSortBy: '&',
}, },
templateUrl: 'top_bar.html', template: require('../../../templates/client/top_bar.html'),
}; };
}; };
'use strict';
// Karma configuration // Karma configuration
var path = require('path'); var path = require('path');
var stringify = require('stringify');
module.exports = function(config) { module.exports = function(config) {
config.set({ config.set({
...@@ -63,6 +66,11 @@ module.exports = function(config) { ...@@ -63,6 +66,11 @@ module.exports = function(config) {
configure: function (bundle) { configure: function (bundle) {
bundle bundle
.transform('coffeeify') .transform('coffeeify')
.transform(stringify, {
appliesTo: {
includeExtensions: ['.html'],
},
})
.plugin('proxyquire-universal') .plugin('proxyquire-universal')
// fix for Proxyquire in PhantomJS 1.x. // fix for Proxyquire in PhantomJS 1.x.
// See https://github.com/bitwit/proxyquireify-phantom-menace // See https://github.com/bitwit/proxyquireify-phantom-menace
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
"retry": "^0.8.0", "retry": "^0.8.0",
"scroll-into-view": "^1.3.1", "scroll-into-view": "^1.3.1",
"showdown": "^1.2.1", "showdown": "^1.2.1",
"stringify": "^5.1.0",
"through2": "^2.0.1", "through2": "^2.0.1",
"tiny-emitter": "^1.0.1", "tiny-emitter": "^1.0.1",
"uglifyify": "^3.0.1", "uglifyify": "^3.0.1",
......
...@@ -11,6 +11,7 @@ var coffeeify = require('coffeeify'); ...@@ -11,6 +11,7 @@ var coffeeify = require('coffeeify');
var exorcist = require('exorcist'); var exorcist = require('exorcist');
var gulpUtil = require('gulp-util'); var gulpUtil = require('gulp-util');
var mkdirp = require('mkdirp'); var mkdirp = require('mkdirp');
var stringify = require('stringify');
var uglifyify = require('uglifyify'); var uglifyify = require('uglifyify');
var watchify = require('watchify'); var watchify = require('watchify');
...@@ -117,6 +118,12 @@ module.exports = function createBundle(config, buildOpts) { ...@@ -117,6 +118,12 @@ module.exports = function createBundle(config, buildOpts) {
var bundle = browserify([], bundleOpts); var bundle = browserify([], bundleOpts);
bundle.transform(stringify, {
appliesTo: {
includeExtensions: ['.html'],
},
});
(config.require || []).forEach(function (req) { (config.require || []).forEach(function (req) {
// When another bundle uses 'bundle.external(<module path>)', // When another bundle uses 'bundle.external(<module path>)',
// the module path is rewritten relative to the // the module path is rewritten relative to the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment