PDF.js rendering inccorrect characters with RequireJS - requirejs

I getting incorrect characters when i tried use pdf.js in my app.
My require.config:
require.config({paths: {'pdfjs-dist/build/pdf':'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.7.570/pdf.min'});
My code like:
define("SomeModule", ["pdfjs-dist/build/pdf"], function(pdf){
pdf.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.7.570/pdf.worker.min.js';
var loadingTask = pdfjsLib.getDocument({data: somePdfData});
})
When i loaded pdf.js via script before RequireJS was loading - all works fine.
<script src="http://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.943/pdf.min.js"></script>

Related

NodeJS os.networkInterfaces() returns [Object object] in Browserify bundle

I am a beginner to Browserify for NodeJS and I wrote a simple module that would list the network interfaces and return it to the person viewing a webpage. I begun by writing the main.js file,
var os = require("os");
document.write(os.networkInterfaces());
Then I compiled the code via this command browserify main.js -o bundle.js which on completion didn't yield any output but resulted in the creation of bundle.js. This is when the html code comes into play,
<html>
<body>
Hi, here are your network interfaces:
<script src="bundle.js"></script>
</body>
</html>
Upon loading the page it says, Hi, here are your network interfaces:[object Object] when I was expecting a string that NodeJS says it's os.networkInterfaces() function returns when called. What did I do wrong and how can I go about fixing it?
That has nothing to do with browserify.
document.write tries to stringify an object by calling the Object#toString() function of that object's prototype.
So, if you want to print a string use JSON.stringify(obj, null, 2) (2 is for 2 spaces, for prettification)
var os = require("os");
document.write(JSON.stringify(os.networkInterfaces(), null, 2)));
Note: you can check in console by typing:
console.log({"foo":"bar"}.toString());
Also, you need to use os-browserify if you want to use os module in browsers

System.import async module loading conflicts with scripts tags sync loading

I started using JSPM with atom/electron for porting a web site I've built using Marionette.
I have all my App written around Marionette modules so I want to load all the JavasSript files before starting the app.
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
loadApp = System.import('./scripts/app_definition').then(function(m){
window.App = m['App'];
});
</script>
<!-- inject:js -->
##LOTS INJECTED SCRIPTS THAT NEEDS window.App to be defined##
<script src="compiled/modules/video/video_app.js"></script>
<!-- endinject -->
<script type="text/javascript">
loadApp.then(function(){
App.start();
})
</script>
I'm having problems with the Async nature of System.import(). How would you load the scripts after System.import has finished loading the App code?
For production I have no problem with this, because I would concatenate all the files in a single js module and the load that module using System.import, but that would be a nightmare to debug, I would prefer to have the files loaded separately.
Any thoughts? Thanks!
Global variables are a big no no when using ES6 modules.
You could load your scripts after the app definition:
loadApp = System.import('./scripts/app_definition').then(function(m){
window.App = m['App'];
var scriptEl = document.createElement('script');
scriptEl.src = "compiled/modules/video/video_app.js";
document.head.appendChild(scriptEl);
});
But i'm not sure what's the use of having JSPM here in the first place. So the real solution would be to transform all your modules to ES6 import syntax and avoid global variables all together.

How does the text! plugin use the baseUrl?

