Skip to content

Commit

Permalink
Add colocated_path to shortcodes
Browse files Browse the repository at this point in the history
Closes #1793
  • Loading branch information
Keats committed Jan 25, 2023
1 parent d435f00 commit 2dbbed6
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This will error if 2 values are set
- Enable locale date formatting for the Tera `date` filter
- Cachebust fingerprint is now only 20 chars long
- Add `text` alias for plain text highlighting (before, only `txt` was used)
- Adds a new built-in variable to shortcodes: `colocated_path` that points to the folder of the current file being rendered if it's a colocated folder. None otherwise.


## 0.16.1 (2022-08-14)
Expand Down
13 changes: 13 additions & 0 deletions components/content/src/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub struct FileInfo {
pub name: String,
/// The .md path, starting from the content directory, with `/` slashes
pub relative: String,
/// The path from the content directory to the colocated directory. Ends with a `/` when set.
/// Only filled if it is a colocated directory, None otherwise.
pub colocated_path: Option<String>,
/// Path of the directory containing the .md file
pub parent: PathBuf,
/// Path of the grand parent directory for that file. Only used in sections to find subsections.
Expand All @@ -63,11 +66,17 @@ impl FileInfo {
} else {
format!("{}.md", name)
};
let mut colocated_path = None;

// If we have a folder with an asset, don't consider it as a component
// Splitting on `.` as we might have a language so it isn't *only* index but also index.fr
// etc
if !components.is_empty() && name.split('.').collect::<Vec<_>>()[0] == "index" {
colocated_path = Some({
let mut val = components.join("/");
val.push('/');
val
});
components.pop();
// also set parent_path to grandparent instead
parent = parent.parent().unwrap().to_path_buf();
Expand All @@ -83,6 +92,7 @@ impl FileInfo {
name,
components,
relative,
colocated_path,
}
}

Expand All @@ -108,6 +118,7 @@ impl FileInfo {
name,
components,
relative,
colocated_path: None,
}
}

Expand Down Expand Up @@ -171,6 +182,7 @@ mod tests {
&PathBuf::new(),
);
assert_eq!(file.components, ["posts".to_string(), "tutorials".to_string()]);
assert_eq!(file.colocated_path, Some("posts/tutorials/python/".to_string()));
}

