diff --git a/CHANGES.md b/CHANGES.md index 405a2dd81..50f6ceb1d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -43,6 +43,7 @@ - Fix layer orders messed up on move, group, reparent and undo [Github #2672](https://github.com/penpot/penpot/issues/2672) - Fix max height in library dialog [Github #2335](https://github.com/penpot/penpot/issues/2335) - Fix undo ungroup (shift+g) scrambles positions [Taiga #4674](https://tree.taiga.io/project/penpot/issue/4674) +- Fix justified text is stretched [Github #2539](https://github.com/penpot/penpot/issues/2539) ## 1.16.2-beta diff --git a/frontend/src/app/util/text_position_data.js b/frontend/src/app/util/text_position_data.js index 9343af1f6..c69c9ca26 100644 --- a/frontend/src/app/util/text_position_data.js +++ b/frontend/src/app/util/text_position_data.js @@ -21,7 +21,7 @@ goog.scope(function () { return [...range.getClientRects()].filter((r) => r.width > 0); } - self.parse_text_nodes = function(parent, textNode) { + self.parse_text_nodes = function(parent, textNode, textAlign) { const content = textNode.textContent; const textSize = content.length; @@ -38,13 +38,14 @@ goog.scope(function () { while (to < textSize) { const rects = getRangeRects(textNode, from, to + 1); + const splitByWords = textAlign == "justify" && content[to].trim() == ""; if (rects.length > 1 && safeguard) { from++; to++; safeguard = false; - } else if (rects.length > 1) { + } else if (rects.length > 1 || splitByWords) { const position = prevRect; result.push({ @@ -53,6 +54,10 @@ goog.scope(function () { text: current }); + if (splitByWords) { + to++; + } + from = to; current = ""; safeguard = true; diff --git a/frontend/src/app/util/text_svg_position.cljs b/frontend/src/app/util/text_svg_position.cljs index a99a57c6c..45cdfe529 100644 --- a/frontend/src/app/util/text_svg_position.cljs +++ b/frontend/src/app/util/text_svg_position.cljs @@ -16,7 +16,7 @@ (defn parse-text-nodes "Given a text node retrieves the rectangles for everyone of its paragraphs and its text." - [parent-node direction text-node] + [parent-node direction text-node text-align] (letfn [(parse-entry [^js entry] (when (some? (.-position entry)) @@ -27,7 +27,7 @@ (into [] (keep parse-entry) - (tpd/parse-text-nodes parent-node text-node)))) + (tpd/parse-text-nodes parent-node text-node text-align)))) (def load-promises (atom {})) @@ -70,11 +70,14 @@ process-text-node (fn [parent-node] (let [root (dom/get-parent-with-selector parent-node ".text-node-html") + paragraph (dom/get-parent-with-selector parent-node ".paragraph") shape-x (-> (dom/get-attribute root "data-x") d/parse-double) shape-y (-> (dom/get-attribute root "data-y") d/parse-double) - direction (.-direction (js/getComputedStyle parent-node))] + direction (.-direction (js/getComputedStyle parent-node)) + text-align (.-textAlign (js/getComputedStyle paragraph))] + (->> (.-childNodes parent-node) - (mapcat #(parse-text-nodes parent-node direction %)) + (mapcat #(parse-text-nodes parent-node direction % text-align)) (mapv #(-> % (update-in [:position :x] + shape-x) (update-in [:position :y] + shape-y))))))]