6 | }
7 | });
--------------------------------------------------------------------------------
/test/fixtures/invalid.vue:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/test/fixtures/protourlrigging_1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/fixtures/protourlrigging_2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello World!
5 |
6 |
7 |
--------------------------------------------------------------------------------
/test/fixtures/roboto.html:
--------------------------------------------------------------------------------
1 |
10 |
11 |
--------------------------------------------------------------------------------
/test/fixtures/source_map.js:
--------------------------------------------------------------------------------
1 | Object.defineProperty(exports, '__esModule', {
2 | value: true
3 | });
4 |
5 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
6 |
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
10 |
11 | var _libStore = require('../src/store');
12 |
13 | var _libStore2 = _interopRequireDefault(_libStore);
14 |
15 | var _lodash = require('lodash');
16 |
17 | var _lodash2 = _interopRequireDefault(_lodash);
18 |
19 | var _utilsFillShape = require('../utils/fill-shape');
20 |
21 | var _utilsFillShape2 = _interopRequireDefault(_utilsFillShape);
22 |
23 | var WindowStore = (function () {
24 | function WindowStore() {
25 | _classCallCheck(this, WindowStore);
26 |
27 | this.MAIN_WINDOW = 'MAIN_WINDOW';
28 | this.SINGLE_TEAM = 'SINGLE_TEAM';
29 | this.NOTIFICATIONS = 'NOTIFICATIONS';
30 | this.SSB = 'SSB';
31 | }
32 |
33 | _createClass(WindowStore, [{
34 | key: 'getWindows',
35 | value: function getWindows() {
36 | return _libStore2['default'].getEntry('windows');
37 | }
38 | }, {
39 | key: 'getWindow',
40 | value: function getWindow(id) {
41 | return this.getWindows()[id];
42 | }
43 | }, {
44 | key: 'getWindowData',
45 | value: function getWindowData(type, params) {
46 | return (0, _utilsFillShape2['default'])(_libStore2['default'].getState(), this.getWindowShape(type, params));
47 | }
48 | }, {
49 | key: 'getWindowShape',
50 | value: function getWindowShape(type, params) {
51 | switch (type) {
52 | case this.MAIN_WINDOW:
53 | return {
54 | app: true,
55 | settings: true,
56 | teams: true,
57 | events: true
58 | };
59 |
60 | case this.SINGLE_TEAM:
61 | // params=teamId
62 | var shape = {
63 | app: true,
64 | settings: true,
65 | teams: {}
66 | };
67 | shape.teams[params] = true;
68 | return shape;
69 |
70 | case this.NOTIFICATIONS:
71 | return {
72 | notifications: true,
73 | teams: true
74 | };
75 | }
76 | return {};
77 | }
78 | }, {
79 | key: 'addWindow',
80 | value: function addWindow(windowList, newWindow, type, params) {
81 | var update = {};
82 | update[newWindow.id] = {
83 | window: newWindow,
84 | type: type,
85 | params: params
86 | };
87 | return _lodash2['default'].assign({}, windowList, update);
88 | }
89 | }, {
90 | key: 'getShapeForWindow',
91 | value: function getShapeForWindow(winId) {
92 | var windowData = this.getWindows()[winId];
93 | return this.getWindowShape(windowData.type, windowData.params);
94 | }
95 | }, {
96 | key: 'reduce',
97 | value: function reduce(windows, action) {
98 | if (windows === undefined) windows = {};
99 |
100 | switch (action.type) {
101 | case 'ADD_WINDOW':
102 | return this.addWindow(windows, action.data.newWindow, action.data.windowType, action.data.params);
103 | default:
104 | return windows;
105 | }
106 | }
107 | }]);
108 |
109 | return WindowStore;
110 | })();
111 |
112 | exports['default'] = new WindowStore();
113 | module.exports = exports['default'];
114 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9wYXVsL2NvZGUvdGlueXNwZWNrL3NsYWNrLXdpbnNzYi9zcmMvc3RvcmVzL3dpbmRvdy1zdG9yZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O3dCQUFrQixjQUFjOzs7O3NCQUNsQixRQUFROzs7OzhCQUNBLHFCQUFxQjs7OztJQUVyQyxXQUFXO1dBQVgsV0FBVzswQkFBWCxXQUFXOztTQUVmLFdBQVcsR0FBRyxhQUFhO1NBQzNCLFdBQVcsR0FBRyxhQUFhO1NBQzNCLGFBQWEsR0FBRyxlQUFlO1NBQy9CLEdBQUcsR0FBRyxLQUFLOzs7ZUFMUCxXQUFXOztXQU9MLHNCQUFHO0FBQ1gsYUFBTyxzQkFBTSxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDbEM7OztXQUVRLG1CQUFDLEVBQUUsRUFBRTtBQUNaLGFBQU8sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQzlCOzs7V0FFWSx1QkFBQyxJQUFJLEVBQUUsTUFBTSxFQUFFO0FBQzFCLGFBQU8saUNBQVUsc0JBQU0sUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztLQUN2RTs7O1dBRWEsd0JBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRTtBQUMzQixjQUFPLElBQUk7QUFDWCxhQUFLLElBQUksQ0FBQyxXQUFXO0FBQ25CLGlCQUFPO0FBQ0wsZUFBRyxFQUFFLElBQUk7QUFDVCxvQkFBUSxFQUFFLElBQUk7QUFDZCxpQkFBSyxFQUFFLElBQUk7QUFDWCxrQkFBTSxFQUFFLElBQUk7V0FDYixDQUFBOztBQUFBLEFBRUgsYUFBSyxJQUFJLENBQUMsV0FBVzs7QUFDbkIsY0FBSSxLQUFLLEdBQUc7QUFDVixlQUFHLEVBQUUsSUFBSTtBQUNULG9CQUFRLEVBQUUsSUFBSTtBQUNkLGlCQUFLLEVBQUUsRUFBRTtXQUNWLENBQUE7QUFDRCxlQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQztBQUMzQixpQkFBTyxLQUFLLENBQUM7O0FBQUEsQUFFZixhQUFLLElBQUksQ0FBQyxhQUFhO0FBQ3JCLGlCQUFPO0FBQ0wseUJBQWEsRUFBRSxJQUFJO0FBQ25CLGlCQUFLLEVBQUUsSUFBSTtXQUNaLENBQUE7QUFBQSxPQUNGO0FBQ0QsYUFBTyxFQUFFLENBQUM7S0FDWDs7O1dBRVEsbUJBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFO0FBQzdDLFVBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztBQUNoQixZQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUFHO0FBQ3JCLGNBQU0sRUFBRSxTQUFTO0FBQ2pCLFlBQUksRUFBRSxJQUFJO0FBQ1YsY0FBTSxFQUFFLE1BQU07T0FDZixDQUFDO0FBQ0YsYUFBTyxvQkFBRSxNQUFNLENBQUMsRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUN6Qzs7O1dBRWdCLDJCQUFDLEtBQUssRUFBRTtBQUN2QixVQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDMUMsYUFBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQ2hFOzs7V0FFSyxnQkFBQyxPQUFPLEVBQU8sTUFBTSxFQUFFO1VBQXRCLE9BQU8sZ0JBQVAsT0FBTyxHQUFHLEVBQUU7O0FBQ2pCLGNBQU8sTUFBTSxDQUFDLElBQUk7QUFDaEIsYUFBSyxZQUFZO0FBQ2YsaUJBQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUFBLEFBQ3BHO0FBQ0UsaUJBQU8sT0FBTyxDQUFDO0FBQUEsT0FDbEI7S0FDRjs7O1NBckVHLFdBQVc7OztxQkF3RUYsSUFBSSxXQUFXLEVBQUUiLCJmaWxlIjoiL1VzZXJzL3BhdWwvY29kZS90aW55c3BlY2svc2xhY2std2luc3NiL3NyYy9zdG9yZXMvd2luZG93LXN0b3JlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFN0b3JlIGZyb20gJy4uL2xpYi9zdG9yZSc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGZpbGxTaGFwZSBmcm9tICcuLi91dGlscy9maWxsLXNoYXBlJztcblxuY2xhc3MgV2luZG93U3RvcmUge1xuXG4gIE1BSU5fV0lORE9XID0gJ01BSU5fV0lORE9XJztcbiAgU0lOR0xFX1RFQU0gPSAnU0lOR0xFX1RFQU0nO1xuICBOT1RJRklDQVRJT05TID0gJ05PVElGSUNBVElPTlMnO1xuICBTU0IgPSAnU1NCJztcblxuICBnZXRXaW5kb3dzKCkge1xuICAgIHJldHVybiBTdG9yZS5nZXRFbnRyeSgnd2luZG93cycpO1xuICB9XG5cbiAgZ2V0V2luZG93KGlkKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0V2luZG93cygpW2lkXTtcbiAgfVxuXG4gIGdldFdpbmRvd0RhdGEodHlwZSwgcGFyYW1zKSB7XG4gICAgcmV0dXJuIGZpbGxTaGFwZShTdG9yZS5nZXRTdGF0ZSgpLCB0aGlzLmdldFdpbmRvd1NoYXBlKHR5cGUsIHBhcmFtcykpO1xuICB9XG5cbiAgZ2V0V2luZG93U2hhcGUodHlwZSwgcGFyYW1zKSB7XG4gICAgc3dpdGNoKHR5cGUpIHtcbiAgICBjYXNlIHRoaXMuTUFJTl9XSU5ET1c6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhcHA6IHRydWUsXG4gICAgICAgIHNldHRpbmdzOiB0cnVlLFxuICAgICAgICB0ZWFtczogdHJ1ZSxcbiAgICAgICAgZXZlbnRzOiB0cnVlXG4gICAgICB9XG5cbiAgICBjYXNlIHRoaXMuU0lOR0xFX1RFQU06IC8vIHBhcmFtcz10ZWFtSWRcbiAgICAgIGxldCBzaGFwZSA9IHtcbiAgICAgICAgYXBwOiB0cnVlLFxuICAgICAgICBzZXR0aW5nczogdHJ1ZSxcbiAgICAgICAgdGVhbXM6IHt9XG4gICAgICB9XG4gICAgICBzaGFwZS50ZWFtc1twYXJhbXNdID0gdHJ1ZTtcbiAgICAgIHJldHVybiBzaGFwZTtcblxuICAgIGNhc2UgdGhpcy5OT1RJRklDQVRJT05TOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbm90aWZpY2F0aW9uczogdHJ1ZSxcbiAgICAgICAgdGVhbXM6IHRydWVcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgYWRkV2luZG93KHdpbmRvd0xpc3QsIG5ld1dpbmRvdywgdHlwZSwgcGFyYW1zKSB7XG4gICAgbGV0IHVwZGF0ZSA9IHt9O1xuICAgIHVwZGF0ZVtuZXdXaW5kb3cuaWRdID0ge1xuICAgICAgd2luZG93OiBuZXdXaW5kb3csXG4gICAgICB0eXBlOiB0eXBlLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuICAgIHJldHVybiBfLmFzc2lnbih7fSwgd2luZG93TGlzdCwgdXBkYXRlKTtcbiAgfVxuXG4gIGdldFNoYXBlRm9yV2luZG93KHdpbklkKSB7XG4gICAgbGV0IHdpbmRvd0RhdGEgPSB0aGlzLmdldFdpbmRvd3MoKVt3aW5JZF07XG4gICAgcmV0dXJuIHRoaXMuZ2V0V2luZG93U2hhcGUod2luZG93RGF0YS50eXBlLCB3aW5kb3dEYXRhLnBhcmFtcyk7XG4gIH1cblxuICByZWR1Y2Uod2luZG93cyA9IHt9LCBhY3Rpb24pIHtcbiAgICBzd2l0Y2goYWN0aW9uLnR5cGUpIHtcbiAgICAgIGNhc2UgJ0FERF9XSU5ET1cnOlxuICAgICAgICByZXR1cm4gdGhpcy5hZGRXaW5kb3cod2luZG93cywgYWN0aW9uLmRhdGEubmV3V2luZG93LCBhY3Rpb24uZGF0YS53aW5kb3dUeXBlLCBhY3Rpb24uZGF0YS5wYXJhbXMpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHdpbmRvd3M7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG5ldyBXaW5kb3dTdG9yZSgpO1xuIl19
--------------------------------------------------------------------------------
/test/fixtures/valid.coffee:
--------------------------------------------------------------------------------
1 | crypto = require 'crypto'
2 | path = require 'path'
3 |
4 | CoffeeScript = null # defer until used
5 | fs = require 'fs-plus'
6 |
7 | stats =
8 | hits: 0
9 | misses: 0
10 | cacheDirectory = null
11 |
12 | getCachePath = (coffee) ->
13 | digest = crypto.createHash('sha1').update(coffee, 'utf8').digest('hex')
14 | path.join(cacheDirectory, "#{digest}.js")
15 |
16 | getCachedJavaScript = (cachePath) ->
17 | if fs.isFileSync(cachePath)
18 | try
19 | cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
20 | stats.hits++
21 | return cachedJavaScript
22 | return
23 |
24 | convertFilePath = (filePath) ->
25 | if process.platform is 'win32'
26 | filePath = "/#{path.resolve(filePath).replace(/\\/g, '/')}"
27 | encodeURI(filePath)
28 |
29 | loadCoffeeScript = ->
30 | coffee = require 'coffee-script'
31 |
32 | # Work around for https://github.com/jashkenas/coffeescript/issues/3890
33 | coffeePrepareStackTrace = Error.prepareStackTrace
34 | if coffeePrepareStackTrace?
35 | Error.prepareStackTrace = (error, stack) ->
36 | try
37 | return coffeePrepareStackTrace(error, stack)
38 | catch coffeeError
39 | return stack
40 |
41 | coffee
42 |
43 | compileCoffeeScript = (coffee, filePath, cachePath) ->
44 | CoffeeScript ?= loadCoffeeScript()
45 | {js, v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
46 | stats.misses++
47 |
48 | if btoa? and unescape? and encodeURIComponent?
49 | js = """
50 | #{js}
51 | //# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}
52 | //# sourceURL=#{convertFilePath(filePath)}
53 | """
54 |
55 | try
56 | fs.writeFileSync(cachePath, js)
57 | js
58 |
59 | requireCoffeeScript = (module, filePath) ->
60 | coffee = fs.readFileSync(filePath, 'utf8')
61 | cachePath = getCachePath(coffee)
62 | js = getCachedJavaScript(cachePath) ? compileCoffeeScript(coffee, filePath, cachePath)
63 | module._compile(js, filePath)
64 |
65 | exports.register = ->
66 | propertyConfig =
67 | enumerable: true
68 | value: requireCoffeeScript
69 | writable: false
70 |
71 | Object.defineProperty(require.extensions, '.coffee', propertyConfig)
72 | Object.defineProperty(require.extensions, '.litcoffee', propertyConfig)
73 | Object.defineProperty(require.extensions, '.coffee.md', propertyConfig)
74 |
75 | return
76 |
77 | exports.getCacheMisses = -> stats.misses
78 |
79 | exports.getCacheHits = -> stats.hits
80 |
81 | exports.resetCacheStats = ->
82 | stats =
83 | hits: 0
84 | misses: 0
85 |
86 | exports.setCacheDirectory = (newCacheDirectory) ->
87 | cacheDirectory = newCacheDirectory
88 |
89 | exports.getCacheDirectory = -> cacheDirectory
90 |
91 | exports.addPathToCache = (filePath) ->
92 | coffee = fs.readFileSync(filePath, 'utf8')
93 | cachePath = getCachePath(coffee)
94 | compileCoffeeScript(coffee, filePath, cachePath)
95 | return
--------------------------------------------------------------------------------
/test/fixtures/valid.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | {
3 | label: 'Application'
4 | submenu: [
5 | {
6 | label: 'About'
7 | command: null
8 | }
9 | ]
10 | id: 1
11 | visible: false
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/test/fixtures/valid.css:
--------------------------------------------------------------------------------
1 | body, html {
2 | margin: 0;
3 | padding: 0;
4 | width: 100%;
5 | height: 100%;
6 | background-color: #000000;
7 | overflow: hidden;
8 | -webkit-user-select: none;
9 | font-family: 'Roboto', sans-serif;
10 | font-size: 12px;
11 | cursor: default;
12 | }
13 |
14 | .right {
15 | float: right;
16 | }
17 |
18 | .hidden {
19 | display: none;
20 | }
21 |
22 | #player {
23 | width: 100%;
24 | height: 100%;
25 | }
26 |
27 | #drag-video {
28 | z-index: 99;
29 | position: absolute;
30 | top: 24px;
31 | bottom: 50px;
32 | left: 0;
33 | right: 0;
34 | }
35 |
36 | #splash {
37 | width: 100%;
38 | height: 100%;
39 | background-image: url('splash.gif');
40 | background-size: 100%;
41 | background-position: -50%;
42 | background-repeat: no-repeat;
43 | -webkit-filter: grayscale(100%);
44 | }
45 |
46 | #overlay {
47 | opacity: 0;
48 | z-index: 10;
49 | position: absolute;
50 | top: 0;
51 | left: 0;
52 | right: 0;
53 | bottom: 0;
54 | transition: opacity 0.3s ease;
55 | }
56 |
57 | #popup {
58 | opacity: 0;
59 | display: none;
60 | position: absolute;
61 | z-index: 20;
62 | right: 5px;
63 | bottom: 55px;
64 | top: 100px;
65 | width: 400px;
66 | background-color: #1F2021;
67 | border-radius: 3px;
68 | font-size: 14px;
69 | transition: opacity 0.3s ease;
70 | }
71 |
72 | #popup.chromecast #chromecast-popup {
73 | display: block;
74 | }
75 |
76 | #popup.chromecast #playlist-popup {
77 | display: none;
78 | }
79 |
80 | #popup.playlist #playlist-popup {
81 | display: block;
82 | }
83 |
84 | #popup.playlist #chromecast-popup {
85 | display: none;
86 | }
87 |
88 | #playlist-entries, #chromecast-entries {
89 | position: absolute;
90 | top: 46px;
91 | bottom: 55px;
92 | right: 0;
93 | left: 0;
94 | overflow: auto;
95 | }
96 |
97 | .playlist-entry, .chromecast-entry {
98 | color: #fff;
99 | font-size: 13px;
100 | padding: 10px 15px;
101 | overflow: hidden;
102 | text-overflow: ellipsis;
103 | white-space: nowrap;
104 | }
105 |
106 | @-webkit-keyframes spin {
107 | to { -webkit-transform: rotate(360deg); }
108 | }
109 |
110 | @-moz-keyframes spin {
111 | to { -moz-transform: rotate(360deg); }
112 | }
113 |
114 | @-ms-keyframes spin {
115 | to { -ms-transform: rotate(360deg); }
116 | }
117 |
118 | @-o-keyframes spin {
119 | to { -o-transform: rotate(360deg); }
120 | }
121 |
122 | @keyframes spin {
123 | to { transform: rotate(360deg); }
124 | }
125 |
126 | .playlist-entry .status {
127 | float: right;
128 | -webkit-animation: spin 1.5s infinite linear;
129 | -moz-animation: spin 1.5s infinite linear;
130 | -ms-animation: spin 1.5s infinite linear;
131 | -o-animation: spin 1.5s infinite linear;
132 | animation: spin 1.5s infinite linear;
133 | }
134 |
135 | .playlist-entry .status:after {
136 | -webkit-transform: rotate(45deg);
137 | -moz-transform: rotate(45deg);
138 | -ms-transform: rotate(45deg);
139 | -o-transform: rotate(45deg);
140 | transform: rotate(45deg);
141 | }
142 |
143 | .playlist-entry.odd, .chromecast-entry.odd {
144 | background-color: #222324;
145 | }
146 |
147 | .playlist-entry.selected, .chromecast-entry.selected {
148 | background-color: #31A357;
149 | }
150 |
151 | #popup .header {
152 | background-color: #363738;
153 | color: #E1E1E1;
154 | font-size: 16px;
155 | line-height: 16px;
156 | padding: 15px;
157 | border-radius: 3px 3px 0 0;
158 | }
159 |
160 | #popup .button {
161 | margin: 10px;
162 | background-color: #31A357;
163 | padding: 10px;
164 | text-align: center;
165 | color: #E1E1E1;
166 | border-radius: 3px;
167 | }
168 |
169 | #controls-timeline-tooltip {
170 | background: #1F2021;
171 | border-radius: 3px;
172 | box-shadow: 0px 1px 2px rgba(0,0,0,.2);
173 | padding: 4px 8px;
174 | color: #fff;
175 | text-align: center;
176 | font-size: 11px;
177 | position: absolute;
178 | bottom: 53px;
179 | z-index: 100;
180 | opacity: 0;
181 | transition: opacity 0.25s;
182 | }
183 |
184 | #controls-timeline-tooltip:after {
185 | width: 0;
186 | height: 0;
187 | top: 100%;
188 | left: 50%;
189 | border-left: 6px solid transparent;
190 | border-right: 6px solid transparent;
191 | border-top: 6px solid #1F2021;
192 | content: "";
193 | margin-left: -6px;
194 | position: absolute;
195 | }
196 |
197 | #popup .button.bottom {
198 | position: absolute;
199 | bottom: 0;
200 | left: 0;
201 | right: 0;
202 | }
203 |
204 | #idle {
205 | position: absolute;
206 | top: 24px;
207 | bottom: 50px;
208 | left: 0;
209 | right: 0;
210 | }
211 |
212 | .hide-cursor {
213 | cursor: none;
214 | }
215 |
216 | .hide-cursor #overlay {
217 | opacity: 0 !important;
218 | }
219 |
220 | body:hover #overlay, body:hover .titlebar {
221 | opacity: 1;
222 | }
223 |
224 | .titlebar {
225 | background-color: #1F2021;
226 | }
227 |
228 | #controls {
229 | z-index: 11;
230 | position: absolute;
231 | left: 0;
232 | right: 0;
233 | bottom: 0;
234 | height: 50px;
235 | background-color: #1F2021;
236 | color: #727374;
237 | }
238 |
239 | #controls .center {
240 | margin-top: 13px;
241 | }
242 |
243 | #controls-timeline {
244 | background-color: #303233;
245 | height: 10px;
246 | width: 100%;
247 | }
248 |
249 | #controls-timeline-position {
250 | background-color: #31A357;
251 | width: 0%;
252 | height: 10px;
253 | transition: width 0.25s linear;
254 | }
255 |
256 | .controls-secondary {
257 | padding: 6px 10px 0 0;
258 | }
259 |
260 | #player-downloadspeed, #controls-playlist, #controls-chromecast {
261 | margin-right: 11px;
262 | }
263 |
264 | #controls-play {
265 | margin: 6px 9px 6px 14px;
266 | }
267 |
268 | #controls-play, #player-downloadspeed, #controls-fullscreen, #controls-playlist, #controls-chromecast {
269 | float: left;
270 | }
271 |
272 | #controls-play .mega-octicon, #player-downloadspeed .mega-octicon,
273 | #controls-fullscreen .mega-octicon, #controls-playlist .mega-octicon {
274 | /* this is the click buffer */
275 | padding: 3px 6px;
276 | }
277 |
278 | #controls-play span:hover .mega-octicon, #player-downloadspeed span:hover .mega-octicon,
279 | #controls-fullscreen span:hover .mega-octicon, #controls-playlist span:hover .mega-octicon,
280 | #controls-chromecast span:hover .mega-octicon {
281 | color: #31A357;
282 | }
283 |
284 | #controls-chromecast .chromecast {
285 | background-image: url('chromecast.png');
286 | background-size: 26px 72px;
287 | background-repeat: no-repeat;
288 | background-position: 0px 0px;
289 | margin-top: 6px;
290 | display: block;
291 | width: 26px;
292 | height: 18px;
293 | }
294 | #controls-chromecast .chromecast:hover, #controls-chromecast.selected .chromecast {
295 | background-position: 0px -18px;
296 | }
297 | .chromecasting #controls-chromecast .chromecast {
298 | background-position: 0px -36px;
299 | }
300 | .chromecasting #controls-chromecast .chromecast:hover, .chromecasting #controls-chromecast.selected .chromecast {
301 | background-position: 0px -54px;
302 | }
303 |
304 | #player-downloadspeed {
305 | margin-top: 4px;
306 | padding: 3px 20px;
307 | }
308 |
309 | #controls-playlist.selected .mega-octicon {
310 | color: #31A357;
311 | }
312 |
313 | .mega-octicon {
314 | color: #F0F0F0;
315 | font-size: 22px;
316 | }
317 |
318 | #controls-play .mega-octicon {
319 | color: #31A357;
320 | }
321 |
322 | #controls-time {
323 | width: 100px;
324 | float: left;
325 | }
326 |
327 | #controls-main {
328 | display: none;
329 | }
330 |
331 | #controls-time-current {
332 | color: #F0F0F0;
333 | }
334 |
335 | #controls-time-current, #controls-time-total {
336 | display: inline-block;
337 | min-width: 33px;
338 | }
339 |
340 | #controls-volume {
341 | margin: 11px 9px 11px 0;
342 | padding: 0;
343 | float: left;
344 | }
345 |
346 | #controls-volume-slider {
347 | -webkit-appearance: none;
348 | background: -webkit-gradient(linear, left top, right top, color-stop(50%, #31A357), color-stop(50%, #727374));
349 | width: 50px;
350 | height: 3px;
351 | border-radius: 0px;
352 | }
353 |
354 | #controls-volume-slider::-webkit-slider-thumb {
355 | -webkit-appearance: none;
356 | background-color: #31A357;
357 | opacity: 1.0;
358 | width: 7px;
359 | height: 7px;
360 | border-radius: 3.5px;
361 | }
362 |
363 | #controls-volume-slider:focus {
364 | outline: none;
365 | }
366 |
367 | #controls-name {
368 | float: left;
369 | margin-left: 20px;
370 | }
371 |
--------------------------------------------------------------------------------
/test/fixtures/valid.graphql:
--------------------------------------------------------------------------------
1 | {
2 | user(id: 5) {
3 | firstName
4 | lastName
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixtures/valid.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | head
4 | title= pageTitle
5 | script(type='text/javascript').
6 | if (foo) {
7 | bar(1 + 5)
8 | }
9 | body
10 | h1 Jade - node template engine
11 | #container.col
12 | if youAreUsingJade
13 | p You are amazing
14 | else
15 | p Get on it!
16 | p.
17 | Jade is a terse and simple
18 | templating language with a
19 | strong focus on performance
20 | and powerful features.
21 |
--------------------------------------------------------------------------------
/test/fixtures/valid.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import crypto from 'crypto';
4 | import path from 'path';
5 | import fs from 'fs';
6 | import mkdirp from 'mkdirp';
7 | import _ from 'lodash';
8 |
9 | export default class CompileCache {
10 | constructor() {
11 | this.stats = {
12 | hits: 0,
13 | misses: 0
14 | };
15 |
16 | this.cacheDir = null;
17 | this.jsCacheDir = null;
18 | this.seenFilePaths = {};
19 | }
20 |
21 | getCompilerInformation() {
22 | throw new Error("Implement this in a derived class");
23 | }
24 |
25 | compile(sourceCode, filePath, cachePath) {
26 | throw new Error("Implement this in a derived class");
27 | }
28 |
29 | getMimeType() {
30 | throw new Error("Implement this in a derived class");
31 | }
32 |
33 | initializeCompiler() {
34 | throw new Error("Implement this in a derived class");
35 | }
36 |
37 | shouldCompileFile(sourceCode, fullPath) {
38 | this.ensureInitialized();
39 | let lowerPath = fullPath.toLowerCase();
40 |
41 | // NB: require() normally does this for us, but in our protocol hook we
42 | // need to do this ourselves
43 | return _.some(
44 | this.extensions,
45 | (ext) => lowerPath.lastIndexOf(ext) + ext.length === lowerPath.length);
46 | }
47 |
48 | ///
49 | /// shasum - Hash with an update() method.
50 | /// value - Must be a value that could be returned by JSON.parse().
51 | ///
52 | updateDigestForJsonValue(shasum, value) {
53 | // Implmentation is similar to that of pretty-printing a JSON object, except:
54 | // * Strings are not escaped.
55 | // * No effort is made to avoid trailing commas.
56 | // These shortcuts should not affect the correctness of this function.
57 | const type = typeof(value);
58 |
59 | if (type === 'string') {
60 | shasum.update('"', 'utf8');
61 | shasum.update(value, 'utf8');
62 | shasum.update('"', 'utf8');
63 | return;
64 | }
65 |
66 | if (type === 'boolean' || type === 'number') {
67 | shasum.update(value.toString(), 'utf8');
68 | return;
69 | }
70 |
71 | if (value === null) {
72 | shasum.update('null', 'utf8');
73 | return;
74 | }
75 |
76 | if (Array.isArray(value)) {
77 | shasum.update('[', 'utf8');
78 | for (let i=0; i < value.length; i++) {
79 | this.updateDigestForJsonValue(shasum, value[i]);
80 | shasum.update(',', 'utf8');
81 | }
82 | shasum.update(']', 'utf8');
83 | return;
84 | }
85 |
86 | // value must be an object: be sure to sort the keys.
87 | let keys = Object.keys(value);
88 | keys.sort();
89 |
90 | shasum.update('{', 'utf8');
91 |
92 | for (let i=0; i < keys.length; i++) {
93 | this.updateDigestForJsonValue(shasum, keys[i]);
94 | shasum.update(': ', 'utf8');
95 | this.updateDigestForJsonValue(shasum, value[keys[i]]);
96 | shasum.update(',', 'utf8');
97 | }
98 |
99 | shasum.update('}', 'utf8');
100 | }
101 |
102 | createDigestForCompilerInformation() {
103 | let sha1 = crypto.createHash('sha1');
104 | this.updateDigestForJsonValue(sha1, this.getCompilerInformation());
105 | return sha1.digest('hex');
106 | }
107 |
108 | getCachePath(sourceCode) {
109 | let digest = crypto.createHash('sha1').update(sourceCode, 'utf8').digest('hex');
110 |
111 | if (!this.jsCacheDir) {
112 | this.jsCacheDir = path.join(this.cacheDir, this.createDigestForCompilerInformation());
113 | mkdirp.sync(this.jsCacheDir);
114 | }
115 |
116 | return path.join(this.jsCacheDir, `${digest}.js`);
117 | }
118 |
119 | getCachedJavaScript(cachePath) {
120 | try {
121 | let ret = fs.readFileSync(cachePath, 'utf8');
122 | this.stats.hits++;
123 |
124 | return ret;
125 | } catch (e) {
126 | return null;
127 | }
128 | }
129 |
130 | saveCachedJavaScript(cachePath, js) {
131 | fs.writeFileSync(cachePath, js);
132 | }
133 |
134 | // Function that obeys the contract of an entry in the require.extensions map.
135 | // Returns the transpiled version of the JavaScript code at filePath, which is
136 | // either generated on the fly or pulled from cache.
137 | loadFile(module, filePath, returnOnly=false, sourceCode=null) {
138 | this.ensureInitialized();
139 |
140 | let fullPath = path.resolve(filePath);
141 | this.seenFilePaths[path.dirname(filePath)] = true;
142 |
143 | sourceCode = sourceCode || fs.readFileSync(filePath, 'utf8');
144 |
145 | if (!this.shouldCompileFile(sourceCode, fullPath)) {
146 | if (returnOnly) return sourceCode;
147 | return module._compile(sourceCode, filePath);
148 | }
149 |
150 | // NB: We do all of these backflips in order to not load compilers unless
151 | // we actually end up using them, since loading them is typically fairly
152 | // expensive
153 | if (!this.compilerInformation.version) {
154 | this.compilerInformation.version = this.initializeCompiler();
155 | }
156 |
157 | let cachePath = this.getCachePath(sourceCode);
158 | let js = this.getCachedJavaScript(cachePath);
159 |
160 | if (!js) {
161 | js = this.compile(sourceCode, filePath, cachePath);
162 | this.stats.misses++;
163 |
164 | this.saveCachedJavaScript(cachePath, js);
165 | }
166 |
167 | if (returnOnly) return js;
168 | return module._compile(js, filePath);
169 | }
170 |
171 | register() {
172 | this.ensureInitialized();
173 |
174 | for (let i=0; i < this.extensions.length; i++) {
175 | Object.defineProperty(require.extensions, `.${this.extensions[i]}`, {
176 | enumerable: true,
177 | writable: false,
178 | value: (module, filePath) => this.loadFile(module, filePath)
179 | });
180 | }
181 | }
182 |
183 | ensureInitialized() {
184 | if (this.extensions) return;
185 |
186 | let info = this.getCompilerInformation();
187 |
188 | if (!info.extension && !info.extensions) {
189 | throw new Error("Compiler must register at least one extension in getCompilerInformation");
190 | }
191 |
192 | this.extensions = (info.extensions ? info.extensions : [info.extension]);
193 | }
194 |
195 | setCacheDirectory(newCacheDir) {
196 | if (this.cacheDir === newCacheDir) return;
197 |
198 | this.cacheDir = newCacheDir;
199 | this.jsCacheDir = null;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/test/fixtures/valid.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default React.createClass({
4 | render() {
5 | return
Hello World!
6 | }
7 | });
--------------------------------------------------------------------------------
/test/fixtures/valid.less:
--------------------------------------------------------------------------------
1 | @nice-blue: #5B83AD;
2 | @light-blue: @nice-blue + #111;
3 |
4 | #header {
5 | color: @light-blue;
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixtures/valid.sass:
--------------------------------------------------------------------------------
1 | #main
2 | color: blue
3 | font-size: 0.3em
4 |
5 | a
6 | font:
7 | weight: bold
8 | family: serif
9 | &:hover
10 | background-color: #eee
11 |
--------------------------------------------------------------------------------
/test/fixtures/valid.scss:
--------------------------------------------------------------------------------
1 | h1 {
2 | color: green;
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/valid.styl:
--------------------------------------------------------------------------------
1 | @import 'nib'
2 |
3 | list = red green blue
4 | no-colors = false
5 |
6 | body
7 | color: color for color in list if length(list) > 2 unless no-colors
8 |
9 | mixin()
10 | color: color for color in list if length(list) > 2 unless no-colors
11 |
12 | body
13 | mixin()
14 |
--------------------------------------------------------------------------------
/test/fixtures/valid.ts:
--------------------------------------------------------------------------------
1 | declare module WinJS {
2 | class Promise
{
3 | then(success?: (value: T) => Promise, error?: (error: any) => Promise, progress?: (progress: any) => void): Promise;
4 | }
5 | }
6 |
7 | declare module Data {
8 | export interface IListItem {
9 | itemIndex: number;
10 | key: any;
11 | data: T;
12 | group: any;
13 | isHeader: boolean;
14 | cached: boolean;
15 | isNonSourceData: boolean;
16 | preventAugmentation: boolean;
17 | }
18 | export interface IVirtualList {
19 | //removeIndices: WinJS.Promise[]>;
20 | removeIndices(indices: number[], options?: any): WinJS.Promise[]>;
21 | }
22 | export class VirtualList implements IVirtualList {
23 | //removeIndices: WinJS.Promise[]>;
24 | public removeIndices(indices: number[], options?: any): WinJS.Promise[]>;
25 | }
26 | }
27 |
28 | class Person {
29 | readonly name: string;
30 |
31 | constructor(name: string) {
32 | if (name.length < 1) {
33 | throw new Error("Empty name!");
34 | }
35 |
36 | this.name = name;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/test/fixtures/valid.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export class SlackApp extends React.Component {
4 | render() {
5 | const vm = this.viewModel;
6 | const shouldShift = vm.isOpen && window.outerWidth > window.outerHeight;
7 |
8 | return
9 |
10 |
11 |
12 |
13 | I'm in the drawer
14 |
15 |
16 | I am the main content
17 |
18 | ;
19 | }
20 | }
21 |
22 | export function HelloWorld ({name}) {
23 | return {`Hi ${name}`}
;
24 | };
25 |
--------------------------------------------------------------------------------
/test/fixtures/valid.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
15 |
16 |
22 |
23 |
24 | div
25 | h1 This is the app
26 | comp-a
27 | comp-b
28 |
29 |
30 |
35 |
--------------------------------------------------------------------------------
/test/fixtures/x-require-valid.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/test/inline-html-compiler.js:
--------------------------------------------------------------------------------
1 | import './support.js';
2 |
3 | import fs from 'fs';
4 | import path from 'path';
5 | import cheerio from 'cheerio';
6 | import pify from 'pify';
7 |
8 | const validInputs = [
9 | 'inline-valid.html',
10 | 'inline-valid-2.html',
11 | 'inline-valid-3.html'
12 | ];
13 |
14 | const pfs = pify(fs);
15 | const InlineHtmlCompiler = global.compilersByMimeType['text/html'];
16 |
17 | const d = require('debug')('test:inline-html-compiler');
18 |
19 | describe('The inline HTML compiler', function() {
20 | beforeEach(function() {
21 | let compilers = Object.keys(global.compilersByMimeType).reduce((acc, x) => {
22 | let Klass = global.compilersByMimeType[x];
23 | acc[x] = new Klass();
24 |
25 | return acc;
26 | }, {});
27 |
28 | compilers['application/javascript'].compilerOptions = {
29 | "presets": ["es2016-node5", "react"],
30 | "sourceMaps": "inline"
31 | };
32 |
33 | compilers['text/coffeescript'].compilerOptions = { sourceMap: true };
34 |
35 | this.fixture = InlineHtmlCompiler.createFromCompilers(compilers);
36 | });
37 |
38 | validInputs.forEach((inputFile) => {
39 | it('should compile the valid fixture ' + inputFile, async function() {
40 | let input = path.join(__dirname, '..', 'test', 'fixtures', inputFile);
41 |
42 | let cc = {};
43 | expect(await this.fixture.shouldCompileFile(input, cc)).to.be.ok;
44 |
45 | let code = await pfs.readFile(input, 'utf8');
46 | let df = await this.fixture.determineDependentFiles(input, code, cc);
47 |
48 | expect(df.length).to.equal(0);
49 |
50 | let result = await this.fixture.compile(code, input, cc);
51 | expect(result.mimeType).to.equal('text/html');
52 |
53 | let $ = cheerio.load(result.code);
54 | let tags = $('script');
55 | expect(tags.length > 0).to.be.ok;
56 |
57 | $('script').map((__, el) => {
58 | let text = $(el).text();
59 | if (!text || text.length < 2) return;
60 |
61 | if ($(el).attr('type').match(/handlebars/)) return;
62 |
63 | expect(text.split('\n').find((l) => l.match(/sourceMappingURL/))).to.be.ok;
64 | });
65 | });
66 |
67 | it('should compile the valid fixture ' + inputFile + ' synchronously', function() {
68 | let input = path.join(__dirname, '..', 'test', 'fixtures', inputFile);
69 |
70 | let cc = {};
71 | expect(this.fixture.shouldCompileFileSync(input, cc)).to.be.ok;
72 |
73 | let code = fs.readFileSync(input, 'utf8');
74 | let df = this.fixture.determineDependentFilesSync(input, code, cc);
75 |
76 | expect(df.length).to.equal(0);
77 |
78 | let result = this.fixture.compileSync(code, input, cc);
79 | expect(result.mimeType).to.equal('text/html');
80 |
81 | let $ = cheerio.load(result.code);
82 | let tags = $('script');
83 | expect(tags.length > 0).to.be.ok;
84 |
85 | $('script').map((__, el) => {
86 | let text = $(el).text();
87 | if (!text || text.length < 2) return;
88 |
89 | d($(el).attr('type'));
90 | if ($(el).attr('type').match(/handlebars/)) return;
91 |
92 | d(text);
93 | expect(text.split('\n').find((l) => l.match(/sourceMappingURL/))).to.be.ok;
94 | });
95 | });
96 | });
97 |
98 | it('should remove protocol-relative URLs because they are dumb', async function() {
99 | let input = path.join(__dirname, '..', 'test', 'fixtures', 'roboto.html');
100 |
101 | let cc = {};
102 | expect(await this.fixture.shouldCompileFile(input, cc)).to.be.ok;
103 |
104 | let code = await pfs.readFile(input, 'utf8');
105 | let df = await this.fixture.determineDependentFiles(input, code, cc);
106 |
107 | expect(df.length).to.equal(0);
108 |
109 | let result = await this.fixture.compile(code, input, cc);
110 |
111 | expect(result.code.length > 0).to.be.ok;
112 | expect(result.mimeType).to.equal('text/html');
113 |
114 | let $ = cheerio.load(result.code);
115 | let tags = $('link');
116 | expect(tags.length === 1).to.be.ok;
117 | expect($(tags[0]).attr('href').match(/^https/i)).to.be.ok;
118 | });
119 |
120 | it('should canonicalize x-require paths', async function() {
121 | let input = path.join(__dirname, '..', 'test', 'fixtures', 'x-require-valid.html');
122 |
123 | let cc = {};
124 | expect(await this.fixture.shouldCompileFile(input, cc)).to.be.ok;
125 |
126 | let code = await pfs.readFile(input, 'utf8');
127 | let df = await this.fixture.determineDependentFiles(input, code, cc);
128 |
129 | expect(df.length).to.equal(0);
130 |
131 | let result = await this.fixture.compile(code, input, cc);
132 |
133 | expect(result.code.length > 0).to.be.ok;
134 | expect(result.mimeType).to.equal('text/html');
135 |
136 | let $ = cheerio.load(result.code);
137 | let tags = $('x-require');
138 | expect(tags.length === 1).to.be.ok;
139 |
140 | $('x-require').map((__, el) => {
141 | let src = $(el).attr('src');
142 | expect(src.split(/[\\\/]/).find((x) => x === '.' || x === '..')).not.to.be.ok;
143 | });
144 | });
145 | });
146 |
--------------------------------------------------------------------------------
/test/packager-cli.js:
--------------------------------------------------------------------------------
1 | import './support.js';
2 |
3 | import sfs from 'fs';
4 | import path from 'path';
5 | import rimraf from 'rimraf';
6 | import mkdirp from 'mkdirp';
7 |
8 | import {packagerMain} from '../src/packager-cli';
9 |
10 | const d = require('debug')('test:packager-cli');
11 |
12 | let testCount = 0;
13 |
14 | function statSyncNoException(fsPath) {
15 | if ('statSyncNoException' in sfs) {
16 | return sfs.statSyncNoException(fsPath);
17 | }
18 |
19 | try {
20 | return sfs.statSync(fsPath);
21 | } catch (e) {
22 | return null;
23 | }
24 | }
25 |
26 | describe.skip('the packager CLI', function() {
27 | this.timeout(120 * 1000);
28 |
29 | beforeEach(function() {
30 | this.tempCacheDir = path.join(__dirname, `__packager_cli_${testCount++}`);
31 | mkdirp.sync(this.tempCacheDir);
32 | });
33 |
34 | afterEach(function() {
35 | rimraf.sync(this.tempCacheDir);
36 | });
37 |
38 | it('should do the basics of electron-packager', async function() {
39 | let inputApp = path.resolve(__dirname, 'electron-app');
40 |
41 | // NB: The first two elements are dummies to fake out what would normally
42 | // be the path to node and the path to the script
43 | await packagerMain(['', '', '--platform', 'win32', '--version', '1.3.2', '--arch', 'all', '--out', this.tempCacheDir, inputApp]);
44 |
45 | const toFind = ['node.dll', 'resources', 'resources/app/src/main.coffee'];
46 | let cacheDir = this.tempCacheDir;
47 |
48 | toFind.forEach((name) => {
49 | let file = path.resolve(cacheDir, 'mp3-encoder-demo-win32-ia32', name);
50 |
51 | d(`Looking for ${file}`);
52 | expect(sfs.statSync(file)).to.be.ok;
53 | });
54 | });
55 |
56 | it('should run electron-compile', async function() {
57 | let inputApp = path.resolve(__dirname, 'electron-app');
58 |
59 | // NB: The first two elements are dummies to fake out what would normally
60 | // be the path to node and the path to the script
61 | await packagerMain(['', '', '--platform', 'win32', '--version', '1.3.2', '--arch', 'x64', '--out', this.tempCacheDir, inputApp]);
62 |
63 | const toFind = ['resources/app/.cache', 'resources/app/.compilerc'];
64 | let cacheDir = this.tempCacheDir;
65 |
66 | toFind.forEach((name) => {
67 | let file = path.resolve(cacheDir, 'mp3-encoder-demo-win32-x64', name);
68 |
69 | d(`Looking for ${file}`);
70 | expect(sfs.statSync(file)).to.be.ok;
71 | });
72 | });
73 |
74 | it('should replace the init script with es6-shim', async function() {
75 | let inputApp = path.resolve(__dirname, 'electron-app');
76 |
77 | // NB: The first two elements are dummies to fake out what would normally
78 | // be the path to node and the path to the script
79 | await packagerMain(['', '', '--platform', 'win32', '--version', '1.3.2', '--arch', 'x64', '--out', this.tempCacheDir, inputApp]);
80 |
81 | const toFind = ['resources/app/package.json', 'resources/app/es6-shim.js'];
82 | let cacheDir = this.tempCacheDir;
83 |
84 | toFind.forEach((name) => {
85 | let file = path.resolve(cacheDir, 'mp3-encoder-demo-win32-x64', name);
86 |
87 | d(`Looking for ${file}`);
88 | expect(sfs.statSync(file)).to.be.ok;
89 | });
90 |
91 | let packageJson = require(
92 | path.join(cacheDir, 'mp3-encoder-demo-win32-x64', 'resources', 'app', 'package.json'));
93 |
94 | expect(packageJson.originalMain).to.equal('main.js');
95 | expect(packageJson.main).to.equal('es6-shim.js');
96 | });
97 |
98 | it('should ASAR archive', async function() {
99 | let inputApp = path.resolve(__dirname, 'electron-app');
100 |
101 | // NB: The first two elements are dummies to fake out what would normally
102 | // be the path to node and the path to the script
103 | await packagerMain(['', '', '--platform', 'win32', '--version', '1.3.2', '--arch', 'x64', '--asar', '--out', this.tempCacheDir, inputApp]);
104 |
105 | const toFind = ['resources/app.asar'];
106 | let cacheDir = this.tempCacheDir;
107 |
108 | toFind.forEach((name) => {
109 | let file = path.resolve(cacheDir, 'mp3-encoder-demo-win32-x64', name);
110 |
111 | d(`Looking for ${file}`);
112 | expect(statSyncNoException(file)).to.be.ok;
113 | });
114 |
115 | const toNotFind = ['resources/app'];
116 | toNotFind.forEach((name) => {
117 | let file = path.resolve(cacheDir, 'mp3-encoder-demo-win32-x64', name);
118 |
119 | d(`Looking for ${file}`);
120 | expect(statSyncNoException(file)).not.to.be.ok;
121 | });
122 | });
123 | });
124 |
--------------------------------------------------------------------------------
/test/protocol-hook.js:
--------------------------------------------------------------------------------
1 | import './support.js';
2 |
3 | import path from 'path';
4 | import fs from 'fs';
5 |
6 | import {rigHtmlDocumentToInitializeElectronCompile} from '../src/protocol-hook';
7 |
8 | describe('protocol hook library', function() {
9 | describe('The HTML include rigging', function() {
10 | it('should rig pages with HEAD tags', function() {
11 | let content = fs.readFileSync(path.join(__dirname, '..', 'test', 'fixtures', 'protourlrigging_1.html'), 'utf8');
12 | let result = rigHtmlDocumentToInitializeElectronCompile(content);
13 |
14 | let lines = result.split('\n');
15 | expect(lines.find((x) => x.match(/head.*__magic__file/i))).to.be.ok;
16 | });
17 |
18 | it('should rig pages without tags', function() {
19 | let content = fs.readFileSync(path.join(__dirname, '..', 'test', 'fixtures', 'protourlrigging_2.html'), 'utf8');
20 | let result = rigHtmlDocumentToInitializeElectronCompile(content);
21 |
22 | let lines = result.split('\n');
23 | expect(lines.find((x) => x.match(/head.*__magic__file/i))).to.be.ok;
24 | });
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/test/support.js:
--------------------------------------------------------------------------------
1 | const allCompilerClasses = require('electron-compilers');
2 |
3 | let chai = require("chai");
4 | let chaiAsPromised = require("chai-as-promised");
5 |
6 | chai.should();
7 | chai.use(chaiAsPromised);
8 |
9 | global.chai = chai;
10 | global.chaiAsPromised = chaiAsPromised;
11 | global.expect = chai.expect;
12 | global.AssertionError = chai.AssertionError;
13 | global.Assertion = chai.Assertion;
14 | global.assert = chai.assert;
15 |
16 | require('../src/rig-mime-types').init();
17 |
18 | global.compilersByMimeType = allCompilerClasses.reduce((acc,x) => {
19 | acc = acc || {};
20 |
21 | for (let type of x.getInputMimeTypes()) { acc[type] = x; }
22 | return acc;
23 | }, {});
24 |
25 | global.compilersByMimeType['text/css'] = global.compilersByMimeType['text/plain'];
26 |
27 | const VueCompiler = global.compilersByMimeType['text/vue'];
28 | class AutoCreatedVueCompiler extends VueCompiler {
29 | constructor() {
30 | let dummy = VueCompiler.createFromCompilers(Object.keys(global.compilersByMimeType).reduce((acc, x) => {
31 | if ('createFromCompilers' in global.compilersByMimeType[x]) return acc;
32 |
33 | acc[x] = new global.compilersByMimeType[x]();
34 | return acc;
35 | }, {}));
36 |
37 | super(dummy.asyncCompilers, dummy.syncCompilers);
38 | }
39 | }
40 |
41 | global.compilersByMimeType['text/vue'] = AutoCreatedVueCompiler;
42 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | export declare class CompilerHost {
2 |
3 | /**
4 | * Creates a development-mode CompilerHost from the previously saved configuration.
5 | */
6 | static createFromConfiguration(
7 | rootCacheDir: string,
8 | appRoot: string,
9 | compilersByMimeType: CompilersByMimeType,
10 | fallbackCompiler: CompilerBase): PromiseLike;
11 |
12 | /**
13 | * Creates a development-mode CompilerHost from the previously saved configuration.
14 | */
15 | static createFromConfigurationSync(
16 | rootCacheDir: string,
17 | appRoot: string,
18 | compilersByMimeType: CompilersByMimeType,
19 | fallbackCompiler: CompilerBase): CompilerHost;
20 |
21 | /**
22 | * Creates a production-mode CompilerHost from the previously saved configuration.
23 | */
24 | static createReadonlyFromConfiguration(
25 | rootCacheDir: string,
26 | appRoot: string,
27 | fallbackCompiler: CompilerBase): PromiseLike;
28 |
29 | /**
30 | * Creates a production-mode CompilerHost from the previously saved configuration.
31 | */
32 | static createReadonlyFromConfigurationSync(
33 | rootCacheDir: string,
34 | appRoot: string,
35 | fallbackCompiler: CompilerBase): CompilerHost
36 |
37 | constructor(
38 | rootCacheDir: string,
39 | compilers: CompilersByMimeType,
40 | fileChangeCache: FileChangedCache,
41 | readOnlyMode?: boolean,
42 | fallbackCompiler?: CompilerBase);
43 |
44 | readonly appRoot: string;
45 | readonly cachesForCompilers: Map;
46 |
47 | compile(filePath: string): {
48 | hashinfo: {},
49 | code: string,
50 | binaryData: Buffer;
51 | mimeType: string;
52 | dependentFiles: string[];
53 | }
54 |
55 | /**
56 | * Pre-caches an entire directory of files recursively. Usually used for building custom compiler tooling.
57 | */
58 | compileAll(
59 | filePath: string,
60 | shouldCompile: (path: string) => boolean): PromiseLike;
61 |
62 | /**
63 | * Pre-caches an entire directory of files recursively. Usually used for building custom compiler tooling.
64 | */
65 | compileAllSync(
66 | filePath: string,
67 | shouldCompile: (path: string) => boolean): void;
68 |
69 | saveConfiguration(): PromiseLike;
70 |
71 | saveConfigurationSync(): void;
72 | }
73 |
74 | export declare function enableLiveReload(options?: {
75 | strategy?: "react-hmr" | "naive";
76 | }): void;
77 |
78 | export declare function calculateDefaultCompileCacheDirectory(): string;
79 |
80 | export declare function createCompilerHostFromBabelRc(file: string, rootCacheDir?: string): PromiseLike;
81 |
82 | export declare function createCompilerHostFromBabelRcSync(file: string, rootCacheDir?: string): CompilerHost;
83 |
84 | export declare function createCompilerHostFromConfigFile
85 | (file: string, rootCacheDir?: string): PromiseLike;
86 |
87 | export declare function createCompilerHostFromConfigFileSync
88 | (file: string, rootCacheDir?: string): CompilerHost;
89 |
90 | export declare function createCompilerHostFromProjectRoot
91 | (rootDir: string, rootCacheDir?: string): PromiseLike;
92 |
93 | export declare function createCompilerHostFromProjectRootSync
94 | (rootDir: string, rootCacheDir?: string): CompilerHost;
95 |
96 | export declare function createCompilers(): CompilersByMimeType;
97 |
98 | // documentation unclear at this time...
99 | export declare function forAllFilesSync(rootDirectory: string, func: any, ... args: any[]): void;
100 |
101 | export declare function getDefaultConfiguration(): object;
102 |
103 | export declare function init(appRoot: string, mainModule: string, productionMode?: boolean): void;
104 |
105 | export declare function initializeGlobalHooks(compilerHost: CompilerHost): void;
106 |
107 | export declare function initializeProtocolHook(compilerHost: CompilerHost): void;
108 |
109 | export declare function registerRequireExtension(compilerHost: CompilerHost): void;
110 |
111 | export interface CompilerBase {
112 |
113 | }
114 |
115 | export interface CompilersByMimeType {
116 | [mimeType: string]: CompilerBase;
117 | }
118 |
119 | export declare class FileChangedCache {
120 |
121 | static loadFromData(
122 | data: Object,
123 | appRoot: string,
124 | failOnCacheMiss: boolean): FileChangedCache;
125 |
126 | static loadFromFile(
127 | file: string,
128 | appRoot: string,
129 | failOnCacheMiss: boolean): FileChangedCache;
130 |
131 | constructor(appRoot: string, failOnCacheMiss?: boolean);
132 | }
133 |
--------------------------------------------------------------------------------