fetta 1.2.0 → 1.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/dist/{chunk-PRR25BMJ.js → chunk-Q2D5AQBW.js} +124 -31
- package/dist/index.js +1 -1
- package/dist/react.js +1 -1
- package/package.json +1 -1
|
@@ -63,6 +63,86 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
63
63
|
"u",
|
|
64
64
|
"var"
|
|
65
65
|
]);
|
|
66
|
+
var KERNING_STYLE_PROPS = [
|
|
67
|
+
"font",
|
|
68
|
+
"font-kerning",
|
|
69
|
+
"font-variant-ligatures",
|
|
70
|
+
"font-feature-settings",
|
|
71
|
+
"font-variation-settings",
|
|
72
|
+
"font-optical-sizing",
|
|
73
|
+
"font-size-adjust",
|
|
74
|
+
"font-stretch",
|
|
75
|
+
"font-variant-caps",
|
|
76
|
+
"font-variant-numeric",
|
|
77
|
+
"font-variant-east-asian",
|
|
78
|
+
"font-synthesis",
|
|
79
|
+
"font-synthesis-weight",
|
|
80
|
+
"font-synthesis-style",
|
|
81
|
+
"letter-spacing",
|
|
82
|
+
"word-spacing",
|
|
83
|
+
"text-rendering",
|
|
84
|
+
"text-transform",
|
|
85
|
+
"direction",
|
|
86
|
+
"unicode-bidi"
|
|
87
|
+
];
|
|
88
|
+
function copyKerningStyles(target, styles) {
|
|
89
|
+
KERNING_STYLE_PROPS.forEach((prop) => {
|
|
90
|
+
const value = styles.getPropertyValue(prop);
|
|
91
|
+
if (value) target.style.setProperty(prop, value);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function buildCanvasFontString(styles) {
|
|
95
|
+
const fontStyle = styles.fontStyle || "normal";
|
|
96
|
+
const fontWeight = styles.fontWeight || "normal";
|
|
97
|
+
const fontSize = styles.fontSize || "16px";
|
|
98
|
+
const fontFamily = styles.fontFamily || "sans-serif";
|
|
99
|
+
return [fontStyle, fontWeight, fontSize, fontFamily].filter(Boolean).join(" ");
|
|
100
|
+
}
|
|
101
|
+
function applyKerningStylesToCanvas(ctx, styles) {
|
|
102
|
+
ctx.font = buildCanvasFontString(styles);
|
|
103
|
+
const ctxAny = ctx;
|
|
104
|
+
const setIfExists = (prop, value) => {
|
|
105
|
+
if (!value || value === "normal") return;
|
|
106
|
+
if (prop in ctxAny) ctxAny[prop] = value;
|
|
107
|
+
};
|
|
108
|
+
setIfExists("fontKerning", styles.getPropertyValue("font-kerning"));
|
|
109
|
+
setIfExists("fontVariantLigatures", styles.getPropertyValue("font-variant-ligatures"));
|
|
110
|
+
setIfExists("fontFeatureSettings", styles.getPropertyValue("font-feature-settings"));
|
|
111
|
+
setIfExists("fontVariationSettings", styles.getPropertyValue("font-variation-settings"));
|
|
112
|
+
setIfExists("fontOpticalSizing", styles.getPropertyValue("font-optical-sizing"));
|
|
113
|
+
setIfExists("fontSizeAdjust", styles.getPropertyValue("font-size-adjust"));
|
|
114
|
+
setIfExists("fontStretch", styles.getPropertyValue("font-stretch"));
|
|
115
|
+
setIfExists("fontVariantCaps", styles.getPropertyValue("font-variant-caps"));
|
|
116
|
+
setIfExists("fontVariantNumeric", styles.getPropertyValue("font-variant-numeric"));
|
|
117
|
+
setIfExists("fontVariantEastAsian", styles.getPropertyValue("font-variant-east-asian"));
|
|
118
|
+
setIfExists("fontSynthesis", styles.getPropertyValue("font-synthesis"));
|
|
119
|
+
setIfExists("fontSynthesisWeight", styles.getPropertyValue("font-synthesis-weight"));
|
|
120
|
+
setIfExists("fontSynthesisStyle", styles.getPropertyValue("font-synthesis-style"));
|
|
121
|
+
setIfExists("letterSpacing", styles.getPropertyValue("letter-spacing"));
|
|
122
|
+
setIfExists("wordSpacing", styles.getPropertyValue("word-spacing"));
|
|
123
|
+
setIfExists("textRendering", styles.getPropertyValue("text-rendering"));
|
|
124
|
+
setIfExists("direction", styles.getPropertyValue("direction"));
|
|
125
|
+
}
|
|
126
|
+
function buildKerningStyleKey(styles) {
|
|
127
|
+
return KERNING_STYLE_PROPS.map((prop) => styles.getPropertyValue(prop)).join("|");
|
|
128
|
+
}
|
|
129
|
+
function shouldUseDomKerning(styles) {
|
|
130
|
+
const textTransform = styles.getPropertyValue("text-transform");
|
|
131
|
+
if (textTransform && textTransform !== "none") return true;
|
|
132
|
+
const fontVariant = styles.getPropertyValue("font-variant");
|
|
133
|
+
if (fontVariant && fontVariant !== "normal") return true;
|
|
134
|
+
const fontStretch = styles.getPropertyValue("font-stretch");
|
|
135
|
+
if (fontStretch && fontStretch !== "normal" && fontStretch !== "100%") return true;
|
|
136
|
+
const fontFeatureSettings = styles.getPropertyValue("font-feature-settings");
|
|
137
|
+
if (fontFeatureSettings && fontFeatureSettings !== "normal") return true;
|
|
138
|
+
const fontVariationSettings = styles.getPropertyValue("font-variation-settings");
|
|
139
|
+
if (fontVariationSettings && fontVariationSettings !== "normal") return true;
|
|
140
|
+
const fontOpticalSizing = styles.getPropertyValue("font-optical-sizing");
|
|
141
|
+
if (fontOpticalSizing && fontOpticalSizing !== "auto") return true;
|
|
142
|
+
const fontSizeAdjust = styles.getPropertyValue("font-size-adjust");
|
|
143
|
+
if (fontSizeAdjust && fontSizeAdjust !== "none") return true;
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
66
146
|
var isSafariBrowser = null;
|
|
67
147
|
function isSafari() {
|
|
68
148
|
if (isSafariBrowser !== null) return isSafariBrowser;
|
|
@@ -70,21 +150,14 @@ function isSafari() {
|
|
|
70
150
|
isSafariBrowser = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
71
151
|
return isSafariBrowser;
|
|
72
152
|
}
|
|
73
|
-
function measureKerningCanvas(
|
|
153
|
+
function measureKerningCanvas(styleSource, chars, styles) {
|
|
74
154
|
const kerningMap = /* @__PURE__ */ new Map();
|
|
75
155
|
if (chars.length < 2) return kerningMap;
|
|
76
156
|
const canvas = document.createElement("canvas");
|
|
77
157
|
const ctx = canvas.getContext("2d");
|
|
78
158
|
if (!ctx) return kerningMap;
|
|
79
|
-
const
|
|
80
|
-
ctx
|
|
81
|
-
if (styles.letterSpacing && styles.letterSpacing !== "normal") {
|
|
82
|
-
ctx.letterSpacing = styles.letterSpacing;
|
|
83
|
-
}
|
|
84
|
-
if (styles.wordSpacing && styles.wordSpacing !== "normal") {
|
|
85
|
-
ctx.wordSpacing = styles.wordSpacing;
|
|
86
|
-
}
|
|
87
|
-
if ("fontVariantLigatures" in ctx) ctx.fontVariantLigatures = "none";
|
|
159
|
+
const computedStyles = styles != null ? styles : getComputedStyle(styleSource);
|
|
160
|
+
applyKerningStylesToCanvas(ctx, computedStyles);
|
|
88
161
|
const charWidths = /* @__PURE__ */ new Map();
|
|
89
162
|
for (const char of new Set(chars)) {
|
|
90
163
|
charWidths.set(char, ctx.measureText(char).width);
|
|
@@ -100,7 +173,7 @@ function measureKerningCanvas(element, chars) {
|
|
|
100
173
|
}
|
|
101
174
|
return kerningMap;
|
|
102
175
|
}
|
|
103
|
-
function measureKerningDOM(
|
|
176
|
+
function measureKerningDOM(container, styleSource, chars, styles) {
|
|
104
177
|
const kerningMap = /* @__PURE__ */ new Map();
|
|
105
178
|
if (chars.length < 2) return kerningMap;
|
|
106
179
|
const measurer = document.createElement("span");
|
|
@@ -109,21 +182,17 @@ function measureKerningDOM(element, chars) {
|
|
|
109
182
|
visibility: hidden;
|
|
110
183
|
white-space: pre;
|
|
111
184
|
`;
|
|
112
|
-
const
|
|
113
|
-
measurer
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
measurer.style.fontKerning = styles.fontKerning;
|
|
117
|
-
measurer.style.fontVariantLigatures = "none";
|
|
118
|
-
const webkitSmoothing = styles.webkitFontSmoothing || styles["-webkit-font-smoothing"];
|
|
119
|
-
const mozSmoothing = styles.MozOsxFontSmoothing || styles["-moz-osx-font-smoothing"];
|
|
185
|
+
const computedStyles = styles != null ? styles : getComputedStyle(styleSource);
|
|
186
|
+
copyKerningStyles(measurer, computedStyles);
|
|
187
|
+
const webkitSmoothing = computedStyles.webkitFontSmoothing || computedStyles["-webkit-font-smoothing"];
|
|
188
|
+
const mozSmoothing = computedStyles.MozOsxFontSmoothing || computedStyles["-moz-osx-font-smoothing"];
|
|
120
189
|
if (webkitSmoothing) {
|
|
121
190
|
measurer.style.webkitFontSmoothing = webkitSmoothing;
|
|
122
191
|
}
|
|
123
192
|
if (mozSmoothing) {
|
|
124
193
|
measurer.style.MozOsxFontSmoothing = mozSmoothing;
|
|
125
194
|
}
|
|
126
|
-
|
|
195
|
+
container.appendChild(measurer);
|
|
127
196
|
const charWidths = /* @__PURE__ */ new Map();
|
|
128
197
|
for (const char of new Set(chars)) {
|
|
129
198
|
measurer.textContent = char;
|
|
@@ -139,12 +208,13 @@ function measureKerningDOM(element, chars) {
|
|
|
139
208
|
kerningMap.set(i + 1, kerning);
|
|
140
209
|
}
|
|
141
210
|
}
|
|
142
|
-
|
|
211
|
+
container.removeChild(measurer);
|
|
143
212
|
return kerningMap;
|
|
144
213
|
}
|
|
145
|
-
function measureKerning(
|
|
214
|
+
function measureKerning(container, styleSource, chars, styles) {
|
|
146
215
|
if (chars.length < 2) return /* @__PURE__ */ new Map();
|
|
147
|
-
|
|
216
|
+
const computedStyles = styles != null ? styles : getComputedStyle(styleSource);
|
|
217
|
+
return isSafari() || shouldUseDomKerning(computedStyles) ? measureKerningDOM(container, styleSource, chars, computedStyles) : measureKerningCanvas(styleSource, chars, computedStyles);
|
|
148
218
|
}
|
|
149
219
|
var srOnlyStylesInjected = false;
|
|
150
220
|
function injectSrOnlyStyles() {
|
|
@@ -407,7 +477,6 @@ function performSplit(element, measuredWords, charClass, wordClass, lineClass, s
|
|
|
407
477
|
}
|
|
408
478
|
charGroups.forEach((group) => {
|
|
409
479
|
group.chars.forEach((measuredChar) => {
|
|
410
|
-
measuredWord.chars.indexOf(measuredChar);
|
|
411
480
|
const charSpan = createSpan(charClass, globalCharIndex, "inline-block", {
|
|
412
481
|
propIndex: options == null ? void 0 : options.propIndex,
|
|
413
482
|
propName: "char"
|
|
@@ -514,13 +583,37 @@ function performSplit(element, measuredWords, charClass, wordClass, lineClass, s
|
|
|
514
583
|
for (const wordSpan of allWords) {
|
|
515
584
|
const wordChars = Array.from(wordSpan.querySelectorAll(`.${charClass}`));
|
|
516
585
|
if (wordChars.length < 2) continue;
|
|
517
|
-
const
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
586
|
+
const styleGroups = [];
|
|
587
|
+
const firstCharStyles = getComputedStyle(wordChars[0]);
|
|
588
|
+
let currentKey = buildKerningStyleKey(firstCharStyles);
|
|
589
|
+
let currentGroup = {
|
|
590
|
+
chars: [wordChars[0]],
|
|
591
|
+
styleSource: wordChars[0],
|
|
592
|
+
styles: firstCharStyles
|
|
593
|
+
};
|
|
594
|
+
for (let i2 = 1; i2 < wordChars.length; i2++) {
|
|
595
|
+
const char = wordChars[i2];
|
|
596
|
+
const charStyles = getComputedStyle(char);
|
|
597
|
+
const key = buildKerningStyleKey(charStyles);
|
|
598
|
+
if (key === currentKey) {
|
|
599
|
+
currentGroup.chars.push(char);
|
|
600
|
+
} else {
|
|
601
|
+
styleGroups.push(currentGroup);
|
|
602
|
+
currentKey = key;
|
|
603
|
+
currentGroup = { chars: [char], styleSource: char, styles: charStyles };
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
styleGroups.push(currentGroup);
|
|
607
|
+
for (const group of styleGroups) {
|
|
608
|
+
if (group.chars.length < 2) continue;
|
|
609
|
+
const charStrings = group.chars.map((c) => c.textContent || "");
|
|
610
|
+
const kerningMap = measureKerning(element, group.styleSource, charStrings, group.styles);
|
|
611
|
+
for (const [charIndex, kerning] of kerningMap) {
|
|
612
|
+
const charSpan = group.chars[charIndex];
|
|
613
|
+
if (charSpan && Math.abs(kerning) < 20) {
|
|
614
|
+
const targetElement = (options == null ? void 0 : options.mask) === "chars" && charSpan.parentElement ? charSpan.parentElement : charSpan;
|
|
615
|
+
targetElement.style.marginLeft = `${kerning}px`;
|
|
616
|
+
}
|
|
524
617
|
}
|
|
525
618
|
}
|
|
526
619
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { splitText } from './chunk-
|
|
1
|
+
export { splitText } from './chunk-Q2D5AQBW.js';
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { splitText, __spreadProps, __spreadValues, normalizeToPromise } from './chunk-
|
|
1
|
+
import { splitText, __spreadProps, __spreadValues, normalizeToPromise } from './chunk-Q2D5AQBW.js';
|
|
2
2
|
import { forwardRef, useRef, useCallback, useState, useLayoutEffect, useEffect, isValidElement, cloneElement } from 'react';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
4
|
|