/* DokuWiki MoaiEditor Match_paragraphs.js file Version : 0.5 (May 5, 2026) Author : MoaiTools License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */ MoaiEditor.MatchParagraphs = class { constructor(outer) { this.outer = outer; this.tools = outer.tools; } // ──────────────────────────────────── match () { // Gather

nodes in this section var nodes = []; for (let node of this.outer.section.nodes) if (node.type == 'P') nodes.push(node); // Return if no

nodes were found if (nodes.length == 0) return; // Filter out all blocks of text that aren't very likely paragraphs var blocks = []; for (let block of this.outer.blocks) if (this.isIsolatedParagraph(block)) blocks.push(block); // Return if no isolated blocks of text were found if (blocks.length == 0) return; // Iterate the

nodes for (let node of nodes) { // Iterate blocks of text var scores = []; for (let block of blocks) { // Skip if block was matched already or it is not a paragraph if (block?.matched) { continue; } // Get scores var score = {n:0, m:0}; this.tools.media.same(score, block, node); this.tools.sameWords(score, block.cleantext, node.handle.textContent, 'whitespace'); if (score.n == 0 || score.m == 0) continue; scores.push({ node:node, block:block, score:score.m/score.n}); } // Sort by score scores.sort((a, b) => (a.score < b.score) ? 1 : -1); var s = []; for (let score of scores) s.push(score.score); // Continue if there are no candidates or both have about the same score if (scores.length == 0) continue; // Continue if the top score is too bad score = scores[0]; if (score.score < 0.4) continue; // Continue if the top two candidates have about the same score if (scores.length >= 2) { const s0 = scores[0].score; const s1 = scores[1].score; const d = s0-s1; if (d < 0.1) continue; } // Prevent the block from being used again score.block.matched = true; // Store the match const type = score.node.type; const handle = score.node.handle; const startline = this.outer.startline + score.block.start; const endline = this.outer.startline + score.block.end; this.outer.outer.matches.add (type, handle, startline, endline, 'paragraph'); } } // ──────────────────────────────────── isIsolatedParagraph (block) { // No line should start with these tags const tags = [' ', '|', '^', '>']; for (let line of block.text.split("\n")) for (let tag of tags) if (line.startsWith(tag)) return false; // It might be a broken paragraph if it has opening or closing block tags if (this.tools.hasBlockTags(block.text)) return false; // Make text matching more accurate and avoid urls like http://images.com/dog.gif from being interpreted as the '//' tag this.tools.media.gatherFromText(block); // Remove media tags from text this.tools.replaceLinks(block); // Replace links with what 'node.textContent' would show // It's very likely the paragraph is broken if it has imbalanced inline tags if (this.tools.hasImbaInlineTags(block.nolinktext)) return false; // It is likely a paragraph (asuming it is surrounded by empty lines above and below) return true; } }; // End Class