mirror of
https://github.com/motajs/template.git
synced 2026-11-02 23:14:34 +08:00
init: 2.B
This commit is contained in:
commit
6bf32174d8
610 files changed
+151444
No files matched your search
@@ -0,0 +1,193 @@
|
||||
import { logger } from '@motajs/common';
|
||||
|
||||
export interface IFontConfig {
|
||||
/** 字体类型 */
|
||||
readonly family: string;
|
||||
/** 字体大小的值 */
|
||||
readonly size: number;
|
||||
/** 字体大小单位,推荐使用 px */
|
||||
readonly sizeUnit: string;
|
||||
/** 字体粗细,范围 0-1000 */
|
||||
readonly weight: number;
|
||||
/** 是否斜体 */
|
||||
readonly italic: boolean;
|
||||
}
|
||||
|
||||
export const enum FontWeight {
|
||||
Light = 300,
|
||||
Normal = 400,
|
||||
Bold = 700
|
||||
}
|
||||
|
||||
type _FontStretch =
|
||||
| 'ultra-condensed'
|
||||
| 'extra-condensed'
|
||||
| 'condensed'
|
||||
| 'semi-condensed'
|
||||
| 'normal'
|
||||
| 'semi-expanded'
|
||||
| 'expanded'
|
||||
| 'extra-expanded'
|
||||
| 'ultra-expanded';
|
||||
|
||||
type _FontVariant = 'normal' | 'small-caps';
|
||||
|
||||
export class Font implements IFontConfig {
|
||||
static defaultFamily: string = 'Verdana';
|
||||
static defaultSize: number = 16;
|
||||
static defaultSizeUnit: string = 'px';
|
||||
static defaultWeight: number = 400;
|
||||
static defaultItalic: boolean = false;
|
||||
|
||||
private readonly fallbacks: Font[] = [];
|
||||
|
||||
private fontString: string = '';
|
||||
|
||||
constructor(
|
||||
public readonly family: string = Font.defaultFamily,
|
||||
public readonly size: number = Font.defaultSize,
|
||||
public readonly sizeUnit: string = Font.defaultSizeUnit,
|
||||
public readonly weight: number = Font.defaultWeight,
|
||||
public readonly italic: boolean = Font.defaultItalic
|
||||
) {
|
||||
this.fontString = this.getFont();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加后备字体,若当前字体不可用,那么会使用后备字体,后备字体也可以添加后备字体,但是请避免递归添加
|
||||
* @param fallback 后备字体
|
||||
*/
|
||||
addFallback(...fallback: Font[]) {
|
||||
this.fallbacks.push(...fallback);
|
||||
this.fontString = this.getFont();
|
||||
}
|
||||
|
||||
private build() {
|
||||
return `${this.italic ? 'italic ' : ''} ${this.weight} ${this.size}${
|
||||
this.sizeUnit
|
||||
} ${this.family}`;
|
||||
}
|
||||
|
||||
private getFallbackFont(used: Set<Font>) {
|
||||
let font = this.build();
|
||||
this.fallbacks.forEach(v => {
|
||||
if (used.has(v)) {
|
||||
logger.warn(62, this.build());
|
||||
return;
|
||||
}
|
||||
used.add(v);
|
||||
font += `, ${v.getFallbackFont(used)}`;
|
||||
});
|
||||
return font;
|
||||
}
|
||||
|
||||
private getFont() {
|
||||
if (this.fallbacks.length === 0) {
|
||||
return this.build();
|
||||
} else {
|
||||
const usedFont = new Set<Font>();
|
||||
return this.getFallbackFont(usedFont);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字体的 CSS 字符串
|
||||
*/
|
||||
string() {
|
||||
return this.fontString;
|
||||
}
|
||||
|
||||
private static parseOne(str: string) {
|
||||
if (!str) return new Font();
|
||||
let italic = this.defaultItalic;
|
||||
let weight = this.defaultWeight;
|
||||
let size = this.defaultSize;
|
||||
let unit = this.defaultSizeUnit;
|
||||
let family = this.defaultFamily;
|
||||
const tokens = str.split(/\s+/);
|
||||
let lastIndex = 0;
|
||||
tokens.forEach((v, i) => {
|
||||
// font-italic
|
||||
if (v === 'italic') {
|
||||
italic = true;
|
||||
lastIndex = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// font-weight
|
||||
const num = Number(v);
|
||||
if (!isNaN(num)) {
|
||||
weight = num;
|
||||
lastIndex = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// font-size
|
||||
const parse = parseFloat(v);
|
||||
if (!isNaN(parse)) {
|
||||
size = parse;
|
||||
unit = v.slice(parse.toString().length);
|
||||
lastIndex = i;
|
||||
return;
|
||||
}
|
||||
});
|
||||
family = tokens.slice(lastIndex + 1).join(' ') ?? 'Verdana';
|
||||
return new Font(family, size, unit, weight, italic);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 CSS 字体字符串解析出 Font 实例,不支持的属性将被忽略
|
||||
*/
|
||||
static parse(str: string) {
|
||||
const fonts = str.split(',');
|
||||
const main = this.parseOne(fonts[0]);
|
||||
for (let i = 1; i < fonts.length; i++) {
|
||||
main.addFallback(this.parseOne(fonts[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认字体
|
||||
*/
|
||||
static setDefaults(font: Font) {
|
||||
this.defaultFamily = font.family;
|
||||
this.defaultItalic = font.italic;
|
||||
this.defaultSize = font.size;
|
||||
this.defaultSizeUnit = font.sizeUnit;
|
||||
this.defaultWeight = font.weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认字体
|
||||
*/
|
||||
static defaults(config?: Partial<IFontConfig>) {
|
||||
if (!config) {
|
||||
return new Font();
|
||||
} else {
|
||||
return new Font(
|
||||
config.family,
|
||||
config.size,
|
||||
config.sizeUnit,
|
||||
config.weight,
|
||||
config.italic
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制一个字体,同时修改字体的一部分属性
|
||||
* @param font 要复制的字体
|
||||
*/
|
||||
static clone(
|
||||
font: Font,
|
||||
{
|
||||
family = font.family,
|
||||
size = font.size,
|
||||
sizeUnit = font.sizeUnit,
|
||||
weight = font.weight,
|
||||
italic = font.italic
|
||||
}: Partial<IFontConfig>
|
||||
) {
|
||||
return new Font(family, size, sizeUnit, weight, italic);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './font';
|
||||
Reference in new issue
Block a user