Инициализация

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich
2021-12-01 10:02:35 +10:00
commit fdd6e010ec
363 changed files with 34022 additions and 0 deletions

18
vendor/twig/twig/.editorconfig vendored Normal file
View File

@@ -0,0 +1,18 @@
; top-most EditorConfig file
root = true
; Unix-style newlines
[*]
end_of_line = LF
[*.php]
indent_style = space
indent_size = 4
[*.test]
indent_style = space
indent_size = 4
[*.rst]
indent_style = space
indent_size = 4

3
vendor/twig/twig/.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
/extra/** export-ignore
/tests export-ignore
/phpunit.xml.dist export-ignore

View File

@@ -0,0 +1,173 @@
name: "CI"
on:
pull_request:
push:
branches:
- '3.x'
env:
SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: 1
jobs:
tests:
name: "PHP ${{ matrix.php-version }}"
runs-on: 'ubuntu-latest'
continue-on-error: ${{ matrix.experimental }}
strategy:
matrix:
php-version:
- '7.2.5'
- '7.3'
- '7.4'
- '8.0'
composer-options: ['']
experimental: [false]
include:
- { php-version: '8.1', experimental: true, composer-options: '--ignore-platform-req=php' }
steps:
- name: "Checkout code"
uses: actions/checkout@v2.3.3
- name: "Install PHP with extensions"
uses: shivammathur/setup-php@2.7.0
with:
coverage: "none"
php-version: ${{ matrix.php-version }}
ini-values: memory_limit=-1
tools: composer:v2
- name: "Add PHPUnit matcher"
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: "Set composer cache directory"
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: "Cache composer"
uses: actions/cache@v2.1.2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-composer-
- run: composer install ${{ matrix.composer-options }}
- name: "Install PHPUnit"
run: vendor/bin/simple-phpunit install
- name: "PHPUnit version"
run: vendor/bin/simple-phpunit --version
- name: "Run tests"
run: vendor/bin/simple-phpunit
extension-tests:
needs:
- 'tests'
name: "${{ matrix.extension }} with PHP ${{ matrix.php-version }}"
runs-on: 'ubuntu-latest'
continue-on-error: true
strategy:
matrix:
php-version:
- '7.2.5'
- '7.3'
- '7.4'
- '8.0'
extension:
- 'extra/cache-extra'
- 'extra/cssinliner-extra'
- 'extra/html-extra'
- 'extra/inky-extra'
- 'extra/intl-extra'
- 'extra/markdown-extra'
- 'extra/string-extra'
- 'extra/twig-extra-bundle'
steps:
- name: "Checkout code"
uses: actions/checkout@v2.3.3
- name: "Install PHP with extensions"
uses: shivammathur/setup-php@2.7.0
with:
coverage: "none"
php-version: ${{ matrix.php-version }}
ini-values: memory_limit=-1
tools: composer:v2
- name: "Add PHPUnit matcher"
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: "Set composer cache directory"
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: "Cache composer"
uses: actions/cache@v2.1.2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.extension }}-
- run: composer install
- name: "Install PHPUnit"
run: vendor/bin/simple-phpunit install
- name: "PHPUnit version"
run: vendor/bin/simple-phpunit --version
- if: matrix.extension == 'extra/markdown-extra' && matrix.php-version == '8.0'
working-directory: ${{ matrix.extension}}
run: composer config platform.php 7.4.99
- name: "Composer install"
working-directory: ${{ matrix.extension}}
run: composer install
- name: "Run tests"
working-directory: ${{ matrix.extension}}
run: ../../vendor/bin/simple-phpunit
#
# Drupal does not support Twig 3 now!
#
# integration-tests:
# needs:
# - 'tests'
#
# name: "Integration tests with PHP ${{ matrix.php-version }}"
#
# runs-on: 'ubuntu-20.04'
#
# continue-on-error: true
#
# strategy:
# matrix:
# php-version:
# - '7.3'
#
# steps:
# - name: "Checkout code"
# uses: actions/checkout@v2.3.3
#
# - name: "Install PHP with extensions"
# uses: shivammathur/setup-php@2.7.0
# with:
# coverage: "none"
# extensions: "gd, pdo_sqlite"
# php-version: ${{ matrix.php-version }}
# ini-values: memory_limit=-1
# tools: composer:v2
#
# - run: bash ./tests/drupal_test.sh
# shell: "bash"

View File

@@ -0,0 +1,60 @@
name: "Documentation"
on:
pull_request:
push:
branches:
- '3.x'
jobs:
build:
name: "Build"
runs-on: ubuntu-latest
steps:
- name: "Checkout code"
uses: actions/checkout@v2
- name: "Set up Python 3.7"
uses: actions/setup-python@v1
with:
python-version: '3.7' # Semantic version range syntax or exact version of a Python version
- name: "Display Python version"
run: python -c "import sys; print(sys.version)"
- name: "Install Sphinx dependencies"
run: sudo apt-get install python-dev build-essential
- name: "Cache pip"
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('_build/.requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: "Install Sphinx + requirements via pip"
working-directory: "doc"
run: pip install -r _build/.requirements.txt
- name: "Build documentation"
working-directory: "doc"
run: make -C _build SPHINXOPTS="-nqW -j auto" html
doctor-rst:
name: "DOCtor-RST"
runs-on: ubuntu-latest
steps:
- name: "Checkout code"
uses: actions/checkout@v2
- name: "Run DOCtor-RST"
uses: docker://oskarstark/doctor-rst
with:
args: --short
env:
DOCS_DIR: 'doc/'

4
vendor/twig/twig/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/composer.lock
/phpunit.xml
/vendor
.phpunit.result.cache

20
vendor/twig/twig/.php-cs-fixer.dist.php vendored Normal file
View File

@@ -0,0 +1,20 @@
<?php
return (new PhpCsFixer\Config())
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'@PHPUnit75Migration:risky' => true,
'php_unit_dedicate_assert' => ['target' => '5.6'],
'array_syntax' => ['syntax' => 'short'],
'php_unit_fqcn_annotation' => true,
'no_unreachable_default_argument_value' => false,
'braces' => ['allow_single_line_closure' => true],
'heredoc_to_nowdoc' => false,
'ordered_imports' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'],
])
->setRiskyAllowed(true)
->setFinder((new PhpCsFixer\Finder())->in(__DIR__))
;

1646
vendor/twig/twig/CHANGELOG vendored Normal file

File diff suppressed because it is too large Load Diff

27
vendor/twig/twig/LICENSE vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2009-2021 by the Twig Team.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Twig nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

24
vendor/twig/twig/README.rst vendored Normal file
View File

@@ -0,0 +1,24 @@
Twig, the flexible, fast, and secure template language for PHP
==============================================================
Twig is a template language for PHP, released under the new BSD license (code
and documentation).
Twig uses a syntax similar to the Django and Jinja template languages which
inspired the Twig runtime environment.
Sponsors
--------
.. raw:: html
<a href="https://blackfire.io/docs/introduction?utm_source=twig&utm_medium=github_readme&utm_campaign=logo">
<img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io">
</a>
More Information
----------------
Read the `documentation`_ for more information.
.. _documentation: https://twig.symfony.com/documentation

50
vendor/twig/twig/composer.json vendored Normal file
View File

@@ -0,0 +1,50 @@
{
"name": "twig/twig",
"type": "library",
"description": "Twig, the flexible, fast, and secure template language for PHP",
"keywords": ["templating"],
"homepage": "https://twig.symfony.com",
"license": "BSD-3-Clause",
"minimum-stability": "dev",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Twig Team",
"role": "Contributors"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
}
],
"require": {
"php": ">=7.2.5",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0",
"psr/container": "^1.0"
},
"autoload": {
"psr-4" : {
"Twig\\" : "src/"
}
},
"autoload-dev": {
"psr-4" : {
"Twig\\Tests\\" : "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "3.3-dev"
}
}
}

54
vendor/twig/twig/doc/.doctor-rst.yaml vendored Normal file
View File

@@ -0,0 +1,54 @@
rules:
american_english: ~
avoid_repetetive_words: ~
blank_line_after_directive: ~
blank_line_before_directive: ~
composer_dev_option_not_at_the_end: ~
correct_code_block_directive_based_on_the_content: ~
deprecated_directive_should_have_version: ~
ensure_order_of_code_blocks_in_configuration_block: ~
extension_xlf_instead_of_xliff: ~
indention: ~
lowercase_as_in_use_statements: ~
max_blank_lines:
max: 2
no_blank_line_after_filepath_in_php_code_block: ~
no_blank_line_after_filepath_in_twig_code_block: ~
no_blank_line_after_filepath_in_xml_code_block: ~
no_blank_line_after_filepath_in_yaml_code_block: ~
no_composer_req: ~
no_explicit_use_of_code_block_php: ~
no_inheritdoc: ~
no_namespace_after_use_statements: ~
no_php_open_tag_in_code_block_php_directive: ~
no_space_before_self_xml_closing_tag: ~
ordered_use_statements: ~
php_prefix_before_bin_console: ~
replace_code_block_types: ~
replacement: ~
short_array_syntax: ~
typo: ~
unused_links: ~
use_deprecated_directive_instead_of_versionadded: ~
use_https_xsd_urls: ~
valid_inline_highlighted_namespaces: ~
valid_use_statements: ~
versionadded_directive_should_have_version: ~
yaml_instead_of_yml_suffix: ~
yarn_dev_option_at_the_end: ~
versionadded_directive_major_version:
major_version: 3
versionadded_directive_min_version:
min_version: '3.0'
deprecated_directive_major_version:
major_version: 3
deprecated_directive_min_version:
min_version: '3.0'
whitelist:
lines:
- 'I like Twig.<br />'

View File

@@ -0,0 +1,6 @@
docutils==0.13.1
Pygments==2.2.0
sphinx==1.8.5
git+https://github.com/fabpot/sphinx-php.git@v2.0.0#egg_name=sphinx-php
jsx-lexer===0.0.8
sphinx_rtd_theme==0.5.0

153
vendor/twig/twig/doc/_build/Makefile vendored Normal file
View File

@@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = .
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -c $(BUILDDIR) -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ../
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Symfony.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Symfony.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Symfony"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Symfony"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

271
vendor/twig/twig/doc/_build/conf.py vendored Normal file
View File

@@ -0,0 +1,271 @@
# -*- coding: utf-8 -*-
#
# Symfony documentation build configuration file, created by
# sphinx-quickstart on Sat Jul 28 21:58:57 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('_exts'))
# adding PhpLexer
from sphinx.highlighting import lexers
from pygments.lexers.special import TextLexer
from pygments.lexers.text import RstLexer
from pygments.lexers.web import PhpLexer
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = '1.8.5'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc', 'sphinx.ext.doctest',
'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig',
'sphinx.ext.viewcode', 'sphinx.ext.extlinks',
'sensio.sphinx.codeblock', 'sensio.sphinx.configurationblock', 'sensio.sphinx.phpcode', 'sensio.sphinx.bestpractice'
]
#spelling_show_sugestions=True
#spelling_lang='en_US'
#spelling_word_list_filename='_build/spelling_word_list.txt'
# Add any paths that contain templates here, relative to this directory.
# templates_path = ['_theme/_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Twig'
copyright = ''
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
# version = '2.2'
# The full version, including alpha/beta/rc tags.
# release = '2.2.13'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
#pygments_style = 'symfonycom.sphinx.SensioStyle'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Settings for symfony doc extension ---------------------------------------------------
# enable highlighting for PHP code not between ``<?php ... ?>`` by default
lexers['php'] = PhpLexer(startinline=True)
lexers['rst'] = RstLexer()
config_block = {
'rst': 'reStructuredText',
}
# don't enable Sphinx Domains
primary_domain = None
# set url for API links
#api_url = 'https://github.com/symfony/symfony/blob/master/src/%s.php'
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'logo_only': True,
'prev_next_buttons_location': None,
'style_nav_header_background': '#f0f0f0'
}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = '_static/symfony-logo.svg'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']
#html_css_files = ['rtd_custom.css']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Twig'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
#latex_documents = []
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
#man_pages = []
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
#texinfo_documents = []
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# Use PHP syntax highlighting in code examples by default
highlight_language='php'

911
vendor/twig/twig/doc/advanced.rst vendored Normal file
View File

@@ -0,0 +1,911 @@
Extending Twig
==============
Twig can be extended in many ways; you can add extra tags, filters, tests,
operators, global variables, and functions. You can even extend the parser
itself with node visitors.
.. note::
The first section of this chapter describes how to extend Twig. If you want
to reuse your changes in different projects or if you want to share them
with others, you should then create an extension as described in the
following section.
.. caution::
When extending Twig without creating an extension, Twig won't be able to
recompile your templates when the PHP code is updated. To see your changes
in real-time, either disable template caching or package your code into an
extension (see the next section of this chapter).
Before extending Twig, you must understand the differences between all the
different possible extension points and when to use them.
First, remember that Twig has two main language constructs:
* ``{{ }}``: used to print the result of an expression evaluation;
* ``{% %}``: used to execute statements.
To understand why Twig exposes so many extension points, let's see how to
implement a *Lorem ipsum* generator (it needs to know the number of words to
generate).
You can use a ``lipsum`` *tag*:
.. code-block:: twig
{% lipsum 40 %}
That works, but using a tag for ``lipsum`` is not a good idea for at least
three main reasons:
* ``lipsum`` is not a language construct;
* The tag outputs something;
* The tag is not flexible as you cannot use it in an expression:
.. code-block:: twig
{{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }}
In fact, you rarely need to create tags; and that's good news because tags are
the most complex extension point.
Now, let's use a ``lipsum`` *filter*:
.. code-block:: twig
{{ 40|lipsum }}
Again, it works. But a filter should transform the passed value to something
else. Here, we use the value to indicate the number of words to generate (so,
``40`` is an argument of the filter, not the value we want to transform).
Next, let's use a ``lipsum`` *function*:
.. code-block:: twig
{{ lipsum(40) }}
Here we go. For this specific example, the creation of a function is the
extension point to use. And you can use it anywhere an expression is accepted:
.. code-block:: twig
{{ 'some text' ~ lipsum(40) ~ 'some more text' }}
{% set lipsum = lipsum(40) %}
Lastly, you can also use a *global* object with a method able to generate lorem
ipsum text:
.. code-block:: twig
{{ text.lipsum(40) }}
As a rule of thumb, use functions for frequently used features and global
objects for everything else.
Keep in mind the following when you want to extend Twig:
========== ========================== ========== =========================
What? Implementation difficulty? How often? When?
========== ========================== ========== =========================
*macro* simple frequent Content generation
*global* simple frequent Helper object
*function* simple frequent Content generation
*filter* simple frequent Value transformation
*tag* complex rare DSL language construct
*test* simple rare Boolean decision
*operator* simple rare Values transformation
========== ========================== ========== =========================
Globals
-------
A global variable is like any other template variable, except that it's
available in all templates and macros::
$twig = new \Twig\Environment($loader);
$twig->addGlobal('text', new Text());
You can then use the ``text`` variable anywhere in a template:
.. code-block:: twig
{{ text.lipsum(40) }}
Filters
-------
Creating a filter consists of associating a name with a PHP callable::
// an anonymous function
$filter = new \Twig\TwigFilter('rot13', function ($string) {
return str_rot13($string);
});
// or a simple PHP function
$filter = new \Twig\TwigFilter('rot13', 'str_rot13');
// or a class static method
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
$filter = new \Twig\TwigFilter('rot13', 'SomeClass::rot13Filter');
// or a class method
$filter = new \Twig\TwigFilter('rot13', [$this, 'rot13Filter']);
// the one below needs a runtime implementation (see below for more information)
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
The first argument passed to the ``\Twig\TwigFilter`` constructor is the name of the
filter you will use in templates and the second one is the PHP callable to
associate with it.
Then, add the filter to the Twig environment::
$twig = new \Twig\Environment($loader);
$twig->addFilter($filter);
And here is how to use it in a template:
.. code-block:: twig
{{ 'Twig'|rot13 }}
{# will output Gjvt #}
When called by Twig, the PHP callable receives the left side of the filter
(before the pipe ``|``) as the first argument and the extra arguments passed
to the filter (within parentheses ``()``) as extra arguments.
For instance, the following code:
.. code-block:: twig
{{ 'TWIG'|lower }}
{{ now|date('d/m/Y') }}
is compiled to something like the following::
<?php echo strtolower('TWIG') ?>
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
The ``\Twig\TwigFilter`` class takes an array of options as its last argument::
$filter = new \Twig\TwigFilter('rot13', 'str_rot13', $options);
Environment-aware Filters
~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to access the current environment instance in your filter, set the
``needs_environment`` option to ``true``; Twig will pass the current
environment as the first argument to the filter call::
$filter = new \Twig\TwigFilter('rot13', function (\Twig\Environment $env, $string) {
// get the current charset for instance
$charset = $env->getCharset();
return str_rot13($string);
}, ['needs_environment' => true]);
Context-aware Filters
~~~~~~~~~~~~~~~~~~~~~
If you want to access the current context in your filter, set the
``needs_context`` option to ``true``; Twig will pass the current context as
the first argument to the filter call (or the second one if
``needs_environment`` is also set to ``true``)::
$filter = new \Twig\TwigFilter('rot13', function ($context, $string) {
// ...
}, ['needs_context' => true]);
$filter = new \Twig\TwigFilter('rot13', function (\Twig\Environment $env, $context, $string) {
// ...
}, ['needs_context' => true, 'needs_environment' => true]);
Automatic Escaping
~~~~~~~~~~~~~~~~~~
If automatic escaping is enabled, the output of the filter may be escaped
before printing. If your filter acts as an escaper (or explicitly outputs HTML
or JavaScript code), you will want the raw output to be printed. In such a
case, set the ``is_safe`` option::
$filter = new \Twig\TwigFilter('nl2br', 'nl2br', ['is_safe' => ['html']]);
Some filters may need to work on input that is already escaped or safe, for
example when adding (safe) HTML tags to originally unsafe output. In such a
case, set the ``pre_escape`` option to escape the input data before it is run
through your filter::
$filter = new \Twig\TwigFilter('somefilter', 'somefilter', ['pre_escape' => 'html', 'is_safe' => ['html']]);
Variadic Filters
~~~~~~~~~~~~~~~~
When a filter should accept an arbitrary number of arguments, set the
``is_variadic`` option to ``true``; Twig will pass the extra arguments as the
last argument to the filter call as an array::
$filter = new \Twig\TwigFilter('thumbnail', function ($file, array $options = []) {
// ...
}, ['is_variadic' => true]);
Be warned that :ref:`named arguments <named-arguments>` passed to a variadic
filter cannot be checked for validity as they will automatically end up in the
option array.
Dynamic Filters
~~~~~~~~~~~~~~~
A filter name containing the special ``*`` character is a dynamic filter and
the ``*`` part will match any string::
$filter = new \Twig\TwigFilter('*_path', function ($name, $arguments) {
// ...
});
The following filters are matched by the above defined dynamic filter:
* ``product_path``
* ``category_path``
A dynamic filter can define more than one dynamic parts::
$filter = new \Twig\TwigFilter('*_path_*', function ($name, $suffix, $arguments) {
// ...
});
The filter receives all dynamic part values before the normal filter arguments,
but after the environment and the context. For instance, a call to
``'foo'|a_path_b()`` will result in the following arguments to be passed to the
filter: ``('a', 'b', 'foo')``.
Deprecated Filters
~~~~~~~~~~~~~~~~~~
You can mark a filter as being deprecated by setting the ``deprecated`` option
to ``true``. You can also give an alternative filter that replaces the
deprecated one when that makes sense::
$filter = new \Twig\TwigFilter('obsolete', function () {
// ...
}, ['deprecated' => true, 'alternative' => 'new_one']);
When a filter is deprecated, Twig emits a deprecation notice when compiling a
template using it. See :ref:`deprecation-notices` for more information.
Functions
---------
Functions are defined in the exact same way as filters, but you need to create
an instance of ``\Twig\TwigFunction``::
$twig = new \Twig\Environment($loader);
$function = new \Twig\TwigFunction('function_name', function () {
// ...
});
$twig->addFunction($function);
Functions support the same features as filters, except for the ``pre_escape``
and ``preserves_safety`` options.
Tests
-----
Tests are defined in the exact same way as filters and functions, but you need
to create an instance of ``\Twig\TwigTest``::
$twig = new \Twig\Environment($loader);
$test = new \Twig\TwigTest('test_name', function () {
// ...
});
$twig->addTest($test);
Tests allow you to create custom application specific logic for evaluating
boolean conditions. As a simple example, let's create a Twig test that checks if
objects are 'red'::
$twig = new \Twig\Environment($loader);
$test = new \Twig\TwigTest('red', function ($value) {
if (isset($value->color) && $value->color == 'red') {
return true;
}
if (isset($value->paint) && $value->paint == 'red') {
return true;
}
return false;
});
$twig->addTest($test);
Test functions must always return ``true``/``false``.
When creating tests you can use the ``node_class`` option to provide custom test
compilation. This is useful if your test can be compiled into PHP primitives.
This is used by many of the tests built into Twig::
namespace App;
use Twig\Environment;
use Twig\Node\Expression\TestExpression;
use Twig\TwigTest;
$twig = new Environment($loader);
$test = new TwigTest(
'odd',
null,
['node_class' => OddTestExpression::class]);
$twig->addTest($test);
class OddTestExpression extends TestExpression
{
public function compile(\Twig\Compiler $compiler)
{
$compiler
->raw('(')
->subcompile($this->getNode('node'))
->raw(' % 2 != 0')
->raw(')')
;
}
}
The above example shows how you can create tests that use a node class. The node
class has access to one sub-node called ``node``. This sub-node contains the
value that is being tested. When the ``odd`` filter is used in code such as:
.. code-block:: twig
{% if my_value is odd %}
The ``node`` sub-node will contain an expression of ``my_value``. Node-based
tests also have access to the ``arguments`` node. This node will contain the
various other arguments that have been provided to your test.
If you want to pass a variable number of positional or named arguments to the
test, set the ``is_variadic`` option to ``true``. Tests support dynamic
names (see dynamic filters for the syntax).
Tags
----
One of the most exciting features of a template engine like Twig is the
possibility to define new **language constructs**. This is also the most complex
feature as you need to understand how Twig's internals work.
Most of the time though, a tag is not needed:
* If your tag generates some output, use a **function** instead.
* If your tag modifies some content and returns it, use a **filter** instead.
For instance, if you want to create a tag that converts a Markdown formatted
text to HTML, create a ``markdown`` filter instead:
.. code-block:: twig
{{ '**markdown** text'|markdown }}
If you want use this filter on large amounts of text, wrap it with the
:doc:`apply <tags/apply>` tag:
.. code-block:: twig
{% apply markdown %}
Title
=====
Much better than creating a tag as you can **compose** filters.
{% endapply %}
* If your tag does not output anything, but only exists because of a side
effect, create a **function** that returns nothing and call it via the
:doc:`filter <tags/do>` tag.
For instance, if you want to create a tag that logs text, create a ``log``
function instead and call it via the :doc:`do <tags/do>` tag:
.. code-block:: twig
{% do log('Log some things') %}
If you still want to create a tag for a new language construct, great!
Let's create a ``set`` tag that allows the definition of simple variables from
within a template. The tag can be used like follows:
.. code-block:: twig
{% set name = "value" %}
{{ name }}
{# should output value #}
.. note::
The ``set`` tag is part of the Core extension and as such is always
available. The built-in version is slightly more powerful and supports
multiple assignments by default.
Three steps are needed to define a new tag:
* Defining a Token Parser class (responsible for parsing the template code);
* Defining a Node class (responsible for converting the parsed code to PHP);
* Registering the tag.
Registering a new tag
~~~~~~~~~~~~~~~~~~~~~
Add a tag by calling the ``addTokenParser`` method on the ``\Twig\Environment``
instance::
$twig = new \Twig\Environment($loader);
$twig->addTokenParser(new Project_Set_TokenParser());
Defining a Token Parser
~~~~~~~~~~~~~~~~~~~~~~~
Now, let's see the actual code of this class::
class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser
{
public function parse(\Twig\Token $token)
{
$parser = $this->parser;
$stream = $parser->getStream();
$name = $stream->expect(\Twig\Token::NAME_TYPE)->getValue();
$stream->expect(\Twig\Token::OPERATOR_TYPE, '=');
$value = $parser->getExpressionParser()->parseExpression();
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag());
}
public function getTag()
{
return 'set';
}
}
The ``getTag()`` method must return the tag we want to parse, here ``set``.
The ``parse()`` method is invoked whenever the parser encounters a ``set``
tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the
``Project_Set_Node`` calls creating is explained in the next section).
The parsing process is simplified thanks to a bunch of methods you can call
from the token stream (``$this->parser->getStream()``):
* ``getCurrent()``: Gets the current token in the stream.
* ``next()``: Moves to the next token in the stream, *but returns the old one*.
* ``test($type)``, ``test($value)`` or ``test($type, $value)``: Determines whether
the current token is of a particular type or value (or both). The value may be an
array of several possible values.
* ``expect($type[, $value[, $message]])``: If the current token isn't of the given
type/value a syntax error is thrown. Otherwise, if the type and value are correct,
the token is returned and the stream moves to the next token.
* ``look()``: Looks at the next token without consuming it.
Parsing expressions is done by calling the ``parseExpression()`` like we did for
the ``set`` tag.
.. tip::
Reading the existing ``TokenParser`` classes is the best way to learn all
the nitty-gritty details of the parsing process.
Defining a Node
~~~~~~~~~~~~~~~
The ``Project_Set_Node`` class itself is quite short::
class Project_Set_Node extends \Twig\Node\Node
{
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line, $tag = null)
{
parent::__construct(['value' => $value], ['name' => $name], $line, $tag);
}
public function compile(\Twig\Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('$context[\''.$this->getAttribute('name').'\'] = ')
->subcompile($this->getNode('value'))
->raw(";\n")
;
}
}
The compiler implements a fluid interface and provides methods that helps the
developer generate beautiful and readable PHP code:
* ``subcompile()``: Compiles a node.
* ``raw()``: Writes the given string as is.
* ``write()``: Writes the given string by adding indentation at the beginning
of each line.
* ``string()``: Writes a quoted string.
* ``repr()``: Writes a PHP representation of a given value (see
``\Twig\Node\ForNode`` for a usage example).
* ``addDebugInfo()``: Adds the line of the original template file related to
the current node as a comment.
* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a
usage example).
* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a
usage example).
.. _creating_extensions:
Creating an Extension
---------------------
The main motivation for writing an extension is to move often used code into a
reusable class like adding support for internationalization. An extension can
define tags, filters, tests, operators, functions, and node visitors.
Most of the time, it is useful to create a single extension for your project,
to host all the specific tags and filters you want to add to Twig.
.. tip::
When packaging your code into an extension, Twig is smart enough to
recompile your templates whenever you make a change to it (when
``auto_reload`` is enabled).
An extension is a class that implements the following interface::
interface \Twig\Extension\ExtensionInterface
{
/**
* Returns the token parser instances to add to the existing list.
*
* @return \Twig\TokenParser\TokenParserInterface[]
*/
public function getTokenParsers();
/**
* Returns the node visitor instances to add to the existing list.
*
* @return \Twig\NodeVisitor\NodeVisitorInterface[]
*/
public function getNodeVisitors();
/**
* Returns a list of filters to add to the existing list.
*
* @return \Twig\TwigFilter[]
*/
public function getFilters();
/**
* Returns a list of tests to add to the existing list.
*
* @return \Twig\TwigTest[]
*/
public function getTests();
/**
* Returns a list of functions to add to the existing list.
*
* @return \Twig\TwigFunction[]
*/
public function getFunctions();
/**
* Returns a list of operators to add to the existing list.
*
* @return array<array> First array of unary operators, second array of binary operators
*/
public function getOperators();
}
To keep your extension class clean and lean, inherit from the built-in
``\Twig\Extension\AbstractExtension`` class instead of implementing the interface as it provides
empty implementations for all methods::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
}
This extension does nothing for now. We will customize it in the next sections.
You can save your extension anywhere on the filesystem, as all extensions must
be registered explicitly to be available in your templates.
You can register an extension by using the ``addExtension()`` method on your
main ``Environment`` object::
$twig = new \Twig\Environment($loader);
$twig->addExtension(new Project_Twig_Extension());
.. tip::
The Twig core extensions are great examples of how extensions work.
Globals
~~~~~~~
Global variables can be registered in an extension via the ``getGlobals()``
method::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension implements \Twig\Extension\GlobalsInterface
{
public function getGlobals(): array
{
return [
'text' => new Text(),
];
}
// ...
}
Functions
~~~~~~~~~
Functions can be registered in an extension via the ``getFunctions()``
method::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getFunctions()
{
return [
new \Twig\TwigFunction('lipsum', 'generate_lipsum'),
];
}
// ...
}
Filters
~~~~~~~
To add a filter to an extension, you need to override the ``getFilters()``
method. This method must return an array of filters to add to the Twig
environment::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getFilters()
{
return [
new \Twig\TwigFilter('rot13', 'str_rot13'),
];
}
// ...
}
Tags
~~~~
Adding a tag in an extension can be done by overriding the
``getTokenParsers()`` method. This method must return an array of tags to add
to the Twig environment::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getTokenParsers()
{
return [new Project_Set_TokenParser()];
}
// ...
}
In the above code, we have added a single new tag, defined by the
``Project_Set_TokenParser`` class. The ``Project_Set_TokenParser`` class is
responsible for parsing the tag and compiling it to PHP.
Operators
~~~~~~~~~
The ``getOperators()`` methods lets you add new operators. Here is how to add
the ``!``, ``||``, and ``&&`` operators::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getOperators()
{
return [
[
'!' => ['precedence' => 50, 'class' => \Twig\Node\Expression\Unary\NotUnary::class],
],
[
'||' => ['precedence' => 10, 'class' => \Twig\Node\Expression\Binary\OrBinary::class, 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
'&&' => ['precedence' => 15, 'class' => \Twig\Node\Expression\Binary\AndBinary::class, 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
],
];
}
// ...
}
Tests
~~~~~
The ``getTests()`` method lets you add new test functions::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getTests()
{
return [
new \Twig\TwigTest('even', 'twig_test_even'),
];
}
// ...
}
Definition vs Runtime
~~~~~~~~~~~~~~~~~~~~~
Twig filters, functions, and tests runtime implementations can be defined as
any valid PHP callable:
* **functions/static methods**: Simple to implement and fast (used by all Twig
core extensions); but it is hard for the runtime to depend on external
objects;
* **closures**: Simple to implement;
* **object methods**: More flexible and required if your runtime code depends
on external objects.
The simplest way to use methods is to define them on the extension itself::
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
private $rot13Provider;
public function __construct($rot13Provider)
{
$this->rot13Provider = $rot13Provider;
}
public function getFunctions()
{
return [
new \Twig\TwigFunction('rot13', [$this, 'rot13']),
];
}
public function rot13($value)
{
return $this->rot13Provider->rot13($value);
}
}
This is very convenient but not recommended as it makes template compilation
depend on runtime dependencies even if they are not needed (think for instance
as a dependency that connects to a database engine).
You can decouple the extension definitions from their runtime implementations by
registering a ``\Twig\RuntimeLoader\RuntimeLoaderInterface`` instance on the
environment that knows how to instantiate such runtime classes (runtime classes
must be autoload-able)::
class RuntimeLoader implements \Twig\RuntimeLoader\RuntimeLoaderInterface
{
public function load($class)
{
// implement the logic to create an instance of $class
// and inject its dependencies
// most of the time, it means using your dependency injection container
if ('Project_Twig_RuntimeExtension' === $class) {
return new $class(new Rot13Provider());
} else {
// ...
}
}
}
$twig->addRuntimeLoader(new RuntimeLoader());
.. note::
Twig comes with a PSR-11 compatible runtime loader
(``\Twig\RuntimeLoader\ContainerRuntimeLoader``).
It is now possible to move the runtime logic to a new
``Project_Twig_RuntimeExtension`` class and use it directly in the extension::
class Project_Twig_RuntimeExtension
{
private $rot13Provider;
public function __construct($rot13Provider)
{
$this->rot13Provider = $rot13Provider;
}
public function rot13($value)
{
return $this->rot13Provider->rot13($value);
}
}
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
{
public function getFunctions()
{
return [
new \Twig\TwigFunction('rot13', ['Project_Twig_RuntimeExtension', 'rot13']),
// or
new \Twig\TwigFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'),
];
}
}
Testing an Extension
--------------------
Functional Tests
~~~~~~~~~~~~~~~~
You can create functional tests for extensions by creating the following file
structure in your test directory::
Fixtures/
filters/
foo.test
bar.test
functions/
foo.test
bar.test
tags/
foo.test
bar.test
IntegrationTest.php
The ``IntegrationTest.php`` file should look like this::
use Twig\Test\IntegrationTestCase;
class Project_Tests_IntegrationTest extends IntegrationTestCase
{
public function getExtensions()
{
return [
new Project_Twig_Extension1(),
new Project_Twig_Extension2(),
];
}
public function getFixturesDir()
{
return __DIR__.'/Fixtures/';
}
}
Fixtures examples can be found within the Twig repository
`tests/Twig/Fixtures`_ directory.
Node Tests
~~~~~~~~~~
Testing the node visitors can be complex, so extend your test cases from
``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository
`tests/Twig/Node`_ directory.
.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/3.x/tests/Fixtures
.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/3.x/tests/Node

