Files
hugo-framework/README.md

1470 lines
60 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Wiki Site Architecture (Hugo)"
description: "Architecture, local development, and deployment documentation for the central Hugo framework repository."
author: wompmacho
date: '2026-06-06T18:41:37Z'
lastmod: '2026-06-06'
tags: [hugo, framework, architecture, deployment, readme]
---
# Wiki Website
This project is a website built with **Hugo v0.162.1 Extended** and the **Blowfish theme**. I've decoupled the theme from Git submodules so it won't break in the future, and I'm currently baking in a ton of my own custom tweaks and features.
## 🚀 Local Development
To preview the wiki contents locally, you should use the `preview.sh` script to run the development server for either the public or private documentation.
### Launching the Preview
Run the script from the project root with the target environment (`public` or `private`) as the argument:
```bash
# Preview the public wiki
./preview.sh public
# Preview the private wiki
./preview.sh private
```
The script automatically handles mounting the content, configures the build, and starts the server. Once running, the site is accessible via code-server's absolute proxy:
👉 **[https://dev.wompmacho.com/absproxy/1313/](https://dev.wompmacho.com/absproxy/1313/)**
### How it Works (Under the Hood)
The `preview.sh` script automates the framework's connection to your external content repository files:
1. **Directory Symlinking**: It deletes the framework's default `content/` and `static/` directories and symlinks them directly to their counterparts in the content repository (`/srv/docs/public` or `/srv/docs/private`).
2. **Configuration Overrides**: If a custom menu configuration (`config/_default/menus.en.toml`) exists inside the content directory, it symlinks it to override the framework's default menu structure.
3. **Dev Server Launch**: It runs `./run-dev.sh` to start the Hugo development server (which removes the output `public/` directory first to prevent caching conflicts and renders to memory at `0.0.0.0:1313`).
4. **Graceful Cleanup Trap**: When the process is interrupted or terminated (e.g., via `Ctrl+C`), a shell `trap` catches the signal, removes the temporary preview symlinks, and performs a `git checkout` to restore the framework's original repository defaults cleanly.
> [!NOTE]
> Do not manually commit symlinks or edited framework configurations while running the preview server. Let the script cleanly exit and restore repository defaults.
---
## 🏗️ Decoupled Architecture
The Blowfish theme is fully **decoupled/vendored** into this project's root folders (`layouts/`, `assets/`, `static/`, `data/`, `i18n/`, `archetypes/`).
* No theme submodules are used, protecting the site from upstream updates breaking the build.
* Custom styling and layouts can be edited directly in the root directories.
### Global Background Injection
The framework injects a diffused global background image natively into `layouts/_default/baseof.html` using a conditional logic block directly in the body template.
- It pulls the image source from `defaultBackgroundImage` in `config/_default/params.toml`.
- It dynamically applies a `has-global-bg` CSS class to the `<body>` element. This class forces the standard Blowfish solid background colors to become transparent (handled in `assets/css/custom.css`), allowing the background div to show through.
- **Bypass Logic**: The template logic automatically bypasses rendering the global background if the page is explicitly configured to use the Blowfish `background` or `hero` layouts (e.g. `layout = "background"` on the homepage or `heroStyle = "background"` on an article). This ensures the framework's native full-page feature images are never broken or layered incorrectly.
- The global background mimics the exact structure of the native homepage `background` layout, utilizing a `h-[1000px]` fixed height container with `object-cover` and honoring the `imagePosition` parameter from `params.toml` for pixel-perfect consistency.
- Project cards (using `layout: card`) have their styling overridden in `assets/css/custom.css` to use a darker, semi-transparent "dark web" palette to contrast nicely with the diffused background.
---
## 🚀 CI/CD Pipeline & Deployment
Deployment is fully automated through Gitea Actions stored in the **Content repositories** (e.g., `.gitea/workflows/deploy.yaml`). **Manual builds to production should be avoided.**
### Build & Deploy Workflow
1. **Source Checkout**: The Gitea Runner checks out the triggering content repository.
2. **Framework Setup**: It clones this central Hugo framework repository dynamically.
3. **Integration Stage**: It injects the content files (`/srv/docs/public` or `/srv/docs/private`) and static assets into the framework environment.
4. **Hugo Compilation**: It builds the static HTML site using Hugo (`hugo --minify`).
5. **Volume Deployment**: The generated production bundle is copied directly into the persistent web server volumes served by Dockerized Nginx containers:
* **Public Wiki**: `/srv/www/docs-public`
* **Private Wiki**: `/srv/www/docs-private`
### File Inclusions (Absolute Paths)
To allow for the inclusion of raw files outside of the standard Hugo `content/` directory (such as system configurations located in `/srv/configs`), this framework utilizes **Hugo Module Mounts** mapping into the virtual `assets/` directory.
#### How it Works
Hugo's `readFile` and `fileExists` functions are blocked by strict OS security policies and cannot read paths outside the project root. To bypass this safely:
1. The external directory is mounted in `config/_default/hugo.toml`:
```toml
[[module.mounts]]
source = "/srv/configs"
target = "assets/srv/configs"
```
2. The custom `include` shortcode (`{{< include "/srv/configs/..." >}}`) detects paths starting with `/srv/`, trims the leading slash, and uses `resources.Get` to fetch the raw file from the virtual `assets/` namespace, completely bypassing the Markdown parser and security blocks.
**⚠️ Critical Note on CI/CD for External Files:**
If you map new external directories in `hugo.toml` (e.g., `/srv/newfolder`), the Docker container running the Gitea Action must also have OS-level access to those files. You must:
1. Allow the volume in the host's Gitea runner config (`/srv/gitea/runner/config.yaml` -> `valid_volumes`).
2. Mount the volume in the job options of the content repository's `.gitea/workflows/deploy.yaml` (e.g., `options: --user root -v /srv/www:/srv/www -v /srv:/srv:ro`).
---
## Shortcodes Quick Reference
Below is a quick-reference list of all the custom, Hugo default, and Blowfish shortcodes available in this framework, ordered by type:
| Shortcode | Type | Description |
| --- | --- | --- |
| [Include](#include) | Custom | Embeds raw configuration or code files from mounted absolute paths (e.g., `/srv/configs`). |
| [Raw HTML](#raw-html) | Custom | Injects unparsed raw HTML blocks directly into markdown files. |
| [Screenshot](#screenshot) | Custom | Renders retina-friendly images scaled down by 50% to maintain high sharpness. |
| [Figure](#figure) | Hugo Default / Blowfish | Renders performance-optimized, responsive pipeline images with zoom support. Can revert to Hugo default `figure` behaviour with `default=true` parameter. |
| [Gist](#gist) | Hugo Default / Blowfish | Embeds complete GitHub Gists or individual files from Gists. |
| [Highlight](https://gohugo.io/content-management/shortcodes/#highlight) | Hugo Default | Renders syntax-highlighted code blocks natively using Chroma. |
| [Instagram](https://gohugo.io/content-management/shortcodes/#instagram) | Hugo Default | Embeds an Instagram post by ID. |
| [Param](https://gohugo.io/content-management/shortcodes/#param) | Hugo Default | Renders a configuration parameter value from Page or Site front matter. |
| [Ref](https://gohugo.io/content-management/shortcodes/#ref-and-relref) | Hugo Default | Resolves an internal page reference to an absolute URL. |
| [Relref](https://gohugo.io/content-management/shortcodes/#ref-and-relref) | Hugo Default | Resolves an internal page reference to a relative URL. |
| [Twitter](https://gohugo.io/content-management/shortcodes/#twitter) | Hugo Default | Embeds a Twitter tweet by ID. |
| [Vimeo](https://gohugo.io/content-management/shortcodes/#vimeo) | Hugo Default | Embeds a Vimeo video player by ID. |
| [Youtube](https://gohugo.io/content-management/shortcodes/#youtube) | Hugo Default | Embeds a standard YouTube video player by ID. |
| [Accordion](#accordion) | Blowfish | Renders collapsible panels to group structured, expand-on-demand content. |
| [Admonition](#admonition) | Blowfish | Markdown-based callout boxes supporting folding (similar to GitHub alerts). |
| [Alert](#alert) | Blowfish | Outputs stylized text panels for warnings, tips, or callouts. |
| [Ansible Galaxy Card](#ansible-galaxy-card) | Blowfish | Fetches and renders stats for an Ansible Galaxy role or collection at build time. |
| [Article](#article) | Blowfish | Embeds a summary/card of another article page using its relative permalink. |
| [Badge](#badge) | Blowfish | Displays small, highlighted labels for metadata or tags. |
| [Button](#button) | Blowfish | Renders primary call-to-action buttons linking to internal ref pages or external URLs. |
| [Carousel](#carousel) | Blowfish | Showcases a list of sliding images inside an interactive 16:9 or 21:9 container. |
| [Chart](#chart) | Blowfish | Embeds structured charts and graphs using Chart.js configurations. |
| [Code Importer](#code-importer) | Blowfish | Imports syntax-highlighted code from external URLs with lines cropping. |
| [Codeberg Card](#codeberg-card) | Blowfish | Embeds a repository card with real-time stats from Codeberg. |
| [Email](#email) | Blowfish | Renders spam-obfuscated email links. |
| [Forgejo Card](#forgejo-card) | Blowfish | Embeds a repository card with real-time stats from Forgejo. |
| [Gallery](#gallery) | Blowfish | Renders a responsive grid of images with custom layouts and captions. |
| [Gitea Card](#gitea-card) | Blowfish | Embeds a repository card with real-time stats from Gitea. |
| [GitHub Card](#github-card) | Blowfish | Embeds a repository card with real-time stats from GitHub. |
| [GitLab Card](#gitlab-card) | Blowfish | Embeds a repository card with real-time stats from GitLab. |
| [Hugging Face Card](#hugging-face-card) | Blowfish | Renders model or dataset card stats from Hugging Face. |
| [Icon](#icon) | Blowfish | Injects clean inline SVG icons scaled to match text size. |
| [KaTeX](#katex) | Blowfish | Formats mathematical expressions using LaTeX syntax. |
| [Keyword](#keyword) | Blowfish | Visually highlights skills or important tags (grouped in lists). |
| [Lead](#lead) | Blowfish | Renders larger paragraph text to draw attention to intro sections. |
| [List](#list) | Blowfish | Renders automated lists of recent posts based on queries. |
| [LTR/RTL](#ltrrtl) | Blowfish | Enforces LTR or RTL text direction mixing for multilingual content. |
| [Markdown Importer](#markdown-importer) | Blowfish | Fetches and renders external markdown documents dynamically at build time. |
| [Mermaid](#mermaid) | Blowfish | Renders charts, diagrams, and flowcharts directly from text definitions. |
| [Swatches](#swatches) | Blowfish | Renders visual color grids with up to three HEX palette codes. |
| [Tabs](#tabs) | Blowfish | Embeds interactive tabbed layouts to showcase multi-platform installation/usage steps. |
| [Timeline](#timeline) | Blowfish | Renders visual timelines for project milestones or career history. |
| [TypeIt](#typeit) | Blowfish | Renders simulated typewriter text animation. |
| [Video](#video) | Blowfish | Embeds local or external videos using HTML5 responsive players. |
| [Youtube Lite](#youtube-lite) | Blowfish | Embeds lightweight, fast-loading YouTube videos. |
---
## Shortcodes Reference
In addition to all the [default Hugo shortcodes](https://gohugo.io/content-management/shortcodes/), Blowfish adds a few extras for additional functionality.
### Include
The `include` shortcode allows you to import and embed raw text or configuration files directly into your pages, bypassing standard Hugo filesystem limits by using asset mounts.
| Parameter | Description |
| --- | --- |
| `src` (or `[0]`) | **Required.** The path to the file to include. Paths starting with `/srv/` map to mounted directories. |
**Example:**
```md
{{</* include "/srv/configs/nginx.conf" */>}}
```
### Screenshot
The `screenshot` shortcode renders retina-friendly screenshots that are scaled down to 50% of their actual image dimensions, ensuring high-density displays render them crisp and clear without taking up too much page width.
| Parameter | Description |
| --- | --- |
| `src` | **Required.** The matching pattern for the image in the page resource bundle. |
| `class` | **Optional.** Custom CSS classes to apply to the `<figure>` element. |
| `href` | **Optional.** A link URL to wrap the image with. |
| `alt` | **Optional.** Alt text for screen readers. |
| `caption` | **Optional.** A markdown-supported caption displayed below the screenshot. |
**Example:**
```md
{{</* screenshot src="settings.png" caption="Application Settings" */>}}
```
### Raw HTML
The `rawhtml` shortcode is used to inject raw, unparsed HTML code directly into your markdown pages.
**Example:**
```md
{{</* rawhtml */>}}
<div class="custom-widget">Raw HTML Content</div>
{{</* /rawhtml */>}}
```
### Alert
`alert` outputs its contents as a stylised message box within your article. It's useful for drawing attention to important information that you don't want the reader to miss.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `icon` | **Optional.** the icon to display on the left side.<br>**Default:** `triangle-exclamation` (Check out the [icon shortcode](#icon) for more details on using icons.) |
| `iconColor` | **Optional.** the color for the icon in basic CSS style.<br>Can be either hex values (`#FFFFFF`) or color names (`white`)<br>By default chosen based on the current color theme . |
| `cardColor` | **Optional.** the color for the card background in basic CSS style.<br>Can be either hex values (`#FFFFFF`) or color names (`white`)<br>By default chosen based on the current color theme . |
| `textColor` | **Optional.** the color for the text in basic CSS style.<br>Can be either hex values (`#FFFFFF`) or color names (`white`)<br>By default chosen based on the current color theme . |
<!-- prettier-ignore-end -->
The input is written in Markdown so you can format it however you please.
**Example 1:** No params
```md
{{</* alert */>}}
**Warning!** This action is destructive!
{{</* /alert */>}}
```
{{< alert >}}
**Warning!** This action is destructive!
{{< /alert >}}
**Example 2:** Unnamed param
```md
{{</* alert "twitter" */>}}
Don't forget to [follow me](https://twitter.com/nunocoracao) on Twitter.
{{</* /alert */>}}
```
{{< alert "twitter" >}}
Don't forget to [follow me](https://twitter.com/nunocoracao) on Twitter.
{{< /alert >}}
**Example 3:** Named params
```md
{{</* alert icon="fire" cardColor="#e63946" iconColor="#1d3557" textColor="#f1faee" */>}}
This is an error!
{{</* /alert */>}}
```
{{< alert icon="fire" cardColor="#e63946" iconColor="#1d3557" textColor="#f1faee" >}}
This is an error!
{{< /alert >}}
### Admonition
Admonitions allow you to insert eye-catching callout boxes in your content.
Admonitions serve a similar purpose as the alert shortcode but are implemented via Hugo render hooks. The key difference is syntax: admonitions use Markdown syntax, making them more portable across different platforms, whereas shortcodes are specific to Hugo. The syntax resembles GitHub alerts:
```md
> [!TIP]
> A Tip type admonition.
> [!TIP]+ Custom Title + Custom Icon
> A collapsible admonition with custom title.
{icon="twitter"}
```
> [!TIP]
> A Tip type admonition.
> [!TIP]+ Custom Title + Custom Icon
> A collapsible admonition with custom title.
{icon="twitter"}
The alert sign (`+` or `-`) is optional to control whether the admonition is folded or not. Note that alert sign is only compatible in Obsidian.
> [!INFO]- Supported types
> Valid admonition types include [GitHub alert types](https://github.blog/changelog/2023-12-14-new-markdown-extension-alerts-provide-distinctive-styling-for-significant-content/) and [Obsidian callout types](https://help.obsidian.md/callouts). The types are case-insensitive.
>
> **GitHub types:** `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`
> **Obsidian types:** `note`, `abstract`, `info`, `todo`, `tip`, `success`, `question`, `warning`, `failure`, `danger`, `bug`, `example`, `quote`
> [!INFO]- Customize admonition
> See the [admonition customization guide](https://github.com/nunocoracao/blowfish/blob/main/layouts/_default/_markup/render-blockquote.html).
### Accordion
`accordion` creates a collapsible set of panels. Use the `accordionItem` sub-shortcode to define each item. You can control whether multiple items can be open at the same time using the `mode` parameter.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ------------------------------------------------------------------------------------------------- |
| `mode` | **Optional.** `collapse` (single open) or `open` (multiple open). Defaults to `collapse`. |
| `separated` | **Optional.** `true` to show each item as a separate card. Defaults to `false` (joined list). |
<!-- prettier-ignore-end -->
`accordionItem` parameters:
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | --------------------------------------------------------------------------------------------------- |
| `title` | **Required.** Title shown in the item header. |
| `open` | **Optional.** Set to `true` to have the item open by default. |
| `header` | **Optional.** Alias for `title`, kept for compatibility with other shortcodes. |
| `icon` | **Optional.** Icon name to display before the title. |
| `align` | **Optional.** Align text within the item: `left`, `center`, `right` |
<!-- prettier-ignore-end -->
**Example 1: `mode="open"` (multiple items can be open) + `separated=true`**
```md
{{</* accordion mode="open" separated=true */>}}
{{</* accordionItem title="Markdown example" icon="code" open=true */>}}
This item demonstrates Markdown rendering:
- **Bold text**
- Lists
- `inline code`
{{</* /accordionItem */>}}
{{</* accordionItem title="Shortcode example" md=false */>}}
This item demonstrates shortcode rendering with <code>md=false</code>:
{{</* alert */>}}This is an inline alert.{{</* /alert */>}}
{{</* /accordionItem */>}}
{{</* /accordion */>}}
```
{{< accordion mode="open" separated=true >}}
{{< accordionItem title="Markdown example" icon="code" open=true >}}
This item demonstrates Markdown rendering:
- **Bold text**
- Lists
- `inline code`
{{< /accordionItem >}}
{{< accordionItem title="Shortcode example" md=false >}}
This item demonstrates shortcode rendering with <code>md=false</code>:
{{< alert >}}This is an inline alert.{{< /alert >}}
{{< /accordionItem >}}
{{< /accordion >}}
**Example 2: `mode="collapse"` (only one item open at a time)**
```md
{{</* accordion mode="collapse" */>}}
{{</* accordionItem title="First item" open=true */>}}
This item uses Markdown with a short list:
1. One
2. Two
3. Three
{{</* /accordionItem */>}}
{{</* accordionItem title="Second item" md=false */>}}
This item includes another shortcode:
{{</* badge */>}}Tip{{</* /badge */>}}
{{</* /accordionItem */>}}
{{</* /accordion */>}}
```
{{< accordion mode="collapse" >}}
{{< accordionItem title="First item" open=true >}}
This item uses Markdown with a short list:
1. One
2. Two
3. Three
{{< /accordionItem >}}
{{< accordionItem title="Second item" md=false >}}
This item includes another shortcode:
{{< badge >}}Tip{{< /badge >}}
{{< /accordionItem >}}
{{< /accordion >}}
### Ansible Galaxy Card
`ansible` renders a card for an [Ansible Galaxy](https://galaxy.ansible.com/) entry, fetched at build time. It accepts either a `role` or a `collection` parameter, both in `namespace.name` form.
<!-- prettier-ignore-start -->
| Parameter | Description |
| ------------ | ------------------------------------------------------------------------------------ |
| `role` | [String] Galaxy role in the format `namespace.name`, e.g. `geerlingguy.docker` |
| `collection` | [String] Galaxy collection in the format `namespace.name`, e.g. `community.general` |
<!-- prettier-ignore-end -->
Set exactly one of `role` or `collection` per call.
All card values are fetched at build time via Hugo's `resources.GetRemote`. Galaxy does not allow cross-origin requests, so the card is not refreshed in the browser — rebuild the site to update the values.
**Example 1: Role**
```md
{{</* ansible role="geerlingguy.docker" */>}}
```
{{< ansible role="geerlingguy.docker" >}}
**Example 2: Collection**
```md
{{</* ansible collection="community.general" */>}}
```
{{< ansible collection="community.general" >}}
### Article
`Article` will embed a single article into a markdown file. The `link` to the file should be the `.RelPermalink` of the file to be embedded. Note that the shortcode will not display anything if it's referencing it's parent. _Note: if you are running your website in a subfolder like Blowfish (i.e. /blowfish/) please include that path in the link._
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | -------------------------------------------------------- |
| `link` | **Required.** the `.RelPermalink` to the target article. |
| `showSummary` | **Optional.** A boolean value indicating whether to show the article summary. If not set, the site's default configuration will be used. |
| `compactSummary` | **Optional.** A boolean value indicating whether to display the summary in compact mode. Default to false. |
<!-- prettier-ignore-end -->
**Example:**
```md
{{</* article link="/docs/welcome/" showSummary=true compactSummary=true */>}}
```
{{< article link="/docs/welcome/" showSummary=true compactSummary=true >}}
### Badge
`badge` outputs a styled badge component which is useful for displaying metadata.
**Example:**
```md
{{</* badge */>}}
New article!
{{</* /badge */>}}
```
{{< badge >}}
New article!
{{< /badge >}}
### Button
`button` outputs a styled button component which can be used to highlight a primary action. It has four optional variables `pageRef`, `href`, `target` and `rel`. `pageRef` resolves an internal page reference using the current page context, producing a language- and trailing-slash-aware URL that is consistent with the theme's navigation menus. `href` accepts any URL or path. When both are set, `pageRef` takes precedence.
**Example:**
```md
{{</* button href="#button" target="_self" */>}}
Call to action
{{</* /button */>}}
```
{{< button href="#button" target="_self" >}}
Call to action
{{< /button >}}
**Example using `pageRef`:**
```md
{{</* button pageRef="docs/getting-started" */>}}
Get started
{{</* /button */>}}
```
{{< button pageRef="docs/getting-started" >}}
Get started
{{< /button >}}
### Carousel
`carousel` is used to showcase multiple images in an interactive and visually appealing way. This allows a user to slide through multiple images while only taking up the vertical space of a single one. All images are displayed using the full width of the parent component and the aspect ratio you set with a default of `16:9`.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `images` | **Required.** A regex string to match image names or URLs. |
| `captions` | **Optional.** A list of `key:caption` pairs. Keys can be image filenames (for local images) or full URLs (for remote images). Captions support Markdown. |
| `aspectRatio` | **Optional.** The aspect ratio for the carousel. It is set to `16-9` by default. |
| `interval` | **Optional.** The interval for the auto-scrooling, specified in milliseconds. Defaults to `2000` (2s) |
<!-- prettier-ignore-end -->
Captions are matched by key. For local images, use the filename (e.g. `01.jpg`). For remote images, use the full URL.
**Example 1:** 16:9 aspect ratio and verbose list of images
```md
{{</* carousel images="{https://cdn.pixabay.com/photo/2016/12/11/12/02/mountains-1899264_960_720.jpg,gallery/03.jpg,gallery/01.jpg,gallery/02.jpg,gallery/04.jpg}" */>}}
```
{{< carousel images="{https://cdn.pixabay.com/photo/2016/12/11/12/02/mountains-1899264_960_720.jpg,gallery/03.jpg,gallery/01.jpg,gallery/02.jpg,gallery/04.jpg}" >}}
**Example 2:** 21:9 aspect ratio and regex-ed list of images
```md
{{</* carousel images="gallery/*" aspectRatio="21-9" interval="2500" */>}}
```
{{< carousel images="gallery/*" aspectRatio="21-9" interval="2500" >}}
**Example 3:** Add captions
```md
{{</* carousel images="gallery/*" captions="{01.jpg:First image with *formatting*,02.jpg:Second image with a [link](https://example.com)}" */>}}
```
{{< carousel images="gallery/*" captions="{01.jpg:First image with *formatting*,02.jpg:Second image with a [link](https://example.com)}" >}}
### Chart
`chart` uses the Chart.js library to embed charts into articles using simple structured data. It supports a number of [different chart styles](https://www.chartjs.org/docs/latest/samples/) and everything can be configured from within the shortcode. Simply provide the chart parameters between the shortcode tags and Chart.js will do the rest.
Refer to the [official Chart.js docs](https://www.chartjs.org/docs/latest/general/) for details on syntax and supported chart types.
**Example:**
```js
{{</* chart */>}}
type: 'bar',
data: {
labels: ['Tomato', 'Blueberry', 'Banana', 'Lime', 'Orange'],
datasets: [{
label: '# of votes',
data: [12, 19, 3, 5, 3],
}]
}
{{</* /chart */>}}
```
<!-- prettier-ignore-start -->
{{< chart >}}
type: 'bar',
data: {
labels: ['Tomato', 'Blueberry', 'Banana', 'Lime', 'Orange'],
datasets: [{
label: '# of votes',
data: [12, 19, 3, 5, 3],
}]
}
{{< /chart >}}
<!-- prettier-ignore-end -->
You can see some additional Chart.js examples on the [charts samples]({{< ref "charts" >}}) page.
### Code Importer
This shortcode is for importing code from external sources easily without copying and pasting.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ------------------------------------------------------- |
| `url` | **Required** URL to an externally hosted code file. |
| `type` | Code type used for syntax highlighting. |
| `startLine` | **Optional** The line number to start the import from. |
| `endLine` | **Optional** The line number to end the import at. |
<!-- prettier-ignore-end -->
**Example:**
```md
{{</* codeimporter url="https://raw.githubusercontent.com/nunocoracao/blowfish/main/layouts/shortcodes/mdimporter.html" type="go" */>}}
```
{{< codeimporter url="https://raw.githubusercontent.com/nunocoracao/blowfish/main/layouts/shortcodes/mdimporter.html" type="go" >}}
```md
{{</* codeimporter url="https://raw.githubusercontent.com/nunocoracao/blowfish/main/config/_default/hugo.toml" type="toml" startLine="11" endLine="18" */>}}
```
{{< codeimporter url="https://raw.githubusercontent.com/nunocoracao/blowfish/main/config/_default/hugo.toml" type="toml" startLine="11" endLine="18">}}
### Codeberg Card
`codeberg` allows you to quickly link a Codeberg repository via the Codeberg API, providing real-time updates on stats such as stars and forks.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ----------------------------------------------------- |
| `repo` | [String] codeberg repo in the format of `username/repo` |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* codeberg repo="forgejo/forgejo" */>}}
```
{{< codeberg repo="forgejo/forgejo" >}}
### Email
Creates an obfuscated mailto link:
```md
{{</* email email="mailto:hello@test.com" text="text" subject="Reply to awesome article" */>}}
```
{{< email email="mailto:hello@test.com" text="text" subject="Reply to awesome article" >}}
### Figure
Blowfish includes a `figure` shortcode for adding images to content. The shortcode replaces the base Hugo functionality in order to provide additional performance benefits.
When a provided image is a page resource, it will be optimised using Hugo Pipes and scaled in order to provide images appropriate to different device resolutions. If a static asset or URL to an external image is provided, it will be included as-is without any image processing by Hugo.
The `figure` shortcode accepts six parameters:
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `src` | **Required.** The local path/filename or URL of the image. When providing a path and filename, the theme will attempt to locate the image using the following lookup order: Firstly, as a [page resource](https://gohugo.io/content-management/page-resources/) bundled with the page; then an asset in the `assets/` directory; then finally, a static image in the `static/` directory. |
| `alt` | [Alternative text description](https://moz.com/learn/seo/alt-text) for the image. |
| `caption` | Markdown for the image caption, which will be displayed below the image. |
| `class` | Additional CSS classes to apply to the image. |
| `figureClass` | Additional CSS classes to apply to the `<figure>` wrapper. Useful for galleries. |
| `href` | URL that the image should be linked to. |
| `target` | The target attribute for the `href` URL. |
| `nozoom` | `nozoom=true` disables the image "zoom" functionality. This is most useful in combination with a `href` link. |
| `default` | Special parameter to revert to default Hugo `figure` behaviour. Simply provide `default=true` and then use normal [Hugo shortcode syntax](https://gohugo.io/content-management/shortcodes/#figure). |
<!-- prettier-ignore-end -->
Blowfish also supports automatic conversion of images included using standard Markdown syntax. Simply use the following format and the theme will handle the rest:
```md
![Alt text](image.jpg "Image caption")
```
**Example:**
```md
{{</* figure
src="abstract.jpg"
alt="Abstract purple artwork"
caption="Photo by [Jr Korpa](https://unsplash.com/@jrkorpa) on [Unsplash](https://unsplash.com/)"
*/>}}
<!-- OR -->
![Abstract purple artwork](abstract.jpg "Photo by [Jr Korpa](https://unsplash.com/@jrkorpa) on [Unsplash](https://unsplash.com/)")
```
{{< figure src="abstract.jpg" alt="Abstract purple artwork" caption="Photo by [Jr Korpa](https://unsplash.com/@jrkorpa) on [Unsplash](https://unsplash.com/)" >}}
### Forgejo Card
`forgejo` allows you to quickly link a Forgejo repository via the forgejo API, providing real-time updates on stats such as stars and forks.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ----------------------------------------------------- |
| `repo` | [String] forgejo repo in the format of `username/repo`|
| `server` | [String] server URL like `https://v11.next.forgejo.org`|
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* forgejo server="https://v11.next.forgejo.org" repo="a/mastodon" */>}}
```
{{< forgejo server="https://v11.next.forgejo.org" repo="a/mastodon" >}}
### Gallery
`gallery` allows you to showcase multiple images at once, in a responsive manner with more varied and interesting layouts.
In order to add images to the gallery, use `img` tags for each image and add `class="grid-wXX"` in order for the gallery to be able to identify the column width for each image. The widths available by default start at 10% and go all the way to 100% in 5% increments. For example, to set the width to 65%, set the class to `grid-w65`. Additionally, widths for 33% and 66% are also available in order to build galleries with 3 cols. You can also leverage tailwind's responsive indicators to have a reponsive grid.
If you need captions, you can use the `figure` shortcode inside the gallery. When doing so, set the grid width on the `figure` using `figureClass`, and use `caption` for the text.
**Example 1: normal gallery**
```md
{{</* gallery */>}}
<img src="gallery/01.jpg" class="grid-w33" />
<img src="gallery/02.jpg" class="grid-w33" />
<img src="gallery/03.jpg" class="grid-w33" />
<img src="gallery/04.jpg" class="grid-w33" />
<img src="gallery/05.jpg" class="grid-w33" />
<img src="gallery/06.jpg" class="grid-w33" />
<img src="gallery/07.jpg" class="grid-w33" />
{{</* /gallery */>}}
```
{{< gallery >}}
<img src="gallery/01.jpg" class="grid-w33" />
<img src="gallery/02.jpg" class="grid-w33" />
<img src="gallery/03.jpg" class="grid-w33" />
<img src="gallery/04.jpg" class="grid-w33" />
<img src="gallery/05.jpg" class="grid-w33" />
<img src="gallery/06.jpg" class="grid-w33" />
<img src="gallery/07.jpg" class="grid-w33" />
{{< /gallery >}}
**Example 2: responsive gallery**
```md
{{</* gallery */>}}
<img src="gallery/01.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/02.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/03.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/04.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/05.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/06.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/07.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
{{</* /gallery */>}}
```
{{< gallery >}}
<img src="gallery/01.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/02.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/03.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/04.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/05.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/06.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
<img src="gallery/07.jpg" class="grid-w50 md:grid-w33 xl:grid-w25" />
{{< /gallery >}}
**Example 3: gallery with captions (using `figure`)**
```md
{{</* gallery */>}}
{{</* figure src="gallery/01.jpg" alt="Gallery image 1" caption="First caption" figureClass="grid-w33" */>}}
{{</* figure src="gallery/02.jpg" alt="Gallery image 2" caption="Second caption" figureClass="grid-w33" */>}}
{{</* figure src="gallery/03.jpg" alt="Gallery image 3" caption="Third caption" figureClass="grid-w33" */>}}
{{</* /gallery */>}}
```
{{< gallery >}}
{{< figure src="gallery/01.jpg" alt="Gallery image 1" caption="First caption" figureClass="grid-w33" >}}
{{< figure src="gallery/02.jpg" alt="Gallery image 2" caption="Second caption" figureClass="grid-w33" >}}
{{< figure src="gallery/03.jpg" alt="Gallery image 3" caption="Third caption" figureClass="grid-w33" >}}
{{< /gallery >}}
### Gist
`gist` shortcode allows you to embed a GitHub Gist directly into your content by specifying the Gist user, ID, and optionally a specific file.
| Parameter | Description |
| -------------- | ------------------------------------------------------------------ |
| `[0]` | [String] GitHub username |
| `[1]` | [String] Gist ID |
| `[2]` (optional)| [String] Filename within the Gist to embed (optional) |
**Example 1: Embed entire Gist**
```md
{{</* gist "octocat" "6cad326836d38bd3a7ae" */>}}
````
{{< gist "octocat" "6cad326836d38bd3a7ae" >}}
**Example 2: Embed specific file from Gist**
```md
{{</* gist "rauchg" "2052694" "README.md" */>}}
```
{{< gist "rauchg" "2052694" "README.md" >}}
### Gitea Card
`gitea` allows you to quickly link a Gitea repository via the gitea API, providing real-time updates on stats such as stars and forks.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ----------------------------------------------------- |
| `repo` | [String] gitea repo in the format of `username/repo` |
| `server` | [String] server URL like `https://git.fsfe.org` |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* gitea server="https://git.fsfe.org" repo="FSFE/fsfe-website" */>}}
```
{{< gitea server="https://git.fsfe.org" repo="FSFE/fsfe-website" >}}
### GitHub Card
`github` allows you to quickly link a github repository, all while showing and updating in realtime stats about it, such as the number of stars and forks it has.
<!-- prettier-ignore-start -->
| Parameter | Description |
|-----------------|---------------------------------------------------------------|
| `repo` | [String] github repo in the format of `username/repo` |
| `showThumbnail` | **Optional** [boolean] display a thumbnail for the repository |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* github repo="nunocoracao/blowfish" showThumbnail=true */>}}
```
{{< github repo="nunocoracao/blowfish" showThumbnail=true >}}
### GitLab Card
`gitlab` allows you to quickly link a GitLab Project (GitLab's jargon for repo).
It displays realtime stats about it, such as the number of stars and forks it has.
Unlike `github` it can't display the main programming language of a project.
Finally, custom GitLab instance URL can be provided, as long as the `api/v4/projects/` endpoint is available, making this shortcode compatible with most self-hosted / enterprise deployments.
<!-- prettier-ignore-start -->
| Parameter | Description |
| ----------- | ----------------------------------------------------------------------- |
| `projectID` | [String] gitlab numeric ProjectID |
| `baseURL` | [String] optional gitlab instance URL, default is `https://gitlab.com/` |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* gitlab projectID="278964" */>}}
```
{{< gitlab projectID="278964" >}}
### Hugging Face Card
`huggingface` allows you to quickly link a Hugging Face model or dataset, displaying real-time information such as the number of likes and downloads, along with type and description.
| Parameter | Description |
|------------|----------------------------------------------------------------|
| `model` | [String] Hugging Face model in the format of `username/model` |
| `dataset` | [String] Hugging Face dataset in the format of `username/dataset` |
**Note:** Use either `model` or `dataset` parameter, not both.
**Example 1 (Model):**
```md
{{</* huggingface model="google-bert/bert-base-uncased" */>}}
```
{{< huggingface model="google-bert/bert-base-uncased" >}}
**Example 2 (Dataset):**
```md
{{</* huggingface dataset="stanfordnlp/imdb" */>}}
```
{{< huggingface dataset="stanfordnlp/imdb" >}}
### Icon
`icon` outputs an SVG icon and takes the icon name as its only parameter. The icon is scaled to match the current text size.
**Example:**
```md
{{</* icon "github" */>}}
```
**Output:** {{< icon "github" >}}
Icons are populated using Hugo pipelines which makes them very flexible. Blowfish includes a number of built-in icons for social, links and other purposes. Check the [icon samples]({{< ref "samples/icons" >}}) page for a full list of supported icons.
Custom icons can be added by providing your own icon assets in the `assets/icons/` directory of your project. The icon can then be referenced in the shortcode by using the SVG filename without the `.svg` extension.
Icons can also be used in partials by calling the [icon partial]({{< ref "partials#icon" >}}).
### KaTeX
The `katex` shortcode can be used to add mathematical expressions to article content using the KaTeX package. Refer to the online reference of [supported TeX functions](https://katex.org/docs/supported.html) for the available syntax.
To include mathematical expressions in an article, simply place the shortcode anywhere with the content. It only needs to be included once per article and KaTeX will automatically render any markup on that page. Both inline and block notation are supported.
Inline notation can be generated by wrapping the expression in `\(` and `\)` delimiters. Alternatively, block notation can be generated using `$$` delimiters.
**Example:**
```md
{{</* katex */>}}
\(f(a,b,c) = (a^2+b^2+c^2)^3\)
```
{{< katex >}}
\(f(a,b,c) = (a^2+b^2+c^2)^3\)
Check out the [mathematical notation samples]({{< ref "mathematical-notation" >}}) page for more examples.
### Keyword
The `keyword` component can be used to visually highlight certain important words or phrases, e.g. professional skills etc. The `keywordList` shortcode can be used to group together multiple `keyword` items. Each item can have the following properties.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | --------------------------------------- |
| `icon` | Optional icon to be used in the keyword |
<!-- prettier-ignore-end -->
The input is written in Markdown so you can format it however you please.
**Example1 :**
```md
{{</* keyword */>}} *Super* skill {{</* /keyword */>}}
```
{{< keyword >}} _Super_ skill {{< /keyword >}}
**Example2 :**
```md
{{</* keywordList */>}}
{{</* keyword icon="github" */>}} Lorem ipsum dolor. {{</* /keyword */>}}
{{</* keyword icon="code" */>}} **Important** skill {{</* /keyword */>}}
{{</* /keywordList */>}}
{{</* keyword */>}} *Standalone* skill {{</* /keyword */>}}
```
{{< keywordList >}}
{{< keyword icon="github" >}} Lorem ipsum dolor {{< /keyword >}}
{{< keyword icon="code" >}} **Important** skill {{< /keyword >}}
{{< /keywordList >}}
{{< keyword >}} _Standalone_ skill {{< /keyword >}}
### Lead
`lead` is used to bring emphasis to the start of an article. It can be used to style an introduction, or to call out an important piece of information. Simply wrap any Markdown content in the `lead` shortcode.
**Example:**
```md
{{</* lead */>}}
When life gives you lemons, make lemonade.
{{</* /lead */>}}
```
{{< lead >}}
When life gives you lemons, make lemonade.
{{< /lead >}}
### List
`List` will display a list of recent articles. This shortcode requires a limit value to constraint the list. Additionally, it supports a `where` and a `value` in order to filter articles by their parameters. Note that this shortcode will not display its parent page but it will count for the limit value.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `limit` | **Required.** the number of recent articles to display. |
| `title` | Optional title for the list, default is `Recent` |
| `cardView` | Optional card view enabled for the list, default is `false` |
| `where` | The variable to be used for the query of articles e.g. `Type` |
| `value` | The value that will need to match the parameter defined in `where` for the query of articles e.g. for `where` == `Type` a valid value could be `sample` |
{{< alert >}}
The `where` and `value` values are used in the following query `where .Site.RegularPages $where $value` in the code of the shortcode. Check [Hugo docs](https://gohugo.io/methods/page/) to learn more about which parameters are available to use.
{{</ alert >}}
<!-- prettier-ignore-end -->
**Example #1:**
```md
{{</* list limit=2 */>}}
```
{{< list limit=2 >}}
**Example #2:**
```md
{{</* list title="Samples" cardView=true limit=6 where="Type" value="sample" */>}}
```
{{< list title="Samples" cardView=true limit=6 where="Type" value="sample">}}
### LTR/RTL
`ltr` and `rtl` allows you to mix your contents. Many RTL language users want to include parts of the content in LTR. Using this shortcode will let you do so, and by leveraging `%` as the outer-most dilemeter in the shortcode [Hugo shortcodes](https://gohugo.io/content-management/shortcodes/#shortcodes-with-markdown), any markdown inside will be rendered normally.
**Example:**
```md
- This is an markdown list.
- Its per default a LTR direction
{{%/* rtl */%}}
- هذه القائمة باللغة العربية
- من اليمين الى اليسار
{{%/* /rtl */%}}
```
- This is an markdown list.
- Its per default a LTR direction
{{% rtl %}}
- هذه القائمة باللغة العربية
- من اليمين الى اليسار
{{% /rtl %}}
### Markdown Importer
This shortcode allows you to import markdown files from external sources. This is useful for including content from other repositories or websites without having to copy and paste the content.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | ------------------------------------------------------- |
| `url` | **Required** URL to an externally hosted markdown file. |
<!-- prettier-ignore-end -->
**Example:**
```md
{{</* mdimporter url="https://raw.githubusercontent.com/nunocoracao/nunocoracao/master/README.md" */>}}
```
{{< mdimporter url="https://raw.githubusercontent.com/nunocoracao/nunocoracao/master/README.md" >}}
### Mermaid
`mermaid` allows you to draw detailed diagrams and visualisations using text. It uses Mermaid under the hood and supports a wide variety of diagrams, charts and other output formats.
Simply write your Mermaid syntax within the `mermaid` shortcode and let the plugin do the rest.
Refer to the [official Mermaid docs](https://mermaid-js.github.io/) for details on syntax and supported diagram types.
**Example:**
```md
{{</* mermaid */>}}
graph LR;
A[Lemons]-->B[Lemonade];
B-->C[Profit]
{{</* /mermaid */>}}
```
{{< mermaid >}}
graph LR;
A[Lemons]-->B[Lemonade];
B-->C[Profit]
{{< /mermaid >}}
You can see some additional Mermaid examples on the [diagrams and flowcharts samples]({{< ref "diagrams-flowcharts" >}}) page.
### Swatches
`swatches` outputs a set of up to three different colors to showcase color elements like a color palette. This shortcode takes the `HEX` codes of each color and creates the visual elements for each.
**Example**
```md
{{</* swatches "#64748b" "#3b82f6" "#06b6d4" */>}}
```
**Output**
{{< swatches "#64748b" "#3b82f6" "#06b6d4" >}}
### Tabs
The `tabs` shortcode is commonly used to present different variants of a particular step. For example, it can be used to show how to install VS Code on different platforms.
| Parameter | Description |
| --------- | -------------------------------------------------------- |
| `group` | **Optional.** Group name for synchronized tab switching. All tabs with the same group name will switch together. |
| `default` | **Optional.** Label of the tab to be active by default. If not set, the first tab will be active. |
| `label` | **Required.** The text label displayed on the tab button. |
| `icon` | **Optional.** Icon name to display before the label. |
| `md` | **Optional.** Render tab content as Markdown (default `true`). Set `md=false` to allow nested shortcodes inside tab content. |
**Example 1: Basic Usage**
`````md
{{</* tabs */>}}
{{</* tab label="Windows" */>}}
Install using Chocolatey:
```pwsh
choco install vscode.install
```
or install using WinGet
```pwsh
winget install -e --id Microsoft.VisualStudioCode
```
{{</* /tab */>}}
{{</* tab label="macOS" */>}}
```bash
brew install --cask visual-studio-code
```
{{</* /tab */>}}
{{</* tab label="Linux" md=false */>}}
{{</* alert */>}}See [documentation](https://code.visualstudio.com/docs/setup/linux#_install-vs-code-on-linux).{{</* /alert */>}}
{{</* /tab */>}}
{{</* /tabs */>}}
`````
**Output**
{{< tabs >}}
{{< tab label="Windows" >}}
Install using Chocolatey:
```pwsh
choco install vscode.install
```
or install using WinGet
```pwsh
winget install -e --id Microsoft.VisualStudioCode
```
{{< /tab >}}
{{< tab label="macOS" >}}
```bash
brew install --cask visual-studio-code
```
{{< /tab >}}
{{< tab label="Linux" md=false >}}
{{< alert >}}See [documentation](https://code.visualstudio.com/docs/setup/linux#_install-vs-code-on-linux).{{< /alert >}}
{{< /tab >}}
{{< /tabs >}}
**Example 2: With Group, Default, and Icon**
`````md
{{</* tabs group="lang" default="Python" */>}}
{{</* tab label="JavaScript" icon="code" */>}}
```javascript
console.log("Hello");
```
{{</* /tab */>}}
{{</* tab label="Python" icon="sun" */>}}
```python
print("Hello")
```
{{</* /tab */>}}
{{</* tab label="Go" icon="moon" */>}}
```go
fmt.Println("Hello")
```
{{</* /tab */>}}
{{</* /tabs */>}}
{{</* tabs group="lang" default="Python" */>}}
{{</* tab label="JavaScript" icon="code" */>}}
```javascript
const add = (a, b) => a + b;
```
{{</* /tab */>}}
{{</* tab label="Python" icon="sun" */>}}
```python
def add(a, b): return a + b
```
{{</* /tab */>}}
{{</* tab label="Go" icon="moon" */>}}
```go
func add(a, b int) int { return a + b }
```
{{</* /tab */>}}
{{</* /tabs */>}}
`````
**Output**
{{< tabs group="lang" default="Python" >}}
{{< tab label="JavaScript" icon="code" >}}
```javascript
console.log("Hello");
```
{{< /tab >}}
{{< tab label="Python" icon="sun" >}}
```python
print("Hello")
```
{{< /tab >}}
{{< tab label="Go" icon="moon" >}}
```go
fmt.Println("Hello")
```
{{< /tab >}}
{{< /tabs >}}
{{< tabs group="lang" default="Python" >}}
{{< tab label="JavaScript" icon="code" >}}
```javascript
const add = (a, b) => a + b;
```
{{< /tab >}}
{{< tab label="Python" icon="sun" >}}
```python
def add(a, b): return a + b
```
{{< /tab >}}
{{< tab label="Go" icon="moon" >}}
```go
func add(a, b int) int { return a + b }
```
{{< /tab >}}
{{< /tabs >}}
In this example, both tab groups share the same `group="lang"` parameter, so clicking any tab will synchronize both groups. The `default="Python"` parameter makes Python the initially active tab, and `icon="code"` adds an icon before each label.
### Timeline
The `timeline` creates a visual timeline that can be used in different use-cases, e.g. professional experience, a project's achievements, etc. The `timeline` shortcode relies on the `timelineItem` sub-shortcode to define each item within the main timeline. Each item can have the following properties.
<!-- prettier-ignore-start -->
| Parameter | Description |
| ----------- | -------------------------------------------- |
| `md` | render the content as Markdown (true/false) |
| `icon` | the icon to be used in the timeline visuals |
| `header` | header for each entry |
| `badge` | text to place within the top right badge |
| `subheader` | entry's subheader |
<!-- prettier-ignore-end -->
**Example:**
```md
{{</* timeline */>}}
{{</* timelineItem icon="github" header="header" badge="badge test" subheader="subheader" */>}}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non magna ex. Donec sollicitudin ut lorem quis lobortis. Nam ac ipsum libero. Sed a ex eget ipsum tincidunt venenatis quis sed nisl. Pellentesque sed urna vel odio consequat tincidunt id ut purus. Nam sollicitudin est sed dui interdum rhoncus.
{{</* /timelineItem */>}}
{{</* timelineItem icon="code" header="Another Awesome Header" badge="date - present" subheader="Awesome Subheader" */>}}
With html code
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
{{</* /timelineItem */>}}
{{</* timelineItem icon="star" header="Shortcodes" badge="AWESOME" */>}}
With other shortcodes
{{</* gallery */>}}
<img src="gallery/01.jpg" class="grid-w33" />
<img src="gallery/02.jpg" class="grid-w33" />
<img src="gallery/03.jpg" class="grid-w33" />
<img src="gallery/04.jpg" class="grid-w33" />
<img src="gallery/05.jpg" class="grid-w33" />
<img src="gallery/06.jpg" class="grid-w33" />
<img src="gallery/07.jpg" class="grid-w33" />
{{</* /gallery */>}}
{{</* /timelineItem */>}}
{{</* timelineItem icon="code" header="Another Awesome Header"*/>}}
{{</* github repo="nunocoracao/blowfish" */>}}
{{</* /timelineItem */>}}
{{</* /timeline */>}}
```
{{< timeline >}}
{{< timelineItem icon="github" header="header" badge="badge test" subheader="subheader" >}}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non magna ex. Donec sollicitudin ut lorem quis lobortis. Nam ac ipsum libero. Sed a ex eget ipsum tincidunt venenatis quis sed nisl. Pellentesque sed urna vel odio consequat tincidunt id ut purus. Nam sollicitudin est sed dui interdum rhoncus.
{{</ timelineItem >}}
{{< timelineItem icon="code" header="Another Awesome Header" badge="date - present" subheader="Awesome Subheader">}}
With html code
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
{{</ timelineItem >}}
{{< timelineItem icon="star" header="Shortcodes" badge="AWESOME" >}}
With other shortcodes
{{< gallery >}}
<img src="gallery/01.jpg" class="grid-w33" />
<img src="gallery/02.jpg" class="grid-w33" />
<img src="gallery/03.jpg" class="grid-w33" />
<img src="gallery/04.jpg" class="grid-w33" />
<img src="gallery/05.jpg" class="grid-w33" />
<img src="gallery/06.jpg" class="grid-w33" />
<img src="gallery/07.jpg" class="grid-w33" />
{{< /gallery >}}
{{</ timelineItem >}}
{{< timelineItem icon="code" header="Another Awesome Header">}}
{{< github repo="nunocoracao/blowfish" >}}
{{</ timelineItem >}}
{{</ timeline >}}
### TypeIt
[TypeIt](https://www.typeitjs.com) is the most versatile JavaScript tool for creating typewriter effects on the planet. With a straightforward configuration, it allows you to type single or multiple strings that break lines, delete & replace each other, and it even handles strings that contain complex HTML.
Blowfish implements a sub-set of TypeIt features using a `shortcode`. Write your text within the `typeit` shortcode and use the following parameters to configure the behavior you want.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `tag` | [String] `html` tag that will be used to render the strings. |
| `classList` | [String] List of `css` classes to apply to the `html` element. |
| `initialString` | [String] Initial string that will appear written and will be replaced. |
| `speed` | [number] Typing speed, measured in milliseconds between each step. |
| `lifeLike` | [boolean] Makes the typing pace irregular, as if a real person is doing it. |
| `startDelay` | [number] The amount of time before the plugin begins typing after being initialized. |
| `breakLines` | [boolean] Whether multiple strings are printed on top of each other (true), or if they're deleted and replaced by each other (false). |
| `waitUntilVisible` | [boolean] Determines if the instance will begin when loaded or only when the target element becomes visible in the viewport. The default is `true` |
| `loop` | [boolean] Whether your strings will continuously loop after completing |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* typeit */>}}
Lorem ipsum dolor sit amet
{{</* /typeit */>}}
```
{{< typeit >}}
Lorem ipsum dolor sit amet
{{< /typeit >}}
**Example 2:**
```md
{{</* typeit
tag=h1
lifeLike=true
*/>}}
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
{{</* /typeit */>}}
```
{{< typeit
tag=h1
lifeLike=true
>}}
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
{{< /typeit >}}
**Example 3:**
```md
{{</* typeit
tag=h3
speed=50
breakLines=false
loop=true
*/>}}
"Frankly, my dear, I don't give a damn." Gone with the Wind (1939)
"I'm gonna make him an offer he can't refuse." The Godfather (1972)
"Toto, I've a feeling we're not in Kansas anymore." The Wizard of Oz (1939)
{{</* /typeit */>}}
```
{{< typeit
tag=h3
speed=50
breakLines=false
loop=true
>}}
"Frankly, my dear, I don't give a damn." Gone with the Wind (1939)
"I'm gonna make him an offer he can't refuse." The Godfather (1972)
"Toto, I've a feeling we're not in Kansas anymore." The Wizard of Oz (1939)
{{< /typeit >}}
### Video
Blowfish includes a `video` shortcode for embedding local or external videos in content. The shortcode renders a `<figure>` wrapper with a responsive video player and an optional caption.
The `video` shortcode accepts the following parameters:
<!-- prettier-ignore-start -->
| Parameter | Description |
| --- | --- |
| `src` | **Required.** Video URL or local path. Local lookup order: page resource → `assets/` → `static/`. |
| `poster` | Optional poster image URL or local path. If omitted, the shortcode attempts a same-name image in the page bundle. |
| `caption` | Optional Markdown caption shown below the video. |
| `autoplay` | `true`/`false`. Enables autoplay when `true`. Default: `false`. |
| `loop` | `true`/`false`. Loops when `true`. Default: `false`. |
| `muted` | `true`/`false`. Mutes when `true`. Default: `false`. |
| `controls` | `true`/`false`. Shows the browsers default playback controls when `true`. Default: `true`. |
| `playsinline` | `true`/`false`. Inline playback on mobile when `true`. Default: `true`. |
| `preload` | `metadata` (load info), `none` (save bandwidth), or `auto` (preload more). Default: `metadata`. |
| `start` | Optional start time in seconds. |
| `end` | Optional end time in seconds. |
| `ratio` | Reserved aspect ratio for the player. Supports `16/9`, `4/3`, `1/1`, or custom `W/H`. Default: `16/9`. |
| `fit` | How the video fits the ratio: `contain` (no crop), `cover` (crop to fill), `fill` (stretch). Default: `contain`. |
<!-- prettier-ignore-end -->
If the browser cannot play the video, the player will show a minimal English fallback message with a download link.
**Example:**
```md
{{</* video
src="https://upload.wikimedia.org/wikipedia/commons/5/5a/CC0_-_Public_Domain_Dedication_video_bumper.webm"
poster="https://upload.wikimedia.org/wikipedia/commons/e/e0/CC0.jpg"
caption="**Public domain demo** — CC0 video and poster."
loop=true
muted=true
*/>}}
```
{{< video
src="https://upload.wikimedia.org/wikipedia/commons/5/5a/CC0_-_Public_Domain_Dedication_video_bumper.webm"
poster="https://upload.wikimedia.org/wikipedia/commons/e/e0/CC0.jpg"
caption="**Public domain demo** — CC0 video and poster."
loop=true
muted=true
>}}
### Youtube Lite
A shortcut to embed youtube videos using the [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed) library. This library is a lightweight alternative to the standard youtube embeds, and it's designed to be faster and more efficient.
<!-- prettier-ignore-start -->
| Parameter | Description |
| --------- | -------------------------------------------- |
| `id` | [String] Youtube video id to embed. |
| `label` | [String] Label for the video |
| `params` | [String] Extras parameters for video playing |
<!-- prettier-ignore-end -->
**Example 1:**
```md
{{</* youtubeLite id="SgXhGb-7QbU" label="Blowfish-tools demo" */>}}
```
{{< youtubeLite id="SgXhGb-7QbU" label="Blowfish-tools demo" >}}
**Example 2:**
You can use all of Youtube's [player parameters](https://developers.google.com/youtube/player_parameters#Parameters) for the `params` variable, as demonstrated below:
> This video will start after 130 seconds (2m10)
```md
{{</* youtubeLite id="SgXhGb-7QbU" label="Blowfish-tools demo" params="start=130" */>}}
```
> This video will not have UI controls, will start playing at 130 seconds and will stop 10 seconds later.
To concatenate multiple options as shown below, you need to add the `&` character between them.
```md
{{</* youtubeLite id="SgXhGb-7QbU" label="Blowfish-tools demo" params="start=130&end=10&controls=0" */>}}
```
{{< youtubeLite id="SgXhGb-7QbU" label="Blowfish-tools demo" params="start=130&end=10&controls=0" >}}
More informations can be found on the [youtubeLite GitHub repo](https://github.com/paulirish/lite-youtube-embed/blob/master/readme.md#custom-player-parameters) and Youtube's [player parameters](https://developers.google.com/youtube/player_parameters#Parameters) page.
---