Dostupni filtri Liquid

Likvidni koriste se za izmjene izlaza nizova, brojeva, varijabli i objekata. Odvojeni su od vrijednosti na koju se primjenjuju pomoću okomite crte |.

{{ 'hal 9000' | upcase }} <!-- Output: HAL 9000 -->

Neki filtri prihvaćaju parametre. Filtri se mogu i kombinirati te se primjenjuju redoslijedom lijevo-desno.

{{ 2 | times: 2 | minus: 1 }} <!-- Output: 3 -->

{{ "Hello, " | append: user.firstname }} <!-- Output: Hello, Dave -->

U odjeljku u nastavku opisani su razni filtri.

Filtri polja

Filtri polja koriste se za rad s poljima.

serija

Dijeli polje u više polja određene veličine.

Kôd

{% assign batches = entityview.records | batch: 2 %}

{% for batch in batches %}

<ul>

{% for item in batch %}

<li>{{ item.fullname }}</li>

{% endfor %}

</ul>

{% endfor %}

Rezultat

<ul>

<li>John Smith</li>

<li>Dave Thomas</li>

</ul>

<ul>

<li>Jake Johnson</li>

<li>Jack Robinson</li>

</ul>

concat

Povezivanje dva polja u jedno novo polje.

Ako je određena stavka parametar, concat prikazuje novo polje koje se sastoji od izvornog polja, a ta stavka je posljednji element.

Kôd

Group #1: {{ group1 | join: ', ' }}

Group #2: {{ group2 | join: ', ' }}

Group #1 + Group #2: {{ group1 | concat: group2 | join: ', ' }}

Group #1 + Leslie: {{ group1 | concat: 'Leslie' | join: ', ' }}

Rezultat

Group #1: John, Pete, Hannah

Group #2: Joan, Bill

Group #1 + Group #2: John, Pete, Hannah, Joan, Bill

Group #1 + Leslie: John, Pete, Hannah, Leslie

osim

Odaberite sve objekte u polju gdje određeni atribut nema određenu vrijednost. (To je obrnuto od where.)

Kôd

{% assign redmond = entityview.records | except: 'address1_city', 'Redmond' %}

{% for item in redmond %}

{{ item.fullname }}

{% endfor %}

Rezultat

Jack Robinson

Prvi

Prikazuje prvi element polja.

first se može koristiti i s posebnom notacijom pomoću točaka, u slučajevima u kojima se treba koristiti u oznaci.

Kôd

{% assign words = This is a run of text | split:   %}

{{ words | first }}

{% if words.first == This %}

The first word is This.

{% endif %}

Rezultat

This

The first word is This.

group_by

Grupirajte stavke u polju po određenom atributu.

Kôd

{% assign groups = entityview.records | group_by: 'address1_city' %}

{% for group in groups %}

{{ group.key }}:

{% for item in group.items %}

{{ item.fullname }}

{% endfor %}

{% endfor %}

Rezultat

Redmond:

John Smith

Dave Thomas

Jake Johnson

New York:

Jack Robinson

spajanje

Spaja elemente polja znakom proslijeđenim kao parametar. Rezultat je jedan niz.

Kôd

{% assign words = This is a run of text | split:   %}

{{ words | join: ,  }}

Rezultat

This, is, a, run, of, text

Zadnji

Prikazuje posljednji element polja.

last se može koristiti i s posebnom notacijom pomoću točaka, u slučajevima u kojima se treba koristiti u oznaci.

Kôd

{% assign words = This is a run of text | split:   -%}

{{ words | last }}

{% if words.last == text -%}

The last word is text.

{% endif -%}

Rezultat

text

The last word is text.

order_by

Prikazuje elemente polja raspoređene po određenom atributu elemenata polja.

Ako to želite, možete navesti desc kao drugi parametar za sortiranje elemenata silaznim redoslijedom, a ne uzlaznim.

Kôd

{{ entityview.records | order_by: 'fullname' | join: ', ' }}

{{ entityview.records | order_by: 'fullname', 'desc' | join: ', ' }}

Rezultat

Dave Thomas, Jack Robinson, Jake Johnson, John Smith

