Generator plugin doesn't render data - jekyll

I am writing a jekyll plugin to render an alternative layout for my posts in category "portfolio". The files are generated in the partial folder but the data is not rendered. What am I doing wrong?
Generator:
module Jekyll
class PartialGenerator < Generator
def generate(site)
site.categories['portfolio'].each do |post|
site.pages << PartialPage.new(site, site.source, post)
end
end
end
class PartialPage < Page
def initialize(site, base, post)
#site = site
#base = base
#dir = 'partials'
#name = "#{post.id}.html".tr('/','')
self.process(name)
self.read_yaml(File.join(base, '_layouts'), "partial.html")
self.data['page'] = post
end
end
end
The partial.html layout includes <h1>{{ page.title }}</h1> and the generated output is <h1></h1>
I've tried puts(post.title) in the initialize method and it prints the correct titles on the console.

I found the solution myself now.
The data you put into self.data[]is available as property of page in the template/layout.
So self.data[‘test'] = "..." can be accessed through {{page.test}}.
Now my generator includes self.data['page'] = post and I access it in my partial.html as <h1>{{page.post.title}}</h1>.

Related

OperationalError (1366, "Incorrect string value: '\\xE2\\x80\\x8ESen...') MySQL Django

I develop django website on cpanel with MySQL database. I have a function that pull feeds from this website https://travelcommunication.net/feed/ and create an object from that (web scraping using beautifulsoup4).
But when I try to grab the content section, the error appears. But that only happens with certain items, not all.
I try on my local (with sqlite database) and all working fine. I have also tried on heroku (with PostgreSQL database) and all working fine.
Here is my code:
#views.py
def pull_feeds(request, pk):
if request.user.is_superuser:
source = Autoblogging.objects.get(pk=pk)
url = requests.get(source.url)
soup = BeautifulSoup(url.content, "html.parser")
length = source.items
items = soup.find_all('item')[:length]
contents = soup.find_all('content:encoded')[:length]
for i in range(length-1, -1, -1):
content = contents[i].text
title = items[i].title.text
body = content[content.find('<p>'):] #the problem is here .. when i comment this, everything works fine
category = Category.objects.get(pk=source.category.id)
if not Post.objects.filter(title=title).exists():
post = Post(title=title,
body=body, #the problem is here .. when i comment this, everything works fine
category=category)
link = content[content.find('src=')+5:content.find('alt')-2]
img_data = requests.get(link).content
with open('temp_image.jpg', 'wb') as handler:
handler.write(img_data)
with open('temp_image.jpg', 'rb') as handler:
file_name = link.split("/")[-1]
post.cover.save(file_name, files.File(handler))
os.remove("temp_image.jpg")
return redirect("news:autoblogging")
else:
return HttpResponse("Sorry you are not allowed to access this page")
Does anyone know how to fix this error? Thanks.

Last modified date hook to collection

I'm trying to apply this hook to a custom collection:
Hook
Jekyll::Hooks.register :docs, :pre_render do |post|
# get the current post last modified time
modification_time = File.mtime( post.path )
# inject modification_time in post's datas.
post.data['last-modified-date'] = modification_time
end
Collection
collections:
docs:
output: true
But right now the last-modified-date isn't being assigned.
I saw on this comment that using the collection name should work.
I'm trying to order them by date and list them, but right now the field is coming out empty. All my fields on doc where created before setting up the hook, so maybe I need to do something for it to work.
Any ideas?
When does the hook run? (specially for pre-existent files)
How should I set it up to work with a collection?
Try this, it is supposed to output some info in your console when you build or serve you jekyll site locally. This can help to debug.
_plugins/hook-docs-pre-render.rb
Jekyll::Hooks.register :docs, :pre_render do |post|
# debug
puts "Firing :docs, :pre_render from : " + File.basename(__FILE__) + " for : " + post.relative_path
# get the current post last modified time
modification_time = File.mtime( post.path )
# debug
puts "modification_time = " + modification_time.strftime('%A, %B %dth %Y at %l:%M%p')
# inject modification_time in post's datas.
post.data['last-modified-date'] = modification_time
end
Note that hooks are not working on github pages.

Nokogiri Exclude HTML Class

I'm trying to scrape the names of all the people who commented on a post in our Facebook group. I downloaded the file locally and am able to scrape the names of the people who commented plus the people who replied to those comments. I only want the original comments, not the replies... it seems like I have to exclude the UFIReplyList class but my code is still pulling all the names. Any help would be greatly appreciated. Thanks!
require 'nokogiri'
require 'pry'
class Scraper
##all = []
def get_page
file = File.read('/Users/mark/Desktop/raffle.html')
doc = Nokogiri::HTML(file)
# binding.pry
doc.css(".UFICommentContent").each do |post|
# binding.pry
author = post.css(".UFICommentActorName").css(":not(.UFIReplyList)").text
##all << author
end
puts ##all
end
end
Scraper.new.get_page
Traverse ancestors for every .UFICommentActorName element, to reject those contained within a .UFIReplyList element.
#authors_nodes = doc.css(".UFICommentActorName").reject do |node|
# extract all ancestor class names;
# beware of random whitespace and multiple classes per node
class_names = node.ancestors.map{ |a| a.attributes['class'].value rescue nil }
class_names = class_names.compact.map{ |names| names.split(' ') }
class_names = class_names.flatten.map(&:strip)
# reject if .UFIReplyList found
class_names.include?('UFIReplyList')
end
#authors_nodes.map(&:text)

Use ERB to access images NOT asset pipeline

I want to display an dynamically chosen image, thus within the html I call upon the variable #background_img, which contains the url to a specific picture. However, doing
<body style='background-image: url(<%=#background_img%>);'>
simply refuses to display the image for the background. Am I misinterpreting how ERB works, because wouldn't Rails simply precompile the CSS and end up with a working HTML image fetch? Using the Chrome Developer Tools when previewing my app reveals url(), and obviously an empty parameter can't fetch the image.
EDIT:
Just wanted to add that I would rather not have to download the images, but keep the urls I already have prepared.
This is the WeatherMan class:
require 'rest-client'
class WeatherMan
#images within accessible data structures, designed to be expandable
def initialize
#hot = ['https://farm2.staticflickr.com/1515/23959664094_9c59962bb0_b.jpg']
#rain = ['https://farm8.staticflickr.com/7062/6845995798_37c20b1b55_h.jpg']
end
def getWeather(cityID)
response = JSON.parse RestClient.get "http://api.openweathermap.org/data/2.5/weather?id=#{cityID}&APPID=bd43836512d5650838d83c93c4412774&units=Imperial"
return {
temp: response['main']['temp'].to_f.round,
cloudiness: response['clouds']['all'].to_f.round,
humidity: response['main']['humidity'].to_f.round,
windiness: response['wind']['speed'],
condition_id: response['weather'][0]['id'].to_f,
condition_name: response['weather'][0]['main'],
condition_description: response['weather'][0]['description'],
condition_img: response['weather'][0]['icon']
}
end
def getImg(temp)
if temp <= 100 #CHANGE!!!
return #rain[rand(#rain.length)]
elsif temp <= 32
return nil
elsif temp <= 50
return nil
elsif temp <= 75
return nil
elsif temp <= 105
return nil
end
end
end
So sorry about the formatting, on mobile right now.
Now, the controller class:
load File.expand_path("../../data_reader.rb", __FILE__)
load File.expand_path("../../weatherstation.rb", __FILE__)
class PagesController < ApplicationController
def home
# `sudo python /home/pi/Documents/coding/raspberryPI/weatherStation/app/led_blink.py`
server = WeatherMan.new
#outside_data = server.getWeather(4219934)
#sensor_temp = DRead.read_data(File.expand_path('../../data.txt', __FILE__), 'temperature')
#sensor_temp = (#sensor_temp.to_f * (9.0/5) + 32).round(2)
#background_img = server.getImg(#outside_data[:temp])
end
end
The problem seems to be that #background_img is not populated.
The reason for this seems to be your Weatherman class. I will attempt to rectify the issue...
Controller
If you're calling #background_img on your body tag, it means it's accessible at every controller action. Thus, instead of declaring it in a solitary home action, you need to make it available each time you load your views:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_background
private
def set_background
server = WeatherMan.new
#outside_data = server.getWeather(4219934)
#sensor_temp = DRead.read_data(File.expand_path('../../data.txt', __FILE__), 'temperature')
#sensor_temp = (#sensor_temp.to_f * (9.0/5) + 32).round(2)
#background_img = server.getImg(#outside_data[:temp])
end
end
--
Class
The main issue I see is that your class is not giving you a value. I'll attempt to refactor your class, although I can't promise anything:
require 'rest-client'
class WeatherMan
##static = {
hot: 'https://farm2.staticflickr.com/1515/23959664094_9c59962bb0_b.jpg',
rain: 'https://farm8.staticflickr.com/7062/6845995798_37c20b1b55_h.jpg'
}
def getWeather(cityID)
response = JSON.parse RestClient.get weather_url(cityID)
return {
temp: response['main']['temp'].to_f.round,
cloudiness: response['clouds']['all'].to_f.round,
humidity: response['main']['humidity'].to_f.round,
windiness: response['wind']['speed'],
condition_id: response['weather'][0]['id'].to_f,
condition_name: response['weather'][0]['main'],
condition_description: response['weather'][0]['description'],
condition_img: response['weather'][0]['icon']
}
end
def getImg(temp)
#### This should return the image ####
#### Below is a test ####
##static[:hot]
end
private
def weather_url city
"http://api.openweathermap.org/data/2.5/weather?id=#{city}&APPID=bd43836512d5650838d83c93c4412774&units=Imperial"
end
end
--
View
You need to make sure you're getting returned data from your controller in order to populate it in your view.
Because your getImg method is returning nil, you're getting a nil response. I have amended this for now with one of the flickr links you have included in the class.
If you always have a returned image, the following should work:
#app/views/layouts/application.html.erb
<body style='background-image: url(<%= #background_img %>);'>
Because your #background_img is an external URL, the above should work. If you were using a file from your asset_pipeline, you'd want to use image_url etc

How can I store a hash for the lifetime of a 'jekyll build'?

I am coding a custom Liquid tag as Jekyll plugin for which I need to preserve some values until the next invocation of the tag within the current run of the jekyll build command.
Is there some global location/namespace that I could use to store and retrieve values (preferably key-value pairs / a hash)?
You could add a module with class variables for storing the persistent values, then include the module in your tag class. You would need the proper accessors depending on the type of the variables and the assignments you might want to make. Here's a trivial example implementing a simple counter that keeps track of the number of times the tag was called in DataToKeep::my_val:
module DataToKeep
##my_val = 0
def my_val
##my_val
end
def my_val= val
##my_val = val
end
end
module Jekyll
class TagWithKeptData < Liquid::Tag
include DataToKeep
def render(context)
self.my_val = self.my_val + 1
return "<p>Times called: #{self.my_val}</p>"
end
end
end
Liquid::Template.register_tag('counter', Jekyll::TagWithKeptData)