<commit_before>(function(window, angular, $) {
    "use strict";
    angular.module('FileManagerApp')
	.controller('FileManagerCtrl', [
    '$scope', '$rootScope', '$translate', '$cookies', '$interval', '$http',
	'fileManagerConfig', 'item', 'fileNavigator', /*'FileUploader',*/ 'ActiveTasks',
    function($scope, $rootScope, $translate, $cookies, $interval, $http,
    		fileManagerConfig, Item, FileNavigator, /*FileUploader,*/ ActiveTasks) {

        $scope.config = fileManagerConfig;
        $scope.appName = fileManagerConfig.appName;
        $scope.orderProp = ['model.type', 'model.name'];
        $scope.query = '';
        $scope.temp = new Item();
        $scope.tempVersion = null;
        $scope.fileNavigator = new FileNavigator();
        //$scope.fileUploader = FileUploader;
        $scope.activeTasks = new ActiveTasks();
        $scope.uploadFileList = [];
        $scope.viewTemplate = $cookies.viewTemplate || 'main-table.html';

        $scope.setTemplate = function(name) {
            $scope.viewTemplate = $cookies.viewTemplate = name;
        };

        $scope.changeLanguage = function (locale) {
            if (locale) {
                return $translate.use($cookies.language = locale);
            }
            $translate.use($cookies.language || fileManagerConfig.defaultLang);
        };

        $scope.touch = function(item) {
            item = (item && item.revert && item) || new Item();
            item.revert && item.revert();
            $scope.temp = item;
        };

        $scope.smartClick = function(item, $event) {
        	//debug.log('smartClick', item.isFolder());
            if (item.isFolder() && $scope.fileNavigator.treeView) {
                if (! $scope.fileNavigator.folderClick(item)) {
            		//$scope.touch(item);
                	//$rootScope.openContextMenu('#context-menu-folder', $event);
                }
            	$event.stopPropagation();
                return;
            };
    		//$scope.touch(item);
        	//$rootScope.openContextMenu('#context-menu-item', $event);
        };

        $scope.smartRightClick = function(item, $event) {
        	$event.stopPropagation();
    		$scope.touch(item);
        	if (item.isFolder()) {
            	$rootScope.openContextMenu('#context-menu-folder', $event);
        	} else {
        		$rootScope.openContextMenu('#context-menu-item', $event);
        	}
        };

        $scope.smartClickVersion = function(item, version, $event) {
        	$event.stopPropagation();
    		$scope.touch(item);
            $scope.tempVersion = version;
        	$rootScope.openContextMenu('#context-menu-version', $event);
        };

        $scope.smartRightClickVersion = function(item, version, $event) {
        	//debug.log('smartRightClickVersion', item, version);
        	$event.stopPropagation();
    		$scope.touch(item);
            $scope.tempVersion = version;
        	$rootScope.openContextMenu('#context-menu-version', $event);
    	};

        $scope.edit = function(item) {
            item.edit(function() {
                $('#edit').modal('hide');
            });
        };

        $scope.changePermissions = function(item) {
            item.changePermissions(function() {
                $('#changepermissions').modal('hide');
            });
        };

        $scope.copy = function(item) {
            var samePath = item.tempModel.path.join() === item.model.path.join();
            if (samePath && $scope.fileNavigator.fileNameExists(item.tempModel.name)) {
                item.error = $translate.instant('error_invalid_filename');
                return false;
            }
            item.copy(function() {
                $scope.fileNavigator.refresh();
                $('#copy').modal('hide');
            });
        };

        $scope.compress = function(item) {
            item.compress(function() {
                item.success = true;
                $scope.fileNavigator.refresh();
            }, function() {
                item.success = false;
            });
        };

        $scope.extract = function(item) {
            item.extract(function() {
                item.success = true;
                $scope.fileNavigator.refresh();
            }, function() {
                item.success = false;
            });
        };

        $scope.remove = function(item) {
            item.remove(function() {
                $scope.fileNavigator.refresh();
                $('#delete').modal('hide');
            });
        };

        $scope.rename = function(item) {
            var samePath = item.tempModel.path.join() === item.model.path.join();
            if (samePath && $scope.fileNavigator.fileNameExists(item.tempModel.name)) {
                item.error = $translate.instant('error_invalid_filename');
                return false;
            }
            item.rename(function() {
                $scope.fileNavigator.refresh();
                $('#rename').modal('hide');
            });
        };

        $scope.createFolder = function(item) {
            var name = item.tempModel.name && item.tempModel.name.trim();
            item.tempModel.type = 'dir';
            item.tempModel.path = $scope.fileNavigator.currentPath;
            if (name && !$scope.fileNavigator.fileNameExists(name)) {
                item.createFolder(function() {
                    $scope.fileNavigator.refresh();
                    $('#newfolder').modal('hide');
                });
            } else {
                $scope.temp.error = $translate.instant('error_invalid_filename');
                return false;
            }
        };

        $scope.uploadFrom = function(item, temp) {
        	//debug.log('uploadFrom', item.model.path);
            temp.tempModel.path = item.model.fullPath().split('/');
            debug.log('uploadFrom', temp.tempModel.path);
            item.upload(function(data) {
            	var fullPath = temp.tempModel.path;
            	$scope.fileNavigator.currentPath =
            		fullPath &&
					fullPath[0] === "" ? [] : fullPath.slice(
						0, fullPath.length-1);
            	debug.log('controller.upload.success',
            		fullPath, $scope.fileNavigator.currentPath);
                $scope.fileNavigator.request_stats();
            	$scope.activeTasks.refresh();
                $scope.fileNavigator.refresh();
                $('#localselector').modal('hide');
            }, function() {
                $scope.fileNavigator.request_stats();
            	$scope.activeTasks.refresh();
            	$scope.fileNavigator.refresh();
            	$('#localselector').modal('hide');
        	});
        };

        $scope.downloadTo = function(item, dest_path) {
        	//debug.log('controller.downloadTo', item, dest_path);
        	item.downloadTo(dest_path, function(data) {
            	$scope.fileNavigator.refresh();
                $('#downloadselector').modal('hide');
        	}, function() {
            	$scope.fileNavigator.refresh();
                $('#downloadselector').modal('hide');
        	});
        };

        $scope.synchronizeItem = function(item) {
            item.upload(function(data) {
                $scope.fileNavigator.refresh_soft();
            }, function() {
            	$scope.fileNavigator.refresh_soft();
        	});
        };

        $scope.exploreItem = function(item) {
        };

        $scope.uploadFiles = function() {
        	/*
            $scope.fileUploader.upload(
            	$scope.uploadFileList,
				$scope.fileNavigator.currentPath).success(function() {
                $scope.fileNavigator.refresh();
                $('#uploadfile').modal('hide');
            }).error(function(data) {
                var errorMsg = data.result && data.result.error ||
                	$translate.instant('error_uploading_files');
                $scope.temp.error = errorMsg;
            });
            */
        };

        $scope.eraseVersion = function(item, version) {
        	debug.log('eraseVersion', item, version);
        	item.removeVersion(version, function(data) {
                $scope.fileNavigator.refresh_soft();
            }, function() {
            	$scope.fileNavigator.refresh_soft();
        	});
        };

        $scope.getQueryParam = function(param) {
            var found;
            window.location.search.substr(1).split("&").forEach(function(item) {
                if (param ===  item.split("=")[0]) {
                    found = item.split("=")[1];
                }
            });
            return found;
        };

        $scope.initialized = function() {
        	return fileManagerConfig.stats && fileManagerConfig.stats['timestamp'];
        };

        $scope.stat = function(key) {
        	if (fileManagerConfig.stats && fileManagerConfig.stats[key]) {
        		return fileManagerConfig.stats[key];
        	}
        	return undefined;
        };

        $scope.hasIndexedItems = function() {
        	return false;
        	if (!fileManagerConfig.stats)
        		return false;
        	var bytes_indexed = fileManagerConfig.stats.bytes_indexed;
        	var items_count = fileManagerConfig.stats.items_count;
        	if (bytes_indexed == undefined || items_count == undefined)
        		return false;
        	//debug.log('hasIndexedItems', bytes_indexed, items_count);
        	return parseInt(bytes_indexed) > 0 || parseInt(items_count) > 1;
        };

        $scope.navigateTo = function (itemPath) {
        	$scope.fileNavigator.currentPath = itemPath.split('/');
        	$scope.fileNavigator.refresh();
        };

        $scope.startRefresherTask = function () {
        	setRefreshCallback(function(data) {
        		// debug.log('refresh', data);
        		if (data.backupID || data.pathID) {
        			$scope.fileNavigator.refresh_soft();
                	$scope.activeTasks.refresh();
            	} else if (data.automat) {
            		$scope.fileNavigator.request_debug_info();
            	} else if (data.contact || data.supplier || data.customer) {
            		$scope.fileNavigator.request_stats_soft();
            	}
        	});
        	startUpdater();
        };

        $scope.changeLanguage($scope.getQueryParam('lang'));
        $scope.isWindows = $scope.getQueryParam('server') === 'Windows';

        $scope.fileNavigator.request_configs();
        $scope.fileNavigator.request_stats();
        $scope.fileNavigator.refresh();
    	$scope.activeTasks.refresh();
        $scope.fileNavigator.request_debug_info();

    	$scope.startRefresherTask();

    }]);
})(window, angular, jQuery);
<commit_msg>ups, need to fixup code after debug<commit_after>(function(window, angular, $) {
    "use strict";
    angular.module('FileManagerApp')
	.controller('FileManagerCtrl', [
    '$scope', '$rootScope', '$translate', '$cookies', '$interval', '$http',
	'fileManagerConfig', 'item', 'fileNavigator', /*'FileUploader',*/ 'ActiveTasks',
    function($scope, $rootScope, $translate, $cookies, $interval, $http,
    		fileManagerConfig, Item, FileNavigator, /*FileUploader,*/ ActiveTasks) {

        $scope.config = fileManagerConfig;
        $scope.appName = fileManagerConfig.appName;
        $scope.orderProp = ['model.type', 'model.name'];
        $scope.query = '';
        $scope.temp = new Item();
        $scope.tempVersion = null;
        $scope.fileNavigator = new FileNavigator();
        //$scope.fileUploader = FileUploader;
        $scope.activeTasks = new ActiveTasks();
        $scope.uploadFileList = [];
        $scope.viewTemplate = $cookies.viewTemplate || 'main-table.html';

        $scope.setTemplate = function(name) {
            $scope.viewTemplate = $cookies.viewTemplate = name;
        };

        $scope.changeLanguage = function (locale) {
            if (locale) {
                return $translate.use($cookies.language = locale);
            }
            $translate.use($cookies.language || fileManagerConfig.defaultLang);
        };

        $scope.touch = function(item) {
            item = (item && item.revert && item) || new Item();
            item.revert && item.revert();
            $scope.temp = item;
        };

        $scope.smartClick = function(item, $event) {
        	//debug.log('smartClick', item.isFolder());
            if (item.isFolder() && $scope.fileNavigator.treeView) {
                if (! $scope.fileNavigator.folderClick(item)) {
            		//$scope.touch(item);
                	//$rootScope.openContextMenu('#context-menu-folder', $event);
                }
            	$event.stopPropagation();
                return;
            };
    		//$scope.touch(item);
        	//$rootScope.openContextMenu('#context-menu-item', $event);
        };

        $scope.smartRightClick = function(item, $event) {
        	$event.stopPropagation();
    		$scope.touch(item);
        	if (item.isFolder()) {
            	$rootScope.openContextMenu('#context-menu-folder', $event);
        	} else {
        		$rootScope.openContextMenu('#context-menu-item', $event);
        	}
        };

        $scope.smartClickVersion = function(item, version, $event) {
        	$event.stopPropagation();
    		$scope.touch(item);
            $scope.tempVersion = version;
        	$rootScope.openContextMenu('#context-menu-version', $event);
        };

        $scope.smartRightClickVersion = function(item, version, $event) {
        	//debug.log('smartRightClickVersion', item, version);
        	$event.stopPropagation();
    		$scope.touch(item);
            $scope.tempVersion = version;
        	$rootScope.openContextMenu('#context-menu-version', $event);
    	};

        $scope.edit = function(item) {
            item.edit(function() {
                $('#edit').modal('hide');
            });
        };

        $scope.changePermissions = function(item) {
            item.changePermissions(function() {
                $('#changepermissions').modal('hide');
            });
        };

        $scope.copy = function(item) {
            var samePath = item.tempModel.path.join() === item.model.path.join();
            if (samePath && $scope.fileNavigator.fileNameExists(item.tempModel.name)) {
                item.error = $translate.instant('error_invalid_filename');
                return false;
            }
            item.copy(function() {
                $scope.fileNavigator.refresh();
                $('#copy').modal('hide');
            });
        };

        $scope.compress = function(item) {
            item.compress(function() {
                item.success = true;
                $scope.fileNavigator.refresh();
            }, function() {
                item.success = false;
            });
        };

        $scope.extract = function(item) {
            item.extract(function() {
                item.success = true;
                $scope.fileNavigator.refresh();
            }, function() {
                item.success = false;
            });
        };

        $scope.remove = function(item) {
            item.remove(function() {
                $scope.fileNavigator.refresh();
                $('#delete').modal('hide');
            });
        };

        $scope.rename = function(item) {
            var samePath = item.tempModel.path.join() === item.model.path.join();
            if (samePath && $scope.fileNavigator.fileNameExists(item.tempModel.name)) {
                item.error = $translate.instant('error_invalid_filename');
                return false;
            }
            item.rename(function() {
                $scope.fileNavigator.refresh();
                $('#rename').modal('hide');
            });
        };

        $scope.createFolder = function(item) {
            var name = item.tempModel.name && item.tempModel.name.trim();
            item.tempModel.type = 'dir';
            item.tempModel.path = $scope.fileNavigator.currentPath;
            if (name && !$scope.fileNavigator.fileNameExists(name)) {
                item.createFolder(function() {
                    $scope.fileNavigator.refresh();
                    $('#newfolder').modal('hide');
                });
            } else {
                $scope.temp.error = $translate.instant('error_invalid_filename');
                return false;
            }
        };

        $scope.uploadFrom = function(item, temp) {
        	//debug.log('uploadFrom', item.model.path);
            temp.tempModel.path = item.model.fullPath().split('/');
            debug.log('uploadFrom', temp.tempModel.path);
            item.upload(function(data) {
            	var fullPath = temp.tempModel.path;
            	$scope.fileNavigator.currentPath =
            		fullPath &&
					fullPath[0] === "" ? [] : fullPath.slice(
						0, fullPath.length-1);
            	debug.log('controller.upload.success',
            		fullPath, $scope.fileNavigator.currentPath);
                $scope.fileNavigator.request_stats();
            	$scope.activeTasks.refresh();
                $scope.fileNavigator.refresh();
                $('#localselector').modal('hide');
            }, function() {
                $scope.fileNavigator.request_stats();
            	$scope.activeTasks.refresh();
            	$scope.fileNavigator.refresh();
            	$('#localselector').modal('hide');
        	});
        };

        $scope.downloadTo = function(item, dest_path) {
        	//debug.log('controller.downloadTo', item, dest_path);
        	item.downloadTo(dest_path, function(data) {
            	$scope.fileNavigator.refresh();
                $('#downloadselector').modal('hide');
        	}, function() {
            	$scope.fileNavigator.refresh();
                $('#downloadselector').modal('hide');
        	});
        };

        $scope.synchronizeItem = function(item) {
            item.upload(function(data) {
                $scope.fileNavigator.refresh_soft();
            }, function() {
            	$scope.fileNavigator.refresh_soft();
        	});
        };

        $scope.exploreItem = function(item) {
        };

        $scope.uploadFiles = function() {
        	/*
            $scope.fileUploader.upload(
            	$scope.uploadFileList,
				$scope.fileNavigator.currentPath).success(function() {
                $scope.fileNavigator.refresh();
                $('#uploadfile').modal('hide');
            }).error(function(data) {
                var errorMsg = data.result && data.result.error ||
                	$translate.instant('error_uploading_files');
                $scope.temp.error = errorMsg;
            });
            */
        };

        $scope.eraseVersion = function(item, version) {
        	debug.log('eraseVersion', item, version);
        	item.removeVersion(version, function(data) {
                $scope.fileNavigator.refresh_soft();
            }, function() {
            	$scope.fileNavigator.refresh_soft();
        	});
        };

        $scope.getQueryParam = function(param) {
            var found;
            window.location.search.substr(1).split("&").forEach(function(item) {
                if (param ===  item.split("=")[0]) {
                    found = item.split("=")[1];
                }
            });
            return found;
        };

        $scope.initialized = function() {
        	return fileManagerConfig.stats && fileManagerConfig.stats['timestamp'];
        };

        $scope.stat = function(key) {
        	if (fileManagerConfig.stats && fileManagerConfig.stats[key]) {
        		return fileManagerConfig.stats[key];
        	}
        	return undefined;
        };

        $scope.hasIndexedItems = function() {
        	//return false;
        	if (!fileManagerConfig.stats)
        		return false;
        	var bytes_indexed = fileManagerConfig.stats.bytes_indexed;
        	var items_count = fileManagerConfig.stats.items_count;
        	if (bytes_indexed == undefined || items_count == undefined)
        		return false;
        	//debug.log('hasIndexedItems', bytes_indexed, items_count);
        	return parseInt(bytes_indexed) > 0 || parseInt(items_count) > 1;
        };

        $scope.navigateTo = function (itemPath) {
        	$scope.fileNavigator.currentPath = itemPath.split('/');
        	$scope.fileNavigator.refresh();
        };

        $scope.startRefresherTask = function () {
        	setRefreshCallback(function(data) {
        		// debug.log('refresh', data);
        		if (data.backupID || data.pathID) {
        			$scope.fileNavigator.refresh_soft();
                	$scope.activeTasks.refresh();
            	} else if (data.automat) {
            		$scope.fileNavigator.request_debug_info();
            	} else if (data.contact || data.supplier || data.customer) {
            		$scope.fileNavigator.request_stats_soft();
            	}
        	});
        	startUpdater();
        };

        $scope.changeLanguage($scope.getQueryParam('lang'));
        $scope.isWindows = $scope.getQueryParam('server') === 'Windows';

        $scope.fileNavigator.request_configs();
        $scope.fileNavigator.request_stats();
        $scope.fileNavigator.refresh();
    	$scope.activeTasks.refresh();
        $scope.fileNavigator.request_debug_info();

    	$scope.startRefresherTask();

    }]);
})(window, angular, jQuery);
<|endoftext|>


