diff --git a/docker/Dockerfile b/docker/Dockerfile index 39208fb..36fcf8c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -33,7 +33,8 @@ RUN \ && /opt/build/venv/bin/python -m pip install -r requirements.txt COPY ./docs ./docs -RUN /opt/build/venv/bin/sphinx-build -M html ./docs build +COPY ./textoutpc ./textoutpc +RUN /opt/build/venv/bin/sphinx-build -M html ./docs ./build COPY ./textoutpc ./textoutpc @@ -52,7 +53,7 @@ COPY --chmod=644 ./docker/nginx.conf /etc/nginx/nginx.conf WORKDIR /opt/app COPY --from=venv /opt/app/venv ./venv COPY --from=builder --chown=app:app /opt/build/textoutpc ./textoutpc -COPY --from=builder /opt/build/docs/_build/html /opt/app/docs +COPY --from=builder /opt/build/build/html /opt/app/docs EXPOSE 80 ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/docs/Makefile b/docs/Makefile index c344aee..40c2a08 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= poetry run sphinx-build -SPHINXAUTOOPTS ?= --ignore "*.kate-swp" --watch ../teal +SPHINXAUTOOPTS ?= --ignore "*.kate-swp" --watch ../textoutpc SPHINXAUTOBUILD ?= poetry run sphinx-autobuild SOURCEDIR = . BUILDDIR = _build diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 0000000..eaff78c --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,12 @@ +h1 img { + vertical-align: top; + width: 1.2em; +} + +.sidebar-logo { + width: 80%; +} + +.mermaid { + text-align: center; +} diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico new file mode 100644 index 0000000..af79c77 Binary files /dev/null and b/docs/_static/favicon.ico differ diff --git a/docs/_static/favicon.png b/docs/_static/favicon.png new file mode 100644 index 0000000..e5d438a Binary files /dev/null and b/docs/_static/favicon.png differ diff --git a/docs/_static/logo.svg b/docs/_static/logo.svg new file mode 100644 index 0000000..16ec1ef --- /dev/null +++ b/docs/_static/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/code.rst b/docs/code.rst new file mode 100644 index 0000000..5b6a1c4 --- /dev/null +++ b/docs/code.rst @@ -0,0 +1,9 @@ +Code reference +============== + +This section presents the code reference, by Python module. + +.. toctree:: + :maxdepth: 1 + + code/textoutpc diff --git a/docs/code/textoutpc.rst b/docs/code/textoutpc.rst new file mode 100644 index 0000000..e200e6d --- /dev/null +++ b/docs/code/textoutpc.rst @@ -0,0 +1,16 @@ +``textoutpc`` -- main namespace for the project +=============================================== + +This section presents the code reference under the ``textoutpc`` namespace. + +.. toctree:: + :maxdepth: 1 + + textoutpc/builtin + textoutpc/demo + textoutpc/exceptions + textoutpc/html + textoutpc/lexer + textoutpc/nodes + textoutpc/parser + textoutpc/tags diff --git a/docs/code/textoutpc/builtin.rst b/docs/code/textoutpc/builtin.rst new file mode 100644 index 0000000..dc35cfc --- /dev/null +++ b/docs/code/textoutpc/builtin.rst @@ -0,0 +1,4 @@ +``textoutpc.builtin`` -- built-in tags for textoutpc +==================================================== + +.. automodule:: textoutpc.builtin diff --git a/docs/code/textoutpc/demo.rst b/docs/code/textoutpc/demo.rst new file mode 100644 index 0000000..eaa5f29 --- /dev/null +++ b/docs/code/textoutpc/demo.rst @@ -0,0 +1,4 @@ +``textoutpc.demo`` -- demonstration web app for textoutpc +========================================================= + +.. automodule:: textoutpc.demo diff --git a/docs/code/textoutpc/exceptions.rst b/docs/code/textoutpc/exceptions.rst new file mode 100644 index 0000000..3770990 --- /dev/null +++ b/docs/code/textoutpc/exceptions.rst @@ -0,0 +1,4 @@ +``textoutpc.exceptions`` -- exceptions for textoutpc +==================================================== + +.. automodule:: textoutpc.exceptions diff --git a/docs/code/textoutpc/html.rst b/docs/code/textoutpc/html.rst new file mode 100644 index 0000000..0cc65c3 --- /dev/null +++ b/docs/code/textoutpc/html.rst @@ -0,0 +1,4 @@ +``textoutpc.html`` -- HTML writer for textoutpc +=============================================== + +.. automodule:: textoutpc.html diff --git a/docs/code/textoutpc/lexer.rst b/docs/code/textoutpc/lexer.rst new file mode 100644 index 0000000..21e3d71 --- /dev/null +++ b/docs/code/textoutpc/lexer.rst @@ -0,0 +1,4 @@ +``textoutpc.lexer`` -- lexer for textoutpc +========================================== + +.. automodule:: textoutpc.lexer diff --git a/docs/code/textoutpc/nodes.rst b/docs/code/textoutpc/nodes.rst new file mode 100644 index 0000000..815b762 --- /dev/null +++ b/docs/code/textoutpc/nodes.rst @@ -0,0 +1,4 @@ +``textoutpc.nodes`` -- docutils nodes specific to textoutpc +=========================================================== + +.. automodule:: textoutpc.nodes diff --git a/docs/code/textoutpc/parser.rst b/docs/code/textoutpc/parser.rst new file mode 100644 index 0000000..e186097 --- /dev/null +++ b/docs/code/textoutpc/parser.rst @@ -0,0 +1,4 @@ +``textoutpc.parser`` -- docutils parser for textoutpc +===================================================== + +.. automodule:: textoutpc.parser diff --git a/docs/code/textoutpc/tags.rst b/docs/code/textoutpc/tags.rst new file mode 100644 index 0000000..43b6868 --- /dev/null +++ b/docs/code/textoutpc/tags.rst @@ -0,0 +1,4 @@ +``textoutpc.tags`` -- tag definitions for textoutpc +=================================================== + +.. automodule:: textoutpc.tags diff --git a/docs/conf.py b/docs/conf.py index 74c3721..3e92d9f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -37,6 +37,8 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] html_theme = "furo" html_static_path = ["_static"] html_title = f"textoutpc {version}" +html_favicon = "_static/favicon.png" +html_logo = "_static/logo.svg" html_use_index = False html_copy_source = False html_show_sourcelink = False @@ -45,9 +47,7 @@ html_css_files = ["custom.css"] intersphinx_mapping = { "python": ("https://docs.python.org/3", None), - "fastapi": ("https://fastapi.tiangolo.com/", None), - "pydantic": ("https://docs.pydantic.dev/2.4/", None), - "sqlalchemy": ("https://docs.sqlalchemy.org/en/20/", None), + "docutils": ("https://sphinx-docutils.readthedocs.io/en/latest/", None), } todo_include_todos = True diff --git a/docs/guides.rst b/docs/guides.rst new file mode 100644 index 0000000..ed72aed --- /dev/null +++ b/docs/guides.rst @@ -0,0 +1,5 @@ +Guides +====== + +This section contains the guides, i.e. concrete steps to accomplish given +tasks with textoutpc. diff --git a/docs/index.rst b/docs/index.rst index 8e1c9c6..74fe6ab 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,31 +1,21 @@ -Welcome to textoutpc's documentation! -===================================== +textoutpc |version| +=================== -textoutpc is a BBcode markup language translator project for `Planète Casio`_. +This project is a set of docutils_ utilities for parsing and rendering the +`Planète Casio`_ flavour of BBCode. -BBcode has been invented in the 90s/2000s for bulletin board systems. -It has been implemented in `Planète Casio`_ during its first years (although -some research has to be made on how that choice was done…). +.. note:: -On `Planète Casio`_, which is coded in PHP at the time I'm writing this, -we have our own custom version of BBcode, which we pass through an internal -utility named ``textout()``. - -I, Thomas “Cakeisalie5” Touhey, rewrote it recently, and it works pretty well -while being secure, but as the next version of `Planète Casio`_ (the ”v5”) -will be written from scratch, I figured out I could rewrite the ``textout()`` -utility in Python, and improve the language parsing to be more practical and -add features that are in the original BBcode markup language. - -As this is a rewrite, the vulnerabilities and bug will not be common to this -project and the online version of the transcoder. + The flavour is named "textout", because that is the name of the original + function in the PHP code of the website. .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 2 - language - usage - tags + guides + language + code +.. _docutils: https://www.docutils.org/ +.. _BBCode: https://en.wikipedia.org/wiki/BBCode .. _Planète Casio: https://www.planet-casio.com/Fr/ diff --git a/docs/language.rst b/docs/language.rst index 48e2cf8..fe8058a 100644 --- a/docs/language.rst +++ b/docs/language.rst @@ -1,5 +1,5 @@ -The textout BBcode markup language -================================== +Markup language reference +========================= The BBcode markup language mainly uses tags, which the starting mark looks like ``[xxx]`` and the ending mark looks like ``[/xxx]``. You can add an @@ -10,287 +10,8 @@ It cannot be used with all tags, so when it is used in the examples below, suppose you can use it, otherwise, it might not be possible (or not implemented yet). --------------- -Align the text --------------- +.. toctree:: -To align the text, you can use either ``[]`` or -``[align=]`` with any of the following modes: - -- ``left``: the text is left-aligned; -- ``right``: the text is right-aligned; -- ``center``: the text is aligned at the horizontal middle of the document; -- ``justify``: the text is justified, i.e. the text spaces are optimized for - the right'n'word to end at the right of the line. - -For example, to right-align some text, you could do something like this: - -.. code:: - - [right]some text[/] - ----------------- -Inserting titles ----------------- - -Do you want to include titles or subtitles to your message, integrated with -the website's design? Use the ``[title]`` and ``[subtitle]`` tags for that: - -.. code:: - - [title]Just do it![/] - [subtitle]Don't let your dreams be dreams![/] - -Notice that this tag cannot embed another tag. - ----------------- -Styling the text ----------------- - -You can add some basic text style by using the following tags: - -- ``[b]`` for **bold** text; -- ``[i]`` for *italic* text; -- ``[u]`` for underlined text; -- ``[o]`` for overlined text; -- ``[s]`` or ``[strike]`` for striked text. - -They can all be ended with the generic ending mark ``[/]``. - ----------------------- -Changing the text font ----------------------- - -You can change the font of the text by using the ``[font=xxx]`` (or ``[xxx]`` -directly, where ``xxx`` represents the font identifier) tag. The following -fonts are available: - -- ``arial`` represents Arial; -- ``comic`` represents Comic MS; -- ``tahoma`` represents Tahoma; -- ``courier`` represents Courier; -- ``haettenschweiler`` represents Haettenschweiler; -- ``mono`` and ``monospace`` represents the basic monospace font. - -They can be ended with the generic ending mark ``[/]`` as well. - ------------------------ -Changing the text color ------------------------ - -You can change the color of the text using the ``[color=xxx]`` (or ``[xxx]`` -directly for simple colors, where ``xxx`` represents the color) tag. This -tag accepts several types of values: - -- simple color names (`inspired from CSS `_) such as - ``red``, ``blue``, ``green``, ``transparent``; -- color hex codes using a hash (``#``) followed by hex digits, e.g. - ``#01020F``, where the first group of hex digits represents the - red component from 0 to 255, the second group of hex digits represents - the green component from 0 to 255, and the third group of hex digits - represents the blue component from 0 to 255. - Incomplete composites will be filled by zero on the left (e.g. ``#0000F`` - is equivalent to ``#00000F``), invalid characters such as ``A`` will be - replaced by 0s; -- three hex digits codes using ``#`` followed by three hex digits, e.g. - ``#123`` which will be translated to ``#112233``; -- ``rgb(, , )``, where the red, green and blue components - are represented using decimal digits and are between 0 and 255 included; -- ``rgba(, , , )``, where the red, green and blue - components are expressed as said before and the alpha component is either - expressed as a percentage (e.g. ``12.34%``) or as a proportion between - ``0.0`` and ``1.0``; -- ``hsl(, , )`` or - ``hls(, ,)``; -- ``hsl(, , , )`` or - ``hls(, , , )``; -- ``hwb(, , )``. - -Here are some examples: - -.. code:: - - [blue]I'm blue![/] - [color=#ff69b4]That color is called “Cuisse de Nymphe émue”![/] - [color=rgb(255, 255,255,0.4)]I'm black![/] - [color=hsl(0,100%, 0.5)]I'm red![/] - --------------------- -Inserting hyperlinks --------------------- - -Creating hyperlinks on a bunch of text is possible through the ``[url]`` tag. -The URL has to be either absolute, relative, or related to an anchor. It has -to be passed to the tag either through the argument (which allows the content -to be the displayed title of the link) or through the content if there is -no argument. By default, if there is no content and an argument, the argument -will be taken as the link title. - -Here are examples: - -.. code:: - - [url]https://planet-casio.com[/] - [url=https://planet-casio.com]Planète Casio[/] - [url=/relative/url.html][/] - -For links to profiles, the ``[profil]`` and ``[profile]`` tags can be used. -They take no attribute but take a content which is the user whose the profile -is to be linked's name. For example: - -.. code:: - - [profil]Cakeisalie5[/] - -For links to topics and tutorials, the ``[topic]`` and ``[tutorial]`` -tags can be used. They take no attribute but take a content which is the -identifier of the topic or tutorial to which to link to. -For example: - -.. code:: - - [topic]234[/] - [tutorial]32[/] - -For links to programs, the ``[program]`` and ``[prog]`` tags can be used. -They take no attribute but take a content which is the identifier of the -program to which to link to. For example: - -.. code:: - - [program]3598[/program] - ---------------- -Quoting someone ---------------- - -To quote someone visually, you can use the ``[quote]`` tag, which takes the -name of the person you're quoting as the attribute and the quote as the -content. A quote can contain another one, of course. If there is no name, -the display will just be generalistic. - -Here are examples: - -.. code:: - - [quote]Someone said that.[/] - [quote=Cakeisalie5]Ever realized that my name contained “Cake”?[/] - -------------------------- -Spoilers/Content Warnings -------------------------- - -To hide something behind a deliberate action of your user, usually to avoid -hurting people or to hide the solution to a problem, you can use the -``[spoiler]`` tag. - -.. code:: - - [spoiler]This is hidden![/] - [spoiler=Uncover the dark secrets of the night]Boo![/] - [spoiler=Uncover this!|Cover this quick!!]BOOO![/] - ---------------- -Presenting code ---------------- - -There are two code tags: - -- ``[code]``, which is supposed to be used as a block for multiline code or - to isolate the code from the text; -- ``[inlinecode]`` or the *backquotes* to include code in the text. - -For example: - -.. code:: - - [code]Some multiline code, with [center]tags shown as they are[/center]. - Incredible, heh?[/code] - [inlinecode]Some inline code.[/inlinecode] - `Some more inline code.` - ------------------- -Inserting an image ------------------- - -In order to insert an image, you will have to use the ``[img]`` tag. It will -make a new paragraph containing the image which the URL is given in the -tag content. The tag can be bundled with some attributes, separated with -the pipe (``|``) character: - -- ``x``: set the dimensions to the image. If the width isn't - given (i.e. if this attribute starts with ``x``), the height will be set - automatically. If the height isn't given (i.e. no ``x`` or nothing after - the ``x``), the width will be set automatically; -- ``left``, ``right``, ``center``: align the image accordingly; -- ``float``: make the image float, i.e. let the text be where the image isn't. - -For example: - -.. code:: - - [img=right|float|x24]https://example.org/image.jpg[/] - -is a right-aligned image, floating (which means text will be allowed on -the left of the image), and with a height of 24 pixels and an automatic -width. - -Planète Casio admins can use the ``[adimg]`` tag which is equivalent to the -``[img]`` tag but adds the special admin image folder prefix to the image -URLs, so this is possible: - -.. code:: - - [adimg]incredible.jpg[/] - ------------------ -Inserting a video ------------------ - -This BBcode translator has the ability to integrate videos from some online -platforms into your message, as a block. To do this, you can use the -``[video]`` and ``[video tiny]`` tags. For example: - -.. code:: - - [video]https://www.youtube.com/watch?v=yhXpV8hRKxQ[/] - [video tiny]https://www.youtube.com/watch?v=yhXpV8hRKxQ[/] - ------------------------- -Inserting a progress bar ------------------------- - -Do you want to present how your project is evolving using a simple graph, -the progress bar? This is possible using the ``[progress]`` tag, which takes -the percentage (between 0 and 100 included) of the advancement as its -attribute. For example: - -.. code:: - - [progress=50]Building a great wall…[/] - [progress=100][/] - ----------------------------- -Inserting labels and targets ----------------------------- - -Is your message in several parts and you only want to link one without using -an entire separate page for the section? This is the tag you might want -to use. To link to a point in your message: - -- first, define the label using the ``[label]`` tag, with the name of the - label as the attribute; -- then link to the label using the ``[target]`` tag. - -You are not obliged to terminate the ``[label]`` tag (the original version of -it didn't support the ``[label]`` tag termination, in fact). For example: - -.. code:: - - [label=sometag][subtitle]Some chapter[/subtitle] - - ... - - [target=sometag]Go back to the beginning of the chapter[/] - -.. _CSS named colors: https://drafts.csswg.org/css-color/#named-colors + language/document + language/style + language/multimedia diff --git a/docs/language/document.rst b/docs/language/document.rst new file mode 100644 index 0000000..f10b173 --- /dev/null +++ b/docs/language/document.rst @@ -0,0 +1,84 @@ +Document structure +================== + +These tags can be used to represent the document structure. + +.. _markup-title: + +Titles and subtitles +-------------------- + +In order to represent titles and subtitles integrated with the website's +design, the ``[title]`` and ``[subtitles]`` tags can be used:: + + [title]Just do it![/] + [subtitle]Don't let your dreams be dreams![/] + +.. note:: + + These tags cannot embed other tags. + +.. _markup-label: + +Labels and targets +------------------ + +Internal references can be defined using labels and targets: + +* Labels place an anchor on a part of the message. They are defined using + the ``[label=]`` tag. +* Targets make a link to a label in another part of the message. They are + defined using the ``[target=]`` tag. + +.. note:: + + The ``[label]`` tag does not need to be terminated; in fact, the original + version of the tag did not support termination. + +An example usage of these tags is the following:: + + [label=sometag][subtitle]Some chapter[/subtitle] + + ... + + [target=sometag]Go back to the beginning of the chapter[/] + +.. _markup-url: + +Hyperlinks +---------- + +Hyperlinks, i.e. reference to other documents available on the World Wide Web, +can be inserted using the ``[url]`` tag. The URL can be provided: + +* As the tag value, e.g. ``[url=https://example.org/]My name[/url]``. + This is mostly useful in order to place a label. +* As the tag contents, e.g. ``[url]https://example.org/[/url]``. + +The URL itself can be either absolute, relative, or related to an anchor. + +Example uses are the following:: + + [url]https://planet-casio.com[/] + [url=https://planet-casio.com]Planète Casio[/] + [url=/relative/url.html][/] + +For links to profiles, the ``[profil]`` and ``[profile]`` tags can be used. +They take no attribute but take a content which is the user whose the profile +is to be linked's name. For example:: + + [profil]Cakeisalie5[/] + +For links to topics and tutorials, the ``[topic]`` and ``[tutorial]`` +tags can be used. They take no attribute but take a content which is the +identifier of the topic or tutorial to which to link to. +For example:: + + [topic]234[/] + [tutorial]32[/] + +For links to programs, the ``[program]`` and ``[prog]`` tags can be used. +They take no attribute but take a content which is the identifier of the +program to which to link to. For example:: + + [program]3598[/program] diff --git a/docs/language/multimedia.rst b/docs/language/multimedia.rst new file mode 100644 index 0000000..f79cf10 --- /dev/null +++ b/docs/language/multimedia.rst @@ -0,0 +1,103 @@ +Multimedia elements +=================== + +The following tags can be used to add complex elements. + +.. _markup-quote: + +Quotes +------ + +To quote someone visually, one can use the ``[quote]`` tag. +This tag takes an optional value being the person or entity being quoted. + +Some examples are:: + + [quote]Someone said that.[/] + [quote=Cakeisalie5]Ever realized that my name contained “Cake”?[/] + +.. _markup-code: + +Code blocks or spans +-------------------- + +There are two tags suitable for presenting code: + +``[code]`` + Block to present multiline code or isolate the code from the text. + +``[inlinecode]`` *(or backquotes)* + Inline code markup. + +Example uses are:: + + [code]Some multiline code, with [center]tags shown as they are[/center]. + Incredible, heh?[/code] + [inlinecode]Some inline code.[/inlinecode] + `Some more inline code.` + +.. _markup-image: + +Images +------ + +In order to insert an image, the ``[img]`` tag can be used. +It will make a new paragraph containing the image which the URL is given in the +tag content. The tag can be bundled with some attributes, separated with +the pipe (``|``) character: + +* ``x``: set the dimensions to the image. If the width isn't + given (i.e. if this attribute starts with ``x``), the height will be set + automatically. If the height isn't given (i.e. no ``x`` or nothing after + the ``x``), the width will be set automatically; +* ``left``, ``right``, ``center``: align the image accordingly; +* ``float``: make the image float, i.e. let the text be where the image isn't. + +The following example is a right-aligned image, floating (which means text +will be allowed on the left of the image), and with a height of 24 pixels and +an automatic width:: + + [img=right|float|x24]https://example.org/image.jpg[/] + +Planète Casio administrators can use the ``[adimg]`` tag which is equivalent to +the ``[img]`` tag but adds the special admin image folder prefix to the image +URLs, so this is possible:: + + [adimg]incredible.jpg[/] + +Videos +------ + +Videos can be inserted as blocks using the ``[video]`` or ``[video tiny]`` +tag. For example:: + + [video]https://www.youtube.com/watch?v=yhXpV8hRKxQ[/] + [video tiny]https://www.youtube.com/watch?v=yhXpV8hRKxQ[/] + +.. _markup-progress-bar: + +Progress bars +------------- + +In order to insert a progress bar, the ``[progress]`` tag can be used. +This tag takes an integer value between 0 and 100 included representing +the advancement. + +For example:: + + [progress=50]Building a great wall…[/] + [progress=100][/] + +.. _markup-spoiler: + +Spoilers / Content Warnings +--------------------------- + +In order to hide something behind a deliberate action of the user, +the ``[spoiler]`` tag can be used. + +For example:: + + [spoiler]This is hidden![/] + [spoiler=Uncover the dark secrets of the night]Boo![/] + [spoiler=Uncover this!|Cover this quick!!]BOOO![/] diff --git a/docs/language/style.rst b/docs/language/style.rst new file mode 100644 index 0000000..fd5364f --- /dev/null +++ b/docs/language/style.rst @@ -0,0 +1,145 @@ +Text styling +============ + +The following tags can be used to style the textual content of the messages. + +.. _markup-align: + +Alignment +--------- + +In order to align text, one can either use ``[]`` or +``[align=]`` with any of the following modes: + +``left`` + The text is left-aligned. + +``right`` + The text is right-aligned. + +``center`` + The text is aligned at the horizontal middle of the document; + +``justify`` + The text is justified, i.e. the text spaces are optimized for + the right'n'word to end at the right of the line. + +For example, to right-align some text, one can do the following:: + + [right]some text[/] + [align=right]some more text[/] + +.. _markup-strong: + +Font weight +----------- + +In order to have text with more weight, the ``[b]`` tag can be used. +For example:: + + [b]Some bold text[/] + +.. _markup-italic: + +Font style +---------- + +In order to set the font as italic, the ``[i]`` tag can be used. +For example:: + + [i]Some italic text[/] + +.. _markup-decoration: + +Font decoration +--------------- + +The following decorations can be applied to text using the following tags: + +``[u]`` + The text will be underlined. + +``[o]`` + The text will be overlined. + +``[s]`` or ``[strike]`` + The text will have a line through. + +For example:: + + [u]This text is underlined.[/] + [o]This text is overlined.[/] + [s]This text is striked through.[/] + +.. _markup-font: + +Text font +--------- + +The text font can be set using the ``[font=xxx]`` (or ``[xxx]`` +directly, where ``xxx`` represents the font identifier) tag. +The following fonts are available: + +``arial`` + Arial. + +``comic`` + Comic MS. + +``tahoma`` + Tahoma. + +``courier`` + Courier. + +``haettenschweiler`` + Haettenschweiler. + +``mono`` or ``monospace`` + Monospace. + +For example:: + + [comic]This text is in comic font![/] + +.. _markup-color: + +Text color +---------- + +The color of the text can be set using the ``[color=xxx]`` (or ``[xxx]`` +directly for simple colors, where ``xxx`` represents the color) tag. This +tag accepts several types of values: + +- Simple color names (`inspired from CSS `_) such as + ``red``, ``blue``, ``green``, ``transparent``; +- Color hex codes using a hash (``#``) followed by hex digits, e.g. + ``#01020F``, where the first group of hex digits represents the + red component from 0 to 255, the second group of hex digits represents + the green component from 0 to 255, and the third group of hex digits + represents the blue component from 0 to 255. + Incomplete composites will be filled by zero on the left (e.g. ``#0000F`` + is equivalent to ``#00000F``), invalid characters such as ``A`` will be + replaced by 0s; +- Three hex digits codes using ``#`` followed by three hex digits, e.g. + ``#123`` which will be translated to ``#112233``; +- ``rgb(, , )``, where the red, green and blue components + are represented using decimal digits and are between 0 and 255 included; +- ``rgba(, , , )``, where the red, green and blue + components are expressed as said before and the alpha component is either + expressed as a percentage (e.g. ``12.34%``) or as a proportion between + ``0.0`` and ``1.0``; +- ``hsl(, , )`` or + ``hls(, ,)``; +- ``hsl(, , , )`` or + ``hls(, , , )``; +- ``hwb(, , )``. + +Some examples are:: + + [blue]I'm blue![/] + [color=#ff69b4]That color is called “Cuisse de Nymphe émue”![/] + [color=rgb(255, 255,255,0.4)]I'm black![/] + [color=hsl(0,100%, 0.5)]I'm red![/] + +.. _CSS named colors: https://drafts.csswg.org/css-color/#named-colors diff --git a/docs/tags.rst b/docs/tags.rst deleted file mode 100644 index 17a9d05..0000000 --- a/docs/tags.rst +++ /dev/null @@ -1,124 +0,0 @@ -Defining tags for textoutpc -=========================== - -A tag is a class defined in the ``textoutpc.Tags`` submodule and referenced -in the `_tags` array in ``textoutpc.Tags.__init__``. It usually takes a name -that starts with ``Textout`` and an uppercase character, and finishes by -``Tag``, and shall inherit one of the base classes defined in -``textoutpc.Tags.__base__`` depending on how the tag will be used: - -- ``TextoutInlineTag``: tag to be used inside a paragraph, - e.g. text formatting; -- ``TextoutBlockTag``: tag to be used at paragraph level, e.g. video. - -There are a few public members you can define as a tag: - -- ``aliases``: the array of names this tag can be accessed as. - Basic tags (the ones with brackets ``[]``) are defined as ``[]`` - (e.g. ``[hello]``) and special characters are defined with their symbol, - e.g. `````; -- ``raw``: the tag's content shall not be interpreted, which is generally - only useful when the content is preprocessed (see below). The default - is ``False`` if there is no preprocess method, and `True` otherwise; -- ``noinline``: for raw tags, forbid inline tags (declared outside of the - tag) within the tag (*only works with ``raw = True``*!); -- ``generic``: the tag can be ended using the generic tag ending mark ``[/]``. - It is defined as ``True`` by default for all tags; -- ``notempty``: ignore the tag when its content is empty. By default, this - value is `False`; -- ``superblock``: is a super-block (for blocks) which means it adds a block - level, and adds a paragraph tag implicitely; -- ``inlined``: if is a block, transforms automatically the surrounding block - into a superblock while it's there; -- ``procvalue``: process the value as normal text before passing it; -- ``not_within_itself``: make that if a tag is opened within itself (depth - included), the tag above and all tags below are closed first; -- ``only_in``: allow the tag to only be beneath certain tags; -- ``allowed_tags``: allowed tags right beneath the current one; -- ``no_text``: disable raw text within the tag; -- ``expect_child``: make that all content below (without depth) that isn't - within the specified tags is ignored. - -So for example, if I want to make the inline tag ``[hello]`` as an example, -with the alternate name ``[hai]``, I'd start off by writing: - -.. code-block:: python - - from textoutpc import InlineTag as _InlineTag - - class TextoutHelloTag(_InlineTag): - """ The [hello] tag, which does things. - Example uses: - - [hello]world[/hello] - [hai=something]world[/hai] """ - - aliases = ('[hello]', '[hai]') - - # ... - ---------------------- -Getting the arguments ---------------------- - -There are two methods the tag can define to get various parts of the user -input: - -- ``prepare(name, value)``: the tag has been called, but the content has not - yet been read — this method uses the name and the value to define the tag's - behaviour. By default, when prepared, the tag does nothing; -- ``preprocess(content)``: the content has been read and the tag wants to know - about it — this method uses the content to define the tag's behaviour. - By default, the tag prints its content while reading it (instead of - storing it for this method); -- ``default()``: the content is empty and the tag wants to know about it (this - method is only called when ``preprocess()`` is not defined). - -Both methods can raise an exception (whatever the exception is) if the tag -is called with invalid arguments; when this is the case, the tag is just -printed as is, e.g. in ``[color=;;]test[/color]``, the ``TextoutColorTag`` -will return an exception at preparation, and the tag will be printed as is. - -The ``prepare()`` and ``preprocess()`` method can be defined for given output -types (languages, e.g. ``html`` or ``lightscript``) by setting up -``_()``-like methods. The ``preprocess()`` methods can -also be defined dynamically by the ``prepare()`` methods, as their existence -is checked after the preparation. - -It is recommended to only use the ``preprocess()`` method when the tag is a -raw tag, and not to check if the content is empty or not, as the ``default()`` -method is here to test this. - -If the ``preprocess()`` method returns a modified content, this content will -be used instead of the original one (and will be escaped for output languages -such as HTML). - ------------------------ -Defining the tag output ------------------------ - -For each output type, there are three output methods the tag can define: - -- ``begin()``: output what comes before the content, e.g. ````; -- ``content()``: output what comes instead of content, e.g. ``hello``; -- ``end()``: output what comes after the content, e.g. ````. - -These methods are **not supposed** to modify any (not even internal) members -or methods, they are just supposed to output, although you can define -variables in ``begin()`` to be used in ``end()``. - -As for ``prepare()`` and ``preprocess()``, these output methods can be defined -for given output types by appending ``_`` to the name, e.g. -``begin_html()``. They can also be defined dynamically by the ``prepare()`` -and ``preprocess()`` methods. - -A ``content()`` method without a ``preprocess()`` means that the content of -the tag in the user input will be ignored. - -------------------------------------- -Defining internal members and methods -------------------------------------- - -For all members and methods specific to the tag objects (except the ones -presented previously), it is recommended to use an underscore before the -name of the member or method, e.g. ``self._bold``. diff --git a/docs/usage.rst b/docs/usage.rst deleted file mode 100644 index 6411351..0000000 --- a/docs/usage.rst +++ /dev/null @@ -1,56 +0,0 @@ -Using textoutpc -=============== - -To use this module, simply use the ``to()`` functions once imported: - -.. code-block:: python - - #!/usr/bin/env python3 - import textoutpc - - text = "Hello, [i]beautiful [b]world[/i]!" - print(textoutpc.tohtml(text)) - print("---") - print(textoutpc.tolightscript(text)) - -The supported output types are: - -- ``html``: `HTML`_ compatible output, requiring some additional style and - script; -- ``lightscript``: `Lightscript`_ Markdown-like language. See - `the Lightscript topic on Planète Casio `_ for - more information. - -The ``tohtml()`` and ``tolightscript()`` can take additional keywords that -tags can read so that they can adapt their behaviour. The name of the tweaks -are case-insensitive and non-alphanumeric characters are ignored: for example, -``label_prefix``, ``LABELPREFIX`` and ``__LaBeL___PRE_FIX__`` are all -equivalent. - -The following tweaks are read by the translator and built-in tags: - -- ``inline``: if ``True``, only use inline tags, not blocks (for inline - contexts such as instant messaging or one-line comments). -- ``label_prefix`` (HTML): prefix to be used by the ``[label]`` and - ``[target]`` tags, e.g. ``msg45529-``. Defaults to `""` for PCv42 - compatibility; -- ``obsolete_tags`` (HTML): use obsolete HTML tags for old browsers - (e.g. lynx) compatibility, e.g. ````, ````, ``
``, and - others. Defaults to ``True``. -- ``title_level`` (HTML): level at which to start for titles and subtitles, - e.g. 5 means ``h5`` for ``h5`` for titles and ``h6`` for subtitles. -- ``link_target`` (HTML): either ``self`` (default, load in the same - frame as it was clicked) or ``blank`` (load in an other window). - -An example call would be: - -.. code-block:: python - - #!/usr/bin/env python3 - import textoutpc - - print(textoutpc.tohtml("Hello, [i]beautiful[/i]!", obsolete__TAGS=False)) - -.. _HTML: https://www.w3.org/html/ -.. _Lightscript: https://git.planet-casio.com/lephe/lightscript -.. _Lightscript topic: https://planet-casio.com/Fr/forums/lecture_sujet.php?id=15022 diff --git a/poetry.lock b/poetry.lock index db08d13..b42c219 100644 --- a/poetry.lock +++ b/poetry.lock @@ -512,6 +512,21 @@ files = [ {file = "jsmin-3.0.1.tar.gz", hash = "sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc"}, ] +[[package]] +name = "livereload" +version = "2.6.3" +description = "Python LiveReload is an awesome tool for web developers" +optional = false +python-versions = "*" +files = [ + {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, + {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, +] + +[package.dependencies] +six = "*" +tornado = {version = "*", markers = "python_version > \"2.7\""} + [[package]] name = "markupsafe" version = "2.1.3" @@ -941,6 +956,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -998,6 +1024,25 @@ docs = ["sphinxcontrib-websupport"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] +[[package]] +name = "sphinx-autobuild" +version = "2021.3.14" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, + {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, +] + +[package.dependencies] +colorama = "*" +livereload = "*" +sphinx = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + [[package]] name = "sphinx-basic-ng" version = "1.0.0b2" @@ -1147,6 +1192,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + [[package]] name = "typing-extensions" version = "4.8.0" @@ -1240,4 +1305,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "f53e8a48b99a511dc9abb02f191abf24ee1617baae006fa8128bb25d2d6c8b73" +content-hash = "0529ac8bca1629d40f672d31f3c24764e58437ed80e3f092837769e18f0d86f7" diff --git a/pyproject.toml b/pyproject.toml index 5caf937..1ac9919 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ typing-extensions = "^4.8.0" pre-commit = "^3.3.3" pytest = "^7.4.3" pytest-cov = "^4.1.0" +sphinx-autobuild = "^2021.3.14" [tool.poetry.group.deployment.dependencies] gunicorn = "^21.2.0" @@ -99,6 +100,7 @@ rst-roles = [ "py:meth", "py:exc", "py:mod", + "ref", ] rst-directives = ["py:data", "doctest"] diff --git a/textoutpc/builtin.py b/textoutpc/builtin.py index f6c08a4..1e4c32d 100644 --- a/textoutpc/builtin.py +++ b/textoutpc/builtin.py @@ -17,13 +17,16 @@ from docutils.nodes import ( Node, Element, Text, + citation, container, emphasis, image, literal, reference, strong, + subtitle, target, + title, ) from thcolor.colors import Color from thcolor.errors import ColorExpressionSyntaxError @@ -59,6 +62,64 @@ FONT_NAMES: dict[str, str] = { } +class TitleTag(RawTag): + """Title tag. + + Example uses:: + + [title]Example title[/] + + See :ref:`markup-title` for more information. + """ + + __slots__ = () + + def validate(self) -> None: + """Validate the name and value for this tag. + + :raises TagValidationError: The name and value combination is invalid. + """ + if self.value is not None: + raise UnexpectedValue() + + def process(self, *, children: Sequence[Node]) -> Iterator[Node]: + """Process the tag with children to build document nodes. + + :param children: The children to process. + :return: The produced nodes. + """ + yield title("", children) + + +class SubtitleTag(RawTag): + """Subtitle tag. + + Example uses:: + + [subtitle]Example subtitle[/] + + See :ref:`markup-title` for more information. + """ + + __slots__ = () + + def validate(self) -> None: + """Validate the name and value for this tag. + + :raises TagValidationError: The name and value combination is invalid. + """ + if self.value is not None: + raise UnexpectedValue() + + def process(self, *, children: Sequence[Node]) -> Iterator[Node]: + """Process the tag with children to build document nodes. + + :param children: The children to process. + :return: The produced nodes. + """ + yield subtitle("", children) + + class TextTag(Tag): """Main tag for setting text formatting. @@ -76,10 +137,18 @@ class TextTag(Tag): [color=rgb(255, 255, 255, 0.4)]BLACKNESS[/color] [color=hsl(0, 100%, 0.5)]This will be red.[/color] - Also supports a hack used on Planète Casio for a while, which - is a CSS injection, e.g.: + Also supports a hack used on Planète Casio for a while, which + is a CSS injection, e.g.:: [color=brown; size: 16pt]Hello world![/color] + + See the following sections for more information: + + * :ref:`markup-strong` + * :ref:`markup-italic` + * :ref:`markup-decoration` + * :ref:`markup-font` + * :ref:`markup-color` """ __slots__ = ( @@ -333,17 +402,23 @@ class AlignTag(Tag): [align=center]This text is centered horizontally.[/align] [justify]This text is justified.[/justify] + + See :ref:`markup-align` for more information. """ __slots__ = ("kind",) - ALIGN_KEYS = { + ALIGN_KEYS: dict[str, Literal["center", "left", "right", "justify"]] = { "center": "center", "centre": "center", "left": "left", "right": "right", "justify": "justify", } + """Alignment keys recognized as tags or tag values.""" + + kind: Literal["center", "left", "right", "justify"] + """Kind of alignment.""" def validate(self) -> None: """Validate the name and value for this tag. @@ -390,6 +465,34 @@ class AlignTag(Tag): yield div +class QuoteTag(Tag): + """Tag for presenting a quote. + + Example uses:: + + [quote]Someone said that.[/] + [quote=Cakeisalie5]Ever realized that my name contained “Cake”?[/] + + See :ref:`markup-quote` for more information. + """ + + __slots__ = () + + def process(self, *, children: Sequence[Node]) -> Iterator[Node]: + """Process the tag with children to build document nodes. + + :param children: The children to process. + :return: The produced nodes. + """ + if self.value is not None: + children = [ + strong("", emphasis("", f"{self.value} a écrit :")), + *children, + ] + + yield citation("", *children) + + class CodeTag(RawTag): """Basic code tag, for displaying code. @@ -399,6 +502,8 @@ class CodeTag(RawTag): { printf("hello, world"); }[/code] + + See :ref:`markup-code` for more information. """ __slots__ = () @@ -425,6 +530,8 @@ class InlineCodeTag(RawTag): `some inline code` [inlinecode][b]The tags will be shown verbatim.[/b][/inlinecode] [inlinecode][inlinecode][i]This also[/inlinecode] works![/inlinecode] + + See :ref:`markup-code` for more information. """ __slots__ = () @@ -472,6 +579,8 @@ class ImageTag(RawTag): [img=12x24]picture_url[/img] [img=center|12x24]picture_url[/img] [img=x24|right]picture_url[/img] + + See :ref:`markup-image` for more information. """ __slots__ = ("width", "height", "alignment", "floating") @@ -610,6 +719,8 @@ class AdminImageTag(ImageTag): [adimg=12x24]some_picture.png[/img] [adimg=center|12x24]some_picture.png[/img] [adimg=x24|right]some_picture.png[/img] + + See :ref:`markup-image` for more information. """ __slots__ = () @@ -632,6 +743,8 @@ class LabelTag(Tag): [label=installation]Installation de tel logiciel... (no ending req.) [label=compilation][/label] Compilation de tel logiciel... + + See :ref:`markup-label` for more information. """ __slots__ = () @@ -660,6 +773,8 @@ class TargetTag(Tag): Example uses:: [target=installation]Check out the installation manual[/target]! + + See :ref:`markup-label` for more information. """ __slots__ = () @@ -694,6 +809,8 @@ class LinkTag(Tag): [url=https://example.org/hi]Go to example.org[/url]! [url=/Fr/index.php][/url] [url]https://random.org/randomize.php[/url] + + See :ref:`markup-url` for more information. """ __slots__ = ("url",) @@ -760,6 +877,8 @@ class ProfileTag(LinkTag): Example uses:: [profil]Cakeisalie5[/] + + See :ref:`markup-url` for more information. """ __slots__ = () @@ -798,6 +917,8 @@ class TopicTag(LinkTag): Example uses:: [topic]234[/] + + See :ref:`markup-url` for more information. """ __slots__ = () @@ -835,6 +956,8 @@ class TutorialTag(LinkTag): Example uses:: [tutorial]71[/] + + See :ref:`markup-url` for more information. """ __slots__ = () @@ -872,6 +995,8 @@ class ProgramTag(LinkTag): Example uses:: [program]3598[/] + + See :ref:`markup-url` for more information. """ __slots__ = () @@ -909,6 +1034,8 @@ class ProgressTag(Tag): [progress=50]My great progress bar[/progress] [progress=100][/progress] + + See :ref:`markup-progress-bar` for more information. """ __slots__ = ("progress_value",) @@ -1026,6 +1153,8 @@ class SpoilerTag(Tag): [spoiler=Y a quelque chose de caché !|Ah, bah en fait non :)]:E And it's multiline, [big]and formatted[/big], as usual :D[/spoiler] + + See :ref:`markup-spoiler` for more information. """ __slots__ = ("_closed_title", "_opened_title") diff --git a/textoutpc/demo/__init__.py b/textoutpc/demo/__init__.py index 4b05087..829c378 100644 --- a/textoutpc/demo/__init__.py +++ b/textoutpc/demo/__init__.py @@ -29,6 +29,7 @@ app = Flask( template_folder=STATIC_PATH / "templates", static_folder=STATIC_PATH / "static", ) +"""WSGI application for the textoutpc demonstration.""" assets = AssetsEnvironment(app) assets.register( diff --git a/textoutpc/parser.py b/textoutpc/parser.py index 4266b65..58c4d74 100644 --- a/textoutpc/parser.py +++ b/textoutpc/parser.py @@ -23,10 +23,13 @@ from .builtin import ( NoEvalTag, ProfileTag, ProgressTag, + QuoteTag, RotTag, SpoilerTag, + SubtitleTag, TargetTag, TextTag, + TitleTag, ) from .exceptions import TagValidationError from .lexer import ( @@ -43,7 +46,6 @@ from .tags import Tag BUILTIN_TAGS = { # TODO: Add the [calc] BBCode tag. - # TODO: Add the [quote] BBCode tag. # TODO: Add the [indent] BBCode tag. # TODO: Add the [list] and [li] BBCode tags. # TODO: Add the [table], [tr], [td] and [th] BBCode tags. @@ -79,6 +81,7 @@ BUILTIN_TAGS = { "[profile]": ProfileTag, "[progress]": ProgressTag, "[purple]": TextTag, + "[quote]": QuoteTag, "[red]": TextTag, "[rot]": RotTag, "[rot13]": RotTag, @@ -87,8 +90,10 @@ BUILTIN_TAGS = { "[small]": TextTag, "[spoiler]": SpoilerTag, "[strike]": TextTag, + "[subtitle]": SubtitleTag, "[tahoma]": TextTag, "[target]": TargetTag, + "[title]": TitleTag, "[u]": TextTag, "[url]": LinkTag, "[yellow]": TextTag,