Django/Jinja template indenter

Related tags

Django djhtml
Overview

DjHTML

A pure-Python Django/Jinja template indenter without dependencies.

DjHTML is a fully automatic template indenter that works with mixed HTML/CSS/Javascript templates that contain Django or Jinja template tags. It works similar to other code-formatting tools such as Black and interoperates nicely with pre-commit.

DjHTML is an indenter and not a formatter: it will only add/remove whitespace at the beginning of lines. It will not insert newlines or other characters. The goal is to correctly indent already well-structured templates, not to fix broken ones.

For example, consider the following incorrectly indented template:

<!doctype html>
<html>
    <body>
        {% block content %}
        Hello, world!
        {% endblock %}
        <script>
            $(function() {
            console.log('Hi mom!');
            });
        </script>
    </body>
</html>

This is what it will look like after processing by DjHTML:

<!doctype html>
<html>
    <body>
        {% block content %}
            Hello, world!
        {% endblock %}
        <script>
            $(function() {
                console.log('Hi mom!');
            });
        </script>
    </body>
</html>

Installation

Install DjHTML with the following command:

$ pip install djhtml

Usage

After installation you can indent templates using the djhtml command. The default is to write the indented output to standard out. To modify the source file in-place, use the -i / --in-place option:

$ djhtml -i template.html
reindented template.html
1 template has been reindented.

Normally, the exit status of 0 means everything went well, regardless of whether any files were changed. If any errors were encountered, the exit status indicated the number of problematic files. However, when the option -c / --check is used, the exit status is the number of files that would have changed, but no changes are actually made.

All available options are:

  • -h / --help: show overview of available options
  • -i / --in-place: modify files in-place
  • -c / --check: don't modify files; the exit status is the number of files that would have changed
  • -q / --quiet: don't print any output
  • -t / --tabwidth: set tabwidth (default is 4)
  • -o / --output-file: write output to specified file

fmt:off and fmt:on

