Skip to content

Commit d756c05

Browse files
authored
Merge pull request #100 from github/flow
Type check with Flow
2 parents 30f3af8 + 721c7b4 commit d756c05

15 files changed

Lines changed: 128 additions & 94 deletions

.eslintrc.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
{
22
"extends": [
33
"plugin:github/browser",
4-
"plugin:github/es6"
4+
"plugin:github/es6",
5+
"plugin:github/flow"
56
],
67
"parser": "babel-eslint",
78
"overrides": [
89
{
910
"files": "test/**/*.js",
1011
"rules": {
12+
"flowtype/require-valid-file-annotation": "off",
1113
"github/unescaped-html-literal": "off"
1214
}
15+
},
16+
{
17+
"files": "test/**/*.js",
18+
"excludedFiles": "test/karma.config.js",
19+
"env": {
20+
"mocha": true
21+
},
22+
"globals": {
23+
"assert": true
24+
}
1325
}
1426
]
1527
}

.flowconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[ignore]
2+
3+
[include]
4+
5+
[libs]
6+
7+
[options]
8+
9+
[lints]

package-lock.json

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"license": "MIT",
77
"scripts": {
88
"clean": "rm -rf ./dist ./node_modules",
9-
"lint": "eslint .",
9+
"lint": "github-lint",
1010
"build": "rollup -c",
1111
"prepublishOnly": "npm run pretest",
1212
"pretest": "npm run lint && npm run build",
@@ -15,11 +15,11 @@
1515
"repository": "github/time-elements",
1616
"devDependencies": {
1717
"@babel/core": "^7.2.2",
18-
"@babel/plugin-proposal-export-default-from": "^7.2.0",
19-
"babel-preset-github": "^2.1.1",
18+
"babel-preset-github": "^2.1.2",
2019
"chai": "^4.2.0",
2120
"eslint": "^5.12.0",
2221
"eslint-plugin-github": "^1.9.0",
22+
"flow-bin": "^0.93.0",
2323
"karma": "^3.1.4",
2424
"karma-chai": "^0.1.0",
2525
"karma-chrome-launcher": "^2.2.0",
@@ -30,5 +30,7 @@
3030
"rollup-plugin-babel": "^4.2.0",
3131
"webcomponents.js": "^0.7.23"
3232
},
33-
"eslintIgnore": ["dist/"]
33+
"eslintIgnore": [
34+
"dist/"
35+
]
3436
}

prettier.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
/* @flow strict */
2+
13
module.exports = require('eslint-plugin-github/prettier.config')

rollup.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* @flow strict */
2+
13
import babel from 'rollup-plugin-babel'
24

