From c5b2459e9dfe24aa7244ebf113ff87390acf0848 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Fri, 8 May 2020 20:53:00 +0100 Subject: [PATCH] Roll our own js to conf solution & use kv --- package-lock.json | 29 --------- package.json | 2 - src/nginxconfig/generators/index.js | 18 ++--- src/nginxconfig/generators/nginx.conf.js | 83 ++++++++++++------------ src/nginxconfig/generators/to_conf.js | 51 +++++++++++++++ src/nginxconfig/scss/style.scss | 8 ++- src/nginxconfig/templates/app.vue | 13 ++-- 7 files changed, 115 insertions(+), 89 deletions(-) create mode 100644 src/nginxconfig/generators/to_conf.js diff --git a/package-lock.json b/package-lock.json index a413ff1..785a17f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1117,14 +1117,6 @@ } } }, - "@webantic/nginx-config-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webantic/nginx-config-parser/-/nginx-config-parser-1.2.0.tgz", - "integrity": "sha512-f+APSFykPZ06UaRgaxBCxAEUSG+qY9NVcGGqQkKfnJZaHBpqGxlR4FZixkdapnIadbw/uyWQ+96iTAXjyyJ+SQ==", - "requires": { - "glob": "^7.1.3" - } - }, "abab": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", @@ -1793,14 +1785,6 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "chevrotain": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.0.1.tgz", - "integrity": "sha512-B/44jrdw5GAzy483LEeVSgXSX0qOYM8lUd3l5+yf6Vl6OQjEUCm2BUiYbHRCIK6xCEvCLAFe1kj8uyV6+zdaVw==", - "requires": { - "regexp-to-ast": "0.5.0" - } - }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -5404,14 +5388,6 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nginx-format": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/nginx-format/-/nginx-format-0.1.7.tgz", - "integrity": "sha512-+6k0BGrASE0vE4X2sYujh0k2cZG+2DT0G82N3O+hS/7/7b3ZNzfHogthRGIJB+2xSJOvgIbJgKRVjqpyerPOtw==", - "requires": { - "chevrotain": "^7.0.1" - } - }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -6673,11 +6649,6 @@ "safe-regex": "^1.1.0" } }, - "regexp-to-ast": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", diff --git a/package.json b/package.json index c46fd70..bcf03ef 100644 --- a/package.json +++ b/package.json @@ -34,12 +34,10 @@ "homepage": "https://github.com/do-community/nginxconfig-vue#readme", "dependencies": { "@babel/runtime": "^7.9.2", - "@webantic/nginx-config-parser": "^1.2.0", "babel-polyfill": "^6.26.0", "clone": "^2.1.2", "do-bulma": "git+https://github.com/do-community/do-bulma.git", "do-vue": "git+https://github.com/do-community/do-vue.git", - "nginx-format": "^0.1.7", "parcel-bundler": "^1.12.4", "pretty-checkbox-vue": "^1.1.9", "prismjs": "^1.20.0", diff --git a/src/nginxconfig/generators/index.js b/src/nginxconfig/generators/index.js index ab47395..22276b0 100644 --- a/src/nginxconfig/generators/index.js +++ b/src/nginxconfig/generators/index.js @@ -1,18 +1,14 @@ -import ConfigParser from '@webantic/nginx-config-parser'; -const parser = new ConfigParser(); - -import { nginxFormat } from 'nginx-format'; - +import toConf from './to_conf'; import nginxConf from './nginx.conf'; -const toConf = obj => { +const toConfig = obj => { // Convert the obj to nginx - const rawConf = nginxFormat(parser.toConf(obj)); + const rawConf = toConf(obj); + // Do some magic to comments const commentConf = rawConf - .replace(/((?:^|\n)(?:[^\S\r\n]*)#.+);($|\n)/g, '$1$2') // Remove semis on comments - .replace(/((?:^|\n)[^\S\r\n]*[^#\s].*[^\n])\n([^\S\r\n]*)#/g, '$1\n$2\n$2#') // Double linebreak before comment - .replace(/((?:^|\n)[^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*)([^#\s])/g, '$1\n$2$3'); // Double linebreak after double comment + .replace(/^([^\S\r\n]*[^#\s].*[^\n])\n([^\S\r\n]*)#/gm, '$1\n\n$2#') // Double linebreak before comment + .replace(/^([^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*[^#\s])/gm, '$1\n$2') // Double linebreak after double comment return commentConf; } @@ -20,7 +16,7 @@ const toConf = obj => { export default (domains, global) => { const files = {}; - files['nginx.conf'] = toConf(nginxConf(domains, global)); + files['nginx.conf'] = toConfig(nginxConf(domains, global)); return files; } diff --git a/src/nginxconfig/generators/nginx.conf.js b/src/nginxconfig/generators/nginx.conf.js index 4d136d0..f1ab609 100644 --- a/src/nginxconfig/generators/nginx.conf.js +++ b/src/nginxconfig/generators/nginx.conf.js @@ -5,10 +5,9 @@ export default (domains, global) => { // Source config['# Generated by nginxconfig.io'] = ''; - if (window.location.search) - config[`# ${window.location.protocol}//${window.location.host}${window.location.pathname}${window.location.search}`] = ''; + config[`# ${window.location.protocol}//${window.location.host}${window.location.pathname}${window.location.search}`] = ''; - // Basic nignx conf + // Basic nginx conf config.user = global.nginx.user.computed; config.pid = global.nginx.pid.computed; config.worker_processes = global.nginx.workerProcesses.computed; @@ -18,40 +17,40 @@ export default (domains, global) => { worker_connections: 65535, }; - // HTTP - config.http = {}; + // HTTP (kv so we can use the same key multiple times) + config.http = []; if (global.php.phpBackupServer.computed) - config.http['upstream php'] = { + config.http.push(['upstream php', { server: [ `${global.php.phpServer.computed[0] === '/' ? 'unix:' : ''}${global.php.phpServer.computed}`, `${global.php.phpBackupServer.computed[0] === '/' ? 'unix:' : ''}${global.php.phpBackupServer.computed} backup`, ], - }; + }]); - config.http.charset = 'utf-8'; - config.http.sendfile = 'on'; - config.http.tcp_nopush = 'on'; - config.http.tcp_nodelay = 'on'; + config.http.push(['charset', 'utf-8']); + config.http.push(['sendfile', 'on']); + config.http.push(['tcp_nopush', 'on']); + config.http.push(['tcp_nodelay', 'on']); if (!global.security.serverTokens.computed) - config.http.server_tokens = 'off'; + config.http.push(['server_tokens', 'off']); if (!global.logging.logNotFound.computed) - config.http.log_not_found = 'off'; - config.http.types_hash_max_size = 2048; - config.http.client_max_body_size = `${global.nginx.clientMaxBodySize.computed}M`; + config.http.push(['log_not_found', 'off']); + config.http.push(['types_hash_max_size', 2048]); + config.http.push(['client_max_body_size', `${global.nginx.clientMaxBodySize.computed}M`]); - config.http['# MIME'] = ''; - config.http.include = 'mime.types'; - config.http.default_type = 'application/octet-stream'; + config.http.push(['# MIME', '']); + config.http.push(['include', 'mime.types']); + config.http.push(['default_type', 'application/octet-stream']); - config.http['# logging'] = ''; - config.http.access_log = global.logging.accessLog.computed.trim() || 'off'; - config.http.error_log = global.logging.errorLog.computed.trim() || '/dev/null'; + config.http.push(['# Logging', '']); + config.http.push(['access_log', global.logging.accessLog.computed.trim() || 'off']); + config.http.push(['error_log', global.logging.errorLog.computed.trim() || '/dev/null']); if (global.security.limitReq.computed) { - config.http['# limits'] = ''; - config.http.limit_req_log_level = 'warn'; - config.http.limit_req_zone = '$binary_remote_addr zone=login:10m rate=10r/m'; + config.http.push(['# Limits', '']); + config.http.push(['limit_req_log_level', 'warn']); + config.http.push(['limit_req_zone', '$binary_remote_addr zone=login:10m rate=10r/m']); } // HTTPS @@ -63,26 +62,26 @@ export default (domains, global) => { } } if (hasHttps) { - config.http['# SSL'] = ''; - config.http.ssl_session_timeout = '1d'; - config.http.ssl_session_cache = 'shared:SSL:10m'; - config.http.ssl_session_tickets = 'off'; + config.http.push(['# SSL', '']); + config.http.push(['ssl_session_timeout', '1d']); + config.http.push(['ssl_session_cache', 'shared:SSL:10m']); + config.http.push(['ssl_session_tickets', 'off']); if (sslProfiles[global.https.sslProfile.computed].dh_param_size) { - config.http['# Diffie-Hellman parameter for DHE ciphersuites'] = ''; - config.http.ssl_dhparam = `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/dhparam.pem`; + config.http.push(['# Diffie-Hellman parameter for DHE ciphersuites', '']); + config.http.push(['ssl_dhparam', `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/dhparam.pem`]); } - config.http[`# ${sslProfiles[global.https.sslProfile.computed].name} configuration`] = ''; - config.http.ssl_protocols = sslProfiles[global.https.sslProfile.computed].protocols.join(' '); + config.http.push([`# ${sslProfiles[global.https.sslProfile.computed].name} configuration`, '']); + config.http.push(['ssl_protocols', sslProfiles[global.https.sslProfile.computed].protocols.join(' ')]); if (sslProfiles[global.https.sslProfile.computed].ciphers.length) - config.http.ssl_ciphers = sslProfiles[global.https.sslProfile.computed].ciphers.join(':'); + config.http.push(['ssl_ciphers', sslProfiles[global.https.sslProfile.computed].ciphers.join(':')]); if (sslProfiles[global.https.sslProfile.computed].server_preferred_order) - config.http.ssl_prefer_server_ciphers = 'on'; + config.http.push(['ssl_prefer_server_ciphers', 'on']); - config.http['# OCSP Stapling'] = ''; - config.http.ssl_stapling = 'on'; - config.http.ssl_stapling_verify = 'on'; + config.http.push(['# OCSP Stapling', '']); + config.http.push(['ssl_stapling', 'on']); + config.http.push(['ssl_stapling_verify', 'on']); if (global.https.ocspCloudflare.computed || global.https.ocspGoogle.computed @@ -92,17 +91,17 @@ export default (domains, global) => { if (global.https.ocspGoogle.computed) ips.push('8.8.8.8', '8.8.4.4'); if (global.https.ocspOpenDns.computed) ips.push('208.67.222.222', '208.67.220.220'); - config.http.resolver = `${ips.join(' ')} valid=60s`; - config.http.resolver_timeout = '2s'; + config.http.push(['resolver', `${ips.join(' ')} valid=60s`]); + config.http.push(['resolver_timeout', '2s']); } } // Configs! - config.http['# load configs'] = ''; - config.http.include = [ + config.http.push(['# Load configs', '']); + config.http.push(['include', [ `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/conf.d/*.conf`, global.tools.modularizedStructure.computed ? `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/sites-enabled/*` : '', - ].filter(x => !!x); + ].filter(x => x.length)]); // Single file configs if (!global.tools.modularizedStructure.computed) { diff --git a/src/nginxconfig/generators/to_conf.js b/src/nginxconfig/generators/to_conf.js new file mode 100644 index 0000000..bde6688 --- /dev/null +++ b/src/nginxconfig/generators/to_conf.js @@ -0,0 +1,51 @@ +import isObject from '../util/is_object'; + +const recurse = (entriesOrObject, depth) => { + // Support an object or kv array entries + // Convert to entries if given an object + const entries = isObject(entriesOrObject) ? Object.entries(entriesOrObject) : entriesOrObject; + + // If not a valid kv entries array, return + if (!Array.isArray(entries) || !entries.every(i => Array.isArray(i) && i.length === 2)) return ''; + + // Initial values + let retVal = ''; + const longestKeyLen = entries.reduce((prev, current) => { + if (!current[0].startsWith('#') && current[0].length > prev) + return current[0].length; + return prev; + }, 0); + const indent = (' ').repeat(depth); + + // Loop over every kv pair + for (const item of entries) { + // If an object, or kv entries, recurse + if (isObject(item[1]) || (Array.isArray(item[1]) && item[1].every(i => Array.isArray(i) && i.length === 2))) { + // Recurse + retVal += '\n' + indent + item[0] + ' {\n'; + retVal += recurse(item[1], depth + 1); + retVal += indent + '}\n\n'; + + // Done + continue; + } + + // Otherwise, assume it can be made a string + // Ensure we're working with an array + const val = Array.isArray(item[1]) ? item[1] : [item[1]]; + + // Calculate spacing + const keyValSpacing = (longestKeyLen - item[0].length) + 4; + const keyValIndent = (' ').repeat(Math.max(keyValSpacing, 0)); + + // Work through each item in the array + val.forEach(subVal => { + const val = subVal.toString(); + retVal += indent + (item[0] + keyValIndent + val).trim() + (item[0].startsWith('#') ? '' : ';') + '\n'; + }); + } + + return retVal.replace(/\n\n\n/g, '\n\n'); +} + +export default entriesOrObject => recurse(entriesOrObject, 0); diff --git a/src/nginxconfig/scss/style.scss b/src/nginxconfig/scss/style.scss index 4704d08..f15f38e 100644 --- a/src/nginxconfig/scss/style.scss +++ b/src/nginxconfig/scss/style.scss @@ -388,10 +388,16 @@ $highlight: #f2c94c; code { &[class*="language-"] { + &, .token { + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 13.6px; font-weight: normal; + line-height: 1.4em; + } - // Fix Bulma interfering with Prism + // Fix Bulma interfering with Prism + .token { &.number, &.tag { background: transparent; diff --git a/src/nginxconfig/templates/app.vue b/src/nginxconfig/templates/app.vue index 8215c0e..fd64c74 100644 --- a/src/nginxconfig/templates/app.vue +++ b/src/nginxconfig/templates/app.vue @@ -63,8 +63,10 @@ limitations under the License.

Config files

- -
{{exportData}}
+
@@ -112,8 +114,11 @@ limitations under the License. activeDomains() { return this.$data.domains.map((domain, index) => [domain, index]).filter(d => d[0] !== null); }, - exportData() { - return generators(this.activeDomains, this.$data.global)['nginx.conf']; + nginxDir() { + return this.$data.global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, ''); + }, + confFiles() { + return generators(this.$data.domains, this.$data.global); }, }, mounted() {