Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨Introduce API to create text spans #88

Merged
merged 1 commit into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Minimum requirements bumped to Node 20 and npm 10.
- The functions `line()`, `rect()`, `circle()`, and `path()` to create
graphics shapes with less code and better tool support.

- The function `span()` to create text spans with less code and better
tool support.

### Deprecated

- `TextAttrs` in favor of `TextProps`.
Expand Down
44 changes: 44 additions & 0 deletions src/api/text.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import crypto from 'node:crypto';

import { describe, expect, it } from 'vitest';

import { span } from './text.ts';

global.crypto ??= (crypto as any).webcrypto;

describe('test', () => {
describe('span', () => {
it('creates text span with given string', () => {
const sp = span('foo');

expect(sp).toEqual({ text: 'foo' });
});

it('creates text span with given string and props', () => {
const sp = span('foo', { fontStyle: 'italic' });

expect(sp).toEqual({ text: 'foo', fontStyle: 'italic' });
});

it('creates text span with given array and props', () => {
const sp = span(['foo', span('bar', { fontStyle: 'italic' })], { fontSize: 8 });

expect(sp).toEqual({ text: ['foo', { text: 'bar', fontStyle: 'italic' }], fontSize: 8 });
});

it('extracts a single array element in text', () => {
const sp = span(['foo'], { fontStyle: 'italic' });

expect(sp).toEqual({ text: 'foo', fontStyle: 'italic' });
});

it('merges a single text span in text, inner span takes precedence', () => {
const sp = span(span('foo', { fontWeight: 'bold' }), {
fontStyle: 'italic',
fontWeight: 'normal',
});

expect(sp).toEqual({ text: 'foo', fontWeight: 'bold', fontStyle: 'italic' });
});
});
});
14 changes: 14 additions & 0 deletions src/api/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ export type Text = string | TextSpan | TextSpan[];
*/
export type TextSpan = { text: string | TextSpan | (string | TextSpan)[] } & TextProps;

/**
* Creates a span of text with the given text and properties.
*
* @param text The text to display in this span.
* @param props Optional properties for the span.
*/
export function span(text: string | TextSpan | (string | TextSpan)[], props?: TextProps): TextSpan {
const unwrappedText = Array.isArray(text) && text.length === 1 ? text[0] : text;
if (typeof unwrappedText === 'string' || Array.isArray(unwrappedText)) {
return { ...props, text: unwrappedText };
}
return { ...props, ...unwrappedText };
}

/**
* The font weight is an integer between 0 and 1000. The keywords
* `normal` (400) and `bold` (700) are also supported.
Expand Down
Loading