Description
Although there's a test that covers removing the UTF-8 BOM from the AsciiDoc source, this only works on Node.js when the input is a string created in JavaScript. When the AsciiDoc source is read from a file, or the string is created from Buffer.from, the UTF-8 BOM is not removed.
This snippet explains why we're hitting this problem:
const fs = require('fs')
fs.writeFileSync('test.adoc', Buffer.concat([Buffer.from([0xEF, 0xBB, 0xBF]), Buffer.from('= Document Title')]))
const contentsFromFile = fs.readFileSync('test.adoc')
console.log(contentsFromFile.toString().charCodeAt())
console.log(contentsFromFile.toString().charCodeAt(1))
// => 65279
// => '='
const contentsFromString = '\xef\xbb\xbf= Document Title'
console.log(contentsFromString.charCodeAt())
console.log(contentsFromString.charCodeAt(3))
// => 239
// => '='
It appears that when Node.js creates a string by way of a Buffer, such as when reading the contents of a file, it changes the UTF-8 BOM into a different BOM character (code: 65279, char ref: 0xFEFF). I have not found any way to disable this behavior. It's basically a quirk of Node.js.
I think Asciidoctor.js should detect this alternate BOM and remove the character. (I'm open to changing Asciidoctor Ruby, if we determine it's necessary).
Activity
mojavelinux commentedon Jul 2, 2021
What I can't figure out is how to emulate this scenario in Ruby. I can't figure how to get Ruby to report the character code (8-bit unsigned integer) 65279. If I try to pack it, this is what I get:
Here's what I get if I unpack the BOM:
And if I write it to a file, Ruby always writes the original BOM, "\xEF\xBB\xFB"
We may just have to accept this character code is a weird quirk of Node.js and deal with it as such. There are translations going on we just can't see.
mojavelinux commentedon Jul 2, 2021
I'm now convinced it's best to deal with this in Asciidoctor.js. Our custom unpack method is an ideal place for it. Here's the logic we could use that would make this work:
Let me know if you want me to proceed with a fix.
mojavelinux commentedon Jul 2, 2021
An alternate way to do this to check if
self[0, 1].bytes
is[255, 254]
. Either way seems to work.mojavelinux commentedon Jul 2, 2021
Here's something that's interesting:
and
So it is recognizing 65279 as a UTF-8 BOM.
I think checking the char code is the right strategy (as proposed above). It's the same as this, with a bit less overhead:
resolves asciidoctor#1344 look for alternate char code for BOM and re…
resolves asciidoctor#1344 look for alternate char code for BOM and re…
🐛 resolves #1344 look for alternate char code for BOM and return stan…
🐛 look for alternate char code for BOM and return standard BOM
🐛 look for alternate char code for BOM and return standard BOM
🐛 resolves #1344 look for alternate char code for BOM and return stan…