pixi-glyphs 4.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.
@@ -0,0 +1,2034 @@
1
+ var PIXI = require('pixi.js');
2
+
3
+ function _interopNamespace(e) {
4
+ if (e && e.__esModule) return e;
5
+ var n = Object.create(null);
6
+ if (e) {
7
+ Object.keys(e).forEach(function (k) {
8
+ if (k !== 'default') {
9
+ var d = Object.getOwnPropertyDescriptor(e, k);
10
+ Object.defineProperty(n, k, d.get ? d : {
11
+ enumerable: true,
12
+ get: function () { return e[k]; }
13
+ });
14
+ }
15
+ });
16
+ }
17
+ n["default"] = e;
18
+ return n;
19
+ }
20
+
21
+ var PIXI__namespace = /*#__PURE__*/_interopNamespace(PIXI);
22
+
23
+ const combineRecords = (a, b) => ({
24
+ ...a,
25
+ ...b
26
+ });
27
+ const first = a => a[0];
28
+ const last = a => a[a.length - 1];
29
+ const isDefined = a => a !== undefined;
30
+ const complement = predicate => input => !predicate(input);
31
+ const pluck = key => objects => objects.map(o => o[key]);
32
+ const assoc = key => value => object => ({
33
+ ...object,
34
+ ...{
35
+ [key]: value
36
+ }
37
+ });
38
+ const flatReduce = (f, acc) => nested => [nested].flat(255).reduce(f, acc);
39
+ const flatEvery = p => flatReduce((acc, t) => acc && p(t), true);
40
+
41
+ const log = type => (handler, supressConsole = false, target) => (code, message) => {
42
+ if (supressConsole !== true) {
43
+ const method = type === "warning" ? console.warn : console.error;
44
+ method(`[${code}] ${message}`);
45
+ }
46
+ if (handler) {
47
+ handler({
48
+ target,
49
+ code,
50
+ message,
51
+ type
52
+ });
53
+ }
54
+ };
55
+ const logWarning = log("warning");
56
+
57
+ const isSpriteSource = s => typeof s === "string" || s instanceof PIXI__namespace.Texture || s instanceof HTMLCanvasElement || s instanceof HTMLVideoElement;
58
+ const isBaseTexture = s => s instanceof PIXI__namespace.Texture;
59
+ const isImageElement = s => s instanceof HTMLImageElement;
60
+ const isTextureSource = s => isImageElement(s) || isBaseTexture(s);
61
+ const IMG_REFERENCE_PROPERTY = "imgSrc";
62
+ const IMG_DISPLAY_PROPERTY = "imgDisplay";
63
+ const DEFAULT_KEY = "default";
64
+ var MeasurementUnit;
65
+ (function (MeasurementUnit) {
66
+ MeasurementUnit["default"] = "px";
67
+ MeasurementUnit["px"] = "px";
68
+ MeasurementUnit["em"] = "em";
69
+ MeasurementUnit["rem"] = "rem";
70
+ MeasurementUnit["pt"] = "pt";
71
+ MeasurementUnit["pc"] = "pc";
72
+ MeasurementUnit["in"] = "in";
73
+ MeasurementUnit["cm"] = "cm";
74
+ MeasurementUnit["mm"] = "mm";
75
+ MeasurementUnit["percent"] = "%";
76
+ MeasurementUnit["unknown"] = "unknown";
77
+ })(MeasurementUnit || (MeasurementUnit = {}));
78
+ const DEFAULT_MEASUREMENT_UNIT = MeasurementUnit.default;
79
+ const createEmptySegmentToken = () => ({
80
+ content: "",
81
+ bounds: new PIXI__namespace.Rectangle(0, 0, 0, 0),
82
+ fontProperties: {
83
+ ascent: 0,
84
+ descent: 0,
85
+ fontSize: 0
86
+ },
87
+ style: {},
88
+ tags: "",
89
+ textDecorations: []
90
+ });
91
+ const isWhitespace = s => s !== "" && s.split("").every(char => char.search(/\s/) === 0);
92
+ const isNewline = s => isWhitespace(s) && s === "\n";
93
+ const _isSpriteToken = t => t.content instanceof PIXI__namespace.Sprite;
94
+ const isSpriteToken = flatEvery(_isSpriteToken);
95
+ const _isTextToken = t => typeof t.content === "string";
96
+ const isTextToken = flatEvery(_isTextToken);
97
+ const _isWhitespaceToken = t => t !== undefined && _isTextToken(t) && isWhitespace(t.content);
98
+ const isWhitespaceToken = flatEvery(_isWhitespaceToken);
99
+ const _isNewlineToken = t => t !== undefined && _isTextToken(t) && isNewline(t.content);
100
+ const isNewlineToken = t => t === undefined ? false : flatEvery(_isNewlineToken)(t);
101
+ const isNotWhitespaceToken = complement(isWhitespaceToken);
102
+ const isEmptyObject = a => a instanceof Object && Object.keys(a).length === 0;
103
+ const measurementValueToComponents = input => {
104
+ if (input === undefined) {
105
+ throw new Error("value is undefined!");
106
+ }
107
+ if (typeof input === "number") {
108
+ return {
109
+ value: input,
110
+ unit: DEFAULT_MEASUREMENT_UNIT
111
+ };
112
+ }
113
+ input = input.trim();
114
+ const pattern = new RegExp(Object.values(MeasurementUnit).join("|") + "$");
115
+ const i = input.search(pattern);
116
+ if (i !== -1) {
117
+ return {
118
+ value: parseFloat(input.slice(0, i)),
119
+ unit: input.slice(i)
120
+ };
121
+ }
122
+ const isAllDigits = input.search(/^[\d.]+$/) === 0;
123
+ if (isAllDigits) {
124
+ const forcedNumberConversion = parseFloat(input);
125
+ if (isNaN(forcedNumberConversion) === false) {
126
+ return {
127
+ value: parseFloat(input),
128
+ unit: DEFAULT_MEASUREMENT_UNIT
129
+ };
130
+ }
131
+ }
132
+ logWarning()("invalid-units", `${input} is not a valid measurement value. Please use one of the following units: ${Object.keys(MeasurementUnit).join(", ")}`);
133
+ return {
134
+ value: NaN,
135
+ unit: MeasurementUnit.unknown
136
+ };
137
+ };
138
+
139
+ var RGI_Emoji = () => {
140
+ // https://mths.be/emoji
141
+ return /\u{1F3F4}\u{E0067}\u{E0062}(?:\u{E0077}\u{E006C}\u{E0073}|\u{E0073}\u{E0063}\u{E0074}|\u{E0065}\u{E006E}\u{E0067})\u{E007F}|(?:\u{1F9D1}\u{1F3FF}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F9D1}|\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FE}]|(?:\u{1F9D1}\u{1F3FE}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F9D1}|\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|(?:\u{1F9D1}\u{1F3FD}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F9D1}|\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|(?:\u{1F9D1}\u{1F3FC}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F9D1}|\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|(?:\u{1F9D1}\u{1F3FB}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F9D1}|\u{1F469}\u{1F3FB}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FC}-\u{1F3FF}]|\u{1F468}(?:\u{1F3FB}(?:\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FF}]|\u{1F468}[\u{1F3FB}-\u{1F3FF}])|\u{1F91D}\u200D\u{1F468}[\u{1F3FC}-\u{1F3FF}]|[\u2695\u2696\u2708]\uFE0F|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]))?|[\u{1F3FC}-\u{1F3FF}]\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FF}]|\u{1F468}[\u{1F3FB}-\u{1F3FF}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F468}|[\u{1F468}\u{1F469}]\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}]|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FE}]|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:[\u{1F468}\u{1F469}]\u200D[\u{1F466}\u{1F467}]|[\u{1F466}\u{1F467}])|\u{1F3FF}|\u{1F3FE}|\u{1F3FD}|\u{1F3FC})?|(?:\u{1F469}(?:\u{1F3FB}\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F3FC}-\u{1F3FF}]\u200D\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}]))|\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]\u200D\u{1F91D}\u200D\u{1F9D1})[\u{1F3FB}-\u{1F3FF}]|\u{1F469}\u200D\u{1F469}\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F469}(?:\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FE}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FD}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FC}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F9D1}(?:\u200D(?:\u{1F91D}\u200D\u{1F9D1}|[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FE}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FD}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FC}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F37C}\u{1F384}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F469}\u200D\u{1F466}\u200D\u{1F466}|\u{1F469}\u200D\u{1F469}\u200D[\u{1F466}\u{1F467}]|\u{1F469}\u200D\u{1F467}\u200D[\u{1F466}\u{1F467}]|(?:\u{1F441}\uFE0F\u200D\u{1F5E8}|\u{1F9D1}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\u{1F469}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\u{1F636}\u200D\u{1F32B}|\u{1F3F3}\uFE0F\u200D\u26A7|\u{1F43B}\u200D\u2744|(?:[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F470}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F935}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D4}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}])\u200D[\u2640\u2642]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\uFE0F\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|\u{1F3F4}\u200D\u2620|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F470}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F935}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D4}\u{1F9D6}-\u{1F9DD}]\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299\u{1F170}\u{1F171}\u{1F17E}\u{1F17F}\u{1F202}\u{1F237}\u{1F321}\u{1F324}-\u{1F32C}\u{1F336}\u{1F37D}\u{1F396}\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}\u{1F39F}\u{1F3CD}\u{1F3CE}\u{1F3D4}-\u{1F3DF}\u{1F3F5}\u{1F3F7}\u{1F43F}\u{1F4FD}\u{1F549}\u{1F54A}\u{1F56F}\u{1F570}\u{1F573}\u{1F576}-\u{1F579}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F5A5}\u{1F5A8}\u{1F5B1}\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5E8}\u{1F5EF}\u{1F5F3}\u{1F5FA}\u{1F6CB}\u{1F6CD}-\u{1F6CF}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6F0}\u{1F6F3}])\uFE0F|\u{1F3F3}\uFE0F\u200D\u{1F308}|\u{1F469}\u200D\u{1F467}|\u{1F469}\u200D\u{1F466}|\u{1F635}\u200D\u{1F4AB}|\u{1F62E}\u200D\u{1F4A8}|\u{1F415}\u200D\u{1F9BA}|\u{1F9D1}(?:\u{1F3FF}|\u{1F3FE}|\u{1F3FD}|\u{1F3FC}|\u{1F3FB})?|\u{1F469}(?:\u{1F3FF}|\u{1F3FE}|\u{1F3FD}|\u{1F3FC}|\u{1F3FB})?|\u{1F1FD}\u{1F1F0}|\u{1F1F6}\u{1F1E6}|\u{1F1F4}\u{1F1F2}|\u{1F408}\u200D\u2B1B|\u2764\uFE0F\u200D[\u{1F525}\u{1FA79}]|\u{1F441}\uFE0F|\u{1F3F3}\uFE0F|\u{1F1FF}[\u{1F1E6}\u{1F1F2}\u{1F1FC}]|\u{1F1FE}[\u{1F1EA}\u{1F1F9}]|\u{1F1FC}[\u{1F1EB}\u{1F1F8}]|\u{1F1FB}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1EE}\u{1F1F3}\u{1F1FA}]|\u{1F1FA}[\u{1F1E6}\u{1F1EC}\u{1F1F2}\u{1F1F3}\u{1F1F8}\u{1F1FE}\u{1F1FF}]|\u{1F1F9}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1ED}\u{1F1EF}-\u{1F1F4}\u{1F1F7}\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FF}]|\u{1F1F8}[\u{1F1E6}-\u{1F1EA}\u{1F1EC}-\u{1F1F4}\u{1F1F7}-\u{1F1F9}\u{1F1FB}\u{1F1FD}-\u{1F1FF}]|\u{1F1F7}[\u{1F1EA}\u{1F1F4}\u{1F1F8}\u{1F1FA}\u{1F1FC}]|\u{1F1F5}[\u{1F1E6}\u{1F1EA}-\u{1F1ED}\u{1F1F0}-\u{1F1F3}\u{1F1F7}-\u{1F1F9}\u{1F1FC}\u{1F1FE}]|\u{1F1F3}[\u{1F1E6}\u{1F1E8}\u{1F1EA}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F4}\u{1F1F5}\u{1F1F7}\u{1F1FA}\u{1F1FF}]|\u{1F1F2}[\u{1F1E6}\u{1F1E8}-\u{1F1ED}\u{1F1F0}-\u{1F1FF}]|\u{1F1F1}[\u{1F1E6}-\u{1F1E8}\u{1F1EE}\u{1F1F0}\u{1F1F7}-\u{1F1FB}\u{1F1FE}]|\u{1F1F0}[\u{1F1EA}\u{1F1EC}-\u{1F1EE}\u{1F1F2}\u{1F1F3}\u{1F1F5}\u{1F1F7}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1EF}[\u{1F1EA}\u{1F1F2}\u{1F1F4}\u{1F1F5}]|\u{1F1EE}[\u{1F1E8}-\u{1F1EA}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}]|\u{1F1ED}[\u{1F1F0}\u{1F1F2}\u{1F1F3}\u{1F1F7}\u{1F1F9}\u{1F1FA}]|\u{1F1EC}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EE}\u{1F1F1}-\u{1F1F3}\u{1F1F5}-\u{1F1FA}\u{1F1FC}\u{1F1FE}]|\u{1F1EB}[\u{1F1EE}-\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1F7}]|\u{1F1EA}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1ED}\u{1F1F7}-\u{1F1FA}]|\u{1F1E9}[\u{1F1EA}\u{1F1EC}\u{1F1EF}\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1FF}]|\u{1F1E8}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1EE}\u{1F1F0}-\u{1F1F5}\u{1F1F7}\u{1F1FA}-\u{1F1FF}]|\u{1F1E7}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EF}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1E6}[\u{1F1E8}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F2}\u{1F1F4}\u{1F1F6}-\u{1F1FA}\u{1F1FC}\u{1F1FD}\u{1F1FF}]|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F470}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F935}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D4}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\uFE0F\u{1F3FB}-\u{1F3FF}]|\u{1F3F4}|[\u270A\u270B\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F57A}\u{1F595}\u{1F596}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90C}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F934}\u{1F936}\u{1F977}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}\u{1F9D3}\u{1F9D5}][\u{1F3FB}-\u{1F3FF}]|[\u261D\u270C\u270D\u{1F574}\u{1F590}][\uFE0F\u{1F3FB}-\u{1F3FF}]|[\u270A\u270B\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F408}\u{1F415}\u{1F43B}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F57A}\u{1F595}\u{1F596}\u{1F62E}\u{1F635}\u{1F636}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90C}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F934}\u{1F936}\u{1F977}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}\u{1F9D3}\u{1F9D5}]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F470}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F935}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D4}\u{1F9D6}-\u{1F9DD}]|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55\u{1F004}\u{1F0CF}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F201}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F236}\u{1F238}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F320}\u{1F32D}-\u{1F335}\u{1F337}-\u{1F37C}\u{1F37E}-\u{1F384}\u{1F386}-\u{1F393}\u{1F3A0}-\u{1F3C1}\u{1F3C5}\u{1F3C6}\u{1F3C8}\u{1F3C9}\u{1F3CF}-\u{1F3D3}\u{1F3E0}-\u{1F3F0}\u{1F3F8}-\u{1F407}\u{1F409}-\u{1F414}\u{1F416}-\u{1F43A}\u{1F43C}-\u{1F43E}\u{1F440}\u{1F444}\u{1F445}\u{1F451}-\u{1F465}\u{1F46A}\u{1F479}-\u{1F47B}\u{1F47D}-\u{1F480}\u{1F484}\u{1F488}-\u{1F48E}\u{1F490}\u{1F492}-\u{1F4A9}\u{1F4AB}-\u{1F4FC}\u{1F4FF}-\u{1F53D}\u{1F54B}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F5A4}\u{1F5FB}-\u{1F62D}\u{1F62F}-\u{1F634}\u{1F637}-\u{1F644}\u{1F648}-\u{1F64A}\u{1F680}-\u{1F6A2}\u{1F6A4}-\u{1F6B3}\u{1F6B7}-\u{1F6BF}\u{1F6C1}-\u{1F6C5}\u{1F6D0}-\u{1F6D2}\u{1F6D5}-\u{1F6D7}\u{1F6EB}\u{1F6EC}\u{1F6F4}-\u{1F6FC}\u{1F7E0}-\u{1F7EB}\u{1F90D}\u{1F90E}\u{1F910}-\u{1F917}\u{1F91D}\u{1F920}-\u{1F925}\u{1F927}-\u{1F92F}\u{1F93A}\u{1F93F}-\u{1F945}\u{1F947}-\u{1F976}\u{1F978}\u{1F97A}-\u{1F9B4}\u{1F9B7}\u{1F9BA}\u{1F9BC}-\u{1F9CB}\u{1F9D0}\u{1F9E0}-\u{1F9FF}\u{1FA70}-\u{1FA74}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA86}\u{1FA90}-\u{1FAA8}\u{1FAB0}-\u{1FAB6}\u{1FAC0}-\u{1FAC2}\u{1FAD0}-\u{1FAD6}]/gu;
142
+ };
143
+
144
+ const defaultLogWarning = logWarning();
145
+ const getTagRegex = (tagNamesToMatch = ["\\w+"]) => {
146
+ const matchingTagNames = tagNamesToMatch.join("|");
147
+ const captureGroup = a => `(${a})`;
148
+ const noCaptureGroup = a => `(?:${a})`;
149
+ const WHITESPACE = `\\s`;
150
+ const S = WHITESPACE + "*";
151
+ const SS = WHITESPACE + "+";
152
+ const TAG_NAMES = captureGroup(matchingTagNames);
153
+ const NOT_CLOSING_TAG = `[^>]`;
154
+ const ATTRIBUTES = captureGroup(noCaptureGroup(`${SS}${NOT_CLOSING_TAG}*`) + "*") + "+";
155
+ const TAG_OPEN = `<` + TAG_NAMES + ATTRIBUTES + S + `>`;
156
+ const TAG_CLOSE = `</${TAG_NAMES}${S}>`;
157
+ const pattern = `${TAG_OPEN}|${TAG_CLOSE}`;
158
+ return new RegExp(pattern, "g");
159
+ };
160
+ const EMOJI_TAG = "__EMOJI__";
161
+ const parseAttributes = (attributesString = "") => {
162
+ if (attributesString === "") {
163
+ return {};
164
+ }
165
+ const attributeMatch = /[a-zA-Z][a-zA-Z0-9]*=('|")[^'"]*('|")/g;
166
+ const attributes = attributesString.trim().match(attributeMatch);
167
+ if (attributes === null) {
168
+ throw new Error('Invalid attributes string: "' + attributesString + '"');
169
+ }
170
+ return [...attributes].reduce((obj, attribute) => {
171
+ const attributePair = [attribute.substring(0, attribute.indexOf("=")), attribute.substring(attribute.indexOf("=") + 1)];
172
+ const name = attributePair[0].trim();
173
+ const valueStr = attributePair[1].substring(1, attributePair[1].length - 1).trim();
174
+ obj[name] = valueStr;
175
+ return obj;
176
+ }, {});
177
+ };
178
+ const createTagMatchData = match => {
179
+ const {
180
+ 0: tag,
181
+ 1: openTagName,
182
+ 2: attributes,
183
+ 3: closeTagName,
184
+ index
185
+ } = match;
186
+ const tagName = openTagName ?? closeTagName;
187
+ const isOpening = openTagName !== undefined;
188
+ return {
189
+ tag,
190
+ tagName,
191
+ isOpening,
192
+ attributes: parseAttributes(attributes),
193
+ index
194
+ };
195
+ };
196
+ const extractSegments = (input, tagMatchData) => {
197
+ const segments = [];
198
+ let remaining = input;
199
+ let offset = 0;
200
+ let tagMatch;
201
+ for (tagMatch of tagMatchData) {
202
+ if (remaining !== undefined) {
203
+ const {
204
+ tag,
205
+ index
206
+ } = tagMatch;
207
+ const startOfTag = index - offset;
208
+ const endOfTag = startOfTag + tag.length;
209
+ offset += endOfTag;
210
+ const segment = remaining.substr(0, startOfTag);
211
+ segments.push(segment);
212
+ remaining = remaining.substr(endOfTag);
213
+ }
214
+ }
215
+ segments.push(remaining);
216
+ return segments;
217
+ };
218
+ const selfClosingTagSearch = (() => {
219
+ const group = s => `(${s})`;
220
+ const any = s => s + `*`;
221
+ const not = function () {
222
+ return `[^${[].slice.call(arguments).join("")}]`;
223
+ };
224
+ const WORD_START = `[A-Za-z_]`;
225
+ const WORD = `[A-Za-z0-9_]`;
226
+ const TAG_OPEN = `<`;
227
+ const TAG_SLASH = `/`;
228
+ const TAG_CLOSE = `>`;
229
+ const TAG_SELF_CLOSE = TAG_SLASH + TAG_CLOSE;
230
+ return new RegExp(TAG_OPEN + group(WORD_START + any(WORD)) + group(any(not(TAG_SLASH, TAG_CLOSE))) + TAG_SELF_CLOSE, `g`);
231
+ })();
232
+ const wrapEmoji = input => {
233
+ const emojiRegex = new RegExp(`((<|</)[^>]*)?(${RGI_Emoji().source})+`, "gum");
234
+ return input.replaceAll(emojiRegex, (match, tagStart) => {
235
+ if (tagStart?.length > 0) {
236
+ return match;
237
+ }
238
+ return `<${EMOJI_TAG}>${match}</${EMOJI_TAG}>`;
239
+ });
240
+ };
241
+ const replaceSelfClosingTags = input => input.replace(selfClosingTagSearch, (_, tag, attributes = "") => {
242
+ let output = `<${tag}${attributes}></${tag}>`;
243
+ output = output.replace(/\s+/g, " ");
244
+ output = output.replace(/\s>/g, ">");
245
+ return output;
246
+ });
247
+ const removeTags = input => input.replace(getTagRegex(), "");
248
+ const tagMatchToTagToken = tag => {
249
+ return {
250
+ tag: tag.tagName,
251
+ children: [],
252
+ ...(isEmptyObject(tag.attributes) ? {} : {
253
+ attributes: tag.attributes
254
+ })
255
+ };
256
+ };
257
+ const createTokensNew = (segments, tags, logWarningFunction = defaultLogWarning) => {
258
+ const rootTokens = {
259
+ children: []
260
+ };
261
+ if (segments[0] !== "") {
262
+ rootTokens.children.push(segments[0]);
263
+ }
264
+ const tokenStack = [rootTokens];
265
+ for (let i = 0; i < tags.length; i++) {
266
+ const tag = tags[i];
267
+ const segment = segments[i + 1] ?? "";
268
+ if (tag.isOpening) {
269
+ const token = tagMatchToTagToken(tag);
270
+ if (segment !== "") {
271
+ token.children.push(segment);
272
+ }
273
+ last(tokenStack).children.push(token);
274
+ tokenStack.push(token);
275
+ } else {
276
+ const poppedToken = tokenStack.pop();
277
+ if (poppedToken === undefined || poppedToken.tag !== tag.tagName) {
278
+ throw new Error(`Unexpected tag nesting. Found a closing tag "${tag.tagName}" that doesn't match the previously open tag "${poppedToken?.tag}"`);
279
+ }
280
+ if (segment !== "") {
281
+ last(tokenStack).children.push(segment);
282
+ }
283
+ }
284
+ }
285
+ if (tokenStack.length > 1) {
286
+ logWarningFunction("unclosed-tags", `Found ${tokenStack.length - 1} unclosed tags in\n${tokenStack.map(token => token.tag).join("-")}`);
287
+ }
288
+ return rootTokens.children;
289
+ };
290
+ const containsEmoji = input => RGI_Emoji().test(input);
291
+ const parseTagsNew = (input, tagNamesToMatch = [], shouldWrapEmoji = false, logWarningFunction = defaultLogWarning) => {
292
+ if (shouldWrapEmoji && containsEmoji(input)) {
293
+ input = wrapEmoji(input);
294
+ }
295
+ input = replaceSelfClosingTags(input);
296
+ const re = getTagRegex(tagNamesToMatch);
297
+ const tagMatches = [];
298
+ let match;
299
+ while (match = re.exec(input)) {
300
+ const tagMatch = createTagMatchData(match);
301
+ tagMatches.push(tagMatch);
302
+ }
303
+ const segments = extractSegments(input, tagMatches);
304
+ const tokens = createTokensNew(segments, tagMatches, logWarningFunction);
305
+ return {
306
+ children: tokens
307
+ };
308
+ };
309
+
310
+ const capitalize = str => {
311
+ const chars = str.split(" ");
312
+ let converted = ``;
313
+ for (let i = 0; i < chars.length; i++) {
314
+ converted += `${chars[i].charAt(0).toUpperCase()}${chars[i].substr(1)} `;
315
+ }
316
+ return converted.trim();
317
+ };
318
+ const stringIsNumber = s => s.trim().search(/^-?[0-9]*\.?[0-9]+$/) === 0;
319
+ const isOnlyWhitespace = s => s.search(/^\s+$/) === 0;
320
+
321
+ const PX_PER_EM = 16;
322
+ const PX_PER_PERCENT = 16 / 100;
323
+ const PX_PER_PT = 1.3281472327365;
324
+ const fontMetricsCache = new Map();
325
+ const measureFont = font => {
326
+ if (fontMetricsCache.has(font)) {
327
+ return fontMetricsCache.get(font);
328
+ }
329
+ const canvas = document.createElement('canvas');
330
+ const context = canvas.getContext('2d');
331
+ if (!context) throw new Error('Cannot get 2D context');
332
+ context.font = font;
333
+ const measureString = "Mgpjy";
334
+ const metrics = context.measureText(measureString);
335
+ const fontSize = parseInt(font.match(/(\d+)px/)?.['1'] || '16');
336
+ const result = {
337
+ ascent: metrics.actualBoundingBoxAscent || fontSize * 0.88,
338
+ descent: metrics.actualBoundingBoxDescent || fontSize * 0.12,
339
+ fontSize: fontSize
340
+ };
341
+ fontMetricsCache.set(font, result);
342
+ return result;
343
+ };
344
+ const getFontPropertiesOfText = (textField, forceUpdate = false) => {
345
+ const style = textField.style;
346
+ const fontSize = typeof style.fontSize === 'number' ? style.fontSize : 16;
347
+ const fontFamily = style.fontFamily || 'Arial';
348
+ const fontWeight = style.fontWeight || 'normal';
349
+ const fontStyle = style.fontStyle || 'normal';
350
+ const font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
351
+ return measureFont(font);
352
+ };
353
+ const cloneSprite = sprite => new PIXI__namespace.Sprite(sprite.texture);
354
+ const fontSizeStringToNumber = size => {
355
+ const [valueString, unit] = size.split(/(%|pt|px|r?em)/);
356
+ const value = parseFloat(valueString);
357
+ switch (unit) {
358
+ case "%":
359
+ return value * PX_PER_PERCENT;
360
+ case "em":
361
+ case "rem":
362
+ return value * PX_PER_EM;
363
+ case "pt":
364
+ return value * PX_PER_PT;
365
+ case "px":
366
+ default:
367
+ return value;
368
+ }
369
+ };
370
+
371
+ const DEFAULT_STYLE = {
372
+ valign: "baseline",
373
+ dropShadowColor: 0x000000,
374
+ fill: 0x000000,
375
+ fontSize: 26,
376
+ stroke: 0x000000,
377
+ [IMG_DISPLAY_PROPERTY]: "inline",
378
+ wordWrap: true,
379
+ wordWrapWidth: 500,
380
+ iconScale: 1.0,
381
+ breakLines: true
382
+ };
383
+ Object.freeze(DEFAULT_STYLE);
384
+
385
+ const combineStyles = combineRecords;
386
+ const combineAllStyles = styles => styles.filter(isDefined).reduce(combineStyles, {});
387
+ const convertAttributeValues = attributes => {
388
+ const convertedAttributes = {};
389
+ for (const key in attributes) {
390
+ const value = attributes[key];
391
+ const isValueString = typeof value === "string";
392
+ const isStringNumber = isValueString && stringIsNumber(value);
393
+ if (isStringNumber) {
394
+ convertedAttributes[key] = parseFloat(value);
395
+ } else {
396
+ convertedAttributes[key] = value;
397
+ }
398
+ }
399
+ return convertedAttributes;
400
+ };
401
+ const injectAttributes = (attributes = {}, style = {}) => {
402
+ if (isEmptyObject(style) && isEmptyObject(attributes)) return undefined;
403
+ return combineRecords(style, convertAttributeValues(attributes));
404
+ };
405
+ const getStyleForTag = (tagName, tagStyles, attributes = {}) => {
406
+ const style = injectAttributes(attributes, tagStyles[tagName]) ?? {};
407
+ if (Object.values(style).length === 0) return undefined;
408
+ return style;
409
+ };
410
+ const tagWithAttributesToStyle = ({
411
+ tagName,
412
+ attributes
413
+ }, tagStyles) => getStyleForTag(tagName, tagStyles, attributes);
414
+ const getStyleForTags = (tags, tagStyles, styleCache) => {
415
+ const tagHash = JSON.stringify(tags);
416
+ if (styleCache[tagHash] === undefined) {
417
+ const defaultStyle = tagStyles.default;
418
+ const styles = tags.map(tag => tagWithAttributesToStyle(tag, tagStyles));
419
+ const stylesWithDefault = [defaultStyle, ...styles];
420
+ styleCache[tagHash] = combineAllStyles(stylesWithDefault);
421
+ }
422
+ return styleCache[tagHash];
423
+ };
424
+ const interpretFontSize = (baseFontSize, fontSize) => {
425
+ const {
426
+ value: baseValue,
427
+ unit: baseUnit
428
+ } = measurementValueToComponents(baseFontSize);
429
+ const {
430
+ value,
431
+ unit
432
+ } = measurementValueToComponents(fontSize);
433
+ if (unit === MeasurementUnit.percent) {
434
+ const percentage = value / 100;
435
+ return baseValue * percentage + baseUnit;
436
+ }
437
+ return fontSize;
438
+ };
439
+ const mapTagsToStyles = (tokens, styles, spriteTemplates) => {
440
+ const defaultStyle = convertDecorationToLineProps(styles.default ?? {});
441
+ const tagStack = [];
442
+ const fontSizeStack = [];
443
+ const styleCache = {};
444
+ const convertTagTokenToStyledToken = token => {
445
+ if (typeof token === "string") {
446
+ return token;
447
+ }
448
+ const {
449
+ tag,
450
+ attributes = {}
451
+ } = token;
452
+ let style = defaultStyle;
453
+ let tags = "";
454
+ const currentBaseFontSize = fontSizeStack[fontSizeStack.length - 1] ?? DEFAULT_STYLE.fontSize;
455
+ if (tag) {
456
+ tagStack.push({
457
+ tagName: tag,
458
+ attributes
459
+ });
460
+ tags = pluck("tagName")(tagStack).join(",");
461
+ style = getStyleForTags(tagStack, styles, styleCache);
462
+ style = convertDecorationToLineProps(style);
463
+ }
464
+ if (style.fontSize !== undefined) {
465
+ style.fontSize = interpretFontSize(currentBaseFontSize, style.fontSize);
466
+ } else {
467
+ style.fontSize = currentBaseFontSize;
468
+ }
469
+ const currentTagStyle = tag ? styles[tag] : {};
470
+ const currentTagColor = currentTagStyle.color;
471
+ const currentTagFill = currentTagStyle.fill;
472
+ if (currentTagColor !== undefined && currentTagFill === undefined) {
473
+ style.fill = style.color;
474
+ }
475
+ style.color = style.fill;
476
+ fontSizeStack.push(style.fontSize);
477
+ const styledToken = {
478
+ style,
479
+ tags,
480
+ children: token.children.map(convertTagTokenToStyledToken)
481
+ };
482
+ const imgKey = style[IMG_REFERENCE_PROPERTY] ?? "";
483
+ if (imgKey) {
484
+ if (spriteTemplates === undefined) {
485
+ throw new Error(`An image tag with ${IMG_REFERENCE_PROPERTY}="${imgKey}" was encountered, but no imgMap was provided. Please include a valid Sprite in the imgMap property in the options in your TaggedText constructor.`);
486
+ }
487
+ const sprite = spriteTemplates[imgKey];
488
+ if (sprite === undefined) {
489
+ throw new Error(`An image tag with ${IMG_REFERENCE_PROPERTY}="${imgKey}" was encountered, but there was no matching sprite in the sprite map. Please include a valid Sprite in the imgMap property in the options in your TaggedText constructor.`);
490
+ }
491
+ if (sprite instanceof PIXI__namespace.Sprite === false) {
492
+ throw new Error(`The image reference you provided for "${imgKey}" is not a Sprite. The imgMap can only accept PIXI.Sprite instances.`);
493
+ }
494
+ const cloneOfSprite = cloneSprite(sprite);
495
+ styledToken.children = [cloneOfSprite, ...styledToken.children];
496
+ }
497
+ tagStack.pop();
498
+ fontSizeStack.pop();
499
+ return styledToken;
500
+ };
501
+ return convertTagTokenToStyledToken(tokens);
502
+ };
503
+ const convertDecorationToLineProps = style => {
504
+ const {
505
+ textDecoration
506
+ } = style;
507
+ if (textDecoration === undefined || textDecoration === "normal" || textDecoration === "none") {
508
+ return style;
509
+ }
510
+ const {
511
+ decorationColor,
512
+ decorationThickness
513
+ } = style;
514
+ const defaultColor = decorationColor || style.fill || DEFAULT_STYLE.fill;
515
+ const defaultThickness = decorationThickness || 1;
516
+ const defaultOffset = 0;
517
+ function mergeDecoration(decorationLineType, decorationLineTypeCamelCase = decorationLineType) {
518
+ if (style.textDecoration?.includes(decorationLineType)) {
519
+ return {
520
+ [`${decorationLineTypeCamelCase}Color`]: style[`${decorationLineTypeCamelCase}Color`] ?? defaultColor,
521
+ [`${decorationLineTypeCamelCase}Thickness`]: style[`${decorationLineTypeCamelCase}Thickness`] ?? defaultThickness,
522
+ [`${decorationLineTypeCamelCase}Offset`]: style[`${decorationLineTypeCamelCase}Offset`] ?? defaultOffset
523
+ };
524
+ }
525
+ return {};
526
+ }
527
+ return {
528
+ ...style,
529
+ ...mergeDecoration("underline"),
530
+ ...mergeDecoration("overline"),
531
+ ...mergeDecoration("line-through", "lineThrough")
532
+ };
533
+ };
534
+ const extractDecorations = (style, textBounds, fontProperties) => {
535
+ const {
536
+ ascent,
537
+ descent
538
+ } = fontProperties;
539
+ const baseline = ascent;
540
+ const {
541
+ width
542
+ } = textBounds;
543
+ const x = 0;
544
+ function styleToMetrics(key) {
545
+ const color = style[`${key}Color`];
546
+ const height = style[`${key}Thickness`];
547
+ const offset = style[`${key}Offset`] ?? 0;
548
+ if (color === undefined || height === undefined) {
549
+ return undefined;
550
+ }
551
+ let y = offset;
552
+ if (key === "underline") {
553
+ y += baseline + descent / 2 + 4;
554
+ } else if (key === "lineThrough") {
555
+ const overlineY = 1;
556
+ const underlineY = baseline + descent / 2 + 4;
557
+ y += (overlineY + underlineY) / 2;
558
+ } else if (key === "overline") {
559
+ y += 1;
560
+ }
561
+ return {
562
+ color,
563
+ bounds: {
564
+ x,
565
+ y,
566
+ width,
567
+ height
568
+ }
569
+ };
570
+ }
571
+ const keySuffices = ["underline", "overline", "lineThrough"];
572
+ const metrics = keySuffices.map(styleToMetrics).filter(x => x !== undefined);
573
+ return metrics;
574
+ };
575
+ const convertUnsupportedAlignment = align => {
576
+ if (align === undefined) {
577
+ return undefined;
578
+ }
579
+ switch (align) {
580
+ case "justify":
581
+ case "justify-left":
582
+ case "justify-all":
583
+ return "left";
584
+ case "justify-center":
585
+ return "center";
586
+ case "justify-right":
587
+ return "right";
588
+ default:
589
+ return align;
590
+ }
591
+ };
592
+
593
+ const ICON_SCALE_BASE = 0.8;
594
+ new PIXI__namespace.Text({
595
+ text: ""
596
+ });
597
+ const rectFromContainer = (container, offset = {
598
+ x: 0,
599
+ y: 0
600
+ }) => {
601
+ const w = container.width;
602
+ const h = container.height;
603
+ const x = offset.x + container.x;
604
+ const y = offset.y + container.y;
605
+ return new PIXI__namespace.Rectangle(x, y, w, h);
606
+ };
607
+ const translatePoint = offset => point => {
608
+ const newX = point.x + offset.x;
609
+ return {
610
+ ...point,
611
+ x: newX,
612
+ y: point.y + offset.y
613
+ };
614
+ };
615
+ const translateLine = offset => line => line.map(translatePoint(offset));
616
+ const lineWidth = wordsInLine => {
617
+ const firstWord = first(wordsInLine);
618
+ const lastWord = last(wordsInLine);
619
+ if (firstWord === undefined) {
620
+ return 0;
621
+ }
622
+ if (lastWord === firstWord) {
623
+ return firstWord.width;
624
+ }
625
+ const width = lastWord.x + lastWord.width - firstWord.x;
626
+ if (width < -1000 || width > 100000 || isNaN(width)) {
627
+ console.warn('Extreme lineWidth detected in animation demo:', {
628
+ width,
629
+ firstWord: {
630
+ x: firstWord.x,
631
+ width: firstWord.width
632
+ },
633
+ lastWord: {
634
+ x: lastWord.x,
635
+ width: lastWord.width
636
+ },
637
+ numWords: wordsInLine.length,
638
+ calculation: `${lastWord.x} + ${lastWord.width} - ${firstWord.x} = ${width}`
639
+ });
640
+ }
641
+ return width;
642
+ };
643
+ const center = (x, context) => {
644
+ if (!isFinite(context)) {
645
+ return 0;
646
+ }
647
+ return (context - x) / 2;
648
+ };
649
+ const setBoundsX = assoc("x");
650
+ const positionWordX = x => word => {
651
+ let prevBounds;
652
+ const positionRecursive = item => {
653
+ if (Array.isArray(item)) {
654
+ return item.map(positionRecursive);
655
+ }
656
+ if (item && item.bounds) {
657
+ if (prevBounds === undefined) {
658
+ item.bounds.x = x;
659
+ prevBounds = item.bounds;
660
+ } else {
661
+ item.bounds.x = prevBounds.x + prevBounds.width;
662
+ prevBounds = item.bounds;
663
+ }
664
+ }
665
+ return item;
666
+ };
667
+ return positionRecursive(word);
668
+ };
669
+ const concatBounds = (originalBounds = {
670
+ x: NaN,
671
+ y: NaN,
672
+ width: NaN,
673
+ height: NaN
674
+ }, bounds = {
675
+ x: NaN,
676
+ y: NaN,
677
+ width: NaN,
678
+ height: NaN
679
+ }) => {
680
+ if (isNaN(originalBounds.x)) {
681
+ return bounds;
682
+ }
683
+ const x = Math.min(originalBounds.x, bounds.x);
684
+ const y = Math.min(originalBounds.y, bounds.y);
685
+ const right = Math.max(originalBounds.x + originalBounds.width, bounds.x + bounds.width);
686
+ const bottom = Math.max(originalBounds.y + originalBounds.height, bounds.y + bounds.height);
687
+ const width = right - x;
688
+ const height = bottom - y;
689
+ return {
690
+ x,
691
+ y,
692
+ width,
693
+ height
694
+ };
695
+ };
696
+ const getCombinedBounds = bounds => bounds.reduce(concatBounds, {
697
+ x: NaN,
698
+ y: NaN,
699
+ width: NaN,
700
+ height: NaN
701
+ });
702
+ const getBoundsNested = flatReduce((acc, t) => {
703
+ if (isNaN(acc.x)) {
704
+ return {
705
+ ...t.bounds
706
+ };
707
+ }
708
+ return concatBounds(acc, t.bounds);
709
+ }, {
710
+ x: NaN,
711
+ y: NaN,
712
+ width: NaN,
713
+ height: NaN
714
+ });
715
+ const alignLeft = line => {
716
+ return line.reduce((newLine, bounds, i) => {
717
+ if (i === 0) {
718
+ return [setBoundsX(0)(bounds)];
719
+ } else {
720
+ const prevBounds = newLine[i - 1];
721
+ const newX = prevBounds.x + prevBounds.width;
722
+ if (Math.abs(newX) > 10000 || prevBounds.width > 10000) {
723
+ console.error('EXTREME SPACING IN alignLeft:', {
724
+ wordIndex: i,
725
+ prevX: prevBounds.x,
726
+ prevWidth: prevBounds.width,
727
+ calculatedX: newX,
728
+ currentBounds: bounds
729
+ });
730
+ }
731
+ return newLine.concat([setBoundsX(newX)(bounds)]);
732
+ }
733
+ }, []);
734
+ };
735
+ const alignRight = maxWidth => line => {
736
+ const leftAligned = alignLeft(line);
737
+ return translateLine({
738
+ x: maxWidth - lineWidth(leftAligned),
739
+ y: 0
740
+ })(leftAligned);
741
+ };
742
+ const alignCenter = maxWidth => line => {
743
+ const leftAligned = alignLeft(line);
744
+ const width = lineWidth(leftAligned);
745
+ const centerOffset = center(width, maxWidth);
746
+ return translateLine({
747
+ x: centerOffset,
748
+ y: 0
749
+ })(leftAligned);
750
+ };
751
+ const alignJustify = maxLineWidth => line => {
752
+ const count = line.length;
753
+ if (count === 0) {
754
+ return [];
755
+ }
756
+ const nonZeroWidthWords = line.filter(({
757
+ width
758
+ }) => width > 0);
759
+ const countNonZeroWidthWords = nonZeroWidthWords.length;
760
+ if (countNonZeroWidthWords === 1) {
761
+ const [first, ...rest] = line;
762
+ first.x = 0;
763
+ return [first, ...rest];
764
+ }
765
+ const result = [];
766
+ const combinedBounds = getCombinedBounds(nonZeroWidthWords);
767
+ const w = combinedBounds.width;
768
+ const totalSpace = maxLineWidth - w;
769
+ const spacerWidth = totalSpace > 0 ? totalSpace / (countNonZeroWidthWords - 1) : 0;
770
+ let previousWord;
771
+ for (let i = 0; i < line.length; i++) {
772
+ const bounds = line[i];
773
+ if (bounds.width === 0) {
774
+ result[i] = {
775
+ ...bounds
776
+ };
777
+ continue;
778
+ }
779
+ let x;
780
+ if (previousWord === undefined) {
781
+ x = 0;
782
+ } else {
783
+ x = previousWord.x + previousWord.width + spacerWidth;
784
+ }
785
+ if (isNaN(x)) {
786
+ throw new Error(`Something went wrong with the justified layout calculation. x is NaN.`);
787
+ }
788
+ const newWord = setBoundsX(x)(bounds);
789
+ previousWord = newWord;
790
+ result[i] = newWord;
791
+ }
792
+ return result;
793
+ };
794
+ const alignLines = (align, maxWidth, lines) => {
795
+ let alignFunction;
796
+ let lastAlignFunction;
797
+ switch (align) {
798
+ case "left":
799
+ alignFunction = alignLeft;
800
+ lastAlignFunction = alignFunction;
801
+ break;
802
+ case "right":
803
+ alignFunction = alignRight(maxWidth);
804
+ lastAlignFunction = alignFunction;
805
+ break;
806
+ case "center":
807
+ alignFunction = alignCenter(maxWidth);
808
+ lastAlignFunction = alignFunction;
809
+ break;
810
+ case "justify":
811
+ case "justify-left":
812
+ alignFunction = alignJustify(maxWidth);
813
+ lastAlignFunction = alignLeft;
814
+ break;
815
+ case "justify-right":
816
+ alignFunction = alignJustify(maxWidth);
817
+ lastAlignFunction = alignRight(maxWidth);
818
+ break;
819
+ case "justify-center":
820
+ alignFunction = alignJustify(maxWidth);
821
+ lastAlignFunction = alignCenter(maxWidth);
822
+ break;
823
+ case "justify-all":
824
+ alignFunction = alignJustify(maxWidth);
825
+ lastAlignFunction = alignFunction;
826
+ break;
827
+ default:
828
+ throw new Error(`Unsupported alignment type ${align}! Use one of : "left", "right", "center", "justify", "justify-left", "justify-right", justify-center", "justify-all"`);
829
+ }
830
+ for (const line of lines) {
831
+ const isLastLine = lines.indexOf(line) === lines.length - 1 || line.flat(2).filter(isNewlineToken).length > 0;
832
+ const wordBoundsForLine = [];
833
+ let alignedLine;
834
+ let isFirstWord = true;
835
+ let expectedX = 0;
836
+ for (const word of line) {
837
+ const wordBounds = getBoundsNested(word);
838
+ if (isFirstWord) {
839
+ expectedX = wordBounds.x;
840
+ wordBounds.x = 0;
841
+ isFirstWord = false;
842
+ } else {
843
+ wordBounds.x = wordBounds.x - expectedX;
844
+ }
845
+ wordBoundsForLine.push(wordBounds);
846
+ }
847
+ if (isLastLine) {
848
+ alignedLine = lastAlignFunction(wordBoundsForLine);
849
+ } else {
850
+ alignedLine = alignFunction(wordBoundsForLine);
851
+ }
852
+ for (let i = 0; i < line.length; i++) {
853
+ const word = line[i];
854
+ if (i < alignedLine.length) {
855
+ const bounds = alignedLine[i];
856
+ const updatedWord = positionWordX(bounds.x)(word);
857
+ line[i] = updatedWord;
858
+ }
859
+ }
860
+ }
861
+ return lines;
862
+ };
863
+ const getTallestToken = line => flatReduce((tallest, current) => {
864
+ let h = current.bounds.height ?? 0;
865
+ if (isSpriteToken(current)) {
866
+ h += current.fontProperties.descent;
867
+ }
868
+ const tallestH = tallest?.bounds.height ?? 0;
869
+ if (h > tallestH) {
870
+ return current;
871
+ }
872
+ return tallest;
873
+ }, createEmptySegmentToken())(line);
874
+ const verticalAlignInLines = (lines, lineSpacing, overrideValign) => {
875
+ let previousTallestToken = createEmptySegmentToken();
876
+ let previousLineBottom = 0;
877
+ let paragraphModifier = 0;
878
+ const newLines = [];
879
+ for (const line of lines) {
880
+ const newLine = [];
881
+ let tallestToken = getTallestToken(line);
882
+ let tallestHeight = (tallestToken.bounds?.height ?? 0) + paragraphModifier;
883
+ let tallestAscent = 0;
884
+ for (const word of line) {
885
+ for (const segment of word) {
886
+ const segAscent = segment.fontProperties?.ascent ?? 0;
887
+ if (segAscent > tallestAscent) {
888
+ tallestAscent = segAscent;
889
+ }
890
+ }
891
+ }
892
+ tallestAscent += paragraphModifier;
893
+ const valignParagraphModifier = paragraphModifier;
894
+ paragraphModifier = 0;
895
+ const lastToken = line[line.length - 1][0];
896
+ if (isNewlineToken(lastToken)) {
897
+ paragraphModifier = tallestToken.style.paragraphSpacing ?? 0;
898
+ }
899
+ if (isSpriteToken(tallestToken)) {
900
+ tallestHeight += tallestToken.fontProperties.descent;
901
+ tallestAscent = tallestToken.bounds.height;
902
+ }
903
+ if (tallestHeight === 0) {
904
+ tallestToken = previousTallestToken;
905
+ } else {
906
+ previousTallestToken = tallestToken;
907
+ }
908
+ for (const word of line) {
909
+ const newWord = [];
910
+ for (const segment of word) {
911
+ const {
912
+ bounds,
913
+ fontProperties,
914
+ style
915
+ } = segment;
916
+ const {
917
+ height
918
+ } = bounds;
919
+ const newBounds = {
920
+ ...bounds
921
+ };
922
+ const valign = overrideValign ?? style.valign;
923
+ let {
924
+ ascent
925
+ } = fontProperties;
926
+ if (isSpriteToken(segment)) {
927
+ const imgDisplay = segment.style[IMG_DISPLAY_PROPERTY];
928
+ if (imgDisplay === 'icon') {
929
+ ascent = segment.bounds.height - 4;
930
+ } else {
931
+ ascent = segment.bounds.height;
932
+ }
933
+ }
934
+ if (isNewlineToken(segment)) {
935
+ const newToken = {
936
+ ...segment
937
+ };
938
+ newToken.bounds.y = previousLineBottom + tallestAscent - ascent;
939
+ newWord.push(newToken);
940
+ continue;
941
+ }
942
+ let newY = previousLineBottom;
943
+ const hasStroke = style?.stroke && style.strokeThickness > 0;
944
+ const strokeThickness = hasStroke ? style.strokeThickness : 0;
945
+ switch (valign) {
946
+ case "bottom":
947
+ newY += tallestHeight - height;
948
+ if (hasStroke) {
949
+ newY -= strokeThickness / 2;
950
+ }
951
+ break;
952
+ case "middle":
953
+ newY += (tallestHeight + valignParagraphModifier - height) / 2;
954
+ if (hasStroke) {
955
+ newY -= strokeThickness / 2;
956
+ }
957
+ break;
958
+ case "top":
959
+ newY += valignParagraphModifier;
960
+ if (hasStroke) {
961
+ newY -= strokeThickness / 2;
962
+ }
963
+ break;
964
+ case "baseline":
965
+ default:
966
+ newY = previousLineBottom + tallestAscent - ascent;
967
+ if (hasStroke) {
968
+ newY -= strokeThickness / 2;
969
+ }
970
+ }
971
+ newBounds.y = newY;
972
+ const newToken = {
973
+ ...segment,
974
+ bounds: newBounds
975
+ };
976
+ newWord.push(newToken);
977
+ }
978
+ newLine.push(newWord);
979
+ }
980
+ previousLineBottom += tallestHeight + lineSpacing;
981
+ newLines.push(newLine);
982
+ }
983
+ return newLines;
984
+ };
985
+ const collapseWhitespacesOnEndOfLines = lines => {
986
+ for (const line of lines) {
987
+ const l = line.length;
988
+ let i = l;
989
+ while (i >= 0) {
990
+ i -= 1;
991
+ const word = line[i];
992
+ if (isNotWhitespaceToken(word)) {
993
+ break;
994
+ } else {
995
+ for (const token of word) {
996
+ token.bounds.width = 0;
997
+ token.bounds.height = Math.min(token.bounds.height, token.fontProperties.fontSize);
998
+ }
999
+ }
1000
+ }
1001
+ }
1002
+ return lines;
1003
+ };
1004
+ const layout = (tokens, maxWidth, lineSpacing, align, _splitStyle) => {
1005
+ const cursor = {
1006
+ x: 0,
1007
+ y: 0
1008
+ };
1009
+ let wordWidth = 0;
1010
+ let word = [];
1011
+ let line = [];
1012
+ const allLines = [];
1013
+ let tallestHeightInLine = 0;
1014
+ let token;
1015
+ for (let i = 0; i < tokens.length; i++) {
1016
+ token = tokens[i];
1017
+ const normalLineBreaks = hasNormalLineBreaks(token);
1018
+ const isWhitespace = isWhitespaceToken(token);
1019
+ const isNewline = isNewlineToken(token);
1020
+ const isImage = isSpriteToken(token);
1021
+ const isWordEndingToken = isWhitespace || isImage;
1022
+ if (isWordEndingToken && normalLineBreaks || isNewline || token.style.breakWords) {
1023
+ positionWordBufferAndAddToLine();
1024
+ }
1025
+ addTokenToWordAndUpdateWordWidth(token);
1026
+ setTallestHeight(token);
1027
+ if (isWhitespace && normalLineBreaks || isNewline) {
1028
+ positionWordBufferAndAddToLine();
1029
+ }
1030
+ if (isNewline || isBlockImage(token)) {
1031
+ addLineToListOfLinesAndMoveCursorToNextLine(token);
1032
+ } else if (wordInBufferExceedsLineLength()) {
1033
+ if (line.length > 0) {
1034
+ addLineToListOfLinesAndMoveCursorToNextLine(token);
1035
+ }
1036
+ }
1037
+ }
1038
+ if (word.length > 0) {
1039
+ positionWordBufferAndAddToLine();
1040
+ }
1041
+ if (line.length > 0) {
1042
+ addLineToListOfLines();
1043
+ }
1044
+ const collapsedWhitespace = collapseWhitespacesOnEndOfLines(allLines);
1045
+ const alignedLines = alignLines(align, maxWidth, collapsedWhitespace);
1046
+ const valignedLines = verticalAlignInLines(alignedLines, lineSpacing);
1047
+ return valignedLines;
1048
+ function addWordBufferToLineBuffer() {
1049
+ if (word !== undefined && word.length > 0) {
1050
+ line.push(word);
1051
+ }
1052
+ word = [];
1053
+ wordWidth = 0;
1054
+ }
1055
+ function addLineToListOfLines() {
1056
+ allLines.push(line);
1057
+ line = [];
1058
+ }
1059
+ function addLineToListOfLinesAndMoveCursorToNextLine(token) {
1060
+ addLineToListOfLines();
1061
+ cursor.x = 0;
1062
+ cursor.y = cursor.y + tallestHeightInLine + lineSpacing;
1063
+ tallestHeightInLine = 0;
1064
+ setTallestHeight(token);
1065
+ }
1066
+ function setTallestHeight(token) {
1067
+ const fontSize = token?.fontProperties?.fontSize ?? 0;
1068
+ const height = token?.bounds?.height ?? 0;
1069
+ tallestHeightInLine = Math.max(tallestHeightInLine, fontSize);
1070
+ if (isNewlineToken(token) === false) {
1071
+ tallestHeightInLine = Math.max(tallestHeightInLine, height);
1072
+ }
1073
+ }
1074
+ function positionTokenAtCursorAndAdvanceCursor(token) {
1075
+ setTallestHeight(token);
1076
+ if (Math.abs(cursor.x) > 10000) {
1077
+ console.error('EXTREME CURSOR.X BEFORE ASSIGNMENT:', {
1078
+ cursorX: cursor.x,
1079
+ cursorY: cursor.y,
1080
+ tokenContent: token.content,
1081
+ tokenWidth: token.bounds.width,
1082
+ tokenBounds: {
1083
+ ...token.bounds
1084
+ }
1085
+ });
1086
+ }
1087
+ token.bounds.x = cursor.x;
1088
+ token.bounds.y = cursor.y;
1089
+ cursor.x += token.bounds.width;
1090
+ if (Math.abs(cursor.x) > 10000) {
1091
+ console.error('EXTREME CURSOR.X AFTER ADVANCING:', {
1092
+ cursorX: cursor.x,
1093
+ tokenContent: token.content,
1094
+ tokenWidth: token.bounds.width
1095
+ });
1096
+ }
1097
+ }
1098
+ function positionWordBufferAtCursorAndAdvanceCursor() {
1099
+ word.forEach(positionTokenAtCursorAndAdvanceCursor);
1100
+ }
1101
+ function wordInBufferExceedsLineLength() {
1102
+ return cursor.x + wordWidth > maxWidth;
1103
+ }
1104
+ function isBlockImage(token) {
1105
+ return token.style[IMG_DISPLAY_PROPERTY] === "block";
1106
+ }
1107
+ function hasNormalLineBreaks(token) {
1108
+ return token.style.breakLines ?? true;
1109
+ }
1110
+ function addTokenToWordAndUpdateWordWidth(token) {
1111
+ word.push(token);
1112
+ wordWidth += token.bounds.width;
1113
+ }
1114
+ function positionWordBufferAndAddToLine() {
1115
+ positionWordBufferAtCursorAndAdvanceCursor();
1116
+ addWordBufferToLineBuffer();
1117
+ }
1118
+ };
1119
+ const notEmptyString = s => s !== "";
1120
+ const SPLIT_MARKER = `_🔪_`;
1121
+ const splitAroundWhitespace = s => s.replace(/\s/g, `${SPLIT_MARKER}$&${SPLIT_MARKER}`).split(SPLIT_MARKER).filter(s => s !== "");
1122
+ const splitText = (s, splitStyle) => {
1123
+ if (splitStyle === "words") {
1124
+ return [s].flatMap(splitAroundWhitespace).filter(notEmptyString);
1125
+ } else if (splitStyle === "characters") {
1126
+ return s.split("");
1127
+ } else {
1128
+ let suggestion = ` Supported styles are "words" and "characters"`;
1129
+ const badStyle = splitStyle.toLowerCase();
1130
+ if (badStyle.indexOf("char") === 0) {
1131
+ suggestion = `Did you mean "characters"?`;
1132
+ } else if (badStyle.indexOf("wor") === 0) {
1133
+ suggestion = `Did you mean "words"?`;
1134
+ }
1135
+ throw new Error(`Unsupported split style "${splitStyle}". ${suggestion}`);
1136
+ }
1137
+ };
1138
+ const calculateTokens = (styledTokens, splitStyle = "words", scaleIcons = true, adjustFontBaseline) => {
1139
+ const defaultStyle = styledTokens.style;
1140
+ let fontProperties;
1141
+ const generateTokensFormStyledToken = (style, tags) => token => {
1142
+ let output = [];
1143
+ const alignClassic = convertUnsupportedAlignment(style.align);
1144
+ tags && tags.includes("outline");
1145
+ const cleanedStyle = {
1146
+ ...style
1147
+ };
1148
+ const sizerStyle = {
1149
+ ...cleanedStyle,
1150
+ align: alignClassic,
1151
+ wordWrap: false,
1152
+ dropShadow: undefined,
1153
+ fontFamily: cleanedStyle.fontFamily || 'Arial',
1154
+ fontSize: cleanedStyle.fontSize || 24,
1155
+ fill: cleanedStyle.fill || 0x000000
1156
+ };
1157
+ const strokeThickness = sizerStyle.strokeThickness;
1158
+ delete sizerStyle.stroke;
1159
+ delete sizerStyle.strokeThickness;
1160
+ const localSizer = new PIXI__namespace.Text({
1161
+ text: "",
1162
+ style: sizerStyle
1163
+ });
1164
+ if (typeof token === "string") {
1165
+ const textSegments = splitText(token, splitStyle);
1166
+ const textTokens = textSegments.map(str => {
1167
+ switch (style.textTransform) {
1168
+ case "uppercase":
1169
+ localSizer.text = str.toUpperCase();
1170
+ break;
1171
+ case "lowercase":
1172
+ localSizer.text = str.toLowerCase();
1173
+ break;
1174
+ case "capitalize":
1175
+ localSizer.text = capitalize(str);
1176
+ break;
1177
+ default:
1178
+ localSizer.text = str;
1179
+ }
1180
+ fontProperties = {
1181
+ ...getFontPropertiesOfText(localSizer, true)
1182
+ };
1183
+ if (isOnlyWhitespace(token) === false) {
1184
+ const stroke = localSizer.style.stroke ?? 0;
1185
+ if (stroke > 0) {
1186
+ fontProperties.descent += stroke / 2;
1187
+ fontProperties.ascent += stroke / 2;
1188
+ fontProperties.fontSize = fontProperties.ascent + fontProperties.descent;
1189
+ }
1190
+ }
1191
+ const sw = style.fontScaleWidth ?? 1.0;
1192
+ const sh = style.fontScaleHeight ?? 1.0;
1193
+ const scaleWidth = isNaN(sw) || sw < 0 ? 0.0 : sw;
1194
+ const scaleHeight = isNaN(sh) || sh < 0 ? 0.0 : sh;
1195
+ localSizer.scale.set(scaleWidth, scaleHeight);
1196
+ fontProperties.ascent *= scaleHeight;
1197
+ fontProperties.descent *= scaleHeight;
1198
+ fontProperties.fontSize *= scaleHeight;
1199
+ let bounds;
1200
+ if (isOnlyWhitespace(str)) {
1201
+ const fontSize = typeof localSizer.style.fontSize === 'string' ? parseInt(localSizer.style.fontSize) : localSizer.style.fontSize || 24;
1202
+ const spaceWidth = fontSize * 0.3 * str.length;
1203
+ const height = fontProperties.fontSize;
1204
+ bounds = new PIXI__namespace.Rectangle(0, 0, spaceWidth, height);
1205
+ } else {
1206
+ const measureSizer = new PIXI__namespace.Text({
1207
+ text: localSizer.text,
1208
+ style: {
1209
+ ...localSizer.style
1210
+ }
1211
+ });
1212
+ measureSizer.scale.set(localSizer.scale.x, localSizer.scale.y);
1213
+ bounds = rectFromContainer(measureSizer);
1214
+ if (strokeThickness && strokeThickness > 0) {
1215
+ bounds.width += strokeThickness;
1216
+ bounds.height += strokeThickness;
1217
+ }
1218
+ }
1219
+ if (isNaN(bounds.width) || isNaN(bounds.height)) {
1220
+ console.error(`[ERROR] NaN bounds after all attempts for token "${str}" with tags="${tags}"`);
1221
+ if (isOnlyWhitespace(str)) {
1222
+ bounds = new PIXI__namespace.Rectangle(0, 0, fontProperties.fontSize * 0.3 * str.length, fontProperties.fontSize);
1223
+ } else {
1224
+ bounds = new PIXI__namespace.Rectangle(0, 0, 0, fontProperties.fontSize);
1225
+ }
1226
+ }
1227
+ const textDecorations = extractDecorations(style, bounds, fontProperties);
1228
+ const baselineAdjustment = getBaselineAdjustment(style, adjustFontBaseline, fontProperties.ascent);
1229
+ fontProperties.ascent += baselineAdjustment;
1230
+ const {
1231
+ letterSpacing
1232
+ } = style;
1233
+ if (letterSpacing) {
1234
+ bounds.width += letterSpacing;
1235
+ }
1236
+ const convertedToken = {
1237
+ content: str,
1238
+ style,
1239
+ tags,
1240
+ bounds,
1241
+ fontProperties,
1242
+ textDecorations
1243
+ };
1244
+ return convertedToken;
1245
+ });
1246
+ output = output.concat(textTokens);
1247
+ } else if (token instanceof PIXI__namespace.Sprite) {
1248
+ const sprite = token;
1249
+ const imgDisplay = style[IMG_DISPLAY_PROPERTY];
1250
+ const isIcon = imgDisplay === "icon";
1251
+ if (localSizer.text === "") {
1252
+ localSizer.text = "Mg";
1253
+ }
1254
+ fontProperties = {
1255
+ ...getFontPropertiesOfText(localSizer, true)
1256
+ };
1257
+ if (strokeThickness && strokeThickness > 0) {
1258
+ fontProperties.ascent += strokeThickness / 2;
1259
+ fontProperties.descent += strokeThickness / 2;
1260
+ fontProperties.fontSize = fontProperties.ascent + fontProperties.descent;
1261
+ }
1262
+ if (isIcon) {
1263
+ const h = Math.max(sprite.height, 1);
1264
+ if (h > 1 && sprite.scale.y === 1) {
1265
+ const {
1266
+ iconScale = 1.0
1267
+ } = style;
1268
+ const effectiveFontSize = fontProperties.fontSize || 20;
1269
+ const ratio = effectiveFontSize / h * ICON_SCALE_BASE * iconScale;
1270
+ sprite.scale.set(ratio);
1271
+ }
1272
+ if (scaleIcons) {
1273
+ const {
1274
+ fontScaleWidth: scaleX = 1.0,
1275
+ fontScaleHeight: scaleY = 1.0
1276
+ } = style;
1277
+ sprite.scale.x *= scaleX;
1278
+ sprite.scale.y *= scaleY;
1279
+ }
1280
+ }
1281
+ const bounds = rectFromContainer(sprite);
1282
+ const {
1283
+ letterSpacing
1284
+ } = style;
1285
+ if (letterSpacing && isIcon) {
1286
+ bounds.width += letterSpacing;
1287
+ }
1288
+ output.push({
1289
+ content: sprite,
1290
+ style,
1291
+ tags,
1292
+ bounds,
1293
+ fontProperties,
1294
+ textDecorations: undefined
1295
+ });
1296
+ } else {
1297
+ const styledToken = token;
1298
+ const {
1299
+ children
1300
+ } = styledToken;
1301
+ const newStyle = styledToken.style;
1302
+ const newTags = styledToken.tags;
1303
+ if (newStyle === undefined) {
1304
+ throw new Error(`Expected to find a 'style' property on ${styledToken}`);
1305
+ }
1306
+ output = output.concat(children.flatMap(generateTokensFormStyledToken(newStyle, newTags)));
1307
+ }
1308
+ return output;
1309
+ };
1310
+ const tags = "";
1311
+ const style = defaultStyle;
1312
+ const finalTokens = styledTokens.children.flatMap(generateTokensFormStyledToken(style, tags));
1313
+ const {
1314
+ wordWrap: ww,
1315
+ wordWrapWidth: www
1316
+ } = defaultStyle;
1317
+ const hasWordWrapWidth = www !== undefined && isNaN(www) === false && www > 0;
1318
+ const maxWidth = ww && hasWordWrapWidth ? www : Number.POSITIVE_INFINITY;
1319
+ const lineSpacing = defaultStyle.lineSpacing ?? 0;
1320
+ const align = defaultStyle.align ?? "left";
1321
+ const lines = layout(finalTokens, maxWidth, lineSpacing, align);
1322
+ return lines;
1323
+ };
1324
+ const getBaselineAdjustment = (style, fontBaselineMap = {}, ascent) => {
1325
+ const fontFamily = style.fontFamily?.toString() ?? "";
1326
+ const adjustBaseline = style.adjustBaseline ?? 0;
1327
+ const adjustFontBaseline = fontBaselineMap[fontFamily] ?? null;
1328
+ let finalValue = adjustBaseline;
1329
+ if (typeof adjustFontBaseline === "string") {
1330
+ const percentPair = adjustFontBaseline.split("%");
1331
+ const isPercent = percentPair.length > 1;
1332
+ const value = Number(percentPair[0]);
1333
+ if (isPercent) {
1334
+ finalValue += ascent * (value / 100);
1335
+ } else {
1336
+ finalValue += value;
1337
+ }
1338
+ } else {
1339
+ finalValue += Number(adjustFontBaseline);
1340
+ }
1341
+ return finalValue;
1342
+ };
1343
+
1344
+ const DEFAULT_OPTIONS = {
1345
+ debug: false,
1346
+ debugConsole: false,
1347
+ splitStyle: "words",
1348
+ imgMap: {},
1349
+ scaleIcons: true,
1350
+ skipUpdates: false,
1351
+ skipDraw: false,
1352
+ drawWhitespace: false,
1353
+ wrapEmoji: true,
1354
+ errorHandler: undefined,
1355
+ supressConsole: false,
1356
+ overdrawDecorations: 0
1357
+ };
1358
+
1359
+ const DEBUG = {
1360
+ WORD_STROKE_COLOR: 0xffcccc,
1361
+ WORD_FILL_COLOR: 0xeeeeee,
1362
+ TEXT_FIELD_STROKE_COLOR: 0xff00ff,
1363
+ WHITESPACE_COLOR: 0xcccccc,
1364
+ WHITESPACE_STROKE_COLOR: 0xaaaaaa,
1365
+ BASELINE_COLOR: 0xffff99,
1366
+ LINE_COLOR: 0xffff00,
1367
+ OUTLINE_COLOR: 0xffcccc,
1368
+ OUTLINE_SHADOW_COLOR: 0x000000,
1369
+ TEXT_STYLE: {
1370
+ fontFamily: "courier",
1371
+ fontSize: 10,
1372
+ fill: 0xffffff,
1373
+ dropShadow: {
1374
+ color: 0x000000,
1375
+ blur: 2,
1376
+ distance: 2,
1377
+ alpha: 1
1378
+ }
1379
+ }
1380
+ };
1381
+ const DEFAULT_STYLE_SET = {
1382
+ default: DEFAULT_STYLE
1383
+ };
1384
+ Object.freeze(DEFAULT_STYLE_SET);
1385
+ Object.freeze(DEFAULT_STYLE);
1386
+ const DEFAULT_DESTROY_OPTIONS = {
1387
+ children: true,
1388
+ texture: true,
1389
+ textureSource: false,
1390
+ context: false
1391
+ };
1392
+ class Glyphs extends PIXI__namespace.Container {
1393
+ static get defaultStyles() {
1394
+ return DEFAULT_STYLE_SET;
1395
+ }
1396
+ static get defaultOptions() {
1397
+ return DEFAULT_OPTIONS;
1398
+ }
1399
+ get options() {
1400
+ return this._options;
1401
+ }
1402
+ get needsUpdate() {
1403
+ return this._needsUpdate;
1404
+ }
1405
+ get needsDraw() {
1406
+ return this._needsDraw;
1407
+ }
1408
+ get tokens() {
1409
+ return this._tokens;
1410
+ }
1411
+ get tokensFlat() {
1412
+ return this._tokens.flat(Infinity);
1413
+ }
1414
+ get text() {
1415
+ return this._text;
1416
+ }
1417
+ set text(text) {
1418
+ this.setText(text);
1419
+ }
1420
+ setText(text, skipUpdate) {
1421
+ if (text === this._text && this._needsUpdate === false) {
1422
+ return;
1423
+ }
1424
+ this._text = text;
1425
+ this._needsUpdate = true;
1426
+ this.updateIfShould(skipUpdate);
1427
+ }
1428
+ get untaggedText() {
1429
+ return removeTags(this.text);
1430
+ }
1431
+ get tagStyles() {
1432
+ return this._tagStyles;
1433
+ }
1434
+ set tagStyles(styles) {
1435
+ this.setTagStyles(styles);
1436
+ }
1437
+ setTagStyles(styles, skipUpdate) {
1438
+ Object.entries(styles).forEach(([tag, style]) => this.setStyleForTag(tag, style, true));
1439
+ this._needsUpdate = true;
1440
+ this.updateIfShould(skipUpdate);
1441
+ }
1442
+ getStyleForTag(tag, attributes = {}) {
1443
+ return getStyleForTag(tag, this.tagStyles, attributes);
1444
+ }
1445
+ getStyleForTags(tags) {
1446
+ const styles = tags.map(({
1447
+ tagName,
1448
+ attributes
1449
+ }) => this.getStyleForTag(tagName, attributes));
1450
+ return combineAllStyles(styles);
1451
+ }
1452
+ setStyleForTag(tag, styles, skipUpdate) {
1453
+ this.tagStyles[tag] = styles;
1454
+ if (tag === DEFAULT_KEY && this.defaultStyle[IMG_REFERENCE_PROPERTY]) {
1455
+ this.logWarning(`${IMG_REFERENCE_PROPERTY}-on-default`, `Style "${IMG_REFERENCE_PROPERTY}" can not be set on the "${DEFAULT_KEY}" style because it will add images to EVERY tag!`);
1456
+ this.defaultStyle[IMG_REFERENCE_PROPERTY] = undefined;
1457
+ }
1458
+ this._needsUpdate = true;
1459
+ this.updateIfShould(skipUpdate);
1460
+ return true;
1461
+ }
1462
+ removeStylesForTag(tag, skipUpdate) {
1463
+ if (tag in this.tagStyles) {
1464
+ delete this.tagStyles[tag];
1465
+ this._needsUpdate = true;
1466
+ this.updateIfShould(skipUpdate);
1467
+ return true;
1468
+ }
1469
+ return false;
1470
+ }
1471
+ get defaultStyle() {
1472
+ return this.tagStyles?.default;
1473
+ }
1474
+ set defaultStyle(defaultStyles) {
1475
+ this.setDefaultStyle(defaultStyles);
1476
+ }
1477
+ setDefaultStyle(defaultStyles, skipUpdate) {
1478
+ this.setStyleForTag(DEFAULT_KEY, defaultStyles, skipUpdate);
1479
+ }
1480
+ get textFields() {
1481
+ return this._textFields;
1482
+ }
1483
+ get sprites() {
1484
+ return this._sprites;
1485
+ }
1486
+ get decorations() {
1487
+ return this._decorations;
1488
+ }
1489
+ get spriteTemplates() {
1490
+ return this._spriteTemplates;
1491
+ }
1492
+ get textContainer() {
1493
+ return this._textContainer;
1494
+ }
1495
+ get decorationContainer() {
1496
+ return this._decorationContainer;
1497
+ }
1498
+ get spriteContainer() {
1499
+ return this._spriteContainer;
1500
+ }
1501
+ get debugContainer() {
1502
+ return this._debugContainer;
1503
+ }
1504
+ constructor(text = "", tagStyles = {}, options = {}) {
1505
+ super();
1506
+ this._options = void 0;
1507
+ this._needsUpdate = true;
1508
+ this._needsDraw = true;
1509
+ this._tokens = [];
1510
+ this._text = "";
1511
+ this._tagStyles = {};
1512
+ this._textFields = [];
1513
+ this._sprites = [];
1514
+ this._decorations = [];
1515
+ this._spriteTemplates = {};
1516
+ this._debugGraphics = void 0;
1517
+ this._textContainer = void 0;
1518
+ this._decorationContainer = void 0;
1519
+ this._spriteContainer = void 0;
1520
+ this._debugContainer = void 0;
1521
+ this.logWarning = (code, message) => logWarning(this.options.errorHandler, this.options.supressConsole, this)(code, message);
1522
+ this._textContainer = new PIXI__namespace.Container();
1523
+ this._spriteContainer = new PIXI__namespace.Container();
1524
+ this._decorationContainer = new PIXI__namespace.Container();
1525
+ this._debugContainer = new PIXI__namespace.Container();
1526
+ this._debugGraphics = new PIXI__namespace.Graphics();
1527
+ this.resetChildren();
1528
+ const mergedOptions = {
1529
+ ...DEFAULT_OPTIONS,
1530
+ ...options
1531
+ };
1532
+ this._options = mergedOptions;
1533
+ tagStyles = {
1534
+ default: {},
1535
+ ...tagStyles
1536
+ };
1537
+ if (this.options.wrapEmoji) {
1538
+ const userStyles = tagStyles[EMOJI_TAG];
1539
+ tagStyles[EMOJI_TAG] = {
1540
+ fontFamily: "sans-serif",
1541
+ ...userStyles
1542
+ };
1543
+ }
1544
+ const mergedDefaultStyles = {
1545
+ ...DEFAULT_STYLE,
1546
+ ...tagStyles.default
1547
+ };
1548
+ tagStyles.default = mergedDefaultStyles;
1549
+ this.tagStyles = tagStyles;
1550
+ if (this.options.imgMap) {
1551
+ this.createSpriteTemplatesFromSourceMap(this.options.imgMap);
1552
+ }
1553
+ this.text = text;
1554
+ }
1555
+ destroyImgMap() {
1556
+ if (this.destroyed) {
1557
+ throw new Error("destroyImgMap() was called after this object was already destroyed. You must call destroyImgMap() before destroy() because imgMap is cleared when the object is destroyed.");
1558
+ }
1559
+ this._spriteContainer.destroy({
1560
+ children: true,
1561
+ texture: true,
1562
+ textureSource: true
1563
+ });
1564
+ }
1565
+ destroy(options) {
1566
+ let destroyOptions;
1567
+ if (options === undefined || options === true) {
1568
+ destroyOptions = {};
1569
+ } else if (options === false) {
1570
+ destroyOptions = DEFAULT_DESTROY_OPTIONS;
1571
+ } else {
1572
+ destroyOptions = {
1573
+ ...DEFAULT_DESTROY_OPTIONS,
1574
+ ...options
1575
+ };
1576
+ }
1577
+ this._spriteContainer.destroy(false);
1578
+ super.destroy(destroyOptions);
1579
+ this._textFields = [];
1580
+ this._sprites = [];
1581
+ this._decorations = [];
1582
+ this._spriteTemplates = {};
1583
+ this._tokens = [];
1584
+ this._tagStyles = {};
1585
+ this._options.imgMap = {};
1586
+ this._options.skipUpdates = true;
1587
+ this._options.skipDraw = true;
1588
+ this._options = {};
1589
+ }
1590
+ resetChildren() {
1591
+ if (this._textContainer) {
1592
+ this._textContainer.removeChildren();
1593
+ this.removeChild(this._textContainer);
1594
+ }
1595
+ this._textContainer = new PIXI__namespace.Container();
1596
+ this.addChild(this._textContainer);
1597
+ if (this._spriteContainer) {
1598
+ this._spriteContainer.removeChildren();
1599
+ this.removeChild(this._spriteContainer);
1600
+ }
1601
+ this._spriteContainer = new PIXI__namespace.Container();
1602
+ this.addChild(this._spriteContainer);
1603
+ if (this._decorationContainer) {
1604
+ this._decorationContainer.removeChildren();
1605
+ this.removeChild(this._decorationContainer);
1606
+ }
1607
+ this._decorationContainer = new PIXI__namespace.Container();
1608
+ this.addChild(this._decorationContainer);
1609
+ if (this._debugContainer) {
1610
+ this._debugContainer.removeChildren();
1611
+ this.removeChild(this._debugContainer);
1612
+ }
1613
+ this._debugContainer = new PIXI__namespace.Container();
1614
+ this.addChild(this._debugContainer);
1615
+ this._textFields = [];
1616
+ this._sprites = [];
1617
+ this._decorations = [];
1618
+ }
1619
+ createSpriteTemplatesFromSourceMap(imgMap) {
1620
+ this._spriteTemplates = {};
1621
+ Object.entries(imgMap).forEach(([key, spriteSource]) => {
1622
+ const wrongFormatError = new TypeError(`The spriteSource provided for key ${key} was not in a valid format. Please use a Sprite, Texture, BaseTexture, string, HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, or SVGElement`);
1623
+ const destroyedError = new Error(`The spriteSource provided for key ${key} appears to be a Sprite or Texture that has been destroyed or removed from PIXI.TextureCache probably using \`destroy()\` with aggressive options or \`destroyImgMap()\`.`);
1624
+ let error = null;
1625
+ let sprite = new PIXI__namespace.Sprite();
1626
+ try {
1627
+ if (spriteSource instanceof PIXI__namespace.Sprite) {
1628
+ sprite = spriteSource;
1629
+ } else if (isSpriteSource(spriteSource)) {
1630
+ const texture = spriteSource instanceof PIXI__namespace.Texture ? spriteSource : PIXI__namespace.Texture.from(spriteSource);
1631
+ sprite = new PIXI__namespace.Sprite(texture);
1632
+ } else if (isTextureSource(spriteSource)) {
1633
+ sprite = new PIXI__namespace.Sprite(PIXI__namespace.Texture.from(spriteSource));
1634
+ } else {
1635
+ error = wrongFormatError;
1636
+ console.log(error);
1637
+ }
1638
+ } catch (e) {
1639
+ error = e;
1640
+ console.log(error);
1641
+ }
1642
+ if (isSpriteSource(spriteSource) && spriteSource.baseTexture === null || sprite !== undefined && (sprite.destroyed || sprite.texture?.baseTexture === null)) {
1643
+ error = destroyedError;
1644
+ console.log(error);
1645
+ }
1646
+ if (error) {
1647
+ throw error;
1648
+ }
1649
+ const texture = sprite.texture;
1650
+ const onTextureUpdate = baseTexture => {
1651
+ this.onImageTextureUpdate(baseTexture);
1652
+ baseTexture.removeListener("update", onTextureUpdate);
1653
+ };
1654
+ texture.baseTexture.addListener("update", onTextureUpdate);
1655
+ this.spriteTemplates[key] = sprite;
1656
+ const existingStyle = this.getStyleForTag(key) ?? {};
1657
+ const style = {
1658
+ [IMG_REFERENCE_PROPERTY]: key,
1659
+ ...existingStyle
1660
+ };
1661
+ this.setStyleForTag(key, style);
1662
+ });
1663
+ }
1664
+ onImageTextureUpdate(_baseTexture) {
1665
+ this._needsUpdate = true;
1666
+ this._needsDraw = true;
1667
+ this.updateIfShould();
1668
+ }
1669
+ updateIfShould(forcedSkipUpdate) {
1670
+ if (forcedSkipUpdate === false || forcedSkipUpdate === undefined && this.options.skipUpdates === false) {
1671
+ this.update();
1672
+ return true;
1673
+ }
1674
+ return false;
1675
+ }
1676
+ update(skipDraw) {
1677
+ const tagStyles = this.tagStyles;
1678
+ const {
1679
+ splitStyle,
1680
+ scaleIcons
1681
+ } = this.options;
1682
+ const spriteTemplates = this.options.imgMap && this.spriteTemplates;
1683
+ const tagTokensNew = parseTagsNew(this.text, Object.keys(this.tagStyles), this.options.wrapEmoji, this.logWarning);
1684
+ const styledTokens = mapTagsToStyles(tagTokensNew, tagStyles, spriteTemplates);
1685
+ const newFinalTokens = calculateTokens(styledTokens, splitStyle, scaleIcons, this.options.adjustFontBaseline);
1686
+ this._tokens = newFinalTokens;
1687
+ this._needsDraw = true;
1688
+ this.drawIfShould(skipDraw);
1689
+ if (this.options.debugConsole) {
1690
+ console.log(this.toDebugString());
1691
+ }
1692
+ this._needsUpdate = false;
1693
+ return newFinalTokens;
1694
+ }
1695
+ drawIfShould(forcedSkipDraw) {
1696
+ if (forcedSkipDraw === false || forcedSkipDraw === undefined && this.options.skipDraw === false) {
1697
+ this.draw();
1698
+ return true;
1699
+ }
1700
+ return false;
1701
+ }
1702
+ draw() {
1703
+ this.resetChildren();
1704
+ if (this.textContainer === null || this.spriteContainer === null) {
1705
+ throw new Error("Somehow the textContainer or spriteContainer is null. This shouldn't be possible. Perhaps you've destroyed this object?");
1706
+ }
1707
+ const textContainer = this.textContainer;
1708
+ const spriteContainer = this.spriteContainer;
1709
+ const {
1710
+ drawWhitespace
1711
+ } = this.options;
1712
+ const tokensFlat = this.tokensFlat;
1713
+ const tokens = drawWhitespace ? tokensFlat : tokensFlat.filter(isNotWhitespaceToken);
1714
+ let drewDecorations = false;
1715
+ let displayObject;
1716
+ tokens.forEach((t, index) => {
1717
+ if (isTextToken(t)) {
1718
+ displayObject = this.createTextFieldForToken(t);
1719
+ textContainer.addChild(displayObject);
1720
+ this.textFields.push(displayObject);
1721
+ if (t.textDecorations && t.textDecorations.length > 0) {
1722
+ for (const d of t.textDecorations) {
1723
+ const drawing = this.createDrawingForTextDecoration(d);
1724
+ displayObject.addChild(drawing);
1725
+ this._decorations.push(drawing);
1726
+ }
1727
+ drewDecorations = true;
1728
+ }
1729
+ }
1730
+ if (isSpriteToken(t)) {
1731
+ displayObject = t.content;
1732
+ this.sprites.push(displayObject);
1733
+ spriteContainer.addChild(displayObject);
1734
+ }
1735
+ const {
1736
+ bounds
1737
+ } = t;
1738
+ displayObject.x = bounds.x;
1739
+ displayObject.y = bounds.y;
1740
+ if (isSpriteToken(t)) {
1741
+ const imgDisplay = t.style['imgDisplay'];
1742
+ if (imgDisplay === 'icon') {
1743
+ let fontSize = t.style.fontSize || 20;
1744
+ if (typeof fontSize === 'string') {
1745
+ fontSize = parseInt(fontSize.replace('px', ''), 10);
1746
+ }
1747
+ const iconOffset = fontSize * 0.1;
1748
+ displayObject.y = bounds.y + iconOffset;
1749
+ }
1750
+ }
1751
+ });
1752
+ if (drawWhitespace === false && drewDecorations) {
1753
+ this.logWarning("text-decoration-and-whitespace", "Text decorations, such as underlines, will not appear under whitespace unless the `drawWhitespace` option is set to `true`.");
1754
+ }
1755
+ if (this.options.debug) {
1756
+ this.drawDebug();
1757
+ }
1758
+ this._needsDraw = false;
1759
+ }
1760
+ createDrawingForTextDecoration(textDecoration) {
1761
+ const {
1762
+ overdrawDecorations: overdraw = 0
1763
+ } = this.options;
1764
+ const {
1765
+ bounds
1766
+ } = textDecoration;
1767
+ let {
1768
+ color
1769
+ } = textDecoration;
1770
+ if (!bounds || bounds.width <= 0 && bounds.height <= 0) {
1771
+ return new PIXI__namespace.Graphics();
1772
+ }
1773
+ const drawing = new PIXI__namespace.Graphics();
1774
+ if (typeof color === "string") {
1775
+ if (color.indexOf("#") === 0) {
1776
+ color = "0x" + color.substring(1);
1777
+ color = parseInt(color, 16);
1778
+ } else {
1779
+ this.logWarning("invalid-color", "Sorry, at this point, only hex colors are supported for textDecorations like underlines. Please use either a hex number like 0x66FF33 or a string like '#66FF33'");
1780
+ color = 0x000000;
1781
+ }
1782
+ }
1783
+ if (color === undefined || color === null) {
1784
+ color = 0x000000;
1785
+ }
1786
+ const finalColor = typeof color === 'number' ? color : 0x000000;
1787
+ const {
1788
+ y,
1789
+ height
1790
+ } = bounds;
1791
+ const midpoint = bounds.x + bounds.width / 2;
1792
+ const x = Math.min(bounds.x - overdraw, midpoint);
1793
+ const width = Math.max(bounds.width + overdraw * 2, 0);
1794
+ drawing.setFillStyle({
1795
+ color: finalColor
1796
+ });
1797
+ drawing.rect(x, y, width, height);
1798
+ drawing.fill();
1799
+ return drawing;
1800
+ }
1801
+ createTextField(text, style) {
1802
+ const cleanedStyle = {
1803
+ ...style
1804
+ };
1805
+ if (cleanedStyle.stroke && typeof cleanedStyle.stroke === 'string') {
1806
+ cleanedStyle.stroke = {
1807
+ color: cleanedStyle.stroke,
1808
+ width: cleanedStyle.strokeThickness || 0
1809
+ };
1810
+ }
1811
+ const textField = new PIXI__namespace.Text({
1812
+ text: text,
1813
+ style: cleanedStyle
1814
+ });
1815
+ return textField;
1816
+ }
1817
+ createTextFieldForToken(token) {
1818
+ const {
1819
+ textTransform = ""
1820
+ } = token.style;
1821
+ let text = token.content;
1822
+ switch (textTransform.toLowerCase()) {
1823
+ case "lowercase":
1824
+ text = text.toLowerCase();
1825
+ break;
1826
+ case "uppercase":
1827
+ text = text.toUpperCase();
1828
+ break;
1829
+ case "capitalize":
1830
+ text = capitalize(text);
1831
+ break;
1832
+ }
1833
+ const alignClassic = convertUnsupportedAlignment(token.style.align);
1834
+ const sanitizedStyle = {
1835
+ ...token.style,
1836
+ align: alignClassic
1837
+ };
1838
+ const textField = this.createTextField(text, sanitizedStyle);
1839
+ let {
1840
+ fontScaleWidth = 1.0,
1841
+ fontScaleHeight = 1.0
1842
+ } = token.style;
1843
+ fontScaleWidth = isNaN(fontScaleWidth) || fontScaleWidth < 0 ? 0 : fontScaleWidth;
1844
+ fontScaleHeight = isNaN(fontScaleHeight) || fontScaleHeight < 0 ? 0 : fontScaleHeight;
1845
+ let finalScaleWidth = fontScaleWidth;
1846
+ let finalScaleHeight = fontScaleHeight;
1847
+ const largerScale = Math.max(fontScaleWidth, fontScaleHeight);
1848
+ if (largerScale > 1) {
1849
+ if (largerScale === fontScaleHeight) {
1850
+ finalScaleWidth /= largerScale;
1851
+ finalScaleHeight = 1.0;
1852
+ } else {
1853
+ finalScaleHeight /= largerScale;
1854
+ finalScaleWidth = 1.0;
1855
+ }
1856
+ const fs = textField.style.fontSize ?? 0;
1857
+ const fontSizePx = (typeof fs === "string" ? fontSizeStringToNumber(fs) : fs) * largerScale;
1858
+ textField.style.fontSize = fontSizePx;
1859
+ }
1860
+ textField.scale.set(finalScaleWidth, finalScaleHeight);
1861
+ return textField;
1862
+ }
1863
+ toDebugString() {
1864
+ const lines = this.tokens;
1865
+ let s = this.untaggedText + "\n=====\n";
1866
+ const nl = "\n ";
1867
+ if (lines !== undefined) {
1868
+ s += lines.map((line, lineNumber) => line.map((word, wordNumber) => word.map((token, tokenNumber) => {
1869
+ let text = "";
1870
+ if (isTextToken(token)) {
1871
+ if (isNewlineToken(token)) {
1872
+ text = `\\n`;
1873
+ } else {
1874
+ text = `"${token.content}"`;
1875
+ }
1876
+ } else if (isSpriteToken(token)) {
1877
+ text = `[Image]`;
1878
+ }
1879
+ let s = `\n${text}: (${lineNumber}/${wordNumber}/${tokenNumber})`;
1880
+ s += `${nl}tags: ${token.tags.length === 0 ? "<none>" : token.tags.split(",").map(tag => `<${tag}>`).join(", ")}`;
1881
+ s += `${nl}style: ${Object.entries(token.style).map(e => e.join(":")).join("; ")}`;
1882
+ s += `${nl}size: x:${token.bounds.x} y:${token.bounds.y} width:${token.bounds.width} height:${token.bounds.height} bottom:${token.bounds.height + token.bounds.y} right:${token.bounds.x + token.bounds.width}`;
1883
+ s += `${nl}font: fontSize:${token.fontProperties.fontSize} ascent:${token.fontProperties.ascent} descent:${token.fontProperties.descent}`;
1884
+ return s;
1885
+ }).join("\n")));
1886
+ }
1887
+ return s;
1888
+ }
1889
+ drawDebug() {
1890
+ const paragraph = this.tokens;
1891
+ this._debugGraphics = new PIXI__namespace.Graphics();
1892
+ if (this.debugContainer === null) {
1893
+ throw new Error("Somehow the debug container is null. This shouldn't be possible. Perhaps you've destroyed this object?");
1894
+ }
1895
+ const debugContainer = this.debugContainer;
1896
+ debugContainer.removeChildren();
1897
+ debugContainer.addChild(this._debugGraphics);
1898
+ const g = this._debugGraphics;
1899
+ g.clear();
1900
+ let lineHeightGraphics = new PIXI__namespace.Graphics();
1901
+ lineHeightGraphics.name = 'lineHeightGraphics';
1902
+ debugContainer.addChild(lineHeightGraphics);
1903
+ lineHeightGraphics.clear();
1904
+ let baselineGraphics = new PIXI__namespace.Graphics();
1905
+ baselineGraphics.name = 'baselineGraphics';
1906
+ baselineGraphics.visible = true;
1907
+ baselineGraphics.alpha = 1;
1908
+ debugContainer.addChild(baselineGraphics);
1909
+ baselineGraphics.clear();
1910
+ const baselines = [];
1911
+ function createInfoText(text, position) {
1912
+ const info = new PIXI__namespace.Text({
1913
+ text,
1914
+ style: DEBUG.TEXT_STYLE
1915
+ });
1916
+ info.x = position.x + 1;
1917
+ info.y = position.y + 1;
1918
+ return info;
1919
+ }
1920
+ for (let lineNumber = 0; lineNumber < paragraph.length; lineNumber++) {
1921
+ const line = paragraph[lineNumber];
1922
+ const lineBounds = getBoundsNested(line);
1923
+ let lineBoxY = lineBounds.y + 2;
1924
+ let lineBoxHeight = lineBounds.height;
1925
+ if (this.defaultStyle.wordWrap) {
1926
+ const w = this.defaultStyle.wordWrapWidth ?? this.width;
1927
+ g.lineStyle(0.5, DEBUG.LINE_COLOR, 0.2);
1928
+ g.drawRect(0, lineBoxY, w, lineBoxHeight);
1929
+ }
1930
+ for (let wordNumber = 0; wordNumber < line.length; wordNumber++) {
1931
+ const word = line[wordNumber];
1932
+ for (const segmentToken of word) {
1933
+ const isSprite = isSpriteToken(segmentToken);
1934
+ const {
1935
+ x,
1936
+ y,
1937
+ width
1938
+ } = segmentToken.bounds;
1939
+ let adjustedY = y;
1940
+ const fontSize = segmentToken.fontProperties?.fontSize || 24;
1941
+ let adjustment = 0;
1942
+ if (fontSize <= 24) {
1943
+ adjustment = -2;
1944
+ } else if (fontSize <= 28) {
1945
+ adjustment = -3;
1946
+ } else if (fontSize === 36) {
1947
+ adjustment = 5;
1948
+ } else if (fontSize > 36 && fontSize <= 47) {
1949
+ adjustment = 5 + (fontSize - 36) * 0.2;
1950
+ } else if (fontSize > 47) {
1951
+ adjustment = 7 + (fontSize - 47) * 0.1;
1952
+ }
1953
+ adjustedY -= adjustment;
1954
+ let baseline;
1955
+ if (isSprite) {
1956
+ baseline = adjustedY + segmentToken.bounds.height;
1957
+ } else {
1958
+ baseline = adjustedY + segmentToken.fontProperties.ascent;
1959
+ const hasStroke = segmentToken.style?.stroke && segmentToken.style.strokeThickness > 0;
1960
+ if (fontSize === 36) {
1961
+ baseline += 15;
1962
+ } else if (hasStroke && fontSize <= 28) {
1963
+ baseline += 6;
1964
+ } else if (fontSize <= 24) {
1965
+ baseline += 4;
1966
+ } else {
1967
+ baseline += 4;
1968
+ }
1969
+ }
1970
+ let boxY = adjustedY;
1971
+ let boxHeight = segmentToken.bounds.height;
1972
+ if (!isSprite) {
1973
+ const ascent = segmentToken.fontProperties.ascent;
1974
+ const descent = segmentToken.fontProperties.descent;
1975
+ boxY = baseline - ascent;
1976
+ boxHeight = ascent + descent;
1977
+ } else {
1978
+ boxHeight += segmentToken.fontProperties.descent;
1979
+ }
1980
+ const strokeColor = isWhitespaceToken(segmentToken) && this.options.drawWhitespace === false ? DEBUG.WHITESPACE_STROKE_COLOR : DEBUG.WORD_STROKE_COLOR;
1981
+ const fillColor = isWhitespaceToken(segmentToken) && this.options.drawWhitespace === false ? DEBUG.WHITESPACE_COLOR : DEBUG.WORD_FILL_COLOR;
1982
+ if (isNewlineToken(segmentToken)) {
1983
+ this.debugContainer.addChild(createInfoText("↩︎", {
1984
+ x,
1985
+ y: boxY + 10
1986
+ }));
1987
+ } else {
1988
+ g.rect(x, boxY, width, boxHeight).stroke({
1989
+ width: 0.5,
1990
+ color: DEBUG.LINE_COLOR,
1991
+ alpha: 0.2
1992
+ });
1993
+ g.rect(x, y, width, segmentToken.bounds.height).fill({
1994
+ color: fillColor,
1995
+ alpha: 0.2
1996
+ }).stroke({
1997
+ width: 0.5,
1998
+ color: strokeColor,
1999
+ alpha: 0.5
2000
+ });
2001
+ baselines.push({
2002
+ x,
2003
+ baseline,
2004
+ width
2005
+ });
2006
+ }
2007
+ let info;
2008
+ if (isTextToken(segmentToken)) {
2009
+ info = `${segmentToken.tags}`;
2010
+ this.debugContainer.addChild(createInfoText(info, {
2011
+ x,
2012
+ y: boxY
2013
+ }));
2014
+ }
2015
+ }
2016
+ }
2017
+ }
2018
+ if (baselines.length > 0) {
2019
+ baselineGraphics.beginFill(DEBUG.BASELINE_COLOR, 0.8);
2020
+ for (const {
2021
+ x,
2022
+ baseline,
2023
+ width
2024
+ } of baselines) {
2025
+ baselineGraphics.drawRect(x, baseline - 1, width, 2);
2026
+ }
2027
+ baselineGraphics.endFill();
2028
+ }
2029
+ }
2030
+ }
2031
+
2032
+ exports.Glyphs = Glyphs;
2033
+ exports["default"] = Glyphs;
2034
+ //# sourceMappingURL=pixi-glyphs.js.map