-
Notifications
You must be signed in to change notification settings - Fork 1
/
fontFace.js
105 lines (95 loc) · 3.03 KB
/
fontFace.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { extname } from 'path'
import { paramCase, snakeCase } from 'change-case'
import { arrayFlat } from './index'
// Font-Face
const FONTFACE_PROPERTIES = {
fontFamily: null,
fontUnicodeRange: null,
fontVariant: 'normal',
fontFeatureSettings: 'normal',
fontStretch: 'normal',
fontWeight: 'normal',
fontStyle: 'normal',
fontDisplay: 'swap'
}
const DEFAULT_FONT_EXTENSIONS = ['woff2', 'woff']
const DEFAULT_CLASS_PATTERN = '[family]_[variant]_[featureSettings]_[stretch]_[weight]_[style]'
export function getFontClasses (pattern, set, properties) {
pattern = pattern || DEFAULT_CLASS_PATTERN
const className = Object.keys(properties).reduce((result, key) => {
let name = key.replace(/^font/, '')
name = name.replace(/^.{1}/, name[0].toLowerCase())
let value = properties[String(key)]
if (name === 'family') {
value = set
}
result = result.replace(`[${name}]`, value)
return result
}, pattern)
return [`font_${set}`, `font_${className}`]
}
export async function prepareFonts (options, resolve, kebabCaseProps = true) {
const { fonts, classPattern } = options
const preparedFonts = (await Promise.all(fonts.map((font) => {
const fileExtensions = getFileExtensions(font)
return font.fontFaces.map((face) => {
const sources = prepareSrc(face.src, fileExtensions, resolve)
const properties = getProperties(
Object.assign({ fontFamily: `${font.fontFamily}` }, face),
kebabCaseProps ? paramCase : name => name
)
const set = snakeCase(font.fontFamily)
return {
classes: getFontClasses(classPattern, set, properties),
properties,
sources,
set,
preload: face.preload || false,
local: [].concat(face.local || [])
}
})
})))
return arrayFlat(preparedFonts)
}
export function createFontFace (font, baseUrl) {
const props = font.properties
const options = {
display: props.fontDisplay,
style: props.fontStyle,
weight: props.fontWeight,
unicodeRange: props.fontUnicodeRange,
variant: props.fontVariant,
featureSettings: props.fontFeatureSettings,
stretch: props.fontStretch
}
const src = `url(${baseUrl + font.sources[0].path})`
return new FontFace(props.fontFamily.replace(/'/g, ''), src, options)
}
function getFileExtensions (font) {
if (Array.isArray(font.fileExtensions) && font.fileExtensions.length > 0) {
return font.fileExtensions
} else {
return DEFAULT_FONT_EXTENSIONS
}
}
function getFormat (path) {
return extname(path).replace(/^\./, '')
}
function getProperties (face, transform = paramCase) {
return Object.keys(FONTFACE_PROPERTIES).reduce((result, prop) => {
const value = face[prop] || FONTFACE_PROPERTIES[prop]
if (value) {
result[transform(prop)] = value
}
return result
}, {})
}
function prepareSrc (src, fileExtensions, pathResolve) {
return fileExtensions.map((fileExtension) => {
const filePath = src + '.' + fileExtension
return {
path: pathResolve(filePath),
format: getFormat(filePath)
}
})
}