-
Notifications
You must be signed in to change notification settings - Fork 373
Reference for template.json
This page describes the available properties of template.json
configuration file.
The templates defined using template.json
are still the "runnable projects" A "runnable project" is a project that can be
executed as a normal project can. Instead of updating your source files to be tokenized you define replacements, and other processing, mostly in an external file,
the template.json
file. This requires that a few changes have to be done on the fly during the preparation of the package, and in the template.json
we define all the operations needed to create a well working package.
Benefits of "runnable project" templates
- Code format is not modified, therefore existing editors work great for template content
- You can still build, run, debug and test your template just like any other project
- No injection of special templating tokens into the project is required (though possible)
Typical layout on disk
.template.config/
template.json
MyTemplate/
MyTemplate.csproj
Program.cs
The templates can be packaged to a NuGet package for further distribution. A tutorial on how to create the template package can be find here.
Category | Description |
---|---|
Template Definition | Metadata of the template |
Content Manipulation | Configuration of content changes in source files |
Output Management | Configuration of the final output |
Name | Description | Mandatory |
---|---|---|
identity |
A unique name for this template | yes |
author |
The author of the template | no |
classifications
|
Zero or more characteristics of the template which may be used in search. In this field you define the values shown as Tags in dotnet new
|
no |
name |
The name for the template. This is displayed as the template name when using dotnet new and Visual Studio. |
yes |
groupIdentity |
The ID of the group this template belongs to. This allows multiple templates to be displayed as one, with the the decision for which one to use based on the template options. | no |
tags |
You can use tags to improve the metadata of your project. Well-known tags are: language and type . To specify the template language, use the tag language . To specify the template type, use the tag type . Supported types are: project , item , solution . |
no |
shortName |
A name for selecting the template in CLI environment. This is the name shown as Short Name in dotnet new list of templates, and is the name to use to run this template. |
yes |
postActions |
Enables actions to be performed after the project is created. See the article on post actions for more details. | no |
constraints |
Template constraints |
Available since .NET SDK 7.0.100.
The template may define the constraints all of which must be met in order for the template to be used.
In case constraints are not met, the template will be installed, however will not be visible by default.
For the details on available constraints, refer to the article.
The constraints are defined under constraints
property (top level in template.json). constraints
contains objects (constraint definition). Each constraint should have a unique name, type
and optional arguments (args
). Argument syntax depends on the constraint implementation.
"constraints": {
"linux-only": {
"type": "os",
"args": "Linux"
},
"sdk-only": {
"type": "host",
"args": [
{
"hostname": "dotnetcli",
"version": "[6.0.100, )"
}
]
}
}
Name | Description | Default | Mandatory |
---|---|---|---|
sources |
The set of mappings in the template content to user directories. It's defined as any array of Source | If not specified, an implicit source is created with "source": "./" and "target": "./" , all other properties in the source are set to their defaults |
no |
guids |
Guids | no | |
symbols |
Symbols | no | |
forms |
Value forms | no |
Name | Description | Default | Mandatory |
---|---|---|---|
source |
The path in the template content (relative to the directory containing the .template.config folder) that should be processed | ./ |
no |
target |
The path (relative to the directory the user has specified) that content should be written to | ./ |
no |
include |
The set of globing patterns indicating the content to process in the path referred to by source
|
[ "**/*" ] | no |
exclude |
The set of globing patterns indicating the content that was included by sources.include that should not be processed | [ "**/[Bb]in/**", "**/[Oo]bj/**", ".template.config/**/*", "**/*.filelist", "**/*.user", "**/*.lock.json" ] |
no |
copyOnly |
The set of globing patterns indicating the content that was included by include , that hasn't been excluded by sources.exclude that should be placed in the user's directory without modification |
[ "**/node_modules/**/*" ] |
no |
rename |
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 - only the values will be evaluated with the information the user supplies | no | |
condition |
A 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 |
no | |
modifiers |
A list of additional source information which gets added to the top-level source information, based on evaluation the corresponding source.modifiers.condition . Is defined as an array of Modifier
|
no |
Name | Description | Mandatory |
---|---|---|
condition |
A boolean condition to indicate if the sources.modifiers instance should be included or ignored. If the condition evaluates to true or is not provided, the sources.modifiers instance will be used for creating the template. If it evaluates to false, the sources.modifiers config will be ignored. |
yes |
include |
Include configuration specific to this sources.modifiers instance, contingent on the corresponding sources.modifiers.condition . See sources.include for more info. |
no |
exclude |
Exclude configuration specific to this sources.modifiers instance, contingent on the corresponding sources.modifiers.condition . See sources.exclude for more info |
no |
copyOnly |
CopyOnly configuration specific to this sources.modifiers instance, contingent on the corresponding sources.modifiers.condition . See sources.copyOnly for more info |
no |
An optional 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. Matching of the guids in the source template works independently on the format and casing of the guids in the template.json
file and source files. Format and casing from template source is preserved in the output (casing and format of the guid in Guids
section of template.json
doesn't influence matching or output generation).
Sample template.json snippet:
"guids": [
"98048C9C-BF28-46BA-A98E-63767EE5E3A8",
"c7ab42cf938548c08b8784349ab5e04b"
],
Sample template file content:
[n]: 98048c9cbf2846baa98e63767ee5e3a8
[d]: 98048c9c-bf28-46ba-a98e-63767ee5e3a8
[b]: {98048c9c-bf28-46ba-a98e-63767ee5e3a8}
[p]: (98048c9c-bf28-46ba-a98e-63767ee5e3a8)
[x]: {0x98048c9c,0xbf28,0x46ba,{0xa9,0x8e,0x63,0x76,0x7e,0xe5,0xe3,0xa8}}
[N]: 98048C9CBF2846BAA98E63767EE5E3A8
[D]: 98048C9C-BF28-46BA-A98E-63767EE5E3A8
[B]: {98048C9C-BF28-46BA-A98E-63767EE5E3A8}
[P]: (98048C9C-BF28-46BA-A98E-63767EE5E3A8)
[X]: {0X98048C9C,0XBF28,0X46BA,{0XA9,0X8E,0X63,0X76,0X7E,0XE5,0XE3,0XA8}}
[n]: c7ab42cf938548c08b8784349ab5e04b
[d]: c7ab42cf-9385-48c0-8b87-84349ab5e04b
[b]: {c7ab42cf-9385-48c0-8b87-84349ab5e04b}
[p]: (c7ab42cf-9385-48c0-8b87-84349ab5e04b)
[x]: {0xc7ab42cf,0x9385,0x48c0,{0x8b,0x87,0x84,0x34,0x9a,0xb5,0xe0,0x4b}}
[N]: C7AB42CF938548C08B8784349AB5E04B
[D]: C7AB42CF-9385-48C0-8B87-84349AB5E04B
[B]: {C7AB42CF-9385-48C0-8B87-84349AB5E04B}
[P]: (C7AB42CF-9385-48C0-8B87-84349AB5E04B)
[X]: {0XC7AB42CF,0X9385,0X48C0,{0X8B,0X87,0X84,0X34,0X9A,0XB5,0XE0,0X4B}}
Output content after template instantiation:
[n]: a6d920ff125841318f5e07df108f5a4a
[d]: a6d920ff-1258-4131-8f5e-07df108f5a4a
[b]: {a6d920ff-1258-4131-8f5e-07df108f5a4a}
[p]: (a6d920ff-1258-4131-8f5e-07df108f5a4a)
[x]: {0xa6d920ff,0x1258,0x4131,{0x8f,0x5e,0x07,0xdf,0x10,0x8f,0x5a,0x4a}}
[N]: A6D920FF125841318F5E07DF108F5A4A
[D]: A6D920FF-1258-4131-8F5E-07DF108F5A4A
[B]: {A6D920FF-1258-4131-8F5E-07DF108F5A4A}
[P]: (A6D920FF-1258-4131-8F5E-07DF108F5A4A)
[X]: {0XA6D920FF,0X1258,0X4131,{0X8F,0X5E,0X07,0XDF,0X10,0X8F,0X5A,0X4A}}
[n]: 2879773c9a5241f78fa5ac318214f54d
[d]: 2879773c-9a52-41f7-8fa5-ac318214f54d
[b]: {2879773c-9a52-41f7-8fa5-ac318214f54d}
[p]: (2879773c-9a52-41f7-8fa5-ac318214f54d)
[x]: {0x2879773c,0x9a52,0x41f7,{0x8f,0xa5,0xac,0x31,0x82,0x14,0xf5,0x4d}}
[N]: 2879773C9A5241F78FA5AC318214F54D
[D]: 2879773C-9A52-41F7-8FA5-AC318214F54D
[B]: {2879773C-9A52-41F7-8FA5-AC318214F54D}
[P]: (2879773C-9A52-41F7-8FA5-AC318214F54D)
[X]: {0X2879773C,0X9A52,0X41F7,{0X8F,0XA5,0XAC,0X31,0X82,0X14,0XF5,0X4D}}
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. The supported symbol types are:
- Parameter
- Derived
- Computed
- Generated
- Bind
There are 3 places from which a symbol can acquire its value:
- Template configuration (this).
- Host provided values, which override template configuration values. For example, the host may provide the operating system kind as "Linux", overriding a template default value of "Windows".
- User provided values, which override host & template values. The way these are provided to the template generation broker is specific to the broker. This may be via additional configuration files, command line parameters, inputs to a UI, etc.
A symbol for which the config provides literal and/or default values.
Name | Description | Mandatory |
---|---|---|
type |
parameter |
yes |
dataType |
Supported values: - bool : boolean type, possible values: true /false . - choice : enumeration, possible values are defined in choices property.- float : double-precision floating format number. Accepts any value that can be parsed by double.TryParse() .- int /integer : 64-bit signed integer. Accepts any value that can be parsed by long.TryParse() .- hex : hex number. Accepts any value that can be parsed by long.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long convertedHex) .- text /string : string type.- <any other> : treated as string. |
no, default - string
|
defaultValue
|
The value assigned to the symbol if no parameter is provided by the user or host. The default is not applied if isRequired configuration is set to true for a parameter (or is set to condition that evaluates to true ), as that is an indication that user specified value is required. |
no |
defaultIfOptionWithoutValue |
The value assigned to the symbol if explicit null parameter value is provided by the user or host. |
no |
replaces
|
The text to be replaced by the symbol value in the template files content | no |
fileRename |
The portion of template filenames to be replaced by the symbol value. | no |
description |
Human readable text describing the meaning of the symbol. This has no effect on template generation. | no |
isRequired
|
Optional. Indicates if the user supplied value is required or not. Might be a fixed boolean value or a condition string that evaluates based on passed parameters - more details in Conditions documentation. If set to true (or condition that evaluates to true ) and user has not specified the value on input, validation error occurs - even if defaultValue is present. |
no |
isEnabled
|
Optional condition indicating whether parameter should be processed. Might be a fixed boolean value or a condition string that evaluates based on passed parameters - more details in Conditions documentation. | no |
choices |
Applicable only when datatype=choice. List of available choices. Contains array of the elements: - choice : possible value of the symbol.- description : human readable text describing the meaning of the choice. This has no effect on template generation. If not provided, there are no valid choices for the symbol, so it can never be assigned a value. |
yes, for dataType = choice
|
allowMultipleValues |
Applicable only when datatype=choice .Enables ability to specify multiple values for single symbol. |
no |
enableQuotelessLiterals
|
Applicable only when datatype=choice . Enables ability to specify choice literals in conditions without quotation. |
no |
onlyIf |
Defines the conditions that should be fulfilled in order that replacement happens. | no |
forms |
Defines the set of transforms that can be referenced by symbol definitions. Forms allow the specification of a "replaces"/"replacement" pair to also apply to other ways the "replaces" value may have been specified in the source by specifying a transform from the original value of "replaces" in configuration to the one that may be found in the source. Details | no |
Boolean optional parameter with default value false
:
"symbols": {
"TestProject": {
"type": "parameter",
"dataType": "bool",
"defaultValue": "false"
}
},
Choice optional parameter with 3 possible values:
"symbols": {
"Framework": {
"type": "parameter",
"description": "The target framework for the project.",
"datatype": "choice",
"enableQuotelessLiterals": true,
"choices": [
{
"choice": "netcoreapp3.1",
"description": "Target netcoreapp3.1"
},
{
"choice": "netstandard2.1",
"description": "Target netstandard2.1"
},
{
"choice": "netstandard2.0",
"description": "Target netstandard2.0"
}
],
"replaces": "netstandard2.0",
"defaultValue": "netstandard2.0"
}
}
String optional parameter, replaces TargetFrameworkOverride:
"symbols": {
"TargetFrameworkOverride": {
"type": "parameter",
"description": "Overrides the target framework",
"replaces": "TargetFrameworkOverride",
"datatype": "string",
"defaultValue": ""
}
}
Multi-choice symbols have similar behavior and usage scenarios as C# Flag enums - they express a range of possible values (not a single value - unlike the plain choice symbol)
"symbols":
{
"Platform": {
"type": "parameter",
"description": "The target platform for the project.",
"datatype": "choice",
"allowMultipleValues": true, // multi-choice indicator
"choices": [
{
"choice": "Windows",
"description": "Windows Desktop"
},
{
"choice": "MacOS",
"description": "Macintosh computers"
},
{
"choice": "iOS",
"description": "iOS mobile"
},
{
"choice": "android",
"description": "android mobile"
},
{
"choice": "nix",
"description": "Linux distributions"
}
],
"defaultValue": "MacOS|iOS"
}
}
There are some specifics in behavior of multi-choice symbols that are worth noting:
-
Condition evaluation - closer described in Conditions document.
-
Switch
symbol evaluation - conditions are evaluated by identical evaluator as preprocessing conditions (previous bullet point). -
Argument passing and tab completion on CLI - User can specify multiple options via repeating the argument switch for each option:
dotnet new MyTemplate --MyParameter value1 --MyParameter value2
or by passing multiple tokens to single option switch:
dotnet new MyTemplate --MyParameter value1 value2
Tab completion works identically as for standard choice symbol
-
Default values specification and API usage - Currently multiple values can be specified within single string separated by
|
or,
characters. Escaping of those characters within values is currently not supported. -
Using multi-choice value as a string in template content - this can be achieved via leveraging the
join
symbol. For simplicity it is as well possible to specify replacement for choice symbol with multiple values - in such case the values will be rendered into single string separated by|
sign.
A symbol that defines transformation of another symbol. The value of this symbol is derived from the value of another symbol by the application of form defined in valueTransform
.
Name | Description | Mandatory |
---|---|---|
type |
derived |
yes |
valueSource |
The name of the other symbol which value will be used to derive this value. | yes |
valueTransform |
The name of the value form to apply to the source value. | yes |
replaces |
The text to be replaced by the symbol value in the template files content | no |
fileRename |
The portion of template filenames to be replaced by the symbol value. | no |
description |
Human readable text describing the meaning of the symbol. This has no effect on template generation. | no |
Renames Application1
file to value of name
symbol after last dot
{
...
"symbols": {
"app1Rename": {
"type": "derived",
"valueSource": "name",
"valueTransform": "ValueAfterLastDot",
"fileRename": "Application1",
"description": "A value derived from the 'name' param, used to rename Application1.cs"
}
}
...
"forms": {
"ValueAfterLastDot": {
"identifier": "replace",
"pattern": "^.*\\.(?=[^\\.]+$)", // regex to match everything up to and including the final "."
"replacement": "" // replace it with empty string
}
}
...
}
A symbol which value gets computed by a built-in symbol value generator. Details
Name | Description | Mandatory |
---|---|---|
type |
generated |
yes |
generator |
Generator to use: See this article for more details. | yes |
parameters |
The parameters for generator. See description for each generator for details. | depends on generator |
replaces |
The text to be replaced by the symbol value in the template files content | no |
fileRename |
(supported in 5.0.200 or higher) The portion of template filenames to be replaced by the symbol value. | no |
dataType |
Supported values: - bool : boolean type, possible values: true /false . - float : double-precision floating format number. Accepts any value that can be parsed by double.TryParse() .- int /integer : 64-bit signed integer. Accepts any value that can be parsed by long.TryParse() .- hex : hex number. Accepts any value that can be parsed by long.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long convertedHex) .- text /string : string type.- <any other> : treated as string. |
no, default: string
|
-
myconstant
: replaces1234
with5001
-
ownername
: replacesJohn Smith (a)
with the value of theownername
parameter -
nameUpper
:- replaces
John Smith (U)
with the value of theownername
parameter in upper case in template files content - replaces
author_uc
with the value of theownername
parameter in upper case in filenames
- replaces
-
nameLower
:- replaces
John Smith (l)
with the value of theownername
parameter in lower case in template files content - replaces
author_lc
with the value of theownername
parameter in lower case in filenames
- replaces
"symbols":{
"myconstant": {
"type": "generated",
"generator": "constant",
"parameters": {
"value":"5001"
},
"replaces":"1234"
},
"ownername":{
"type": "parameter",
"datatype":"text",
"replaces": "John Smith (a)",
"defaultValue": "John Doe"
},
"nameUpper":{
"type": "generated",
"generator": "casing",
"parameters": {
"source":"ownername",
"toLower": false
},
"replaces":"John Smith (U)",
"fileRename": "author_uc"
},
"nameLower":{
"type": "generated",
"generator": "casing",
"parameters": {
"source":"ownername",
"toLower": true
},
"replaces":"John Smith (l)",
"fileRename": "author_lc"
}
}
A symbol for which the config provides a Boolean predicate whose evaluation result is the computed symbol result.
Name | Description | Mandatory |
---|---|---|
type |
computed |
yes |
value |
Boolean expression to be computed. | yes |
evaluator |
Language to be used for evaluation of expression: - C++2 - C++ - MSBUILD - VB
|
no, default: C++2
|
Please note that math operations are not supported in expressions at this point.
Values of OrganizationalAuth
, WindowsAuth
, MultiOrgAuth
, SingleOrgAuth
, IndividualAuth
, NoAuth
, RequiresHttps
symbols are computed based on auth
symbol.
"symbols": {
"auth": {
"type": "parameter",
"datatype": "choice",
"choices": [
{
"choice": "None",
"description": "No authentication"
},
{
"choice": "Individual",
"description": "Individual authentication"
},
{
"choice": "SingleOrg",
"description": "Organizational authentication for a single tenant"
},
{
"choice": "MultiOrg",
"description": "Organizational authentication for multiple tenants"
},
{
"choice": "Windows",
"description": "Windows authentication"
}
],
"defaultValue": "Individual",
"description": "The type of authentication to use"
},
"OrganizationalAuth": {
"type": "computed",
"value": "(auth == \"SingleOrg\" || auth == \"MultiOrg\")"
},
"WindowsAuth": {
"type": "computed",
"value": "(auth == \"Windows\")"
},
"MultiOrgAuth": {
"type": "computed",
"value": "(auth == \"MultiOrg\")"
},
"SingleOrgAuth": {
"type": "computed",
"value": "(auth == \"SingleOrg\")"
},
"IndividualAuth": {
"type": "computed",
"value": "(auth == \"Individual\")"
},
"NoAuth": {
"type": "computed",
"value": "(!(IndividualAuth || MultiOrgAuth || SingleOrgAuth || WindowsAuth))"
},
"RequiresHttps": {
"type": "computed",
"value": "(OrganizationalAuth)"
}
}
See the article.
Name | Description | Default | Mandatory |
---|---|---|---|
sourceName |
The name in the source tree to replace with the name the user specifies. The value to be replaced with can be given using the -n --name options while running a template. The template engine will look for any occurrence of the name present in the config file and replace it in file names and file contents. If no name is specified by the host, the current directory is used. The value of the sourceName is available in built-in name symbol and can be used as the source for creating other symbols and condition expressions. |
no | |
preferNameDirectory |
Boolean value, 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). | If not specified, false is used. |
no |
placeholderFilename |
A filename that will be completely ignored, used to indicate that its containing directory should be copied. This allows creation of empty directory in the created template, by having a corresponding source directory containing just the placeholder file. By default, empty directories are ignored. | If not specified, a default value of "-.-" is used. |
no |
primaryOutputs |
A list of template files for further processing by the host (including post-actions). The path should contain the relative path to the file prior to the symbol based renaming that may happen during template generation. It is defined as an array of Primary Outputs | no |
Primary outputs define the list of template files for further processing, usually post actions.
Name | Description | Mandatory |
---|---|---|
path |
should contain the relative path to the file after the template is instantiated. | yes |
condition |
if the condition evaluates to true , the corresponding path will be added to primary outputs, if false , the path is ignored. If no condition is provided for a path, the condition defaults to true . |
no |
For more information on primary outputs, refer to the article.
This advanced configuration allows the template author to define custom actions for the template creation process. Global custom operations are scoped globally unless overridden by a more restrictive custom configuration. Special custom operations are scoped to the files matched by their glob pattern.
Customizations allowed include:
- Flag definitions
- Modification operations
There can only be one instance of the (global) customOperations
section, as follows:
"customOperations": {
// configuration details
}
But since there can be many instances of the SpecialCustomOperations, each applicable to their glob patterns, the specialCustomOperations
configuration section is defined as follows:
"specialCustomOperations": {
"<fileglob1>": {
// configuration details
},
"<fileglob2>": {
// configuration details
},
}
The configuration details options are identical in both situations, they only differ in the scopes they're applied in. The below sections are labelled customOperations.<item>
, but are equally applicable to specialCustomOperations.<fileglob>.<Item>
Name | Description | Mandatory |
---|---|---|
flagPrefix |
Overrides the default prefix to indicate a flag option in a file being processed. | no |
operations |
An array that defines custom operations for processing data in the files within the scope of the configuration. These operations are applied in addition to other operations setup by default, except in the case of the conditional operation. If a custom conditional operation is defined, the default conditional operation(s) are ignored (in this scope). | no |
operations.type |
Indicates the type of operation being configured. The operations currently available to configure are: - balancedNesting - conditional - flag - include - region - replacement
|
yes |
operations.condition |
A boolean expression whose result determines whether or not to use this custom operation. If this is not provided, the operation is used. | no |
operations.configuration |
The details of the operation configuration. Each type of operation has its own configuration options, as detailed below. | yes |
SpecialCustomOperations can be used for adding conditions for handling files with extensions not listed in Conditional processing and comment syntax.
{
"SpecialCustomOperations": {
"**.axml": {
"operations": [
{
"type": "conditional",
"configuration": {
"endif": [ "#endif", "<!--#endif" ],
"actionableIf": [ "<!--#if" ],
"actionableElse": [ "#else", "<!--#else" ],
"actionableElseif": [ "#elseif", "<!--#elseif", "#elif", "<!--#elif" ],
"trim": true,
"wholeLine": true,
"evaluator": "C++"
}
}
]
}
}
}
This operation type is designed to be used in conjunction with a conditional operation, to help maintain the proper commenting on conditional, and the text they may optionally emit. See the section on configuring a custom conditional operation for more details.
Conditional operations allow sections of template files to be optionally included during template creation.
The customization of this operation facilitates preprocessing on many file formats for which there is no standard preprocessor syntax defined, by defining comment-based symbols to represent the preprocessor directives. By using comments recognized by the file formats, the unprocessed file content is valid even when it contains the customized preprocessor directives (since they're commented out as needed).
Conditional processing is based on the 4 conditional keywords:
if
elseif
else
endif
Other than the endif
keyword, each keyword type can be defined in up to 2 flavors, basic
and actionable
. The basic flavor indicates that if the condition is true
, the contents should be emitted verbatim. The actionable
flavor indicates that other actions should be taken on the content of the conditional - usually the other action is uncommenting.
Here is an example of defining a custom conditional operation (this is the actual predefined C-style line comments conditional configuration, which is the default for .json files)
{
"type": "conditional",
"configuration": {
"if": [ "//#if" ],
"else": [ "//#else" ],
"elseif": [ "//#elseif" ],
"endif": [ "//#endif" ],
"actionableIf": [ "////#if" ],
"actionableElse": [ "////#else" ],
"actionableElseif": [ "////#elseif" ],
"actions": [ "cStyleUncomment", "cStyleReduceComment" ],
"trim": true,
"wholeLine": true,
"evaluator": "C++"
},
}
Because there are actionable keywords, there is an "actions" field provided, which refers to other action(s) to activate when an actionable token is encountered. The other actions remain active until any other token in the conditional config is encountered. In this case, the other actions jobs are to remove comments, and to reduce consecutive double comments to a single comment.
These other actions are defined as:
{
"type": "replacement",
"configuration": {
"original": "//",
"replacement": "",
"id": "cStyleUncomment",
},
},
{
"type": "replacement",
"configuration": {
"original": "////",
"replacement": "//",
"id": "cStyleReduceComment",
},
}
Note that the id
in the replacement configurations correspond to the actions in the conditional configuration. This is what ties them together - it causes the replacements to be activated / deactivated when the actionable tokens are in / out of scope.
Let's look at a specific example of a template file being processed by this configuration, and see what happens:
...
//#if (A)
// comment related to the 'if' content
default content // also appropriate if A is true
////#elseif (B)
//// comment related to the 'elseif' content
//content for when B is true and A is false
////#else
// comment related to the 'else' content
// content for when both A & B are false
//#endif
...
There are 4 possible scenarios for when this appears in a template file.
- No appropriate conditional processing. In this case, the entire block above will be copied to the created template as-is. This includes all the commenting, i.e.:
//#if (A)
// comment related to the 'if' content
default content // also appropriate if A is true
////#elseif (B)
//// comment related to the 'elseif' content
//content for when B is true and A is false
////#else
//// comment related to the 'else' content
// content for when both A & B are false
//#endif
which means only the default content under the 'if' will be interpreted in the created template.
- A is
true
Because the conditional token //#if
was specified in the conditional configuration as an if
token (as opposed to an actionableIf
token), the actions
operations are not activated, so no commenting will change. Thus, the lines between the //#if
and the /#elseif
is the only part emitted to the created template, i.e.:
// comment related to the 'if' content
default content // also appropriate if A is true
- B is true (A is false)
The elseif
predicate is true
, so only content under the elseif will be emitted to the created template. But ////#elseif
is an actionable token, so the actions
operations get activated, resulting in this text to be output:
// comment related to the 'elseif' content
content for when B is true and A is false
Note the comment changes from the original text - they're a results of the other 'actions'.
- Both A & B are false
The else should happen. Note that ////#else
is an actionable token, resulting in this text to be output:
// comment related to the 'else' content
content for when both A & B are false
For more details, refer to Conditional processing article.