Generating a PDF in Rails with MathJax and wkhtmltopdf - ruby-on-rails

I'm writing a website using Rails 3.2.6 and it needs to be able to display maths formatting on the website. To do this job I am using the mathjax-rails gem which works perfectly rendering the maths on, for example, questions/1. However, I would like the user to be able to download the question containing the maths content as a PDF. I have done a lot of searching and fiddling with my app and the closest I have come to a solution is wkhtmltopdf and the wicked_pdf gem. This works, in that a PDF is created which is saved to the user's computer. However, the maths is not rendered properly because, I presume, mathjax is not actually processing it.
Having done a bit of reading, I thought I found the answer elsewhere where it said to add a delay to the controller to give mathjax a chance to do its magic:
format.pdf do
render :pdf => 'filename',
:javascript_delay=>5000
end
However this doesn't work either and I end up with a PDF covered in things like:
[itex]3H_{2~(g)} + 2N_{2~(g)} ⇌ NH_{3~(g)}[/itex]
Rather than formatted maths. Has anyone got any clues on how I can get this to work?
Thanks in advance.

This is even a bit silly, but have you tried a longer delay?
With wkhtmltopdf this works:
wkhtmltopdf.exe --javascript-delay 15000 http://www.mathjax.org/demos/mathml-samples/ MML.pdf && MML.pdf
This does not work
wkhtmltopdf.exe --javascript-delay 5000 http://www.mathjax.org/demos/mathml-samples/ MML.pdf && MML.pdf
It's the same for the TeX samples as well

I finally solved it like this, the only thing is that I used the cdn instead of the gem:
This is my show action in the controller:
def show
#example = Exam.find(params[:id])
respond_to do |format|
format.html
format.pdf do
render pdf: #exam.name,
template: "exams/show.pdf.erb", // The template that you want to convert to pdf
:javascript_delay=>5000,
locals: {:exam => #exam},
layout: "application-pdf.html.erb"
end
end
end
And inside app/views/layouts/application-pdf.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>MathTest</title>
<meta charset='utf-8' />
<%= stylesheet_link_tag "https://fonts.googleapis.com/icon?family=Material+Icons" %>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
<script type="text/javascript" async
src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
</head>
<body>
<%= yield %>
</body>
</html>
The key is to wrap your pdf template, in my case "exams/show.pdf.erb" in an application layout designed for your pdf, the cdn is loaded in the layout and you just have to give wickedpdf the option to delay the javascript processing so mathjax has enough time to process the page.
Hope it helps.
UPDATE
As Peter Krautzberger mentioned, cdn.mathjax.org is shutting down due to budget issues. The solution would stay the same, you just have to load the mathjax from your project internally or use another cdn. You can fiend some cdn alternatives here: https://www.mathjax.org/cdn-shutting-down/

Related

Trouble rendering some latex syntax in MathJax with Jekyll on github pages

I found that some of latex syntaxes are not rendered with MathJax with Jekyll in my git page.
For example, in this post
this line:
$z = \overbrace{\underbrace{x}\text{real} +\underbrace{iy}\text{imaginary}}^\text{complex number}$
should look like this
Some other latex syntax works well, like this
What should I add to solve this problem? I guess MathJax is not loading the required library (e.g. \usepackage{amsmath} in the above case).
The code of the page is here.
The following code shows the my configuration of matjax.
<script type="text/x-mathjax-config"> MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: "all" } } }); </script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>
Note that in Jekyll's Markdown syntax, underlines are used to indicate italic text, so Jekyll is inserting <em> tags around \text{real} +\underbrace{iy} where the underscores were (notice that the underscores are missing in the output and that the text is in italics). MathJax can't process math that contains HTML tags, so this math equation is skipped.
You need to make sure that Markdown doesn't interfere with your TeX notation. That can be done in several ways. You could use \_ instead of _ in order to prevent the underscores from being interpreted as italics. Alternatively, you could use <span>...</span> around inline math and <div>...</div> around display math, as suggested here.
Just a hunch but looking at the code posted within your question, I think it might be better to keep all the MathJax related stuff within the <script> tags. I write this because I've yet to find the need to wrap anything in a <span>.
Here's what my _includes/mathjax.html file looks like by piecing together two blocks from the docs...
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
processEscapes: true
}
});
</script>
... and this is how I include it...
---
layout: post
title: Some of Thing
---
{%- include mathjax.html -%}
Notes about $ \sum_{Thing} $
Note how the configs are within the same <script> tag as what is doing the sourcing (src="<url-or-path>"),
For completeness a post source to go with rendered post, which uses the $$ way of doing multi-line formatting within the first thirty lines of the source, and then the $ in line way of doing things just after the first code formatted block (within the notes) of the rendered version.
And (for bonus points I suppose), what I think the corrected code might look like from the question.
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript">
MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: "all" } } });
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true
}
});
</script>
One other note worthy thing that I found my tests is that the \( ... \sum_{Thing} ... \), in-line syntax did not trigger whatever pre-parser Jekyll's using to add html tags to such things; in other-words I had to use the $ ... \sum_{Thing} ... $ syntax even before adding any configs for MathJax's srcing.
For those that got this far but wanted to cut-down on the CDN usage for some reason, ya may instead be interested in the other answer that I've posted on getting MathJax and Jekyll to play-nice.
And for those that want some Liquid to JavaScript configuration translation liquid-utilities/includes-mathjax is now available; allows for configuring MathJax via _config.yml and individual post/page FrontMatter.

