@webstudio-is/fonts 0.91.0 → 0.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/constants.js +6 -10
- package/lib/font-weights.js +2 -4
- package/lib/get-font-faces.js +2 -4
- package/{src/get-font-faces.test.ts → lib/get-font-faces.test.js} +26 -29
- package/lib/index.js +1 -0
- package/lib/schema.js +6 -10
- package/lib/types/constants.d.ts +2 -0
- package/lib/types/schema.d.ts +6 -6
- package/package.json +10 -25
- package/lib/cjs/constants.js +0 -40
- package/lib/cjs/font-data.js +0 -76
- package/lib/cjs/font-weights.js +0 -61
- package/lib/cjs/get-font-faces.js +0 -70
- package/lib/cjs/index.js +0 -21
- package/lib/cjs/index.server.js +0 -24
- package/lib/cjs/package.json +0 -1
- package/lib/cjs/schema.js +0 -68
- package/lib/font-data.js +0 -56
- package/lib/index.server.js +0 -4
- package/lib/types/font-data.d.ts +0 -29
- package/lib/types/font-data.test.d.ts +0 -1
- package/lib/types/index.server.d.ts +0 -1
- package/src/__snapshots__/get-font-faces.test.ts.snap +0 -64
- package/src/constants.ts +0 -21
- package/src/font-data.test.ts +0 -70
- package/src/font-data.ts +0 -88
- package/src/font-weights.ts +0 -40
- package/src/get-font-faces.ts +0 -79
- package/src/index.server.ts +0 -1
- package/src/index.ts +0 -4
- package/src/schema.ts +0 -56
package/lib/constants.js
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
export const SYSTEM_FONTS = /* @__PURE__ */ new Map([
|
|
2
3
|
["Arial", ["Roboto", "sans-serif"]],
|
|
3
4
|
["Times New Roman", ["sans"]],
|
|
4
5
|
["Courier New", ["monospace"]],
|
|
5
6
|
["system-ui", []]
|
|
6
7
|
]);
|
|
7
|
-
const DEFAULT_FONT_FALLBACK = "sans-serif";
|
|
8
|
-
const FONT_FORMATS = /* @__PURE__ */ new Map([
|
|
8
|
+
export const DEFAULT_FONT_FALLBACK = "sans-serif";
|
|
9
|
+
export const FONT_FORMATS = /* @__PURE__ */ new Map([
|
|
9
10
|
["woff", "woff"],
|
|
10
11
|
["woff2", "woff2"],
|
|
11
12
|
["ttf", "truetype"],
|
|
12
13
|
["otf", "opentype"]
|
|
13
14
|
]);
|
|
14
|
-
const FONT_MIME_TYPES = Array.from(FONT_FORMATS.keys()).map((format) => `.${format}`).join(", ");
|
|
15
|
-
export
|
|
16
|
-
DEFAULT_FONT_FALLBACK,
|
|
17
|
-
FONT_FORMATS,
|
|
18
|
-
FONT_MIME_TYPES,
|
|
19
|
-
SYSTEM_FONTS
|
|
20
|
-
};
|
|
15
|
+
export const FONT_MIME_TYPES = Array.from(FONT_FORMATS.keys()).map((format) => `.${format}`).join(", ");
|
|
16
|
+
export const FONT_STYLES = ["normal", "italic", "oblique"];
|
package/lib/font-weights.js
CHANGED
package/lib/get-font-faces.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
import { FONT_FORMATS } from "./constants";
|
|
2
3
|
const formatFace = (asset, format, url) => {
|
|
3
4
|
if ("variationAxes" in asset.meta) {
|
|
@@ -25,7 +26,7 @@ const getKey = (asset) => {
|
|
|
25
26
|
}
|
|
26
27
|
return asset.meta.family + asset.meta.style + asset.meta.weight;
|
|
27
28
|
};
|
|
28
|
-
const getFontFaces = (assets, options) => {
|
|
29
|
+
export const getFontFaces = (assets, options) => {
|
|
29
30
|
const { assetBaseUrl } = options;
|
|
30
31
|
const faces = /* @__PURE__ */ new Map();
|
|
31
32
|
for (const asset of assets) {
|
|
@@ -45,6 +46,3 @@ const getFontFaces = (assets, options) => {
|
|
|
45
46
|
}
|
|
46
47
|
return Array.from(faces.values());
|
|
47
48
|
};
|
|
48
|
-
export {
|
|
49
|
-
getFontFaces
|
|
50
|
-
};
|
|
@@ -1,87 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
import { describe, test, expect } from "@jest/globals";
|
|
2
|
-
import { getFontFaces
|
|
3
|
-
|
|
3
|
+
import { getFontFaces } from "./get-font-faces";
|
|
4
4
|
describe("getFontFaces()", () => {
|
|
5
5
|
test("different formats", () => {
|
|
6
|
-
const assets
|
|
6
|
+
const assets = [
|
|
7
7
|
{
|
|
8
8
|
format: "woff",
|
|
9
9
|
meta: {
|
|
10
10
|
family: "Roboto",
|
|
11
11
|
style: "normal",
|
|
12
|
-
weight: 400
|
|
12
|
+
weight: 400
|
|
13
13
|
},
|
|
14
|
-
name: "roboto.woff"
|
|
14
|
+
name: "roboto.woff"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
format: "ttf",
|
|
18
18
|
meta: {
|
|
19
19
|
family: "Roboto",
|
|
20
20
|
style: "normal",
|
|
21
|
-
weight: 400
|
|
21
|
+
weight: 400
|
|
22
22
|
},
|
|
23
|
-
name: "roboto.ttf"
|
|
24
|
-
}
|
|
23
|
+
name: "roboto.ttf"
|
|
24
|
+
}
|
|
25
25
|
];
|
|
26
26
|
expect(getFontFaces(assets, { assetBaseUrl: "/fonts/" })).toMatchSnapshot();
|
|
27
27
|
});
|
|
28
|
-
|
|
29
28
|
test("different style", () => {
|
|
30
|
-
const assets
|
|
29
|
+
const assets = [
|
|
31
30
|
{
|
|
32
31
|
format: "ttf",
|
|
33
32
|
meta: {
|
|
34
33
|
family: "Roboto",
|
|
35
34
|
style: "normal",
|
|
36
|
-
weight: 400
|
|
35
|
+
weight: 400
|
|
37
36
|
},
|
|
38
|
-
name: "roboto.ttf"
|
|
37
|
+
name: "roboto.ttf"
|
|
39
38
|
},
|
|
40
39
|
{
|
|
41
40
|
format: "ttf",
|
|
42
41
|
meta: {
|
|
43
42
|
family: "Roboto",
|
|
44
43
|
style: "italic",
|
|
45
|
-
weight: 400
|
|
44
|
+
weight: 400
|
|
46
45
|
},
|
|
47
|
-
name: "roboto-italic.ttf"
|
|
48
|
-
}
|
|
46
|
+
name: "roboto-italic.ttf"
|
|
47
|
+
}
|
|
49
48
|
];
|
|
50
49
|
expect(getFontFaces(assets, { assetBaseUrl: "/fonts/" })).toMatchSnapshot();
|
|
51
50
|
});
|
|
52
|
-
|
|
53
51
|
test("different weight", () => {
|
|
54
|
-
const assets
|
|
52
|
+
const assets = [
|
|
55
53
|
{
|
|
56
54
|
format: "ttf",
|
|
57
55
|
meta: {
|
|
58
56
|
family: "Roboto",
|
|
59
57
|
style: "normal",
|
|
60
|
-
weight: 400
|
|
58
|
+
weight: 400
|
|
61
59
|
},
|
|
62
|
-
name: "roboto.ttf"
|
|
60
|
+
name: "roboto.ttf"
|
|
63
61
|
},
|
|
64
62
|
{
|
|
65
63
|
format: "ttf",
|
|
66
64
|
meta: {
|
|
67
65
|
family: "Roboto",
|
|
68
66
|
style: "normal",
|
|
69
|
-
weight: 500
|
|
67
|
+
weight: 500
|
|
70
68
|
},
|
|
71
|
-
name: "roboto-bold.ttf"
|
|
72
|
-
}
|
|
69
|
+
name: "roboto-bold.ttf"
|
|
70
|
+
}
|
|
73
71
|
];
|
|
74
72
|
expect(getFontFaces(assets, { assetBaseUrl: "/fonts/" })).toMatchSnapshot();
|
|
75
73
|
});
|
|
76
|
-
|
|
77
74
|
test("variable font", () => {
|
|
78
|
-
const assets
|
|
75
|
+
const assets = [
|
|
79
76
|
{
|
|
80
77
|
format: "ttf",
|
|
81
78
|
meta: {
|
|
82
79
|
family: "Inter",
|
|
83
80
|
variationAxes: {
|
|
84
|
-
wght: { name: "wght", min: 100, default: 400, max:
|
|
81
|
+
wght: { name: "wght", min: 100, default: 400, max: 1e3 },
|
|
85
82
|
wdth: { name: "wdth", min: 25, default: 100, max: 151 },
|
|
86
83
|
opsz: { name: "opsz", min: 8, default: 14, max: 144 },
|
|
87
84
|
GRAD: { name: "GRAD", min: -200, default: 0, max: 150 },
|
|
@@ -93,11 +90,11 @@ describe("getFontFaces()", () => {
|
|
|
93
90
|
YTUC: { name: "YTUC", min: 528, default: 712, max: 760 },
|
|
94
91
|
YTAS: { name: "YTAS", min: 649, default: 750, max: 854 },
|
|
95
92
|
YTDE: { name: "YTDE", min: -305, default: -203, max: -98 },
|
|
96
|
-
YTFI: { name: "YTFI", min: 560, default: 738, max: 788 }
|
|
97
|
-
}
|
|
93
|
+
YTFI: { name: "YTFI", min: 560, default: 738, max: 788 }
|
|
94
|
+
}
|
|
98
95
|
},
|
|
99
|
-
name: "inter.ttf"
|
|
100
|
-
}
|
|
96
|
+
name: "inter.ttf"
|
|
97
|
+
}
|
|
101
98
|
];
|
|
102
99
|
expect(getFontFaces(assets, { assetBaseUrl: "/fonts/" })).toMatchSnapshot();
|
|
103
100
|
});
|
package/lib/index.js
CHANGED
package/lib/schema.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
const FontFormat = z.union([
|
|
3
|
+
import { FONT_STYLES } from "./constants";
|
|
4
|
+
export const FontFormat = z.union([
|
|
4
5
|
z.literal("ttf"),
|
|
5
6
|
z.literal("woff"),
|
|
6
7
|
z.literal("woff2"),
|
|
@@ -31,18 +32,13 @@ const VariationAxes = z.record(
|
|
|
31
32
|
max: z.number()
|
|
32
33
|
})
|
|
33
34
|
);
|
|
34
|
-
const FontMetaStatic = z.object({
|
|
35
|
+
export const FontMetaStatic = z.object({
|
|
35
36
|
family: z.string(),
|
|
36
|
-
style: z.enum(
|
|
37
|
+
style: z.enum(FONT_STYLES),
|
|
37
38
|
weight: z.number()
|
|
38
39
|
});
|
|
39
40
|
const FontMetaVariable = z.object({
|
|
40
41
|
family: z.string(),
|
|
41
42
|
variationAxes: VariationAxes
|
|
42
43
|
});
|
|
43
|
-
const FontMeta = z.union([FontMetaStatic, FontMetaVariable]);
|
|
44
|
-
export {
|
|
45
|
-
FontFormat,
|
|
46
|
-
FontMeta,
|
|
47
|
-
FontMetaStatic
|
|
48
|
-
};
|
|
44
|
+
export const FontMeta = z.union([FontMetaStatic, FontMetaVariable]);
|
package/lib/types/constants.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export declare const SYSTEM_FONTS: Map<string, string[]>;
|
|
|
3
3
|
export declare const DEFAULT_FONT_FALLBACK = "sans-serif";
|
|
4
4
|
export declare const FONT_FORMATS: Map<FontFormat, string>;
|
|
5
5
|
export declare const FONT_MIME_TYPES: string;
|
|
6
|
+
export declare const FONT_STYLES: readonly ["normal", "italic", "oblique"];
|
|
7
|
+
export type FontStyle = (typeof FONT_STYLES)[number];
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -23,13 +23,13 @@ export declare const FontMetaStatic: z.ZodObject<{
|
|
|
23
23
|
style: z.ZodEnum<["normal", "italic", "oblique"]>;
|
|
24
24
|
weight: z.ZodNumber;
|
|
25
25
|
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
family: string;
|
|
26
27
|
style: "normal" | "italic" | "oblique";
|
|
27
28
|
weight: number;
|
|
28
|
-
family: string;
|
|
29
29
|
}, {
|
|
30
|
+
family: string;
|
|
30
31
|
style: "normal" | "italic" | "oblique";
|
|
31
32
|
weight: number;
|
|
32
|
-
family: string;
|
|
33
33
|
}>;
|
|
34
34
|
export type FontMetaStatic = z.infer<typeof FontMetaStatic>;
|
|
35
35
|
export declare const FontMeta: z.ZodUnion<[z.ZodObject<{
|
|
@@ -37,13 +37,13 @@ export declare const FontMeta: z.ZodUnion<[z.ZodObject<{
|
|
|
37
37
|
style: z.ZodEnum<["normal", "italic", "oblique"]>;
|
|
38
38
|
weight: z.ZodNumber;
|
|
39
39
|
}, "strip", z.ZodTypeAny, {
|
|
40
|
+
family: string;
|
|
40
41
|
style: "normal" | "italic" | "oblique";
|
|
41
42
|
weight: number;
|
|
42
|
-
family: string;
|
|
43
43
|
}, {
|
|
44
|
+
family: string;
|
|
44
45
|
style: "normal" | "italic" | "oblique";
|
|
45
46
|
weight: number;
|
|
46
|
-
family: string;
|
|
47
47
|
}>, z.ZodObject<{
|
|
48
48
|
family: z.ZodString;
|
|
49
49
|
variationAxes: z.ZodRecord<z.ZodEnum<["wght", "wdth", "slnt", "opsz", "ital", "GRAD", "XTRA", "XOPQ", "YOPQ", "YTLC", "YTUC", "YTAS", "YTDE", "YTFI"]>, z.ZodObject<{
|
|
@@ -63,21 +63,21 @@ export declare const FontMeta: z.ZodUnion<[z.ZodObject<{
|
|
|
63
63
|
max: number;
|
|
64
64
|
}>>;
|
|
65
65
|
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
family: string;
|
|
66
67
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
67
68
|
name: string;
|
|
68
69
|
min: number;
|
|
69
70
|
default: number;
|
|
70
71
|
max: number;
|
|
71
72
|
}>>;
|
|
72
|
-
family: string;
|
|
73
73
|
}, {
|
|
74
|
+
family: string;
|
|
74
75
|
variationAxes: Partial<Record<"wght" | "wdth" | "slnt" | "opsz" | "ital" | "GRAD" | "XTRA" | "XOPQ" | "YOPQ" | "YTLC" | "YTUC" | "YTAS" | "YTDE" | "YTFI", {
|
|
75
76
|
name: string;
|
|
76
77
|
min: number;
|
|
77
78
|
default: number;
|
|
78
79
|
max: number;
|
|
79
80
|
}>>;
|
|
80
|
-
family: string;
|
|
81
81
|
}>]>;
|
|
82
82
|
export type FontMeta = z.infer<typeof FontMeta>;
|
|
83
83
|
export {};
|
package/package.json
CHANGED
|
@@ -1,44 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/fonts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.92.0",
|
|
4
4
|
"description": "Fonts utils",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"dependencies": {
|
|
9
|
-
"fontkit": "^2.0.2"
|
|
10
|
-
},
|
|
11
8
|
"devDependencies": {
|
|
12
|
-
"@jest/globals": "^29.6.
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"typescript": "5.1.6",
|
|
9
|
+
"@jest/globals": "^29.6.4",
|
|
10
|
+
"jest": "^29.6.4",
|
|
11
|
+
"typescript": "5.2.2",
|
|
16
12
|
"zod": "^3.21.4",
|
|
17
|
-
"@webstudio-is/design-system": "^0.91.0",
|
|
18
13
|
"@webstudio-is/jest-config": "^1.0.7",
|
|
19
|
-
"@webstudio-is/scripts": "^0.0.0",
|
|
20
14
|
"@webstudio-is/tsconfig": "^1.0.7"
|
|
21
15
|
},
|
|
22
16
|
"peerDependencies": {
|
|
23
17
|
"zod": "^3.19.1"
|
|
24
18
|
},
|
|
25
19
|
"exports": {
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"import": "./lib/index.js",
|
|
30
|
-
"require": "./lib/cjs/index.js"
|
|
31
|
-
},
|
|
32
|
-
"./index.server": {
|
|
33
|
-
"source": "./src/index.server.ts",
|
|
34
|
-
"types": "./lib/types/index.server.d.ts",
|
|
35
|
-
"import": "./lib/index.server.js"
|
|
36
|
-
}
|
|
20
|
+
"source": "./src/index.ts",
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"import": "./lib/index.js"
|
|
37
23
|
},
|
|
38
24
|
"files": [
|
|
39
25
|
"lib/*",
|
|
40
|
-
"
|
|
41
|
-
"!*.test.*"
|
|
26
|
+
"!*.{test,stories}.*"
|
|
42
27
|
],
|
|
43
28
|
"license": "AGPL-3.0-or-later",
|
|
44
29
|
"private": false,
|
|
@@ -47,8 +32,8 @@
|
|
|
47
32
|
"typecheck": "tsc",
|
|
48
33
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
49
34
|
"checks": "pnpm typecheck && pnpm test",
|
|
50
|
-
"dev": "build
|
|
51
|
-
"build": "
|
|
35
|
+
"dev": "pnpm build --watch",
|
|
36
|
+
"build": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib",
|
|
52
37
|
"dts": "tsc --project tsconfig.dts.json"
|
|
53
38
|
}
|
|
54
39
|
}
|
package/lib/cjs/constants.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var constants_exports = {};
|
|
20
|
-
__export(constants_exports, {
|
|
21
|
-
DEFAULT_FONT_FALLBACK: () => DEFAULT_FONT_FALLBACK,
|
|
22
|
-
FONT_FORMATS: () => FONT_FORMATS,
|
|
23
|
-
FONT_MIME_TYPES: () => FONT_MIME_TYPES,
|
|
24
|
-
SYSTEM_FONTS: () => SYSTEM_FONTS
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(constants_exports);
|
|
27
|
-
const SYSTEM_FONTS = /* @__PURE__ */ new Map([
|
|
28
|
-
["Arial", ["Roboto", "sans-serif"]],
|
|
29
|
-
["Times New Roman", ["sans"]],
|
|
30
|
-
["Courier New", ["monospace"]],
|
|
31
|
-
["system-ui", []]
|
|
32
|
-
]);
|
|
33
|
-
const DEFAULT_FONT_FALLBACK = "sans-serif";
|
|
34
|
-
const FONT_FORMATS = /* @__PURE__ */ new Map([
|
|
35
|
-
["woff", "woff"],
|
|
36
|
-
["woff2", "woff2"],
|
|
37
|
-
["ttf", "truetype"],
|
|
38
|
-
["otf", "opentype"]
|
|
39
|
-
]);
|
|
40
|
-
const FONT_MIME_TYPES = Array.from(FONT_FORMATS.keys()).map((format) => `.${format}`).join(", ");
|
package/lib/cjs/font-data.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var font_data_exports = {};
|
|
20
|
-
__export(font_data_exports, {
|
|
21
|
-
getFontData: () => getFontData,
|
|
22
|
-
normalizeFamily: () => normalizeFamily,
|
|
23
|
-
parseSubfamily: () => parseSubfamily,
|
|
24
|
-
styles: () => styles
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(font_data_exports);
|
|
27
|
-
var import_fontkit = require("fontkit");
|
|
28
|
-
var import_font_weights = require("./font-weights");
|
|
29
|
-
const styles = ["normal", "italic", "oblique"];
|
|
30
|
-
const parseSubfamily = (subfamily) => {
|
|
31
|
-
const subfamilyLow = subfamily.toLowerCase();
|
|
32
|
-
let style = "normal";
|
|
33
|
-
for (const possibleStyle of styles) {
|
|
34
|
-
if (subfamilyLow.includes(possibleStyle)) {
|
|
35
|
-
style = possibleStyle;
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
let weight = "400";
|
|
40
|
-
for (weight in import_font_weights.fontWeights) {
|
|
41
|
-
const { names } = import_font_weights.fontWeights[weight];
|
|
42
|
-
if (names.some((name) => subfamilyLow.includes(name))) {
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return { style, weight: Number(weight) };
|
|
47
|
-
};
|
|
48
|
-
const splitAndTrim = (string) => string.split(" ").map((part) => part.trim()).filter(Boolean);
|
|
49
|
-
const normalizeFamily = (family, subfamily) => {
|
|
50
|
-
const familyParts = splitAndTrim(family);
|
|
51
|
-
const subfamilyParts = splitAndTrim(subfamily.toLowerCase());
|
|
52
|
-
const familyPartsNormalized = familyParts.filter(
|
|
53
|
-
(familyPart) => subfamilyParts.includes(familyPart.toLowerCase()) === false
|
|
54
|
-
);
|
|
55
|
-
return familyPartsNormalized.join(" ");
|
|
56
|
-
};
|
|
57
|
-
const getFontData = (data) => {
|
|
58
|
-
const font = (0, import_fontkit.create)(data);
|
|
59
|
-
const format = font.type.toLowerCase();
|
|
60
|
-
const originalFamily = font.getName("fontFamily");
|
|
61
|
-
const subfamily = font.getName("preferredSubfamily") ?? font.getName("fontSubfamily");
|
|
62
|
-
const family = normalizeFamily(originalFamily, subfamily);
|
|
63
|
-
const isVariable = Object.keys(font.variationAxes).length !== 0;
|
|
64
|
-
if (isVariable) {
|
|
65
|
-
return {
|
|
66
|
-
format,
|
|
67
|
-
family,
|
|
68
|
-
variationAxes: font.variationAxes
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
format,
|
|
73
|
-
family,
|
|
74
|
-
...parseSubfamily(subfamily)
|
|
75
|
-
};
|
|
76
|
-
};
|
package/lib/cjs/font-weights.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var font_weights_exports = {};
|
|
20
|
-
__export(font_weights_exports, {
|
|
21
|
-
fontWeights: () => fontWeights
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(font_weights_exports);
|
|
24
|
-
const fontWeights = {
|
|
25
|
-
"100": {
|
|
26
|
-
label: "Thin",
|
|
27
|
-
names: ["thin", "hairline"]
|
|
28
|
-
},
|
|
29
|
-
"200": {
|
|
30
|
-
label: "Extra Light",
|
|
31
|
-
names: ["extra light", "extralight", "ultra light", "ultralight"]
|
|
32
|
-
},
|
|
33
|
-
"300": {
|
|
34
|
-
label: "Light",
|
|
35
|
-
names: ["light"]
|
|
36
|
-
},
|
|
37
|
-
"400": {
|
|
38
|
-
label: "Normal",
|
|
39
|
-
names: ["normal", "regular"]
|
|
40
|
-
},
|
|
41
|
-
"500": {
|
|
42
|
-
label: "Medium",
|
|
43
|
-
names: ["medium"]
|
|
44
|
-
},
|
|
45
|
-
"600": {
|
|
46
|
-
label: "Semi Bold",
|
|
47
|
-
names: ["semi bold", "semibold", "demi bold", "demibold"]
|
|
48
|
-
},
|
|
49
|
-
"700": {
|
|
50
|
-
label: "Bold",
|
|
51
|
-
names: ["bold", "bold"]
|
|
52
|
-
},
|
|
53
|
-
"800": {
|
|
54
|
-
label: "Extra Bold",
|
|
55
|
-
names: ["extra bold", "extrabold", "ultra bold", "ultrabold"]
|
|
56
|
-
},
|
|
57
|
-
"900": {
|
|
58
|
-
label: "Black",
|
|
59
|
-
names: ["black", "heavy"]
|
|
60
|
-
}
|
|
61
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var get_font_faces_exports = {};
|
|
20
|
-
__export(get_font_faces_exports, {
|
|
21
|
-
getFontFaces: () => getFontFaces
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(get_font_faces_exports);
|
|
24
|
-
var import_constants = require("./constants");
|
|
25
|
-
const formatFace = (asset, format, url) => {
|
|
26
|
-
if ("variationAxes" in asset.meta) {
|
|
27
|
-
const { wght, wdth } = asset.meta?.variationAxes ?? {};
|
|
28
|
-
return {
|
|
29
|
-
fontFamily: asset.meta.family,
|
|
30
|
-
fontStyle: "normal",
|
|
31
|
-
fontDisplay: "swap",
|
|
32
|
-
src: `url('${url}') format('${format}')`,
|
|
33
|
-
fontStretch: wdth ? `${wdth.min}% ${wdth.max}%` : void 0,
|
|
34
|
-
fontWeight: wght ? `${wght.min} ${wght.max}` : void 0
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
fontFamily: asset.meta.family,
|
|
39
|
-
fontStyle: asset.meta.style,
|
|
40
|
-
fontWeight: asset.meta.weight,
|
|
41
|
-
fontDisplay: "swap",
|
|
42
|
-
src: `url('${url}') format('${format}')`
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
const getKey = (asset) => {
|
|
46
|
-
if ("variationAxes" in asset.meta) {
|
|
47
|
-
return asset.meta.family + Object.values(asset.meta.variationAxes).join("");
|
|
48
|
-
}
|
|
49
|
-
return asset.meta.family + asset.meta.style + asset.meta.weight;
|
|
50
|
-
};
|
|
51
|
-
const getFontFaces = (assets, options) => {
|
|
52
|
-
const { assetBaseUrl } = options;
|
|
53
|
-
const faces = /* @__PURE__ */ new Map();
|
|
54
|
-
for (const asset of assets) {
|
|
55
|
-
const url = `${assetBaseUrl}${asset.name}`;
|
|
56
|
-
const assetKey = getKey(asset);
|
|
57
|
-
const face = faces.get(assetKey);
|
|
58
|
-
const format = import_constants.FONT_FORMATS.get(asset.format);
|
|
59
|
-
if (format === void 0) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
if (face === void 0) {
|
|
63
|
-
const face2 = formatFace(asset, format, url);
|
|
64
|
-
faces.set(assetKey, face2);
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
face.src += `, url('${url}') format('${format}')`;
|
|
68
|
-
}
|
|
69
|
-
return Array.from(faces.values());
|
|
70
|
-
};
|
package/lib/cjs/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __copyProps = (to, from, except, desc) => {
|
|
7
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
-
for (let key of __getOwnPropNames(from))
|
|
9
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
-
}
|
|
12
|
-
return to;
|
|
13
|
-
};
|
|
14
|
-
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
-
var src_exports = {};
|
|
17
|
-
module.exports = __toCommonJS(src_exports);
|
|
18
|
-
__reExport(src_exports, require("./constants"), module.exports);
|
|
19
|
-
__reExport(src_exports, require("./get-font-faces"), module.exports);
|
|
20
|
-
__reExport(src_exports, require("./schema"), module.exports);
|
|
21
|
-
__reExport(src_exports, require("./font-weights"), module.exports);
|
package/lib/cjs/index.server.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var index_server_exports = {};
|
|
20
|
-
__export(index_server_exports, {
|
|
21
|
-
getFontData: () => import_font_data.getFontData
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(index_server_exports);
|
|
24
|
-
var import_font_data = require("./font-data");
|
package/lib/cjs/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type":"commonjs"}
|
package/lib/cjs/schema.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var schema_exports = {};
|
|
20
|
-
__export(schema_exports, {
|
|
21
|
-
FontFormat: () => FontFormat,
|
|
22
|
-
FontMeta: () => FontMeta,
|
|
23
|
-
FontMetaStatic: () => FontMetaStatic
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(schema_exports);
|
|
26
|
-
var import_zod = require("zod");
|
|
27
|
-
var import_font_data = require("./font-data");
|
|
28
|
-
const FontFormat = import_zod.z.union([
|
|
29
|
-
import_zod.z.literal("ttf"),
|
|
30
|
-
import_zod.z.literal("woff"),
|
|
31
|
-
import_zod.z.literal("woff2"),
|
|
32
|
-
import_zod.z.literal("otf")
|
|
33
|
-
]);
|
|
34
|
-
const AxisName = import_zod.z.enum([
|
|
35
|
-
"wght",
|
|
36
|
-
"wdth",
|
|
37
|
-
"slnt",
|
|
38
|
-
"opsz",
|
|
39
|
-
"ital",
|
|
40
|
-
"GRAD",
|
|
41
|
-
"XTRA",
|
|
42
|
-
"XOPQ",
|
|
43
|
-
"YOPQ",
|
|
44
|
-
"YTLC",
|
|
45
|
-
"YTUC",
|
|
46
|
-
"YTAS",
|
|
47
|
-
"YTDE",
|
|
48
|
-
"YTFI"
|
|
49
|
-
]);
|
|
50
|
-
const VariationAxes = import_zod.z.record(
|
|
51
|
-
AxisName,
|
|
52
|
-
import_zod.z.object({
|
|
53
|
-
name: import_zod.z.string(),
|
|
54
|
-
min: import_zod.z.number(),
|
|
55
|
-
default: import_zod.z.number(),
|
|
56
|
-
max: import_zod.z.number()
|
|
57
|
-
})
|
|
58
|
-
);
|
|
59
|
-
const FontMetaStatic = import_zod.z.object({
|
|
60
|
-
family: import_zod.z.string(),
|
|
61
|
-
style: import_zod.z.enum(import_font_data.styles),
|
|
62
|
-
weight: import_zod.z.number()
|
|
63
|
-
});
|
|
64
|
-
const FontMetaVariable = import_zod.z.object({
|
|
65
|
-
family: import_zod.z.string(),
|
|
66
|
-
variationAxes: VariationAxes
|
|
67
|
-
});
|
|
68
|
-
const FontMeta = import_zod.z.union([FontMetaStatic, FontMetaVariable]);
|
package/lib/font-data.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { create as createFontKit } from "fontkit";
|
|
2
|
-
import { fontWeights } from "./font-weights";
|
|
3
|
-
const styles = ["normal", "italic", "oblique"];
|
|
4
|
-
const parseSubfamily = (subfamily) => {
|
|
5
|
-
const subfamilyLow = subfamily.toLowerCase();
|
|
6
|
-
let style = "normal";
|
|
7
|
-
for (const possibleStyle of styles) {
|
|
8
|
-
if (subfamilyLow.includes(possibleStyle)) {
|
|
9
|
-
style = possibleStyle;
|
|
10
|
-
break;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
let weight = "400";
|
|
14
|
-
for (weight in fontWeights) {
|
|
15
|
-
const { names } = fontWeights[weight];
|
|
16
|
-
if (names.some((name) => subfamilyLow.includes(name))) {
|
|
17
|
-
break;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return { style, weight: Number(weight) };
|
|
21
|
-
};
|
|
22
|
-
const splitAndTrim = (string) => string.split(" ").map((part) => part.trim()).filter(Boolean);
|
|
23
|
-
const normalizeFamily = (family, subfamily) => {
|
|
24
|
-
const familyParts = splitAndTrim(family);
|
|
25
|
-
const subfamilyParts = splitAndTrim(subfamily.toLowerCase());
|
|
26
|
-
const familyPartsNormalized = familyParts.filter(
|
|
27
|
-
(familyPart) => subfamilyParts.includes(familyPart.toLowerCase()) === false
|
|
28
|
-
);
|
|
29
|
-
return familyPartsNormalized.join(" ");
|
|
30
|
-
};
|
|
31
|
-
const getFontData = (data) => {
|
|
32
|
-
const font = createFontKit(data);
|
|
33
|
-
const format = font.type.toLowerCase();
|
|
34
|
-
const originalFamily = font.getName("fontFamily");
|
|
35
|
-
const subfamily = font.getName("preferredSubfamily") ?? font.getName("fontSubfamily");
|
|
36
|
-
const family = normalizeFamily(originalFamily, subfamily);
|
|
37
|
-
const isVariable = Object.keys(font.variationAxes).length !== 0;
|
|
38
|
-
if (isVariable) {
|
|
39
|
-
return {
|
|
40
|
-
format,
|
|
41
|
-
family,
|
|
42
|
-
variationAxes: font.variationAxes
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
format,
|
|
47
|
-
family,
|
|
48
|
-
...parseSubfamily(subfamily)
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
export {
|
|
52
|
-
getFontData,
|
|
53
|
-
normalizeFamily,
|
|
54
|
-
parseSubfamily,
|
|
55
|
-
styles
|
|
56
|
-
};
|
package/lib/index.server.js
DELETED
package/lib/types/font-data.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { FontFormat, VariationAxes } from "./schema";
|
|
2
|
-
declare module "fontkit" {
|
|
3
|
-
interface Font {
|
|
4
|
-
type: string;
|
|
5
|
-
getName: (name: string) => string;
|
|
6
|
-
variationAxes: VariationAxes;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
export declare const styles: readonly ["normal", "italic", "oblique"];
|
|
10
|
-
type Style = (typeof styles)[number];
|
|
11
|
-
export declare const parseSubfamily: (subfamily: string) => {
|
|
12
|
-
style: "normal" | "italic" | "oblique";
|
|
13
|
-
weight: number;
|
|
14
|
-
};
|
|
15
|
-
export declare const normalizeFamily: (family: string, subfamily: string) => string;
|
|
16
|
-
type FontDataStatic = {
|
|
17
|
-
format: FontFormat;
|
|
18
|
-
family: string;
|
|
19
|
-
style: Style;
|
|
20
|
-
weight: number;
|
|
21
|
-
};
|
|
22
|
-
type FontDataVariable = {
|
|
23
|
-
format: FontFormat;
|
|
24
|
-
family: string;
|
|
25
|
-
variationAxes: VariationAxes;
|
|
26
|
-
};
|
|
27
|
-
type FontData = FontDataStatic | FontDataVariable;
|
|
28
|
-
export declare const getFontData: (data: Uint8Array) => FontData;
|
|
29
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { getFontData } from "./font-data";
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`getFontFaces() different formats 1`] = `
|
|
4
|
-
[
|
|
5
|
-
{
|
|
6
|
-
"fontDisplay": "swap",
|
|
7
|
-
"fontFamily": "Roboto",
|
|
8
|
-
"fontStyle": "normal",
|
|
9
|
-
"fontWeight": 400,
|
|
10
|
-
"src": "url('/fonts/roboto.woff') format('woff'), url('/fonts/roboto.ttf') format('truetype')",
|
|
11
|
-
},
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
14
|
-
|
|
15
|
-
exports[`getFontFaces() different style 1`] = `
|
|
16
|
-
[
|
|
17
|
-
{
|
|
18
|
-
"fontDisplay": "swap",
|
|
19
|
-
"fontFamily": "Roboto",
|
|
20
|
-
"fontStyle": "normal",
|
|
21
|
-
"fontWeight": 400,
|
|
22
|
-
"src": "url('/fonts/roboto.ttf') format('truetype')",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"fontDisplay": "swap",
|
|
26
|
-
"fontFamily": "Roboto",
|
|
27
|
-
"fontStyle": "italic",
|
|
28
|
-
"fontWeight": 400,
|
|
29
|
-
"src": "url('/fonts/roboto-italic.ttf') format('truetype')",
|
|
30
|
-
},
|
|
31
|
-
]
|
|
32
|
-
`;
|
|
33
|
-
|
|
34
|
-
exports[`getFontFaces() different weight 1`] = `
|
|
35
|
-
[
|
|
36
|
-
{
|
|
37
|
-
"fontDisplay": "swap",
|
|
38
|
-
"fontFamily": "Roboto",
|
|
39
|
-
"fontStyle": "normal",
|
|
40
|
-
"fontWeight": 400,
|
|
41
|
-
"src": "url('/fonts/roboto.ttf') format('truetype')",
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"fontDisplay": "swap",
|
|
45
|
-
"fontFamily": "Roboto",
|
|
46
|
-
"fontStyle": "normal",
|
|
47
|
-
"fontWeight": 500,
|
|
48
|
-
"src": "url('/fonts/roboto-bold.ttf') format('truetype')",
|
|
49
|
-
},
|
|
50
|
-
]
|
|
51
|
-
`;
|
|
52
|
-
|
|
53
|
-
exports[`getFontFaces() variable font 1`] = `
|
|
54
|
-
[
|
|
55
|
-
{
|
|
56
|
-
"fontDisplay": "swap",
|
|
57
|
-
"fontFamily": "Inter",
|
|
58
|
-
"fontStretch": "25% 151%",
|
|
59
|
-
"fontStyle": "normal",
|
|
60
|
-
"fontWeight": "100 1000",
|
|
61
|
-
"src": "url('/fonts/inter.ttf') format('truetype')",
|
|
62
|
-
},
|
|
63
|
-
]
|
|
64
|
-
`;
|
package/src/constants.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { FontFormat } from "./schema";
|
|
2
|
-
|
|
3
|
-
export const SYSTEM_FONTS = new Map([
|
|
4
|
-
["Arial", ["Roboto", "sans-serif"]],
|
|
5
|
-
["Times New Roman", ["sans"]],
|
|
6
|
-
["Courier New", ["monospace"]],
|
|
7
|
-
["system-ui", []],
|
|
8
|
-
]);
|
|
9
|
-
|
|
10
|
-
export const DEFAULT_FONT_FALLBACK = "sans-serif";
|
|
11
|
-
|
|
12
|
-
export const FONT_FORMATS: Map<FontFormat, string> = new Map([
|
|
13
|
-
["woff", "woff"],
|
|
14
|
-
["woff2", "woff2"],
|
|
15
|
-
["ttf", "truetype"],
|
|
16
|
-
["otf", "opentype"],
|
|
17
|
-
]);
|
|
18
|
-
|
|
19
|
-
export const FONT_MIME_TYPES = Array.from(FONT_FORMATS.keys())
|
|
20
|
-
.map((format) => `.${format}`)
|
|
21
|
-
.join(", ");
|
package/src/font-data.test.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "@jest/globals";
|
|
2
|
-
import { parseSubfamily, normalizeFamily } from "./font-data";
|
|
3
|
-
|
|
4
|
-
describe("font-data", () => {
|
|
5
|
-
describe("parseSubfamily()", () => {
|
|
6
|
-
test("Black Italic", () => {
|
|
7
|
-
expect(parseSubfamily("Black Italic")).toEqual({
|
|
8
|
-
style: "italic",
|
|
9
|
-
weight: 900,
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
test("Bold", () => {
|
|
13
|
-
expect(parseSubfamily("Bold")).toEqual({
|
|
14
|
-
style: "normal",
|
|
15
|
-
weight: 700,
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
test("Demi Bold Italic", () => {
|
|
19
|
-
expect(parseSubfamily("Demi Bold Italic")).toEqual({
|
|
20
|
-
style: "italic",
|
|
21
|
-
weight: 600,
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
test("Light", () => {
|
|
25
|
-
expect(parseSubfamily("Light")).toEqual({
|
|
26
|
-
style: "normal",
|
|
27
|
-
weight: 300,
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
test("Extra Light", () => {
|
|
31
|
-
expect(parseSubfamily("Extra Light")).toEqual({
|
|
32
|
-
style: "normal",
|
|
33
|
-
weight: 200,
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
test("Extra Light Italic", () => {
|
|
37
|
-
expect(parseSubfamily("Extra Light Italic")).toEqual({
|
|
38
|
-
style: "italic",
|
|
39
|
-
weight: 200,
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
test("Heavy Italic", () => {
|
|
43
|
-
expect(parseSubfamily("Heavy Italic")).toEqual({
|
|
44
|
-
style: "italic",
|
|
45
|
-
weight: 900,
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
test("Medium Italic", () => {
|
|
49
|
-
expect(parseSubfamily("Medium Italic")).toEqual({
|
|
50
|
-
style: "italic",
|
|
51
|
-
weight: 500,
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe("normalizeFamily()", () => {
|
|
57
|
-
test("basic", () => {
|
|
58
|
-
expect(normalizeFamily("Roboto Black", "Black")).toBe("Roboto");
|
|
59
|
-
expect(normalizeFamily("Roboto Light", "Light Italic")).toBe("Roboto");
|
|
60
|
-
expect(normalizeFamily("Robolder Bold", "Bold")).toBe("Robolder");
|
|
61
|
-
expect(normalizeFamily(" Roboto X Bold ", "Bold")).toBe("Roboto X");
|
|
62
|
-
expect(normalizeFamily(" 'Roboto X' Bold ", "Bold")).toBe("'Roboto X'");
|
|
63
|
-
expect(normalizeFamily(` "Roboto X" Bold `, "Bold")).toBe(`"Roboto X"`);
|
|
64
|
-
expect(normalizeFamily(`"Roboto Bold"`, "Bold")).toBe(`"Roboto Bold"`);
|
|
65
|
-
expect(normalizeFamily(`"Roboto Bold" Bold`, "Bold")).toBe(
|
|
66
|
-
`"Roboto Bold"`
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
});
|
package/src/font-data.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import type { FontFormat, VariationAxes } from "./schema";
|
|
2
|
-
import { create as createFontKit } from "fontkit";
|
|
3
|
-
import { type FontWeight, fontWeights } from "./font-weights";
|
|
4
|
-
|
|
5
|
-
// @todo sumbit this to definitely typed, they are not up to date
|
|
6
|
-
declare module "fontkit" {
|
|
7
|
-
export interface Font {
|
|
8
|
-
type: string;
|
|
9
|
-
getName: (name: string) => string;
|
|
10
|
-
variationAxes: VariationAxes;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const styles = ["normal", "italic", "oblique"] as const;
|
|
15
|
-
type Style = (typeof styles)[number];
|
|
16
|
-
|
|
17
|
-
export const parseSubfamily = (subfamily: string) => {
|
|
18
|
-
const subfamilyLow = subfamily.toLowerCase();
|
|
19
|
-
let style: Style = "normal";
|
|
20
|
-
for (const possibleStyle of styles) {
|
|
21
|
-
if (subfamilyLow.includes(possibleStyle)) {
|
|
22
|
-
style = possibleStyle;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
let weight: FontWeight = "400";
|
|
27
|
-
for (weight in fontWeights) {
|
|
28
|
-
const { names } = fontWeights[weight];
|
|
29
|
-
if (names.some((name) => subfamilyLow.includes(name))) {
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return { style, weight: Number(weight) };
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const splitAndTrim = (string: string) =>
|
|
37
|
-
string
|
|
38
|
-
.split(" ")
|
|
39
|
-
.map((part) => part.trim())
|
|
40
|
-
.filter(Boolean);
|
|
41
|
-
|
|
42
|
-
// Family name can contain additional information like "Roboto Black" or "Roboto Bold", though we need pure family name "Roboto", because the rest is already encoded in weight and style.
|
|
43
|
-
// We need a name we can reference in CSS font-family property, while CSS matches it with the right font-face considering the weight and style.
|
|
44
|
-
export const normalizeFamily = (family: string, subfamily: string) => {
|
|
45
|
-
const familyParts = splitAndTrim(family);
|
|
46
|
-
const subfamilyParts = splitAndTrim(subfamily.toLowerCase());
|
|
47
|
-
const familyPartsNormalized = familyParts.filter(
|
|
48
|
-
(familyPart) => subfamilyParts.includes(familyPart.toLowerCase()) === false
|
|
49
|
-
);
|
|
50
|
-
return familyPartsNormalized.join(" ");
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
type FontDataStatic = {
|
|
54
|
-
format: FontFormat;
|
|
55
|
-
family: string;
|
|
56
|
-
style: Style;
|
|
57
|
-
weight: number;
|
|
58
|
-
};
|
|
59
|
-
type FontDataVariable = {
|
|
60
|
-
format: FontFormat;
|
|
61
|
-
family: string;
|
|
62
|
-
variationAxes: VariationAxes;
|
|
63
|
-
};
|
|
64
|
-
type FontData = FontDataStatic | FontDataVariable;
|
|
65
|
-
|
|
66
|
-
export const getFontData = (data: Uint8Array): FontData => {
|
|
67
|
-
const font = createFontKit(data as Buffer);
|
|
68
|
-
const format = font.type.toLowerCase() as FontData["format"];
|
|
69
|
-
const originalFamily = font.getName("fontFamily");
|
|
70
|
-
const subfamily =
|
|
71
|
-
font.getName("preferredSubfamily") ?? font.getName("fontSubfamily");
|
|
72
|
-
const family = normalizeFamily(originalFamily, subfamily);
|
|
73
|
-
const isVariable = Object.keys(font.variationAxes).length !== 0;
|
|
74
|
-
|
|
75
|
-
if (isVariable) {
|
|
76
|
-
return {
|
|
77
|
-
format,
|
|
78
|
-
family,
|
|
79
|
-
variationAxes: font.variationAxes,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
format,
|
|
85
|
-
family,
|
|
86
|
-
...parseSubfamily(subfamily),
|
|
87
|
-
};
|
|
88
|
-
};
|
package/src/font-weights.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export const fontWeights = {
|
|
2
|
-
"100": {
|
|
3
|
-
label: "Thin",
|
|
4
|
-
names: ["thin", "hairline"],
|
|
5
|
-
},
|
|
6
|
-
"200": {
|
|
7
|
-
label: "Extra Light",
|
|
8
|
-
names: ["extra light", "extralight", "ultra light", "ultralight"],
|
|
9
|
-
},
|
|
10
|
-
"300": {
|
|
11
|
-
label: "Light",
|
|
12
|
-
names: ["light"],
|
|
13
|
-
},
|
|
14
|
-
"400": {
|
|
15
|
-
label: "Normal",
|
|
16
|
-
names: ["normal", "regular"],
|
|
17
|
-
},
|
|
18
|
-
"500": {
|
|
19
|
-
label: "Medium",
|
|
20
|
-
names: ["medium"],
|
|
21
|
-
},
|
|
22
|
-
"600": {
|
|
23
|
-
label: "Semi Bold",
|
|
24
|
-
names: ["semi bold", "semibold", "demi bold", "demibold"],
|
|
25
|
-
},
|
|
26
|
-
"700": {
|
|
27
|
-
label: "Bold",
|
|
28
|
-
names: ["bold", "bold"],
|
|
29
|
-
},
|
|
30
|
-
"800": {
|
|
31
|
-
label: "Extra Bold",
|
|
32
|
-
names: ["extra bold", "extrabold", "ultra bold", "ultrabold"],
|
|
33
|
-
},
|
|
34
|
-
"900": {
|
|
35
|
-
label: "Black",
|
|
36
|
-
names: ["black", "heavy"],
|
|
37
|
-
},
|
|
38
|
-
} as const;
|
|
39
|
-
|
|
40
|
-
export type FontWeight = keyof typeof fontWeights;
|
package/src/get-font-faces.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { FONT_FORMATS } from "./constants";
|
|
2
|
-
import type { FontMeta, FontFormat, FontMetaStatic } from "./schema";
|
|
3
|
-
|
|
4
|
-
export type PartialFontAsset = {
|
|
5
|
-
format: FontFormat;
|
|
6
|
-
meta: FontMeta;
|
|
7
|
-
name: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type FontFace = {
|
|
11
|
-
fontFamily: string;
|
|
12
|
-
fontDisplay: "swap" | "auto" | "block" | "fallback" | "optional";
|
|
13
|
-
src: string;
|
|
14
|
-
fontStyle?: FontMetaStatic["style"];
|
|
15
|
-
fontWeight?: number | string;
|
|
16
|
-
fontStretch?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const formatFace = (
|
|
20
|
-
asset: PartialFontAsset,
|
|
21
|
-
format: string,
|
|
22
|
-
url: string
|
|
23
|
-
): FontFace => {
|
|
24
|
-
if ("variationAxes" in asset.meta) {
|
|
25
|
-
const { wght, wdth } = asset.meta?.variationAxes ?? {};
|
|
26
|
-
return {
|
|
27
|
-
fontFamily: asset.meta.family,
|
|
28
|
-
fontStyle: "normal",
|
|
29
|
-
fontDisplay: "swap",
|
|
30
|
-
src: `url('${url}') format('${format}')`,
|
|
31
|
-
fontStretch: wdth ? `${wdth.min}% ${wdth.max}%` : undefined,
|
|
32
|
-
fontWeight: wght ? `${wght.min} ${wght.max}` : undefined,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
fontFamily: asset.meta.family,
|
|
37
|
-
fontStyle: asset.meta.style,
|
|
38
|
-
fontWeight: asset.meta.weight,
|
|
39
|
-
fontDisplay: "swap",
|
|
40
|
-
src: `url('${url}') format('${format}')`,
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const getKey = (asset: PartialFontAsset) => {
|
|
45
|
-
if ("variationAxes" in asset.meta) {
|
|
46
|
-
return asset.meta.family + Object.values(asset.meta.variationAxes).join("");
|
|
47
|
-
}
|
|
48
|
-
return asset.meta.family + asset.meta.style + asset.meta.weight;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const getFontFaces = (
|
|
52
|
-
assets: Array<PartialFontAsset>,
|
|
53
|
-
options: {
|
|
54
|
-
assetBaseUrl: string;
|
|
55
|
-
}
|
|
56
|
-
): Array<FontFace> => {
|
|
57
|
-
const { assetBaseUrl } = options;
|
|
58
|
-
const faces = new Map();
|
|
59
|
-
for (const asset of assets) {
|
|
60
|
-
const url = `${assetBaseUrl}${asset.name}`;
|
|
61
|
-
const assetKey = getKey(asset);
|
|
62
|
-
const face = faces.get(assetKey);
|
|
63
|
-
const format = FONT_FORMATS.get(asset.format);
|
|
64
|
-
if (format === undefined) {
|
|
65
|
-
// Should never happen since we allow only uploading formats we support
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (face === undefined) {
|
|
70
|
-
const face = formatFace(asset, format, url);
|
|
71
|
-
faces.set(assetKey, face);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// We already have that font face, so we need to add the new src
|
|
76
|
-
face.src += `, url('${url}') format('${format}')`;
|
|
77
|
-
}
|
|
78
|
-
return Array.from(faces.values());
|
|
79
|
-
};
|
package/src/index.server.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { getFontData } from "./font-data";
|
package/src/index.ts
DELETED
package/src/schema.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { styles } from "./font-data";
|
|
3
|
-
|
|
4
|
-
export const FontFormat = z.union([
|
|
5
|
-
z.literal("ttf"),
|
|
6
|
-
z.literal("woff"),
|
|
7
|
-
z.literal("woff2"),
|
|
8
|
-
z.literal("otf"),
|
|
9
|
-
]);
|
|
10
|
-
export type FontFormat = z.infer<typeof FontFormat>;
|
|
11
|
-
|
|
12
|
-
const AxisName = z.enum([
|
|
13
|
-
"wght",
|
|
14
|
-
"wdth",
|
|
15
|
-
"slnt",
|
|
16
|
-
"opsz",
|
|
17
|
-
"ital",
|
|
18
|
-
"GRAD",
|
|
19
|
-
"XTRA",
|
|
20
|
-
"XOPQ",
|
|
21
|
-
"YOPQ",
|
|
22
|
-
"YTLC",
|
|
23
|
-
"YTUC",
|
|
24
|
-
"YTAS",
|
|
25
|
-
"YTDE",
|
|
26
|
-
"YTFI",
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
const VariationAxes = z.record(
|
|
30
|
-
AxisName,
|
|
31
|
-
z.object({
|
|
32
|
-
name: z.string(),
|
|
33
|
-
min: z.number(),
|
|
34
|
-
default: z.number(),
|
|
35
|
-
max: z.number(),
|
|
36
|
-
})
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
export type VariationAxes = z.infer<typeof VariationAxes>;
|
|
40
|
-
|
|
41
|
-
export const FontMetaStatic = z.object({
|
|
42
|
-
family: z.string(),
|
|
43
|
-
style: z.enum(styles),
|
|
44
|
-
weight: z.number(),
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
export type FontMetaStatic = z.infer<typeof FontMetaStatic>;
|
|
48
|
-
|
|
49
|
-
const FontMetaVariable = z.object({
|
|
50
|
-
family: z.string(),
|
|
51
|
-
variationAxes: VariationAxes,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
export const FontMeta = z.union([FontMetaStatic, FontMetaVariable]);
|
|
55
|
-
|
|
56
|
-
export type FontMeta = z.infer<typeof FontMeta>;
|