Kramdown table of content doesn't display inside HTML block - jekyll

I was following this question, but it doesn't seem to take effect for me. Any help would be greatly appreciated.
_includes/layout.html
<main>
<div>
<!-- Sidebar -->
<aside markdown="1">
<h4>Table of Contents</h4>
* ToC
{:toc}
</aside>
<!-- END Sidebar -->
<!-- Main content -->
<article>
{{ content }}
</article>
<!-- END Main content -->
</div>
</main>
_config.yml
markdown: kramdown
Result:
Update
_layouts/site.html
<aside markdown="1">
mark**down**
</aside>
It just renders as above. Kramdown is turned on in config.

Solved by using pure liquid ToC by allejo.
% capture tocWorkspace %}
{% comment %}
"...like all things liquid - where there's a will, and ~36 hours to spare, there's usually a/some way" ~jaybe
Usage:
{% include toc_pure_liquid.html html=content sanitize=true class="inline_toc" id="my_toc" h_min=2 h_max=3 %}
Parameters:
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
Optional Parameters:
* sanitize (bool) : false - when set to true, the headers will be stripped of any HTML in the TOC
* class (string) : '' - a CSS class assigned to the TOC
* id (string) : '' - an ID to assigned to the TOC
* h_min (int) : 1 - the minimum TOC header level to use; any header lower than this value will be ignored
* h_max (int) : 6 - the maximum TOC header level to use; any header greater than this value will be ignored
Output:
An unordered list representing the table of contents of a markdown block. This snippet will only generate the table of contents and will NOT output the markdown given to it
{% endcomment %}
{% capture my_toc %}{% endcapture %}
{% assign minHeader = include.h_min | default: 1 %}
{% assign maxHeader = include.h_max | default: 6 %}
{% assign nodes = include.html | split: '<h' %}
{% for node in nodes %}
{% if node == "" %}
{% continue %}
{% endif %}
{% assign headerLevel = node | replace: '"', '' | slice: 0, 1 %}
{% assign headerLevel = headerLevel | times: 1 %}
{% assign indentAmount = headerLevel | minus: minHeader | add: 1 %}
{% assign _workspace = node | split: '</h' %}
{% unless headerLevel >= minHeader %}
{% continue %}
{% endunless %}
{% if headerLevel > maxHeader %}
{% continue %}
{% endif %}
{% assign _idWorkspace = _workspace[0] | split: '"' %}
{% assign html_id = _idWorkspace[1] %}
{% capture _hAttrToStrip %}{{ headerLevel }} id="{{ html_id }}">{% endcapture %}
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
{% assign space = '' %}
{% for i in (1..indentAmount) %}
{% assign space = space | prepend: ' ' %}
{% endfor %}
{% capture my_toc %}{{ my_toc }}
{{ space }}- [{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}](#{{ html_id }}){% endcapture %}
{% endfor %}
{% if include.class %}
{% capture my_toc %}{:.{{ include.class }}}
{{ my_toc | lstrip }}{% endcapture %}
{% endif %}
{% if include.id %}
{% capture my_toc %}{: #{{ include.id }}}
{{ my_toc | lstrip }}{% endcapture %}
{% endif %}
{% endcapture %}{% assign tocWorkspace = '' %}
{{ my_toc | markdownify }}

In theory it should work that way, (it is not working for me either) but you can force to process the code inside a block with `markdown="1" like this:
<aside markdown="1">
<h4>Table of Contents</h4>
* ToC
{:toc}
</aside>
Make sure you don't indent the code inside the aside tag or it will be parsed as kramdown code.
By default, kramdown parses all block HTML tags and all XML tags as
raw HTML blocks. However, this can be configured with the
parse_block_html. If this is set to true, then syntax parsing in HTML
blocks is globally enabled. It is also possible to enable/disable
syntax parsing on a tag per tag basis using the markdown attribute:
If an HTML tag has an attribute markdown="0", then the tag is parsed as raw HTML block.
If an HTML tag has an attribute markdown="1", then the default mechanism for parsing syntax in this tag is used.
Update
I've checked your repo, you need to rename index.html to index.md so kramdown will parse it and then you can also add the line to _config.yml to parse markdown inside html blocks.

Jekyll only parse .md or .mardown files.
.html files are not proccessed by markdown parser.
If you rename a file from .html to .md, it will be processed as kramdown.
But there you will have problems with indentation.
Mixing html and markdown is not so easy ;-)

Related

How to use a Jinja variable inside of sphinx ref directive or head tag?

I'm using sphinx and auto-summary to create my documentation. However, for each module a I want to generate customized list of references. However, to do that, I need to pass the objname to ref directive. How can I achieve that?
{{ fullname | escape | underline}}
.. automodule:: {{ fullname }}
Items
-----
{% block classestab %}
{% if classes %}
{% for objname in classes %}
- :ref:` {{objname}} <{{objname}}>`_ // doesn't work
{%- endfor %}
{% endif %}
{% endblock %}
I've also trying to use a jinja variable to create headings for my documentation. However I don't know to achieve this. The code below will not work of course
{% block table %}
{% if classes %}
{% for objname in classes %}
{{objname}}
===========
{%- endfor %}
{% endif %}
{% endblock %}

Include a file, but only if it exists?

I'm creating a style guide in Jekyll and using Collections to define different elements of the guide. For example, headings, lists, etc.
I'm trying to separate the Sass into files that match up with the partials, one to one, and I'd like to render the Sass files as part of each collection.
So, something like:
{% if _includes/_sass/{{ entry.title | append: ".scss"}} %}
{% highlight sass %}
{% include _includes/_sass/{{ entry.title | append: ".scss" }} %}
{% endhighlight %}
{% endif %}
Basically, what I want is "Include a file in this directory that has the same name as this entry in my collection. If it doesn't exist, don't break."
How do I do this? I've explored storing the file path in a variable but can't seem to get that to work.
Thanks in advance.
It can be done.
This works on Jekyll 3 but it can certainly be ported to Jekyll 2.
Starting from a base install (jekyll new)
_config.yml
collections:
guide:
sasssamples:
Style guide files
Our samples will be grouped in the _guide collection.
Example file : _guide/header/header1.hmtl
---
title: Header level 1
---
<h1>Header level 1</h1>
SCSS samples
We want our SCSS samples to be included in our css/main.scss and use variables defined in our other SCSS files. Our samples will be integrated at the end of our css/main.scss
We don't want our SCSS samples to render as css so no .scss extension. Switch to .txt extension
We want to access SCSS samples from a list. Let's put them in a sasssamples collection.
Example file : _sasssamples/header/header1.txt
---
---
h1{
color: $brand-color;
border: 1px solid $brand-color;
}
SCSS samples integration
Add this code at the very end of you bootstraping scss file (css/main.scss on a base Jekyll install)
css/main.scss
[ original code ... ]
{% comment %} Selecting a collection the Jekyll 3 way. See https://github.com/jekyll/jekyll/issues/4392 {% endcomment %}
{% assign scssCollection = site.collections | where: 'label', 'sasssamples' | first %}
{% comment %}
Printing documents in sasssamples collection.
All SCSS from style guide are sandboxed in .guide class
This allows us to apply styles only to style guide html samples
{% endcomment %}
.guide{
{% for doc in scssCollection.docs %}
{{ doc.content }}
{% endfor %}
}
The style guide
<h2>Style guide</h2>
{% comment %}Selecting a collection the Jekyll 3 way. See https://github.com/jekyll/jekyll/issues/4392 {% endcomment %}
{% assign guideCollection = site.collections | where: 'label', 'guide' | first %}
{% assign scssCollection = site.collections | where: 'label', 'sasssamples' | first %}
{% comment %} Looping hover style guide samples {% endcomment %}
{% assign samples = guideCollection.docs %}
{% for sample in samples %}
<article>
<h3>Element : {{ sample.title }}</h3>
<h4>Render</h4>
<div class="guide">
{{ sample.content }}
</div>
<h4>html code</h4>
{% highlight html %}{{ sample.content }}{% endhighlight %}
{% comment %}
Changing a path like : _guide/headers/header1.html
to : _sasssamples/headers/header1.txt
{% endcomment %}
{% assign scssPath = sample.path | replace: '_guide', '_sasssamples' %}
{% assign scssPath = scssPath | replace: '.html', '.txt' %}
{% comment %} Try to find a SCSS sample with equivalent path {% endcomment %}
{% assign scssSample = scssCollection.docs | where: 'path', scssPath | first %}
{% comment %}We print SCSS sample only if we found an equivalent path{% endcomment %}
{% if scssSample != nil %}
<h4>SCSS code</h4>
{% highlight css %}{{ scssSample.content }}{% endhighlight %}
{% endif %}
</article>
{% endfor %}
Done!
Seems it only miss on assigning the correct path
{% if _includes/_sass/{{ entry.title | append: ".scss"}}
Need to be replaced to relative path to the scss file:
{% assign scssPath = 'relative/path/to/your/scss/' %}
{% if {{ entry.title | append: ".scss" | prepend: scssPath }} != nil %}

How do I make my Jekyll Blog have titles with the page number?

Google Webmaster tools complains about pages with the same title. I'm trying to figure out how to make my blog index pages have different titles (by including the page number)
I set my titles through frontmatter so they are available to my base template.
I can't set the title in frontmatter to include the page number, since frontmatter doesn't evaluate variables.
I also tried {% assign page.title = 'freestyle' %} but found out page.title isn't really a variable
I created a new variable called titleOverwrite which correctly gets the data I want. Unfortunately it isn't scoped in my base template.
How can I get the titles to include the blog page number?
Here is what I tried:
Base Template
{% assign title = page.title %}
{% if page.overwriteTitle %}
{% assign title = page.overwriteTitle %}
{% endif %}
<title>{{title}} {{page.subtitle}}</title>
blog index.html
{% assign overwriteTitle = page.title | append: ' Page ' | append: paginator.page %}
<p>prove it works </p>
<p> {{ overwriteTitle }} </p>
_includes/head.html or any template affecting title tag
We test the paginator variable which is only present in paginated pages :
<title>
{% if paginator %}
{% assign overwriteTitle = page.title | append: ' Page ' | append: paginator.page %}
{{ overwriteTitle }}
{% else %}
{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}
{% endif %}
</title>

In my Jekyll include file how do I get the markdown for a post?

Is there a way to get ahold of a posts markdown in an include file?
My include file has this code: {{workingPost.content}}
When I include this in a markdown file I get the HTML. I pass that to another include that expects markdown and instead this is passing HTML.
Is there a way to access the markdown instead of the HTML for the post?
As requested here are the code files. What they do is get a featured post for the right hand side of the site like this. In that link the code is static HTML. I want to update it to make it dynamic via the following code. I already have the first image grabbing code working when it receives markdown. I'd like to use that code to grab the first image from the post here too, but by the time the code gets it the markdown has been turned into HTML.
Include file timely.html
{% assign workingPost = nil %}
{% for page in site.posts %}
{% if page.title == 'We Convert All Dollars To Bitcoin' %}
{% assign workingPost = page %}
{% endif %}
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
<div class="panel-body">
<a href="{{workingPost.url}}">
{% assign workingPostContent = workingPost.content %}
{% include first-post-image-src2.html param=workingPostContent %}
<img src="{% include first-post-image-src2.html param=workingPostContent %}" alt="{{workingPost.title}}">
<p>{{workingPost.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p>
<br>
<br>
</a>
</div>
</div>
include file first-post-image-src2.html
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}
Yes translating from markdown to html is one of the first thinks made when Jekyll build. So, no way to grab the markdown in an include. The only way to bypass this limitation is to do it with a plugin. But it's not the subject.
Now back to you code. It's to complicated and fragile.
Jekyll has all the needed functionalities to do what you want to do. Don't try to do data processing with liquid. Use the tags and filters and you will not have to fear a Gem upgrade that will break your site and bring you to a really difficult debugging.
eg : somewhere in your code, you're processing a string with a | split:"/>" filter that rely on how kramdown is rendering ìmg tag. If one day they decide to remove this useless closing slash, your code will break.
The way you can go : put all the datas in your post, in the simplest form possible, and then use them with simple Jekyll tags and filter.
The idea is to use yaml Front Matter custom variables and Jekyll post or page excerpt functionalities.
In your _config.yml, define a new excerpt separator :
excerpt_separator: "<!-- excerpt end -->" # default is "\n\n" = two new lines
In all your posts :
---
excerpt_image_src: "/images/dollarsToBitcoins.jpg"
excerpt_image_alt: "Bitcoin Bulls converts dollars to bitcoins."
popular : true # I'll explain that latter
---
Bitcoin Bulls customers pay in USD but those dollars are all converted to bitcoin.
<!-- excerpt end -->
Bulls, I'm excited to announce...
In default.html
{% if page.is_post %}
<link rel="alternate" type="application/atom+xml" title="{{ site.name }} — Atom" href="{{ site.url }}/blog/feed.atom" />
<meta property="og:image" content="{{ site.url }}{{ page.excerpt_image_src | strip_newlines }}" />
<meta property="og:description" content="{{page.excerpt}}" />
{% else %}
In _includes/timely.html :
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
{% for p in site.posts %}{% if p.popular == true %}
<div class="panel-body">
<a href="{{p.url}}">
<img src="{{p.excerpt_image_src}}" alt="{{excerpt_image_alt}}">
<p>{{p.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</div>
{% endif %}{% endfor %}
</div>
Note the {% if p.popular == true %} that filter posts with a front matter variable popular: true.
In _includes/blog-post.html :
<li>
<a href="{{ post.url }}">
<p>{{post.date | date: "%B %d, %Y" }}</p>
<img src="{{post.excerpt_image_src}}" alt="{{post.excerpt_image_alt}}">
<!-- No need to wrap excerpt in <p> tag, Jekyll does it.
If you want to put your own tag :
<div>{{ post.excerpt | strip_html }}</div> -->
{{ post.excerpt }}
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</li>
In _layouts/post.html :
<h1>{{page.title}}</h1>
<div style="color:#666;">by David Smith on {{page.date | date: "%B %d, %Y" }}</div>
{% if page.excerpt_image_src %}
<p><img src="{{page.excerpt_image_src}}" alt="{{page.excerpt_image_alt}}"></p>
{% endif %}
{{ page.content | remove: page.excerpt | markdownify }}
<br>
As you're not actually displaying post excerpt in post page, it's {{ page.content | remove: page.excerpt | markdownify }}. If you want to display excerpt it's : {{ page.content | markdownify }}
I don't know why but page.content return mardown and not html, so the filter | markdownify to transform markdown to html.
Et voila ! Long live Bitcoinbulls !
The markdown isn't available. It is rendered earlier and not available.
From this answer it sounds like the markdown isn't available.
In my case I made my first-post-image-src2.html include handle the case where it gets markdown or HTML like this:
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% if include.param contains '![' %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if foundImageAgain ==0 %}
{% assign imagesAgain = include.param | split:"<img" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains 'src="' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:'src="' %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:'"' | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}

Breadcrumbs in liquid

I am trying to add breadcrumbs for my product pages on an ecommerce store. I need some help with the liquid syntax.
I want to include the first product tag as a part of the breadcrumb, unless the tag is 'stickers', 'stationery', or 'accessories', in which case I would like to use the second tag. If the second tag is also either 'stickers', 'stationery', or 'accessories', I would like to use the third tag, and so on.
Perhaps a better way to say this would be: I would like to call the first available tag that isn't either 'stickers', 'stationery', or 'accessories'.
The closest I have gotten is this:
{% if product.tags.first contains 'stickers' or product.tags.first contains 'stationery' or product.tags.first contains 'accessories' %}
<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><span itemprop="title">{% if product.tags.size > 0 %}{% assign words = product.tags.last | split: '-' %}{% for word in words %}{% if word == 'and' %}{{ word }} {% else %}{{ word | capitalize }} {% endif %} {% endfor %}{% endif %}</span></li>
{% else %}
<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><span itemprop="title">{% if product.tags.size > 0 %}{% assign words = product.tags.first | split: '-' %}{% for word in words %}{% if word == 'and' %}{{ word }} {% else %}{{ word | capitalize }} {% endif %} {% endfor %}{% endif %}</span></li>
{% endif %}
This is inelegant, but it works up until a point. The point at which is breaks down is when both the first and last tags fall into one of the categories I wanted to exclude.
As far as I can see, there doesn't seem to be an option to call something like "product.tags.second" (only "first" and "last" seem to work).
I am a little out of my depth and would really appreciate some advice on how to sort this out.
The platform I'm on is Shopify.
Thanks!
Here's a couple of ways you could approach it:
<!-- 1. Loop through the product tags to find the first tag you want included in the breadcrumb -->
{% assign found_tag = false %}
{% assign tag_for_breadcrumb = '' %}
{% for tag in product.tags %}
{% if found_tag == false and tag != 'stickers' and tag != 'stationery' and tag != 'accessories' %}
{% assign tag_for_breadcrumb = tag %}
{% assign found_tag = true %}
{% endif %}
{% endfor %}
{{ tag_for_breadcrumb }}
<!-- 2. Convert the tags array into a string, remove the tags you don't want, and then get the first tag from those remaining -->
{% assign tag_string = product.tags | join: ' ' %}
{% assign filtered_tag_string = tag_string | remove: 'stickers' | remove: 'stationery' | remove: 'accessories' %}
{% assign filtered_tag_array = filtered_tag_string | split: ' ' %}
{{ filtered_tag_array.first }}