-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add some utilities for detecting and converting fonts
- Loading branch information
1 parent
425daa7
commit d8cf34d
Showing
5 changed files
with
269 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const wawoff2 = require('wawoff2'); | ||
const woffTool = require('woff2sfnt-sfnt2woff'); | ||
|
||
const supportedFormats = new Set(['truetype', 'woff', 'woff2']); | ||
const detectFontFormat = require('./detectFontFormat'); | ||
|
||
async function convertFontBuffer(buffer, toFormat, fromFormat) { | ||
if (!supportedFormats.has(toFormat)) { | ||
throw new Error(`Cannot convert to ${toFormat}`); | ||
} | ||
if (fromFormat) { | ||
if (!supportedFormats.has(fromFormat)) { | ||
throw new Error(`Cannot convert from ${toFormat}`); | ||
} | ||
} else { | ||
fromFormat = detectFontFormat(buffer); | ||
} | ||
|
||
if (fromFormat === toFormat) { | ||
return buffer; | ||
} | ||
if (fromFormat === 'woff') { | ||
buffer = woffTool.toSfnt(buffer); | ||
} else if (fromFormat === 'woff2') { | ||
buffer = Buffer.from(await wawoff2.decompress(buffer)); | ||
} | ||
|
||
if (toFormat === 'woff') { | ||
buffer = woffTool.toWoff(buffer); | ||
} else if (toFormat === 'woff2') { | ||
buffer = Buffer.from(await wawoff2.compress(buffer)); | ||
} | ||
return buffer; | ||
} | ||
|
||
module.exports = convertFontBuffer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
function detectFontFormat(buffer) { | ||
const signature = buffer.toString('ascii', 0, 4); | ||
if (signature === 'wOFF') { | ||
return 'woff'; | ||
} else if (signature === 'wOF2') { | ||
return 'woff2'; | ||
} else if ( | ||
signature === 'true' || | ||
signature === 'OTTO' || | ||
signature === '\x00\x01\x00\x00' | ||
) { | ||
return 'truetype'; | ||
} else { | ||
throw new Error(`Unrecognized font signature: ${signature}`); | ||
} | ||
} | ||
|
||
module.exports = detectFontFormat; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
const convertFontBuffer = require('../lib/convertFontBuffer'); | ||
const detectFontFormat = require('../lib/detectFontFormat'); | ||
const fs = require('fs').promises; | ||
const pathModule = require('path'); | ||
const expect = require('unexpected').clone(); | ||
|
||
describe('convertFontBuffer', function () { | ||
before(async function () { | ||
this.truetype = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.ttf' | ||
) | ||
); | ||
this.woff = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.woff' | ||
) | ||
); | ||
this.woff2 = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.woff2' | ||
) | ||
); | ||
}); | ||
|
||
describe('when the source format is not given', function () { | ||
it('should throw if the source format could not be detected', async function () { | ||
expect( | ||
() => convertFontBuffer(Buffer.from('abcd'), 'truetype'), | ||
'to error', | ||
'Unrecognized font signature: abcd' | ||
); | ||
}); | ||
|
||
it('should convert a truetype font to truetype', async function () { | ||
const buffer = await convertFontBuffer(this.truetype, 'truetype'); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
expect(buffer, 'to be', this.truetype); // Should be a noop | ||
}); | ||
|
||
it('should convert a truetype font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.truetype, 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
}); | ||
|
||
it('should convert a truetype font to woff2', async function () { | ||
const buffer = await convertFontBuffer(this.truetype, 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
}); | ||
|
||
it('should convert a woff font to truetype', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'truetype'); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
}); | ||
|
||
it('should convert a woff font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
expect(buffer, 'to be', this.woff); // Should be a noop | ||
}); | ||
|
||
it('should convert a woff font to woff2', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
}); | ||
|
||
it('should convert a woff2 font to truetype', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'truetype'); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
}); | ||
|
||
it('should convert a woff2 font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
}); | ||
|
||
it('should convert a woff2 font to woff2', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
expect(buffer, 'to be', this.woff2); // Should be a noop | ||
}); | ||
}); | ||
|
||
describe('when the source format is given', function () { | ||
it('should convert a truetype font to truetype', async function () { | ||
const buffer = await convertFontBuffer( | ||
this.truetype, | ||
'truetype', | ||
'truetype' | ||
); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
expect(buffer, 'to be', this.truetype); // Should be a noop | ||
}); | ||
|
||
it('should convert a truetype font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.truetype, 'woff', 'truetype'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
}); | ||
|
||
it('should convert a truetype font to woff2', async function () { | ||
const buffer = await convertFontBuffer( | ||
this.truetype, | ||
'woff2', | ||
'truetype' | ||
); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
}); | ||
|
||
it('should convert a woff font to truetype', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'truetype', 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
}); | ||
|
||
it('should convert a woff font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'woff', 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
expect(buffer, 'to be', this.woff); // Should be a noop | ||
}); | ||
|
||
it('should convert a woff font to woff2', async function () { | ||
const buffer = await convertFontBuffer(this.woff, 'woff2', 'woff'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
}); | ||
|
||
it('should convert a woff2 font to truetype', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'truetype', 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
}); | ||
|
||
it('should convert a woff2 font to woff', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'woff', 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
}); | ||
|
||
it('should convert a woff2 font to woff2', async function () { | ||
const buffer = await convertFontBuffer(this.woff2, 'woff2', 'woff2'); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
expect(buffer, 'to be', this.woff2); // Should be a noop | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
const convertFontBuffer = require('../lib/convertFontBuffer'); | ||
const detectFontFormat = require('../lib/detectFontFormat'); | ||
const fs = require('fs').promises; | ||
const pathModule = require('path'); | ||
const expect = require('unexpected').clone(); | ||
|
||
describe('detectFontFormat', function () { | ||
it('should throw if the contents of the buffer could not be recognized', async function () { | ||
expect( | ||
() => convertFontBuffer(Buffer.from('abcd'), 'truetype'), | ||
'to error', | ||
'Unrecognized font signature: abcd' | ||
); | ||
}); | ||
|
||
it('should detect a truetype font', async function () { | ||
const buffer = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.ttf' | ||
) | ||
); | ||
expect(detectFontFormat(buffer), 'to equal', 'truetype'); | ||
}); | ||
|
||
it('should detect a woff font', async function () { | ||
const buffer = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.woff' | ||
) | ||
); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff'); | ||
}); | ||
|
||
it('should detect a woff2 font', async function () { | ||
const buffer = await fs.readFile( | ||
pathModule.resolve( | ||
__dirname, | ||
'..', | ||
'testdata', | ||
'subsetFonts', | ||
'Roboto-400.woff2' | ||
) | ||
); | ||
expect(detectFontFormat(buffer), 'to equal', 'woff2'); | ||
}); | ||
}); |