583
vendor/twig/twig/doc/api.rst vendored Normal file
View File

@@ -0,0 +1,583 @@
Twig for Developers
===================
This chapter describes the API to Twig and not the template language. It will
be most useful as reference to those implementing the template interface to
the application and not those who are creating Twig templates.
Basics
------
Twig uses a central object called the **environment** (of class
``\Twig\Environment``). Instances of this class are used to store the
configuration and extensions, and are used to load templates.
Most applications create one ``\Twig\Environment`` object on application
initialization and use that to load templates. In some cases, it might be useful
to have multiple environments side by side, with different configurations.
The typical way to configure Twig to load templates for an application looks
roughly like this::
require_once '/path/to/vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
$twig = new \Twig\Environment($loader, [
'cache' => '/path/to/compilation_cache',
]);
This creates a template environment with a default configuration and a loader
that looks up templates in the ``/path/to/templates/`` directory. Different
loaders are available and you can also write your own if you want to load
templates from a database or other resources.
.. note::
Notice that the second argument of the environment is an array of options.
The ``cache`` option is a compilation cache directory, where Twig caches
the compiled templates to avoid the parsing phase for sub-sequent
requests. It is very different from the cache you might want to add for
the evaluated templates. For such a need, you can use any available PHP
cache library.
Rendering Templates
-------------------
To load a template from a Twig environment, call the ``load()`` method which
returns a ``\Twig\TemplateWrapper`` instance::
$template = $twig->load('index.html');
To render the template with some variables, call the ``render()`` method::
echo $template->render(['the' => 'variables', 'go' => 'here']);
.. note::
The ``display()`` method is a shortcut to output the rendered template.
You can also load and render the template in one fell swoop::
echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
If a template defines blocks, they can be rendered individually via the
``renderBlock()`` call::
echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
.. _environment_options:
Environment Options
-------------------
When creating a new ``\Twig\Environment`` instance, you can pass an array of
options as the constructor second argument::
$twig = new \Twig\Environment($loader, ['debug' => true]);
The following options are available:
* ``debug`` *boolean*
When set to ``true``, the generated templates have a
``__toString()`` method that you can use to display the generated nodes
(default to ``false``).
* ``charset`` *string* (defaults to ``utf-8``)
The charset used by the templates.
* ``cache`` *string* or ``false``
An absolute path where to store the compiled templates, or
``false`` to disable caching (which is the default).
* ``auto_reload`` *boolean*
When developing with Twig, it's useful to recompile the
template whenever the source code changes. If you don't provide a value for
the ``auto_reload`` option, it will be determined automatically based on the
``debug`` value.
* ``strict_variables`` *boolean*
If set to ``false``, Twig will silently ignore invalid
variables (variables and or attributes/methods that do not exist) and
replace them with a ``null`` value. When set to ``true``, Twig throws an
exception instead (default to ``false``).
* ``autoescape`` *string*
Sets the default auto-escaping strategy (``name``, ``html``, ``js``, ``css``,
``url``, ``html_attr``, or a PHP callback that takes the template "filename"
and returns the escaping strategy to use -- the callback cannot be a function
name to avoid collision with built-in escaping strategies); set it to
``false`` to disable auto-escaping. The ``name`` escaping strategy determines
the escaping strategy to use for a template based on the template filename
extension (this strategy does not incur any overhead at runtime as
auto-escaping is done at compilation time.)
* ``optimizations`` *integer*
A flag that indicates which optimizations to apply
(default to ``-1`` -- all optimizations are enabled; set it to ``0`` to
disable).
Loaders
-------
Loaders are responsible for loading templates from a resource such as the file
system.
Compilation Cache
~~~~~~~~~~~~~~~~~
All template loaders can cache the compiled templates on the filesystem for
future reuse. It speeds up Twig a lot as templates are only compiled once.
Built-in Loaders
~~~~~~~~~~~~~~~~
Here is a list of the built-in loaders:
``\Twig\Loader\FilesystemLoader``
.................................
``\Twig\Loader\FilesystemLoader`` loads templates from the file system. This loader
can find templates in folders on the file system and is the preferred way to
load them::
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
It can also look for templates in an array of directories::
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
With such a configuration, Twig will first look for templates in
``$templateDir1`` and if they do not exist, it will fallback to look for them
in the ``$templateDir2``.
You can add or prepend paths via the ``addPath()`` and ``prependPath()``
methods::
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
The filesystem loader also supports namespaced templates. This allows to group
your templates under different namespaces which have their own template paths.
When using the ``setPaths()``, ``addPath()``, and ``prependPath()`` methods,
specify the namespace as the second argument (when not specified, these
methods act on the "main" namespace)::
$loader->addPath($templateDir, 'admin');
Namespaced templates can be accessed via the special
``@namespace_name/template_path`` notation::
$twig->render('@admin/index.html', []);
``\Twig\Loader\FilesystemLoader`` support absolute and relative paths. Using relative
paths is preferred as it makes the cache keys independent of the project root
directory (for instance, it allows warming the cache from a build server where
the directory might be different from the one used on production servers)::
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');
.. note::
When not passing the root path as a second argument, Twig uses ``getcwd()``
for relative paths.
``\Twig\Loader\ArrayLoader``
............................
``\Twig\Loader\ArrayLoader`` loads a template from a PHP array. It is passed an
array of strings bound to template names::
$loader = new \Twig\Loader\ArrayLoader([
'index.html' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);
echo $twig->render('index.html', ['name' => 'Fabien']);
This loader is very useful for unit testing. It can also be used for small
projects where storing all templates in a single PHP file might make sense.
.. tip::
When using the ``Array`` loader with a cache mechanism, you should know that
a new cache key is generated each time a template content "changes" (the
cache key being the source code of the template). If you don't want to see
your cache grows out of control, you need to take care of clearing the old
cache file by yourself.
``\Twig\Loader\ChainLoader``
............................
``\Twig\Loader\ChainLoader`` delegates the loading of templates to other loaders::
$loader1 = new \Twig\Loader\ArrayLoader([
'base.html' => '{% block content %}{% endblock %}',
]);
$loader2 = new \Twig\Loader\ArrayLoader([
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
'base.html' => 'Will never be loaded',
]);
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
$twig = new \Twig\Environment($loader);
When looking for a template, Twig tries each loader in turn and returns as soon
as the template is found. When rendering the ``index.html`` template from the
above example, Twig will load it with ``$loader2`` but the ``base.html``
template will be loaded from ``$loader1``.
.. note::
You can also add loaders via the ``addLoader()`` method.
Create your own Loader
~~~~~~~~~~~~~~~~~~~~~~
All loaders implement the ``\Twig\Loader\LoaderInterface``::
interface \Twig\Loader\LoaderInterface
{
/**
* Returns the source context for a given template logical name.
*
* @param string $name The template logical name
*
* @return \Twig\Source
*
* @throws \Twig\Error\LoaderError When $name is not found
*/
public function getSourceContext($name);
/**
* Gets the cache key to use for the cache for a given template name.
*
* @param string $name The name of the template to load
*
* @return string The cache key
*
* @throws \Twig\Error\LoaderError When $name is not found
*/
public function getCacheKey($name);
/**
* Returns true if the template is still fresh.
*
* @param string $name The template name
* @param timestamp $time The last modification time of the cached template
*
* @return bool true if the template is fresh, false otherwise
*
* @throws \Twig\Error\LoaderError When $name is not found
*/
public function isFresh($name, $time);
/**
* Check if we have the source code of a template, given its name.
*
* @param string $name The name of the template to check if we can load
*
* @return bool If the template source code is handled by this loader or not
*/
public function exists($name);
}
The ``isFresh()`` method must return ``true`` if the current cached template
is still fresh, given the last modification time, or ``false`` otherwise.
The ``getSourceContext()`` method must return an instance of ``\Twig\Source``.
Using Extensions
----------------
Twig extensions are packages that add new features to Twig. Register an
extension via the ``addExtension()`` method::
$twig->addExtension(new \Twig\Extension\SandboxExtension());
Twig comes bundled with the following extensions:
* *Twig\Extension\CoreExtension*: Defines all the core features of Twig.
* *Twig\Extension\DebugExtension*: Defines the ``dump`` function to help debug
template variables.
* *Twig\Extension\EscaperExtension*: Adds automatic output-escaping and the
possibility to escape/unescape blocks of code.
* *Twig\Extension\SandboxExtension*: Adds a sandbox mode to the default Twig
environment, making it safe to evaluate untrusted code.
* *Twig\Extension\ProfilerExtension*: Enables the built-in Twig profiler.
* *Twig\Extension\OptimizerExtension*: Optimizes the node tree before
compilation.
* *Twig\Extension\StringLoaderExtension*: Defines the ``template_from_string``
function to allow loading templates from string in a template.
The Core, Escaper, and Optimizer extensions are registered by default.
Built-in Extensions
-------------------
This section describes the features added by the built-in extensions.
.. tip::
Read the chapter about :doc:`extending Twig <advanced>` to learn how to
create your own extensions.
Core Extension
~~~~~~~~~~~~~~
The ``core`` extension defines all the core features of Twig:
* :doc:`Tags <tags/index>`;
* :doc:`Filters <filters/index>`;
* :doc:`Functions <functions/index>`;
* :doc:`Tests <tests/index>`.
Escaper Extension
~~~~~~~~~~~~~~~~~
The ``escaper`` extension adds automatic output escaping to Twig. It defines a
tag, ``autoescape``, and a filter, ``raw``.
When creating the escaper extension, you can switch on or off the global
output escaping strategy::
$escaper = new \Twig\Extension\EscaperExtension('html');
$twig->addExtension($escaper);
If set to ``html``, all variables in templates are escaped (using the ``html``
escaping strategy), except those using the ``raw`` filter:
.. code-block:: twig
{{ article.to_html|raw }}
You can also change the escaping mode locally by using the ``autoescape`` tag:
.. code-block:: twig
{% autoescape 'html' %}
{{ var }}
{{ var|raw }} {# var won't be escaped #}
{{ var|escape }} {# var won't be double-escaped #}
{% endautoescape %}
.. warning::
The ``autoescape`` tag has no effect on included files.
The escaping rules are implemented as follows:
* Literals (integers, booleans, arrays, ...) used in the template directly as
variables or filter arguments are never automatically escaped:
.. code-block:: html+twig
{{ "Twig<br/>" }} {# won't be escaped #}
{% set text = "Twig<br/>" %}
{{ text }} {# will be escaped #}
* Expressions which the result is a literal or a variable marked safe
are never automatically escaped:
.. code-block:: html+twig
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# won't be escaped #}
{% set text = "Twig<br/>" %}
{{ true ? text : "<br/>Twig" }} {# will be escaped #}
{{ false ? text : "<br/>Twig" }} {# won't be escaped #}
{% set text = "Twig<br/>" %}
{{ foo ? text|raw : "<br/>Twig" }} {# won't be escaped #}
* Objects with a ``__toString`` method are converted to strings and
escaped. You can mark some classes and/or interfaces as being safe for some
strategies via ``EscaperExtension::addSafeClass()``:
.. code-block:: twig
// mark object of class Foo as safe for the HTML strategy
$escaper->addSafeClass('Foo', ['html']);
// mark object of interface Foo as safe for the HTML strategy
$escaper->addSafeClass('FooInterface', ['html']);
// mark object of class Foo as safe for the HTML and JS strategies
$escaper->addSafeClass('Foo', ['html', 'js']);
// mark object of class Foo as safe for all strategies
$escaper->addSafeClass('Foo', ['all']);
* Escaping is applied before printing, after any other filter is applied:
.. code-block:: twig
{{ var|upper }} {# is equivalent to {{ var|upper|escape }} #}
* The `raw` filter should only be used at the end of the filter chain:
.. code-block:: twig
{{ var|raw|upper }} {# will be escaped #}
{{ var|upper|raw }} {# won't be escaped #}
* Automatic escaping is not applied if the last filter in the chain is marked
safe for the current context (e.g. ``html`` or ``js``). ``escape`` and
``escape('html')`` are marked safe for HTML, ``escape('js')`` is marked
safe for JavaScript, ``raw`` is marked safe for everything.
.. code-block:: twig
{% autoescape 'js' %}
{{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
{{ var }} {# will be escaped for JavaScript #}
{{ var|escape('js') }} {# won't be double-escaped #}
{% endautoescape %}
.. note::
Note that autoescaping has some limitations as escaping is applied on
expressions after evaluation. For instance, when working with
concatenation, ``{{ foo|raw ~ bar }}`` won't give the expected result as
escaping is applied on the result of the concatenation, not on the
individual variables (so, the ``raw`` filter won't have any effect here).
Sandbox Extension
~~~~~~~~~~~~~~~~~
The ``sandbox`` extension can be used to evaluate untrusted code. Access to
unsafe attributes and methods is prohibited. The sandbox security is managed
by a policy instance. By default, Twig comes with one policy class:
``\Twig\Sandbox\SecurityPolicy``. This class allows you to white-list some
tags, filters, properties, and methods::
$tags = ['if'];
$filters = ['upper'];
$methods = [
'Article' => ['getTitle', 'getBody'],
];
$properties = [
'Article' => ['title', 'body'],
];
$functions = ['range'];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
With the previous configuration, the security policy will only allow usage of
the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be
able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
objects, and the ``title`` and ``body`` public properties. Everything else
won't be allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception.
The policy object is the first argument of the sandbox constructor::
$sandbox = new \Twig\Extension\SandboxExtension($policy);
$twig->addExtension($sandbox);
By default, the sandbox mode is disabled and should be enabled when including
untrusted template code by using the ``sandbox`` tag:
.. code-block:: twig
{% sandbox %}
{% include 'user.html' %}
{% endsandbox %}
You can sandbox all templates by passing ``true`` as the second argument of
the extension constructor::
$sandbox = new \Twig\Extension\SandboxExtension($policy, true);
Profiler Extension
~~~~~~~~~~~~~~~~~~
The ``profiler`` extension enables a profiler for Twig templates; it should
only be used on your development machines as it adds some overhead::
$profile = new \Twig\Profiler\Profile();
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));
$dumper = new \Twig\Profiler\Dumper\TextDumper();
echo $dumper->dump($profile);
A profile contains information about time and memory consumption for template,
block, and macro executions.
You can also dump the data in a `Blackfire.io <https://blackfire.io/>`_
compatible format::
$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
Upload the profile to visualize it (create a `free account
<https://blackfire.io/signup?utm_source=twig&utm_medium=doc&utm_campaign=profiler>`_
first):
.. code-block:: sh
blackfire --slot=7 upload /path/to/profile.prof
Optimizer Extension
~~~~~~~~~~~~~~~~~~~
The ``optimizer`` extension optimizes the node tree before compilation::
$twig->addExtension(new \Twig\Extension\OptimizerExtension());
By default, all optimizations are turned on. You can select the ones you want
to enable by passing them to the constructor::
$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);
$twig->addExtension($optimizer);
Twig supports the following optimizations:
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL``, enables all optimizations
(this is the default value).
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE``, disables all optimizations.
This reduces the compilation time, but it can increase the execution time
and the consumed memory.
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR``, optimizes the ``for`` tag by
removing the ``loop`` variable creation whenever possible.
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER``, removes the ``raw``
filter whenever possible.
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS``, simplifies the creation
and access of variables in the compiled templates whenever possible.
Exceptions
----------
Twig can throw exceptions:
* ``\Twig\Error\Error``: The base exception for all errors.
* ``\Twig\Error\SyntaxError``: Thrown to tell the user that there is a problem with
the template syntax.
* ``\Twig\Error\RuntimeError``: Thrown when an error occurs at runtime (when a filter
does not exist for instance).
* ``\Twig\Error\LoaderError``: Thrown when an error occurs during template loading.
* ``\Twig\Sandbox\SecurityError``: Thrown when an unallowed tag, filter, or
method is called in a sandboxed template.

View File

@@ -0,0 +1,101 @@
Coding Standards
================
When writing Twig templates, we recommend you to follow these official coding
standards:
* Put one (and only one) space after the start of a delimiter (``{{``, ``{%``,
and ``{#``) and before the end of a delimiter (``}}``, ``%}``, and ``#}``):
.. code-block:: twig
{{ foo }}
{# comment #}
{% if foo %}{% endif %}
When using the whitespace control character, do not put any spaces between
it and the delimiter:
.. code-block:: twig
{{- foo -}}
{#- comment -#}
{%- if foo -%}{%- endif -%}
* Put one (and only one) space before and after the following operators:
comparison operators (``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``), math
operators (``+``, ``-``, ``/``, ``*``, ``%``, ``//``, ``**``), logic
operators (``not``, ``and``, ``or``), ``~``, ``is``, ``in``, and the ternary
operator (``?:``):
.. code-block:: twig
{{ 1 + 2 }}
{{ foo ~ bar }}
{{ true ? true : false }}
* Put one (and only one) space after the ``:`` sign in hashes and ``,`` in
arrays and hashes:
.. code-block:: twig
{{ [1, 2, 3] }}
{{ {'foo': 'bar'} }}
* Do not put any spaces after an opening parenthesis and before a closing
parenthesis in expressions:
.. code-block:: twig
{{ 1 + (2 * 3) }}
* Do not put any spaces before and after string delimiters:
.. code-block:: twig
{{ 'foo' }}
{{ "foo" }}
* Do not put any spaces before and after the following operators: ``|``,
``.``, ``..``, ``[]``:
.. code-block:: twig
{{ foo|upper|lower }}
{{ user.name }}
{{ user[name] }}
{% for i in 1..12 %}{% endfor %}
* Do not put any spaces before and after the parenthesis used for filter and
function calls:
.. code-block:: twig
{{ foo|default('foo') }}
{{ range(1..10) }}
* Do not put any spaces before and after the opening and the closing of arrays
and hashes:
.. code-block:: twig
{{ [1, 2, 3] }}
{{ {'foo': 'bar'} }}
* Use lower cased and underscored variable names:
.. code-block:: twig
{% set foo = 'foo' %}
{% set foo_bar = 'foo' %}
* Indent your code inside tags (use the same indentation as the one used for
the target language of the rendered template):
.. code-block:: twig
{% block foo %}
{% if true %}
true
{% endif %}
{% endblock %}

6
vendor/twig/twig/doc/deprecated.rst vendored Normal file
View File

@@ -0,0 +1,6 @@
Deprecated Features
===================
This document lists deprecated features in Twig 3.x. Deprecated features are
kept for backward compatibility and removed in the next major release (a
feature that was deprecated in Twig 3.x is removed in Twig 4.0).

18
vendor/twig/twig/doc/filters/abs.rst vendored Normal file
View File

@@ -0,0 +1,18 @@
``abs``
=======
The ``abs`` filter returns the absolute value.
.. code-block:: twig
{# number = -5 #}
{{ number|abs }}
{# outputs 5 #}
.. note::
Internally, Twig uses the PHP `abs`_ function.
.. _`abs`: https://www.php.net/abs

44
vendor/twig/twig/doc/filters/batch.rst vendored Normal file
View File

@@ -0,0 +1,44 @@
``batch``
=========
The ``batch`` filter "batches" items by returning a list of lists with the
given number of items. A second parameter can be provided and used to fill in
missing items:
.. code-block:: html+twig
{% set items = ['a', 'b', 'c', 'd'] %}
<table>
{% for row in items|batch(3, 'No item') %}
<tr>
{% for column in row %}
<td>{{ column }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
The above example will be rendered as:
.. code-block:: html+twig
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
<tr>
<td>d</td>
<td>No item</td>
<td>No item</td>
</tr>
</table>
Arguments
---------
* ``size``: The size of the batch; fractional numbers will be rounded up
* ``fill``: Used to fill in missing items
* ``preserve_keys``: Whether to preserve keys or not

View File

@@ -0,0 +1,11 @@
``capitalize``
==============
The ``capitalize`` filter capitalizes a value. The first character will be
uppercase, all others lowercase:
.. code-block:: twig
{{ 'my first car'|capitalize }}
{# outputs 'My first car' #}

24
vendor/twig/twig/doc/filters/column.rst vendored Normal file
View File

@@ -0,0 +1,24 @@
``column``
==========
The ``column`` filter returns the values from a single column in the input
array.
.. code-block:: twig
{% set items = [{ 'fruit' : 'apple'}, {'fruit' : 'orange' }] %}
{% set fruits = items|column('fruit') %}
{# fruits now contains ['apple', 'orange'] #}
.. note::
Internally, Twig uses the PHP `array_column`_ function.
Arguments
---------
* ``name``: The column name to extract
.. _`array_column`: https://www.php.net/array_column

View File

@@ -0,0 +1,22 @@
``convert_encoding``
====================
The ``convert_encoding`` filter converts a string from one encoding to
another. The first argument is the expected output charset and the second one
is the input charset:
.. code-block:: twig
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
.. note::
This filter relies on the `iconv`_ extension.
Arguments
---------
* ``to``: The output charset
* ``from``: The input charset
.. _`iconv`: https://www.php.net/iconv

View File

@@ -0,0 +1,44 @@
``country_name``
================
The ``country_name`` filter returns the country name given its ISO-3166
two-letter code:
.. code-block:: twig
{# France #}
{{ 'FR'|country_name }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# États-Unis #}
{{ 'US'|country_name('fr') }}
.. note::
The ``country_name`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

View File

@@ -0,0 +1,47 @@
``currency_name``
=================
The ``currency_name`` filter returns the currency name given its three-letter
code:
.. code-block:: twig
{# Euro #}
{{ 'EUR'|currency_name }}
{# Japanese Yen #}
{{ 'JPY'|currency_name }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# yen japonais #}
{{ 'JPY'|currency_name('fr_FR') }}
.. note::
The ``currency_name`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

View File

@@ -0,0 +1,47 @@
``currency_symbol``
===================
The ``currency_symbol`` filter returns the currency symbol given its three-letter
code:
.. code-block:: twig
{# € #}
{{ 'EUR'|currency_symbol }}
{# ¥ #}
{{ 'JPY'|currency_symbol }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# ¥ #}
{{ 'JPY'|currency_symbol('fr') }}
.. note::
The ``currency_symbol`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

View File

@@ -0,0 +1,55 @@
``data_uri``
============
The ``data_uri`` filter generates a URL using the data scheme as defined in
`RFC 2397`_:
.. code-block:: html+twig
{{ image_data|data_uri }}
{{ source('path_to_image')|data_uri }}
{# force the mime type, disable the guessing of the mime type #}
{{ image_data|data_uri(mime="image/svg") }}
{# also works with plain text #}
{{ '<b>foobar</b>'|data_uri(mime="text/html") }}
{# add some extra parameters #}
{{ '<b>foobar</b>'|data_uri(mime="text/html", parameters={charset: "ascii"}) }}
.. note::
The ``data_uri`` filter is part of the ``HtmlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/html-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Html\HtmlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new HtmlExtension());
.. note::
The filter does not perform any length validation on purpose (limit depends
on the usage context), validation should be done before calling this filter.
Arguments
---------
* ``mime``: The mime type
* ``parameters``: An array of parameters
.. _RFC 2397: https://tools.ietf.org/html/rfc2397

78
vendor/twig/twig/doc/filters/date.rst vendored Normal file
View File

@@ -0,0 +1,78 @@
``date``
========
The ``date`` filter formats a date to a given format:
.. code-block:: twig
{{ post.published_at|date("m/d/Y") }}
The format specifier is the same as supported by `date`_,
except when the filtered data is of type `DateInterval`_, when the format must conform to
`DateInterval::format`_ instead.
The ``date`` filter accepts strings (it must be in a format supported by the
`strtotime`_ function), `DateTime`_ instances, or `DateInterval`_ instances. For
instance, to display the current date, filter the word "now":
.. code-block:: twig
{{ "now"|date("m/d/Y") }}
To escape words and characters in the date format use ``\\`` in front of each
character:
.. code-block:: twig
{{ post.published_at|date("F jS \\a\\t g:ia") }}
If the value passed to the ``date`` filter is ``null``, it will return the
current date by default. If an empty string is desired instead of the current
date, use a ternary operator:
.. code-block:: twig
{{ post.published_at is empty ? "" : post.published_at|date("m/d/Y") }}
If no format is provided, Twig will use the default one: ``F j, Y H:i``. This
default can be changed by calling the ``setDateFormat()`` method on the
``core`` extension instance. The first argument is the default format for
dates and the second one is the default format for date intervals::
$twig = new \Twig\Environment($loader);
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setDateFormat('d/m/Y', '%d days');
Timezone
--------
By default, the date is displayed by applying the default timezone (the one
specified in php.ini or declared in Twig -- see below), but you can override
it by explicitly specifying a timezone:
.. code-block:: twig
{{ post.published_at|date("m/d/Y", "Europe/Paris") }}
If the date is already a DateTime object, and if you want to keep its current
timezone, pass ``false`` as the timezone value:
.. code-block:: twig
{{ post.published_at|date("m/d/Y", false) }}
The default timezone can also be set globally by calling ``setTimezone()``::
$twig = new \Twig\Environment($loader);
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setTimezone('Europe/Paris');
Arguments
---------
* ``format``: The date format
* ``timezone``: The date timezone
.. _`strtotime`: https://www.php.net/strtotime
.. _`DateTime`: https://www.php.net/DateTime
.. _`DateInterval`: https://www.php.net/DateInterval
.. _`date`: https://www.php.net/date
.. _`DateInterval::format`: https://www.php.net/DateInterval.format

View File

@@ -0,0 +1,20 @@
``date_modify``
===============
The ``date_modify`` filter modifies a date with a given modifier string:
.. code-block:: twig
{{ post.published_at|date_modify("+1 day")|date("m/d/Y") }}
The ``date_modify`` filter accepts strings (it must be in a format supported
by the `strtotime`_ function) or `DateTime`_ instances. You can combine
it with the :doc:`date<date>` filter for formatting.
Arguments
---------
* ``modifier``: The modifier
.. _`strtotime`: https://www.php.net/strtotime
.. _`DateTime`: https://www.php.net/DateTime

View File

@@ -0,0 +1,42 @@
``default``
===========
The ``default`` filter returns the passed default value if the value is
undefined or empty, otherwise the value of the variable:
.. code-block:: twig
{{ var|default('var is not defined') }}
{{ var.foo|default('foo item on var is not defined') }}
{{ var['foo']|default('foo item on var is not defined') }}
{{ ''|default('passed var is empty') }}
When using the ``default`` filter on an expression that uses variables in some
method calls, be sure to use the ``default`` filter whenever a variable can be
undefined:
.. code-block:: twig
{{ var.method(foo|default('foo'))|default('foo') }}
Using the ``default`` filter on a boolean variable might trigger unexpected behavior, as
``false`` is treated as an empty value. Consider using ``??`` instead:
.. code-block:: twig
{% set foo = false %}
{{ foo|default(true) }} {# true #}
{{ foo ?? true }} {# false #}
.. note::
Read the documentation for the :doc:`defined<../tests/defined>` and
:doc:`empty<../tests/empty>` tests to learn more about their semantics.
Arguments
---------
* ``default``: The default value

117
vendor/twig/twig/doc/filters/escape.rst vendored Normal file
View File

@@ -0,0 +1,117 @@
``escape``
==========
The ``escape`` filter escapes a string using strategies that depend on the
context.
By default, it uses the HTML escaping strategy:
.. code-block:: html+twig
<p>
{{ user.username|escape }}
</p>
For convenience, the ``e`` filter is defined as an alias:
.. code-block:: html+twig
<p>
{{ user.username|e }}
</p>
The ``escape`` filter can also be used in other contexts than HTML thanks to
an optional argument which defines the escaping strategy to use:
.. code-block:: twig
{{ user.username|e }}
{# is equivalent to #}
{{ user.username|e('html') }}
And here is how to escape variables included in JavaScript code:
.. code-block:: twig
{{ user.username|escape('js') }}
{{ user.username|e('js') }}
The ``escape`` filter supports the following escaping strategies for HTML
documents:
* ``html``: escapes a string for the **HTML body** context.
* ``js``: escapes a string for the **JavaScript** context.
* ``css``: escapes a string for the **CSS** context. CSS escaping can be
applied to any string being inserted into CSS and escapes everything except
alphanumerics.
* ``url``: escapes a string for the **URI or parameter** contexts. This should
not be used to escape an entire URI; only a subcomponent being inserted.
* ``html_attr``: escapes a string for the **HTML attribute** context.
Note that doing contextual escaping in HTML documents is hard and choosing the
right escaping strategy depends on a lot of factors. Please, read related
documentation like `the OWASP prevention cheat sheet
<https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md>`_
to learn more about this topic.
.. note::
Internally, ``escape`` uses the PHP native `htmlspecialchars`_ function
for the HTML escaping strategy.
.. caution::
When using automatic escaping, Twig tries to not double-escape a variable
when the automatic escaping strategy is the same as the one applied by the
escape filter; but that does not work when using a variable as the
escaping strategy:
.. code-block:: twig
{% set strategy = 'html' %}
{% autoescape 'html' %}
{{ var|escape('html') }} {# won't be double-escaped #}
{{ var|escape(strategy) }} {# will be double-escaped #}
{% endautoescape %}
When using a variable as the escaping strategy, you should disable
automatic escaping:
.. code-block:: twig
{% set strategy = 'html' %}
{% autoescape 'html' %}
{{ var|escape(strategy)|raw }} {# won't be double-escaped #}
{% endautoescape %}
Custom Escapers
---------------
You can define custom escapers by calling the ``setEscaper()`` method on the
escaper extension instance. The first argument is the escaper name (to be
used in the ``escape`` call) and the second one must be a valid PHP callable::
$twig = new \Twig\Environment($loader);
$twig->getExtension(\Twig\Extension\EscaperExtension::class)->setEscaper('csv', 'csv_escaper');
When called by Twig, the callable receives the Twig environment instance, the
string to escape, and the charset.
.. note::
Built-in escapers cannot be overridden mainly because they should be
considered as the final implementation and also for better performance.
Arguments
---------
* ``strategy``: The escaping strategy
* ``charset``: The string charset
.. _`htmlspecialchars`: https://www.php.net/htmlspecialchars

55
vendor/twig/twig/doc/filters/filter.rst vendored Normal file
View File

@@ -0,0 +1,55 @@
``filter``
==========
The ``filter`` filter filters elements of a sequence or a mapping using an arrow
function. The arrow function receives the value of the sequence or mapping:
.. code-block:: twig
{% set sizes = [34, 36, 38, 40, 42] %}
{{ sizes|filter(v => v > 38)|join(', ') }}
{# output 40, 42 #}
Combined with the ``for`` tag, it allows to filter the items to iterate over:
.. code-block:: twig
{% for v in sizes|filter(v => v > 38) -%}
{{ v }}
{% endfor %}
{# output 40 42 #}
It also works with mappings:
.. code-block:: twig
{% set sizes = {
xs: 34,
s: 36,
m: 38,
l: 40,
xl: 42,
} %}
{% for k, v in sizes|filter(v => v > 38) -%}
{{ k }} = {{ v }}
{% endfor %}
{# output l = 40 xl = 42 #}
The arrow function also receives the key as a second argument:
.. code-block:: twig
{% for k, v in sizes|filter((v, k) => v > 38 and k != "xl") -%}
{{ k }} = {{ v }}
{% endfor %}
{# output l = 40 #}
Note that the arrow function has access to the current context.
Arguments
---------
* ``array``: The sequence or mapping
* ``arrow``: The arrow function

22
vendor/twig/twig/doc/filters/first.rst vendored Normal file
View File

@@ -0,0 +1,22 @@
``first``
=========
The ``first`` filter returns the first "element" of a sequence, a mapping, or
a string:
.. code-block:: twig
{{ [1, 2, 3, 4]|first }}
{# outputs 1 #}
{{ { a: 1, b: 2, c: 3, d: 4 }|first }}
{# outputs 1 #}
{{ '1234'|first }}
{# outputs 1 #}
.. note::
It also works with objects implementing the `Traversable`_ interface.
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php

18
vendor/twig/twig/doc/filters/format.rst vendored Normal file
View File

@@ -0,0 +1,18 @@
``format``
==========
The ``format`` filter formats a given string by replacing the placeholders
(placeholders follows the `sprintf`_ notation):
.. code-block:: twig
{{ "I like %s and %s."|format(foo, "bar") }}
{# outputs I like foo and bar
if the foo parameter equals to the foo string. #}
.. seealso::
:doc:`replace<replace>`
.. _`sprintf`: https://www.php.net/sprintf

View File

@@ -0,0 +1,77 @@
``format_currency``
===================
The ``format_currency`` filter formats a number as a currency:
.. code-block:: twig
{# €1,000,000.00 #}
{{ '1000000'|format_currency('EUR') }}
You can pass attributes to tweak the output:
.. code-block:: twig
{# €12.34 #}
{{ '12.345'|format_currency('EUR', {rounding_mode: 'floor'}) }}
{# €1,000,000.0000 #}
{{ '1000000'|format_currency('EUR', {fraction_digit: 4}) }}
The list of supported options:
* ``grouping_used``;
* ``decimal_always_shown``;
* ``max_integer_digit``;
* ``min_integer_digit``;
* ``integer_digit``;
* ``max_fraction_digit``;
* ``min_fraction_digit``;
* ``fraction_digit``;
* ``multiplier``;
* ``grouping_size``;
* ``rounding_mode``;
* ``rounding_increment``;
* ``format_width``;
* ``padding_position``;
* ``secondary_grouping_size``;
* ``significant_digits_used``;
* ``min_significant_digits_used``;
* ``max_significant_digits_used``;
* ``lenient_parse``.
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# 1.000.000,00 € #}
{{ '1000000'|format_currency('EUR', locale='de') }}
.. note::
The ``format_currency`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``currency``: The currency
* ``attrs``: A map of attributes
* ``locale``: The locale

View File

@@ -0,0 +1,36 @@
``format_date``
===============
The ``format_date`` filter formats a date. It behaves in the exact same way as
the :doc:`format_datetime<format_datetime>` filter, but without the time.
.. note::
The ``format_date`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale
* ``dateFormat``: The date format
* ``pattern``: A date time pattern
* ``timezone``: The date timezone
* ``calendar``: The calendar (Gregorian by default)

View File

@@ -0,0 +1,73 @@
``format_datetime``
===================
The ``format_datetime`` filter formats a date time:
.. code-block:: twig
{# Aug 7, 2019, 11:39:12 PM #}
{{ '2019-08-07 23:39:12'|format_datetime() }}
You can tweak the output for the date part and the time part:
.. code-block:: twig
{# 23:39 #}
{{ '2019-08-07 23:39:12'|format_datetime('none', 'short', locale='fr') }}
{# 07/08/2019 #}
{{ '2019-08-07 23:39:12'|format_datetime('short', 'none', locale='fr') }}
{# mercredi 7 août 2019 23:39:12 UTC #}
{{ '2019-08-07 23:39:12'|format_datetime('full', 'full', locale='fr') }}
Supported values are: ``none``, ``short``, ``medium``, ``long``, and ``full``.
For greater flexiblity, you can even define your own pattern (see the `ICU user
guide
<https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax>`_
for supported patterns).
.. code-block:: twig
{# 11 oclock PM, GMT #}
{{ '2019-08-07 23:39:12'|format_datetime(pattern="hh 'oclock' a, zzzz") }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# 7 août 2019 23:39:12 #}
{{ '2019-08-07 23:39:12'|format_datetime(locale='fr') }}
.. note::
The ``format_datetime`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale
* ``dateFormat``: The date format
* ``timeFormat``: The time format
* ``pattern``: A date time pattern
* ``timezone``: The date timezone
* ``calendar``: The calendar (Gregorian by default)

View File

@@ -0,0 +1,117 @@
``format_number``
=================
The ``format_number`` filter formats a number:
.. code-block:: twig
{{ '12.345'|format_number }}
You can pass attributes to tweak the output:
.. code-block:: twig
{# 12.34 #}
{{ '12.345'|format_number({rounding_mode: 'floor'}) }}
{# 1000000.0000 #}
{{ '1000000'|format_number({fraction_digit: 4}) }}
The list of supported options:
* ``grouping_used``;
* ``decimal_always_shown``;
* ``max_integer_digit``;
* ``min_integer_digit``;
* ``integer_digit``;
* ``max_fraction_digit``;
* ``min_fraction_digit``;
* ``fraction_digit``;
* ``multiplier``;
* ``grouping_size``;
* ``rounding_mode``;
* ``rounding_increment``;
* ``format_width``;
* ``padding_position``;
* ``secondary_grouping_size``;
* ``significant_digits_used``;
* ``min_significant_digits_used``;
* ``max_significant_digits_used``;
* ``lenient_parse``.
Besides plain numbers, the filter can also format numbers in various styles:
.. code-block:: twig
{# 1,234% #}
{{ '12.345'|format_number(style='percent') }}
{# twelve point three four five #}
{{ '12.345'|format_number(style='spellout') }}
{# 12 sec. #}
{{ '12'|format_duration_number }}
The list of supported styles:
* ``decimal``;
* ``currency``;
* ``percent``;
* ``scientific``;
* ``spellout``;
* ``ordinal``;
* ``duration``.
As a shortcut, you can use the ``format_*_number`` filters by replacing `*` with
a style:
.. code-block:: twig
{# 1,234% #}
{{ '12.345'|format_percent_number }}
{# twelve point three four five #}
{{ '12.345'|format_spellout_number }}
You can pass attributes to tweak the output:
.. code-block:: twig
{# 12.3% #}
{{ '0.12345'|format_percent_number({rounding_mode: 'floor', fraction_digit: 1}) }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# 12,345 #}
{{ '12.345'|format_number(locale='fr') }}
.. note::
The ``format_number`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale
* ``attrs``: A map of attributes
* ``style``: The style of the number output

View File

@@ -0,0 +1,36 @@
``format_time``
===============
The ``format_time`` filter formats a time. It behaves in the exact same way as
the :doc:`format_datetime<format_datetime>` filter, but without the date.
.. note::
The ``format_time`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale
* ``timeFormat``: The time format
* ``pattern``: A date time pattern
* ``timezone``: The date timezone
* ``calendar``: The calendar (Gregorian by default)

View File

@@ -0,0 +1,77 @@
``html_to_markdown``
====================
The ``html_to_markdown`` filter converts a block of HTML to Markdown:
.. code-block:: html+twig
{% apply html_to_markdown %}
<html>
<h1>Hello!</h1>
</html>
{% endapply %}
You can also use the filter on an entire template which you ``include``:
.. code-block:: twig
{{ include('some_template.html.twig')|html_to_markdown }}
.. note::
The ``html_to_markdown`` filter is part of the ``MarkdownExtension`` which
is not installed by default. Install it first:
.. code-block:: bash
$ composer require twig/markdown-extra
On Symfony projects, you can automatically enable it by installing the
``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Or add the extension explicitly on the Twig environment::
use Twig\Extra\Markdown\MarkdownExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new MarkdownExtension());
If you are not using Symfony, you must also register the extension runtime::
use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
public function load($class) {
if (MarkdownRuntime::class === $class) {
return new MarkdownRuntime(new DefaultMarkdown());
}
}
});
``html_to_markdown`` is just a frontend; the actual conversion is done by one of
the following compatible libraries, from which you can choose:
* `league/html-to-markdown`_
* `michelf/php-markdown`_
* `erusev/parsedown`_
Depending on the library, you can also add some options by passing them as an argument
to the filter. Example for ``league/html-to-markdown``:
.. code-block:: html+twig
{% apply html_to_markdown({hard_break: false}) %}
<html>
<h1>Hello!</h1>
</html>
{% endapply %}
.. _league/html-to-markdown: https://github.com/thephpleague/html-to-markdown
.. _michelf/php-markdown: https://github.com/michelf/php-markdown
.. _erusev/parsedown: https://github.com/erusev/parsedown

60
vendor/twig/twig/doc/filters/index.rst vendored Normal file
View File

@@ -0,0 +1,60 @@
Filters
=======
.. toctree::
:maxdepth: 1
abs
batch
capitalize
column
convert_encoding
country_name
currency_name
currency_symbol
data_uri
date
date_modify
default
escape
filter
first
format
format_currency
format_date
format_datetime
format_number
format_time
html_to_markdown
inline_css
inky_to_html
join
json_encode
keys
language_name
last
length
locale_name
lower
map
markdown_to_html
merge
nl2br
number_format
raw
reduce
replace
reverse
round
slice
slug
sort
spaceless
split
striptags
timezone_name
title
trim
u
upper
url_encode

View File

@@ -0,0 +1,42 @@
``inky_to_html``
================
The ``inky_to_html`` filter processes an `inky email template
<https://github.com/zurb/inky>`_:
.. code-block:: html+twig
{% apply inky_to_html %}
<row>
<columns large="6"></columns>
<columns large="6"></columns>
</row>
{% endapply %}
You can also use the filter on an included file:
.. code-block:: twig
{{ include('some_template.inky.twig')|inky_to_html }}
.. note::
The ``inky_to_html`` filter is part of the ``InkyExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/inky-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Inky\InkyExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new InkyExtension());

View File

@@ -0,0 +1,66 @@
``inline_css``
==============
The ``inline_css`` filter inline CSS styles in HTML documents:
.. code-block:: html+twig
{% apply inline_css %}
<html>
<head>
<style>
p { color: red; }
</style>
</head>
<body>
<p>Hello CSS!</p>
</body>
</html>
{% endapply %}
You can also add some stylesheets by passing them as arguments to the filter:
.. code-block:: html+twig
{% apply inline_css(source("some_styles.css"), source("another.css")) %}
<html>
<body>
<p>Hello CSS!</p>
</body>
</html>
{% endapply %}
Styles loaded via the filter override the styles defined in the ``<style>`` tag
of the HTML document.
You can also use the filter on an included file:
.. code-block:: twig
{{ include('some_template.html.twig')|inline_css }}
{{ include('some_template.html.twig')|inline_css(source("some_styles.css")) }}
Note that the CSS inliner works on an entire HTML document, not a fragment.
.. note::
The ``inline_css`` filter is part of the ``CssInlinerExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/cssinliner-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\CssInliner\CssInlinerExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new CssInlinerExtension());

32
vendor/twig/twig/doc/filters/join.rst vendored Normal file
View File

@@ -0,0 +1,32 @@
``join``
========
The ``join`` filter returns a string which is the concatenation of the items
of a sequence:
.. code-block:: twig
{{ [1, 2, 3]|join }}
{# returns 123 #}
The separator between elements is an empty string per default, but you can
define it with the optional first parameter:
.. code-block:: twig
{{ [1, 2, 3]|join('|') }}
{# outputs 1|2|3 #}
A second parameter can also be provided that will be the separator used between
the last two items of the sequence:
.. code-block:: twig
{{ [1, 2, 3]|join(', ', ' and ') }}
{# outputs 1, 2 and 3 #}
Arguments
---------
* ``glue``: The separator
* ``and``: The separator for the last pair of input items

View File

@@ -0,0 +1,23 @@
``json_encode``
===============
The ``json_encode`` filter returns the JSON representation of a value:
.. code-block:: twig
{{ data|json_encode() }}
.. note::
Internally, Twig uses the PHP `json_encode`_ function.
Arguments
---------
* ``options``: A bitmask of `json_encode options`_: ``{{
data|json_encode(constant('JSON_PRETTY_PRINT')) }}``.
Combine constants using :ref:`bitwise operators<template_logic>`:
``{{ data|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_HEX_QUOT')) }}``
.. _`json_encode`: https://www.php.net/json_encode
.. _`json_encode options`: https://www.php.net/manual/en/json.constants.php

11
vendor/twig/twig/doc/filters/keys.rst vendored Normal file
View File

@@ -0,0 +1,11 @@
``keys``
========
The ``keys`` filter returns the keys of an array. It is useful when you want to
iterate over the keys of an array:
.. code-block:: twig
{% for key in array|keys %}
...
{% endfor %}

View File

@@ -0,0 +1,47 @@
``language_name``
=================
The ``language_name`` filter returns the language name given its two-letter
code:
.. code-block:: twig
{# German #}
{{ 'de'|language_name }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# allemand #}
{{ 'de'|language_name('fr') }}
{# français canadien #}
{{ 'fr_CA'|language_name('fr_FR') }}
.. note::
The ``language_name`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

22
vendor/twig/twig/doc/filters/last.rst vendored Normal file
View File

@@ -0,0 +1,22 @@
``last``
========
The ``last`` filter returns the last "element" of a sequence, a mapping, or
a string:
.. code-block:: twig
{{ [1, 2, 3, 4]|last }}
{# outputs 4 #}
{{ { a: 1, b: 2, c: 3, d: 4 }|last }}
{# outputs 4 #}
{{ '1234'|last }}
{# outputs 4 #}
.. note::
It also works with objects implementing the `Traversable`_ interface.
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php

19
vendor/twig/twig/doc/filters/length.rst vendored Normal file
View File

@@ -0,0 +1,19 @@
``length``
==========
The ``length`` filter returns the number of items of a sequence or mapping, or
the length of a string.
For objects that implement the ``Countable`` interface, ``length`` will use the
return value of the ``count()`` method.
For objects that implement the ``__toString()`` magic method (and not ``Countable``),
it will return the length of the string provided by that method.
For objects that implement the ``Traversable`` interface, ``length`` will use the return value of the ``iterator_count()`` method.
.. code-block:: twig
{% if users|length > 10 %}
...
{% endif %}

View File

@@ -0,0 +1,47 @@
``locale_name``
===============
The ``locale_name`` filter returns the locale name given its two-letter
code:
.. code-block:: twig
{# German #}
{{ 'de'|locale_name }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# allemand #}
{{ 'de'|locale_name('fr') }}
{# français (Canada) #}
{{ 'fr_CA'|locale_name('fr_FR') }}
.. note::
The ``locale_name`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

10
vendor/twig/twig/doc/filters/lower.rst vendored Normal file
View File

@@ -0,0 +1,10 @@
``lower``
=========
The ``lower`` filter converts a value to lowercase:
.. code-block:: twig
{{ 'WELCOME'|lower }}
{# outputs 'welcome' #}

34
vendor/twig/twig/doc/filters/map.rst vendored Normal file
View File

@@ -0,0 +1,34 @@
``map``
=======
The ``map`` filter applies an arrow function to the elements of a sequence or a
mapping. The arrow function receives the value of the sequence or mapping:
.. code-block:: twig
{% set people = [
{first: "Bob", last: "Smith"},
{first: "Alice", last: "Dupond"},
] %}
{{ people|map(p => "#{p.first} #{p.last}")|join(', ') }}
{# outputs Bob Smith, Alice Dupond #}
The arrow function also receives the key as a second argument:
.. code-block:: twig
{% set people = {
"Bob": "Smith",
"Alice": "Dupond",
} %}
{{ people|map((last, first) => "#{first} #{last}")|join(', ') }}
{# outputs Bob Smith, Alice Dupond #}
Note that the arrow function has access to the current context.
Arguments
---------
* ``arrow``: The arrow function

View File

@@ -0,0 +1,72 @@
``markdown_to_html``
====================
The ``markdown_to_html`` filter converts a block of Markdown to HTML:
.. code-block:: twig
{% apply markdown_to_html %}
Title
======
Hello!
{% endapply %}
Note that you can indent the Markdown content as leading whitespaces will be
removed consistently before conversion:
.. code-block:: twig
{% apply markdown_to_html %}
Title
======
Hello!
{% endapply %}
You can also use the filter on an included file or a variable:
.. code-block:: twig
{{ include('some_template.markdown.twig')|markdown_to_html }}
{{ changelog|markdown_to_html }}
.. note::
The ``markdown_to_html`` filter is part of the ``MarkdownExtension`` which
is not installed by default. Install it first:
.. code-block:: bash
$ composer require twig/markdown-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Markdown\MarkdownExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new MarkdownExtension());
If you are not using Symfony, you must also register the extension runtime::
use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
public function load($class) {
if (MarkdownRuntime::class === $class) {
return new MarkdownRuntime(new DefaultMarkdown());
}
}
});
Afterwards you need to install a markdown library of your choice. Some of them are
mentioned in the ``require-dev`` section of the ``twig/markdown-extra`` package.

48
vendor/twig/twig/doc/filters/merge.rst vendored Normal file
View File

@@ -0,0 +1,48 @@
``merge``
=========
The ``merge`` filter merges an array with another array:
.. code-block:: twig
{% set values = [1, 2] %}
{% set values = values|merge(['apple', 'orange']) %}
{# values now contains [1, 2, 'apple', 'orange'] #}
New values are added at the end of the existing ones.
The ``merge`` filter also works on hashes:
.. code-block:: twig
{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}
{% set items = items|merge({ 'peugeot': 'car', 'renault': 'car' }) %}
{# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car', 'renault': 'car' } #}
For hashes, the merging process occurs on the keys: if the key does not
already exist, it is added but if the key already exists, its value is
overridden.
.. tip::
If you want to ensure that some values are defined in an array (by given
default values), reverse the two elements in the call:
.. code-block:: twig
{% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
{% set items = { 'apple': 'unknown' }|merge(items) %}
{# items now contains { 'apple': 'fruit', 'orange': 'fruit' } #}
.. note::
Internally, Twig uses the PHP `array_merge`_ function. It supports
Traversable objects by transforming those to arrays.
.. _`array_merge`: https://www.php.net/array_merge

19
vendor/twig/twig/doc/filters/nl2br.rst vendored Normal file
View File

@@ -0,0 +1,19 @@
``nl2br``
=========
The ``nl2br`` filter inserts HTML line breaks before all newlines in a string:
.. code-block:: html+twig
{{ "I like Twig.\nYou will like it too."|nl2br }}
{# outputs
I like Twig.<br />
You will like it too.
#}
.. note::
The ``nl2br`` filter pre-escapes the input before applying the
transformation.

View File

@@ -0,0 +1,51 @@
``number_format``
=================
The ``number_format`` filter formats numbers. It is a wrapper around PHP's
`number_format`_ function:
.. code-block:: twig
{{ 200.35|number_format }}
You can control the number of decimal places, decimal point, and thousands
separator using the additional arguments:
.. code-block:: twig
{{ 9800.333|number_format(2, '.', ',') }}
To format negative numbers or math calculation, wrap the previous statement
with parentheses (needed because of Twig's :ref:`precedence of operators
<twig-expressions>`):
.. code-block:: twig
{{ -9800.333|number_format(2, '.', ',') }} {# outputs : -9 #}
{{ (-9800.333)|number_format(2, '.', ',') }} {# outputs : -9,800.33 #}
{{ 1 + 0.2|number_format(2) }} {# outputs : 1.2 #}
{{ (1 + 0.2)|number_format(2) }} {# outputs : 1.20 #}
If no formatting options are provided then Twig will use the default formatting
options of:
* 0 decimal places.
* ``.`` as the decimal point.
* ``,`` as the thousands separator.
These defaults can be changed through the core extension::
$twig = new \Twig\Environment($loader);
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setNumberFormat(3, '.', ',');
The defaults set for ``number_format`` can be over-ridden upon each call using the
additional parameters.
Arguments
---------
* ``decimal``: The number of decimal points to display
* ``decimal_point``: The character(s) to use for the decimal point
* ``thousand_sep``: The character(s) to use for the thousands separator
.. _`number_format`: https://www.php.net/number_format

12
vendor/twig/twig/doc/filters/raw.rst vendored Normal file
View File

@@ -0,0 +1,12 @@
``raw``
=======
The ``raw`` filter marks the value as being "safe", which means that in an
environment with automatic escaping enabled this variable will not be escaped
if ``raw`` is the last filter applied to it:
.. code-block:: twig
{% autoescape %}
{{ var|raw }} {# var won't be escaped #}
{% endautoescape %}

29
vendor/twig/twig/doc/filters/reduce.rst vendored Normal file
View File

@@ -0,0 +1,29 @@
``reduce``
==========
The ``reduce`` filter iteratively reduces a sequence or a mapping to a single
value using an arrow function, so as to reduce it to a single value. The arrow
function receives the return value of the previous iteration and the current
value of the sequence or mapping:
.. code-block:: twig
{% set numbers = [1, 2, 3] %}
{{ numbers|reduce((carry, v) => carry + v) }}
{# output 6 #}
The ``reduce`` filter takes an ``initial`` value as a second argument:
.. code-block:: twig
{{ numbers|reduce((carry, v) => carry + v, 10) }}
{# output 16 #}
Note that the arrow function has access to the current context.
Arguments
---------
* ``arrow``: The arrow function
* ``initial``: The initial value

View File

@@ -0,0 +1,27 @@
``replace``
===========
The ``replace`` filter formats a given string by replacing the placeholders
(placeholders are free-form):
.. code-block:: twig
{{ "I like %this% and %that%."|replace({'%this%': foo, '%that%': "bar"}) }}
{# outputs I like foo and bar
if the foo parameter equals to the foo string. #}
{# using % as a delimiter is purely conventional and optional #}
{{ "I like this and --that--."|replace({'this': foo, '--that--': "bar"}) }}
{# outputs I like foo and bar #}
Arguments
---------
* ``from``: The placeholder values
.. seealso::
:doc:`format<format>`

View File

@@ -0,0 +1,44 @@
``reverse``
===========
The ``reverse`` filter reverses a sequence, a mapping, or a string:
.. code-block:: twig
{% for user in users|reverse %}
...
{% endfor %}
{{ '1234'|reverse }}
{# outputs 4321 #}
.. tip::
For sequences and mappings, numeric keys are not preserved. To reverse
them as well, pass ``true`` as an argument to the ``reverse`` filter:
.. code-block:: twig
{% for key, value in {1: "a", 2: "b", 3: "c"}|reverse %}
{{ key }}: {{ value }}
{%- endfor %}
{# output: 0: c 1: b 2: a #}
{% for key, value in {1: "a", 2: "b", 3: "c"}|reverse(true) %}
{{ key }}: {{ value }}
{%- endfor %}
{# output: 3: c 2: b 1: a #}
.. note::
It also works with objects implementing the `Traversable`_ interface.
Arguments
---------
* ``preserve_keys``: Preserve keys when reversing a mapping or a sequence.
.. _`Traversable`: https://www.php.net/Traversable

34
vendor/twig/twig/doc/filters/round.rst vendored Normal file
View File

@@ -0,0 +1,34 @@
``round``
=========
The ``round`` filter rounds a number to a given precision:
.. code-block:: twig
{{ 42.55|round }}
{# outputs 43 #}
{{ 42.55|round(1, 'floor') }}
{# outputs 42.5 #}
The ``round`` filter takes two optional arguments; the first one specifies the
precision (default is ``0``) and the second the rounding method (default is
``common``):
* ``common`` rounds either up or down (rounds the value up to precision decimal
places away from zero, when it is half way there -- making 1.5 into 2 and
-1.5 into -2);
* ``ceil`` always rounds up;
* ``floor`` always rounds down.
.. note::
The ``//`` operator is equivalent to ``|round(0, 'floor')``.
Arguments
---------
* ``precision``: The rounding precision
* ``method``: The rounding method

68
vendor/twig/twig/doc/filters/slice.rst vendored Normal file
View File

@@ -0,0 +1,68 @@
``slice``
===========
The ``slice`` filter extracts a slice of a sequence, a mapping, or a string:
.. code-block:: twig
{% for i in [1, 2, 3, 4, 5]|slice(1, 2) %}
{# will iterate over 2 and 3 #}
{% endfor %}
{{ '12345'|slice(1, 2) }}
{# outputs 23 #}
You can use any valid expression for both the start and the length:
.. code-block:: twig
{% for i in [1, 2, 3, 4, 5]|slice(start, length) %}
{# ... #}
{% endfor %}
As syntactic sugar, you can also use the ``[]`` notation:
.. code-block:: twig
{% for i in [1, 2, 3, 4, 5][start:length] %}
{# ... #}
{% endfor %}
{{ '12345'[1:2] }} {# will display "23" #}
{# you can omit the first argument -- which is the same as 0 #}
{{ '12345'[:2] }} {# will display "12" #}
{# you can omit the last argument -- which will select everything till the end #}
{{ '12345'[2:] }} {# will display "345" #}
The ``slice`` filter works as the `array_slice`_ PHP function for arrays and
`mb_substr`_ for strings with a fallback to `substr`_.
If the start is non-negative, the sequence will start at that start in the
variable. If start is negative, the sequence will start that far from the end
of the variable.
If length is given and is positive, then the sequence will have up to that
many elements in it. If the variable is shorter than the length, then only the
available variable elements will be present. If length is given and is
negative then the sequence will stop that many elements from the end of the
variable. If it is omitted, then the sequence will have everything from offset
up until the end of the variable.
.. note::
It also works with objects implementing the `Traversable`_ interface.
Arguments
---------
* ``start``: The start of the slice
* ``length``: The size of the slice
* ``preserve_keys``: Whether to preserve key or not (when the input is an array)
.. _`Traversable`: https://www.php.net/manual/en/class.traversable.php
.. _`array_slice`: https://www.php.net/array_slice
.. _`mb_substr`: https://www.php.net/mb-substr
.. _`substr`: https://www.php.net/substr

59
vendor/twig/twig/doc/filters/slug.rst vendored Normal file
View File

@@ -0,0 +1,59 @@
``slug``
========
The ``slug`` filter transforms a given string into another string that
only includes safe ASCII characters.
Here is an example:
.. code-block:: twig
{{ 'Wôrķšƥáçè ~~sèťtïñğš~~'|slug }}
Workspace-settings
The default separator between words is a dash (``-``), but you can
define a selector of your choice by passing it as an argument:
.. code-block:: twig
{{ 'Wôrķšƥáçè ~~sèťtïñğš~~'|slug('/') }}
Workspace/settings
The slugger automatically detects the language of the original
string, but you can also specify it explicitly using the second
argument:
.. code-block:: twig
{{ '...'|slug('-', 'ko') }}
The ``slug`` filter uses the method by the same name in Symfony's
`AsciiSlugger <https://symfony.com/doc/current/components/string.html#slugger>`_.
.. note::
The ``slug`` filter is part of the ``StringExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/string-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\String\StringExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new StringExtension());
Arguments
---------
* ``separator``: The separator that is used to join words (defaults to ``-``)
* ``locale``: The locale of the original string (if none is specified, it will be automatically detected)

42
vendor/twig/twig/doc/filters/sort.rst vendored Normal file
View File

@@ -0,0 +1,42 @@
``sort``
========
The ``sort`` filter sorts an array:
.. code-block:: twig
{% for user in users|sort %}
...
{% endfor %}
.. note::
Internally, Twig uses the PHP `asort`_ function to maintain index
association. It supports Traversable objects by transforming
those to arrays.
You can pass an arrow function to sort the array:
.. code-block:: html+twig
{% set fruits = [
{ name: 'Apples', quantity: 5 },
{ name: 'Oranges', quantity: 2 },
{ name: 'Grapes', quantity: 4 },
] %}
{% for fruit in fruits|sort((a, b) => a.quantity <=> b.quantity)|column('name') %}
{{ fruit }}
{% endfor %}
{# output in this order: Oranges, Grapes, Apples #}
Note the usage of the `spaceship`_ operator to simplify the comparison.
Arguments
---------
* ``arrow``: An arrow function
.. _`asort`: https://www.php.net/asort
.. _`spaceship`: https://www.php.net/manual/en/language.operators.comparison.php

View File

@@ -0,0 +1,56 @@
``spaceless``
=============
Use the ``spaceless`` filter to remove whitespace *between HTML tags*, not
whitespace within HTML tags or whitespace in plain text:
.. code-block:: html+twig
{{
"<div>
<strong>foo</strong>
</div>
"|spaceless }}
{# output will be <div><strong>foo</strong></div> #}
You can combine ``spaceless`` with the ``apply`` tag to apply the transformation
on large amounts of HTML:
.. code-block:: html+twig
{% apply spaceless %}
<div>
<strong>foo</strong>
</div>
{% endapply %}
{# output will be <div><strong>foo</strong></div> #}
This tag is not meant to "optimize" the size of the generated HTML content but
merely to avoid extra whitespace between HTML tags to avoid browser rendering
quirks under some circumstances.
.. caution::
As the filter uses a regular expression behind the scenes, its performance
is directly related to the text size you are working on (remember that
filters are executed at runtime).
.. tip::
If you want to optimize the size of the generated HTML content, gzip
compress the output instead.
.. tip::
If you want to create a tag that actually removes all extra whitespace in
an HTML string, be warned that this is not as easy as it seems to be
(think of ``textarea`` or ``pre`` tags for instance). Using a third-party
library like Tidy is probably a better idea.
.. tip::
For more information on whitespace control, read the
:ref:`dedicated section <templates-whitespace-control>` of the documentation and learn how
you can also use the whitespace control modifier on your tags.

50
vendor/twig/twig/doc/filters/split.rst vendored Normal file
View File

@@ -0,0 +1,50 @@
``split``
=========
The ``split`` filter splits a string by the given delimiter and returns a list
of strings:
.. code-block:: twig
{% set foo = "one,two,three"|split(',') %}
{# foo contains ['one', 'two', 'three'] #}
You can also pass a ``limit`` argument:
* If ``limit`` is positive, the returned array will contain a maximum of
limit elements with the last element containing the rest of string;
* If ``limit`` is negative, all components except the last -limit are
returned;
* If ``limit`` is zero, then this is treated as 1.
.. code-block:: twig
{% set foo = "one,two,three,four,five"|split(',', 3) %}
{# foo contains ['one', 'two', 'three,four,five'] #}
If the ``delimiter`` is an empty string, then value will be split by equal
chunks. Length is set by the ``limit`` argument (one character by default).
.. code-block:: twig
{% set foo = "123"|split('') %}
{# foo contains ['1', '2', '3'] #}
{% set bar = "aabbcc"|split('', 2) %}
{# bar contains ['aa', 'bb', 'cc'] #}
.. note::
Internally, Twig uses the PHP `explode`_ or `str_split`_ (if delimiter is
empty) functions for string splitting.
Arguments
---------
* ``delimiter``: The delimiter
* ``limit``: The limit argument
.. _`explode`: https://www.php.net/explode
.. _`str_split`: https://www.php.net/str_split

View File

@@ -0,0 +1,29 @@
``striptags``
=============
The ``striptags`` filter strips SGML/XML tags and replace adjacent whitespace
by one space:
.. code-block:: twig
{{ some_html|striptags }}
You can also provide tags which should not be stripped:
.. code-block:: html+twig
{{ some_html|striptags('<br><p>') }}
In this example, the ``<br/>``, ``<br>``, ``<p>``, and ``</p>`` tags won't be
removed from the string.
.. note::
Internally, Twig uses the PHP `strip_tags`_ function.
Arguments
---------
* ``allowable_tags``: Tags which should not be stripped
.. _`strip_tags`: https://www.php.net/strip_tags

View File

@@ -0,0 +1,46 @@
``timezone_name``
=================
The ``timezone_name`` filter returns the timezone name given a timezone identifier:
.. code-block:: twig
{# Central European Time (Paris) #}
{{ 'Europe/Paris'|timezone_name }}
{# Pacific Time (Los Angeles) #}
{{ 'America/Los_Angeles'|timezone_name }}
By default, the filter uses the current locale. You can pass it explicitly:
.. code-block:: twig
{# heure du Pacifique nord-américain (Los Angeles) #}
{{ 'America/Los_Angeles'|timezone_name('fr') }}
.. note::
The ``timezone_name`` filter is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());
Arguments
---------
* ``locale``: The locale

11
vendor/twig/twig/doc/filters/title.rst vendored Normal file
View File

@@ -0,0 +1,11 @@
``title``
=========
The ``title`` filter returns a titlecased version of the value. Words will
start with uppercase letters, all remaining characters are lowercase:
.. code-block:: twig
{{ 'my first car'|title }}
{# outputs 'My First Car' #}

39
vendor/twig/twig/doc/filters/trim.rst vendored Normal file
View File

@@ -0,0 +1,39 @@
``trim``
========
The ``trim`` filter strips whitespace (or other characters) from the beginning
and end of a string:
.. code-block:: twig
{{ ' I like Twig. '|trim }}
{# outputs 'I like Twig.' #}
{{ ' I like Twig.'|trim('.') }}
{# outputs ' I like Twig' #}
{{ ' I like Twig. '|trim(side='left') }}
{# outputs 'I like Twig. ' #}
{{ ' I like Twig. '|trim(' ', 'right') }}
{# outputs ' I like Twig.' #}
.. note::
Internally, Twig uses the PHP `trim`_, `ltrim`_, and `rtrim`_ functions.
Arguments
---------
* ``character_mask``: The characters to strip
* ``side``: The default is to strip from the left and the right (`both`) sides, but `left`
and `right` will strip from either the left side or right side only
.. _`trim`: https://www.php.net/trim
.. _`ltrim`: https://www.php.net/ltrim
.. _`rtrim`: https://www.php.net/rtrim

87
vendor/twig/twig/doc/filters/u.rst vendored Normal file
View File

@@ -0,0 +1,87 @@
``u``
=====
The ``u`` filter wraps a text in a Unicode object (a `Symfony UnicodeString
instance <https://symfony.com/doc/current/components/string.html>`_) that
exposes methods to "manipulate" the string.
Let's see some common use cases.
Wrapping a text to a given number of characters:
.. code-block:: twig
{{ 'Symfony String + Twig = <3'|u.wordwrap(5) }}
Symfony
String
+
Twig
= <3
Truncating a string:
.. code-block:: twig
{{ 'Lorem ipsum'|u.truncate(8) }}
Lorem ip
{{ 'Lorem ipsum'|u.truncate(8, '...') }}
Lorem...
The ``truncate`` method also accepts a third argument to preserve whole words:
.. code-block:: twig
{{ 'Lorem ipsum dolor'|u.truncate(10, '...', false) }}
Lorem ipsum...
Converting a string to *snake* case or *camelCase*:
.. code-block:: twig
{{ 'SymfonyStringWithTwig'|u.snake }}
symfony_string_with_twig
{{ 'symfony_string with twig'|u.camel.title }}
SymfonyStringWithTwig
You can also chain methods:
.. code-block:: twig
{{ 'Symfony String + Twig = <3'|u.wordwrap(5).upper }}
SYMFONY
STRING
+
TWIG
= <3
For large strings manipulation, use the ``apply`` tag:
.. code-block:: twig
{% apply u.wordwrap(5) %}
Some large amount of text...
{% endapply %}
.. note::
The ``u`` filter is part of the ``StringExtension`` which is not installed
by default. Install it first:
.. code-block:: bash
$ composer require twig/string-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\String\StringExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new StringExtension());

10
vendor/twig/twig/doc/filters/upper.rst vendored Normal file
View File

@@ -0,0 +1,10 @@
``upper``
=========
The ``upper`` filter converts a value to uppercase:
.. code-block:: twig
{{ 'welcome'|upper }}
{# outputs 'WELCOME' #}

View File

@@ -0,0 +1,23 @@
``url_encode``
==============
The ``url_encode`` filter percent encodes a given string as URL segment
or an array as query string:
.. code-block:: twig
{{ "path-seg*ment"|url_encode }}
{# outputs "path-seg%2Ament" #}
{{ "string with spaces"|url_encode }}
{# outputs "string%20with%20spaces" #}
{{ {'param': 'value', 'foo': 'bar'}|url_encode }}
{# outputs "param=value&foo=bar" #}
.. note::
Internally, Twig uses the PHP `rawurlencode`_ or the `http_build_query`_ function.
.. _`rawurlencode`: https://www.php.net/rawurlencode
.. _`http_build_query`: https://www.php.net/http_build_query

View File

@@ -0,0 +1,23 @@
``attribute``
=============
The ``attribute`` function can be used to access a "dynamic" attribute of a
variable:
.. code-block:: twig
{{ attribute(object, method) }}
{{ attribute(object, method, arguments) }}
{{ attribute(array, item) }}
In addition, the ``defined`` test can check for the existence of a dynamic
attribute:
.. code-block:: twig
{{ attribute(object, method) is defined ? 'Method exists' : 'Method does not exist' }}
.. note::
The resolution algorithm is the same as the one used for the ``.``
notation, except that the item can be any valid expression.

View File

@@ -0,0 +1,37 @@
``block``
=========
When a template uses inheritance and if you want to print a block multiple
times, use the ``block`` function:
.. code-block:: html+twig
<title>{% block title %}{% endblock %}</title>
<h1>{{ block('title') }}</h1>
{% block body %}{% endblock %}
The ``block`` function can also be used to display one block from another
template:
.. code-block:: twig
{{ block("title", "common_blocks.twig") }}
Use the ``defined`` test to check if a block exists in the context of the
current template:
.. code-block:: twig
{% if block("footer") is defined %}
...
{% endif %}
{% if block("footer", "common_blocks.twig") is defined %}
...
{% endif %}
.. seealso::
:doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`

View File

@@ -0,0 +1,23 @@
``constant``
============
``constant`` returns the constant value for a given string:
.. code-block:: twig
{{ some_date|date(constant('DATE_W3C')) }}
{{ constant('Namespace\\Classname::CONSTANT_NAME') }}
You can read constants from object instances as well:
.. code-block:: twig
{{ constant('RSS', date) }}
Use the ``defined`` test to check if a constant is defined:
.. code-block:: twig
{% if constant('SOME_CONST') is defined %}
...
{% endif %}

View File

@@ -0,0 +1,32 @@
``country_timezones``
=====================
The ``country_timezones`` function returns the names of the timezones associated
with a given country code:
.. code-block:: twig
{# Europe/Paris #}
{{ country_timezones('FR')|join(', ') }}
.. note::
The ``country_timezones`` function is part of the ``IntlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/intl-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Intl\IntlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new IntlExtension());

View File

@@ -0,0 +1,28 @@
``cycle``
=========
The ``cycle`` function cycles on an array of values:
.. code-block:: twig
{% set start_year = date() | date('Y') %}
{% set end_year = start_year + 5 %}
{% for year in start_year..end_year %}
{{ cycle(['odd', 'even'], loop.index0) }}
{% endfor %}
The array can contain any number of values:
.. code-block:: twig
{% set fruits = ['apple', 'orange', 'citrus'] %}
{% for i in 0..10 %}
{{ cycle(fruits, i) }}
{% endfor %}
Arguments
---------
* ``position``: The cycle position

44
vendor/twig/twig/doc/functions/date.rst vendored Normal file
View File

@@ -0,0 +1,44 @@
``date``
========
Converts an argument to a date to allow date comparison:
.. code-block:: html+twig
{% if date(user.created_at) < date('-2days') %}
{# do something #}
{% endif %}
The argument must be in one of PHPs supported `date and time formats`_.
You can pass a timezone as the second argument:
.. code-block:: html+twig
{% if date(user.created_at) < date('-2days', 'Europe/Paris') %}
{# do something #}
{% endif %}
If no argument is passed, the function returns the current date:
.. code-block:: html+twig
{% if date(user.created_at) < date() %}
{# always! #}
{% endif %}
.. note::
You can set the default timezone globally by calling ``setTimezone()`` on
the ``core`` extension instance::
$twig = new \Twig\Environment($loader);
$twig->getExtension(\Twig\Extension\CoreExtension::class)->setTimezone('Europe/Paris');
Arguments
---------
* ``date``: The date
* ``timezone``: The timezone
.. _`date and time formats`: https://www.php.net/manual/en/datetime.formats.php

66
vendor/twig/twig/doc/functions/dump.rst vendored Normal file
View File

@@ -0,0 +1,66 @@
``dump``
========
The ``dump`` function dumps information about a template variable. This is
mostly useful to debug a template that does not behave as expected by
introspecting its variables:
.. code-block:: twig
{{ dump(user) }}
.. note::
The ``dump`` function is not available by default. You must add the
``\Twig\Extension\DebugExtension`` extension explicitly when creating your Twig
environment::
$twig = new \Twig\Environment($loader, [
'debug' => true,
// ...
]);
$twig->addExtension(new \Twig\Extension\DebugExtension());
Even when enabled, the ``dump`` function won't display anything if the
``debug`` option on the environment is not enabled (to avoid leaking debug
information on a production server).
In an HTML context, wrap the output with a ``pre`` tag to make it easier to
read:
.. code-block:: html+twig
<pre>
{{ dump(user) }}
</pre>
.. tip::
Using a ``pre`` tag is not needed when `XDebug`_ is enabled and
``html_errors`` is ``on``; as a bonus, the output is also nicer with
XDebug enabled.
You can debug several variables by passing them as additional arguments:
.. code-block:: twig
{{ dump(user, categories) }}
If you don't pass any value, all variables from the current context are
dumped:
.. code-block:: twig
{{ dump() }}
.. note::
Internally, Twig uses the PHP `var_dump`_ function.
Arguments
---------
* ``context``: The context to dump
.. _`XDebug`: https://xdebug.org/docs/display
.. _`var_dump`: https://www.php.net/var_dump

View File

@@ -0,0 +1,35 @@
``html_classes``
================
The ``html_classes`` function returns a string by conditionally joining class
names together:
.. code-block:: html+twig
<p class="{{ html_classes('a-class', 'another-class', {
'errored': object.errored,
'finished': object.finished,
'pending': object.pending,
}) }}">How are you doing?</p>
.. note::
The ``html_classes`` function is part of the ``HtmlExtension`` which is not
installed by default. Install it first:
.. code-block:: bash
$ composer require twig/html-extra
Then, on Symfony projects, install the ``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Otherwise, add the extension explicitly on the Twig environment::
use Twig\Extra\Html\HtmlExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new HtmlExtension());

View File

@@ -0,0 +1,77 @@
``include``
===========
The ``include`` function returns the rendered content of a template:
.. code-block:: twig
{{ include('template.html') }}
{{ include(some_var) }}
Included templates have access to the variables of the active context.
If you are using the filesystem loader, the templates are looked for in the
paths defined by it.
The context is passed by default to the template but you can also pass
additional variables:
.. code-block:: twig
{# template.html will have access to the variables from the current context and the additional ones provided #}
{{ include('template.html', {foo: 'bar'}) }}
You can disable access to the context by setting ``with_context`` to
``false``:
.. code-block:: twig
{# only the foo variable will be accessible #}
{{ include('template.html', {foo: 'bar'}, with_context = false) }}
.. code-block:: twig
{# no variables will be accessible #}
{{ include('template.html', with_context = false) }}
And if the expression evaluates to a ``\Twig\Template`` or a
``\Twig\TemplateWrapper`` instance, Twig will use it directly::
// {{ include(template) }}
$template = $twig->load('some_template.twig');
$twig->display('template.twig', ['template' => $template]);
When you set the ``ignore_missing`` flag, Twig will return an empty string if
the template does not exist:
.. code-block:: twig
{{ include('sidebar.html', ignore_missing = true) }}
You can also provide a list of templates that are checked for existence before
inclusion. The first template that exists will be rendered:
.. code-block:: twig
{{ include(['page_detailed.html', 'page.html']) }}
If ``ignore_missing`` is set, it will fall back to rendering nothing if none
of the templates exist, otherwise it will throw an exception.
When including a template created by an end user, you should consider
sandboxing it:
.. code-block:: twig
{{ include('page.html', sandboxed = true) }}
Arguments
---------
* ``template``: The template to render
* ``variables``: The variables to pass to the template
* ``with_context``: Whether to pass the current context variables or not
* ``ignore_missing``: Whether to ignore missing templates or not
* ``sandboxed``: Whether to sandbox the template or not

View File

@@ -0,0 +1,22 @@
Functions
=========
.. toctree::
:maxdepth: 1
attribute
block
constant
cycle
date
dump
html_classes
include
max
min
parent
random
range
source
country_timezones
template_from_string

17
vendor/twig/twig/doc/functions/max.rst vendored Normal file
View File

@@ -0,0 +1,17 @@
``max``
=======
``max`` returns the biggest value of a sequence or a set of values:
.. code-block:: twig
{{ max(1, 3, 2) }}
{{ max([1, 3, 2]) }}
When called with a mapping, max ignores keys and only compares values:
.. code-block:: twig
{{ max({2: "e", 1: "a", 3: "b", 5: "d", 4: "c"}) }}
{# returns "e" #}

17
vendor/twig/twig/doc/functions/min.rst vendored Normal file
View File

@@ -0,0 +1,17 @@
``min``
=======
``min`` returns the lowest value of a sequence or a set of values:
.. code-block:: twig
{{ min(1, 3, 2) }}
{{ min([1, 3, 2]) }}
When called with a mapping, min ignores keys and only compares values:
.. code-block:: twig
{{ min({2: "e", 3: "a", 1: "b", 5: "d", 4: "c"}) }}
{# returns "a" #}

View File

@@ -0,0 +1,22 @@
``parent``
==========
When a template uses inheritance, it's possible to render the contents of the
parent block when overriding a block by using the ``parent`` function:
.. code-block:: html+twig
{% extends "base.html" %}
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
The ``parent()`` call will return the content of the ``sidebar`` block as
defined in the ``base.html`` template.
.. seealso::
:doc:`extends<../tags/extends>`, :doc:`block<../functions/block>`, :doc:`block<../tags/block>`

View File

@@ -0,0 +1,25 @@
``random``
==========
The ``random`` function returns a random value depending on the supplied
parameter type:
* a random item from a sequence;
* a random character from a string;
* a random integer between 0 and the integer parameter (inclusive).
* a random integer between the integer parameter (when negative) and 0 (inclusive).
* a random integer between the first integer and the second integer parameter (inclusive).
.. code-block:: twig
{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
{{ random('ABC') }} {# example output: C #}
{{ random() }} {# example output: 15386094 (works as the native PHP mt_rand function) #}
{{ random(5) }} {# example output: 3 #}
{{ random(50, 100) }} {# example output: 63 #}
Arguments
---------
* ``values``: The values
* ``max``: The max value when values is an integer

View File

@@ -0,0 +1,58 @@
``range``
=========
Returns a list containing an arithmetic progression of integers:
.. code-block:: twig
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
{# outputs 0, 1, 2, 3, #}
When step is given (as the third parameter), it specifies the increment (or
decrement for negative values):
.. code-block:: twig
{% for i in range(0, 6, 2) %}
{{ i }},
{% endfor %}
{# outputs 0, 2, 4, 6, #}
.. note::
Note that if the start is greater than the end, ``range`` assumes a step of
``-1``:
.. code-block:: twig
{% for i in range(3, 0) %}
{{ i }},
{% endfor %}
{# outputs 3, 2, 1, 0, #}
The Twig built-in ``..`` operator is just syntactic sugar for the ``range``
function (with a step of ``1``, or ``-1`` if the start is greater than the end):
.. code-block:: twig
{% for i in 0..3 %}
{{ i }},
{% endfor %}
.. tip::
The ``range`` function works as the native PHP `range`_ function.
Arguments
---------
* ``low``: The first value of the sequence.
* ``high``: The highest possible value of the sequence.
* ``step``: The increment between elements of the sequence.
.. _`range`: https://www.php.net/range

View File

@@ -0,0 +1,26 @@
``source``
==========
The ``source`` function returns the content of a template without rendering it:
.. code-block:: twig
{{ source('template.html') }}
{{ source(some_var) }}
When you set the ``ignore_missing`` flag, Twig will return an empty string if
the template does not exist:
.. code-block:: twig
{{ source('template.html', ignore_missing = true) }}
The function uses the same template loaders as the ones used to include
templates. So, if you are using the filesystem loader, the templates are looked
for in the paths defined by it.
Arguments
---------
* ``name``: The name of the template to read
* ``ignore_missing``: Whether to ignore missing templates or not

View File

@@ -0,0 +1,37 @@
``template_from_string``
========================
The ``template_from_string`` function loads a template from a string:
.. code-block:: twig
{{ include(template_from_string("Hello {{ name }}")) }}
{{ include(template_from_string(page.template)) }}
To ease debugging, you can also give the template a name that will be part of
any related error message:
.. code-block:: twig
{{ include(template_from_string(page.template, "template for page " ~ page.name)) }}
.. note::
The ``template_from_string`` function is not available by default. You
must add the ``\Twig\Extension\StringLoaderExtension`` extension explicitly when
creating your Twig environment::
$twig = new \Twig\Environment(...);
$twig->addExtension(new \Twig\Extension\StringLoaderExtension());
.. note::
Even if you will probably always use the ``template_from_string`` function
with the ``include`` function, you can use it with any tag or function that
takes a template as an argument (like the ``embed`` or ``extends`` tags).
Arguments
---------
* ``template``: The template
* ``name``: A name for the template

19
vendor/twig/twig/doc/index.rst vendored Normal file
View File

@@ -0,0 +1,19 @@
Twig
====
.. toctree::
:maxdepth: 2
intro
installation
templates
api
advanced
internals
deprecated
recipes
coding_standards
tags/index
filters/index
functions/index
tests/index

10
vendor/twig/twig/doc/installation.rst vendored Normal file
View File

@@ -0,0 +1,10 @@
Installation
============
Install `Composer`_ and run the following command to get the latest version:
.. code-block:: bash
composer require "twig/twig:^3.0"
.. _`Composer`: https://getcomposer.org/download/

140
vendor/twig/twig/doc/internals.rst vendored Normal file
View File

@@ -0,0 +1,140 @@
Twig Internals
==============
Twig is very extensible and you can hack it. Keep in mind that you
should probably try to create an extension before hacking the core, as most
features and enhancements can be handled with extensions. This chapter is also
useful for people who want to understand how Twig works under the hood.
How does Twig work?
-------------------
The rendering of a Twig template can be summarized into four key steps:
* **Load** the template: If the template is already compiled, load it and go
to the *evaluation* step, otherwise:
* First, the **lexer** tokenizes the template source code into small pieces
for easier processing;
* Then, the **parser** converts the token stream into a meaningful tree
of nodes (the Abstract Syntax Tree);
* Finally, the *compiler* transforms the AST into PHP code.
* **Evaluate** the template: It means calling the ``display()``
method of the compiled template and passing it the context.
The Lexer
---------
The lexer tokenizes a template source code into a token stream (each token is
an instance of ``\Twig\Token``, and the stream is an instance of
``\Twig\TokenStream``). The default lexer recognizes 13 different token types:
* ``\Twig\Token::BLOCK_START_TYPE``, ``\Twig\Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``)
* ``\Twig\Token::VAR_START_TYPE``, ``\Twig\Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``)
* ``\Twig\Token::TEXT_TYPE``: A text outside an expression;
* ``\Twig\Token::NAME_TYPE``: A name in an expression;
* ``\Twig\Token::NUMBER_TYPE``: A number in an expression;
* ``\Twig\Token::STRING_TYPE``: A string in an expression;
* ``\Twig\Token::OPERATOR_TYPE``: An operator;
* ``\Twig\Token::PUNCTUATION_TYPE``: A punctuation sign;
* ``\Twig\Token::INTERPOLATION_START_TYPE``, ``\Twig\Token::INTERPOLATION_END_TYPE``: Delimiters for string interpolation;
* ``\Twig\Token::EOF_TYPE``: Ends of template.
You can manually convert a source code into a token stream by calling the
``tokenize()`` method of an environment::
$stream = $twig->tokenize(new \Twig\Source($source, $identifier));
As the stream has a ``__toString()`` method, you can have a textual
representation of it by echoing the object::
echo $stream."\n";
Here is the output for the ``Hello {{ name }}`` template:
.. code-block:: text
TEXT_TYPE(Hello )
VAR_START_TYPE()
NAME_TYPE(name)
VAR_END_TYPE()
EOF_TYPE()
.. note::
The default lexer (``\Twig\Lexer``) can be changed by calling
the ``setLexer()`` method::
$twig->setLexer($lexer);
The Parser
----------
The parser converts the token stream into an AST (Abstract Syntax Tree), or a
node tree (an instance of ``\Twig\Node\ModuleNode``). The core extension defines
the basic nodes like: ``for``, ``if``, ... and the expression nodes.
You can manually convert a token stream into a node tree by calling the
``parse()`` method of an environment::
$nodes = $twig->parse($stream);
Echoing the node object gives you a nice representation of the tree::
echo $nodes."\n";
Here is the output for the ``Hello {{ name }}`` template:
.. code-block:: text
\Twig\Node\ModuleNode(
\Twig\Node\TextNode(Hello )
\Twig\Node\PrintNode(
\Twig\Node\Expression\NameExpression(name)
)
)
.. note::
The default parser (``\Twig\TokenParser\AbstractTokenParser``) can be changed by calling the
``setParser()`` method::
$twig->setParser($parser);
The Compiler
------------
The last step is done by the compiler. It takes a node tree as an input and
generates PHP code usable for runtime execution of the template.
You can manually compile a node tree to PHP code with the ``compile()`` method
of an environment::
$php = $twig->compile($nodes);
The generated template for a ``Hello {{ name }}`` template reads as follows
(the actual output can differ depending on the version of Twig you are
using)::
/* Hello {{ name }} */
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Template
{
protected function doDisplay(array $context, array $blocks = [])
{
// line 1
echo "Hello ";
echo twig_escape_filter($this->env, (isset($context["name"]) ? $context["name"] : null), "html", null, true);
}
// some more code
}
.. note::
The default compiler (``\Twig\Compiler``) can be changed by calling the
``setCompiler()`` method::
$twig->setCompiler($compiler);

74
vendor/twig/twig/doc/intro.rst vendored Normal file
View File

@@ -0,0 +1,74 @@
Introduction
============
Welcome to the documentation for Twig, the flexible, fast, and secure template
engine for PHP.
Twig is both designer and developer friendly by sticking to PHP's principles and
adding functionality useful for templating environments.
The key-features are...
* *Fast*: Twig compiles templates down to plain optimized PHP code. The
overhead compared to regular PHP code was reduced to the very minimum.
* *Secure*: Twig has a sandbox mode to evaluate untrusted template code. This
allows Twig to be used as a template language for applications where users
may modify the template design.
* *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
developer to define their own custom tags and filters, and to create their own DSL.
Twig is used by many Open-Source projects like Symfony, Drupal8, eZPublish,
phpBB, Matomo, OroCRM; and many frameworks have support for it as well like
Slim, Yii, Laravel, and Codeigniter — just to name a few.
.. admonition:: Screencast
Like to learn from video tutorials? Check out the `SymfonyCasts Twig Tutorial`_!
Prerequisites
-------------
Twig 3.x needs at least **PHP 7.2.5** to run.
Installation
------------
The recommended way to install Twig is via Composer:
.. code-block:: bash
composer require "twig/twig:^3.0"
Basic API Usage
---------------
This section gives you a brief introduction to the PHP API for Twig::
require_once '/path/to/vendor/autoload.php';
$loader = new \Twig\Loader\ArrayLoader([
'index' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);
echo $twig->render('index', ['name' => 'Fabien']);
Twig uses a loader (``\Twig\Loader\ArrayLoader``) to locate templates, and an
environment (``\Twig\Environment``) to store its configuration.
The ``render()`` method loads the template passed as a first argument and
renders it with the variables passed as a second argument.
As templates are generally stored on the filesystem, Twig also comes with a
filesystem loader::
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
$twig = new \Twig\Environment($loader, [
'cache' => '/path/to/compilation_cache',
]);
echo $twig->render('index.html', ['name' => 'Fabien']);
.. _`SymfonyCasts Twig Tutorial`: https://symfonycasts.com/screencast/twig

531
vendor/twig/twig/doc/recipes.rst vendored Normal file
View File

@@ -0,0 +1,531 @@
Recipes
=======
.. _deprecation-notices:
Displaying Deprecation Notices
------------------------------
Deprecated features generate deprecation notices (via a call to the
``trigger_error()`` PHP function). By default, they are silenced and never
displayed nor logged.
To remove all deprecated feature usages from your templates, write and run a
script along the lines of the following::
require_once __DIR__.'/vendor/autoload.php';
$twig = create_your_twig_env();
$deprecations = new \Twig\Util\DeprecationCollector($twig);
print_r($deprecations->collectDir(__DIR__.'/templates'));
The ``collectDir()`` method compiles all templates found in a directory,
catches deprecation notices, and return them.
.. tip::
If your templates are not stored on the filesystem, use the ``collect()``
method instead. ``collect()`` takes a ``Traversable`` which must return
template names as keys and template contents as values (as done by
``\Twig\Util\TemplateDirIterator``).
However, this code won't find all deprecations (like using deprecated some Twig
classes). To catch all notices, register a custom error handler like the one
below::
$deprecations = [];
set_error_handler(function ($type, $msg) use (&$deprecations) {
if (E_USER_DEPRECATED === $type) {
$deprecations[] = $msg;
}
});
// run your application
print_r($deprecations);
Note that most deprecation notices are triggered during **compilation**, so
they won't be generated when templates are already cached.
.. tip::
If you want to manage the deprecation notices from your PHPUnit tests, have
a look at the `symfony/phpunit-bridge
<https://github.com/symfony/phpunit-bridge>`_ package, which eases the
process.
Making a Layout conditional
---------------------------
Working with Ajax means that the same content is sometimes displayed as is,
and sometimes decorated with a layout. As Twig layout template names can be
any valid expression, you can pass a variable that evaluates to ``true`` when
the request is made via Ajax and choose the layout accordingly:
.. code-block:: twig
{% extends request.ajax ? "base_ajax.html" : "base.html" %}
{% block content %}
This is the content to be displayed.
{% endblock %}
Making an Include dynamic
-------------------------
When including a template, its name does not need to be a string. For
instance, the name can depend on the value of a variable:
.. code-block:: twig
{% include var ~ '_foo.html' %}
If ``var`` evaluates to ``index``, the ``index_foo.html`` template will be
rendered.
As a matter of fact, the template name can be any valid expression, such as
the following:
.. code-block:: twig
{% include var|default('index') ~ '_foo.html' %}
Overriding a Template that also extends itself
----------------------------------------------
A template can be customized in two different ways:
* *Inheritance*: A template *extends* a parent template and overrides some
blocks;
* *Replacement*: If you use the filesystem loader, Twig loads the first
template it finds in a list of configured directories; a template found in a
directory *replaces* another one from a directory further in the list.
But how do you combine both: *replace* a template that also extends itself
(aka a template in a directory further in the list)?
Let's say that your templates are loaded from both ``.../templates/mysite``
and ``.../templates/default`` in this order. The ``page.twig`` template,
stored in ``.../templates/default`` reads as follows:
.. code-block:: twig
{# page.twig #}
{% extends "layout.twig" %}
{% block content %}
{% endblock %}
You can replace this template by putting a file with the same name in
``.../templates/mysite``. And if you want to extend the original template, you
might be tempted to write the following:
.. code-block:: twig
{# page.twig in .../templates/mysite #}
{% extends "page.twig" %} {# from .../templates/default #}
However, this will not work as Twig will always load the template from
``.../templates/mysite``.
It turns out it is possible to get this to work, by adding a directory right
at the end of your template directories, which is the parent of all of the
other directories: ``.../templates`` in our case. This has the effect of
making every template file within our system uniquely addressable. Most of the
time you will use the "normal" paths, but in the special case of wanting to
extend a template with an overriding version of itself we can reference its
parent's full, unambiguous template path in the extends tag:
.. code-block:: twig
{# page.twig in .../templates/mysite #}
{% extends "default/page.twig" %} {# from .../templates #}
.. note::
This recipe was inspired by the following Django wiki page:
https://code.djangoproject.com/wiki/ExtendingTemplates
Customizing the Syntax
----------------------
Twig allows some syntax customization for the block delimiters. It's **not**
recommended to use this feature as templates will be tied with your custom
syntax. But for specific projects, it can make sense to change the defaults.
To change the block delimiters, you need to create your own lexer object::
$twig = new \Twig\Environment(...);
$lexer = new \Twig\Lexer($twig, [
'tag_comment' => ['{#', '#}'],
'tag_block' => ['{%', '%}'],
'tag_variable' => ['{{', '}}'],
'interpolation' => ['#{', '}'],
]);
$twig->setLexer($lexer);
Here are some configuration example that simulates some other template engines
syntax::
// Ruby erb syntax
$lexer = new \Twig\Lexer($twig, [
'tag_comment' => ['<%#', '%>'],
'tag_block' => ['<%', '%>'],
'tag_variable' => ['<%=', '%>'],
]);
// SGML Comment Syntax
$lexer = new \Twig\Lexer($twig, [
'tag_comment' => ['<!--#', '-->'],
'tag_block' => ['<!--', '-->'],
'tag_variable' => ['${', '}'],
]);
// Smarty like
$lexer = new \Twig\Lexer($twig, [
'tag_comment' => ['{*', '*}'],
'tag_block' => ['{', '}'],
'tag_variable' => ['{$', '}'],
]);
Using dynamic Object Properties
-------------------------------
When Twig encounters a variable like ``article.title``, it tries to find a
``title`` public property in the ``article`` object.
It also works if the property does not exist but is rather defined dynamically
thanks to the magic ``__get()`` method; you need to also implement the
``__isset()`` magic method like shown in the following snippet of code::
class Article
{
public function __get($name)
{
if ('title' == $name) {
return 'The title';
}
// throw some kind of error
}
public function __isset($name)
{
if ('title' == $name) {
return true;
}
return false;
}
}
Accessing the parent Context in Nested Loops
--------------------------------------------
Sometimes, when using nested loops, you need to access the parent context. The
parent context is always accessible via the ``loop.parent`` variable. For
instance, if you have the following template data::
$data = [
'topics' => [
'topic1' => ['Message 1 of topic 1', 'Message 2 of topic 1'],
'topic2' => ['Message 1 of topic 2', 'Message 2 of topic 2'],
],
];
And the following template to display all messages in all topics:
.. code-block:: twig
{% for topic, messages in topics %}
* {{ loop.index }}: {{ topic }}
{% for message in messages %}
- {{ loop.parent.loop.index }}.{{ loop.index }}: {{ message }}
{% endfor %}
{% endfor %}
The output will be similar to:
.. code-block:: text
* 1: topic1
- 1.1: The message 1 of topic 1
- 1.2: The message 2 of topic 1
* 2: topic2
- 2.1: The message 1 of topic 2
- 2.2: The message 2 of topic 2
In the inner loop, the ``loop.parent`` variable is used to access the outer
context. So, the index of the current ``topic`` defined in the outer for loop
is accessible via the ``loop.parent.loop.index`` variable.
Defining undefined Functions, Filters, and Tags on the Fly
----------------------------------------------------------
.. versionadded:: 3.2
The ``registerUndefinedTokenParserCallback()`` method was added in Twig
3.2.
When a function/filter/tag is not defined, Twig defaults to throw a
``\Twig\Error\SyntaxError`` exception. However, it can also call a `callback`_
(any valid PHP callable) which should return a function/filter/tag.
For tags, register callbacks with ``registerUndefinedTokenParserCallback()``.
For filters, register callbacks with ``registerUndefinedFilterCallback()``.
For functions, use ``registerUndefinedFunctionCallback()``::
// auto-register all native PHP functions as Twig functions
// NEVER do this in a project as it's NOT secure
$twig->registerUndefinedFunctionCallback(function ($name) {
if (function_exists($name)) {
return new \Twig\TwigFunction($name, $name);
}
return false;
});
If the callable is not able to return a valid function/filter/tag, it must
return ``false``.
If you register more than one callback, Twig will call them in turn until one
does not return ``false``.
.. tip::
As the resolution of functions/filters/tags is done during compilation,
there is no overhead when registering these callbacks.
Validating the Template Syntax
------------------------------
When template code is provided by a third-party (through a web interface for
instance), it might be interesting to validate the template syntax before
saving it. If the template code is stored in a ``$template`` variable, here is
how you can do it::
try {
$twig->parse($twig->tokenize(new \Twig\Source($template)));
// the $template is valid
} catch (\Twig\Error\SyntaxError $e) {
// $template contains one or more syntax errors
}
If you iterate over a set of files, you can pass the filename to the
``tokenize()`` method to get the filename in the exception message::
foreach ($files as $file) {
try {
$twig->parse($twig->tokenize(new \Twig\Source($template, $file->getFilename(), $file)));
// the $template is valid
} catch (\Twig\Error\SyntaxError $e) {
// $template contains one or more syntax errors
}
}
.. note::
This method won't catch any sandbox policy violations because the policy
is enforced during template rendering (as Twig needs the context for some
checks like allowed methods on objects).
Refreshing modified Templates when OPcache or APC is enabled
------------------------------------------------------------
When using OPcache with ``opcache.validate_timestamps`` set to ``0`` or APC
with ``apc.stat`` set to ``0`` and Twig cache enabled, clearing the template
cache won't update the cache.
To get around this, force Twig to invalidate the bytecode cache::
$twig = new \Twig\Environment($loader, [
'cache' => new \Twig\Cache\FilesystemCache('/some/cache/path', \Twig\Cache\FilesystemCache::FORCE_BYTECODE_INVALIDATION),
// ...
]);
Reusing a stateful Node Visitor
-------------------------------
When attaching a visitor to a ``\Twig\Environment`` instance, Twig uses it to
visit *all* templates it compiles. If you need to keep some state information
around, you probably want to reset it when visiting a new template.
This can be achieved with the following code::
protected $someTemplateState = [];
public function enterNode(\Twig\Node\Node $node, \Twig\Environment $env)
{
if ($node instanceof \Twig\Node\ModuleNode) {
// reset the state as we are entering a new template
$this->someTemplateState = [];
}
// ...
return $node;
}
Using a Database to store Templates
-----------------------------------
If you are developing a CMS, templates are usually stored in a database. This
recipe gives you a simple PDO template loader you can use as a starting point
for your own.
First, let's create a temporary in-memory SQLite3 database to work with::
$dbh = new PDO('sqlite::memory:');
$dbh->exec('CREATE TABLE templates (name STRING, source STRING, last_modified INTEGER)');
$base = '{% block content %}{% endblock %}';
$index = '
{% extends "base.twig" %}
{% block content %}Hello {{ name }}{% endblock %}
';
$now = time();
$dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['base.twig', $base, $now]);
$dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['index.twig', $index, $now]);
We have created a simple ``templates`` table that hosts two templates:
``base.twig`` and ``index.twig``.
Now, let's define a loader able to use this database::
class DatabaseTwigLoader implements \Twig\Loader\LoaderInterface
{
protected $dbh;
public function __construct(PDO $dbh)
{
$this->dbh = $dbh;
}
public function getSourceContext(string $name): Source
{
if (false === $source = $this->getValue('source', $name)) {
throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name));
}
return new \Twig\Source($source, $name);
}
public function exists(string $name)
{
return $name === $this->getValue('name', $name);
}
public function getCacheKey(string $name): string
{
return $name;
}
public function isFresh(string $name, int $time): bool
{
if (false === $lastModified = $this->getValue('last_modified', $name)) {
return false;
}
return $lastModified <= $time;
}
protected function getValue($column, $name)
{
$sth = $this->dbh->prepare('SELECT '.$column.' FROM templates WHERE name = :name');
$sth->execute([':name' => (string) $name]);
return $sth->fetchColumn();
}
}
Finally, here is an example on how you can use it::
$loader = new DatabaseTwigLoader($dbh);
$twig = new \Twig\Environment($loader);
echo $twig->render('index.twig', ['name' => 'Fabien']);
Using different Template Sources
--------------------------------
This recipe is the continuation of the previous one. Even if you store the
contributed templates in a database, you might want to keep the original/base
templates on the filesystem. When templates can be loaded from different
sources, you need to use the ``\Twig\Loader\ChainLoader`` loader.
As you can see in the previous recipe, we reference the template in the exact
same way as we would have done it with a regular filesystem loader. This is
the key to be able to mix and match templates coming from the database, the
filesystem, or any other loader for that matter: the template name should be a
logical name, and not the path from the filesystem::
$loader1 = new DatabaseTwigLoader($dbh);
$loader2 = new \Twig\Loader\ArrayLoader([
'base.twig' => '{% block content %}{% endblock %}',
]);
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
$twig = new \Twig\Environment($loader);
echo $twig->render('index.twig', ['name' => 'Fabien']);
Now that the ``base.twig`` templates is defined in an array loader, you can
remove it from the database, and everything else will still work as before.
Loading a Template from a String
--------------------------------
From a template, you can load a template stored in a string via the
``template_from_string`` function (via the
``\Twig\Extension\StringLoaderExtension`` extension):
.. code-block:: twig
{{ include(template_from_string("Hello {{ name }}")) }}
From PHP, it's also possible to load a template stored in a string via
``\Twig\Environment::createTemplate()``::
$template = $twig->createTemplate('hello {{ name }}');
echo $template->render(['name' => 'Fabien']);
Using Twig and AngularJS in the same Templates
----------------------------------------------
Mixing different template syntaxes in the same file is not a recommended
practice as both AngularJS and Twig use the same delimiters in their syntax:
``{{`` and ``}}``.
Still, if you want to use AngularJS and Twig in the same template, there are
two ways to make it work depending on the amount of AngularJS you need to
include in your templates:
* Escaping the AngularJS delimiters by wrapping AngularJS sections with the
``{% verbatim %}`` tag or by escaping each delimiter via ``{{ '{{' }}`` and
``{{ '}}' }}``;
* Changing the delimiters of one of the template engines (depending on which
engine you introduced last):
* For AngularJS, change the interpolation tags using the
``interpolateProvider`` service, for instance at the module initialization
time:
.. code-block:: javascript
angular.module('myApp', []).config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[').endSymbol(']}');
});
* For Twig, change the delimiters via the ``tag_variable`` Lexer option::
$env->setLexer(new \Twig\Lexer($env, [
'tag_variable' => ['{[', ']}'],
]));
.. _callback: https://www.php.net/manual/en/function.is-callable.php

20
vendor/twig/twig/doc/tags/apply.rst vendored Normal file
View File

@@ -0,0 +1,20 @@
``apply``
=========
The ``apply`` tag allows you to apply Twig filters on a block of template data:
.. code-block:: twig
{% apply upper %}
This text becomes uppercase
{% endapply %}
You can also chain filters and pass arguments to them:
.. code-block:: html+twig
{% apply lower|escape('html') %}
<strong>SOME TEXT</strong>
{% endapply %}
{# outputs "&lt;strong&gt;some text&lt;/strong&gt;" #}

View File

@@ -0,0 +1,61 @@
``autoescape``
==============
Whether automatic escaping is enabled or not, you can mark a section of a
template to be escaped or not by using the ``autoescape`` tag:
.. code-block:: twig
{% autoescape %}
Everything will be automatically escaped in this block
using the HTML strategy
{% endautoescape %}
{% autoescape 'html' %}
Everything will be automatically escaped in this block
using the HTML strategy
{% endautoescape %}
{% autoescape 'js' %}
Everything will be automatically escaped in this block
using the js escaping strategy
{% endautoescape %}
{% autoescape false %}
Everything will be outputted as is in this block
{% endautoescape %}
When automatic escaping is enabled everything is escaped by default except for
values explicitly marked as safe. Those can be marked in the template by using
the :doc:`raw<../filters/raw>` filter:
.. code-block:: twig
{% autoescape %}
{{ safe_value|raw }}
{% endautoescape %}
Functions returning template data (like :doc:`macros<macro>` and
:doc:`parent<../functions/parent>`) always return safe markup.
.. note::
Twig is smart enough to not escape an already escaped value by the
:doc:`escape<../filters/escape>` filter.
.. note::
Twig does not escape static expressions:
.. code-block:: html+twig
{% set hello = "<strong>Hello</strong>" %}
{{ hello }}
{{ "<strong>world</strong>" }}
Will be rendered "<strong>Hello</strong> **world**".
.. note::
The chapter :doc:`Twig for Developers<../api>` gives more information
about when and how automatic escaping is applied.

12
vendor/twig/twig/doc/tags/block.rst vendored Normal file
View File

@@ -0,0 +1,12 @@
``block``
=========
Blocks are used for inheritance and act as placeholders and replacements at
the same time. They are documented in detail in the documentation for the
:doc:`extends<../tags/extends>` tag.
Block names must consist of alphanumeric characters, and underscores. The first char can't be a digit and dashes are not permitted.
.. seealso::
:doc:`block<../functions/block>`, :doc:`parent<../functions/parent>`, :doc:`use<../tags/use>`, :doc:`extends<../tags/extends>`

113
vendor/twig/twig/doc/tags/cache.rst vendored Normal file
View File

@@ -0,0 +1,113 @@
``cache``
=========
.. versionadded:: 3.2
The ``cache`` tag was added in Twig 3.2.
The ``cache`` tag tells Twig to cache a template fragment:
.. code-block:: twig
{% cache "cache key" %}
Cached forever (depending on the cache implementation)
{% endcache %}
If you want to expire the cache after a certain amount of time, specify an
expiration in seconds via the ``ttl()`` modifier:
.. code-block:: twig
{% cache "cache key" ttl(300) %}
Cached for 300 seconds
{% endcache %}
The cache key can be any string that does not use the following reserved
characters ``{}()/\@:``; a good practice is to embed some useful information in
the key that allows the cache to automatically expire when it must be
refreshed:
* Give each cache a unique name and namespace it like your templates;
* Embed an integer that you increment whenever the template code changes (to
automatically invalidate all current caches);
* Embed a unique key that is updated whenever the variables used in the
template code changes.
For instance, I would use ``{% cache "blog_post;v1;" ~ post.id ~ ";" ~
post.updated_at %}`` to cache a blog content template fragment where
``blog_post`` describes the template fragment, ``v1`` represents the first
version of the template code, ``post.id`` represent the id of the blog post,
and ``post.updated_at`` returns a timestamp that represents the time where the
blog post was last modified.
Using such a strategy for naming cache keys allows to avoid using a ``ttl``.
It's like using a "validation" strategy instead of an "expiration" strategy as
we do for HTTP caches.
If your cache implementation supports tags, you can also tag your cache items:
.. code-block:: twig
{% cache "cache key" tags('blog') %}
Some code
{% endcache %}
{% cache "cache key" tags(['cms', 'blog']) %}
Some code
{% endcache %}
The ``cache`` tag creates a new "scope" for variables, meaning that the changes
are local to the template fragment:
.. code-block:: twig
{% set count = 1 %}
{% cache "cache key" tags('blog') %}
{# Won't affect the value of count outside of the cache tag #}
{% set count = 2 %}
Some code
{% endcache %}
{# Displays 1 #}
{{ count }}
.. note::
The ``cache`` tag is part of the ``CacheExtension`` which is not installed
by default. Install it first:
.. code-block:: bash
$ composer require twig/cache-extra
On Symfony projects, you can automatically enable it by installing the
``twig/extra-bundle``:
.. code-block:: bash
$ composer require twig/extra-bundle
Or add the extension explicitly on the Twig environment::
use Twig\Extra\Cache\CacheExtension;
$twig = new \Twig\Environment(...);
$twig->addExtension(new CacheExtension());
If you are not using Symfony, you must also register the extension runtime::
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
use Twig\Extra\Cache\CacheRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
public function load($class) {
if (CacheRuntime::class === $class) {
return new CacheRuntime(new TagAwareAdapter(new FilesystemAdapter()));
}
}
});

View File

@@ -0,0 +1,27 @@
``deprecated``
==============
Twig generates a deprecation notice (via a call to the ``trigger_error()``
PHP function) where the ``deprecated`` tag is used in a template:
.. code-block:: twig
{# base.twig #}
{% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
{% extends 'layout.twig' %}
Also you can deprecate a block in the following way:
.. code-block:: twig
{% block hey %}
{% deprecated 'The "hey" block is deprecated, use "greet" instead.' %}
{{ block('greet') }}
{% endblock %}
{% block greet %}
Hey you!
{% endblock %}
Note that by default, the deprecation notices are silenced and never displayed nor logged.
See :ref:`deprecation-notices` to learn how to handle them.

Some files were not shown because too many files have changed in this diff Show More