mirror of
https://github.com/penpot/penpot.git
synced 2025-01-11 01:10:28 -05:00
🐛 Fix problem with RTL
This commit is contained in:
parent
0bcf3d99a0
commit
3a6072bc8f
2 changed files with 81 additions and 40 deletions
66
frontend/src/app/util/text_position_data.js
Normal file
66
frontend/src/app/util/text_position_data.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
self.parse_text_nodes = function(parent, direction, textNode) {
|
||||
const content = textNode.textContent;
|
||||
const textSize = content.length;
|
||||
const rtl = direction === "rtl";
|
||||
|
||||
let from = 0;
|
||||
let to = 0;
|
||||
let current = "";
|
||||
let result = [];
|
||||
|
||||
while (to < textSize) {
|
||||
const rects = getRangeRects(textNode, from, to + 1);
|
||||
|
||||
if (rects.length > 1) {
|
||||
let position;
|
||||
|
||||
if (rtl) {
|
||||
position = rects[1];
|
||||
} else {
|
||||
position = rects[0];
|
||||
}
|
||||
|
||||
result.push({
|
||||
node: parent,
|
||||
position: position,
|
||||
text: current
|
||||
});
|
||||
|
||||
from = to;
|
||||
current = "";
|
||||
|
||||
} else {
|
||||
current += content[to];
|
||||
to = to + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// to == textSize
|
||||
const rects = getRangeRects(textNode, from, to);
|
||||
result.push({node: parent, position: rects[0], text: current});
|
||||
return result;
|
||||
};
|
||||
});
|
|
@ -11,45 +11,20 @@
|
|||
[app.common.transit :as transit]
|
||||
[app.main.store :as st]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as global]))
|
||||
[app.util.text-position-data :as tpd]))
|
||||
|
||||
(defn get-range-rects
|
||||
"Retrieve the rectangles that cover the selection given by a `node` adn
|
||||
the start and end index `start-i`, `end-i`"
|
||||
[^js node start-i end-i]
|
||||
(let [^js range (.createRange global/document)]
|
||||
(.setStart range node start-i)
|
||||
(.setEnd range node end-i)
|
||||
(.getClientRects range)))
|
||||
|
||||
;; TODO: Evaluate to change this function to Javascript
|
||||
(defn parse-text-nodes
|
||||
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
||||
[parent-node rtl text-node]
|
||||
[parent-node direction text-node]
|
||||
|
||||
(let [content (.-textContent text-node)
|
||||
text-size (.-length content)]
|
||||
|
||||
(loop [from-i 0
|
||||
to-i 0
|
||||
current ""
|
||||
result []]
|
||||
(if (>= to-i text-size)
|
||||
(let [rects (get-range-rects text-node from-i to-i)
|
||||
entry {:node parent-node
|
||||
:position (dom/bounding-rect->rect (first rects))
|
||||
:text current}]
|
||||
;; We need to add the last element not closed yet
|
||||
(conj result entry))
|
||||
|
||||
(let [rects (get-range-rects text-node from-i (inc to-i))]
|
||||
;; If the rects increase means we're in a new paragraph
|
||||
(if (> (.-length rects) 1)
|
||||
(let [entry {:node parent-node
|
||||
:position (dom/bounding-rect->rect (if rtl (second rects) (first rects)))
|
||||
:text current}]
|
||||
(recur to-i to-i "" (conj result entry)))
|
||||
(recur from-i (inc to-i) (str current (nth content to-i)) result)))))))
|
||||
(letfn [(parse-entry [^js entry]
|
||||
{:node (.-node entry)
|
||||
:position (dom/bounding-rect->rect (.-position entry))
|
||||
:text (.-text entry)})]
|
||||
(into
|
||||
[]
|
||||
(map parse-entry)
|
||||
(tpd/parse-text-nodes parent-node direction text-node))))
|
||||
|
||||
|
||||
(defn calc-text-node-positions
|
||||
|
@ -87,9 +62,9 @@
|
|||
(->> text-nodes
|
||||
(mapcat
|
||||
(fn [parent-node]
|
||||
(let [rtl (= "rtl" (.-dir (.-parentElement parent-node)))]
|
||||
(let [direction (.-direction (js/getComputedStyle parent-node))]
|
||||
(->> (.-childNodes parent-node)
|
||||
(mapcat #(parse-text-nodes parent-node rtl %))))))
|
||||
(mapcat #(parse-text-nodes parent-node direction %))))))
|
||||
(mapv #(update % :position translate-rect))))))
|
||||
|
||||
(defn calc-position-data
|
||||
|
@ -102,15 +77,13 @@
|
|||
(->> text-data
|
||||
(mapv (fn [{:keys [node position text]}]
|
||||
(let [{:keys [x y width height]} position
|
||||
rtl (= "rtl" (.-dir (.-parentElement ^js node)))
|
||||
styles (js/getComputedStyle ^js node)
|
||||
get (fn [prop]
|
||||
(let [value (.getPropertyValue styles prop)]
|
||||
(when (and value (not= value ""))
|
||||
value)))]
|
||||
(d/without-nils
|
||||
{:rtl rtl
|
||||
:x (if rtl (+ x width) x)
|
||||
{:x x
|
||||
:y (+ y height)
|
||||
:width width
|
||||
:height height
|
||||
|
@ -123,3 +96,5 @@
|
|||
:font-style (str (get "font-style"))
|
||||
:fills (transit/decode-str (get "--fills"))
|
||||
:text text}))))))))))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue