diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000..def46d0 --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,19 @@ +module.exports = function(api) { + return { + presets: [ + [ + "@babel/preset-env", + { + targets: { + chrome: 59, + edge: 13, + firefox: 50, + ie: 11 + }, + // for uglifyjs... + forceAllTransforms: api.env("production"), + }, + ], + ], + }; +}; diff --git a/.gitignore b/.gitignore index 35a04f3..519d3c5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /lib mergely-*.tgz package-lock.json +*.log diff --git a/CHANGES.md b/CHANGES.md index f5069e5..3e7f5e5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # Changes +## 4.0.8 +* chore: updated webpack + ## 4.0.7 * chore: updated documentation diff --git a/examples/app.html b/examples/app.html new file mode 100644 index 0000000..053c404 --- /dev/null +++ b/examples/app.html @@ -0,0 +1,21 @@ + + + + + Mergely - Simple Example + + + + + + + +
+
+
+
+
+ + diff --git a/examples/app.js b/examples/app.js new file mode 100644 index 0000000..0437acc --- /dev/null +++ b/examples/app.js @@ -0,0 +1,18 @@ +require('codemirror/lib/codemirror.css'); +require('../src/mergely.css'); + +$(document).ready(function () { + $('#mergely').mergely({ + license: 'lgpl', + cmsettings: { + readOnly: false + }, + _debug: '', + lhs: function(setValue) { + setValue('the quick red fox\njumped over the hairy dog'); + }, + rhs: function(setValue) { + setValue('the quick brown fox\njumped over the lazy dog'); + } + }); +}); diff --git a/karma.conf.js b/karma.conf.js index 947d6ce..c820dbf 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,5 @@ const path = require('path'); -const webpackCfg = require('./webpack.config'); -const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = function(config) { config.set({ @@ -40,9 +39,11 @@ module.exports = function(config) { webpack: { entry: './src/mergely.js', module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader') } - ] + rules: [{ + test: /\.(js)$/, + exclude: /node_modules/, + use: ['babel-loader'] + }] }, resolve: { extensions: ['.js'], @@ -52,7 +53,11 @@ module.exports = function(config) { } }, plugins: [ - new ExtractTextPlugin('mergely.css') + new CopyWebpackPlugin([{ + from: 'src/mergely.css', + to: 'mergely.css', + toType: 'file' + }]) ] }, webpackServer: { diff --git a/package.json b/package.json old mode 100755 new mode 100644 index 6533602..d005e77 --- a/package.json +++ b/package.json @@ -1,17 +1,12 @@ { "name": "mergely", - "version": "4.0.7", + "version": "4.0.8", "description": "A javascript UI for diff/merge", "directories": { "doc": "doc", "example": "examples", "test": "test" }, - "scripts": { - "build": "rm -rf lib && webpack", - "test": "karma start", - "test:chrome": "karma start --browsers Chrome --singleRun=false" - }, "repository": { "type": "git", "url": "git+https://github.com/wickedest/Mergely.git" @@ -20,7 +15,8 @@ "files": [ "lib", "examples", - "README.md" + "README.md", + "LICENSE" ], "keywords": [ "merge", @@ -38,14 +34,20 @@ }, "homepage": "https://github.com/wickedest/Mergely#readme", "devDependencies": { + "@babel/core": "^7.1.6", + "@babel/preset-env": "^7.1.6", + "@webpack-cli/init": "^0.1.2", + "babel-loader": "^8.0.4", + "babel-plugin-syntax-dynamic-import": "^6.18.0", "chai": "^4.1.2", "codemirror": "^5.32.0", - "css-loader": "^0.28.7", - "extract-text-webpack-plugin": "^3.0.2", + "copy-webpack-plugin": "^4.6.0", + "css-loader": "^0.28.11", "file-loader": "^1.1.5", + "html-webpack-plugin": "^3.2.0", "image-webpack-loader": "^3.4.2", "jquery": "^3.2.1", - "karma": "^2.0.0", + "karma": "^3.1.1", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^2.2.0", "karma-coverage-istanbul-reporter": "^1.3.0", @@ -53,6 +55,16 @@ "karma-mocha-reporter": "^2.2.5", "karma-webpack": "^2.0.9", "mocha": "^4.0.1", - "webpack": "^3.8.1" + "style-loader": "^0.23.0", + "uglifyjs-webpack-plugin": "^2.0.1", + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2", + "webpack-dev-server": "^3.1.9" + }, + "scripts": { + "build": "rm -rf lib && webpack --config ./webpack.prod.js", + "start": "webpack-dev-server -w --debug --progress --colors --config ./webpack.dev.js --content-base ./dist --inline --hot --host 0.0.0.0", + "test": "karma start", + "test:chrome": "karma start --browsers Chrome --singleRun=false" } } diff --git a/src/Timer.js b/src/Timer.js new file mode 100644 index 0000000..ea7dbd3 --- /dev/null +++ b/src/Timer.js @@ -0,0 +1,16 @@ +class Timer { + static start() { + Timer.t0 = Date.now(); + } + + static stop() { + var t1 = Date.now(); + var td = t1 - Timer.t0; + Timer.t0 = t1; + return td; + } +} + +Timer.t0 = 0; + +exports = module.exports = Timer; diff --git a/src/mergely.js b/src/mergely.js index bb9d00f..bf7d7b8 100644 --- a/src/mergely.js +++ b/src/mergely.js @@ -1,25 +1,13 @@ "use strict"; -require('./mergely.css'); - (function(jQuery, CodeMirror) { var Mgly = {}; -Mgly.Timer = function(){ - var self = this; - self.start = function() { self.t0 = new Date().getTime(); }; - self.stop = function() { - var t1 = new Date().getTime(); - var d = t1 - self.t0; - self.t0 = t1; - return d; - }; - self.start(); -}; - Mgly.ChangeExpression = new RegExp(/(^(?![><\-])*\d+(?:,\d+)?)([acd])(\d+(?:,\d+)?)/); +const Timer = require('./Timer'); + Mgly.DiffParser = function(diff) { var changes = []; var change_id = 0; @@ -751,7 +739,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { }).append('

mergelyThis software is a Combined Work using Mergely and is covered by the ' + lic + ' license. For the full license, see http://www.mergely.com/license.

'); jQuery('body').one('click', function () { jQuery('#mergely-splash').fadeOut(100, 'linear', function () { - this.remove(); + jQuery('#mergely-splash').remove(); }); }); } @@ -950,13 +938,13 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { else this.trace('scroll', 'not scrolling other side'); if (this.settings.autoupdate) { - var timer = new Mgly.Timer(); + Timer.start(); this._calculate_offsets(editor_name1, editor_name2, this.changes); - this.trace('change', 'offsets time', timer.stop()); + this.trace('change', 'offsets time', Timer.stop()); this._markup_changes(editor_name1, editor_name2, this.changes); - this.trace('change', 'markup time', timer.stop()); + this.trace('change', 'markup time', Timer.stop()); this._draw_diff(editor_name1, editor_name2, this.changes); - this.trace('change', 'draw time', timer.stop()); + this.trace('change', 'draw time', Timer.stop()); } this.trace('scroll', 'scrolled'); } @@ -966,9 +954,9 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { var self = this; if (this.changed_timeout != null) clearTimeout(this.changed_timeout); this.changed_timeout = setTimeout(function(){ - var timer = new Mgly.Timer(); + Timer.start(); self._changed(editor_name1, editor_name2); - self.trace('change', 'total time', timer.stop()); + self.trace('change', 'total time', Timer.stop()); }, this.settings.change_timeout); }, _changed: function(editor_name1, editor_name2) { @@ -979,7 +967,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { var self = this, name, editor, fns, timer, i, change, l; var clear_changes = function() { - timer = new Mgly.Timer(); + Timer.start(); for (i = 0, l = editor.lineCount(); i < l; ++i) { editor.removeLineClass(i, 'background'); } @@ -993,7 +981,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { change.clear(); } editor.clearGutter('merge'); - self.trace('change', 'clear time', timer.stop()); + self.trace('change', 'clear time', Timer.stop()); }; for (name in this.editor) { @@ -1029,23 +1017,23 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { _diff: function(editor_name1, editor_name2) { var lhs = this.editor[editor_name1].getValue(); var rhs = this.editor[editor_name2].getValue(); - var timer = new Mgly.Timer(); + Timer.start(); var d = new Mgly.diff(lhs, rhs, this.settings); - this.trace('change', 'diff time', timer.stop()); + this.trace('change', 'diff time', Timer.stop()); this.changes = Mgly.DiffParser(d.normal_form()); - this.trace('change', 'parse time', timer.stop()); + this.trace('change', 'parse time', Timer.stop()); if (this._current_diff === undefined && this.changes.length) { // go to first difference on start-up this._current_diff = 0; this._scroll_to_change(this.changes[0]); } - this.trace('change', 'scroll_to_change time', timer.stop()); + this.trace('change', 'scroll_to_change time', Timer.stop()); this._calculate_offsets(editor_name1, editor_name2, this.changes); - this.trace('change', 'offsets time', timer.stop()); + this.trace('change', 'offsets time', Timer.stop()); this._markup_changes(editor_name1, editor_name2, this.changes); - this.trace('change', 'markup time', timer.stop()); + this.trace('change', 'markup time', Timer.stop()); this._draw_diff(editor_name1, editor_name2, this.changes); - this.trace('change', 'draw time', timer.stop()); + this.trace('change', 'draw time', Timer.stop()); }, _parse_diff: function (editor_name1, editor_name2, diff) { this.trace('diff', 'diff results:\n', diff); @@ -1235,7 +1223,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { var lhsvp = this._get_viewport_side(editor_name1); var rhsvp = this._get_viewport_side(editor_name2); - var timer = new Mgly.Timer(); + Timer.start(); led.operation(function() { for (var i = 0; i < changes.length; ++i) { var change = changes[i]; @@ -1288,7 +1276,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { } }.bind(this)); - this.trace('change', 'markup lhs-editor time', timer.stop()); + this.trace('change', 'markup lhs-editor time', Timer.stop()); red.operation(function() { for (var i = 0; i < changes.length; ++i) { var change = changes[i]; @@ -1340,7 +1328,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { } } }.bind(this)); - this.trace('change', 'markup rhs-editor time', timer.stop()); + this.trace('change', 'markup rhs-editor time', Timer.stop()); // mark text deleted, LCS changes var marktext = [], i, j, k, p; @@ -1400,7 +1388,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { } } } - this.trace('change', 'LCS marktext time', timer.stop()); + this.trace('change', 'LCS marktext time', Timer.stop()); // mark changes outside closure led.operation(function() { @@ -1420,7 +1408,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { } }); - this.trace('change', 'LCS markup time', timer.stop()); + this.trace('change', 'LCS markup time', Timer.stop()); // merge buttons var ed = {lhs:led, rhs:red}; @@ -1484,7 +1472,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, { } } - this.trace('change', 'markup buttons time', timer.stop()); + this.trace('change', 'markup buttons time', Timer.stop()); }, _merge_change : function(change, side, oside) { if (!change) return; diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 5c3d433..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,38 +0,0 @@ -const webpack = require('webpack'); -const path = require('path'); -const ExtractTextPlugin = require('extract-text-webpack-plugin'); - -module.exports = { - entry: { - mergely: './src/mergely.js', - // 'mergely.min': './src/mergely.js' - }, - output: { - path: path.join(__dirname, 'lib'), - filename: './[name].js', - library: 'mergely', - libraryTarget: 'umd', - umdNamedDefine: true - }, - module: { - loaders: [ - { test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader') } - ] - }, - resolve: { - extensions: ['.js'] - }, - externals: { - jquery: 'jQuery', - CodeMirror: 'CodeMirror' - }, - plugins: [ - // new webpack.optimize.UglifyJsPlugin({ - // sourceMap: true, - // include: /\.js$/, - // // include: /\.min\.js$/, - // exclude: /node_modules/ - // }), - new ExtractTextPlugin('mergely.css') - ] -}; diff --git a/webpack.dev.js b/webpack.dev.js new file mode 100644 index 0000000..d2ad442 --- /dev/null +++ b/webpack.dev.js @@ -0,0 +1,80 @@ +const webpack = require('webpack') +const path = require('path') +const HtmlWebpackPlugin = require('html-webpack-plugin'); + +module.exports = { + mode: 'development', + + module: { + rules: [{ + include: [ + path.resolve(__dirname, 'src'), + path.resolve(__dirname, 'examples') + ], + test: /\.js$/ + }, { + test: /\.(js)$/, + exclude: /node_modules/, + use: ['babel-loader'] + }, { + test: /\.css$/, + use: [{ + loader: 'style-loader', + options: { + sourceMap: true + } + }, { + loader: 'css-loader' + }] + }] + }, + + resolve: { + extensions: ['.js'], + alias: { + 'CodeMirror': path.join(__dirname, 'node_modules', 'codemirror'), + 'jQuery': path.join(__dirname, 'node_modules', 'jquery') + } + }, + + plugins: [ + new HtmlWebpackPlugin({ + template: 'examples/app.html', + filename: 'mergely.html' + }), + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery' + }), + new webpack.ProvidePlugin({ + CodeMirror: 'codemirror' + }) + ], + + entry: { + app: [ + './examples/app', + './src/mergely', + ] + }, + + output: { + filename: 'mergely.js', + }, + + optimization: { + splitChunks: { + cacheGroups: { + vendors: { + priority: -10, + test: /[\\/]node_modules[\\/]/ + } + }, + + chunks: 'async', + minChunks: 1, + minSize: 30000, + name: true + } + } +} \ No newline at end of file diff --git a/webpack.prod.js b/webpack.prod.js new file mode 100644 index 0000000..644ec3e --- /dev/null +++ b/webpack.prod.js @@ -0,0 +1,38 @@ +const webpack = require('webpack'); +const path = require('path'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = { + mode: 'production', + entry: { + mergely: './src/mergely.js', + }, + output: { + path: path.join(__dirname, 'lib'), + filename: './[name].js', + library: 'mergely', + libraryTarget: 'umd', + umdNamedDefine: true + }, + module: { + rules: [{ + test: /\.(js)$/, + exclude: /node_modules/, + use: ['babel-loader'] + }] + }, + resolve: { + extensions: ['.js'] + }, + externals: { + jquery: 'jQuery', + CodeMirror: 'CodeMirror' + }, + plugins: [ + new CopyWebpackPlugin([{ + from: 'src/mergely.css', + to: 'mergely.css', + toType: 'file' + }]) + ] +};