├── .coveragerc ├── .editorconfig ├── .github ├── scripts │ └── report_nightly_build_failure.py └── workflows │ ├── nightly.yml │ ├── publish.yml │ ├── ruff.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── docs ├── Makefile ├── authors.rst ├── conf.py ├── contributing.rst ├── history.rst ├── images │ └── mathblock.png ├── index.rst ├── installation.rst ├── make.bat └── readme.rst ├── pyproject.toml ├── ruff.toml ├── src └── wagtailmath │ ├── __init__.py │ ├── apps.py │ ├── blocks.py │ ├── models.py │ ├── static │ └── wagtailmath │ │ └── js │ │ ├── mathjax-textarea-adapter.js │ │ ├── wagtailmath-mathjax-controller.js │ │ └── wagtailmath.js │ ├── templates │ └── wagtailmath │ │ └── mathjaxwidget.html │ ├── templatetags │ ├── __init__.py │ └── wagtailmath.py │ └── widgets.py ├── tests ├── __init__.py ├── conftest.py ├── manage.py ├── test_placeholder.py ├── testapp │ ├── __init__.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ └── templates │ │ └── testapp │ │ └── math_page.html └── testproject │ ├── __init__.py │ ├── settings.py │ └── urls.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | concurrency = multiprocessing, thread 4 | parallel = True 5 | source_pkgs = wagtailmath 6 | omit = 7 | **/migrations/* 8 | tests/* 9 | 10 | [paths] 11 | source = 12 | src/wagtailmath 13 | .tox/py*/**/site-packages 14 | 15 | [report] 16 | show_missing = True 17 | ignore_errors = True 18 | skip_covered = True 19 | 20 | # Regexes for lines to exclude from consideration 21 | exclude_also = 22 | # Have to re-enable the standard pragma 23 | pragma: no cover 24 | 25 | # Don't complain about missing debug-only code: 26 | def __repr__ 27 | if self.debug 28 | if settings.DEBUG 29 | 30 | # Don't complain if tests don't hit defensive assertion code: 31 | raise AssertionError 32 | raise NotImplementedError 33 | 34 | # Don't complain if non-runnable code isn't run: 35 | if 0: 36 | if __name__ == .__main__.: 37 | 38 | # Nor complain about type checking 39 | "if TYPE_CHECKING:", 40 | class .*\bProtocol\): 41 | @(abc\.)?abstractmethod 42 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | 11 | [Makefile] 12 | indent_style = tab 13 | 14 | [*.py] 15 | max_line_length = 88 16 | 17 | [*.{html,rst,md}] 18 | indent_size = 4 19 | 20 | [*.{js,ts,tsx,json,yml,yaml,css,scss}] 21 | indent_size = 2 22 | 23 | [*.md] 24 | trim_trailing_whitespace = false 25 | -------------------------------------------------------------------------------- /.github/scripts/report_nightly_build_failure.py: -------------------------------------------------------------------------------- 1 | """ 2 | Called by GH Actions when the nightly build fails. 3 | 4 | This reports an error to the #nightly-build-failures Slack channel. 5 | """ 6 | 7 | import os 8 | 9 | import requests 10 | 11 | 12 | if "SLACK_WEBHOOK_URL" in os.environ: 13 | print("Reporting to #nightly-build-failures slack channel") 14 | response = requests.post( 15 | os.environ["SLACK_WEBHOOK_URL"], 16 | json={ 17 | "text": "A Nightly build failed. See https://github.com/wagtail-nest/wagtail-polymath/actions/runs/" 18 | + os.environ["GITHUB_RUN_ID"], 19 | }, 20 | timeout=30, 21 | ) 22 | 23 | print("Slack responded with:", response) 24 | 25 | else: 26 | print( 27 | "Unable to report to #nightly-build-failures slack channel because SLACK_WEBHOOK_URL is not set" 28 | ) 29 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: Nightly Wagtail Test 2 | 3 | on: 4 | schedule: 5 | - cron: '0 1 * * *' 6 | # At 01:00, daily 7 | workflow_dispatch: 8 | 9 | env: 10 | WEBHOOK_EXISTS: ${{ secrets.SLACK_WEBHOOK_URL != '' }} 11 | 12 | jobs: 13 | nightly-wagtail-test: 14 | runs-on: ubuntu-latest 15 | if: ${{ vars.WEBHOOK_EXISTS }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: '3.11' 22 | 23 | - run: git clone https://github.com/wagtail/wagtail.git 24 | 25 | - run: python -m pip install flit 26 | - run: flit install --deps production --extras testing 27 | - run: python -m pip install ./wagtail 28 | 29 | - run: python tests/manage.py test 30 | 31 | - name: Report failure 32 | run: | 33 | python -m pip install requests 34 | python ./.github/scripts/report_nightly_build_failure.py 35 | if: ${{ failure() && env.WEBHOOK_EXISTS == 'true' }} 36 | env: 37 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 38 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # See https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/ 2 | # for a detailed guide 3 | name: Publish to PyPI 4 | 5 | on: 6 | release: 7 | types: [published] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read # to fetch code (actions/checkout) 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Set up Python 3.11 20 | uses: actions/setup-python@v5 21 | with: 22 | python-version: '3.11' 23 | 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | python -m pip install flit 28 | python -m flit install --symlink 29 | 30 | - name: Build 31 | run: python -m flit build 32 | 33 | - uses: actions/upload-artifact@v4 34 | with: 35 | path: ./dist 36 | 37 | publish: 38 | needs: build 39 | runs-on: ubuntu-latest 40 | permissions: 41 | contents: none 42 | id-token: write # required for trusted publishing 43 | environment: publish 44 | steps: 45 | - uses: actions/download-artifact@v4 46 | 47 | - name: Publish to PyPI 48 | uses: pypa/gh-action-pypi-publish@release/v1 49 | with: 50 | packages-dir: artifact/ 51 | print-hash: true 52 | -------------------------------------------------------------------------------- /.github/workflows/ruff.yml: -------------------------------------------------------------------------------- 1 | name: Ruff 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - 'stable/**' 8 | pull_request: 9 | branches: [main] 10 | 11 | jobs: 12 | ruff: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | # Keep in sync with .pre-comit-config.yaml 19 | - run: python -Im pip install --user ruff==0.4.9 20 | 21 | - name: Run ruff 22 | working-directory: ./src 23 | run: ruff --output-format=github wagtailmath 24 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: polymath CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - 'stable/**' 8 | 9 | pull_request: 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | permissions: 16 | contents: read # to fetch code (actions/checkout) 17 | 18 | jobs: 19 | lint: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - name: Set up Python 3.12 26 | uses: actions/setup-python@v5 27 | with: 28 | python-version: '3.12' 29 | - uses: pre-commit/action@v3.0.1 30 | 31 | test-sqlite: 32 | runs-on: ubuntu-latest 33 | needs: lint 34 | strategy: 35 | matrix: 36 | python: ['3.8', '3.9', '3.10', '3.11', '3.12'] 37 | 38 | steps: 39 | - uses: actions/checkout@v4 40 | - name: Set up Python ${{ matrix.python }} 41 | uses: actions/setup-python@v5 42 | with: 43 | python-version: ${{ matrix.python }} 44 | - name: Install 45 | run: | 46 | python -Im pip install --upgrade pip setuptools wheel 47 | python -Im pip install .[ci] 48 | - name: Test 49 | run: tox 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Directories in the project root 2 | /.venv/ 3 | /venv/ 4 | /.vscode/ 5 | /.tox/ 6 | /build/ 7 | /dist/ 8 | 9 | # Files in the project root 10 | /.coverage* 11 | !/.coveragerc 12 | 13 | # Files anywhere 14 | *.db 15 | *.py[co] 16 | *.swp 17 | *.egg-info 18 | .env 19 | 20 | # Directories anywhere 21 | .ruff_cache/ 22 | .pytest_cache/ 23 | __pycache__/ 24 | test-media/ 25 | test-static/ 26 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | ci: 2 | autofix_prs: false 3 | 4 | default_language_version: 5 | python: python3 6 | 7 | repos: 8 | - repo: https://github.com/pre-commit/pre-commit-hooks 9 | rev: v4.6.0 10 | hooks: 11 | - id: check-added-large-files 12 | - id: check-case-conflict 13 | - id: check-json 14 | - id: check-merge-conflict 15 | - id: check-symlinks 16 | - id: check-toml 17 | - id: check-yaml 18 | args: ['--unsafe'] 19 | - id: end-of-file-fixer 20 | - id: trailing-whitespace 21 | - repo: https://github.com/astral-sh/ruff-pre-commit 22 | # ruff config is in ruff.toml. Keep in sync with .github/workflows/ruff.yml 23 | rev: v0.4.9 24 | hooks: 25 | - id: ruff 26 | args: [--fix] 27 | - id: ruff-format 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # wagtail-polymath Changelog 2 | 3 | ## Unreleased 4 | 5 | ## 1.3.0 (2024-07-04) 6 | 7 | - Updated project tooling: 8 | - added linting with ruff 9 | - switched to using flit for packaging 10 | - added GitHub Actions, including PyPI trusted publishing 11 | - added tests skeleton 12 | - Added support for Wagtail 5.2+ 13 | - Dropped support for Wagtail < 5.2, Django < 4.2 14 | 15 | ## 1.2.0 (2021-05-18) 16 | 17 | - Upgrade to newer version of Django + Wagtail 18 | 19 | ## 0.1.0 (2017-04-24) 20 | 21 | - First release on PyPI. 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Wagtail Polymath 2 | 3 | Thank you for considering to help Wagtail Polymath. 4 | 5 | We welcome all support, whether on bug reports, code, reviews, tests, documentation, translations or just feature requests. 6 | 7 | ## Working on an issue 8 | 9 | 👉 If an issue isn’t being worked on by anyone, go for it! **No need to ask "please assign me this issue".** Add a comment to claim the issue once you’re ready to start. 10 | 11 | Always start work on issues or features by creating a new git branch from the most up-to-date `main` branch. 12 | When ready, open a pull request with as detailed a description as possible, including a reference to the GitHub issue 13 | number that the PR addresses or relates to. Use `Fixes #123`, `Closes #123` or `Addresses #123` when fixing an issue. 14 | Use `Relates to #123` or `Part of #123` if addressing a small part of a multi-item issue. 15 | 16 | 17 | ## Reporting bugs 18 | 19 | To report bugs, use our [issue tracker](https://github.com/wagtail-nest/wagtail-polymath/issues). 20 | 21 | 22 | ## Feature requests 23 | 24 | Use our [issue tracker](https://github.com/wagtail-nest/wagtail-polymath/issues) for feature requests 25 | 26 | 27 | ## Code reviews 28 | 29 | We welcome code reviews from everyone. You can see a list of [pull requests](https://github.com/wagtail-nest/wagtail-polymath/pulls) 30 | 31 | 32 | ## Triaging issues 33 | 34 | We welcome help with triaging issues and pull requests. You can help by: 35 | 36 | - Adding more details or your own perspective to bug reports or feature requests. 37 | - Reviewing or otherwise offering your feedback on pull requests. 38 | 39 | 40 | ## Development instructions 41 | 42 | ### Install 43 | 44 | To make changes to this project, first clone this repository: 45 | 46 | ```sh 47 | git clone git@github.com:wagtail-nest/wagtail-polymath.git 48 | cd wagtail-polymath 49 | ``` 50 | 51 | With your preferred virtualenv activated, install testing dependencies: 52 | 53 | ```sh 54 | pip install -e '.[testing]' -U 55 | ``` 56 | 57 | ### pre-commit 58 | 59 | Note that this project uses [pre-commit](https://github.com/pre-commit/pre-commit). To set up locally: 60 | 61 | ```shell 62 | # if you don't have it yet, globally 63 | $ pip install pre-commit 64 | # go to the project directory 65 | $ cd wagtail-polymath 66 | # initialize pre-commit 67 | $ pre-commit install 68 | 69 | # Optional, run all checks once for this, then the checks will run only on the changed files 70 | $ pre-commit run --all-files 71 | ``` 72 | 73 | ### How to run tests 74 | 75 | Now you can run tests as shown below: 76 | 77 | ```sh 78 | tox 79 | ``` 80 | 81 | or, you can run them for a specific environment `tox -e python3.11-django4.2-wagtail5.2` or specific test 82 | `tox -e python3.11-django4.2-wagtail5.2 -- tests/test_placeholder.py` 83 | 84 | To run the test app interactively, use `tox -e interactive`, visit `http://127.0.0.1:8020/admin/` and log in with `admin`/`changeme`. 85 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Maintainers 4 | 5 | - The Wagtail Nest crew 6 | 7 | ## Original development Lead 8 | 9 | - James Ramm (jamessramm@gmail.com) 10 | 11 | # Contributors 12 | 13 | - Andre Bar\'yudin (https://www.baryudin.com/) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017-2024, James Ramm 4 | Copyright (c) 2024, Wagtail Nest contributors 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | define BROWSER_PYSCRIPT 4 | import os, webbrowser, sys 5 | try: 6 | from urllib import pathname2url 7 | except: 8 | from urllib.request import pathname2url 9 | 10 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 11 | endef 12 | export BROWSER_PYSCRIPT 13 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 14 | 15 | help: 16 | @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}' 17 | 18 | clean: clean-build clean-pyc 19 | 20 | clean-build: ## remove build artifacts 21 | rm -fr build/ 22 | rm -fr dist/ 23 | rm -fr *.egg-info 24 | 25 | clean-pyc: ## remove Python file artifacts 26 | find . -name '*.pyc' -exec rm -f {} + 27 | find . -name '*.pyo' -exec rm -f {} + 28 | find . -name '*~' -exec rm -f {} + 29 | 30 | lint: ## check style with flake8 31 | flake8 wagtailmath tests 32 | 33 | test: ## run tests quickly with the default Python 34 | python runtests.py tests 35 | 36 | test-all: ## run tests on every Python version with tox 37 | tox 38 | 39 | coverage: ## check code coverage quickly with the default Python 40 | coverage run --source wagtailmath runtests.py tests 41 | coverage report -m 42 | coverage html 43 | open htmlcov/index.html 44 | 45 | docs: ## generate Sphinx HTML documentation, including API docs 46 | rm -f docs/wagtailmath.rst 47 | rm -f docs/modules.rst 48 | sphinx-apidoc -o docs/ wagtailmath 49 | $(MAKE) -C docs clean 50 | $(MAKE) -C docs html 51 | $(BROWSER) docs/_build/html/index.html 52 | 53 | release: clean ## package and upload a release 54 | python setup.py sdist upload 55 | python setup.py bdist_wheel upload 56 | 57 | sdist: clean ## package 58 | python setup.py sdist 59 | ls -l dist 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wagtail-polymath 2 | 3 | [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) 4 | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) 5 | [![PyPI version](https://img.shields.io/pypi/v/wagtailmath.svg?style=flat)](https://pypi.org/project/wagtailmath) 6 | [![Build status](https://img.shields.io/github/actions/workflow/status/wagtail-nest/wagtail-polymath/test.yml?branch=main)](https://github.com/wagtail-nest/wagtail-polymath/actions) 7 | 8 | ## Links 9 | 10 | - [Documentation](https://github.com/wagtail-nest/wagtail-polymath/blob/main/README.md) 11 | - [Changelog](https://github.com/wagtail-nest/wagtail-polymath/blob/main/CHANGELOG.md) 12 | - [Contributing](https://github.com/wagtail-nest/wagtail-polymath/blob/main/CONTRIBUTING.md) 13 | - [Discussions](https://github.com/wagtail-nest/wagtail-polymath/discussions) 14 | - [Security](https://github.com/wagtail-nest/wagtail-polymath/security) 15 | 16 | wagtail-polymath allows you to write equations in your 17 | [Wagtail](https://github.com/wagtail/wagtail) content using markup and 18 | render them beautifully. 19 | 20 | wagtail-polymath provides a `MathBlock` so you can write equations in markup 21 | (TeX, MathML, ASCIIMath) and render them with MathJax. It features a 22 | live preview: 23 | 24 | ![](https://github.com/wagtail-nest/wagtail-polymath/blob/main/docs/images/mathblock.png) 25 | 26 | `MathBlock` uses MathJax for rendering so there is very little to do on 27 | the front end. Simply include the MathJax JS and render the raw 28 | `MathBlock` content as you would for any other streamfield plain text 29 | block. 30 | 31 | wagtail-polymath even includes a template tag to include the MathJax JS for 32 | you from a CDN. By default, MathJax is configured to accept all 33 | recognised markup (TeX, MathML, ASCIIMath) and renders them to HTML. To 34 | change the configuration, you can pass the desired config command to the 35 | templatetag. See the [MathJax documentation](https://docs.mathjax.org/en/v2.7-latest/config-files.html#combined-configurations) 36 | for possible configurations. 37 | 38 | For help on using the markup languages see the relevant MathJax 39 | documentation (e.g. https://docs.mathjax.org/en/v2.7-latest/tex.html) and 40 | the markup language-specific documentation (e.g. https://en.wikibooks.org/wiki/LaTeX) 41 | 42 | ## Quickstart 43 | 44 | Install wagtailmath: 45 | 46 | pip install wagtailmath 47 | 48 | Add it to your `INSTALLED_APPS`: 49 | 50 | ```python 51 | # settings.py 52 | 53 | INSTALLED_APPS = ( 54 | # ... 55 | "wagtailmath", 56 | # ... 57 | ) 58 | ``` 59 | 60 | Use `MathBlock` in your `StreamField` content: 61 | 62 | ```python 63 | from wagtailmath.blocks import MathBlock 64 | 65 | class MyPage(Page): 66 | body = StreamField([ 67 | ('heading', blocks.CharBlock(classname="full title")), 68 | ('paragraph', blocks.RichTextBlock()), 69 | ('equation', MathBlock()) 70 | ]) 71 | ``` 72 | 73 | Use the `mathjax` template tag in your front end template to load the 74 | MathJax library: 75 | 76 | ```django+html 77 | {% load wagtailmath %} 78 | ... 79 | 80 | 81 | ``` 82 | 83 | 84 | ## Contributing 85 | 86 | All contributions are welcome! See [CONTRIBUTING.md](https://github.com/wagtail-nest/wagtail-polymath/blob/main/CONTRIBUTING.md) 87 | 88 | Supported versions: 89 | 90 | - Python 3.8, 3.9, 3.10, 3.11, 3.12 91 | - Django 4.2, 5.0 92 | - Wagtail 5.2 (LTS), 6.0, 6.1 93 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | We take the security of Wagtail, and related packages we maintain, seriously. If you have found a security issue with any of our projects please email us at security@wagtail.org so we can work together to find and patch the issue. We appreciate responsible disclosure with any security related issues, so please contact us first before creating a Github issue. 4 | 5 | If you want to send an encrypted email (optional), refer to https://wagtail.org/.well-known/security.txt for details. 6 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/complexity.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/complexity.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/complexity" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/complexity" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../AUTHORS.rst 2 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # 2 | # complexity documentation build configuration file, created by 3 | # sphinx-quickstart on Tue Jul 9 22:26:36 2013. 4 | # 5 | # This file is execfile()d with the current directory set to its containing dir. 6 | # 7 | # Note that not all possible configuration values are present in this 8 | # autogenerated file. 9 | # 10 | # All configuration values have a default; values that are commented out 11 | # serve to show the default. 12 | 13 | import os 14 | import sys 15 | 16 | import mathblock 17 | 18 | 19 | # If extensions (or modules to document with autodoc) are in another directory, 20 | # add these directories to sys.path here. If the directory is relative to the 21 | # documentation root, use os.path.abspath to make it absolute, like shown here. 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | 24 | cwd = os.getcwd() 25 | parent = os.path.dirname(cwd) 26 | sys.path.append(parent) 27 | 28 | 29 | # -- General configuration ----------------------------------------------------- 30 | 31 | # If your documentation needs a minimal Sphinx version, state it here. 32 | # needs_sphinx = '1.0' 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be extensions 35 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 36 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode"] 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ["_templates"] 40 | 41 | # The suffix of source filenames. 42 | source_suffix = ".rst" 43 | 44 | # The encoding of source files. 45 | # source_encoding = 'utf-8-sig' 46 | 47 | # The master toctree document. 48 | master_doc = "index" 49 | 50 | # General information about the project. 51 | project = "wagtail_mathblock" 52 | copyright = "2017, James Ramm" 53 | 54 | # The version info for the project you're documenting, acts as replacement for 55 | # |version| and |release|, also used in various other places throughout the 56 | # built documents. 57 | # 58 | # The short X.Y version. 59 | version = mathblock.__version__ 60 | # The full version, including alpha/beta/rc tags. 61 | release = mathblock.__version__ 62 | 63 | # The language for content autogenerated by Sphinx. Refer to documentation 64 | # for a list of supported languages. 65 | # language = None 66 | 67 | # There are two options for replacing |today|: either, you set today to some 68 | # non-false value, then it is used: 69 | # today = '' 70 | # Else, today_fmt is used as the format for a strftime call. 71 | # today_fmt = '%B %d, %Y' 72 | 73 | # List of patterns, relative to source directory, that match files and 74 | # directories to ignore when looking for source files. 75 | exclude_patterns = ["_build"] 76 | 77 | # The reST default role (used for this markup: `text`) to use for all documents. 78 | # default_role = None 79 | 80 | # If true, '()' will be appended to :func: etc. cross-reference text. 81 | # add_function_parentheses = True 82 | 83 | # If true, the current module name will be prepended to all description 84 | # unit titles (such as .. function::). 85 | # add_module_names = True 86 | 87 | # If true, sectionauthor and moduleauthor directives will be shown in the 88 | # output. They are ignored by default. 89 | # show_authors = False 90 | 91 | # The name of the Pygments (syntax highlighting) style to use. 92 | pygments_style = "sphinx" 93 | 94 | # A list of ignored prefixes for module index sorting. 95 | # modindex_common_prefix = [] 96 | 97 | # If true, keep warnings as "system message" paragraphs in the built documents. 98 | # keep_warnings = False 99 | 100 | 101 | # -- Options for HTML output --------------------------------------------------- 102 | 103 | # The theme to use for HTML and HTML Help pages. See the documentation for 104 | # a list of builtin themes. 105 | html_theme = "default" 106 | 107 | # Theme options are theme-specific and customize the look and feel of a theme 108 | # further. For a list of options available for each theme, see the 109 | # documentation. 110 | # html_theme_options = {} 111 | 112 | # Add any paths that contain custom themes here, relative to this directory. 113 | # html_theme_path = [] 114 | 115 | # The name for this set of Sphinx documents. If None, it defaults to 116 | # " v documentation". 117 | # html_title = None 118 | 119 | # A shorter title for the navigation bar. Default is the same as html_title. 120 | # html_short_title = None 121 | 122 | # The name of an image file (relative to this directory) to place at the top 123 | # of the sidebar. 124 | # html_logo = None 125 | 126 | # The name of an image file (within the static path) to use as favicon of the 127 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 128 | # pixels large. 129 | # html_favicon = None 130 | 131 | # Add any paths that contain custom static files (such as style sheets) here, 132 | # relative to this directory. They are copied after the builtin static files, 133 | # so a file named "default.css" will overwrite the builtin "default.css". 134 | html_static_path = ["_static"] 135 | 136 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 137 | # using the given strftime format. 138 | # html_last_updated_fmt = '%b %d, %Y' 139 | 140 | # If true, SmartyPants will be used to convert quotes and dashes to 141 | # typographically correct entities. 142 | # html_use_smartypants = True 143 | 144 | # Custom sidebar templates, maps document names to template names. 145 | # html_sidebars = {} 146 | 147 | # Additional templates that should be rendered to pages, maps page names to 148 | # template names. 149 | # html_additional_pages = {} 150 | 151 | # If false, no module index is generated. 152 | # html_domain_indices = True 153 | 154 | # If false, no index is generated. 155 | # html_use_index = True 156 | 157 | # If true, the index is split into individual pages for each letter. 158 | # html_split_index = False 159 | 160 | # If true, links to the reST sources are added to the pages. 161 | # html_show_sourcelink = True 162 | 163 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 164 | # html_show_sphinx = True 165 | 166 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 167 | # html_show_copyright = True 168 | 169 | # If true, an OpenSearch description file will be output, and all pages will 170 | # contain a tag referring to it. The value of this option must be the 171 | # base URL from which the finished HTML is served. 172 | # html_use_opensearch = '' 173 | 174 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 175 | # html_file_suffix = None 176 | 177 | # Output file base name for HTML help builder. 178 | htmlhelp_basename = "wagtail-mathblockdoc" 179 | 180 | 181 | # -- Options for LaTeX output -------------------------------------------------- 182 | 183 | latex_elements = { 184 | # The paper size ('letterpaper' or 'a4paper'). 185 | #'papersize': 'letterpaper', 186 | # The font size ('10pt', '11pt' or '12pt'). 187 | #'pointsize': '10pt', 188 | # Additional stuff for the LaTeX preamble. 189 | #'preamble': '', 190 | } 191 | 192 | # Grouping the document tree into LaTeX files. List of tuples 193 | # (source start file, target name, title, author, documentclass [howto/manual]). 194 | latex_documents = [ 195 | ( 196 | "index", 197 | "wagtail-mathblock.tex", 198 | "wagtail_mathblock Documentation", 199 | "James Ramm", 200 | "manual", 201 | ), 202 | ] 203 | 204 | # The name of an image file (relative to this directory) to place at the top of 205 | # the title page. 206 | # latex_logo = None 207 | 208 | # For "manual" documents, if this is true, then toplevel headings are parts, 209 | # not chapters. 210 | # latex_use_parts = False 211 | 212 | # If true, show page references after internal links. 213 | # latex_show_pagerefs = False 214 | 215 | # If true, show URL addresses after external links. 216 | # latex_show_urls = False 217 | 218 | # Documents to append as an appendix to all manuals. 219 | # latex_appendices = [] 220 | 221 | # If false, no module index is generated. 222 | # latex_domain_indices = True 223 | 224 | 225 | # -- Options for manual page output -------------------------------------------- 226 | 227 | # One entry per manual page. List of tuples 228 | # (source start file, name, description, authors, manual section). 229 | man_pages = [ 230 | ("index", "wagtail-mathblock", "wagtail_mathblock Documentation", ["James Ramm"], 1) 231 | ] 232 | 233 | # If true, show URL addresses after external links. 234 | # man_show_urls = False 235 | 236 | 237 | # -- Options for Texinfo output ------------------------------------------------ 238 | 239 | # Grouping the document tree into Texinfo files. List of tuples 240 | # (source start file, target name, title, author, 241 | # dir menu entry, description, category) 242 | texinfo_documents = [ 243 | ( 244 | "index", 245 | "wagtail-mathblock", 246 | "wagtail_mathblock Documentation", 247 | "James Ramm", 248 | "wagtail-mathblock", 249 | "One line description of project.", 250 | "Miscellaneous", 251 | ), 252 | ] 253 | 254 | # Documents to append as an appendix to all manuals. 255 | # texinfo_appendices = [] 256 | 257 | # If false, no module index is generated. 258 | # texinfo_domain_indices = True 259 | 260 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 261 | # texinfo_show_urls = 'footnote' 262 | 263 | # If true, do not generate a @detailmenu in the "Top" node's menu. 264 | # texinfo_no_detailmenu = False 265 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /docs/history.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../HISTORY.rst 2 | -------------------------------------------------------------------------------- /docs/images/mathblock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/docs/images/mathblock.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. complexity documentation master file, created by 2 | sphinx-quickstart on Tue Jul 9 22:26:36 2013. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to wagtailmath's documentation! 7 | ================================================================= 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | readme 15 | installation 16 | contributing 17 | authors 18 | history 19 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | At the command line:: 6 | 7 | $ easy_install wagtailmath 8 | 9 | Or, if you have virtualenvwrapper installed:: 10 | 11 | $ mkvirtualenv wagtailmath 12 | $ pip install wagtailmath 13 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | goto end 41 | ) 42 | 43 | if "%1" == "clean" ( 44 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 45 | del /q /s %BUILDDIR%\* 46 | goto end 47 | ) 48 | 49 | 50 | %SPHINXBUILD% 2> nul 51 | if errorlevel 9009 ( 52 | echo. 53 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 54 | echo.installed, then set the SPHINXBUILD environment variable to point 55 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 56 | echo.may add the Sphinx directory to PATH. 57 | echo. 58 | echo.If you don't have Sphinx installed, grab it from 59 | echo.http://sphinx-doc.org/ 60 | exit /b 1 61 | ) 62 | 63 | if "%1" == "html" ( 64 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 68 | goto end 69 | ) 70 | 71 | if "%1" == "dirhtml" ( 72 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 76 | goto end 77 | ) 78 | 79 | if "%1" == "singlehtml" ( 80 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 84 | goto end 85 | ) 86 | 87 | if "%1" == "pickle" ( 88 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can process the pickle files. 92 | goto end 93 | ) 94 | 95 | if "%1" == "json" ( 96 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 97 | if errorlevel 1 exit /b 1 98 | echo. 99 | echo.Build finished; now you can process the JSON files. 100 | goto end 101 | ) 102 | 103 | if "%1" == "htmlhelp" ( 104 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 105 | if errorlevel 1 exit /b 1 106 | echo. 107 | echo.Build finished; now you can run HTML Help Workshop with the ^ 108 | .hhp project file in %BUILDDIR%/htmlhelp. 109 | goto end 110 | ) 111 | 112 | if "%1" == "qthelp" ( 113 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 117 | .qhcp project file in %BUILDDIR%/qthelp, like this: 118 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\complexity.qhcp 119 | echo.To view the help file: 120 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\complexity.ghc 121 | goto end 122 | ) 123 | 124 | if "%1" == "devhelp" ( 125 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished. 129 | goto end 130 | ) 131 | 132 | if "%1" == "epub" ( 133 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 137 | goto end 138 | ) 139 | 140 | if "%1" == "latex" ( 141 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 145 | goto end 146 | ) 147 | 148 | if "%1" == "latexpdf" ( 149 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 150 | cd %BUILDDIR%/latex 151 | make all-pdf 152 | cd %BUILDDIR%/.. 153 | echo. 154 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 155 | goto end 156 | ) 157 | 158 | if "%1" == "latexpdfja" ( 159 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 160 | cd %BUILDDIR%/latex 161 | make all-pdf-ja 162 | cd %BUILDDIR%/.. 163 | echo. 164 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 165 | goto end 166 | ) 167 | 168 | if "%1" == "text" ( 169 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 170 | if errorlevel 1 exit /b 1 171 | echo. 172 | echo.Build finished. The text files are in %BUILDDIR%/text. 173 | goto end 174 | ) 175 | 176 | if "%1" == "man" ( 177 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 178 | if errorlevel 1 exit /b 1 179 | echo. 180 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 181 | goto end 182 | ) 183 | 184 | if "%1" == "texinfo" ( 185 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 186 | if errorlevel 1 exit /b 1 187 | echo. 188 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 189 | goto end 190 | ) 191 | 192 | if "%1" == "gettext" ( 193 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 194 | if errorlevel 1 exit /b 1 195 | echo. 196 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 197 | goto end 198 | ) 199 | 200 | if "%1" == "changes" ( 201 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 202 | if errorlevel 1 exit /b 1 203 | echo. 204 | echo.The overview file is in %BUILDDIR%/changes. 205 | goto end 206 | ) 207 | 208 | if "%1" == "linkcheck" ( 209 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 210 | if errorlevel 1 exit /b 1 211 | echo. 212 | echo.Link check complete; look for any errors in the above output ^ 213 | or in %BUILDDIR%/linkcheck/output.txt. 214 | goto end 215 | ) 216 | 217 | if "%1" == "doctest" ( 218 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 219 | if errorlevel 1 exit /b 1 220 | echo. 221 | echo.Testing of doctests in the sources finished, look at the ^ 222 | results in %BUILDDIR%/doctest/output.txt. 223 | goto end 224 | ) 225 | 226 | if "%1" == "xml" ( 227 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 228 | if errorlevel 1 exit /b 1 229 | echo. 230 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 231 | goto end 232 | ) 233 | 234 | if "%1" == "pseudoxml" ( 235 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 236 | if errorlevel 1 exit /b 1 237 | echo. 238 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 239 | goto end 240 | ) 241 | 242 | :end 243 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=3.2,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [project] 6 | name = "wagtailmath" 7 | authors = [{name = "James Ramm", email = "jamessramm@gmail.com"}] 8 | description = "Wagtail StreamField block for rendering mathematical equations" 9 | readme = "README.md" 10 | license = {file = "LICENSE"} 11 | classifiers = [ 12 | "Development Status :: 3 - Alpha", 13 | "Intended Audience :: Developers", 14 | "License :: OSI Approved :: BSD License", 15 | "Operating System :: OS Independent", 16 | "Programming Language :: Python", 17 | "Programming Language :: Python :: 3", 18 | "Programming Language :: Python :: 3.8", 19 | "Programming Language :: Python :: 3.9", 20 | "Programming Language :: Python :: 3.10", 21 | "Programming Language :: Python :: 3.11", 22 | "Programming Language :: Python :: 3.12", 23 | "Framework :: Django", 24 | "Framework :: Django :: 4.2", 25 | "Framework :: Django :: 5.0", 26 | "Framework :: Wagtail", 27 | "Framework :: Wagtail :: 5", 28 | "Framework :: Wagtail :: 6", 29 | ] 30 | requires-python = ">=3.8" 31 | dynamic = ["version"] 32 | dependencies = [ 33 | "Django>=4.2", 34 | "Wagtail>=5.2" 35 | ] 36 | [project.optional-dependencies] 37 | linting = ["pre-commit>=3.6.0,<4",] 38 | testing = [ 39 | "dj-database-url==2.1.0", 40 | "pytest==8.1.1", 41 | "pytest-cov==5.0.0", 42 | "pytest-django==4.8.0", 43 | ] 44 | ci = [ 45 | "tox>=4.15.1,<5", 46 | "tox-gh-actions>=3.2,<3.3", 47 | ] 48 | 49 | [project.urls] 50 | Home = "https://github.com/wagtail-nest/wagtail-polymath" 51 | Changelog = "https://github.com/wagtail-nest/wagtail-polymath/blob/main/CHANGELOG.md" 52 | Documentation = "https://github.com/wagtail-nest/wagtail-polymath/blob/main/docs/" 53 | 54 | [tool.flit.module] 55 | name = "wagtailmath" 56 | 57 | [tool.flit.sdist] 58 | exclude = [ 59 | "docs", 60 | "tests", 61 | ".*", 62 | "*.js", 63 | "*.json", 64 | "*.ini", 65 | "*.yml", 66 | "ruff.toml", 67 | "Makefile", 68 | ] 69 | 70 | [tool.pytest.ini_options] 71 | pythonpath = ". tests" 72 | DJANGO_SETTINGS_MODULE = "testproject.settings" 73 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | extend-exclude = [ 2 | "LC_MESSAGES", 3 | "locale", 4 | ] 5 | line-length = 88 6 | 7 | 8 | [lint] 9 | select = [ 10 | "B", # flake8-bugbear 11 | "C4", # flake8-comprehensions 12 | "DJ", # flake8-django 13 | "E", # pycodestyle errors 14 | "F", # pyflakes 15 | "I", # isort 16 | "RUF100", # unused noqa 17 | "S", # flake8-bandit 18 | "UP", # pyupgrade 19 | "W", # warning 20 | ] 21 | fixable = ["C4", "E", "F", "I", "UP"] 22 | 23 | # E501: Line too long 24 | ignore = ["E501"] 25 | 26 | 27 | [lint.isort] 28 | known-first-party = ["wagtail_polymath"] 29 | lines-after-imports = 2 30 | lines-between-types = 1 31 | 32 | 33 | [lint.per-file-ignores] 34 | "tests/**/*.py" = [ 35 | "S101", # asserts allowed in tests 36 | "ARG", # unused function args (pytest fixtures) 37 | "FBT", # booleans as positional arguments (@pytest.mark.parametrize) 38 | "PLR2004", # magic value used in comparison 39 | "S311", # standard pseudo-random generators are not suitable for cryptographic purposes 40 | ] 41 | "setup.py" = ["S605", "S607"] 42 | 43 | 44 | [format] 45 | docstring-code-format = true 46 | -------------------------------------------------------------------------------- /src/wagtailmath/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.3.0" 2 | -------------------------------------------------------------------------------- /src/wagtailmath/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class WagtailMathConfig(AppConfig): 5 | name = "wagtailmath" 6 | -------------------------------------------------------------------------------- /src/wagtailmath/blocks.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.utils.functional import cached_property 3 | from wagtail.blocks import TextBlock 4 | 5 | from .widgets import MathJaxWidget 6 | 7 | 8 | class MathBlock(TextBlock): 9 | @cached_property 10 | def field(self): 11 | field_kwargs = {"widget": MathJaxWidget(attrs={"rows": self.rows})} 12 | field_kwargs.update(self.field_options) 13 | return forms.CharField(**field_kwargs) 14 | -------------------------------------------------------------------------------- /src/wagtailmath/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/src/wagtailmath/models.py -------------------------------------------------------------------------------- /src/wagtailmath/static/wagtailmath/js/mathjax-textarea-adapter.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function MathJaxTextarea(html, config) { 3 | this.html = html; 4 | this.baseConfig = config; 5 | } 6 | MathJaxTextarea.prototype.render = function(placeholder, name, id, initialState) { 7 | placeholder.outerHTML = this.html.replace(/__NAME__/g, name).replace(/__ID__/g, id); 8 | 9 | var element = document.getElementById(id); 10 | element.value = initialState; 11 | 12 | initMathJaxPreview(id); 13 | 14 | // define public API functions for the widget: 15 | // https://docs.wagtail.io/en/latest/reference/streamfield/widget_api.html 16 | return { 17 | idForLabel: null, 18 | getValue: function() { 19 | return element.value; 20 | }, 21 | getState: function() { 22 | return element.value; 23 | }, 24 | setState: function() { 25 | throw new Error('MathJaxTextarea.setState is not implemented'); 26 | }, 27 | getTextLabel: function(opts) { 28 | if (!element.value) return ''; 29 | var maxLength = opts && opts.maxLength, 30 | result = element.value; 31 | if (maxLength && result.length > maxLength) { 32 | return result.substring(0, maxLength - 1) + '…'; 33 | } 34 | return result; 35 | }, 36 | }; 37 | }; 38 | 39 | window.telepath.register('wagtailmath.widgets.MathJaxWidget', MathJaxTextarea); 40 | })(); 41 | -------------------------------------------------------------------------------- /src/wagtailmath/static/wagtailmath/js/wagtailmath-mathjax-controller.js: -------------------------------------------------------------------------------- 1 | class WagtailMathJaxController extends window.StimulusModule.Controller { 2 | connect() { 3 | initMathJaxPreview(this.element.id); 4 | } 5 | } 6 | 7 | window.wagtail.app.register('wagtailmathjax', WagtailMathJaxController); 8 | -------------------------------------------------------------------------------- /src/wagtailmath/static/wagtailmath/js/wagtailmath.js: -------------------------------------------------------------------------------- 1 | // Update the preview area on input. Lifted directly from mathjax website examples 2 | class Preview { 3 | 4 | // Get the preview and buffer DIV's 5 | // 6 | constructor(previewId, bufferId, inputId) { 7 | this.preview = document.getElementById(previewId); 8 | this.buffer = document.getElementById(bufferId); 9 | this.input = document.getElementById(inputId); 10 | this.delay = 150; // delay after keystroke before updating 11 | this.timeout = null; // store setTimout id 12 | this.mjRunning = false; // true when MathJax is processing 13 | this.mjPending = false; // true when a typeset has been queued 14 | this.oldText = null; // used to check if an update is needed 15 | } 16 | 17 | // 18 | // Switch the buffer and preview, and display the right one. 19 | // (We use visibility:hidden rather than display:none since 20 | // the results of running MathJax are more accurate that way.) 21 | // 22 | SwapBuffers() { 23 | var buffer = this.preview, preview = this.buffer; 24 | this.buffer = buffer; 25 | this.preview = preview; 26 | buffer.style.visibility = "hidden"; 27 | buffer.style.position = "absolute"; 28 | preview.style.position = ""; 29 | preview.style.visibility = ""; 30 | } 31 | 32 | // 33 | // This gets called when a key is pressed in the textarea. 34 | // We check if there is already a pending update and clear it if so. 35 | // Then set up an update to occur after a small delay (so if more keys 36 | // are pressed, the update won't occur until after there has been 37 | // a pause in the typing). 38 | // The callback function is set up below, after the Preview object is set up. 39 | // 40 | Update() { 41 | if (this.timeout) { 42 | clearTimeout(this.timeout); 43 | } 44 | this.timeout = setTimeout(this.callback, this.delay); 45 | } 46 | 47 | // 48 | // Creates the preview and runs MathJax on it. 49 | // If MathJax is already trying to render the code, return 50 | // If the text hasn't changed, return 51 | // Otherwise, indicate that MathJax is running, and start the 52 | // typesetting. After it is done, call PreviewDone. 53 | // 54 | CreatePreview() { 55 | this.timeout = null; 56 | if (this.mjPending) return; 57 | var text = this.input.value; 58 | if (text === this.oldtext) return; 59 | if (this.mjRunning) { 60 | this.mjPending = true; 61 | MathJax.Hub.Queue(["CreatePreview", this]); 62 | } else { 63 | this.buffer.innerHTML = this.oldtext = text; 64 | this.mjRunning = true; 65 | MathJax.Hub.Queue( 66 | ["Typeset", MathJax.Hub, this.buffer], 67 | ["PreviewDone", this] 68 | ); 69 | } 70 | } 71 | 72 | // 73 | // Indicate that MathJax is no longer running, 74 | // and swap the buffers to show the results. 75 | // 76 | PreviewDone() { 77 | this.mjRunning = this.mjPending = false; 78 | this.SwapBuffers(); 79 | } 80 | } 81 | 82 | 83 | function initMathJaxPreview(id) { 84 | window.wagtailMathPreviews = window.wagtailMathPreviews || {}; 85 | 86 | window.wagtailMathPreviews[id] = new Preview( 87 | "MathPreview-" + id, 88 | "MathBuffer-" + id, 89 | id 90 | ); 91 | 92 | // Cache a callback to the CreatePreview action 93 | window.wagtailMathPreviews[id].callback = MathJax.Callback(["CreatePreview", window.wagtailMathPreviews[id]]); 94 | window.wagtailMathPreviews[id].callback.autoReset = true; // make sure it can run more than once 95 | window.wagtailMathPreviews[id].Update(); 96 | 97 | // attach a keyup event listener so we update the preview 98 | const target = document.getElementById(id); 99 | if (target) { 100 | target.addEventListener("keyup", function() { 101 | window.wagtailMathPreviews[id].Update(); 102 | }) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/wagtailmath/templates/wagtailmath/mathjaxwidget.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