You can exclude specific lines from being processed with the {# fmt:off #} and {# fmt:on #} operators:

<div class="
    {# fmt:off #}
      ,-._|\
     /     .\
     \_,--._/
    {# fmt:on #}
"/>

Contents inside <pre> ... </pre>, <!-- ... --->, /* ... */, and {% comment %} ... {% endcomment %} tags are also ignored (depending on the current mode).

Modes

The indenter operates in one of three different modes:

  • DjHTML mode: the default mode. Invoked by using the djhtml command or the pre-commit hook.

  • DjCSS mode. Will be entered when a <style> tag is encountered in DjHTML mode. It can also be invoked directly with the command djcss.

  • DjJS mode. Will be entered when a <script> tag is encountered in DjHTML mode. It can also be invoked directly with the command djjs.

pre-commit configuration

You can use DjHTML as a pre-commit hook to automatically indent your templates upon each commit.

First, install pre-commit:

$ pip install pre-commit
$ pre-commit install

Then, add the following to your .pre-commit-config.yaml:

repos:
- repo: https://github.com/rtts/djhtml
  rev: main
  hooks:
    - id: djhtml

Finally, run the following command:

$ pre-commit autoupdate

Now when you run git commit you will see something like the following output:

$ git commit

djhtml...................................................................Failed
- hook id: djhtml
- files were modified by this hook

reindented template.html
1 template has been reindented.

To inspect the changes that were made, use git diff. If you are happy with the changes, you can commit them normally. If you are not happy, please do the following:

  1. Run SKIP=djhtml git commit to commit anyway, skipping the djhtml hook.

  2. Consider opening an issue with the relevant part of the input file that was incorrectly formatted, and an example of how it should have been formatted.

Your feedback for improving DjHTML is very welcome!

Development

Use your preferred system for setting up a virtualenv, docker environment, or whatever else, then run the following:

python -m pip install -e .[dev]
pre-commit install --install-hooks

Tests can then be run quickly in that environment:

python -m unittest discover -v

Or testing in all available supported environments and linting can be run with nox:

nox
Comments
  • (S)CSS files get no indention

    (S)CSS files get no indention

    Hi there, just checked out this packge after the DjangoCon recommendation. It looks very nice but I guess I found an issue.

    The djcss is removing any indention of my SCSS files which makes it more or less unreadable.

    grafik

    Any ideas how I can fix this? Is there a setting to adjust the indention?

    Thx!

    cannot-reproduce 
    opened by GitRon 21
  • Too many open files when trying to edit multiple files

    Too many open files when trying to edit multiple files

    Hi,

    Thanks for creating this tool. I wanted to update all the templates of my project like this:

    find . -name "*.html" -type f -exec djhtml -i -t2 {} +, But it gives me this error:

    But I get this error:

    usage: djhtml [-h] [-i] [-q] [-t N] [-o filename] [filenames ...]
    djhtml: error: argument filenames: can't open './demo_cms/template/content_news.html': [Errno 24] Too many open files: './demo_cms/template/content_news.html'
    

    Please let me know if I am doing something wrong. I don't want to edit each file by hand.

    opened by vinitkumar 7
  • Config file to ignore some block tags

    Config file to ignore some block tags

    Hello. Firstly thanks for the library, we're trying it out on our projects and really like it so far.

    We have one small problem though. We use a markdown block filter, where the content of the block is parsed as markdown. This means initial space (as djhtml adds) is parsed as a blockquote.

    I know we can use the fmt control comments, but ideally we'd be able to automatically ignore anything inside {% filter markdown %}.

    I was going to raise a PR for this, but I realise that this is a very specific case. Rather than adding exemptions ad-hoc, it might be better to allow configuring blocks to be excluded by the user / project.

    Alternatively, it might be a good idea to slip formatting inside filter blocks altogether - but I don't know enough about how they're used in other projects to know if this would be a good idea.

    I'd be interested to hear your thoughts on this, and would be happy to submit a PR once we've worked out a good solution.

    opened by symroe 6
  • Could you also support jinja templates?

    Could you also support jinja templates?

    Thanks for building this, its been on my wish list for a while.

    I think it wouldn't be too hard to support Jinja2 templates as well (I think the syntax is very similar), would this be something you are willing to do?

    yes 
    opened by pgjones 6
  • Still pretty verbose when running `pre-commit run --all-files`

    Still pretty verbose when running `pre-commit run --all-files`

    When running pre-commit run --all-files it's still pretty verbose:

    djhtml...................................................................Failed
    - hook id: djhtml
    - files were modified by this hook
    
    All done! \o/
    16 templates left unchanged.
    All done! \o/
    16 templates left unchanged.
    All done! \o/
    16 templates left unchanged.
    All done! \o/
    16 templates left unchanged.
    All done! \o/
    16 templates left unchanged.
    All done! \o/
    16 templates left unchanged.
    reindented babeldat/core/templates/partials/_menu.html
    All done! \o/
    1 template reindented, 15 templates left unchanged.
    All done! \o/
    11 templates left unchanged.
    

    FYI: I had 16 files staged, only 4 of them were templates

    opened by richarddewit 5
  • In/dedentation is sometimes incorrect when multiple tags are on the same line

    In/dedentation is sometimes incorrect when multiple tags are on the same line

    Really impressed with this package!

    I noticed that in some of my longer templates in which I have sloppily at times had variations on <div><div> or </div><div> or </div></div> in the same line, things can get a bit weird. It's still valid html, but it's not pretty, and seems to trip djhtml up just a bit.

    For instance, this minimal example:

    {% block css %}
    {% endblock css %}{% block content %}
    <div class="row">
    <div class="input-group date" data-provide="datepicker" data-date-format="yyyy/mm/dd">
    <div class="btn">
    </div></div>
    </div><div>
    <div class="custom-control custom-switch">
    <input type="checkbox" name="filter-changes" id="filter-changes" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_changes %}{% if request.session.manage_filter_changes == True %}checked{% endif %}{% endif %}>
    </div>
    <form class="form-inline">
    <div class="custom-control custom-switch">
    <input type="checkbox" name="filter-status-new" id="filter-status-new" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_status_new %}{% if request.session.manage_filter_status_new == True %}checked{% endif %}{% endif %}>
    </div>
    </form>
    </div>
    {% endblock content %}
    

    I would expect something like this where the final div and {% endblock %} are fully left-justified:

    {% block css %}
    {% endblock css %}{% block content %}
    <div class="row">
        <div class="input-group date" data-provide="datepicker" data-date-format="yyyy/mm/dd">
            <div class="btn">
        </div></div>
    </div><div>
        <div class="custom-control custom-switch">
            <input type="checkbox" name="filter-changes" id="filter-changes" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_changes %}{% if request.session.manage_filter_changes == True %}checked{% endif %}{% endif %}>
        </div>
        <form class="form-inline">
            <div class="custom-control custom-switch">
                <input type="checkbox" name="filter-status-new" id="filter-status-new" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_status_new %}{% if request.session.manage_filter_status_new == True %}checked{% endif %}{% endif %}>
            </div>
        </form>
    </div>
    {% endblock content %}
    

    Or maybe this in a perfect world (though I suspect this would take a LOT more work to achieve via djhtml)

    {% block css %}
    {% endblock css %}
    {% block content %}
    <div class="row">
        <div class="input-group date" data-provide="datepicker" data-date-format="yyyy/mm/dd">
            <div class="btn">
            </div>
        </div>
    </div>
    <div>
        <div class="custom-control custom-switch">
            <input type="checkbox" name="filter-changes" id="filter-changes" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_changes %}{% if request.session.manage_filter_changes == True %}checked{% endif %}{% endif %}>
        </div>
        <form class="form-inline">
            <div class="custom-control custom-switch">
                <input type="checkbox" name="filter-status-new" id="filter-status-new" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_status_new %}{% if request.session.manage_filter_status_new == True %}checked{% endif %}{% endif %}>
            </div>
        </form>
    </div>
    {% endblock content %}
    

    But the actual output is this:

    {% block css %}
    {% endblock css %}{% block content %}
    <div class="row">
        <div class="input-group date" data-provide="datepicker" data-date-format="yyyy/mm/dd">
            <div class="btn">
        </div></div>
    </div><div>
        <div class="custom-control custom-switch">
            <input type="checkbox" name="filter-changes" id="filter-changes" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_changes %}{% if request.session.manage_filter_changes == True %}checked{% endif %}{% endif %}>
            </div>
            <form class="form-inline">
                <div class="custom-control custom-switch">
                    <input type="checkbox" name="filter-status-new" id="filter-status-new" class="custom-control-input fs-nano" value="0" {% if request.session.manage_filter_status_new %}{% if request.session.manage_filter_status_new == True %}checked{% endif %}{% endif %}>
                    </div>
                </form>
            </div>
        {% endblock content %}
    

    I wish I were good enough with parsing/formatting to submit a PR, but hopefully this is at least helpful input.

    bug 
    opened by jacklinke 5
  • Indention bug with Stimulus action

    Indention bug with Stimulus action

    If we have a simple test.html file

    <div>
      <div data-action="click->modal#closeBackground">
      </div>
    </div>
    

    If I run djhtml -i test.html

    I got

    <div>
        <div data-action="click->modal#closeBackground">
        </div>
        </div>
    

    As you can see, the last </div> indention is not correct.

    The click->modal#closeBackground caused this problem.

    opened by michael-yin 4
  • Inserting final newlines isn’t safe

    Inserting final newlines isn’t safe

    I’ve been trying out djhtml on a project and our visual regression testing showed there were differences before-after the reformatting. Upon further inspection this seems to be due to djhtml inserting final newlines in some occurences.

    Looking at the code, this seems to be done on purpose, but there are two issues:

    • Whitespace is often sensitive in HTML – so inserting whitespace where there wasn’t any will change how the page renders.
    • The "insertion of final newline" logic isn’t consistent – djhtml will only add the newline when it made other changes to the template. It won’t add the newline if the template’s formatting is already good.

    Here is a practical example where this happens. With an icon.html template:

    <svg>
    <use href="#my-icon"></use>
    </svg>
    

    And a button.html:

    <button>{% include "icon.html" }My button</button>
    

    Without a final newline in icon.html, this renders as:

    <button<svg>
    <use href="#my-icon"></use>
    </svg>My button</button>
    

    With a final newline (which djhtml inserts) in icon.html, this becomes:

    <button<svg>
        <use href="#my-icon"></use>
    </svg>
    My button</button>
    

    This will cause additional space between the icon and the text. I’ve made a small demo to help illustrate.


    As a resolution to this, my preference would be for djhtml to completely stop inserting final newlines. There are a lot of tools that do this already for people who want to, and it’s not something that can be applied to existing HTML templates with full certainty as the behavior depends on how the partials are used.

    opened by thibaudcolas 4
  • Jinja

    Jinja "whitespace control" is not understood

    Jinja allows one to control whitespace generated by tags. For instance:

    <div>
        {% for item in sequence %}
            {{ item }}
        {%- endfor %}
    </div>
    

    but DjHTML then misses the endfor.

    opened by sjoerdjob 4
  • Support passing directories as command-line arguments

    Support passing directories as command-line arguments

    This makes it easier to run djhtml over a bunch of files in a directory or directories.

    The default suffixes are used as a filter with no configuration allowed (as black seems to work).

    I'm aware of #13 recommending using find ... | xargs or the usage of pre-commit. However, I would like a single command that works on Linux, MacOS, and crucially Windows systems (find and xargs don't work). This would allow me to recommend to users how to use djhtml without having to add lots of additional text explaining how to do it on different systems i.e. djhtml src/templates is all that is needed.

    opened by pgjones 3
  • Indentation of Internet Explorer conditional comment

    Indentation of Internet Explorer conditional comment

    The following HTML:

    <div>
    <!--[if lt IE 9]>
        <p>Not supported</p>
    <![endif]-->
    </div>
    

    gets indented as:

    <div>
        <!--[if lt IE 9]>
        <p>Not supported</p>
    <![endif]-->
    </div>
    

    I would have expected djhtml to apply the same amount of indentation to every line within the div. I imagine it’s IE conditional comments that are causing this – if so they probably don’t warrant any kind of support as they’re well past their expiration date. But I thought I’d report it anyway just in case.

    wontfix 
    opened by thibaudcolas 3
  • Indentation of multiline method chains in script tags

    Indentation of multiline method chains in script tags

    The following JS within HTML:

    <script>
    window.fetch('/test.html')
        .then((html) => {
            document.body.innerHTML = html;
        });
    </script>
    

    gets indented as:

    <script>
        window.fetch('/test.html')
            .then((html) => {
            document.body.innerHTML = html;
        });
    </script>
    

    I would have expected everything within the script tag to get one extra level of indentation. I’m not sure what is causing this, but I at least tried with both a function and the arrow function as above, so I suspect it’s the method chaining that might be the problem.

    help wanted 
    opened by thibaudcolas 1
  • Multi-line tag attribute alignment

    Multi-line tag attribute alignment

    I had some multi-line tags like:

    <img src="/some/long/path"
         alt="Some text">
    

    DjHTML indented them like so:

    <img src="/some/long/path"
      alt="Some text">
    

    I think it would be more nautral to retain the “attribute alignment”, and keep alt at the same column as src.

    Do you think this would be possible?

    Otherwise, the attribue-aligned style I found that works with DjHTML is:

    <img
      src="/some/long/path"
      alt="Some text">
    
    help wanted 
    opened by adamchainz 3
