Skip to content

Commit

Permalink
Merge pull request #87 from karthik2804/themeing_support
Browse files Browse the repository at this point in the history
Themeing support
  • Loading branch information
vdice committed Jul 28, 2022
2 parents 22d0eba + f0514cd commit dca3741
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 8 deletions.
4 changes: 3 additions & 1 deletion docs/content/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ title = "Bartholomew"
# logo = "URL to logo"
base_url = "http://localhost:3000"
about = "This site is generated with Bartholomew, the Spin micro-CMS. And this message is in site.toml."
theme = "fermyon"
[extra]
copyright = "The Site Authors"
Expand All @@ -31,10 +32,11 @@ It has a few pre-defined fields:
- logo: a URL or static path to your logo
- base_url: a base URL that templates can use to construct full URLs to content. This can be overridden by setting the `-e BASE_URL="https://example.com"` environment variable for Spin.
- about: a brief description of the site
- theme: the name of the theme for the website from the `/themes/` folder

You can define your own fields in the `[extra]` section. Anything in `[extra]` is not
used by the system itself. But it's a useful way to pass information from one central
place to all of your templates. For example, a template can access the `copyright` value
using `{{site.info.extra.copyright}}`.

Let's take a look at how you can do something special in your templates [using scripting](./scripting.md).
Let's take a look at how you can configure your site to use [themes](./themes.md).
87 changes: 87 additions & 0 deletions docs/content/themes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
title = "Bartholomew themes"
date = "2022-07-20T22:44:01.300319091Z"

[extra]

---

Bartholomew supports theming which allows for easy customization of the site along with the user-defined tempaltes.

## Adding a theme

Once the initial site has been set up using the [quickstart section](/quickstart), create a themes folder where you will be able to download different themes.
```bash
mkdir themes
```

Once the folder is created, different themes can be added as submodules to the folder which can then in turn be used to theme the site.

```bash
cd themes
git submodule add <Source_to_the_theme>
```

Multiple themes can be added to the themes directory but only one of them will be active at a given time as described in the next section.

## Configuring the site to use the theme

To choose a theme for the website, the `theme` attribute in `config/site.toml` must be configured, where the value is the name of the theme as found in the `themes/` folder.

```toml
title = "Bartholomew Documentation"
base_url = "http://localhost:3000"
about = "The Micro-CMS for WebAssembly and Spin"
theme = "<theme-directory>"

[extra]
copyright = "Fermyon"
github = "https://github.com/fermyon/bartholomew"
twitter = "https://twitter.com/fermyontech"
ga_measurement_id = ""

date_style = "%B %e, %Y"
```
One more step that needs to be done before themes are fully available to the site is to the change the static file server component in the `spin.toml` configuration so that it provides the static assets of the selected theme. The convention of mounting the static assets of the themes before the user-defined static assets is recommened.

```
.
.
.
[[component]]
source = "modules/spin_static_fs.wasm"
id = "fileserver"
files = [ {source = "themes/<name of theme>/static", destination ="/"}, { source = "static/", destination = "/" }, ]
[component.trigger]
route = "/static/..."
```


## Template precedence

When a theme is enabled for a site, both the user-defined and theme-provided assets like the templates, scripts and static assets will be available. If a theme-provided asset and user-provided asset have the same name, the user-defined asset takes precedence. This allows for the user to override the theme to allow for customization.

As an example, if both `templates/main.hbs` and `themes/<name of theme>/templates/main.hbs` exist, the user-defined `templates/main.hbs` takes precedence leading to the rendering engine using the user-defined template overriding the theme.

## Creating a Theme

Creating a theme for Bartholomew is easy. Create a new folder and initialize it.

```
mkdir custom_theme
cd custom_theme
git init
```

Once the git repository is initialized, create the three required directories.
```
mkdir templates scripts static
```

Create the custom theme by placing the handlebar templates in the `template/` folder while the Rhai scripts are placed in the `scripts/` folder. All the static assets such as the images, JS and CSS are placed in the static folder. For reference on creating templates, refer to the [templates section](/templates).

Once the required changes are done, commit and push the changes to a remote repository, so as to allow for the theme to cloned as a submodule that can be used for theming a site.


Let's take a look at how you can do something special in your templates [using scripting](./scripting.md).
Binary file modified docs/modules/bartholomew.wasm
Binary file not shown.
4 changes: 2 additions & 2 deletions docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"sass": "^1.49.9"
},
"scripts": {
"spin": "nodemon --watch content --watch static --watch templates --ext md,rhai,hbs,css,js --verbose --legacy-watch --signal SIGINT --exec 'spin up --file spin.toml'",
"spin": "nodemon --watch content --watch static --watch templates --watch themes --ext md,rhai,hbs,css,js --verbose --legacy-watch --signal SIGINT --exec 'spin up --file spin.toml'",
"styles": "npx parcel build static/sass/styles.scss --dist-dir static/css --no-optimize"
}
}
4 changes: 2 additions & 2 deletions docs/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ trigger = { type = "http", base = "/" }
[[component]]
source = "modules/bartholomew.wasm"
id = "bartholomew"
files = [ "content/**/*" , "templates/*", "scripts/*", "config/*"]
files = [ "content/**/*" , "templates/*", "themes/**/*", "scripts/*", "config/*"]
[component.trigger]
route = "/..."