{% translate "Enter the MathJax markup" %}

4 | 5 | 7 | 8 |

{% translate "Preview" %}

9 |
10 | 11 | -------------------------------------------------------------------------------- /src/wagtailmath/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/src/wagtailmath/templatetags/__init__.py -------------------------------------------------------------------------------- /src/wagtailmath/templatetags/wagtailmath.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | from wagtailmath.widgets import MATHJAX_VERSION 4 | 5 | 6 | register = template.Library() 7 | 8 | 9 | @register.simple_tag 10 | def mathjax(config="TeX-MML-AM_CHTML"): 11 | return f"https://cdnjs.cloudflare.com/ajax/libs/mathjax/{MATHJAX_VERSION}/MathJax.js?config={config}" 12 | -------------------------------------------------------------------------------- /src/wagtailmath/widgets.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from wagtail import VERSION as WAGTAIL_VERSION 3 | from wagtail.admin.staticfiles import versioned_static 4 | 5 | 6 | MATHJAX_VERSION = "2.7.9" 7 | 8 | 9 | class MathJaxWidgetBase(forms.Textarea): 10 | template_name = "wagtailmath/mathjaxwidget.html" 11 | 12 | def _get_media_js(self): 13 | return ( 14 | f"https://cdnjs.cloudflare.com/ajax/libs/mathjax/{MATHJAX_VERSION}/MathJax.js?config=TeX-MML-AM_HTMLorMML", 15 | versioned_static("wagtailmath/js/wagtailmath.js"), 16 | ) 17 | 18 | @property 19 | def media(self): 20 | return forms.Media(js=self._get_media_js()) 21 | 22 | 23 | if WAGTAIL_VERSION >= (6, 0): 24 | 25 | class MathJaxWidget(MathJaxWidgetBase): 26 | def build_attrs(self, *args, **kwargs): 27 | attrs = super().build_attrs(*args, **kwargs) 28 | attrs["data-controller"] = "wagtailmathjax" 29 | 30 | return attrs 31 | 32 | def _get_media_js(self): 33 | return ( 34 | *super()._get_media_js(), 35 | versioned_static("wagtailmath/js/wagtailmath-mathjax-controller.js"), 36 | ) 37 | else: 38 | from wagtail.telepath import register 39 | from wagtail.utils.widgets import WidgetWithScript 40 | from wagtail.widget_adapters import WidgetAdapter 41 | 42 | class MathJaxWidget(WidgetWithScript, MathJaxWidgetBase): 43 | def render_js_init(self, id_, name, value): 44 | return f'initMathJaxPreview("{id_}");' 45 | 46 | class MathJaxAdapter(WidgetAdapter): 47 | js_constructor = "wagtailmath.widgets.MathJaxWidget" 48 | 49 | class Media: 50 | # TODO: remove the adapter when dropping support for Wagtail 5.2 51 | js = ["wagtailmath/js/mathjax-textarea-adapter.js"] 52 | 53 | register(MathJaxAdapter(), MathJaxWidget) 54 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture(autouse=True) 5 | def temporary_media_dir(settings, tmp_path: pytest.TempdirFactory): 6 | settings.MEDIA_ROOT = tmp_path / "media" 7 | -------------------------------------------------------------------------------- /tests/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import os 5 | import shutil 6 | import sys 7 | import warnings 8 | 9 | from django.core.management import execute_from_command_line 10 | 11 | 12 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testproject.settings") 13 | sys.path.append("tests") 14 | 15 | 16 | def make_parser(): 17 | parser = argparse.ArgumentParser() 18 | parser.add_argument( 19 | "--deprecation", 20 | choices=["all", "pending", "imminent", "none"], 21 | default="imminent", 22 | ) 23 | return parser 24 | 25 | 26 | def parse_args(args=None): 27 | return make_parser().parse_known_args(args) 28 | 29 | 30 | def runtests(): 31 | args, rest = parse_args() 32 | 33 | only_wagtail = r"^wagtail(\.|$)" 34 | if args.deprecation == "all": 35 | # Show all deprecation warnings from all packages 36 | warnings.simplefilter("default", DeprecationWarning) 37 | warnings.simplefilter("default", PendingDeprecationWarning) 38 | elif args.deprecation == "pending": 39 | # Show all deprecation warnings from wagtail 40 | warnings.filterwarnings( 41 | "default", category=DeprecationWarning, module=only_wagtail 42 | ) 43 | warnings.filterwarnings( 44 | "default", category=PendingDeprecationWarning, module=only_wagtail 45 | ) 46 | elif args.deprecation == "imminent": 47 | # Show only imminent deprecation warnings from wagtail 48 | warnings.filterwarnings( 49 | "default", category=DeprecationWarning, module=only_wagtail 50 | ) 51 | elif args.deprecation == "none": 52 | # Deprecation warnings are ignored by default 53 | pass 54 | 55 | argv = [sys.argv[0]] + rest 56 | 57 | try: 58 | execute_from_command_line(argv) 59 | finally: 60 | from wagtail.test.settings import MEDIA_ROOT, STATIC_ROOT 61 | 62 | shutil.rmtree(STATIC_ROOT, ignore_errors=True) 63 | shutil.rmtree(MEDIA_ROOT, ignore_errors=True) 64 | 65 | 66 | if __name__ == "__main__": 67 | runtests() 68 | -------------------------------------------------------------------------------- /tests/test_placeholder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Placeholder test, so that pytest doesn't fail with an empty testsuite. Feel free to 3 | remove this when you start writing tests. 4 | https://github.com/pytest-dev/pytest/issues/2393 5 | """ 6 | 7 | import pytest 8 | 9 | 10 | pytestmark = pytest.mark.django_db 11 | 12 | 13 | def test_homepage(client): 14 | assert client.get("/").status_code == 200 15 | -------------------------------------------------------------------------------- /tests/testapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/tests/testapp/__init__.py -------------------------------------------------------------------------------- /tests/testapp/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.6 on 2024-06-21 09:50 2 | 3 | import django.db.models.deletion 4 | import wagtail.blocks 5 | import wagtail.fields 6 | import wagtailmath.blocks 7 | 8 | from django.db import migrations, models 9 | 10 | 11 | class Migration(migrations.Migration): 12 | initial = True 13 | 14 | dependencies = [ 15 | ("wagtailcore", "0089_log_entry_data_json_null_to_object"), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name="MathPage", 21 | fields=[ 22 | ( 23 | "page_ptr", 24 | models.OneToOneField( 25 | auto_created=True, 26 | on_delete=django.db.models.deletion.CASCADE, 27 | parent_link=True, 28 | primary_key=True, 29 | serialize=False, 30 | to="wagtailcore.page", 31 | ), 32 | ), 33 | ( 34 | "body", 35 | wagtail.fields.StreamField( 36 | [ 37 | ( 38 | "heading", 39 | wagtail.blocks.CharBlock(form_classname="full title"), 40 | ), 41 | ("paragraph", wagtail.blocks.RichTextBlock()), 42 | ("equation", wagtailmath.blocks.MathBlock()), 43 | ], 44 | use_json_field=True, 45 | ), 46 | ), 47 | ], 48 | options={ 49 | "abstract": False, 50 | }, 51 | bases=("wagtailcore.page",), 52 | ), 53 | ] 54 | -------------------------------------------------------------------------------- /tests/testapp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagtail-nest/wagtail-polymath/2a977b5feb2416b755fde168e7ca4a0872665c6a/tests/testapp/migrations/__init__.py -------------------------------------------------------------------------------- /tests/testapp/models.py: -------------------------------------------------------------------------------- 1 | from wagtail import blocks 2 | from wagtail.admin.panels import FieldPanel 3 | from wagtail.fields import StreamField 4 | from wagtail.models import Page 5 | from wagtailmath.blocks import MathBlock 6 | 7 | 8 | class MathPage(Page): 9 | body = StreamField( 10 | [ 11 | ("heading", blocks.CharBlock(classname="full title")), 12 | ("paragraph", blocks.RichTextBlock()), 13 | ("equation", MathBlock()), 14 | ], 15 | use_json_field=True, 16 | ) 17 | 18 | content_panels = Page.content_panels + [FieldPanel("body")] 19 | -------------------------------------------------------------------------------- /tests/testapp/templates/testapp/math_page.html: -------------------------------------------------------------------------------- 1 | {% load wagtailmath %} 2 | 3 | 4 | 5 | 6 | 7 |

