penpot/frontend/src/app/util/text_position_data.js
2022-05-18 22:27:21 +02:00

72 lines
1.8 KiB
JavaScript

/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) UXBOX Labs SL
*/
"use strict";
goog.provide("app.util.text_position_data");
goog.scope(function () {
const self = app.util.text_position_data;
const document = goog.global.document;
function getRangeRects(node, start, end) {
const range = document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
return [...range.getClientRects()].filter((r) => r.width > 0);
}
self.parse_text_nodes = function(parent, textNode) {
const content = textNode.textContent;
const textSize = content.length;
let from = 0;
let to = 0;
let current = "";
let result = [];
let prevRect = null;
// This variable is to make sure there are not infinite loops
// when we don't advance `to` we store true and then force to
// advance `to` on the next iteration if the condition is true again
let safeguard = false;
while (to < textSize) {
const rects = getRangeRects(textNode, from, to + 1);
if (rects.length > 1 && safeguard) {
from++;
to++;
safeguard = false;
} else if (rects.length > 1) {
const position = prevRect;
result.push({
node: parent,
position: position,
text: current
});
from = to;
current = "";
safeguard = true;
} else {
prevRect = rects[0];
current += content[to];
to = to + 1;
safeguard = false;
}
}
// to == textSize
const rects = getRangeRects(textNode, from, to);
result.push({node: parent, position: rects[0], text: current});
return result;
};
});