nuxt-font-loader-strategy
Version:
Helps to load fonts and activate them by preloading.
117 lines (103 loc) • 3.29 kB
JavaScript
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
}
}
export function getMimeTypeByFormat (format) {
return 'font/' + ({
truetype: 'ttf'
}[String(format)] || format)
}
function getFormat (path) {
const ext = extname(path).replace(/^\./, '')
return {
ttf: 'truetype'
}[String(ext)] || ext
}
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)
}
})
}