35
const pkg = require('./package.json')
@@ -7,8 +9,7 @@ export default [
79
input: 'src/index.js',
810
plugins: [
911
babel({
10-
presets: ['github'],
11-
plugins: ['@babel/plugin-proposal-export-default-from']
12+
presets: ['github']
1213
})
1314
],
1415
output: {
@@ -21,8 +22,7 @@ export default [
2122
input: 'src/index.js',
2223
plugins: [
2324
babel({
24-
presets: ['github'],
25-
plugins: ['@babel/plugin-proposal-export-default-from']
25+
presets: ['github']
2626
})
2727
],
2828
output: {

src/extended-time-element.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
/* @flow strict */
2+
13
import {makeFormatter} from './utils'
24

35
export default class ExtendedTimeElement extends HTMLElement {
6+
_date: ?Date
7+
48
static get observedAttributes() {
59
return ['datetime', 'day', 'format', 'hour', 'minute', 'month', 'second', 'title', 'weekday', 'year']
610
}
711

812
// Internal: Refresh the time element's formatted date when an attribute changes.
913
//
1014
// Returns nothing.
11-
attributeChangedCallback(attrName, oldValue, newValue) {
15+
attributeChangedCallback(attrName: string, oldValue: string, newValue: string) {
1216
if (attrName === 'datetime') {
1317
const millis = Date.parse(newValue)
1418
this._date = isNaN(millis) ? null : new Date(millis)
@@ -30,26 +34,27 @@ export default class ExtendedTimeElement extends HTMLElement {
3034
// value takes precedence over this custom format.
3135
//
3236
// Returns a formatted time String.
33-
getFormattedTitle() {
34-
if (!this._date) {
35-
return
36-
}
37+
getFormattedTitle(): ?string {
38+
const date = this._date
39+
if (!date) return
3740

3841
const formatter = titleFormatter()
3942
if (formatter) {
40-
return formatter.format(this._date)
43+
return formatter.format(date)
4144
} else {
4245
try {
43-
return this._date.toLocaleString()
46+
return date.toLocaleString()
4447
} catch (e) {
4548
if (e instanceof RangeError) {
46-
return this._date.toString()
49+
return date.toString()
4750
} else {
4851
throw e
4952
}
5053
}
5154
}
5255
}
56+
57+
getFormattedDate(): ?string {}
5358
}
5459

5560
const titleFormatter = makeFormatter({

src/index.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
export LocalTimeElement from './local-time-element'
2-
export RelativeTimeElement from './relative-time-element'
3-
export TimeAgoElement from './time-ago-element'
4-
export TimeUntilElement from './time-until-element'
1+
/* @flow strict */
2+
3+
import LocalTimeElement from './local-time-element'
4+
import RelativeTimeElement from './relative-time-element'
5+
import TimeAgoElement from './time-ago-element'
6+
import TimeUntilElement from './time-until-element'
7+
8+
export {LocalTimeElement, RelativeTimeElement, TimeAgoElement, TimeUntilElement}

src/local-time-element.js

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
/* @flow strict */
2+
13
import {strftime, makeFormatter, isDayFirst} from './utils'
24
import ExtendedTimeElement from './extended-time-element'
35

46
const formatters = new WeakMap()
57

68
export default class LocalTimeElement extends ExtendedTimeElement {
7-
attributeChangedCallback(attrName, oldValue, newValue) {
9+
attributeChangedCallback(attrName: string, oldValue: string, newValue: string) {
810
if (attrName === 'hour' || attrName === 'minute' || attrName === 'second' || attrName === 'time-zone-name') {
911
formatters.delete(this)
1012
}
@@ -27,13 +29,12 @@ export default class LocalTimeElement extends ExtendedTimeElement {
2729
// second - "numeric", "2-digit"
2830
//
2931
// Returns a formatted time String.
30-
getFormattedDate() {
31-
if (!this._date) {
32-
return
33-
}
32+
getFormattedDate(): ?string {
33+
const d = this._date
34+
if (!d) return
3435

35-
const date = formatDate(this) || ''
36-
const time = formatTime(this) || ''
36+
const date = formatDate(this, d) || ''
37+
const time = formatTime(this, d) || ''
3738
return `${date} ${time}`.trim()
3839
}
3940
}
@@ -48,7 +49,7 @@ export default class LocalTimeElement extends ExtendedTimeElement {
4849
// el - The local-time element to format.
4950
//
5051
// Returns a date String or null if no date formats are provided.
51-
function formatDate(el) {
52+
function formatDate(el: Element, date: Date) {
5253
// map attribute values to strftime
5354
const props = {
5455
weekday: {
@@ -80,7 +81,7 @@ function formatDate(el) {
8081
format = format.replace(/(\s,)|(,\s$)/, '')
8182

8283
// squeeze spaces from final string
83-
return strftime(el._date, format)
84+
return strftime(date, format)
8485
.replace(/\s+/, ' ')
8586
.trim()
8687
}
@@ -91,21 +92,18 @@ function formatDate(el) {
9192
// el - The local-time element to format.
9293
//
9394
// Returns a time String or null if no time formats are provided.
94-
function formatTime(el) {
95-
// retrieve format settings from attributes
96-
const options = {
97-
hour: el.getAttribute('hour'),
98-
minute: el.getAttribute('minute'),
99-
second: el.getAttribute('second'),
100-
timeZoneName: el.getAttribute('time-zone-name')
101-
}
95+
function formatTime(el: Element, date: Date) {
96+
const options: Intl$DateTimeFormatOptions = {}
10297

103-
// Remove unset format attributes.
104-
for (const opt in options) {
105-
if (!options[opt]) {
106-
delete options[opt]
107-
}
108-
}
98+
// retrieve format settings from attributes
99+
const hour = el.getAttribute('hour')
100+
if (hour === 'numeric' || hour === '2-digit') options.hour = hour
101+
const minute = el.getAttribute('minute')
102+
if (minute === 'numeric' || minute === '2-digit') options.minute = minute
103+
const second = el.getAttribute('second')
104+
if (second === 'numeric' || second === '2-digit') options.second = second
105+
const tz = el.getAttribute('time-zone-name')
106+
if (tz === 'short' || tz === 'long') options.timeZoneName = tz
109107

110108
// No time format attributes provided.
111109
if (Object.keys(options).length === 0) {
@@ -121,11 +119,11 @@ function formatTime(el) {
121119
const formatter = factory()
122120
if (formatter) {
123121
// locale-aware formatting of 24 or 12 hour times
124-
return formatter.format(el._date)
122+
return formatter.format(date)
125123
} else {
126124
// fall back to strftime for non-Intl browsers
127125
const timef = options.second ? '%H:%M:%S' : '%H:%M'
128-
return strftime(el._date, timef)
126+
return strftime(date, timef)
129127
}
130128
}
131129

src/relative-time-element.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* @flow strict */
2+
13
import RelativeTime from './relative-time'
24
import ExtendedTimeElement from './extended-time-element'
35

@@ -45,7 +47,7 @@ function updateNowElements() {
4547
let time, i, len
4648
for (i = 0, len = nowElements.length; i < len; i++) {
4749
time = nowElements[i]
48-
time.textContent = time.getFormattedDate()
50+
time.textContent = time.getFormattedDate() || ''
4951
}
5052
}
5153

0 commit comments

Comments
 (0)