parent
89bbcd4a17
commit
5d38569238
11 changed files with 232 additions and 177 deletions
146
README.md
146
README.md
|
@ -53,156 +53,137 @@ Monospace Iosevka contains various stylistic sets to change the shape of certain
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss01</code></td>
|
<td colspan="2"><code>ss01</code> — Andale Mono Style</td>
|
||||||
<td colspan="3">Andale Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss01-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss01-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss01-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss01-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss02</code></td>
|
<td colspan="2"><code>ss02</code> — Anonymous Pro Style</td>
|
||||||
<td colspan="3">Anonymous Pro Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss02-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss02-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss02-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss02-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss03</code></td>
|
<td colspan="2"><code>ss03</code> — Consolas Style</td>
|
||||||
<td colspan="3">Consolas Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss03-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss03-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss03-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss03-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss04</code></td>
|
<td colspan="2"><code>ss04</code> — Menlo Style</td>
|
||||||
<td colspan="3">Menlo Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss04-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss04-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss04-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss04-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss05</code></td>
|
<td colspan="2"><code>ss05</code> — Fira Mono Style</td>
|
||||||
<td colspan="3">Fira Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss05-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss05-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss05-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss05-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss06</code></td>
|
<td colspan="2"><code>ss06</code> — Liberation Mono Style</td>
|
||||||
<td colspan="3">Liberation Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss06-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss06-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss06-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss06-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss07</code></td>
|
<td colspan="2"><code>ss07</code> — Monaco Style</td>
|
||||||
<td colspan="3">Monaco Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss07-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss07-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss07-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss07-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss08</code></td>
|
<td colspan="2"><code>ss08</code> — Pragmata Pro Style</td>
|
||||||
<td colspan="3">Pragmata Pro Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss08-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss08-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss08-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss08-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss09</code></td>
|
<td colspan="2"><code>ss09</code> — Source Code Pro Style</td>
|
||||||
<td colspan="3">Source Code Pro Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss09-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss09-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss09-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss09-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss10</code></td>
|
<td colspan="2"><code>ss10</code> — Envy Code R Style</td>
|
||||||
<td colspan="3">Envy Code R Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss10-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss10-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss10-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss10-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss11</code></td>
|
<td colspan="2"><code>ss11</code> — X Window Style</td>
|
||||||
<td colspan="3">X Window Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss11-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss11-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss11-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss11-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss12</code></td>
|
<td colspan="2"><code>ss12</code> — Ubuntu Mono Style</td>
|
||||||
<td colspan="3">Ubuntu Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss12-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss12-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss12-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss12-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss13</code></td>
|
<td colspan="2"><code>ss13</code> — Lucida Style</td>
|
||||||
<td colspan="3">Lucida Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss13-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss13-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss13-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss13-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss14</code></td>
|
<td colspan="2"><code>ss14</code> — JetBrains Mono Style</td>
|
||||||
<td colspan="3">JetBrains Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss14-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss14-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss14-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss14-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss15</code></td>
|
<td colspan="2"><code>ss15</code> — IBM Plex Mono Style</td>
|
||||||
<td colspan="3">IBM Plex Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss15-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss15-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss15-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss15-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss16</code></td>
|
<td colspan="2"><code>ss16</code> — PT Mono Style</td>
|
||||||
<td colspan="3">PT Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss16-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss16-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss16-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss16-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss17</code></td>
|
<td colspan="2"><code>ss17</code> — Recursive Mono Style</td>
|
||||||
<td colspan="3">Recursive Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss17-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss17-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss17-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss17-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss18</code></td>
|
<td colspan="2"><code>ss18</code> — Input Mono Style</td>
|
||||||
<td colspan="3">Input Mono Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss18-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss18-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss18-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss18-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>ss20</code></td>
|
<td colspan="2"><code>ss20</code> — Curly Style</td>
|
||||||
<td colspan="3">Curly Style</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><img src="images/stylistic-set-u-ss20-1.png"/></td>
|
<td><img src="images/stylistic-set-u-ss20-1.png"/></td>
|
||||||
<td colspan="2"><img src="images/stylistic-set-i-ss20-1.png"/></td>
|
<td><img src="images/stylistic-set-i-ss20-1.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -2971,16 +2952,23 @@ Subsection `variants` is used to configure character variants in the font. Prope
|
||||||
|
|
||||||
Subsection `weights` is used to change the weight grades that the custom family needs. It is a dictionary of sub-objects with properties:
|
Subsection `weights` is used to change the weight grades that the custom family needs. It is a dictionary of sub-objects with properties:
|
||||||
|
|
||||||
* `shape`: Integer, configures the weight grade of the glyphs' shapes.
|
* `shape`: Number, configures the weight grade of the glyphs' shapes.
|
||||||
* `menu`: Integer, configures the weight grade used when naming fonts.
|
* `menu`: Integer, configures the weight grade used when naming fonts.
|
||||||
* `css`: Integer, configures the weight grade used in web font CSS.
|
* `css`: Integer, configures the weight grade used in web font CSS.
|
||||||
|
|
||||||
Subsection `widths` is used to change the weight grades that the custom family needs. It is a dictionary of sub-objects with properties:
|
Subsection `widths` is used to change the width grades that the custom family needs. It is a dictionary of sub-objects with properties:
|
||||||
|
|
||||||
* `shape`: Integer, configures the width of the glyphs' shapes, measured in 1/1000 em.
|
* `shape`: Number, configures the width of the glyphs' shapes, measured in 1/1000 em.
|
||||||
* `menu`: Integer, configures the width grade used when naming fonts. The valid values are `1` to `9`, inclusive.
|
* `menu`: Integer, configures the width grade used when naming fonts. The valid values are `1` to `9`, inclusive.
|
||||||
* `css`: String, configures the [font-stretch](https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch) value used in web font CSS.
|
* `css`: String, configures the [font-stretch](https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch) value used in web font CSS.
|
||||||
|
|
||||||
|
Subsection `slopes` is used to change the slope angles and grades that the custom family needs. It is a dictionary of sub-objects with properties:
|
||||||
|
|
||||||
|
* `angle`: Number, configures the slope angle in degrees. The valid vales are `0` to `15`, inclusive.
|
||||||
|
* `shape`: String from `upright`, `italic` or `oblique`. Configures the slope used for variant selection.
|
||||||
|
* `menu`: String from `upright`, `italic` or `oblique`. Configures the slope grade used when naming fonts.
|
||||||
|
* `css`: String from `normal`, `italic` or `oblique`. Configures the [CSS font-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/font-style) value.
|
||||||
|
|
||||||
Subsection `slopes` is a simple string-to-string dictionary maps slopes (`upright`, `italic` or `oblique`) to [CSS font-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/font-style) values, represented in string.
|
Subsection `slopes` is a simple string-to-string dictionary maps slopes (`upright`, `italic` or `oblique`) to [CSS font-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/font-style) values, represented in string.
|
||||||
|
|
||||||
#### Compatibility Ligatures
|
#### Compatibility Ligatures
|
||||||
|
|
|
@ -990,11 +990,6 @@ from = ["iosevka-aile"]
|
||||||
release = true
|
release = true
|
||||||
from = ["iosevka-etoile"]
|
from = ["iosevka-etoile"]
|
||||||
|
|
||||||
[collectConfig]
|
|
||||||
distinguishWeights = true
|
|
||||||
distinguishWidths = false
|
|
||||||
distinguishSlope = false
|
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
# Weight mappings (style => shape weight, menu weight, CSS weight)
|
# Weight mappings (style => shape weight, menu weight, CSS weight)
|
||||||
# Shape weight : affects the shape of the glyphs
|
# Shape weight : affects the shape of the glyphs
|
||||||
|
@ -1048,13 +1043,24 @@ shape = 900
|
||||||
menu = 900
|
menu = 900
|
||||||
css = 900
|
css = 900
|
||||||
|
|
||||||
# slope mappings (style => CSS)
|
# slope mappings (style => slope angle, shape slope grade, menu slope, CSS slope)
|
||||||
# NOTE: This mapping does NOT affect the font's metadata, only affects
|
[slopes.upright]
|
||||||
# the webfont CSS. Change `params/parameters.toml` instead.
|
angle = 0
|
||||||
[slopes]
|
shape = "upright"
|
||||||
upright = "normal"
|
menu = "upright"
|
||||||
oblique = "oblique"
|
css = "normal"
|
||||||
italic = "italic"
|
|
||||||
|
[slopes.oblique]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "oblique"
|
||||||
|
menu = "oblique"
|
||||||
|
css = "oblique"
|
||||||
|
|
||||||
|
[slopes.italic]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "italic"
|
||||||
|
menu = "italic"
|
||||||
|
css = "italic"
|
||||||
|
|
||||||
# Width mappings (style => shape width, menu width, CSS stretch)
|
# Width mappings (style => shape width, menu width, CSS stretch)
|
||||||
# Shape width : affects the shape of the glyphs
|
# Shape width : affects the shape of the glyphs
|
||||||
|
|
22
changes/8.0.0.md
Normal file
22
changes/8.0.0.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
* \[**Breaking**\] Add support for slope customization (#599, #1165).
|
||||||
|
- Slope customization format has a major change, giving ability to customize slope grade used for variant selection, as well as slope angle.
|
||||||
|
- The format will look like this:
|
||||||
|
``` toml
|
||||||
|
[buildPlans.iosevka-custom.slopes.upright]
|
||||||
|
angle = 0 # Angle in degrees. Valid range [0, 15]
|
||||||
|
shape = "upright" # Slope grade used for shape selection. `upright` | `oblique` | `italic`
|
||||||
|
menu = "upright" # Slope grade used for naming. `upright` | `oblique` | `italic`
|
||||||
|
css = "normal" # Slope grade used for webfont CSS. `normal` | `oblique` | `italic`
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.slopes.oblique]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "oblique"
|
||||||
|
menu = "oblique"
|
||||||
|
css = "oblique"
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.slopes.italic]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "italic"
|
||||||
|
menu = "italic"
|
||||||
|
css = "italic"
|
||||||
|
```
|
|
@ -26,6 +26,7 @@ async function getParameters() {
|
||||||
const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml");
|
const PARAMETERS_TOML = path.resolve(__dirname, "../params/parameters.toml");
|
||||||
const WEIGHTS_TOML = path.resolve(__dirname, "../params/shape-weight.toml");
|
const WEIGHTS_TOML = path.resolve(__dirname, "../params/shape-weight.toml");
|
||||||
const WIDTHS_TOML = path.resolve(__dirname, "../params/shape-width.toml");
|
const WIDTHS_TOML = path.resolve(__dirname, "../params/shape-width.toml");
|
||||||
|
const SLOPES_TOML = path.resolve(__dirname, "../params/shape-slope.toml");
|
||||||
const PRIVATE_TOML = path.resolve(__dirname, "../params/private-parameters.toml");
|
const PRIVATE_TOML = path.resolve(__dirname, "../params/private-parameters.toml");
|
||||||
const VARIANTS_TOML = path.resolve(__dirname, "../params/variants.toml");
|
const VARIANTS_TOML = path.resolve(__dirname, "../params/variants.toml");
|
||||||
const LIGATIONS_TOML = path.resolve(__dirname, "../params/ligation-set.toml");
|
const LIGATIONS_TOML = path.resolve(__dirname, "../params/ligation-set.toml");
|
||||||
|
@ -35,6 +36,7 @@ async function getParameters() {
|
||||||
await tryParseToml(PARAMETERS_TOML),
|
await tryParseToml(PARAMETERS_TOML),
|
||||||
await tryParseToml(WEIGHTS_TOML),
|
await tryParseToml(WEIGHTS_TOML),
|
||||||
await tryParseToml(WIDTHS_TOML),
|
await tryParseToml(WIDTHS_TOML),
|
||||||
|
await tryParseToml(SLOPES_TOML),
|
||||||
fs.existsSync(PRIVATE_TOML) ? await tryParseToml(PRIVATE_TOML) : {}
|
fs.existsSync(PRIVATE_TOML) ? await tryParseToml(PRIVATE_TOML) : {}
|
||||||
);
|
);
|
||||||
const rawVariantsData = await tryParseToml(VARIANTS_TOML);
|
const rawVariantsData = await tryParseToml(VARIANTS_TOML);
|
||||||
|
|
|
@ -11,6 +11,7 @@ function initPara(data, argv) {
|
||||||
|
|
||||||
applyBlendingParam(argv, para, data, "shapeWeight", "weight");
|
applyBlendingParam(argv, para, data, "shapeWeight", "weight");
|
||||||
applyBlendingParam(argv, para, data, "shapeWidth", "width");
|
applyBlendingParam(argv, para, data, "shapeWidth", "width");
|
||||||
|
applyBlendingParam(argv, para, data, "shapeSlopeAngle", "slopeAngle");
|
||||||
applyAlternatesParam(argv, para, data, "slope", "slope");
|
applyAlternatesParam(argv, para, data, "slope", "slope");
|
||||||
|
|
||||||
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
if (argv.featureControl.noCvSs) para.enableCvSs = false;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "iosevka",
|
"name": "iosevka",
|
||||||
"version": "7.3.3",
|
"version": "8.0.0",
|
||||||
"main": "./font-src/index.js",
|
"main": "./font-src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node utility/ensure-verda-exists && verda -f verdafile.js",
|
"build": "node utility/ensure-verda-exists && verda -f verdafile.js",
|
||||||
|
|
|
@ -127,8 +127,6 @@ diversityII = 0.50
|
||||||
###### Slopes
|
###### Slopes
|
||||||
[slope-italic]
|
[slope-italic]
|
||||||
isItalic = true
|
isItalic = true
|
||||||
slopeAngle = 9.4
|
|
||||||
|
|
||||||
[slope-oblique]
|
[slope-oblique]
|
||||||
isOblique = true
|
isOblique = true
|
||||||
slopeAngle = 9.4
|
|
||||||
|
|
8
params/shape-slope.toml
Normal file
8
params/shape-slope.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[shapeSlopeAngle.blend.0]
|
||||||
|
slopeAngle = 0
|
||||||
|
|
||||||
|
[shapeSlopeAngle.blend.-15]
|
||||||
|
slopeAngle = -15
|
||||||
|
|
||||||
|
[shapeSlopeAngle.blend.15]
|
||||||
|
slopeAngle = 15
|
|
@ -67,14 +67,25 @@ css = 700
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
# Override default building slope sets
|
# Override default building slope sets
|
||||||
# Format: <upright|italic|oblique> = <"normal"|"italic"|"oblique">
|
|
||||||
# When this section is absent, all slopes would be built.
|
# When this section is absent, all slopes would be built.
|
||||||
|
|
||||||
[buildPlans.iosevka-custom.slopes]
|
[buildPlans.iosevka-custom.slopes.upright]
|
||||||
upright = "normal"
|
angle = 0 # Angle in degrees. Valid range [0, 15]
|
||||||
italic = "italic"
|
shape = "upright" # Slope grade used for shape selection. `upright` | `oblique` | `italic`
|
||||||
oblique = "oblique"
|
menu = "upright" # Slope grade used for naming. `upright` | `oblique` | `italic`
|
||||||
|
css = "normal" # Slope grade used for webfont CSS. `normal` | `oblique` | `italic`
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.slopes.oblique]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "oblique"
|
||||||
|
menu = "oblique"
|
||||||
|
css = "oblique"
|
||||||
|
|
||||||
|
[buildPlans.iosevka-custom.slopes.italic]
|
||||||
|
angle = 9.4
|
||||||
|
shape = "italic"
|
||||||
|
menu = "italic"
|
||||||
|
css = "italic"
|
||||||
# End slope section
|
# End slope section
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
|
|
|
@ -39,18 +39,13 @@ async function processSsOt() {
|
||||||
if (!ss.rank) continue;
|
if (!ss.rank) continue;
|
||||||
{
|
{
|
||||||
md.log(`<tr>`);
|
md.log(`<tr>`);
|
||||||
md.log(`<td><code>${ss.tag}</code></td>`);
|
md.log(`<td colspan="2"><code>${ss.tag}</code> — ${ss.description}</td>`);
|
||||||
md.log(`<td colspan="3">${ss.description}</td>`);
|
|
||||||
md.log(`</tr>`);
|
md.log(`</tr>`);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
md.log(`<tr>`);
|
md.log(`<tr>`);
|
||||||
md.log(
|
md.log(`<td><img src="images/stylistic-set-u-${ss.tag}-${ss.rank}.png"/></td>`);
|
||||||
`<td colspan="2"><img src="images/stylistic-set-u-${ss.tag}-${ss.rank}.png"/></td>`
|
md.log(`<td><img src="images/stylistic-set-i-${ss.tag}-${ss.rank}.png"/></td>`);
|
||||||
);
|
|
||||||
md.log(
|
|
||||||
`<td colspan="2"><img src="images/stylistic-set-i-${ss.tag}-${ss.rank}.png"/></td>`
|
|
||||||
);
|
|
||||||
md.log(`</tr>`);
|
md.log(`</tr>`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
164
verdafile.js
164
verdafile.js
|
@ -36,7 +36,6 @@ const webfontFormatsPages = [["woff2", "woff2"]];
|
||||||
const WIDTH_NORMAL = "normal";
|
const WIDTH_NORMAL = "normal";
|
||||||
const WEIGHT_NORMAL = "regular";
|
const WEIGHT_NORMAL = "regular";
|
||||||
const SLOPE_NORMAL = "upright";
|
const SLOPE_NORMAL = "upright";
|
||||||
const SLOPE_OBLIQUE = "oblique";
|
|
||||||
const DEFAULT_SUBFAMILY = "regular";
|
const DEFAULT_SUBFAMILY = "regular";
|
||||||
|
|
||||||
const BUILD_PLANS = "build-plans.toml";
|
const BUILD_PLANS = "build-plans.toml";
|
||||||
|
@ -189,8 +188,9 @@ const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileNa
|
||||||
serifs: bp.serifs || null,
|
serifs: bp.serifs || null,
|
||||||
spacing: bp.spacing || null,
|
spacing: bp.spacing || null,
|
||||||
weight: sfi.shapeWeight,
|
weight: sfi.shapeWeight,
|
||||||
slope: sfi.slope,
|
width: sfi.shapeWidth,
|
||||||
width: sfi.shapeWidth
|
slope: sfi.shapeSlope,
|
||||||
|
slopeAngle: sfi.shapeSlopeAngle
|
||||||
},
|
},
|
||||||
// Menu
|
// Menu
|
||||||
menu: {
|
menu: {
|
||||||
|
@ -228,23 +228,28 @@ function getSuffixMapping(weights, slopes, widths) {
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
function getSuffixMappingItem(weights, w, slopes, s, widths, wd) {
|
function getSuffixMappingItem(weights, w, slopes, s, widths, wd) {
|
||||||
|
const weightDef = wwsDefValidate("Weight definition of " + s, weights[w]);
|
||||||
|
const widthDef = wwsDefValidate("Width definition of " + s, widths[wd]);
|
||||||
|
const slopeDef = wwsDefValidate("Slope definition of " + s, slopes[s]);
|
||||||
return {
|
return {
|
||||||
// Weights
|
// Weights
|
||||||
weight: w,
|
weight: w,
|
||||||
shapeWeight: nValidate("Shape weight of " + w, weights[w].shape, VlShapeWeight),
|
shapeWeight: nValidate("Shape weight of " + w, weightDef.shape, VlShapeWeight),
|
||||||
cssWeight: nValidate("CSS weight of " + w, weights[w].css, VlCssWeight),
|
cssWeight: nValidate("CSS weight of " + w, weightDef.css, VlCssWeight),
|
||||||
menuWeight: nValidate("Menu weight of " + w, weights[w].menu, VlMenuWeight),
|
menuWeight: nValidate("Menu weight of " + w, weightDef.menu, VlMenuWeight),
|
||||||
|
|
||||||
// Widths
|
// Widths
|
||||||
width: wd,
|
width: wd,
|
||||||
shapeWidth: nValidate("Shape width of " + wd, widths[wd].shape, VlShapeWidth),
|
shapeWidth: nValidate("Shape width of " + wd, widthDef.shape, VlShapeWidth),
|
||||||
cssStretch: widths[wd].css || wd,
|
cssStretch: sValidate("CSS stretch of " + wd, widthDef.css, VlCssFontStretch),
|
||||||
menuWidth: nValidate("Menu width of " + wd, widths[wd].menu, VlMenuWidth),
|
menuWidth: nValidate("Menu width of " + wd, widthDef.menu, VlMenuWidth),
|
||||||
|
|
||||||
// Slopes
|
// Slopes
|
||||||
slope: s,
|
slope: s,
|
||||||
cssStyle: slopes[s] || s,
|
shapeSlope: sValidate("Shape slope of " + s, slopeDef.shape, VlShapeSlope),
|
||||||
menuSlope: slopes[s] || s
|
shapeSlopeAngle: nValidate("Angle of " + s, slopeDef.angle, VlSlopeAngle),
|
||||||
|
cssStyle: sValidate("CSS style of " + s, slopeDef.css, VlCssStyle),
|
||||||
|
menuSlope: sValidate("Menu slope of " + s, slopeDef.menu, VlShapeSlope)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,18 +371,11 @@ const DistWoff2 = file.make(
|
||||||
|
|
||||||
const CollectPlans = computed(`metadata:collect-plans`, async target => {
|
const CollectPlans = computed(`metadata:collect-plans`, async target => {
|
||||||
const [rawPlans] = await target.need(RawPlans);
|
const [rawPlans] = await target.need(RawPlans);
|
||||||
return await getCollectPlans(
|
return await getCollectPlans(target, rawPlans.collectPlans);
|
||||||
target,
|
|
||||||
rawPlans.collectPlans,
|
|
||||||
rawPlans.collectConfig,
|
|
||||||
fnStandardTtc
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getCollectPlans(target, rawCollectPlans, config, fnFileName) {
|
async function getCollectPlans(target, rawCollectPlans) {
|
||||||
const glyfTtcComposition = {},
|
const plans = {};
|
||||||
ttcComposition = {},
|
|
||||||
plans = {};
|
|
||||||
|
|
||||||
let allCollectableGroups = new Set();
|
let allCollectableGroups = new Set();
|
||||||
for (const collectPrefix in rawCollectPlans) {
|
for (const collectPrefix in rawCollectPlans) {
|
||||||
|
@ -392,65 +390,60 @@ async function getCollectPlans(target, rawCollectPlans, config, fnFileName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const collectPrefix in amendedRawCollectPlans) {
|
for (const collectPrefix in amendedRawCollectPlans) {
|
||||||
const groupFileList = new Set();
|
const glyfTtcComposition = {};
|
||||||
|
const ttcComposition = {};
|
||||||
const collect = amendedRawCollectPlans[collectPrefix];
|
const collect = amendedRawCollectPlans[collectPrefix];
|
||||||
if (!collect || !collect.from || !collect.from.length) continue;
|
if (!collect || !collect.from || !collect.from.length) continue;
|
||||||
|
|
||||||
for (const prefix of collect.from) {
|
for (const prefix of collect.from) {
|
||||||
const [gri] = await target.need(BuildPlanOf(prefix));
|
const [gri] = await target.need(BuildPlanOf(prefix));
|
||||||
const ttfFileNameSet = new Set(gri.targets);
|
const ttfFileNameSet = new Set(gri.targets);
|
||||||
const suffixMapping = getSuffixMapping(gri.weights, gri.slopes, gri.widths);
|
const suffixMap = getSuffixMapping(gri.weights, gri.slopes, gri.widths);
|
||||||
for (const suffix in suffixMapping) {
|
for (const suffix in suffixMap) {
|
||||||
const sfi = suffixMapping[suffix];
|
const sfi = suffixMap[suffix];
|
||||||
const ttcFileName = fnFileName(
|
|
||||||
config,
|
|
||||||
collectPrefix,
|
|
||||||
sfi.weight,
|
|
||||||
sfi.width,
|
|
||||||
sfi.slope
|
|
||||||
);
|
|
||||||
const glyfTtcFileName = fnFileName(
|
|
||||||
{ ...config, distinguishWidths: true, distinguishWhetherUpright: true },
|
|
||||||
collectPrefix,
|
|
||||||
sfi.weight,
|
|
||||||
sfi.width,
|
|
||||||
sfi.slope
|
|
||||||
);
|
|
||||||
|
|
||||||
const ttfTargetName = makeFileName(prefix, suffix);
|
const ttfTargetName = makeFileName(prefix, suffix);
|
||||||
if (!ttfFileNameSet.has(ttfTargetName)) continue;
|
if (!ttfFileNameSet.has(ttfTargetName)) continue;
|
||||||
|
|
||||||
|
const glyfTtcFileName = fnStandardTtc(true, collectPrefix, suffixMap, sfi);
|
||||||
if (!glyfTtcComposition[glyfTtcFileName]) glyfTtcComposition[glyfTtcFileName] = [];
|
if (!glyfTtcComposition[glyfTtcFileName]) glyfTtcComposition[glyfTtcFileName] = [];
|
||||||
glyfTtcComposition[glyfTtcFileName].push({ dir: prefix, file: ttfTargetName });
|
glyfTtcComposition[glyfTtcFileName].push({ dir: prefix, file: ttfTargetName });
|
||||||
|
|
||||||
|
const ttcFileName = fnStandardTtc(false, collectPrefix, suffixMap, sfi);
|
||||||
if (!ttcComposition[ttcFileName]) ttcComposition[ttcFileName] = [];
|
if (!ttcComposition[ttcFileName]) ttcComposition[ttcFileName] = [];
|
||||||
ttcComposition[ttcFileName].push(glyfTtcFileName);
|
ttcComposition[ttcFileName].push(glyfTtcFileName);
|
||||||
|
|
||||||
groupFileList.add(ttcFileName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plans[collectPrefix] = {
|
plans[collectPrefix] = {
|
||||||
ttcContents: [...groupFileList],
|
glyfTtcComposition,
|
||||||
|
ttcComposition,
|
||||||
groupDecomposition: [...collect.from],
|
groupDecomposition: [...collect.from],
|
||||||
inRelease: !!collect.release,
|
inRelease: !!collect.release,
|
||||||
isAmended: !!collect.isAmended
|
isAmended: !!collect.isAmended
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return { glyfTtcComposition, ttcComposition, plans };
|
return plans;
|
||||||
}
|
}
|
||||||
function fnStandardTtc(collectConfig, prefix, w, wd, s) {
|
|
||||||
const ttcSuffix = makeSuffix(
|
function fnStandardTtc(fIsGlyfTtc, prefix, suffixMapping, sfi) {
|
||||||
collectConfig.distinguishWeights ? w : WEIGHT_NORMAL,
|
let optimalSfi = null,
|
||||||
collectConfig.distinguishWidths ? wd : WIDTH_NORMAL,
|
maxScore = 0;
|
||||||
collectConfig.distinguishSlope
|
for (const ttcSuffix in suffixMapping) {
|
||||||
? s
|
const sfiT = suffixMapping[ttcSuffix];
|
||||||
: collectConfig.distinguishWhetherUpright
|
if (sfi.shapeWeight !== sfiT.shapeWeight) continue;
|
||||||
? s === SLOPE_NORMAL
|
if (sfi.shapeWidth !== sfiT.shapeWidth) continue;
|
||||||
? SLOPE_NORMAL
|
if (fIsGlyfTtc && sfi.shapeSlopeAngle !== sfiT.shapeSlopeAngle) continue;
|
||||||
: SLOPE_OBLIQUE
|
const score =
|
||||||
: SLOPE_NORMAL,
|
(sfiT.weight === WEIGHT_NORMAL ? 1 : 0) +
|
||||||
DEFAULT_SUBFAMILY
|
(sfiT.width === WIDTH_NORMAL ? 1 : 0) +
|
||||||
);
|
(sfiT.slope === SLOPE_NORMAL ? 1 : 0);
|
||||||
return `${prefix}-${ttcSuffix}`;
|
if (!optimalSfi || score > maxScore) {
|
||||||
|
maxScore = score;
|
||||||
|
optimalSfi = sfiT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!optimalSfi) throw new Error("Unreachable: TTC name decision");
|
||||||
|
return `${prefix}-${makeSuffix(optimalSfi.weight, optimalSfi.width, optimalSfi.slope)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -464,25 +457,25 @@ const CollectedSuperTtcFile = file.make(
|
||||||
cgr => `${DIST_SUPER_TTC}/${cgr}.ttc`,
|
cgr => `${DIST_SUPER_TTC}/${cgr}.ttc`,
|
||||||
async (target, out, cgr) => {
|
async (target, out, cgr) => {
|
||||||
const [cp] = await target.need(CollectPlans, de(out.dir));
|
const [cp] = await target.need(CollectPlans, de(out.dir));
|
||||||
const parts = Array.from(new Set(cp.plans[cgr].ttcContents));
|
const parts = Array.from(Object.keys(cp[cgr].glyfTtcComposition));
|
||||||
const [inputs] = await target.need(parts.map(pt => CollectedTtcFile(cgr, pt)));
|
const [inputs] = await target.need(parts.map(pt => GlyfTtc(cgr, pt)));
|
||||||
await buildCompositeTtc(out, inputs);
|
await buildCompositeTtc(out, inputs);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const CollectedTtcFile = file.make(
|
const CollectedTtcFile = file.make(
|
||||||
(cgr, f) => `${BUILD}/ttc-collect/${cgr}/ttc/${f}.ttc`,
|
(cgr, f) => `${BUILD}/ttc-collect/${cgr}/${f}.ttc`,
|
||||||
async (target, out, gr, f) => {
|
async (target, out, cgr, f) => {
|
||||||
const [cp] = await target.need(CollectPlans, de`${out.dir}`);
|
const [cp] = await target.need(CollectPlans, de`${out.dir}`);
|
||||||
const parts = Array.from(new Set(cp.ttcComposition[f]));
|
const parts = Array.from(new Set(cp[cgr].ttcComposition[f]));
|
||||||
const [inputs] = await target.need(parts.map(pt => GlyfTtc(gr, pt)));
|
const [inputs] = await target.need(parts.map(pt => GlyfTtc(cgr, pt)));
|
||||||
await buildCompositeTtc(out, inputs);
|
await buildCompositeTtc(out, inputs);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const GlyfTtc = file.make(
|
const GlyfTtc = file.make(
|
||||||
(cgr, f) => `${BUILD}/glyf-ttc/${cgr}/${f}.ttc`,
|
(cgr, f) => `${BUILD}/glyf-ttc/${cgr}/${f}.ttc`,
|
||||||
async (target, out, gr, f) => {
|
async (target, out, cgr, f) => {
|
||||||
const [cp] = await target.need(CollectPlans);
|
const [cp] = await target.need(CollectPlans);
|
||||||
const parts = cp.glyfTtcComposition[f];
|
const parts = cp[cgr].glyfTtcComposition[f];
|
||||||
await buildGlyphSharingTtc(target, parts, out);
|
await buildGlyphSharingTtc(target, parts, out);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -508,13 +501,13 @@ async function buildGlyphSharingTtc(target, parts, out) {
|
||||||
const TtcArchiveFile = file.make(
|
const TtcArchiveFile = file.make(
|
||||||
(cgr, version) => `${ARCHIVE_DIR}/ttc-${cgr}-${version}.zip`,
|
(cgr, version) => `${ARCHIVE_DIR}/ttc-${cgr}-${version}.zip`,
|
||||||
async (target, out, cgr) => {
|
async (target, out, cgr) => {
|
||||||
const [collectPlans] = await target.need(CollectPlans, de`${out.dir}`);
|
const [cp] = await target.need(CollectPlans, de`${out.dir}`);
|
||||||
const ttcFiles = Array.from(new Set(collectPlans.plans[cgr].ttcContents));
|
const ttcFiles = Array.from(Object.keys(cp[cgr].ttcComposition));
|
||||||
await target.need(ttcFiles.map(pt => CollectedTtcFile(cgr, pt)));
|
await target.need(ttcFiles.map(pt => CollectedTtcFile(cgr, pt)));
|
||||||
|
|
||||||
// Packaging
|
// Packaging
|
||||||
await rm(out.full);
|
await rm(out.full);
|
||||||
await cd(`${BUILD}/ttc-collect/${cgr}/ttc`).run(
|
await cd(`${BUILD}/ttc-collect/${cgr}`).run(
|
||||||
["7z", "a"],
|
["7z", "a"],
|
||||||
["-tzip", "-r", "-mx=9"],
|
["-tzip", "-r", "-mx=9"],
|
||||||
`../../../../${out.full}`,
|
`../../../../${out.full}`,
|
||||||
|
@ -795,7 +788,7 @@ phony(`clean`, async () => {
|
||||||
phony(`release`, async target => {
|
phony(`release`, async target => {
|
||||||
const [collectPlans] = await target.need(CollectPlans);
|
const [collectPlans] = await target.need(CollectPlans);
|
||||||
let goals = [];
|
let goals = [];
|
||||||
for (const [cgr, plan] of Object.entries(collectPlans.plans)) {
|
for (const [cgr, plan] of Object.entries(collectPlans)) {
|
||||||
if (!plan.inRelease) continue;
|
if (!plan.inRelease) continue;
|
||||||
goals.push(ReleaseGroup(cgr));
|
goals.push(ReleaseGroup(cgr));
|
||||||
}
|
}
|
||||||
|
@ -804,7 +797,7 @@ phony(`release`, async target => {
|
||||||
});
|
});
|
||||||
const ReleaseGroup = phony.group("release-group", async (target, cgr) => {
|
const ReleaseGroup = phony.group("release-group", async (target, cgr) => {
|
||||||
const [version, collectPlans] = await target.need(Version, CollectPlans);
|
const [version, collectPlans] = await target.need(Version, CollectPlans);
|
||||||
const subGroups = collectPlans.plans[cgr].groupDecomposition;
|
const subGroups = collectPlans[cgr].groupDecomposition;
|
||||||
|
|
||||||
let goals = [TtcArchiveFile(cgr, version), SuperTtcArchiveFile(cgr, version)];
|
let goals = [TtcArchiveFile(cgr, version), SuperTtcArchiveFile(cgr, version)];
|
||||||
for (const gr of subGroups) {
|
for (const gr of subGroups) {
|
||||||
|
@ -887,6 +880,7 @@ const Parameters = task(`meta:parameters`, async target => {
|
||||||
sfu`params/parameters.toml`,
|
sfu`params/parameters.toml`,
|
||||||
sfu`params/shape-weight.toml`,
|
sfu`params/shape-weight.toml`,
|
||||||
sfu`params/shape-width.toml`,
|
sfu`params/shape-width.toml`,
|
||||||
|
sfu`params/shape-slope.toml`,
|
||||||
ofu`params/private-parameters.toml`,
|
ofu`params/private-parameters.toml`,
|
||||||
sfu`params/variants.toml`,
|
sfu`params/variants.toml`,
|
||||||
sfu`params/ligation-set.toml`
|
sfu`params/ligation-set.toml`
|
||||||
|
@ -937,6 +931,13 @@ function validateRecommendedWeight(w, value, label) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value validation
|
// Value validation
|
||||||
|
function wwsDefValidate(key, obj) {
|
||||||
|
if (!obj || typeof obj === "string") {
|
||||||
|
throw new TypeError(`${key} is invalid.`);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
function nValidate(key, v, validator) {
|
function nValidate(key, v, validator) {
|
||||||
if (validator.fixup) v = validator.fix(v);
|
if (validator.fixup) v = validator.fix(v);
|
||||||
if (typeof v !== "number" || !isFinite(v) || !validator.validate(v)) {
|
if (typeof v !== "number" || !isFinite(v) || !validator.validate(v)) {
|
||||||
|
@ -968,3 +969,26 @@ const VlShapeWidth = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const VlMenuWidth = { validate: x => x >= 1 && x <= 9 && x % 1 === 0 };
|
const VlMenuWidth = { validate: x => x >= 1 && x <= 9 && x % 1 === 0 };
|
||||||
|
const VlSlopeAngle = { validate: x => x >= 0 && x <= 15 };
|
||||||
|
|
||||||
|
function sValidate(key, v, validator) {
|
||||||
|
if (validator.fixup) v = validator.fix(v);
|
||||||
|
if (typeof v !== "string" || !validator.validate(v)) {
|
||||||
|
throw new TypeError(`${key} = ${v} is not a valid string.`);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
const VlShapeSlope = { validate: x => x === "upright" || x === "oblique" || x === "italic" };
|
||||||
|
const VlCssStyle = { validate: x => x === "normal" || x === "oblique" || x === "italic" };
|
||||||
|
const VlCssFontStretch = {
|
||||||
|
validate: x =>
|
||||||
|
x == "ultra-condensed" ||
|
||||||
|
x == "extra-condensed" ||
|
||||||
|
x == "condensed" ||
|
||||||
|
x == "semi-condensed" ||
|
||||||
|
x == "normal" ||
|
||||||
|
x == "semi-expanded" ||
|
||||||
|
x == "expanded" ||
|
||||||
|
x == "extra-expanded" ||
|
||||||
|
x == "ultra-expanded"
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue