diff --git a/lib/settings.js b/lib/settings.js index acb48e8..3a1b0c3 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -955,64 +955,156 @@ exports.blockchain_specific = { } }; -exports.reloadSettings = function reloadSettings() { - // Discover where the settings file lives - var settingsFilename = "settings.json"; - settingsFilename = "./" + settingsFilename; - - var settingsStr; - try{ - //read the settings sync - settingsStr = fs.readFileSync(settingsFilename).toString(); - } catch(e){ - console.warn('No settings file found. Continuing using defaults!'); - } - - // try to parse the settings +exports.loadSettings = function loadSettings() { + var settings_filename = "./settings.json"; var settings; - try { - if(settingsStr) { - settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); - settings = JSON.parse(settingsStr); + var json_settings; + // define an exception list of setting json paths (period separated) that do not have defaults and should not throw 'unknown setting' errors + var exceptions = ['labels']; + + // check if the settings.json file exists + if (fs.existsSync(settings_filename)) { + try { + // read settings.json into a string variable + settings = fs.readFileSync(settings_filename).toString(); + } catch(e) { + console.warn('The settings.json file is missing. Continuing using defaults.'); } - }catch(e){ - console.error('There was an error processing your settings.json file: '+e.message); + } else + console.warn('The settings.json file is missing. Continuing using defaults.'); + + try { + // check if the settings string was populated + if (settings) { + // get settings string ready for json conversion + settings = jsonminify(settings).replace(",]","]").replace(",}","}"); + // convert settings string to json object + json_settings = JSON.parse(settings); + } + } catch(e) { + console.error('There was an error processing your settings.json file: ' + e.message); process.exit(1); } - //loop trough the settings - for(var i in settings) - { - //test if the setting start with a low character - if(i.charAt(0).search("[a-z]") !== 0) - { - console.warn("Settings should start with a low character: '" + i + "'"); + // check if the json settings were populated + if (json_settings != null) { + // loop through all settings from the settings.json file + for (var current_setting in json_settings) { + // merge settings from settings.json with the defaults from settings.js + merge_settings(json_settings, exceptions, json_settings[current_setting], current_setting); } - //we know this setting, so we overwrite it - if(exports[i] !== undefined) - { - // This check uses old .user and .pass config strings if they exist, and .username, .password don't. - if (i == 'wallet') - { - if (!settings.wallet.hasOwnProperty('username') && settings.wallet.hasOwnProperty('user')) - { - settings.wallet.username = settings.wallet.user; - } - if (!settings.wallet.hasOwnProperty('password') && settings.wallet.hasOwnProperty('pass')) - { - settings.wallet.password = settings.wallet.pass; - } - } - exports[i] = settings[i]; - } - //this setting is unkown, output a warning and throw it away - else - { - console.warn("Unknown Setting: '" + i + "'. This setting doesn't exist or it was removed"); + // re-initialize the exceptions list + exceptions = ['loadSettings']; + + // loop through the loaded/default settings (settings.js) to look for missing settings + for (var current_setting in exports) { + // look for missing settings from settings.json based on the defaults from settings.js + check_missing_settings(json_settings, exceptions, exports[current_setting], current_setting); } } }; -// initially load settings -exports.reloadSettings(); \ No newline at end of file +// define a recursive function used to merge settings from different json objects +merge_settings = function(json_settings, exceptions, current_setting, path) { + // check if this is an object with more properties + if (typeof current_setting === 'object' && current_setting !== null) { + // this is an object + // check if this object already exists in the default settings (settings.js) + if (Object.byString(exports, path) == null) { + // this setting object does not exist in settings.js + // show warning msg + console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed."); + } else { + // the object exists in the loaded settings + // check if the object is an array or is one of the exceptions + if (Array.isArray(current_setting) || exceptions.indexOf(path) > -1) { + // the object is an array or is an exception + // merge the object into settings.js without checking object keys + eval('exports' + fix_object_path(path) + ' = ' + JSON.stringify(Object.byString(json_settings, path))); + } else { + // the object is not an array or an exception + // loop through the object keys to continue checking for missing properties + for (var setting_name in current_setting) { + // recursively step through all properties of this object and merge setting values + merge_settings(json_settings, exceptions, current_setting[setting_name], path + '.' + setting_name); + } + } + } + } else { + // this is a property + // check if this property already exists in the default settings (settings.js) + if (Object.byString(exports, path) == null) { + // this setting property does not exist in settings.js + // show warning msg + console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed."); + } else { + // the property exists in the loaded settings + // get the settings.json value + var setting_value = Object.byString(json_settings, path); + // overwrite the property value with the value from settings.json + eval('exports' + fix_object_path(path) + ' = ' + (typeof setting_value === "string" ? '"' : '') + setting_value + (typeof setting_value === "string" ? '"' : '')); + } + } +} + +// define a recursive function used to check settings for missing entries between json objects +check_missing_settings = function(json_settings, exceptions, current_setting, path) { + // check if this is an object with more properties + if (typeof current_setting === 'object' && current_setting !== null) { + // this is an object + // check if this object exists in the json settings (settings.json) + if (Object.byString(json_settings, path) == null) { + // this setting object does not exist in settings.json + // check if it is an exception + if (exceptions.indexOf(path) == -1) { + // this is not one of the exceptions + // show warning msg + console.warn("setting '" + path + "' is missing. Loading default value."); + } + } else { + // the object exists in the json settings + // loop through the object keys to continue checking for missing properties + for (var setting_name in current_setting) { + // recursively step through all properties of this object + check_missing_settings(json_settings, exceptions, current_setting[setting_name], path + '.' + setting_name); + } + } + } else { + // this is a property + // check if this property exists in the json settings (settings.json) + if (Object.byString(json_settings, path) == null) { + // this setting property does not exist in settings.json + // check if it is an exception + if (exceptions.indexOf(path) == -1) { + // this is not one of the exceptions + // show warning msg + console.warn("setting '" + path + "' is missing. Loading default value."); + } + } + } +} + +// define a function used to fix object paths +fix_object_path = function(path) { + return "['" + path.replace(/\./g, "']['") + "']"; +} + +/* Special thanks to Alnitak for the Object.byString function: https://stackoverflow.com/a/6491621/3038650 */ +Object.byString = function(o, s) { + s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties + s = s.replace(/^\./, ''); // strip a leading dot + var a = s.split('.'); + for (var i = 0, n = a.length; i < n; ++i) { + var k = a[i]; + if (k in o) { + o = o[k]; + } else { + return; + } + } + return o; +} + +// populate settings +exports.loadSettings(); \ No newline at end of file diff --git a/scripts/sass_theme_reader.sh b/scripts/sass_theme_reader.sh index f29ebff..38c161e 100644 --- a/scripts/sass_theme_reader.sh +++ b/scripts/sass_theme_reader.sh @@ -1,3 +1,7 @@ #!/bin/bash -echo "\$theme-name: \"$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json shared_pages.theme)\";" > ./public/css/_theme-selector.scss +if [ -f ./settings.json ]; then + echo "\$theme-name: \"$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json shared_pages.theme)\";" > ./public/css/_theme-selector.scss +else + echo "\$theme-name: \"Exor\";" > ./public/css/_theme-selector.scss +fi \ No newline at end of file