John Smith, Jake Johnson, Jack Robinson, Dave Thomas

nasumično

Vraća jednu nasumično odabranu stavku iz polja.

Kôd

{{ group1 | join: ', ' }}

{{ group1 | random }}

Rezultat

John, Pete, Hannah

Pete

odabir

Odabire vrijednost određenog atributa za svaku stavku u polju i vraća te vrijednosti kao polje.

Kôd

{{ entityview.records | select: 'address1_city' | join: ', ' }}

Rezultat

Redmond, New York

izmiješaj

Primijenjeno na polje, vraća novo polje s istim stavkama nasumičnim redoslijedom.

Kôd

{{ group1 | join: ', ' }}

{{ group1 | shuffle | join: ', ' }}

Rezultat

John, Pete, Hannah

Hannah, John, Pete

veličina

Vraća broj stavki u polju.

size se može koristiti i s posebnom notacijom pomoću točaka, u slučajevima u kojima se treba koristiti u oznaci.

Kôd

{% assign words = This is a run of text | split:   -%}

{{ words | size }}

{% if words.size == 6 -%}

The text contains 6 words.

{% endif -%}

Rezultat

6

The text contains 6 words.

preskoči

Preskače određeni broj stavki u polju, a vraća ostatak.

Kôd

{% assign words = This is a run of text | split:   %}

{{ words | skip: 3 | join: ', ' }}

Rezultat

run, of, text

uzmi

Uzima određeni broj stavki iz polja te vraća uzete stavke.

Kôd

{% assign words = This is a run of text | split:   %}

{{ words | take: 3 | join: ', ' }}

Rezultat


This, is, a

then_by

Dodaje dodatni naknadni redoslijed polju koje je već raspoređeno po order_by.

Ako to želite, možete navesti desc kao drugi parametar za sortiranje elemenata silaznim redoslijedom, a ne uzlaznim.

Kôd

{{ entityview.records | order_by: 'address1_city' | then_by: 'fullname' | join: ', ' }}

{{ entityview.records | order_by: 'address1_city' | then_by: 'fullname', 'desc' | join: ', ' }}

Rezultat

Dave Thomas, Jack Robinson, Jake Johnson, John Smith

John Smith, Jake Johnson, Jack Robinson, Dave Thomas

gdje

Odaberite sve objekte u polju gdje određeni atribut ima određenu vrijednost.

Kôd

{% assign redmond = entityview.records | where: 'address1_city', 'Redmond' %}

{% for item in redmond %}

{{ item.fullname }}

{% endfor %}

Rezultat

John Smith

Dave Thomas

Jake Johnson

Filtri datuma

Filtri datuma mogu se koristiti za izračun datuma ili pretvaranje vrijednosti datuma i vremena u različite oblike.

datum

Oblikuje vrijednost Datum i vrijeme pomoću niza oblika .NET.

Standardni nizovi oblikovanja datuma i vremena

Prilagođeni nizovi oblikovanja datuma i vremena

Kôd

{{ now | date: 'g' }}

{{ now | date: 'MMMM dd, yyyy' }}

Rezultat

5/7/2018 7:20 AM

May 07, 2018

date_add_days

Dodaje određeni broj cijelih i djelomičnih dana vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_days: 1 }}

{{ now | date_add_days: -2.5 }}

Rezultat

5/7/2018 7:20:46 AM

5/8/2018 7:20:46 AM

5/4/2018 7:20:46 PM

date_add_hours

Dodaje određeni broj cijelih i djelomičnih sati vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_hours: 1 }}

{{ now | date_add_hours: -2.5 }}

Rezultat

5/7/2018 7:20:46 AM

5/7/2018 8:20:46 AM

5/7/2018 4:50:46 AM

date_add_minutes

Dodaje određeni broj cijelih i djelomičnih minuta vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_minutes: 10 }}

{{ now | date_add_minutes: -2.5 }}

Rezultat

5/7/2018 7:20:46 AM

5/7/2018 7:30:46 AM

5/7/2018 7:18:16 AM

date_add_months

Dodaje određeni broj cijelih i djelomičnih mjeseci vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_months: 1 }}

