mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
feat: date filters from Jekyll
This commit is contained in:
@@ -36,6 +36,10 @@ filters:
|
|||||||
compact: compact.html
|
compact: compact.html
|
||||||
concat: concat.html
|
concat: concat.html
|
||||||
date: date.html
|
date: date.html
|
||||||
|
date_to_long_string: date_to_long_string.html
|
||||||
|
date_to_rfc822: date_to_rfc822.html
|
||||||
|
date_to_string: date_to_string.html
|
||||||
|
date_to_xmlschema: date_to_xmlschema.html
|
||||||
default: default.html
|
default: default.html
|
||||||
divided_by: divided_by.html
|
divided_by: divided_by.html
|
||||||
downcase: downcase.html
|
downcase: downcase.html
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: date_to_long_string
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Convert a date to long format. Same with Jekyll `date_to_long_string` filter.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_long_string }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
07 November 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_long_string: "ordinal" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
7th November 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that JavaScript `Date` has not timezone information, see [date][date] filter for details.
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: date_to_rfc822
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Convert a Date into the RFC-822 format used for RSS feeds, same as Jekyll filter `date_to_rfc822`.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_rfc822 }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
Mon, 07 Nov 2008 13:07:54 -0800
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that JavaScript `Date` has not timezone information, see [date][date] filter for details.
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: date_to_string
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Convert a date to short format. Same with Jekyll `date_to_string` filter.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_string }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
07 Nov 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_string: "ordinal", "US" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
Nov 7th, 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that JavaScript `Date` has not timezone information, see [date][date] filter for details.
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: date_to_xmlschema
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Convert a Date into XML Schema (ISO 8601) format, same as Jekyll filter `date_to_xmlschema`.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_xmlschema }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
2008-11-07T13:07:54-08:00
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that JavaScript `Date` has not timezone information, see [date][date] filter for details.
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -13,7 +13,7 @@ Math | plus, minus, modulo, times, floor, ceil, round, divided_by, abs, at_least
|
|||||||
String | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last,remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
String | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last,remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
||||||
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
||||||
Array | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
Array | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
||||||
Date | date
|
Date | date, date_to_xmlschema, date_to_rfc822, date_to_string, date_to_long_string
|
||||||
Misc | default, json, jsonify, inspect, raw, to_integer
|
Misc | default, json, jsonify, inspect, raw, to_integer
|
||||||
|
|
||||||
[shopify/liquid]: https://github.com/Shopify/liquid
|
[shopify/liquid]: https://github.com/Shopify/liquid
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
title: date_to_long_string
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
把日期转换为长格式(只支持 US/UK 两种),与 Jekyll 的 `date_to_long_string` 过滤器一样。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_long_string }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
07 November 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_long_string: "ordinal" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
7th November 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
注意 JavaScript `Date` 没有时区信息,详情请参考 [date][date] 过滤器。
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: date_to_rfc822
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
把日期转换为 RFC-822 格式用于 RSS feed,与 Jekyll 的 `date_to_rfc822` 过滤器一样。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_rfc822 }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输入
|
||||||
|
```text
|
||||||
|
Mon, 07 Nov 2008 13:07:54 -0800
|
||||||
|
```
|
||||||
|
|
||||||
|
注意 JavaScript `Date` 没有时区信息,详情请参考 [date][date] 过滤器。
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: date_to_string
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
把日期转换为短格式(只支持 US/UK 两种),与 Jekyll 的 `date_to_string` 过滤器一样。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_string }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
07 Nov 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_string: "ordinal", "US" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
Nov 7th, 2008
|
||||||
|
```
|
||||||
|
|
||||||
|
注意 JavaScript `Date` 没有时区信息,详情请参考 [date][date] 过滤器。
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: date_to_xmlschema
|
||||||
|
---
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
把日期转换为 XML Schema (ISO 8601) 格式,与 Jekyll 的 `date_to_xmlschema` 过滤器一样。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ site.time | date_to_xmlschema }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
2008-11-07T13:07:54-08:00
|
||||||
|
```
|
||||||
|
|
||||||
|
注意 JavaScript `Date` 没有时区信息,详情请参考 [date][date] 过滤器。
|
||||||
|
|
||||||
|
[date]: ./date.html
|
||||||
@@ -13,7 +13,7 @@ LiquidJS 共支持 40+ 个过滤器,可以分为如下几类:
|
|||||||
字符串 | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last, remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
字符串 | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last, remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
||||||
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
||||||
数组 | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
数组 | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
||||||
日期 | date
|
日期 | date, date_to_xmlschema, date_to_rfc822, date_to_string, date_to_long_string
|
||||||
其他 | default, json, jsonify, inspect, raw, to_integer
|
其他 | default, json, jsonify, inspect, raw, to_integer
|
||||||
|
|
||||||
[shopify/liquid]: https://github.com/Shopify/liquid
|
[shopify/liquid]: https://github.com/Shopify/liquid
|
||||||
|
|||||||
+39
-6
@@ -1,13 +1,46 @@
|
|||||||
import { toValue, stringify, isString, isNumber, TimezoneDate, LiquidDate, strftime, isNil } from '../util'
|
import { toValue, stringify, isString, isNumber, TimezoneDate, LiquidDate, strftime, isNil } from '../util'
|
||||||
import { FilterImpl } from '../template'
|
import { FilterImpl } from '../template'
|
||||||
|
import { LiquidOptions } from '../liquid-options'
|
||||||
|
|
||||||
export function date (this: FilterImpl, v: string | Date, format?: string, timezoneOffset?: number | string) {
|
export function date (this: FilterImpl, v: string | Date, format?: string, timezoneOffset?: number | string) {
|
||||||
const opts = this.context.opts
|
const date = parseDate(v, this.context.opts, timezoneOffset)
|
||||||
|
if (!date) return v
|
||||||
|
format = toValue(format)
|
||||||
|
format = isNil(format) ? this.context.opts.dateFormat : stringify(format)
|
||||||
|
return strftime(date, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date_to_xmlschema (this: FilterImpl, v: string | Date) {
|
||||||
|
return date.call(this, v, '%Y-%m-%dT%H:%M:%S%:z')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date_to_rfc822 (this: FilterImpl, v: string | Date) {
|
||||||
|
return date.call(this, v, '%a, %d %b %Y %H:%M:%S %z')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date_to_string (this: FilterImpl, v: string | Date, type?: string, style?: string) {
|
||||||
|
return stringify_date.call(this, v, '%b', type, style)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function date_to_long_string (this: FilterImpl, v: string | Date, type?: string, style?: string) {
|
||||||
|
return stringify_date.call(this, v, '%B', type, style)
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringify_date (this: FilterImpl, v: string | Date, month_type: string, type?: string, style?: string) {
|
||||||
|
const date = parseDate(v, this.context.opts)
|
||||||
|
if (!date) return v
|
||||||
|
if (type === 'ordinal') {
|
||||||
|
const d = date.getDate()
|
||||||
|
return style === 'US'
|
||||||
|
? strftime(date, `${month_type} ${d}%q, %Y`)
|
||||||
|
: strftime(date, `${d}%q ${month_type} %Y`)
|
||||||
|
}
|
||||||
|
return strftime(date, `%d ${month_type} %Y`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDate (v: string | Date, opts: LiquidOptions, timezoneOffset?: number | string): LiquidDate | undefined {
|
||||||
let date: LiquidDate
|
let date: LiquidDate
|
||||||
v = toValue(v)
|
v = toValue(v)
|
||||||
format = toValue(format)
|
|
||||||
if (isNil(format)) format = opts.dateFormat
|
|
||||||
else format = stringify(format)
|
|
||||||
if (v === 'now' || v === 'today') {
|
if (v === 'now' || v === 'today') {
|
||||||
date = new Date()
|
date = new Date()
|
||||||
} else if (isNumber(v)) {
|
} else if (isNumber(v)) {
|
||||||
@@ -23,13 +56,13 @@ export function date (this: FilterImpl, v: string | Date, format?: string, timez
|
|||||||
} else {
|
} else {
|
||||||
date = v
|
date = v
|
||||||
}
|
}
|
||||||
if (!isValidDate(date)) return v
|
if (!isValidDate(date)) return
|
||||||
if (timezoneOffset !== undefined) {
|
if (timezoneOffset !== undefined) {
|
||||||
date = new TimezoneDate(date, timezoneOffset)
|
date = new TimezoneDate(date, timezoneOffset)
|
||||||
} else if (!(date instanceof TimezoneDate) && opts.timezoneOffset !== undefined) {
|
} else if (!(date instanceof TimezoneDate) && opts.timezoneOffset !== undefined) {
|
||||||
date = new TimezoneDate(date, opts.timezoneOffset)
|
date = new TimezoneDate(date, opts.timezoneOffset)
|
||||||
}
|
}
|
||||||
return strftime(date, format)
|
return date
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidDate (date: any): date is Date {
|
function isValidDate (date: any): date is Date {
|
||||||
|
|||||||
+8
-23
@@ -45,31 +45,16 @@ function isLeapYear (d: LiquidDate) {
|
|||||||
const year = d.getFullYear()
|
const year = d.getFullYear()
|
||||||
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
|
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
|
||||||
}
|
}
|
||||||
function getSuffix (d: LiquidDate) {
|
function ordinal (d: LiquidDate) {
|
||||||
const date = d.getDate()
|
const date = d.getDate()
|
||||||
|
if ([11, 12, 13].includes(date)) return 'th'
|
||||||
|
|
||||||
let suffix = 'th'
|
switch (date % 10) {
|
||||||
|
case 1: return 'st'
|
||||||
switch (date) {
|
case 2: return 'nd'
|
||||||
case 11:
|
case 3: return 'rd'
|
||||||
case 12:
|
default: return 'th'
|
||||||
case 13:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
switch (date % 10) {
|
|
||||||
case 1:
|
|
||||||
suffix = 'st'
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
suffix = 'nd'
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
suffix = 'rd'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return suffix
|
|
||||||
}
|
}
|
||||||
function century (d: LiquidDate) {
|
function century (d: LiquidDate) {
|
||||||
return parseInt(d.getFullYear().toString().substring(0, 2), 10)
|
return parseInt(d.getFullYear().toString().substring(0, 2), 10)
|
||||||
@@ -138,7 +123,7 @@ const formatCodes = {
|
|||||||
},
|
},
|
||||||
p: (d: LiquidDate) => (d.getHours() < 12 ? 'AM' : 'PM'),
|
p: (d: LiquidDate) => (d.getHours() < 12 ? 'AM' : 'PM'),
|
||||||
P: (d: LiquidDate) => (d.getHours() < 12 ? 'am' : 'pm'),
|
P: (d: LiquidDate) => (d.getHours() < 12 ? 'am' : 'pm'),
|
||||||
q: (d: LiquidDate) => getSuffix(d),
|
q: (d: LiquidDate) => ordinal(d),
|
||||||
s: (d: LiquidDate) => Math.round(d.getTime() / 1000),
|
s: (d: LiquidDate) => Math.round(d.getTime() / 1000),
|
||||||
S: (d: LiquidDate) => d.getSeconds(),
|
S: (d: LiquidDate) => d.getSeconds(),
|
||||||
u: (d: LiquidDate) => d.getDay() || 7,
|
u: (d: LiquidDate) => d.getDay() || 7,
|
||||||
|
|||||||
@@ -146,3 +146,54 @@ describe('filters/date', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('filters/date_to_xmlschema', function () {
|
||||||
|
const liquid = new Liquid()
|
||||||
|
it('should support literal date', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "1990-10-15T23:00:00" | date_to_xmlschema }}')
|
||||||
|
expect(output).toMatch(/^1990-10-15T23:00:00[+-]\d\d:\d\d$/)
|
||||||
|
})
|
||||||
|
it('should timezoned date', function () {
|
||||||
|
const liquid = new Liquid({ preserveTimezones: true })
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_xmlschema }}')
|
||||||
|
expect(output).toEqual('2008-11-07T13:07:54-08:00')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('filters/date_to_rfc822', function () {
|
||||||
|
const liquid = new Liquid()
|
||||||
|
it('should support literal date', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "1990-10-15T23:00:00" | date_to_rfc822 }}')
|
||||||
|
expect(output).toMatch(/^Mon, 15 Oct 1990 23:00:00 [+-]\d{4}$/)
|
||||||
|
})
|
||||||
|
it('should timezoned date', function () {
|
||||||
|
const liquid = new Liquid({ preserveTimezones: true })
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_rfc822 }}')
|
||||||
|
expect(output).toEqual('Fri, 07 Nov 2008 13:07:54 -0800')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('filters/date_to_string', function () {
|
||||||
|
const liquid = new Liquid({ preserveTimezones: true })
|
||||||
|
it('should default to non-ordinal, UK', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_string }}')
|
||||||
|
expect(output).toEqual('07 Nov 2008')
|
||||||
|
})
|
||||||
|
it('should support ordinal, US', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_string: "ordinal", "US" }}')
|
||||||
|
expect(output).toEqual('Nov 7th, 2008')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('filters/date_to_long_string', function () {
|
||||||
|
const liquid = new Liquid({ preserveTimezones: true })
|
||||||
|
it('should default to non-ordinal, UK', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_long_string }}')
|
||||||
|
expect(output).toEqual('07 November 2008')
|
||||||
|
})
|
||||||
|
it('should support ordinal, US', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_long_string: "ordinal", "US" }}')
|
||||||
|
expect(output).toEqual('November 7th, 2008')
|
||||||
|
})
|
||||||
|
it('should support ordinal, UK', function () {
|
||||||
|
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_long_string: "ordinal" }}')
|
||||||
|
expect(output).toEqual('7th November 2008')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user