{{ page.title }}

8 | 9 |
10 | {{ page.body }} 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/testproject/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = "tests.apps.WagtailPolymathTestAppConfig" 2 | -------------------------------------------------------------------------------- /tests/testproject/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for temp project. 3 | 4 | For more information on this file, see 5 | https://docs.djangoproject.com/en/stable/topics/settings/ 6 | 7 | For the full list of settings and their values, see 8 | https://docs.djangoproject.com/en/stable/ref/settings/ 9 | """ 10 | 11 | import os 12 | 13 | import dj_database_url 14 | 15 | 16 | # Build paths inside the project like this: os.path.join(PROJECT_DIR, ...) 17 | PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 18 | BASE_DIR = os.path.dirname(PROJECT_DIR) 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/stable/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = "not-a-secure-key" # noqa: S105 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = ["localhost", "testserver"] 30 | 31 | IS_INTERACTIVE = "INTERACTIVE" in os.environ 32 | 33 | # Application definition 34 | 35 | INSTALLED_APPS = [ 36 | "wagtailmath", 37 | "testapp", 38 | "wagtail.users", 39 | "wagtail.snippets", 40 | "wagtail.documents", 41 | "wagtail.images", 42 | "wagtail.search", 43 | "wagtail.admin", 44 | "wagtail.contrib.routable_page", 45 | "wagtail.contrib.styleguide", 46 | "wagtail.sites", 47 | "wagtail", 48 | "taggit", 49 | "django.contrib.admin", 50 | "django.contrib.auth", 51 | "django.contrib.contenttypes", 52 | "django.contrib.sessions", 53 | "django.contrib.messages", 54 | "django.contrib.staticfiles", 55 | ] 56 | 57 | MIDDLEWARE = [ 58 | "django.middleware.security.SecurityMiddleware", 59 | "django.contrib.sessions.middleware.SessionMiddleware", 60 | "django.middleware.common.CommonMiddleware", 61 | "django.middleware.csrf.CsrfViewMiddleware", 62 | "django.contrib.auth.middleware.AuthenticationMiddleware", 63 | "django.contrib.messages.middleware.MessageMiddleware", 64 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 65 | "wagtail.contrib.redirects.middleware.RedirectMiddleware", 66 | ] 67 | 68 | ROOT_URLCONF = "testproject.urls" 69 | 70 | TEMPLATES = [ 71 | { 72 | "BACKEND": "django.template.backends.django.DjangoTemplates", 73 | "DIRS": [], 74 | "APP_DIRS": True, 75 | "OPTIONS": { 76 | "context_processors": [ 77 | "django.template.context_processors.debug", 78 | "django.template.context_processors.request", 79 | "django.contrib.auth.context_processors.auth", 80 | "django.contrib.messages.context_processors.messages", 81 | ] 82 | }, 83 | } 84 | ] 85 | 86 | 87 | # Using DatabaseCache to make sure that the cache is cleared between tests. 88 | # This prevents false-positives in some wagtail core tests where we are 89 | # changing the 'wagtail_root_paths' key which may cause future tests to fail. 90 | CACHES = { 91 | "default": { 92 | "BACKEND": "django.core.cache.backends.db.DatabaseCache", 93 | "LOCATION": "cache", 94 | } 95 | } 96 | 97 | 98 | # don't use the intentionally slow default password hasher 99 | PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",) 100 | 101 | 102 | # Database 103 | # https://docs.djangoproject.com/en/stable/ref/settings/#databases 104 | 105 | DATABASES = { 106 | "default": dj_database_url.config(default="sqlite:///test_wagtail_polymath.db"), 107 | } 108 | 109 | 110 | # Password validation 111 | # https://docs.djangoproject.com/en/stable/ref/settings/#auth-password-validators 112 | 113 | AUTH_PASSWORD_VALIDATORS = [ 114 | { 115 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" 116 | }, 117 | {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, 118 | {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, 119 | {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, 120 | ] 121 | 122 | 123 | # Internationalization 124 | # https://docs.djangoproject.com/en/stable/topics/i18n/ 125 | 126 | LANGUAGE_CODE = "en-us" 127 | TIME_ZONE = "UTC" 128 | USE_I18N = True 129 | USE_L10N = True 130 | USE_TZ = True 131 | 132 | 133 | # Static files (CSS, JavaScript, Images) 134 | # https://docs.djangoproject.com/en/stable/howto/static-files/ 135 | 136 | STATICFILES_FINDERS = [ 137 | "django.contrib.staticfiles.finders.FileSystemFinder", 138 | "django.contrib.staticfiles.finders.AppDirectoriesFinder", 139 | ] 140 | 141 | STATICFILES_DIRS = [os.path.join(PROJECT_DIR, "static")] 142 | 143 | STATIC_ROOT = os.path.join(BASE_DIR, "test-static") 144 | STATIC_URL = "/static/" 145 | 146 | MEDIA_ROOT = os.path.join(BASE_DIR, "test-media") 147 | 148 | 149 | # Wagtail settings 150 | 151 | WAGTAIL_SITE_NAME = "Wagtail Polymath test site" 152 | WAGTAILADMIN_BASE_URL = "http://localhost:8020" 153 | -------------------------------------------------------------------------------- /tests/testproject/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import include, path 2 | from wagtail import urls as wagtail_urls 3 | from wagtail.admin import urls as wagtailadmin_urls 4 | from wagtail.documents import urls as wagtaildocs_urls 5 | 6 | 7 | urlpatterns = [ 8 | path("admin/", include(wagtailadmin_urls)), 9 | path("documents/", include(wagtaildocs_urls)), 10 | path("", include(wagtail_urls)), 11 | ] 12 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | min_version = 4.11 3 | 4 | envlist = 5 | python{3.8,3.9,3.10,3.11}-django{4.2}-wagtail{5.2,6.1}-{sqlite} 6 | python{3.10,3.11,3.12}-django{5.0}-wagtail{5.2,6.1}-{sqlite} 7 | 8 | [gh-actions] 9 | python = 10 | 3.8: python3.8 11 | 3.9: python3.9 12 | 3.10: python3.10 13 | 3.11: python3.11 14 | 3.12: python3.12 15 | 16 | [testenv] 17 | package = wheel 18 | wheel_build_env = .pkg 19 | use_frozen_constraints = true 20 | constrain_package_deps = true 21 | 22 | pass_env = 23 | FORCE_COLOR 24 | NO_COLOR 25 | 26 | setenv = 27 | PYTHONPATH = {toxinidir}/tests:{toxinidir} 28 | PYTHONDEVMODE = 1 29 | # will use the Python 3.12+ sys.monitoring when available 30 | COVERAGE_CORE=sysmon 31 | COVERAGE_FILE = .coverage.{envname} 32 | 33 | deps = 34 | coverage>=7.0,<8.0 35 | 36 | django4.2: Django>=4.2,<4.3 37 | django5.0: Django>=5.0,<5.1 38 | 39 | wagtail5.2: wagtail>=5.2,<5.3 40 | wagtail6.1: wagtail>=6.1,<6.2 41 | 42 | extras = testing 43 | 44 | install_command = python -Im pip install -U --pre {opts} {packages} 45 | 46 | allowlist_externals = pytest 47 | commands_pre = python -I {toxinidir}/tests/manage.py migrate 48 | commands = python -Im pytest --cov --cov-append --ignore=docs/ {posargs: -vv} 49 | 50 | [testenv:interactive] 51 | description = An interactive environment for local testing purposes 52 | basepython = python3.12 53 | package = editable 54 | 55 | deps = 56 | wagtail >= 5.2, <6.0 57 | 58 | commands_pre = 59 | python {toxinidir}/tests/manage.py makemigrations 60 | python {toxinidir}/tests/manage.py migrate 61 | python {toxinidir}/tests/manage.py shell -c "from django.contrib.auth.models import User;(not User.objects.filter(username='admin').exists()) and User.objects.create_superuser('admin', 'super@example.com', 'changeme')" 62 | python {toxinidir}/tests/manage.py createcachetable 63 | 64 | commands = 65 | {posargs:python -I {toxinidir}/tests/manage.py runserver 0.0.0.0:8020} 66 | 67 | setenv = 68 | INTERACTIVE = 1 69 | 70 | [testenv:wagtailmain] 71 | deps = 72 | flit>=3.8 73 | coverage>=7.0,<8.0 74 | wagtailmain: git+https://github.com/wagtail/wagtail.git@main#egg=Wagtail 75 | --------------------------------------------------------------------------------