{{ now | date_add_months: -2 }}

Rezultat

5/7/2018 7:20:46 AM

6/7/2018 7:20:46 AM

3/7/2018 7:20:46 AM

date_add_seconds

Dodaje određeni broj cijelih i djelomičnih sekundi vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_seconds: 10 }}

{{ now | date_add_seconds: -1.25 }}

Rezultat

5/7/2018 7:20:46 AM

5/7/2018 7:20:56 AM

5/7/2018 7:20:45 AM

date_add_years

Dodaje određeni broj cijelih i djelomičnih godina vrijednosti Datum i vrijeme. Parametar može biti pozitivan ili negativan.

Kôd

{{ now }}

{{ now | date_add_years: 1 }}

{{ now | date_add_years: -2 }}

Rezultat

5/7/2018 7:20:46 AM

5/7/2019 7:20:46 AM

5/7/2016 7:20:46 AM

date_to_iso8601

Oblikuje vrijednost DateTime u skladu s normom ISO 8601. Korisno prilikom stvaranja sažetaka sadržaja Atom ili elementa HTML5 <time>.

Kôd

{{ now | date_to_iso8601 }}

Rezultat

2018-05-07T07:20:46Z

date_to_rfc822

Oblikuje vrijednost DateTime u skladu s normom RFC 822. Korisno prilikom stvaranja sažetaka sadržaja RSS.

Kod

{{ now | date_to_rfc822 }}

Izlaz

Mon, 07 May 2018 07:20:46 Z

Filtri popisa

Filtri popisa koriste za rad s određenim vrijednostima atributa entitylist, a radi stvaranja prikaza popisa.

current_sort

Ako se unese izraz za sortiranje, vraća trenutni smjer sortiranja za određeni atribut.

Kôd

{{ 'name ASC, createdon DESC' | current_sort: 'createdon' }}

Rezultat

DESC

metafilters

Raščlanjuje JSON vrijednost entitylist filter_definition u grupu objekta mogućnosti filtra.

metafilters može se po želji omogućiti s trenutnim upitom filtriranja za atribut i trenutačnim entitylist, čime se dopušta da su vraćeni objekti filtra označeni kao odabrani ili neodabrani.

Kod

{% assign filters = entitylist | metafilters: params.mf, entityview %}
{% if filters.size > 0 %}
  <ul id=entitylist-filters>
    {% for filter in filters %}
      <li class=entitylist-filter-option-group>
        {% if filter.selection_mode == 'Single' %}
          {% assign type = 'radio' %}
        {% else %}
          {% assign type = 'checkbox' %}
        {% endif %}
        <h4 class=entitylist-filter-option-group-label
          data-filter-id={{ filter.id | h }}>
          {{ filter.label | h }}
        </h4>
        <ul>
          {% for option in filter.options %}
            <li class=entitylist-filter-option>
              {% if option.type == 'text' %}
                <div class=input-group entitylist-filter-option-text>
                  <span class=input-group-addon>
                    <span class=fa fa-filter aria-hidden=true></span>
                  </span>
                  <input class=form-control
                    type=text
                    name={{ filter.id | h }}
                    value={{ option.text | h }} />
                </div>
              {% else %}
                <div class={{ type | h }}>
                  <label>
                    <input
                      type={{ type | h }}
                      name={{ filter.id | h }}
                      value={{ option.id | h }}
                      {% if option.checked %}
                        checked=checked
                        data-checked=true{% endif %}
                      />
                    {{ option.label | h }}
                  </label>
                </div>
              {% endif %}
            </li>
          {% endfor %}
        </ul>
      </li>
    {% endfor %}
  </ul>
  <button class=btn btn-default data-serialized-query=mf data-target=#entitylist-filters>Apply Filters</button>
{% endif %}

reverse_sort

Kada se navede smjer sortiranja, vraća se suprotni smjer sortiranja.

Kôd

<!-- Sort direction is not case-sensitive -->

{{ 'ASC' | reverse_sort }}

{{ 'desc' | reverse_sort }}

Rezultat

DESC

ASC

Matematički filtri

Matematički filtri omogućuju izvođenje matematičkih operacija na numbers.

