fontaine 0.1.3 → 0.2.1
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/README.md +39 -0
- package/dist/index.cjs +8 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +9 -5
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -52,6 +52,8 @@ const options = {
|
|
|
52
52
|
fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'],
|
|
53
53
|
// You may need to resolve assets like `/fonts/Roboto.woff2` to a particular directory
|
|
54
54
|
resolvePath: (id) => 'file:///path/to/public/dir' + id,
|
|
55
|
+
// overrideName: (originalName) => `${name} override`
|
|
56
|
+
// sourcemap: false
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
// Vite
|
|
@@ -67,11 +69,48 @@ export default {
|
|
|
67
69
|
return config
|
|
68
70
|
},
|
|
69
71
|
}
|
|
72
|
+
|
|
73
|
+
// Docusaurus plugin - to be provided to the plugins option of docusaurus.config.js
|
|
74
|
+
// n.b. you'll likely need to require fontaine rather than importing it
|
|
75
|
+
const fontaine = require('fontaine')
|
|
76
|
+
|
|
77
|
+
function fontainePlugin(_context, _options) {
|
|
78
|
+
return {
|
|
79
|
+
name: 'fontaine-plugin',
|
|
80
|
+
configureWebpack(_config, _isServer) {
|
|
81
|
+
return {
|
|
82
|
+
plugins: [
|
|
83
|
+
fontaine.FontaineTransform.webpack(options),
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Gatsby config - gatsby-node.js
|
|
91
|
+
const { FontaineTransform } = require('fontaine')
|
|
92
|
+
|
|
93
|
+
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
|
|
94
|
+
const config = getConfig()
|
|
95
|
+
config.plugins.push(FontaineTransform.webpack(options))
|
|
96
|
+
actions.replaceWebpackConfig(config)
|
|
97
|
+
}
|
|
70
98
|
```
|
|
71
99
|
|
|
72
100
|
> **Note**
|
|
73
101
|
> If you are using Nuxt, check out [nuxt-font-metrics](https://github.com/danielroe/nuxt-font-metrics) which uses `fontaine` under the hood.
|
|
74
102
|
|
|
103
|
+
If your custom font is used through the mechanism of CSS variables, you'll need to make a tweak to your CSS variables to give fontaine a helping hand. Docusaurus is an example of this, it uses the `--ifm-font-family-base` variable to reference a custom font. In order that fontaine can connect the variable with the font, we need to add a `{Name of Font} override` suffix to that variable. What does this look like? Well imagine we were using the custom font Poppins which is referenced from the `--ifm-font-family-base` variable, we'd make the following adjustment:
|
|
104
|
+
|
|
105
|
+
```diff
|
|
106
|
+
:root {
|
|
107
|
+
/* ... */
|
|
108
|
+
- --ifm-font-family-base: 'Poppins';
|
|
109
|
+
+ --ifm-font-family-base: 'Poppins', 'Poppins override';
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Behind the scenes, there is a 'Poppins override' `@font-face` rule that has been created by fontaine. By manually adding this override font family to our CSS variable, we make our site use the fallback `@font-face` rule with the correct font metrics that fontaine generates.
|
|
113
|
+
|
|
75
114
|
## How it works
|
|
76
115
|
|
|
77
116
|
`fontaine` will scan your `@font-face` rules and generate fallback rules with the correct metrics. For example:
|
package/dist/index.cjs
CHANGED
|
@@ -98,9 +98,10 @@ const FontaineTransform = unplugin.createUnplugin(
|
|
|
98
98
|
(options) => {
|
|
99
99
|
const cssContext = options.css = options.css || {};
|
|
100
100
|
cssContext.value = "";
|
|
101
|
-
|
|
101
|
+
const resolvePath = options.resolvePath || ((id) => id);
|
|
102
|
+
const overrideName = options.overrideName || generateOverrideName;
|
|
102
103
|
function readMetricsFromId(path, importer) {
|
|
103
|
-
const resolvedPath = pathe.isAbsolute(importer) && path.startsWith(".") ? pathe.join(importer, path) :
|
|
104
|
+
const resolvedPath = pathe.isAbsolute(importer) && path.startsWith(".") ? pathe.join(importer, path) : resolvePath(path);
|
|
104
105
|
return readMetrics(resolvedPath);
|
|
105
106
|
}
|
|
106
107
|
return {
|
|
@@ -108,7 +109,7 @@ const FontaineTransform = unplugin.createUnplugin(
|
|
|
108
109
|
enforce: "pre",
|
|
109
110
|
transformInclude(id) {
|
|
110
111
|
const { pathname } = ufo.parseURL(id);
|
|
111
|
-
return
|
|
112
|
+
return CSS_RE.test(pathname) || CSS_RE.test(id);
|
|
112
113
|
},
|
|
113
114
|
async transform(code, id) {
|
|
114
115
|
const s = new MagicString(code);
|
|
@@ -124,7 +125,7 @@ const FontaineTransform = unplugin.createUnplugin(
|
|
|
124
125
|
const metrics = await getMetricsForFamily(family) || source && await readMetricsFromId(source, id).catch(() => null);
|
|
125
126
|
if (metrics) {
|
|
126
127
|
const fontFace = generateFontFace(metrics, {
|
|
127
|
-
name:
|
|
128
|
+
name: overrideName(family),
|
|
128
129
|
fallbacks: options.fallbacks
|
|
129
130
|
});
|
|
130
131
|
cssContext.value += fontFace;
|
|
@@ -168,6 +169,9 @@ const FONT_FAMILY_RE = magicRegexp.createRegExp(
|
|
|
168
169
|
magicRegexp.charNotIn(";}").times.any().as("family").after(magicRegexp.exactly("font-family:").and(magicRegexp.whitespace.times.any())).before(magicRegexp.charIn(";}").or(magicRegexp.exactly("").at.lineEnd())),
|
|
169
170
|
["g"]
|
|
170
171
|
);
|
|
172
|
+
const CSS_RE = magicRegexp.createRegExp(
|
|
173
|
+
magicRegexp.exactly(".").and(magicRegexp.anyOf("sass", "css", "scss")).at.lineEnd()
|
|
174
|
+
);
|
|
171
175
|
|
|
172
176
|
exports.FontaineTransform = FontaineTransform;
|
|
173
177
|
exports.generateFontFace = generateFontFace;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ interface FontaineTransformOptions {
|
|
|
7
7
|
};
|
|
8
8
|
fallbacks: string[];
|
|
9
9
|
resolvePath?: (path: string) => string | URL;
|
|
10
|
+
/** this should produce an unquoted font family name */
|
|
11
|
+
overrideName?: (name: string) => string;
|
|
10
12
|
sourcemap?: boolean;
|
|
11
13
|
}
|
|
12
14
|
declare const FontaineTransform: unplugin.UnpluginInstance<FontaineTransformOptions>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createUnplugin } from 'unplugin';
|
|
2
|
-
import { createRegExp, charIn, exactly, whitespace, charNotIn } from 'magic-regexp';
|
|
2
|
+
import { createRegExp, charIn, exactly, whitespace, charNotIn, anyOf } from 'magic-regexp';
|
|
3
3
|
import MagicString from 'magic-string';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { fromFile, fromUrl } from '@capsizecss/unpack';
|
|
@@ -96,9 +96,10 @@ const FontaineTransform = createUnplugin(
|
|
|
96
96
|
(options) => {
|
|
97
97
|
const cssContext = options.css = options.css || {};
|
|
98
98
|
cssContext.value = "";
|
|
99
|
-
|
|
99
|
+
const resolvePath = options.resolvePath || ((id) => id);
|
|
100
|
+
const overrideName = options.overrideName || generateOverrideName;
|
|
100
101
|
function readMetricsFromId(path, importer) {
|
|
101
|
-
const resolvedPath = isAbsolute(importer) && path.startsWith(".") ? join(importer, path) :
|
|
102
|
+
const resolvedPath = isAbsolute(importer) && path.startsWith(".") ? join(importer, path) : resolvePath(path);
|
|
102
103
|
return readMetrics(resolvedPath);
|
|
103
104
|
}
|
|
104
105
|
return {
|
|
@@ -106,7 +107,7 @@ const FontaineTransform = createUnplugin(
|
|
|
106
107
|
enforce: "pre",
|
|
107
108
|
transformInclude(id) {
|
|
108
109
|
const { pathname } = parseURL(id);
|
|
109
|
-
return
|
|
110
|
+
return CSS_RE.test(pathname) || CSS_RE.test(id);
|
|
110
111
|
},
|
|
111
112
|
async transform(code, id) {
|
|
112
113
|
const s = new MagicString(code);
|
|
@@ -122,7 +123,7 @@ const FontaineTransform = createUnplugin(
|
|
|
122
123
|
const metrics = await getMetricsForFamily(family) || source && await readMetricsFromId(source, id).catch(() => null);
|
|
123
124
|
if (metrics) {
|
|
124
125
|
const fontFace = generateFontFace(metrics, {
|
|
125
|
-
name:
|
|
126
|
+
name: overrideName(family),
|
|
126
127
|
fallbacks: options.fallbacks
|
|
127
128
|
});
|
|
128
129
|
cssContext.value += fontFace;
|
|
@@ -166,5 +167,8 @@ const FONT_FAMILY_RE = createRegExp(
|
|
|
166
167
|
charNotIn(";}").times.any().as("family").after(exactly("font-family:").and(whitespace.times.any())).before(charIn(";}").or(exactly("").at.lineEnd())),
|
|
167
168
|
["g"]
|
|
168
169
|
);
|
|
170
|
+
const CSS_RE = createRegExp(
|
|
171
|
+
exactly(".").and(anyOf("sass", "css", "scss")).at.lineEnd()
|
|
172
|
+
);
|
|
169
173
|
|
|
170
174
|
export { FontaineTransform, generateFontFace, generateOverrideName, getMetricsForFamily, readMetrics };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fontaine",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Automatic font fallback based on font metrics",
|
|
5
5
|
"repository": "unjs/fontaine",
|
|
6
6
|
"keywords": [
|
|
@@ -53,15 +53,15 @@
|
|
|
53
53
|
"pathe": "^0.3.9",
|
|
54
54
|
"scule": "^0.3.2",
|
|
55
55
|
"ufo": "^0.8.6",
|
|
56
|
-
"unplugin": "^0.
|
|
56
|
+
"unplugin": "^0.10.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@nuxtjs/eslint-config-typescript": "latest",
|
|
60
60
|
"@release-it/conventional-changelog": "latest",
|
|
61
61
|
"@types/node": "latest",
|
|
62
62
|
"@types/serve-handler": "^6.1.1",
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "^5.40.
|
|
64
|
-
"@typescript-eslint/parser": "^5.40.
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
|
64
|
+
"@typescript-eslint/parser": "^5.40.1",
|
|
65
65
|
"@vitest/coverage-c8": "^0.24.3",
|
|
66
66
|
"conventional-changelog-conventionalcommits": "latest",
|
|
67
67
|
"eslint": "latest",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"resolutions": {
|
|
84
84
|
"fontaine": "link:."
|
|
85
85
|
},
|
|
86
|
-
"packageManager": "pnpm@7.13.
|
|
86
|
+
"packageManager": "pnpm@7.13.5"
|
|
87
87
|
}
|