Making PDF.js work with digital signatures

Out of the box PDF.js doesn’t support displaying signatures on PDF files. This is strange since it’s such a common scenario and it’s been requested many times over the years.

Thankfully there’s a simple solution to this. You need to modify the pdf.worker.js file with the following modification.

In the var WidgetAnnotation = /*#__PURE__*/ function, look for the following code:

if (data.fieldType === 'Sig') {
  data.fieldValue = null;
  _this3.setFlags(_util.AnnotationFlag.HIDDEN);
}

And comment out the setFlags line like this:

if (data.fieldType === 'Sig') {
  data.fieldValue = null;
  // _this3.setFlags(_util.AnnotationFlag.HIDDEN);
}

You don’t need to make any modifications to the pdf.js file itself just the pdf.worker.js file.

To do this you download PDF.js from the project page. Take the pdf.worker.js file from the build folder and make the modification. In your web project, use the local modified version of this file but keep referencing the base file through a CDN (or locally if you wish).

Don’t forget to minify your modified worker file afterwards.

Of course, you’ll have to make this manual modification each time you update PDF.js.

JavaScript tip: format console.log output

You can format the output of console.log() using CSS. Use %c in your console log string and then add an argument for the CSS.

Here’s a simple script that uses CSS formatting to make a formatted console logger:

const fl = {
  log: function (title, message, color) {
    console.log('%c%s:%c %s', 
      `color: ${color}; font-weight: bold; text-decoration: underline ${color}`,
      'color: black',
      title, message);
  },

  info: function (message) {
    this.log('Info', message, 'green');
  },

  warning: function (message) {
    this.log('Warning', message, 'orange');
  },

  error: function (message) {
    this.log('Error', message, 'red');
  }
};

 

Here is the result in the console:

console formatting

JavaScript tip 4: use let and const

ES6 (aka. ECMAScript 2015, 6th edition) introduced the let and const statements.

These are meant as alternatives to var and baring browser compatibility issues, I recommend that you should be using them over var.

Speaking of browser compatibility, modern browsers support them, the main pain point being IE version 10 and older. Sadly some of us (ahem… yours truly) still sometimes work on intranet applications that must support older browsers so I mention it.

The difference between let and var is that let is scoped to the current scope (function, block, expression) while var is scoped to it’s containing function or barring that globally.

Here are some examples of behaviour which people not used to var‘s scoping might find odd:

function test1() {
  var foo = 1;

  if (true) {
    var foo = 2;
  }

  console.log(foo);  
}

test1();

function test2() {
  let foo = 1;

  if (true) {
    let foo = 2;
  }

  console.log(foo);  
}

test2();

Here test1() returns 2 even though the second foo declaration was in an inner scope. test2() on the other hand returns 1 has the second foo is scoped to it’s containing if statement.

Here is another example:

function test3() {
  for (var i = 0; i < 10; i++) {
    var inner = i;  
  }
    
  console.log(inner);
}

test3();

function test4() {
  for (let i = 0; i <= 10; i++) {
    let inner = i;  
  }
  
  console.log(inner);
}

test4();

In test3(), the output is 9 which is the last value of i in the loop’s inner scope. test4() returns an inner is not defined error which is more appropriate.

const scoping rules work like let but:

  • You must assign a value at declaration
  • You cannot re-assign a new value later on

This behaviour is similar to readonly and const in other languages like C# and affords an extra level of security for values that cannot change.