diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2e65ce8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: node_js -node_js: "9" - -env: - global: - - REPO_SLUG=paritytech/parity-config-generator - - secure: "VyqeNnK4Hi7nmTuoEhdTpJUv5fG/ZxrVXQug1vFr8qQfAMEEVGEoFgLrejEBhssHN/LwrSWQrAYqpPraHKvlDH1D5no9V9I39Q6AqvJ5tWGoUuNjV4aq74GGgRVhq5Tfl8gSIvjC8d2HwOjEpa6QjTuUAJtjO/UgujTmxhChLfmZnCTfoAGvmP2akOUwV1D6+Pbdoq46dW5BuHVVe2yPN/rStEuS8vTdAs5f6JxlSOjA36OKNuA4V2vqYLGzcXEzCnOS7DICXkBhxSG6rBY0q0bFOQy0vFFVkQVS4C4MRbmhMkUiwbXFJoNBsr+mi6tEdmd+QIpyyfqpPEQyB4Q7b4C6+YLeTaNLAk/t/wrhtLHjscxYss3BArHL8teeBz9VwiEPUM4Fy8QTHTsqhkBWy+RJpZIyfDNNo2fNZTqSorEuF7GF36QyQf1qcZ4An8FtkbI/Umay0MQycCM6fDpNEd5usgINKoRO/BTvQlreY/2AciCml/hKspqxHkLgaDm32z1Aouv8mACOZgT/50YqILcBn7wQqmq62hhmhy72wUZzvOLDO9V9Fpy63dGSGzG8lPfdgYNjK9gR3+RbKFS+GAb6xS+VrRUUy6P6t9wJONEe7N1TVb7Ruzamqdr2YTsUT5sWM5S/n97MW8er0Tm15ICIPmdy+V8CTVMpDSiPEUY=" - -script: - - yarn test - - yarn build - -after_success: - - ./scripts/deploy-to-gh-pages.sh diff --git a/README.md b/README.md index 7ed28f9..d802dd7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # CodeChain Config Generator - See demo at: [CodeChain Config Generator](ADD_LINK) ## Development - -To update the list of fields, run `npm run generate-data`. This will parse the command-line options and configuration fields [from the parity repo](https://github.com/paritytech/parity/blob/master/parity/cli/mod.rs), apply the manual overwrites and extra information of `src/data.extra.json` and save the result into `src/data.compiled.json`, which is the file used by Parity Config Generator. +Taken from [Parity's config generator code](https://github.com/paritytech/parity-config-generator). diff --git a/docs/docTemplate.js b/docs/docTemplate.js deleted file mode 100644 index 9a358a8..0000000 --- a/docs/docTemplate.js +++ /dev/null @@ -1,49 +0,0 @@ - -const BufferList = require('bl'); - -module.exports = { - preExampleConfig: new BufferList(` ---- -title: Configuring Parity Ethereum ---- - -Parity can be configured using either the [CLI options](#cli-options) or a [config file](#config-file). Should the CLI flags and the config file disagree about a setting, the CLI takes precedence. - -You can list all CLI options by running \`$parity --help\`. The vast majority of CLI options map to a setting in the TOML file, for example \`--mode-timeout 500\` can be set by creating a config file: - -\`\`\`toml -[parity] -mode_timeout = 500 -\`\`\` - -## Config File - -Parity can be configured using a [TOML](https://github.com/toml-lang/toml) file. The file can be generated using the [Parity Config Generator](https://paritytech.github.io/parity-config-generator/). To start parity with a config file, the file needs to be located in: - - * Windows: \`%UserProfile%\\AppData\\Roaming\\Parity\\Ethereum\\config.toml\` - * Linux: \`~/.local/share/io.parity.ethereum/config.toml\` - * macOS: \`$HOME/Library/Application Support/io.parity.ethereum/config.toml\` - -To use a custom path run \`$ parity --config path/to/config.toml\`. - -## Default config.toml - -The following is a representation of a configuration file with all default values (*note: the \`[stratum]\` section is not present by default, and including it in your config currently enables stratum*). - -\`\`\`toml`), - postExampleConfig: new BufferList('\n```\n'), - preConfigDoc: new BufferList(` -## Presets - -Parity can also be launched with a [preset configuration file](https://github.com/paritytech/parity-ethereum/tree/master/parity/cli/presets) using the \`--config\` flag with one of the following values: - * \`dev\`: uses [dev chain specifications](Private-development-chain) with [Instant-seal](Pluggable-Consensus#instant-seal) consensus engine. The gas price is set to 0. - * \`dev-insecure\`: uses the same configuration as \`dev\`, plus sets the flag \`no_consensus\`, allows all RPC APIs and accepts all RPC interfaces and hosts, as well as all IPFS hosts. - * \`insecure\`: uses the Mainnet default configuration, plus sets the flag \`no_consensus\`, allows all RPC APIs and accepts all RPC interfaces and hosts, as well as all IPFS hosts. - * \`mining\`: uses the Mainnet default configuration, plus increases the number of peers to min 50 and max 100, it disables the Dapps and IPC interface. It forces the sealing of blocks with a minimum of 4 seconds interval, forces the reseal for any new transaction (external or local), reduces the transaction queue size to 2048 while increasing the cache size to 256 MB and setting the \`trace\` logging level for the \`miner\` and \`own_tx\` modules. - * \`non-standard-ports\`: sets the client to listen to the port 30305 and 8645 for RPC connections. - -## Configuration options - -`), - postConfigDoc: new BufferList(``) -}; diff --git a/package.json b/package.json index a248528..7217387 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "parity-config-generator", + "name": "codechain-config-generator", "version": "0.1.0", "private": true, - "homepage": "http://paritytech.github.io/parity-config-generator", + "homepage": "AddPage", "devDependencies": { "babel-eslint": "^7.1.1", "react-scripts": "0.4.3", @@ -27,9 +27,7 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "lint": "semistandard --verbose | snazzy", - "lint-fix": "semistandard --fix --verbose | snazzy", - "generate-data": "node scripts/generate-config-data.js", - "generate-docs": "node scripts/generate-config-docs.js" + "lint-fix": "semistandard --fix --verbose | snazzy" }, "semistandard": { "parser": "babel-eslint" diff --git a/scripts/generate-config-data.js b/scripts/generate-config-data.js deleted file mode 100644 index adbb6dd..0000000 --- a/scripts/generate-config-data.js +++ /dev/null @@ -1,309 +0,0 @@ -const https = require('https'); -const fs = require('fs').promises; -const path = require('path'); -const bl = require('bl'); - -const CONFIG_IS = { - SAME: 'same', - OPPOSITE: 'opposite', - ARRAY_OF: 'array_of', - NONE: 'none', - UNKNOWN: 'unknown' -}; - -function fetchSource () { - if (process.env.AUTOGENSCRIPT) { - return fs.readFile(path.resolve(__dirname, '../../parity/cli/mod.rs'), 'UTF-8'); - } - return new Promise((resolve, reject) => { - https.get('https://raw.githubusercontent.com/paritytech/parity/master/parity/cli/mod.rs', res => { - if (res.statusCode !== 200) { - reject(new Error(`Failed to load source code, status code: ${res.statusCode}`)); - } - - res.pipe(bl(function (err, data) { - if (err) { - reject(new Error(err)); - } - - resolve(data.toString()); - })); - }); - } - ); -} - -function getCliOptions (source) { - const regex = /^\s*(FLAG|ARG) (\w+): *\([\w<>]+?\) *= (.+?)(?:u\d+|usize)?, or (.+),\n.+\n\s*"(.+)",(?:\s+\/\/.+)?$/gm; - - const cliOptions = []; - for (const [, type, variableName, defaultValueString, configCallbackString, helpString] of execAll(regex, source)) { - if (configCallbackString.includes('_legacy')) { - continue; - } - cliOptions.push({type, variableName, defaultValueString, configCallbackString, helpString}); - } - - const parsedCliOptions = cliOptions.map(({defaultValueString, configCallbackString, helpString, ...rest}) => { - const defaultValue = parseDefaultValue(defaultValueString); - const help = helpString.replace(/\\"/g, '"'); - const {configSection, configProp, configIs} = parseConfigCallback(configCallbackString); - return {defaultValue, help, configSection, configProp, configIs, ...rest}; - }); - - return parsedCliOptions; -} - -function* execAll (regex, str) { - const localCopy = new RegExp(regex, regex.flags); - let match; - while ((match = localCopy.exec(str))) { - yield match; - } -} - -function parseDefaultValue (defaultValue) { - switch (defaultValue) { - case 'None': - return null; - case 'Vec::new()': - return []; - default: - try { - // Remove thousands separators if numeric value - if (/^\d[\d_]+\d$/.test(defaultValue)) { - defaultValue = defaultValue.replace(/_/g, ''); - } - - defaultValue = defaultValue.replace(/^Some\((".+").into\(\)\)$/, '$1'); - - return JSON.parse(defaultValue); - } catch (e) { - console.warn('Warning: Failed to parse default value', defaultValue, e.message); - } - } -} - -function parseConfigCallback (configCallback) { - const regexToConfigIs = [ - [ - /^\|c: &Config\| c\.([a-zA-Z_]+)\.as_ref\(\)\?\.([a-zA-Z_]+)(?:\.clone\(\))?$/, - CONFIG_IS.SAME - ], - [ - /^\|c: &Config\| c\.([a-zA-Z_]+)\.as_ref\(\)\?\.([a-zA-Z_]+)(?:\.clone\(\))?\.map\(\|([a-zA-Z_]+)\| !\3\)(\.clone\(\))?$/, - CONFIG_IS.OPPOSITE - ], - [ - /^\|c: &Config\| c\.([a-zA-Z_]+)\.as_ref\(\)\?\.([a-zA-Z_]+)(?:\.clone\(\)|\.as_ref\(\))?\.map\(\|vec\| vec\.join\(","\)\)?$/, - CONFIG_IS.ARRAY_OF - ], - [ - /^\|_\| None$/, - CONFIG_IS.UNKNOWN - ] - ]; - - for (const [regex, configIs] of regexToConfigIs) { - const parts = regex.exec(configCallback); - if (parts !== null) { - const [, configSection, configProp] = parts; - return {configIs, configSection, configProp}; - } - } - - console.warn('Warning: Failed to recognize callback', configCallback); - return {configIs: CONFIG_IS.UNKNOWN}; -} - -function makeCliConfigTree (parsedCliOptions) { - const configCliOptions = parsedCliOptions - .filter(({configIs}) => configIs !== CONFIG_IS.NONE && configIs !== CONFIG_IS.UNKNOWN); - - const tree = {}; - configCliOptions.forEach(({configSection, configProp, ...rest}) => { - tree[configSection] = tree[configSection] || {}; - tree[configSection][configProp] = {...rest}; - }); - return tree; -} - -function getStructFields (name, source) { - const subsource = source.match(new RegExp(`^struct ${name} {[^]+?}`, 'm'))[0]; - - const fields = subsource.split('\n').slice(1, -1).filter(s => s.trim() && !s.trim().startsWith('#') && !s.trim().startsWith('_legacy')); - - const parsedFields = fields.map(line => { - const matches = line.match(/^\s*(\w+): Option<([\w<>]+)>,$/); - const [, name, type] = matches; - return {name, type}; - }); - - return parsedFields; -} - -function hydrateConfigWithCli (config, cliConfig) { - const data = {}; - - for (const section of config) { - data[section.name] = {}; - data[section.name].section = section.name_friendly; - - for (const prop of section.props) { - data[section.name][prop.name] = {}; - data[section.name][prop.name].name = prop.name.replace(/_/g, ' ').replace(/^./, a => a.toUpperCase()); - data[section.name][prop.name].type = prop.type; - - // If the config prop is linked to a CLI command - if (section.name in cliConfig && - prop.name in cliConfig[section.name]) { - const cliConfigProp = cliConfig[section.name][prop.name]; - const dataProp = data[section.name][prop.name]; - - switch (cliConfigProp.configIs) { - case CONFIG_IS.SAME: - dataProp.description = cliConfigProp.help; - dataProp.default = cliConfigProp.defaultValue; - break; - case CONFIG_IS.ARRAY_OF: - dataProp.description = cliConfigProp.help; - if (cliConfigProp.defaultValue !== null) { - dataProp.default = cliConfigProp.defaultValue.split(','); - } else { - dataProp.default = []; - } - break; - case CONFIG_IS.OPPOSITE: - dataProp.default = !cliConfigProp.defaultValue; - break; - default: - throw new Error(`Error: Unreachable: configIs with value '${cliConfigProp.configIs}' can be 'same', 'array_of', 'opposite', 'none', 'unknown'; is none of the first three; last two are pruned in makeCliConfigTree; qed.`); - } - } else { - console.warn('Warning: Config option %s.%s is not linked to any CLI option.', section.name, prop.name); - } - } - } - - return data; -} - -function augment (data, extra) { - const dataAugmented = Object.assign({}, data); - const overwritten = []; - - for (const section in extra) { - if (!(section in dataAugmented)) { - dataAugmented[section] = extra[section]; - overwritten.push(section); - continue; - } - - for (const prop in extra[section]) { - if (prop === 'section' || prop === 'description' || prop === 'condition') { - dataAugmented[section][prop] = extra[section][prop]; - continue; - } - - overwritten.push(`${section}.${prop}`); - dataAugmented[section][prop] = {...dataAugmented[section][prop], ...extra[section][prop]}; - } - } - - // Quick hack to retain the key order of data.extra.json - // (make new object and insert data.extra.json props first) - - const dataAugmentedOrdered = {}; - - overwritten.forEach(id => { - if (!id.includes('.')) { - dataAugmentedOrdered[id] = dataAugmented[id]; - } else { - const [section, prop] = id.split('.'); - dataAugmentedOrdered[section] = dataAugmentedOrdered[section] || {}; - dataAugmentedOrdered[section][prop] = dataAugmented[section][prop]; - } - }); - - Object.keys(dataAugmented) - .filter(section => !overwritten.includes(section)) - .forEach(section => { - dataAugmentedOrdered[section] = dataAugmentedOrdered[section] || {}; - - Object.keys(dataAugmented[section]) - .filter(prop => !overwritten.includes(`${section}.${prop}`)) - .forEach(prop => { - dataAugmentedOrdered[section][prop] = dataAugmented[section][prop]; - }); - }); - - return dataAugmentedOrdered; -} - -function generateAugmentedData (source, extra) { - // Parse CLI options - - const cliOptions = getCliOptions(source); - const configCliOptions = makeCliConfigTree(cliOptions); - - // Parse config structs - - const configSections = getStructFields('Config', source).map(({name: section, type: sectionStructName}) => - ({ - name: section, - name_friendly: sectionStructName, - props: getStructFields(sectionStructName, source).map(prop => { - prop.type = prop.type.toLowerCase().replace(/vec<(.+)>/, '$1[]').replace(/u16|u32|u64|usize/, 'number'); - return prop; - }) - }) - ).filter(({props}) => props.length); - - // Hydrate config structs with CLI options - - const data = hydrateConfigWithCli(configSections, configCliOptions); - - // Augment with data.extra.json - - return augment(data, extra); -} - -async function fetchExtraData(){ - return JSON.parse(await fs.readFile(path.resolve(__dirname, '../src/data.extra.json'), 'UTF-8')); -} - -if (!module.parent) { - (async function () { - // Make sure that config items with unrecognized default values - // were set a default value in data.extra.json - const dataAugmented = generateAugmentedData(await fetchSource(), await fetchExtraData()); - - - Object.keys(dataAugmented).forEach(section => { - const undefinedDefaults = Object.keys(dataAugmented[section]) - .filter(prop => { - const item = dataAugmented[section][prop]; - return typeof item === 'object' && typeof item.default === 'undefined'; - }) - .map(prop => `${section}.${prop}`); - - if (undefinedDefaults.length) { - throw new Error(`Couldn't parse the default CLI value for the following config items: ${undefinedDefaults.join(', ')}. Please set a default value for them in data.extra.json.`); - } - }); - - // Write to file - - await fs.writeFile(path.resolve(__dirname, '../src/data.compiled.json'), JSON.stringify(dataAugmented, null, 2)); - })().catch(e => { - console.error(e); - process.exit(1); - }); -} else { - module.exports = { - fetchSource: fetchSource, - fetchExtra: fetchExtraData, - getCliOptions: getCliOptions, - getData: generateAugmentedData - }; -} diff --git a/scripts/generate-config-docs.js b/scripts/generate-config-docs.js deleted file mode 100644 index b12113a..0000000 --- a/scripts/generate-config-docs.js +++ /dev/null @@ -1,110 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const BufferList = require('bl'); -const docTemplate = require('../docs/docTemplate.js'); -const data = require('./generate-config-data.js'); - -const outputDir = '../docs/'; -const outputFile = 'config.md'; - -function dirtySerialize (valueItem) { - if (typeof valueItem !== 'undefined') { - const rawDefaultValue = valueItem; - var defaultValue; - if (typeof rawDefaultValue === 'object') { - if (rawDefaultValue === null) { - defaultValue = 'null'; - } else { - defaultValue = JSON.stringify(rawDefaultValue); - } - } else { - if (rawDefaultValue === '') { - defaultValue = '""'; - } else { - defaultValue = rawDefaultValue; - } - } - return defaultValue; - } -} - -function compiledToml (compiledData) { - var compiledBuffer = new BufferList(); - for (const key in compiledData) { - if (key[0] !== '_') { - const sectionValues = compiledData[key]; - compiledBuffer.append('[' + key + ']\n'); - for (const value in sectionValues) { - if (value.indexOf('section') < 0 && value.indexOf('description') < 0) { - const valueItem = sectionValues[value]['default']; - compiledBuffer.append(value + ' = ' + dirtySerialize(valueItem) + '\n'); - } - } - compiledBuffer.append('\n'); - } - } - return compiledBuffer; -} - -// Command line options, configs, and descriptions. -function compiledMd (cliOptions) { - const compiledBuffer = new BufferList(); - const builtTree = {}; - for (const option in cliOptions) { - const configSection = cliOptions[option]['configSection']; - const configProp = cliOptions[option]['configProp']; - const helpText = cliOptions[option]['help']; - const variableName = cliOptions[option]['variableName']; - const defaultValue = dirtySerialize(cliOptions[option]['defaultValue']); - var cliName = variableName.replace(/_/g, '-').slice(4); - if (cliName[0] === '-') { - cliName = cliName.slice(1); - } - cliName = '--' + cliName; - const toAppend = BufferList('\n'); - toAppend.append('## ' + cliName.slice(2) + '\n'); - toAppend.append(helpText + '\n'); // description - toAppend.append('#### Command line option \n `' + cliName + '`\n'); // cli flag - if (typeof configSection !== 'undefined') { - toAppend.append('#### Config file option \n```toml\n' + '[' + configSection + ']' + '\n' + configProp + ' = ' + defaultValue + '\n```\n'); // config item - } - toAppend.append('#### Default Value \n`' + defaultValue + '`\n'); - if (typeof builtTree[configSection] !== 'undefined') { - builtTree[configSection].append(toAppend); - } else { - builtTree[configSection] = toAppend; - } - } - for (var section in builtTree) { - var sectionText = section; - if (section === 'undefined') { - sectionText = 'CLI Only'; - } - compiledBuffer.append('# ' + sectionText + '\n'); - compiledBuffer.append(builtTree[section]); - compiledBuffer.append('\n'); - } - - return compiledBuffer; -} - -async function buildPage () { - var compiledBuffer = new BufferList(); - const source = await data.fetchSource(); - const extra = await data.fetchExtra(); - compiledBuffer.append(docTemplate.preExampleConfig); - compiledBuffer.append(compiledToml(data.getData(source, extra))); - compiledBuffer.append(docTemplate.postExampleConfig); - compiledBuffer.append(docTemplate.preConfigDoc); - compiledBuffer.append(compiledMd(data.getCliOptions(source))); - compiledBuffer.append(docTemplate.postConfigDoc); - return compiledBuffer; -} - -(async function () { - fs.writeFileSync(path.resolve(__dirname, outputDir + outputFile), (await buildPage()).toString()); -})().catch(e => { - console.error(e); - process.exit(1); -}); - diff --git a/src/components/Preview.js b/src/components/Preview.js index 9777d78..53fecd2 100644 --- a/src/components/Preview.js +++ b/src/components/Preview.js @@ -100,10 +100,8 @@ function toToml (settings, defaults) { } const { platform } = settings.__internal || defaults.__internal; - const configPath = joinPath([basePath(platform), 'config.toml'], platform); toml.unshift( - '# This config should be placed in following path:', - `# ${configPath}`, + '# The config file path should be specified by using the --config CLI option.' ); return toml.join('\n'); diff --git a/src/components/TopBar.css b/src/components/TopBar.css new file mode 100644 index 0000000..f9b6b04 --- /dev/null +++ b/src/components/TopBar.css @@ -0,0 +1,6 @@ +.topbar-color +{ + background-color:#05aad1 !important; +} + + \ No newline at end of file diff --git a/src/components/TopBar.js b/src/components/TopBar.js index d9151e1..01cc6f5 100644 --- a/src/components/TopBar.js +++ b/src/components/TopBar.js @@ -1,8 +1,9 @@ import React from 'react'; +import './TopBar.css'; function TopBar () { return ( -