Skip to content

Commit

Permalink
Add escape_square_brackets into comment_formats markdown configur…
Browse files Browse the repository at this point in the history
…ation (#379)

* feat(forge): Add `escape_square_brackets` into `comment_formats` markdown configuration

* feat(forge): Change default value for `escape_square_brackets`
  • Loading branch information
lquerel authored Sep 19, 2024
1 parent bc8e7ec commit 2d4d070
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.

What's changed

* Add `escape_square_brackets` into `comment_formats` markdown configuration. ([#XXX](...) by lquerel).
* Add `enforce_trailing_dots` into the `comment_formats` configuration. ([#XXX](...) by lquerel).
* Add support for `indent_type` in both the comment filter and the `comment_formats` configuration. ([#XXX](...) by lquerel).
* Add `regex_replace` filter to support replacing text using regex. ([#XXX](...) by lquerel).
Expand Down
1 change: 1 addition & 0 deletions crates/weaver_forge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ comment_formats: # optional

# Fields specific to 'markdown' format
escape_backslashes: <bool> # Whether to escape backslashes in markdown (default: false).
escape_square_brackets: <bool> # Whether to escape square brackets in markdown (default: false).
shortcut_reference_links: <bool> # Convert inlined links into shortcut reference links (default: false).
indent_first_level_list_items: <bool> # Indent the first level of list items in markdown (default: false).
default_block_code_language: <string> # Default language for block code snippets (default: "").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
/// > Lorem ipsum dolor sit amet, consectetur adipiscing
/// > elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
///
/// > [!NOTE] Something very important here
/// > \[!NOTE\] Something very important here
const ATTR: &str = "";


125 changes: 121 additions & 4 deletions crates/weaver_forge/src/formats/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ use std::collections::HashMap;
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
#[serde(rename_all = "snake_case")]
pub struct MarkdownRenderOptions {
/// Whether to escape backslashes in the markdown.
/// Whether to escape backslashes in the Markdown.
/// Default is false.
#[serde(default)]
pub(crate) escape_backslashes: bool,
/// Whether to escape square brackets in the Markdown text. Valid links are not affected.
/// Default is true.
#[serde(default = "default_bool::<true>")]
pub(crate) escape_square_brackets: bool,
/// Whether to indent the first level of list items in the markdown.
/// Default is false.
#[serde(default)]
Expand All @@ -30,6 +34,12 @@ pub struct MarkdownRenderOptions {
pub(crate) default_block_code_language: Option<String>,
}

/// Used to set a default value for a boolean field in a struct.
#[must_use]
pub const fn default_bool<const V: bool>() -> bool {
V
}

pub(crate) struct ShortcutReferenceLink {
pub(crate) label: String,
pub(crate) url: String,
Expand Down Expand Up @@ -196,11 +206,36 @@ impl MarkdownRenderer {
}
}
Node::Text(text) => {
fn escape_unescaped_chars(s: &str, chars_to_escape: &[char]) -> String {
let mut result = String::with_capacity(s.len());
let mut backslash_count = 0;

for c in s.chars() {
if c == '\\' {
backslash_count += 1;
result.push(c);
} else {
if chars_to_escape.contains(&c) && backslash_count % 2 == 0 {
// Even number of backslashes means the character is unescaped
result.push('\\');
}
result.push(c);
// Reset the backslash count after a non-backslash character
backslash_count = 0;
}
}

result
}

let mut text = text.value.clone();
if options.escape_backslashes {
ctx.add_text(&text.value.replace('\\', "\\\\"));
} else {
ctx.add_text(&text.value);
text = text.replace('\\', "\\\\");
}
if options.escape_square_brackets {
text = escape_unescaped_chars(&text, &['[', ']']);
}
ctx.add_text(&text);
}
Node::Paragraph(p) => {
ctx.add_cond_blank_line();
Expand Down Expand Up @@ -375,6 +410,7 @@ mod tests {
indent_type: IndentType::Space,
format: RenderFormat::Markdown(MarkdownRenderOptions {
escape_backslashes: false,
escape_square_brackets: false,
indent_first_level_list_items: true,
shortcut_reference_link: true,
default_block_code_language: None,
Expand Down Expand Up @@ -467,6 +503,87 @@ it's RECOMMENDED to:
- Use a domain-specific attribute
- Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not."##
);

let config = WeaverConfig {
comment_formats: Some(
vec![(
"go".to_owned(),
CommentFormat {
header: None,
prefix: Some("// ".to_owned()),
footer: None,
format: RenderFormat::Markdown(MarkdownRenderOptions {
escape_backslashes: false,
escape_square_brackets: false,
indent_first_level_list_items: true,
shortcut_reference_link: true,
default_block_code_language: None,
}),
trim: true,
remove_trailing_dots: true,
indent_type: Default::default(),
enforce_trailing_dots: false,
},
)]
.into_iter()
.collect(),
),
default_comment_format: Some("go".to_owned()),
..WeaverConfig::default()
};

let renderer = MarkdownRenderer::try_new(&config)?;
let markdown = r##"In some cases a [URL] may refer to an [IP](http://ip.com) and/or port directly,
The file \\[extension\\] extracted \\[from] the `url.full`, excluding the leading dot."##;
let html = renderer.render(markdown, "go")?;
assert_eq!(
html,
r##"In some cases a [URL] may refer to an [IP] and/or port directly,
The file \[extension\] extracted \[from] the `url.full`, excluding the leading dot.
[IP]: http://ip.com"##
);

let config = WeaverConfig {
comment_formats: Some(
vec![(
"go".to_owned(),
CommentFormat {
header: None,
prefix: Some("// ".to_owned()),
footer: None,
format: RenderFormat::Markdown(MarkdownRenderOptions {
escape_backslashes: false,
escape_square_brackets: true,
indent_first_level_list_items: true,
shortcut_reference_link: true,
default_block_code_language: None,
}),
trim: true,
remove_trailing_dots: true,
indent_type: Default::default(),
enforce_trailing_dots: false,
},
)]
.into_iter()
.collect(),
),
default_comment_format: Some("go".to_owned()),
..WeaverConfig::default()
};

let renderer = MarkdownRenderer::try_new(&config)?;
let markdown = r##"In some cases a [URL] may refer to an [IP](http://ip.com) and/or port directly,
The file \[extension\] extracted \[from] the `url.full`, excluding the leading dot."##;
let html = renderer.render(markdown, "go")?;
assert_eq!(
html,
r##"In some cases a \[URL\] may refer to an [IP] and/or port directly,
The file \[extension\] extracted \[from\] the `url.full`, excluding the leading dot.
[IP]: http://ip.com"##
);

Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/weaver_forge/templates/comment_format/weaver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ comment_formats:
shortcut_reference_link: true
trim: true
remove_trailing_dots: true
escape_square_brackets: false
python:
format: markdown
header: '"""'
footer: '"""'
escape_backslashes: true
trim: true
remove_trailing_dots: true
escape_square_brackets: false

templates:
- template: "example.java.j2"
Expand Down
1 change: 1 addition & 0 deletions docs/weaver-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ comment_formats: # optional

# The following fields are enabled only when format is set to 'markdown'
escape_backslashes: <bool> # Whether to escape backslashes in the markdown (default: false).
escape_square_brackets: <bool> # Whether to escape square brackets in markdown (default: false).
shortcut_reference_links: <bool> # Use this to convert inlined links into shortcut reference links, similar to those in Go documentation (default: false).
indent_first_level_list_items: <bool> # Whether to indent the first level of list items in the markdown (default: false).
default_block_code_language: <string> # The default language for block code snippets (default: "").
Expand Down

0 comments on commit 2d4d070

Please sign in to comment.