Search Installed
Provide a helper to search pages from other pages.
Options See on deno.land
- name string
The helper name
Default:"search"
- returnPageData boolean
To return only the
Default:page.data
valuefalse
Description
This plugin registers the search
helper to search pages from other pages. It's useful to build menus or other navigation stuff.
Installation
This plugin is installed by default. 🎉
Searching pages
The function search.pages()
returns an array of pages that you can filter and sort.
To search by tags, just include the tag names as the first argument, separated by spaces. For example, to search all pages containing the tags post
and html
, you would execute search.pages("post html")
:
<ul>
{% for post in search.pages("post html") %}
<li>{{ post.data.title }}</li>
{% endfor %}
</ul>
You can use quotes to search for tags containing spaces. For example to search by the tags post
and static site generator
:
<ul>
{% for post in search.pages("post 'static site generator'") %}
<li>{{ post.data.title }}</li>
{% endfor %}
</ul>
Use the exclamation mark to search pages that doesn't contain a specific tag. For example, to search pages with the tag "post" not containing the tag "html":
<ul>
{% for post in search.pages("post !html") %}
<li>{{ post.data.title }}</li>
{% endfor %}
</ul>
Sort pages
The second argument is the value used to sort. By default, the pages are sorted by date
, but you can use any field. For example, if you want to sort by title:
<ul>
{% for post in search.pages("post html", "title") %}
<li>{{ post.data.title }}</li>
{% endfor %}
</ul>
Note: You can use dot notation to sort by any subfield. For example: header.title
.
Sorting allows specifying multiple fields. For example let's sort by the "order" and "title" fields:
{% for post in search.pages("post html", "order title") %}
...
{% endfor %}
By default, sort is ascendening, but this can be changed by appending =desc
to the field name:
{% for post in search.pages("post html", "order=asc title=desc") %}
...
{% endfor %}
Limit the results
The third argument of search.pages()
allows limiting the number of results. You can use a positive number to return the first n
results or a negative number to return the last n
results:
<!-- Get the 3 first values -->
{% for post in search.pages("post html", "order title", 3) %}
...
{% endfor %}
<!-- Get the 3 last values -->
{% for post in search.pages("post html", "order title", -3) %}
...
{% endfor %}
Filtering by a field
You can filter pages not only by tags but also by any other field that you want. For example, to search all pages with the value menu
as true
, simply include the query menu=true
:
{% for option in search.pages("menu=true") %}
<a href="{{ option.data.url }}">
{{ option.data.title }}
</a>
{% endfor %}
The available operators for the conditions are:
=
to search coincidences, for examplemenu=true
. The stringstrue
andfalse
are converted to booleans automatically.undefined
andnull
are also converted so you can filter pages without a value withkeyname=undefined
. The strings with numeric values are also converted to numbers.^=
to search values starting with another value. For example all categories starting with the letterA
:category^=A
.$=
to search values ending with another value. For example all categories ending with the letterb
:category$=b
.*=
to search values containing another value. For example all titles containing the stringsecurity
:title*=security
.<
,>
,<=
,>=
to search values lower or greater than the other value. For example, all pages with level greater than 2:level>2
.
You can use the dot notation and even combine queries with tags. For example, let's say you want to select all pages with the value taxonomy.category=sport
and with the tag football
:
{% for post in search.pages("taxonomy.category=sport football") %}
<a href="{{ post.data.url }}">
{{ post.data.title }}
</a>
{% endfor %}
Negative conditions
You can prepend the !
character to the operator to negate the condition. For example while menu=true
returns pages whose menu
variable is true
, menu!=true
returns pages whose menu
variable is NOT true
.
All operators accepts NOT operators. For example category!^=A
(pages which categories that does NOT start with the letter A
), or title!*=security
(pages whose title does NOT contain the word "security").
Alternatively, you can prepend the !
character at the begining of the condition. For example !menu=true
is equivalent to menu!=true
, and !category^=A
is equivalent to category!^=A
.
Using |
for OR conditions
You can assign several values for any condition using the pipe character |
. For example, if you want to search pages having the tag html
OR css
, you can do it with search.pages("html|css")
. You can combine AND and OR using spaces and pipes. For example, to search all pages with the tag post
and also one of the tags html
or css
: search.pages("post html|css")
.
OR conditions can be used with other fields. For example, to search pages with titles containing the words "html", "css" or "javascript": search.pages("title*=html|css|javascript")
.
The data
filter
In most cases, you don't need the Page
instance, only the data
object of the pages. So you can use the data
filter to return only these objects. So instead of this:
{% for post in search.pages("category=lume"]) %}
<a href="{{ post.data.url }}">
{{ post.data.title }}
</a>
{% endfor %}
You can do this:
{% for post in search.pages("category=lume"]) | data %}
<a href="{{ post.url }}">
{{ post.title }}
</a>
{% endfor %}
Search one page
The function search.page()
is very similar to search.pages()
but only returns the first page found. Note the limit
argument is not available.
Searching next and previous page
If the current page belongs to a list of pages (for example, a list of pages under the same tag), you can get the previous and next page in this list. To do that we have the functions search.previousPage()
and search.nextPage()
. The syntax is the same as search.pages()
, but the first argument is the URL of the current page. Let's see an example:
<h2>More articles tagged as "html"</h2>
{% set post = search.previousPage(url, "html") %}
{% if post %}
<a href="{{ post.data.url }}" rel="prev">← {{ post.data.title }}</a>
{% endif %}
{% set post = search.nextPage(url, "html") %}
{% if post %}
<a href="{{ post.data.url }}" rel="next">{{ post.data.title }} →</a>
{% endif %}
Get all values of a key
The function values()
returns all values found for a specific key, removing duplicates. For example, let's say your pages have the variable author
and you want to list all authors:
<strong>List of authors:</strong>
<ul>
{% for author in search.values("author") %}
<li>
{{ author }}
</li>
{% endfor %}
</ul>
Use the second argument to filter the pages to get the values. For example, to get the authors of pages in the category sport
: search.values("author", "category=sport")
There's the function search.tags()
for backward compatibility. It's the equivalent of using search.values("tags")
, to return all tags found in some pages.
Searching data
The function data
returns the data associated with any file or directory in the source directory. This is useful to get the data stored in any _data
of any directory. For example:
{% set companyData = search.data("about/the-company") %}
Search files
The function files()
allows to search any file that will be copied to the dest
folder and returns its URL. It accepts an regular expression or a string with a glob expression. For example, to search all CSS files:
This site uses the following CSS files:
<ul>
{% for file in search.files("*.css") %}
<a href="{{ file }}">
{{ file }}
</a>
{% endfor %}
</ul>
Configuration
If you want to change the default configuration, use the second argument of lume()
function in your _config.ts
file.
import lume from "lume/mod.ts";
// Search plugin configuration
const search = {/* your config here */};
// Apply the plugin config
const site = lume({}, { search });
returnPageData
Use this option to return only the page.data
object instead the page instance. Probably this is what you want and will make your code shorter.
It's disabled by default due compatibility with the old behavior but in the future Lume 2.0 it will be the default behavior.
import lume from "lume/mod.ts";
const search = { returnPageData: true };
const site = lume({}, { search });
Once configured, the following code:
{% for article in search.pages("type=article", "date=desc") %}
<a href="{{ article.data.url }}">
<h1>{{ article.data.title }}</h1>
</a>
{% endfor %}
must be changed to:
{% for article in search.pages("type=article", "date=desc") %}
<a href="{{ article.url }}">
<h1>{{ article.title }}</h1>
</a>
{% endfor %}