diff --git a/dev/Common/Base64.jsx b/dev/Common/Base64.ts similarity index 89% rename from dev/Common/Base64.jsx rename to dev/Common/Base64.ts index b669f67ed..f2be4ea2d 100644 --- a/dev/Common/Base64.jsx +++ b/dev/Common/Base64.ts @@ -2,18 +2,16 @@ // Base64 encode / decode // http://www.webtoolkit.info/ -const BASE_64_CHR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +const BASE_64_CHR: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; -/* jslint bitwise: true */ -/* eslint-disable */ const Base64 = { // public method for urlsafe encoding - urlsafe_encode: (input) => Base64.encode(input) + urlsafe_encode: (input: string): string => Base64.encode(input) .replace(/[+]/g, '-').replace(/[\/]/g, '_').replace(/[=]/g, '.'), // public method for encoding - encode: (input) => { + encode: (input: string): string => { let output = '', @@ -52,7 +50,7 @@ const Base64 = { }, // public method for decoding - decode: (input) => { + decode: (input: string): string => { let output = '', @@ -90,7 +88,7 @@ const Base64 = { }, // private method for UTF-8 encoding - _utf8_encode: (string) => { + _utf8_encode: (string: string): string => { string = string.replace(/\r\n/g, "\n"); @@ -126,7 +124,7 @@ const Base64 = { }, // private method for UTF-8 decoding - _utf8_decode: (utftext) => { + _utf8_decode: (utftext: string): string => { let string = '', @@ -163,8 +161,6 @@ const Base64 = { return string; } }; -/* jslint bitwise: false */ -/* eslint-enable */ export const decode = Base64.decode; export const encode = Base64.encode; diff --git a/dev/Common/Consts.jsx b/dev/Common/Consts.jsx deleted file mode 100644 index 7b150b60d..000000000 --- a/dev/Common/Consts.jsx +++ /dev/null @@ -1,44 +0,0 @@ - -/* eslint max-len: 0 */ - -export const MESSAGES_PER_PAGE = 20; - -export const MESSAGES_PER_PAGE_VALUES = [10, 20, 30, 50, 100]; - -export const CONTACTS_PER_PAGE = 50; - -export const DEFAULT_AJAX_TIMEOUT = 30000; - -export const SEARCH_AJAX_TIMEOUT = 300000; - -export const SEND_MESSAGE_AJAX_TIMEOUT = 300000; - -export const SAVE_MESSAGE_AJAX_TIMEOUT = 200000; - -export const CONTACTS_SYNC_AJAX_TIMEOUT = 200000; - -export const UNUSED_OPTION_VALUE = '__UNUSE__'; - -export const CLIENT_SIDE_STORAGE_INDEX_NAME = 'rlcsc'; - -export const IMAP_DEFAULT_PORT = 143; - -export const IMAP_DEFAULT_SECURE_PORT = 993; - -export const SMTP_DEFAULT_PORT = 25; - -export const SMTP_DEFAULT_SECURE_PORT = 465; - -export const SIEVE_DEFAULT_PORT = 4190; - -export const MESSAGE_BODY_CACHE_LIMIT = 15; - -export const AJAX_ERROR_LIMIT = 7; - -export const TOKEN_ERROR_LIMIT = 10; - -export const RAINLOOP_TRIAL_KEY = 'RAINLOOP-TRIAL-KEY'; - -export const DATA_IMAGE_USER_DOT_PIC = 'data:image/png;base64,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'; - -export const DATA_IMAGE_TRANSP_PIC = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII='; diff --git a/dev/Common/Consts.ts b/dev/Common/Consts.ts new file mode 100644 index 000000000..cd1258cec --- /dev/null +++ b/dev/Common/Consts.ts @@ -0,0 +1,42 @@ + +export const MESSAGES_PER_PAGE: number = 20; + +export const MESSAGES_PER_PAGE_VALUES: number[] = [10, 20, 30, 50, 100]; + +export const CONTACTS_PER_PAGE: number = 50; + +export const DEFAULT_AJAX_TIMEOUT: number = 30000; + +export const SEARCH_AJAX_TIMEOUT: number = 300000; + +export const SEND_MESSAGE_AJAX_TIMEOUT: number = 300000; + +export const SAVE_MESSAGE_AJAX_TIMEOUT: number = 200000; + +export const CONTACTS_SYNC_AJAX_TIMEOUT: number = 200000; + +export const UNUSED_OPTION_VALUE: string = '__UNUSE__'; + +export const CLIENT_SIDE_STORAGE_INDEX_NAME: string = 'rlcsc'; + +export const IMAP_DEFAULT_PORT: number = 143; + +export const IMAP_DEFAULT_SECURE_PORT: number = 993; + +export const SMTP_DEFAULT_PORT: number = 25; + +export const SMTP_DEFAULT_SECURE_PORT: number = 465; + +export const SIEVE_DEFAULT_PORT: number = 4190; + +export const MESSAGE_BODY_CACHE_LIMIT: number = 15; + +export const AJAX_ERROR_LIMIT: number = 7; + +export const TOKEN_ERROR_LIMIT: number = 10; + +export const RAINLOOP_TRIAL_KEY: string = 'RAINLOOP-TRIAL-KEY'; + +export const DATA_IMAGE_USER_DOT_PIC: string = 'data:image/png;base64,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'; + +export const DATA_IMAGE_TRANSP_PIC: string = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII='; diff --git a/dev/Common/Enums.jsx b/dev/Common/Enums.ts similarity index 99% rename from dev/Common/Enums.jsx rename to dev/Common/Enums.ts index 2cc74877f..d6431fe64 100644 --- a/dev/Common/Enums.jsx +++ b/dev/Common/Enums.ts @@ -1,6 +1,4 @@ -/* eslint quote-props: 0 */ - /** * @enum {string} */ diff --git a/dev/Common/Mime.jsx b/dev/Common/Mime.ts similarity index 98% rename from dev/Common/Mime.jsx rename to dev/Common/Mime.ts index a0f3aae78..a2578e569 100644 --- a/dev/Common/Mime.jsx +++ b/dev/Common/Mime.ts @@ -1,8 +1,5 @@ -/* eslint key-spacing: 0 */ -/* eslint quote-props: 0 */ - -const Mime = { +const Mime: { [id: string]: string } = { 'eml' : 'message/rfc822', 'mime' : 'message/rfc822', 'txt' : 'text/plain', diff --git a/dev/Common/Spec.ts b/dev/Common/Spec.ts new file mode 100644 index 000000000..452955df1 --- /dev/null +++ b/dev/Common/Spec.ts @@ -0,0 +1,202 @@ + +import { Mime } from './Mime'; +import { EventKeyCode } from './Enums'; + +interface IPage { + current: boolean, + name: string, + custom: boolean, + title: string, + value: string +}; + +export function computedPagenatorHelper(koCurrentPage: () => number, koPageCount: () => number) +{ + return (): IPage[] => { + + const + currentPage: number = koCurrentPage(), + pageCount: number = koPageCount(), + result: IPage[] = [], + fAdd = (index: number, push: boolean = true, customName: string = ''): void => { + + const data: IPage = { + current: index === currentPage, + name: '' === customName ? index.toString() : customName.toString(), + custom: '' === customName ? false : true, + title: '' === customName ? '' : index.toString(), + value: index.toString() + }; + + if (push) + { + result.push(data); + } + else + { + result.unshift(data); + } + } + ; + + let + prev: number = 0, + next: number = 0, + limit: number = 2 + ; + + if (1 < pageCount || (0 < pageCount && pageCount < currentPage)) + { + if (pageCount < currentPage) + { + fAdd(pageCount); + prev = pageCount; + next = pageCount; + } + else + { + if (3 >= currentPage || pageCount - 2 <= currentPage) + { + limit += 2; + } + + fAdd(currentPage); + prev = currentPage; + next = currentPage; + } + + while (0 < limit) { + + prev -= 1; + next += 1; + + if (0 < prev) + { + fAdd(prev, false); + limit--; + } + + if (pageCount >= next) + { + fAdd(next, true); + limit--; + } + else if (0 >= prev) + { + break; + } + } + + if (3 === prev) + { + fAdd(2, false); + } + else if (3 < prev) + { + fAdd(Math.round((prev - 1) / 2), false, '...'); + } + + if (pageCount - 2 === next) + { + fAdd(pageCount - 1, true); + } + else if (pageCount - 2 > next) + { + fAdd(Math.round((pageCount + next) / 2), true, '...'); + } + + // first and last + if (1 < prev) + { + fAdd(1, false); + } + + if (pageCount > next) + { + fAdd(pageCount, true); + } + } + + return result; + }; +} + +/** + * @param {string} fileName + * @return {string} + */ +export function getFileExtension(fileName: string): string +{ + fileName = fileName.trim().toLowerCase(); + + const result = fileName.split('.').pop(); + return result === fileName ? '' : result; +} + +/** + * @param {string} fileName + * @return {string} + */ +export function mimeContentType(fileName: string): string +{ + let + ext = '', + result = 'application/octet-stream' + ; + + fileName = fileName.trim().toLowerCase(); + + if ('winmail.dat' === fileName) + { + return 'application/ms-tnef'; + } + + ext = getFileExtension(fileName); + if (ext && 0 < ext.length && undefined !== Mime[ext]) + { + result = Mime[ext]; + } + + return result; +} + +/** + * @param {string} url + * @param {number} value + * @param {Function} fCallback + */ +export function resizeAndCrop(url: string, value: number, fCallback: (data: string) => void) +{ + const img = new Image(); + img.onload = function() { + + let + diff: number[] = [0, 0] + ; + + const + canvas: HTMLCanvasElement = window.document.createElement('canvas'), + ctx: CanvasRenderingContext2D = canvas.getContext('2d') + ; + + canvas.width = value; + canvas.height = value; + + if (this.width > this.height) + { + diff = [this.width - this.height, 0]; + } + else + { + diff = [0, this.height - this.width]; + } + + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, value, value); + ctx.drawImage(this, diff[0] / 2, diff[1] / 2, this.width - diff[0], this.height - diff[1], 0, 0, value, value); + + fCallback(canvas.toDataURL('image/jpeg')); + }; + + img.src = url; +} diff --git a/dev/Common/Utils.jsx b/dev/Common/Utils.jsx index db96c775c..4e4aef61a 100644 --- a/dev/Common/Utils.jsx +++ b/dev/Common/Utils.jsx @@ -5,7 +5,6 @@ import _ from '_'; import ko from 'ko'; import {$win, $div, dropdownVisibility, data as GlobalsData} from 'Common/Globals'; import {ComposeType, EventKeyCode, SaveSettingsStep, FolderType} from 'Common/Enums'; -import {Mime} from 'Common/Mime'; import JSEncrypt from 'JSEncrypt'; import Autolinker from 'Autolinker'; @@ -1040,45 +1039,6 @@ export function plainToHtml(plain, findEmailAndLinksInText = false) window.rainloop_Utils_htmlToPlain = htmlToPlain; window.rainloop_Utils_plainToHtml = plainToHtml; - -/** - * @param {string} url - * @param {number} value - * @param {Function} fCallback - */ -export function resizeAndCrop(url, value, fCallback) -{ - const img = new window.Image(); - img.onload = function() { - - let - diff = [0, 0], - canvas = window.document.createElement('canvas'), - ctx = canvas.getContext('2d') - ; - - canvas.width = value; - canvas.height = value; - - if (this.width > this.height) - { - diff = [this.width - this.height, 0]; - } - else - { - diff = [0, this.height - this.width]; - } - - ctx.fillStyle = '#fff'; - ctx.fillRect(0, 0, value, value); - ctx.drawImage(this, diff[0] / 2, diff[1] / 2, this.width - diff[0], this.height - diff[1], 0, 0, value, value); - - fCallback(canvas.toDataURL('image/jpeg')); - }; - - img.src = url; -} - /** * @param {Array} aSystem * @param {Array} aList @@ -1210,121 +1170,6 @@ export function folderListOptionsBuilder(aSystem, aList, aDisabled, aHeaderLines return aResult; } -export function computedPagenatorHelper(koCurrentPage, koPageCount) -{ - return () => { - - let - iPrev = 0, - iNext = 0, - iLimit = 2, - result = [], - iCurrentPage = koCurrentPage(), - iPageCount = koPageCount(), - - /** - * @param {number} index - * @param {boolean=} push = true - * @param {string=} customName = '' - */ - fAdd = (index, push = true, customName = '') => { - - const data = { - current: index === iCurrentPage, - name: isUnd(customName) || '' === customName ? index.toString() : customName.toString(), - custom: isUnd(customName) || '' === customName ? false : true, - title: isUnd(customName) || '' === customName ? '' : index.toString(), - value: index.toString() - }; - - if (push) - { - result.push(data); - } - else - { - result.unshift(data); - } - } - ; - - if (1 < iPageCount || (0 < iPageCount && iPageCount < iCurrentPage)) -// if (0 < iPageCount && 0 < iCurrentPage) - { - if (iPageCount < iCurrentPage) - { - fAdd(iPageCount); - iPrev = iPageCount; - iNext = iPageCount; - } - else - { - if (3 >= iCurrentPage || iPageCount - 2 <= iCurrentPage) - { - iLimit += 2; - } - - fAdd(iCurrentPage); - iPrev = iCurrentPage; - iNext = iCurrentPage; - } - - while (0 < iLimit) { - - iPrev -= 1; - iNext += 1; - - if (0 < iPrev) - { - fAdd(iPrev, false); - iLimit--; - } - - if (iPageCount >= iNext) - { - fAdd(iNext, true); - iLimit--; - } - else if (0 >= iPrev) - { - break; - } - } - - if (3 === iPrev) - { - fAdd(2, false); - } - else if (3 < iPrev) - { - fAdd(window.Math.round((iPrev - 1) / 2), false, '...'); - } - - if (iPageCount - 2 === iNext) - { - fAdd(iPageCount - 1, true); - } - else if (iPageCount - 2 > iNext) - { - fAdd(window.Math.round((iPageCount + iNext) / 2), true, '...'); - } - - // first and last - if (1 < iPrev) - { - fAdd(1, false); - } - - if (iPageCount > iNext) - { - fAdd(iPageCount, true); - } - } - - return result; - }; -} - export function selectElement(element) { let sel, range; @@ -1369,18 +1214,6 @@ export function triggerAutocompleteInputChange(delay = false) { } } -/** - * @param {string} fileName - * @return {string} - */ -export function getFileExtension(fileName) -{ - fileName = trim(fileName).toLowerCase(); - - const result = fileName.split('.').pop(); - return (result === fileName) ? '' : result; -} - let configurationScriptTagCache = {}; /** @@ -1403,33 +1236,6 @@ export function getConfigurationFromScriptTag(configuration) return result; } -/** - * @param {string} fileName - * @return {string} - */ -export function mimeContentType(fileName) -{ - let - ext = '', - result = 'application/octet-stream' - ; - - fileName = trim(fileName).toLowerCase(); - - if ('winmail.dat' === fileName) - { - return 'application/ms-tnef'; - } - - ext = getFileExtension(fileName); - if (ext && 0 < ext.length && !isUnd(Mime[ext])) - { - result = Mime[ext]; - } - - return result; -} - /** * @param {mixed} mPropOrValue * @param {mixed} value @@ -1575,9 +1381,9 @@ if ('ab'.substr(-1) !== 'b') start = start < 0 ? str.length + start : start; return str.substr(start, length); }; -} -export {substr}; + window.String.substr = substr; +} /** * @param {string} mailToUrl diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index 05d6b96f8..d2801fc9f 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -11,6 +11,7 @@ Enums = require('Common/Enums'), Globals = require('Common/Globals'), Utils = require('Common/Utils'), + Spec = require('Common/Spec'), Links = require('Common/Links'), Audio = require('Common/Audio'), @@ -102,7 +103,7 @@ this.friendlySize = Utils.friendlySize(this.estimatedSize); this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, ''); - this.fileNameExt = Utils.getFileExtension(this.fileName); + this.fileNameExt = Spec.getFileExtension(this.fileName); this.fileType = AttachmentModel.staticFileType(this.fileNameExt, this.mimeType); bResult = true; @@ -488,7 +489,7 @@ aTypes = _.uniq(_.compact(_.map(aData, function (aItem) { return aItem ? AttachmentModel.staticFileType( - Utils.getFileExtension(aItem[0]), aItem[1]) : ''; + Spec.getFileExtension(aItem[0]), aItem[1]) : ''; }))); if (aTypes && 1 === aTypes.length && aTypes[0]) diff --git a/dev/Model/ComposeAttachment.js b/dev/Model/ComposeAttachment.js index 3507db7e9..800b6d211 100644 --- a/dev/Model/ComposeAttachment.js +++ b/dev/Model/ComposeAttachment.js @@ -8,6 +8,7 @@ ko = require('ko'), Utils = require('Common/Utils'), + Spec = require('Common/Spec'), AttachmentModel = require('Model/Attachment'), @@ -67,11 +68,11 @@ }, this); this.mimeType = ko.computed(function () { - return Utils.mimeContentType(this.fileName()); + return Spec.mimeContentType(this.fileName()); }, this); this.fileExt = ko.computed(function () { - return Utils.getFileExtension(this.fileName()); + return Spec.getFileExtension(this.fileName()); }, this); this.regDisposables([this.progressText, this.progressStyle, this.title, this.friendlySize, this.mimeType, this.fileExt]); diff --git a/dev/View/Popup/AdvancedSearch.js b/dev/View/Popup/AdvancedSearch.js index fff3dd514..1121d13d5 100644 --- a/dev/View/Popup/AdvancedSearch.js +++ b/dev/View/Popup/AdvancedSearch.js @@ -81,6 +81,7 @@ break; case 'is:unseen,flagged': self.starred(true); + /* falls through */ case 'is:unseen': self.unseen(true); break; diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index 35968ec02..714aa196b 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -14,6 +14,7 @@ Consts = require('Common/Consts'), Globals = require('Common/Globals'), Utils = require('Common/Utils'), + Spec = require('Common/Spec'), Selector = require('Common/Selector'), Links = require('Common/Links'), Translator = require('Common/Translator'), @@ -72,7 +73,7 @@ return 0 >= iPage ? 1 : iPage; }, this); - this.contactsPagenator = ko.computed(Utils.computedPagenatorHelper(this.contactsPage, this.contactsPageCount)); + this.contactsPagenator = ko.computed(Spec.computedPagenatorHelper(this.contactsPage, this.contactsPageCount)); this.emptySelection = ko.observable(true); this.viewClearSearch = ko.observable(false); diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index be42a9276..19b8eea2e 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -16,6 +16,7 @@ Consts = require('Common/Consts'), Globals = require('Common/Globals'), Utils = require('Common/Utils'), + Spec = require('Common/Spec'), Links = require('Common/Links'), Events = require('Common/Events'), Selector = require('Common/Selector'), @@ -116,7 +117,7 @@ return '' === sValue ? '' : Translator.i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', {'SEARCH': sValue}); }); - this.messageListPagenator = ko.computed(Utils.computedPagenatorHelper( + this.messageListPagenator = ko.computed(Spec.computedPagenatorHelper( MessageStore.messageListPage, MessageStore.messageListPageCount)); this.checkAll = ko.computed({ diff --git a/gulpfile.js b/gulpfile.js index 4f7491d75..bcbd104d8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -97,9 +97,10 @@ function copyFile(sFile, sNewFile, callback) callback(); } -cfg.paths.globjs = 'dev/**/*.{js,jsx,html,css}'; +cfg.paths.globjs = 'dev/**/*.{js,jsx,ts,html,css}'; cfg.paths.globjsonly = 'dev/**/*.js'; cfg.paths.globjsxonly = 'dev/**/*.jsx'; +cfg.paths.globtsonly = 'dev/**/*.ts'; cfg.paths.static = 'rainloop/v/' + cfg.devVersion + '/static/'; cfg.paths.staticJS = 'rainloop/v/' + cfg.devVersion + '/static/js/'; cfg.paths.staticMinJS = 'rainloop/v/' + cfg.devVersion + '/static/js/min/'; @@ -316,12 +317,7 @@ gulp.task('js:ckeditor:beautify', function() { .pipe(gulp.dest(cfg.paths.static + 'ckeditor/')); }); -gulp.task('js:webpack:clear', function() { - return gulp.src([cfg.paths.staticJS + '*.subapp.js', cfg.paths.staticMinJS + '*.subapp.js'], {read: false}) - .pipe(require('gulp-rimraf')()); -}); - -gulp.task('js:webpack', [/*'js:webpack:clear'*/], function(callback) { +gulp.task('js:webpack', [], function(callback) { var webpack = require('webpack'), @@ -409,16 +405,8 @@ gulp.task('js:admin', ['js:webpack'], function() { .on('error', gutil.log); }); -gulp.task('js:chunks', ['js:webpack'], function() { - return gulp.src(cfg.paths.staticJS + '*.subapp.js') - .pipe(header(getHead() + '\n')) - .pipe(eol('\n', true)) - .pipe(gulp.dest(cfg.paths.staticJS)) - .on('error', gutil.log); -}); - // - min -gulp.task('js:min', ['js:app', 'js:admin', 'js:chunks', 'js:validate'], function() { +gulp.task('js:min', ['js:app', 'js:admin', 'js:validate'], function() { return gulp.src(cfg.paths.staticJS + '*.js') .pipe(replace(/"rainloop\/v\/([^\/]+)\/static\/js\/"/g, '"rainloop/v/$1/static/js/min/"')) .pipe(uglify(cfg.uglify)) @@ -450,7 +438,17 @@ gulp.task('js:eslint', function() { .pipe(eslint.failAfterError()); }); -gulp.task('js:validate', ['js:lint', 'js:eslint']); +gulp.task('js:tslint', function() { + + var tslint = require('gulp-tslint'); // todo + + return gulp.src(cfg.paths.globtsonly) + .pipe(tslint()) + .pipe(tslint.format()) + .pipe(tslint.failAfterError()); +}); + +gulp.task('js:validate', ['js:lint', 'js:eslint'/*, 'js:tslint'*/]); // OTHER regOtherMinTask('other:cookie', 'vendors/jquery-cookie/', 'jquery.cookie.js', 'jquery.cookie-1.4.0.min.js', @@ -667,7 +665,7 @@ gulp.task('rainloop:owncloud:shortname', ['rainloop:owncloud:md5'], function(cal gulp.task('js:pgp', ['js:openpgp', 'js:openpgpworker']); gulp.task('default', ['js:libs', 'js:pgp', 'js:min', 'css:main:min', 'ckeditor', 'fontastic']); -gulp.task('fast-', ['js:app', 'js:admin', 'js:chunks', 'css:main']); +gulp.task('fast-', ['js:app', 'js:admin', 'css:main']); gulp.task('fast', ['package:community-on', 'fast-']); gulp.task('fast+', ['package:community-off', 'fast-']); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1590ec052..1acc220a6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1414,7 +1414,8 @@ }, "extend": { "version": "3.0.0", - "from": "extend@>=3.0.0 <4.0.0" + "from": "extend@3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" }, "extglob": { "version": "0.3.2", @@ -2496,7 +2497,8 @@ "dependencies": { "esprima": { "version": "2.7.2", - "from": "esprima@>=2.6.0 <3.0.0" + "from": "esprima@2.7.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz" } } }, @@ -3078,6 +3080,11 @@ "from": "modify-babel-preset@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/modify-babel-preset/-/modify-babel-preset-1.2.0.tgz" }, + "moment": { + "version": "2.13.0", + "from": "moment@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.13.0.tgz" + }, "ms": { "version": "0.7.1", "from": "ms@0.7.1", @@ -3305,6 +3312,11 @@ "from": "pify@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" }, + "pikaday": { + "version": "1.4.0", + "from": "pikaday@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.4.0.tgz" + }, "pinkie": { "version": "2.0.4", "from": "pinkie@>=2.0.0 <3.0.0", @@ -3431,7 +3443,8 @@ }, "raw-loader": { "version": "0.5.1", - "from": "raw-loader@>=0.5.1 <0.6.0" + "from": "raw-loader@0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz" }, "rcfinder": { "version": "0.1.9", @@ -3949,6 +3962,38 @@ "from": "tryor@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz" }, + "ts-loader": { + "version": "0.8.2", + "from": "ts-loader@>=0.8.2 <0.9.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-0.8.2.tgz", + "dependencies": { + "enhanced-resolve": { + "version": "0.9.1", + "from": "enhanced-resolve@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz" + }, + "memory-fs": { + "version": "0.2.0", + "from": "memory-fs@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz" + }, + "object-assign": { + "version": "2.1.1", + "from": "object-assign@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz" + }, + "semver": { + "version": "5.1.1", + "from": "semver@>=5.0.1 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.1.tgz" + }, + "tapable": { + "version": "0.1.10", + "from": "tapable@>=0.1.8 <0.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz" + } + } + }, "tty-browserify": { "version": "0.0.0", "from": "tty-browserify@0.0.0", @@ -3981,6 +4026,11 @@ "from": "typedarray@>=0.0.5 <0.1.0", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, + "typescript": { + "version": "1.8.10", + "from": "typescript@>=1.8.10 <2.0.0", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz" + }, "uglify-js": { "version": "2.6.4", "from": "uglify-js@>=2.6.0 <3.0.0", diff --git a/package.json b/package.json index 92fcc30d4..af2324d0a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "RainLoop", "title": "RainLoop Webmail", "version": "1.10.2", - "release": "133", + "release": "135", "private": true, "ownCloudPackageVersion": "4.19", "description": "Simple, modern & fast web-based email client", @@ -89,6 +89,8 @@ "pikaday": "^1.4.0", "raw-loader": "^0.5.1", "rimraf": "*", + "ts-loader": "^0.8.2", + "typescript": "^1.8.10", "webpack": "2.1.0-beta.13" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..05322d5ee --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs", + "allowSyntheticDefaultImports": true + }, + "exclude": [ + "node_modules", + "vendors" + ] +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index c19ae914e..fac339e3c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -18,8 +18,7 @@ module.exports = { pathinfo: true, path: __dirname + '/rainloop/v/0.0.0/static/js/', filename: '[name].js', - publicPath: 'rainloop/v/0.0.0/static/js/', - chunkFilename: '[chunkhash].subapp.js' + publicPath: 'rainloop/v/0.0.0/static/js/' }, // devtool: "#source-map", plugins: [ @@ -28,7 +27,7 @@ module.exports = { ], resolve: { modules: [path.resolve(__dirname, 'dev'), 'node_modules'], - extensions: ['', '.js', '.jsx'], + extensions: ['', '.js', '.jsx', '.ts'], alias: { 'Opentip': __dirname + '/dev/External/Opentip.js', 'ko': __dirname + '/dev/External/ko.js' @@ -41,13 +40,18 @@ module.exports = { loader: 'raw' }, { - test: /\.(json)$/, + test: /\.json$/, loader: 'json' }, + { + test: /\.tsx?$/, + loader: 'babel-loader?' + JSON.stringify(jsLoaderQuery) + '!ts-loader', + exclude: /(node_modules|bower_components|vendors)/ + }, { test: /\.jsx$/, loader: 'babel', - exclude: /(node_modules|bower_components)/, + exclude: /(node_modules|bower_components|vendors)/, query: jsLoaderQuery } ]