tags and categories pages #23
@@ -219,3 +219,5 @@ sort:
|
||||
score/desc: "Most relevant first"
|
||||
previous: "Previous"
|
||||
next: "Next"
|
||||
search:
|
||||
placeholder: "Search"
|
||||
|
||||
@@ -197,3 +197,5 @@ lorem_ipsum:
|
||||
quis mauris semper feugiat eu id arcu. Quisque quis vehicula ante.
|
||||
Ut hendrerit urna egestas tempor semper. <small>Nam viverra quam
|
||||
turpis.</small>
|
||||
search:
|
||||
placeholder: "Buscar"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
tags:
|
||||
- Topic-community
|
||||
- Status-pending
|
||||
|
||||
- title: Topic-community
|
||||
url: ""
|
||||
- title: Status-pending
|
||||
url: ""
|
||||
|
||||
@@ -3,9 +3,11 @@ items:
|
||||
- title: "Title post"
|
||||
created_at: "2026-05-31 14:54:26.236392904 -06:00"
|
||||
image:
|
||||
path: 'public/8k2m9p2w1rqw6mza53x9plkq98/floral-compaq.jpg'
|
||||
description: 'floral compaq image'
|
||||
content: 'Celebrating the mid-point between solar solstices with 2000+ words of updates on the (many) happenings in our corner of radical technology co-operativism.'
|
||||
path: "public/8k2m9p2w1rqw6mza53x9plkq98/floral-compaq.jpg"
|
||||
description: "floral compaq image"
|
||||
content: "Celebrating the mid-point between solar solstices with 2000+ words of updates on the (many) happenings in our corner of radical technology co-operativism."
|
||||
tags:
|
||||
- Topic-community
|
||||
- Status-pending
|
||||
- title: Topic-community
|
||||
url: ""
|
||||
- title: Status-pending
|
||||
url: ""
|
||||
|
||||
@@ -57,10 +57,10 @@ categories:
|
||||
en: "Tool"
|
||||
article:
|
||||
en: "Article"
|
||||
topic:
|
||||
topics:
|
||||
type: "new_predefined_array"
|
||||
label:
|
||||
en: "Topic"
|
||||
en: "Topics"
|
||||
help:
|
||||
en: "Select Topic"
|
||||
values:
|
||||
|
||||
@@ -37,10 +37,10 @@ image:
|
||||
en: "Main image description"
|
||||
help:
|
||||
en: "Describe the image for accesibility purposes and for indexation in search engines"
|
||||
topic:
|
||||
topics:
|
||||
type: "new_predefined_array"
|
||||
label:
|
||||
en: "Topic"
|
||||
en: "Topics"
|
||||
help:
|
||||
en: "Select Topic"
|
||||
values:
|
||||
|
||||
@@ -5,7 +5,7 @@ image:
|
||||
description: ''
|
||||
path:
|
||||
categories: []
|
||||
topic:
|
||||
topics:
|
||||
- tech
|
||||
status: pending
|
||||
author: []
|
||||
|
||||
@@ -5,7 +5,7 @@ image:
|
||||
description: ''
|
||||
path:
|
||||
categories: []
|
||||
topic:
|
||||
topics:
|
||||
- community
|
||||
status: in_progress
|
||||
author: []
|
||||
|
||||
@@ -3,25 +3,37 @@ title:
|
||||
type: 'string'
|
||||
description:
|
||||
type: 'string'
|
||||
default: ''
|
||||
url:
|
||||
type: 'string'
|
||||
tags:
|
||||
type: 'array'
|
||||
default: []
|
||||
categories:
|
||||
type: 'array'
|
||||
default: []
|
||||
topics:
|
||||
type: 'array'
|
||||
default: []
|
||||
---
|
||||
|
||||
<div class="card" >
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<a href="{{ url }}">
|
||||
<a href="{{ url | component_escape }}">
|
||||
<p class="fs-2 card-title fw-bold text-primary text-decoration-underline">
|
||||
{{- title -}}
|
||||
</p>
|
||||
</a>
|
||||
<p class="card-text">{{- description -}}</p>
|
||||
{% for tag in tags %}
|
||||
<span class="card-link bg-body-color rounded-3 px-2 py-1 text-white">{{- tag -}}</span>
|
||||
{% endfor %}
|
||||
<p class="card-text text-break">{{- description -}}</p>
|
||||
<div class="d-flex flex-grow-1 w-100">
|
||||
{% for tag in tags %}
|
||||
{% render 'tag.html', **tag %}
|
||||
{% endfor %}
|
||||
{% for category in categories %}
|
||||
{% render 'category.html', **category %}
|
||||
{% endfor %}
|
||||
{% for topic in topics %}
|
||||
{% render 'topic.html', **topic %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
url:
|
||||
type: 'string'
|
||||
title:
|
||||
type: 'string'
|
||||
---
|
||||
<a
|
||||
href="{{ url | component_escape }}"
|
||||
class="card-link bg-category rounded-3 px-2 py-1 text-white text-decoration-none me-2"
|
||||
>
|
||||
{{- title -}}
|
||||
</a>
|
||||
@@ -4,6 +4,9 @@ id:
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
required:
|
||||
type: 'bool'
|
||||
default: false
|
||||
@@ -13,12 +16,16 @@ attributes:
|
||||
class:
|
||||
type: 'string'
|
||||
default: 'form-select'
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
items:
|
||||
type: 'array'
|
||||
---
|
||||
{% assign checked = value %}
|
||||
{% assign base_id = id | append: '_' %}
|
||||
{% assign name = name | default: id | append: '[]' %}
|
||||
{% assign attributes = attributes
|
||||
{% assign general_attributes = attributes
|
||||
| append: ' '
|
||||
| append: 'data-required-checkbox-target="checkbox" data-action="required-checkbox#change"'
|
||||
%}
|
||||
@@ -45,6 +52,8 @@ items:
|
||||
{% assign value = input_item | try: 'value' | default: input_item %}
|
||||
{% assign item = input_item | try: 'item' | default: value %}
|
||||
{% assign id = base_id | append: uuid %}
|
||||
{% assign attributes = general_attributes %}
|
||||
{% assign attributes = checked | equals: value | ternary: 'checked ', '' | append: attributes %}
|
||||
|
||||
{% render 'forms/checkbox.html', name:, id:, value:, item:, attributes: %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,6 +4,9 @@ id:
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
required:
|
||||
type: 'bool'
|
||||
default: false
|
||||
@@ -13,6 +16,9 @@ attributes:
|
||||
class:
|
||||
type: 'string'
|
||||
default: 'form-select'
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
items:
|
||||
type: 'array'
|
||||
other:
|
||||
@@ -22,9 +28,13 @@ other:
|
||||
en: 'Other'
|
||||
ar: 'Other'
|
||||
---
|
||||
{% comment %}
|
||||
TODO: Set the value on the other input if no checkbox matches
|
||||
{% endcomment %}
|
||||
{% assign checked = value %}
|
||||
{% assign base_id = id | append: '_' %}
|
||||
{% assign name = name | default: id | append: '[]' %}
|
||||
{% assign attributes = attributes
|
||||
{% assign general_attributes = attributes
|
||||
| append: ' '
|
||||
| append: 'data-required-checkbox-target="checkbox" data-action="required-checkbox#change"'
|
||||
%}
|
||||
@@ -51,6 +61,7 @@ other:
|
||||
{% assign value = input_item | try: 'value' | default: input_item %}
|
||||
{% assign item = input_item | try: 'item' | default: value %}
|
||||
{% assign id = base_id | append: uuid %}
|
||||
{% assign attributes = checked | equals: value | ternary: 'checked ', '' | append: general_attributes %}
|
||||
|
||||
{% render 'forms/checkbox.html', name:, id:, value:, item:, attributes: %}
|
||||
{% endfor %}
|
||||
@@ -76,6 +87,6 @@ other:
|
||||
data-form-dependencies-condition="checked"
|
||||
hidden
|
||||
>
|
||||
{% render 'forms/text.html', id: other_id, name:, attributes: 'disabled' %}
|
||||
{% render 'forms/text.html', id: other_id, name:, attributes: 'disabled', placeholder: %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,9 @@ id:
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
items:
|
||||
type: 'array'
|
||||
class:
|
||||
@@ -29,6 +32,8 @@ required:
|
||||
render 'forms/input.html',
|
||||
type: 'text',
|
||||
id:,
|
||||
name:,
|
||||
value:
|
||||
class:,
|
||||
list: datalist_id,
|
||||
placeholder:,
|
||||
|
||||
@@ -22,5 +22,11 @@ value:
|
||||
attributes:
|
||||
type: 'string'
|
||||
default: ''
|
||||
maxlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
minlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
---
|
||||
{% render 'forms/input.html', type: 'date', id:, name:, class:, placeholder:, required:, autofocus:, value:, attributes: %}
|
||||
|
||||
@@ -28,6 +28,12 @@ label:
|
||||
es: 'Edad'
|
||||
en: 'Age'
|
||||
ar: 'Age'
|
||||
maxlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
minlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
---
|
||||
{% assign age_attributes = attributes | append: ' ' | append: 'readonly data-dob-target="age"' %}
|
||||
{% assign attributes = 'data-dob-target="date" data-action="dob#update"' %}
|
||||
|
||||
@@ -21,6 +21,12 @@ value:
|
||||
default: ''
|
||||
attributes:
|
||||
type: 'string'
|
||||
default: ''
|
||||
default: 'autocomplete="email"'
|
||||
maxlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
minlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
---
|
||||
{% render 'forms/input.html', id:, type: "email", class:, required:, autofocus:, name:, placeholder:, attributes: %}
|
||||
|
||||
@@ -24,6 +24,11 @@ default_label_class_by_type:
|
||||
{% assign depends_on = field[1] | try: 'depends_on' %}
|
||||
{% assign dependents = field[1] | try: 'dependents' %}
|
||||
{% assign attributes = '' %}
|
||||
{% assign help = field[1] | try: 'help' %}
|
||||
|
||||
{% if help %}
|
||||
{% assign attributes = attributes | append: ' aria-describedby="' | append: id | append: '"' %}
|
||||
{% endif %}
|
||||
|
||||
{% if type == 'end_row' %}
|
||||
</div>
|
||||
@@ -75,10 +80,17 @@ default_label_class_by_type:
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% continue %}
|
||||
{% elsif type == 'lead' %}
|
||||
{% block 'forms/lead.html', id: %}
|
||||
{{ field[1].label[locale] }}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% continue %}
|
||||
{% else %}
|
||||
{% assign class = default_label_class_by_type | try: type %}
|
||||
{% block 'forms/label.html', id:, class: %}
|
||||
{{ field[1].label[locale] }}
|
||||
{{ required | value_if: '*' }}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
@@ -94,7 +106,8 @@ default_label_class_by_type:
|
||||
{% endcomment %}
|
||||
{% case default_value_types[type] %}
|
||||
{% when 'array' %}
|
||||
{% render template, required:, id:, name:, items: default_values, attributes: %}
|
||||
{% assign value = default_values | try: 'value' | default: '' %}
|
||||
{% render template, required:, id:, name:, items: default_values, attributes:, placeholder:, value: %}
|
||||
{% when 'hash' %}
|
||||
{% assign value = default_values | try: 'value' %}
|
||||
{% assign item = default_values | try: 'item' | default: value %}
|
||||
@@ -103,7 +116,16 @@ default_label_class_by_type:
|
||||
{% assign schema = field[1].schema %}
|
||||
{% render template, schema:, default_value_types:, name:, default_label_class_by_type: %}
|
||||
{% else %}
|
||||
{% render template, required:, id:, name:, value: default_values, attributes: %}
|
||||
{% assign placeholder = field[1] | try: 'placeholder' | try: locale | default: '' %}
|
||||
{% assign maxlength = field[1] | try: 'maxlength' %}
|
||||
{% assign minlength = field[1] | try: 'minlength' %}
|
||||
{% render template, required:, id:, name:, value: default_values, attributes:, maxlength:, minlength:, placeholder: %}
|
||||
{% endcase %}
|
||||
|
||||
{% if help %}
|
||||
<div id="{{ id }}-help" class="form-text">
|
||||
{{- help[locale] -}}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -7,8 +7,11 @@ name:
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
required:
|
||||
type: 'bool'
|
||||
default: false
|
||||
---
|
||||
{% render 'forms/input.html', type: 'hidden', id:, name:, value:, required: %}
|
||||
{% render 'forms/input.html', type: 'hidden', id:, name:, value:, required:, placeholder: %}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
id:
|
||||
type: 'string'
|
||||
---
|
||||
<p id="{{ id | escape_once }}" class="lead">
|
||||
{{- yield -}}
|
||||
</p>
|
||||
@@ -19,6 +19,12 @@ value:
|
||||
attributes:
|
||||
type: 'string'
|
||||
default: ''
|
||||
maxlength:
|
||||
type: 'integer'
|
||||
default: 2048
|
||||
minlength:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
---
|
||||
<textarea
|
||||
id="{{ id | escape_once }}"
|
||||
@@ -27,4 +33,8 @@ attributes:
|
||||
{{ attributes }}
|
||||
placeholder="{{ placeholder | escape_once }}"
|
||||
class="{{ class }}"
|
||||
{%- if minlength != 0 -%}
|
||||
minlength="{{ minlength }}"
|
||||
{%- endif -%}
|
||||
maxlength="{{ maxlength }}"
|
||||
>{{- value -}}</textarea>
|
||||
|
||||
@@ -35,4 +35,4 @@ attributes:
|
||||
|
||||
{%- assign attributes = attributes | append: ' ' | append: number_attributes -%}
|
||||
|
||||
{% render 'forms/text.html', id:, class:, placeholder:, required:, autofocus:, name:, value:, placeholder:, minlength:, maxlength:, attributes: %}
|
||||
{% render 'forms/text.html', id:, class:, placeholder:, required:, autofocus:, name:, value:, minlength:, maxlength:, attributes: %}
|
||||
|
||||
@@ -4,6 +4,9 @@ id:
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
required:
|
||||
type: 'bool'
|
||||
default: false
|
||||
@@ -13,17 +16,23 @@ attributes:
|
||||
class:
|
||||
type: 'string'
|
||||
default: 'form-select'
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
items:
|
||||
type: 'array'
|
||||
---
|
||||
{% assign base_id = id | append: '_' %}
|
||||
{% assign name = name | default: id | append: '[]' %}
|
||||
{% assign checked = value %}
|
||||
{% assign general_attributes = attributes %}
|
||||
|
||||
{% for input_item in items %}
|
||||
{% capture uuid %}{% uuid %}{% endcapture %}
|
||||
{% assign value = input_item | try: 'value' | default: input_item %}
|
||||
{% assign item = input_item | try: 'item' | default: value %}
|
||||
{% assign id = base_id | append: uuid %}
|
||||
{% assign attributes = checked | equals: value | ternary: 'checked ', '' | append: general_attributes %}
|
||||
|
||||
{% render 'forms/radio.html', name:, id:, value:, item:, required:, attributes: %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,6 +4,9 @@ id:
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
required:
|
||||
type: 'bool'
|
||||
default: false
|
||||
@@ -13,9 +16,13 @@ attributes:
|
||||
class:
|
||||
type: 'string'
|
||||
default: 'form-select'
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
items:
|
||||
type: 'array'
|
||||
---
|
||||
{% assign selected = value %}
|
||||
<select
|
||||
class="{{ class | escape_once }}"
|
||||
name="{{- name | default: id | escape_once -}}"
|
||||
@@ -23,13 +30,13 @@ items:
|
||||
{{ required | value_if: 'required' }}
|
||||
{{ attributes }}
|
||||
>
|
||||
{% render 'forms/option.html', value: '', item: '' %}
|
||||
{% render 'forms/option.html', value: '', item: placeholder %}
|
||||
|
||||
{% for option in items %}
|
||||
{% assign value = option | try: 'value' | default: option %}
|
||||
{% assign item = option | try: 'item' | default: value %}
|
||||
{% assign depends_on = option | try: 'depends_on' %}
|
||||
{% assign attributes = '' %}
|
||||
{% assign attributes = selected | equals: value | ternary: 'selected', '' %}
|
||||
|
||||
{% if depends_on %}
|
||||
{% capture attributes %}
|
||||
|
||||
@@ -3,5 +3,8 @@ id:
|
||||
type: 'string'
|
||||
name:
|
||||
type: 'string'
|
||||
placeholder:
|
||||
type: 'string'
|
||||
default: ''
|
||||
---
|
||||
{% render 'forms/input.html', type: 'text', id:, name: %}
|
||||
{% render 'forms/input.html', type: 'text', id:, name:, placeholder: %}
|
||||
|
||||
@@ -11,22 +11,18 @@ tags:
|
||||
type: 'array'
|
||||
default: []
|
||||
---
|
||||
|
||||
{% assign words = content | strip_html | number_of_words %}
|
||||
<div class="d-flex flex-column align-items-start justify-content-center w-100">
|
||||
<h1 class="text-primary m-0">{{- title -}}</h1>
|
||||
<p class="fst-italic pt-3 m-0">{{ created_at | date: "%B %d, %Y" }}</p>
|
||||
<small class="fst-italic pb-3">
|
||||
Reading time: {{ words | divided_by: 180.0 | round | at_least: 1 }} minutes
|
||||
</small>
|
||||
<p class="fst-italic pt-3 m-0">{{ created_at | date: '%B %d, %Y' }}</p>
|
||||
<small class="fst-italic pb-3"> Reading time: {{ words | divided_by: 180.0 | round | at_least: 1 }} minutes </small>
|
||||
<div class="d-flex align-items-center justify-content-start pb-2 w-100">
|
||||
{% for tag in tags %}
|
||||
<span class="card-link bg-body-color rounded-3 px-2 py-1 text-white me-2">
|
||||
{{- tag -}}
|
||||
</span>
|
||||
{% render 'tag.html', **tag %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% render 'responsive_img.html',
|
||||
{%
|
||||
render 'responsive_img.html',
|
||||
image:,
|
||||
class: 'w-100 rounded-3'
|
||||
%}
|
||||
|
||||
@@ -11,9 +11,36 @@ categories:
|
||||
type: 'array'
|
||||
tags:
|
||||
type: 'array'
|
||||
topics:
|
||||
type: 'array'
|
||||
status:
|
||||
type: 'array'
|
||||
sort:
|
||||
type: 'array'
|
||||
categories_title:
|
||||
type: 'hash'
|
||||
default:
|
||||
en: 'Any category'
|
||||
topics_title:
|
||||
type: 'hash'
|
||||
default:
|
||||
en: 'Any topic'
|
||||
status_title:
|
||||
type: 'hash'
|
||||
default:
|
||||
en: 'Any status'
|
||||
tags_title:
|
||||
type: 'hash'
|
||||
default:
|
||||
en: 'Any tag'
|
||||
value:
|
||||
type: 'string'
|
||||
default: ''
|
||||
name:
|
||||
type: 'string'
|
||||
default: ''
|
||||
---
|
||||
{% assign selected_value = value %}
|
||||
<form
|
||||
class="w-100 mr-4"
|
||||
action="{{ url | component_escape }}"
|
||||
@@ -21,23 +48,37 @@ sort:
|
||||
data-pagefind-target="form"
|
||||
data-action="pagefind#search:prevent"
|
||||
>
|
||||
<div class="row row-cols-1 row-cols-lg-5">
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'categories', items: categories %}
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'tags', items: tags %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8 mb-3">
|
||||
<input type="search" class="form-control w-100" placeholder="{{ placeholder[locale] | escape_once }}" name="q">
|
||||
</div>
|
||||
|
||||
<div class="col mb-3">
|
||||
<input type="search" class="form-control w-100" placeholder="{{ placeholder[locale] | escape_once }}" name="q">
|
||||
</div>
|
||||
<div class="col-12 col-lg-4 mb-3">
|
||||
{% render 'forms/select.html', id: 'sort', items: sort, value: 'score/desc', placeholder: 'Sort by' %}
|
||||
</div>
|
||||
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'sort', items: sort %}
|
||||
</div>
|
||||
<div class="col-12 col-lg-3 mb-3">
|
||||
{% assign value = name | equals: 'categories' | ternary: selected_value, '' %}
|
||||
{% render 'forms/select.html', id: 'categories', items: categories, placeholder: categories_title[locale], value: %}
|
||||
</div>
|
||||
|
||||
<div class="col mb-3">
|
||||
<input type="submit" class="btn btn-primary" value="{{ placeholder[locale] | escape_once }}">
|
||||
<div class="col-12 col-lg-3 mb-3">
|
||||
{% assign value = name | equals: 'topics' | ternary: selected_value, '' %}
|
||||
{% render 'forms/select.html', id: 'topics', items: topics, placeholder: topics_title[locale], value: %}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-3 mb-3">
|
||||
{% assign value = name | equals: 'status' | ternary: selected_value, '' %}
|
||||
{% render 'forms/select.html', id: 'status', items: status, placeholder: status_title[locale], value: %}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-3 mb-3">
|
||||
{% assign value = name | equals: 'tags' | ternary: selected_value, '' %}
|
||||
{% render 'forms/select.html', id: 'tags', items: tags, placeholder: tags_title[locale], value: %}
|
||||
</div>
|
||||
|
||||
<div class="col-12 mb-3">
|
||||
<input type="submit" class="btn btn-primary w-100" value="{{ placeholder[locale] | escape_once }}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
url:
|
||||
type: 'string'
|
||||
title:
|
||||
type: 'string'
|
||||
---
|
||||
<a
|
||||
href="{{ url | component_escape }}"
|
||||
class="card-link bg-status rounded-3 px-2 py-1 text-white text-decoration-none me-2"
|
||||
>
|
||||
{{- title -}}
|
||||
</a>
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
url:
|
||||
type: 'string'
|
||||
title:
|
||||
type: 'string'
|
||||
---
|
||||
<a
|
||||
href="{{ url | component_escape }}"
|
||||
class="card-link bg-tag rounded-3 px-2 py-1 text-white text-decoration-none me-2"
|
||||
>
|
||||
{{- title -}}
|
||||
</a>
|
||||
@@ -6,12 +6,12 @@ locale:
|
||||
i18n:
|
||||
type: hash
|
||||
---
|
||||
{% assign tags = data.fixtures.card_search.tags %}
|
||||
|
||||
{%assign tags = data.fixtures.card_search.tags %}
|
||||
|
||||
{% render 'card_search.html',
|
||||
{%
|
||||
render 'card_search.html',
|
||||
title: '11node',
|
||||
description: 'bried description of this node. Up to a couple line at most.',
|
||||
url:'#?' ,
|
||||
url:'#?',
|
||||
tags:
|
||||
%}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
url:
|
||||
type: 'string'
|
||||
title:
|
||||
type: 'string'
|
||||
---
|
||||
<a
|
||||
href="{{ url | component_escape }}"
|
||||
class="card-link bg-topic rounded-3 px-2 py-1 text-white text-decoration-none me-2"
|
||||
>
|
||||
{{- title -}}
|
||||
</a>
|
||||
+10
-2
@@ -66,13 +66,21 @@
|
||||
<meta data-pagefind-filter="layout[content]" content="{{ page.layout | escape_once }}">
|
||||
|
||||
{% for category in page.categories %}
|
||||
<meta data-pagefind-filter="categories[content]" content="{{ category | escape_once }}">
|
||||
<meta data-pagefind-filter="categories[content]" content="{{ category.title | escape_once }}">
|
||||
{% endfor %}
|
||||
|
||||
{% for tag in page.tags %}
|
||||
<meta data-pagefind-filter="tags[content]" content="{{ tag | escape_once }}">
|
||||
<meta data-pagefind-filter="tags[content]" content="{{ tag.title | escape_once }}">
|
||||
{% endfor %}
|
||||
|
||||
{% for topic in page.topics %}
|
||||
<meta data-pagefind-filter="topics[content]" content="{{ topic.title | escape_once }}">
|
||||
{% endfor %}
|
||||
|
||||
{% if page.status %}
|
||||
<meta data-pagefind-filter="status[content]" content="{{ page.status.title | escape_once }}">
|
||||
{% endif %}
|
||||
|
||||
<meta
|
||||
data-pagefind-sort="last_modified_at[content]"
|
||||
content="{{ page.last_modified_at | default: page.created_at | default: page.date | default: site.time | date: "%F %T" }}"
|
||||
|
||||
@@ -6,11 +6,7 @@ layout: default
|
||||
|
||||
<article class="h-entry mw-content m-auto container pt-5" itemscope itemtype="http://schema.org/Article">
|
||||
<header>
|
||||
{% render 'sutty/title.html',
|
||||
title: page.title,
|
||||
description: page.description,
|
||||
class: 'text-primary'
|
||||
%}
|
||||
{% render 'sutty/title.html', title: page.title, description: page.description, class: 'text-primary' %}
|
||||
{%- if page.image.path -%}
|
||||
<picture>
|
||||
{% for size in site.images.sizes %}
|
||||
@@ -61,9 +57,9 @@ layout: default
|
||||
{%- endif -%}
|
||||
|
||||
{%- if page.tags %}
|
||||
<span itemprop="keywords" hidden>{{ page.tags | join: ', ' }}</span>
|
||||
<span itemprop="keywords" hidden>{{ page.tags | map: 'title' | join: ', ' }}</span>
|
||||
{%- for tag in page.tags -%}
|
||||
<span hidden class="h-category">{{ tag }}</span>
|
||||
<span hidden class="h-category">{{ tag.title }}</span>
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</footer>
|
||||
|
||||
+3
-7
@@ -5,11 +5,7 @@ layout: default
|
||||
|
||||
<article class="h-entry mw-content m-auto container pt-5" itemscope itemtype="http://schema.org/Article">
|
||||
<header>
|
||||
{% render 'sutty/title.html',
|
||||
title: page.title,
|
||||
description: page.description,
|
||||
class: 'text-primary'
|
||||
%}
|
||||
{% render 'sutty/title.html', title: page.title, description: page.description, class: 'text-primary' %}
|
||||
{%- if page.image.path -%}
|
||||
<picture>
|
||||
{% for size in site.images.sizes %}
|
||||
@@ -57,9 +53,9 @@ layout: default
|
||||
{%- endif -%}
|
||||
|
||||
{%- if page.tags %}
|
||||
<span itemprop="keywords" hidden>{{ page.tags | join: ', ' }}</span>
|
||||
<span itemprop="keywords" hidden>{{ page.tags | map: 'title' | join: ', ' }}</span>
|
||||
{%- for tag in page.tags -%}
|
||||
<span hidden class="h-category">{{ tag }}</span>
|
||||
<span hidden class="h-category">{{ tag.title }}</span>
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</footer>
|
||||
|
||||
+12
-10
@@ -3,18 +3,14 @@ layout: default
|
||||
---
|
||||
{% assign license = site.posts | find: 'layout', 'license' %}
|
||||
|
||||
{%- assign posts = site.posts | where: 'layout', 'post' | sort: 'date'-%}
|
||||
{%- assign posts = site.posts | where: 'layout', 'post' | sort: 'date' -%}
|
||||
|
||||
{% assign prev = page | prev: posts %}
|
||||
{% assign next = page | next: posts %}
|
||||
|
||||
<article class="h-entry mw-content m-auto container pt-5" itemscope itemtype="http://schema.org/Article">
|
||||
<header>
|
||||
{% render 'sutty/title.html',
|
||||
title: page.title,
|
||||
description: page.description,
|
||||
class: 'text-primary'
|
||||
%}
|
||||
{% render 'sutty/title.html', title: page.title, description: page.description, class: 'text-primary' %}
|
||||
{%- if page.image.path -%}
|
||||
<picture>
|
||||
{% for size in site.images.sizes %}
|
||||
@@ -62,20 +58,26 @@ layout: default
|
||||
{%- endif -%}
|
||||
|
||||
{%- if page.tags %}
|
||||
<span itemprop="keywords" hidden>{{ page.tags | join: ', ' }}</span>
|
||||
<span itemprop="keywords" hidden>{{ page.tags | map: 'title' | join: ', ' }}</span>
|
||||
{%- for tag in page.tags -%}
|
||||
<span hidden class="h-category">{{ tag }}</span>
|
||||
<span hidden class="h-category">{{ tag.title }}</span>
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
<div class="d-flex justify-content-center my-3 pt-5">
|
||||
<a class="btn btn-white pl-2 pr-md-5 mr-2 w-50 text-right border-primary border rounded-3 me-1 {{ prev | blank | value_if: 'invisible' }}" href="{{ prev.url }}">
|
||||
<a
|
||||
class="btn btn-white pl-2 pr-md-5 mr-2 w-50 text-right border-primary border rounded-3 me-1 {{ prev | blank | value_if: 'invisible' }}"
|
||||
href="{{ prev.url }}"
|
||||
>
|
||||
<p class="f-14 black border-bottom border-primary">{{ site.i18n.previous }}</p>
|
||||
<p class="text-uppercase f-13 black">
|
||||
{{ prev.title }}
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a class="btn btn-white pr-2 pl-md-5 w-50 text-left border-primary border rounded-3 ms-1 {{ next | blank | value_if: 'invisible' }}" href="{{ next.url }}">
|
||||
<a
|
||||
class="btn btn-white pr-2 pl-md-5 w-50 text-left border-primary border rounded-3 ms-1 {{ next | blank | value_if: 'invisible' }}"
|
||||
href="{{ next.url }}"
|
||||
>
|
||||
<p class="f-14 black border-bottom border-primary">{{ site.i18n.next }}</p>
|
||||
<p class="text-uppercase f-13 black">
|
||||
{{ next.title }}
|
||||
|
||||
+20
-8
@@ -17,17 +17,29 @@ layout: "default"
|
||||
>
|
||||
{% render 'forms/hidden.html', id: 'layout', value: 'recipe' %}
|
||||
<div class="row row-cols-1 row-cols-lg-5">
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'categories', items: site.data.pagefind.app_categories %}
|
||||
<div class="col-12 col-lg-8 mb-3">
|
||||
<input type="search" class="form-control w-100" placeholder="Search" name="q">
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'rating', items: site.data.pagefind.rating %}
|
||||
<div class="col-12 col-lg-4 mb-3">
|
||||
{% render 'forms/select.html',
|
||||
id: 'sort',
|
||||
items: site.data.pagefind.sort,
|
||||
placeholder: 'Sort by',
|
||||
value: 'score/desc'
|
||||
%}
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
<input type="search" class="form-control w-100" placeholder="" name="q">
|
||||
<div class="col-12 col-lg-6 mb-3">
|
||||
{% render 'forms/select.html',
|
||||
id: 'categories',
|
||||
items: site.data.pagefind.app_categories,
|
||||
placeholder: 'Any category'
|
||||
%}
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
{% render 'forms/select.html', id: 'sort', items: site.data.pagefind.sort %}
|
||||
<div class="col-12 col-lg-6 mb-3">
|
||||
{% render 'forms/select.html', id: 'rating', items: site.data.pagefind.rating, placeholder: 'Any rating' %}
|
||||
</div>
|
||||
<div class="col-12 mb-3">
|
||||
<input type="submit" class="btn btn-primary w-100" value="{{ site.i18n.search.placeholder | escape_once }}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -7,6 +7,8 @@ layout: default
|
||||
url: page.url,
|
||||
categories: site.data.pagefind.categories,
|
||||
tags: site.data.pagefind.tags,
|
||||
status: site.data.pagefind.status,
|
||||
topics: site.data.pagefind.topics,
|
||||
sort: site.data.pagefind.sort
|
||||
%}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
<div class="container" data-controller="pagefind">
|
||||
<header>
|
||||
<h1 class="pb-3 text-primary">{{ page.type | capitalize }}: {{ page.title | default: '' | escape }}</h1>
|
||||
</header>
|
||||
|
||||
<div class="mb-3">
|
||||
{% render 'search_box_with_filters.html',
|
||||
url: page.url,
|
||||
categories: site.data.pagefind.categories,
|
||||
tags: site.data.pagefind.tags,
|
||||
status: site.data.pagefind.status,
|
||||
topics: site.data.pagefind.topics,
|
||||
sort: site.data.pagefind.sort,
|
||||
value: page.title,
|
||||
name: page.type
|
||||
%}
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-pagefind-target="container"
|
||||
class="row row-cols-1 row-cols-md-2 w-100 g-0"
|
||||
>
|
||||
{% for post in page.posts %}
|
||||
{% render 'card_search.html', **post %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% render 'sutty/placeholder.html', controller: 'pagefind' %}
|
||||
|
||||
<section data-pagefind-target="empty" class="mx-auto" hidden>
|
||||
<h2>No results</h2>
|
||||
</section>
|
||||
|
||||
<section data-pagefind-target="searching" class="mx-auto" hidden>
|
||||
<h2>Searching...</h2>
|
||||
</section>
|
||||
</div>
|
||||
+17
-2
@@ -5,6 +5,18 @@ require 'open3'
|
||||
# This hook keeps the array of categories updated from the schema
|
||||
# declaration.
|
||||
Jekyll::Hooks.register :site, :post_read, priority: :low do |site|
|
||||
%w[categories topics].each do |field|
|
||||
site.data['pagefind'][field] = site.data['layouts']['document'][field]['values'].map do |value, item|
|
||||
{ value:, item: item[site.locale] }.transform_keys(&:to_s)
|
||||
end
|
||||
end
|
||||
|
||||
%w[status].each do |field|
|
||||
site.data['pagefind'][field] = site.data['layouts']['document'][field]['values'][site.locale].each_pair.map do |value, item|
|
||||
{ value:, item: }.transform_keys(&:to_s)
|
||||
end
|
||||
end
|
||||
|
||||
site.data['pagefind']['categories'] = site.data['layouts']['document']['categories']['values'].map do |value, item|
|
||||
{ value:, item: item[site.locale] }.transform_keys(&:to_s)
|
||||
end
|
||||
@@ -13,8 +25,11 @@ Jekyll::Hooks.register :site, :post_read, priority: :low do |site|
|
||||
{ item:, value: }.transform_keys(&:to_s)
|
||||
end
|
||||
|
||||
site.data['pagefind']['tags'] = site.documents.map { _1['tags'] }.flatten.uniq.compact.sort
|
||||
site.data['pagefind']['app_categories'] = site.collections['recipes'].docs.map { _1['categories'] }.flatten.uniq.compact.sort
|
||||
site.documents.tap do |documents|
|
||||
site.data['pagefind']['tags'] = documents.map { _1['tags'] }.compact.flatten.map { _1['title'] }.uniq.sort
|
||||
end
|
||||
|
||||
site.data['pagefind']['app_categories'] = site.collections['recipes'].docs.map { _1['categories'] }.compact.flatten.map { _1['title'] }.uniq.sort
|
||||
end
|
||||
|
||||
Jekyll::Hooks.register :site, :post_write, priority: :low do |site|
|
||||
|
||||
+52
-10
@@ -1,16 +1,12 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Jekyll::Router.draw do |router|
|
||||
get '/:recipe/', recipe: (site.data.dig('recipes') || {}).keys do |page, recipe|
|
||||
Jekyll::Router.draw do |_router|
|
||||
get '/:recipe/', recipe: (site.data['recipes'] || {}).keys do |page, recipe|
|
||||
page.data['metadata'] = site.data.dig('recipes', recipe)
|
||||
page.data['title'] = recipe
|
||||
page.data['description'] = page['metadata']['description']
|
||||
page.data['uuid'] = recipe
|
||||
|
||||
unless page['metadata']['category'].empty?
|
||||
page.data['categories'] = [ page['metadata']['category'] ]
|
||||
page.data['tags'] = [ page['metadata']['category'] ]
|
||||
end
|
||||
page.data['categories'] = [page['metadata']['category']].compact.map(&:strip).reject(&:empty?)
|
||||
|
||||
collection = site.collections['recipes'] ||= Jekyll::Collection.new(site, 'recipes')
|
||||
collection.docs << page
|
||||
@@ -26,8 +22,9 @@ with Co-op Cloud."
|
||||
|
||||
# Finds every Jekyll::Document whose collection marks it as indexable
|
||||
# and generates a Hash of UUID => Jekyll::Document.
|
||||
indexed_docs = site.collections.slice(*site.data.dig('pagefind', 'collections')).values.map(&:docs).flatten.to_h do |doc|
|
||||
[ doc['uuid'], doc ]
|
||||
indexed_docs = site.collections.slice(*site.data.dig('pagefind',
|
||||
'collections')).values.map(&:docs).flatten.to_h do |doc|
|
||||
[doc['uuid'], doc]
|
||||
end
|
||||
|
||||
# Generates a new page representing every indexed documents and
|
||||
@@ -40,7 +37,7 @@ with Co-op Cloud."
|
||||
end
|
||||
|
||||
indexed_recipes = site.collections['recipes'].docs.to_h do |doc|
|
||||
[ doc['uuid'], doc ]
|
||||
[doc['uuid'], doc]
|
||||
end
|
||||
|
||||
# Generates a new page representing every indexed recipe and
|
||||
@@ -51,4 +48,49 @@ with Co-op Cloud."
|
||||
page.data['page'] = indexed_recipes[indexed_recipe]
|
||||
indexed_recipes[indexed_recipe].data['indexed_recipe'] = page
|
||||
end
|
||||
|
||||
# Emulates Jekyll::Site#categories including every
|
||||
# collection and not just posts, and also slugifies names.
|
||||
#
|
||||
# If you want to add a new field to create collection pages by, add
|
||||
# the field name to the routes hash.
|
||||
slugs = {}
|
||||
routes = { categories: nil, tags: nil, topics: nil, status: nil }
|
||||
site.collections.values.map(&:docs).flatten.each do |doc|
|
||||
routes.each_key do |route|
|
||||
routes[route] ||= Hash.new { |hash, key| hash[key] = [] }
|
||||
|
||||
case doc[route.to_s]
|
||||
when Array
|
||||
doc[route.to_s]&.each do |value|
|
||||
slug = slugs[value] ||= Jekyll::Utils.slugify(value, mode: 'ascii')
|
||||
routes[route][slug] << doc
|
||||
end
|
||||
when String
|
||||
value = doc[route.to_s]
|
||||
slug = slugs[value] ||= Jekyll::Utils.slugify(value, mode: 'ascii')
|
||||
routes[route][slug] << doc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
routes.each_key do |route|
|
||||
# Generates a page per category
|
||||
get "/#{route}/:value/", value: routes[route].keys do |page, value|
|
||||
page.data['type'] = route
|
||||
page.data['title'] = slugs.key(value)
|
||||
page.data['posts'] = routes[route][value]
|
||||
page.data['uuid'] = page.url
|
||||
|
||||
page.data['posts'].each do |doc|
|
||||
case doc.data[route.to_s]
|
||||
when Array
|
||||
doc.data[route.to_s].delete(page['title'])
|
||||
doc.data[route.to_s] << page
|
||||
else
|
||||
doc.data[route.to_s] = page
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,11 @@ weight: 100
|
||||
@use "fonts";
|
||||
@use "@suttyweb/fork-awesome/scss/fork-awesome";
|
||||
|
||||
$category: #fff;
|
||||
$topic: #fff;
|
||||
$tag: #fff;
|
||||
$status: #fff;
|
||||
|
||||
@import "bootstrap/scss/functions";
|
||||
|
||||
{{ site.theme | yaml_to_scss: site.data.layouts.theme }}
|
||||
|
||||
Reference in New Issue
Block a user