Skip to content

Commit

Permalink
Update version.
Browse files Browse the repository at this point in the history
Add `directives` explanation to README.
Fix that markdown directive wasn't being added to Vector.
Abstract markdown mutation out of `create_variable` into the main method to handle mutating of any variable, not just content.
Change parser to always add markdown if variable is named `content`.
  • Loading branch information
BritishWerewolf committed Mar 27, 2024
1 parent 2c20aad commit 092580e
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "blogs-md-easy"
description = "Iteratively convert a collection of Markdown files into a respective HTML template."
version = "0.1.5"
version = "0.2.0"
edition = "2021"
keywords = ["markdown", "html", "template", "blog"]
categories = ["command-line-interface", "config", "web-programming"]
Expand Down
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,62 @@ Variables can be reused as many times as required, and will be replaced, providi

Finally, the `£content` variable is automatically generated based on the entire body of the Markdown file.

#### Directives
It's possible to mutate the placeholders during rendering by providing directives.
A directive is just a way of applying a pre-defined function to any placeholder variable.

Let's use our previous template, and apply a simple directive to the `£title` variable.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="{{ £description }}">

<title>{{ £title }}</title>
</head>
<body>
<section>
<h1>{{ £title | uppercase }}</h1>
<p>Authored by {{ £author }}</p>
</section>
<section>{{ £content }}</section>
</body>
</html>
```
By providing the function after a pipe (`|`) character, we can mutate that variable in that particular location. This is particularly useful in cases where a placeholder is required multiple times through a template, but the formatting should be different in all cases.

There are currently three supported directives:
* `lowercase` - Convert the value to lowercase.
* `uppercase` - Convert the value to uppercase.
* `markdown` - Convert the value from Markdown into HTML.

By default, no directives will be provided, unless specified within the template, with the exception of `£content` which will have `markdown` applied.

Directives are case insensitive, meaning `| uppercase` is the same as `| UPPERCASE`. They can also be chained together, such as in the following example.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="{{ £description }}">

<title>{{ £title }}</title>
</head>
<body>
<section>
{{ £title | uppercase | markdown }}
<p>Authored by {{ £author }}</p>
</section>
<section>{{ £content }}</section>
</body>
</html>
```
Here we are converting the title to uppercase, and then mutating the value into markdown.
Chained directives are evaluated from left to right.

### Markdowns
[Markdowns](https://daringfireball.net/projects/markdown) are simple text files that contain any text, and an optional `meta` section.

Expand Down Expand Up @@ -171,7 +227,8 @@ Currently, a new line is placed before all headings (from `h2` to to `h6`), but

## Todo List
- [ ] Add if statements to render content based on a condition.
- [ ] Add directives to placeholders.
- [x] Add directives to placeholders.
- [ ] Add directives that support arguments.
- [ ] Add tag filter to prevent parsing scripts.
- [ ] Add better handling for errors in meta sections.
- For example if a key is passed without a value, then no meta values are parsed.
Expand Down
39 changes: 29 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ fn parse_placeholder_directive_enum(input: Span) -> IResult<Span, Option<Directi
"date" => arg.and_then(|arg| Some(Directive::Date(arg.to_string()))),
"lowercase" => Some(Directive::Lowercase),
"uppercase" => Some(Directive::Uppercase),
"markdown" => Some(Directive::Markdown),
_ => None,
};
Ok((input, directive))
Expand Down Expand Up @@ -411,7 +412,12 @@ fn parse_placeholder(input: Span) -> IResult<Span, Placeholder> {
many0(parse_placeholder_directive),
tuple((multispace0, tag("}}"))),
))(input)
.map(|(input, (start, variable, directives, end))| {
.map(|(input, (start, variable, mut directives, end))| {
// By default, £content will always be parsed as Markdown.
if variable.to_ascii_lowercase().as_str() == "content" && !directives.contains(&Some(Directive::Markdown)) {
directives.push(Some(Directive::Markdown));
}

(input, Placeholder {
name: variable.to_string(),
directives: directives.into_iter().filter_map(|d| d).collect(),
Expand Down Expand Up @@ -535,14 +541,6 @@ fn create_variables(markdown: Span, meta_values: Vec<Option<Meta>>) -> Result<Ha
}
if !variables.contains_key("content") {
let content = markdown.fragment().trim().to_string();
let content = markdown::to_html_with_options(&content, &markdown::Options {
compile: markdown::CompileOptions {
allow_dangerous_html: true,
allow_dangerous_protocol: false,
..Default::default()
},
..Default::default()
}).unwrap_or_default();
variables.insert("content".to_string(), content);
}

Expand All @@ -567,7 +565,7 @@ fn main() -> Result<(), anyhow::Error> {
// Get only existing markdowns.
let markdown_urls: Vec<PathBuf> = cli.markdowns
.into_iter()
.filter(|file| file.exists() && file.extension().unwrap_or_default() == "md" )
.filter(|file| file.exists() && file.extension().unwrap_or_default() == "md")
.collect();
let markdowns: Vec<String> = markdown_urls
.iter()
Expand Down Expand Up @@ -602,6 +600,27 @@ fn main() -> Result<(), anyhow::Error> {

for placeholder in &placeholders {
if let Some(variable) = variables.get(&placeholder.name) {
// Used to deref the variable.
let mut variable = variable.to_owned();

for directive in &placeholder.directives {
variable = match directive {
Directive::Lowercase => variable.to_lowercase(),
Directive::Uppercase => variable.to_uppercase(),
Directive::Markdown => {
markdown::to_html_with_options(&variable, &markdown::Options {
compile: markdown::CompileOptions {
allow_dangerous_html: true,
allow_dangerous_protocol: false,
..Default::default()
},
..Default::default()
}).unwrap_or_default()
}
_ => unimplemented!(),
}
}

html_doc = replace_substring(&html_doc, placeholder.selection.start.offset, placeholder.selection.end.offset, &variable);
} else {
let url = markdown_url.to_str().unwrap_or_default();
Expand Down

0 comments on commit 092580e

Please sign in to comment.