I'm having an issue getting the text! plugin to work in my requirejs site. It's always including lib/ in the request url, however all of the other files (not using text!) are being successfully found and loaded. Here is my directory structure:
WebContent/
|--backbone/
|--Bunch of folders and files
|--config/
|--config.js
|--lib/
|--jquery.js
|--text.js
|--require.js
|--index.html
my index.html file is:
<body>
<div id="siteLayoutContainer"></div>
<script data-main='config/config' src="lib/require.js"></script>
</body>
The config file is:
requirejs.config({
baseUrl: './',
paths: {
jquery: 'lib/jquery.js',
backbone: 'lib/backbone.js',
text: 'lib/text',
application: 'backbone/application'
},
text: {
env: 'xhr'
}
});
require(['application'], function(App) {
App.start();
});
I'm using the text! plugin like so:
define([
'jquery',
'text!backbone/templates/SomeTemplate.html'
], function(jQuery, NotFoundHtml) {
//Some code here
}
So, in the above script, the url being used for the template is:
http://localhost/lib/backbone/templates/SomeTemplate.html
and I am expecting it to be:
http://localhost/backbone/templates/SomeTemplate.html
I've tried the following:
Moving the text.js and require.js files out into the WebContent
directory but I get the same results. Also something interesting is
if I put a space after text! and then the path, that works fine and
doesn't include the lib/ directory in the request to get the html
template. However the optimizer includes the space and can't find the
template.
Not defining a baseUrl - same results.
Moved the
require config.js content into index.html in it's own script tag that runs
before the require.js script tag - same results.
Getting rid of the the text options in the config file
Oh yeah, forgot I've also tried 'text!../backbone/templates/SomeTemplate.html - same results
So I'm stuck and can't figure out what I'm missing. I'm obviously not understanding how the text! plugin uses the baseUrl or how it determines the url it's going to use to fetch the defined file.
After your edits to your question, it now contains all the information to diagnose the problem. As you guessed in one of your comments, the issue is indeed that this path:
backbone: 'lib/backbone.js',
is throwing off the resolution of the template you give to the text plugin. When the text plugin loads what you give to it, it takes the path after the ! symbol and treats it as if it were a module name, and it goes through the module resolution process. The way module resolution works is that it checks if there is a prefix that matches any of the keys in paths and will change the prefix with the value associated with the key, which gives the result you obtained. One way to fix the issue would be to add this to your paths configuration:
"backbone/templates": "backbone/templates"
This will make it so that anything you request under backbone/templates won't get messed up by the backbone path.
Note: it is preferable to avoid putting extensions in module names so you should remove it from the values you have for jQuery and Backbone.

using EJS with requirejs

I had a problem include ejs into requirejs. I put <script data-main="js/app" src="js/require.js"></script> in my and inside of body create EJS object.
In my app.js,
require.config({
paths: {
//library
jquery: 'lib/jquery-1.11.1.min',
jquerymobile: "lib/jquery.mobile-1.4.2.min",
text: 'text',
ejs: 'ejs_0.9_alpha_1_production'
},
shim: {
"ejs": {
exports: 'ejs'
}
}
});
require(['jquery', 'jquerymobile','text','ejs'], function ($, mobile) {
console.log('jQuery version:', $.fn.jquery); // 1.9.0
});
when it is running, it throws EJS is not defined error. However, if I include
<script type="text/javascript" src="js/ejs_0.9_alpha_1_production.js"></script>
in the head, everything goes well.
Regards
Hammer
Lately I just get through similar trouble using ejs from the browser. I post the answer as it could save somebody's time.
I suggest you double check your ejs library is indeed coming from https://github.com/visionmedia/ejs. There is quite some tuned version of ejs around right now because it is becoming very popular. Unfortunatly most of thoses versions target specific needs and return different object to the window (eg. EJS instead of ejs) or don't even return anything usefull for requirejs.
=> In both case this would expalin why your shim exports return undefined.
Once you get it to load properly, let me also spot on an awesome requirejs-ejs plugin at https://github.com/whitcomb/requirejs-ejs . It could help you preload and render your template in a nice requirejs way.

Is it possible to use PhantomJS and Node to dynamically generate PDFs from templates?

Background / Need
I am working with a group on a web application using Node.JS and Express. We need to be able to generate reports which can be printed as hard copies and also hard copy forms. Preferably we'd like to dynamically generate PDFs on the server for both reports and hand written forms. We're currently using EJS templates on the server.
Options
I was thinking that it would be convenient to be able to use templates to be able to build forms/reports and generate a PDF from the resulting HTML, however my options to do this appear limited as far as I can find. I have looked at two different possible solutions:
PhantomJS -- (npm node-phantom module)
PDFKit
EDIT: I found another Node.JS module which is able to generate PDFs from HTML called node-wkhtml which relies on wkhtmltopdf. I am now comparing using node-phantom and node-wkhtml. I have been able to generate PDFs on a Node server with both of these and they both appear to be capable of doing what I need.
I have seen some examples of using PhantomJS to render PDF documents from websites, but all of the examples I have seen use a URL and do not feed it a string of HTML. I am not sure if I could make this work with templates in order to dynamically generate PDF reports.
When a request for a report comes in I was hoping to generate HTML from an EJS template, and use that to generate a PDF. Is there anyway for me to use Phantom to dynamically create a page completely on the server without making a request?
My other option is to use PDFkit which allows dynamic generation of PDFs, but it is a canvas-like API and doesn't really support any notion of templates as far as I can tell.
The Question
Does anyone know if I can use PhantomJS with Node to dynamically generate PDFs from HTML generated from a template? Or does anyone know any other solutions I can use to generate and serve printable reports/forms from my Node/Express back-end.
EJS seems to run fine in PhantomJS (after installing the path module). To load a page in PhantomJS given a string of HTML, do page.content = '<html><head>...';.
npm install ejs and npm install path, then:
var ejs = require('ejs'),
page = require('webpage').create();
var html = ejs.render('<h1><%= title %></h1>', {
title: 'wow'
});
page.content = html;
page.render('test.pdf');
phantom.exit();
(Run this script with phantomjs, not node.)
I am going to post an answer for anyone trying to do something similar with node-phantom. Because node-phantom controls the local installation of PhantomJS, it must use asynchronous methods for everything even when the corresponding PhantomJS operation is synchronous. When setting the content for a page to be rendered in PhantomJS you can simply do:
page.content = '<h1>Some Markup</h1>';
page.render('page.pdf');
However, using the node-phantom module within node you must use the page.set method. This is the code I used below.
'use strict';
var phantom = require('node-phantom');
var html = '<!DOCTYPE html><html><head><title>My Webpage</title></head>' +
'<body><h1>My Webpage</h1><p>This is my webpage. I hope you like it' +
'!</body></html>';
phantom.create(function (error, ph) {
ph.createPage(function (error, page) {
page.set('content', html, function (error) {
if (error) {
console.log('Error setting content: %s', error);
} else {
page.render('page.pdf', function (error) {
if (error) console.log('Error rendering PDF: %s', error);
});
}
ph.exit();
});
});
});
A really easy solution to this problem is the node-webshot module - you can put raw html directly in as an argument and it prints the pdf directly.

Resources