its-swiss 0.7.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a5ab32d42d182f1c9e0c8efa403cd4f90857e9c8c1b955ba31023330b1095a8
4
- data.tar.gz: 0f39bbc46d60b4374c1334b644c28e4d061cc9778b08b2f9a474cbb4aa824341
3
+ metadata.gz: 21caf44ed83d26ed7f70b687206792252028a0120aafd843821322c776f0fd87
4
+ data.tar.gz: 3b3612935647de8dfc405d205a3adf6fd170b5f0493faa34d019cac02d237e4c
5
5
  SHA512:
6
- metadata.gz: 80cff5ca6de7fa9aa649fcf1146e78b9315d61531ef4968875e895db0abd8bd636fd07b33df90b41b38a6374a530945459e4032534c303f599774abd347182c3
7
- data.tar.gz: 3090006b7c520d07a88c2527a73b18f94cac3a484d225c393d88e8956a1bb8af559e26dafc8bc384922659892f0577638fa9174d2c03a168b23e43fb8f7d4171
6
+ metadata.gz: 478f0c8ded5c737b5370029359ab04c18b717b6398a9c2c6c3985a2289ebe8e8fc62797e3303d3e05bc593a23b0c565ae0fc88591afb53de3d4f20be638f54a5
7
+ data.tar.gz: 8bcebb3045f45a9d2a9a636b1544936badd47ea45c16ff6f8bcf79c45fe9706b1663da0f70b7d8ad262744d70589f8ede84fca40f30ca4289f4944df30c35ed6
data/CHANGELOG.md CHANGED
@@ -2,10 +2,21 @@
2
2
 
3
3
  Semver. Consumers pin `~> 0.1`.
4
4
 
5
- ## Unreleased
5
+ ## 0.7.1 — 2026-09-04
6
6
 
7
7
  ### Fixed
8
8
 
9
+ - **A control's text was clipped at the rule.** The faces put every
10
+ baseline on the under edge of its line by giving the type no descent, and
11
+ a browser centres an input's text in a box of its own and clips it there
12
+ — so with `font: inherit` every descender in a field, a select or a
13
+ textarea was cut off. A control's text is now set in `--font-family`
14
+ itself, with the font's own metrics, on one line inside the two-line box:
15
+ the box stays on the grid and the type is deliberately off the baseline,
16
+ the way a button's label is. `its_swiss_typeface` takes `family:` and
17
+ declares the typeface under its own name as well, so that `--font-family`
18
+ resolves to it.
19
+
9
20
  - **A pinned specimen stopped existing.** Pages replaces the whole site on
10
21
  every deploy, so a version-stamped page survives only if the run writes it
11
22
  again. The step meant to carry them forward read them back off the live
@@ -20,7 +31,7 @@ Semver. Consumers pin `~> 0.1`.
20
31
  from itself. `0.6.0.html` is restored there, rendered from the 0.6.0 commit
21
32
  by that version's own `bin/specimen`.
22
33
 
23
- ## 0.7.0 — Unreleased
34
+ ## 0.7.0 — 2026-09-04
24
35
 
25
36
  Every baseline on the grid, in every browser, whatever the font.
26
37
 
data/README.md CHANGED
@@ -177,11 +177,18 @@ its label centred in it, and its label's baseline is the one baseline in the
177
177
  library that is not on a line — on purpose, since a label set on the second
178
178
  line of a two-line box reads as a field with a rule under it. Its keyline is
179
179
  an inset shadow rather than a border, so the box is the label's line and two
180
- paddings and nothing else. A control's own text is the one thing neither
181
- mechanism reaches in Safari: an input, a select or a textarea cannot be
182
- trimmed, and with the faces ignored its text sits where the font puts it, a
183
- few pixels above the line. The box is on the grid; the type in it is the
184
- font's until WebKit honours the descriptors.
180
+ paddings and nothing else.
181
+
182
+ A control's own text an input, a select, a textarea — is the other run of
183
+ type the library takes off the baseline, and it does so on purpose too. A
184
+ browser sets that text in a box of its own, centres it there and clips it
185
+ there, and on a face with no descent every descender was cut off at the
186
+ rule. So the text is set in `--font-family` itself, with the font's own
187
+ metrics, on one line inside the two-line box: the box is on the grid, the
188
+ line is the ladder's, and where the baseline falls inside the line is the
189
+ font's. Which means the typeface has to exist under its own name as well as
190
+ under the faces; `its_swiss_typeface` declares it there when given
191
+ `family:`, and `--font-family` names it.
185
192
 
186
193
  #### Your own typeface
187
194
 
@@ -191,6 +198,7 @@ it:
191
198
  ```erb
192
199
  <%= its_swiss_typeface regular: "inter-regular.woff2", bold: "inter-bold.woff2" %>
193
200
  <%= its_swiss_typeface variable: "inter.woff2", mono: "jetbrains-mono.woff2" %>
201
+ <%= its_swiss_typeface variable: "inter.woff2", family: "Inter" %>
194
202
  ```
195
203
 
196
204
  Put it after the library's stylesheets. The declarations are unlayered, and a
@@ -273,7 +273,18 @@
273
273
  border-bottom: var(--rule-hair) solid var(--ink);
274
274
  background: transparent;
275
275
  color: inherit;
