Skip to content

Commit

Permalink
Full unicode support in TextLine
Browse files Browse the repository at this point in the history
  • Loading branch information
viktor-podzigun committed Mar 16, 2024
1 parent faf4630 commit 7526ea7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
23 changes: 14 additions & 9 deletions src/TextLine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* @typedef {import("./TextLine").TextLineProps} TextLineProps
*/
import React from "react";
import UiString from "./UiString.mjs";
import TextAlign from "./TextAlign.mjs";

const h = React.createElement;
Expand All @@ -13,27 +14,27 @@ const TextLine = (props) => {
const paddingLen = props.padding ?? 1;
const padding = " ".repeat(paddingLen);
const wrapped = TextLine.wrapText(props.text, props.width - paddingLen * 2);
const text = `${padding}${wrapped}${padding}`;
const text = UiString(`${padding}${wrapped}${padding}`);

if (text.length > 0) {
if (text.strWidth() > 0) {
function getLeft() {
switch (props.align) {
case TextAlign.left:
return props.left;
case TextAlign.right:
return props.left + props.width - text.length;
return props.left + props.width - text.strWidth();
default:
return props.left + Math.trunc((props.width - text.length) / 2);
return props.left + Math.trunc((props.width - text.strWidth()) / 2);
}
}

return h("text", {
width: text.length,
width: text.strWidth(),
height: 1,
left: getLeft(),
top: props.top,
style: props.focused ?? false ? props.style.focus : props.style,
content: text,
content: text.toString(),
});
}

Expand All @@ -49,10 +50,14 @@ TextLine.displayName = "TextLine";
* @returns {string}
*/
TextLine.wrapText = (text, width, prefixLen = 3) => {
const dx = text.length - width;
const t = UiString(text);
const dx = t.strWidth() - width;
if (dx > 0) {
const prefix = text.slice(0, Math.min(prefixLen, text.length));
const sufix = text.slice(Math.min(dx + prefixLen + 3, text.length)); // prefix + ...
const prefix = t.slice(0, Math.min(prefixLen, t.strWidth()));
const sufix = t.slice(
Math.min(dx + prefixLen + 3, t.strWidth()),
t.strWidth()
); // prefix + ...
return `${prefix}...${sufix}`;
}

Expand Down
29 changes: 15 additions & 14 deletions test/TextLine.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React from "react";
import TestRenderer from "react-test-renderer";
import assert from "node:assert/strict";
import { assertComponents } from "react-assert";
import UiString from "../src/UiString.mjs";
import TextAlign from "../src/TextAlign.mjs";
import TextLine from "../src/TextLine.mjs";

Expand All @@ -29,15 +30,15 @@ describe("TextLine.test.mjs", () => {
left: left,
top: 2,
width: 15,
text: "test item",
text: "test itemй",
};

//when
const result = TestRenderer.create(h(TextLine, props)).root;

//then
assert.deepEqual(TextLine.displayName, "TextLine");
assertTextLine(result, props, left, " test item ");
assertTextLine(result, props, left, " test itemй ");
});

it("should render Center aligned text", () => {
Expand All @@ -49,14 +50,14 @@ describe("TextLine.test.mjs", () => {
left: left,
top: 2,
width: 15,
text: "test item",
text: "test itemй",
};

//when
const result = TestRenderer.create(h(TextLine, props)).root;

//then
assertTextLine(result, props, left + 2, " test item ");
assertTextLine(result, props, left + 1, " test itemй ");
});

it("should render Right aligned text", () => {
Expand All @@ -68,15 +69,15 @@ describe("TextLine.test.mjs", () => {
left: left,
top: 2,
width: 15,
text: "test item",
text: "test itemй",
};

//when
let result = TestRenderer.create(h(TextLine, props)).root;
//then
// 10| 15|
// test item
assertTextLine(result, props, left + 4, " test item ");
// test itemй
assertTextLine(result, props, left + 3, " test itemй ");

//when empty
result = TestRenderer.create(h(TextLine, { ...props, text: "" })).root;
Expand All @@ -89,8 +90,8 @@ describe("TextLine.test.mjs", () => {
result = TestRenderer.create(h(TextLine, { ...props, padding: 0 })).root;
//then
// 10| 15|
// test item
assertTextLine(result, props, left + 6, "test item");
// test itemй
assertTextLine(result, props, left + 5, "test itemй");

//when empty text without padding
result = TestRenderer.create(
Expand Down Expand Up @@ -127,7 +128,7 @@ describe("TextLine.test.mjs", () => {
left: left,
top: 2,
width: 12,
text: "test item",
text: "test itemй",
focused: false,
padding: 0,
};
Expand All @@ -136,7 +137,7 @@ describe("TextLine.test.mjs", () => {
const result = TestRenderer.create(h(TextLine, props)).root;

//then
assertTextLine(result, props, left, "test item");
assertTextLine(result, props, left, "test itemй");
});

it("should render long text with ellipsis", () => {
Expand All @@ -147,14 +148,14 @@ describe("TextLine.test.mjs", () => {
left: left,
top: 2,
width: 12,
text: "test long item",
text: "test long itemй",
};

//when
const result = TestRenderer.create(h(TextLine, props)).root;

//then
assertTextLine(result, props, left, " tes...item ");
assertTextLine(result, props, left, " tes...temй ");
});
});

Expand Down Expand Up @@ -187,7 +188,7 @@ function assertTextLine(result, props, left, text) {
assertComponents(
result.children,
h("text", {
width: text.length,
width: UiString(text).strWidth(),
height: 1,
left: left,
top: props.top,
Expand Down

0 comments on commit 7526ea7

Please sign in to comment.