@webstudio-is/fonts 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Webstudio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Fonts utils
2
+
3
+ Fonts logic reusable across all systems.
@@ -0,0 +1,6 @@
1
+ import type { FontFormat } from "./types";
2
+ export declare const SYSTEM_FONTS: Map<string, string[]>;
3
+ export declare const DEFAULT_FONT_FALLBACK = "sans-serif";
4
+ export declare const FONT_FORMATS: Map<FontFormat, string>;
5
+ export declare const FONT_MIME_TYPES: string;
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,eAAO,MAAM,YAAY,uBAKvB,CAAC;AAEH,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAK/C,CAAC;AAEH,eAAO,MAAM,eAAe,QAEf,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FONT_MIME_TYPES = exports.FONT_FORMATS = exports.DEFAULT_FONT_FALLBACK = exports.SYSTEM_FONTS = void 0;
4
+ exports.SYSTEM_FONTS = new Map([
5
+ ["Arial", ["sans-serif"]],
6
+ ["Times New Roman", ["sans"]],
7
+ ["Courier New", ["monospace"]],
8
+ ["system-ui", []],
9
+ ]);
10
+ exports.DEFAULT_FONT_FALLBACK = "sans-serif";
11
+ exports.FONT_FORMATS = new Map([
12
+ ["woff", "woff"],
13
+ ["woff2", "woff2"],
14
+ ["ttf", "truetype"],
15
+ ["otf", "opentype"],
16
+ ]);
17
+ exports.FONT_MIME_TYPES = Array.from(exports.FONT_FORMATS.keys())
18
+ .map((format) => `.${format}`)
19
+ .join(", ");
@@ -0,0 +1,40 @@
1
+ import type { FontFormat } from "./types";
2
+ declare module "fontkit" {
3
+ interface Font {
4
+ type: string;
5
+ getName: (name: string) => string;
6
+ }
7
+ }
8
+ export declare const styles: readonly ["normal", "italic", "oblique"];
9
+ declare type Style = typeof styles[number];
10
+ declare const weights: {
11
+ readonly thin: 100;
12
+ readonly hairline: 100;
13
+ readonly "extra light": 200;
14
+ readonly "ultra light": 200;
15
+ readonly light: 300;
16
+ readonly normal: 400;
17
+ readonly medium: 500;
18
+ readonly "semi bold": 600;
19
+ readonly "demi bold": 600;
20
+ readonly bold: 700;
21
+ readonly "extra bold": 800;
22
+ readonly "ultra bold": 800;
23
+ readonly black: 900;
24
+ readonly heavy: 900;
25
+ };
26
+ declare type WeightKey = keyof typeof weights;
27
+ declare type WeightValue = typeof weights[WeightKey];
28
+ export declare const parseSubfamily: (subfamily: string) => {
29
+ style: "normal" | "italic" | "oblique";
30
+ weight: WeightValue;
31
+ };
32
+ declare type FontData = {
33
+ format: FontFormat;
34
+ family: string;
35
+ style: Style;
36
+ weight: WeightValue;
37
+ };
38
+ export declare const getFontData: (data: Uint8Array) => FontData;
39
+ export {};
40
+ //# sourceMappingURL=get-font-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-font-data.d.ts","sourceRoot":"","sources":["../src/get-font-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAiB,IAAI;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;KACnC;CACF;AAED,eAAO,MAAM,MAAM,0CAA2C,CAAC;AAC/D,aAAK,KAAK,GAAG,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;AAEnC,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;CAeH,CAAC;AAEX,aAAK,SAAS,GAAG,MAAM,OAAO,OAAO,CAAC;AACtC,aAAK,WAAW,GAAG,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;AAE7C,eAAO,MAAM,cAAc,cAAe,MAAM;;;CAkB/C,CAAC;AAEF,aAAK,QAAQ,GAAG;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,WAAW,SAAU,UAAU,KAAG,QAa9C,CAAC"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getFontData = exports.parseSubfamily = exports.styles = void 0;
7
+ const fontkit_1 = __importDefault(require("fontkit"));
8
+ exports.styles = ["normal", "italic", "oblique"];
9
+ const weights = {
10
+ thin: 100,
11
+ hairline: 100,
12
+ "extra light": 200,
13
+ "ultra light": 200,
14
+ light: 300,
15
+ normal: 400,
16
+ medium: 500,
17
+ "semi bold": 600,
18
+ "demi bold": 600,
19
+ bold: 700,
20
+ "extra bold": 800,
21
+ "ultra bold": 800,
22
+ black: 900,
23
+ heavy: 900,
24
+ };
25
+ const parseSubfamily = (subfamily) => {
26
+ const subfamilyLow = subfamily.toLowerCase();
27
+ let style = "normal";
28
+ for (const possibleStyle of exports.styles) {
29
+ if (subfamilyLow.includes(possibleStyle)) {
30
+ style = possibleStyle;
31
+ break;
32
+ }
33
+ }
34
+ let weight = weights.normal;
35
+ let possibleWeight;
36
+ for (possibleWeight in weights) {
37
+ if (subfamilyLow.includes(possibleWeight)) {
38
+ weight = weights[possibleWeight];
39
+ break;
40
+ }
41
+ }
42
+ return { style, weight };
43
+ };
44
+ exports.parseSubfamily = parseSubfamily;
45
+ const getFontData = (data) => {
46
+ const font = fontkit_1.default.create(data);
47
+ const format = font.type.toLowerCase();
48
+ const family = font.getName("fontFamily");
49
+ const subfamily = font.getName("preferredSubfamily") ?? font.getName("fontSubfamily");
50
+ const parsedSubfamily = (0, exports.parseSubfamily)(subfamily);
51
+ return {
52
+ format,
53
+ family,
54
+ ...parsedSubfamily,
55
+ };
56
+ };
57
+ exports.getFontData = getFontData;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-font-data.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-font-data.test.d.ts","sourceRoot":"","sources":["../src/get-font-data.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_font_data_1 = require("./get-font-data");
4
+ describe("parseSubfamily()", () => {
5
+ test("Black Italic", () => {
6
+ expect((0, get_font_data_1.parseSubfamily)("Black Italic")).toEqual({
7
+ style: "italic",
8
+ weight: 900,
9
+ });
10
+ });
11
+ test("Bold", () => {
12
+ expect((0, get_font_data_1.parseSubfamily)("Bold")).toEqual({
13
+ style: "normal",
14
+ weight: 700,
15
+ });
16
+ });
17
+ test("Demi Bold Italic", () => {
18
+ expect((0, get_font_data_1.parseSubfamily)("Demi Bold Italic")).toEqual({
19
+ style: "italic",
20
+ weight: 600,
21
+ });
22
+ });
23
+ test("Light", () => {
24
+ expect((0, get_font_data_1.parseSubfamily)("Light")).toEqual({
25
+ style: "normal",
26
+ weight: 300,
27
+ });
28
+ });
29
+ test("Extra Light", () => {
30
+ expect((0, get_font_data_1.parseSubfamily)("Extra Light")).toEqual({
31
+ style: "normal",
32
+ weight: 200,
33
+ });
34
+ });
35
+ test("Extra Light Italic", () => {
36
+ expect((0, get_font_data_1.parseSubfamily)("Extra Light Italic")).toEqual({
37
+ style: "italic",
38
+ weight: 200,
39
+ });
40
+ });
41
+ test("Heavy Italic", () => {
42
+ expect((0, get_font_data_1.parseSubfamily)("Heavy Italic")).toEqual({
43
+ style: "italic",
44
+ weight: 900,
45
+ });
46
+ });
47
+ test("Medium Italic", () => {
48
+ expect((0, get_font_data_1.parseSubfamily)("Medium Italic")).toEqual({
49
+ style: "italic",
50
+ weight: 500,
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,9 @@
1
+ import type { FontMeta } from "./schema";
2
+ import type { FontFormat } from "./types";
3
+ export declare type PartialFontAsset = {
4
+ format: FontFormat;
5
+ meta: FontMeta;
6
+ path: string;
7
+ };
8
+ export declare const getFontFaces: (assets: Array<PartialFontAsset>) => any[];
9
+ //# sourceMappingURL=get-font-faces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-font-faces.d.ts","sourceRoot":"","sources":["../src/get-font-faces.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,oBAAY,gBAAgB,GAAG;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,YAAY,WAAY,MAAM,gBAAgB,CAAC,UAqB3D,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFontFaces = void 0;
4
+ const constants_1 = require("./constants");
5
+ const getFontFaces = (assets) => {
6
+ const faces = new Map();
7
+ for (const asset of assets) {
8
+ const face = faces.get(asset.meta.family);
9
+ const format = constants_1.FONT_FORMATS.get(asset.format);
10
+ if (face === undefined) {
11
+ faces.set(asset.meta.family, {
12
+ fontFamily: asset.meta.family,
13
+ fontStyle: asset.meta.style,
14
+ fontWeight: asset.meta.weight,
15
+ fontDisplay: "swap",
16
+ src: `url('${asset.path}') format('${format}')`,
17
+ });
18
+ continue;
19
+ }
20
+ // We already have that font face, so we need to add the new src
21
+ face.src += `, url('${asset.path}') format('${format}')`;
22
+ }
23
+ return Array.from(faces.values());
24
+ };
25
+ exports.getFontFaces = getFontFaces;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-font-faces.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-font-faces.test.d.ts","sourceRoot":"","sources":["../src/get-font-faces.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_font_faces_1 = require("./get-font-faces");
4
+ describe("getFontFaces()", () => {
5
+ test("same family, but different formats", () => {
6
+ const assets = [
7
+ {
8
+ format: "woff",
9
+ meta: {
10
+ family: "Roboto",
11
+ style: "normal",
12
+ weight: 400,
13
+ },
14
+ path: "/fonts/roboto.woff",
15
+ },
16
+ {
17
+ format: "ttf",
18
+ meta: {
19
+ family: "Roboto",
20
+ style: "normal",
21
+ weight: 400,
22
+ },
23
+ path: "/fonts/roboto.ttf",
24
+ },
25
+ ];
26
+ expect((0, get_font_faces_1.getFontFaces)(assets)).toMatchSnapshot();
27
+ });
28
+ });
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./constants";
2
+ export * from "./get-font-faces";
3
+ export * from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./get-font-faces"), exports);
19
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+ export declare const FontMeta: z.ZodObject<{
3
+ family: z.ZodString;
4
+ style: z.ZodEnum<["normal", "italic", "oblique"]>;
5
+ weight: z.ZodNumber;
6
+ }, "strip", z.ZodTypeAny, {
7
+ family: string;
8
+ style: "normal" | "italic" | "oblique";
9
+ weight: number;
10
+ }, {
11
+ family: string;
12
+ style: "normal" | "italic" | "oblique";
13
+ weight: number;
14
+ }>;
15
+ export declare type FontMeta = z.infer<typeof FontMeta>;
16
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,QAAQ;;;;;;;;;;;;EAInB,CAAC;AACH,oBAAY,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC"}
package/lib/schema.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FontMeta = void 0;
4
+ const zod_1 = require("zod");
5
+ const get_font_data_1 = require("./get-font-data");
6
+ exports.FontMeta = zod_1.z.object({
7
+ family: zod_1.z.string(),
8
+ style: zod_1.z.enum(get_font_data_1.styles),
9
+ weight: zod_1.z.number(),
10
+ });
package/lib/types.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare type FontFormat = "ttf" | "woff" | "woff2" | "otf";
2
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC"}
package/lib/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@webstudio-is/fonts",
3
+ "version": "0.1.0",
4
+ "description": "Fonts utils",
5
+ "author": "Webstudio <github@webstudio.is>",
6
+ "homepage": "https://webstudio.is",
7
+ "scripts": {
8
+ "typecheck": "tsc --noEmit",
9
+ "test": "jest",
10
+ "checks": "yarn typecheck && yarn lint && yarn test",
11
+ "dev": "tsup src/index.ts --format esm,cjs --watch --out-dir=lib",
12
+ "build": "rm -fr lib tsconfig.tsbuildinfo && tsc",
13
+ "lint": "eslint ./src --ext .ts,.tsx --max-warnings 0"
14
+ },
15
+ "dependencies": {
16
+ "zod": "^3.19.1",
17
+ "fontkit": "^2.0.2"
18
+ },
19
+ "devDependencies": {
20
+ "@webstudio-is/design-system": "*",
21
+ "@webstudio-is/jest-config": "*",
22
+ "tsup": "^6.1.3",
23
+ "typescript": "4.7.4",
24
+ "@types/fontkit": "^1.8.0"
25
+ },
26
+ "main": "lib/index.js",
27
+ "types": "lib/index.d.ts",
28
+ "files": [
29
+ "lib/*",
30
+ "README.md",
31
+ "!*.test.*"
32
+ ],
33
+ "license": "MIT",
34
+ "private": false
35
+ }