1/*  DokuWiki MoaiEditor Matcher.js file
2    Author  : MoaiTools <info@moaitools.org>
3    License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */
4
5MoaiEditor.Matcher = class {
6
7    constructor(outer) {
8
9        this.matches = outer;
10
11        // Variables
12        this.lines = [];         // array of plain text lines
13        this.sections = [];      // array of {prevHeaderIdx, nextHeaderIdx, nodes:[ {i, type, handle, [textContent, innerText ]}
14
15        // Objects
16        this.tools = new MoaiEditor.MatchTools(this);
17        this.headers = new MoaiEditor.MatchHeaders(this);
18        this.section = new MoaiEditor.MatchSection(this);
19    }
20
21    onAjax(top, bottom, startline, endline) {
22
23        const start = Date.now();
24
25        // Get the lines of text to be parsed
26        this.lines = moaiEditor.editor.current.watcher.lines.slice(startline, endline);
27
28        // Parse html
29        this.parseDOM(top, bottom);
30
31        // Parse headers
32        this.headers.parseText(this.lines);
33        this.headers.findAll();
34
35        // Parse sections
36        for (let section of this.sections)
37            this.section.match(section);
38
39        const elapsed = Date.now() - start;
40    }
41
42    parseDOM(top, bottom) {
43
44        // Reset the arrays
45        this.sections = [];
46        this.headers.nodes = [];
47
48        // Preparations
49        var nodes = [];
50        var prevHeaderIdx = null;
51        var nodeidx = 0;
52        var headeridx = 0;
53        var started = false;
54        if (top === null)
55            started = true;
56
57        // Iterate the preview nodes
58        for (let node of document.querySelectorAll("#moaied__preview_content *")) {
59
60            // Ignore nodes before and after the last preview zone
61            if (top !== null  &&  top.handle == node)
62                started = true;
63            if (!started)
64                continue;
65            if (bottom !== null  &&  bottom.handle == node)
66                break;
67
68            // If we find a header
69            if (['H1','H2','H3','H4','H5'].includes(node.tagName)) {
70
71                // Store the header
72                this.headers.nodes.push({
73                    i         : headeridx,
74                    type      : node.tagName,
75                    text      : node.textContent,
76                    handle    : node,
77                    matchline : null
78                });
79                // Create a new section if there is at least one element inside
80                if (nodes.length > 0) {
81                    this.sections.push({
82                        prevHeaderIdx : prevHeaderIdx,
83                        nextHeaderIdx : headeridx,
84                        nodes      : nodes
85                    });
86                    nodeidx = 0;
87                    nodes = [];
88                }
89                // Make header clickable
90                moaiEditor.scroll.makeElementClickable(node);
91
92                // Continue
93                prevHeaderIdx = headeridx;
94                headeridx += 1;
95                continue;
96            }
97            // Else add the node to the current section
98            nodes.push({
99                i      : nodeidx,
100                type   : node.tagName,
101                handle : node,
102            });
103            nodeidx += 1;
104        }
105        // Create the last section if there are elements inside
106        if (nodes.length > 0)
107            this.sections.push({
108                prevHeaderIdx : prevHeaderIdx,
109                nextHeaderIdx : null,
110                nodes      : nodes
111            });
112
113        //
114        /*
115        */
116    }
117}; // End Class
118
119// ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆
120// ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆
121
122MoaiEditor.MatchSection = class {
123
124    constructor(outer) {
125
126        // Arguments
127        this.outer = outer;
128        this.tools = outer.tools;
129        this.paragraphs = new MoaiEditor.MatchParagraphs(this);
130    }
131
132    match (section) {
133
134        // Init variables
135        this.text = '';             // Plaintext of this section
136        this.lines = [];            // Text lines of this section {text, [cleantext, matched, media, }
137        this.blocks = [];           // Blocks of text of this section {i, text, start, end, [cleantext, matched, media, }
138        this.section = section;     // {prevHeaderIdx, nextHeaderIdx, nodes:[]}
139        this.startline = null;      // Start line of this section in the main text
140
141        // Get the text for this section (this.text, this.lines, this.blocks)
142        this.getSectionText();
143
144
145        for (let type of ['P'])
146            if (type == 'P')
147                this.paragraphs.match();
148
149    }
150
151    getSectionText () {
152
153        // Calc starting and ending lines
154        var prevLine = this.outer.headers.nodes[this.section.prevHeaderIdx]?.matchline;
155        var nextLine = this.outer.headers.nodes[this.section.nextHeaderIdx]?.matchline;
156        if (prevLine === undefined) prevLine = -1;
157        if (nextLine === undefined) nextLine = this.outer.lines.length;
158        const start = prevLine + 1;
159        const end = nextLine - 1;
160        this.startline = start;
161
162        // Iterate the lines
163        var blockStart = 0;
164        var block = {text:'', start:0};
165        var j = 0;
166        var b = 0;
167        for (let i = start; i <= end; i++) {
168            const line = this.outer.lines[i];
169            this.lines.push({text:line});
170            this.text += line + '\n';
171            // If line is not empty, add line to the block
172            if (line.trim().length > 0) {
173                block.text += line + '\n';
174            // If line is empty
175            } else {
176                // If the block is not empty, save it and start a new one
177                if (block.text.trim().length > 0) {
178                    block.i = b;
179                    block.end = j-1;
180                    block.text = block.text.trimEnd();
181                    this.blocks.push(block);
182                    b += 1
183                }
184                // Restart the block regardless
185                block = {text:'', start:j+1};
186            }
187            j += 1;
188        }
189        if (block.text.trim().length > 0) {
190            block.i = b;
191            block.end = j-1;
192            block.text = block.text.trimEnd();
193            this.blocks.push(block);
194        }
195    }
196}; // End Class
197
198// ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆
199// ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆
200
201
202MoaiEditor.MatchPreformatted = class {
203
204    constructor(outer) {
205        this.outer = outer;
206        this.tools = outer.tools;
207    }
208
209    match () {
210
211    }
212}; // End Class
213