wicked_pdf (with wkhtmltopdf) doesn’t render Font Awesome icons - css

I’m trying to convert an existing html document with Font Awesome icons included in pdf. I use wicked_pdf for this task. But obviously is creating a pdf some very hard task.
All Font Awesome Icons are replaced with blanks. I need some advise to make things work.
My configuration:
wicked_pdf (1.1.0)
wkhtmltopdf-binary-edge (0.12.4.0)
The generated html looks like this:
<p>
<i class="fa fa-phone"></i> +49 123 4567890
</p>
The controller action for creating the pdf:
def create_pdf
#presenter = PortfolioPDFPresenter.new(#portfolio, self)
html = render_to_string(template: 'portfolios/pdf_templates/portfolio',
layout: 'pdf_layout')
footer_html = render_to_string(template: 'portfolios/pdf_templates/footer',
layout: 'pdf_layout')
title = ActionView::Base.full_sanitizer.sanitize(#portfolio.heading.html_safe, tags: [])
pdf = WickedPdf.new.pdf_from_string(html,
title: title,
author: current_user.fullname,
page_size: 'A4',
margin: { top: 20, bottom: 40 },
print_media_type: true,
dpi: 600,
zoom: 1,
no_pdf_compression: false,
lowquality: false,
outline: { outline: true, outline_depth: 4 },
footer: { content: footer_html },
extra: '--encoding UTF8 --disable-smart-shrinking')
send_data(pdf,
filename: "#{t('activerecord.models.portfolio.one')}-#{current_user.fullname}.pdf",
disposition: 'attachment',
type: :pdf)
end # create_pdf
And finally the layout:
!!!
%html{lang: "#{I18n.locale.to_s}"}
%head
%meta{ content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type' }
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, shrink-to-fit=no' }
%meta{ 'http-equiv': 'Accept-CH', content: 'DPR, Viewport-Width, Width' }
%title
= t('app_title')
= csrf_meta_tags
= stylesheet_link_tag 'https://fonts.googleapis.com/css?family=Exo+2:400,700'
= stylesheet_link_tag wicked_pdf_asset_base64("pdf_styles"), media: 'print'
= stylesheet_link_tag wicked_pdf_asset_base64("pdf_styles")
= stylesheet_link_tag 'http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css'
%body
#main-content
= yield

Faced a similar issue myself. First I wasn't getting any icons and then subsequently, I started getting a weird W-on-top-of-M kind of icon.
Not getting any icons
Was resolved once I added the absolute CDN path to Font awesome to my pdf layout file.
https://github.com/brunzino/wpdf-icon-debug/pull/1/files?diff=split
Getting a weird W-on-top-of-M icon
This wasn't a problem on the server (Ubuntu 16.04). As in, the icon showed correctly on the production site. However on my Mac all icons were replaced by this strange icon. Never really resolved it but read somewhere that this gets resolved by installing the ttf font on the Mac.
Hope this helps

Related

How can I force electron to update rendering based on new css?

I'm trying to build an electron app (my first) on Windows 10 (using Visual Studio Code and Git Bash as tools), and for some reason my app has simply stopped updating based on css changes. In particular, I have a search box which I had been playing around with using different bootstrap form input styling. However, when I decided to take all of that away and just put in a vanilla html form, I still get the fancy bootstrap input.
I can successfully change the html by adding more text that shows up in the app, but as long as I have a text input element, I end up with the fancy styled bootstrap input. I tried deleting the electron cache for my app, and I then tried deleting the entire ~/AppData/Roaming/myapp directory, neither of which helped. I then tried creating a new app entirely in a new folder, reran "npm install --save electron", copied in my html and js files (but not any other files), and tried again... and I still get the bootstrap styled form! I have looked at solutions like the one described here (Electron not using updated css file) but without any noticeable difference. I am at a total loss of what to do and can only imagine that either electron is hiding another cache somewhere or that somehow Visual Studio Code or Git Bash are hiding caches somewhere that are screwing me over.
Here are the only 3 files in my project:
package.json:
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": "",
"devDependencies": {
"electron": "^6.0.10"
}
}
main.js:
const electron = require('electron');
const path = require('path');
const url = require('url');
// SET ENV
process.env.NODE_ENV = 'development';
const {app, BrowserWindow, Menu} = electron;
let mainWindow;
// Listen for app to be ready
app.on('ready', function(){
// Create new window
mainWindow = new BrowserWindow({});
mainWindowURL = url.format({
pathname: path.join(__dirname, 'mainWindow.html'),
protocol: 'file:',
slashes:true
});
mainWindow.webContents.session.clearCache(function(){})
mainWindow.loadURL(mainWindowURL, {"extraHeaders":"pragma: no-cache\n"})
// Quit app when closed
mainWindow.on('closed', function(){
app.quit();
});
// Build menu from template
const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
// Insert menu
Menu.setApplicationMenu(mainMenu);
// Clear cache from any previous sessions
//mainWindow.webContents.session.clearStorageData();
//win.once('ready-to-show', ()=>{win.show()})
//const win = BrowserWindow.getAllWindows()[0];
//const ses = win.webContents.session;
//ses.clearCache(() => {});
});
// Add developer tools option if in dev
if(process.env.NODE_ENV !== 'production'){
mainMenuTemplate.push({
label: 'Developer Tools',
submenu:[
{
role: 'reload'
},
{
label: 'Toggle DevTools',
accelerator:process.platform == 'darwin' ? 'Command+I' : 'Ctrl+I',
click(item, focusedWindow){
focusedWindow.toggleDevTools();
}
}
]
});
}
mainWindow.html:
<!DOCTYPE html>
<html>
<head>
<title>Miobium</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
<!--<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">-->
<!--<link rel="script" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js">-->
<style>
.fullPageContainer{
}
#left_panel {
background-color: white;
height: 100vh;
float: left;
width: 20vw;
border-right: 1px solid grey;
}
#main_panel{
background-color: white;
height: 100vh;
float: right;
width: calc(78vw - 2px);
}
input[type=text]{
width: 80%;
border: 1px solid grey;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="fullPageContainer">
<div id="left_panel">
Tags
</div>
<div id="main_panel">
Search
<form>
<input type='text'>
</form>
</div>
</div>
<script>
const electron = require('electron');
const {ipcRenderer} = electron;
</script>
</body>
</html>
I would greatly appreciate any insight you guys may have! I am a novice with electron and am hoping there is something simple that I can do to fix this problem. Thanks!
It appears I have been suffering from an unbelievable coincidence, but I have now resolved the issue.
Prior to when I started having the problem, I had been trying bootstrap search bar styles. The very last bootstrap style I tried was one which was EXACTLY the same as the material.css text input style, and I had even changed the bootstrap style all on my own to have exactly the same 'active' color as material.css uses by default.
When I took away the bootstrap to try styling on my own, nothing happened... The input stayed exactly the same. I assumed that this obviously meant that there was a cache somewhere. However, it turned out that material.css just had exactly the same style I had created with bootstrap, and material.css doesn't require you to add any special class labels to elements before styling them so I never suspected. Removing material.css immediately fixed the problem.
Definitely the weirdest bug coincidence I have ever experienced by orders of magnitude.

Using Font awesome in Kendo grid

I use Font awesome in Kendo grid. I expect to work without problems , it shows as good as possible , Actually if I click on icon (each icon has parent) it will jump. Any idea about fixing this issue?
Here is my code:
<kendogrid
entity_id='restaurantId'
fields="{restaurantId: {editable: false, nullable: true},rgn: {required: true},type: {required: true},url: {editable: false, nullable: true}}"
controller="restaurant"
tools='false'
colmns='[
{
field: "restaurantId",
title: "id",
width: "100px",
locked: true,
lockable: true,
},
{
field: "type",
title:"type ",
width: "120px",
lockable: true,
minScreenWidth: 500,
sortable :false
},
{
field:"restaurantRateAverage" ,
title:"average ",
width: "80px",
lockable: true
},
{
title: "operation",
width: "110px",
lockable: true,
template: "
<a class=\"warning-color knd-custom-action-btn\" href=\"\\#/foods/add/${restaurantId}\" ><i class=\"fa fa-cutlery\"></i></a>
<a class=\"primary2-color knd-custom-action-btn\" href=\"\\#/delivery-zones/add/${restaurantId}/${restaurantCityId}\" ><i class=\"fa fa-map-marker\"></i></a>
<a class=\"danger-color knd-custom-action-btn k-grid-delete show-${restaurantId}\" href=\"\\#\"><span class=\"fa fa-times\"></span></a>
"
}
]'
hard-delete="true"
></kendogrid>
EDITED :
After reading this link I changed my code :
css :
#font-face {
font-family: "FontAwesome";
/*public/app/admin/assets/fonts/fontawesome-webfont.woff */
src: url("../fonts/fontawesome-webfont.woff") format("woff"),
url("../fonts/fontawesome-webfont.woff") format("truetype");
}
.km-icon:after,
.km-icon:before
{
font: 1em/1em "FontAwesome";
}
html:
{
field:"restaurantRateAverage" ,
title:"average ",
width: "80px",
lockable: true,
template: "<div data-role=\"tabstrip\">
<a data-icon=\"fa fa-check\"> </a></div>"
}
Actually it print fa fa-check and doesn't show fontawesome.
To display font-icons you need not only the font but also the correct CSS to display the correct icon. The "correct CSS" is not the same for everyone, since there are many ways to get the font.
You can get it from http://fontello.com and only select icons you really need (there are also some other services like fontello, I would advise to use on of them to only select the icons you really need)
After you get your font you have to implement it in your site. You already did this step, you declared a #font-face and used the font on your km-icon (font: 1em/1em "FontAwesome";)
Finally you need to say which icon to display for your km-icon, if you get the icons from fontello, you get a demo.html where all the unicode-codes for your CSS are stored, if you get it from the fontawesome site use this cheat sheet. You can either copy-paste the icon directly from there with the developer-tools, but since you don't have the font in your css-editor it will show up as . (or a ? or something similar, depending on what program you use)
Another way to specify it in the CSS is with the -notation, for example:
.icon-example::before{
content: '\e83e';
font-family: "Font Awesome";
}
The last way to add it is to do it like they did it on the fontawesome-site, to add the icon directly into the html, have a look at the font-awesome cheat-sheet site i linked earlier to see what I mean.

