-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
date: Add types #29789
date: Add types #29789
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,50 @@ import 'moment-timezone/moment-timezone'; | |
import 'moment-timezone/moment-timezone-utils'; | ||
|
||
/** @typedef {import('moment').Moment} Moment */ | ||
/** @typedef {import('moment').LocaleSpecification} MomentLocaleSpecification */ | ||
|
||
/** | ||
* @typedef MeridiemConfig | ||
* @property {string} am Lowercase AM. | ||
* @property {string} AM Uppercase AM. | ||
* @property {string} pm Lowercase PM. | ||
* @property {string} PM Uppercase PM. | ||
*/ | ||
|
||
/** | ||
* @typedef FormatsConfig | ||
* @property {string} time Time format. | ||
* @property {string} date Date format. | ||
* @property {string} datetime Datetime format. | ||
* @property {string} datetimeAbbreviated Abbreviated datetime format. | ||
*/ | ||
|
||
/** | ||
* @typedef TimezoneConfig | ||
* @property {string} offset Offset setting. | ||
* @property {string} string The timezone as a string (e.g., `'America/Los_Angeles'`). | ||
* @property {string} abbr Abbreviation for the timezone. | ||
*/ | ||
|
||
/* eslint-disable jsdoc/valid-types */ | ||
/** | ||
* @typedef L10nSettings | ||
* @property {string} locale Moment locale. | ||
* @property {MomentLocaleSpecification['months']} months Locale months. | ||
* @property {MomentLocaleSpecification['monthsShort']} monthsShort Locale months short. | ||
* @property {MomentLocaleSpecification['weekdays']} weekdays Locale weekdays. | ||
* @property {MomentLocaleSpecification['weekdaysShort']} weekdaysShort Locale weekdays short. | ||
* @property {MeridiemConfig} meridiem Meridiem config. | ||
* @property {MomentLocaleSpecification['relativeTime']} relative Relative time config. | ||
*/ | ||
/* eslint-enable jsdoc/valid-types */ | ||
|
||
/** | ||
* @typedef DateSettings | ||
* @property {L10nSettings} l10n Localization settings. | ||
* @property {FormatsConfig} formats Date/time formats config. | ||
* @property {TimezoneConfig} timezone Timezone settings. | ||
*/ | ||
|
||
const WP_ZONE = 'WP'; | ||
|
||
|
@@ -15,6 +59,7 @@ const VALID_UTC_OFFSET = /^[+-][0-1][0-9](:?[0-9][0-9])?$/; | |
|
||
// Changes made here will likely need to be made in `lib/client-assets.php` as | ||
// well because it uses the `setSettings()` function to change these settings. | ||
/** @type {DateSettings} */ | ||
let settings = { | ||
l10n: { | ||
locale: 'en', | ||
|
@@ -86,7 +131,7 @@ let settings = { | |
/** | ||
* Adds a locale to moment, using the format supplied by `wp_localize_script()`. | ||
* | ||
* @param {Object} dateSettings Settings, including locale data. | ||
* @param {DateSettings} dateSettings Settings, including locale data. | ||
*/ | ||
export function setSettings( dateSettings ) { | ||
settings = dateSettings; | ||
|
@@ -112,10 +157,13 @@ export function setSettings( dateSettings ) { | |
}, | ||
longDateFormat: { | ||
LT: dateSettings.formats.time, | ||
// @ts-ignore Forcing this to `null` | ||
LTS: null, | ||
// @ts-ignore Forcing this to `null` | ||
L: null, | ||
LL: dateSettings.formats.date, | ||
LLL: dateSettings.formats.datetime, | ||
// @ts-ignore Forcing this to `null` | ||
LLLL: null, | ||
}, | ||
// From human_time_diff? | ||
|
@@ -177,8 +225,6 @@ const HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS; | |
* | ||
* This should only be used through {@link wp.date.format}, not | ||
* directly. | ||
* | ||
* @type {Object} | ||
*/ | ||
const formatMap = { | ||
// Day | ||
|
@@ -212,7 +258,7 @@ const formatMap = { | |
*/ | ||
z( momentDate ) { | ||
// DDD - 1 | ||
return '' + parseInt( momentDate.format( 'DDD' ), 10 ) - 1; | ||
return ( parseInt( momentDate.format( 'DDD' ), 10 ) - 1 ).toString(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
}, | ||
|
||
// Week | ||
|
@@ -228,7 +274,7 @@ const formatMap = { | |
* | ||
* @param {Moment} momentDate Moment instance. | ||
* | ||
* @return {string} Formatted date. | ||
* @return {number} Formatted date. | ||
*/ | ||
t( momentDate ) { | ||
return momentDate.daysInMonth(); | ||
|
@@ -257,18 +303,20 @@ const formatMap = { | |
* | ||
* @param {Moment} momentDate Moment instance. | ||
* | ||
* @return {string} Formatted date. | ||
* @return {number} Formatted date. | ||
*/ | ||
B( momentDate ) { | ||
const timezoned = momentLib( momentDate ).utcOffset( 60 ); | ||
const seconds = parseInt( timezoned.format( 's' ), 10 ), | ||
minutes = parseInt( timezoned.format( 'm' ), 10 ), | ||
hours = parseInt( timezoned.format( 'H' ), 10 ); | ||
return parseInt( | ||
( seconds + | ||
minutes * MINUTE_IN_SECONDS + | ||
hours * HOUR_IN_SECONDS ) / | ||
86.4, | ||
( | ||
( seconds + | ||
minutes * MINUTE_IN_SECONDS + | ||
hours * HOUR_IN_SECONDS ) / | ||
86.4 | ||
).toString(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks safe, |
||
10 | ||
); | ||
}, | ||
|
@@ -300,13 +348,16 @@ const formatMap = { | |
* | ||
* @param {Moment} momentDate Moment instance. | ||
* | ||
* @return {string} Formatted date. | ||
* @return {number} Formatted date. | ||
*/ | ||
Z( momentDate ) { | ||
// Timezone offset in seconds. | ||
const offset = momentDate.format( 'Z' ); | ||
const sign = offset[ 0 ] === '-' ? -1 : 1; | ||
const parts = offset.substring( 1 ).split( ':' ); | ||
const parts = offset | ||
.substring( 1 ) | ||
.split( ':' ) | ||
.map( ( n ) => parseInt( n, 10 ) ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The explicit conversion looks much better than the one we were implicitly doing with multiplication and addition below 👍 |
||
return ( | ||
sign * | ||
( parts[ 0 ] * HOUR_IN_MINUTES + parts[ 1 ] ) * | ||
|
@@ -324,14 +375,14 @@ const formatMap = { | |
* | ||
* @param {string} dateFormat PHP-style formatting string. | ||
* See php.net/date. | ||
* @param {Date|string|Moment|null} dateValue Date object or string, | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, | ||
* parsable by moment.js. | ||
* | ||
* @return {string} Formatted date. | ||
*/ | ||
export function format( dateFormat, dateValue = new Date() ) { | ||
let i, char; | ||
let newFormat = []; | ||
const newFormat = []; | ||
const momentDate = momentLib( dateValue ); | ||
for ( i = 0; i < dateFormat.length; i++ ) { | ||
char = dateFormat[ i ]; | ||
|
@@ -343,31 +394,32 @@ export function format( dateFormat, dateValue = new Date() ) { | |
continue; | ||
} | ||
if ( char in formatMap ) { | ||
if ( typeof formatMap[ char ] !== 'string' ) { | ||
const formatter = | ||
formatMap[ /** @type {keyof formatMap} */ ( char ) ]; | ||
if ( typeof formatter !== 'string' ) { | ||
// If the format is a function, call it. | ||
newFormat.push( '[' + formatMap[ char ]( momentDate ) + ']' ); | ||
newFormat.push( '[' + formatter( momentDate ) + ']' ); | ||
} else { | ||
// Otherwise, add as a formatting string. | ||
newFormat.push( formatMap[ char ] ); | ||
newFormat.push( formatter ); | ||
} | ||
} else { | ||
newFormat.push( '[' + char + ']' ); | ||
} | ||
} | ||
// Join with [] between to separate characters, and replace | ||
// unneeded separators with static text. | ||
newFormat = newFormat.join( '[]' ); | ||
return momentDate.format( newFormat ); | ||
return momentDate.format( newFormat.join( '[]' ) ); | ||
} | ||
|
||
/** | ||
* Formats a date (like `date()` in PHP). | ||
* | ||
* @param {string} dateFormat PHP-style formatting string. | ||
* See php.net/date. | ||
* @param {Date|string|Moment|null} dateValue Date object or string, parsable | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, parsable | ||
* by moment.js. | ||
* @param {string|number|null} timezone Timezone to output result in or a | ||
* @param {string | undefined} timezone Timezone to output result in or a | ||
* UTC offset. Defaults to timezone from | ||
* site. | ||
* | ||
|
@@ -386,7 +438,7 @@ export function date( dateFormat, dateValue = new Date(), timezone ) { | |
* | ||
* @param {string} dateFormat PHP-style formatting string. | ||
* See php.net/date. | ||
* @param {Date|string|Moment|null} dateValue Date object or string, | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, | ||
* parsable by moment.js. | ||
* | ||
* @return {string} Formatted date in English. | ||
|
@@ -404,9 +456,9 @@ export function gmdate( dateFormat, dateValue = new Date() ) { | |
* | ||
* @param {string} dateFormat PHP-style formatting string. | ||
* See php.net/date. | ||
* @param {Date|string|Moment|null} dateValue Date object or string, parsable by | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by | ||
* moment.js. | ||
* @param {string|number|boolean|null} timezone Timezone to output result in or a | ||
* @param {string | boolean | undefined} timezone Timezone to output result in or a | ||
* UTC offset. Defaults to timezone from | ||
* site. Notice: `boolean` is effectively | ||
* deprecated, but still supported for | ||
|
@@ -437,7 +489,7 @@ export function dateI18n( dateFormat, dateValue = new Date(), timezone ) { | |
* | ||
* @param {string} dateFormat PHP-style formatting string. | ||
* See php.net/date. | ||
* @param {Date|string|Moment|null} dateValue Date object or string, | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, | ||
* parsable by moment.js. | ||
* | ||
* @return {string} Formatted date. | ||
|
@@ -480,9 +532,9 @@ export function getDate( dateString ) { | |
/** | ||
* Creates a moment instance using the given timezone or, if none is provided, using global settings. | ||
* | ||
* @param {Date|string|Moment|null} dateValue Date object or string, parsable | ||
* @param {Moment | Date | string | undefined} dateValue Date object or string, parsable | ||
* by moment.js. | ||
* @param {string|number|null} timezone Timezone to output result in or a | ||
* @param {string | undefined} timezone Timezone to output result in or a | ||
* UTC offset. Defaults to timezone from | ||
* site. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"declarationDir": "build-types", | ||
"noUnusedParameters": false | ||
}, | ||
"include": [ "src/**/*" ] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a bunch more locale specification properties available. Should we include more as available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only included the ones that are actually used in the
settings
object and in thesetSettings
function. Were the specific other ones you think we should include for some reason even though they're not used?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's a good start 👍 The only problem would be if someone uses some of the other ones and gets TS errors. Those could be added incrementally, though - this isn't something that should be blocking this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh hmm that's interesting. I guess someone could be adding extraneous properties? But then shouldn't they indeed get an error considering those properties aren't supported by the code? Or should we extend this as a
Record<string, any>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the thing is that they're supported by Moment, so practically they're also supported by the code. The typed ones we're adding here are only the default settings, right?
Anyway, we could make this a
Record
, but I believe would be much more precise if we just borrow the rest of theLocaleSpecification
interface.I'll leave it to you to decide the level of precision you'd like to achieve with this first PR - I'm fine with what we have as a start already 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, if you check out the
setSettings
function I only added the properties we actually access off thel10n
object.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha 👍
Well, I don't see a good reason to add more in that case.