<commit_before>const { createCanvas, registerFont } = require('canvas');

module.exports = (Oled) => {
  return class OledCanvas extends Oled {
    constructor(..._args) {
      const args = _args.slice(0, _args.length - 1);
      const opts = _args[_args.length - 1];
      super(...args, opts);

      if (opts.fontFile) {
        // use filename as family name
        const fontFamily = opts.fontFile.replace(/^(.*\/)?\.[a-zA-Z]+$/, '');

        this.fontFamily = fontFamily;
        registerFont(opts.fontFile, { family: fontFamily });
      } else {
        this.font = 'monospace';
      }

      const canvas = createCanvas(this.WIDTH, this.HEIGHT);
      this._ctx = canvas.getContext('2d');
      this.clearCanvas();
    }

    _canvasPixelToOledPixel(pixel) {
      const threshold = 127;

      // assume pi using little-endian
      const r = pixel & 0xff;
      // const g = pixel >>> 8 & 0xff;
      // const b = pixel >>> 16 & 0xff;
      // const a = pixel >>> 24;

      // assume gray pixel has the same amount of r, g and b
      return r < threshold ? 1 : 0;
    }

    clearCanvas() {
      this.fillRect(0, 0, this.WIDTH, this.HEIGHT, { color: '#fff', update: false });
    }

    clearDisplay({ update = true } = {}) {
      this.clearCanvas();
      if (update) this.update();
    }

    drawLine(x0, y0, x1, y1, { color = '#000', update = true } = {}) {
      const ctx = this._ctx;
      ctx.strokeStyle = color;
      ctx.beginPath();
      ctx.moveTo(x0, y0);
      ctx.lineTo(x1, y1);
      ctx.stroke();

      if (update) this.update();
    }

    drawPixels(pixels, { update = true } = {}) {
      if (!Array.isArray(pixels[0])) pixels = [pixels];

      pixels.forEach((elem) => {
        const [x, y, pixel] = elem;
        this.fillRect(x, y, 1, 1, { color: pixel ? '#000' : 'fff', update: false });
      });

      if (update) this.update();
    }

    fillRect(x, y, w, h, { color = '#000', update = true } = {}) {
      const ctx = this._ctx;
      ctx.fillStyle = color;
      ctx.fillRect(x, y, w, h);

      if (update) this.update();
    }

    getContext() {
      return this._ctx;
    }

    drawString(string, { fontSize, color = '#000', update = true } = {}) {
      if (!Number.isFinite(fontSize) || fontSize < 0) {
        throw new Error('fontSize must be positive number.');
      }

      const ctx = this._ctx;
      ctx.font = `${fontSize}px "${this.fontFamily}"`;
      ctx.textBaseline = 'bottom';

      const width = ctx.measureText(string).width;

      this.fillRect(this.cursor_x, this.cursor_y, width, { fontSize, color: '#fff', update });

      ctx.fillStyle = color;
      ctx.fillText(string, this.cursor_x, this.cursor_y + fontSize);

      if (update) this.update();
    }

    update() {
      // wait for oled to be ready
      this._waitUntilReady(function() {
        const ctx = this._ctx;
        const pageHeight = 8;
        const pageLen = this.HEIGHT / pageHeight;

        // set the start and endbyte locations for oled display update
        const displaySeq = [
          this.COLUMN_ADDR,
          this.screenConfig.coloffset,
          this.screenConfig.coloffset + this.WIDTH - 1, // column start and end address
          this.PAGE_ADDR, 0, pageLen - 1 // page start and end address
        ];

        // send intro seq
        displaySeq.forEach((elem) => {
          this._transfer('cmd', elem);
        });

        // send canvas data
        const bitsToByte = (bits) => {
          return bits.reverse()
            .map((i, index) => i ? 2 ** index : 0, 0)
            .reduce((a, b) => a + b, 0);
        };

        for (let page = 0; page < pageLen; page++) {
          const pagePixels = new Uint32Array(ctx.getImageData(0, page * pageHeight, this.WIDTH, pageHeight).data.buffer) // Uint8Array to Uint32Array
            .map(this._canvasPixelToOledPixel);

          for (let i = 0; i < this.WIDTH; i++) {
            this._transfer('data', bitsToByte([
              pagePixels[1024 + i],
              pagePixels[896 + i],
              pagePixels[768 + i],
              pagePixels[640 + i],
              pagePixels[512 + i],
              pagePixels[384 + i],
              pagePixels[256 + i],
              pagePixels[128 + i],
              pagePixels[0 + i],
            ]));
          }
        }
      }.bind(this));
    }
  }
};
<commit_msg>Fix # was missing in color code<commit_after>const { createCanvas, registerFont } = require('canvas');