Releases(v1.5.2)
  • v1.5.2(Aug 4, 2022)

    What's Changed

    • Support passing directories as command-line arguments by @pgjones in https://github.com/rtts/djhtml/pull/64

    New Contributors

    • @pgjones made their first contribution in https://github.com/rtts/djhtml/pull/64

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.5.1...v1.5.2

    Source code(tar.gz)
    Source code(zip)
  • v1.5.1(Jun 23, 2022)

    What's Changed

    • Upgrade Black by @rupertbaker in https://github.com/rtts/djhtml/pull/63
    • Fix interpretation of closing arrows in HTML attrs by @rupertbaker in https://github.com/rtts/djhtml/pull/62

    New Contributors

    • @rupertbaker made their first contribution in https://github.com/rtts/djhtml/pull/63

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.5.0...v1.5.1

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Feb 14, 2022)

    What's Changed

    The behavior regarding final newlines has changed between DjHTML v1.4.14 and v1.5.0. It used to always append the final newline, but now this will only happen when the source file already contains a final newline.

    See https://github.com/rtts/djhtml/issues/56 for the discussion that led to this change.

    If you still need the old behavior, the best option is to use https://github.com/pre-commit/pre-commit-hooks#end-of-file-fixer by adding the following to your .pre-commit-config.yaml:

    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: main  # replace with the latest tag on GitHub
      hooks:
        - id: end-of-file-fixer
    

    New Contributors

    • @thibaudcolas pointed out the inconsistent behavior in appending final newlines

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.4.14...v1.5.0

    Source code(tar.gz)
    Source code(zip)
  • v1.4.14(Feb 8, 2022)

    What's Changed

    • Improve pre-commit hook of DjCSS by @DmytroLitvinov in https://github.com/rtts/djhtml/pull/55

    New Contributors

    • @DmytroLitvinov made their first contribution in https://github.com/rtts/djhtml/pull/55

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.4.13...v1.4.14

    Source code(tar.gz)
    Source code(zip)
  • v1.4.13(Feb 6, 2022)

    What's Changed

    • Indent CSS functions by @neruson in https://github.com/rtts/djhtml/pull/52
    • Further indent HTML attribute values by @JaapJoris in https://github.com/rtts/djhtml/pull/54

    New Contributors

    • @neruson made their first contribution in https://github.com/rtts/djhtml/pull/52

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.4.12...v1.4.13

    Source code(tar.gz)
    Source code(zip)
  • v1.4.12(Feb 4, 2022)

  • v1.4.11(Dec 20, 2021)

    What's Changed

    • Update pre-commit hooks by @adamchainz in https://github.com/rtts/djhtml/pull/45
    • Remove linting from nox by @adamchainz in https://github.com/rtts/djhtml/pull/46
    • Add CI run of nox on GitHub Actions by @adamchainz in https://github.com/rtts/djhtml/pull/47
    • Recommend using tags for pre-commit by @adamchainz in https://github.com/rtts/djhtml/pull/44
    • Added support for JavaScript switch statement. by @pawelpel in https://github.com/rtts/djhtml/pull/49

    New Contributors

    • @pawelpel made their first contribution in https://github.com/rtts/djhtml/pull/49

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.4.10...v1.4.11

    Source code(tar.gz)
    Source code(zip)
  • v1.4.10(Nov 9, 2021)

    What's Changed

    • Support Python 3.10 by @adamchainz in https://github.com/rtts/djhtml/pull/43

    New Contributors

    • @adamchainz made their first contribution in https://github.com/rtts/djhtml/pull/43

    Full Changelog: https://github.com/rtts/djhtml/compare/v1.4.9...v1.4.10

    Source code(tar.gz)
    Source code(zip)
  • v1.4.9(Jun 16, 2021)

  • v1.4.8(Jun 7, 2021)

  • v1.4.7(Jun 4, 2021)

  • v1.4.6(Jun 3, 2021)

  • v1.4.5(May 28, 2021)

  • v1.4.4(May 28, 2021)

  • v1.4.3(May 26, 2021)

  • v1.4.2(May 25, 2021)

  • v1.4.1(May 25, 2021)

  • v1.4.0(May 23, 2021)

  • v1.3.0(May 23, 2021)

  • v1.2.2(May 18, 2021)

  • v1.2.1(May 17, 2021)

  • v1.2.0(May 17, 2021)

  • v1.0.2(May 16, 2021)