276
- font: inherit;
276
+ /* The one run of type in the library that is taken off the baseline on
277
+ purpose. A control's text is not in the document: the browser sets it
278
+ in a box of its own, centres it there and clips it there, and on a
279
+ face with no descent — the faces are what put every other baseline on
280
+ the under edge of its line — every descender was cut off at the rule.
281
+ So the type is set in the typeface itself, with the font's own
282
+ metrics, on one line. The line is the ladder's and so is the box; only
283
+ where the baseline falls inside the line is the font's. */
284
+ font-family: var(--font-family);
285
+ font-size: inherit;
286
+ font-weight: inherit;
287
+ line-height: var(--line);
277
288
  /* No padding above it: the rule belongs under the text, not a line's
278
289
  height below it, or the label reads as belonging to nothing. */
279
290
  block-size: var(--line-2);
@@ -202,8 +202,9 @@
202
202
  trimmed through its first and last child and would be corrected twice.
203
203
  A list item or a definition holds either, so they are trimmed only when
204
204
  they hold text. A control's own text — an input, a select, a textarea —
205
- cannot be trimmed, and in a browser without the faces it sits where the
206
- font puts it.
205
+ is not trimmed and not on a face: components.css sets it in the typeface
206
+ itself, on one line, because a browser centres it in a box of its own
207
+ and clips it there.
207
208
 
208
209
  The correction is written for the browser that uses it. WebKit trims a
209
210
  line to its cap height rounded to a whole pixel while its cap unit is
@@ -40,21 +40,29 @@ module ItsSwiss
40
40
  #
41
41
  # <%= its_swiss_typeface regular: "inter-regular.woff2", bold: "inter-bold.woff2" %>
42
42
  # <%= its_swiss_typeface variable: "inter.woff2", mono: "jetbrains-mono.woff2" %>
43
+ # <%= its_swiss_typeface variable: "inter.woff2", family: "Inter" %>
44
+ #
45
+ # family: declares the same files under the font's own name as well, with
46
+ # the font's own metrics. A control's text is set in --font-family rather
47
+ # than on a face, so an application that names its typeface there needs
48
+ # the name to resolve — or its fields are set in the machine's grotesque
49
+ # while the page around them is set in its own.
43
50
  #
44
51
  # Unlayered, which is how it wins: a name defined outside a layer beats
45
52
  # the same name defined inside one, the way the application's rules beat
46
53
  # the library's. Put it after the library's stylesheets all the same, for
47
54
  # a browser that resolves a name by order rather than by layer.
48
- def its_swiss_typeface(regular: nil, bold: nil, variable: nil, mono: nil)
55
+ def its_swiss_typeface(regular: nil, bold: nil, variable: nil, mono: nil, family: nil)
49
56
  raise ArgumentError, "a regular file or a variable one" unless regular || variable
50
57
  raise ArgumentError, "a variable file carries both weights" if variable && (regular || bold)
51
58
 
52
59
  weights = variable ? { "100 900" => variable } : { "400" => regular, "700" => bold }.compact
53
60
 
54
- faces = ItsSwiss::FACES.flat_map do |family, ratio|
55
- weights.map { |weight, file| its_swiss_face(family, file, ratio, weight: weight) }
61
+ faces = ItsSwiss::FACES.flat_map do |family_name, ratio|
62
+ weights.map { |weight, file| its_swiss_face(family_name, file, ratio, weight: weight) }
56
63
  end
57
- faces += ItsSwiss::MONO_FACE.map { |family, ratio| its_swiss_face(family, mono, ratio) } if mono
64
+ faces += ItsSwiss::MONO_FACE.map { |family_name, ratio| its_swiss_face(family_name, mono, ratio) } if mono
65
+ faces += weights.map { |weight, file| its_swiss_face(family, file, nil, weight: weight) } if family
58
66
 
59
67
  tag.style(faces.join("\n").html_safe) # rubocop:disable Rails/OutputSafety -- every value is a number or a JSON-quoted path
60
68
  end
@@ -107,18 +115,20 @@ module ItsSwiss
107
115
 
108
116
  FONT_FORMATS = { ".woff2" => "woff2", ".woff" => "woff", ".ttf" => "truetype", ".otf" => "opentype" }.freeze
109
117
 
118
+ # With a ratio, a face whose ascent is that ratio and whose descent is
119
+ # nothing; without one, the font under its own name with its own metrics.
110
120
  def its_swiss_face(family, file, ratio, weight: nil)
111
121
  source = "url(#{asset_path(file).to_json})"
112
122
  source += %( format("#{FONT_FORMATS[File.extname(file)]}")) if FONT_FORMATS[File.extname(file)]
113
- ascent = (ratio * 100).to_f.round(4).to_s.sub(/\.0\z/, "")
123
+ ascent = (ratio * 100).to_f.round(4).to_s.sub(/\.0\z/, "") if ratio
114
124
 
115
125
  [ "@font-face {",
116
126
  " font-family: #{family.to_json};",
117
127
  (" font-weight: #{weight};" if weight),
118
128
  " src: #{source};",
119
- " ascent-override: #{ascent}%;",
120
- " descent-override: 0%;",
121
- " line-gap-override: 0%;",
129
+ (" ascent-override: #{ascent}%;" if ratio),
130
+ (" descent-override: 0%;" if ratio),
131
+ (" line-gap-override: 0%;" if ratio),
122
132
  "}" ].compact.join("\n")
123
133
  end
124
134
  private :its_swiss_face
@@ -1,3 +1,3 @@
1
1
  module ItsSwiss
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: its-swiss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bobby Meyer