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

feat: Add fileNameWithEllipsis helper #34

Merged
merged 1 commit into from
Nov 21, 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chatwoot/utils",
"version": "0.0.25",
"version": "0.0.26",
"description": "Chatwoot utils",
"private": false,
"license": "MIT",
Expand Down
31 changes: 31 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,34 @@ export const convertSecondsToTimeUnit = (
return { time: Number((seconds / 3600).toFixed(1)), unit: unitNames.hour };
return { time: Number((seconds / 86400).toFixed(1)), unit: unitNames.day };
};

/**
* @name fileNameWithEllipsis
* @description Truncates a filename while preserving the extension
* @param {Object} file - File object containing filename or name property
* @param {number} [maxLength=26] - Maximum length of the filename (excluding extension)
* @param {string} [ellipsis='…'] - Character to use for truncation
* @returns {string} Truncated filename with extension
* @example
* fileNameWithEllipsis({ filename: 'very-long-filename.pdf' }, 10) // 'very-long-f….pdf'
* fileNameWithEllipsis({ name: 'short.txt' }, 10) // 'short.txt'
*/
export const fileNameWithEllipsis = (
file: { filename?: string; name?: string },
maxLength: number = 26,
ellipsis: string = '…'
): string => {
const fullName = file?.filename ?? file?.name ?? 'Untitled';

const dotIndex = fullName.lastIndexOf('.');
if (dotIndex === -1) return fullName;

const [name, extension] = [
fullName.slice(0, dotIndex),
fullName.slice(dotIndex),
];

if (name.length <= maxLength) return fullName;

return `${name.slice(0, maxLength)}${ellipsis}${extension}`;
};
47 changes: 46 additions & 1 deletion test/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { convertSecondsToTimeUnit } from '../src/helpers';
import { convertSecondsToTimeUnit, fileNameWithEllipsis } from '../src/helpers';

describe('#convertSecondsToTimeUnit', () => {
it("it should return { time: 1, unit: 'm' } if 60 seconds passed", () => {
Expand Down Expand Up @@ -49,3 +49,48 @@ describe('#convertSecondsToTimeUnit', () => {
).toEqual({ time: '', unit: '' });
});
});

describe('fileNameWithEllipsis', () => {
it('should return original filename if name length is within limit', () => {
const file = { name: 'document.pdf' };
expect(fileNameWithEllipsis(file)).toBe('document.pdf');
});

it('should truncate filename if it exceeds max length', () => {
const file = { name: 'very-long-filename-that-needs-truncating.pdf' };
expect(fileNameWithEllipsis(file)).toBe('very-long-filename-that-ne….pdf');
});

it('should handle files without extension', () => {
const file = { name: 'README' };
expect(fileNameWithEllipsis(file)).toBe('README');
});

it('should handle files with multiple dots', () => {
const file = { name: 'archive.tar.gz' };
expect(fileNameWithEllipsis(file)).toBe('archive.tar.gz');
});

it('should handle hidden files', () => {
const file = { name: '.gitignore' };
expect(fileNameWithEllipsis(file)).toBe('.gitignore');
});

it('should handle both filename and name properties', () => {
const file = {
filename: 'from-filename.pdf',
name: 'from-name.pdf',
};
expect(fileNameWithEllipsis(file)).toBe('from-filename.pdf');
});

it('should handle special characters', () => {
const file = { name: 'résumé-2023_final-version.doc' };
expect(fileNameWithEllipsis(file)).toBe('résumé-2023_final-version.doc');
});

it('should handle very short filenames', () => {
const file = { name: 'a.txt' };
expect(fileNameWithEllipsis(file)).toBe('a.txt');
});
});
Loading