List directory in Jekyll - jekyll

How can a directory and its subdirectories be listed to display HTML files using Jekyll?
2020/nov/16.html
2020/nov/18/index.html
2020/nov/22.html
2020/dec/10.html
2020/dec/12.html

You need to can create an custom liquid-filer written in ruby. Create a file named list-content-filter.rb (you can choose any filename, just use .rb as extension, place the file inside your _plugins folder of your jekyll project.
module Jekyll
module ListContent
def echo_folder(folder)
"Your folder: " + folder
end
def list_files(folder, type="*.png")
files = Dir
.glob(folder + "**/" + type)
.select { |e| File.file? e }
.join("<br>")
end
def list_folders(folder)
folders = Dir
.glob(folder + '**/*')
.select { |e| File.directory? e }
.join("<br>")
end
end
end
Liquid::Template.register_filter(Jekyll::ListContent)
The comamnd .join("<br>") will join the array elements with an HTML new line, may replace it with "\n" or any other char.
The last line of the plugin script, will register ListContent as a global filter. To use the filter write {{ "my-folder/" | list_files: < List of parms> }} in your markdown file.
The filter offers three functions echo_folder, list_files (with type as optional parameter; default is "*.png") and list_folders. Define the fuction after the |.
# List content of `assets` folder
Echo just the folder
{{ "assets/" | echo_folder }}
<hr>
List `png`-files (omit parameter, use default type) from `assets` folder (recursive)
{{ "assets/" | list_files }}
<hr>
List `svg`-files from `assets` folder (recursive)
{{ "assets/" | list_files: "*.svg" }}
<hr>
List `subfolders` from `assets` folder (recursive)
{{ "assets/" | list_folders }}
In your case replace assets/ with 2020 and the type with *.html
{{ "2020/" | list_files: "*.html" }}

Related

Unable to read Pillar having array with dictionary structure using Jinja

I am trying to read an array of dictionary present in my salt pillar file inside my state sls file, but unable to read.
root#xxxxxxx:/srv/salt# salt-master --version
salt-master 3003.3
I am having pillar file as below:
Pillar File:
common:
sysctl.net.core.netdev_max_backlog: 16384
sysctl.net.core.optmem_max: 25165824
sysctl.net.core.rmem_max: 33554432
sysctl.net.core.somaxconn: 16384
deploy2:
packages:
- repo_name: xxxxxxxx
tag: xxxxxx
path: /tmp/sp_repo_1
- repo_name: xxxxxx
tag: sxxxxxx
path: /tmp/sp_repo_2
My state file as below:
{% for package in salt.pillar.get('deploy2:packages') %}
print my data:
cmd.run:
- name: "echo {{ package.repo_name }}"
{% endfor %}
Error:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:
Data failed to compile:
----------
Rendering SLS 'base:test' failed: while constructing a mapping
in "<unicode string>", line 3, column 1
found conflicting ID 'print my data'
in "<unicode string>", line 9, column 1
The ID of the states being run in context of an execution should be unique.
As you are iterating over an array of dictionaries having two elements, it creates two state IDs as print my data, which is not allowed. To avoid this, we need to use some element of the dict in the ID itself so that it is unique.
Example:
{% for package in salt.pillar.get('deploy2:packages') %}
print-my-{{ package.repo_name }}:
cmd.run:
- name: "echo {{ package.repo_name }}"
{% endfor %}
This will create 2 unique IDs - print-my-xxxxxxxx and print-my-xxxxxx. You could use package.tag or any such key which has unique values.

Trouble while extending CKAN template

I was extending a ckan template as per:
http://docs.ckan.org/en/latest/theming/templates.html
So when I add {% ckan_extends %} in an empty index.html file in my extension to use the original index.html I get the following exception and traceback(My debug is set to true):
WebError Traceback:
⇝ ValueError: invalid literal for int() with base 10: ''
View as: Interactive (full) | Text (full) | XML (full)
Module ckan.controllers.home:88 in index view
>> return base.render('home/index.html', cache_force=True)
Module ckan.lib.base:174 in render view
>> return cached_template(template_name, render_template)
Module pylons.templating:249 in cached_template view
>> return render_func()
Module ckan.lib.base:128 in render_template view
>> return render_jinja2(template_name, globs)
Module ckan.lib.base:85 in render_jinja2 view
>> return template.render(**extra_vars)
Module jinja2.environment:989 in render view
>> return self.environment.handle_exception(exc_info, True)
Module jinja2.environment:748 in handle_exception view
>> traceback = _make_traceback(exc_info, source_hint)
Module jinja2.debug:140 in make_traceback view
>> return translate_exception(exc_info, initial_skip)
Module jinja2.debug:182 in translate_exception view
>> lineno = template.get_corresponding_lineno(tb.tb_lineno)
Module jinja2.environment:1056 in get_corresponding_lineno view
>> for template_line, code_line in reversed(self.debug_info):
Module jinja2.environment:1072 in debug_info view
>> self._debug_info.split('&')]
ValueError: invalid literal for int() with base 10: ''
Help needed.

