diff --git a/src/components/Functions/Utils.mdx b/src/components/Functions/Utils.mdx new file mode 100644 index 00000000..e7f13b23 --- /dev/null +++ b/src/components/Functions/Utils.mdx @@ -0,0 +1,16 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as UtilFunctionStories from './Utils.stories.svelte'; + + + + +# Utils + +Utils TKTK + + +```javascript +import {prettifyDate} from '@reuters-graphics/graphics-components'; + +``` \ No newline at end of file diff --git a/src/components/Functions/Utils.stories.svelte b/src/components/Functions/Utils.stories.svelte new file mode 100644 index 00000000..fe7b28a9 --- /dev/null +++ b/src/components/Functions/Utils.stories.svelte @@ -0,0 +1,9 @@ + + + diff --git a/src/index.ts b/src/index.ts index 35ad5ae4..790e9306 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,9 @@ export { default as cssVariables } from './actions/cssVariables/index'; export { default as resizeObserver } from './actions/resizeObserver/index'; +// Utils +export { prettifyDate } from './utils/index'; + // Components export { default as Analytics, diff --git a/src/test/utils.test.ts b/src/test/utils.test.ts index 30f26910..3d120620 100644 --- a/src/test/utils.test.ts +++ b/src/test/utils.test.ts @@ -79,7 +79,7 @@ describe('Utils tests', () => { const formattedMay = 'May'; expect(prettifyDate(unformattedMay)).toBe(formattedMay); - const unformattedJune = 'Jun.'; + const unformattedJune = 'JUN.'; const formattedJune = 'June'; expect(prettifyDate(unformattedJune)).toBe(formattedJune); @@ -87,17 +87,17 @@ describe('Utils tests', () => { const formattedJuly = 'July'; expect(prettifyDate(unformattedJuly)).toBe(formattedJuly); - const unformattedSept = 'Sep.'; + const unformattedSept = 'sep.'; const formattedSept = 'Sept.'; expect(prettifyDate(unformattedSept)).toBe(formattedSept); }); it('should format months with year properly', () => { - const unformattedMarch = 'Mar. 2025'; + const unformattedMarch = 'MAR. 2025'; const formattedMarch = 'March 2025'; expect(prettifyDate(unformattedMarch)).toBe(formattedMarch); - const unformattedApril = 'Apr. 2025'; + const unformattedApril = 'apr. 2025'; const formattedApril = 'April 2025'; expect(prettifyDate(unformattedApril)).toBe(formattedApril); @@ -136,6 +136,22 @@ describe('Utils tests', () => { expect(prettifyDate(unformattedJune)).toBe(formattedJune); }); + it('should work with lower or upper case', () => { + const unformattedMarch = 'MAR. 1, 2023, 10:00pm'; + const formattedMarch = 'March 1, 2023, 10:00 p.m.'; + expect(prettifyDate(unformattedMarch)).toBe(formattedMarch); + const unformattedApril = 'APR. 1, 2023, 10:00AM'; + const formattedApril = 'April 1, 2023, 10:00 a.m.'; + expect(prettifyDate(unformattedApril)).toBe(formattedApril); + + const unformattedMay = 'may. 1, 2023, 10:00am'; + const formattedMay = 'May 1, 2023, 10:00 a.m.'; + expect(prettifyDate(unformattedMay)).toBe(formattedMay); + + const unformattedJune = 'JUN. 1, 2023, 10:00AM'; + const formattedJune = 'June 1, 2023, 10:00 a.m.'; + expect(prettifyDate(unformattedJune)).toBe(formattedJune); + }); }); diff --git a/src/utils/index.ts b/src/utils/index.ts index 5ad8d129..f854de2a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -34,49 +34,50 @@ export const getAuthorPageUrl = (author: string): string => { * */ export const prettifyDate = (input: string) => { - // Define a object to map full month names to their Reuters style equivalents + // Define an object to map full month names to their Reuters style equivalents const conversions: { [key: string]: string } = { // full months - January: 'Jan.', - February: 'Feb.', - August: 'Aug.', - September: 'Sept.', - October: 'Oct.', - November: 'Nov.', - December: 'Dec.', + january: 'Jan.', + february: 'Feb.', + august: 'Aug.', + september: 'Sept.', + october: 'Oct.', + november: 'Nov.', + december: 'Dec.', // 3-letter abbreviations that need fixing - Jan: 'Jan.', - Feb: 'Feb.', - Mar: 'March', - Apr: 'April', - Jun: 'June', - Jul: 'July', - Sep: 'Sept.', + jan: 'Jan.', + feb: 'Feb.', + mar: 'March', + apr: 'April', + jun: 'June', + jul: 'July', + sep: 'Sept.', }; - // If the key in conversions is found in the input, replace it with the corresponding value + // If the key in conversions is found in the input (case insensitive), replace it with the corresponding value let formatted = Object.keys(conversions).reduce((acc, key) => { - const regex = new RegExp(`\\b${key}\\b`, 'g'); + const regex = new RegExp(`\\b${key}\\b`, 'gi'); // Added 'i' flag for case insensitive return acc.replace(regex, conversions[key]); }, input); - // Fix rogue periods in abbreviations - let fixedAbbr = formatted.replace('Mar.', 'March') - .replace('March.', 'March') - .replace('Apr.', 'April') - .replace('April.', 'April') - .replace('May.', 'May') - .replace('June.', 'June') - .replace('July.', 'July') - .replace('Sep.', 'Sept.'); + // Fix rogue periods in abbreviations (case insensitive) + let fixedAbbr = formatted + .replace(/\bmar\./gi, 'March') + .replace(/\bmarch\./gi, 'March') + .replace(/\bapr\./gi, 'April') + .replace(/\bapril\./gi, 'April') + .replace(/\bmay\./gi, 'May') + .replace(/\bjune\./gi, 'June') + .replace(/\bjuly\./gi, 'July') + .replace(/\bsep\./gi, 'Sept.'); // Replace double periods with a single period - let fixedPeriods = fixedAbbr.replace('..', '.'); + let fixedPeriods = fixedAbbr.replace(/\.{2,}/g, '.'); - // Fix 'Mar. 1, 2023, 10:00pm' to 'March 1, 2023, 10:00 p.m.', with a space before 'p.m.' - return prettifyAmPm(fixedPeriods) -} + // Fix am/pm formatting + return prettifyAmPm(fixedPeriods); +}; const prettifyAmPm = (text: string) => { return text.replace(/(\d)\s*(am|AM|pm|PM)\b/g, (match, digit, timeDesignator) => {