feat(ci): automate config.md docs generation (#2887)

This commit is contained in:
Lucas Fernandes Nogueira 2021-11-14 09:26:41 -03:00 committed by GitHub
parent bffd5131fb
commit 4e3b366e64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 233 additions and 9 deletions

View File

@ -269,7 +269,7 @@
"path": "./tooling/cli.rs",
"manager": "rust",
"dependencies": ["tauri-bundler"],
"postversion": "node ../../.scripts/covector/generate-cli-doc.js && cargo check"
"postversion": "node ../../.scripts/covector/generate-cli-doc.js && node ../../.scripts/covector/generate-config-doc.js && cargo check"
},
"create-tauri-app": {
"path": "./tooling/create-tauri-app",

View File

@ -0,0 +1,114 @@
const fs = require('fs')
const path = require('path')
const schema = JSON.parse(fs.readFileSync('tooling/cli.rs/schema.json').toString())
const templatePath = path.join(__dirname, '../../docs/.templates/config.md')
const targetPath = path.join(__dirname, '../../docs/api/config.md')
const template = fs.readFileSync(templatePath, 'utf8')
function formatDescription(description) {
return description ?
description
.replace(/`/g, '\\`')
.replace(/\n/g, ' ')
.replace(/ /g, ' ')
.replace(/{/g, '\\{')
.replace(/}/g, '\\}') :
''
}
function generatePropertiesEl(schema, anchorRoot, definition, tab) {
const previousTabLevel = tab.replace(' ', '')
const fields = [`anchorRoot="${anchorRoot}"`]
if (definition.additionalProperties) {
fields.push(`type="${definition.type}"`)
fields.push(`description="${formatDescription(definition.description)}"`)
}
const rows = []
for (const propertyName in definition.properties) {
const property = definition.properties[propertyName]
if ('type' in property) {
let type
if ('items' in property) {
if (property.items.type) {
type = `${property.items.type}[]`
} else {
const typeName = property.items.$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[typeName]
const propertyEl = generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `)
rows.push({
property: propertyName,
optional: ('default' in property) || property.type.includes('null'),
type: `${typeName}[]`,
description: property.description,
child: `<Array type="${typeName}">\n${tab}${propertyEl}\n${previousTabLevel}</Array>`
})
continue
}
} else if (Array.isArray(property.type)) {
type = property.type.join(' | ')
} else {
type = property.type
}
rows.push({
property: propertyName,
optional: true,
type,
description: property.description,
default: property.default
})
} else if ('anyOf' in property) {
const subType = property.anyOf[0].$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[subType]
const propertyEl = generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `)
rows.push({
property: propertyName,
optional: property.anyOf.length > 1 && property.anyOf[1].type === 'null',
type: subType,
description: property.description,
child: propertyEl
})
} else if ('allOf' in property) {
const subType = property.allOf[0].$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[subType]
const propertyEl = propDefinition.properties ? generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `) : undefined
rows.push({
property: propertyName,
optional: 'default' in property,
type: property.type || subType,
description: property.description,
child: propertyEl
})
}
}
if (rows.length > 0) {
const serializedRows = rows
.map(row => {
const fields = [`property: "${row.property}"`, `optional: ${row.optional}`, `type: "${row.type}"`, `description: \`${formatDescription(row.description)}\``]
if (row.child) {
fields.push(`child: ${row.child}`)
}
return `{ ${fields.join(', ')} },`
})
.join(`\n${tab}`)
fields.push(`rows={[\n${tab}${serializedRows}\n${previousTabLevel}]}`)
} else {
fields.push('rows={[]}')
}
return `<Properties ${fields.join(' ')}/>`
}
const output = []
for (const propertyName in schema.properties) {
const property = schema.properties[propertyName]
const definitionName = property.allOf[0].$ref.replace('#/definitions/', '')
const definition = schema.definitions[definitionName]
let contents = `## \`${propertyName}\`\n\n${generatePropertiesEl(schema, propertyName, definition, ' ')}`
output.push(contents)
}
fs.writeFileSync(targetPath, template.replace('{properties}', output.join('\n\n')))

103
docs/.templates/config.md Normal file
View File

@ -0,0 +1,103 @@
---
title: Configuration
---
import Properties from '@theme/Properties'
import Array from '@theme/Array'
import Alert from '@theme/Alert'
The `tauri.conf.json` is a file generated by the `tauri init` command (see <a href="/docs/api/cli#tauri-init">here</a>) that lives in your Tauri application source directory (src-tauri).
Once generated, you may modify it at will to customize your Tauri application.
# Platform-specific configuration
In addition to the JSON defined on the `tauri.conf.json` file, Tauri reads a platform-specific configuration on `tauri.linux.conf.json`, `tauri.windows.conf.json` and `tauri.macos.conf.json` and merges it with the main `tauri.conf.json` configuration.
# Configuration structure
`tauri.conf.json` is composed of the following properties:
{properties}
<!-- Dirty trick to have an anchor without make it appear in the table of contents -->
<div id="bootstrapper"></div>
<Alert title="bootstrapper script">
Instead of launching the app directly, we configure the bundled app to run a script that tries to expose the environment variables to the app; without that you'll have trouble using system CLI apps like Node.js.
</Alert>
```js title=Example
"tauri": {
"cli": {
"description": "Tauri communication example",
"longDescription": null,
"beforeHelp": null,
"afterHelp": null,
"args": [{
"short": "c",
"name": "config",
"takesValue": true,
"description": "Config path"
}, {
"short": "t",
"name": "theme",
"takesValue": true,
"description": "App theme",
"possibleValues": ["light", "dark", "system"]
}, {
"short": "v",
"name": "verbose",
"multipleOccurrences": true,
"description": "Verbosity level"
}],
"subcommands": {
"update": {
"description": "Updates the app",
"longDescription": null,
"beforeHelp": null,
"afterHelp": null,
"args": [{
"short": "b",
"name": "background",
"description": "Update in background"
}],
"subcommands": null
}
}
},
"bundle": {
"active": true,
"targets": ["deb"],
"identifier": "com.tauri.dev",
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
"resources": [],
"externalBin": [],
"copyright": "",
"category": "DeveloperTool",
"shortDescription": "",
"longDescription": "",
"deb": {
"depends": []
},
"macOS": {
"frameworks": [],
"minimumSystemVersion": "",
"exceptionDomain": ""
}
},
"allowlist": {
"all": true
},
"windows": [{
"title": "Tauri App",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false
}],
"security": {
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'"
}
}
```

View File

@ -841,8 +841,6 @@ fn default_dist_dir() -> AppUrl {
AppUrl::Url("../dist".to_string())
}
type JsonObject = HashMap<String, JsonValue>;
/// The tauri.conf.json mapper.
#[skip_serializing_none]
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
@ -859,9 +857,13 @@ pub struct Config {
pub build: BuildConfig,
/// The plugins config.
#[serde(default)]
pub plugins: HashMap<String, JsonObject>,
pub plugins: PluginConfig,
}
/// The plugin configs holds a HashMap mapping a plugin name to its configuration object.
#[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize, JsonSchema)]
pub struct PluginConfig(pub HashMap<String, JsonValue>);
fn default_build() -> BuildConfig {
BuildConfig {
runner: None,

View File

@ -29,11 +29,11 @@
"plugins": {
"description": "The plugins config.",
"default": {},
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": true
}
"allOf": [
{
"$ref": "#/definitions/PluginConfig"
}
]
},
"tauri": {
"description": "The Tauri configuration.",
@ -954,6 +954,11 @@
},
"additionalProperties": false
},
"PluginConfig": {
"description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.",
"type": "object",
"additionalProperties": true
},
"SecurityConfig": {
"type": "object",
"properties": {