Skip to content

Commit

Permalink
support config files, flatten config
Browse files Browse the repository at this point in the history
  • Loading branch information
jfschwarz committed Feb 24, 2022
1 parent 9ffd721 commit f3ab7dc
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 504 deletions.
86 changes: 59 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,55 @@ npm run solid-mustache ./path/to/template.hbs

The compiled template library will be written to `./path/to/template.sol`.

### Configuration

solid-mustache uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support.
This means you can configure it using any of the following ways:

- A `"solid-mustache"` key in your package.json
- A `.solid-mustacherc` file in JSON format.
- A `.solid-mustacherc.json` file.
- A `.solid-mustacherc.js`, `.solid-mustacherc.cjs`, `solid-mustache.config.js`, or `solid-mustache.config.cjs` file that exports an object using `module.exports`.

The configuration file will be resolved starting from the location of the template file and searching up the file tree until a config file is found.

All configuration options can also be specified as CLI arguments.
CLI arguments override values from configuration files.
Config files are not read if using solid-mustache via the JavaScript API.

## Options

#### Name

Specify the name of the generated Solidity library or template.

| Default | CLI Override | API Override |
| ------------ | ----------------- | ---------------- |
| `"Template"` | `--name <string>` | `name: <string>` |
| Default | Config field | CLI Override |
| ------------ | ---------------- | ----------------- |
| `"Template"` | `name: <string>` | `--name <string>` |

#### Solidity pragma

Define the Solidity pragma for the compiled .sol file.

| Default | Config field | CLI Override |
| ----------- | -------------------------- | ---------------------------- |
| `"^0.8.6""` | `solidityPragma: <string>` | `--solidity-pragma <string>` |

#### Header

Define a custom header for the .sol file.

| Default | Config field | CLI Override |
| ------------------------------------------- | ------------------ | ------------------- |
| `"// SPDX-License-Identifier: UNLICENSED""` | `header: <string>` | `--header <string>` |

#### Condense whitespace

Condense sequences of consecutive whitespace characters into a single space character.

| Default | CLI Override | API Override |
| ------- | ------------ | ---------------------------- |
| `false` | `--condense` | `condenseWhitespace: <bool>` |
| Default | Config field | CLI Override |
| ------- | ---------------------------- | ------------ |
| `false` | `condenseWhitespace: <bool>` | `--condense` |

#### <a name="partials-option"></a>Partials

Expand All @@ -182,57 +214,57 @@ By default, a glob pattern is used based on the dirname of the template file and

When using the API, partials are specified as an object, where keys are the partial names and values are the partial template strings.

| Default | CLI Override | API Override |
| ------- | ------------------- | ----------------------------------------- |
| | `--partials <glob>` | `partials: { <name0>: <template0>, ... }` |
| Default | Config field | CLI Override |
| ------- | ----------------------------------------- | ------------------- |
| | `partials: { <name0>: <template0>, ... }` | `--partials <glob>` |

#### Print Width

Specify the line length that the printer will wrap on.

| Default | CLI Override | API Override |
| ------- | --------------------- | ------------------- |
| `80` | `--print-width <int>` | `printWidth: <int>` |
| Default | Config field | CLI Override |
| ------- | ------------------- | --------------------- |
| `80` | `printWidth: <int>` | `--print-width <int>` |

#### Tab Width

Specify the number of spaces per indentation-level.

| Default | CLI Override | API Override |
| ------- | ------------------- | ----------------- |
| `2` | `--tab-width <int>` | `tabWidth: <int>` |
| Default | Config field | CLI Override |
| ------- | ----------------- | ------------------- |
| `2` | `tabWidth: <int>` | `--tab-width <int>` |

#### Tabs

Indent lines with tabs instead of spaces.

| Default | CLI Override | API Override |
| ------- | ------------ | ----------------- |
| `false` | `--use-tabs` | `useTabs: <bool>` |
| Default | Config field | CLI Override |
| ------- | ----------------- | ------------ |
| `false` | `useTabs: <bool>` | `--use-tabs` |

#### Quotes

Use single quotes instead of double quotes.

| Default | CLI Override | API Override |
| ------- | ---------------- | --------------------- |
| `false` | `--single-quote` | `singleQuote: <bool>` |
| Default | Config field | CLI Override |
| ------- | --------------------- | ---------------- |
| `false` | `singleQuote: <bool>` | `--single-quote` |

#### Bracket Spacing

Print spaces between brackets.

| Default | CLI Override | API Override |
| ------- | ---------------------- | ------------------------ |
| `true` | `--no-bracket-spacing` | `bracketSpacing: <bool>` |
| Default | Config field | CLI Override |
| ------- | ------------------------ | ---------------------- |
| `true` | `bracketSpacing: <bool>` | `--no-bracket-spacing` |

#### Explicit Types

Use explicit types (`uint256`) rather than aliases (`uint`).

| Default | CLI Override | API Override |
| ------- | --------------------- | ----------------------- |
| `true` | `--no-explicit-types` | `explicitTypes: <bool>` |
| Default | Config field | CLI Override |
| ------- | ----------------------- | --------------------- |
| `true` | `explicitTypes: <bool>` | `--no-explicit-types` |

## API

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
},
"dependencies": {
"@handlebars/parser": "^2.1.0",
"cosmiconfig": "^7.0.1",
"glob": "^7.2.0",
"prettier": "^2.5.1",
"prettier-plugin-solidity": "^1.0.0-beta.19",
Expand Down
13 changes: 9 additions & 4 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mkdirSync, readFileSync, writeFileSync } from "fs"
import path, { basename, dirname, extname } from "path"

