mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-14 20:00:39 -07:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
050f161794 | ||
|
|
2634f9de7b | ||
|
|
f9a1316d16 |
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'latest'
|
||||
node-version: '20'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Build
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'latest'
|
||||
node-version: '22'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Test
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'latest'
|
||||
node-version: '20'
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'latest'
|
||||
node-version: '20'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'latest'
|
||||
node-version: '20'
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -24,7 +24,12 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npx semantic-release
|
||||
run: |
|
||||
if [ ${{ github.ref == 'refs/heads/master' }} ]; then
|
||||
npx semantic-release
|
||||
else
|
||||
npx semantic-release --dry-run
|
||||
fi
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
|
||||
@@ -7,10 +7,20 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
timezone: [Etc/GMT, Asia/Shanghai, America/New_York]
|
||||
node-version: [latest]
|
||||
node-version: [22]
|
||||
include:
|
||||
- os: macos-latest
|
||||
timezone: America/New_York
|
||||
node-versoin: 22
|
||||
- os: ubuntu-latest
|
||||
node-version: lts/*
|
||||
timezone: Etc/GMT
|
||||
node-version: 20
|
||||
- os: ubuntu-latest
|
||||
timezone: Asia/Shanghai
|
||||
node-version: 18
|
||||
- os: ubuntu-latest
|
||||
timezone: Asia/Shanghai
|
||||
node-version: 16
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -29,7 +39,7 @@ jobs:
|
||||
name: dist-${{ matrix.os }}
|
||||
path: dist
|
||||
- name: Run Test
|
||||
run: TZ=${{ matrix.timezone || 'Etc/GMT' }} npm test
|
||||
run: TZ=${{ matrix.timezone }} npm test
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
@@ -47,7 +57,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: latest
|
||||
node-version: 22
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
const gitPlugin = [
|
||||
'@semantic-release/git',
|
||||
{
|
||||
assets: ['package.json', 'package-lock.json', 'CHANGELOG.md'],
|
||||
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
|
||||
}
|
||||
]
|
||||
|
||||
const githubPlugin = [
|
||||
'@semantic-release/github',
|
||||
{
|
||||
assets: [
|
||||
{ path: 'dist/*.umd.js', label: 'liquid.js' },
|
||||
{ path: 'dist/*.min.js', label: 'liquid.min.js' },
|
||||
{ path: 'dist/*.min.js.map', label: 'liquid.min.js.map' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const basePlugins = [
|
||||
'@semantic-release/commit-analyzer',
|
||||
'@semantic-release/release-notes-generator',
|
||||
'@semantic-release/changelog',
|
||||
'@semantic-release/npm'
|
||||
]
|
||||
|
||||
// next is branch-protected (PR-only); skip @semantic-release/git there and publish to npm only.
|
||||
const onMaster = process.env.GITHUB_REF === 'refs/heads/master'
|
||||
|
||||
module.exports = {
|
||||
branches: [
|
||||
'master',
|
||||
{ name: 'next', prerelease: 'alpha' }
|
||||
],
|
||||
plugins: [
|
||||
...basePlugins,
|
||||
...(onMaster ? [gitPlugin] : []),
|
||||
githubPlugin
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,14 @@
|
||||
## [10.27.2](https://github.com/harttle/liquidjs/compare/v10.27.1...v10.27.2) (2026-07-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* charge join/json/inspect filters by produced output size ([#925](https://github.com/harttle/liquidjs/issues/925)) ([7ab49f9](https://github.com/harttle/liquidjs/commit/7ab49f999ac045ec1e87f3a7a9fd68dd9e8602b3))
|
||||
* **date:** zero-pad milliseconds when formatting %N fractional seconds ([#929](https://github.com/harttle/liquidjs/issues/929)) ([2634f9d](https://github.com/harttle/liquidjs/commit/2634f9de7b1228cd887b7cab880af8a795c77053))
|
||||
* enforce ownPropertyOnly for inherited array indices ([#924](https://github.com/harttle/liquidjs/issues/924)) ([552819a](https://github.com/harttle/liquidjs/commit/552819a84b80c62306fe61072628a756272dc749))
|
||||
* **filters:** modulo should follow divisor sign for negative operands ([#922](https://github.com/harttle/liquidjs/issues/922)) ([568bd5f](https://github.com/harttle/liquidjs/commit/568bd5f9cb99f596292c09fd70b00284b8216f0c))
|
||||
* **filters:** return empty for out-of-range slice begin or negative length ([#928](https://github.com/harttle/liquidjs/issues/928)) ([f9a1316](https://github.com/harttle/liquidjs/commit/f9a1316d161f4f20018c833160f42dfcf0cde507))
|
||||
|
||||
## [10.27.1](https://github.com/harttle/liquidjs/compare/v10.27.0...v10.27.1) (2026-06-23)
|
||||
|
||||
|
||||
|
||||
Generated
+3
-3
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "liquidjs",
|
||||
"version": "10.27.1",
|
||||
"version": "10.27.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "liquidjs",
|
||||
"version": "10.27.1",
|
||||
"version": "10.27.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^10.0.0"
|
||||
@@ -64,7 +64,7 @@
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
|
||||
+41
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "liquidjs",
|
||||
"version": "10.27.1",
|
||||
"version": "10.27.2",
|
||||
"sideEffects": false,
|
||||
"description": "A simple, expressive, extensible Liquid template engine for JavaScript — Shopify, Jekyll and GitHub Pages compatible, for Node.js, browsers, and the CLI, with TypeScript support.",
|
||||
"main": "dist/liquid.node.js",
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"types": "dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": ">=16"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"**/*.mjs\" \"**/*.ts\" .",
|
||||
@@ -121,6 +121,45 @@
|
||||
"dependencies": {
|
||||
"commander": "^10.0.0"
|
||||
},
|
||||
"release": {
|
||||
"branch": "master",
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/changelog",
|
||||
"@semantic-release/npm",
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/github",
|
||||
{
|
||||
"assets": [
|
||||
{
|
||||
"path": "dist/*.umd.js",
|
||||
"label": "liquid.js"
|
||||
},
|
||||
{
|
||||
"path": "dist/*.min.js",
|
||||
"label": "liquid.min.js"
|
||||
},
|
||||
{
|
||||
"path": "dist/*.min.js.map",
|
||||
"label": "liquid.min.js.map"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"publishConfig": {
|
||||
"provenance": true
|
||||
},
|
||||
|
||||
+4
-4
@@ -89,7 +89,7 @@ const nodeEsm = {
|
||||
plugins: [
|
||||
versionInjection,
|
||||
replace(esmRequire),
|
||||
typescript(tsconfig('ES2020'))
|
||||
typescript(tsconfig('es6'))
|
||||
],
|
||||
treeshake,
|
||||
input
|
||||
@@ -108,7 +108,7 @@ const browserEsm = {
|
||||
replace(browserBase64),
|
||||
replace(browserCrypto),
|
||||
replace(browserStream),
|
||||
typescript(tsconfig('ES2020'))
|
||||
typescript(tsconfig('es6'))
|
||||
],
|
||||
treeshake,
|
||||
input
|
||||
@@ -128,7 +128,7 @@ const browserUmd = {
|
||||
replace(browserBase64),
|
||||
replace(browserCrypto),
|
||||
replace(browserStream),
|
||||
typescript(tsconfig('ES2020'))
|
||||
typescript(tsconfig('es5'))
|
||||
],
|
||||
treeshake,
|
||||
input
|
||||
@@ -148,7 +148,7 @@ const browserMin = {
|
||||
replace(browserBase64),
|
||||
replace(browserCrypto),
|
||||
replace(browserStream),
|
||||
typescript(tsconfig('ES2020')),
|
||||
typescript(tsconfig('es5')),
|
||||
uglify()
|
||||
],
|
||||
treeshake,
|
||||
|
||||
@@ -2,6 +2,11 @@ import * as base64 from './base64-impl-browser'
|
||||
import { JSDOM } from 'jsdom'
|
||||
|
||||
describe('base64-impl/browser', function () {
|
||||
if (+(process.version.match(/^v(\d+)/) as RegExpMatchArray)[1] < 8) {
|
||||
console.info('jsdom not supported, skipping base64-impl-browser...')
|
||||
return
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
const dom = new JSDOM(``, {
|
||||
url: 'https://example.com/',
|
||||
|
||||
@@ -3,6 +3,10 @@ import * as sinon from 'sinon'
|
||||
import { JSDOM } from 'jsdom'
|
||||
|
||||
describe('fs/browser', function () {
|
||||
if (+(process.version.match(/^v(\d+)/) as RegExpMatchArray)[1] < 8) {
|
||||
console.info('jsdom not supported, skipping template-browser...')
|
||||
return
|
||||
}
|
||||
beforeEach(function () {
|
||||
const dom = new JSDOM(``, {
|
||||
url: 'https://example.com/foo/bar/',
|
||||
|
||||
@@ -46,7 +46,7 @@ export function * sort_natural<T> (this: FilterImpl, arr: T[], property?: string
|
||||
return yield * sortBy.call(this, arr, property, caseInsensitiveCompare)
|
||||
}
|
||||
|
||||
export const size = (v: string | any[]) => v?.length || 0
|
||||
export const size = (v: string | any[]) => (v && v.length) || 0
|
||||
|
||||
export function * map (this: FilterImpl, arr: Scope[], property: string): IterableIterator<unknown> {
|
||||
const results = []
|
||||
@@ -114,6 +114,7 @@ export function slice<T> (this: FilterImpl, v: T[] | string, begin: number, leng
|
||||
if (isNil(v)) return []
|
||||
if (!isArray(v)) v = stringify(v)
|
||||
begin = begin < 0 ? v.length + begin : begin
|
||||
if (begin < 0 || length < 0) return isArray(v) ? [] : ''
|
||||
this.context.memoryLimit.use(length)
|
||||
return isArray(v)
|
||||
? Array.prototype.slice.call(v, begin, begin + length)
|
||||
|
||||
@@ -204,11 +204,11 @@ export const defaultOptions: NormalizedFullOptions = {
|
||||
}
|
||||
|
||||
export function normalize (options: LiquidOptions): NormalizedFullOptions {
|
||||
if ('root' in options) {
|
||||
if (!('partials' in options)) options.partials = options.root
|
||||
if (!('layouts' in options)) options.layouts = options.root
|
||||
if (options.hasOwnProperty('root')) {
|
||||
if (!options.hasOwnProperty('partials')) options.partials = options.root
|
||||
if (!options.hasOwnProperty('layouts')) options.layouts = options.root
|
||||
}
|
||||
if ('cache' in options) {
|
||||
if (options.hasOwnProperty('cache')) {
|
||||
let cache: LiquidCache | undefined
|
||||
if (typeof options.cache === 'number') cache = options.cache > 0 ? new LRU(options.cache) : undefined
|
||||
else if (typeof options.cache === 'object') cache = options.cache
|
||||
|
||||
@@ -87,6 +87,15 @@ describe('util/strftime', function () {
|
||||
expect(t(time, '%10N')).toBe('1290000000')
|
||||
expect(t(time, '%0N')).toBe('129000000')
|
||||
})
|
||||
it('should zero pad %N for sub-100ms fractional seconds', function () {
|
||||
const time = new TestDate('2019-12-15 01:21:00.005')
|
||||
expect(t(time, '%N')).toBe('005000000')
|
||||
expect(t(time, '%3N')).toBe('005')
|
||||
expect(t(time, '%6N')).toBe('005000')
|
||||
const tens = new TestDate('2019-12-15 01:21:00.050')
|
||||
expect(t(tens, '%N')).toBe('050000000')
|
||||
expect(t(tens, '%2N')).toBe('05')
|
||||
})
|
||||
it('should format %p as upper cased am/pm', function () {
|
||||
expect(t(now, '%p')).toBe('PM')
|
||||
expect(t(then, '%p')).toBe('AM')
|
||||
|
||||
@@ -98,7 +98,7 @@ const formatCodes: Record<string, FormatCodeHandler> = {
|
||||
M: (d: LiquidDate) => d.getMinutes(),
|
||||
N: (d: LiquidDate, opts: FormatOptions) => {
|
||||
const width = Number(opts.width) || 9
|
||||
const str = String(d.getMilliseconds()).slice(0, width)
|
||||
const str = padStart(String(d.getMilliseconds()), 3, '0').slice(0, width)
|
||||
opts.memoryLimit?.use(width - str.length)
|
||||
return padEnd(str, width, '0')
|
||||
},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Drop } from '../drop/drop'
|
||||
|
||||
export const toString = Object.prototype.toString
|
||||
export const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
const toLowerCase = String.prototype.toLowerCase
|
||||
|
||||
export const hasOwnProperty = Object.hasOwnProperty
|
||||
|
||||
export function isString (value: any): value is string {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
@@ -89,7 +90,8 @@ export function isUndefined (value: any): boolean {
|
||||
}
|
||||
|
||||
export function isArray (value: any): value is any[] {
|
||||
return Array.isArray(value)
|
||||
// be compatible with IE 8
|
||||
return toString.call(value) === '[object Array]'
|
||||
}
|
||||
|
||||
export function isArrayLike (value: any): value is any[] {
|
||||
|
||||
@@ -288,6 +288,9 @@ describe('filters/array', function () {
|
||||
it('should slice substr by -2,2', () => test('{{ "abc" | slice: -2, 2 }}', 'bc'))
|
||||
it('should support array', () => test('{{ "1,2,3,4" | split: "," | slice: 1,2 | join }}', '2 3'))
|
||||
it('should return empty array for nil value', () => test('{{ nil | slice: 0 }}', ''))
|
||||
it('should return empty when begin is out of negative range', () => test('{{ "hello" | slice: -10, 2 }}', ''))
|
||||
it('should return empty when length is negative', () => test('{{ "Liquid" | slice: 1, -2 }}', ''))
|
||||
it('should return empty array when begin is out of negative range', () => test('{{ "1,2,3,4,5" | split: "," | slice: -10, 2 | join: "," }}', ''))
|
||||
})
|
||||
describe('sort', function () {
|
||||
it('should support sort', function () {
|
||||
|
||||
+3
-4
@@ -1,9 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module":"ES2020",
|
||||
"lib": ["ES2020", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"target": "es6",
|
||||
"module":"CommonJS",
|
||||
"lib": ["es2015", "es2016", "es2017", "dom"],
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
|
||||
Reference in New Issue
Block a user