@atlaskit/renderer
Version:
Renderer component
71 lines (66 loc) • 3.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.countMatches = countMatches;
exports.getIndexMatch = getIndexMatch;
// getIndexMatch finds the position of a given string within a given document, in accordance to the Confluence Annotation backend
// The document is serialised into one large string, excluding any nodes that can not have annotations (eg: emojis, media).
// Finds where the given query string is relative to the serialised partial document
function getIndexMatch(doc, schema, selectedText, startIndex) {
var textContent = '';
var matchIndex = 0;
var numMatches = 0;
var blockNodePos;
doc.descendants(function (node, pos) {
var nodeType = node.type;
var media = schema.nodes.media;
// Mirrors Confluence backend and doesn't construct textContent if it doesn't allow annotations
// Don't skip media node so that block node can be defined its startIndex in within [nodeStart, nodeEnd]
if ((node.isText || !nodeType.allowsMarkType(schema.marks.annotation)) && nodeType !== media) {
// Note: `return true` as a parent disallowing annotations does not mean a child disallows annotations.
// Eg: panel (invalid) > p (valid)
return true;
}
var nodeStart = pos;
var nodeEnd = nodeStart + node.nodeSize;
if (startIndex >= nodeStart && startIndex <= nodeEnd) {
// if it's a node block, set position to pos to indicate to the backend
// that it's an annotation on a block node
if (nodeType === media) {
blockNodePos = pos;
}
// If the start of the annotation selection is within the current node, we scan the document for previous occurrences
// Find the index by counting all previous instances of the selectedText in the partial textContent
// Need to scan from start, up to `startIndex` (which includes partial of the current node)
textContent += doc.textBetween(nodeStart, startIndex - 1);
matchIndex = countMatches(textContent, selectedText);
// Complete appending of the node
textContent += doc.textBetween(startIndex, nodeEnd);
} else {
textContent += node.textContent;
}
return true;
});
// Count total number of matches in final text
numMatches = countMatches(textContent, selectedText);
return {
numMatches: numMatches,
matchIndex: matchIndex,
textContent: textContent,
blockNodePos: blockNodePos
};
}
// countMatches finds the total number of occurrences of `query` within a given `searchString`
function countMatches(searchString, query) {
if (searchString === '' || query === '') {
return 0;
}
// Escape characters that would trigger as syntax in a regex query before converting to the query
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
var reg = new RegExp(query.replace(/(?=[.\\+*?[^\]$(){}\|])/g, '\\'), 'g');
return (searchString.match(reg) || []).length;
}