sc0ttj / mdsh

A simple static site generator, using Markdown and Bash
https://sc0ttj.github.io/mdsh/
10 stars 0 forks source link

Liquid filters #78

Closed sc0ttj closed 4 years ago

sc0ttj commented 5 years ago

New feature: liquid-like templating

Summary

You can now do stuff like this:

Filtering variables

  1. In your templates:
{{page_name | uppercase}}

or, a more advanced example:

{{page_name | truncate_words 6 ".." | strip_newlines}}

These filters can also be applied to whole sections (if you must!):

{{page_header | strip_html}}

Filtering with Iterators and Arrays

  1. Normal arrays work as iterators, and can also take filters:
{{#someArray | sort_array desc | where foo | limit 3}}
  {{. | titlecase}}
{{/someArray}}
  1. Associative arrays (hashes) also work:
{{#someAssocArray | sort_array desc | where age >= 18 | limit 3}}
  Hi {{item.name | titlecase}},
  paid {{item.price | money '£'}}
  deliver to {{item.address | uppercase}}
{{/someArray}}

Use filters in your Markdown!

<?bash echo "$something" | replace_all foo bar ;?>

Available filters (so far)

# string filters:

slice                 Slice a string from start ($1) [to end ($2)]
uppercase             Make text upper case
lowercase             Make text lower case
titlecase             Make text title case
capitalize            Capitalise first-letter of string, lower case the rest
slugify               Convert string to slug 
camelcase_to_slug     Convert camel case string to a slug
slug_to_camelcase     Convert a slug to camel case
lstrip                Remove leading whitepace from (left of string)
rstrip                Remove trailing white space (right of string)
strip                 Remove leading and trailing whitespace
strip_html            Remove all HTML tags, keeping the inner content
strip_newlines        Strip newline `\n` characters from string
escape_html           Replace `<p>` with `&lt;p&gt;`
unescape_html         Replace `&lt;p&gt;` WITH `<p>`
json_escape           Make string safe for JSON
newline_to_br         Replace newline characters with `<br>` tags
br_to_newline         Replace `<br>` tags with newline characters
reverse               Reverse a string
replace_first         Replace first occurance of $1 with $2
replace_last,         Replace last occurance of $1 with $2
replace_all           Replace all occurances of $1 with $2
prepend               Prepend a string with another string
append                Append a string with another
truncate              Truncate to given number of chars
truncate_words        Truncate to given number of words
urlencode             Encode string to URL friendly format 
urldecode             Decode string from URL friendly format
rgb2hex               Convert colour values `255 0 0` into `#ff0000`
hex2rgb               Convert colour values `#ff0000` into `255 0 0`
md5                   Replace string with its md5 checksum
sha1                  Replace string with its sha1 checksum
sha256                Replace string with its sha256 checksum
sha512                Replace string with its sha512 checksum

# data filters:

markdown_to_html      convert the given markdown to html
csv_to_markdown       convert the given csv to a markdown table
csv_to_html           convert the given csv to a HTML table
csv_to_json           convert the given csv to json
csv_to_array          turns csv data into one big, flat indexed-array
csv_to_arrays         turns csv data into array of associative
                      arrays. It can be used to iterate over
                      and filter CSV data in your templates:

                      Usage:

                      `cat file.csv | csv_to_arrays | where id "<" 100`

# number filters:

at_least              Sets a minimum value for returned numbers
at_most               Sets a maximum value for returned numbers
decimal_places        Limit number togiven number of decimal places
divided_by            Divide number by given number
minus                 Subtract the given number from the input number
plus                  Add the given number to the input number
modulo                Find remainder after division of input and given number
ordinal               Return the given number in ordinal form (112 => 112th)
to_int                Convert a float to an int
floor                 Round float down to nearest int
ceil                  Round float up to nearest int
pluralize             Append a singular ($1) or plural ($2) to a number.

                      Usage:

                      {{someNumber | pluralize "dog" "dogs"}}
                      {{someNumber | pluralize "ox" "oxen"}}
                      {{someNumber | pluralize "sheep" "sheep"}}

convert               Perform unit conversions. Supported
                      conversions: inches/feet, miles/km,
                      kgs/stones, kgs/lbs, gallons/quarts.

                      Usage:

                      {{someNumber | convert kg to lbs}}
                      {{someNumber | convert miles to km}}

# money filters:

money                    Converts number to money format, with 
                         currency (locale aware)

money_with_currency      Same as above, but appends "GBP", "USD", etc

money_without_currency   Format as previous filters, without currency 
                         symbol or name

without_leading_zeros    Remove ".0*" from end of numbers/strings

                         Examples (when "en_US" is current locale):

                        `echo 2100 | money`   =>   $2,100.00
                        `echo 2100 | money £`  => £2,100.00
                        `echo 2100 | money_with_currency` => $2,100.00 USD
                        `echo 2100 | money_with_currency £ GBP` => £2,100.00 GBP

# date filters:

date_format             Re-format a date, where `format` is: 

                       `basic`              09/31/2019
                       `basic_uk`           31/09/2019
                       `iso8601`            2019-90-31
                       `to_string`          09 Nov 2019
                       `to_long_string`     09 November 2019
                       `rfc822`             Mon, 09 Nov 2019 13:07:54 -0800

                       `format` can also be any valid GNU `date` format:

                       - `"%Y %m %d"`         2019 09 31
                       - `"%d %B %Y"`         31 November 2009
                       - etc..

                       Note that `rfc822` has these, easier aliases:  

                       - `rss`, or `email`

                       Example usage of `date_format`:

                       `{{page_created | date_format iso8601}}`    

                       You can also use `now` to get the current date/time 
                       when the page is built:

                       `{{now | date_format rss}}`    

# html filters

absolute_url           Return the absolute URL to the given file,
                       starting with "http://${blog_domain}${blog_url}".

relative_url           Return a relative URL to the given string, 
                       starting with "${blog_url}" (top dir of blog)

asset_url              Return a relative path to the given file,
                       appended with a timestamp as a query string,
                       for cache busting purposes. Uses `find` to locate 
                       the path to the file (if it exists), else it uses the 
                       given string.

link_tag               Return a `<a href="..">..</a>` tag, linking
                       to the given string. Works well with these
                       other filters: `asset_url`, `absolute_url`,
                       `relative_url`.

                       Usage:

                       {{someURL | link_tag "My link title"}}

time_tag               Return a `<time>` tag, with `datetime`
                       attribute. $1 is required and formats the
                       printed (visible) date. $2 is optional, and
                       formats the `datetime` atrribute. Supports
                       the same options as the `date_format` filter:
                       `basic`, `basic_uk`, `to_string`, `email`, and
                       GNU date format strings like "%d %M %Y %H:%M"

                       Usage:

                       `echo  $some_date | time_tag format attr-format`

                       Examples:

                       `echo  $some_date | time_tag "basic" iso8601`
                       `echo  $some_date | time_tag "%H:%M" rfc2822`
                       `echo  $some_date | time_tag "%Y-%M" "%Y-%M-%d"`

                       `echo  2019-07-13T23:56:01Z | time_tag to_string "%Y-%M-%d"`

                       Outputs:

                      `<time datetime="2019-07-13">13 July, 2019</time>`

script_tag             Return the given content in a script tag

stylesheet_tag         Return the given URL in a stylesheet
                       tag. Works well with `asset_url`.

img_tag                Return the given URL in an img  tag,
                       optionally give $1 to set alt text.

# array filters:

concat                Merge 2 arrays
compact               Remove empty items from array
unique                Remove duplicate items from array
limit                 Limit total items returned to the given number
sort_array            Sort the array 'asc' or 'desc'
exclude               Exclude all items matching the given string
exclude_first         Exclude the first item matching the given string
exclude_last          Exclude the last item matching the given string 
exclude_exact         Exclude all items matching the given string exactly
join_by               Convert an array into a string delimeted by the given string
sort_by               Sort an array by the given key, either ascending or descending.

                      Usage:

                      {{#someAssocArray | sort_by "age" "desc"}}
                          {{item.name}} is {{item.age}}
                      {{/someAssocArray}}

where                 Keep only the array items matching the given 
                      string/expression

                      Examples of the `where` filter:

                      With associative arrays (hashes):

                      - `{{assocArray | where name contains "Smith" }}`
                      - `{{assocArray | where name != "Smith" }}`
                      - `{{assocArray | where name = "Smith" }}`
                      - `{{assocArray | where age >= 20 }}`
                      - `{{assocArray | where age < 60 }}`

                      With simple (indexed) arrays:

                      - `{{array | where contains "Smith" }}`
                      - `{{array | where > 20 }}`

Other things in this PR:

Fixed: cached rebuilds

Added <html> stuff to its own template, and rebuilds now uses a cached version if it exists.

sc0ttj commented 5 years ago

Other, more complex filters for future PRs:

Octopod filters

Data filters

See the "Data folder" issue for useful libraries we could use.

HTML filters

payment_button

Provides a payment button on the given page.

{{page_data | payment_button 'paypal'}} 

would produce something like:

<form action="https://paypal.com..?foo={{page_slug}}" method="post">
    <input type="hidden" name="slug" value="{{page_slug}}" />
    <input type="hidden" name="price" value="{{page_price | money_without_currency}}" />

    <input type="submit" value="Buy now: {{page_price | money}}" />
</form>