Compare commits

...
Author SHA1 Message Date
39233ba9f2 docs: publish .nojekyll so GitHub Pages serves underscore API pages (#952)
EOF

Co-authored-by: Cursor <[email protected]>
2026-09-06 19:38:56 +08:00
allcontributors[bot]GitHuballcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
8f57d9fed8 docs: add sarathfrancis90 as a contributor for code (#951)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-09-06 19:16:55 +08:00
Sarath FrancisandGitHub 9af92f5d8c fix(url_decode): keep %2B as a literal plus when decoding (#939)
url_decode decoded the percent-encoding first and only then replaced
"+" with a space, so a "%2B" became "+" and was immediately turned into
a space. Any literal "+" was therefore lost when round-tripped through
url_encode. I now replace "+" with a space before decodeURIComponent,
which lines up with Ruby's CGI.unescape used by Shopify.
2026-09-06 19:16:16 +08:00
semantic-release-bot 747bdbdbee chore(release): 10.29.0 [skip ci]
# [10.29.0](https://github.com/harttle/liquidjs/compare/v10.28.0...v10.29.0) (2026-08-11)

### Features

* add unregisterFilter method ([#946](https://github.com/harttle/liquidjs/issues/946)) ([69b2c58](https://github.com/harttle/liquidjs/commit/69b2c589f9b69a34427cb8533ddb938bd997914f))
* **filters:** add squish filter ([#943](https://github.com/harttle/liquidjs/issues/943)) ([875513f](https://github.com/harttle/liquidjs/commit/875513f4c5136bed0c64562cccabb21a7db8d36c))
2026-08-11 12:53:56 +00:00
MildlyMeticulousandGitHub 875513f4c5 feat(filters): add squish filter (#943) 2026-08-11 20:52:07 +08:00
allcontributors[bot]GitHuballcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
f88a528e27 docs: add YacovGold as a contributor for code (#947)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-08-11 20:04:09 +08:00
11 changed files with 86 additions and 5 deletions
+18
View File
@@ -847,6 +847,24 @@
"contributions": [
"code"
]
},
{
"login": "YacovGold",
"name": "YacovGold",
"avatar_url": "https://avatars.githubusercontent.com/u/8984042?v=4",
"profile": "https://github.com/YacovGold",
"contributions": [
"code"
]
},
{
"login": "sarathfrancis90",
"name": "Sarath Francis",
"avatar_url": "https://avatars.githubusercontent.com/u/9289498?v=4",
"profile": "https://github.com/sarathfrancis90",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
+8
View File
@@ -1,3 +1,11 @@
# [10.29.0](https://github.com/harttle/liquidjs/compare/v10.28.0...v10.29.0) (2026-08-11)
### Features
* add unregisterFilter method ([#946](https://github.com/harttle/liquidjs/issues/946)) ([69b2c58](https://github.com/harttle/liquidjs/commit/69b2c589f9b69a34427cb8533ddb938bd997914f))
* **filters:** add squish filter ([#943](https://github.com/harttle/liquidjs/issues/943)) ([875513f](https://github.com/harttle/liquidjs/commit/875513f4c5136bed0c64562cccabb21a7db8d36c))
# [10.28.0](https://github.com/harttle/liquidjs/compare/v10.27.2...v10.28.0) (2026-08-01)
+2
View File
@@ -242,6 +242,8 @@ Want to contribute? see [Contribution Guidelines][contribution]. Thanks goes to
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/spokodev"><img src="https://avatars.githubusercontent.com/u/239690017?v=4?s=100" width="100px;" alt="spokodev"/><br /><sub><b>spokodev</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=spokodev" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YacovGold"><img src="https://avatars.githubusercontent.com/u/8984042?v=4?s=100" width="100px;" alt="YacovGold"/><br /><sub><b>YacovGold</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=YacovGold" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sarathfrancis90"><img src="https://avatars.githubusercontent.com/u/9289498?v=4?s=100" width="100px;" alt="Sarath Francis"/><br /><sub><b>Sarath Francis</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=sarathfrancis90" title="Code">💻</a></td>
</tr>
</tbody>
</table>
+1
View File
@@ -94,6 +94,7 @@ filters:
sort: sort.html
sort_natural: sort_natural.html
split: split.html
squish: squish.html
strip: strip.html
strip_html: strip_html.html
strip_newlines: strip_newlines.html
+18
View File
@@ -0,0 +1,18 @@
---
title: squish
---
{% since %}v10.28.0{% endsince %}
Removes leading and trailing whitespace from a string, and replaces every run of whitespace inside it with a single space.
Input
```liquid
{{ " Hello there,
Major Tom. " | squish }}
```
Output
```text
Hello there, Major Tom.
```
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "liquidjs",
"version": "10.28.0",
"version": "10.29.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "liquidjs",
"version": "10.28.0",
"version": "10.29.0",
"license": "MIT",
"dependencies": {
"commander": "^10.0.0"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "liquidjs",
"version": "10.28.0",
"version": "10.29.0",
"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",
@@ -35,7 +35,7 @@
"build:contributors": "node bin/build-contributors.js",
"build:apidoc": "shx rm -rf docs/source/api && typedoc --plugin typedoc-plugin-missing-exports ./src --gitRevision master --out docs/source/api",
"build:changelog": "node bin/build-changelog.js",
"build:docs-hexo": "cd docs && npm ci && npm run build && shx cp CNAME public/",
"build:docs-hexo": "cd docs && npm ci && npm run build && shx cp CNAME .nojekyll public/",
"serve:docs": "cd docs && npm run start",
"dev:docs": "run-s prepare:docs serve:docs"
},
+6
View File
@@ -128,6 +128,12 @@ export function strip_newlines (this: FilterImpl, v: string) {
return str.replace(/\r?\n/gm, '')
}
export function squish (this: FilterImpl, v: string) {
const str = stringify(v)
this.context.memoryLimit.use(str.length)
return str.replace(/\s+/g, ' ').trim()
}
export function capitalize (this: FilterImpl, str: string) {
str = stringify(str)
this.context.memoryLimit.use(str.length)
+1 -1
View File
@@ -1,6 +1,6 @@
import { stringify } from '../util/underscore'
export const url_decode = (x: string) => decodeURIComponent(stringify(x)).replace(/\+/g, ' ')
export const url_decode = (x: string) => decodeURIComponent(stringify(x).replace(/\+/g, ' '))
export const url_encode = (x: string) => encodeURIComponent(stringify(x)).replace(/%20/g, '+')
export const cgi_escape = (x: string) => encodeURIComponent(stringify(x))
.replace(/%20/g, '+')
+20
View File
@@ -153,6 +153,26 @@ describe('filters/string', function () {
'{{ string_with_newlines | strip_newlines }}',
'Hellothere')
})
describe('squish', function () {
it('should collapse whitespace between words', function () {
return test('{{ "Hello World!" | squish }}', 'Hello World!')
})
it('should strip leading and trailing whitespace', function () {
return test('{{ " HelloWorld! " | squish }}', 'HelloWorld!')
})
it('should treat newlines and tabs as whitespace', function () {
return test('{{ " \n\t\r\nHello \n\t World! \n" | squish }}', 'Hello World!')
})
it('should return empty string for whitespace only', function () {
return test('{{ " \n\t " | squish }}', '')
})
it('should stringify a number', function () {
return test('{{ 5 | squish }}', '5')
})
it('should return empty string for undefined', function () {
return test('{{ nosuchthing | squish }}', '')
})
})
describe('truncate', function () {
it('should truncate when string too long', function () {
return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
+8
View File
@@ -7,6 +7,14 @@ describe('filters/url', () => {
const html = liquid.parseAndRenderSync('{{ "%27Stop%21%27+said+Fred" | url_decode }}')
expect(html).toEqual("'Stop!' said Fred")
})
it('should decode %2B to a literal plus', () => {
const html = liquid.parseAndRenderSync('{{ "1%2B1" | url_decode }}')
expect(html).toEqual('1+1')
})
it('should keep a literal plus when round-tripped through url_encode', () => {
const html = liquid.parseAndRenderSync('{{ "a+b c" | url_encode | url_decode }}')
expect(html).toEqual('a+b c')
})
})
describe('url_encode', () => {