PageSourceSearch

https://www.pfarrverein.ch/_kirchenweb/js/hyphenopoly/Hyphenopoly_Loader.js?v=d5e37

js pfarrverein.ch collected 2026-09-25 08:39:13 UTC 27,196 bytes, 781 lines download raw bytes

1/**
2 * @license Hyphenopoly_Loader 3.0.2 - client side hyphenation
3 * ©2019  Mathias Nater, Zürich (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
10/* global Hyphenopoly */
11
12(function H9YL() {
13    "use strict";
14    const d = document;
15    const H = Hyphenopoly;
16
17    /**
18     * Create Object without standard Object-prototype
19     * @returns {Object} empty object
20     */
21    function empty() {
22        return Object.create(null);
23    }
24
25
26    /**
27     * Shorthand for Object.keys(obj).forEach(function () {})
28     * @param {Object} obj the object to iterate
29     * @param {function} fn the function to execute
30     * @returns {undefined}
31     */
32    function eachKey(obj, fn) {
33        Object.keys(obj).forEach(fn);
34    }
35
36    (function configFeat() {
37        // Set H.clientFeat (either from sessionStorage or empty)
38        if (H.cacheFeatureTests && sessionStorage.getItem("Hyphenopoly_Loader")) {
39            H.clientFeat = JSON.parse(sessionStorage.getItem("Hyphenopoly_Loader"));
40        } else {
41            H.clientFeat = {
42                "langs": empty(),
43                "polyfill": false,
44                "wasm": null
45            };
46        }
47    }());
48    (function configPaths() {
49        // Set defaults for paths and setup
50        H.dfltPaths = Object.create({
51            "maindir": "../Hyphenopoly/",
52            "patterndir": "../Hyphenopoly/patterns/"
53        });
54        if (H.paths) {
55            if (H.paths.patterndir) {
56                H.dfltPaths.patterndir = H.paths.patterndir;
57            }
58            if (H.paths.maindir) {
59                H.dfltPaths.maindir = H.paths.maindir;
60            }
61        }
62    }());
63    (function configSetup() {
64        if (H.setup) {
65            H.setup.selectors = H.setup.selectors || {".hyphenate": {}};
66            H.setup.timeout = H.setup.timeout || 1000;
67            H.setup.hide = H.setup.hide || "all";
68        } else {
69            H.setup = {
70                "hide": "all",
71                "selectors": {".hyphenate": {}},
72                "timeout": 1000
73            };
74        }
75    }());
76    (function configRequire() {
77        H.lcRequire = new Map();
78        eachKey(H.require, function copyRequire(k) {
79            /* eslint-disable security/detect-object-injection */
80            H.lcRequire.set(k.toLowerCase(), H.require[k]);
81            /* eslint-enable security/detect-object-injection */
82        });
83        if (H.fallbacks) {
84            H.lcFallbacks = new Map();
85            eachKey(H.fallbacks, function copyFallbacks(k) {
86                /* eslint-disable security/detect-object-injection */
87                H.lcFallbacks.set(
88                    k.toLowerCase(),
89                    H.fallbacks[k].toLowerCase()
90                );
91                /* eslint-enable security/detect-object-injection */
92            });
93        }
94    }());
95
96    H.toggle = function toggle(state) {
97        if (state === "on") {
98            const stylesNode = d.getElementById("H9Y_Styles");
99            if (stylesNode) {
100                stylesNode.parentNode.removeChild(stylesNode);
101            }
102        } else {
103            const vis = " {visibility: hidden !important}\n";
104            const sc = d.createElement("style");
105            let myStyle = "";
106            sc.id = "H9Y_Styles";
107            switch (H.setup.hide) {
108            case "all":
109                myStyle = "html" + vis;
110                break;
111            case "element":
112                eachKey(H.setup.selectors, function eachSelector(sel) {
113                    myStyle += sel + vis;
114                });
115                break;
116            case "text":
117                eachKey(H.setup.selectors, function eachSelector(sel) {
118                    myStyle += sel + " {color: transparent !important}\n";
119                });
120                break;
121            default:
122                myStyle = "";
123            }
124            sc.appendChild(document.createTextNode(myStyle));
125            d.getElementsByTagName("head")[0].appendChild(sc);
126        }
127    };
128
129    (function setupEvents() {
130        // Events known to the system
131        const definedEvents = new Map();
132        // Default events, execution deferred to Hyphenopoly.js
133        const deferred = [];
134
135        /*
136         * Eegister for custom event handlers, where event is not yet defined
137         * these events will be correctly registered in Hyphenopoly.js
138         */
139        const tempRegister = [];
140
141        /**
142         * Create Event Object
143         * @param {string} name The Name of the event
144         * @param {function} defFunc The default method of the event
145         * @param {boolean} cancellable Is the default cancellable
146         * @returns {undefined}
147         */
148        function define(name, defFunc, cancellable) {
149            definedEvents.set(name, {
150                "cancellable": cancellable,
151                "default": defFunc,
152                "register": []
153            });
154        }
155
156        define(
157            "timeout",
158            function def(e) {
159                H.toggle("on");
160                window.console.info(
161                    "Hyphenopolys 'FOUHC'-prevention timed out after %dms",
162                    e.delay
163                );
164            },
165            false
166        );
167
168        define(
169            "error",
170            function def(e) {
171                switch (e.lvl) {
172                case "info":
173                    window.console.info(e.msg);
174                    break;
175                case "warn":
176                    window.console.warn(e.msg);
177                    break;
178                default:
179                    window.console.error(e.msg);
180                }
181            },
182            true
183        );
184
185        define(
186            "contentLoaded",
187            function def(e) {
188                deferred.push({
189                    "data": e,
190                    "name": "contentLoaded"
191                });
192            },
193            false
194        );
195
196        define(
197            "engineLoaded",
198            function def(e) {
199                deferred.push({
200                    "data": e,
201                    "name": "engineLoaded"
202                });
203            },
204            false
205        );
206
207        define(
208            "hpbLoaded",
209            function def(e) {
210                deferred.push({
211                    "data": e,
212                    "name": "hpbLoaded"
213                });
214            },
215            false
216        );
217
218        define(
219            "loadError",
220            function def(e) {
221                deferred.push({
222                    "data": e,
223                    "name": "loadError"
224                });
225            }
226        );
227
228        define(
229            "tearDown",
230            null,
231            true
232        );
233
234        /**
235         * Dispatch event <name> with arguments <data>
236         * @param {string} name The name of the event
237         * @param {Object|undefined} data Data of the event
238         * @returns {undefined}
239         */
240        function dispatch(name, data) {
241            data = data || empty();
242            let defaultPrevented = false;
243            definedEvents.get(name).register.forEach(
244                function call(currentHandler) {
245                    data.preventDefault = function preventDefault() {
246                        if (definedEvents.get(name).cancellable) {
247                            defaultPrevented = true;
248                        }
249                    };
250                    currentHandler(data);
251                }
252            );
253            if (
254                !defaultPrevented &&
255                definedEvents.get(name).default
256            ) {
257                definedEvents.get(name).default(data);
258            }
259        }
260
261        /**
262         * Add EventListender <handler> to event <name>
263         * @param {string} name The name of the event
264         * @param {function} handler Function to register
265         * @param {boolean} defer If the registration is deferred
266         * @returns {undefined}
267         */
268        function addListener(name, handler, defer) {
269            if (definedEvents.has(name)) {
270                definedEvents.get(name).register.push(handler);
271            } else if (defer) {
272                tempRegister.push({
273                    "handler": handler,
274                    "name": name
275                });
276            } else {
277                H.events.dispatch(
278                    "error",
279                    {
280                        "lvl": "warn",
281                        "msg": "unknown Event \"" + name + "\" discarded"
282                    }
283                );
284            }
285        }
286
287        if (H.handleEvent) {
288            eachKey(H.handleEvent, function add(name) {
289                /* eslint-disable security/detect-object-injection */
290                addListener(name, H.handleEvent[name], true);
291                /* eslint-enable security/detect-object-injection */
292            });
293        }
294
295        H.events = empty();
296        H.events.deferred = deferred;
297        H.events.tempRegister = tempRegister;
298        H.events.dispatch = dispatch;
299        H.events.define = define;
300        H.events.addListener = addListener;
301    }());
302
303    /**
304     * Test if wasm is supported
305     * @returns {undefined}
306     */
307    function featureTestWasm() {
308        /* eslint-disable no-prototype-builtins */
309        /**
310         * Feature test for wasm
311         * @returns {boolean} support
312         */
313        function runWasmTest() {
314            /*
315             * This is the original test, without webkit workaround
316             * if (typeof WebAssembly === "object" &&
317             *     typeof WebAssembly.instantiate === "function") {
318             *     const module = new WebAssembly.Module(Uint8Array.from(
319             *         [0, 97, 115, 109, 1, 0, 0, 0]
320             *     ));
321             *     if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
322             *         return WebAssembly.Instance.prototype.isPrototypeOf(
323             *             new WebAssembly.Instance(module)
324             *         );
325             *     }
326             * }
327             * return false;
328             */
329
330            /*
331             * Wasm feature test with iOS bug detection
332             * (https://bugs.webkit.org/show_bug.cgi?id=181781)
333             */
334            if (
335                typeof WebAssembly === "object" &&
336                typeof WebAssembly.instantiate === "function"
337            ) {
338                /* eslint-disable array-element-newline */
339                const module = new WebAssembly.Module(Uint8Array.from([
340                    0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127,
341                    3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 8, 1, 4, 116, 101, 115,
342                    116, 0, 0, 10, 16, 1, 14, 0, 32, 0, 65, 1, 54, 2, 0, 32,
343                    0, 40, 2, 0, 11
344                ]));
345                /* eslint-enable array-element-newline */
346                if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
347                    const inst = new WebAssembly.Instance(module);
348                    return WebAssembly.Instance.prototype.isPrototypeOf(inst) &&
349                            (inst.exports.test(4) !== 0);
350                }
351            }
352            return false;
353        }
354        /* eslint-enable no-prototype-builtins */
355        if (H.clientFeat.wasm === null) {
356            H.clientFeat.wasm = runWasmTest();
357        }
358    }
359
360    /**
361     * Load script by adding <script>-tag
362     * @param {string} path Where the script is stored
363     * @param {string} filename Filename of the script
364     * @returns {undefined}
365     */
366    function scriptLoader(path, filename) {
367        const script = d.createElement("script");
368        script.src = path + filename;
369        if (filename === "hyphenEngine.asm.js") {
370            script.addEventListener("load", function listener() {
371                H.events.dispatch("engineLoaded", {"msg": "asm"});
372            });
373        }
374        d.head.appendChild(script);
375    }
376
377    const loadedBins = new Map();
378
379    /**
380     * Load binary files either with fetch (on new browsers that support wasm)
381     * or with xmlHttpRequest
382     * @param {string} path Where the script is stored
383     * @param {string} fne Filename of the script with extension
384     * @param {string} name Name of the ressource
385     * @param {Object} msg Message
386     * @returns {undefined}
387     */
388    function binLoader(path, fne, name, msg) {
389        /**
390         * Get bin file using fetch
391         * @param {string} p Where the script is stored
392         * @param {string} f Filename of the script with extension
393         * @param {string} n Name of the ressource
394         * @param {Object} m Message
395         * @returns {undefined}
396         */
397        function fetchBinary(p, f, n, m) {
398            if (!loadedBins.has(f)) {
399                loadedBins.set(f, [m]);
400                window.fetch(p + f).then(
401                    function resolve(response) {
402                        if (response.ok) {
403                            if (n === "hyphenEngine") {
404                                H.binaries.set(n, response.arrayBuffer().then(
405                                    function getModule(buf) {
406                                        return new WebAssembly.Module(buf);
407                                    }
408                                ));
409                                H.events.dispatch("engineLoaded", {"msg": m});
410                            } else {
411                                const files = loadedBins.get(f);
412                                files.forEach(function eachHpb(rn) {
413                                    H.binaries.set(
414                                        rn,
415                                        (files.length > 1)
416                                            ? response.clone().arrayBuffer()
417                                            : response.arrayBuffer()
418                                    );
419                                    H.events.dispatch(
420                                        "hpbLoaded",
421                                        {"msg": rn}
422                                    );
423                                });
424                            }
425                        } else {
426                            H.events.dispatch("loadError", {
427                                "file": f,
428                                "msg": m,
429                                "name": n,
430                                "path": p
431                            });
432                        }
433                    }
434                );
435            } else if (n !== "hyphenEngine") {
436                loadedBins.get(f).push(m);
437            }
438        }
439
440        /**
441         * Get bin file using XHR
442         * @param {string} p Where the script is stored
443         * @param {string} f Filename of the script with extension
444         * @param {string} n Name of the ressource
445         * @param {Object} m Message
446         * @returns {undefined}
447         */
448        function requestBinary(p, f, n, m) {
449            /* eslint-disable-next-line no-negated-condition */
450            if (!loadedBins.has(f)) {
451                loadedBins.set(f, [m]);
452                const xhr = new XMLHttpRequest();
453                xhr.onload = function onload() {
454                    if (xhr.statusText === "OK") {
455                        loadedBins.get(f).
456                            forEach(function eachHpb(rn) {
457                                H.binaries.set(
458                                    rn,
459                                    xhr.response
460                                );
461                                H.events.dispatch(
462                                    "hpbLoaded",
463                                    {"msg": rn}
464                                );
465                            });
466                    } else {
467                        H.events.dispatch("loadError", {
468                            "file": f,
469                            "msg": m,
470                            "name": n,
471                            "path": p
472                        });
473                    }
474                };
475                xhr.open("GET", p + f);
476                xhr.responseType = "arraybuffer";
477                xhr.send();
478            } else {
479                loadedBins.get(f).push(m);
480            }
481        }
482        if (H.clientFeat.wasm) {
483            fetchBinary(path, fne, name, msg);
484        } else {
485            requestBinary(path, fne, name, msg);
486        }
487    }
488
489    /**
490     * Pre-Allocate memory for (w)asm
491     * Default is 32 wasm Pages (). For languages with larger .hpb
492     * files a higher value is needed.
493     * Get the value from baseData.heapSize in Hyphenopoly.js
494     * @param {string} lang Language
495     * @returns {undefined}
496     */
497    function allocateMemory(lang) {
498        const specVal = new Map(
499            [["de", 54], ["hu", 205], ["nb-no", 91], ["nl", 41]]
500        );
501        const wasmPages = specVal.get(lang) || 32;
502        H.specMems = H.specMems || new Map();
503        if (H.clientFeat.wasm) {
504            H.specMems.set(lang, new WebAssembly.Memory({
505                "initial": wasmPages,
506                "maximum": 256
507            }));
508        } else {
509            /**
510             * Polyfill Math.log2
511             * @param {number} x argument
512             * @return {number} Log2(x)
513             */
514            Math.log2 = Math.log2 || function polyfillLog2(x) {
515                return Math.log(x) * Math.LOG2E;
516            };
517            /* eslint-disable no-bitwise */
518            const asmPages = (2 << Math.floor(Math.log2(wasmPages))) * 65536;
519            /* eslint-enable no-bitwise */
520            H.specMems.set(lang, new ArrayBuffer(asmPages));
521        }
522    }
523
524    (function featureTestCSSHyphenation() {
525        const tester = (function tester() {
526            let fakeBody = null;
527
528            const css = (function createCss() {
529                /* eslint-disable array-element-newline */
530                const props = [
531                    "visibility:hidden;",
532                    "-moz-hyphens:auto;",
533                    "-webkit-hyphens:auto;",
534                    "-ms-hyphens:auto;",
535                    "hyphens:auto;",
536                    "width:48px;",
537                    "font-size:12px;",
538                    "line-height:12px;",
539                    "border:none;",
540                    "padding:0;",
541                    "word-wrap:normal"
542                ];
543                /* eslint-enable array-element-newline */
544                return props.join("");
545            }());
546
547            /**
548             * Create and append div with CSS-hyphenated word
549             * @param {string} lang Language
550             * @returns {undefined}
551             */
552            function create(lang) {
553                /* eslint-disable security/detect-object-injection */
554                if (H.clientFeat.langs[lang]) {
555                    return;
556                }
557                /* eslint-enable security/detect-object-injection */
558                fakeBody = fakeBody || d.createElement("body");
559                const testDiv = d.createElement("div");
560                testDiv.lang = lang;
561                testDiv.id = lang;
562                testDiv.style.cssText = css;
563                testDiv.appendChild(d.createTextNode(H.lcRequire.get(lang)));
564                fakeBody.appendChild(testDiv);
565            }
566
567            /**
568             * Append fakeBody with tests to target (document)
569             * @param {Object} target Where to append fakeBody
570             * @returns {Object|null} The body element or null, if no tests
571             */
572            function append(target) {
573                if (fakeBody) {
574                    target.appendChild(fakeBody);
575                    return fakeBody;
576                }
577                return null;
578            }
579
580            /**
581             * Remove fakeBody
582             * @returns {undefined}
583             */
584            function clear() {
585                if (fakeBody) {
586                    fakeBody.parentNode.removeChild(fakeBody);
587                }
588            }
589            return {
590                "append": append,
591                "clear": clear,
592                "create": create
593            };
594        }());
595
596        /**
597         * Checks if hyphens (ev.prefixed) is set to auto for the element.
598         * @param {Object} elm - the element
599         * @returns {Boolean} result of the check
600         */
601        function checkCSSHyphensSupport(elm) {
602            return (
603                elm.style.hyphens === "auto" ||
604                elm.style.webkitHyphens === "auto" ||
605                elm.style.msHyphens === "auto" ||
606                elm.style["-moz-hyphens"] === "auto"
607            );
608        }
609
610        /**
611         * Expose the hyphenate-function of a specific language to
612         * Hyphenopoly.hyphenators.<language>
613         *
614         * Hyphenopoly.hyphenators.<language> is a Promise that fullfills
615         * to hyphenate(entity, sel) as soon as the ressources are loaded
616         * and the engine is ready.
617         * If Promises aren't supported (e.g. IE11) a error message is produced.
618         *
619         * @param {string} lang - the language
620         * @returns {undefined}
621         */
622        function exposeHyphenateFunction(lang) {
623            /* eslint-disable security/detect-object-injection */
624            H.hyphenators = H.hyphenators || empty();
625            if (!H.hyphenators[lang]) {
626                if (window.Promise) {
627                    H.hyphenators[lang] = new Promise(function pro(rs, rj) {
628                        H.events.addListener("engineReady", function handler(e) {
629                            if (e.msg === lang) {
630                                rs(H.createHyphenator(e.msg));
631                            }
632                        }, true);
633                        H.events.addListener("error", function handler(e) {
634                            if (e.key === lang || e.key === "hyphenEngine") {
635                                rj(e.msg);
636                            }
637                        }, true);
638                    });
639                } else {
640                    H.hyphenators[lang] = {
641
642                        /**
643                         * Fires an error message, if then is called
644                         * @returns {undefined}
645                         */
646                        "then": function () {
647                            H.events.dispatch(
648                                "error",
649                                {"msg": "Promises not supported in this engine. Use a polyfill (e.g. https://github.com/taylorhakes/promise-polyfill)!"}
650                            );
651                        }
652                    };
653                }
654            }
655            /* eslint-enable security/detect-object-injection */
656        }
657
658        /**
659         * Load all ressources for a required <lang>, check if wasm is supported
660         * and expose the hyphenate function.
661         * @param {string} lang The language
662         * @returns {undefined}
663         */
664        function loadPattern(lang) {
665            let filename = lang + ".hpb";
666            let langFallback = lang;
667            if (H.lcFallbacks && H.lcFallbacks.has(lang)) {
668                langFallback = H.lcFallbacks.get(lang);
669                filename = langFallback + ".hpb";
670            }
671            H.binaries = H.binaries || new Map();
672            binLoader(H.dfltPaths.patterndir, filename, langFallback, lang);
673        }
674        featureTestWasm();
675        H.lcRequire.forEach(function eachReq(value, lang) {
676            /* eslint-disable security/detect-object-injection */
677            if (value === "FORCEHYPHENOPOLY") {
678                H.clientFeat.polyfill = true;
679                H.clientFeat.langs[lang] = "H9Y";
680                loadPattern(lang);
681            } else if (
682                H.clientFeat.langs[lang] &&
683                H.clientFeat.langs[lang] === "H9Y"
684            ) {
685                loadPattern(lang);
686            } else {
687                tester.create(lang);
688            }
689            /* eslint-enable security/detect-object-injection */
690        });
691
692        const testContainer = tester.append(d.documentElement);
693        if (testContainer !== null) {
694            H.lcRequire.forEach(function eachReq(value, lang) {
695                if (value !== "FORCEHYPHENOPOLY") {
696                    const el = d.getElementById(lang);
697                    /* eslint-disable security/detect-object-injection */
698                    if (checkCSSHyphensSupport(el) && el.offsetHeight > 12) {
699                        H.clientFeat.langs[lang] = "CSS";
700                    } else {
701                        H.clientFeat.polyfill = true;
702                        H.clientFeat.langs[lang] = "H9Y";
703                        loadPattern(lang);
704                    }
705                    /* eslint-enable security/detect-object-injection */
706                }
707            });
708            tester.clear();
709        }
710        if (H.clientFeat.polyfill) {
711            scriptLoader(H.dfltPaths.maindir, "Hyphenopoly.js");
712            if (H.clientFeat.wasm) {
713                binLoader(
714                    H.dfltPaths.maindir,
715                    "hyphenEngine.wasm",
716                    "hyphenEngine",
717                    "wasm"
718                );
719            } else {
720                scriptLoader(H.dfltPaths.maindir, "hyphenEngine.asm.js");
721            }
722            eachKey(H.clientFeat.langs, function prepareEach(lang) {
723                /* eslint-disable security/detect-object-injection */
724                if (H.clientFeat.langs[lang] === "H9Y") {
725                    allocateMemory(lang);
726                    exposeHyphenateFunction(lang);
727                }
728                /* eslint-enable security/detect-object-injection */
729            });
730        }
731    }());
732
733    /**
734     * Hides the specified elements and starts the process by
735     * dispatching a "contentLoaded"-event in Hyphenopoly
736     * @returns {undefined}
737     */
738    function handleDCL() {
739        if (H.setup.hide.match(/^(?:element|text)$/)) {
740            H.toggle("off");
741        }
742        H.events.dispatch(
743            "contentLoaded",
744            {"msg": ["contentLoaded"]}
745        );
746    }
747
748    if (H.clientFeat.polyfill) {
749        if (H.setup.hide === "all") {
750            H.toggle("off");
751        }
752        if (H.setup.hide !== "none") {
753            H.setup.timeOutHandler = window.setTimeout(function timedOut() {
754                H.toggle("on");
755                H.events.dispatch("timeout", {"delay": H.setup.timeout});
756            }, H.setup.timeout);
757        }
758        if (d.readyState === "loading") {
759            d.addEventListener(
760                "DOMContentLoaded",
761                handleDCL,
762                {
763                    "once": true,
764                    "passive": true
765                }
766            );
767        } else {
768            handleDCL();
769        }
770    } else {
771        H.events.dispatch("tearDown", {});
772        window.Hyphenopoly = null;
773    }
774
775    if (H.cacheFeatureTests) {
776        sessionStorage.setItem(
777            "Hyphenopoly_Loader",
778            JSON.stringify(H.clientFeat)
779        );
780    }
781}());

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.