├── .nvmrc ├── tests ├── __init__.py ├── tests │ ├── __init__.py │ ├── utils.py │ ├── test_sections.py │ ├── test_context.py │ ├── test_tags.py │ ├── test_utils.py │ ├── test_context_modifiers.py │ └── test_commands.py ├── settings │ ├── __init__.py │ ├── dev.py │ ├── production.py │ └── base.py ├── templatetags │ ├── __init__.py │ ├── test_tags_invalid.py │ └── test_tags.py ├── templates │ ├── patterns │ │ ├── atoms │ │ │ ├── icons │ │ │ │ ├── icon.yaml │ │ │ │ └── icon.html │ │ │ ├── test_atom │ │ │ │ ├── test_atom.html │ │ │ │ ├── test_atom.yaml │ │ │ │ └── test_atom.md │ │ │ ├── test_atom_yml │ │ │ │ ├── test_atom_yml.html │ │ │ │ └── test_atom_yml.yml │ │ │ ├── test_extends │ │ │ │ ├── base.html │ │ │ │ ├── extended.yaml │ │ │ │ └── extended.html │ │ │ ├── test_includes │ │ │ │ ├── test_includes.html │ │ │ │ └── test_includes.yaml │ │ │ ├── tags_test_atom │ │ │ │ ├── invalid_tags_test_atom.html.fail │ │ │ │ ├── tags_test_atom.html │ │ │ │ └── tags_test_atom.yaml │ │ │ └── sprites │ │ │ │ └── sprites.html │ │ ├── molecules │ │ │ ├── test-molecule │ │ │ │ └── test-molecule.html │ │ │ ├── test_molecule │ │ │ │ ├── test_molecule_no_context.html │ │ │ │ ├── test_molecule.yaml │ │ │ │ └── test_molecule.html │ │ │ ├── accordion │ │ │ │ ├── accordion.md │ │ │ │ ├── accordion.yaml │ │ │ │ └── accordion.html │ │ │ ├── button │ │ │ │ ├── button.yaml │ │ │ │ └── button.html │ │ │ └── field │ │ │ │ └── field.html │ │ ├── pages │ │ │ ├── people │ │ │ │ ├── person_page.md │ │ │ │ ├── person_page.yaml │ │ │ │ └── person_page.html │ │ │ ├── search │ │ │ │ ├── search.yaml │ │ │ │ └── search.html │ │ │ ├── test_page │ │ │ │ ├── test_page.html │ │ │ │ └── test_page.yaml │ │ │ └── forms │ │ │ │ └── example_form.html │ │ ├── base_page.html │ │ └── base.html │ └── non-patterns │ │ ├── variable_include.html │ │ └── include.html ├── jinja │ ├── non-patterns │ │ ├── variable_include.html │ │ └── include.html │ └── patterns_jinja │ │ ├── components │ │ ├── test_atom │ │ │ ├── test_atom.html │ │ │ ├── test_atom.yaml │ │ │ └── test_atom.md │ │ ├── icons │ │ │ ├── icon.yaml │ │ │ └── icon.html │ │ ├── test_molecule │ │ │ ├── test_molecule_no_context.html │ │ │ ├── test_molecule.yaml │ │ │ └── test_molecule.html │ │ ├── test_extends │ │ │ ├── base.html │ │ │ ├── extended.yaml │ │ │ └── extended.html │ │ ├── button │ │ │ ├── button.yaml │ │ │ └── button.html │ │ ├── accordion │ │ │ ├── accordion.md │ │ │ ├── accordion.yaml │ │ │ └── accordion.html │ │ ├── test_includes │ │ │ ├── test_includes.html │ │ │ └── test_includes.yaml │ │ └── sprites │ │ │ └── sprites.html │ │ ├── base_page_jinja.html │ │ ├── pages │ │ ├── search │ │ │ ├── search.yaml │ │ │ └── search.html │ │ └── test_page │ │ │ ├── test_page.html │ │ │ └── test_page.yaml │ │ └── base_jinja.html ├── forms.py ├── urls.py ├── jinja2.py ├── static │ ├── main.js │ └── main.css └── pattern_contexts.py ├── pattern_library ├── py.typed ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── render_patterns.py ├── apps.py ├── static │ └── pattern_library │ │ └── src │ │ ├── scss │ │ ├── layout │ │ │ ├── _main.scss │ │ │ ├── _body.scss │ │ │ ├── _header.scss │ │ │ └── _sidebar.scss │ │ ├── components │ │ │ ├── _code.scss │ │ │ ├── _icon.scss │ │ │ ├── _wrapper.scss │ │ │ ├── _iframe.scss │ │ │ ├── _md.scss │ │ │ ├── _button.scss │ │ │ ├── _heading.scss │ │ │ ├── _tabbed-listing.scss │ │ │ └── _list.scss │ │ ├── _config.scss │ │ ├── main.scss │ │ ├── abstracts │ │ │ └── _base.scss │ │ └── hljs │ │ │ ├── _a11y-dark.scss │ │ │ └── _a11y-light.scss │ │ └── js │ │ ├── components │ │ ├── hide-menu-mobile.js │ │ ├── syntax-highlighting.js │ │ ├── navigation.js │ │ ├── persist-menu.js │ │ ├── tabbed-content.js │ │ ├── pattern-search.js │ │ └── iframe.js │ │ └── app.js ├── exceptions.py ├── urls.py ├── cm_utils.py ├── templates │ └── pattern_library │ │ ├── pattern_group.html │ │ ├── base.html │ │ └── index.html ├── __init__.py ├── context_modifiers.py └── views.py ├── .dockerignore ├── docs ├── images │ ├── favicon.png │ ├── pattern-library-screenshot.webp │ ├── pattern-library-talk-youtube.webp │ ├── getting-started │ │ ├── PatternLibraryEmpty.png │ │ └── getting-started-complete.png │ ├── logo.svg │ └── favicon.svg ├── recipes │ ├── inclusion-tags.md │ ├── image-include.md │ ├── image-lazyload.md │ ├── api-rendering.md │ ├── looping-for-tags.md │ ├── forms-and-fields.md │ └── pagination.md ├── community │ ├── security-policy.md │ ├── support.md │ ├── related-projects.md │ └── code-of-conduct.md ├── guides │ ├── reuse-across-projects.md │ ├── static-site-export.md │ ├── multiple-variants.md │ ├── customizing-template-rendering.md │ └── usage-tips.md ├── reference │ ├── concepts.md │ └── known-issues.md └── index.md ├── .github ├── pattern-library-screenshot.webp ├── SECURITY.md ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── BUG_REPORT.md │ └── FEATURE_REQUEST.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── codeql-analysis.yml │ └── ci.yml ├── tox_install.sh ├── setup.py ├── .babelrc.js ├── stylelint.config.js ├── .prettierrc.toml ├── .editorconfig ├── .git-blame-ignore-revs ├── Dockerfile ├── docker-compose.yml ├── .devcontainer └── devcontainer.json ├── tox.ini ├── runtests.py ├── .gitpod.yml ├── webpack.config.js ├── package.json ├── LICENSE ├── .gitignore ├── mkdocs.yml ├── pyproject.toml ├── README.md └── CONTRIBUTING.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 24 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pattern_library/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pattern_library/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pattern_library/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/settings/dev.py: -------------------------------------------------------------------------------- 1 | from .base import * # noqa 2 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/icons/icon.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | name: close 3 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_atom/test_atom.html: -------------------------------------------------------------------------------- 1 | {{ atom_var }} 2 | -------------------------------------------------------------------------------- /tests/jinja/non-patterns/variable_include.html: -------------------------------------------------------------------------------- 1 | included content from variable 2 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_atom/test_atom.html: -------------------------------------------------------------------------------- 1 | {{ atom_var }} 2 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_atom_yml/test_atom_yml.html: -------------------------------------------------------------------------------- 1 | {{ atom_var }} 2 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/icons/icon.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | name: close 3 | -------------------------------------------------------------------------------- /tests/templates/non-patterns/variable_include.html: -------------------------------------------------------------------------------- 1 | included content from variable 2 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/test-molecule/test-molecule.html: -------------------------------------------------------------------------------- 1 | template-with-dash 2 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/test_molecule/test_molecule_no_context.html: -------------------------------------------------------------------------------- 1 | No context 2 | -------------------------------------------------------------------------------- /tests/jinja/non-patterns/include.html: -------------------------------------------------------------------------------- 1 | SHOWME 2 | {% if False %} 3 | HIDEME 4 | {% endif %} 5 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_molecule/test_molecule_no_context.html: -------------------------------------------------------------------------------- 1 | No context 2 | -------------------------------------------------------------------------------- /tests/templates/non-patterns/include.html: -------------------------------------------------------------------------------- 1 | SHOWME 2 | {% if False %} 3 | HIDEME 4 | {% endif %} 5 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_extends/base.html: -------------------------------------------------------------------------------- 1 | {% block content %}base content{% endblock %} 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /.git/ 2 | node_modules/ 3 | /build/ 4 | /dist/ 5 | /pattern_library/static/ 6 | site/ 7 | -------------------------------------------------------------------------------- /docs/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/docs/images/favicon.png -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_extends/base.html: -------------------------------------------------------------------------------- 1 | {% block content %}base content{% endblock %} 2 | -------------------------------------------------------------------------------- /tests/templates/patterns/pages/people/person_page.md: -------------------------------------------------------------------------------- 1 | # person_page 2 | 3 | Testing page-level documentation 4 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_atom/test_atom.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | atom_var: 'atom_var value from test_atom.yaml' 3 | -------------------------------------------------------------------------------- /tests/templates/patterns/base_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'patterns/base.html' %} 2 | 3 | {% block title %}Page{% endblock %} 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_atom/test_atom.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | atom_var: 'atom_var value from test_atom.yaml' 3 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_extends/extended.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | parent_template_name: patterns/atoms/test_extends/base.html 3 | -------------------------------------------------------------------------------- /.github/pattern-library-screenshot.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/.github/pattern-library-screenshot.webp -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/accordion/accordion.md: -------------------------------------------------------------------------------- 1 | # Accordion 2 | 3 | The accordion is a good example of a pattern library component. 4 | -------------------------------------------------------------------------------- /docs/images/pattern-library-screenshot.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/docs/images/pattern-library-screenshot.webp -------------------------------------------------------------------------------- /docs/images/pattern-library-talk-youtube.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/docs/images/pattern-library-talk-youtube.webp -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/base_page_jinja.html: -------------------------------------------------------------------------------- 1 | {% extends 'patterns_jinja/base_jinja.html' %} 2 | 3 | {% block title %}{{ page.title }}{% endblock %} 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_extends/extended.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | parent_template_name: patterns_jinja/components/test_extends/base.html 3 | -------------------------------------------------------------------------------- /tox_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | poetry install 5 | 6 | if [ ! -z "$@" ] 7 | then 8 | poetry run python -m pip install $@ 9 | fi 10 | -------------------------------------------------------------------------------- /docs/images/getting-started/PatternLibraryEmpty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/docs/images/getting-started/PatternLibraryEmpty.png -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_atom_yml/test_atom_yml.yml: -------------------------------------------------------------------------------- 1 | context: 2 | atom_var: 'atom_var value from test_atom.yml (notice the missing "a" in the extension)' 3 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_extends/extended.html: -------------------------------------------------------------------------------- 1 | {% extends parent_template_name %} 2 | 3 | {% block content %}{{ super() }} - extended content{% endblock %} 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/pages/search/search.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | search_query: test query 3 | search_results: 4 | - title: First result 5 | - title: Second result 6 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_extends/extended.html: -------------------------------------------------------------------------------- 1 | {% extends parent_template_name %} 2 | 3 | {% block content %}{{ block.super }} - extended content{% endblock %} 4 | -------------------------------------------------------------------------------- /tests/templates/patterns/pages/search/search.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | search_query: test query 3 | search_results: 4 | - title: First result 5 | - title: Second result 6 | -------------------------------------------------------------------------------- /docs/images/getting-started/getting-started-complete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/django-pattern-library/HEAD/docs/images/getting-started/getting-started-complete.png -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/button/button.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | target_page: 3 | title: Get started 4 | tags: 5 | pageurl: 6 | target_page: 7 | raw: /get-started 8 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | To report vulnerabilities, please refer to the project’s [security policy](https://torchbox.github.io/django-pattern-library/community/security-policy/) on our website. 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # We use Poetry to build this package, 2 | # this setup.py is only for GitHub’s "Used by" detection. 3 | from setuptools import setup 4 | 5 | setup(name="django-pattern-library") 6 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/button/button.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | target_page: 3 | title: Get started 4 | tags: 5 | pageurl: 6 | target_page: 7 | raw: /get-started 8 | -------------------------------------------------------------------------------- /pattern_library/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PatternLibraryAppConfig(AppConfig): 5 | name = "pattern_library" 6 | default_auto_field = "django.db.models.AutoField" 7 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_includes/test_includes.html: -------------------------------------------------------------------------------- 1 | {% load test_tags %} 2 | 3 | {% include 'non-patterns/include.html' %} 4 | {% include variable_include %} 5 | 6 | {% error_tag include %} 7 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/test_molecule/test_molecule.yaml: -------------------------------------------------------------------------------- 1 | name: Pretty name for test molecule 2 | 3 | context: 4 | atom_var: 'atom_var value from test_molecule.yaml' 5 | utf8_test_var: '你好,世界' 6 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/scss/layout/_main.scss: -------------------------------------------------------------------------------- 1 | @use '../config' as *; 2 | 3 | .main { 4 | display: block; 5 | padding: 20px; 6 | background: $white; 7 | overflow: scroll; 8 | } 9 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/accordion/accordion.md: -------------------------------------------------------------------------------- 1 | # Accordion (Jinja) 2 | 3 | The accordion is a good example of a pattern library component. This one uses [Jinja](https://jinja.palletsprojects.com/). 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_molecule/test_molecule.yaml: -------------------------------------------------------------------------------- 1 | name: Pretty name for test molecule 2 | 3 | context: 4 | atom_var: 'atom_var value from test_molecule.yaml' 5 | utf8_test_var: '你好,世界' 6 | -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | modules: false, 7 | }, 8 | ], 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('stylelint').Config} */ 2 | export default { 3 | // See https://github.com/torchbox/stylelint-config-torchbox for rules. 4 | extends: 'stylelint-config-torchbox', 5 | }; 6 | -------------------------------------------------------------------------------- /tests/tests/utils.py: -------------------------------------------------------------------------------- 1 | from django import VERSION as DJANGO_VERSION 2 | 3 | if DJANGO_VERSION < (2,): 4 | from django.core.urlresolvers import reverse # noqa 5 | else: 6 | from django.urls import reverse # noqa 7 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/scss/components/_code.scss: -------------------------------------------------------------------------------- 1 | .code { 2 | width: 600px; 3 | overflow: scroll; 4 | 5 | @media only screen and (min-width: 1200px) { 6 | width: 80vw; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/icons/icon.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/icons/icon.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_includes/test_includes.html: -------------------------------------------------------------------------------- 1 | {% include 'non-patterns/include.html' %} 2 | {% include variable_include %} 3 | 4 | {# TODO: Unsupported override with Jinja #} 5 | {# {{ error_tag() }} #} 6 | -------------------------------------------------------------------------------- /tests/settings/production.py: -------------------------------------------------------------------------------- 1 | from .base import * # noqa 2 | 3 | # Serve the site as if it was hosted at the `/django-pattern-library/` sub-path 4 | STATIC_URL = "/django-pattern-library/demo/static/" 5 | GITHUB_PAGES_EXPORT = True 6 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_includes/test_includes.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | variable_include: non-patterns/variable_include.html 3 | 4 | tags: 5 | error_tag: 6 | include: 7 | template_name: 'non-patterns/include.html' 8 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | Please refer to the code of conduct on our website: [Contributor Covenant Code of Conduct](https://torchbox.github.io/django-pattern-library/community/code-of-conduct/). 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: '❓ Question' 4 | url: https://github.com/torchbox/django-pattern-library/discussions 5 | about: Use GitHub Discussions to get help with this project. 6 | -------------------------------------------------------------------------------- /pattern_library/exceptions.py: -------------------------------------------------------------------------------- 1 | class PatternLibraryException(Exception): 2 | pass 3 | 4 | 5 | class TemplateIsNotPattern(PatternLibraryException): 6 | pass 7 | 8 | 9 | class PatternLibraryEmpty(PatternLibraryException): 10 | pass 11 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/button/button.html: -------------------------------------------------------------------------------- 1 | 2 | {% if label %}{{ label }}{% else %}{{ target_page.title }}{% endif %} 3 | 4 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/test_molecule/test_molecule.html: -------------------------------------------------------------------------------- 1 | {% include 'patterns/atoms/test_atom/test_atom.html' %} 2 | {% include 'patterns/atoms/test_atom/test_atom.html' with atom_var='atom_var value from test_molecule.html include tag' %} 3 | -------------------------------------------------------------------------------- /.prettierrc.toml: -------------------------------------------------------------------------------- 1 | # See https://prettier.io/docs/options.html. 2 | # Prettier also reads .editorconfig. 3 | printWidth = 80 4 | singleQuote = true 5 | quoteProps = 'consistent' 6 | trailingComma = 'all' 7 | arrowParens = 'always' 8 | proseWrap = 'preserve' 9 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/test_atom/test_atom.md: -------------------------------------------------------------------------------- 1 | # Documentation for test atom - heading 1 2 | 3 | **bold text** 4 | 5 | _italic text_ 6 | 7 | ## Here's a heading 2 8 | 9 | ### Here's a heading 3 10 | 11 | - here's a list item 12 | - and another 13 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_atom/test_atom.md: -------------------------------------------------------------------------------- 1 | # Documentation for test atom - heading 1 2 | 3 | **bold text** 4 | 5 | _italic text_ 6 | 7 | ## Here's a heading 2 8 | 9 | ### Here's a heading 3 10 | 11 | - here's a list item 12 | - and another 13 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/tags_test_atom/invalid_tags_test_atom.html.fail: -------------------------------------------------------------------------------- 1 | {% load test_tags_invalid %} 2 | 3 | MARMA{% default_html_tag_invalid empty_string %}LADE01 4 | MARMA{% default_html_tag_invalid none %}LADE02 5 | MARMA{% default_html_tag_invalid dict %}LADE03 6 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/button/button.html: -------------------------------------------------------------------------------- 1 | {% load test_tags %} 2 | 3 | {% if label %}{{ label }}{% else %}{{ target_page.title }}{% endif %} 4 | 5 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_includes/test_includes.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | variable_include: non-patterns/variable_include.html 3 | 4 | # TODO: Unsupported override with Jinja 5 | tags: 6 | error_tag: 7 | include: 8 | template_name: 'non-patterns/include.html' 9 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/test_molecule/test_molecule.html: -------------------------------------------------------------------------------- 1 | {% include 'patterns_jinja/components/test_atom/test_atom.html' %} 2 | {% set atom_var='atom_var value from test_molecule.html include tag' %} 3 | {% include 'patterns_jinja/components/test_atom/test_atom.html' %} 4 | -------------------------------------------------------------------------------- /docs/recipes/inclusion-tags.md: -------------------------------------------------------------------------------- 1 | ## Inclusion tags 2 | 3 | ```jinja2 4 |
7 | ``` 8 | 9 | ```yaml 10 | tags: 11 | footernav: 12 | '': 13 | template_name: 'patterns/molecules/navigation/footernav.html' 14 | ``` 15 | -------------------------------------------------------------------------------- /.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 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | 13 | [*.{yaml,yml,json,json5,md,toml}] 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/js/components/hide-menu-mobile.js: -------------------------------------------------------------------------------- 1 | export default function () { 2 | // hide the sidebar if coming from a mobile device 3 | if (window.matchMedia('(max-width: 600px)').matches) { 4 | document.querySelector('body').classList.add('nav-closed'); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class ExampleForm(forms.Form): 5 | single_line_text = forms.CharField( 6 | max_length=255, help_text="This is some help text" 7 | ) 8 | choices = (("one", "One"), ("two", "Two"), ("three", "Three"), ("four", "Four")) 9 | select = forms.ChoiceField(choices=choices) 10 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # git-blame ignored revisions 2 | # To configure, run 3 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 4 | # Requires Git > 2.23 5 | # See https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt 6 | 7 | # Initial Prettier reformatting (#TBC) 8 | 849aaa98b7900ec5e93cfbed56379ddeb44c723d 9 | -------------------------------------------------------------------------------- /tests/templates/patterns/pages/test_page/test_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'patterns/base_page.html' %} 2 | 3 | {% block content %} 4 |is_pattern_library = {{ is_pattern_library }}
11 | {% endif %} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/pages/test_page/test_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'patterns_jinja/base_page_jinja.html' %} 2 | 3 | {% block content %} 4 |is_pattern_library = {{ is_pattern_library }}
11 | {% endif %} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/js/components/syntax-highlighting.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js/lib/core'; 2 | import django from 'highlight.js/lib/languages/django'; 3 | import yaml from 'highlight.js/lib/languages/yaml'; 4 | 5 | export default function () { 6 | hljs.registerLanguage('django', django); 7 | hljs.registerLanguage('yaml', yaml); 8 | hljs.highlightAll(); 9 | } 10 | -------------------------------------------------------------------------------- /tests/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.urls import include, path 3 | 4 | from pattern_library import urls as pattern_library_urls 5 | 6 | if settings.GITHUB_PAGES_EXPORT: 7 | urlpatterns = [ 8 | path("django-pattern-library/demo/", include(pattern_library_urls)), 9 | ] 10 | else: 11 | urlpatterns = [ 12 | path("", include(pattern_library_urls)), 13 | ] 14 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/scss/layout/_body.scss: -------------------------------------------------------------------------------- 1 | @use '../config' as *; 2 | 3 | .body { 4 | display: grid; 5 | grid-template-columns: $sidebar-width 1fr; 6 | 7 | &.nav-closed { 8 | grid-template-columns: 0 1fr; 9 | } 10 | 11 | @media only screen and (min-width: 600px) { 12 | transition: grid-template-columns 0.25s ease; // works in firefox 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/templates/patterns/molecules/accordion/accordion.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | id_prefix: test 3 | accordions: 4 | - title: Title A 5 | description: Description A. Ask for help. 6 | - title: Title B 7 | description: Description B. Ask for help. 8 | - title: Title C 9 | description: Description C. Ask for help. 10 | - title: Title D 11 | description: Description D. Ask for help. 12 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/components/accordion/accordion.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | id_prefix: test 3 | accordions: 4 | - title: Title A (Jinja) 5 | description: Description A. Ask for help. 6 | - title: Title B 7 | description: Description B. Ask for help. 8 | - title: Title C 9 | description: Description C. Ask for help. 10 | - title: Title D 11 | description: Description D. Ask for help. 12 | -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/tags_test_atom/tags_test_atom.html: -------------------------------------------------------------------------------- 1 | {% load test_tags %} 2 | 3 | SAND{% error_tag empty_string %}WICH 4 | SAND{% error_tag none %}WICH 5 | SAND{% error_tag zero %}WICH 6 | 7 | POTA{% default_html_tag page.url %}TO 8 | POTA{% default_html_tag page.child.url %}TO 9 | POTA{% default_html_tag None %}TO 10 | 11 | POTA{% default_html_tag_falsey empty_string %}TO1 12 | POTA{% default_html_tag_falsey none %}TO2 13 | POTA{% default_html_tag_falsey zero %}TO3 -------------------------------------------------------------------------------- /tests/templates/patterns/atoms/tags_test_atom/tags_test_atom.yaml: -------------------------------------------------------------------------------- 1 | tags: 2 | error_tag: 3 | empty_string: 4 | raw: '' 5 | none: 6 | raw: None 7 | zero: 8 | raw: 0 9 | default_html_tag: 10 | page.url: 11 | raw: 'example' 12 | page.child.url: 13 | raw: 'another_example' 14 | # None handled by default html value. 15 | default_html_tag_falsey: 16 | empty_string: 17 | raw: '' 18 | none: 19 | raw: None 20 | zero: 21 | raw: 0 22 | -------------------------------------------------------------------------------- /tests/templatetags/test_tags_invalid.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | from pattern_library.monkey_utils import override_tag 4 | 5 | register = template.Library() 6 | 7 | 8 | @register.simple_tag() 9 | def default_html_tag_invalid(arg=None): 10 | "Just raise an exception, never do anything" 11 | raise Exception("default_tag raised an exception") 12 | 13 | 14 | # Test overriding tag with a default_html that's not valid in Django >= 4.0 15 | override_tag(register, "default_html_tag_invalid", default_html=[1, 2, 3]) 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10 2 | 3 | WORKDIR /app 4 | 5 | RUN useradd --create-home dpl && \ 6 | mkdir -p /venv/ && \ 7 | chown -R dpl:dpl /venv/ /app/ 8 | 9 | ENV PATH=/venv/bin:/home/dpl/.local/bin:$PATH \ 10 | PYTHONPATH=/app/ \ 11 | VIRTUAL_ENV=/venv/ \ 12 | DJANGO_SETTINGS_MODULE=tests.settings.dev 13 | 14 | USER dpl 15 | 16 | RUN pip install --user "poetry>=2.1.2,<3" && \ 17 | python -m venv /venv/ 18 | 19 | COPY pyproject.toml ./ 20 | RUN poetry install --no-root 21 | 22 | CMD django-admin runserver 0.0.0.0:8000 23 | -------------------------------------------------------------------------------- /pattern_library/static/pattern_library/src/scss/components/_icon.scss: -------------------------------------------------------------------------------- 1 | @use '../config' as *; 2 | 3 | .icon { 4 | &--close-menu { 5 | width: 14px; 6 | height: 14px; 7 | fill: $white; 8 | transition: transform 0.25s ease; 9 | 10 | .nav-closed & { 11 | transform: rotate(-45deg); 12 | } 13 | } 14 | 15 | &--external { 16 | width: 18px; 17 | height: 20px; 18 | fill: $link-color; 19 | vertical-align: -4px; 20 | margin-left: 3px; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/base_jinja.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |5 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod 6 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 7 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 8 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 9 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat 10 | non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 11 |
12 | -------------------------------------------------------------------------------- /tests/jinja/patterns_jinja/pages/test_page/test_page.yaml: -------------------------------------------------------------------------------- 1 | context: 2 | page: 3 | title: Jinja test page 4 | body: > 5 |6 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod 7 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 8 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 9 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 10 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat 11 | non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 12 |
13 | -------------------------------------------------------------------------------- /docs/recipes/image-include.md: -------------------------------------------------------------------------------- 1 | ## Image include 2 | 3 | To create test cases for images, we recommend using an image hotlinking service like [Unsplash](https://unsplash.com/) or [placeholder.com](https://placeholder.com/). 4 | 5 | ```jinja2 6 |{{ accordion.description }}
12 |{{ accordion.description }}
14 |{{ page.job_title }}
11 | {% endif %} 12 | 13 | {% if page.website %} 14 | 15 | {% endif %} 16 | 17 | {% if page.email %} 18 | 19 | {% endif %} 20 | 21 | {% for item in page.social_media_profile.all %} 22 | 23 | {% endfor %} 24 | 25 | {% with phone_numbers=page.phone_numbers.all %} 26 | {% if phone_numbers %} 27 | {% for related_phone_number in phone_numbers %} 28 | 29 | {% endfor %} 30 | {% endif %} 31 | {% endwith %} 32 |{{ page.introduction }}
38 | {% endif %} 39 |{{ person_type }}
53 | {% endfor %} 54 |{{ call_to_action.title }}
11 | {% include "patterns/atoms/link/link.html" with type="primary" classes="call-to-action__link" href=call_to_action.get_link_url text=call_to_action.get_link_text %} 12 |{{ call_to_action.type }}
35 | {% include "patterns/molecules/cta/call_to_action.html" with call_to_action=call_to_action %} 36 |{{ pattern_source }}
42 | {{ pattern_config }}
46 | 31 |38 | ``` 39 | 40 | We could create another template next to it called `quote_block_example.html`, 41 | 42 | ```django 43 |32 |37 |{{ quote }}
33 | {% if attribution %} 34 |{{ attribution }}
35 | {% endif %} 36 |