matrix-react-sdk
Version:
SDK for matrix.org using React
126 lines (122 loc) • 19.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fixupColorFonts = fixupColorFonts;
var _logger = require("matrix-js-sdk/src/logger");
/*
Copyright 2024 New Vector Ltd.
Copyright 2019-2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
/*
* Based on...
* ChromaCheck 1.16
* author Roel Nieskens, https://pixelambacht.nl
* MIT license
*/
function safariVersionCheck(ua) {
_logger.logger.log("Browser is Safari - checking version for COLR support");
try {
const safariVersionMatch = ua.match(/Mac OS X ([\d|_]+).*Version\/([\d|.]+).*Safari/);
if (safariVersionMatch) {
const macOSVersionStr = safariVersionMatch[1];
const safariVersionStr = safariVersionMatch[2];
const macOSVersion = macOSVersionStr.split("_").map(n => parseInt(n, 10));
const safariVersion = safariVersionStr.split(".").map(n => parseInt(n, 10));
const colrFontSupported = macOSVersion[0] >= 10 && macOSVersion[1] >= 14 && safariVersion[0] >= 12 && safariVersion[0] < 17;
// https://www.colorfonts.wtf/ states Safari supports COLR fonts from this version on but Safari 17 breaks it
_logger.logger.log(`COLR support on Safari requires macOS 10.14 and Safari 12-16, ` + `detected Safari ${safariVersionStr} on macOS ${macOSVersionStr}, ` + `COLR supported: ${colrFontSupported}`);
return colrFontSupported;
}
} catch (err) {
_logger.logger.error("Error in Safari COLR version check", err);
}
_logger.logger.warn("Couldn't determine Safari version to check COLR font support, assuming no.");
return false;
}
async function isColrFontSupported() {
_logger.logger.log("Checking for COLR support");
const {
userAgent
} = navigator;
// Firefox has supported COLR fonts since version 26
// but doesn't support the check below without
// "Extract canvas data" permissions
// when content blocking is enabled.
if (userAgent.includes("Firefox")) {
_logger.logger.log("Browser is Firefox - assuming COLR is supported");
return true;
}
// Safari doesn't wait for the font to load (if it doesn't have it in cache)
// to emit the load event on the image, so there is no way to not make the check
// reliable. Instead sniff the version.
// Excluding "Chrome", as it's user agent unhelpfully also contains Safari...
if (!userAgent.includes("Chrome") && userAgent.includes("Safari")) {
return safariVersionCheck(userAgent);
}
try {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const img = new Image();
// eslint-disable-next-line
const fontCOLR = "d09GRgABAAAAAAKAAAwAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDT0xSAAACVAAAABYAAAAYAAIAJUNQQUwAAAJsAAAAEgAAABLJAAAQT1MvMgAAAYAAAAA6AAAAYBfxJ0pjbWFwAAABxAAAACcAAAAsAAzpM2dseWYAAAH0AAAAGgAAABoNIh0kaGVhZAAAARwAAAAvAAAANgxLumdoaGVhAAABTAAAABUAAAAkCAEEAmhtdHgAAAG8AAAABgAAAAYEAAAAbG9jYQAAAewAAAAGAAAABgANAABtYXhwAAABZAAAABsAAAAgAg4AHW5hbWUAAAIQAAAAOAAAAD4C5wsecG9zdAAAAkgAAAAMAAAAIAADAAB4AWNgZGAAYQ5+qdB4fpuvDNIsDCBwaQGTAIi+VlscBaJZGMDiHAxMIAoAtjIF/QB4AWNgZGBgYQACOAkUQQWMAAGRABAAAAB4AWNgZGBgYGJgAdMMUJILJMQgAWICAAH3AC4AeAFjYGFhYJzAwMrAwDST6QwDA0M/hGZ8zWDMyMmAChgFkDgKQMBw4CXDSwYWEBdIYgAFBgYA/8sIdAAABAAAAAAAAAB4AWNgYGBkYAZiBgYeBhYGBSDNAoRA/kuG//8hpDgjWJ4BAFVMBiYAAAAAAAANAAAAAQAAAAAEAAQAAAMAABEhESEEAPwABAD8AAAAeAEtxgUNgAAAAMHHIQTShTlOAty9/4bf7AARCwlBNhBw4L/43qXjYGUmf19TMuLcj/BJL3XfBg54AWNgZsALAAB9AAR4AWNgYGAEYj4gFgGygGwICQACOwAoAAAAAAABAAEAAQAAAA4AAAAAyP8AAA==";
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="100" style="background:#fff;fill:#000;">
<style type="text/css">
@font-face {
font-family: "chromacheck-colr";
src: url(data:application/x-font-woff;base64,${fontCOLR}) format("woff");
}
</style>
<text x="0" y="0" font-size="20">
<tspan font-family="chromacheck-colr" x="0" dy="20"></tspan>
</text>
</svg>`;
canvas.width = 20;
canvas.height = 100;
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
_logger.logger.log("Waiting for COLR SVG to load");
await new Promise(resolve => img.onload = resolve);
_logger.logger.log("Drawing canvas to detect COLR support");
context.drawImage(img, 0, 0);
const colrFontSupported = context.getImageData(10, 10, 1, 1).data[0] === 200;
_logger.logger.log("Canvas check revealed COLR is supported? " + colrFontSupported);
return colrFontSupported;
} catch (e) {
_logger.logger.error("Couldn't load COLR font", e);
return false;
}
}
let colrFontCheckStarted = false;
async function fixupColorFonts() {
if (colrFontCheckStarted) {
return;
}
colrFontCheckStarted = true;
if (await isColrFontSupported()) {
const path = `url('${require("../../res/fonts/Twemoji_Mozilla/TwemojiMozilla-colr.woff2")}')`;
document.fonts.add(new FontFace("Twemoji", path, {}));
// For at least Chrome on Windows 10, we have to explictly add extra
// weights for the emoji to appear in bold messages, etc.
document.fonts.add(new FontFace("Twemoji", path, {
weight: "600"
}));
document.fonts.add(new FontFace("Twemoji", path, {
weight: "700"
}));
} else {
// fall back to SBIX, generated via https://github.com/matrix-org/twemoji-colr/tree/matthew/sbix
const path = `url('${require("../../res/fonts/Twemoji_Mozilla/TwemojiMozilla-sbix.woff2")}')`;
document.fonts.add(new FontFace("Twemoji", path, {}));
document.fonts.add(new FontFace("Twemoji", path, {
weight: "600"
}));
document.fonts.add(new FontFace("Twemoji", path, {
weight: "700"
}));
}
// ...and if SBIX is not supported, the browser will fall back to one of the native fonts specified.
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwicmVxdWlyZSIsInNhZmFyaVZlcnNpb25DaGVjayIsInVhIiwibG9nZ2VyIiwibG9nIiwic2FmYXJpVmVyc2lvbk1hdGNoIiwibWF0Y2giLCJtYWNPU1ZlcnNpb25TdHIiLCJzYWZhcmlWZXJzaW9uU3RyIiwibWFjT1NWZXJzaW9uIiwic3BsaXQiLCJtYXAiLCJuIiwicGFyc2VJbnQiLCJzYWZhcmlWZXJzaW9uIiwiY29sckZvbnRTdXBwb3J0ZWQiLCJlcnIiLCJlcnJvciIsIndhcm4iLCJpc0NvbHJGb250U3VwcG9ydGVkIiwidXNlckFnZW50IiwibmF2aWdhdG9yIiwiaW5jbHVkZXMiLCJjYW52YXMiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJjb250ZXh0IiwiZ2V0Q29udGV4dCIsImltZyIsIkltYWdlIiwiZm9udENPTFIiLCJzdmciLCJ3aWR0aCIsImhlaWdodCIsInNyYyIsImVuY29kZVVSSUNvbXBvbmVudCIsIlByb21pc2UiLCJyZXNvbHZlIiwib25sb2FkIiwiZHJhd0ltYWdlIiwiZ2V0SW1hZ2VEYXRhIiwiZGF0YSIsImUiLCJjb2xyRm9udENoZWNrU3RhcnRlZCIsImZpeHVwQ29sb3JGb250cyIsInBhdGgiLCJmb250cyIsImFkZCIsIkZvbnRGYWNlIiwid2VpZ2h0Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL0ZvbnRNYW5hZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5LTIwMjEgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuLypcbiAqIEJhc2VkIG9uLi4uXG4gKiBDaHJvbWFDaGVjayAxLjE2XG4gKiBhdXRob3IgUm9lbCBOaWVza2VucywgaHR0cHM6Ly9waXhlbGFtYmFjaHQubmxcbiAqIE1JVCBsaWNlbnNlXG4gKi9cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuZnVuY3Rpb24gc2FmYXJpVmVyc2lvbkNoZWNrKHVhOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBsb2dnZXIubG9nKFwiQnJvd3NlciBpcyBTYWZhcmkgLSBjaGVja2luZyB2ZXJzaW9uIGZvciBDT0xSIHN1cHBvcnRcIik7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgc2FmYXJpVmVyc2lvbk1hdGNoID0gdWEubWF0Y2goL01hYyBPUyBYIChbXFxkfF9dKykuKlZlcnNpb25cXC8oW1xcZHwuXSspLipTYWZhcmkvKTtcbiAgICAgICAgaWYgKHNhZmFyaVZlcnNpb25NYXRjaCkge1xuICAgICAgICAgICAgY29uc3QgbWFjT1NWZXJzaW9uU3RyID0gc2FmYXJpVmVyc2lvbk1hdGNoWzFdO1xuICAgICAgICAgICAgY29uc3Qgc2FmYXJpVmVyc2lvblN0ciA9IHNhZmFyaVZlcnNpb25NYXRjaFsyXTtcbiAgICAgICAgICAgIGNvbnN0IG1hY09TVmVyc2lvbiA9IG1hY09TVmVyc2lvblN0ci5zcGxpdChcIl9cIikubWFwKChuKSA9PiBwYXJzZUludChuLCAxMCkpO1xuICAgICAgICAgICAgY29uc3Qgc2FmYXJpVmVyc2lvbiA9IHNhZmFyaVZlcnNpb25TdHIuc3BsaXQoXCIuXCIpLm1hcCgobikgPT4gcGFyc2VJbnQobiwgMTApKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbHJGb250U3VwcG9ydGVkID1cbiAgICAgICAgICAgICAgICBtYWNPU1ZlcnNpb25bMF0gPj0gMTAgJiYgbWFjT1NWZXJzaW9uWzFdID49IDE0ICYmIHNhZmFyaVZlcnNpb25bMF0gPj0gMTIgJiYgc2FmYXJpVmVyc2lvblswXSA8IDE3O1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cuY29sb3Jmb250cy53dGYvIHN0YXRlcyBTYWZhcmkgc3VwcG9ydHMgQ09MUiBmb250cyBmcm9tIHRoaXMgdmVyc2lvbiBvbiBidXQgU2FmYXJpIDE3IGJyZWFrcyBpdFxuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICAgICAgICBgQ09MUiBzdXBwb3J0IG9uIFNhZmFyaSByZXF1aXJlcyBtYWNPUyAxMC4xNCBhbmQgU2FmYXJpIDEyLTE2LCBgICtcbiAgICAgICAgICAgICAgICAgICAgYGRldGVjdGVkIFNhZmFyaSAke3NhZmFyaVZlcnNpb25TdHJ9IG9uIG1hY09TICR7bWFjT1NWZXJzaW9uU3RyfSwgYCArXG4gICAgICAgICAgICAgICAgICAgIGBDT0xSIHN1cHBvcnRlZDogJHtjb2xyRm9udFN1cHBvcnRlZH1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBjb2xyRm9udFN1cHBvcnRlZDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBpbiBTYWZhcmkgQ09MUiB2ZXJzaW9uIGNoZWNrXCIsIGVycik7XG4gICAgfVxuICAgIGxvZ2dlci53YXJuKFwiQ291bGRuJ3QgZGV0ZXJtaW5lIFNhZmFyaSB2ZXJzaW9uIHRvIGNoZWNrIENPTFIgZm9udCBzdXBwb3J0LCBhc3N1bWluZyBuby5cIik7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpc0NvbHJGb250U3VwcG9ydGVkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGxvZ2dlci5sb2coXCJDaGVja2luZyBmb3IgQ09MUiBzdXBwb3J0XCIpO1xuXG4gICAgY29uc3QgeyB1c2VyQWdlbnQgfSA9IG5hdmlnYXRvcjtcbiAgICAvLyBGaXJlZm94IGhhcyBzdXBwb3J0ZWQgQ09MUiBmb250cyBzaW5jZSB2ZXJzaW9uIDI2XG4gICAgLy8gYnV0IGRvZXNuJ3Qgc3VwcG9ydCB0aGUgY2hlY2sgYmVsb3cgd2l0aG91dFxuICAgIC8vIFwiRXh0cmFjdCBjYW52YXMgZGF0YVwiIHBlcm1pc3Npb25zXG4gICAgLy8gd2hlbiBjb250ZW50IGJsb2NraW5nIGlzIGVuYWJsZWQuXG4gICAgaWYgKHVzZXJBZ2VudC5pbmNsdWRlcyhcIkZpcmVmb3hcIikpIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIkJyb3dzZXIgaXMgRmlyZWZveCAtIGFzc3VtaW5nIENPTFIgaXMgc3VwcG9ydGVkXCIpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgLy8gU2FmYXJpIGRvZXNuJ3Qgd2FpdCBmb3IgdGhlIGZvbnQgdG8gbG9hZCAoaWYgaXQgZG9lc24ndCBoYXZlIGl0IGluIGNhY2hlKVxuICAgIC8vIHRvIGVtaXQgdGhlIGxvYWQgZXZlbnQgb24gdGhlIGltYWdlLCBzbyB0aGVyZSBpcyBubyB3YXkgdG8gbm90IG1ha2UgdGhlIGNoZWNrXG4gICAgLy8gcmVsaWFibGUuIEluc3RlYWQgc25pZmYgdGhlIHZlcnNpb24uXG4gICAgLy8gRXhjbHVkaW5nIFwiQ2hyb21lXCIsIGFzIGl0J3MgdXNlciBhZ2VudCB1bmhlbHBmdWxseSBhbHNvIGNvbnRhaW5zIFNhZmFyaS4uLlxuICAgIGlmICghdXNlckFnZW50LmluY2x1ZGVzKFwiQ2hyb21lXCIpICYmIHVzZXJBZ2VudC5pbmNsdWRlcyhcIlNhZmFyaVwiKSkge1xuICAgICAgICByZXR1cm4gc2FmYXJpVmVyc2lvbkNoZWNrKHVzZXJBZ2VudCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIikhO1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgIGNvbnN0IGZvbnRDT0xSID1cbiAgICAgICAgICAgIFwiZDA5R1JnQUJBQUFBQUFLQUFBd0FBQUFBQW93QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJEVDB4U0FBQUNWQUFBQUJZQUFBQVlBQUlBSlVOUVFVd0FBQUpzQUFBQUVnQUFBQkxKQUFBUVQxTXZNZ0FBQVlBQUFBQTZBQUFBWUJmeEowcGpiV0Z3QUFBQnhBQUFBQ2NBQUFBc0FBenBNMmRzZVdZQUFBSDBBQUFBR2dBQUFCb05JaDBrYUdWaFpBQUFBUndBQUFBdkFBQUFOZ3hMdW1kb2FHVmhBQUFCVEFBQUFCVUFBQUFrQ0FFRUFtaHRkSGdBQUFHOEFBQUFCZ0FBQUFZRUFBQUFiRzlqWVFBQUFld0FBQUFHQUFBQUJnQU5BQUJ0WVhod0FBQUJaQUFBQUJzQUFBQWdBZzRBSFc1aGJXVUFBQUlRQUFBQU9BQUFBRDRDNXdzZWNHOXpkQUFBQWtnQUFBQU1BQUFBSUFBREFBQjRBV05nWkdBQVlRNStxZEI0ZnB1dkROSXNEQ0J3YVFHVEFJaStWbHNjQmFKWkdNRGlIQXhNSUFvQXRqSUYvUUI0QVdOZ1pHQmdZUUFDT0FrVVFRV01BQUdSQUJBQUFBQjRBV05nWkdCZ1lHSmdBZE1NVUpJTEpNUWdBV0lDQUFIM0FDNEFlQUZqWUdGaFlKekF3TXJBd0RTVDZRd0RBME0vaEdaOHpXRE15TW1BQ2hnRmtEZ0tRTUJ3NENYRFN3WVdFQmRJWWdBRkJnWUEvOHNJZEFBQUJBQUFBQUFBQUFCNEFXTmdZR0JrWUFaaUJnWWVCaFlHQlNETkFvUkEva3VHLy84aHBEZ2pXSjRCQUZWTUJpWUFBQUFBQUFBTkFBQUFBUUFBQUFBRUFBUUFBQU1BQUJFaEVTRUVBUHdBQkFEOEFBQUFlQUV0eGdVTmdBQUFBTUhISVFUU2hUbE9BdHk5LzRiZjdBQVJDd2xCTmhCdzRMLzQzcVhqWUdVbWYxOVRNdUxjai9CSkwzWGZCZzU0QVdOZ1pzQUxBQUI5QUFSNEFXTmdZR0FFWWo0Z0ZnR3lnR3dJQ1FBQ093QW9BQUFBQUFBQkFBRUFBUUFBQUE0QUFBQUF5UDhBQUE9PVwiO1xuICAgICAgICBjb25zdCBzdmcgPSBgXG4gICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIxMDBcIiBzdHlsZT1cImJhY2tncm91bmQ6I2ZmZjtmaWxsOiMwMDA7XCI+XG4gICAgICAgICAgICA8c3R5bGUgdHlwZT1cInRleHQvY3NzXCI+XG4gICAgICAgICAgICAgICAgQGZvbnQtZmFjZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvbnQtZmFtaWx5OiBcImNocm9tYWNoZWNrLWNvbHJcIjtcbiAgICAgICAgICAgICAgICAgICAgc3JjOiB1cmwoZGF0YTphcHBsaWNhdGlvbi94LWZvbnQtd29mZjtiYXNlNjQsJHtmb250Q09MUn0pIGZvcm1hdChcIndvZmZcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9zdHlsZT5cbiAgICAgICAgICAgIDx0ZXh0IHg9XCIwXCIgeT1cIjBcIiBmb250LXNpemU9XCIyMFwiPlxuICAgICAgICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT1cImNocm9tYWNoZWNrLWNvbHJcIiB4PVwiMFwiIGR5PVwiMjBcIj4mI3hlOTAwOzwvdHNwYW4+XG4gICAgICAgICAgICA8L3RleHQ+XG4gICAgICAgIDwvc3ZnPmA7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IDIwO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gMTAwO1xuXG4gICAgICAgIGltZy5zcmMgPSBcImRhdGE6aW1hZ2Uvc3ZnK3htbDtjaGFyc2V0PXV0Zi04LFwiICsgZW5jb2RlVVJJQ29tcG9uZW50KHN2Zyk7XG5cbiAgICAgICAgbG9nZ2VyLmxvZyhcIldhaXRpbmcgZm9yIENPTFIgU1ZHIHRvIGxvYWRcIik7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiAoaW1nLm9ubG9hZCA9IHJlc29sdmUpKTtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIkRyYXdpbmcgY2FudmFzIHRvIGRldGVjdCBDT0xSIHN1cHBvcnRcIik7XG4gICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGltZywgMCwgMCk7XG4gICAgICAgIGNvbnN0IGNvbHJGb250U3VwcG9ydGVkID0gY29udGV4dC5nZXRJbWFnZURhdGEoMTAsIDEwLCAxLCAxKS5kYXRhWzBdID09PSAyMDA7XG4gICAgICAgIGxvZ2dlci5sb2coXCJDYW52YXMgY2hlY2sgcmV2ZWFsZWQgQ09MUiBpcyBzdXBwb3J0ZWQ/IFwiICsgY29sckZvbnRTdXBwb3J0ZWQpO1xuICAgICAgICByZXR1cm4gY29sckZvbnRTdXBwb3J0ZWQ7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJDb3VsZG4ndCBsb2FkIENPTFIgZm9udFwiLCBlKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxubGV0IGNvbHJGb250Q2hlY2tTdGFydGVkID0gZmFsc2U7XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZml4dXBDb2xvckZvbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChjb2xyRm9udENoZWNrU3RhcnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbHJGb250Q2hlY2tTdGFydGVkID0gdHJ1ZTtcblxuICAgIGlmIChhd2FpdCBpc0NvbHJGb250U3VwcG9ydGVkKCkpIHtcbiAgICAgICAgY29uc3QgcGF0aCA9IGB1cmwoJyR7cmVxdWlyZShcIi4uLy4uL3Jlcy9mb250cy9Ud2Vtb2ppX01vemlsbGEvVHdlbW9qaU1vemlsbGEtY29sci53b2ZmMlwiKX0nKWA7XG4gICAgICAgIGRvY3VtZW50LmZvbnRzLmFkZChuZXcgRm9udEZhY2UoXCJUd2Vtb2ppXCIsIHBhdGgsIHt9KSk7XG4gICAgICAgIC8vIEZvciBhdCBsZWFzdCBDaHJvbWUgb24gV2luZG93cyAxMCwgd2UgaGF2ZSB0byBleHBsaWN0bHkgYWRkIGV4dHJhXG4gICAgICAgIC8vIHdlaWdodHMgZm9yIHRoZSBlbW9qaSB0byBhcHBlYXIgaW4gYm9sZCBtZXNzYWdlcywgZXRjLlxuICAgICAgICBkb2N1bWVudC5mb250cy5hZGQobmV3IEZvbnRGYWNlKFwiVHdlbW9qaVwiLCBwYXRoLCB7IHdlaWdodDogXCI2MDBcIiB9KSk7XG4gICAgICAgIGRvY3VtZW50LmZvbnRzLmFkZChuZXcgRm9udEZhY2UoXCJUd2Vtb2ppXCIsIHBhdGgsIHsgd2VpZ2h0OiBcIjcwMFwiIH0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBmYWxsIGJhY2sgdG8gU0JJWCwgZ2VuZXJhdGVkIHZpYSBodHRwczovL2dpdGh1Yi5jb20vbWF0cml4LW9yZy90d2Vtb2ppLWNvbHIvdHJlZS9tYXR0aGV3L3NiaXhcbiAgICAgICAgY29uc3QgcGF0aCA9IGB1cmwoJyR7cmVxdWlyZShcIi4uLy4uL3Jlcy9mb250cy9Ud2Vtb2ppX01vemlsbGEvVHdlbW9qaU1vemlsbGEtc2JpeC53b2ZmMlwiKX0nKWA7XG4gICAgICAgIGRvY3VtZW50LmZvbnRzLmFkZChuZXcgRm9udEZhY2UoXCJUd2Vtb2ppXCIsIHBhdGgsIHt9KSk7XG4gICAgICAgIGRvY3VtZW50LmZvbnRzLmFkZChuZXcgRm9udEZhY2UoXCJUd2Vtb2ppXCIsIHBhdGgsIHsgd2VpZ2h0OiBcIjYwMFwiIH0pKTtcbiAgICAgICAgZG9jdW1lbnQuZm9udHMuYWRkKG5ldyBGb250RmFjZShcIlR3ZW1vamlcIiwgcGF0aCwgeyB3ZWlnaHQ6IFwiNzAwXCIgfSkpO1xuICAgIH1cbiAgICAvLyAuLi5hbmQgaWYgU0JJWCBpcyBub3Qgc3VwcG9ydGVkLCB0aGUgYnJvd3NlciB3aWxsIGZhbGwgYmFjayB0byBvbmUgb2YgdGhlIG5hdGl2ZSBmb250cyBzcGVjaWZpZWQuXG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQWNBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQWRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQSxTQUFTQyxrQkFBa0JBLENBQUNDLEVBQVUsRUFBVztFQUM3Q0MsY0FBTSxDQUFDQyxHQUFHLENBQUMs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