Change the font size of chart.js with chartkick

first of all, please excuse my english.
I'm a junior developer on Ruby on Rails and I developed an user management application, among other things. I'm working on the last feature that is generating statistics in a PDF using Chartkick and WickedPDF.
But, I have a problem because the generated JS has a very tiny font size. I tried everything, but nothing to do, I can not enlarge this font.
Here is the line that generates one of my graphs :
<%= pie_chart Infosheet.group(:gender).count, library: {FontSize: 90} %>
This generate this code :
<script type="text/javascript">
new Chartkick.PieChart("chart-1", {"man":4}, {"library":{"FontSize":90}});
</script>
But nothing change. I tried lots of other things that I do not have in mind anymore... In my PDF, the graph has a gigantic margin and a tiny font. :/
I despair because I have to return the project next week.
Can someone help me?
thank you very much
EDIT :
This is my statistics in my PDF :
https://i.gyazo.com/c86a39b2a9e529b7551f8654bee838b4.mp4
The font is... really tiny. my statistics have a size of 5000px x 5000px.
Also, nothing changes if I increase the dpi of PDF
RESOLVED :
Finally, I forked chartkick to change the font-size directly into it, as no option was passed.
There you are
<%= pie_chart counters, library: { legend: { position: "left", labels: { fontSize: 26 } } } %>
I think you're passing the attribute with wrong case. Should probably be snakeCase and also try using a pixel size like so:
<%= pie_chart Infosheet.group(:gender).count, library: {fontSize: "50px"} %>
<script type="text/javascript">
new Chartkick.PieChart("chart-1", {"man":4}, {"library":{"fontSize":"50px"}});
</script>
Use this code
<%= pie_chart Infosheet.group(:gender).count, library: {fontSize: 90} %>

Rails 4 + Sass - No background image in production

