HAML::Engine, image is not rendering - ruby

I am using just Ruby (no rails) to make a gem that takes a yaml file as an input an it produces a pdf.
I am using pdfKit and Haml. In the haml file I need to render an image. When using pure HTML, PDFKit shows the image, but when using Haml::Engine and the haml file the image doesn't get rendered.
I have put the image, the .module and the haml file under one folder to make sure the issue is not the path.
In my gemspec I have the following
.
.
gem.add_development_dependency("pdfkit", "0.8.2")
gem.add_development_dependency("wkhtmltopdf-binary")
gem.add_development_dependency("haml")
The HTML that works:
<html>
<head>
<title>
junk
</title>
</head>
<body>
HI
<img src="watermark.png"/>
Bye
</body>
</html>
Haml version that doesn't work:
%html
%head
%title
junk
%body
HI
= img "watermark.png"
Bye
module:
require "pdfkit"
require "yaml"
require "haml"
require "pry"
.
.
junk = Haml::Engine.new(File.read("lib/abc/models/junk.haml")).render
kit2 = PDFKit.new(junk)
kit2.to_file("pdf/junk.pdf")
when using the html file, pdf renders the image, however, when I use the haml this is now my pdf looks like
and If I use
%img(src="watermark.png")
I get the following error when pdf is generated
Exit with code 1 due to network error: ContentNotFoundError
The PDF still gets generated, but the still looks like the image above.
So I am trying to see without using any rails, and img_tag, image_tag etc.. how would I just use the %img in haml file to render the proper image
Following is the output of junk, when I create #img = "watermark.png"
1 pry(DD)> junk
=> "<html>\n<head>\n<title>\njunk\n</title>\n</head>\n<body>\nHI\n<img src='watermark.png'>\nBye\n</body>\n</html>\n"
Replace the img tag %img(src=#img) still same result

I think this is not HAML issue, but wkhtmltopdf thing. Apparently it's not very good at handling relative urls to images. It should work with absolute path, for example:
%img(src="/home/user/junk/watermark.png")

To create an image tag in HAML you will need to use
%img(src="foo.png")
# or
%img{src: "foo.png"}
If you use
= img "watermark.png"
then you are calling the img method (if it exists), passing it "watermark.png" as argument and outputting the return value of that method in the generated HTML.
Honestly i'm not sure how that HTML template should work, when the HAML template that generates the same HTML does not. So I guess you run that script from different directories or so?
Anyways: Problem is, that you will need absolute paths for your files. Otherwise wkhtmltopdf will not be able to resolve your images.
You can use File.expand_path (see sample) for this, or write a custom helper.
I tried following:
Created two files:
/tmp/script.rb
/tmp/watermark.png
/tmp/template.haml
Where watermark.png is a screenshot I took from this question, script.rb is:
require "pdfkit"
require "haml"
template = File.read("template.haml")
html = Haml::Engine.new(template).render
File.write("template.html", html)
pdf = PDFKit.new(html)
pdf.to_file("output.pdf")
And template.haml is:
%html
%head
%title Something
%body
BEFORE
%img(src="#{File.expand_path(__dir__, "watermark.png")}")
AFTER
When I run this script like:
ruby-2.5.0 tmp$ ruby script.rb
Then the HTML that is generated is:
<html>
<head>
<title>Something</title>
</head>
<body>
BEFORE
<img src='/tmp/watermark.png'>
AFTER
</body>
</html>
And the generated PDF looks like:

Related

Injecting base directory to RDiscount Markdown conversion

I am using Ruby's RDiscount to convert markdown to HTML.
The markdown documents contain links (or images) that are relative to the path of the markdown file itself.
Is there a way for me to tell RDiscount that it should prepend all relative links with a string (folder) of my choice?
I am trying to achieve an effect similar to how GitHub shows images in README - where the files are looked for in the same directory as the README.
Here is an example code:
require 'rdiscount'
markdown = "![pic](image.png)\n\n[link](somewhere.html)"
doc = RDiscount.new(markdown)
# I would like to do something here, like:
# doc.base_link_path = 'SOMEFOLDER'
html = doc.to_html
puts html
# actual output =>
# <p><img src="image.png" alt="pic" /></p>
# <p>link</p>"
# desired output =>
# <p><img src="SOMEFOLDER/image.png" alt="pic" /></p>
# <p>link</p>"
I looked at the RDiscount class documentation but did not find anything like this.

Using Ruby and Sinatra, Is it possible to use HAML in an "internal" or "inline" manner?

I've done gem install sinatra and gem install haml
And I have this .rb file
require 'sinatra'
get '/abc2' do
"<b>aaaaaaaaaaaaa</b>"
end
Now say I want that line of HTML but in HAML. and not externally
I know I can do
get '/abc' do
haml :index # /views/index.haml
end
And index.haml could have a line of haml %b aaaaaaa
But is there any way that I can include %b aaaaaaa in my ruby file itself and have it rendered. Without having to refer to a file e.g. without having to refer to /views/index.haml ?
Like CSS lets you have the CSS External, or it lets you have it internal within the html file.. Similarly, Javascript lets you import javascript externally, or it lets you have it internal to the html file.. Well i'm asking about using HAML internally to the .rb file. Is it possible?
I know HAML is intended as a template language for injecting data into.. but it is also a shorthand for writing HTML more concisely.
For small apps you can add the views at the end of your script so there are no external files.
get '/abc' do
haml :hello
end
__END__
## hello
%h1= "Hello there"
You should be able to use Haml::Engine#render to convert the Haml to HTML like so:
get '/abc2' do
Haml::Engine.new(<<-Haml).render(binding)
%b aaaaaa
Haml
end
This uses a heredoc (everything between the <<-Haml line and the closing Haml. binding is a special variable that basically refers to the current scope.

Using Redcarpet Gem with .erb file

I am trying to pull up a markdown file from a database that I created. My server. rb file has the following:
get "/designers/:id" do
id = params[:id]
#content = conn.exec_params("SELECT * FROM articles_info WHERE id = $1",[id]).first
erb :raf
end
In that table is the following markdown information:
# **RAF SIMONS**
*THIS IS THE RAF SIMONS BIO* :blush:
*[Raf Link](http://rafsimons.com/)*
The .erb file works when I have plain text or the following in it:
<%= "#{#content["content"]}" %>
However it only prints the actual .md text as it is. So I have tried using Redcarpet to render the markdown file. The code is as follows in my .erb:
renderer = Redcarpet::Render::HTML.new
markdown = Redcarpet::Markdown.new(renderer)
<%= markdown.render(#content.content) %>
But I am getting the error:
ArgumentError at /designers/1
wrong number of arguments (0 for 1..3)
Which is stemming from the <%= line. I thought at first that the syntax was wrong, so I tried:
markdown.render <%= "#{#content["content"]} %>
However that did not change anything. I also tried adding in a method in the server.rb file, but that gave me more errors. I read through the entire documentation: https://github.com/vmg/redcarpet file but am not understanding where the error is coming from. Is it possible that I need extensions in order to make it work? I also tried:
markdown = Redcarpet::Markdown::new(renderer, extensions={})
But that didn't change anything. Not sure what else to try here! I know that it is tricky but I thought I had a handle on it and have now tried many different iterations and still am having trouble executing it. Any advice would be much appreciated!

Explain to me a Sinatra setup for dummy's for a preview of html/css code

A word of warning up front: I do not know even the ruby basics, but I'm trying to learn more and more of the world of shell scripting this year.
I saw this Vimeo video of Ben Schwarz and immediately thought that I'd like to use such a tool to debug my sass and haml files.
So this is a call to help me to grasp the concept of Sinatra.
What I want is a simple way to output the code of my index.html to check if all the haml magic was applied correctly - so it should function as a source viewer that gives me live updates. I'd prefer it if Sinatra simply looked at the files that LiveReload already rendered (c.f. index.html) in my project folder.
Update: This is a screenshot of the Vimeo Video. It shows just the raw CSS output of a Sass file. This is what I'd like to have for my Haml and Sass code, or better for the output files that are already rendered by LiveReload as HTML and CSS.
I looked at the source file from #benschwarz at his github, but I wasn't even with his own example I'm only getting the standard: "Sinatra doesn’t know this ditty." So transferring this to work with html is still out of my reach.
What I did so far:
I setup my project as usual in ~/Sites/projectname
I setup RVM and install all the gems I need
Sass, Compass, Haml - the output gets compiled via LiveReload
Sinatra
I created myapp.rb in ~/Sites/projectname with the following content:
# myapp.rb
require 'sinatra'
set :public_folder, '/'
get '/' do
File.read(File.join('public', 'index.html'))
end
Whatever, I fired up Sinatra and checked http://localhost:4567/ – this didn't work because I do not know how to set the public_folder to ~/Sites/projectname.
Afterthoughts:
So I went on to search the net, but my limited knowledge of Ruby put my attempt of an successful research to an immediate halt.
Here are some sites I stumpled upon which are obvioulsy close to the solution I need, but… like I told you in the first sentence: if the solution was a book, I'd need the "For Dummies" version.
https://bitbucket.org/sulab/genelist_store/src/30fc0ba390b9/idea8/idea8.rb
Serving static files with Sinatra
http://www.sinatrarb.com/intro
Obvioulsy the reference documentation of Sinatra would help me, but I don't speak the language, hence, I don't get the lingo.
About public folder:
The public_folder is relative to your app file myapp.rb. If you have a public folder inside the projectname folder, this is your public folder. If you have your css, js and image files in another folder, say, includes under project_name, then you need to change the line:
# Actually, you need to remove the line above from myapp.rb as it is.
# The line means that the public folder which is used to have css, js and
# image files under '/' and that means that even myapp.rb is visible to everyone.
set :public_folder, '/'
# to:
set :public_folder, File.dirname(__FILE__) + '/includes'
And that will serve up css, js and/or image files from the project_name/includes folder instead of project_name/public folder.
Reading the html file:
Reading the html files does not depend on the public folder settings. These need not be inside the public folder.
get '/' do
File.read(File.dirname(__FILE__) + '/index.html')
# This says that the app should read the index.html
# Assuming that both myapp.rb and index.html are in the same folder.
# incase the html files are inside a different directory, say, html,
# change that line to:
# File.read(File.dirname(__FILE__) + '/html/index.html')
# Directory structure sample:
# project_name
# | - myapp.rb
# | - index.html (and not html/index.html etc.)
# | /public (or includes incase the css, js assets have a different location)
# | | /css
# | | /js
# | | /images
end
To get the html output inside the browser
After the file is read, typically, this will be your string: "<html><head></head><body></body></html>"
Without escaping the string, the browser renders the html string as html (no pun) and that's why you won't see any text. To escape the html, you can use the CGI class provided by Ruby (hat tip). So, in the end, this will be your snippet:
get '/' do
CGI::escapeHTML(File.read(File.dirname(__FILE__) + 'index.html'))
end
But that will spit out the html file in a single line. To clean it up,
# myapp.rb
get '/' do
#raw_html = CGI::escapeHTML(File.read(File.dirname(__FILE__) + 'index.html'))
end
# Using inline templates to keep things simple.
# get '/' do...end gets the index.erb file and hence, in the inline template,
# we need to use the ## index representation. If we say get '/home' do...end,
# then the inline template will come under ## home. All the html/erb between
# two "##"s will be rendered as one template (also called as view).
# The <%= #raw_html %>spews out the entire html string read inside the "get" block
__END__
## index
<html>
<head></head>
<body>
<pre>
<%= #raw_html %>
</pre>
</body>
</html>
If you're trying to render an index.html file, I would try storing it in the /views directory with an .erb extension. Or use an inline template. Here is a great resource

gather all links to *.txt files

I need to retrieve all the links to text files in an HTML document, I don't know what the best way to do this is but, I have tried the following in ruby...
line.scan(/<a href="([\w+:\/.-]*.txt)/)
but I am not sure if this expression covers all possible links pointing to text file, I am wondering if there are some built-in regular expressions for this? or if anyone knows of a better way to retrieve all links to a text file in a huge webpage.
This will walk through the HTML and find all hrefs with a '.txt' extension:
#!/usr/bin/env ruby
require 'nokogiri'
html = <<EOT
<html>
<head><title>foo</title></head>
<body>
text file
jpg file
text file 2
</body>
</html>
EOT
doc = Nokogiri::HTML(html)
puts doc.search('a').select { |n| n['href'][/\.txt$/] }.map{ |n| n['href'] }
> file.txt
> file2.txt
It's using Nokogiri to parse the content, which really is a lot more bullet-proof than trying to use regex.
Try this (captures all txt files, not just links):
html.scan(/[^\s"']+\.txt/)
To capture links to text files only:
html.scan(/<a [^<>\n]*?href=["']([^\s"']+\.txt)["'][^<>\n]*?>.*?<\/a>/m)

Resources