How to include caption for gallery using magnific popup?

I am trying to include a caption on the actual webpage under the image while using the magnificence popup gallery. Using a div and class caption or carousel-caption, I am unable to do so without the images in the gallery stacking vertically one by one. How can I do this?
<a href="img/base/ggg.PNG" title="HELLO" class="chicken">
<img src="img/base/pop.PNG" alt="remember your alt tag" />
</a>
$(document).ready(function() {
$('.chicken').magnificPopup({
type: 'image',
gallery:{enabled:true}
// other options here
// end each line (except the last) with a comma
});
});
js fiddle: https://jsfiddle.net/sb4btox7/
Since I don't yet have enough reputation points to comment, I'm commenting here, in addition to providing a solution.
Comment: JSFiddle isn't working with your http:// images because JSFiddle is trying to serve them from https://
Solution:
You are halfway there. There are 2 parts to making the captions work.
You correctly have put the link in the anchor tag and not the
image tag
You must specify your title source in your
initialization script like this.
$(document).ready(function() {
$('.chicken').magnificPopup({
type: 'image',
gallery:{enabled:true},
type: 'image',
image: {
titleSrc: 'title'
// this tells the script which attribute has your caption
}
});
});
The script then automatically writes your caption to its div labeled class="mfp-title"
BONUS Solution: I needed my lightbox image to open in a new window for users on their phones to zoom in, so I added this after the first titleSrc declaration:
titleSrc: 'title',
titleSrc: function(item) {
return '' + item.el.attr('title') + '';
}
This information is in the documentation: http://dimsemenov.com/plugins/magnific-popup/documentation.html in the "Image Type" section
I tried to use the selected answer, but even using the documentation, the examples wouldn't work for me. What I ended up using was:
$('.elements').magnificPopup({
type: 'image',
gallery: {
enabled: true
},
image: {
titleSrc: function(item) {
return item.el.find('img').attr('title');
}
}
});
This probably has something to do with the version I was using, but it wasn't clear what version the documentation was for. Hopefully this is useful to someone.

