Include handlebars partials when they exist based on context in Ghost - handlebars.js

I've got a customized theme for Ghost. I nave a guest author once on a while. I'd love the ability to include any number of custom links to the authors page for each author.
I'm aware of the authors-{{slug}}.hbs convention I could use to create a complete custom page for each author, but that's a nightmare to maintain.
Instead I was trying to try to include a partial when it exists. According to the handlebars docs the {{#> partial }} should work. But that works when I know the exact name of the partial.
I need the name of the partial to be dynamic based on the context. In my case the ghost slug for the author. According to the handlebar docs I need to pass in a function...
I tried a few ways, but gscan dislikes all of them:
{{#> (concat "partials/socials-" slug) }}
{{#> (concat "partials/socials-" (lookup . 'slug')) }}
{{#> concat "partials/socials-" (lookup . 'slug') }}
{{#> "partials/socials-{{slug}}" }}
{{#> partials/socials-{{slug}} }}
All give me:
Checking theme compatibility...
Your theme has 1 error!
----
Errors
------
Important to fix, functionality may be degraded.
- Error: Templates must contain valid Handlebars
Files: author.hbs

Have you used content blocks before? They're a way to re-use template code but still allow for customisation, it's a method used in Casper which you've forked from. Check out these lines here in page.hbs: https://github.com/jessehouwing/jessehouwingnl-Casper/blob/customized/page.hbs#L58-L65
as well as this line shown in default.hbs: https://github.com/jessehouwing/jessehouwingnl-Casper/blob/customized/default.hbs#L127
What you could do is create a custom author template that inherits the existing author.hbs template. For this example I'm going to create a custom author page for the author 'ghost' by creating author-ghost.hbs:
{{!< author}}
{{#contentFor "links"}}
<ul>
<li>Example link</li>
<li>Example link</li>
<li>Example link</li>
</ul>
{{/contentFor}}
The above code inherits author.hbs and creates a block called links. Then in the original author.hbs template we can add the block reference to where we want the contents of the block to appear:
{{{block "links"}}}
Not only will this insert the code in the custom author template, but it'll also gracefully fallback to no output if there isn't a custom author template for the author.
Hope this helps!

I had the same issue and here how I solved. Just use the lookup in this syntax.
{{#foreach navigation}}
<li class="nav-{{slug}}">
<a href="{{url}}" class="social-link" target="_blank" rel="noopener">
{{>(lookup . 'slug')}}
</a>
</li>
{{/foreach}}

Related

WooCommerce: Add class to Related Product Loop item <ul class="products columns-4 owl-carousel four-col">

I want to add some Owl Carousel Classes to the Related Products from <ul class="products columns-4"> to <ul class="products columns-4 owl-carousel four-col"> in the Unordered List, in the single product page.
The CSS classes I want to add are owl-carousel four-col.
Doing this I know requires some knowledge of WordPress hooks and filters.
Any idea on how to implement this will be appreciated :)
As far as I know there is no filter available to modify classes set to <ul class="products"> element.
This element is actually rendered with WC template templates/loop/loop-start.php and this template is called with woocommerce_product_loop_start() function. This is a pluggable function, meaning you can override it in your active theme/child-theme.
The better and simpler way would be to modify the related template directly, located in templates/single-product/related.php (learn how to properly override WC templates in your child-theme, do NOT modify WC source templates directly in plugin's folder).
It should be enough to replace this line in the related template:
<?php woocommerce_product_loop_start(); ?>
with this line:
<ul class="products columns-4 owl-carousel four-col">
Another approach would be to set those classes dynamically with jQuery, but I'm not sure whether it would work well with Owl Carousel (it might not load properly).

Hugo Theme Academic: Rename "interests" in about section

I'm setting up a Hugo website, theme academic, in R via hugodown. In the "about" section is a column named "interests" which I want to rename into "work".
What I have done so far:
The content/authors/admin/_index.md file contains following code:
interests: # <- I want to rename this into 'work'
- Artificial Intelligence
- Computational Linguistics
- Information Retrieval
If only this file is renamed then the whole column "interests" won't show.
There is another file layouts/partial/widgets/about.html which contains the following code:
{{ with $person.interests }}
<div class="col-md-5">
<h3>{{ i18n "interests" | markdownify }}</h3>
<ul class="ul-interests">
{{ range . }}
<li>{{ . | markdownify | emojify }}</li>
{{ end }}
</ul>
</div>
{{ end }}
Additional to the above change, naming with $person.interests into with $person.work will show the column again, but it is still called "interests". When additionally changing the i18n "interests" in the <h3> tag into i18n "work" the heading "interests" is removed and only the content of the column is displayed without a heading.
It seems like the new column name "work" has to be registered somewhere else, before it is properly display.
Any help appreciated.
After fiddling around I found the answer to my question. As I expected there is a file in which all ids and their translation are registred. It depends on the choosen language. If the chosen language is English en then it is enough to go to the folder: themes/academic/i18n/ and open the file en.yaml. Here we find:
# About widget
- id: interests
translation: Interests
This can be changed to:
- id: interests
translation: Work
Now the website will properly display "Work" instead of "Interests" on the About widget page.

Fetching all tags to make a navigation component, Ghost

I was creating a ghost blog and i created a custom component to display all the tags in the blog.
I used the below code to do so,
{{#get "tags" limit="all"}}
<ul class="tags">
{{#foreach tags}}
<li>
{{name}}
</li>
{{/foreach}}
</ul>
{{/get}}
I made the component to act as a filter. But I am facing some issues,
Tags with no posts are not displaying.
Also is there any way to know which tag filter is currently active?
can someone help me with what I am doing wrong.?
Thanks in advance.
I believe tags with no posts technically don't exist so they don't they don't create empty page routes, as all tags have their own tag page (/tag/example-tag/). As for knowing the active class I assume you're wanting to apply an active class to the tag link, which can be done with link_class:
<a class="tag {{link_class for=url class='tag-current'}}" href="{{url}}">{{name}}</a>

How do I set Ghost Blog Custom Routes.yaml Collection Title / Meta Description in my custom template?

Using the Ghost blog routes.yaml file it is possible to use the collections block to create a custom collection made from some tag(s) and / or other data. You can also tell this collection to use a custom theme template see:
https://docs.ghost.org/tutorials/creating-content-collections/
https://docs.ghost.org/concepts/routing/#content-structure
For instance:
collections:
/example/:
permalink: /example/{slug}/
controller: channel
filter: tag:example-tag
template:
- example
All of the above works and my collection properly uses my new example theme file.
The issue is that unlike the tag page (for example-tag) my new custom collection does not have a readily documented way to work with the title etc.
It does not pull the title / meta description from the tag used to build the collection (which would be great for collections built from single tags). In an attempt to work around that I tried some {{#has}} statements but I can't figure out what context the custom route would fit into.
With the above example routes.yaml the title for the custom collection ends up as 'My Site Name (Page 1)' — and there is no Meta Description.
This issue also extends into the Open Graph data which lists an identical title as well as no description for the custom collection.
My guess is that it may be possible to use a data property attached to the routes.yaml file to achieve this (see: https://docs.ghost.org/concepts/routing/#data) but I haven't found a solution as of now.
While my initial attempts at googling for a solution came up empty, this is the best reference I have seen to the issue:
https://forum.ghost.org/t/dynamic-routing-page-post-data-context-in-default-hbs-nested-navigation-on-custom-collections/4204
https://github.com/TryGhost/Ghost/issues/10082
I found a way to work around.
You create a page called example in the Ghost Admin tool.
Customize routes (instead of collections) in the routes.yaml as following:
routes:
/example/:
controller: channel
filter: tag:example-tag
template: example
data: page.example
The page.example will use the metadata of this page in the Ghost.
This is possible only with workaround described in issue: https://github.com/TryGhost/Ghost/issues/10082
Generally do following:
create page Example (with slug example) and fill metadata title & description you want
in routes.yaml alter your collection definition /example/ add following:data: page.example to link your collection root with specified page
now in your template definition example.hbs you could use e.g. {{#page}} {{content}} {{/page}} tag to insert content from your page. You can do it also in default.hbs template which is included from your example.hbs. So replace: <title>{{meta_title}}</title> in default.hbs with following:
{{#unless page}}
<title>{{meta_title}}</title>
{{else}}
{{#page}}
<title>{{meta_title}}</title>
<meta name="description" content="{{meta_description}}"/>
{{/page}}
{{/unless}}
This will set specific title/description for your collection root pages in general way. It is possible to generate schema.org metadata in the similar way. Unfortunately Facebook and Twitter metadata is not so simple to do because, {{ghost_head}} tag in default.hbs already inserts site metadata to this page. Last note: besides {{meta_title}} and {{meta_description}} I suppose you could use all metadata fields defined here.
In default.hbs I added the following block:
{{{ block "metaTitle"}}}
and eg. in post.hbs I filled that block as follows:
{{!< default}}
<div class="content-area">
<main class="site-main">
{{#post}}
{{#contentFor "metaTitle"}}
<title>{{title}}</title>
{{/contentFor}}
...
For other pages like page.hbs, blog.hbs, author.hbs I did the same. I think that solution is more flexible because we have more control over title value.

Additional content in Wordpress - possible use of Custom Taxonomies

I'm fairly new to the Custom Taxonomies in Wordpress, but I wanted to see if I can use this feature to achieve a list of items that link of to pages within my site.
Here is the final HTML I am looking to output:
<ul>
<li>Custom Taxonomy 1</li>
<li>Custom Taxonomy 2</li>
<li>Custom Taxonomy 3</li>
<li>Custom Taxonomy 4</li>
</ul>
As you can see above I have various taxonomy items (i.e. 1 & 4) both linking to the same URL.
So I am looking to see if it is possible to:
Setup Custom Taxonomies with two data inputs (name & custom URL) that I could reference in my theme
Alternatively, I would just create another HTML section where I could define the content (& links) in each post. (Almost as if it was a secondary 'content' area).
I would prefer not to use a plugin if possible, as I am attempting to maintain autonomy of the background code. Is this possible?
EDIT:
Sorry if this wasn't clear. I'm not 100% if Custom Taxonomies is the correct way to go.
Basically, I have a list of 'features' that I want to tag on each of my 'portfolio' posts. I want to display these features in a simple (linked) unordered list.
The important thing however is I don't want the list to be linked to a category/archive (like normal tags work). I want to be able to define the URL to an existing 'service' page for each feature, so the user can read more.
Therefore I need to be able to define both the name of the feature and the url of the page the link should point to.
As the list of 'features' & the pages they point to will always remain the same, I thought Custom Taxonomies may be the solution.
You can make a template for each taxonomy term , in your case for each feature.
So ie if you have a term with the name 'premium' you can make a taxonomy-features-premium.php template file and place whatever you want.
So on your page where the portfolio post is being display you can show all the features with their permalinks and if you have make the template files for every term when you click on a term will show the template file for the term that you selected.
or inside the template files you can just redirect them to the page you want.
Update :
In your single-portfolio.php (the template file responsible for showing the portfolio custom post) you can put somewhere in your code (depending your needs and the style of your page) :
echo '<ul>';
echo get_the_term_list( $post->ID, 'features', '<li>', ',</li><li>', '</li>' );
echo '</ul>';
Doc : http://codex.wordpress.org/Function_Reference/get_the_term_list or you can use : http://codex.wordpress.org/Function_Reference/get_the_terms if you want to take more control of your terms.
This would return something like :
<ul>
<li>Premium Feature</li>
<li>Basic Feature</li>
</ul>
So now you have all the terms belonging to the specific post. So if you create a taxonomy-features-premium.php template file, when the user clicks the Premium Feature link wordpress will show whatever is in that template. Notice that if you don't have a taxonomy-features-premium.php template wordpress will search for a taxonomy-features.php (that template is usufull if you want all your terms to be shown the same way). More about template hierarchy here : http://codex.wordpress.org/Template_Hierarchy#Custom_Taxonomies_display
Now inside the template or you can copy paste the code that you have in your page + add some modifications corresponding to the term or you can just redirect to the page you want : wp_redirect(get_permalink( $your_page_id )); exit;

Resources