Reputation: 271
I created a simple app using knockout/bootstrap/gulp that downloads a pdf using pdfMake.js. It works fine in debug mode using VS2017. After publishing and using gulp it gives this error when run: File 'Roboto-Regular.ttf' not found in virtual file system
Note: After gulp, all JS files are in one script.js file.
I tried many things, it always works when debugging, as soon as I run gulp, it gives the error.
I tried joepal1976's solution from here (what I did with the dependencies in require.config.js)
Someone suggested .pipe(uglify({ compress: { hoist_funs: false } })) which doesn't appear to help.
Included in require.config like so:
var require = {
baseUrl: ".",
paths: {
"jquery": "js-libs/jquery.min",
"bootstrap": "js-libs/bootstrap.min",
"crossroads": "js-libs/crossroads.min",
"hasher": "js-libs/hasher.min",
"knockout": "js-libs/knockout",
"knockout-projections": "js-libs/knockout-projections.min",
"signals": "js-libs/signals.min",
"text": "js-libs/text",
"vfs_fonts": "js-libs/vfs_fonts",
"pdfMake": "js-libs/pdfmake.min"
},
shim: {
"bootstrap": { deps: ["jquery"] },
'pdfMake':
{
exports: 'vfs_fonts'
},
'vfs_fonts':
{
deps: ['pdfMake'],
exports: 'vfs_fonts'
}
}
};
JS for the page:
define(["knockout", "text!./home.html"], function (ko, homeTemplate) {
function HomeViewModel(route) {
var thisVM = this;
this.VMInit = function () {
var thePDF = {
content: [
'My test invoice.',
]
};
pdfMake.createPdf(thePDF).download('pdf_test.pdf');
}
thisVM.VMInit();
}
return { viewModel: HomeViewModel, template: homeTemplate };
});
The Gulp file:
//-----------------------------------------------------------------------
// Node modules
var fs = require('fs'),
vm = require('vm'),
merge = require('deeply'),
chalk = require('chalk'),
es = require('event-stream');
//-----------------------------------------------------------------------
// Gulp and plugins
var gulp = require('gulp'),
rjs = require('gulp-requirejs-bundler'),
concat = require('gulp-concat'),
clean = require('gulp-clean'),
replace = require('gulp-replace'),
uglify = require('gulp-uglify'),
htmlreplace = require('gulp-html-replace');
// Config
var requireJsRuntimeConfig =
vm.runInNewContext(fs.readFileSync('src/app/require.config.js') + '; require;');
requireJsOptimizerConfig = merge(requireJsRuntimeConfig, {
out: 'scripts.js',
baseUrl: './src',
name: 'app/startup',
paths: {
requireLib: 'js-libs/require'
},
include: [
'requireLib',
'components/nav-bar/nav-bar',
'components/home-page/home',
'text!components/about-page/about.html'
],
insertRequire: ['app/startup'],
bundles: {
// If you want parts of the site to load on demand, remove them from the 'include' list
// above, and group them into bundles here.
// 'bundle-name': [ 'some/module', 'another/module' ],
// 'another-bundle-name': [ 'yet-another-module' ]
}
});
//-----------------------------------------------------------------------
// Discovers all AMD dependencies, concatenates together all required .js
files, minifies them
gulp.task('js', function () {
return rjs(requireJsOptimizerConfig)
.pipe(replace('Views/src/', ''))
.pipe(replace('img/', 'Assets/img/'))
.pipe(replace('css/', 'Assets/css/'))
.pipe(uglify({
preserveComments: 'some'
}))
.pipe(gulp.dest('./dist-app/Assets/js/'));
});
gulp.task('css', function () {
return gulp.src(['./src/css/bootstrap.css',
'./src/css/bootstrap-switch.css',
'./src/css/dataTables.bootstrap.css',
'./src/css/dataTables.colVis.css',
'./src/css/dataTables.responsive.css',
'./src/css/daterangePicker.css'])
.pipe(concat('styles.css'))
.pipe(gulp.dest('./dist-app/Assets/css/'));
});
// Copies index.html, replacing <script> and <link> tags to reference production
URLs
gulp.task('html', function () {
return gulp.src('./src/index.html')
.pipe(htmlreplace({
dependencies_top: '<link href="Assets/css/styles.css"
rel="stylesheet">',
dependencies_bottom: '<script src="Assets/js/scripts.js"></script>'
}))
.pipe(gulp.dest('./dist-app/'));
});
// Removes all files from ./dist/
gulp.task('clean', function () {
console.log("the clean task");
return gulp.src('./dist-app/**/*', { read: false })
.pipe(clean());
});
// All tasks in [] must complete before 'default' can begin
gulp.task('default', ['html', 'js', 'css'], function (callback) {
callback();
console.log('\nPlaced optimized files in ' + chalk.magenta('dist-app/\n'));
});
The Startup.js file if its helpful:
define(['jquery',
'knockout',
'./router',
'bootstrap',
'knockout-projections',
'pdfMake',
'vfs_fonts'], function ($, ko, router) {
// Components can be packaged as AMD modules, such as the following:
ko.components.register('nav-bar', { require: 'components/nav-bar/nav-bar' });
ko.components.register('home-page', { require: 'components/home-page/home'
});
// ... or for template-only components, you can just point to a .html file
directly:
ko.components.register('about-page', {
template: { require: 'text!components/about-page/about.html' }
});
ko.components.register('new-page', { require: 'components/new-page/new-page'
});
// [Scaffolded component registrations will be inserted here. To retain this
//feature, don't remove this comment.]
// Start the application
ko.applyBindings({ route: router.currentRoute });
});
Upvotes: 27
Views: 53748
Reputation: 139
Create a file: src/typings/pdfmake.d.ts
declare module 'pdfmake/build/pdfmake' {
const pdfMake: any;
export = pdfMake;
}
declare module 'pdfmake/build/vfs_fonts' {
const pdfFonts: any;
export = pdfFonts;
}
Verify Your tsconfig.json
{
"compilerOptions": {
"typeRoots": [
"node_modules/@types",
"src/typings"
]
}
}
In your angular code
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
(pdfMake as any).vfs = pdfFonts.pdfMake.vfs;
Upvotes: 0
Reputation: 13
currently i amusing this versionofpdfMake"pdfmake": "^0.2.10", and in this you cannot assign font by this pdfMake.vfs = pdfFonts.pdfMake.vfs; so whenever you write pdfMake.createPdf() inside that assign font case 'download':
pdfMake.createPdf(documentDefinition,undefined,undefined,pdfFonts.pdfMake.vfs).open(); break;
UPDATE 2025
Version: 0.2.18
pdfMake.vfs
is now undefined and pdfMake.setFonts(pdfFonts.pdfMake.vfs)
does not help as it throws error of 'cannot create bold with...'
Code Example
import * as pdfFonts from 'pdfmake/build/vfs_fonts';
...
pdfMake.createPdf(documentDefinition,undefined,undefined,pdfFonts).open();
Upvotes: 1
Reputation: 11
try this
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts['Roboto-Regular.ttf'];
Upvotes: 1
Reputation: 1
TYPESCRIPT VUE 3 2024-11-28
if you see this You might get build errors or same error as OP. Don't import pdfFonts. instead follow this.
pdfMake.fonts = { Helvetica: { normal: "Helvetica",bold: "Helvetica-Bold",italics: "Helvetica-Oblique",bolditalics: "Helvetica-BoldOblique",},}
and remember to add following to your docDefinition (TDocumentDefinitions)
defaultStyle: { font: 'Helvetica' }
what we have done is instead depending on Roboto font we used 'Helvetica' font insted, which is browser safe font(comes pre installed in most OS and web browsers). and this method only works with English Charactors. you could try to change this for your desired font but I cannot guarantee if it will work for you. read documentation for more info : https://pdfmake.github.io/docs/0.1/fonts/standard-14-fonts/
Upvotes: 0
Reputation: 53
In 2024 with version 0.2.13 you may pass the fonts as the fourth argument in createPDF
:
import * as pdfFonts from 'pdfmake/build/vfs_fonts';
import * as pdfMake from 'pdfmake/build/pdfmake';
pdfMake.createPdf(docDefinition, undefined, undefined, pdfFonts.pdfMake.vfs).open();
Pass undefined
instead of null
as someone else suggested. Note that the import order does not actually matter.
pdfMake.vfs
is not mutable, so the following does not work:
pdfMake.vfs = pdfFonts.pdfMake.vfs; // Doesn't work
(window as any).pdfMake.vfs = pdfFonts.pdfMake.vfs // Don't use
Don't forget to install the typings via
npm install -D @types/pdfmake
Upvotes: 0
Reputation: 4378
As of the most recent update, the following code works inconsistently across different systems:
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
Using this will often result in virtual file-system errors and pdfFonts.pdfMake.vfs
sometimes being undefined.
I have found that creating a wrapper method that points directly to the VFS data generated by pdfmake
is far more reliable.
First, navigate to node_modules/pdfmake/build/vfs_fonts.js
and copy the data into a new file in your repo (vfs.js
) like so:
export const vfs = {
"Roboto-Italic.ttf": "...",
"Roboto-Medium.ttf": "...",
"Roboto-MediumItalic.ttf": "...",
"Roboto-Regular.ttf": "...",
}
Create the wrapper utility:
import type { CustomTableLayout } from "pdfmake/interfaces";
import type { TDocumentDefinitions } from "pdfmake/interfaces";
import pdfMake from "pdfmake/build/pdfmake";
import { vfs } from "./vfs";
export const generatePdf = (
options: TDocumentDefinitions,
layouts?: Record<string, CustomTableLayout>,
) => {
// Register fonts...
(<any>pdfMake).vfs = vfs;
return pdfMake.createPdf({
...YOUR_DEFAULT_OPTIONS,
...options,
});
}
Then use like so:
import { generatePdf } from "location/of/generatePdf";
const generator = generatePdf({ ... });
Upvotes: 0
Reputation: 1
Use this fonts script in ReactJs:
import pdfMake from "pdfmake/build/pdfmake.min";
pdfMake.fonts = {
Roboto: {
normal: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Regular.ttf',
bold: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Medium.ttf',
italics: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Italic.ttf',
bolditalics: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-MediumItalic.ttf'
}
}
Upvotes: 0
Reputation: 712
@Rijo solution worked in one file, but oddly enough refused to work in another file.
In the other file I had to use:
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
// Wherever you call createPdf, you have to pass VFS
pdfMake.createPdf(docDefinition, null, null, pdfFonts.pdfMake.vfs).open();
Upvotes: 3
Reputation: 3668
I came across this issue and resolved it by including vfs_fonts.js
just after the pdfmake Javascript file.
Here is my code, you should just need to set the file path to wherever your copy of the file is placed.
<script src="~/Content/DataTables/pdfmake-0.1.32/pdfmake.min.js"></script>
<script src="~/Content/DataTables/pdfmake-0.1.32/vfs_fonts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js"></script>
please follow the hierarchy/dependency of links else it won't work
Upvotes: 15
Reputation: 386
I battled with this recently on stackblitz when using it with angular. the issue was pdfmake.vfs on the window object was not being set. so i had to manually set it in the constructor of my pdf service like so.
constructor() {
(window as any).pdfMake.vfs = pdfFonts.pdfMake.vfs;
}
Upvotes: 18
Reputation: 2718
Following code worked for me:
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
Upvotes: 58
Reputation: 161
It is just the sequence of the files, add first the pdfmake and then vfs_fonts.
Upvotes: 5