Przeglądaj źródła

defaultRangeSeparator. moment range formatting. tests

Adam Shaw 7 lat temu
rodzic
commit
3f196e7b4f

+ 18 - 10
plugins/moment/main.ts

@@ -36,9 +36,9 @@ fc.registerCmdFormatter('moment', function(cmdStr: string, arg: fc.VerboseFormat
     )
     )
     return formatRange(
     return formatRange(
       cmd,
       cmd,
-      startMom.format.bind(startMom),
-      endMom.format.bind(endMom),
-      arg.separator // TODO: test separator
+      createMomentFormatFunc(startMom),
+      createMomentFormatFunc(endMom),
+      arg.separator
     )
     )
   }
   }
 
 
@@ -50,6 +50,12 @@ fc.registerCmdFormatter('moment', function(cmdStr: string, arg: fc.VerboseFormat
   ).format(cmd.whole) // TODO: test for this
   ).format(cmd.whole) // TODO: test for this
 })
 })
 
 
+function createMomentFormatFunc(mom: moment.Moment) {
+  return function(cmdStr) {
+    return cmdStr ? mom.format(cmdStr) : '' // because calling with blank string results in ISO8601 :(
+  }
+}
+
 function convertToMoment(input: any, timeZone: string, timeZoneOffset: number | null, locale: string): moment.Moment {
 function convertToMoment(input: any, timeZone: string, timeZoneOffset: number | null, locale: string): moment.Moment {
   let mom: moment.Moment
   let mom: moment.Moment
 
 
@@ -81,20 +87,22 @@ function convertToMoment(input: any, timeZone: string, timeZoneOffset: number |
 
 
 interface CmdParts {
 interface CmdParts {
   head: string | null
   head: string | null
-  middle: string | null
+  middle: CmdParts | null
   tail: string | null
   tail: string | null
   whole: string
   whole: string
 }
 }
 
 
 function parseCmdStr(cmdStr: string): CmdParts {
 function parseCmdStr(cmdStr: string): CmdParts {
-  let parts = cmdStr.match(/^(.*?)\{(.*?)\}(.*)$/)
+  let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/) // TODO: lookbehinds for escape characters
 
 
   if (parts) {
   if (parts) {
+    let middle = parseCmdStr(parts[2])
+
     return {
     return {
       head: parts[1],
       head: parts[1],
-      middle: parts[2],
+      middle,
       tail: parts[3],
       tail: parts[3],
-      whole: parts[1] + parts[2] + parts[3]
+      whole: parts[1] + middle.whole + parts[3]
     }
     }
   } else {
   } else {
     return {
     return {
@@ -107,13 +115,13 @@ function parseCmdStr(cmdStr: string): CmdParts {
 }
 }
 
 
 function formatRange(cmd: CmdParts, formatStart: (cmdStr: string) => string, formatEnd: (cmdStr: string) => string, separator: string): string {
 function formatRange(cmd: CmdParts, formatStart: (cmdStr: string) => string, formatEnd: (cmdStr: string) => string, separator: string): string {
-  if (cmd.head) {
+  if (cmd.middle) {
     let startHead = formatStart(cmd.head)
     let startHead = formatStart(cmd.head)
-    let startMiddle = formatStart(cmd.middle)
+    let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator)
     let startTail = formatStart(cmd.tail)
     let startTail = formatStart(cmd.tail)
 
 
     let endHead = formatEnd(cmd.head)
     let endHead = formatEnd(cmd.head)
-    let endMiddle = formatEnd(cmd.middle)
+    let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator)
     let endTail = formatEnd(cmd.tail)
     let endTail = formatEnd(cmd.tail)
 
 
     if (startHead === endHead && startTail === endTail) {
     if (startHead === endHead && startTail === endTail) {

+ 5 - 2
src/Calendar.ts

@@ -776,7 +776,10 @@ export default class Calendar {
 
 
   formatDate(d: Date, formatter): string {
   formatDate(d: Date, formatter): string {
     const { dateEnv } = this
     const { dateEnv } = this
-    return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter))
+    return dateEnv.format(
+      dateEnv.createMarker(d),
+      createFormatter(formatter)
+    )
   }
   }
 
 
 
 
@@ -785,7 +788,7 @@ export default class Calendar {
     return dateEnv.formatRange(
     return dateEnv.formatRange(
       dateEnv.createMarker(d0),
       dateEnv.createMarker(d0),
       dateEnv.createMarker(d1),
       dateEnv.createMarker(d1),
-      createFormatter(formatter),
+      createFormatter(formatter, this.opt('defaultRangeSeparator')),
       { isEndExclusive }
       { isEndExclusive }
     )
     )
   }
   }

+ 1 - 1
src/api/EventApi.ts

@@ -167,7 +167,7 @@ export default class EventApi {
   formatRange(formatInput: FormatterInput) {
   formatRange(formatInput: FormatterInput) {
     let dateEnv = this.calendar.dateEnv
     let dateEnv = this.calendar.dateEnv
     let { instance } = this
     let { instance } = this
-    let formatter = createFormatter(formatInput)
+    let formatter = createFormatter(formatInput, this.calendar.opt('defaultRangeSeparator'))
 
 
     if (this.def.hasEnd) {
     if (this.def.hasEnd) {
       return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
       return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {

+ 2 - 1
src/component/renderers/EventRenderer.ts

@@ -43,7 +43,8 @@ export default class EventRenderer {
 
 
     this.eventTimeFormat = createFormatter(
     this.eventTimeFormat = createFormatter(
       this.opt('eventTimeFormat') ||
       this.opt('eventTimeFormat') ||
-      this.computeEventTimeFormat()
+      this.computeEventTimeFormat(),
+      this.opt('defaultRangeSeparator')
     )
     )
 
 
     displayEventTime = this.opt('displayEventTime')
     displayEventTime = this.opt('displayEventTime')

+ 1 - 2
src/datelib/formatting-native.ts

@@ -5,7 +5,6 @@ import { Locale } from './locale'
 import { DateFormatter, DateFormattingContext, ZonedMarker, formatTimeZoneOffset } from './formatting'
 import { DateFormatter, DateFormattingContext, ZonedMarker, formatTimeZoneOffset } from './formatting'
 
 
 
 
-const DEFAULT_SEPARATOR = ' - '
 const EXTENDED_SETTINGS_AND_SEVERITIES = {
 const EXTENDED_SETTINGS_AND_SEVERITIES = {
   week: 3,
   week: 3,
   separator: 0, // 0 = not applicable
   separator: 0, // 0 = not applicable
@@ -160,7 +159,7 @@ export class NativeFormatter implements DateFormatter {
     let partial1 = this.format(end, context, partialFormatSettings)
     let partial1 = this.format(end, context, partialFormatSettings)
 
 
     let insertion = findCommonInsertion(full0, partial0, full1, partial1)
     let insertion = findCommonInsertion(full0, partial0, full1, partial1)
-    let separator = this.extendedSettings.separator || DEFAULT_SEPARATOR
+    let separator = this.extendedSettings.separator || ''
 
 
     if (insertion) {
     if (insertion) {
       return insertion.before + partial0 + separator + partial1 + insertion.after
       return insertion.before + partial0 + separator + partial1 + insertion.after

+ 10 - 4
src/formatting-api.ts

@@ -1,7 +1,8 @@
 import { DateEnv, DateInput } from './datelib/env'
 import { DateEnv, DateInput } from './datelib/env'
 import { assignTo } from './util/object'
 import { assignTo } from './util/object'
 import { createFormatter } from './datelib/formatting'
 import { createFormatter } from './datelib/formatting'
-import { getLocale } from './datelib/locale';
+import { getLocale } from './datelib/locale'
+import { globalDefaults } from './options'
 
 
 export function formatDate(dateInput: DateInput, settings = {}) {
 export function formatDate(dateInput: DateInput, settings = {}) {
   let dateEnv = buildDateEnv(settings)
   let dateEnv = buildDateEnv(settings)
@@ -17,9 +18,14 @@ export function formatDate(dateInput: DateInput, settings = {}) {
   })
   })
 }
 }
 
 
-export function formatRange(startInput: DateInput, endInput: DateInput, settings = {}) {
-  let dateEnv = buildDateEnv(settings)
-  let formatter = createFormatter(settings)
+export function formatRange(
+  startInput: DateInput,
+  endInput: DateInput,
+  settings, // mixture of env and formatter settings
+  defaultSeparator: string = globalDefaults.defaultRangeSeparator
+) {
+  let dateEnv = buildDateEnv(typeof settings === 'object' && settings ? settings : {}) // pass in if non-null object
+  let formatter = createFormatter(settings, defaultSeparator)
   let startMeta = dateEnv.createMarkerMeta(startInput)
   let startMeta = dateEnv.createMarkerMeta(startInput)
   let endMeta = dateEnv.createMarkerMeta(endInput)
   let endMeta = dateEnv.createMarkerMeta(endInput)
 
 

+ 2 - 2
src/options.ts

@@ -3,7 +3,9 @@ import { mergeProps } from './util/object'
 
 
 export const globalDefaults = {
 export const globalDefaults = {
 
 
+  defaultRangeSeparator: ' - ',
   titleRangeSeparator: ' \u2013 ', // en dash
   titleRangeSeparator: ' \u2013 ', // en dash
+  //cmdFormatter: null,
 
 
   defaultTimedEventDuration: '02:00:00',
   defaultTimedEventDuration: '02:00:00',
   defaultAllDayEventDuration: { day: 1 },
   defaultAllDayEventDuration: { day: 1 },
@@ -40,8 +42,6 @@ export const globalDefaults = {
 
 
   timeZone: 'UTC', // TODO: throw error if given falsy value?
   timeZone: 'UTC', // TODO: throw error if given falsy value?
 
 
-  //cmdFormatter: null,
-
   // allDayDefault: undefined,
   // allDayDefault: undefined,
 
 
   // locale
   // locale

+ 2 - 1
tests/automated/datelib/main.js

@@ -210,7 +210,8 @@ describe('datelib', function() {
       var formatter = createFormatter({
       var formatter = createFormatter({
         day: 'numeric',
         day: 'numeric',
         month: 'long',
         month: 'long',
-        year: 'numeric'
+        year: 'numeric',
+        separator: ' - '
       })
       })
 
 
       it('works with different days of same month', function() {
       it('works with different days of same month', function() {

+ 53 - 1
tests/automated/datelib/moment.js

@@ -64,7 +64,7 @@ describe('moment plugin', function() {
 
 
   })
   })
 
 
-  describe('formatting', function() {
+  describe('date formatting', function() {
 
 
     it('produces event time text', function() {
     it('produces event time text', function() {
       initCalendar({
       initCalendar({
@@ -80,6 +80,58 @@ describe('moment plugin', function() {
       expect(getEventElTimeText(getSingleEl())).toBe('13:30:20!')
       expect(getEventElTimeText(getSingleEl())).toBe('13:30:20!')
     })
     })
 
 
+  })
+
+  describe('range formatting', function() {
+
+    it('renders with same month', function() {
+      let calendar = new FullCalendar.Calendar(document.createElement('div'), {
+        cmdFormatter: 'moment'
+      })
+      let s
+
+      s = calendar.formatRange('2018-09-03', '2018-09-05', 'MMMM {D}, YYYY [nice]')
+      expect(s).toEqual('September 3 - 5, 2018 nice')
+
+      s = calendar.formatRange('2018-09-03', '2018-09-05', '{D} MMMM, YYYY [nice]')
+      expect(s).toEqual('3 - 5 September, 2018 nice')
+    })
+
+    it('renders with same year but different month', function() {
+      let calendar = new FullCalendar.Calendar(document.createElement('div'), {
+        cmdFormatter: 'moment'
+      })
+      let s
+
+      s = calendar.formatRange('2018-09-03', '2018-10-05', '{MMMM {D}}, YYYY [nice]')
+      expect(s).toEqual('September 3 - October 5, 2018 nice')
+
+      s = calendar.formatRange('2018-09-03', '2018-10-05', '{{D} MMMM}, YYYY [nice]')
+      expect(s).toEqual('3 September - 5 October, 2018 nice')
+    })
+
+    it('renders with different years', function() {
+      let calendar = new FullCalendar.Calendar(document.createElement('div'), {
+        cmdFormatter: 'moment'
+      })
+      let s
+
+      s = calendar.formatRange('2018-09-03', '2019-10-05', '{MMMM {D}}, YYYY [nice]')
+      expect(s).toEqual('September 3, 2018 nice - October 5, 2019 nice')
+
+      s = calendar.formatRange('2018-09-03', '2019-10-05', '{{D} MMMM}, YYYY [nice]')
+      expect(s).toEqual('3 September, 2018 nice - 5 October, 2019 nice')
+    })
+
+    it('inherits defaultRangeSeparator', function() {
+      let calendar = new FullCalendar.Calendar(document.createElement('div'), {
+        cmdFormatter: 'moment',
+        defaultRangeSeparator: ' to '
+      })
+      let s = calendar.formatRange('2018-09-03', '2018-09-05', 'MMMM D, YYYY [nice]')
+      expect(s).toEqual('September 3, 2018 nice to September 5, 2018 nice')
+    })
+
     it('produces title with titleRangeSeparator', function() {
     it('produces title with titleRangeSeparator', function() {
       initCalendar({ // need to render the calendar to get view.title :(
       initCalendar({ // need to render the calendar to get view.title :(
         defaultView: 'basicWeek',
         defaultView: 'basicWeek',