Skip to content

Commit c81e85a

Browse files
authored
feat: improve templates with new handlebars helper (#9)
* feat: improve templates with new handlebars helper * chore: update docs
1 parent 39701f4 commit c81e85a

15 files changed

+92
-31
lines changed

docs/guide/helper-functions.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,45 @@ Hello, World!
3737
─────────────
3838
```
3939

40+
### `format_text`
41+
42+
Thu helper is designed to prepare plain or structured text for HTML or Markdown-like rendering. It does the following:
43+
44+
- Replaces line breaks (`\n`) in the input text with a custom line break string (like `<br/>` or an actual newline).
45+
46+
- Wraps inline code snippets—identified by delimiter pairs like <code>\`</code> or `'` — in `<code>` tags for HTML formatting (e.g., turning 'param' into `<code>param</code>`).
47+
48+
This helper is especially useful for formatting capability descriptions in web documentation, markdown previews, or any UI where readable line breaks and inline code styling are needed.
49+
50+
The `code_wrap_chars` parameter (last parameter of the helper function) defines pairs of characters that will wrap inline code blocks and get converted to <code>...</code> in the output.
51+
52+
You must pass a string made up of an even number of characters, where each two characters form one pair:
53+
54+
The first character is the opening delimiter
55+
The last character is the closing delimiter
56+
57+
| Input | Effect |
58+
| -------- | -------------------------------------- |
59+
| `"[]"` | Matches `[code]``<code>code</code>` |
60+
| `"''"` | Matches `'code'``<code>code</code>` |
61+
| `"['']"` | Matches both `[code]` and `'code'` |
62+
63+
Example:
64+
65+
```hbs
66+
{{format_text "Each entry includes 'name', `type` , and 'children' for directories." "<br>" "'``'" }}
67+
```
68+
69+
Output text:
70+
71+
```md
72+
Each entry includes <code>name</code>, <code>type</code> , and <code>children</code> for directories.
73+
```
74+
75+
Rendered Output:
76+
77+
Each entry includes <code>name</code>, <code>type</code> , and <code>children</code> for directories.
78+
4079
### `capability`
4180

4281
This helper formats a capability with an optional count and a boolean indicator based on whether the capability is supported.

src/render_template.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,46 @@ pub fn register_helpers(handlebar: &mut Handlebars) {
6767
// Helper: Adds 1 to an integer value.
6868
handlebars_helper!(plus_one: |v: i64| format!("{}", v+1));
6969

70+
// Helper: replaces new line characters with provided `new_line` and optionally wraps tokens enclosed in specified delimiter pairs (like `` or '') with <code> tags.
71+
// This can be used to format plain text for HTML or MD display, enabling readable line breaks and inline code styling.
72+
handlebars_helper!(format_text: |text: Option<String>, new_line: Option<String>, code_wrap_chars:Option<String> | {
73+
74+
let text = text.unwrap_or_default();
75+
76+
let new_line = new_line.unwrap_or(line_ending(&text, None).to_string());
77+
78+
let mut replacers = vec![("\\n".to_string(),new_line)];
79+
80+
if let Some(code_wrap_chars) = code_wrap_chars {
81+
// Proceed only if `code_wrap_chars` contains an even number of characters,
82+
// so we can pair each starting wrap character with a corresponding ending one.
83+
if code_wrap_chars.len() % 2 == 0 {
84+
for (left_char, right_char) in code_wrap_chars
85+
.chars()
86+
.take(code_wrap_chars.len() / 2)
87+
.zip(code_wrap_chars.chars().rev())
88+
{
89+
replacers.push((
90+
format!(
91+
"{}([\\w\\-\\_]+){}",
92+
regex::escape(&left_char.to_string()),
93+
regex::escape(&right_char.to_string()),
94+
),
95+
"<code>$1</code>".to_string(),
96+
));
97+
}
98+
}
99+
}
100+
101+
let mut result = text;
102+
for (regex_str, replace_str) in replacers {
103+
let re = Regex::new(&regex_str).unwrap();
104+
result = re.replace_all(&result, replace_str).to_string();
105+
}
106+
107+
result
108+
});
109+
70110
// Helper: Formats a capability tag with a boolean indicator and optional count.
71111
handlebars_helper!(capability_tag: |label:Value, supported: Value, count: Option<i64>| {
72112
let count_str = count.map_or("".to_string(), |count| format!(" ({})", count));
@@ -120,6 +160,7 @@ pub fn register_helpers(handlebar: &mut Handlebars) {
120160
let helpers: Vec<(&str, Box<dyn HelperDef + Send + Sync>)> = vec![
121161
("plus_one", Box::new(plus_one)),
122162
("underline", Box::new(underline)),
163+
("format_text", Box::new(format_text)),
123164
("capability_tag", Box::new(capability_tag)),
124165
("capability", Box::new(capability)),
125166
("capability_title", Box::new(capability_title)),

templates/html/html_prompts.hbs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
<td>
1717
<code><b>{{{this.name}}}</b></code>
1818
</td>
19-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>")
20-
"\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
19+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2120
</tr>
2221
{{/each}}
2322
</tbody>

templates/html/html_resource_templates.hbs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
<td>
2121
<a>{{this.uriTemplate}} {{#if this.mimeType}}({{{this.mimeType}}}){{/if}}</a>
2222
</td>
23-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>")
24-
"\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
23+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2524
</tr>
2625
{{/each}}
2726
</tbody>

templates/html/html_resources.hbs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
<td>
2121
<a>{{this.uri}}</a> {{#if this.mimeType}}<i>({{{this.mimeType}}})</i>{{/if}}
2222
</td>
23-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>")
24-
"\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
23+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2524
</tr>
2625
{{/each}}
2726
</tbody>

templates/html/html_tools.hbs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
<td>
1818
<code><b>{{{this.name}}}</b></code>
1919
</td>
20-
<td>{{{replace_regex ( replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\n" "<br/>")
21-
"\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
20+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2221
<td>
2322
<ul>
2423
{{#each this.params}}

templates/markdown/md_plain_prompts.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
{{#each prompts}}
66

77
- **{{{this.name}}}**
8-
- {{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}
8+
- {{{format_text this.description "<br/>" "['``']"}}}
99
{{/each}}
1010
{{/if}}

templates/markdown/md_plain_resource_templates.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
- **{{{this.name}}}**
77
{{#if this.description}}
8-
- {{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}
8+
- {{{format_text this.description "<br/>" "['``']"}}}
99
{{/if}}
1010
{{#if this.uri}}
1111
- URI: <a>{{this.uriTemplate}}</a> {{#if this.mimeType}}<i>({{{this.mimeType}}})</i>{{/if}}

templates/markdown/md_plain_resources.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
- **{{{this.name}}}**
77
{{#if this.description}}
8-
- {{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}{{/if}}
8+
- {{{format_text this.description "<br/>" "['``']"}}}{{/if}}
99
{{#if this.uri}}
1010
- URI: <a>{{this.uri}}</a> <i>{{#if this.mimeType}}({{{this.mimeType}}}){{/if}}</i>
1111
{{/if}}

templates/markdown/md_plain_tools.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{{#each tools}}
55

66
- **{{{this.name}}}**
7-
- {{{replace_regex (replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\n" "\n ") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}
7+
- {{{format_text this.description "<br/>" "['``']"}}}
88
{{#if this.params}}
99
- **Inputs:**
1010
{{#each this.params}}

templates/markdown/md_prompts.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<td>
1717
<code><b>{{{this.name}}}</b></code>
1818
</td>
19-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
19+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2020
</tr>
2121
{{/each}}
2222
</tbody>

templates/markdown/md_resource_templates.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<td>
2121
<a>{{this.uriTemplate}}</a> {{#if this.mimeType}}<i>({{{this.mimeType}}})</i>{{/if}}
2222
</td>
23-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
23+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2424
</tr>
2525
{{/each}}
2626
</tbody>

templates/markdown/md_resources.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<td>
2121
<a>{{this.uri}}</a> <i>{{#if this.mimeType}}({{{this.mimeType}}}){{/if}}</i>
2222
</td>
23-
<td>{{{replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
23+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2424
</tr>
2525
{{/each}}
2626
</tbody>

templates/markdown/md_tools.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<td>
1818
<code><b>{{{this.name}}}</b></code>
1919
</td>
20-
<td>{{{replace_regex (replace_regex (replace_regex this.description "'([\\w\\-\\_]+)'" "<code>$1</code>") "\\n" "\\n ")"\\[([\\w\\-\\_]+)\\]" "<code>$1</code>"}}}</td>
20+
<td>{{{format_text this.description "<br/>" "['``']"}}}</td>
2121
<td>
2222
<ul>
2323
{{#each this.params}}

tests/fixtures/cmds.txt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,8 @@
1-
# create md-create.md
21
./mcp-discovery create -f ../../tests/fixtures/md-create.md -- npx -y @modelcontextprotocol/server-everything
3-
4-
# create md-create.md
52
./mcp-discovery create -f ../../tests/fixtures/md-plain-create.md --template md-plain -- npx -y @modelcontextprotocol/server-everything
6-
7-
# create txt-create.txt
83
./mcp-discovery create -f ../../tests/fixtures/txt-create.txt --template txt -- npx -y @modelcontextprotocol/server-everything
9-
10-
# full update md-update.md
114
./mcp-discovery update -f ../../tests/fixtures/md-update.md -- npx -y @modelcontextprotocol/server-everything
12-
13-
# full update md-plain-update.md
145
./mcp-discovery update -f ../../tests/fixtures/md-plain-update.md -t md-plain -- npx -y @modelcontextprotocol/server-everything
15-
16-
# md-plain-update-file-prop.md
176
./mcp-discovery update -f ../../tests/fixtures/md-plain-update-file-prop.md -- npx -y @modelcontextprotocol/server-everything
18-
19-
# md-plain-update-template-prop.md
207
./mcp-discovery update -f ../../tests/fixtures/md-plain-update-template-prop.md -- npx -y @modelcontextprotocol/server-everything
21-
22-
# md-plain-update-inline.md
238
./mcp-discovery update -f ../../tests/fixtures/md-plain-update-inline.md -- npx -y @modelcontextprotocol/server-everything

0 commit comments

Comments
 (0)