Owner
Return to the Source
Smart online platforms for innovative businesses + fun side projects
Return to the Source
Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

tzangms 557 Oct 19, 2022
A starter template for building a backend with Django and django-rest-framework using docker with PostgreSQL as the primary DB.

Django-Rest-Template! This is a basic starter template for a backend project with Django as the server and PostgreSQL as the database. About the templ

Akshat Sharma 11 Dec 6, 2022
Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project

Django URL Shortener Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project Install this package to your Dja

Rishav Sinha 4 Nov 18, 2021
Django Phyton Web Apps template themes

Django Phyton Web Apps template themes Free download source code project for build a modern website using django phyton web apps. Documentation instal

Mesin Kasir 4 Dec 15, 2022
Template de desarrollo Django

Template de desarrollo Django Python Django Docker Postgres Nginx CI/CD Descripción del proyecto : Proyecto template de directrices para la estandariz

Diego Esteban 1 Feb 25, 2022
Template for Django Project Using Docker

You want a Django project who use Docker and Docker-compose for Development and for Production ? It's for you !

null 1 Dec 17, 2021
React.JS - Django Application Template

OTS React.JS - DJango Web Application (UNTESTED) This repository servers as a template for creating React.JS - Django Web Applications. Note that the

Darryl See Wei Shen 5 Aug 19, 2022
This is a template tag project for django to calculate in templates , enjoy it

