{
  "$id": "https://json.schemastore.org/template.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "datatype": {
      "description": "Indicates limitations on the valid values a symbol may be assigned. When specified, the symbol value is attempted to be converted to this type. The datatype \"choice\" is supported only for parameter symbols and requires providing symbols.choices configuration for the symbol.",
      "anyOf": [
        {
          "enum": ["choice", "bool", "float", "int", "hex", "text"]
        },
        {
          "pattern": "^(integer|string)$"
        }
      ]
    },
    "generatorConstant": {
      "properties": {
        "generator": {
          "enum": ["constant"]
        },
        "parameters": {
          "properties": {
            "value": {
              "description": "The constant value to be assigned to the symbol.",
              "type": "string"
            }
          }
        }
      }
    },
    "generatorGuid": {
      "properties": {
        "generator": {
          "enum": ["guid"]
        },
        "parameters": {
          "properties": {
            "format": {
              "deprecated": true,
              "deprecationMessage": "This property is not maintained and may be removed in the future. Use defaultFormat instead, or use 'guids' section.",
              "description": "This property is not maintained and may be removed in the future. Use defaultFormat instead, or use 'guids' section.",
              "type": "string"
            },
            "defaultFormat": {
              "description": "The format of guid to be generated. Accepts a single value from ('n', 'd', 'b', 'p', 'x') for lowercase output or ('N', 'D', 'B', 'P', 'X') for uppercase output. The formats are defined in Guid.ToString() method documentation.",
              "type": "string"
            }
          }
        }
      }
    },
    "generatorNow": {
      "properties": {
        "generator": {
          "enum": ["now"]
        },
        "parameters": {
          "properties": {
            "format": {
              "description": "The format string to use when converting the date-time to a string representation.",
              "type": "string"
            },
            "utc": {
              "description": "If true, use UTC time. If false, use local time.",
              "type": "boolean"
            }
          }
        }
      }
    },
    "generatorRandom": {
      "properties": {
        "generator": {
          "enum": ["random"]
        },
        "parameters": {
          "required": ["low"],
          "properties": {
            "low": {
              "description": "An integer value indicating the low-end of the range to generate the random number in.",
              "type": "integer"
            },
            "high": {
              "description": "An integer value indicating the high-end of the range to generate the random number in. If not explicitly provided, defaults to int.MaxValue.",
              "type": "integer"
            }
          }
        }
      }
    },
    "generatorRegex": {
      "properties": {
        "generator": {
          "enum": ["regex"]
        },
        "parameters": {
          "properties": {
            "source": {
              "description": "The name of a different parameter in the template configuration. A copy of its value will be used by this generator's regex to generate the value for this parameter. The value of the source parameter is not modified.",
              "type": "string"
            },
            "steps": {
              "description": "An ordered list of key-value pairs indicating the regex replacement actions. Each element of the list must contain exactly the keys 'regex' and 'replacement' - along with their values. These replacements will be applied to the result of the previous replacement (except the first, which acts on the original value from the source).",
              "type": "array",
              "items": {
                "required": ["regex", "replacement"],
                "properties": {
                  "regex": {
                    "description": "The regular expression to use to locate the sequence to replace.",
                    "type": "string"
                  },
                  "replacement": {
                    "description": "The replacement for any sequences matched by the supplied regular expression.",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "generatorRegexMatch": {
      "properties": {
        "generator": {
          "enum": ["regexMatch"]
        },
        "datatype": {
          "enum": ["bool"]
        },
        "parameters": {
          "properties": {
            "source": {
              "description": "The symbol to search for a match. Its value will be used by this generator's regex to evaluate if there is a match. The value of the source parameter is not modified.",
              "type": "string"
            },
            "pattern": {
              "description": "The regular expression to use to match.",
              "type": "string"
            }
          }
        }
      }
    },
    "generatorCoalesce": {
      "properties": {
        "generator": {
          "enum": ["coalesce"]
        },
        "parameters": {
          "type": "object",
          "required": ["sourceVariableName", "fallbackVariableName"],
          "properties": {
            "sourceVariableName": {
              "type": "string",
              "description": "The name of the symbol whose value will be inspected - if the value is effectively equal to the default value, the value of the symbol referred to by fallbackVariableName is used, otherwise the value of this symbol."
            },
            "defaultValue": {
              "type": "string",
              "description": "The value to consider as being the default - if the value of the symbol referred to by sourceVariableName is equal to this, the value of the symbol referred to in fallbackVariableName is used instead.",
              "default": ""
            },
            "fallbackVariableName": {
              "type": "string",
              "description": "The name of the symbol to return the value of if the symbol referred to by sourceVariableName has a value equal to the value of defaultValue."
            }
          }
        }
      }
    },
    "generatorCasing": {
      "properties": {
        "generator": {
          "enum": ["casing"]
        },
        "parameters": {
          "required": ["source"],
          "properties": {
            "source": {
              "description": "The name of the symbol whose value should have its case changed.",
              "type": "string"
            },
            "toLower": {
              "description": "Whether the case changed to should be lower case, if false, the value is made to be uppercase instead.",
              "type": "boolean",
              "default": true
            }
          }
        }
      }
    },
    "generatorPort": {
      "properties": {
        "generator": {
          "enum": ["port"]
        },
        "parameters": {
          "properties": {
            "low": {
              "description": "The lower bound of acceptable port numbers.",
              "type": "integer",
              "default": 1024
            },
            "high": {
              "description": "The upper bound of acceptable port numbers.",
              "type": "integer",
              "default": 65535
            },
            "fallback": {
              "description": "The port number to use if no free ports could be found.",
              "type": "integer",
              "default": 0
            }
          }
        }
      }
    },
    "generatorSwitch": {
      "properties": {
        "generator": {
          "enum": ["switch"]
        },
        "parameters": {
          "properties": {
            "evaluator": {
              "description": "The style of evaluator to use.",
              "enum": ["C++", "C++2", "MSBUILD", "VB"],
              "default": "C++"
            },
            "datatype": {
              "$ref": "#/definitions/datatype"
            },
            "cases": {
              "description": "The set of cases to test for. The first one, in document order, to return true's value is used, if none return true, empty string is returned.",
              "type": "array",
              "items": {
                "type": "object",
                "required": ["condition", "value"],
                "properties": {
                  "condition": {
                    "description": "An expression to be interpreted by the specified evaluator type.",
                    "type": "string"
                  },
                  "value": {
                    "description": "The value to return if the condition evaluates to true.",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "generatorJoin": {
      "properties": {
        "generator": {
          "enum": ["join"]
        },
        "parameters": {
          "properties": {
            "separator": {
              "description": "The value used as the separator between the values to be concatenated, notice that you can use \"/\" as folder separator also on Windows since File API will convert it into \"\\\".",
              "default": "",
              "type": "string"
            },
            "removeEmptyValues": {
              "description": "Indication whether null and empty strings should be removed from joining to prevent repetitive separators.",
              "default": "false",
              "type": "boolean"
            },
            "symbols": {
              "description": "All values to concatenate.",
              "type": "array",
              "items": {
                "type": "object",
                "required": ["value"],
                "properties": {
                  "type": {
                    "description": "\"ref\" to reference value from another symbol or \"const\" for string constant, defaults to \"const\".",
                    "enum": ["ref", "const"]
                  },
                  "value": {
                    "description": "Either name of another symbol or string constant.",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "guid": {
      "pattern": "^\\{?[0-9A-Fa-f]{8}[-]?([0-9A-Fa-f]{4}[-]?){3}[0-9A-Fa-f]{12}\\}?$",
      "description": "A guid string to be replaced in source files. Format and casing is not significant in the config as format and casing is preserved based on the particular guid in processed file(s).",
      "type": "string"
    },
    "ice": {
      "anyOf": [
        {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string"
          }
        },
        {
          "type": "string"
        }
      ]
    },
    "modifier": {
      "type": "object",
      "properties": {
        "condition": {
          "description": "Boolean condition to indicate if the sources configuration should be included or ignored. If the condition evaluates to true or is not provided, the sources config will be used for creating the template. If it evaluates to false, the sources config will be ignored.",
          "type": "string"
        },
        "exclude": {
          "description": "The set of globbing patterns indicating the content that was included by sources.include that should not be processed.",
          "allOf": [
            {
              "$ref": "#/definitions/ice"
            }
          ],
          "default": [
            "**/[Bb]in/**",
            "**/[Oo]bj/**",
            ".template.config/**/*",
            "**/*.filelist",
            "**/*.user",
            "**/*.lock.json"
          ]
        },
        "include": {
          "description": "The set of globbing patterns indicating the content to process in the path referred to by the source.",
          "allOf": [
            {
              "$ref": "#/definitions/ice"
            }
          ],
          "default": ["**/*"]
        },
        "copyOnly": {
          "description": "The set of globbing patterns indicating the content that was included by sources.include, that hasn't been excluded by sources.exclude that should be placed in the user's directory without modification.",
          "allOf": [
            {
              "$ref": "#/definitions/ice"
            }
          ],
          "default": ["**/node_modules/**/*"]
        },
        "rename": {
          "description": "The set of explicit renames to perform. Each key is a path to a file in the source, each value is a path to the target location.",
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    },
    "source": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/definitions/modifier"
        }
      ],
      "properties": {
        "modifiers": {
          "description": "A list of additional source information which gets added to the top-level source information, based on evaluation the corresponding source.modifiers.condition.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/modifier"
          }
        },
        "source": {
          "description": "The path in the template content (relative to the directory containing the .template.config folder) that should be processed.",
          "type": "string",
          "default": "./"
        },
        "target": {
          "description": "The path (relative to the directory the user has specified) that content should be written to.",
          "type": "string",
          "default": "./"
        }
      }
    }
  },
  "properties": {
    "author": {
      "description": "The author of the template.",
      "type": "string"
    },
    "classifications": {
      "description": "Zero or more characteristics of the template that a user might search for it by.",
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "defaultName": {
      "description": "The name to use during creation if no name has been specified by the user or provided from the host.",
      "type": "string",
      "minLength": 1
    },
    "generatorVersions": {
      "description": "The semantic version range of the Microsoft.TemplateEngine.Orchestrator.RunnableProjects package that this template is usable with. In older versions of the engine, the four octet version string is used but is matched against a constant which was never changed from 1.0.0.0 - either syntax is now accepted, however the four octet string will not be changed from 1.0.0.0.",
      "type": "string",
      "default": "[1.0.0.0-*)"
    },
    "groupIdentity": {
      "description": "The ID of the group this template belongs to. When combined with the \"tags\" section, this allows multiple templates to be displayed as one, with the the decision for which one to use being presented as a choice in each one of the pivot categories (keys).",
      "type": "string",
      "minLength": 1
    },
    "guids": {
      "description": "A list of guids which appear in the template source and should be replaced in the template output. For each guid listed, a replacement guid is generated, and replaces all occurrences of the source guid in the output.",
      "type": "array",
      "uniqueItems": true,
      "items": {
        "$ref": "#/definitions/guid"
      }
    },
    "identity": {
      "description": "A unique name for this template.",
      "type": "string",
      "minLength": 1
    },
    "name": {
      "description": "The name for the template that users should see.",
      "type": "string",
      "minLength": 1
    },
    "placeholderFilename": {
      "description": "A filename that will be completely ignored except to indicate that its containing directory should be copied. This allows creation of an empty directory in the created template, by having a corresponding source directory containing just the placeholder file. Completely empty directories are ignored.",
      "type": "string",
      "default": "-.-"
    },
    "postActions": {
      "description": "Defines an ordered list of actions to perform after template generation. The post action information is provided to the creation broker, to act on as appropriate.",
      "type": "array",
      "items": {
        "type": "object",
        "allOf": [
          {
            "required": ["actionId", "manualInstructions"],
            "properties": {
              "actionId": {
                "description": "A guid uniquely defining the action. The value must correspond to a post-action known by the broker.",
                "allOf": [
                  {
                    "$ref": "#/definitions/guid"
                  }
                ]
              },
              "args": {
                "description": "A list of key-value pairs to use when performing the action. The specific parameters required / allowed are defined by the action itself.",
                "type": "object"
              },
              "condition": {
                "description": "A C++ style expression that, if it evaluates to 'false' causes the post-action to be skipped. This expression may refer to any symbols that have been defined.",
                "type": "string"
              },
              "continueOnError": {
                "description": "If this action fails, the value of continueOnError indicates whether to attempt the next action, or stop processing the post actions. Should be set to true when subsequent actions rely on the success of the current action.",
                "type": "boolean",
                "default": false
              },
              "description": {
                "description": "A human-readable description of the action.",
                "type": "string"
              },
              "id": {
                "description": "Defines identifier to be used when localizing the post action artifacts.",
                "type": "string"
              },
              "applyFileRenamesToArgs": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "A list of arguments names from 'args' to which the file renames configured in symbols should be applied."
              },
              "applyFileRenamesToManualInstructions": {
                "description": "If set to true, the file renames configured in symbols should be applied to manual instructions.",
                "type": "boolean",
                "default": false
              },
              "manualInstructions": {
                "description": "An ordered list of possible instructions to display if the action cannot be performed. Each element in the list must contain a key named \"text\", whose value contains the instructions. Each element may also optionally provide a key named \"condition\" - a Boolean evaluate-able string. The first instruction whose condition is false or blank will be considered valid, all others are ignored.",
                "type": "array",
                "items": {
                  "type": "object",
                  "required": ["text"],
                  "properties": {
                    "condition": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "id": {
                      "description": "Defines identifier to be used when localizing the manual instructions.",
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          {
            "oneOf": [
              {
                "not": {
                  "required": ["actionId"],
                  "properties": {
                    "actionId": {
                      "enum": [
                        "AC1156F7-BB77-4DB8-B28F-24EEBCCA1E5C",
                        "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2",
                        "B17581D1-C5C9-4489-8F0A-004BE667B814",
                        "cb9a6cf3-4f5c-4860-b9d2-03a574959774",
                        "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
                        "D396686C-DE0E-4DE6-906D-291CD29FC5DE",
                        "84C0DA21-51C8-4541-9940-6CA19AF04EE6"
                      ]
                    }
                  }
                }
              },
              {
                "description": "Instruction display - shows a message given by description and manualInstructions as well as an optional command line to ask the user to execute.",
                "properties": {
                  "actionId": {
                    "enum": ["AC1156F7-BB77-4DB8-B28F-24EEBCCA1E5C"]
                  },
                  "args": {
                    "properties": {
                      "executable": {
                        "description": "The executable to instruct the user to run.",
                        "type": "string"
                      },
                      "args": {
                        "description": "The arguments to instruct the user to run the executable with - if executable is not specified, this value is unused.",
                        "type": "string"
                      }
                    }
                  }
                }
              },
              {
                "description": "Process start - starts a process.",
                "properties": {
                  "actionId": {
                    "enum": ["3A7C4B45-1F5D-4A30-959A-51B88E82B5D2"]
                  },
                  "args": {
                    "required": ["executable"],
                    "properties": {
                      "redirectStandardOutput": {
                        "description": "Whether or not to redirect stdout for the process (prevents output from being displayed if true).",
                        "type": "boolean",
                        "default": true
                      },
                      "redirectStandardError": {
                        "description": "Defines whether or not the stderr should be redirected. If the output is redirected, it prevents it from being displayed.",
                        "type": "boolean",
                        "default": true
                      },
                      "executable": {
                        "description": "The executable to run.",
                        "type": "string"
                      },
                      "args": {
                        "description": "The arguments to supply to the executable.",
                        "type": "string"
                      }
                    }
                  }
                }
              },
              {
                "description": "Add reference - adds a reference to a project, package or framework assembly.",
                "properties": {
                  "actionId": {
                    "enum": ["B17581D1-C5C9-4489-8F0A-004BE667B814"]
                  },
                  "args": {
                    "required": ["referenceType", "reference"],
                    "properties": {
                      "referenceType": {
                        "description": "The type of reference to add. project = A project to project reference. package = A NuGet package reference. framework - A framework assembly reference.",
                        "type": "string",
                        "enum": ["project", "package", "framework"],
                        "default": "false"
                      },
                      "projectFileExtensions": {
                        "description": "Must be a literal extension for the project file(s) of interest, may be a semicolon delimited list. If unspecified, any project file (*.*proj) is allowed.",
                        "type": "string"
                      },
                      "reference": {
                        "description": "The reference to be added (if referenceType=package, this is the package ID; if referenceType=framework, this is the path or assembly name; if referenceType=project, this is the path to the project reference to add).",
                        "type": "string"
                      },
                      "version": {
                        "description": "The version of the package reference to add, applicable only if referenceType=package.",
                        "type": "string"
                      },
                      "targetFiles": {
                        "oneOf": [
                          {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "uniqueItems": true
                            },
                            "description": "An array of files that should be processed. If not specified, the project file in output directory or its closest parent directory will be used."
                          },
                          {
                            "type": "string",
                            "description": "A semicolon delimited list of files that should be processed. If not specified, the project file in output directory or its closest parent directory will be used."
                          }
                        ]
                      }
                    }
                  }
                }
              },
              {
                "description": "chmod - runs chmod on a particular file.",
                "properties": {
                  "actionId": {
                    "enum": ["cb9a6cf3-4f5c-4860-b9d2-03a574959774"]
                  },
                  "args": {
                    "type": "object",
                    "description": "The permissions to set: the key-value pairs, where the key is a permission, and the value is a file or array of files to apply the permission to.",
                    "additionalProperties": {
                      "oneOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "uniqueItems": true
                          },
                          "description": "The set of files (or patterns) to apply the permission specified in the property name to."
                        },
                        {
                          "type": "string",
                          "description": "The file (or pattern) to apply the permission specified in the property name to."
                        }
                      ]
                    }
                  }
                }
              },
              {
                "description": "NuGet package restore - restores NuGet packages for all primary outputs with file extensions *.proj or *.sln.",
                "properties": {
                  "actionId": {
                    "enum": ["210D431B-A78B-4D2F-B762-4ED3E3EA9025"]
                  },
                  "args": {
                    "properties": {
                      "files": {
                        "oneOf": [
                          {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "uniqueItems": true
                            },
                            "description": "An array of files that should be restored. If not specified, all primary outputs are restored."
                          },
                          {
                            "type": "string",
                            "description": "A semicolon delimited list of files that should be restored. If not specified, all primary outputs are restored."
                          }
                        ]
                      }
                    }
                  }
                }
              },
              {
                "description": "Add to solution - Adds one or more of the primary outputs to the first sln file found (searches up the directory tree from the output folder).",
                "properties": {
                  "actionId": {
                    "enum": ["D396686C-DE0E-4DE6-906D-291CD29FC5DE"]
                  },
                  "args": {
                    "properties": {
                      "primaryOutputIndexes": {
                        "type": "string",
                        "description": "A semicolon delimited list of indexes of the primary outputs that should be added to the solution, if not specified, all primary outputs are used."
                      },
                      "solutionFolder": {
                        "type": "string",
                        "description": "The destination solution folder path to add the projects to. Can't be used with 'inRoot'. Optional."
                      },
                      "inRoot": {
                        "type": "boolean",
                        "description": "Places the projects in the root of the solution, rather than creating a solution folder. Cannot be used with 'solutionFolder'. Optional. Available since .NET SDK 7.0.200."
                      },
                      "projectFiles": {
                        "oneOf": [
                          {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "uniqueItems": true
                            },
                            "description": "An array of project files that should be added to solution. If not specified, primary outputs will be used instead."
                          },
                          {
                            "type": "string",
                            "description": "A semicolon delimited list of files that should be added to solution. If not specified, primary outputs will be used instead."
                          }
                        ]
                      }
                    }
                  }
                }
              },
              {
                "description": "Open in editor - Adds one or more of the primary outputs to the first sln file found (searches up the directory tree from the output folder).",
                "properties": {
                  "actionId": {
                    "enum": ["84C0DA21-51C8-4541-9940-6CA19AF04EE6"]
                  },
                  "args": {
                    "properties": {
                      "files": {
                        "type": "string",
                        "description": "A semicolon delimited list of indexes of the primary outputs that should be opened in the editor."
                      }
                    }
                  }
                }
              }
            ]
          }
        ]
      }
    },
    "precedence": {
      "description": "A value used to determine how preferred this template is among the other templates with the same groupIdentity (higher values are more preferred).",
      "type": ["integer", "string"],
      "pattern": "^([0-9]+)$",
      "default": 0
    },
    "preferDefaultName": {
      "description": "Indicated which behaviour to use when no `--name` is specified during template creation. If `true` it will use the template's `defaultName`. If no `defaultName` is found, or `preferDefaultName` is `false` it uses the fallback (output folder).",
      "type": ["boolean"]
    },
    "preferNameDirectory": {
      "description": "Indicates whether to create a directory for the template if name is specified but an output directory is not set (instead of creating the content directly in the current directory).",
      "type": "boolean"
    },
    "primaryOutputs": {
      "description": "A list of important output paths created during template generation. These paths need to be added to the newly created project at the end of template creation.",
      "type": "array",
      "items": {
        "type": "object",
        "required": ["path"],
        "properties": {
          "path": {
            "description": "The path to the file in the template content whose corresponding output file should be included as a primary output.",
            "type": "string"
          },
          "condition": {
            "description": "The condition for including the specified path in the primary outputs set.",
            "type": "string",
            "default": "true"
          }
        }
      }
    },
    "shortName": {
      "oneOf": [
        {
          "description": "A shorthand name for selecting the template in CLI environment. The template short name should be unique across all the installed templates.",
          "type": "string"
        },
        {
          "type": "array",
          "description": "A shorthand name for selecting the template in CLI environment. The first element is a primary choice, and will be used in scenarios which allow only single value for the short name. The template short name should be unique across all the installed templates.",
          "items": {
            "type": "string"
          }
        }
      ],
      "minLength": 1
    },
    "sourceName": {
      "description": "The text in the source content to replace with the name the user specifies. The value of the 'sourceName' is available in built-in 'name' symbol that can be used as the source for creating other symbols and condition expressions. See important information about how to select correct 'sourceName' in https://github.com/dotnet/templating/wiki/Naming-and-default-value-forms.",
      "type": "string"
    },
    "sources": {
      "description": "The set of mappings in the template content to user directories.",
      "type": "array",
      "items": {
        "$ref": "#/definitions/source"
      },
      "default": {
        "source": "./",
        "target": "./"
      }
    },
    "forms": {
      "type": "object",
      "description": "Custom value forms used by the template.",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "identifier": {
            "type": "string",
            "description": "The identifier for the value form component that will be used to transform the value."
          }
        },
        "oneOf": [
          {
            "not": {
              "required": ["identifier"],
              "properties": {
                "identifier": {
                  "enum": [
                    "lowerCaseInvariant",
                    "xmlEncode",
                    "safe_name",
                    "lower_safe_name",
                    "upperCaseInvariant",
                    "replace",
                    "safe_namespace",
                    "lower_safe_namespace",
                    "chain",
                    "lowerCase",
                    "identity",
                    "upperCase",
                    "jsonEncode",
                    "firstLowerCase",
                    "firstLowerCaseInvariant",
                    "firstUpperCase",
                    "firstUpperCaseInvariant",
                    "titleCase",
                    "kebabCase"
                  ]
                }
              }
            }
          },
          {
            "description": "Lowercases the source value in a culture invariant way.",
            "properties": {
              "identifier": {
                "enum": ["lowerCaseInvariant"]
              }
            }
          },
          {
            "description": "XML encodes the source value.",
            "properties": {
              "identifier": {
                "enum": ["xmlEncode"]
              }
            }
          },
          {
            "description": "Converts the source value to a string suitable for a C# identifier.",
            "properties": {
              "identifier": {
                "enum": ["safe_name"]
              }
            }
          },
          {
            "description": "Converts the source value to a lowercase string suitable for a C# identifier.",
            "properties": {
              "identifier": {
                "enum": ["lower_safe_name"]
              }
            }
          },
          {
            "required": ["pattern", "replacement"],
            "description": "Performs a regular expression replacement on the source value.",
            "properties": {
              "identifier": {
                "enum": ["replace"]
              },
              "pattern": {
                "description": "A regular expression whose matches will be replaced with the literal value specified in replacement.",
                "type": "string"
              },
              "replacement": {
                "description": "The value to replace the matches of the specified pattern in the source value with.",
                "type": "string"
              }
            }
          },
          {
            "description": "Converts the source value to a string suitable for a C# namespace.",
            "properties": {
              "identifier": {
                "enum": ["safe_namespace"]
              }
            }
          },
          {
            "description": "Converts the source value to a lowercase string suitable for a C# namespace.",
            "properties": {
              "identifier": {
                "enum": ["lower_safe_namespace"]
              }
            }
          },
          {
            "required": ["steps"],
            "description": "Performs a series of transforms.",
            "properties": {
              "identifier": {
                "enum": ["chain"]
              },
              "steps": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "The name of the form to apply to the previous step (or source value if this is the first step)."
                }
              }
            }
          },
          {
            "description": "Changes the case of source value to lower-case.",
            "properties": {
              "identifier": {
                "enum": ["lowerCase"]
              }
            }
          },
          {
            "description": "Returns the source value.",
            "properties": {
              "identifier": {
                "enum": ["identity"]
              }
            }
          },
          {
            "description": "Converts the source value to upper-case using the casing rules of the current culture.",
            "properties": {
              "identifier": {
                "enum": ["upperCase"]
              }
            }
          },
          {
            "description": "Converts the source value to upper-case using the casing rules of the invariant culture.",
            "properties": {
              "identifier": {
                "enum": ["upperCaseInvariant"]
              }
            }
          },
          {
            "description": "JSON encodes the source value.",
            "properties": {
              "identifier": {
                "enum": ["jsonEncode"]
              }
            }
          },
          {
            "description": "Converts the first letter of the value to lowercase using the casing rules of the current culture.",
            "properties": {
              "identifier": {
                "enum": ["firstLowerCase"]
              }
            }
          },
          {
            "description": "Converts the first letter of the value to lowercase using the casing rules of the invariant culture.",
            "properties": {
              "identifier": {
                "enum": ["firstLowerCaseInvariant"]
              }
            }
          },
          {
            "description": "Converts the first letter of the value to uppercase using the casing rules of the current culture.",
            "properties": {
              "identifier": {
                "enum": ["firstUpperCase"]
              }
            }
          },
          {
            "description": "Converts the first letter of the value to uppercase using the casing rules of the invariant culture.",
            "properties": {
              "identifier": {
                "enum": ["firstUpperCaseInvariant"]
              }
            }
          },
          {
            "description": "Converts the value to title case using the casing rules of the current culture.",
            "properties": {
              "identifier": {
                "enum": ["titleCase"]
              }
            }
          },
          {
            "description": "Converts the value to kebab case using the casing rules of the invariant culture.",
            "properties": {
              "identifier": {
                "enum": ["kebabCase"]
              }
            }
          }
        ]
      }
    },
    "symbols": {
      "description": "The symbols section defines variables and their values, the values may be the defined in terms of other symbols. When a defined symbol name is encountered anywhere in the template definition, it is replaced by the value defined in this configuration. The symbols configuration is a collection of key-value pairs. The keys are the symbol names, and the value contains key-value-pair configuration information on how to assign the symbol a value.",
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "required": ["type"],
        "properties": {
          "datatype": {
            "$ref": "#/definitions/datatype"
          },
          "type": {
            "type": "string",
            "enum": ["bind", "derived", "generated", "parameter", "computed"]
          }
        },
        "oneOf": [
          {
            "required": ["binding"],
            "properties": {
              "type": {
                "description": "The symbol binds value from external sources.",
                "enum": ["bind"]
              },
              "binding": {
                "description": "The source and the name of parameter to take the value from. The syntax is: <external source>:<parameter name>. Well known external sources are: host - a value that is defined by the template engine host; env - environment variable.",
                "type": "string"
              },
              "defaultValue": {
                "description": "The value assigned to the symbol if no value was provided from external source(s).",
                "type": "string"
              },
              "replaces": {
                "type": "string",
                "description": "The text to replace with the value of this symbol."
              },
              "fileRename": {
                "type": "string",
                "description": "Defines the portion of file names which will be replaced by symbol value."
              },
              "onlyIf": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "after": {
                      "description": "The replacement string occurs after this value.",
                      "type": "string"
                    },
                    "before": {
                      "description": "The replacement string occurs before this value.",
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          {
            "required": ["valueSource", "valueTransform"],
            "properties": {
              "type": {
                "description": "The value of this symbol is derived from the value of another symbol by the application of value forms.",
                "enum": ["derived"]
              },
              "valueSource": {
                "type": "string",
                "description": "The name of the symbol that the value should be derived from."
              },
              "valueTransform": {
                "type": "string",
                "description": "The name of the value form that should be applied to the source value to use as the value of this symbol."
              },
              "defaultValue": {
                "description": "The value assigned to the symbol if no value was provided.",
                "type": "string"
              },
              "replaces": {
                "type": "string",
                "description": "The text to replace with the value of this symbol."
              },
              "fileRename": {
                "type": "string",
                "description": "Defines the portion of file names which will be replaced by symbol value."
              },
              "onlyIf": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "after": {
                      "description": "The replacement string occurs after this value.",
                      "type": "string"
                    },
                    "before": {
                      "description": "The replacement string occurs before this value.",
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          {
            "required": ["generator"],
            "properties": {
              "type": {
                "description": "Defines the high level configuration of symbol.",
                "enum": ["generated"]
              },
              "replaces": {
                "type": "string",
                "description": "The text to replace with the value of this symbol."
              },
              "fileRename": {
                "type": "string",
                "description": "Defines the portion of file names which will be replaced by symbol value."
              },
              "onlyIf": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "after": {
                      "description": "The replacement string occurs after this value.",
                      "type": "string"
                    },
                    "before": {
                      "description": "The replacement string occurs before this value.",
                      "type": "string"
                    }
                  }
                }
              }
            },
            "oneOf": [
              {
                "$ref": "#/definitions/generatorCasing"
              },
              {
                "$ref": "#/definitions/generatorCoalesce"
              },
              {
                "$ref": "#/definitions/generatorConstant"
              },
              {
                "$ref": "#/definitions/generatorGuid"
              },
              {
                "$ref": "#/definitions/generatorNow"
              },
              {
                "$ref": "#/definitions/generatorPort"
              },
              {
                "$ref": "#/definitions/generatorRandom"
              },
              {
                "$ref": "#/definitions/generatorRegex"
              },
              {
                "$ref": "#/definitions/generatorRegexMatch"
              },
              {
                "$ref": "#/definitions/generatorSwitch"
              },
              {
                "$ref": "#/definitions/generatorJoin"
              }
            ]
          },
          {
            "properties": {
              "type": {
                "description": "Defines the high level configuration of symbol.",
                "enum": ["parameter"]
              },
              "isRequired": {
                "oneOf": [
                  {
                    "type": "boolean",
                    "description": "Flag indicating whether the parameter has to be specified on the input."
                  },
                  {
                    "type": "string",
                    "description": "Condition indicating whether the parameter has to be specified on the input."
                  }
                ]
              },
              "isEnabled": {
                "oneOf": [
                  {
                    "type": "boolean",
                    "description": "Flag indicating parameter visibility."
                  },
                  {
                    "type": "string",
                    "description": "Condition indicating parameter visibility."
                  }
                ]
              },
              "choices": {
                "description": "An array listing the valid choices for a symbol whose datatype = choice. If not provided, there are no valid choices for the symbol, so it can never be assigned a value.",
                "type": "array",
                "items": {
                  "required": ["choice"],
                  "properties": {
                    "choice": {
                      "description": "A valid value for the symbol.",
                      "type": "string"
                    },
                    "description": {
                      "description": "Help text describing the meaning of the corresponding value.",
                      "type": "string"
                    },
                    "displayName": {
                      "type": "string",
                      "description": "The friendly name of the choice to be displayed to the user. This property can be localized."
                    }
                  }
                }
              },
              "defaultValue": {
                "description": "The value assigned to the symbol if no value for it is provided by the user or host.",
                "type": "string"
              },
              "description": {
                "description": "The description of the parameter.",
                "type": "string"
              },
              "replaces": {
                "type": "string",
                "description": "The text to replace with the value of this symbol."
              },
              "fileRename": {
                "type": "string",
                "description": "The element defines the portion of file names which will be replaced by symbol value."
              },
              "onlyIf": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "after": {
                      "description": "The replacement string occurs after this value.",
                      "type": "string"
                    },
                    "before": {
                      "description": "The replacement string occurs before this value.",
                      "type": "string"
                    }
                  }
                }
              },
              "allowMultipleValues": {
                "description": "Indication whether multiple values can be specified for a parameter. Valid only for datatype = choice.",
                "type": "boolean",
                "default": false
              },
              "enableQuotelessLiterals": {
                "description": "Indication whether implicit symbols for each choice value should be added to parameter collection. This allows condition syntax without using quotes for choice literals. Valid only for datatype = choice.",
                "type": "boolean",
                "default": false
              },
              "displayName": {
                "type": "string",
                "description": "The friendly name of the symbol to be displayed to the user. This property can be localized."
              },
              "forms": {
                "type": "object",
                "properties": {
                  "global": {
                    "oneOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "uniqueItems": true
                        },
                        "description": "An array of the forms applied to the parameter symbol. Note that the forms should produce the different result on the value of 'replaces' and 'fileRename' properties. Use the form in the template content to apply corresponding transformation to the value given by the user as the parameter."
                      },
                      {
                        "type": "string",
                        "description": "The form applied to the parameter symbol. Note that the forms should produce the different result on the value of 'replaces' and 'fileRename' properties. Use the form in the template content to apply corresponding transformation to the value given by the user as the parameter."
                      }
                    ]
                  }
                }
              }
            }
          },
          {
            "properties": {
              "type": {
                "description": "Defines the high level configuration of symbol.",
                "enum": ["computed"]
              },
              "value": {
                "description": "An evaluate-able condition whose result defines the value of the symbol.",
                "type": "string"
              }
            }
          }
        ]
      }
    },
    "baselines": {
      "description": "Alternate sets of defaults for symbols.",
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "description": "A named set of alternate defaults.",
        "properties": {
          "description": {
            "type": "string",
            "description": "A string to use to indicate the intent of the baseline."
          },
          "defaultOverrides": {
            "description": "A lookup of symbol names to new defaults.",
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "description": "An updated default value for the specified symbol."
            }
          }
        }
      }
    },
    "tags": {
      "description": "Common information about templates, these are effectively interchangeable with choice type parameter symbols.",
      "type": "object",
      "required": ["type"],
      "properties": {
        "language": {
          "description": "The programming language the template primarily contains or is intended for use with.",
          "type": "string"
        },
        "type": {
          "description": "The type of template: project or item.",
          "enum": ["project", "item", "solution"]
        }
      }
    },
    "thirdPartyNotices": {
      "description": "An URL for a document indicating any libraries used by the template that are not owned/provided by the template author.",
      "type": "string"
    },
    "description": {
      "type": "string",
      "description": "A description of the template's purpose or contents for use in help."
    },
    "constraints": {
      "description": "The constraints section defines the restrictions when the template can be run. Available since .NET SDK 7.0.100.",
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "required": ["type"],
        "properties": {
          "type": {
            "type": "string",
            "description": "Constraint type."
          },
          "args": {
            "description": "Constraints arguments."
          }
        },
        "oneOf": [
          {
            "not": {
              "required": ["type"],
              "properties": {
                "type": {
                  "enum": [
                    "os",
                    "host",
                    "workload",
                    "sdk-version",
                    "project-capability"
                  ]
                }
              }
            },
            "properties": {
              "args": {
                "type": ["array", "object", "string"]
              }
            }
          },
          {
            "description": "Operating system constraint. Allows to restrict the template to be run only on specific operating systems.",
            "properties": {
              "type": {
                "enum": ["os"]
              },
              "args": {
                "oneOf": [
                  {
                    "type": "string",
                    "enum": ["Windows", "Linux", "OSX"]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": ["Windows", "Linux", "OSX"]
                    }
                  }
                ]
              }
            }
          },
          {
            "description": "Host constraint. Allows to restrict the template to be run only on specific applications using template engine.",
            "properties": {
              "type": {
                "enum": ["host"]
              },
              "args": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": ["hostname"],
                  "properties": {
                    "hostname": {
                      "type": "string",
                      "description": "The identifier of supported host. Commonly used identifiers are: 'dotnetcli'' - .NET SDK, 'vs' - Visual Studio, 'vs-mac' - Visual Studio for Mac, 'ide' - Visual Studio (any platform).",
                      "oneOf": [
                        {
                          "not": {
                            "enum": ["dotnetcli", "vs", "vs-mac", "ide"]
                          }
                        },
                        {
                          "enum": ["dotnetcli", "vs", "vs-mac", "ide"]
                        }
                      ]
                    },
                    "version": {
                      "type": "string",
                      "description": "The supported version of the host. May be an exact version, float version or version range. Refer to https://docs.microsoft.com/en-us/nuget/concepts/package-versioning for more info."
                    }
                  }
                }
              }
            }
          },
          {
            "description": "Installed workload constraint. Allows to restrict the template to be run only on host with specific workloads installed.",
            "properties": {
              "type": {
                "enum": ["workload"]
              },
              "args": {
                "oneOf": [
                  {
                    "type": "string",
                    "description": "supported workload (running host need to have at least one of the requested workloads installed)."
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "supported workload (running host need to have at least one of the requested workloads installed)."
                    }
                  }
                ]
              }
            }
          },
          {
            "description": "SDK version constraint. Allows to restrict the template to be run only on specific .NET SDK version(s).",
            "properties": {
              "type": {
                "enum": ["sdk-version"]
              },
              "args": {
                "oneOf": [
                  {
                    "type": "string",
                    "description": "The supported version of the SDK. May be an exact version, float version or version range. Refer to https://docs.microsoft.com/en-us/nuget/concepts/package-versioning for more info."
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "The supported version of the SDK. May be an exact version, float version or version range. Refer to https://docs.microsoft.com/en-us/nuget/concepts/package-versioning for more info."
                    }
                  }
                ]
              }
            }
          },
          {
            "description": "The project context constraint. Allows to restrict the item template to be run only on inside .NET project with certain capabilities.",
            "properties": {
              "type": {
                "enum": ["project-capability"]
              },
              "args": {
                "type": "string",
                "description": "Project capability expression that should be satisfied by the project. Refer to https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.shell.interop.vsprojectcapabilityexpressionmatcher for more info."
              }
            }
          }
        ]
      }
    }
  },
  "required": [
    "author",
    "classifications",
    "identity",
    "name",
    "shortName",
    "tags"
  ],
  "title": "JSON schema .NET template configuration (template.json).",
  "type": "object"
}
