diff --git a/.gitignore b/.gitignore index ade14b9..4f88a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store npm-debug.log node_modules +src/options.json \ No newline at end of file diff --git a/package.json b/package.json index f8feed8..6cb34de 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "bluebird": "^2.9.30", "coffee-fmt": "0.11.0", "coffee-formatter": "^0.1.2", + "coffee-script": "^1.10.0", "cross-spawn": "^2.0.0", "csscomb": "^3.1.7", "diff": "^2.1.0", @@ -179,11 +180,11 @@ "elm" ], "devDependencies": { - "coffee-script": "^1.9.3", "coffeelint": "^1.10.1", "handlebars": "^4.0.2" }, "scripts": { + "postinstall": "./node_modules/.bin/coffee script/build-options.coffee", "prepublish": "npm run docs", "docs": "coffee docs/", "lint": "coffeelint src/ spec/", diff --git a/script/build-options.coffee b/script/build-options.coffee new file mode 100644 index 0000000..9578e0b --- /dev/null +++ b/script/build-options.coffee @@ -0,0 +1,202 @@ +fs = require('fs') +path = require('path') +_ = require('lodash') +_plus = require('underscore-plus') +Beautifiers = require("../src/beautifiers") + +buildOptionsForBeautifiers = (beautifiers, allLanguages) -> + + # Get all Options for Languages + langOptions = {} + languages = {} # Hash map of languages with their names + for lang in allLanguages + # Use the namespace from language as key prefix + namespace = lang.namespace + langOptions[namespace] ?= { + title: lang.name, + type: 'object', + description: "Options for language #{lang.name}" + collapsed: true + beautifiers: [] + properties: {} + } + languages[lang.name] ?= lang + options = _.get(langOptions, "#{namespace}.properties") + + # Init field for supported beautifiers + lang.beautifiers = [] + + # Process all language options + for field, op of lang.options + if not op.title? + op.title = _plus.uncamelcase(field).split('.') + .map(_plus.capitalize).join(' ') + # op.title = "#{lang.name} - #{op.title}" + + # Init field for supported beautifiers + op.beautifiers = [] + + # Remember Option's Key + op.key = field + + # Remember Option's Language + op.language = { + name: lang.name, + namespace: lang.namespace + } + # Add option + options[field] = op + + # Language fallback options + for lang in allLanguages + # Use the namespace from language as key prefix + namespaceDest = lang.namespace + optionsDest = _.get(langOptions, "#{namespaceDest}.properties") + fallback = _.reverse(lang.fallback ? []) + for namespaceSrc in fallback + optionsSrc = _.get(langOptions, "#{namespaceSrc}.properties") + _.merge(optionsDest, optionsSrc) + + # Find supported beautifiers for each language + for beautifier in beautifiers + beautifierName = beautifier.name + + # Iterate over supported languages + for languageName, options of beautifier.options + namespace = languages[languageName].namespace + laOp = _.get(langOptions, "#{namespace}.properties") + + # Is a valid Language name + if typeof options is "boolean" + + # Enable / disable all options + # Add Beautifier support to Language + languages[languageName]?.beautifiers.push(beautifierName) + _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) + + # Check for beautifier's options support + if options is true + + # Beautifier supports all options for this language + if laOp + + # logger.verbose('add supported beautifier', languageName, beautifierName) + for field, op of laOp + op.beautifiers.push(beautifierName) + else + + # Supports language but no options specifically + logger.warn("Could not find options for language: #{languageName}") + else if typeof options is "object" + + # Iterate over beautifier's options for this language + for field, op of options + if typeof op is "boolean" + + # Transformation + if op is true + languages[languageName]?.beautifiers.push(beautifierName) + _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) + laOp?[field]?.beautifiers.push(beautifierName) + else if typeof op is "string" + + # Rename + # logger.verbose('support option with rename:', field, op, languageName, beautifierName, langOptions) + languages[languageName]?.beautifiers.push(beautifierName) + laOp?[op]?.beautifiers.push(beautifierName) + else if typeof op is "function" + + # Transformation + languages[languageName]?.beautifiers.push(beautifierName) + _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) + laOp?[field]?.beautifiers.push(beautifierName) + else if _.isArray(op) + + # Complex Function + [fields..., fn] = op + + # Add beautifier support to all required fields + languages[languageName]?.beautifiers.push(beautifierName) + _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) + for f in fields + + # Add beautifier to required field + laOp?[f]?.beautifiers.push(beautifierName) + else + + # Unsupported + logger.warn("Unsupported option:", beautifierName, languageName, field, op, langOptions) + + # Improve descriptions to each language option + unsupportedOptions = [] + for g,group of langOptions + for o,optionDef of group.properties + if optionDef.beautifiers.length > 0 + optionDef.description = "#{optionDef.description} (Supported by #{optionDef.beautifiers.join(', ')})" + else + # optionDef.description = "#{optionDef.description} (Not supported by any beautifiers)" + # logger.warn("#{g}'s option '#{optionDef.title} not supported by any beautifiers!") + unsupportedOptions.push("#{g}.properties.#{o}") + # Delete unsupported options + for p in unsupportedOptions + _.unset(langOptions, p) + + # Generate Language configurations + # logger.verbose('languages', languages) + for langName, lang of languages + + # logger.verbose(langName, lang) + name = lang.name + namespace = lang.namespace + beautifiers = lang.beautifiers + optionName = "language_#{namespace}" + + # Add Language configurations + _.set(langOptions, "#{namespace}.properties.disabled", { + title : "Disable Beautifying Language" + order : -3 + type : 'boolean' + default : false + description : "Disable #{name} Beautification" + }) + + defaultBeautifier = lang.defaultBeautifier ? beautifiers[0] + _.set(langOptions, "#{namespace}.properties.default_beautifier", { + title : "Default Beautifier" + order : -2 + type : 'string' + default : defaultBeautifier + description : "Default Beautifier to be used for #{name}" + enum : _.uniq(beautifiers) + }) + if !_.includes(beautifiers, defaultBeautifier) + logger.warn("Language #{name} has a default beautifier of #{defaultBeautifier}, however it is not one of the supported beautifiers: #{optionDef.beautifiers.join(', ')}.") + + _.set(langOptions, "#{namespace}.properties.beautify_on_save", { + title : "Beautify On Save" + order : -1 + type : 'boolean' + default : false + description : "Automatically beautify #{name} files on save" + }) + + # logger.verbose('langOptions', langOptions) + return langOptions + +beautifier = new Beautifiers() +# console.log(beautifier.languages.languages) +# Build options from @beautifiers and @languages +console.log('Building options for beautifiers') +beautifierOptions = buildOptionsForBeautifiers(beautifier.beautifiers, beautifier.languages.languages) +console.log('Done building options for beautifiers') +# Save options to file +optionsStr = JSON.stringify(beautifierOptions, null, 2) +outputFilename = path.resolve(__dirname,'../src/options.json') +fs.writeFile(outputFilename, optionsStr, (err) -> + if err + console.log('An error occured saving the beautifier options') + console.error(err) + else + console.log("Beautifier options successfully saved to " + outputFilename) +) + diff --git a/src/beautifiers/index.coffee b/src/beautifiers/index.coffee index 3981bad..491857a 100644 --- a/src/beautifiers/index.coffee +++ b/src/beautifiers/index.coffee @@ -95,188 +95,11 @@ module.exports = class Beautifiers extends EventEmitter new Beautifier() ) - - # Build options from @beautifiers and @languages - @options = @buildOptionsForBeautifiers( @beautifiers) - - - buildOptionsForBeautifiers : (beautifiers) -> - - # Get all Options for Languages - langOptions = {} - languages = {} # Hash map of languages with their names - for lang in @languages.languages - # Use the namespace from language as key prefix - namespace = lang.namespace - langOptions[namespace] ?= { - title: lang.name, - type: 'object', - description: "Options for language #{lang.name}" - collapsed: true - beautifiers: [] - properties: {} - } - languages[lang.name] ?= lang - options = _.get(langOptions, "#{namespace}.properties") - - # Init field for supported beautifiers - lang.beautifiers = [] - - # Process all language options - for field, op of lang.options - if not op.title? - op.title = _plus.uncamelcase(field).split('.') - .map(_plus.capitalize).join(' ') - # op.title = "#{lang.name} - #{op.title}" - - # Init field for supported beautifiers - op.beautifiers = [] - - # Remember Option's Key - op.key = field - - # Remember Option's Language - op.language = lang - - # Add option - options[field] = op - - # Language fallback options - for lang in @languages.languages - # Use the namespace from language as key prefix - namespaceDest = lang.namespace - optionsDest = _.get(langOptions, "#{namespaceDest}.properties") - fallback = _.reverse(lang.fallback ? []) - for namespaceSrc in fallback - optionsSrc = _.get(langOptions, "#{namespaceSrc}.properties") - _.merge(optionsDest, optionsSrc) - - # Find supported beautifiers for each language - for beautifier in beautifiers - beautifierName = beautifier.name - - # Iterate over supported languages - for languageName, options of beautifier.options - namespace = languages[languageName].namespace - laOp = _.get(langOptions, "#{namespace}.properties") - - # Is a valid Language name - if typeof options is "boolean" - - # Enable / disable all options - # Add Beautifier support to Language - languages[languageName]?.beautifiers.push(beautifierName) - _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) - - # Check for beautifier's options support - if options is true - - # Beautifier supports all options for this language - if laOp - - # logger.verbose('add supported beautifier', languageName, beautifierName) - for field, op of laOp - op.beautifiers.push(beautifierName) - else - - # Supports language but no options specifically - logger.warn("Could not find options for language: #{languageName}") - else if typeof options is "object" - - # Iterate over beautifier's options for this language - for field, op of options - if typeof op is "boolean" - - # Transformation - if op is true - languages[languageName]?.beautifiers.push(beautifierName) - _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) - laOp?[field]?.beautifiers.push(beautifierName) - else if typeof op is "string" - - # Rename - # logger.verbose('support option with rename:', field, op, languageName, beautifierName, langOptions) - languages[languageName]?.beautifiers.push(beautifierName) - laOp?[op]?.beautifiers.push(beautifierName) - else if typeof op is "function" - - # Transformation - languages[languageName]?.beautifiers.push(beautifierName) - _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) - laOp?[field]?.beautifiers.push(beautifierName) - else if _.isArray(op) - - # Complex Function - [fields..., fn] = op - - # Add beautifier support to all required fields - languages[languageName]?.beautifiers.push(beautifierName) - _.get(langOptions, "#{namespace}.beautifiers")?.push(beautifierName) - for f in fields - - # Add beautifier to required field - laOp?[f]?.beautifiers.push(beautifierName) - else - - # Unsupported - logger.warn("Unsupported option:", beautifierName, languageName, field, op, langOptions) - - # Improve descriptions to each language option - unsupportedOptions = [] - for g,group of langOptions - for o,optionDef of group.properties - if optionDef.beautifiers.length > 0 - optionDef.description = "#{optionDef.description} (Supported by #{optionDef.beautifiers.join(', ')})" - else - # optionDef.description = "#{optionDef.description} (Not supported by any beautifiers)" - # logger.warn("#{g}'s option '#{optionDef.title} not supported by any beautifiers!") - unsupportedOptions.push("#{g}.properties.#{o}") - # Delete unsupported options - for p in unsupportedOptions - _.unset(langOptions, p) - - # Generate Language configurations - # logger.verbose('languages', languages) - for langName, lang of languages - - # logger.verbose(langName, lang) - name = lang.name - namespace = lang.namespace - beautifiers = lang.beautifiers - optionName = "language_#{namespace}" - - # Add Language configurations - _.set(langOptions, "#{namespace}.properties.disabled", { - title : "Disable Beautifying Language" - order : -3 - type : 'boolean' - default : false - description : "Disable #{name} Beautification" - }) - - defaultBeautifier = lang.defaultBeautifier ? beautifiers[0] - _.set(langOptions, "#{namespace}.properties.default_beautifier", { - title : "Default Beautifier" - order : -2 - type : 'string' - default : defaultBeautifier - description : "Default Beautifier to be used for #{name}" - enum : _.uniq(beautifiers) - }) - if !_.includes(beautifiers, defaultBeautifier) - logger.warn("Language #{name} has a default beautifier of #{defaultBeautifier}, however it is not one of the supported beautifiers: #{optionDef.beautifiers.join(', ')}.") - - _.set(langOptions, "#{namespace}.properties.beautify_on_save", { - title : "Beautify On Save" - order : -1 - type : 'boolean' - default : false - description : "Automatically beautify #{name} files on save" - }) - - # logger.verbose('langOptions', langOptions) - return langOptions - + try + @options = require('../options.json') + catch + console.warn('Beautifier options not found.') + @options = {} ### From https://github.com/atom/notifications/blob/01779ade79e7196f1603b8c1fa31716aa4a33911/lib/notification-issue.coffee#L130