fontaine 0.8.2 → 1.0.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/dist/capsize-font-metrics.mjs +1 -1
- package/dist/index.cjs +8 -10
- package/dist/index.d.cts +11 -10
- package/dist/index.d.mts +11 -10
- package/dist/index.mjs +6 -8
- package/dist/{metrics-DgPzfV2U.mjs → metrics-BfrxJdKT.mjs} +17 -12
- package/dist/{metrics-ChAPPk2j.cjs → metrics-CS5CISMK.cjs} +18 -13
- package/dist/postcss.cjs +2 -3
- package/dist/postcss.d.cts +4 -4
- package/dist/postcss.d.mts +4 -4
- package/dist/postcss.mjs +2 -3
- package/package.json +9 -11
package/dist/index.cjs
CHANGED
|
@@ -21,10 +21,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
const require_metrics = require("./metrics-
|
|
24
|
+
const require_metrics = require("./metrics-CS5CISMK.cjs");
|
|
25
25
|
let css_tree = require("css-tree");
|
|
26
|
-
let
|
|
27
|
-
let pathe = require("pathe");
|
|
26
|
+
let node_path = require("node:path");
|
|
28
27
|
let node_url = require("node:url");
|
|
29
28
|
let node_fs_promises = require("node:fs/promises");
|
|
30
29
|
let node_module = require("node:module");
|
|
@@ -37,9 +36,9 @@ const supportedExtensions = [
|
|
|
37
36
|
"woff",
|
|
38
37
|
"ttf"
|
|
39
38
|
];
|
|
40
|
-
const CSS_RE = (
|
|
41
|
-
const RELATIVE_RE = (
|
|
42
|
-
const SCSS_RE = (
|
|
39
|
+
const CSS_RE = /\.(?:sass|css|scss)(?:\?.+)?$/;
|
|
40
|
+
const RELATIVE_RE = /^(?:\.|\.\.)(?:\/|\\)/;
|
|
41
|
+
const SCSS_RE = /\.(?:sass|scss)(?:\?.+)?$/;
|
|
43
42
|
/**
|
|
44
43
|
* Replaces `//` line comments with spaces, preserving offsets.
|
|
45
44
|
*
|
|
@@ -105,7 +104,7 @@ function extractCssImports(ast) {
|
|
|
105
104
|
}
|
|
106
105
|
function resolveCssImport(specifier, importer) {
|
|
107
106
|
try {
|
|
108
|
-
if (RELATIVE_RE.test(specifier) || (0,
|
|
107
|
+
if (RELATIVE_RE.test(specifier) || (0, node_path.isAbsolute)(specifier)) return (0, node_url.fileURLToPath)(new URL(specifier, (0, node_url.pathToFileURL)(importer)));
|
|
109
108
|
return (0, node_module.createRequire)(importer).resolve(specifier.replace(/^~/, ""));
|
|
110
109
|
} catch {
|
|
111
110
|
return;
|
|
@@ -120,7 +119,6 @@ function resolveCssImport(specifier, importer) {
|
|
|
120
119
|
const FontaineTransform = (0, unplugin.createUnplugin)((options) => {
|
|
121
120
|
const cssContext = options.css = options.css || {};
|
|
122
121
|
cssContext.value = "";
|
|
123
|
-
const resolvePath = options.resolvePath || ((id) => id);
|
|
124
122
|
const fallbackName = options.fallbackName || options.overrideName || require_metrics.generateFallbackName;
|
|
125
123
|
const skipFontFaceGeneration = options.skipFontFaceGeneration || (() => false);
|
|
126
124
|
return {
|
|
@@ -137,7 +135,7 @@ const FontaineTransform = (0, unplugin.createUnplugin)((options) => {
|
|
|
137
135
|
importer: id,
|
|
138
136
|
prefix: ""
|
|
139
137
|
}));
|
|
140
|
-
if ((0,
|
|
138
|
+
if ((0, node_path.isAbsolute)(id)) {
|
|
141
139
|
const imports = extractCssImports(ast);
|
|
142
140
|
const insertionIndex = imports.length ? Math.max(...imports.map((i) => i.end)) : 0;
|
|
143
141
|
const seen = /* @__PURE__ */ new Set([id]);
|
|
@@ -169,7 +167,7 @@ const FontaineTransform = (0, unplugin.createUnplugin)((options) => {
|
|
|
169
167
|
const source = rawSource && require_metrics.withoutQueryOrFragment(rawSource);
|
|
170
168
|
if (!supportedExtensions.some((e) => source?.endsWith(e))) continue;
|
|
171
169
|
if (skipFontFaceGeneration(fallbackName(family))) continue;
|
|
172
|
-
const metrics = await require_metrics.getMetricsForFamily(family) || source && await require_metrics.readMetricsForSource(source, importer, resolvePath).catch(() => null);
|
|
170
|
+
const metrics = await require_metrics.getMetricsForFamily(family) || source && await require_metrics.readMetricsForSource(source, importer, options.resolvePath).catch(() => null);
|
|
173
171
|
/* v8 ignore next 2 */
|
|
174
172
|
if (!metrics) continue;
|
|
175
173
|
const familyFallbacks = require_metrics.resolveCategoryFallbacks({
|
package/dist/index.d.cts
CHANGED
|
@@ -8,7 +8,7 @@ import { createUnplugin } from "unplugin";
|
|
|
8
8
|
* @param {string} name - The full font family string.
|
|
9
9
|
* @returns {string} - The fallback font name.
|
|
10
10
|
*/
|
|
11
|
-
declare function generateFallbackName(name: string): string;
|
|
11
|
+
export declare function generateFallbackName(name: string): string;
|
|
12
12
|
interface FallbackOptions {
|
|
13
13
|
/**
|
|
14
14
|
* The name of the fallback font.
|
|
@@ -37,7 +37,7 @@ type FontFaceMetrics = Pick<Font, "ascent" | "descent" | "lineGap" | "unitsPerEm
|
|
|
37
37
|
* @param {FallbackOptions} fallback - The fallback options, including name, font and optional metrics. See {@link FallbackOptions}.
|
|
38
38
|
* @returns {string} - The full `@font-face` CSS declaration.
|
|
39
39
|
*/
|
|
40
|
-
declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOptions): string;
|
|
40
|
+
export declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOptions): string;
|
|
41
41
|
//#endregion
|
|
42
42
|
//#region src/metrics.d.ts
|
|
43
43
|
/**
|
|
@@ -46,15 +46,16 @@ declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOp
|
|
|
46
46
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves with the filtered font metrics or null if not found. See {@link FontFaceMetrics}.
|
|
47
47
|
* @async
|
|
48
48
|
*/
|
|
49
|
-
declare function getMetricsForFamily(family: string): Promise<FontFaceMetrics | null>;
|
|
49
|
+
export declare function getMetricsForFamily(family: string): Promise<FontFaceMetrics | null>;
|
|
50
50
|
/**
|
|
51
|
-
* Reads font metrics from a
|
|
51
|
+
* Reads font metrics from a source URL, which may be a `file:` URL or a remote one. A string
|
|
52
|
+
* that is not a URL, such as a bare path or a root-relative one, resolves to `null`.
|
|
52
53
|
* It caches the results to optimise subsequent requests for the same source.
|
|
53
|
-
* @param {URL | string} _source - The source URL
|
|
54
|
+
* @param {URL | string} _source - The source URL from which to read the font metrics.
|
|
54
55
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves to the filtered font metrics or null if the source cannot be processed.
|
|
55
56
|
* @async
|
|
56
57
|
*/
|
|
57
|
-
declare function readMetrics(_source: URL | string): Promise<FontFaceMetrics | null>;
|
|
58
|
+
export declare function readMetrics(_source: URL | string): Promise<FontFaceMetrics | null>;
|
|
58
59
|
//#endregion
|
|
59
60
|
//#region src/transform.d.ts
|
|
60
61
|
interface FontaineTransformOptions {
|
|
@@ -83,8 +84,8 @@ interface FontaineTransformOptions {
|
|
|
83
84
|
*/
|
|
84
85
|
categoryFallbacks?: Partial<Record<FontCategory, string[]>>;
|
|
85
86
|
/**
|
|
86
|
-
* Function to resolve a
|
|
87
|
-
*
|
|
87
|
+
* Function to resolve a font `src` value declared in a stylesheet to the font file it
|
|
88
|
+
* refers to, as either a URL or an absolute path on disk.
|
|
88
89
|
* @optional
|
|
89
90
|
*/
|
|
90
91
|
resolvePath?: (path: string) => string | URL;
|
|
@@ -113,6 +114,6 @@ interface FontaineTransformOptions {
|
|
|
113
114
|
* @param options - The transformation options. See {@link FontaineTransformOptions}.
|
|
114
115
|
* @returns The unplugin instance.
|
|
115
116
|
*/
|
|
116
|
-
declare const FontaineTransform: ReturnType<typeof createUnplugin<FontaineTransformOptions>>;
|
|
117
|
+
export declare const FontaineTransform: ReturnType<typeof createUnplugin<FontaineTransformOptions>>;
|
|
117
118
|
//#endregion
|
|
118
|
-
export { DEFAULT_CATEGORY_FALLBACKS, type FontCategory,
|
|
119
|
+
export { DEFAULT_CATEGORY_FALLBACKS, type FontCategory, type FontaineTransformOptions, type ResolveCategoryFallbacksOptions, resolveCategoryFallbacks };
|
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ import { createUnplugin } from "unplugin";
|
|
|
8
8
|
* @param {string} name - The full font family string.
|
|
9
9
|
* @returns {string} - The fallback font name.
|
|
10
10
|
*/
|
|
11
|
-
declare function generateFallbackName(name: string): string;
|
|
11
|
+
export declare function generateFallbackName(name: string): string;
|
|
12
12
|
interface FallbackOptions {
|
|
13
13
|
/**
|
|
14
14
|
* The name of the fallback font.
|
|
@@ -37,7 +37,7 @@ type FontFaceMetrics = Pick<Font, "ascent" | "descent" | "lineGap" | "unitsPerEm
|
|
|
37
37
|
* @param {FallbackOptions} fallback - The fallback options, including name, font and optional metrics. See {@link FallbackOptions}.
|
|
38
38
|
* @returns {string} - The full `@font-face` CSS declaration.
|
|
39
39
|
*/
|
|
40
|
-
declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOptions): string;
|
|
40
|
+
export declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOptions): string;
|
|
41
41
|
//#endregion
|
|
42
42
|
//#region src/metrics.d.ts
|
|
43
43
|
/**
|
|
@@ -46,15 +46,16 @@ declare function generateFontFace(metrics: FontFaceMetrics, fallback: FallbackOp
|
|
|
46
46
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves with the filtered font metrics or null if not found. See {@link FontFaceMetrics}.
|
|
47
47
|
* @async
|
|
48
48
|
*/
|
|
49
|
-
declare function getMetricsForFamily(family: string): Promise<FontFaceMetrics | null>;
|
|
49
|
+
export declare function getMetricsForFamily(family: string): Promise<FontFaceMetrics | null>;
|
|
50
50
|
/**
|
|
51
|
-
* Reads font metrics from a
|
|
51
|
+
* Reads font metrics from a source URL, which may be a `file:` URL or a remote one. A string
|
|
52
|
+
* that is not a URL, such as a bare path or a root-relative one, resolves to `null`.
|
|
52
53
|
* It caches the results to optimise subsequent requests for the same source.
|
|
53
|
-
* @param {URL | string} _source - The source URL
|
|
54
|
+
* @param {URL | string} _source - The source URL from which to read the font metrics.
|
|
54
55
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves to the filtered font metrics or null if the source cannot be processed.
|
|
55
56
|
* @async
|
|
56
57
|
*/
|
|
57
|
-
declare function readMetrics(_source: URL | string): Promise<FontFaceMetrics | null>;
|
|
58
|
+
export declare function readMetrics(_source: URL | string): Promise<FontFaceMetrics | null>;
|
|
58
59
|
//#endregion
|
|
59
60
|
//#region src/transform.d.ts
|
|
60
61
|
interface FontaineTransformOptions {
|
|
@@ -83,8 +84,8 @@ interface FontaineTransformOptions {
|
|
|
83
84
|
*/
|
|
84
85
|
categoryFallbacks?: Partial<Record<FontCategory, string[]>>;
|
|
85
86
|
/**
|
|
86
|
-
* Function to resolve a
|
|
87
|
-
*
|
|
87
|
+
* Function to resolve a font `src` value declared in a stylesheet to the font file it
|
|
88
|
+
* refers to, as either a URL or an absolute path on disk.
|
|
88
89
|
* @optional
|
|
89
90
|
*/
|
|
90
91
|
resolvePath?: (path: string) => string | URL;
|
|
@@ -113,6 +114,6 @@ interface FontaineTransformOptions {
|
|
|
113
114
|
* @param options - The transformation options. See {@link FontaineTransformOptions}.
|
|
114
115
|
* @returns The unplugin instance.
|
|
115
116
|
*/
|
|
116
|
-
declare const FontaineTransform: ReturnType<typeof createUnplugin<FontaineTransformOptions>>;
|
|
117
|
+
export declare const FontaineTransform: ReturnType<typeof createUnplugin<FontaineTransformOptions>>;
|
|
117
118
|
//#endregion
|
|
118
|
-
export { DEFAULT_CATEGORY_FALLBACKS, type FontCategory,
|
|
119
|
+
export { DEFAULT_CATEGORY_FALLBACKS, type FontCategory, type FontaineTransformOptions, type ResolveCategoryFallbacksOptions, resolveCategoryFallbacks };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { a as resolveCategoryFallbacks, c as generateFontFace, d as withoutQueryOrFragment, f as withoutQuotes, i as DEFAULT_CATEGORY_FALLBACKS, l as genericCSSFamilies, n as readMetrics, o as cssWideKeywords, r as readMetricsForSource, s as generateFallbackName, t as getMetricsForFamily, u as parseFontFace } from "./metrics-
|
|
1
|
+
import { a as resolveCategoryFallbacks, c as generateFontFace, d as withoutQueryOrFragment, f as withoutQuotes, i as DEFAULT_CATEGORY_FALLBACKS, l as genericCSSFamilies, n as readMetrics, o as cssWideKeywords, r as readMetricsForSource, s as generateFallbackName, t as getMetricsForFamily, u as parseFontFace } from "./metrics-BfrxJdKT.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { parse, walk } from "css-tree";
|
|
4
|
-
import {
|
|
5
|
-
import { isAbsolute } from "pathe";
|
|
4
|
+
import { isAbsolute } from "node:path";
|
|
6
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
6
|
import { readFile } from "node:fs/promises";
|
|
8
7
|
import MagicString from "magic-string";
|
|
@@ -13,9 +12,9 @@ const supportedExtensions = [
|
|
|
13
12
|
"woff",
|
|
14
13
|
"ttf"
|
|
15
14
|
];
|
|
16
|
-
const CSS_RE =
|
|
17
|
-
const RELATIVE_RE =
|
|
18
|
-
const SCSS_RE =
|
|
15
|
+
const CSS_RE = /\.(?:sass|css|scss)(?:\?.+)?$/;
|
|
16
|
+
const RELATIVE_RE = /^(?:\.|\.\.)(?:\/|\\)/;
|
|
17
|
+
const SCSS_RE = /\.(?:sass|scss)(?:\?.+)?$/;
|
|
19
18
|
/**
|
|
20
19
|
* Replaces `//` line comments with spaces, preserving offsets.
|
|
21
20
|
*
|
|
@@ -96,7 +95,6 @@ function resolveCssImport(specifier, importer) {
|
|
|
96
95
|
const FontaineTransform = createUnplugin((options) => {
|
|
97
96
|
const cssContext = options.css = options.css || {};
|
|
98
97
|
cssContext.value = "";
|
|
99
|
-
const resolvePath = options.resolvePath || ((id) => id);
|
|
100
98
|
const fallbackName = options.fallbackName || options.overrideName || generateFallbackName;
|
|
101
99
|
const skipFontFaceGeneration = options.skipFontFaceGeneration || (() => false);
|
|
102
100
|
return {
|
|
@@ -145,7 +143,7 @@ const FontaineTransform = createUnplugin((options) => {
|
|
|
145
143
|
const source = rawSource && withoutQueryOrFragment(rawSource);
|
|
146
144
|
if (!supportedExtensions.some((e) => source?.endsWith(e))) continue;
|
|
147
145
|
if (skipFontFaceGeneration(fallbackName(family))) continue;
|
|
148
|
-
const metrics = await getMetricsForFamily(family) || source && await readMetricsForSource(source, importer, resolvePath).catch(() => null);
|
|
146
|
+
const metrics = await getMetricsForFamily(family) || source && await readMetricsForSource(source, importer, options.resolvePath).catch(() => null);
|
|
149
147
|
/* v8 ignore next 2 */
|
|
150
148
|
if (!metrics) continue;
|
|
151
149
|
const familyFallbacks = resolveCategoryFallbacks({
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { generate, parse, walk } from "css-tree";
|
|
2
|
-
import {
|
|
3
|
-
import { isAbsolute } from "pathe";
|
|
4
|
-
import { hasProtocol, parseURL } from "ufo";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
5
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
4
|
import { fromUrl } from "@capsizecss/unpack";
|
|
7
5
|
import { fromFile } from "@capsizecss/unpack/fs";
|
|
@@ -12,9 +10,9 @@ function toPercentage(value, fractionDigits = 4) {
|
|
|
12
10
|
function toCSS(properties, indent = 2) {
|
|
13
11
|
return Object.entries(properties).map(([key, value]) => `${" ".repeat(indent)}${key}: ${value};`).join("\n");
|
|
14
12
|
}
|
|
15
|
-
const QUOTES_RE =
|
|
13
|
+
const QUOTES_RE = /(?:^["']|["']$)/g;
|
|
16
14
|
const withoutQuotes = (str) => str.trim().replace(QUOTES_RE, "");
|
|
17
|
-
const QUERY_OR_FRAGMENT_RE =
|
|
15
|
+
const QUERY_OR_FRAGMENT_RE = /[?#](?:.+)?$/;
|
|
18
16
|
/** Removes any `?query` or `#fragment` suffix, which is not part of the file a URL points to. */
|
|
19
17
|
function withoutQueryOrFragment(source) {
|
|
20
18
|
return source.replace(QUERY_OR_FRAGMENT_RE, "");
|
|
@@ -28,7 +26,7 @@ function withoutQueryOrFragment(source) {
|
|
|
28
26
|
* resolving against the stylesheet finds nothing.
|
|
29
27
|
*/
|
|
30
28
|
function isStylesheetRelative(source) {
|
|
31
|
-
return !
|
|
29
|
+
return !source.startsWith("/") && !URL.canParse(source);
|
|
32
30
|
}
|
|
33
31
|
const cssWideKeywords = /* @__PURE__ */ new Set([
|
|
34
32
|
"inherit",
|
|
@@ -310,19 +308,20 @@ async function getMetricsForFamily(family) {
|
|
|
310
308
|
}
|
|
311
309
|
const urlRequestCache = /* @__PURE__ */ new Map();
|
|
312
310
|
/**
|
|
313
|
-
* Reads font metrics from a
|
|
311
|
+
* Reads font metrics from a source URL, which may be a `file:` URL or a remote one. A string
|
|
312
|
+
* that is not a URL, such as a bare path or a root-relative one, resolves to `null`.
|
|
314
313
|
* It caches the results to optimise subsequent requests for the same source.
|
|
315
|
-
* @param {URL | string} _source - The source URL
|
|
314
|
+
* @param {URL | string} _source - The source URL from which to read the font metrics.
|
|
316
315
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves to the filtered font metrics or null if the source cannot be processed.
|
|
317
316
|
* @async
|
|
318
317
|
*/
|
|
319
318
|
async function readMetrics(_source) {
|
|
320
319
|
const source = typeof _source !== "string" && "href" in _source ? _source.href : _source;
|
|
321
320
|
if (source in metricCache) return metricCache[source] ?? null;
|
|
322
|
-
const
|
|
323
|
-
if (!
|
|
321
|
+
const url = typeof _source === "string" ? isAbsolute(_source) ? null : URL.parse(_source) : _source;
|
|
322
|
+
if (!url) return null;
|
|
324
323
|
let metrics;
|
|
325
|
-
if (protocol === "file:") metrics = await fromFile(fileURLToPath(source));
|
|
324
|
+
if (url.protocol === "file:") metrics = await fromFile(fileURLToPath(source));
|
|
326
325
|
else if (urlRequestCache.has(source)) metrics = await urlRequestCache.get(source);
|
|
327
326
|
else {
|
|
328
327
|
const requestPromise = fromUrl(source);
|
|
@@ -339,13 +338,19 @@ async function readMetrics(_source) {
|
|
|
339
338
|
* A scheme-less, non-rooted URL is resolved against the stylesheet first, then handed to
|
|
340
339
|
* `resolvePath` if that yields no metrics: bare package specifiers and webpack's `~` prefix
|
|
341
340
|
* look identical to stylesheet-relative paths, and only the caller's resolver can map them.
|
|
341
|
+
*
|
|
342
|
+
* `resolvePath` returns a location rather than a URL, so an absolute path it returns is a file
|
|
343
|
+
* on disk. Without a resolver `source` is still the URL the stylesheet declared, where a leading
|
|
344
|
+
* slash means the document root.
|
|
342
345
|
*/
|
|
343
346
|
async function readMetricsForSource(source, importer, resolvePath) {
|
|
344
347
|
if (importer && isAbsolute(importer) && isStylesheetRelative(source)) {
|
|
345
348
|
const metrics = await readMetrics(new URL(source, pathToFileURL(importer))).catch(() => null);
|
|
346
349
|
if (metrics) return metrics;
|
|
347
350
|
}
|
|
348
|
-
return readMetrics(
|
|
351
|
+
if (!resolvePath) return readMetrics(source);
|
|
352
|
+
const resolved = resolvePath(source);
|
|
353
|
+
return readMetrics(typeof resolved === "string" && isAbsolute(resolved) ? pathToFileURL(resolved) : resolved);
|
|
349
354
|
}
|
|
350
355
|
function fontFamilyToCamelCase(str) {
|
|
351
356
|
return str.split(/[\s|-]/).filter(Boolean).map((s, i) => `${s.charAt(0)[i > 0 ? "toUpperCase" : "toLowerCase"]()}${s.slice(1)}`).join("");
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
let css_tree = require("css-tree");
|
|
2
|
-
let
|
|
3
|
-
let pathe = require("pathe");
|
|
4
|
-
let ufo = require("ufo");
|
|
2
|
+
let node_path = require("node:path");
|
|
5
3
|
let node_url = require("node:url");
|
|
6
4
|
let _capsizecss_unpack = require("@capsizecss/unpack");
|
|
7
5
|
let _capsizecss_unpack_fs = require("@capsizecss/unpack/fs");
|
|
@@ -12,9 +10,9 @@ function toPercentage(value, fractionDigits = 4) {
|
|
|
12
10
|
function toCSS(properties, indent = 2) {
|
|
13
11
|
return Object.entries(properties).map(([key, value]) => `${" ".repeat(indent)}${key}: ${value};`).join("\n");
|
|
14
12
|
}
|
|
15
|
-
const QUOTES_RE = (
|
|
13
|
+
const QUOTES_RE = /(?:^["']|["']$)/g;
|
|
16
14
|
const withoutQuotes = (str) => str.trim().replace(QUOTES_RE, "");
|
|
17
|
-
const QUERY_OR_FRAGMENT_RE =
|
|
15
|
+
const QUERY_OR_FRAGMENT_RE = /[?#](?:.+)?$/;
|
|
18
16
|
/** Removes any `?query` or `#fragment` suffix, which is not part of the file a URL points to. */
|
|
19
17
|
function withoutQueryOrFragment(source) {
|
|
20
18
|
return source.replace(QUERY_OR_FRAGMENT_RE, "");
|
|
@@ -28,7 +26,7 @@ function withoutQueryOrFragment(source) {
|
|
|
28
26
|
* resolving against the stylesheet finds nothing.
|
|
29
27
|
*/
|
|
30
28
|
function isStylesheetRelative(source) {
|
|
31
|
-
return !
|
|
29
|
+
return !source.startsWith("/") && !URL.canParse(source);
|
|
32
30
|
}
|
|
33
31
|
const cssWideKeywords = /* @__PURE__ */ new Set([
|
|
34
32
|
"inherit",
|
|
@@ -310,19 +308,20 @@ async function getMetricsForFamily(family) {
|
|
|
310
308
|
}
|
|
311
309
|
const urlRequestCache = /* @__PURE__ */ new Map();
|
|
312
310
|
/**
|
|
313
|
-
* Reads font metrics from a
|
|
311
|
+
* Reads font metrics from a source URL, which may be a `file:` URL or a remote one. A string
|
|
312
|
+
* that is not a URL, such as a bare path or a root-relative one, resolves to `null`.
|
|
314
313
|
* It caches the results to optimise subsequent requests for the same source.
|
|
315
|
-
* @param {URL | string} _source - The source URL
|
|
314
|
+
* @param {URL | string} _source - The source URL from which to read the font metrics.
|
|
316
315
|
* @returns {Promise<FontFaceMetrics | null>} - A promise that resolves to the filtered font metrics or null if the source cannot be processed.
|
|
317
316
|
* @async
|
|
318
317
|
*/
|
|
319
318
|
async function readMetrics(_source) {
|
|
320
319
|
const source = typeof _source !== "string" && "href" in _source ? _source.href : _source;
|
|
321
320
|
if (source in metricCache) return metricCache[source] ?? null;
|
|
322
|
-
const
|
|
323
|
-
if (!
|
|
321
|
+
const url = typeof _source === "string" ? (0, node_path.isAbsolute)(_source) ? null : URL.parse(_source) : _source;
|
|
322
|
+
if (!url) return null;
|
|
324
323
|
let metrics;
|
|
325
|
-
if (protocol === "file:") metrics = await (0, _capsizecss_unpack_fs.fromFile)((0, node_url.fileURLToPath)(source));
|
|
324
|
+
if (url.protocol === "file:") metrics = await (0, _capsizecss_unpack_fs.fromFile)((0, node_url.fileURLToPath)(source));
|
|
326
325
|
else if (urlRequestCache.has(source)) metrics = await urlRequestCache.get(source);
|
|
327
326
|
else {
|
|
328
327
|
const requestPromise = (0, _capsizecss_unpack.fromUrl)(source);
|
|
@@ -339,13 +338,19 @@ async function readMetrics(_source) {
|
|
|
339
338
|
* A scheme-less, non-rooted URL is resolved against the stylesheet first, then handed to
|
|
340
339
|
* `resolvePath` if that yields no metrics: bare package specifiers and webpack's `~` prefix
|
|
341
340
|
* look identical to stylesheet-relative paths, and only the caller's resolver can map them.
|
|
341
|
+
*
|
|
342
|
+
* `resolvePath` returns a location rather than a URL, so an absolute path it returns is a file
|
|
343
|
+
* on disk. Without a resolver `source` is still the URL the stylesheet declared, where a leading
|
|
344
|
+
* slash means the document root.
|
|
342
345
|
*/
|
|
343
346
|
async function readMetricsForSource(source, importer, resolvePath) {
|
|
344
|
-
if (importer && (0,
|
|
347
|
+
if (importer && (0, node_path.isAbsolute)(importer) && isStylesheetRelative(source)) {
|
|
345
348
|
const metrics = await readMetrics(new URL(source, (0, node_url.pathToFileURL)(importer))).catch(() => null);
|
|
346
349
|
if (metrics) return metrics;
|
|
347
350
|
}
|
|
348
|
-
return readMetrics(
|
|
351
|
+
if (!resolvePath) return readMetrics(source);
|
|
352
|
+
const resolved = resolvePath(source);
|
|
353
|
+
return readMetrics(typeof resolved === "string" && (0, node_path.isAbsolute)(resolved) ? (0, node_url.pathToFileURL)(resolved) : resolved);
|
|
349
354
|
}
|
|
350
355
|
function fontFamilyToCamelCase(str) {
|
|
351
356
|
return str.split(/[\s|-]/).filter(Boolean).map((s, i) => `${s.charAt(0)[i > 0 ? "toUpperCase" : "toLowerCase"]()}${s.slice(1)}`).join("");
|
package/dist/postcss.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_metrics = require("./metrics-
|
|
1
|
+
const require_metrics = require("./metrics-CS5CISMK.cjs");
|
|
2
2
|
let css_tree = require("css-tree");
|
|
3
3
|
//#region src/postcss.ts
|
|
4
4
|
const supportedExtensions = [
|
|
@@ -23,7 +23,6 @@ function isFontFaceRule(node) {
|
|
|
23
23
|
return node?.type === "atrule" && node.name.toLowerCase() === "font-face";
|
|
24
24
|
}
|
|
25
25
|
function fontaine(options) {
|
|
26
|
-
const resolvePath = options.resolvePath || ((id) => id);
|
|
27
26
|
const fallbackName = options.fallbackName || require_metrics.generateFallbackName;
|
|
28
27
|
const skipFontFaceGeneration = options.skipFontFaceGeneration || (() => false);
|
|
29
28
|
return {
|
|
@@ -35,7 +34,7 @@ function fontaine(options) {
|
|
|
35
34
|
const source = url && require_metrics.withoutQueryOrFragment(url);
|
|
36
35
|
if (!source || !supportedExtensions.some((e) => source.endsWith(e))) continue;
|
|
37
36
|
if (skipFontFaceGeneration(fallbackName(family))) continue;
|
|
38
|
-
const metrics = await require_metrics.getMetricsForFamily(family) || await require_metrics.readMetricsForSource(source, originatingFile(rule, result), resolvePath).catch(() => null);
|
|
37
|
+
const metrics = await require_metrics.getMetricsForFamily(family) || await require_metrics.readMetricsForSource(source, originatingFile(rule, result), options.resolvePath).catch(() => null);
|
|
39
38
|
if (!metrics) continue;
|
|
40
39
|
const familyFallbacks = require_metrics.resolveCategoryFallbacks({
|
|
41
40
|
fontFamily: family,
|
package/dist/postcss.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as FontCategory } from "./fallbacks-Cj4LUWhi.cjs";
|
|
2
2
|
import { Plugin } from "postcss";
|
|
3
3
|
//#region src/postcss.d.ts
|
|
4
|
-
interface FontainePostcssOptions {
|
|
4
|
+
export interface FontainePostcssOptions {
|
|
5
5
|
/**
|
|
6
6
|
* Font family fallbacks to use.
|
|
7
7
|
* Can be an array of fallback font family names to use for all fonts,
|
|
@@ -16,8 +16,8 @@ interface FontainePostcssOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
categoryFallbacks?: Partial<Record<FontCategory, string[]>>;
|
|
18
18
|
/**
|
|
19
|
-
* Function to resolve a
|
|
20
|
-
*
|
|
19
|
+
* Function to resolve a font `src` value declared in a stylesheet to the font file it
|
|
20
|
+
* refers to, as either a URL or an absolute path on disk.
|
|
21
21
|
* @optional
|
|
22
22
|
*/
|
|
23
23
|
resolvePath?: (path: string) => string | URL;
|
|
@@ -49,4 +49,4 @@ interface FontainePlugin {
|
|
|
49
49
|
}
|
|
50
50
|
declare const plugin: FontainePlugin;
|
|
51
51
|
//#endregion
|
|
52
|
-
export {
|
|
52
|
+
export { plugin as default };
|
package/dist/postcss.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as FontCategory } from "./fallbacks-Cj4LUWhi.mjs";
|
|
2
2
|
import { Plugin } from "postcss";
|
|
3
3
|
//#region src/postcss.d.ts
|
|
4
|
-
interface FontainePostcssOptions {
|
|
4
|
+
export interface FontainePostcssOptions {
|
|
5
5
|
/**
|
|
6
6
|
* Font family fallbacks to use.
|
|
7
7
|
* Can be an array of fallback font family names to use for all fonts,
|
|
@@ -16,8 +16,8 @@ interface FontainePostcssOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
categoryFallbacks?: Partial<Record<FontCategory, string[]>>;
|
|
18
18
|
/**
|
|
19
|
-
* Function to resolve a
|
|
20
|
-
*
|
|
19
|
+
* Function to resolve a font `src` value declared in a stylesheet to the font file it
|
|
20
|
+
* refers to, as either a URL or an absolute path on disk.
|
|
21
21
|
* @optional
|
|
22
22
|
*/
|
|
23
23
|
resolvePath?: (path: string) => string | URL;
|
|
@@ -49,4 +49,4 @@ interface FontainePlugin {
|
|
|
49
49
|
}
|
|
50
50
|
declare const plugin: FontainePlugin;
|
|
51
51
|
//#endregion
|
|
52
|
-
export {
|
|
52
|
+
export { plugin as default };
|
package/dist/postcss.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveCategoryFallbacks, c as generateFontFace, d as withoutQueryOrFragment, f as withoutQuotes, l as genericCSSFamilies, o as cssWideKeywords, r as readMetricsForSource, s as generateFallbackName, t as getMetricsForFamily, u as parseFontFace } from "./metrics-
|
|
1
|
+
import { a as resolveCategoryFallbacks, c as generateFontFace, d as withoutQueryOrFragment, f as withoutQuotes, l as genericCSSFamilies, o as cssWideKeywords, r as readMetricsForSource, s as generateFallbackName, t as getMetricsForFamily, u as parseFontFace } from "./metrics-BfrxJdKT.mjs";
|
|
2
2
|
import { parse } from "css-tree";
|
|
3
3
|
//#region src/postcss.ts
|
|
4
4
|
const supportedExtensions = [
|
|
@@ -23,7 +23,6 @@ function isFontFaceRule(node) {
|
|
|
23
23
|
return node?.type === "atrule" && node.name.toLowerCase() === "font-face";
|
|
24
24
|
}
|
|
25
25
|
function fontaine(options) {
|
|
26
|
-
const resolvePath = options.resolvePath || ((id) => id);
|
|
27
26
|
const fallbackName = options.fallbackName || generateFallbackName;
|
|
28
27
|
const skipFontFaceGeneration = options.skipFontFaceGeneration || (() => false);
|
|
29
28
|
return {
|
|
@@ -35,7 +34,7 @@ function fontaine(options) {
|
|
|
35
34
|
const source = url && withoutQueryOrFragment(url);
|
|
36
35
|
if (!source || !supportedExtensions.some((e) => source.endsWith(e))) continue;
|
|
37
36
|
if (skipFontFaceGeneration(fallbackName(family))) continue;
|
|
38
|
-
const metrics = await getMetricsForFamily(family) || await readMetricsForSource(source, originatingFile(rule, result), resolvePath).catch(() => null);
|
|
37
|
+
const metrics = await getMetricsForFamily(family) || await readMetricsForSource(source, originatingFile(rule, result), options.resolvePath).catch(() => null);
|
|
39
38
|
if (!metrics) continue;
|
|
40
39
|
const familyFallbacks = resolveCategoryFallbacks({
|
|
41
40
|
fontFamily: family,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fontaine",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "Automatic font fallback based on font metrics",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Daniel Roe",
|
|
@@ -60,26 +60,24 @@
|
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@capsizecss/unpack": "^4.0.0",
|
|
62
62
|
"css-tree": "^3.1.0",
|
|
63
|
-
"magic-regexp": "^0.11.0",
|
|
64
63
|
"magic-string": "^1.0.0",
|
|
65
|
-
"pathe": "^2.0.3",
|
|
66
|
-
"ufo": "^1.6.1",
|
|
67
64
|
"unplugin": "^3.0.0"
|
|
68
65
|
},
|
|
69
66
|
"devDependencies": {
|
|
70
|
-
"@capsizecss/metrics": "4.
|
|
67
|
+
"@capsizecss/metrics": "4.3.0",
|
|
71
68
|
"@types/css-tree": "3.2.0",
|
|
72
|
-
"@types/node": "24.13.
|
|
69
|
+
"@types/node": "24.13.6",
|
|
73
70
|
"@types/serve-handler": "6.1.4",
|
|
74
|
-
"@vitest/coverage-v8": "5.0.
|
|
75
|
-
"eslint": "10.
|
|
71
|
+
"@vitest/coverage-v8": "5.0.1",
|
|
72
|
+
"eslint": "10.11.0",
|
|
76
73
|
"get-port-please": "3.2.0",
|
|
77
|
-
"
|
|
74
|
+
"magic-regexp": "0.11.0",
|
|
75
|
+
"postcss": "8.5.28",
|
|
78
76
|
"serve-handler": "6.1.7",
|
|
79
|
-
"tsdown": "0.
|
|
77
|
+
"tsdown": "0.23.0",
|
|
80
78
|
"typescript": "6.0.3",
|
|
81
79
|
"vite": "8.3.0",
|
|
82
|
-
"vitest": "5.0.
|
|
80
|
+
"vitest": "5.0.1"
|
|
83
81
|
},
|
|
84
82
|
"scripts": {
|
|
85
83
|
"build": "tsdown",
|