Skip to content

Commit 3fa4b33

Browse files
authored
Add support for variable operator syntax (#1563)
* Add support for variable operator syntax * do not report version variables as unused * Allow a space after {{ * carry trimming over to split * Temporarily make variables with spaces that are not found hints, we used to not do anything here * flip ternary
1 parent b3ea986 commit 3fa4b33

File tree

9 files changed

+311
-51
lines changed

9 files changed

+311
-51
lines changed

docs/syntax/substitutions.md

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ sub:
33
frontmatter_key: "Front Matter Value"
44
a-key-with-dashes: "A key with dashes"
55
version: 7.17.0
6+
hello-world: "Hello world!"
67
---
78

89
# Substitutions
@@ -26,7 +27,7 @@ Doing so will result in a build error.
2627

2728
To use the variables in your files, surround them in curly brackets (`{{variable}}`).
2829

29-
## Example
30+
### Example
3031

3132
Here are some variable substitutions:
3233

@@ -36,6 +37,97 @@ Here are some variable substitutions:
3637
| {{a-key-with-dashes}} | Front Matter |
3738
| {{a-global-variable}} | `docset.yml` |
3839

40+
## Mutations
41+
42+
Substitutions can be mutated using a chain of operators seperated by a pipe (`|`).
43+
44+
````markdown
45+
`{{hello-world | trim | lc | tc}}`
46+
````
47+
48+
Will trim, lowercase and finally titlecase the contents of the 'hello-world' variable.
49+
50+
### Operators
51+
52+
53+
| Operator | Purpose |
54+
|----------|----------------------------------------------------|
55+
| `lc` | LowerCase, |
56+
| `uc` | UpperCase, |
57+
| `tc` | TitleCase, capitalizes all words, |
58+
| `c` | Capitalize the first letter, |
59+
| `kc` | Convert to KebabCase, |
60+
| `sc` | Convert to SnakeCase, |
61+
| `cc` | Convert to CamelCase, |
62+
| `pc` | Convert to PascalCase, |
63+
| `trim` | Trim common non word characters from start and end |
64+
65+
For variables declaring a semantic version or `Major.Minor` the following operations are also exposed
66+
67+
| Operator | Purpose |
68+
|----------|------------------------------------------|
69+
| `M` | Display only the major component |
70+
| `M.x` | Display major component followed by '.x' |
71+
| `M.M` | Display only the major and the minor |
72+
| `M+1` | The next major version |
73+
| `M.M+1` | The next minor version |
74+
75+
### Example
76+
77+
Given the following frontmatter:
78+
79+
```yaml
80+
---
81+
sub:
82+
hello-world: "Hello world!"
83+
---
84+
```
85+
86+
::::{tab-set}
87+
88+
:::{tab-item} Output
89+
90+
* Lowercase: {{hello-world | lc}}
91+
* Uppercase: {{hello-world | uc}}
92+
* TitleCase: {{hello-world | tc}}
93+
* kebab-case: {{hello-world | kc}}
94+
* camelCase: {{hello-world | tc | cc}}
95+
* PascalCase: {{hello-world | pc}}
96+
* SnakeCase: {{hello-world | sc}}
97+
* CapitalCase (chained): {{hello-world | lc | c}}
98+
* Trim: {{hello-world | trim}}
99+
* M.x: {{version.stack | M.x }}
100+
* M.M: {{version.stack | M.M }}
101+
* M: {{version.stack | M }}
102+
* M+1: {{version.stack | M+1 }}
103+
* M+1 | M.M: {{version.stack | M+1 | M.M }}
104+
* M.M+1: {{version.stack | M.M+1 }}
105+
106+
:::
107+
108+
:::{tab-item} Markdown
109+
110+
````markdown
111+
* Lowercase: {{hello-world | lc}}
112+
* Uppercase: {{hello-world | uc}}
113+
* TitleCase: {{hello-world | tc}}
114+
* kebab-case: {{hello-world | kc}}
115+
* camelCase: {{hello-world | tc | cc}}
116+
* PascalCase: {{hello-world | pc}}
117+
* SnakeCase: {{hello-world | sc}}
118+
* CapitalCase (chained): {{hello-world | lc | c}}
119+
* Trim: {{hello-world | trim}}
120+
* M.x: {{version.stack | M.x }}
121+
* M.M: {{version.stack | M.M }}
122+
* M: {{version.stack | M }}
123+
* M+1: {{version.stack | M+1 }}
124+
* M+1 | M.M: {{version.stack | M+1 | M.M }}
125+
* M.M+1: {{version.stack | M.M+1 }}
126+
````
127+
:::
128+
129+
::::
130+
39131
## Code blocks
40132

41133
Substitutions are supported in code blocks but are disabled by default. Enable substitutions by adding `subs=true` to the code block.

docs/syntax/version-variables.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,21 @@ Besides the current version, the following suffixes are available:
1010

1111
| Version substitution | result | purpose |
1212
|--------------------------------------|-----------------------------------|-----------------------------------------|
13-
| `{{versions.stack}}` | {{version.stack}} | Current version |
14-
| `{{versions.stack.major_minor}}` | {{version.stack.major_minor}} | Current `MAJOR.MINOR` |
15-
| `{{versions.stack.major_x}}` | {{version.stack.major_x}} | Current `MAJOR.X` |
16-
| `{{versions.stack.major_component}}` | {{version.stack.major_component}} | Current major component |
17-
| `{{versions.stack.next_major}}` | {{version.stack.next_major}} | The next major version |
18-
| `{{versions.stack.next_minor}}` | {{version.stack.next_minor}} | The next minor version |
19-
| `{{versions.stack.base}}` | {{version.stack.base}} | The first version on the new doc system |
13+
| `{{version.stack}}` | {{version.stack}} | Current version |
14+
| `{{version.stack.base}}` | {{version.stack.base}} | The first version on the new doc system |
2015

16+
## Formatting
17+
18+
Using specialized [mutation operators](substitutions.md#mutations) versions
19+
can be printed in any kind of ways.
20+
21+
22+
| Version substitution | result |
23+
|------------------------|-----------|
24+
| `{{version.stack| M.M}}` | {{version.stack|M.M}} |
25+
| `{{version.stack.base | M }}` | {{version.stack.base | M }} |
26+
| `{{version.stack | M+1 | M }}` | {{version.stack | M+1 | M }} |
27+
| `{{version.stack.base | M.M+1 }}` | {{version.stack.base | M.M+1 }} |
2128

2229
## Available versioning schemes.
2330

src/Elastic.Documentation.Configuration/Builder/ConfigurationFile.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -163,27 +163,11 @@ public ConfigurationFile(IDocumentationContext context, VersionsConfiguration ve
163163
foreach (var (id, system) in versionsConfig.VersioningSystems)
164164
{
165165
var name = id.ToStringFast(true);
166-
var current = system.Current;
167166
var key = $"version.{name}";
168167
_substitutions[key] = system.Current;
169168

170169
key = $"version.{name}.base";
171170
_substitutions[key] = system.Base;
172-
173-
key = $"version.{name}.major_minor";
174-
_substitutions[key] = $"{current.Major:N0}.{current.Minor:N0}";
175-
176-
key = $"version.{name}.major_x";
177-
_substitutions[key] = $"{current.Major:N0}.x";
178-
179-
key = $"version.{name}.major_component";
180-
_substitutions[key] = $"{current.Major:N0}";
181-
182-
key = $"version.{name}.next_minor";
183-
_substitutions[key] = new SemVersion(current.Major, current.Minor + 1, current.Patch, current.Prerelease, current.Metadata);
184-
185-
key = $"version.{name}.next_major";
186-
_substitutions[key] = new SemVersion(current.Major + 1, current.Minor, current.Patch, current.Prerelease, current.Metadata);
187171
}
188172

189173
var toc = new TableOfContentsConfiguration(this, sourceFile, ScopeDirectory, _context, 0, "");

src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,24 @@ public static class ProcessorDiagnosticExtensions
1414
{
1515
private static string CreateExceptionMessage(string message, Exception? e) => message + (e != null ? Environment.NewLine + e : string.Empty);
1616

17-
public static void EmitError(this InlineProcessor processor, int line, int column, int length, string message)
18-
{
19-
var context = processor.GetContext();
20-
if (context.SkipValidation)
21-
return;
22-
var d = new Diagnostic
23-
{
24-
Severity = Severity.Error,
25-
File = processor.GetContext().MarkdownSourcePath.FullName,
26-
Column = column,
27-
Line = line,
28-
Message = message,
29-
Length = length
30-
};
31-
context.Build.Collector.Write(d);
32-
}
17+
public static void EmitError(this InlineProcessor processor, int line, int column, int length, string message) =>
18+
processor.Emit(Severity.Error, line, column, length, message);
3319

3420

35-
public static void EmitWarning(this InlineProcessor processor, int line, int column, int length, string message)
21+
public static void EmitWarning(this InlineProcessor processor, int line, int column, int length, string message) =>
22+
processor.Emit(Severity.Warning, line, column, length, message);
23+
24+
public static void EmitHint(this InlineProcessor processor, int line, int column, int length, string message) =>
25+
processor.Emit(Severity.Hint, line, column, length, message);
26+
27+
public static void Emit(this InlineProcessor processor, Severity severity, int line, int column, int length, string message)
3628
{
3729
var context = processor.GetContext();
3830
if (context.SkipValidation)
3931
return;
4032
var d = new Diagnostic
4133
{
42-
Severity = Severity.Warning,
34+
Severity = severity,
4335
File = processor.GetContext().MarkdownSourcePath.FullName,
4436
Column = column,
4537
Line = line,

src/Elastic.Markdown/DocumentationGenerator.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,13 @@ private void HintUnusedSubstitutionKeys()
180180
{
181181
var definedKeys = new HashSet<string>(Context.Configuration.Substitutions.Keys.ToArray());
182182
var inUse = new HashSet<string>(Context.Collector.InUseSubstitutionKeys.Keys);
183-
var keysNotInUse = definedKeys.Except(inUse).ToArray();
183+
var keysNotInUse = definedKeys.Except(inUse)
184+
// versions keys are injected
185+
.Where(key => !key.StartsWith("version."))
186+
// reserving context namespace
187+
.Where(key => !key.StartsWith("context."))
188+
.ToArray();
189+
184190
// If we have less than 20 unused keys, emit them separately,
185191
// Otherwise emit one hint with all of them for brevity
186192
if (keysNotInUse.Length >= 20)

0 commit comments

Comments
 (0)