Can't get the glyph code when using gulp-iconfont

I'm trying to use gulp-iconfont to build an icon font from a set of svg images.
I've created my gulp task and there're no errors when I run it. But neither can I get the code for each icon, which is what I need to use the icons on css pseudoelements.
The console output shows strange characters where the unicode is supposed to be:
Here's my gulp task:
gulp.task('iconfont', function(){
gulp.src(['assets/icons/*.svg'])
.pipe(iconfont({
fontName: 'icon-font', // required
appendUnicode: true, // recommended option
normalize: true,
centerHorizontally: true,
fontHeight: 100,
formats: ['ttf', 'eot', 'woff'],
}))
.on('glyphs', function(glyphs, options) {
console.log(glyphs, options);
})
.pipe(gulp.dest('assets/fonts/'));
});
As the appendUnicode option is set to true, I can see it at the beggining of my svg file name, for example uEA02-calendar.svg.
However, if I try to use it on my css file:
.calendar:before {
content: "uEA02";
speak: none;
font-style: normal;
font-weight: normal;
font-family: "icon-font"; }
what I see is the text uEA02 instead of my icon. I've checked and the font is loading, I don't know what could I be missing here?
I usually pair gulp-iconfont with gulp-iconfont-css. This additional package exports a stylesheet with the appropriate entities binded to a class. You can export pre-processed css or vanilla css.
Here's my gulp task.
var iconfont = require('gulp-iconfont');
var iconfontCss = require('gulp-iconfont-css');
var glyphFontName = 'icon';
var stream = gulp.src('resources/assets/glyph/*.svg')
.pipe(iconfontCss({
fontName: glyphFontName,
path: 'node_modules/gulp-iconfont-css/templates/_icons.scss',
targetPath: '../../resources/sass/generated/' + glyphFontName + '.scss',
fontPath: '../fonts/',
cssClass: 'i',
centerHorizontally: true
}))
.pipe(iconfont({
fontName: glyphFontName,
formats: [
'ttf',
'eot',
'woff',
'woff2'
],
}))
.pipe(gulp.dest('public/fonts/'));
return stream;
You simply need to escape the unicode string with a backslash (\).
In your CSS just write:
.calendar:before {
content: "\EA02";
speak: none;
font-style: normal;
font-weight: normal;
font-family: "icon-font";
}
You need to reformat the unicode from within the function you're passing to the "on glyphs" event. Otherwise the unicode will be lost in templating.
I'd suggest something like this:
.on('glyphs', function(glyphs, options) {
glyphs = glyphs.map((glyph) => {
...glyph,
unicode: glyph.unicode[0].codePointAt(0).toString(16).toUpperCase()
});
console.log(glyphs, options);
})
Can't take credit for this solution - found the answer in this post

