feat(editor): Add truncate directive (#10842)

This commit is contained in:
Csaba Tuncsik 2024-09-17 14:00:22 +02:00 committed by GitHub
parent a63a9b53f0
commit 57836cc17a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 128 additions and 0 deletions

View file

@ -0,0 +1 @@
export { n8nTruncate } from './n8n-truncate';

View file

@ -0,0 +1,76 @@
import { render } from '@testing-library/vue';
import { n8nTruncate } from './n8n-truncate';
describe('Directive n8n-truncate', () => {
it('should truncate text to 30 chars by default', async () => {
const { html } = render(
{
props: {
text: {
type: String,
},
},
template: '<div v-n8n-truncate>{{text}}</div>',
},
{
props: {
text: 'This is a very long text that should be truncated',
},
global: {
directives: {
n8nTruncate,
},
},
},
);
expect(html()).toBe('<div>This is a very long text that...</div>');
});
it('should truncate text to 30 chars in case of wrong argument', async () => {
const { html } = render(
{
props: {
text: {
type: String,
},
},
template: '<div v-n8n-truncate:ab>{{text}}</div>',
},
{
props: {
text: 'This is a very long text that should be truncated',
},
global: {
directives: {
n8nTruncate,
},
},
},
);
expect(html()).toBe('<div>This is a very long text that...</div>');
});
it('should truncate text to given length', async () => {
const { html } = render(
{
props: {
text: {
type: String,
},
},
template: '<div v-n8n-truncate:25>{{text}}</div>',
},
{
props: {
text: 'This is a very long text that should be truncated',
},
global: {
directives: {
n8nTruncate,
},
},
},
);
expect(html()).toBe('<div>This is a very long text...</div>');
});
});

View file

@ -0,0 +1,26 @@
import type { DirectiveBinding, ObjectDirective } from 'vue';
import { truncate } from '../utils/string';
/**
* Custom directive `n8nTruncate` to truncate text content of an HTML element.
*
* Usage:
* In your Vue template, use the directive `v-n8n-truncate` with an argument to specify the length to truncate to.
*
* Example:
* <p v-n8n-truncate:10>Some long text that will be truncated</p>
*
* This will truncate the text content of the paragraph to 10 characters.
*
* Hint: Do not use it on components
* https://vuejs.org/guide/reusability/custom-directives#usage-on-components
*/
export const n8nTruncate: ObjectDirective = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
el.textContent = truncate(el.textContent ?? '', Number(binding.arg) || undefined);
},
updated(el: HTMLElement, binding: DirectiveBinding) {
el.textContent = truncate(el.textContent ?? '', Number(binding.arg) || undefined);
},
};

View file

@ -5,4 +5,5 @@ export * from './components';
export * from './plugin';
export * from './types';
export * from './utils';
export * from './directives';
export { locale };

View file

@ -1,5 +1,6 @@
import type { Component, Plugin } from 'vue';
import * as components from './components';
import * as directives from './directives';
export interface N8nPluginOptions {}
@ -8,5 +9,9 @@ export const N8nPlugin: Plugin<N8nPluginOptions> = {
for (const [name, component] of Object.entries(components)) {
app.component(name, component as unknown as Component);
}
for (const [name, directive] of Object.entries(directives)) {
app.directive(name, directive);
}
},
};

View file

@ -0,0 +1,17 @@
import { truncate } from './string';
describe('Utils string', () => {
describe('truncate', () => {
it('should truncate text to 30 chars by default', () => {
expect(truncate('This is a very long text that should be truncated')).toBe(
'This is a very long text that...',
);
});
it('should truncate text to given length', () => {
expect(truncate('This is a very long text that should be truncated', 25)).toBe(
'This is a very long text...',
);
});
});
});

View file

@ -0,0 +1,2 @@
export const truncate = (text: string, length = 30): string =>
text.length > length ? text.slice(0, length).trim() + '...' : text;