Concatenate arrays in liquid

I am trying to concatenate three arrays in liquid/jekyll but in the final array (publications) I get only the elements of the first one (papers)
{% assign papers = (site.publications | where:"type","paper" | sort: 'date') | reverse %}
{% assign posters = (site.publications | where:"type","poster" | sort: 'date') | reverse %}
{% assign abstracts = (site.publications | where:"type","abstract" | sort: 'date') | reverse %}
{% assign publications = papers | concat: posters | concat: abstracts %}
What am I missing?
New answer
Jekyll now uses Liquid 4.x. So we can use the concat filter !
Old answer
concat filter is not part of current liquid gem (3.0.6) used by jekyll 3.2.1.
It will only be available in liquid 4 (https://github.com/Shopify/liquid/blob/v4.0.0.rc3/lib/liquid/standardfilters.rb#L218).
I will probably be available for Jekyll 4.
In the meantime, this plugin can do the job :
=begin
Jekyll filter to concatenate arrays
Usage:
{% assign result = array-1 | concatArray: array-2 %}
=end
module Jekyll
module ConcatArrays
# copied from https://github.com/Shopify/liquid/blob/v4.0.0.rc3/lib/liquid/standardfilters.rb
def concat(input, array)
unless array.respond_to?(:to_ary)
raise ArgumentError.new("concat filter requires an array argument")
end
InputIterator.new(input).concat(array)
end
class InputIterator
include Enumerable
def initialize(input)
#input = if input.is_a?(Array)
input.flatten
elsif input.is_a?(Hash)
[input]
elsif input.is_a?(Enumerable)
input
else
Array(input)
end
end
def concat(args)
to_a.concat(args)
end
def each
#input.each do |e|
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
end
end
end
end
end
Liquid::Template.register_filter(Jekyll::ConcatArrays)

How to include a script (variables, functions etc.) from another file for windows and linux?

First file named first.lua has:
var1 = 1
var2 = 2
var3 = 3
function first(var4)
print(var4)
return true
end
Second file named second.lua should have:
if var1 == 1 and var2 == 2 and var3 == 3 then
first('goal')
end
How to include these variables and function on windows and linux? In PHP i use require or include a path file, but in lua? Thanks.
Assuming the two files are in the same directory, the variables you want to access should be global OR returned
First Way
FILE 1 named first.lua
variable1 = "YOU CAN SEE ME !"
local variable2 = "YOU CANNOT !"
FILE 2 named second.lua
require("first") --> If file first.lua is in directory directName existing in the same area
--> as the file second.lua, use "directName/first"
--> if it's in the folder outside the current one, you can
--> do ../first and so on it goes
print(variable1) --> This will print : YOU CAN SEE ME
print(variable2) --> This will print nil because variable2 does not exist in file2, it is local
Second Way
Using this one, you can simply return a table at the end of the file
FILE 1 named first.lua
local to_access = {}
to_access.variable1 = "HALLALOUJA"
local impossible_to_get = "Hello"
return to_access --> Note this return is very important
File 2 named second.lua
accessed = require("first") --> or the path you use, without having .lua ofcourse
print ( accessed.variable1 )--> This will print "HALLALOUJA"!
print ( impossible_to_get )--> Dear ol' nil will be printed

batch convert HTML to Markdown

I have a whole lot of html files that live in one folder. I need to convert these to markdown I found a couple gems out there that does this great one by one.
my question is...
How can I loop though each file in the folder and run the command to convert these to md on a separate folder.
UPDATE
#!/usr/bin/ruby
root = 'C:/Doc'
inDir = File.join(root, '/input')
outDir = File.join(root, '/output')
extension = nil
fileName = nil
Dir.foreach(inDir) do |file|
# Dir.foreach will always show current and parent directories
if file == '.' or item == '..' then
next
end
# makes sure the current iteration is not a sub directory
if not File.directory?(file) then
extension = File.extname(file)
fileName = File.basename(file, extension)
end
# strips off the last string if it contains a period
if fileName[fileName.length - 1] == "." then
fileName = fileName[0..-1]
end
# this is where I got stuck
reverse_markdown File.join(inDir, fileName, '.html') > File.join(outDir, fileName, '.md')
Dir.glob(directory) {|f| ... } will loop through all files inside a directory. For example using the Redcarpet library you could do something like this:
require 'redcarpet'
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true)
Dir.glob('*.md') do |in_filename|
out_filename = File.join(File.dirname(in_filename), "#{File.basename(in_filename,'.*')}.html")
File.open(in_filename, 'r') do |in_file|
File.open(out_filename, 'w') do |out_file|
out_file.write markdown.render(in_file.read)
end
end
end