Matematički filtri mogu se povezati, baš kao i svi ostali filtri, te se primjenjuju redoslijedom lijevo-desno.

Kôd

{{ 10 | times: 2 | minus: 5 | divided_by: 3 }}

Rezultat

5

ceil

Zaokružuje vrijednost na najbliži veći cijeli broj.

Kôd

{{ 4.6 | ceil }}

{{ 4.3 | ceil }}

Rezultat

5

5

divided_by

Dijeli broj nekim drugim brojem.

Kôd

{{ 10 | divided_by: 2 }}

{{ 10 | divided_by: 3 }}

{{ 10.0 | divided_by: 3 }}

Rezultat

5

3

3.333333

floor

Zaokružuje vrijednost na najbliži manji cijeli broj.

Kôd

{{ 4.6 | floor }}

{{ 4.3 | floor }}

Rezultat

4

4

minus

Oduzima broj od nekog drugog broja.

Kôd

<!-- entityview.page = 11 -->

{{ entityview.page | minus: 1 }}

{{ 10 | minus: 1.1 }}

{{ 10.1 | minus: 1 }}

Rezultat

10

9

9.1

modulo

Dijeli broj drugim brojem i vraća ostatak.

Kôd

{{ 12 | modulo: 5 }}

Rezultat

2

plus

Dodaje broj nekom drugom broju.

Kôd

<!-- entityview.page = 11 -->

{{ entityview.page | plus: 1 }}

{{ 10 | plus: 1.1 }}

{{ 10.1 | plus: 1 }}

Rezultat

12

11

11.1

round

Zaokružuje vrijednost na najbliži cijeli broj ili određeni broj decimalnih mjesta.

Kôd

{{ 4.6 | round }}

{{ 4.3 | round }}

{{ 4.5612 | round: 2 }}

Rezultat

5

4

4.56

times

Množi broj nekim drugim brojem.

Kod

{{ 10 | times: 2 }}

{{ 10 | times: 2.2 }}

{{ 10.1 | times: 2 }}

Izlaz

20

20

20.2

Filtri niza

Filtri niza rukuju nizovima.

dodavanje

Dodaje niz na kraj drugog niza.

Kod

{{ 'filename' | append: '.js' }}

Rezultat

filename.js

capitalize

piše velikim slovom prvu riječ u nizu.

Kôd

{{ 'capitalize me' | capitalize }}

Rezultat

Capitalize Me

downcase

Pretvara niz u mala slova.

Kôd

{{ 'MIxed Case TExt' | downcase }}

Rezultat

mixed case text

escape

HTML – izlaz iz niza.

Kôd

{{ '<p>test</p>' | escape }}

Rezultat

&lt;p&gt;test&lt;/p&gt;

newline_to_br

Umeće HTML oznaku prijeloma retka <br /> u svaki prijelom retka u nizu.

Kôd

{% capture text %}

A

B

C

{% endcapture %}

{{ text | newline_to_br }}

Rezultat

A<br />

B<br />

C<br />

prepend

Pridaje niz na početak drugog niza.

Kôd

{{ 'Jane Johnson' | prepend: 'Dr. ' }}

Rezultat

Dr. Jane Johnson

remove

Uklonite sva pojavljivanja podniza iz niza.

Kôd

{{ 'Hello, Dave. How are you, Dave?' | remove: 'Dave' }}

Rezultat

Hello, . How are you, ?

remove_first

Uklanja prvo pojavljivanje podniza iz niza.

Kôd

{{ 'Hello, Dave. How are you, Dave?' | remove_first: 'Dave' }}

Rezultat

Hello, . How are you, Dave?

replace

Zamjenjuje sva pojavljivanja niza podnizom.

Kôd

{{ 'Hello, Dave. How are you, Dave?' | replace: 'Dave', 'John' }}

Rezultat

Hello, John. How are you, John?

replace_first

Zamjenjuje prvo pojavljivanje niza podnizom.

Kôd

{{ 'Hello, Dave. How are you, Dave?' | replace_first: 'Dave', 'John' }}

Rezultat

Hello, John. How are you, Dave?

split

