Custom filename for generated file in Jekyll - jekyll

In my _config.yml file I have defined the permalink like permalink: /posts/:title/ (notice the ending slash).
For a post in _posts/my_first_post/2017-05-06-my_first_post.markdown the generated file is _site/posts/my_first_post/index.html.
How can I change the filename from index.html to something arbitrary like something.htm?
Edit 1:
Didn't want to do this, but I ultimately had to look at the Jekyll source code:
In the lib/jekyll/page.rb there is this:
def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index") if url.end_with?("/")
path << output_ext unless path.end_with? output_ext
path
end
And in lib/jekyll/document.rb there is this:
def destination(base_directory)
dest = site.in_dest_dir(base_directory)
path = site.in_dest_dir(dest, URL.unescape_path(url))
if url.end_with? "/"
path = File.join(path, "index.html")
else
path << output_ext unless path.end_with? output_ext
end
path
end
So the index.html part is hardcoded. This question cannot be answered...unless there is a plugin that does what I want.

Create a plugin and monkey patch those classes
Create _plugins/_my_custom_index.rb
module Jekyll
class Page
def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index") if url.end_with?("/")
path << output_ext unless path.end_with? output_ext
# replace index with title
path.sub! 'index', data['title'] if data['title']
path
end
end
end
module Jekyll
class Document
def destination(base_directory)
dest = site.in_dest_dir(base_directory)
path = site.in_dest_dir(dest, URL.unescape_path(url))
if url.end_with? "/"
path = File.join(path, "index.html")
else
path << output_ext unless path.end_with? output_ext
end
# replace index with title
path.sub! 'index', data['title'] if data['title']
path
end
end
end

You can adjust the code of Jekyll to your specific requirement.
Open lib\jekyll\Page.rb in jekyll folder and update the destination method:
module Jekyll
class Page
def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index") if url.end_with?("/")
path << output_ext unless path.end_with? output_ext
# replace index with title
path.sub! 'index', data['title'] if data['title']
path
end
end
end
Also update the destination method in lib\jekyll\Document.rb with the same line before returning path

You can use permalink: /posts/:title/something:output_ext in the _config.yml or in post front matter

You can change to permalink /posts/:title/:title.html
However, the post will be now accessible via http://server/post/my_first_post/my_first_post.html
If you want to change the default behavior, you should modify Jekyll.Page.destination

Related

Prevent jekyll from cleaning up generated JSON file?