I know there are alot of similar questions/answers on SO about this, and I have tried at least 7 of the proposed methods. I can display my app's background image locally in a variety of ways. After trying for nearly 40 hours, there seems to be no way to render it in production. It runs on the following:
Ruby 2.1.5
Rails 4.1.8
Puma 2.1 via Amazon Elastic Beanstalk (single instance - no load balancer)
I've tried every combination of config.serve_static_assets=[true|false] and setting RAILS_SKIP_ASSET_COMPILATION to true and false.
Ran rake assets:precompile RAILS_ENV=production
Tried every path I can think of, but it's not finding the background image. One thing I noticed was that precompilation changes the name of the image when it copies to the public/assets directory. (example: "foo.jpg" becomes "foo-ilfajwe8hjsa8erfjsdf.jpg") So I tried copying the original image files to the new public/assets directory, hoping the app would find them there. That didn't work.
I'm thinking it might be how I'm referencing it in my css, because oddly the favicon file displays as does the fonts from my app's "fonts" folder. And both have their names appended to just like the background image.
Here is my application.html.erb..
<!DOCTYPE html>
<html>
<head>
<title>Capstone v1.4.5</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<%= favicon_link_tag 'capstone_icon.png' %>
</head>
<body>
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
<%= render 'navigation' %>
<main>
<%= yield %>
</main>
</body>
</html>
Here is the application.css.sass..
/*
*= require bootstrap.min
*/
#import "bootstrap-sprockets"
#import "bootstrap"
#font-face
font-family: 'Cinzel-Regular'
src: font-url('Cinzel-Regular.ttf')
#font-face
font-family: 'Oxygen'
src: font-url('Oxygen.otf')
html
position: relative
min-height: 100%
body
background-image: image-url("snowy_prairie_bg.jpg")
background-repeat: no-repeat
background-position: center top
font-family: 'Oxygen'
margin: 0 0 95px
The contents of my public directory (after precompilation)
application-6cca23f2f72df0ad7d26279535719396.css
application-6cca23f2f72df0ad7d26279535719396.css.gz
application-fddd9c84ba451526dbd2ef5bf46e494c.js
application-fddd9c84ba451526dbd2ef5bf46e494c.js.gz
bootstrap
capstone_icon-ed6ffe0ae4bbbb56a8b74a4d7ff230cf.png
capstone_icon.png
Cinzel-Regular-59dcda430d3afc3ace221f1835d7fb08.ttf
images
manifest-73d04c0fd1290b15fb280becfcf62b7b.json
Oxygen-1c736bd9242de63cf87c07f0a48c9b5c.otf
Oxygen-Bold-01bc72645c864aa090d57754565ef634.otf
Oxygen-BoldItalic-cfe32a5aedef7b25f8b1efdfcbdbd72a.otf
Oxygen-Italic-2a51c29c8f2bd242ac27e6fb7860f6a1.otf
snowy_prairie_bg-d246fbbe1178a09d38df31be96aee79a.jpg
snowy_prairie_bg.jpg
Am I referencing the image wrong in my css? Again, it renders great locally. Should I be using Passenger instead of Puma? This is not a very small app and I've got alot invested in the database, also hosted on Amazon. But like I said, I'm approaching 40 hours just trying to get this background rendered.
If you have any ideas, please help. I am willing to try anything!
Thank you
FYI - the above bootstraps, fonts, other images and sass styles render perfectly. It's just the background image. Thanks
EDIT: When I go to the page, capstonesavings.com, the following error is shown in the dev. console: Failed to load resource: the server responded with a status of 403 (Forbidden). Do I need to change permissions on something?
OK, SO I THINK I FIXED IT!
Most of the above code is correct, but I changed the following from the above application.css.sass..
Changed
background-image: image-url("snowy_prairie_bg.jpg")
To
background-image: asset-url("snowy_prairie_bg.jpg")
Then, I SSH'ed into the instance (eb ssh) and did the following:
cd /var/app/current
followed by
sudo chmod 755 public/assets/snowy_prairie_bg-d246fbbe1178a09d38df31be96aee79a.jpg
I had tried the above change to the SaSS before, but it didn't work without changing permissions. Thanks to Chrome developer tools, I noticed a (tiny) error flag when the page was rendered. I clicked it and it showed the 403 error that I added in the above edit. This is some stuff that Amazon uses to make things secure, since I guess you can route your log files, etc. to the associated S3 bucket. So that's why I explicitly targeted the image in question when changing the perms. This site isn't going to have a ton of images, but if it did I'd probably take the time to elaborate on the storage within the bucket and set broader perms accordingly.
This saved the day for me. Hope it helps someone else.