Filtar split preuzima podniz kao parametar. Podniz se koristi kao graničnik za dijeljenje niza u polje.

Kôd

{% assign words = This is a demo of the split filter | split: ' ' %}

First word: {{ words.first }}

First word: {{ words[0] }}

Second word: {{ words[1] }}

Last word: {{ words.last }}

All words: {{ words | join: ', ' }}

Rezultat

First word: This

First word: This

Second word: is

Last word: filter

All words: This, is, a, demo, of, the, split, filter

strip_html

Uklanja sve HTML oznake iz niza.

Kôd

<p>Hello</p>

Rezultat

Hello

strip_newlines

Uklanja prijelome retka iz niza.

Kôd

{% capture text %}

A

B

C

{% endcapture %}

{{ text | strip_newlines }}

Rezultat

ABC

text_to_html

Oblikuje niz običnog teksta kao jednostavni HTML. Cjelokupni tekst bit će šifriran kao HTML, blokovi teksta odvojeni praznim retkom bit će omotani oznakama <p> odlomka, pojedinačni prijelomi retka bit će zamijenjeni pomoću <br>, a URL-ovi će se pretvoriti u hiperveze.

Kôd

{{ note.notetext | text_to_html }}

Rezultat

<p>This is the first paragraph of notetext. It contains a URL: <a href="https://example.com/" rel="nofollow">https://example.com</a></p>

<p>This is a second paragraph.</p>

truncate

Skraćuje niz na određeni broj znakova. Tri točke (...) pridodaju se nizu i uključuju se u broj znakova.

Kôd

{{ 'This is a long run of text.' | truncate: 10 }}

Rezultat

This is...

truncate_words

Skraćuje niz na određeni broj riječi. Tri točke (...) pridodaju se skraćenom nizu.

Kôd

{{ 'This is a long run of text.' | truncate_words: 3 }}

Rezultat

This is a...

upcase

Pretvara niz u velika slova.

Kôd

{{ 'MIxed Case TExt' | upcase }}

Rezultat

MIXED CASE TEXT

url_escape

URI prekida niz za uključivanje u URL.

Kôd

{{ 'This & that//' | url_escape }}

Rezultat

This+%26+that%2F%2F

xml_escape

XML prekida niz za uključivanje u XML izlaz.

Kôd

{{ '<p>test</p>' | xml_escape }}

Rezultat

&lt;p&gt;test&lt;/p&gt;

Vrste filtara

Vrste filtara omogućuju vam pretvorbu vrijednosti određene vrste u druge vrste.

boolean

Pokušava pretvoriti vrijednost niza u Booleov operator. Ako je vrijednost već Booleov operator, vratit će se nepromijenjena. Ako se vrijednost ne može se pretvoriti u Booleovu vrijednost, vratit će se null.

Ovaj filtar će prihvatiti uključeno, omogućeno ili da kao true i isključeno, onemogućeno i ne kao false.

Kod

{{ true | boolean }}

{{ 'false' | boolean }}

{{ 'enabled' | boolean }}

{{ settings['something/enabled'] | boolean | default: false }}

Izlaz

true

false

true

false

decimala

Pokušava pretvoriti vrijednost niza u decimalni broj. Ako je vrijednost već decimalni broj, vratit će se nepromijenjena. Ako se vrijednost ne može se pretvoriti u decimalni broj, vratit će se null.

Kôd

{{ 10.1 | decimal }}

{{ '3.14' | decimal }}

{{ 'text' | decimal | default: 3.14 }}

Rezultat

10.1

3.14

3.14

integer

Pokušava pretvoriti vrijednost niza u cijeli broj. Ako je vrijednost već cijeli broj, vratit će se nepromijenjena. Ako se vrijednost ne može se pretvoriti u cijeli broj, vratit će se null.

Kôd

{{ 10 | integer }}

{{ '10' | integer }}

{{ '10.1' | integer }}

{{ 'text' | integer | default: 2 }}

Rezultat

10

10


2

string

Pokušava pretvoriti vrijednost u prikaz niza. Ako je vrijednost već niz, vratit će se nepromijenjena. Ako je vrijednost null, vratit će se null.

URL filtri

