Merge pull request #346 from reuters-graphics/mf-date-formatter
Adds date formatter util, docs, tests
This commit is contained in:
commit
a76415b156
8 changed files with 587 additions and 3 deletions
5
.changeset/spicy-donkeys-attend.md
Normal file
5
.changeset/spicy-donkeys-attend.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@reuters-graphics/graphics-components': patch
|
||||
---
|
||||
|
||||
Adds util function prettifyDate
|
||||
|
|
@ -23,7 +23,8 @@
|
|||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"changeset:version": "changeset version",
|
||||
"changeset:publish": "git add --all && changeset publish",
|
||||
"knip": "knip"
|
||||
"knip": "knip",
|
||||
"test": "vitest"
|
||||
},
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
|
@ -102,14 +103,15 @@
|
|||
"dayjs": "^1.11.13",
|
||||
"es-toolkit": "^1.35.0",
|
||||
"journalize": "^2.6.0",
|
||||
"mp4box": "^0.5.4",
|
||||
"proper-url-join": "^2.1.2",
|
||||
"pym.js": "^1.3.2",
|
||||
"slugify": "^1.6.6",
|
||||
"storybook-addon-rtl": "^1.1.0",
|
||||
"svelte-fa": "^4.0.3",
|
||||
"svelte-intersection-observer": "^1.0.0",
|
||||
"mp4box": "^0.5.4",
|
||||
"ua-parser-js": "^2.0.3"
|
||||
"ua-parser-js": "^2.0.3",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
|
|
|
|||
308
pnpm-lock.yaml
308
pnpm-lock.yaml
|
|
@ -53,6 +53,9 @@ importers:
|
|||
ua-parser-js:
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3
|
||||
vitest:
|
||||
specifier: ^3.2.4
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
devDependencies:
|
||||
'@changesets/cli':
|
||||
specifier: ^2.29.2
|
||||
|
|
@ -1061,6 +1064,9 @@ packages:
|
|||
'@types/aria-query@5.0.4':
|
||||
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
|
||||
|
||||
'@types/chai@5.2.2':
|
||||
resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
|
||||
|
||||
'@types/concat-stream@2.0.3':
|
||||
resolution: {integrity: sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==}
|
||||
|
||||
|
|
@ -1082,6 +1088,9 @@ packages:
|
|||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
|
||||
'@types/deep-eql@4.0.2':
|
||||
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
|
||||
|
||||
'@types/eslint@9.6.1':
|
||||
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
|
||||
|
||||
|
|
@ -1225,21 +1234,50 @@ packages:
|
|||
'@vitest/expect@2.0.5':
|
||||
resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==}
|
||||
|
||||
'@vitest/expect@3.2.4':
|
||||
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
|
||||
|
||||
'@vitest/mocker@3.2.4':
|
||||
resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
|
||||
peerDependencies:
|
||||
msw: ^2.4.9
|
||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
|
||||
peerDependenciesMeta:
|
||||
msw:
|
||||
optional: true
|
||||
vite:
|
||||
optional: true
|
||||
|
||||
'@vitest/pretty-format@2.0.5':
|
||||
resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==}
|
||||
|
||||
'@vitest/pretty-format@2.1.9':
|
||||
resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
|
||||
|
||||
'@vitest/pretty-format@3.2.4':
|
||||
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
|
||||
|
||||
'@vitest/runner@3.2.4':
|
||||
resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
|
||||
|
||||
'@vitest/snapshot@3.2.4':
|
||||
resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
|
||||
|
||||
'@vitest/spy@2.0.5':
|
||||
resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==}
|
||||
|
||||
'@vitest/spy@3.2.4':
|
||||
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
|
||||
|
||||
'@vitest/utils@2.0.5':
|
||||
resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==}
|
||||
|
||||
'@vitest/utils@2.1.9':
|
||||
resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
|
||||
|
||||
'@vitest/utils@3.2.4':
|
||||
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
|
||||
|
||||
abbrev@2.0.0:
|
||||
resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
|
|
@ -1392,6 +1430,10 @@ packages:
|
|||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
cac@6.7.14:
|
||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -1721,6 +1763,15 @@ packages:
|
|||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.4.1:
|
||||
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decode-named-character-reference@1.1.0:
|
||||
resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
|
||||
|
||||
|
|
@ -1898,6 +1949,9 @@ packages:
|
|||
resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-module-lexer@1.7.0:
|
||||
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -2085,6 +2139,10 @@ packages:
|
|||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
expect-type@1.2.2:
|
||||
resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
extend@3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
|
||||
|
|
@ -2125,6 +2183,14 @@ packages:
|
|||
picomatch:
|
||||
optional: true
|
||||
|
||||
fdir@6.4.6:
|
||||
resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==}
|
||||
peerDependencies:
|
||||
picomatch: ^3 || ^4
|
||||
peerDependenciesMeta:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
|
@ -2574,6 +2640,9 @@ packages:
|
|||
js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
js-tokens@9.0.1:
|
||||
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
|
||||
|
||||
js-yaml@3.14.1:
|
||||
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
|
||||
hasBin: true
|
||||
|
|
@ -2689,6 +2758,9 @@ packages:
|
|||
loupe@3.1.3:
|
||||
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
|
||||
|
||||
loupe@3.2.0:
|
||||
resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==}
|
||||
|
||||
lower-case@2.0.2:
|
||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||
|
||||
|
|
@ -3154,6 +3226,9 @@ packages:
|
|||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
pathval@2.0.0:
|
||||
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
|
||||
engines: {node: '>= 14.16'}
|
||||
|
|
@ -3524,6 +3599,9 @@ packages:
|
|||
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
|
@ -3592,6 +3670,12 @@ packages:
|
|||
sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
std-env@3.9.0:
|
||||
resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
|
||||
|
||||
storybook-addon-rtl@1.1.0:
|
||||
resolution: {integrity: sha512-L8JljF1M+30rcSuM4JjeIi4ZRmg9WZi/1u4T/5/EQvpDKCMOAq7uHeOKj4YS1InC4Zksnz3DrggXmO3mISXKcQ==}
|
||||
|
||||
|
|
@ -3669,6 +3753,9 @@ packages:
|
|||
resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
strip-literal@3.0.0:
|
||||
resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==}
|
||||
|
||||
stylis@4.3.6:
|
||||
resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==}
|
||||
|
||||
|
|
@ -3784,18 +3871,40 @@ packages:
|
|||
tiny-invariant@1.3.3:
|
||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
||||
|
||||
tinybench@2.9.0:
|
||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||
|
||||
tinyexec@0.3.2:
|
||||
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
|
||||
|
||||
tinyglobby@0.2.12:
|
||||
resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinyglobby@0.2.14:
|
||||
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinypool@1.1.1:
|
||||
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
|
||||
tinyrainbow@1.2.0:
|
||||
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tinyrainbow@2.0.0:
|
||||
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tinyspy@3.0.2:
|
||||
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tinyspy@4.0.3:
|
||||
resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tmp@0.0.33:
|
||||
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
|
|
@ -3973,6 +4082,11 @@ packages:
|
|||
vfile@6.0.3:
|
||||
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
||||
|
||||
vite-node@3.2.4:
|
||||
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
hasBin: true
|
||||
|
||||
vite@6.3.2:
|
||||
resolution: {integrity: sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
|
|
@ -4021,6 +4135,34 @@ packages:
|
|||
vite:
|
||||
optional: true
|
||||
|
||||
vitest@3.2.4:
|
||||
resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@types/debug': ^4.1.12
|
||||
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
|
||||
'@vitest/browser': 3.2.4
|
||||
'@vitest/ui': 3.2.4
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@types/debug':
|
||||
optional: true
|
||||
'@types/node':
|
||||
optional: true
|
||||
'@vitest/browser':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
|
||||
walk-up-path@3.0.1:
|
||||
resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==}
|
||||
|
||||
|
|
@ -4065,6 +4207,11 @@ packages:
|
|||
engines: {node: ^16.13.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
word-wrap@1.2.5:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -5098,6 +5245,10 @@ snapshots:
|
|||
|
||||
'@types/aria-query@5.0.4': {}
|
||||
|
||||
'@types/chai@5.2.2':
|
||||
dependencies:
|
||||
'@types/deep-eql': 4.0.2
|
||||
|
||||
'@types/concat-stream@2.0.3':
|
||||
dependencies:
|
||||
'@types/node': 22.14.1
|
||||
|
|
@ -5118,6 +5269,8 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
|
||||
'@types/deep-eql@4.0.2': {}
|
||||
|
||||
'@types/eslint@9.6.1':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.7
|
||||
|
|
@ -5299,6 +5452,22 @@ snapshots:
|
|||
chai: 5.2.0
|
||||
tinyrainbow: 1.2.0
|
||||
|
||||
'@vitest/expect@3.2.4':
|
||||
dependencies:
|
||||
'@types/chai': 5.2.2
|
||||
'@vitest/spy': 3.2.4
|
||||
'@vitest/utils': 3.2.4
|
||||
chai: 5.2.0
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.17
|
||||
optionalDependencies:
|
||||
vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
|
||||
'@vitest/pretty-format@2.0.5':
|
||||
dependencies:
|
||||
tinyrainbow: 1.2.0
|
||||
|
|
@ -5307,10 +5476,30 @@ snapshots:
|
|||
dependencies:
|
||||
tinyrainbow: 1.2.0
|
||||
|
||||
'@vitest/pretty-format@3.2.4':
|
||||
dependencies:
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/runner@3.2.4':
|
||||
dependencies:
|
||||
'@vitest/utils': 3.2.4
|
||||
pathe: 2.0.3
|
||||
strip-literal: 3.0.0
|
||||
|
||||
'@vitest/snapshot@3.2.4':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
magic-string: 0.30.17
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/spy@2.0.5':
|
||||
dependencies:
|
||||
tinyspy: 3.0.2
|
||||
|
||||
'@vitest/spy@3.2.4':
|
||||
dependencies:
|
||||
tinyspy: 4.0.3
|
||||
|
||||
'@vitest/utils@2.0.5':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 2.0.5
|
||||
|
|
@ -5324,6 +5513,12 @@ snapshots:
|
|||
loupe: 3.1.3
|
||||
tinyrainbow: 1.2.0
|
||||
|
||||
'@vitest/utils@3.2.4':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
loupe: 3.2.0
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
abbrev@2.0.0: {}
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.14.1):
|
||||
|
|
@ -5473,6 +5668,8 @@ snapshots:
|
|||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
cac@6.7.14: {}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
|
@ -5807,6 +6004,10 @@ snapshots:
|
|||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@4.4.1:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
decode-named-character-reference@1.1.0:
|
||||
dependencies:
|
||||
character-entities: 2.0.2
|
||||
|
|
@ -6026,6 +6227,8 @@ snapshots:
|
|||
iterator.prototype: 1.1.5
|
||||
safe-array-concat: 1.1.3
|
||||
|
||||
es-module-lexer@1.7.0: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
|
@ -6351,6 +6554,8 @@ snapshots:
|
|||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
expect-type@1.2.2: {}
|
||||
|
||||
extend@3.0.2: {}
|
||||
|
||||
extendable-error@0.1.7: {}
|
||||
|
|
@ -6389,6 +6594,10 @@ snapshots:
|
|||
optionalDependencies:
|
||||
picomatch: 4.0.2
|
||||
|
||||
fdir@6.4.6(picomatch@4.0.2):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.2
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
dependencies:
|
||||
flat-cache: 3.2.0
|
||||
|
|
@ -6849,6 +7058,8 @@ snapshots:
|
|||
|
||||
js-tokens@4.0.0: {}
|
||||
|
||||
js-tokens@9.0.1: {}
|
||||
|
||||
js-yaml@3.14.1:
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
|
|
@ -6964,6 +7175,8 @@ snapshots:
|
|||
|
||||
loupe@3.1.3: {}
|
||||
|
||||
loupe@3.2.0: {}
|
||||
|
||||
lower-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
|
@ -7720,6 +7933,8 @@ snapshots:
|
|||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pathval@2.0.0: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
|
@ -8130,6 +8345,8 @@ snapshots:
|
|||
side-channel-map: 1.0.1
|
||||
side-channel-weakmap: 1.0.2
|
||||
|
||||
siginfo@2.0.0: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
sirv@3.0.1:
|
||||
|
|
@ -8189,6 +8406,10 @@ snapshots:
|
|||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
std-env@3.9.0: {}
|
||||
|
||||
storybook-addon-rtl@1.1.0: {}
|
||||
|
||||
storybook@8.6.12(prettier@3.5.3):
|
||||
|
|
@ -8292,6 +8513,10 @@ snapshots:
|
|||
|
||||
strip-json-comments@5.0.1: {}
|
||||
|
||||
strip-literal@3.0.0:
|
||||
dependencies:
|
||||
js-tokens: 9.0.1
|
||||
|
||||
stylis@4.3.6: {}
|
||||
|
||||
supports-color@7.2.0:
|
||||
|
|
@ -8396,15 +8621,30 @@ snapshots:
|
|||
|
||||
tiny-invariant@1.3.3: {}
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
|
||||
tinyexec@0.3.2: {}
|
||||
|
||||
tinyglobby@0.2.12:
|
||||
dependencies:
|
||||
fdir: 6.4.3(picomatch@4.0.2)
|
||||
picomatch: 4.0.2
|
||||
|
||||
tinyglobby@0.2.14:
|
||||
dependencies:
|
||||
fdir: 6.4.6(picomatch@4.0.2)
|
||||
picomatch: 4.0.2
|
||||
|
||||
tinypool@1.1.1: {}
|
||||
|
||||
tinyrainbow@1.2.0: {}
|
||||
|
||||
tinyrainbow@2.0.0: {}
|
||||
|
||||
tinyspy@3.0.2: {}
|
||||
|
||||
tinyspy@4.0.3: {}
|
||||
|
||||
tmp@0.0.33:
|
||||
dependencies:
|
||||
os-tmpdir: 1.0.2
|
||||
|
|
@ -8647,6 +8887,27 @@ snapshots:
|
|||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.2
|
||||
|
||||
vite-node@3.2.4(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.1
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.2
|
||||
|
|
@ -8666,6 +8927,48 @@ snapshots:
|
|||
optionalDependencies:
|
||||
vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
|
||||
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.2
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
'@vitest/spy': 3.2.4
|
||||
'@vitest/utils': 3.2.4
|
||||
chai: 5.2.0
|
||||
debug: 4.4.1
|
||||
expect-type: 1.2.2
|
||||
magic-string: 0.30.17
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.2
|
||||
std-env: 3.9.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.14
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
vite-node: 3.2.4(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 22.14.1
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
walk-up-path@3.0.1: {}
|
||||
|
||||
wcwidth@1.0.1:
|
||||
|
|
@ -8733,6 +9036,11 @@ snapshots:
|
|||
dependencies:
|
||||
isexe: 3.1.1
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
|
|
|
|||
23
src/components/Functions/Utils.mdx
Normal file
23
src/components/Functions/Utils.mdx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { Meta } from '@storybook/blocks';
|
||||
|
||||
import * as UtilFunctionStories from './Utils.stories.svelte';
|
||||
|
||||
<Meta of={UtilFunctionStories} />
|
||||
|
||||
# Util functions
|
||||
|
||||
This library provides utility functions that can be used across various components and applications.
|
||||
|
||||
## Prettify date in the Reuters format
|
||||
|
||||
The function `prettifyDate` formats the input string, which is expected to be in English, to format the month and time designator (AM/PM) according to the Reuters style guide. The function is case agnostic and will format both full month names and their 3-letter abbreviations (i.e. `Mar` or `Jun`) correctly.
|
||||
|
||||
```javascript
|
||||
import { prettifyDate } from '@reuters-graphics/graphics-components';
|
||||
|
||||
// Example usage
|
||||
prettifyDate('January 1, 2023, 10:00 AM'); // returns 'Jan. 1, 2023, 10:00 a.m.'
|
||||
prettifyDate('Jan 1, 2023, 10:00 PM'); // returns 'Jan. 1, 2023, 10:00 p.m.'
|
||||
prettifyDate('MAR. 2025'); // returns 'March 2025'
|
||||
prettifyDate('sep. 1, 2023, 10:00PM'); // returns 'Sept. 1, 2023, 10:00 p.m.'
|
||||
```
|
||||
9
src/components/Functions/Utils.stories.svelte
Normal file
9
src/components/Functions/Utils.stories.svelte
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Components/Utilities/Functions',
|
||||
});
|
||||
</script>
|
||||
|
||||
<Story name="Demo" tags={['!autodocs', '!dev']} />
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
158
src/test/utils.test.ts
Normal file
158
src/test/utils.test.ts
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import { prettifyDate } from '../utils/index';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
process.env.TESTING = 'true';
|
||||
|
||||
describe('Utils tests', () => {
|
||||
it('should format full month correctly', () => {
|
||||
const unformatted = 'January 1, 2023, 10:00 AM';
|
||||
const formatted = 'Jan. 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformatted)).toBe(formatted);
|
||||
});
|
||||
|
||||
it('should format 3-letter abbreviated month correctly', () => {
|
||||
const unformatted = 'Jan 1, 2023, 10:00 AM';
|
||||
const formatted = 'Jan. 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformatted)).toBe(formatted);
|
||||
});
|
||||
|
||||
it('should format March, April, June, July correctly', () => {
|
||||
const unformattedMarch = 'Mar 1, 2023, 10:00 AM';
|
||||
const formattedMarch = 'March 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
|
||||
|
||||
const unformattedApril = 'Apr 1, 2023, 10:00 AM';
|
||||
const formattedApril = 'April 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedApril)).toBe(formattedApril);
|
||||
|
||||
const unformattedJune = 'Jun 1, 2023, 10:00 AM';
|
||||
const formattedJune = 'June 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
|
||||
|
||||
const unformattedJuly = 'Jul 1, 2023, 10:00 am';
|
||||
const formattedJuly = 'July 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedJuly)).toBe(formattedJuly);
|
||||
|
||||
const unformattedSept = 'Sep 1, 2023, 10:00 AM';
|
||||
const formattedSept = 'Sept. 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
|
||||
});
|
||||
|
||||
it('should format months with periods correctly', () => {
|
||||
const unformattedMarch = 'Mar. 1, 2023, 10:00 pm';
|
||||
const formattedMarch = 'March 1, 2023, 10:00 p.m.';
|
||||
expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
|
||||
|
||||
const unformattedApril = 'Apr. 1, 2023, 10:00 AM';
|
||||
const formattedApril = 'April 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedApril)).toBe(formattedApril);
|
||||
|
||||
const unformattedMay = 'May. 1, 2023, 10:00 am';
|
||||
const formattedMay = 'May 1, 2023, 10:00 a.m.';
|
||||
expect(prettifyDate(unformattedMay)).toBe(formattedMay);
|
||||
|
||||
const unformattedJune = 'Jun. 1, 2023, 10:00 PM';
|
||||
const formattedJune = 'June 1, 2023, 10:00 p.m.';
|
||||
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
|
||||
|
||||
const unformattedJuly = 'Jul. 1, 2023, 10:00 PM';
|
||||
const formattedJuly = 'July 1, 2023, 10:00 p.m.';
|
||||
expect(prettifyDate(unformattedJuly)).toBe(formattedJuly);
|
||||
|
||||
const unformattedSept = 'Sep. 1, 2023, 10:00 PM';
|
||||
const formattedSept = 'Sept. 1, 2023, 10:00 p.m.';
|
||||
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
|
||||
});
|
||||
|
||||
it('should format months on their own properly', () => {
|
||||
const unformattedMarch = 'Mar.';
|
||||
const formattedMarch = 'March';
|
||||
expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
|
||||
|
||||
const unformattedApril = 'Apr.';
|
||||
const formattedApril = 'April';
|
||||
expect(prettifyDate(unformattedApril)).toBe(formattedApril);
|
||||
|
||||
const unformattedMay = 'May.';
|
||||
const formattedMay = 'May';
|
||||
expect(prettifyDate(unformattedMay)).toBe(formattedMay);
|
||||
|
||||
const unformattedJune = 'JUN.';
|
||||
const formattedJune = 'June';
|
||||
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
|
||||
|
||||
const unformattedJuly = 'Jul.';
|
||||
const formattedJuly = 'July';
|
||||
expect(prettifyDate(unformattedJuly)).toBe(formattedJuly);
|
||||
|
||||
const unformattedSept = 'sep.';
|
||||
const formattedSept = 'Sept.';
|
||||
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
|
||||
});
|
||||
|
||||
it('should format months with year properly', () => {
|
||||
const unformattedMarch = 'MAR. 2025';
|
||||
const formattedMarch = 'March 2025';
|
||||
expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
|
||||
|
||||
const unformattedApril = 'apr. 2025';
|
||||
const formattedApril = 'April 2025';
|
||||
expect(prettifyDate(unformattedApril)).toBe(formattedApril);
|
||||
|
||||
const unformattedMay = 'May. 2025';
|
||||
const formattedMay = 'May 2025';
|
||||
expect(prettifyDate(unformattedMay)).toBe(formattedMay);
|
||||
|
||||
const unformattedJune = 'Jun. 2025';
|
||||
const formattedJune = 'June 2025';
|
||||
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
|
||||
|
||||
const unformattedJuly = 'Jul. 2025';
|
||||
const formattedJuly = 'July 2025';
|
||||
expect(prettifyDate(unformattedJuly)).toBe(formattedJuly);
|
||||
|
||||
const unformattedSept = 'Sep. 2025';
|
||||
const formattedSept = 'Sept. 2025';
|
||||
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
|
||||
});
|
||||
|
||||
it('should fix spacing between time and am/pm', () => {
|
||||
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);
|
||||
|
||||
const unformattedSept = 'sep. 1, 2023, 10:00PM';
|
||||
const formattedSept = 'Sept. 1, 2023, 10:00 p.m.';
|
||||
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
@ -13,3 +13,79 @@ export const getAuthorPageUrl = (author: string): string => {
|
|||
const authorSlug = slugify(author.trim(), { lower: true });
|
||||
return `https://www.reuters.com/authors/${authorSlug}/`;
|
||||
};
|
||||
|
||||
/** Formats a string containing a full or 3-letter abbreviated month, AM/PM, and am/pm to match the Reuters style.
|
||||
*
|
||||
* All months, full or abbreviated to 3 letters, are formatted to:
|
||||
* - Jan.
|
||||
* - Feb.
|
||||
* - March
|
||||
* - April]
|
||||
* - May
|
||||
* - June
|
||||
* - July
|
||||
* - Aug.
|
||||
* - Sept.
|
||||
* - Oct.
|
||||
* - Nov.
|
||||
* - Dec.
|
||||
*
|
||||
* AM and PM are formatted as lowercase.
|
||||
*
|
||||
*/
|
||||
export const prettifyDate = (input: string) => {
|
||||
// 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.',
|
||||
|
||||
// 3-letter abbreviations that need fixing
|
||||
jan: 'Jan.',
|
||||
feb: 'Feb.',
|
||||
mar: 'March',
|
||||
apr: 'April',
|
||||
jun: 'June',
|
||||
jul: 'July',
|
||||
sep: 'Sept.',
|
||||
};
|
||||
|
||||
// If the key in conversions is found in the input (case insensitive), replace it with the corresponding value
|
||||
const formatted = Object.keys(conversions).reduce((acc, key) => {
|
||||
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 (case insensitive)
|
||||
const 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
|
||||
const fixedPeriods = fixedAbbr.replace(/\.{2,}/g, '.');
|
||||
|
||||
// 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) => {
|
||||
const formattedDesignator =
|
||||
timeDesignator.toLowerCase() === 'am' ? 'a.m.' : 'p.m.';
|
||||
return `${digit} ${formattedDesignator}`;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue