From 8e69c58ed781ebe98c0ff1714bb9ebb6e87ce356 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Tue, 13 Aug 2024 12:28:15 +0200 Subject: [PATCH] [FEATURE] Create a rst theme to convert markdown Convert basic mark-down into restructured Text * headlines * paragpraphs * links * lists * emphasis * inline-code --- composer.json | 3 +- composer.lock | 44 ++++++- config.subsplit-publish.json | 5 + deptrac.packages.yaml | 1 + packages/guides-theme-rst/.gitattributes | 4 + packages/guides-theme-rst/.gitignore | 1 + packages/guides-theme-rst/CONTRIBUTING.rst | 23 ++++ packages/guides-theme-rst/LICENSE | 21 ++++ packages/guides-theme-rst/README.rst | 37 ++++++ packages/guides-theme-rst/composer.json | 32 +++++ .../resources/config/guides-theme-rst.php | 34 ++++++ .../resources/template/rst/body/code.rst.twig | 6 + .../template/rst/body/list/list.rst.twig | 11 ++ .../template/rst/body/paragraph.rst.twig | 6 + .../template/rst/body/quote.rst.twig | 3 + .../template/rst/body/separator.rst.twig | 1 + .../template/rst/guides/inline/br.rst.twig | 1 + .../rst/guides/inline/emphasis.rst.twig | 1 + .../template/rst/guides/inline/link.rst.twig | 5 + .../rst/guides/inline/literal.rst.twig | 1 + .../template/rst/guides/inline/nbsp.rst.twig | 1 + .../guides/inline/strong-emphasis.rst.twig | 1 + .../rst/guides/structure/header/meta.rst.twig | 0 .../guides/structure/header/title.rst.twig | 1 + .../template/rst/inline/emphasis.rst.twig | 1 + .../template/rst/inline/image.rst.twig | 4 + .../template/rst/inline/inline-node.rst.twig | 3 + .../template/rst/inline/link.rst.twig | 7 ++ .../template/rst/inline/literal.rst.twig | 5 + .../template/rst/inline/plain-text.rst.twig | 1 + .../template/rst/inline/strong.rst.twig | 1 + .../template/rst/structure/document.rst.twig | 7 ++ .../rst/structure/header-title.rst.twig | 1 + .../template/rst/structure/project.rst.twig | 3 + .../template/rst/structure/section.rst.twig | 4 + .../resources/template/rst/template.php | 110 ++++++++++++++++++ .../RstTheme/Configuration/HeaderSyntax.php | 43 +++++++ .../DependencyInjection/RstThemeExtension.php | 53 +++++++++ .../src/RstTheme/Renderer/RstRenderer.php | 20 ++++ .../src/RstTheme/Twig/RstExtension.php | 80 +++++++++++++ psalm-baseline.xml | 2 +- psalm.xml | 1 + .../blockquote-md-to-rst/expected/index.rst | 32 +++++ .../blockquote-md-to-rst/input/guides.xml | 11 ++ .../blockquote-md-to-rst/input/index.md | 27 +++++ .../code-md-to-rst/expected/index.rst | 33 ++++++ .../md-to-rst/code-md-to-rst/input/guides.xml | 11 ++ .../md-to-rst/code-md-to-rst/input/index.md | 26 +++++ .../emphasis-md-to-rst/expected/index.rst | 5 + .../emphasis-md-to-rst/input/guides.xml | 11 ++ .../emphasis-md-to-rst/input/index.md | 4 + .../index-md-to-rst/expected/index.rst | 12 ++ .../index-md-to-rst/input/guides.xml | 11 ++ .../md-to-rst/index-md-to-rst/input/index.md | 9 ++ .../inline-code-md-to-rst/expected/index.rst | 7 ++ .../inline-code-md-to-rst/input/guides.xml | 11 ++ .../inline-code-md-to-rst/input/index.md | 5 + .../md-to-rst-list-link/expected/index.rst | 53 +++++++++ .../md-to-rst-list-link/input/guides.xml | 11 ++ .../md-to-rst-list-link/input/index.md | 41 +++++++ 60 files changed, 905 insertions(+), 4 deletions(-) create mode 100644 packages/guides-theme-rst/.gitattributes create mode 100644 packages/guides-theme-rst/.gitignore create mode 100644 packages/guides-theme-rst/CONTRIBUTING.rst create mode 100644 packages/guides-theme-rst/LICENSE create mode 100644 packages/guides-theme-rst/README.rst create mode 100644 packages/guides-theme-rst/composer.json create mode 100644 packages/guides-theme-rst/resources/config/guides-theme-rst.php create mode 100644 packages/guides-theme-rst/resources/template/rst/body/code.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/body/list/list.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/body/paragraph.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/body/quote.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/body/separator.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/br.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/emphasis.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/link.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/literal.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/nbsp.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/inline/strong-emphasis.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/structure/header/meta.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/guides/structure/header/title.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/emphasis.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/image.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/inline-node.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/link.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/literal.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/plain-text.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/inline/strong.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/structure/document.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/structure/header-title.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/structure/project.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/structure/section.rst.twig create mode 100644 packages/guides-theme-rst/resources/template/rst/template.php create mode 100644 packages/guides-theme-rst/src/RstTheme/Configuration/HeaderSyntax.php create mode 100644 packages/guides-theme-rst/src/RstTheme/DependencyInjection/RstThemeExtension.php create mode 100644 packages/guides-theme-rst/src/RstTheme/Renderer/RstRenderer.php create mode 100644 packages/guides-theme-rst/src/RstTheme/Twig/RstExtension.php create mode 100644 tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/index.md create mode 100644 tests/Integration/tests-full/md-to-rst/code-md-to-rst/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/index.md create mode 100644 tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/index.md create mode 100644 tests/Integration/tests-full/md-to-rst/index-md-to-rst/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/index.md create mode 100644 tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/index.md create mode 100644 tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/expected/index.rst create mode 100644 tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/guides.xml create mode 100644 tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/index.md diff --git a/composer.json b/composer.json index 931d19b51..f37cf7698 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,8 @@ "phpdocumentor/guides-graphs": "^2.0@dev || ^1.0", "phpdocumentor/guides-markdown": "^2.0@dev || ^1.0", "phpdocumentor/guides-restructured-text": "^2.0@dev || ^1.0", - "phpdocumentor/guides-theme-bootstrap": "^2.0@dev || ^1.0" + "phpdocumentor/guides-theme-bootstrap": "^2.0@dev || ^1.0", + "phpdocumentor/guides-theme-rst": "^2.0@dev || ^1.0" }, "require-dev": { "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 14334b856..eb615a2be 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "838af16e3563e2e1002a608d028b0f55", + "content-hash": "5c44fdb9ce8b1709c92d86b1d5c127e8", "packages": [ { "name": "dflydev/dot-access-data", @@ -1590,6 +1590,45 @@ "relative": true } }, + { + "name": "phpdocumentor/guides-theme-rst", + "version": "dev-main", + "dist": { + "type": "path", + "url": "./packages/guides-theme-rst", + "reference": "70ef007a53221f1c725d02d6cc71adb4e7648177" + }, + "require": { + "php": "^8.1", + "phpdocumentor/guides": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Guides\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "phpDocumentor\\Guides\\": [ + "tests/unit/" + ] + } + }, + "license": [ + "MIT" + ], + "description": "Adds a reStructuredText theme used to convert Markdown into reStructuredText", + "homepage": "https://www.phpdoc.org", + "transport-options": { + "relative": true + } + }, { "name": "psr/clock", "version": "1.0.0", @@ -8188,7 +8227,8 @@ "phpdocumentor/guides-graphs": 20, "phpdocumentor/guides-markdown": 20, "phpdocumentor/guides-restructured-text": 20, - "phpdocumentor/guides-theme-bootstrap": 20 + "phpdocumentor/guides-theme-bootstrap": 20, + "phpdocumentor/guides-theme-rst": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config.subsplit-publish.json b/config.subsplit-publish.json index 30bc21248..6c10e9680 100644 --- a/config.subsplit-publish.json +++ b/config.subsplit-publish.json @@ -34,6 +34,11 @@ "name": "guides-code", "directory": "packages/guides-code", "target": "git@github.com:phpDocumentor/guides-code.git" + }, + { + "name": "guides-theme-rst", + "directory": "packages/guides-rst-theme", + "target": "git@github.com:phpDocumentor/guides-theme-rst.git" } ] } diff --git a/deptrac.packages.yaml b/deptrac.packages.yaml index a0d5a9500..f7211eae1 100644 --- a/deptrac.packages.yaml +++ b/deptrac.packages.yaml @@ -40,6 +40,7 @@ deptrac: CLI: - "Guides" - "RST" + - "Markdown" RST: - "Guides" Markdown: diff --git a/packages/guides-theme-rst/.gitattributes b/packages/guides-theme-rst/.gitattributes new file mode 100644 index 000000000..29d77c0df --- /dev/null +++ b/packages/guides-theme-rst/.gitattributes @@ -0,0 +1,4 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/docs export-ignore +/tests export-ignore diff --git a/packages/guides-theme-rst/.gitignore b/packages/guides-theme-rst/.gitignore new file mode 100644 index 000000000..140fada73 --- /dev/null +++ b/packages/guides-theme-rst/.gitignore @@ -0,0 +1 @@ +vendor/* diff --git a/packages/guides-theme-rst/CONTRIBUTING.rst b/packages/guides-theme-rst/CONTRIBUTING.rst new file mode 100644 index 000000000..799a7918a --- /dev/null +++ b/packages/guides-theme-rst/CONTRIBUTING.rst @@ -0,0 +1,23 @@ +====================================== +Contribute to the phpDocumentor Guides +====================================== + +Go to the mono-repository +========================= + +This project is developed in the mono-repository `phpDocumentor Guides `__. +The repository you are currently in gets auto-created by splitting the mono-repository. You **must not** contribute +to this repository directly but always to the mono-repository linked above. + +Create Issues +============= + +* If you find something missing or something is wrong in this library, you are welcome to write an issue + describing the problem: `Issues on GitHub `__. +* If you can, please try to fix the problem yourself. + +Make changes (create pull requests) +=================================== + +See the `Contribution chapter `__ in the +`Documentation` `__. diff --git a/packages/guides-theme-rst/LICENSE b/packages/guides-theme-rst/LICENSE new file mode 100644 index 000000000..792e4040f --- /dev/null +++ b/packages/guides-theme-rst/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2010 Mike van Riel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/guides-theme-rst/README.rst b/packages/guides-theme-rst/README.rst new file mode 100644 index 000000000..4457b1028 --- /dev/null +++ b/packages/guides-theme-rst/README.rst @@ -0,0 +1,37 @@ + +.. image:: http://poser.pugx.org/phpdocumentor/guides-restructured-text/require/php + :alt: PHP Version Require + :target: https://packagist.org/packages/phpdocumentor/guides-restructured-text + +.. image:: http://poser.pugx.org/phpdocumentor/guides-restructured-text/v/stable + :alt: Latest Stable Version + :target: https://packagist.org/packages/phpdocumentor/guides-restructured-text + +.. image:: http://poser.pugx.org/phpdocumentor/guides-restructured-text/v/unstable + :alt: Latest Unstable Version + :target: https://packagist.org/packages/phpdocumentor/guides-restructured-text + +.. image:: https://poser.pugx.org/phpdocumentor/guides-restructured-text/d/total + :alt: Total Downloads + :target: https://packagist.org/packages/phpdocumentor/guides-restructured-text + +.. image:: https://poser.pugx.org/phpdocumentor/guides-restructured-text/d/monthly + :alt: Monthly Downloads + :target: https://packagist.org/packages/phpdocumentor/guides-restructured-text + +==================== +phpDocumentor Guides +==================== + +This repository is part of `phpDocumentor's Guides library `__, a framework +designed to take hand-written documentation in code repositories and create an AST (abstract syntax tree) from it. +This AST is then fed to a renderer, which produces the desired output, such as HTML. + +The package `phpdocumentor/guides-restructured-text `__ adds +`reStructuredText Markup `__ support to the +phpDocumentor's Guides library. + +:Mono-Repository: https://github.com/phpDocumentor/guides +:Documentation: https://github.com/phpDocumentor/guides/tree/main/docs/index.rst +:Packagist: https://packagist.org/packages/phpdocumentor/guides-restructured-text +:Contribution: https://github.com/phpDocumentor/guides/tree/main/CONTRIBUTING.rst diff --git a/packages/guides-theme-rst/composer.json b/packages/guides-theme-rst/composer.json new file mode 100644 index 000000000..7a3681a80 --- /dev/null +++ b/packages/guides-theme-rst/composer.json @@ -0,0 +1,32 @@ +{ + "name": "phpdocumentor/guides-theme-rst", + "description": "Adds a reStructuredText theme used to convert Markdown into reStructuredText", + "type": "library", + "license": "MIT", + "homepage": "https://www.phpdoc.org", + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Guides\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "phpDocumentor\\Guides\\": [ + "tests/unit/" + ] + } + }, + "minimum-stability": "stable", + "require": { + "php": "^8.1", + "phpdocumentor/guides": "^1.0 || ^2.0" + }, + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + } +} diff --git a/packages/guides-theme-rst/resources/config/guides-theme-rst.php b/packages/guides-theme-rst/resources/config/guides-theme-rst.php new file mode 100644 index 000000000..34b3fe095 --- /dev/null +++ b/packages/guides-theme-rst/resources/config/guides-theme-rst.php @@ -0,0 +1,34 @@ +services() + ->defaults() + ->autowire() + ->autoconfigure() + /* + ->load( + 'phpDocumentor\\Guides\RstTheme\\NodeRenderers\\Rst\\', + '%vendor_dir%/phpdocumentor/guides-rst-theme/src/RstTheme/NodeRenderers/Rst', + ) + ->tag('phpdoc.guides.noderenderer.rst') + */ + + ->set(RstRenderer::class) + ->tag( + 'phpdoc.renderer.typerenderer', + [ + 'noderender_tag' => 'phpdoc.guides.noderenderer.rst', + 'format' => 'rst', + ], + ) + + ->set(RstExtension::class) + ->tag('twig.extension') + ->autowire(); +}; diff --git a/packages/guides-theme-rst/resources/template/rst/body/code.rst.twig b/packages/guides-theme-rst/resources/template/rst/body/code.rst.twig new file mode 100644 index 000000000..720289765 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/body/code.rst.twig @@ -0,0 +1,6 @@ +.. code-block:: plaintext + +{{ renderRstIndent(node.value|raw, 1)|raw }} +{{ "\n" }} +{{ "\n" }} + diff --git a/packages/guides-theme-rst/resources/template/rst/body/list/list.rst.twig b/packages/guides-theme-rst/resources/template/rst/body/list/list.rst.twig new file mode 100644 index 000000000..4aebaa88d --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/body/list/list.rst.twig @@ -0,0 +1,11 @@ +{{ "\n" }} +{% if node.isOrdered -%} + {%- for item in node.value -%} + #. {{ renderNode(item.value)|raw }}{{ "\n" }} + {% endfor -%} +{%- else -%} + {%- for item in node.value -%} + * {{ renderNode(item.value)|raw }}{{ "\n" }} + {%- endfor -%} +{%- endif %} +{{ "\n" }} diff --git a/packages/guides-theme-rst/resources/template/rst/body/paragraph.rst.twig b/packages/guides-theme-rst/resources/template/rst/body/paragraph.rst.twig new file mode 100644 index 000000000..043801fdf --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/body/paragraph.rst.twig @@ -0,0 +1,6 @@ +{% set text = renderNode(node.value)|raw -%} +{%- if text|trim %} + {{- text|raw -}} +{% endif -%} +{{ "\n" }} +{{ "\n" }} diff --git a/packages/guides-theme-rst/resources/template/rst/body/quote.rst.twig b/packages/guides-theme-rst/resources/template/rst/body/quote.rst.twig new file mode 100644 index 000000000..70f1798d7 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/body/quote.rst.twig @@ -0,0 +1,3 @@ +{{ renderRstIndent(renderNode(node.value)|raw, 1)|raw }} +{{ "\n" }} +{{ "\n" }} diff --git a/packages/guides-theme-rst/resources/template/rst/body/separator.rst.twig b/packages/guides-theme-rst/resources/template/rst/body/separator.rst.twig new file mode 100644 index 000000000..693a05c9a --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/body/separator.rst.twig @@ -0,0 +1 @@ +==== diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/br.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/br.rst.twig new file mode 100644 index 000000000..ae7ddaf01 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/br.rst.twig @@ -0,0 +1 @@ +\\\\\\\\\n diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/emphasis.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/emphasis.rst.twig new file mode 100644 index 000000000..f74bede9a --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/emphasis.rst.twig @@ -0,0 +1 @@ +\textit{{ '{' }}{{ text|raw }}{{ '}' }} diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/link.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/link.rst.twig new file mode 100644 index 000000000..34797c039 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/link.rst.twig @@ -0,0 +1,5 @@ +{% if type == 'ref' %} +\ref{{ '{' }}{{ url }}{{ '}' }} +{% else %} +\href{{ '{' }}{{ url }}{{ '}' }}{{ '{' }}{{ title }}{{ '}' }} +{% endif %} diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/literal.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/literal.rst.twig new file mode 100644 index 000000000..c883ec94d --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/literal.rst.twig @@ -0,0 +1 @@ +\verb|{{ node.value|raw }}| diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/nbsp.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/nbsp.rst.twig new file mode 100644 index 000000000..54bcf3046 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/nbsp.rst.twig @@ -0,0 +1 @@ +~ diff --git a/packages/guides-theme-rst/resources/template/rst/guides/inline/strong-emphasis.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/inline/strong-emphasis.rst.twig new file mode 100644 index 000000000..9802bb260 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/inline/strong-emphasis.rst.twig @@ -0,0 +1 @@ +\textbf{{ '{' }}{{ text|raw }}{{ '}' }} diff --git a/packages/guides-theme-rst/resources/template/rst/guides/structure/header/meta.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/structure/header/meta.rst.twig new file mode 100644 index 000000000..e69de29bb diff --git a/packages/guides-theme-rst/resources/template/rst/guides/structure/header/title.rst.twig b/packages/guides-theme-rst/resources/template/rst/guides/structure/header/title.rst.twig new file mode 100644 index 000000000..ae1d71fe2 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/guides/structure/header/title.rst.twig @@ -0,0 +1 @@ +\{{ type }}{{ '{' }}{{ renderNode(titleNode.value) }}{{ '}' }} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/emphasis.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/emphasis.rst.twig new file mode 100644 index 000000000..7c0eee195 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/emphasis.rst.twig @@ -0,0 +1 @@ +*{{- node.value|raw -}}* diff --git a/packages/guides-theme-rst/resources/template/rst/inline/image.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/image.rst.twig new file mode 100644 index 000000000..d68c54a0a --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/image.rst.twig @@ -0,0 +1,4 @@ +{{ "\n" }} +.. figure:: {{ node.url|raw }} + :alt: {{ node.altText|raw }} +{{ "\n" }} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/inline-node.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/inline-node.rst.twig new file mode 100644 index 000000000..9150f32bc --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/inline-node.rst.twig @@ -0,0 +1,3 @@ +{%- for child in node.children -%} + {{- renderNode(child)|raw -}} +{%- endfor -%} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/link.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/link.rst.twig new file mode 100644 index 000000000..edde6ce9c --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/link.rst.twig @@ -0,0 +1,7 @@ +{%- if node.url -%} + `{{ node.value|raw }} <{{- node.url -}}>`__ +{%- elseif node.targetReference -%} + :doc:`{{ node.value|raw }} <{{- node.targetReference -}}>` +{%- else -%} + {{- node.value -}} +{%- endif -%} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/literal.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/literal.rst.twig new file mode 100644 index 000000000..827697faf --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/literal.rst.twig @@ -0,0 +1,5 @@ +{%- if node.value matches '/`/' -%} + ``{{- node.value|raw -}}`` +{%- else -%} + `{{- node.value|raw -}}` +{%- endif -%} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/plain-text.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/plain-text.rst.twig new file mode 100644 index 000000000..7fd22d7bc --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/plain-text.rst.twig @@ -0,0 +1 @@ +{{- node.value|raw -}} diff --git a/packages/guides-theme-rst/resources/template/rst/inline/strong.rst.twig b/packages/guides-theme-rst/resources/template/rst/inline/strong.rst.twig new file mode 100644 index 000000000..3a08cb2cc --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/inline/strong.rst.twig @@ -0,0 +1 @@ +**{{- node.value|raw -}}** diff --git a/packages/guides-theme-rst/resources/template/rst/structure/document.rst.twig b/packages/guides-theme-rst/resources/template/rst/structure/document.rst.twig new file mode 100644 index 000000000..5f654d27e --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/structure/document.rst.twig @@ -0,0 +1,7 @@ +{%- set renderedContent -%} + {%- for child in node.children -%} + {{- renderNode(child) -}} + {%- endfor -%} +{%- endset -%} + +{{- renderedContent | clean_content | raw -}} diff --git a/packages/guides-theme-rst/resources/template/rst/structure/header-title.rst.twig b/packages/guides-theme-rst/resources/template/rst/structure/header-title.rst.twig new file mode 100644 index 000000000..bf9f3bfbb --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/structure/header-title.rst.twig @@ -0,0 +1 @@ +{{ renderRstTitle(node, renderNode(node.value)) }} diff --git a/packages/guides-theme-rst/resources/template/rst/structure/project.rst.twig b/packages/guides-theme-rst/resources/template/rst/structure/project.rst.twig new file mode 100644 index 000000000..adbd7d6c3 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/structure/project.rst.twig @@ -0,0 +1,3 @@ +{%- for document in documents %} + {{- renderNode(document) }} +{%- endfor -%} diff --git a/packages/guides-theme-rst/resources/template/rst/structure/section.rst.twig b/packages/guides-theme-rst/resources/template/rst/structure/section.rst.twig new file mode 100644 index 000000000..e9538aa5d --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/structure/section.rst.twig @@ -0,0 +1,4 @@ +{% for childNode in node.children -%} + {{- renderNode(childNode) }} + +{% endfor -%} diff --git a/packages/guides-theme-rst/resources/template/rst/template.php b/packages/guides-theme-rst/resources/template/rst/template.php new file mode 100644 index 000000000..14bd87902 --- /dev/null +++ b/packages/guides-theme-rst/resources/template/rst/template.php @@ -0,0 +1,110 @@ + 'inline/anchor.rst.twig', + FigureNode::class => 'body/figure.rst.twig', + MetaNode::class => 'structure/header/meta.rst.twig', + ParagraphNode::class => 'body/paragraph.rst.twig', + QuoteNode::class => 'body/quote.rst.twig', + SeparatorNode::class => 'body/separator.rst.twig', + TitleNode::class => 'structure/header-title.rst.twig', + SectionNode::class => 'structure/section.rst.twig', + DocumentNode::class => 'structure/document.rst.twig', + ImageNode::class => 'body/image.rst.twig', + CodeNode::class => 'body/code.rst.twig', + DefinitionListNode::class => 'body/definition-list.rst.twig', + DefinitionNode::class => 'body/definition.rst.twig', + FieldListNode::class => 'body/field-list.rst.twig', + ListNode::class => 'body/list/list.rst.twig', + ListItemNode::class => 'body/list/list-item.rst.twig', + LiteralBlockNode::class => 'body/literal-block.rst.twig', + CitationNode::class => 'body/citation.rst.twig', + FootnoteNode::class => 'body/footnote.rst.twig', + AnnotationListNode::class => 'body/annotation-list.rst.twig', + // Inline + ImageInlineNode::class => 'inline/image.rst.twig', + InlineCompoundNode::class => 'inline/inline-node.rst.twig', + AbbreviationInlineNode::class => 'inline/textroles/abbreviation.rst.twig', + CitationInlineNode::class => 'inline/citation.rst.twig', + DocReferenceNode::class => 'inline/doc.rst.twig', + EmphasisInlineNode::class => 'inline/emphasis.rst.twig', + FootnoteInlineNode::class => 'inline/footnote.rst.twig', + HyperLinkNode::class => 'inline/link.rst.twig', + LiteralInlineNode::class => 'inline/literal.rst.twig', + NewlineInlineNode::class => 'inline/newline.rst.twig', + WhitespaceInlineNode::class => 'inline/nbsp.rst.twig', + PlainTextInlineNode::class => 'inline/plain-text.rst.twig', + ReferenceNode::class => 'inline/ref.rst.twig', + StrongInlineNode::class => 'inline/strong.rst.twig', + VariableInlineNode::class => 'inline/variable.rst.twig', + GenericTextRoleInlineNode::class => 'inline/textroles/generic.rst.twig', + // Output as Metatags + AuthorNode::class => 'structure/header/author.rst.twig', + CopyrightNode::class => 'structure/header/copyright.rst.twig', + DateNode::class => 'structure/header/date.rst.twig', + NoSearchNode::class => 'structure/header/no-search.rst.twig', + TopicNode::class => 'structure/header/topic.rst.twig', + // No output in page header in tex - might be output in i.e. LaTex + AddressNode::class => 'structure/header/blank.rst.twig', + AuthorsNode::class => 'structure/header/blank.rst.twig', + ContactNode::class => 'structure/header/blank.rst.twig', + NoCommentsNode::class => 'structure/header/blank.rst.twig', + OrganizationNode::class => 'structure/header/blank.rst.twig', + OrphanNode::class => 'structure/header/blank.rst.twig', + RevisionNode::class => 'structure/header/blank.rst.twig', + TocDepthNode::class => 'structure/header/blank.rst.twig', + VersionNode::class => 'structure/header/blank.rst.twig', +]; diff --git a/packages/guides-theme-rst/src/RstTheme/Configuration/HeaderSyntax.php b/packages/guides-theme-rst/src/RstTheme/Configuration/HeaderSyntax.php new file mode 100644 index 000000000..ba1d1858a --- /dev/null +++ b/packages/guides-theme-rst/src/RstTheme/Configuration/HeaderSyntax.php @@ -0,0 +1,43 @@ + '=', + HeaderSyntax::H3 => '-', + HeaderSyntax::H4 => '~', + HeaderSyntax::H5 => '#', + HeaderSyntax::H6 => '*', + }; + } + + public function hasTopDelimiter(): bool + { + return match ($this) { + HeaderSyntax::H1 => true, + default => false, + }; + } +} diff --git a/packages/guides-theme-rst/src/RstTheme/DependencyInjection/RstThemeExtension.php b/packages/guides-theme-rst/src/RstTheme/DependencyInjection/RstThemeExtension.php new file mode 100644 index 000000000..8913e0624 --- /dev/null +++ b/packages/guides-theme-rst/src/RstTheme/DependencyInjection/RstThemeExtension.php @@ -0,0 +1,53 @@ +load('guides-theme-rst.php'); + } + + public function prepend(ContainerBuilder $container): void + { + $container->prependExtensionConfig('guides', [ + 'themes' => ['rst' => dirname(__DIR__, 3) . '/resources/template/rst'], + ]); + + $container->prependExtensionConfig( + 'guides', + [ + 'templates' => templateArray( + require dirname(__DIR__, 3) . '/resources/template/rst/template.php', + 'rst', + ), + ], + ); + } +} diff --git a/packages/guides-theme-rst/src/RstTheme/Renderer/RstRenderer.php b/packages/guides-theme-rst/src/RstTheme/Renderer/RstRenderer.php new file mode 100644 index 000000000..4144dabf5 --- /dev/null +++ b/packages/guides-theme-rst/src/RstTheme/Renderer/RstRenderer.php @@ -0,0 +1,20 @@ +renderRstTitle(...), ['is_safe' => ['rst'], 'needs_context' => false]), + new TwigFunction('renderRstIndent', $this->renderRstIndent(...), ['is_safe' => ['rst'], 'needs_context' => false]), + ]; + } + + /** @return TwigFilter[] */ + public function getFilters(): array + { + return [ + new TwigFilter('clean_content', [$this, 'cleanContent']), + ]; + } + + public function cleanContent(string $content): string + { + $lines = explode("\n", $content); + $lines = array_map('rtrim', $lines); + $content = implode("\n", $lines); + + $content = preg_replace('/(\n){2,}/', "\n\n", $content); + + return rtrim($content) . "\n"; + } + + public function renderRstIndent(string $text, int $indentNr): string + { + $indent = str_repeat(' ', $indentNr * 4); + + return preg_replace('/^/m', $indent, $text); + } + + public function renderRstTitle(TitleNode $node, string $content): string + { + $headerSyntax = HeaderSyntax::from(min($node->getLevel(), 6)); + $ret = ''; + if ($headerSyntax->hasTopDelimiter()) { + $ret .= str_repeat($headerSyntax->delimiter(), strlen($content)) . "\n"; + } + + $ret .= $content . "\n" . str_repeat($headerSyntax->delimiter(), strlen($content)); + + return $ret; + } +} diff --git a/psalm-baseline.xml b/psalm-baseline.xml index c6b80b2dd..58414e0c2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + diff --git a/psalm.xml b/psalm.xml index 9b5270fd2..29e1aefb7 100644 --- a/psalm.xml +++ b/psalm.xml @@ -43,6 +43,7 @@ + diff --git a/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/expected/index.rst b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/expected/index.rst new file mode 100644 index 000000000..6c678a114 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/expected/index.rst @@ -0,0 +1,32 @@ +==================== +Markdown Blockquotes +==================== + + This is a blockquote. It can span multiple lines. + +Blockquotes with Multiple Paragraphs +==================================== + + Dorothy followed her through many of the beautiful rooms in her castle. + + The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. + +Blockquotes with Other Elements +=============================== + + The quarterly results look great! + + * Revenue was off the chart. + + * Profits were higher than ever. + + *Everything* is going according to **plan**. + +Blockquotes Best Practices +========================== + +Try to put a blank line before... + + This is a blockquote + +...and after a blockquote. diff --git a/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/guides.xml b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/index.md b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/index.md new file mode 100644 index 000000000..f5e2f829a --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/blockquote-md-to-rst/input/index.md @@ -0,0 +1,27 @@ +# Markdown Blockquotes + +> This is a blockquote. +> It can span multiple lines. + +## Blockquotes with Multiple Paragraphs + +> Dorothy followed her through many of the beautiful rooms in her castle. +> +> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. + +## Blockquotes with Other Elements + +> The quarterly results look great! +> +> - Revenue was off the chart. +> - Profits were higher than ever. +> +> *Everything* is going according to **plan**. + +## Blockquotes Best Practices + +Try to put a blank line before... + +> This is a blockquote + +...and after a blockquote. diff --git a/tests/Integration/tests-full/md-to-rst/code-md-to-rst/expected/index.rst b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/expected/index.rst new file mode 100644 index 000000000..39771396a --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/expected/index.rst @@ -0,0 +1,33 @@ +========================= +Markdown with Code Blocks +========================= + +.. code-block:: plaintext + + + + + + +Fenced Code Blocks +================== + +.. code-block:: plaintext + + { + "firstName": "John", + "lastName": "Smith", + "age": 25 + } + +Fenced Code Block with caption +============================== + +.. code-block:: plaintext + + procedure startSwinging(swing, child) + while child.isComfortable() + swing.giveGentlePush() + waitForNextIteration() + end while + end procedure diff --git a/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/guides.xml b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/index.md b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/index.md new file mode 100644 index 000000000..099159e36 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/code-md-to-rst/input/index.md @@ -0,0 +1,26 @@ +# Markdown with Code Blocks + + + + + + +## Fenced Code Blocks + +``` +{ + "firstName": "John", + "lastName": "Smith", + "age": 25 +} +``` + +## Fenced Code Block with caption + +```pseudocode +procedure startSwinging(swing, child) + while child.isComfortable() + swing.giveGentlePush() + waitForNextIteration() + end while +end procedure \ No newline at end of file diff --git a/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/expected/index.rst b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/expected/index.rst new file mode 100644 index 000000000..326d93cd6 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/expected/index.rst @@ -0,0 +1,5 @@ +====================== +Markdown with emphasis +====================== + +*Italic* or *Italic* **Bold** or **Bold** diff --git a/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/guides.xml b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/index.md b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/index.md new file mode 100644 index 000000000..fc8f1bd97 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/emphasis-md-to-rst/input/index.md @@ -0,0 +1,4 @@ +# Markdown with emphasis + +*Italic* or _Italic_ +**Bold** or __Bold__ diff --git a/tests/Integration/tests-full/md-to-rst/index-md-to-rst/expected/index.rst b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/expected/index.rst new file mode 100644 index 000000000..15f9e2805 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/expected/index.rst @@ -0,0 +1,12 @@ +================ +Markdown Example +================ + +This is a Markdown document with some basic formatting. + +Headings +======== + +You can create headings using hash symbols. + +This text is part of a paragraph under the "Headings" heading. diff --git a/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/guides.xml b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/index.md b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/index.md new file mode 100644 index 000000000..184118784 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/index-md-to-rst/input/index.md @@ -0,0 +1,9 @@ +# Markdown Example + +This is a Markdown document with some basic formatting. + +## Headings + +You can create headings using hash symbols. + +This text is part of a paragraph under the "Headings" heading. diff --git a/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/expected/index.rst b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/expected/index.rst new file mode 100644 index 000000000..b852a2213 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/expected/index.rst @@ -0,0 +1,7 @@ +========================= +Markdown with inline Code +========================= + +Lorem Ipsum Dolor: `$dolor`... + +``Use `code` in your Markdown file.`` diff --git a/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/guides.xml b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/index.md b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/index.md new file mode 100644 index 000000000..ee105de49 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/inline-code-md-to-rst/input/index.md @@ -0,0 +1,5 @@ +# Markdown with inline Code + +Lorem Ipsum Dolor: `$dolor`... + +``Use `code` in your Markdown file.`` diff --git a/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/expected/index.rst b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/expected/index.rst new file mode 100644 index 000000000..12d11e25b --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/expected/index.rst @@ -0,0 +1,53 @@ +========================================= +TYPO3 Extension powermail - Documentation +========================================= + +This documentation helps + +* Administrators to install and configure powermail + +* Editors to use powermail + +* Developers to extend powermail + +Example Screenshots +=================== + +Frontend: Show a form with different field types +------------------------------------------------ + +.. figure:: Images/frontend1.png + :alt: Example form + +Example Form with Input, Textarea, Select, Multiselect, Checkboxes, Radiobuttons, and Submit + +Frontend: Multistep Form +------------------------ + +.. figure:: Images/frontend2.png + :alt: Example form2 + +Example Multistep Form with clientside validation + +Backend: Mail Listing +--------------------- + +.. figure:: Images/backend1.png + :alt: backend1 + +Manage the delivered mails with a fulltext search and some export possibilities + +Backend: Reporting +------------------ + +.. figure:: Images/backend2.png + :alt: backend2 + +See the reporting about the delivered mails (Form or Marketing Data Analyses are possible) + +Documentation overview +====================== + +* `Introduction `__ + +* `Documentation for editors `__ diff --git a/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/guides.xml b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/guides.xml new file mode 100644 index 000000000..a4d11241d --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/guides.xml @@ -0,0 +1,11 @@ + + + + + rst + diff --git a/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/index.md b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/index.md new file mode 100644 index 000000000..bf4885420 --- /dev/null +++ b/tests/Integration/tests-full/md-to-rst/md-to-rst-list-link/input/index.md @@ -0,0 +1,41 @@ +# TYPO3 Extension powermail - Documentation + +This documentation helps +* Administrators to install and configure powermail +* Editors to use powermail +* Developers to extend powermail + +## Example Screenshots + + +### Frontend: Show a form with different field types + +![Example form](Images/frontend1.png "Example Form") + +Example Form with Input, Textarea, Select, Multiselect, Checkboxes, Radiobuttons, and Submit + + +### Frontend: Multistep Form + +![Example form2](Images/frontend2.png "Example Form with validation") + +Example Multistep Form with clientside validation + +### Backend: Mail Listing + +![backend1](Images/backend1.png) + +Manage the delivered mails with a fulltext search and some export possibilities + + +### Backend: Reporting + +![backend2](Images/backend2.png) + +See the reporting about the delivered mails (Form or Marketing Data Analyses are possible) + + +## Documentation overview + +* [Introduction](https://github.com/in2code-de/powermail/blob/develop/Documentation/Readme.md) +* [Documentation for editors](https://github.com/in2code-de/powermail/blob/develop/Documentation/ForEditors/Readme.md)