[[component]]
source = "modules/spin_static_fs.wasm"
id = "fileserver"
files = [ { source = "static/", destination = "/" } ]
files = [{ source = "static/", destination = "/" }, ]
[component.trigger]
route = "/static/..."
1 change: 1 addition & 0 deletions docs/templates/content_sidebar.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<li><a href="{{site.info.base_url}}/quickstart">Quickstart</a></li>
<li><a href="{{site.info.base_url}}/templates">Templates</a></li>
<li><a href="{{site.info.base_url}}/configuration">Configuration</a></li>
<li><a href="{{site.info.base_url}}/themes">Themes</a></li>
<li><a href="{{site.info.base_url}}/scripting">Scripting</a></li>
<li><a href="{{site.info.base_url}}/markdown">Markdown guide</a></li>
</ul>
Expand Down
Empty file added docs/templates/index.hbs
Empty file.
10 changes: 10 additions & 0 deletions src/bartholomew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,18 @@ pub fn render(req: Request) -> Result<Response> {
}
eprintln!("Base URL: {:?}", &config.base_url);

// If a theme is specifed, create theme path
let theme_dir = if config.theme.is_some() {
let mut path: PathBuf = PathBuf::from(THEME_PATH);
path.push(config.theme.as_ref().unwrap());
Some(path)
} else {
None
};

let mut engine = template::Renderer::new(
PathBuf::from(TEMPLATE_PATH),
theme_dir,
PathBuf::from(SCRIPT_PATH),
PathBuf::from(CONTENT_PATH),
);
Expand Down
1 change: 1 addition & 0 deletions src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::io::Write;

pub const CONTENT_PATH: &str = "/content/";
pub const TEMPLATE_PATH: &str = "/templates/";
pub const THEME_PATH: &str = "/themes/";
pub const SCRIPT_PATH: &str = "/scripts/";
pub const CONFIG_FILE: &str = "/config/site.toml";

Expand Down
31 changes: 29 additions & 2 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct SiteInfo {
pub logo: Option<String>,
pub base_url: Option<String>,
pub about: Option<String>,
pub theme: Option<String>,
pub extra: BTreeMap<String, String>,
}

Expand Down Expand Up @@ -72,6 +73,7 @@ impl From<Content> for PageValues {
/// Renderer can execute a handlebars template and render the results into HTML.
pub struct Renderer<'a> {
pub template_dir: PathBuf,
pub theme_dir: Option<PathBuf>,
pub script_dir: PathBuf,
pub content_dir: PathBuf,
pub show_unpublished: bool,
Expand All @@ -80,9 +82,15 @@ pub struct Renderer<'a> {

impl<'a> Renderer<'a> {
/// Create a new renderer with the necessary directories attached.
pub fn new(template_dir: PathBuf, script_dir: PathBuf, content_dir: PathBuf) -> Self {
pub fn new(
template_dir: PathBuf,
theme_dir: Option<PathBuf>,
script_dir: PathBuf,
content_dir: PathBuf,
) -> Self {
Renderer {
template_dir,
theme_dir,
script_dir,
content_dir,
show_unpublished: false,
Expand All @@ -98,15 +106,34 @@ impl<'a> Renderer<'a> {
/// Load the template directory.
pub fn load_template_dir(&mut self) -> Result<(), anyhow::Error> {
self.register_helpers();

// If there is a theme, load the templates provided by it first
// Allows for user defined tempaltes to take precedence
if self.theme_dir.is_some() {
let mut templates = self.theme_dir.as_ref().unwrap().to_owned();
templates.push("templates");
self.handlebars
.register_templates_directory(".hbs", templates)?;
}
self.handlebars
.register_templates_directory(".hbs", &self.template_dir)?;
Ok(())
}

/// Load the scripts directory
pub fn load_script_dir(&mut self) -> anyhow::Result<()> {
let mut theme_scripts: Vec<PathBuf> = Vec::new();

// If theme has scripts,load it first to follow proper precedence
if self.theme_dir.is_some() {
let mut theme_scripts_path = self.theme_dir.as_ref().unwrap().to_owned();
theme_scripts_path.push("scripts");
theme_scripts = crate::content::all_files(theme_scripts_path)?;
}
let user_scripts = crate::content::all_files(self.script_dir.clone())?;
// TODO: rewrite all_files so we don't need to clone here.
let scripts = crate::content::all_files(self.script_dir.clone())?;
let scripts = [theme_scripts, user_scripts].concat();

for script in scripts {
// Relative file name without extension. Note that we skip any file
// that doesn't have this.
Expand Down

0 comments on commit dca3741

Please sign in to comment.