Loading PDF in Ext.Window

I have a servlet that returns a PDF. What i trying do is loading the PDF to Ext.Window. Below is the sample source
Ext.getCmp('hisAmpPhyWin').load(
{
url:'servlet/Servlet/',
params: {xhtml:xhtmlData},
text: 'Loading PDF...',
scripts: false
});
Where 'hisAmpPhyWin' is a Ext.Window instance.
The thing is its showing the PDF content (i mean ascii characters) not the actual PDF in the browser.
Please help to fix this issue.
I think you might be better off using an IFRAME tag for this.
var win = new Ext.Window({
title: 'PDF Content',
width: 420,
height: 320,
plain:true,
html: String.format(
'<iframe src="servlet/Servlet?p1={0}&p2={1}" width="400" height="300" />',
xhtmlData.p1, xhtmlData.p2)
})
win.show();
Note: A browser only opens your data as PDF if it knows the content type is application/pdf, in here you are using the AJAX .load() method which ignores the content type coming back from the servlet response, however if you refer to it directly using an IFRAME the browser will apply the correct MIME format.
Dont forget to make sure every instance of your window is destroyed (closeAction = 'close', which is set by default), otherwise it'll keep opening up the same PDF document over and over again.
I don't think you can do it natively, but there is a really good UX that should do it.
http://www.sencha.com/forum/showthread.php?23983-ux.Media-.Flash-Flex-Components-2.1.2&highlight=ux.Media
Ext.onReady(function () {
Ext.create({
title: 'My PDF',
xtype: 'panel',
width: 600,
height: 400,
items: {
xtype: 'box',
autoEl: {
tag: 'iframe',
style: 'height: 100%; width: 100%',
src: '/files/pdf-sample.pdf'
}
},
renderTo: 'output'
});
});

Resources