1/*  DokuWiki MoaiEditor Match_media.js file
2    Version : 0.5 (May 5, 2026)
3    Author  : MoaiTools <info@moaitools.org>
4    License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */
5
6MoaiEditor.MatchMedia = class {
7
8    constructor(outer) {
9        this.tools = outer;
10    }
11    // ────────────────────────────────────
12    same (score, block, node) {
13
14        // Gather media tags in the text (if not cached)
15        if (!('media' in block))
16            this.gatherFromText(block);
17
18        // Gather media elements in the htlm element (if not cached)
19        if (!('media' in node))
20            this.gatherFromNode(node);
21
22
23        // Copy array because it will be trimmed
24        var textMedia = block.media.slice();
25
26        // Check matches
27        var n = 0;
28        var m = 0;
29        for (let pathname of node.media) {
30            var i = 0;
31            for (let words of textMedia)
32                if (this.tools.wordsInString(words, pathname).score == 1) {
33                    m += 1;
34                    textMedia.splice(i,1);
35                    break;
36                }
37            n += 1;
38        }
39
40        // Update the score
41        score.m += m;
42        score.n += n;
43    }
44    // ────────────────────────────────────
45    gatherFromText (block) {
46
47        // Get the text from the block
48        var text = block.text;
49        if ('cleantext' in block)
50            text = block.cleantext;
51
52        // Define patterns
53        const patterns = [
54        /*  /\[\{\{(?:[^\}]|(?:\}[^\}]))+\}\}\]/gu,       //  Imagebox plugin [{{ }}] */
55            /\{\{(?:[^\}]|(?:\}[^\}]))+\}\}/gu,           //  Bundled dokuwiki media tag {{wiki:dokuwiki-128.png?linkonly|Description}}
56        ];
57        // Gather media tags in the text
58        var media = [];
59        for (let pattern of patterns) {
60            const matches = text.match(pattern);
61            if (matches === null)
62                continue;
63            // Remove the matches from the text to avoid double matching
64            for (let match of matches)
65                text = text.replace(match,'');
66            // Parse the filename with namespace part
67            for (let match of matches) {
68                const filepath = match.match(/[^{]*?(?=[?|}])/);
69                if (filepath !== null) {
70                    var parts = filepath[0].trim().split(/[:/\\]/);
71                    parts = parts.filter(str => (str !== ''));
72                    if (parts.length > 0)
73                        media.push(parts);
74                }
75            }
76        }
77        // Store
78        block.media = media;
79        block.cleantext = text;
80    }
81    // ────────────────────────────────────
82    gatherFromNode (node) {
83
84        // Gather media files
85        var pathnames = [];
86        for (let mediaElement of node.handle.querySelectorAll(":scope > .media")) {       // The filename can be either in 'src' or 'href'
87            var pathname = null;
88            const tag = mediaElement.tagName;
89            if (tag == 'A')
90                pathname = mediaElement.querySelector(":scope > img")?.src;
91            if (tag == 'VIDEO')
92                pathname = mediaElement.querySelector(":scope source")?.src;
93            if (pathname !== undefined  &&  pathname !== null) {
94                pathnames.push(pathname);
95            }
96        }
97        node.media = pathnames;
98    }
99
100}; // End Class
101