-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The text attributes `bold` and `italic` only allow the selection of a single alternative font weight and font style. This commit introduces the text attributes `fontWeight` and `fontStyle` as replacement for `bold` and `italic`. These new attributes correspond to the CSS properties [font-weight] and [font-style]. This enables the use of different weights of the same font family. The attributes `bold` and `italic` are still supported, but they are deprecated and will be removed in a future release. [font-weight]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight [font-style]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style
- Loading branch information
Showing
12 changed files
with
373 additions
and
159 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
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 |
---|---|---|
@@ -1,94 +1,137 @@ | ||
import { beforeEach, describe, expect, it } from '@jest/globals'; | ||
|
||
import { createFontLoader, FontLoader } from './font-loader.js'; | ||
import { Font } from './fonts.js'; | ||
import { fakeFont } from './test/test-utils.js'; | ||
import { FontDef } from './fonts.js'; | ||
import { mkData } from './test/test-utils.js'; | ||
|
||
describe('font-loader', () => { | ||
let normalFont: Font; | ||
let italicFont: Font; | ||
let boldFont: Font; | ||
let italicBoldFont: Font; | ||
let otherFont: Font; | ||
let normalFont: FontDef; | ||
let italicFont: FontDef; | ||
let obliqueFont: FontDef; | ||
let boldFont: FontDef; | ||
let italicBoldFont: FontDef; | ||
let obliqueBoldFont: FontDef; | ||
let otherFont: FontDef; | ||
let fontLoader: FontLoader; | ||
|
||
beforeEach(() => { | ||
normalFont = fakeFont('Test'); | ||
italicFont = fakeFont('Test', { italic: true }); | ||
boldFont = fakeFont('Test', { bold: true }); | ||
italicBoldFont = fakeFont('Test', { italic: true, bold: true }); | ||
otherFont = fakeFont('Other'); | ||
fontLoader = createFontLoader([normalFont, italicFont, boldFont, italicBoldFont, otherFont]); | ||
}); | ||
|
||
it('rejects for unknown font', async () => { | ||
const loader = createFontLoader([]); | ||
|
||
expect(loader.loadFont({})).rejects.toThrowError('No font defined for normal'); | ||
}); | ||
|
||
it('rejects for unknown font name', async () => { | ||
await expect(fontLoader.loadFont({ fontFamily: 'foo' })).rejects.toThrowError( | ||
"No font defined for 'foo', normal" | ||
); | ||
}); | ||
describe('createFontLoader', () => { | ||
beforeEach(() => { | ||
normalFont = fakeFontDef('Test'); | ||
italicFont = fakeFontDef('Test', { style: 'italic' }); | ||
obliqueFont = fakeFontDef('Test', { style: 'oblique' }); | ||
boldFont = fakeFontDef('Test', { weight: 700 }); | ||
italicBoldFont = fakeFontDef('Test', { style: 'italic', weight: 700 }); | ||
obliqueBoldFont = fakeFontDef('Test', { style: 'oblique', weight: 700 }); | ||
otherFont = fakeFontDef('Other'); | ||
fontLoader = createFontLoader([normalFont, italicFont, boldFont, italicBoldFont, otherFont]); | ||
}); | ||
|
||
it('selects different font variants', async () => { | ||
const fontFamily = 'Test'; | ||
it('rejects when no fonts defined', async () => { | ||
const loader = createFontLoader([]); | ||
|
||
expect(await fontLoader.loadFont({ fontFamily })).toEqual({ | ||
name: 'Test', | ||
data: normalFont.data, | ||
}); | ||
expect(await fontLoader.loadFont({ fontFamily, bold: true })).toEqual({ | ||
name: 'Test', | ||
data: boldFont.data, | ||
await expect(loader.loadFont({})).rejects.toThrowError('No fonts defined'); | ||
}); | ||
expect(await fontLoader.loadFont({ fontFamily, italic: true })).toEqual({ | ||
name: 'Test', | ||
data: italicFont.data, | ||
|
||
it('rejects for unknown font name', async () => { | ||
await expect(fontLoader.loadFont({ fontFamily: 'Unknown' })).rejects.toThrowError( | ||
"No font defined for 'Unknown'" | ||
); | ||
}); | ||
expect(await fontLoader.loadFont({ fontFamily, italic: true, bold: true })).toEqual({ | ||
name: 'Test', | ||
data: italicBoldFont.data, | ||
|
||
it('rejects when no matching font style can be found', async () => { | ||
await expect(() => | ||
fontLoader.loadFont({ fontFamily: 'Other', fontStyle: 'italic' }) | ||
).rejects.toThrowError("No font defined for 'Other', style=italic"); | ||
}); | ||
}); | ||
|
||
it('selects first matching font if no family specified', async () => { | ||
await expect(fontLoader.loadFont({})).resolves.toEqual({ | ||
name: 'Test', | ||
data: normalFont.data, | ||
it('selects different font variants', async () => { | ||
const fontFamily = 'Test'; | ||
|
||
expect(await fontLoader.loadFont({ fontFamily })).toEqual({ | ||
name: 'Test', | ||
data: normalFont.data, | ||
}); | ||
expect(await fontLoader.loadFont({ fontFamily, fontWeight: 'bold' })).toEqual({ | ||
name: 'Test', | ||
data: boldFont.data, | ||
}); | ||
expect(await fontLoader.loadFont({ fontFamily, fontStyle: 'italic' })).toEqual({ | ||
name: 'Test', | ||
data: italicFont.data, | ||
}); | ||
expect( | ||
await fontLoader.loadFont({ fontFamily, fontStyle: 'italic', fontWeight: 'bold' }) | ||
).toEqual({ | ||
name: 'Test', | ||
data: italicBoldFont.data, | ||
}); | ||
}); | ||
await expect(fontLoader.loadFont({ bold: true })).resolves.toEqual({ | ||
name: 'Test', | ||
data: boldFont.data, | ||
|
||
it('selects first matching font if no family specified', async () => { | ||
await expect(fontLoader.loadFont({})).resolves.toEqual({ | ||
name: 'Test', | ||
data: normalFont.data, | ||
}); | ||
await expect(fontLoader.loadFont({ fontWeight: 'bold' })).resolves.toEqual({ | ||
name: 'Test', | ||
data: boldFont.data, | ||
}); | ||
await expect(fontLoader.loadFont({ fontStyle: 'italic' })).resolves.toEqual({ | ||
name: 'Test', | ||
data: italicFont.data, | ||
}); | ||
await expect( | ||
fontLoader.loadFont({ fontStyle: 'italic', fontWeight: 'bold' }) | ||
).resolves.toEqual({ | ||
name: 'Test', | ||
data: italicBoldFont.data, | ||
}); | ||
}); | ||
await expect(fontLoader.loadFont({ italic: true })).resolves.toEqual({ | ||
name: 'Test', | ||
data: italicFont.data, | ||
|
||
it('selects font with matching font family', async () => { | ||
await expect(fontLoader.loadFont({ fontFamily: 'Other' })).resolves.toEqual({ | ||
name: 'Other', | ||
data: otherFont.data, | ||
}); | ||
}); | ||
await expect(fontLoader.loadFont({ italic: true, bold: true })).resolves.toEqual({ | ||
name: 'Test', | ||
data: italicBoldFont.data, | ||
|
||
it('falls back to oblique when no italic font can be found', async () => { | ||
fontLoader = createFontLoader([normalFont, obliqueFont, boldFont, obliqueBoldFont]); | ||
await expect( | ||
fontLoader.loadFont({ fontFamily: 'Test', fontStyle: 'italic' }) | ||
).resolves.toEqual({ | ||
name: 'Test', | ||
data: obliqueFont.data, | ||
}); | ||
}); | ||
}); | ||
|
||
it('selects font with matching font family', async () => { | ||
await expect(fontLoader.loadFont({ fontFamily: 'Other' })).resolves.toEqual({ | ||
name: 'Other', | ||
data: otherFont.data, | ||
it('falls back to italic when no oblique font can be found', async () => { | ||
await expect( | ||
fontLoader.loadFont({ fontFamily: 'Test', fontStyle: 'oblique' }) | ||
).resolves.toEqual({ | ||
name: 'Test', | ||
data: italicFont.data, | ||
}); | ||
}); | ||
}); | ||
|
||
it('rejects when no matching font can be found', async () => { | ||
await expect(() => | ||
fontLoader.loadFont({ fontFamily: 'Other', italic: true }) | ||
).rejects.toThrowError("No font defined for 'Other', italic"); | ||
await expect(() => | ||
fontLoader.loadFont({ fontFamily: 'Other', bold: true }) | ||
).rejects.toThrowError("No font defined for 'Other', bold"); | ||
await expect(() => | ||
fontLoader.loadFont({ fontFamily: 'Other', italic: true, bold: true }) | ||
).rejects.toThrowError("No font defined for 'Other', bold italic"); | ||
it('falls back when no matching font weight can be found', async () => { | ||
await expect( | ||
fontLoader.loadFont({ fontFamily: 'Other', fontWeight: 'bold' }) | ||
).resolves.toEqual({ | ||
name: 'Other', | ||
data: otherFont.data, | ||
}); | ||
await expect(fontLoader.loadFont({ fontFamily: 'Other', fontWeight: 200 })).resolves.toEqual({ | ||
name: 'Other', | ||
data: otherFont.data, | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
function fakeFontDef(family: string, options?: Partial<FontDef>): FontDef { | ||
const style = options?.style ?? 'normal'; | ||
const weight = options?.weight ?? 400; | ||
const data = options?.data ?? mkData([family, style, weight].join('_') as string); | ||
return { family, style, weight, data }; | ||
} |
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
Oops, something went wrong.