/*jshint node:true */
|
/*
|
|
The MIT License (MIT)
|
|
Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
|
|
Permission is hereby granted, free of charge, to any person
|
obtaining a copy of this software and associated documentation files
|
(the "Software"), to deal in the Software without restriction,
|
including without limitation the rights to use, copy, modify, merge,
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
and to permit persons to whom the Software is furnished to do so,
|
subject to the following conditions:
|
|
The above copyright notice and this permission notice shall be
|
included in all copies or substantial portions of the Software.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
SOFTWARE.
|
*/
|
|
'use strict';
|
|
function Options(options, merge_child_field) {
|
this.raw_options = _mergeOpts(options, merge_child_field);
|
|
// Support passing the source text back with no change
|
this.disabled = this._get_boolean('disabled');
|
|
this.eol = this._get_characters('eol', 'auto');
|
this.end_with_newline = this._get_boolean('end_with_newline');
|
this.indent_size = this._get_number('indent_size', 4);
|
this.indent_char = this._get_characters('indent_char', ' ');
|
this.indent_level = this._get_number('indent_level');
|
|
this.preserve_newlines = this._get_boolean('preserve_newlines', true);
|
this.max_preserve_newlines = this._get_number('max_preserve_newlines', 32786);
|
if (!this.preserve_newlines) {
|
this.max_preserve_newlines = 0;
|
}
|
|
this.indent_with_tabs = this._get_boolean('indent_with_tabs', this.indent_char === '\t');
|
if (this.indent_with_tabs) {
|
this.indent_char = '\t';
|
|
// indent_size behavior changed after 1.8.6
|
// It used to be that indent_size would be
|
// set to 1 for indent_with_tabs. That is no longer needed and
|
// actually doesn't make sense - why not use spaces? Further,
|
// that might produce unexpected behavior - tabs being used
|
// for single-column alignment. So, when indent_with_tabs is true
|
// and indent_size is 1, reset indent_size to 4.
|
if (this.indent_size === 1) {
|
this.indent_size = 4;
|
}
|
}
|
|
// Backwards compat with 1.3.x
|
this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char'));
|
|
this.indent_empty_lines = this._get_boolean('indent_empty_lines');
|
|
// valid templating languages ['django', 'erb', 'handlebars', 'php', 'smarty']
|
// For now, 'auto' = all off for javascript, all on for html (and inline javascript).
|
// other values ignored
|
this.templating = this._get_selection_list('templating', ['auto', 'none', 'django', 'erb', 'handlebars', 'php', 'smarty'], ['auto']);
|
}
|
|
Options.prototype._get_array = function(name, default_value) {
|
var option_value = this.raw_options[name];
|
var result = default_value || [];
|
if (typeof option_value === 'object') {
|
if (option_value !== null && typeof option_value.concat === 'function') {
|
result = option_value.concat();
|
}
|
} else if (typeof option_value === 'string') {
|
result = option_value.split(/[^a-zA-Z0-9_\/\-]+/);
|
}
|
return result;
|
};
|
|
Options.prototype._get_boolean = function(name, default_value) {
|
var option_value = this.raw_options[name];
|
var result = option_value === undefined ? !!default_value : !!option_value;
|
return result;
|
};
|
|
Options.prototype._get_characters = function(name, default_value) {
|
var option_value = this.raw_options[name];
|
var result = default_value || '';
|
if (typeof option_value === 'string') {
|
result = option_value.replace(/\\r/, '\r').replace(/\\n/, '\n').replace(/\\t/, '\t');
|
}
|
return result;
|
};
|
|
Options.prototype._get_number = function(name, default_value) {
|
var option_value = this.raw_options[name];
|
default_value = parseInt(default_value, 10);
|
if (isNaN(default_value)) {
|
default_value = 0;
|
}
|
var result = parseInt(option_value, 10);
|
if (isNaN(result)) {
|
result = default_value;
|
}
|
return result;
|
};
|
|
Options.prototype._get_selection = function(name, selection_list, default_value) {
|
var result = this._get_selection_list(name, selection_list, default_value);
|
if (result.length !== 1) {
|
throw new Error(
|
"Invalid Option Value: The option '" + name + "' can only be one of the following values:\n" +
|
selection_list + "\nYou passed in: '" + this.raw_options[name] + "'");
|
}
|
|
return result[0];
|
};
|
|
|
Options.prototype._get_selection_list = function(name, selection_list, default_value) {
|
if (!selection_list || selection_list.length === 0) {
|
throw new Error("Selection list cannot be empty.");
|
}
|
|
default_value = default_value || [selection_list[0]];
|
if (!this._is_valid_selection(default_value, selection_list)) {
|
throw new Error("Invalid Default Value!");
|
}
|
|
var result = this._get_array(name, default_value);
|
if (!this._is_valid_selection(result, selection_list)) {
|
throw new Error(
|
"Invalid Option Value: The option '" + name + "' can contain only the following values:\n" +
|
selection_list + "\nYou passed in: '" + this.raw_options[name] + "'");
|
}
|
|
return result;
|
};
|
|
Options.prototype._is_valid_selection = function(result, selection_list) {
|
return result.length && selection_list.length &&
|
!result.some(function(item) { return selection_list.indexOf(item) === -1; });
|
};
|
|
|
// merges child options up with the parent options object
|
// Example: obj = {a: 1, b: {a: 2}}
|
// mergeOpts(obj, 'b')
|
//
|
// Returns: {a: 2}
|
function _mergeOpts(allOptions, childFieldName) {
|
var finalOpts = {};
|
allOptions = _normalizeOpts(allOptions);
|
var name;
|
|
for (name in allOptions) {
|
if (name !== childFieldName) {
|
finalOpts[name] = allOptions[name];
|
}
|
}
|
|
//merge in the per type settings for the childFieldName
|
if (childFieldName && allOptions[childFieldName]) {
|
for (name in allOptions[childFieldName]) {
|
finalOpts[name] = allOptions[childFieldName][name];
|
}
|
}
|
return finalOpts;
|
}
|
|
function _normalizeOpts(options) {
|
var convertedOpts = {};
|
var key;
|
|
for (key in options) {
|
var newKey = key.replace(/-/g, "_");
|
convertedOpts[newKey] = options[key];
|
}
|
return convertedOpts;
|
}
|
|
module.exports.Options = Options;
|
module.exports.normalizeOpts = _normalizeOpts;
|
module.exports.mergeOpts = _mergeOpts;
|