1(function () {
2    if (window.DokuWikiProsemirrorFileStatePolyfill) return;
3
4    function mergeAttrsFromHiddenJson(state, input, ownAttrs) {
5        if (!input || !state || !state.doc) return null;
6
7        const json = state.doc.toJSON();
8        let existingAttrs = {};
9
10        if (input.value) {
11            try {
12                const existingJson = JSON.parse(input.value);
13                if (existingJson && typeof existingJson === 'object' && existingJson.attrs && typeof existingJson.attrs === 'object') {
14                    existingAttrs = existingJson.attrs;
15                }
16            } catch (e) {
17                // Ignore invalid JSON and rebuild from the current editor state.
18            }
19        }
20
21        json.attrs = {
22            ...(json.attrs || {}),
23            ...existingAttrs,
24            ...(ownAttrs || {})
25        };
26
27        input.value = JSON.stringify(json);
28        return json;
29    }
30
31    function makeBurstScheduler(callback) {
32        let scheduled = false;
33
34        function runOnce() {
35            if (scheduled) return;
36            scheduled = true;
37            window.requestAnimationFrame(() => {
38                scheduled = false;
39                callback();
40            });
41        }
42
43        return function scheduleBurst() {
44            runOnce();
45            window.setTimeout(runOnce, 0);
46            window.setTimeout(runOnce, 100);
47            window.setTimeout(runOnce, 300);
48        };
49    }
50
51    function bindCommonEditorLifecycle(options) {
52        const onSwitchToText = options && options.onSwitchToText ? options.onSwitchToText : function () {};
53        const onSubmit = options && options.onSubmit ? options.onSubmit : function () {};
54        const onEditorToggle = options && options.onEditorToggle ? options.onEditorToggle : function () {};
55        const onAfterSwitch = options && options.onAfterSwitch ? options.onAfterSwitch : function () {};
56
57        document.addEventListener('mousedown', (event) => {
58            const target = event.target instanceof Element ? event.target : null;
59            if (!target || !target.closest('.plugin_prosemirror_useWYSIWYG')) return;
60            onSwitchToText();
61        }, true);
62
63        document.addEventListener('click', (event) => {
64            const target = event.target instanceof Element ? event.target : null;
65            if (!target) return;
66
67            if (target.closest('.plugin_prosemirror_useWYSIWYG')) {
68                onEditorToggle();
69            }
70
71            const submitControl = target.closest('#dw__editform button[type="submit"], #dw__editform input[type="submit"]');
72            if (!submitControl) return;
73            onSubmit();
74        }, true);
75
76        document.addEventListener('submit', (event) => {
77            const form = event.target instanceof HTMLFormElement ? event.target : null;
78            if (!form || form.id !== 'dw__editform') return;
79            onSubmit();
80        }, true);
81
82        jQuery(window).on('fastwiki:afterSwitch', function () {
83            onAfterSwitch();
84        });
85    }
86
87    function addPolyfillScript(eventData, pluginBase) {
88        if (empty(eventData) || !Array.isArray(eventData.script)) return;
89        const src = DOKU_BASE + 'lib/plugins/' + pluginBase + '/script/prosemirror_file_state_polyfill.js';
90        eventData.script.push({
91            type: 'text/javascript',
92            src: src,
93            _data: '',
94            defer: 'defer'
95        });
96    }
97
98    function empty(value) {
99        return value === null || typeof value === 'undefined';
100    }
101
102    window.DokuWikiProsemirrorFileStatePolyfill = {
103        addPolyfillScript: addPolyfillScript,
104        bindCommonEditorLifecycle: bindCommonEditorLifecycle,
105        makeBurstScheduler: makeBurstScheduler,
106        mergeAttrsFromHiddenJson: mergeAttrsFromHiddenJson
107    };
108})();
109