Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Equation helper for Tiny Equation plugin.
18
 *
19
 * @module      tiny_equation/equation
20
 * @copyright   2022 Huong Nguyen <huongnv13@gmail.com>
21
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
import Selectors from 'tiny_equation/selectors';
25
 
26
let sourceEquation = null;
27
 
28
/**
29
 * Get the source equation.
30
 * @returns {Object}
31
 */
32
export const getSourceEquation = () => sourceEquation;
33
 
34
/**
35
 * Get selected equation.
36
 * @param {TinyMCE} editor
37
 * @returns {boolean}
38
 */
39
export const getSelectedEquation = (editor) => {
40
    const currentSelection = editor.selection.getSel();
41
    if (!currentSelection) {
42
        // Do the early return if there is no text selected.
43
        return false;
44
    }
45
    const textSelection = editor.selection.getNode().textContent;
46
    const currentCaretPos = currentSelection.focusOffset;
47
    let returnValue = false;
48
 
49
    Selectors.equationPatterns.forEach((pattern) => {
50
        // For each pattern in turn, find all whole matches (including the delimiters).
51
        const regexPattern = new RegExp(pattern.source, "g");
52
        [...textSelection.matchAll(regexPattern)].forEach((matches) => {
53
            const match = matches[0];
54
            // Check each occurrence of this match.
55
            let startIndex = 0;
56
            const startOuter = textSelection.indexOf(match, startIndex);
57
            const endOuter = startOuter + match.length;
58
 
59
            // This match is in our current position - fetch the innerMatch data.
60
            const innerMatch = match.match(pattern);
61
            if (innerMatch && innerMatch.length) {
62
                // We need the start and end of the inner match for later.
63
                const startInner = textSelection.indexOf(innerMatch[1], startOuter);
64
                const endInner = startInner + innerMatch[1].length;
65
 
66
                // We need to check the caret position before returning the match.
67
                if (currentCaretPos >= startOuter && currentCaretPos <= endOuter) {
68
                    // We'll be returning the inner match for use in the editor itself.
69
                    returnValue = innerMatch[1];
70
 
71
                    // Save all data for later.
72
                    sourceEquation = {
73
                        // Inner match data.
74
                        startInnerPosition: startInner,
75
                        endInnerPosition: endInner,
76
                        innerMatch: innerMatch
77
                    };
78
 
79
                    return;
80
                }
81
            }
82
 
83
            // Update the startIndex to match the end of the current match so that we can continue hunting
84
            // for further matches.
85
            startIndex = endOuter;
86
        });
87
    });
88
 
89
    // We trim the equation when we load it and then add spaces when we save it.
90
    if (returnValue !== false) {
91
        returnValue = returnValue.trim();
92
    } else {
93
        // Clear the saved source equation.
94
        sourceEquation = null;
95
    }
96
 
97
    return returnValue;
98
};
99
 
100
/**
101
 * Get current equation data.
102
 * @param {TinyMCE} editor
103
 * @returns {{}}
104
 */
105
export const getCurrentEquationData = (editor) => {
106
    let properties = {};
107
    const equation = getSelectedEquation(editor);
108
    if (equation) {
109
        properties.equation = equation;
110
    }
111
 
112
    return properties;
113
};
114
 
115
/**
116
 * Handle insertion of a new equation, or update of an existing one.
117
 * @param {Element} currentForm
118
 * @param {TinyMCE} editor
119
 */
120
export const setEquation = (currentForm, editor) => {
121
    const input = currentForm.querySelector(Selectors.elements.equationTextArea);
122
    const sourceEquation = getSourceEquation();
123
    let value = input.value;
124
 
125
    if (value !== '') {
126
        if (sourceEquation) {
127
            const selectedNode = editor.selection.getNode();
128
            const text = selectedNode.textContent;
129
            value = ' ' + value + ' ';
130
            selectedNode.textContent = text.slice(0, sourceEquation.startInnerPosition)
131
                + value
132
                + text.slice(sourceEquation.endInnerPosition);
133
        } else {
134
            value = Selectors.delimiters.start + ' ' + value + ' ' + Selectors.delimiters.end;
135
            editor.insertContent(value);
136
        }
137
    }
138
};