module.exports = (Oled) => {
  return class OledCanvas extends Oled {
    constructor(..._args) {
      const args = _args.slice(0, _args.length - 1);
      const opts = _args[_args.length - 1];
      super(...args, opts);

      if (opts.fontFile) {
        // use filename as family name
        const fontFamily = opts.fontFile.replace(/^(.*\/)?\.[a-zA-Z]+$/, '');

        this.fontFamily = fontFamily;
        registerFont(opts.fontFile, { family: fontFamily });
      } else {
        this.font = 'monospace';
      }

      const canvas = createCanvas(this.WIDTH, this.HEIGHT);
      this._ctx = canvas.getContext('2d');
      this.clearCanvas();
    }

    _canvasPixelToOledPixel(pixel) {
      const threshold = 127;

      // assume pi using little-endian
      const r = pixel & 0xff;
      // const g = pixel >>> 8 & 0xff;
      // const b = pixel >>> 16 & 0xff;
      // const a = pixel >>> 24;

      // assume gray pixel has the same amount of r, g and b
      return r < threshold ? 1 : 0;
    }

    clearCanvas() {
      this.fillRect(0, 0, this.WIDTH, this.HEIGHT, { color: '#fff', update: false });
    }

    clearDisplay({ update = true } = {}) {
      this.clearCanvas();
      if (update) this.update();
    }

    drawLine(x0, y0, x1, y1, { color = '#000', update = true } = {}) {
      const ctx = this._ctx;
      ctx.strokeStyle = color;
      ctx.beginPath();
      ctx.moveTo(x0, y0);
      ctx.lineTo(x1, y1);
      ctx.stroke();

      if (update) this.update();
    }

    drawPixels(pixels, { update = true } = {}) {
      if (!Array.isArray(pixels[0])) pixels = [pixels];

      pixels.forEach((elem) => {
        const [x, y, pixel] = elem;
        this.fillRect(x, y, 1, 1, { color: pixel ? '#000' : '#fff', update: false });
      });

      if (update) this.update();
    }

    fillRect(x, y, w, h, { color = '#000', update = true } = {}) {
      const ctx = this._ctx;
      ctx.fillStyle = color;
      ctx.fillRect(x, y, w, h);

      if (update) this.update();
    }

    getContext() {
      return this._ctx;
    }

    drawString(string, { fontSize, color = '#000', update = true } = {}) {
      if (!Number.isFinite(fontSize) || fontSize < 0) {
        throw new Error('fontSize must be positive number.');
      }

      const ctx = this._ctx;
      ctx.font = `${fontSize}px "${this.fontFamily}"`;
      ctx.textBaseline = 'bottom';

      const width = ctx.measureText(string).width;

      this.fillRect(this.cursor_x, this.cursor_y, width, { fontSize, color: '#fff', update });

      ctx.fillStyle = color;
      ctx.fillText(string, this.cursor_x, this.cursor_y + fontSize);

      if (update) this.update();
    }

    update() {
      // wait for oled to be ready
      this._waitUntilReady(function() {
        const ctx = this._ctx;
        const pageHeight = 8;
        const pageLen = this.HEIGHT / pageHeight;

        // set the start and endbyte locations for oled display update
        const displaySeq = [
          this.COLUMN_ADDR,
          this.screenConfig.coloffset,
          this.screenConfig.coloffset + this.WIDTH - 1, // column start and end address
          this.PAGE_ADDR, 0, pageLen - 1 // page start and end address
        ];

        // send intro seq
        displaySeq.forEach((elem) => {
          this._transfer('cmd', elem);
        });

        // send canvas data
        const bitsToByte = (bits) => {
          return bits.reverse()
            .map((i, index) => i ? 2 ** index : 0, 0)
            .reduce((a, b) => a + b, 0);
        };

        for (let page = 0; page < pageLen; page++) {
          const pagePixels = new Uint32Array(ctx.getImageData(0, page * pageHeight, this.WIDTH, pageHeight).data.buffer) // Uint8Array to Uint32Array
            .map(this._canvasPixelToOledPixel);

          for (let i = 0; i < this.WIDTH; i++) {
            this._transfer('data', bitsToByte([
              pagePixels[1024 + i],
              pagePixels[896 + i],
              pagePixels[768 + i],
              pagePixels[640 + i],
              pagePixels[512 + i],
              pagePixels[384 + i],
              pagePixels[256 + i],
              pagePixels[128 + i],
              pagePixels[0 + i],
            ]));
          }
        }
      }.bind(this));
    }
  }
};
<|endoftext|>


<commit_before>import Conditions from '../../../../../resources/conditions';
import NetRegexes from '../../../../../resources/netregexes';
import { Responses } from '../../../../../resources/responses';
import ZoneId from '../../../../../resources/zone_id';

