Skip to content

Commit

Permalink
Sphinx documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Jun 10, 2021
1 parent 1cdc1f1 commit e9afd81
Show file tree
Hide file tree
Showing 11 changed files with 506 additions and 220 deletions.
178 changes: 5 additions & 173 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,177 +6,9 @@ Flask-Moment
This extension enhances Jinja2 templates with formatting of dates and times
using [moment.js](https://momentjs.com/).

Quick Start
-----------
Resources
---------

Step 1: Initialize the extension:

from flask_moment import Moment
moment = Moment(app)

Step 2: In your `<head>` section of your base template add the following code:

<head>
{{ moment.include_moment() }}
</head>

This extension also supports the [Flask application factory pattern](https://flask.palletsprojects.com/en/latest/patterns/appfactories/)
by allowing you to create a Moment object and then separately initialize it
for an app:

moment = Moment()

def create_app(config):
app = Flask(__name__)
app.config.from_object(config)
# initialize moment on the app within create_app()
moment.init_app(app)

app = create_app(prod_config)

Note that older versions of this extension required jQuery, but this library
isn't needed anymore. The `include_jquery()` function that existed in older
releases has now been removed.

The `include_moment()` methods take some optional arguments. If you pass a
`version` argument to any of these two calls, then the requested version will
be loaded from the default CDN. If you pass `local_js`, then the given local
path will be used to load the library. The `include_moment()` argument takes a
third argument `no_js` that when set to `True` will assume that the Moment
JavaScript library is already loaded and will only add the JavaScript code
that supports this extension.

Step 3: Render timestamps in your template. For example:

<p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>
<p>Something happened {{ moment(then).fromTime(now) }}.</p>
<p>{{ moment(then).calendar() }}.</p>

In the second and third examples template variables `then` and `now` are used.
These must be instances of Python's `datetime` class, and <u>must be "naive"
objects</u>. See the [documentation](https://docs.python.org/3/library/datetime.html)
for a discussion of naive date and time objects. As an example, `now` can be
set as follows:

now = datetime.utcnow()

By default the timestamps will be converted from UTC to the local time in each
client's machine before rendering. To disable the conversion to local time
pass `local=True`.

Note that even though the timestamps are provided in UTC the rendered dates
and times will be in the local time of the client computer, so each users will
always see their local time regardless of where they are located.

Function Reference
------------------

The supported list of display functions is shown below:

- `moment(timestamp=None, local=False).format(format_string=None)`
- `moment(timestamp=None, local=False).fromNow(no_suffix=False)`
- `moment(timestamp=None, local=False).fromTime(another_timesatmp, no_suffix=False)`
- `moment(timestamp=None, local=False).toNow(no_suffix=False)`
- `moment(timestamp=None, local=False).toTime(another_timesatmp, no_suffix=False)`
- `moment(timestamp=None, local=False).calendar()`
- `moment(timestamp=None, local=False).valueOf()`
- `moment(timestamp=None, local=False).unix()`
- `moment(timestamp=None, local=False).diff(another_timesatmp, units='days')`

Consult the [moment.js documentation](https://momentjs.com/) for details on
these functions.

Auto-Refresh
------------

All the display functions take an optional `refresh` argument that when set to
`True` will re-render timestamps every minute. This can be useful for relative
time formats such as the one returned by the `fromNow()` or `fromTime()`
functions. By default refreshing is disabled.

Default Format
--------------

The `format()` function can be invoked without arguments, in which case a
default format of ISO8601 defined by the moment.js library is used. If you
want to set a different default, you can set the `MOMENT_DEFAULT_FORMAT`
variable in the Flask configuration. Consult the [moment.js format documentation](https://momentjs.com/docs/#/displaying/format/)
for a list of accepted tokens.

Internationalization
--------------------

By default dates and times are rendered in English. To change to a different
language add the following line in the `<head>` section after the
`include_moment()` line:

{{ moment.locale("es") }}

The above example sets the language to Spanish. Moment.js supports a large
number of languages, consult the documentation for the list of languages and
their two letter codes.

The extension also supports auto-detection of the client's browser language:

{{ moment.locale(auto_detect=True) }}

Custom locales can also be included as a dictionary:

{{ moment.locale(customizations={ ... }) }}

See the [Moment.js locale customizations](https://momentjs.com/docs/#/i18n/changing-locale/)
documentation for details on how to define a custom locale.

Ajax Support
------------

It is also possible to create Flask-Moment timestamps in Python code, for
cases where a template is not used. This is the syntax:

timestamp = moment.create(datetime.utcnow()).calendar()

The `moment` variable is the `Moment` instance that was created at
initialization time.

A timestamp created in this way is an HTML string that can be returned as part
of a response. For example, here is how a timestamp can be returned in a JSON
object:

return jsonify({ 'timestamp': moment.create(datetime.utcnow()).format('L') })

The Ajax callback in the browser needs to call `flask_moment_render_all()`
each time an element containing a timestamp is added to the DOM. The included
application demonstrates how this is done.

Subresource Integrity(SRI)
-----------
[SRI ](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
is a security feature that enables browsers to verify that resources they
fetch are not maliciously manipulated. To do so a cryptographic hash is
provided that proves integrity.

SRI is enabled by default. If you wish to use another version or want to host
your own javascript, a [separate hash ](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity#tools_for_generating_sri_hashes)
can be provided.

Just add `sri=<YOUR-HASH>` when calling `moment.include_moment()`. If no SRI
hash is provided and you choose to use a non default version of javascript, no
SRI hash will be added.

You can always choose to disable SRI. To do so just set `sri=False`.


Development
-----------

Currently the tests are written using pytest.

pip install pytest

To run the tests from the root directory use: `pytest`.

Reports on coverage with missing line numbers can be generated using pytest-cov:

pip install pytest-cov

And then running: `pytest --cov-report term-missing --cov=flask_moment`
- [Documentation](http://flask-moment.readthedocs.io/en/latest/)
- [PyPI](https://pypi.python.org/pypi/flask-moment)
- [Change Log](https://github.com/miguelgrinberg/flask-moment/blob/main/CHANGES.md)
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
3 changes: 3 additions & 0 deletions docs/_static/css/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.py .class, .py .method, .py .property {
margin-top: 20px;
}
94 changes: 94 additions & 0 deletions docs/advanced.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
Advanced options
----------------

Auto-Refresh
~~~~~~~~~~~~

All the display functions take an optional ``refresh`` argument that when set
to ``True`` will re-render timestamps every minute. If a different time
interval is desired, pass the interval in minutes as the value of the
``refresh`` argument.

This option is useful for relative time formats such as the one returned by
the ``fromNow()`` or ``fromTime()`` functions. For example, the date of a
comment would appear as "a few seconds ago" when the comment was just entered,
but a minute later it would automatically refresh to "a minute ago" without
the need to refresh the page.

By default automatic refreshing is disabled.

Default Format
~~~~~~~~~~~~~~

The ``format()`` function can be invoked without arguments, in which case a
default format of ISO8601 defined by the moment.js library is used. If you
want to set a different default, you can set the ``MOMENT_DEFAULT_FORMAT``
variable in the Flask configuration. Consult the
`moment.js format documentation <https://momentjs.com/docs/#/displaying/format/>`_
for a list of accepted tokens.

Internationalization
~~~~~~~~~~~~~~~~~~~~

By default dates and times are rendered in English. To change to a different
language add the following line in the ``<head>`` section of your template(s),
after the ``include_moment()`` line::

{{ moment.locale("es") }}
The above example sets the language to Spanish. Moment.js supports a large
number of languages. Consult the documentation for the list of languages and
their corresponding two letter codes.

This extension also supports auto-detection of the client's browser language::

{{ moment.locale(auto_detect=True) }}

Custom locales can also be included as a dictionary::

{{ moment.locale(customizations={ ... }) }}

See the `moment.js locale customizations <https://momentjs.com/docs/#/i18n/changing-locale/>`_
documentation for details on how to define a custom locale.

Ajax Support
~~~~~~~~~~~~

It is also possible to create Flask-Moment timestamps in Python code that is
invoked from the client page through Ajax, without the use of Jinja templates::


timestamp = moment.create(datetime.utcnow()).calendar()

The ``moment`` variable is the ``Moment`` instance that was created at
initialization time.

A timestamp created in this way is an HTML string that can be returned as part
of a response. For example, here is how a timestamp can be returned in a JSON
object::

return { 'timestamp': moment.create(datetime.utcnow()).format('L') }

The Ajax callback in the browser needs to call ``flask_moment_render_all()``
each time an element containing a timestamp is added to the DOM. The example
application in the Flask-Moment GitHub repository demonstrates how this is
done.

Subresource Integrity (SRI)
~~~~~~~~~~~~~~~~~~~~~~~~~~~

`SRI <https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity>`_
is a security feature that enables browsers to verify that resources they
fetch are not maliciously manipulated. To do so a cryptographic hash is
provided that proves integrity.

SRI for the moment.js library is enabled by default. If you wish to use
a version different than the one bundled with this extension, or want to host
your own javascript, a `separate hash <https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity#tools_for_generating_sri_hashes>`_
can be provided.

Just add ``sri=<YOUR-HASH>`` when calling ``moment.include_moment()``. If no
SRI hash is provided when a custom moment.js version is used, then SRI
verification is not used.

To disable SRI, pass ``sri=False`` in the ``include_moment()`` call.
5 changes: 5 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
API Reference
-------------

.. autoclass:: flask_moment.moment
:members:
72 changes: 72 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('../src'))


# -- Project information -----------------------------------------------------

project = 'Flask-Moment'
copyright = '2021, Miguel Grinberg'
author = 'Miguel Grinberg'


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

html_css_files = [
'css/custom.css',
]

html_theme_options = {
'github_user': 'miguelgrinberg',
'github_repo': 'flask-moment',
'github_banner': True,
'github_button': True,
'github_type': 'star',
'fixed_sidebar': True,
}

autodoc_default_options = {
'member-order': 'bysource',
}

add_module_names = False
17 changes: 17 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.. Flask-Moment documentation master file, created by
sphinx-quickstart on Wed Jun 9 23:10:03 2021.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Flask-Moment
============

.. toctree::
:maxdepth: 2

quickstart
advanced
api

* :ref:`genindex`
* :ref:`search`
Loading

0 comments on commit e9afd81

Please sign in to comment.