Calculator-Template-Django this is a template tag project for django to calculate in templates , enjoy it Get Started : 1 - Download Source Code 2 - M

null 1 Feb 1, 2022
A Django GraphQL (Graphene) base template

backend A Django GraphQL (Graphene) base template Make sure your IDE/Editor has Black and EditorConfig plugins installed; and configure it lint file a

Reckonsys 4 May 25, 2022
Meta package to combine turbo-django and stimulus-django

Hotwire + Django This repository aims to help you integrate Hotwire with Django ?? Inspiration might be taken from @hotwired/hotwire-rails. We are sti

Hotwire for Django 31 Aug 9, 2022
django-reversion is an extension to the Django web framework that provides version control for model instances.

django-reversion django-reversion is an extension to the Django web framework that provides version control for model instances. Requirements Python 3

Dave Hall 2.8k Jan 2, 2023
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.

Django-environ django-environ allows you to use Twelve-factor methodology to configure your Django application with environment variables. import envi

Daniele Faraglia 2.7k Jan 7, 2023
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Marco Bonetti 909 Dec 26, 2022
Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.

Cookiecutter Django Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. Documentati

Daniel Feldroy 10k Dec 31, 2022
Django project starter on steroids: quickly create a Django app AND generate source code for data models + REST/GraphQL APIs (the generated code is auto-linted and has 100% test coverage).

Create Django App ?? We're a Django project starter on steroids! One-line command to create a Django app with all the dependencies auto-installed AND

imagine.ai 68 Oct 19, 2022
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

lhy 139 Dec 5, 2022
A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, celery and redis.

Django Channels Websocket Chatbot A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, c

Yunbo Shi 8 Oct 28, 2022
A handy tool for generating Django-based backend projects without coding. On the other hand, it is a code generator of the Django framework.

Django Sage Painless The django-sage-painless is a valuable package based on Django Web Framework & Django Rest Framework for high-level and rapid web

sageteam 51 Sep 15, 2022
A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a unique id.

Django-URL-Shortener A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a uni

Rohini Rao 3 Aug 8, 2021