vendor: 11,343 bytes, lines 1-347
1/** 2 * @license Hyphenopoly_Loader 5.3.0 - client side hyphenation 3 * ©2024 Mathias Nater, Güttingen (mathiasnater at gmail dot com) 4 * https://github.com/mnater/Hyphenopoly 5 * 6 * Released under the MIT license 7 * http://mnater.github.io/Hyphenopoly/LICENSE 8 */ 9/* globals Hyphenopoly:readonly */ 10window.Hyphenopoly = {}; 11 12((w, d, H, o) => { 13 "use strict"; 14 15 /** 16 * Shortcut for new Map 17 * @param {any} init - initialiser for new Map 18 * @returns {Map} 19 */ 20 const mp = (init) => { 21 return new Map(init); 22 }; 23 24 const scriptName = "Hyphenopoly_Loader.js"; 25 const thisScript = d.currentScript.src; 26 const store = sessionStorage; 27 let mainScriptLoaded = false; 28 29 /** 30 * The main function runs the feature test and loads Hyphenopoly if 31 * necessary. 32 */ 33 const main = (() => { 34 const shortcuts = { 35 "ac": "appendChild", 36 "ce": "createElement", 37 "ct": "createTextNode" 38 }; 39 40 /** 41 * Create deferred Promise 42 * 43 * From http://lea.verou.me/2016/12/resolve-promises-externally-with- 44 * this-one-weird-trick/ 45 * @return {promise} 46 */ 47 const defProm = () => { 48 let res = null; 49 let rej = null; 50 const promise = new Promise((resolve, reject) => { 51 res = resolve; 52 rej = reject; 53 }); 54 promise.resolve = res; 55 promise.reject = rej; 56 return promise; 57 }; 58 59 H.ac = new AbortController(); 60 const fetchOptions = { 61 "credentials": H.s.CORScredentials, 62 "signal": H.ac.signal 63 }; 64 65 let stylesNode = null; 66 67 /** 68 * Define function H.hide. 69 * This function hides (state = 1) or unhides (state = 0) 70 * the whole document (mode == 0) or 71 * each selected element (mode == 1) or 72 * text of each selected element (mode == 2) or 73 * nothing (mode == -1) 74 * @param {integer} state - State 75 * @param {integer} mode - Mode 76 */ 77 H.hide = (state, mode) => { 78 if (state) { 79 let vis = "{visibility:hidden!important}"; 80 stylesNode = d[shortcuts.ce]("style"); 81 let myStyle = ""; 82 if (mode === 0) { 83 myStyle = "html" + vis; 84 } else if (mode !== -1) { 85 if (mode === 2) { 86 vis = "{color:transparent!important}"; 87 } 88 o.keys(H.s.selectors).forEach((sel) => { 89 myStyle += sel + vis; 90 }); 91 } 92 stylesNode[shortcuts.ac](d[shortcuts.ct](myStyle)); 93 d.head[shortcuts.ac](stylesNode); 94 } else if (stylesNode) { 95 stylesNode.remove(); 96 } 97 }; 98 99 const tester = (() => { 100 let fakeBody = null; 101 return { 102 103 /** 104 * Append fakeBody with tests to document 105 * @returns {Object|null} The body element or null, if no tests 106 */ 107 "ap": () => { 108 if (fakeBody) { 109 d.documentElement[shortcuts.ac](fakeBody); 110 return fakeBody; 111 } 112 return null; 113 }, 114 115 /** 116 * Remove fakeBody 117 * @returns {undefined} 118 */ 119 "cl": () => { 120 if (fakeBody) { 121 fakeBody.remove(); 122 } 123 }, 124 125 /** 126 * Create and append div with CSS-hyphenated word 127 * @param {string} lang Language 128 * @returns {undefined} 129 */ 130 "cr": (lang) => { 131 if (H.cf.langs.has(lang)) { 132 return; 133 } 134 fakeBody ||= d[shortcuts.ce]("body"); 135 const testDiv = d[shortcuts.ce]("div"); 136 const ha = "hyphens:auto"; 137 testDiv.lang = lang; 138 testDiv.style.cssText = `visibility:hidden;-webkit-${ha};-ms-${ha};${ha};width:48px;font-size:12px;line-height:12px;border:none;padding:0;word-wrap:normal`; 139 testDiv[shortcuts.ac]( 140 d[shortcuts.ct](H.lrq.get(lang).wo.toLowerCase()) 141 ); 142 fakeBody[shortcuts.ac](testDiv); 143 } 144 }; 145 })(); 146 147 /** 148 * Checks if hyphens (ev.prefixed) is set to auto for the element. 149 * @param {Object} elm - the element 150 * @returns {Boolean} result of the check 151 */ 152 const checkCSSHyphensSupport = (elmStyle) => { 153 const h = elmStyle.hyphens || 154 elmStyle.webkitHyphens || 155 elmStyle.msHyphens; 156 return (h === "auto"); 157 }; 158 159 H.res = { 160 "he": mp() 161 }; 162 163 /** 164 * Load hyphenEngines to H.res.he 165 * 166 * Make sure each .wasm is loaded exactly once, even for fallbacks 167 * Store a list of languages to by hyphenated with each .wasm 168 * @param {string} lang The language 169 * @returns {undefined} 170 */ 171 const loadhyphenEngine = (lang) => { 172 const fn = H.lrq.get(lang).fn; 173 H.cf.pf = true; 174 H.cf.langs.set(lang, "H9Y"); 175 if (H.res.he.has(fn)) { 176 H.res.he.get(fn).l.push(lang); 177 } else { 178 H.res.he.set( 179 fn, 180 { 181 "l": [lang], 182 "w": w.fetch(H.paths.patterndir + fn + ".wasm", fetchOptions) 183 } 184 ); 185 } 186 }; 187 H.lrq.forEach((value, lang) => { 188 if (value.wo === "FORCEHYPHENOPOLY" || H.cf.langs.get(lang) === "H9Y") { 189 loadhyphenEngine(lang); 190 } else { 191 tester.cr(lang); 192 } 193 }); 194 const testContainer = tester.ap(); 195 if (testContainer) { 196 testContainer.querySelectorAll("div").forEach((n) => { 197 if (checkCSSHyphensSupport(n.style) && n.offsetHeight > 12) { 198 H.cf.langs.set(n.lang, "CSS"); 199 } else { 200 loadhyphenEngine(n.lang); 201 } 202 }); 203 tester.cl(); 204 } 205 const hev = H.hev; 206 if (H.cf.pf) { 207 H.res.DOM = new Promise((res) => { 208 if (d.readyState === "loading") { 209 d.addEventListener( 210 "DOMContentLoaded", 211 res, 212 { 213 "once": true, 214 "passive": true 215 } 216 ); 217 } else { 218 res(); 219 } 220 }); 221 H.hide(1, H.s.hide); 222 H.timeOutHandler = w.setTimeout(() => { 223 H.hide(0, null); 224 // eslint-disable-next-line no-bitwise 225 if (H.s.timeout & 1) { 226 H.ac.abort(); 227 } 228 // eslint-disable-next-line no-console 229 console.info(scriptName + " timed out."); 230 }, H.s.timeout); 231 if (mainScriptLoaded) { 232 H.main(); 233 } else { 234 // Load main script 235 fetch(H.paths.maindir + "Hyphenopoly.js", fetchOptions). 236 then((response) => { 237 if (response.ok) { 238 response.blob().then((blb) => { 239 const script = d[shortcuts.ce]("script"); 240 script.src = URL.createObjectURL(blb); 241 d.head[shortcuts.ac](script); 242 mainScriptLoaded = true; 243 URL.revokeObjectURL(script.src); 244 }); 245 } 246 }); 247 } 248 H.hy6ors = mp(); 249 H.cf.langs.forEach((langDef, lang) => { 250 if (langDef === "H9Y") { 251 H.hy6ors.set(lang, defProm()); 252 } 253 }); 254 H.hy6ors.set("HTML", defProm()); 255 H.hyphenators = new Proxy(H.hy6ors, { 256 "get": (target, key) => { 257 return target.get(key); 258 }, 259 "set": () => { 260 // Inhibit setting of hyphenators 261 return true; 262 } 263 }); 264 (() => { 265 if (hev && hev.polyfill) { 266 hev.polyfill(); 267 } 268 })(); 269 } else { 270 (() => { 271 if (hev && hev.tearDown) { 272 hev.tearDown(); 273 } 274 w.Hyphenopoly = null; 275 })(); 276 } 277 (() => { 278 if (H.cft) { 279 store.setItem(scriptName, JSON.stringify( 280 { 281 "langs": [...H.cf.langs.entries()], 282 "pf": H.cf.pf 283 } 284 )); 285 } 286 })(); 287 }); 288 289 H.config = (c) => { 290 /** 291 * Sets default properties for an Object 292 * @param {object} obj - The object to set defaults to 293 * @param {object} defaults - The defaults to set 294 * @returns {object} 295 */ 296 const setDefaults = (obj, defaults) => { 297 if (obj) { 298 o.entries(defaults).forEach(([k, v]) => { 299 // eslint-disable-next-line security/detect-object-injection 300 obj[k] ||= v; 301 }); 302 return obj; 303 } 304 return defaults; 305 }; 306 307 H.cft = Boolean(c.cacheFeatureTests); 308 if (H.cft && store.getItem(scriptName)) { 309 H.cf = JSON.parse(store.getItem(scriptName)); 310 H.cf.langs = mp(H.cf.langs); 311 } else { 312 H.cf = { 313 "langs": mp(), 314 "pf": false 315 }; 316 } 317 318 const maindir = thisScript.slice(0, (thisScript.lastIndexOf("/") + 1)); 319 const patterndir = maindir + "patterns/"; 320 H.paths = setDefaults(c.paths, { 321 maindir, 322 patterndir 323 }); 324 H.s = setDefaults(c.setup, { 325 "CORScredentials": "include", 326 "hide": "all", 327 "selectors": {".hyphenate": {}}, 328 "timeout": 1000 329 }); 330 // Change mode string to mode int 331 H.s.hide = ["all", "element", "text"].indexOf(H.s.hide); 332 if (c.handleEvent) { 333 H.hev = c.handleEvent; 334 } 335 336 const fallbacks = mp(o.entries(c.fallbacks || {})); 337 H.lrq = mp(); 338 o.entries(c.require).forEach(([lang, wo]) => { 339 H.lrq.set(lang.toLowerCase(), { 340 "fn": fallbacks.get(lang) || lang, 341 wo 342 }); 343 }); 344 345 main(); 346 }; 347})(window, document, Hyphenopoly, Object);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.