export default {
  zoneId: ZoneId.Paglthan,
  timelineFile: 'paglthan.txt',
  timelineTriggers: [
    {
      // This is a rear cone attack that always follows Wide Blaster.
      // It has a cast time of under a GCD, so we pre-warn during Wide Blaster.
      // Only the sides are safe to call at this moment.
      id: 'Paglthan Spike Flail',
      regex: /Spike Flail/,
      beforeSeconds: 4,
      response: Responses.goSides(),
    },
  ],
  triggers: [
    {
      id: 'Paglthan Critical Rip',
      netRegex: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C4E', source: 'アムルック' }),
      condition: Conditions.caresAboutPhysical(),
      response: Responses.tankBuster(),
    },
    {
      id: 'Paglthan Electric Burst',
      netRegex: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C4D', source: 'アムルック', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Lightning Rod Gain',
      netRegex: NetRegexes.gainsEffect({ effectId: 'A0E' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Go to a lightning rod',
          de: 'Geh zu einem Blitzableiter',
          fr: 'Allez sur un paratonnerre',
        },
      },
    },
    {
      id: 'Paglthan Lightning Rod Lose',
      netRegex: NetRegexes.losesEffect({ effectId: 'A0E' }),
      condition: Conditions.targetIsYou(),
      response: Responses.goMiddle(),
    },
    {
      id: 'Paglthan Ballistic',
      netRegex: NetRegexes.startsUsing({ id: '5C97', source: 'Magitek Fortress', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C97', source: 'Magitek-Festung', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C97', source: 'Forteresse Magitek', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C97', source: '魔導フォートレス', capture: false }),
      response: Responses.knockback(),
    },
    {
      id: 'Paglthan Defensive Reaction',
      netRegex: NetRegexes.startsUsing({ id: '5C9E', source: 'Magitek Core', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C9E', source: 'Magitek-Reaktor', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C9E', source: 'Réacteur Magitek', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C9E', source: '魔導コア', capture: false }),
      netRegexCn: NetRegexes.startsUsing({ id: '5C9E', source: '魔导核心', capture: false }),
      netRegexKo: NetRegexes.startsUsing({ id: '5C9E', source: '마도핵', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Twisted Scream',
      netRegex: NetRegexes.startsUsing({ id: '5B47', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B47', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B47', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B47', source: 'ルナバハムート', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Akh Morn',
      netRegex: NetRegexes.headMarker({ id: '005D' }),
      response: Responses.stackMarkerOn(),
    },
    {
      id: 'Paglthan Mega Flare Spread',
      netRegex: NetRegexes.headMarker({ id: '0017' }),
      condition: Conditions.targetIsYou(),
      response: Responses.spread(),
    },
    {
      id: 'Paglthan Mega Flare Move',
      netRegex: NetRegexes.ability({ id: '5B4D', source: 'Lunar Bahamut' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Away from circles',
          de: 'Weg von den Kreisen',
          fr: 'Éloignez-vous des cercles',
        },
      },
    },
    {
      id: 'Paglthan Kan Rhai Marker',
      netRegex: NetRegexes.headMarker({ id: '0104' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Kan Rhai on YOU',
          de: 'Kan Rhai auf DIR',
          fr: 'Kan Rhai sur VOUS',
          ko: '십자 장판 대상자',
        },
      },
    },
    {
      id: 'Paglthan Kan Rhai Move',
      netRegex: NetRegexes.ability({ id: '5B4F', source: 'Lunar Bahamut', capture: false }),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Away from crosses',
          de: 'Weg von dem Kreuz',
          fr: 'Éloignez-vous des croix',
          ko: '십자 피하기',
        },
      },
    },
    {
      id: 'Paglthan Flatten',
      netRegex: NetRegexes.startsUsing({ id: '5B58', source: 'Lunar Bahamut' }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B58', source: 'Luna-Bahamut' }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B58', source: 'Luna-Bahamut' }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B58', source: 'ルナバハムート' }),
      condition: Conditions.caresAboutPhysical(),
      response: Responses.tankBuster(),
    },
    {
      id: 'Paglthan Giga Flare',
      netRegex: NetRegexes.startsUsing({ id: '5B57', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B57', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B57', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B57', source: 'ルナバハムート', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
  ],
  timelineReplace: [
    {
      'locale': 'de',
      'replaceSync': {
        'Amhuluk': 'Amhuluk',
        'Lunar Bahamut': 'Luna-Bahamut',
        'Magitek Fortress': 'Magitek-Festung',
        'Magitek Core': 'Magitek-Reaktor',
        'Sunseat': 'Dämmergarten',
        'The Gathering Ring': 'Festplatz von Zolm\'ak',
      },
      'replaceText': {
        '\\(circles\\)': '(Kreise)',
        '\\(explosions\\)': '(Explosionen)',
        '--Levin orbs--': '--Elektrosphären--',
        'Akh Morn': 'Akh Morn',
        'Big Burst': 'Detonation',
        'Critical Rip': 'Kritischer Riss',
        'Electric Burst': 'Stromstoß',
        'Flatten': 'Einebnen',
        'Gigaflare': 'Gigaflare',
        'Kan Rhai': 'Kan Rhai',
        'Lightning Bolt': 'Blitzschlag',
        'Lunar Flare': 'Lunaflare',
        'Megaflare(?! Dive)': 'Megaflare',
        'Megaflare Dive': 'Megaflare-Sturz',
        'Perigean Breath': 'Perigäum-Atem',
        'Spike Flail': 'Dornendresche',
        'Thundercall': 'Donnerruf',
        'Twisted Scream': 'Verzerrtes Brüllen',
        'Upburst': 'Quantengravitation',
        'Wide Blaster': 'Weitwinkel-Blaster',
      },
    },
    {
      'locale': 'fr',
      'replaceSync': {
        'Amhuluk': 'Amhuluk',
        'Lunar Bahamut': 'Luna-Bahamut',
        'Magitek Fortress': 'forteresse magitek',
        'Magitek Core': 'réacteur magitek',
        'Sunseat': 'Clos du Crépuscule',
        'The Gathering Ring': 'Autel de Zolm\'ak',
      },
      'replaceText': {
        '\\(circles\\)': '(cercles)',
        '\\(explosions\\)': '(explosions)',
        '--Levin orbs--': '--Orbes de foudre--',
        'Akh Morn': 'Akh Morn',
        'Big Burst': 'Grosse explosion',
        'Critical Rip': 'Griffure critique',
        'Electric Burst': 'Salve électrique',
        'Flatten': 'Compression',
        'Gigaflare': 'GigaBrasier',
        'Kan Rhai': 'Kan Rhai',
        'Lightning Bolt': 'Éclair de foudre',
        'Lunar Flare': 'LunaBrasier',
        'Megaflare(?! Dive)': 'MégaBrasier',
        'Megaflare Dive': 'Plongeon MégaBrasier',
        'Perigean Breath': 'Souffle de périgée',
        'Spike Flail': 'Fléau à pointes',
        'Thundercall': 'Drain fulminant',
        'Twisted Scream': 'Hurlement de l\'Anomalie',
        'Upburst': 'Saillie',
        'Wide Blaster': 'Fulguration large',
      },
    },
    {
      'locale': 'ja',
      'missingTranslations': true,
      'replaceSync': {
        'Amhuluk': 'アムルック',
        'Lunar Bahamut': 'ルナバハムート',
        'Magitek Fortress': '魔導フォートレス',
        'Magitek Core': '魔導コア',
        'Sunseat': '黄昏の庭',
        'The Gathering Ring': 'ゾレマク祭場',
      },
      'replaceText': {
        'Akh Morn': 'アク・モーン',
        'Big Burst': '大爆発',
        'Critical Rip': 'クリティカルリップ',
        'Electric Burst': 'エレクトリックバースト',
        'Flatten': 'フラッテン',
        'Gigaflare': 'ギガフレア',
        'Kan Rhai': 'カン・ラーイ',
        'Lightning Bolt': '落雷',
        'Lunar Flare': 'ルナフレア',
        'Megaflare(?! Dive)': 'メガフレア',
        'Megaflare Dive': 'メガフレアダイブ',
        'Perigean Breath': 'ペリジアンブレス',
        'Spike Flail': 'スパイクフレイル',
        'Thundercall': '招雷',
        'Twisted Scream': '異形の咆哮',
        'Upburst': '突出',
        'Wide Blaster': 'ワイドブラスター',
      },
    },
  ],
};
<commit_msg>raidboss: Add Lunar Flare Trigger (#2767)<commit_after>import Conditions from '../../../../../resources/conditions';
import NetRegexes from '../../../../../resources/netregexes';
import { Responses } from '../../../../../resources/responses';
import ZoneId from '../../../../../resources/zone_id';

export default {
  zoneId: ZoneId.Paglthan,
  timelineFile: 'paglthan.txt',
  timelineTriggers: [
    {
      // This is a rear cone attack that always follows Wide Blaster.
      // It has a cast time of under a GCD, so we pre-warn during Wide Blaster.
      // Only the sides are safe to call at this moment.
      id: 'Paglthan Spike Flail',
      regex: /Spike Flail/,
      beforeSeconds: 4,
      response: Responses.goSides(),
    },
  ],
  triggers: [
    {
      id: 'Paglthan Critical Rip',
      netRegex: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C4E', source: 'Amhuluk' }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C4E', source: 'アムルック' }),
      condition: Conditions.caresAboutPhysical(),
      response: Responses.tankBuster(),
    },
    {
      id: 'Paglthan Electric Burst',
      netRegex: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C4D', source: 'Amhuluk', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C4D', source: 'アムルック', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Lightning Rod Gain',
      netRegex: NetRegexes.gainsEffect({ effectId: 'A0E' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Go to a lightning rod',
          de: 'Geh zu einem Blitzableiter',
          fr: 'Allez sur un paratonnerre',
        },
      },
    },
    {
      id: 'Paglthan Lightning Rod Lose',
      netRegex: NetRegexes.losesEffect({ effectId: 'A0E' }),
      condition: Conditions.targetIsYou(),
      response: Responses.goMiddle(),
    },
    {
      id: 'Paglthan Ballistic',
      netRegex: NetRegexes.startsUsing({ id: '5C97', source: 'Magitek Fortress', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C97', source: 'Magitek-Festung', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C97', source: 'Forteresse Magitek', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C97', source: '魔導フォートレス', capture: false }),
      response: Responses.knockback(),
    },
    {
      id: 'Paglthan Defensive Reaction',
      netRegex: NetRegexes.startsUsing({ id: '5C9E', source: 'Magitek Core', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5C9E', source: 'Magitek-Reaktor', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5C9E', source: 'Réacteur Magitek', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5C9E', source: '魔導コア', capture: false }),
      netRegexCn: NetRegexes.startsUsing({ id: '5C9E', source: '魔导核心', capture: false }),
      netRegexKo: NetRegexes.startsUsing({ id: '5C9E', source: '마도핵', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Twisted Scream',
      netRegex: NetRegexes.startsUsing({ id: '5B47', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B47', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B47', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B47', source: 'ルナバハムート', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
    {
      id: 'Paglthan Akh Morn',
      netRegex: NetRegexes.headMarker({ id: '005D' }),
      response: Responses.stackMarkerOn(),
    },
    {
      id: 'Paglthan Mega Flare Spread',
      netRegex: NetRegexes.headMarker({ id: '0017' }),
      condition: Conditions.targetIsYou(),
      response: Responses.spread(),
    },
    {
      id: 'Paglthan Mega Flare Move',
      netRegex: NetRegexes.ability({ id: '5B4D', source: 'Lunar Bahamut' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Away from circles',
          de: 'Weg von den Kreisen',
          fr: 'Éloignez-vous des cercles',
        },
      },
    },
    {
      id: 'Paglthan Kan Rhai Marker',
      netRegex: NetRegexes.headMarker({ id: '0104' }),
      condition: Conditions.targetIsYou(),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Kan Rhai on YOU',
          de: 'Kan Rhai auf DIR',
          fr: 'Kan Rhai sur VOUS',
          ko: '십자 장판 대상자',
        },
      },
    },
    {
      id: 'Paglthan Kan Rhai Move',
      netRegex: NetRegexes.ability({ id: '5B4F', source: 'Lunar Bahamut', capture: false }),
      alertText: (data, _, output) => output.text(),
      outputStrings: {
        text: {
          en: 'Away from crosses',
          de: 'Weg von dem Kreuz',
          fr: 'Éloignez-vous des croix',
          ko: '십자 피하기',
        },
      },
    },
    {
      id: 'Paglthan Lunar Flare Reset',
      netRegex: NetRegexes.ability({ id: '5B49', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.ability({ id: '5B49', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.ability({ id: '5B49', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.ability({ id: '5B49', source: 'ルナバハムート', capture: false }),
      run: (data) => data.lunarFlares = 0,
    },
    {
      id: 'Paglthan Lunar Flare Collect',
      netRegex: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'ルナバハムート', capture: false }),
      run: (data) => data.lunarFlares = (data.lunarFlares || 0) + 1,
    },
    {
      // Get middle is 4x5B4A and 4x5B4B, get outside is 5x5B4A
      id: 'Paglthan Lunar Flare',
      netRegex: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B4[AB]', source: 'ルナバハムート', capture: false }),
      delaySeconds: 0.5,
      suppressSeconds: 1,
      alertText: (data, _, output) => {
        if (data.lunarFlares === 5)
          return output.getOutsideBetweenCircles();
        if (data.lunarFlares === 8)
          return output.getMiddle();
      },
      outputStrings: {
        getMiddle: {
          en: 'Get Middle',
          de: 'In die Mitte gehen',
          fr: 'Allez au milieu',
          ja: '中心へ',
          cn: '中间',
          ko: '중앙으로',
        },
        getOutsideBetweenCircles: {
          en: 'Get Outside Between Circles',
        },
      },
    },
    {
      id: 'Paglthan Flatten',
      netRegex: NetRegexes.startsUsing({ id: '5B58', source: 'Lunar Bahamut' }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B58', source: 'Luna-Bahamut' }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B58', source: 'Luna-Bahamut' }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B58', source: 'ルナバハムート' }),
      condition: Conditions.caresAboutPhysical(),
      response: Responses.tankBuster(),
    },
    {
      id: 'Paglthan Giga Flare',
      netRegex: NetRegexes.startsUsing({ id: '5B57', source: 'Lunar Bahamut', capture: false }),
      netRegexDe: NetRegexes.startsUsing({ id: '5B57', source: 'Luna-Bahamut', capture: false }),
      netRegexFr: NetRegexes.startsUsing({ id: '5B57', source: 'Luna-Bahamut', capture: false }),
      netRegexJa: NetRegexes.startsUsing({ id: '5B57', source: 'ルナバハムート', capture: false }),
      condition: Conditions.caresAboutAOE(),
      response: Responses.aoe(),
    },
  ],
  timelineReplace: [
    {
      'locale': 'de',
      'replaceSync': {
        'Amhuluk': 'Amhuluk',
        'Lunar Bahamut': 'Luna-Bahamut',
        'Magitek Fortress': 'Magitek-Festung',
        'Magitek Core': 'Magitek-Reaktor',
        'Sunseat': 'Dämmergarten',
        'The Gathering Ring': 'Festplatz von Zolm\'ak',
      },
      'replaceText': {
        '\\(circles\\)': '(Kreise)',
        '\\(explosions\\)': '(Explosionen)',
        '--Levin orbs--': '--Elektrosphären--',
        'Akh Morn': 'Akh Morn',
        'Big Burst': 'Detonation',
        'Critical Rip': 'Kritischer Riss',
        'Electric Burst': 'Stromstoß',
        'Flatten': 'Einebnen',
        'Gigaflare': 'Gigaflare',
        'Kan Rhai': 'Kan Rhai',
        'Lightning Bolt': 'Blitzschlag',
        'Lunar Flare': 'Lunaflare',
        'Megaflare(?! Dive)': 'Megaflare',
        'Megaflare Dive': 'Megaflare-Sturz',
        'Perigean Breath': 'Perigäum-Atem',
        'Spike Flail': 'Dornendresche',
        'Thundercall': 'Donnerruf',
        'Twisted Scream': 'Verzerrtes Brüllen',
        'Upburst': 'Quantengravitation',
        'Wide Blaster': 'Weitwinkel-Blaster',
      },
    },
    {
      'locale': 'fr',
      'replaceSync': {
        'Amhuluk': 'Amhuluk',
        'Lunar Bahamut': 'Luna-Bahamut',
        'Magitek Fortress': 'forteresse magitek',
        'Magitek Core': 'réacteur magitek',
        'Sunseat': 'Clos du Crépuscule',
        'The Gathering Ring': 'Autel de Zolm\'ak',
      },
      'replaceText': {
        '\\(circles\\)': '(cercles)',
        '\\(explosions\\)': '(explosions)',
        '--Levin orbs--': '--Orbes de foudre--',
        'Akh Morn': 'Akh Morn',
        'Big Burst': 'Grosse explosion',
        'Critical Rip': 'Griffure critique',
        'Electric Burst': 'Salve électrique',
        'Flatten': 'Compression',
        'Gigaflare': 'GigaBrasier',
        'Kan Rhai': 'Kan Rhai',
        'Lightning Bolt': 'Éclair de foudre',
        'Lunar Flare': 'LunaBrasier',
        'Megaflare(?! Dive)': 'MégaBrasier',
        'Megaflare Dive': 'Plongeon MégaBrasier',
        'Perigean Breath': 'Souffle de périgée',
        'Spike Flail': 'Fléau à pointes',
        'Thundercall': 'Drain fulminant',
        'Twisted Scream': 'Hurlement de l\'Anomalie',
        'Upburst': 'Saillie',
        'Wide Blaster': 'Fulguration large',
      },
    },
    {
      'locale': 'ja',
      'missingTranslations': true,
      'replaceSync': {
        'Amhuluk': 'アムルック',
        'Lunar Bahamut': 'ルナバハムート',
        'Magitek Fortress': '魔導フォートレス',
        'Magitek Core': '魔導コア',
        'Sunseat': '黄昏の庭',
        'The Gathering Ring': 'ゾレマク祭場',
      },
      'replaceText': {
        'Akh Morn': 'アク・モーン',
        'Big Burst': '大爆発',
        'Critical Rip': 'クリティカルリップ',
        'Electric Burst': 'エレクトリックバースト',
        'Flatten': 'フラッテン',
        'Gigaflare': 'ギガフレア',
        'Kan Rhai': 'カン・ラーイ',
        'Lightning Bolt': '落雷',
        'Lunar Flare': 'ルナフレア',
        'Megaflare(?! Dive)': 'メガフレア',
        'Megaflare Dive': 'メガフレアダイブ',
        'Perigean Breath': 'ペリジアンブレス',
        'Spike Flail': 'スパイクフレイル',
        'Thundercall': '招雷',
        'Twisted Scream': '異形の咆哮',
        'Upburst': '突出',
        'Wide Blaster': 'ワイドブラスター',
      },
    },
  ],
};
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var OptionsApply = require("./OptionsApply");

var LoaderTargetPlugin = require("./LoaderTargetPlugin");
var FunctionModulePlugin = require("./FunctionModulePlugin");
var EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
var SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
var EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin");

var EntryOptionPlugin = require("./EntryOptionPlugin");
var RecordIdsPlugin = require("./RecordIdsPlugin");

var APIPlugin = require("./APIPlugin");
var ConstPlugin = require("./ConstPlugin");
var RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
var NodeStuffPlugin = require("./NodeStuffPlugin");
var CompatibilityPlugin = require("./CompatibilityPlugin");
var DefinePlugin = require("./DefinePlugin");

var MovedToPluginWarningPlugin = require("./MovedToPluginWarningPlugin");
var TemplatedPathPlugin = require("./TemplatedPathPlugin");
var WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");

var LoaderPlugin = require("./dependencies/LoaderPlugin");
var CommonJsPlugin = require("./dependencies/CommonJsPlugin");
var AMDPlugin = require("./dependencies/AMDPlugin");
var RequireContextPlugin = require("./dependencies/RequireContextPlugin");
var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");

var RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
var RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
var MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
var FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");

var UnsafeCachePlugin = require("enhanced-resolve/lib/UnsafeCachePlugin");
var ModulesInDirectoriesPlugin = require("enhanced-resolve/lib/ModulesInDirectoriesPlugin");
var ModulesInRootPlugin = require("enhanced-resolve/lib/ModulesInRootPlugin");
var ModuleTemplatesPlugin = require("enhanced-resolve/lib/ModuleTemplatesPlugin");
var ModuleAsFilePlugin = require("enhanced-resolve/lib/ModuleAsFilePlugin");
var ModuleAsDirectoryPlugin = require("enhanced-resolve/lib/ModuleAsDirectoryPlugin");
var ModuleAliasPlugin = require("enhanced-resolve/lib/ModuleAliasPlugin");
var DirectoryDefaultFilePlugin = require("enhanced-resolve/lib/DirectoryDefaultFilePlugin");
var DirectoryDescriptionFilePlugin = require("enhanced-resolve/lib/DirectoryDescriptionFilePlugin");
var DirectoryDescriptionFileFieldAliasPlugin = require("enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin");
var FileAppendPlugin = require("enhanced-resolve/lib/FileAppendPlugin");
var DirectoryResultPlugin = require("enhanced-resolve/lib/DirectoryResultPlugin");
var ResultSymlinkPlugin = require("enhanced-resolve/lib/ResultSymlinkPlugin");

function WebpackOptionsApply() {
	OptionsApply.call(this);
}
module.exports = WebpackOptionsApply;

WebpackOptionsApply.prototype = Object.create(OptionsApply.prototype);
WebpackOptionsApply.prototype.process = function(options, compiler) {
	compiler.context = options.context;
	if(options.plugins && Array.isArray(options.plugins)) {
		compiler.apply.apply(compiler, options.plugins);
	}
	compiler.outputPath = options.output.path;
	compiler.recordsInputPath = options.recordsInputPath || options.recordsPath;
	compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath;
	compiler.name = options.name;
	if(typeof options.target === "string") {
		switch(options.target) {
			case "web":
				var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
				var NodeSourcePlugin = require("./node/NodeSourcePlugin");
				compiler.apply(
					new JsonpTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeSourcePlugin(options.node),
					new LoaderTargetPlugin("web")
				);
				break;
			case "webworker":
				var WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin");
				var NodeSourcePlugin = require("./node/NodeSourcePlugin");
				compiler.apply(
					new WebWorkerTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeSourcePlugin(options.node),
					new LoaderTargetPlugin("webworker")
				);
				break;
			case "node":
			case "async-node":
				var NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				compiler.apply(
					new NodeTemplatePlugin(options.output, options.target === "async-node"),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new LoaderTargetPlugin("node")
				);
				break;
			case "node-webkit":
				var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				var ExternalsPlugin = require("./ExternalsPlugin");
				compiler.apply(
					new JsonpTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new ExternalsPlugin("commonjs", "nw.gui"),
					new LoaderTargetPlugin("node-webkit")
				);
				break;
			case "atom":
			case "electron":
				var NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				var ExternalsPlugin = require("./ExternalsPlugin");
				compiler.apply(
					new NodeTemplatePlugin(options.output, true),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new ExternalsPlugin("commonjs", [
						"app",
						"auto-updater",
						"browser-window",
						"content-tracing",
						"dialog",
						"global-shortcut",
						"ipc",
						"menu",
						"menu-item",
						"power-monitor",
						"protocol",
						"tray",
						"remote",
						"web-view",
						"clipboard",
						"crash-reporter",
						"screen",
						"shell",
						"native-image"
					]),
					new LoaderTargetPlugin(options.target)
				);
				break;
			default:
				throw new Error("Unsupported target '" + options.target + "'.");
		}
	} else if(options.target !== false) {
		options.target(compiler);
	} else {
		throw new Error("Unsupported target '" + options.target + "'.");
	}
	if(options.output.library || options.output.libraryTarget !== "var") {
		var LibraryTemplatePlugin = require("./LibraryTemplatePlugin");
		compiler.apply(new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget, options.output.umdNamedDefine));
	}
	if(options.externals) {
		var ExternalsPlugin = require("./ExternalsPlugin");
		compiler.apply(new ExternalsPlugin(options.output.libraryTarget, options.externals));
	}

	if(options.hot) {
		compiler.apply(new MovedToPluginWarningPlugin("hot", "HotModuleReplacementPlugin"));
		var HotModuleReplacementPlugin = require("./HotModuleReplacementPlugin");
		compiler.apply(new HotModuleReplacementPlugin(options.output));
	}

	if(options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)) {
		var hidden = options.devtool.indexOf("hidden") >= 0;
		var inline = options.devtool.indexOf("inline") >= 0;
		var evalWrapped = options.devtool.indexOf("eval") >= 0;
		var cheap = options.devtool.indexOf("cheap") >= 0;
		var moduleMaps = options.devtool.indexOf("module") >= 0;
		var legacy = options.devtool.indexOf("@") >= 0;
		var modern = options.devtool.indexOf("#") >= 0;
		var comment = legacy && modern ? "\n/*\n//@ sourceMappingURL=[url]\n//# sourceMappingURL=[url]\n*/" :
			legacy ? "\n/*\n//@ sourceMappingURL=[url]\n*/" :
			modern ? "\n//# sourceMappingURL=[url]" :
			null;
		var Plugin = evalWrapped ? EvalSourceMapDevToolPlugin : SourceMapDevToolPlugin;
		compiler.apply(new Plugin({
			filename: inline ? null : options.output.sourceMapFilename,
			moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
			fallbackModuleFilenameTemplate: options.output.devtoolFallbackModuleFilenameTemplate,
			append: hidden ? false : comment,
			module: moduleMaps ? true : cheap ? false : true,
			columns: cheap ? false : true,
			lineToLine: options.output.devtoolLineToLine
		}));
	} else if(options.devtool && options.devtool.indexOf("eval") >= 0) {
		var legacy = options.devtool.indexOf("@") >= 0;
		var modern = options.devtool.indexOf("#") >= 0;
		var comment = legacy && modern ? "//@ sourceURL=[url]\n//# sourceURL=[url]" :
			legacy ? "//@ sourceURL=[url]" :
			modern ? "//# sourceURL=[url]" :
			null;
		compiler.apply(new EvalDevToolModulePlugin(comment, options.output.devtoolModuleFilenameTemplate));
	}

	compiler.apply(new EntryOptionPlugin());
	compiler.applyPluginsBailResult("entry-option", options.context, options.entry);

	if(options.prefetch) {
		compiler.apply(new MovedToPluginWarningPlugin("prefetch", "PrefetchPlugin"));
		var PrefetchPlugin = require("./PrefetchPlugin");
		options.prefetch.map(function(request) {
			compiler.apply(new PrefetchPlugin(options.context, request));
		});
	}
	compiler.apply(
		new CompatibilityPlugin(),
		new LoaderPlugin(),
		new NodeStuffPlugin(options.node),
		new RequireJsStuffPlugin(),
		new APIPlugin(),
		new ConstPlugin(),
		new RequireIncludePlugin(),
		new RequireEnsurePlugin(),
		new RequireContextPlugin(options.resolve.modulesDirectories, options.resolve.extensions),
		new AMDPlugin(options.module, options.amd || {}),
		new CommonJsPlugin(options.module)
	);

	compiler.apply(
		new RemoveParentModulesPlugin(),
		new RemoveEmptyChunksPlugin(),
		new MergeDuplicateChunksPlugin(),
		new FlagIncludedChunksPlugin()
	);

	compiler.apply(new TemplatedPathPlugin());

	compiler.apply(new RecordIdsPlugin());

	compiler.apply(new WarnCaseSensitiveModulesPlugin());

	if(options.optimize && options.optimize.occurenceOrder) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.occurenceOrder", "optimize.OccurrenceOrderPlugin"));
		var OccurrenceOrderPlugin = require("./optimize/OccurrenceOrderPlugin");
		compiler.apply(new OccurrenceOrderPlugin(options.optimize.occurenceOrderPreferEntry));
	}

	if(options.optimize && options.optimize.minChunkSize) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.minChunkSize", "optimize.MinChunkSizePlugin"));
		var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin");
		compiler.apply(new MinChunkSizePlugin(options.optimize));
	}

	if(options.optimize && options.optimize.maxChunks) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.maxChunks", "optimize.LimitChunkCountPlugin"));
		var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin");
		compiler.apply(new LimitChunkCountPlugin(options.optimize));
	}

	if(options.optimize.minimize) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.minimize", "optimize.UglifyJsPlugin"));
		var UglifyJsPlugin = require("./optimize/UglifyJsPlugin");
		if(options.optimize.minimize === true)
			compiler.apply(new UglifyJsPlugin());
		else
			compiler.apply(new UglifyJsPlugin(options.optimize.minimize));
	}

	if(options.cache === undefined ? options.watch : options.cache) {
		var CachePlugin = require("./CachePlugin");
		compiler.apply(new CachePlugin(typeof options.cache === "object" ? options.cache : null));
	}

	if(typeof options.provide === "object") {
		compiler.apply(new MovedToPluginWarningPlugin("provide", "ProvidePlugin"));
		var ProvidePlugin = require("./ProvidePlugin");
		compiler.apply(new ProvidePlugin(options.provide));
	}

	if(options.define) {
		compiler.apply(new MovedToPluginWarningPlugin("define", "DefinePlugin"));
		var defineObject = {};
		if(typeof options.define === "object") {
			Object.keys(options.define).forEach(function(key) {
				defineObject[key] = options.define[key];
			});
		}
		compiler.apply(new DefinePlugin(defineObject));
	}
	if(options.defineDebug !== false)
		compiler.apply(new DefinePlugin({
			DEBUG: !!options.debug
		}));

	compiler.applyPlugins("after-plugins", compiler);
	compiler.resolvers.normal.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		options.resolve.packageAlias ? new DirectoryDescriptionFileFieldAliasPlugin("package.json", options.resolve.packageAlias) : function() {},
		new ModuleAliasPlugin(options.resolve.alias),
		makeRootPlugin("module", options.resolve.root),
		new ModulesInDirectoriesPlugin("module", options.resolve.modulesDirectories),
		makeRootPlugin("module", options.resolve.fallback),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryDescriptionFilePlugin("package.json", options.resolve.packageMains),
		new DirectoryDefaultFilePlugin(["index"]),
		new FileAppendPlugin(options.resolve.extensions),
		new ResultSymlinkPlugin()
	);
	compiler.resolvers.context.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		new ModuleAliasPlugin(options.resolve.alias),
		makeRootPlugin("module", options.resolve.root),
		new ModulesInDirectoriesPlugin("module", options.resolve.modulesDirectories),
		makeRootPlugin("module", options.resolve.fallback),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryResultPlugin(),
		new ResultSymlinkPlugin()
	);
	compiler.resolvers.loader.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		new ModuleAliasPlugin(options.resolveLoader.alias),
		makeRootPlugin("loader-module", options.resolveLoader.root),
		new ModulesInDirectoriesPlugin("loader-module", options.resolveLoader.modulesDirectories),
		makeRootPlugin("loader-module", options.resolveLoader.fallback),
		new ModuleTemplatesPlugin("loader-module", options.resolveLoader.moduleTemplates, "module"),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryDescriptionFilePlugin("package.json", options.resolveLoader.packageMains),
		new DirectoryDefaultFilePlugin(["index"]),
		new FileAppendPlugin(options.resolveLoader.extensions),
		new ResultSymlinkPlugin()
	);
	compiler.applyPlugins("after-resolvers", compiler);
	return options;
};

function makeRootPlugin(name, root) {
	if(typeof root === "string")
		return new ModulesInRootPlugin(name, root);
	else if(Array.isArray(root)) {
		return function() {
			root.forEach(function(root) {
				this.apply(new ModulesInRootPlugin(name, root));
			}, this);
		};
	}
	return function() {};
}
<commit_msg>`electron-main` and `electron-renderer` targets<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var OptionsApply = require("./OptionsApply");

var LoaderTargetPlugin = require("./LoaderTargetPlugin");
var FunctionModulePlugin = require("./FunctionModulePlugin");
var EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
var SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
var EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin");

var EntryOptionPlugin = require("./EntryOptionPlugin");
var RecordIdsPlugin = require("./RecordIdsPlugin");

var APIPlugin = require("./APIPlugin");
var ConstPlugin = require("./ConstPlugin");
var RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
var NodeStuffPlugin = require("./NodeStuffPlugin");
var CompatibilityPlugin = require("./CompatibilityPlugin");
var DefinePlugin = require("./DefinePlugin");

var MovedToPluginWarningPlugin = require("./MovedToPluginWarningPlugin");
var TemplatedPathPlugin = require("./TemplatedPathPlugin");
var WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");

var LoaderPlugin = require("./dependencies/LoaderPlugin");
var CommonJsPlugin = require("./dependencies/CommonJsPlugin");
var AMDPlugin = require("./dependencies/AMDPlugin");
var RequireContextPlugin = require("./dependencies/RequireContextPlugin");
var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");

var RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
var RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
var MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
var FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");

var UnsafeCachePlugin = require("enhanced-resolve/lib/UnsafeCachePlugin");
var ModulesInDirectoriesPlugin = require("enhanced-resolve/lib/ModulesInDirectoriesPlugin");
var ModulesInRootPlugin = require("enhanced-resolve/lib/ModulesInRootPlugin");
var ModuleTemplatesPlugin = require("enhanced-resolve/lib/ModuleTemplatesPlugin");
var ModuleAsFilePlugin = require("enhanced-resolve/lib/ModuleAsFilePlugin");
var ModuleAsDirectoryPlugin = require("enhanced-resolve/lib/ModuleAsDirectoryPlugin");
var ModuleAliasPlugin = require("enhanced-resolve/lib/ModuleAliasPlugin");
var DirectoryDefaultFilePlugin = require("enhanced-resolve/lib/DirectoryDefaultFilePlugin");
var DirectoryDescriptionFilePlugin = require("enhanced-resolve/lib/DirectoryDescriptionFilePlugin");
var DirectoryDescriptionFileFieldAliasPlugin = require("enhanced-resolve/lib/DirectoryDescriptionFileFieldAliasPlugin");
var FileAppendPlugin = require("enhanced-resolve/lib/FileAppendPlugin");
var DirectoryResultPlugin = require("enhanced-resolve/lib/DirectoryResultPlugin");
var ResultSymlinkPlugin = require("enhanced-resolve/lib/ResultSymlinkPlugin");

function WebpackOptionsApply() {
	OptionsApply.call(this);
}
module.exports = WebpackOptionsApply;

WebpackOptionsApply.prototype = Object.create(OptionsApply.prototype);
WebpackOptionsApply.prototype.process = function(options, compiler) {
	compiler.context = options.context;
	if(options.plugins && Array.isArray(options.plugins)) {
		compiler.apply.apply(compiler, options.plugins);
	}
	compiler.outputPath = options.output.path;
	compiler.recordsInputPath = options.recordsInputPath || options.recordsPath;
	compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath;
	compiler.name = options.name;
	if(typeof options.target === "string") {
		switch(options.target) {
			case "web":
				var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
				var NodeSourcePlugin = require("./node/NodeSourcePlugin");
				compiler.apply(
					new JsonpTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeSourcePlugin(options.node),
					new LoaderTargetPlugin("web")
				);
				break;
			case "webworker":
				var WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin");
				var NodeSourcePlugin = require("./node/NodeSourcePlugin");
				compiler.apply(
					new WebWorkerTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeSourcePlugin(options.node),
					new LoaderTargetPlugin("webworker")
				);
				break;
			case "node":
			case "async-node":
				var NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				compiler.apply(
					new NodeTemplatePlugin(options.output, options.target === "async-node"),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new LoaderTargetPlugin("node")
				);
				break;
			case "node-webkit":
				var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				var ExternalsPlugin = require("./ExternalsPlugin");
				compiler.apply(
					new JsonpTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new ExternalsPlugin("commonjs", "nw.gui"),
					new LoaderTargetPlugin("node-webkit")
				);
				break;
			case "atom":
			case "electron":
			case "electron-main":
				var NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				var ExternalsPlugin = require("./ExternalsPlugin");
				compiler.apply(
					new NodeTemplatePlugin(options.output, true),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new ExternalsPlugin("commonjs", [
						"app",
						"auto-updater",
						"browser-window",
						"content-tracing",
						"dialog",
						"global-shortcut",
						"ipc",
						"menu",
						"menu-item",
						"power-monitor",
						"protocol",
						"tray",
						"remote",
						"web-view",
						"clipboard",
						"crash-reporter",
						"screen",
						"shell",
						"native-image"
					]),
					new LoaderTargetPlugin(options.target)
				);
				break;
			case "electron-renderer":
				var JsonpTemplatePlugin = require("./JsonpTemplatePlugin");
				var NodeTargetPlugin = require("./node/NodeTargetPlugin");
				var ExternalsPlugin = require("./ExternalsPlugin");
				compiler.apply(
					new JsonpTemplatePlugin(options.output),
					new FunctionModulePlugin(options.output),
					new NodeTargetPlugin(),
					new ExternalsPlugin("commonjs", [
						"app",
						"auto-updater",
						"browser-window",
						"content-tracing",
						"dialog",
						"global-shortcut",
						"ipc",
						"menu",
						"menu-item",
						"power-monitor",
						"protocol",
						"tray",
						"remote",
						"web-view",
						"clipboard",
						"crash-reporter",
						"screen",
						"shell"
					]),
					new LoaderTargetPlugin(options.target)
				);
				break;
			default:
				throw new Error("Unsupported target '" + options.target + "'.");
		}
	} else if(options.target !== false) {
		options.target(compiler);
	} else {
		throw new Error("Unsupported target '" + options.target + "'.");
	}
	if(options.output.library || options.output.libraryTarget !== "var") {
		var LibraryTemplatePlugin = require("./LibraryTemplatePlugin");
		compiler.apply(new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget, options.output.umdNamedDefine));
	}
	if(options.externals) {
		var ExternalsPlugin = require("./ExternalsPlugin");
		compiler.apply(new ExternalsPlugin(options.output.libraryTarget, options.externals));
	}

	if(options.hot) {
		compiler.apply(new MovedToPluginWarningPlugin("hot", "HotModuleReplacementPlugin"));
		var HotModuleReplacementPlugin = require("./HotModuleReplacementPlugin");
		compiler.apply(new HotModuleReplacementPlugin(options.output));
	}

	if(options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)) {
		var hidden = options.devtool.indexOf("hidden") >= 0;
		var inline = options.devtool.indexOf("inline") >= 0;
		var evalWrapped = options.devtool.indexOf("eval") >= 0;
		var cheap = options.devtool.indexOf("cheap") >= 0;
		var moduleMaps = options.devtool.indexOf("module") >= 0;
		var legacy = options.devtool.indexOf("@") >= 0;
		var modern = options.devtool.indexOf("#") >= 0;
		var comment = legacy && modern ? "\n/*\n//@ sourceMappingURL=[url]\n//# sourceMappingURL=[url]\n*/" :
			legacy ? "\n/*\n//@ sourceMappingURL=[url]\n*/" :
			modern ? "\n//# sourceMappingURL=[url]" :
			null;
		var Plugin = evalWrapped ? EvalSourceMapDevToolPlugin : SourceMapDevToolPlugin;
		compiler.apply(new Plugin({
			filename: inline ? null : options.output.sourceMapFilename,
			moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
			fallbackModuleFilenameTemplate: options.output.devtoolFallbackModuleFilenameTemplate,
			append: hidden ? false : comment,
			module: moduleMaps ? true : cheap ? false : true,
			columns: cheap ? false : true,
			lineToLine: options.output.devtoolLineToLine
		}));
	} else if(options.devtool && options.devtool.indexOf("eval") >= 0) {
		var legacy = options.devtool.indexOf("@") >= 0;
		var modern = options.devtool.indexOf("#") >= 0;
		var comment = legacy && modern ? "//@ sourceURL=[url]\n//# sourceURL=[url]" :
			legacy ? "//@ sourceURL=[url]" :
			modern ? "//# sourceURL=[url]" :
			null;
		compiler.apply(new EvalDevToolModulePlugin(comment, options.output.devtoolModuleFilenameTemplate));
	}

	compiler.apply(new EntryOptionPlugin());
	compiler.applyPluginsBailResult("entry-option", options.context, options.entry);

	if(options.prefetch) {
		compiler.apply(new MovedToPluginWarningPlugin("prefetch", "PrefetchPlugin"));
		var PrefetchPlugin = require("./PrefetchPlugin");
		options.prefetch.map(function(request) {
			compiler.apply(new PrefetchPlugin(options.context, request));
		});
	}
	compiler.apply(
		new CompatibilityPlugin(),
		new LoaderPlugin(),
		new NodeStuffPlugin(options.node),
		new RequireJsStuffPlugin(),
		new APIPlugin(),
		new ConstPlugin(),
		new RequireIncludePlugin(),
		new RequireEnsurePlugin(),
		new RequireContextPlugin(options.resolve.modulesDirectories, options.resolve.extensions),
		new AMDPlugin(options.module, options.amd || {}),
		new CommonJsPlugin(options.module)
	);

	compiler.apply(
		new RemoveParentModulesPlugin(),
		new RemoveEmptyChunksPlugin(),
		new MergeDuplicateChunksPlugin(),
		new FlagIncludedChunksPlugin()
	);

	compiler.apply(new TemplatedPathPlugin());

	compiler.apply(new RecordIdsPlugin());

	compiler.apply(new WarnCaseSensitiveModulesPlugin());

	if(options.optimize && options.optimize.occurenceOrder) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.occurenceOrder", "optimize.OccurrenceOrderPlugin"));
		var OccurrenceOrderPlugin = require("./optimize/OccurrenceOrderPlugin");
		compiler.apply(new OccurrenceOrderPlugin(options.optimize.occurenceOrderPreferEntry));
	}

	if(options.optimize && options.optimize.minChunkSize) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.minChunkSize", "optimize.MinChunkSizePlugin"));
		var MinChunkSizePlugin = require("./optimize/MinChunkSizePlugin");
		compiler.apply(new MinChunkSizePlugin(options.optimize));
	}

	if(options.optimize && options.optimize.maxChunks) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.maxChunks", "optimize.LimitChunkCountPlugin"));
		var LimitChunkCountPlugin = require("./optimize/LimitChunkCountPlugin");
		compiler.apply(new LimitChunkCountPlugin(options.optimize));
	}

	if(options.optimize.minimize) {
		compiler.apply(new MovedToPluginWarningPlugin("optimize.minimize", "optimize.UglifyJsPlugin"));
		var UglifyJsPlugin = require("./optimize/UglifyJsPlugin");
		if(options.optimize.minimize === true)
			compiler.apply(new UglifyJsPlugin());
		else
			compiler.apply(new UglifyJsPlugin(options.optimize.minimize));
	}

	if(options.cache === undefined ? options.watch : options.cache) {
		var CachePlugin = require("./CachePlugin");
		compiler.apply(new CachePlugin(typeof options.cache === "object" ? options.cache : null));
	}

	if(typeof options.provide === "object") {
		compiler.apply(new MovedToPluginWarningPlugin("provide", "ProvidePlugin"));
		var ProvidePlugin = require("./ProvidePlugin");
		compiler.apply(new ProvidePlugin(options.provide));
	}

	if(options.define) {
		compiler.apply(new MovedToPluginWarningPlugin("define", "DefinePlugin"));
		var defineObject = {};
		if(typeof options.define === "object") {
			Object.keys(options.define).forEach(function(key) {
				defineObject[key] = options.define[key];
			});
		}
		compiler.apply(new DefinePlugin(defineObject));
	}
	if(options.defineDebug !== false)
		compiler.apply(new DefinePlugin({
			DEBUG: !!options.debug
		}));

	compiler.applyPlugins("after-plugins", compiler);
	compiler.resolvers.normal.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		options.resolve.packageAlias ? new DirectoryDescriptionFileFieldAliasPlugin("package.json", options.resolve.packageAlias) : function() {},
		new ModuleAliasPlugin(options.resolve.alias),
		makeRootPlugin("module", options.resolve.root),
		new ModulesInDirectoriesPlugin("module", options.resolve.modulesDirectories),
		makeRootPlugin("module", options.resolve.fallback),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryDescriptionFilePlugin("package.json", options.resolve.packageMains),
		new DirectoryDefaultFilePlugin(["index"]),
		new FileAppendPlugin(options.resolve.extensions),
		new ResultSymlinkPlugin()
	);
	compiler.resolvers.context.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		new ModuleAliasPlugin(options.resolve.alias),
		makeRootPlugin("module", options.resolve.root),
		new ModulesInDirectoriesPlugin("module", options.resolve.modulesDirectories),
		makeRootPlugin("module", options.resolve.fallback),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryResultPlugin(),
		new ResultSymlinkPlugin()
	);
	compiler.resolvers.loader.apply(
		new UnsafeCachePlugin(options.resolve.unsafeCache),
		new ModuleAliasPlugin(options.resolveLoader.alias),
		makeRootPlugin("loader-module", options.resolveLoader.root),
		new ModulesInDirectoriesPlugin("loader-module", options.resolveLoader.modulesDirectories),
		makeRootPlugin("loader-module", options.resolveLoader.fallback),
		new ModuleTemplatesPlugin("loader-module", options.resolveLoader.moduleTemplates, "module"),
		new ModuleAsFilePlugin("module"),
		new ModuleAsDirectoryPlugin("module"),
		new DirectoryDescriptionFilePlugin("package.json", options.resolveLoader.packageMains),
		new DirectoryDefaultFilePlugin(["index"]),
		new FileAppendPlugin(options.resolveLoader.extensions),
		new ResultSymlinkPlugin()
	);
	compiler.applyPlugins("after-resolvers", compiler);
	return options;
};

function makeRootPlugin(name, root) {
	if(typeof root === "string")
		return new ModulesInRootPlugin(name, root);
	else if(Array.isArray(root)) {
		return function() {
			root.forEach(function(root) {
				this.apply(new ModulesInRootPlugin(name, root));
			}, this);
		};
	}
	return function() {};
}
<|endoftext|>