URL filtri omogućuju stvaranje ili izdvajanje dijelova URL-ova.

add_query

Dodaje URL-u parametar niza upita. Ako taj parametar već postoji u URL-u, ažurirat će se vrijednost parametra.

Ako se filtar primjenjuje na potpuno apsolutni URL, ažurirat će se apsolutni URL. Ako se primjenjuje na put, ažurirat će se put.

Kôd

{{ 'https://example.com/path?page=1' | add_query: 'foo', 'bar' }}

{{ '/path?page=1' | add_query: 'page', 2 }}

Rezultat

https://example.com/path?page=1&foo=bar

/path?page=2

base

Dohvaća osnovni URL navedenog URL-a.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | base }}

Rezultat

https://example.com

host

Dohvaća dio URL-a koji se odnosi na glavno računalo.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | host }}

Rezultat

example.com

path

Dohvaća dio URL-a koji se odnosi na put.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | path }}

{{ '/path?foo=bar&page=2' | path }}

Rezultat

/path

/path

path_and_query

Dohvaća dio URL-a koji se odnosi na put i upit.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | path_and_query }}

{{ '/path?foo=bar&page=2' | path_and_query }}

Rezultat

/path?foo=bar&page=2

/path?foo=bar&page=2

port

Dohvaća broj priključka URL-a.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | port }}

{{ 'https://example.com/path?foo=bar&page=2' | port }}

{{ 'https://example.com:9000/path?foo=bar&page=2' | port }}

Rezultat

80

443

9000

remove_query

Uklanja iz URL-a parametar niza upita. Ako parametar ne postoji u URL-u, URL će se vratiti nepromijenjen.

Ako se filtar primjenjuje na potpuno apsolutni URL, ažurirat će se apsolutni URL. Ako se primjenjuje na put, ažurirat će se put.

Kôd

{{ 'https://example.com/path?page=1' | remove_query: 'page' }}

{{ '/path?page=1' | remove_query: 'page' }}

Rezultat

https://example.com/path

/path

scheme

Dohvaća dio URL-a koji se odnosi na shemu.

Kôd

{{ 'https://example.com/path?foo=bar&page=2' | scheme }}

{{ 'https://example.com/path?foo=bar&page=2' | scheme }}

Rezultat

http

https

Dodatni filtri

Ti filtri nude opće korisne funkcije.

default

Vraća zadane vrijednosti za sve varijable bez dodijeljene vrijednosti (tj. null).

Kôd

{{ snippets[Header] | default: 'My Website' }}

Rezultat

<!-- If a snippet with the name Header returns null -->

My Website

file_size

Primjenjuje brojčanu vrijednost koja predstavlja broj bajtova, vraća oblikovanu datoteku s jedinicom odgovarajućeg mjerila.

Ako želite, parametar preciznosti može se proslijediti u svrhu upravljanja brojem decimalnih mjesta u rezultatima. Zadana preciznost je 1.

Kôd

{{ 10000000 | file_size }}

{{ 2050 | file_size: 0 }}

{{ entity.notes.first.filesize | file_size: 2 }}

Rezultat

9.5 MB

2 KB

207.14 KB

has_role

Primjenjuje se na korisnika, vraća vrijednost točno ako korisnik pripada danoj ulozi. Vraća false ako to nije slučaj.

Kôd

{% assign is_admin = user | has_role: 'Administrators' %}

{% if is_admin %}

User is an administrator.

{% endif %}

liquid

Renderira niz kao likvidni kod. Ovaj kod će imati pristup za trenutnom kontekstu likvidnog izvršenja (varijable itd.).

Napomena

Ovaj filtar treba se koristiti s upozorenjem i treba se općenito samo primijeniti na vrijednosti koje su pod isključivom kontrolom autora sadržaja portala ili drugim korisnicima kojima se može povjeriti pisanje likvidnog koda.

Kod

{{ page.adx_copy | liquid }}

Pogledajte također

Pohrana izvornog sadržaja pomoću web-predložaka
Objašnjenje operatora jezika Liquid Vrste jezika Liquid
Objekti jezika Liquid
Oznake jezika Liquid
Filtri jezika Liquid