I've written a simple plugin that generates a small JSON file
module Jekyll
require 'pathname'
require 'json'
class SearchFileGenerator < Generator
safe true
def generate(site)
output = [{"title" => "Test"}]
path = Pathname.new(site.dest) + "search.json"
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write("---\nlayout: null\n---\n")
f.write(output.to_json)
end
# 1/0
end
end
end
But the generated JSON file gets deleted every time Jekyll runs to completion. If I uncomment the division by zero line and cause it to error out, I can see that the search.json file is being generated, but it's getting subsequently deleted. How do I prevent this?
I found the following issue, which suggested adding the file to keep_files: https://github.com/jekyll/jekyll/issues/5162 which worked:
The new code seems to avoid search.json from getting deleted:
module Jekyll
require 'pathname'
require 'json'
class SearchFileGenerator < Generator
safe true
def generate(site)
output = [{"title" => "Test"}]
path = Pathname.new(site.dest) + "search.json"
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write("---\nlayout: null\n---\n")
f.write(output.to_json)
end
site.keep_files << "search.json"
end
end
end
Add your new page to site.pages :
module Jekyll
class SearchFileGenerator < Generator
def generate(site)
#site = site
search = PageWithoutAFile.new(#site, site.source, "/", "search.json")
search.data["layout"] = nil
search.content = [{"title" => "Test 32"}].to_json
#site.pages << search
end
end
end
Inspired by jekyll-feed code.

Issue with Compass/Sass config.rb

I am trying to update my asset directories within my scss config.rb file. I need to access compass mixins such as height: image-height($image); For this to work, my images path has to be relative to my project’s image directory, defined in your config.rb file. However, I cannot get this to work. I have used the compass url_helpers but nothing seems to be changing. No matter how I update the assets in my config.rb, the following is returned when declaring an image variable in my scss..."No such file or directory # rb_sysopen - /private/var/www/websites/gc/app/sites/all/themes/merge/scss/../images/../search-b-image.jpg" Where is this ../images/.. coming from if its not in my config.rb? Any help is much appreciated.
config.rb file is:
http_path = "/"
css_dir = "compiled_css"
sass_dir = "scss"
images_dir = "img"
javascripts_dir = "js"
environment = :development
relative_assets = true
output_style = :expanded
output_style = :compressed
preferred_syntax = :scss

Opening multiple html files & outputting to .txt with Nokogiri

Just wondering if these two functions are to be done using Nokogiri or via more basic Ruby commands.
require 'open-uri'
require 'nokogiri'
require "net/http"
require "uri"
doc = Nokogiri.parse(open("example.html"))
doc.xpath("//meta[#name='author' or #name='Author']/#content").each do |metaauth|
puts "Author: #{metaauth}"
end
doc.xpath("//meta[#name='keywords' or #name='Keywords']/#content").each do |metakey|
puts "Keywords: #{metakey}"
end
etc...
Question 1: I'm just trying to parse a directory of .html documents, get the information from the meta html tags, and output the results to a text file if possible. I tried a simple *.html wildcard replacement, but that didn't seem to work (at least not with Nokogiri.parse(open()) maybe it works with ::HTML or ::XML)
Question 2: But more important, is it possible to output all of those meta content outputs into a text file to replace the puts command?
Also forgive me if the code is overly complicated for the simple task being performed, but I'm a little new to Nokogiri / xpath / Ruby.
Thanks.
I have a code similar.
Please refer to:
module MyParser
HTML_FILE_DIR = `your html file dir`
def self.run(options = {})
file_list = Dir.entries(HTML_FILE_DIR).reject { |f| f =~ /^\./ }
result = file_list.map do |file|
html = File.read("#{HTML_FILE_DIR}/#{file}")
doc = Nokogiri::HTML(html)
parse_to_hash(doc)
end
write_csv(result)
end
def self.parse_to_hash(doc)
array = []
array << doc.css(`your select conditons`).first.content
... #add your selector code css or xpath
array
end
def self.write_csv(result)
::CSV.open("`your out put file name`", 'w') do |csv|
result.each { |row| csv << row }
end
end
end
MyParser.run
You can output to a file like so:
File.open('results.txt','w') do |file|
file.puts "output" # See http://ruby-doc.org/core-2.1.2/IO.html#method-i-puts
end
Alternatively, you could do something like:
authors = doc.xpath("//meta[#name='author' or #name='Author']/#content")
keywrds = doc.xpath("//meta[#name='keywords' or #name='Keywords']/#content")
results = authors.map{ |x| "Author: #{x}" }.join("\n") +
keywrds.map{ |x| "Keywords: #{x}" }.join("\n")
File.open('results.txt','w'){ |f| f << results }

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

RSpec - how to exclude spec files in subdirectory?

Say I have the following spec subdirectories:
lib
models
observers
workers
In the spec_helper.rb file, how do I tell rspec to exclude all spec files in the lib subdirectory?
Spork.prefork do
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run :focus => true
end
end
Spork.each_run do
FactoryGirl.reload
end
FYI - I'm using guard to auto-reload tests.
Not sure how to exclude but you can include a list in guard like this:
guard 'rspec', :spec_paths => ['spec/models', 'spec/workers', 'spec/observers'] do
# ...
end
One solution is Exclusion Filters:
RSpec.configure do |c|
# declare an exclusion filter
c.filter_run_excluding :broken => true
end
describe "something" do
it "does one thing" do
end
# tag example for exclusion by adding metadata
it "does another thing", :broken => true do
end
end
exclusion flag can be applied to describe and context too.
Also, this is useful config option:
RSpec.configure do |c|
c.run_all_when_everything_filtered = true
end
So if everything in /lib is excluded, you will still be able
to run specs manually with rspec spec/lib/