import { cosmiconfigSync } from "cosmiconfig"
import glob from "glob"
import yargs from "yargs"
import { hideBin } from "yargs/helpers"
Expand All @@ -25,7 +26,7 @@ const { argv } = yargs(hideBin(process.argv)).command(
.option("name", {
alias: "n",
type: "string",
description: "The name of the compiled library/contract",
description: "The name to use for the compiled library",
})
.option("solidity-pragma", {
alias: "s",
Expand All @@ -36,8 +37,8 @@ const { argv } = yargs(hideBin(process.argv)).command(
.option("header", {
alias: "h",
type: "string",
description:
"Define the custom header for the .sol file, such as a SPDX-License-Identifier comment",
default: "// SPDX-License-Identifier: UNLICENSED",
description: "Define a custom header for the .sol file",
})
.option("condense", {
alias: "c",
Expand Down Expand Up @@ -99,9 +100,13 @@ const main = async () => {
flag: "r",
})

const defaultPartials = `${dirname(templatePath)}/*.partial.hbs`
const dir = dirname(templatePath)
const configFile = cosmiconfigSync("solid-mustache").search(dir)

const defaultPartials = `${dir}/*.partial.hbs`

const solContent = compile(templateContent, {
...configFile,
name,
solidityPragma,
header,
Expand Down
51 changes: 27 additions & 24 deletions src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,42 @@ const INPUT_STRUCT_NAME = "__Input"
const INPUT_VAR_NAME = "__input"
const RESULT_VAR_NAME = "__result"

interface FormatOptions {
printWidth?: number
tabWidth?: number
useTabs?: boolean
singleQuote?: boolean
bracketSpacing?: boolean
explicitTypes?: boolean
}

interface Options {
/** Assign a custom name to the library/contract (default: "Template") */
name?: string
/** Define the solidity pragma (default: "^0.8.6") */
solidityPragma?: string
/** Define the custom header for the .sol file (default: "// SPDX-License-Identifier: UNLICENSED") */
header?: string
/** Define the solidity pragma (default: "^0.8.6") */
solidityPragma?: string
/** Set to true to compile into a contract rather than a library */
contract?: boolean
/** Allows providing additional templates that can be used via partial call expressions */
partials?: Record<string, string>
/** Set to true to condense sequences of whitespace into single space, saving some contract size */
condenseWhitespace?: boolean
/** Formatting options for prettier */
format?: FormatOptions

/* Formatting options for prettier */
printWidth?: number
tabWidth?: number
useTabs?: boolean
singleQuote?: boolean
bracketSpacing?: boolean
explicitTypes?: boolean
}

export const compile = (template: string, options: Options = {}): string => {
const preprocessedTemplate = options.condenseWhitespace
const {
name = "Template",
header = "// SPDX-License-Identifier: UNLICENSED",
solidityPragma = "^0.8.6",
contract,
partials,
condenseWhitespace: shallCondenseWhitespace,

...formatOptions
} = options

const preprocessedTemplate = shallCondenseWhitespace
? condenseWhitespace(template)
: template
const ast = parse(preprocessedTemplate)
Expand All @@ -100,15 +108,10 @@ export const compile = (template: string, options: Options = {}): string => {
.map((partial) => solDefinePartial(partial, typeNames))
.join("\n\n")

const {
header = "// SPDX-License-Identifier: UNLICENSED",
solidityPragma = "^0.8.6",
} = options

const solidityCode = `${header}
pragma solidity ${solidityPragma};
${options.contract ? "contract" : "library"} ${options.name || "Template"} {
${contract ? "contract" : "library"} ${name} {
${structDefs}
Expand All @@ -128,8 +131,8 @@ ${options.contract ? "contract" : "library"} ${options.name || "Template"} {
return format(solidityCode, {
plugins: [prettierPluginSolidity],
parser: "solidity-parse",
...options.format,
explicitTypes: options.format?.explicitTypes === false ? "never" : "always",
...formatOptions,
explicitTypes: formatOptions.explicitTypes === false ? "never" : "always",
} as Parameters<typeof format>[1])

/** AST processing function sharing access to options and usedPartials variables via JS function scope */
Expand Down Expand Up @@ -341,7 +344,7 @@ ${options.contract ? "contract" : "library"} ${options.name || "Template"} {
): Output[] {
if (statement.name.type !== "PathExpression") throw new Error("Unsupported")
const partialName = statement.name.original
const partialTemplate = options.partials && options.partials[partialName]
const partialTemplate = partials && partials[partialName]
if (!partialTemplate) {
throw new Error(`Trying to use an unknown partial: ${partialName}`)
}
Expand All @@ -352,7 +355,7 @@ ${options.contract ? "contract" : "library"} ${options.name || "Template"} {

let partial = usedPartials.find((p) => p.name === partialName)
if (!partial) {
const preprocessedPartialTemplate = options.condenseWhitespace
const preprocessedPartialTemplate = shallCondenseWhitespace
? condenseWhitespace(partialTemplate)
: partialTemplate
const ast = parse(preprocessedPartialTemplate)
Expand Down
3 changes: 3 additions & 0 deletions test/cases/wand.only/.solid-mustacherc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"condenseWhitespace": true
}
Loading

0 comments on commit f3ab7dc

Please sign in to comment.