Skip to content

Commit

Permalink
fix: calculate x position of tspan elements without explicit x prop
Browse files Browse the repository at this point in the history
  • Loading branch information
klingebiel-sii committed Nov 18, 2024
1 parent 06875b7 commit a6cf9f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
7 changes: 7 additions & 0 deletions packages/layout/src/svg/inheritProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ const inheritProps = (node) => {
const children = node.children.map((child) => {
const props = Object.assign({}, inheritedProps, child.props || {});
const newChild = Object.assign({}, child, { props });

// Do not inherit "x" for <tspan> elements from <text> parent
// If no explicit x is provided, the x-offset will be calculated in layoutText.js
if (child.type === 'TSPAN') {
newChild.props.x = child.props.x;
}

return inheritProps(newChild);
});

Expand Down
26 changes: 23 additions & 3 deletions packages/layout/src/svg/layoutText.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ const AlmostInfinity = 999999999999;

const shrinkWhitespaceFactor = { before: -0.5, after: -0.5 };

const layoutTspan = (fontStore) => (node) => {
const layoutTspan = (fontStore) => (node, xOffset) => {
const attributedString = getAttributedString(fontStore, node);

const x = node.props?.x || 0;
const x = node.props.x === undefined ? xOffset : node.props.x;
const y = node.props?.y || 0;

const container = { x, y, width: AlmostInfinity, height: AlmostInfinity };
Expand All @@ -120,7 +120,27 @@ const layoutTspan = (fontStore) => (node) => {
const layoutText = (fontStore, node) => {
if (!node.children) return node;

const children = node.children.map(layoutTspan(fontStore));
let currentXOffset = node.props?.x || 0;

const layoutFn = layoutTspan(fontStore);

const children = node.children.map((child, index) => {
// If the <tspan> has no explicit x position, and it's not the last child of the <text> node, and it has a value, add a space to the end of the value
if (
child.props.x === undefined &&
index < node.children.length - 1 &&
child.children?.[0]?.value
) {
// eslint-disable-next-line no-param-reassign
child.children[0].value += ' ';
}

const childWithLayout = layoutFn(child, currentXOffset);

currentXOffset += childWithLayout.lines[0].xAdvance;

return childWithLayout;
});

return Object.assign({}, node, { children });
};
Expand Down

0 comments on commit a6cf9f9

Please sign in to comment.