#[test]
Expand Down Expand Up @@ -211,6 +223,7 @@ mod tests {
&PathBuf::new(),
);
assert_eq!(file.components, ["posts".to_string(), "tutorials".to_string()]);
assert_eq!(file.colocated_path, Some("posts/tutorials/python/".to_string()));
let res = file.find_language("en", &["fr"]);
assert!(res.is_ok());
assert_eq!(res.unwrap(), "fr");
Expand Down
1 change: 1 addition & 0 deletions components/content/src/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ impl Page {
context.set_shortcode_definitions(shortcode_definitions);
context.set_current_page_path(&self.file.relative);
context.tera_context.insert("page", &SerializingPage::new(self, None, false));
context.tera_context.insert("colocated_path", &self.file.colocated_path);

let res = render_content(&self.raw_content, &context)
.with_context(|| format!("Failed to render content of {}", self.file.path.display()))?;
Expand Down
1 change: 1 addition & 0 deletions components/content/src/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Section {
context
.tera_context
.insert("section", &SerializingSection::new(self, SectionSerMode::ForMarkdown));
context.tera_context.insert("colocated_path", &self.file.colocated_path);

let res = render_content(&self.raw_content, &context)
.with_context(|| format!("Failed to render content of {}", self.file.path.display()))?;
Expand Down
1 change: 0 additions & 1 deletion components/imageproc/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ impl ImageMetaResponse {

impl From<ImageMeta> for ImageMetaResponse {
fn from(im: ImageMeta) -> Self {
println!("{:?}", im);
Self {
width: im.size.0,
height: im.size.1,
Expand Down
10 changes: 9 additions & 1 deletion components/imageproc/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,14 @@ impl Processor {
// Only add it to the set of things to process if the file doesn't exist or the input file
// is stale
if !output_path.exists() || ufs::file_stale(&input_path, &output_path) {
self.img_ops.insert(ImageOp { input_path, output_path, instr, format });
println!(
"Processing {:?}, output_exists? {}, is stale? {}",
input_path,
output_path.exists(),
ufs::file_stale(&input_path, &output_path)
);
let img_op = ImageOp { input_path, output_path, instr, format };
self.img_ops.insert(img_op);
}

Ok(enqueue_response)
Expand Down Expand Up @@ -193,6 +200,7 @@ impl Processor {
.iter()
.map(|o| o.output_path.file_name().unwrap().to_string_lossy())
.collect();

for entry in fs::read_dir(&self.output_dir)? {
let entry_path = entry?.path();
if entry_path.is_file() {
Expand Down
25 changes: 16 additions & 9 deletions components/templates/src/global_fns/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ impl TeraFn for ResizeImage {
return Err("`resize_image`: `quality` must be in range 1-100".to_string().into());
}
}
let resize_op = imageproc::ResizeOperation::from_args(&op, width, height).map_err(|e| format!("`resize_image`: {}", e))?;
let resize_op = imageproc::ResizeOperation::from_args(&op, width, height)
.map_err(|e| format!("`resize_image`: {}", e))?;
let mut imageproc = self.imageproc.lock().unwrap();
let (file_path, unified_path) =
match search_for_file(&self.base_path, &path, &self.theme, &self.output_path)
Expand All @@ -72,7 +73,6 @@ impl TeraFn for ResizeImage {
}
};


let response = imageproc
.enqueue(resize_op, unified_path, file_path, &format, quality)
.map_err(|e| format!("`resize_image`: {}", e))?;
Expand Down Expand Up @@ -193,23 +193,27 @@ mod tests {

assert_eq!(
data["static_path"],
to_value(&format!("{}", static_path.join("gutenberg.da10f4be4f1c441e.jpg").display())).unwrap()
to_value(&format!("{}", static_path.join("gutenberg.da10f4be4f1c441e.jpg").display()))
.unwrap()
);
assert_eq!(
data["url"],
to_value("http://a-website.com/processed_images/gutenberg.da10f4be4f1c441e.jpg").unwrap()
to_value("http://a-website.com/processed_images/gutenberg.da10f4be4f1c441e.jpg")
.unwrap()
);

// 2. resizing an image in content with a relative path
args.insert("path".to_string(), to_value("content/gutenberg.jpg").unwrap());
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(
data["static_path"],
to_value(&format!("{}", static_path.join("gutenberg.3301b37eed389d2e.jpg").display())).unwrap()
to_value(&format!("{}", static_path.join("gutenberg.3301b37eed389d2e.jpg").display()))
.unwrap()
);
assert_eq!(
data["url"],
to_value("http://a-website.com/processed_images/gutenberg.3301b37eed389d2e.jpg").unwrap()
to_value("http://a-website.com/processed_images/gutenberg.3301b37eed389d2e.jpg")
.unwrap()
);

// 3. resizing with an absolute path is the same as the above
Expand All @@ -227,7 +231,8 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(
data["static_path"],
to_value(&format!("{}", static_path.join("asset.d2fde9a750b68471.jpg").display())).unwrap()
to_value(&format!("{}", static_path.join("asset.d2fde9a750b68471.jpg").display()))
.unwrap()
);
assert_eq!(
data["url"],
Expand All @@ -239,11 +244,13 @@ mod tests {
let data = static_fn.call(&args).unwrap().as_object().unwrap().clone();
assert_eq!(
data["static_path"],
to_value(&format!("{}", static_path.join("in-theme.9b0d29e07d588b60.jpg").display())).unwrap()
to_value(&format!("{}", static_path.join("in-theme.9b0d29e07d588b60.jpg").display()))
.unwrap()
);
assert_eq!(
data["url"],
to_value("http://a-website.com/processed_images/in-theme.9b0d29e07d588b60.jpg").unwrap()
to_value("http://a-website.com/processed_images/in-theme.9b0d29e07d588b60.jpg")
.unwrap()
);
}

Expand Down
1 change: 0 additions & 1 deletion components/utils/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ where
path.as_ref().file_name().and_then(|s| s.to_str()).map(|s| s.starts_with('.')).unwrap_or(false)
}


/// Returns whether the path we received corresponds to a temp file created
/// by an editor or the OS
pub fn is_temp_file(path: &Path) -> bool {
Expand Down
26 changes: 20 additions & 6 deletions docs/content/documentation/content/shortcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ Every shortcode can access some variables, beyond what you explicitly passed as

- invocation count (`nth`)
- current language (`lang`), unless called from the `markdown` template filter (in which case it will always be the same value as `default_language` in configuration, or `en` when it is unset)
- `colocated_path`

When one of these variables conflict with a variable passed as argument, the argument value will be used.

### Invocation Count
### `nth`: invocation count

Every shortcode context is passed in a variable named `nth` that tracks how many times a particular shortcode has
been invoked in the current Markdown file. Given a shortcode `true_statement.html` template:
Expand All @@ -184,17 +185,30 @@ It could be used in our Markdown as follows:

This is useful when implementing custom markup for features such as sidenotes or end notes.

### Current language
### `lang`: current language
**NOTE:** When calling a shortcode from within the `markdown` template filter, the `lang` variable will always be `en`.
If you feel like you need that, please consider using template macros instead.
If you really need that, you can rewrite your Markdown content to pass `lang` as argument to the shortcode.

**NOTE:** When calling a shortcode from within the `markdown` template filter, the `lang` variable will always be `en`. If you feel like you need that, please consider using template macros instead. If you really need that, you can rewrite your Markdown content to pass `lang` as argument to the shortcode.

Every shortcode can access the current language in the `lang` variable in the context. This is useful for presenting/filtering information in a shortcode depending in a per-language manner. For example, to display a per-language book cover for the current page in a shortcode called `bookcover.md`:
Every shortcode can access the current language in the `lang` variable in the context.
This is useful for presenting/filtering information in a shortcode depending in a per-language manner. For example, to display a per-language book cover for the current page in a shortcode called `bookcover.md`:

```jinja2
![Book cover in {{ lang }}](cover.{{ lang }}.png)
```

You can then use it in your Markdown like so: `{{/* bookcover() */}}`
### `colocated_path`
This is used when you want to pass the name of some assets to shortcodes without repeating the full folders path.
Mostly useful when combined with `load_data` or `resize_image`.

```jinja2
{% set resized = resize_image(format="jpg", path=colocated_path ~ img_name, width=width, op="fit_width") %}
<img alt="{{ alt }}" src="{{ resized.url | safe }}" />
```

### `page` or `section`
You can access a slighty stripped down version of the equivalent variables in the normal templates.
The only things missing are translations, backlinks and pages for sections as we are still in the middle of processing.

## Examples

Expand Down
5 changes: 2 additions & 3 deletions src/cmd/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ use mime_guess::from_path as mimetype_from_path;
use time::macros::format_description;
use time::{OffsetDateTime, UtcOffset};

use libs::percent_encoding;
use libs::serde_json;
use libs::globset::GlobSet;
use libs::percent_encoding;
use libs::relative_path::{RelativePath, RelativePathBuf};
use libs::serde_json;
use notify::{watcher, RecursiveMode, Watcher};
use ws::{Message, Sender, WebSocket};

Expand Down Expand Up @@ -652,7 +652,6 @@ fn is_ignored_file(ignored_content_globset: &Option<GlobSet>, path: &Path) -> bo
}
}


/// Detect what changed from the given path so we have an idea what needs
/// to be reloaded
fn detect_change_kind(pwd: &Path, path: &Path, config_path: &Path) -> (ChangeKind, PathBuf) {
Expand Down

0 comments on commit 2dbbed6

Please sign in to comment.