JW-Player and Rails 3.2

I'm trying to use JW-Player in my application. Researching the issue a bit, there seems to be several abandoned efforts to produce a gem, and the latest is undocumented. So, here's how I'm going about it:
I downloaded the JW-Player version 6, unzipped and copied the files in my /app/assets/javascripts directory as follows:
app/assets/javascripts/jwplayer/jwplayer.js
app/assets/javascripts/jwplayer.html5.js
app/assets/javascripts/jwplayer.flash.swf
In my app/views/layouts/application.html.erb, I have the following:
<head>
<%= javascript_include_tag "/assets/javascripts/jwplayer/" %>
</head>
and in app/views/pages/about.html.erb, I have the following:
<%= jw_player("http://xxxxx/video.mp4",
:width => 200, :height => 110) %>
Here's what happens when I click on the About page link:
Showing xxxxxxxx/app/views/pages/about.html.erb where line #10 raised:
undefined method `jw_player' for #<#<Class:0x007fe77e37c018>:0x007fe780c1f678>
First time user of JW-Player.
When implementing JWPlayer 6.6, we stood before the choice of putting the jwplayer.flash.swf file into the public folder, to make the flash mode work, but it seemed very messy to have the files separated like that. What I did in the end to make it work both on development and production was:
Put all 3 files to vendor/assets/javascripts/jwplayer
Rename jwplayer.js to jwplayer.js.erb
Inside jwplayer.js.erb, update the flash file path config like this (the 1st line with the html5 file path config is just for reference)
j={type:"html5",src:e.base+"jwplayer.html5.js"},
b={type:"flash",src:"<%= asset_path('jwplayer/jwplayer.flash.swf') %>"};
(note that the "e.base+" before the path was removed for the flash file path - that's the trick that allowed working relative paths in the development environemtn)
In my understanding, the JWPlayer license allows modifications like this:
"Adaptations
Publisher shall be permitted to make Adaptations reasonably necessary for the purpose of exercising its rights under these Terms of Service, such as Adaptations to integrate the Products into Publisher’s websites or other properties. All Adaptations created by Publisher are strictly for its own Use and Publisher is prohibited from Distributing any Adaptation it creates. The Company reserves the right to prohibit the Use of any Adaptation in its sole discretion."
I have just finished working on a gem started by choix and improved by mattherick called jwplayer-rails that probably worked in older version of rails. It wasn't working with the assets pipeline but mattherick did a great job at fixing that up and I went on to update JWPlayer to the newest version.
You can see the repository here.
The following instructions are right out of the repo above.
To add this gem to your rails app just add this line to your application's Gemfile:
gem 'jwplayer-rails', :git => 'git://github.com/dutgriff/jwplayer-rails.git'
To use it first include assets on the page
<%= jwplayer_assets %>
Then place a div with JW Player
<%= jwplayer %>
You can pass options to jwplayer helper to customize it:
<%= jwplayer({width: 500, height: 200}) %>
More information for customization could be found here.
It works great for me so far but if you find an issue let me know on here or github.
I've found a solution to this.
The main issue you need to work-around is that jwplayer.js wants to fetch jwplayer.flash.swf and jwplayer.html5.js based on the path of jwplayer.js.
You can see that in Chrome Developer Toolbar for jwplayer.js (with pretty print):
(h.embed.config = function(b) {
var e = {fallback: !0,height: 270,primary: "html5",width: 480,base: b.base ? b.base : j.getScriptPath("jwplayer.js"),aspectratio: ""};
b = j.extend(e, h.defaults, b);
var e = {type: "html5",src: b.base + "jwplayer.html5.js"},
g = {type: "flash",src: b.base + "jwplayer.flash.swf"};
You can use that base property as an undocumented api to tell jwplayer where the jwplayer.flash.swf and jwplayer.html5.js can be found.
Example:
jwplayer("player-id").setup({
width: 640,
height: 480,
file: "www.w3schools.com/html/movie.mp4",
base: "http://cloudfront.net/assets/vendor/jwplayer/"
};
Then it will look for http://cloudfront.net/assets/vendor/jwplayer/jwplayer.flash.swf. Note: jwplayer has no notion of the asset pipeline fingerprint filenames, so make sure you sync both the file with md5 and without.
This worked for me:
Place jwplayer folder in public (Downloaded from longtail video)
Include it like an external script, without using asset pipeline (HAML).
%script{:src => '/jwplayer/jwplayer.js'}
In your video partial (ERB)
<script type="text/javascript">
jwplayer.key="Your key here";
$(document).ready(function(){
jwplayer("video").setup({
height: 360,
width: 640,
playlist: [
<% videos.each do |v| %>
{
image: "<%= v.poster %>",
sources: [
{ file: "<%= v.url %>" },
]
},
<% end %>
]
});
})
</script>
<video id="video">Video Loading... Ensure JavaScript is enabled...</video>
Did you restart the server after downloading the player and including it in your layouts. This could be one reason of failure.
Download jwplayer from http://www.longtailvideo.com/jw-player/download/
Put these files to the particular directory:-
app/assets/jwplayer/jwplayer.flash.swf
vendor/assets/javascripts/jwplayer.js
vendor/assets/javascripts/jwplayer.html5.js
Then add these line in application.js
//= require jwplayer
//= require jwplayer.html5
On the page where you are playing video, add these lines
<script type="text/javascript">jwplayer.key="YOUR_JWPLAYER_KEY";</script>
<div id="video">Loading the player ...</div>
<script type="text/javascript">
jwplayer("video").setup({
flashplayer: "<%=asset_path('jwplayer.flash.swf')%>",
file: "<%= file_path %>",
height: 360,
width: 640,
analytics: {
enabled: false,
cookies: false
}
});
http://account.longtailvideo.com/#/home from where you can get your free self hosted key in signing up from Get Your License Key portion.
I also chose JWplayer.
Here are my steps.
I'm using https://github.com/choix/jwplayer-rails gem.
Added
gem 'jwplayer-rails', '1.0.1'
to my Gemfile.
Did all things from above page; in a show.html.slim view file included these lines:
= jwplayer_assets
br
br
= jwplayer({file:#lesson.media_file})
lesson.media_file attribute contains file location. For a video file project/public/videos/videoclip.webm, media_file contains string "/videos/videoclip.webm".
Hope this will be useful.

How to use Ruby on Rails 3.2 with 'yui 3.5'?

I'm writing write my first RoR application with YUI framework. I tried googling for ror+yui manuals with no success. So I went to YUI site. YUI says:
// Put the YUI seed file on your page.
<script src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js"></script>
Where it's supposed to be putted in RoR app?
I've tried to app/assert/javascripts/yui-min.js.
As a result i got <html class="yui3-js-enabled"> in every page. Supposing YUI is working now i've tried to copy-paste "Work with the DOM" example from YUI's page to app/public/index.html.
The error I received was:
Uncaught ReferenceError: YUI is not defined.
I tried the info in this link and it was not helpful to me:
https://stackoverflow.com/questions/1452829/tutorial-suggestions-on-yui-with-ruby-on-rails
Your first step in any rails app is to delete app/public/index.html ... then work in your pages inside of rails.
So that means create an app/views/layouts/application.html, and that's where you add your
<html>
<head>
<script src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js"></script>
Based on the link, you might not have it in your <head> and it needs to be.
UPDATE: (sample javascript code to change h1)
<script>
YUI().use('node', function (Y) {
var headerElement = Y.one('h1');
headerElement.setHTML("I have been updated");
});
</script>

Resources