LCOV - code coverage report
Current view: top level - tests - catch_convert_ansi.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.0 % 159 151
Test Date: 2025-07-04 17:06:38 Functions: 100.0 % 3 3
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2006-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/snaplogger
       4              : // contact@m2osw.com
       5              : //
       6              : // This program is free software; you can redistribute it and/or modify
       7              : // it under the terms of the GNU General Public License as published by
       8              : // the Free Software Foundation; either version 2 of the License, or
       9              : // (at your option) any later version.
      10              : //
      11              : // This program is distributed in the hope that it will be useful,
      12              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              : // GNU General Public License for more details.
      15              : //
      16              : // You should have received a copy of the GNU General Public License along
      17              : // with this program; if not, write to the Free Software Foundation, Inc.,
      18              : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19              : 
      20              : // self
      21              : //
      22              : #include    "catch_main.h"
      23              : 
      24              : 
      25              : // snaplogger
      26              : //
      27              : #include    <snaplogger/convert_ansi.h>
      28              : #include    <snaplogger/exception.h>
      29              : 
      30              : 
      31              : // snapdev
      32              : //
      33              : #include    <snapdev/string_replace_many.h>
      34              : 
      35              : 
      36              : // libutf8
      37              : //
      38              : #include    <libutf8/libutf8.h>
      39              : 
      40              : 
      41              : // C
      42              : //
      43              : //#include    <unistd.h>
      44              : 
      45              : 
      46              : 
      47              : namespace
      48              : {
      49              : 
      50              : 
      51              : 
      52              : struct convert_t
      53              : {
      54              :     char const *        f_input = nullptr;
      55              :     char const *        f_plain_text = nullptr;
      56              :     char const *        f_html = nullptr;
      57              :     char const *        f_optimized_html = nullptr;
      58              :     char const *        f_markdown = nullptr;
      59              :     char const *        f_styles = nullptr;
      60              :     char const *        f_styles_with_defaults = nullptr;
      61              : };
      62              : 
      63              : 
      64              : constexpr convert_t const g_convert_data[] =
      65              : {
      66              :     // plain text
      67              :     {
      68              :         .f_input = "plain",
      69              :         .f_plain_text = "plain",
      70              :         .f_html = "plain",
      71              :     },
      72              : 
      73              :     // normal
      74              :     {
      75              :         .f_input = "\033[0mnormal\033[m",
      76              :         .f_plain_text = "normal",
      77              :         .f_html = "normal",
      78              :     },
      79              : 
      80              :     // bold
      81              :     {
      82              :         .f_input = "\033[1mbold\033[m",
      83              :         .f_plain_text = "bold",
      84              :         .f_html = "<span class=\"ansi-b\">bold</span>",
      85              :         .f_optimized_html = "<b>bold</b>",
      86              :         .f_markdown = "*bold*",
      87              :         .f_styles = ".ansi-b{font-weight:bold}\n",
      88              :         .f_styles_with_defaults = "b,.ansi-b{font-weight:bold}\n",
      89              :     },
      90              : 
      91              :     // light
      92              :     {
      93              :         .f_input = "\033[2mlight\033[m",
      94              :         .f_plain_text = "light",
      95              :         .f_html = "<span class=\"ansi-l\">light</span>",
      96              :         .f_styles = ".ansi-l{font-weight:light}\n",
      97              :     },
      98              : 
      99              :     // italic
     100              :     {
     101              :         .f_input = "\033[3mitalic\033[m",
     102              :         .f_plain_text = "italic",
     103              :         .f_html = "<span class=\"ansi-i\">italic</span>",
     104              :         .f_optimized_html = "<i>italic</i>",
     105              :         .f_markdown = "**italic**",
     106              :         .f_styles = ".ansi-i{font-style:italic}\n",
     107              :         .f_styles_with_defaults = "i,.ansi-i{font-style:italic}\n",
     108              :     },
     109              : 
     110              :     // underline
     111              :     {
     112              :         .f_input = "\033[4munderline\033[m",
     113              :         .f_plain_text = "underline",
     114              :         .f_html = "<span class=\"ansi-u\">underline</span>",
     115              :         .f_optimized_html = "<u>underline</u>",
     116              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     117              :                     ".ansi-u{text-decoration-line:underline}\n"
     118              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     119              :                     ".ansi-v{text-decoration-line:overline;}\n"
     120              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     121              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     122              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     123              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     124              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     125              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     126              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     127              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     128              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     129              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     130              :                     ".ansi-v{text-decoration-line:overline;}\n"
     131              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     132              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     133              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     134              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     135              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     136              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     137              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     138              :     },
     139              : 
     140              :     // slow blink
     141              :     {
     142              :         .f_input = "\033[5mslow blink\033[m",
     143              :         .f_plain_text = "slow blink",
     144              :         .f_html = "<span class=\"ansi-sb\">slow blink</span>",
     145              :         .f_styles = "@keyframes ansi-blinker{50%{opacity:0}}\n.ansi-sb{animation:ansi-blinker 2s linear infinite}\n",
     146              :     },
     147              : 
     148              :     // fast blink
     149              :     {
     150              :         .f_input = "\033[6mfast blink\033[m",
     151              :         .f_plain_text = "fast blink",
     152              :         .f_html = "<span class=\"ansi-fb\">fast blink</span>",
     153              :         .f_styles = "@keyframes ansi-blinker{50%{opacity:0}}\n.ansi-fb{animation:ansi-blinker 0.4s linear infinite}\n",
     154              :     },
     155              : 
     156              :     // inverse
     157              :     {
     158              :         .f_input = "\033[7minverse\033[m",
     159              :         .f_plain_text = "inverse",
     160              :         .f_html = "<span style=\"color:#ffffff;background-color:#000000\">inverse</span>",
     161              :     },
     162              : 
     163              :     // conceal
     164              :     {
     165              :         .f_input = "\033[8mconceal this now\033[m",
     166              :         .f_plain_text = "",
     167              :         .f_html = "",
     168              :     },
     169              : 
     170              :     // cross out
     171              :     {
     172              :         .f_input = "\033[9mcross out\033[m",
     173              :         .f_plain_text = "cross out",
     174              :         .f_html = "<span class=\"ansi-s\">cross out</span>",
     175              :         .f_optimized_html = "<s>cross out</s>",
     176              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     177              :                     ".ansi-u{text-decoration-line:underline}\n"
     178              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     179              :                     ".ansi-v{text-decoration-line:overline;}\n"
     180              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     181              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     182              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     183              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     184              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     185              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     186              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     187              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     188              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     189              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     190              :                     ".ansi-v{text-decoration-line:overline;}\n"
     191              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     192              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     193              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     194              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     195              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     196              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     197              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     198              :     },
     199              : 
     200              :     // cross out + underline
     201              :     {
     202              :         .f_input = "\033[9;4mcross out + underline\033[m",
     203              :         .f_plain_text = "cross out + underline",
     204              :         .f_html = "<span class=\"ansi-us\">cross out + underline</span>",
     205              :         .f_optimized_html = "<u><s>cross out + underline</s></u>",
     206              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     207              :                     ".ansi-u{text-decoration-line:underline}\n"
     208              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     209              :                     ".ansi-v{text-decoration-line:overline;}\n"
     210              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     211              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     212              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     213              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     214              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     215              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     216              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     217              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     218              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     219              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     220              :                     ".ansi-v{text-decoration-line:overline;}\n"
     221              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     222              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     223              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     224              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     225              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     226              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     227              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     228              :     },
     229              : 
     230              :     // underline + cross out
     231              :     {
     232              :         .f_input = "\033[4;9munderline + cross out\033[m",
     233              :         .f_plain_text = "underline + cross out",
     234              :         .f_html = "<span class=\"ansi-us\">underline + cross out</span>",
     235              :         .f_optimized_html = "<u><s>underline + cross out</s></u>",
     236              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     237              :                     ".ansi-u{text-decoration-line:underline}\n"
     238              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     239              :                     ".ansi-v{text-decoration-line:overline;}\n"
     240              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     241              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     242              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     243              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     244              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     245              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     246              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     247              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     248              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     249              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     250              :                     ".ansi-v{text-decoration-line:overline;}\n"
     251              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     252              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     253              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     254              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     255              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     256              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     257              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     258              :     },
     259              : 
     260              :     // double underline
     261              :     {
     262              :         .f_input = "\033[21mdouble underline\033[m",
     263              :         .f_plain_text = "double underline",
     264              :         .f_html = "<span class=\"ansi-d\">double underline</span>",
     265              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     266              :                     ".ansi-u{text-decoration-line:underline}\n"
     267              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     268              :                     ".ansi-v{text-decoration-line:overline;}\n"
     269              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     270              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     271              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     272              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     273              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     274              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     275              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     276              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     277              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     278              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     279              :                     ".ansi-v{text-decoration-line:overline;}\n"
     280              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     281              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     282              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     283              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     284              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     285              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     286              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     287              :     },
     288              : 
     289              :     // cross out + double underline
     290              :     {
     291              :         .f_input = "\033[9;21mcross out + double underline\033[m",
     292              :         .f_plain_text = "cross out + double underline",
     293              :         .f_html = "<span class=\"ansi-ds\">cross out + double underline</span>",
     294              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     295              :                     ".ansi-u{text-decoration-line:underline}\n"
     296              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     297              :                     ".ansi-v{text-decoration-line:overline;}\n"
     298              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     299              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     300              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     301              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     302              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     303              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     304              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     305              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     306              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     307              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     308              :                     ".ansi-v{text-decoration-line:overline;}\n"
     309              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     310              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     311              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     312              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     313              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     314              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     315              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     316              :     },
     317              : 
     318              :     // double underline + cross out
     319              :     {
     320              :         .f_input = "\033[21;9mdouble underline + cross out\033[m",
     321              :         .f_plain_text = "double underline + cross out",
     322              :         .f_html = "<span class=\"ansi-ds\">double underline + cross out</span>",
     323              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     324              :                     ".ansi-u{text-decoration-line:underline}\n"
     325              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     326              :                     ".ansi-v{text-decoration-line:overline;}\n"
     327              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     328              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     329              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     330              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     331              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     332              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     333              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     334              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     335              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     336              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     337              :                     ".ansi-v{text-decoration-line:overline;}\n"
     338              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     339              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     340              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     341              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     342              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     343              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     344              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     345              :     },
     346              : 
     347              :     // bold + normal intensity
     348              :     {
     349              :         .f_input = "normal then \033[1mbold\033[22m and not\033[m",
     350              :         .f_plain_text = "normal then bold and not",
     351              :         .f_html = "normal then <span class=\"ansi-b\">bold </span>and not",
     352              :         .f_optimized_html = "normal then <b>bold </b>and not",
     353              :         .f_markdown = "normal then *bold* and not",
     354              :         .f_styles = ".ansi-b{font-weight:bold}\n",
     355              :         .f_styles_with_defaults = "b,.ansi-b{font-weight:bold}\n",
     356              :     },
     357              : 
     358              :     // light + normal intensity
     359              :     {
     360              :         .f_input = "normal then \033[2mlight\033[22m and not\033[m",
     361              :         .f_plain_text = "normal then light and not",
     362              :         .f_html = "normal then <span class=\"ansi-l\">light </span>and not",
     363              :         .f_styles = ".ansi-l{font-weight:light}\n",
     364              :     },
     365              : 
     366              :     // italic + normal intensity
     367              :     {
     368              :         .f_input = "normal then \033[3mitalic\033[23m and not\033[m",
     369              :         .f_plain_text = "normal then italic and not",
     370              :         .f_html = "normal then <span class=\"ansi-i\">italic </span>and not",
     371              :         .f_optimized_html = "normal then <i>italic </i>and not",
     372              :         .f_markdown = "normal then **italic** and not",
     373              :         .f_styles = ".ansi-i{font-style:italic}\n",
     374              :         .f_styles_with_defaults = "i,.ansi-i{font-style:italic}\n",
     375              :     },
     376              : 
     377              :     // underline + not-underline
     378              :     {
     379              :         .f_input = "normal then \033[4munderline\033[24m and not\033[m",
     380              :         .f_plain_text = "normal then underline and not",
     381              :         .f_html = "normal then <span class=\"ansi-u\">underline </span>and not",
     382              :         .f_optimized_html = "normal then <u>underline </u>and not",
     383              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     384              :                     ".ansi-u{text-decoration-line:underline}\n"
     385              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     386              :                     ".ansi-v{text-decoration-line:overline;}\n"
     387              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     388              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     389              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     390              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     391              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     392              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     393              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     394              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     395              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     396              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     397              :                     ".ansi-v{text-decoration-line:overline;}\n"
     398              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     399              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     400              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     401              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     402              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     403              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     404              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     405              :     },
     406              : 
     407              :     // double underline + not-underline
     408              :     {
     409              :         .f_input = "normal then \033[21mdouble underline\033[24m and not\033[m",
     410              :         .f_plain_text = "normal then double underline and not",
     411              :         .f_html = "normal then <span class=\"ansi-d\">double underline </span>and not",
     412              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     413              :                     ".ansi-u{text-decoration-line:underline}\n"
     414              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     415              :                     ".ansi-v{text-decoration-line:overline;}\n"
     416              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     417              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     418              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     419              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     420              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     421              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     422              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     423              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     424              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     425              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     426              :                     ".ansi-v{text-decoration-line:overline;}\n"
     427              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     428              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     429              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     430              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     431              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     432              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     433              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     434              :     },
     435              : 
     436              :     // slow blink + not blink
     437              :     {
     438              :         .f_input = "normal then \033[5mslow blink\033[25m and not\033[m",
     439              :         .f_plain_text = "normal then slow blink and not",
     440              :         .f_html = "normal then <span class=\"ansi-sb\">slow blink </span>and not",
     441              :         .f_styles = "@keyframes ansi-blinker{50%{opacity:0}}\n.ansi-sb{animation:ansi-blinker 2s linear infinite}\n",
     442              :     },
     443              : 
     444              :     // fast blink + not blink
     445              :     {
     446              :         .f_input = "normal then \033[6mfast blink\033[25m and not\033[m",
     447              :         .f_plain_text = "normal then fast blink and not",
     448              :         .f_html = "normal then <span class=\"ansi-fb\">fast blink </span>and not",
     449              :         .f_styles = "@keyframes ansi-blinker{50%{opacity:0}}\n.ansi-fb{animation:ansi-blinker 0.4s linear infinite}\n",
     450              :     },
     451              : 
     452              :     // proportional
     453              :     {
     454              :         .f_input = "normal then \033[26mproportional\033[50m and not\033[m",
     455              :         .f_plain_text = "normal then proportional and not",
     456              :         .f_html = "normal then <span class=\"ansi-p\">proportional </span>and not",
     457              :         .f_styles = ".ansi-p{font-family:sans-serif}\n",
     458              :     },
     459              : 
     460              :     // inverse + positive
     461              :     {
     462              :         .f_input = "normal then \033[7minverse\033[27m and not\033[m",
     463              :         .f_plain_text = "normal then inverse and not",
     464              :         .f_html = "normal then <span style=\"color:#ffffff;background-color:#000000\">inverse </span>and not",
     465              :     },
     466              : 
     467              :     // conceal + visible
     468              :     {
     469              :         .f_input = "normal then \033[8mconcealed\033[28m and not\033[m",
     470              :         .f_plain_text = "normal then  and not",
     471              :         .f_html = "normal then  and not",
     472              :     },
     473              : 
     474              :     // cross out + not cross out
     475              :     {
     476              :         .f_input = "normal then \033[9mcross out\033[29m and not\033[m",
     477              :         .f_plain_text = "normal then cross out and not",
     478              :         .f_html = "normal then <span class=\"ansi-s\">cross out </span>and not",
     479              :         .f_optimized_html = "normal then <s>cross out </s>and not",
     480              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     481              :                     ".ansi-u{text-decoration-line:underline}\n"
     482              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     483              :                     ".ansi-v{text-decoration-line:overline;}\n"
     484              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     485              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     486              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     487              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     488              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     489              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     490              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     491              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     492              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     493              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     494              :                     ".ansi-v{text-decoration-line:overline;}\n"
     495              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     496              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     497              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     498              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     499              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     500              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     501              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     502              :     },
     503              : 
     504              :     // foreground black color
     505              :     {
     506              :         .f_input = "foreground \033[30mblack\033[39m color\033[m",
     507              :         .f_plain_text = "foreground black color",
     508              :         .f_html = "foreground <span style=\"color:#000000;background-color:#ffffff\">black </span>color",
     509              :     },
     510              : 
     511              :     // foreground red color
     512              :     {
     513              :         .f_input = "foreground \033[31mred\033[39m color\033[m",
     514              :         .f_plain_text = "foreground red color",
     515              :         .f_html = "foreground <span style=\"color:#de382b;background-color:#ffffff\">red </span>color",
     516              :     },
     517              : 
     518              :     // foreground green color
     519              :     {
     520              :         .f_input = "foreground \033[32mgreen\033[39m color\033[m",
     521              :         .f_plain_text = "foreground green color",
     522              :         .f_html = "foreground <span style=\"color:#39b54a;background-color:#ffffff\">green </span>color",
     523              :     },
     524              : 
     525              :     // foreground yellow color
     526              :     {
     527              :         .f_input = "foreground \033[33myellow\033[39m color\033[m",
     528              :         .f_plain_text = "foreground yellow color",
     529              :         .f_html = "foreground <span style=\"color:#ffc706;background-color:#ffffff\">yellow </span>color",
     530              :     },
     531              : 
     532              :     // foreground blue color
     533              :     {
     534              :         .f_input = "foreground \033[34mblue\033[39m color\033[m",
     535              :         .f_plain_text = "foreground blue color",
     536              :         .f_html = "foreground <span style=\"color:#006fb8;background-color:#ffffff\">blue </span>color",
     537              :     },
     538              : 
     539              :     // foreground magenta color
     540              :     {
     541              :         .f_input = "foreground \033[35mmagenta\033[39m color\033[m",
     542              :         .f_plain_text = "foreground magenta color",
     543              :         .f_html = "foreground <span style=\"color:#762671;background-color:#ffffff\">magenta </span>color",
     544              :     },
     545              : 
     546              :     // foreground cyan color
     547              :     {
     548              :         .f_input = "foreground \033[36mcyan\033[39m color\033[m",
     549              :         .f_plain_text = "foreground cyan color",
     550              :         .f_html = "foreground <span style=\"color:#2cb5e9;background-color:#ffffff\">cyan </span>color",
     551              :     },
     552              : 
     553              :     // foreground white color
     554              :     {
     555              :         .f_input = "foreground \033[37mwhite\033[39m color\033[m",
     556              :         .f_plain_text = "foreground white color",
     557              :         .f_html = "foreground <span style=\"color:#cccccc;background-color:#ffffff\">white </span>color",
     558              :     },
     559              : 
     560              :     // foreground transparent
     561              :     {
     562              :         .f_input = "foreground \033[38;1mtransparent\033[39m color\033[m",
     563              :         .f_plain_text = "foreground transparent color",
     564              :         .f_html = "foreground <span style=\"opacity:0%;background-color:#ffffff\">transparent </span>color",
     565              :     },
     566              : 
     567              :     // foreground RGB color
     568              :     {
     569              :         .f_input = "foreground \033[38;2;32;64;96mRGB\033[39m color\033[m",
     570              :         .f_plain_text = "foreground RGB color",
     571              :         .f_html = "foreground <span style=\"color:#204060;background-color:#ffffff\">RGB </span>color",
     572              :     },
     573              : 
     574              :     // foreground CMY color
     575              :     {
     576              :         .f_input = "foreground \033[38;3;32;64;96mCMY\033[39m color\033[m",
     577              :         .f_plain_text = "foreground CMY color",
     578              :         .f_html = "foreground <span style=\"color:#dfbf9f;background-color:#ffffff\">CMY </span>color",
     579              :     },
     580              : 
     581              :     // foreground CMYK color
     582              :     {
     583              :         .f_input = "foreground \033[38;4;32;64;96;128mCMYK\033[39m color\033[m",
     584              :         .f_plain_text = "foreground CMYK color",
     585              :         .f_html = "foreground <span style=\"color:#6f5f4f;background-color:#ffffff\">CMYK </span>color",
     586              :     },
     587              : 
     588              :     // foreground index color 100
     589              :     {
     590              :         .f_input = "foreground \033[38;5;100mindex color 100\033[39m color\033[m",
     591              :         .f_plain_text = "foreground index color 100 color",
     592              :         .f_html = "foreground <span style=\"color:#878700;background-color:#ffffff\">index color 100 </span>color",
     593              :     },
     594              : 
     595              :     // inverse does not work on foreground transparent
     596              :     // (i.e. the background color is #ffffff when foreground is transparent)
     597              :     {
     598              :         .f_input = "foreground \033[7minverse here \033[38;1mthen transparent\033[39m then not\033[m",
     599              :         .f_plain_text = "foreground inverse here then transparent then not",
     600              :         .f_html = "foreground <span style=\"color:#ffffff;background-color:#000000\">inverse here </span><span style=\"opacity:0%;background-color:#ffffff\">then transparent </span><span style=\"color:#ffffff;background-color:#000000\">then not</span>",
     601              :     },
     602              : 
     603              :     // background black color
     604              :     {
     605              :         .f_input = "background \033[40mblack\033[49m color\033[m",
     606              :         .f_plain_text = "background black color",
     607              :         .f_html = "background <span style=\"color:#000000;background-color:#000000\">black </span>color",
     608              :     },
     609              : 
     610              :     // background red color
     611              :     {
     612              :         .f_input = "background \033[41mred\033[49m color\033[m",
     613              :         .f_plain_text = "background red color",
     614              :         .f_html = "background <span style=\"color:#000000;background-color:#de382b\">red </span>color",
     615              :     },
     616              : 
     617              :     // background green color
     618              :     {
     619              :         .f_input = "background \033[42mgreen\033[49m color\033[m",
     620              :         .f_plain_text = "background green color",
     621              :         .f_html = "background <span style=\"color:#000000;background-color:#39b54a\">green </span>color",
     622              :     },
     623              : 
     624              :     // background yellow color
     625              :     {
     626              :         .f_input = "background \033[43myellow\033[49m color\033[m",
     627              :         .f_plain_text = "background yellow color",
     628              :         .f_html = "background <span style=\"color:#000000;background-color:#ffc706\">yellow </span>color",
     629              :     },
     630              : 
     631              :     // background blue color
     632              :     {
     633              :         .f_input = "background \033[44mblue\033[49m color\033[m",
     634              :         .f_plain_text = "background blue color",
     635              :         .f_html = "background <span style=\"color:#000000;background-color:#006fb8\">blue </span>color",
     636              :     },
     637              : 
     638              :     // background magenta color
     639              :     {
     640              :         .f_input = "background \033[45mmagenta\033[49m color\033[m",
     641              :         .f_plain_text = "background magenta color",
     642              :         .f_html = "background <span style=\"color:#000000;background-color:#762671\">magenta </span>color",
     643              :     },
     644              : 
     645              :     // background cyan color
     646              :     {
     647              :         .f_input = "background \033[46mcyan\033[49m color\033[m",
     648              :         .f_plain_text = "background cyan color",
     649              :         .f_html = "background <span style=\"color:#000000;background-color:#2cb5e9\">cyan </span>color",
     650              :     },
     651              : 
     652              :     // background white color
     653              :     {
     654              :         .f_input = "background \033[47mwhite\033[49m color\033[m",
     655              :         .f_plain_text = "background white color",
     656              :         .f_html = "background <span style=\"color:#000000;background-color:#cccccc\">white </span>color",
     657              :     },
     658              : 
     659              :     // background RGB color
     660              :     {
     661              :         .f_input = "background \033[48;2;32;64;96mRGB\033[49m color\033[m",
     662              :         .f_plain_text = "background RGB color",
     663              :         .f_html = "background <span style=\"color:#000000;background-color:#204060\">RGB </span>color",
     664              :     },
     665              : 
     666              :     // background CMY color
     667              :     {
     668              :         .f_input = "background \033[48;3;32;64;96mCMY\033[49m color\033[m",
     669              :         .f_plain_text = "background CMY color",
     670              :         .f_html = "background <span style=\"color:#000000;background-color:#dfbf9f\">CMY </span>color",
     671              :     },
     672              : 
     673              :     // background CMYK color
     674              :     {
     675              :         .f_input = "background \033[48;4;32;64;96;128mCMYK\033[49m color\033[m",
     676              :         .f_plain_text = "background CMYK color",
     677              :         .f_html = "background <span style=\"color:#000000;background-color:#6f5f4f\">CMYK </span>color",
     678              :     },
     679              : 
     680              :     // background index color 100
     681              :     {
     682              :         .f_input = "background \033[48;5;100mindex color 100\033[49m color\033[m",
     683              :         .f_plain_text = "background index color 100 color",
     684              :         .f_html = "background <span style=\"color:#000000;background-color:#878700\">index color 100 </span>color",
     685              :     },
     686              : 
     687              :     // overline
     688              :     {
     689              :         .f_input = "\033[53moverline\033[m",
     690              :         .f_plain_text = "overline",
     691              :         .f_html = "<span class=\"ansi-v\">overline</span>",
     692              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     693              :                     ".ansi-u{text-decoration-line:underline}\n"
     694              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     695              :                     ".ansi-v{text-decoration-line:overline;}\n"
     696              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     697              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     698              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     699              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     700              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     701              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     702              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     703              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     704              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     705              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     706              :                     ".ansi-v{text-decoration-line:overline;}\n"
     707              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     708              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     709              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     710              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     711              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     712              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     713              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     714              :     },
     715              : 
     716              :     // overline + not overline
     717              :     {
     718              :         .f_input = "normal \033[53mthen overline\033[55m and not\033[m",
     719              :         .f_plain_text = "normal then overline and not",
     720              :         .f_html = "normal <span class=\"ansi-v\">then overline </span>and not",
     721              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     722              :                     ".ansi-u{text-decoration-line:underline}\n"
     723              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     724              :                     ".ansi-v{text-decoration-line:overline;}\n"
     725              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     726              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     727              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     728              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     729              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     730              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     731              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     732              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     733              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     734              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     735              :                     ".ansi-v{text-decoration-line:overline;}\n"
     736              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     737              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     738              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     739              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     740              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     741              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     742              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     743              :     },
     744              : 
     745              :     // cross out + overline
     746              :     {
     747              :         .f_input = "\033[9;53mcross out + overline\033[m",
     748              :         .f_plain_text = "cross out + overline",
     749              :         .f_html = "<span class=\"ansi-vs\">cross out + overline</span>",
     750              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     751              :                     ".ansi-u{text-decoration-line:underline}\n"
     752              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     753              :                     ".ansi-v{text-decoration-line:overline;}\n"
     754              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     755              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     756              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     757              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     758              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     759              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     760              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     761              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     762              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     763              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     764              :                     ".ansi-v{text-decoration-line:overline;}\n"
     765              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     766              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     767              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     768              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     769              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     770              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     771              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     772              :     },
     773              : 
     774              :     // overline + cross out
     775              :     {
     776              :         .f_input = "\033[53;9moverline + cross out\033[m",
     777              :         .f_plain_text = "overline + cross out",
     778              :         .f_html = "<span class=\"ansi-vs\">overline + cross out</span>",
     779              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     780              :                     ".ansi-u{text-decoration-line:underline}\n"
     781              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     782              :                     ".ansi-v{text-decoration-line:overline;}\n"
     783              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     784              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     785              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     786              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     787              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     788              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     789              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     790              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     791              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     792              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     793              :                     ".ansi-v{text-decoration-line:overline;}\n"
     794              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     795              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     796              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     797              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     798              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     799              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     800              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     801              :     },
     802              : 
     803              :     // cross out + overline + underline
     804              :     {
     805              :         .f_input = "\033[9;53;4mcross out + overline + underline\033[m",
     806              :         .f_plain_text = "cross out + overline + underline",
     807              :         .f_html = "<span class=\"ansi-uvs\">cross out + overline + underline</span>",
     808              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     809              :                     ".ansi-u{text-decoration-line:underline}\n"
     810              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     811              :                     ".ansi-v{text-decoration-line:overline;}\n"
     812              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     813              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     814              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     815              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     816              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     817              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     818              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     819              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     820              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     821              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     822              :                     ".ansi-v{text-decoration-line:overline;}\n"
     823              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     824              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     825              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     826              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     827              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     828              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     829              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     830              :     },
     831              : 
     832              :     // overline + cross out + underline
     833              :     {
     834              :         .f_input = "\033[53;9;4moverline + cross out + underline\033[m",
     835              :         .f_plain_text = "overline + cross out + underline",
     836              :         .f_html = "<span class=\"ansi-uvs\">overline + cross out + underline</span>",
     837              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     838              :                     ".ansi-u{text-decoration-line:underline}\n"
     839              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     840              :                     ".ansi-v{text-decoration-line:overline;}\n"
     841              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     842              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     843              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     844              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     845              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     846              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     847              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     848              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     849              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     850              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     851              :                     ".ansi-v{text-decoration-line:overline;}\n"
     852              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     853              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     854              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     855              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     856              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     857              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     858              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     859              :     },
     860              : 
     861              :     // underline + cross out + overline
     862              :     {
     863              :         .f_input = "\033[4;9;53munderline + cross out + overline\033[m",
     864              :         .f_plain_text = "underline + cross out + overline",
     865              :         .f_html = "<span class=\"ansi-uvs\">underline + cross out + overline</span>",
     866              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     867              :                     ".ansi-u{text-decoration-line:underline}\n"
     868              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     869              :                     ".ansi-v{text-decoration-line:overline;}\n"
     870              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     871              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     872              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     873              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     874              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     875              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     876              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     877              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     878              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     879              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     880              :                     ".ansi-v{text-decoration-line:overline;}\n"
     881              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     882              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     883              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     884              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     885              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     886              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     887              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     888              :     },
     889              : 
     890              :     // underline + overline + cross out
     891              :     {
     892              :         .f_input = "\033[4;53;9munderline + overline + cross out\033[m",
     893              :         .f_plain_text = "underline + overline + cross out",
     894              :         .f_html = "<span class=\"ansi-uvs\">underline + overline + cross out</span>",
     895              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     896              :                     ".ansi-u{text-decoration-line:underline}\n"
     897              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     898              :                     ".ansi-v{text-decoration-line:overline;}\n"
     899              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     900              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     901              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     902              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     903              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     904              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     905              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     906              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     907              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     908              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     909              :                     ".ansi-v{text-decoration-line:overline;}\n"
     910              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     911              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     912              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     913              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     914              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     915              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     916              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     917              :     },
     918              : 
     919              :     // cross out + underline + overline
     920              :     {
     921              :         .f_input = "\033[9;4;53mcross out + underline + overline\033[m",
     922              :         .f_plain_text = "cross out + underline + overline",
     923              :         .f_html = "<span class=\"ansi-uvs\">cross out + underline + overline</span>",
     924              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     925              :                     ".ansi-u{text-decoration-line:underline}\n"
     926              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     927              :                     ".ansi-v{text-decoration-line:overline;}\n"
     928              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     929              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     930              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     931              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     932              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     933              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     934              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     935              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     936              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     937              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     938              :                     ".ansi-v{text-decoration-line:overline;}\n"
     939              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     940              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     941              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     942              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     943              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     944              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     945              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     946              :     },
     947              : 
     948              :     // overline + underline + cross out
     949              :     {
     950              :         .f_input = "\033[53;4;9moverline + underline + cross out\033[m",
     951              :         .f_plain_text = "overline + underline + cross out",
     952              :         .f_html = "<span class=\"ansi-uvs\">overline + underline + cross out</span>",
     953              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     954              :                     ".ansi-u{text-decoration-line:underline}\n"
     955              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     956              :                     ".ansi-v{text-decoration-line:overline;}\n"
     957              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     958              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     959              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     960              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     961              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     962              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     963              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     964              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     965              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     966              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     967              :                     ".ansi-v{text-decoration-line:overline;}\n"
     968              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     969              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     970              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     971              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     972              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     973              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     974              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     975              :     },
     976              : 
     977              :     // cross out + overline + double underline
     978              :     {
     979              :         .f_input = "\033[9;53;21mcross out + overline + double underline\033[m",
     980              :         .f_plain_text = "cross out + overline + double underline",
     981              :         .f_html = "<span class=\"ansi-dvs\">cross out + overline + double underline</span>",
     982              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
     983              :                     ".ansi-u{text-decoration-line:underline}\n"
     984              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     985              :                     ".ansi-v{text-decoration-line:overline;}\n"
     986              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     987              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     988              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
     989              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
     990              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
     991              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
     992              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
     993              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
     994              :                     "u,.ansi-u{text-decoration-line:underline}\n"
     995              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
     996              :                     ".ansi-v{text-decoration-line:overline;}\n"
     997              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
     998              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
     999              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1000              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1001              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1002              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1003              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1004              :     },
    1005              : 
    1006              :     // overline + cross out + double underline
    1007              :     {
    1008              :         .f_input = "\033[53;9;21moverline + cross out + double underline\033[m",
    1009              :         .f_plain_text = "overline + cross out + double underline",
    1010              :         .f_html = "<span class=\"ansi-dvs\">overline + cross out + double underline</span>",
    1011              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1012              :                     ".ansi-u{text-decoration-line:underline}\n"
    1013              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1014              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1015              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1016              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1017              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1018              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1019              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1020              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1021              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1022              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1023              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1024              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1025              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1026              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1027              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1028              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1029              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1030              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1031              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1032              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1033              :     },
    1034              : 
    1035              :     // double underline + cross out + overline
    1036              :     {
    1037              :         .f_input = "\033[21;9;53mdouble underline + cross out + overline\033[m",
    1038              :         .f_plain_text = "double underline + cross out + overline",
    1039              :         .f_html = "<span class=\"ansi-dvs\">double underline + cross out + overline</span>",
    1040              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1041              :                     ".ansi-u{text-decoration-line:underline}\n"
    1042              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1043              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1044              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1045              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1046              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1047              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1048              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1049              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1050              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1051              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1052              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1053              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1054              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1055              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1056              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1057              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1058              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1059              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1060              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1061              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1062              :     },
    1063              : 
    1064              :     // double underline + overline + cross out
    1065              :     {
    1066              :         .f_input = "\033[21;53;9mdouble underline + overline + cross out\033[m",
    1067              :         .f_plain_text = "double underline + overline + cross out",
    1068              :         .f_html = "<span class=\"ansi-dvs\">double underline + overline + cross out</span>",
    1069              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1070              :                     ".ansi-u{text-decoration-line:underline}\n"
    1071              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1072              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1073              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1074              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1075              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1076              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1077              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1078              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1079              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1080              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1081              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1082              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1083              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1084              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1085              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1086              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1087              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1088              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1089              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1090              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1091              :     },
    1092              : 
    1093              :     // cross out + double underline + overline
    1094              :     {
    1095              :         .f_input = "\033[9;21;53mcross out + double underline + overline\033[m",
    1096              :         .f_plain_text = "cross out + double underline + overline",
    1097              :         .f_html = "<span class=\"ansi-dvs\">cross out + double underline + overline</span>",
    1098              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1099              :                     ".ansi-u{text-decoration-line:underline}\n"
    1100              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1101              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1102              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1103              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1104              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1105              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1106              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1107              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1108              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1109              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1110              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1111              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1112              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1113              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1114              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1115              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1116              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1117              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1118              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1119              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1120              :     },
    1121              : 
    1122              :     // overline + double underline + cross out
    1123              :     {
    1124              :         .f_input = "\033[53;21;9moverline + double underline + cross out\033[m",
    1125              :         .f_plain_text = "overline + double underline + cross out",
    1126              :         .f_html = "<span class=\"ansi-dvs\">overline + double underline + cross out</span>",
    1127              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1128              :                     ".ansi-u{text-decoration-line:underline}\n"
    1129              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1130              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1131              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1132              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1133              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1134              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1135              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1136              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1137              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1138              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1139              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1140              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1141              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1142              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1143              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1144              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1145              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1146              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1147              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1148              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1149              :     },
    1150              : 
    1151              :     // underline + overline
    1152              :     {
    1153              :         .f_input = "\033[4;53munderline + overline\033[m",
    1154              :         .f_plain_text = "underline + overline",
    1155              :         .f_html = "<span class=\"ansi-uv\">underline + overline</span>",
    1156              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1157              :                     ".ansi-u{text-decoration-line:underline}\n"
    1158              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1159              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1160              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1161              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1162              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1163              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1164              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1165              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1166              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1167              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1168              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1169              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1170              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1171              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1172              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1173              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1174              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1175              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1176              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1177              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1178              :     },
    1179              : 
    1180              :     // overline + underline
    1181              :     {
    1182              :         .f_input = "\033[53;4moverline + underline\033[m",
    1183              :         .f_plain_text = "overline + underline",
    1184              :         .f_html = "<span class=\"ansi-uv\">overline + underline</span>",
    1185              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1186              :                     ".ansi-u{text-decoration-line:underline}\n"
    1187              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1188              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1189              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1190              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1191              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1192              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1193              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1194              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1195              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1196              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1197              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1198              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1199              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1200              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1201              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1202              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1203              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1204              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1205              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1206              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1207              :     },
    1208              : 
    1209              :     // double underline + overline
    1210              :     {
    1211              :         .f_input = "\033[21;53mdouble underline + overline\033[m",
    1212              :         .f_plain_text = "double underline + overline",
    1213              :         .f_html = "<span class=\"ansi-dv\">double underline + overline</span>",
    1214              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1215              :                     ".ansi-u{text-decoration-line:underline}\n"
    1216              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1217              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1218              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1219              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1220              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1221              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1222              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1223              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1224              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1225              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1226              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1227              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1228              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1229              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1230              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1231              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1232              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1233              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1234              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1235              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1236              :     },
    1237              : 
    1238              :     // overline + double underline
    1239              :     {
    1240              :         .f_input = "\033[53;21moverline + double underline\033[m",
    1241              :         .f_plain_text = "overline + double underline",
    1242              :         .f_html = "<span class=\"ansi-dv\">overline + double underline</span>",
    1243              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1244              :                     ".ansi-u{text-decoration-line:underline}\n"
    1245              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1246              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1247              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1248              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1249              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1250              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1251              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1252              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1253              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1254              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1255              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1256              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1257              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1258              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1259              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1260              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1261              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1262              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1263              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1264              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1265              :     },
    1266              : 
    1267              :     // underline with a different color
    1268              :     {
    1269              :         .f_input = "normal \033[4mthen underline\033[58;5;200m with color\033[59m and not\033[m",
    1270              :         .f_plain_text = "normal then underline with color and not",
    1271              :         .f_html = "normal <span class=\"ansi-u\">then underline </span><span class=\"ansi-u\" style=\"text-decoration-color:#ff00d7\">with color </span><span class=\"ansi-u\">and not</span>",
    1272              :         .f_optimized_html = "normal <u>then underline </u><u><span style=\"text-decoration-color:#ff00d7\">with color </span></u><u>and not</u>",
    1273              :         .f_styles = ".ansi-s{text-decoration-line:line-through}\n"
    1274              :                     ".ansi-u{text-decoration-line:underline}\n"
    1275              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1276              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1277              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1278              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1279              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1280              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1281              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1282              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1283              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1284              :         .f_styles_with_defaults = "s,.ansi-s{text-decoration-line:line-through}\n"
    1285              :                     "u,.ansi-u{text-decoration-line:underline}\n"
    1286              :                     ".ansi-d{text-decoration-line:underline;text-decoration-style:double}\n"
    1287              :                     ".ansi-v{text-decoration-line:overline;}\n"
    1288              :                     ".ansi-us{text-decoration-line:underline line-through}\n"
    1289              :                     ".ansi-uv{text-decoration-line:underline overline}\n"
    1290              :                     ".ansi-uvs{text-decoration-line:underline overline line-through}\n"
    1291              :                     ".ansi-ds{text-decoration-line:underline line-through;text-decoration-style:double}\n"
    1292              :                     ".ansi-dv{text-decoration-line:underline overline;text-decoration-style:double}\n"
    1293              :                     ".ansi-dvs{text-decoration-line:underline overline line-through;text-decoration-style:double}\n"
    1294              :                     ".ansi-vs{text-decoration-line:overline line-through}\n",
    1295              :     },
    1296              : 
    1297              :     // foreground, background, and underline colors
    1298              :     {
    1299              :         .f_input = "normal \033[38;2;5;15;35;48;2;65;85;95;58;2;4;44;144mcolorful\033[39;49;59m normal",
    1300              :         .f_plain_text = "normal colorful normal",
    1301              :         .f_html = "normal <span style=\"color:#050f23;background-color:#41555f;text-decoration-color:#042c90\">colorful </span>normal",
    1302              :     },
    1303              : 
    1304              :     // superscript
    1305              :     {
    1306              :         .f_input = "\033[73msuperscript\033[m",
    1307              :         .f_plain_text = "superscript",
    1308              :         .f_html = "<span class=\"ansi-sup\">superscript</span>",
    1309              :         .f_optimized_html = "<sup>superscript</sup>",
    1310              :         .f_styles = ".ansi-sup{font-size:60%;vertical-align:super}\n",
    1311              :         .f_styles_with_defaults = "sup,.ansi-sup{font-size:60%;vertical-align:super}\n",
    1312              :     },
    1313              : 
    1314              :     // subscript
    1315              :     {
    1316              :         .f_input = "\033[74msubscript\033[m",
    1317              :         .f_plain_text = "subscript",
    1318              :         .f_html = "<span class=\"ansi-sub\">subscript</span>",
    1319              :         .f_optimized_html = "<sub>subscript</sub>",
    1320              :         .f_styles = ".ansi-sub{font-size:60%;vertical-align:sub}\n",
    1321              :         .f_styles_with_defaults = "sub,.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1322              :     },
    1323              : 
    1324              :     // superscript + not superscript
    1325              :     {
    1326              :         .f_input = "normal \033[73mthen superscript\033[75m and not\033[m",
    1327              :         .f_plain_text = "normal then superscript and not",
    1328              :         .f_html = "normal <span class=\"ansi-sup\">then superscript </span>and not",
    1329              :         .f_optimized_html = "normal <sup>then superscript </sup>and not",
    1330              :         .f_styles = ".ansi-sup{font-size:60%;vertical-align:super}\n",
    1331              :         .f_styles_with_defaults = "sup,.ansi-sup{font-size:60%;vertical-align:super}\n",
    1332              :     },
    1333              : 
    1334              :     // subscript + not subscript
    1335              :     {
    1336              :         .f_input = "normal \033[74mthen subscript\033[75m and not\033[m",
    1337              :         .f_plain_text = "normal then subscript and not",
    1338              :         .f_html = "normal <span class=\"ansi-sub\">then subscript </span>and not",
    1339              :         .f_optimized_html = "normal <sub>then subscript </sub>and not",
    1340              :         .f_styles = ".ansi-sub{font-size:60%;vertical-align:sub}\n",
    1341              :         .f_styles_with_defaults = "sub,.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1342              :     },
    1343              : 
    1344              :     // superscript + subscript are mutually exclusive
    1345              :     {
    1346              :         .f_input = "normal \033[73mthen superscript \033[74mthen subscript\033[75m and then not\033[m",
    1347              :         .f_plain_text = "normal then superscript then subscript and then not",
    1348              :         .f_html = "normal <span class=\"ansi-sup\">then superscript </span><span class=\"ansi-sub\">then subscript </span>and then not",
    1349              :         .f_optimized_html = "normal <sup>then superscript </sup><sub>then subscript </sub>and then not",
    1350              :         .f_styles = ".ansi-sup{font-size:60%;vertical-align:super}\n.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1351              :         .f_styles_with_defaults = "sup,.ansi-sup{font-size:60%;vertical-align:super}\nsub,.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1352              :     },
    1353              : 
    1354              :     // subscript + superscript are mutually exclusive
    1355              :     {
    1356              :         .f_input = "normal \033[74mthen subscript \033[73mthen superscript\033[75m and then not\033[m",
    1357              :         .f_plain_text = "normal then subscript then superscript and then not",
    1358              :         .f_html = "normal <span class=\"ansi-sub\">then subscript </span><span class=\"ansi-sup\">then superscript </span>and then not",
    1359              :         .f_optimized_html = "normal <sub>then subscript </sub><sup>then superscript </sup>and then not",
    1360              :         .f_styles = ".ansi-sup{font-size:60%;vertical-align:super}\n.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1361              :         .f_styles_with_defaults = "sup,.ansi-sup{font-size:60%;vertical-align:super}\nsub,.ansi-sub{font-size:60%;vertical-align:sub}\n",
    1362              :     },
    1363              : 
    1364              :     // foreground gray color
    1365              :     {
    1366              :         .f_input = "foreground \033[90mgray\033[39m color\033[m",
    1367              :         .f_plain_text = "foreground gray color",
    1368              :         .f_html = "foreground <span style=\"color:#808080;background-color:#ffffff\">gray </span>color",
    1369              :     },
    1370              : 
    1371              :     // foreground bright red color
    1372              :     {
    1373              :         .f_input = "foreground \033[91mbright red\033[39m color\033[m",
    1374              :         .f_plain_text = "foreground bright red color",
    1375              :         .f_html = "foreground <span style=\"color:#ff0000;background-color:#ffffff\">bright red </span>color",
    1376              :     },
    1377              : 
    1378              :     // foreground bright green color
    1379              :     {
    1380              :         .f_input = "foreground \033[92mbright green\033[39m color\033[m",
    1381              :         .f_plain_text = "foreground bright green color",
    1382              :         .f_html = "foreground <span style=\"color:#00ff00;background-color:#ffffff\">bright green </span>color",
    1383              :     },
    1384              : 
    1385              :     // foreground bright yellow color
    1386              :     {
    1387              :         .f_input = "foreground \033[93mbright yellow\033[39m color\033[m",
    1388              :         .f_plain_text = "foreground bright yellow color",
    1389              :         .f_html = "foreground <span style=\"color:#ffff00;background-color:#ffffff\">bright yellow </span>color",
    1390              :     },
    1391              : 
    1392              :     // foreground bright blue color
    1393              :     {
    1394              :         .f_input = "foreground \033[94mbright blue\033[39m color\033[m",
    1395              :         .f_plain_text = "foreground bright blue color",
    1396              :         .f_html = "foreground <span style=\"color:#0000ff;background-color:#ffffff\">bright blue </span>color",
    1397              :     },
    1398              : 
    1399              :     // foreground bright magenta color
    1400              :     {
    1401              :         .f_input = "foreground \033[95mbright magenta\033[39m color\033[m",
    1402              :         .f_plain_text = "foreground bright magenta color",
    1403              :         .f_html = "foreground <span style=\"color:#ff00ff;background-color:#ffffff\">bright magenta </span>color",
    1404              :     },
    1405              : 
    1406              :     // foreground bright cyan color
    1407              :     {
    1408              :         .f_input = "foreground \033[96mbright cyan\033[39m color\033[m",
    1409              :         .f_plain_text = "foreground bright cyan color",
    1410              :         .f_html = "foreground <span style=\"color:#00ffff;background-color:#ffffff\">bright cyan </span>color",
    1411              :     },
    1412              : 
    1413              :     // foreground bright white color
    1414              :     {
    1415              :         .f_input = "foreground \033[97mbright white\033[39m color\033[m",
    1416              :         .f_plain_text = "foreground bright white color",
    1417              :         .f_html = "foreground <span style=\"color:#ffffff;background-color:#ffffff\">bright white </span>color",
    1418              :     },
    1419              : 
    1420              :     // background gray color
    1421              :     {
    1422              :         .f_input = "background \033[100mgray\033[49m color\033[m",
    1423              :         .f_plain_text = "background gray color",
    1424              :         .f_html = "background <span style=\"color:#000000;background-color:#808080\">gray </span>color",
    1425              :     },
    1426              : 
    1427              :     // background bright red color
    1428              :     {
    1429              :         .f_input = "background \033[101mbright red\033[49m color\033[m",
    1430              :         .f_plain_text = "background bright red color",
    1431              :         .f_html = "background <span style=\"color:#000000;background-color:#ff0000\">bright red </span>color",
    1432              :     },
    1433              : 
    1434              :     // background bright green color
    1435              :     {
    1436              :         .f_input = "background \033[102mbright green\033[49m color\033[m",
    1437              :         .f_plain_text = "background bright green color",
    1438              :         .f_html = "background <span style=\"color:#000000;background-color:#00ff00\">bright green </span>color",
    1439              :     },
    1440              : 
    1441              :     // background bright yellow color
    1442              :     {
    1443              :         .f_input = "background \033[103mbright yellow\033[49m color\033[m",
    1444              :         .f_plain_text = "background bright yellow color",
    1445              :         .f_html = "background <span style=\"color:#000000;background-color:#ffff00\">bright yellow </span>color",
    1446              :     },
    1447              : 
    1448              :     // background bright blue color
    1449              :     {
    1450              :         .f_input = "background \033[104mbright blue\033[49m color\033[m",
    1451              :         .f_plain_text = "background bright blue color",
    1452              :         .f_html = "background <span style=\"color:#000000;background-color:#0000ff\">bright blue </span>color",
    1453              :     },
    1454              : 
    1455              :     // background bright magenta color
    1456              :     {
    1457              :         .f_input = "background \033[105mbright magenta\033[49m color\033[m",
    1458              :         .f_plain_text = "background bright magenta color",
    1459              :         .f_html = "background <span style=\"color:#000000;background-color:#ff00ff\">bright magenta </span>color",
    1460              :     },
    1461              : 
    1462              :     // background bright cyan color
    1463              :     {
    1464              :         .f_input = "background \033[106mbright cyan\033[49m color\033[m",
    1465              :         .f_plain_text = "background bright cyan color",
    1466              :         .f_html = "background <span style=\"color:#000000;background-color:#00ffff\">bright cyan </span>color",
    1467              :     },
    1468              : 
    1469              :     // background bright white color
    1470              :     {
    1471              :         .f_input = "background \033[107mbright white\033[49m color\033[m",
    1472              :         .f_plain_text = "background bright white color",
    1473              :         .f_html = "background <span style=\"color:#000000;background-color:#ffffff\">bright white </span>color",
    1474              :     },
    1475              : 
    1476              :     // HTML special characters
    1477              :     {
    1478              :         .f_input = "quot - \", amp - &, apos - ', lt - <, and gt - >",
    1479              :         .f_plain_text = "quot - \", amp - &, apos - ', lt - <, and gt - >",
    1480              :         .f_html = "quot - &quot;, amp - &amp;, apos - &apos;, lt - &lt;, and gt - &gt;",
    1481              :         .f_markdown = "quot \\- \", amp \\- &, apos \\- ', lt \\- \\<, and gt \\- \\>",
    1482              :     },
    1483              : 
    1484              :     // markdown special characters
    1485              :     {
    1486              :         .f_input = "++ * - # _ < > ` [ \\ ++",
    1487              :         .f_plain_text = "++ * - # _ < > ` [ \\ ++",
    1488              :         .f_html = "++ * - # _ &lt; &gt; ` [ \\ ++",
    1489              :         .f_markdown = "++ \\* \\- \\# \\_ \\< \\> \\` \\[ \\\\ ++",
    1490              :     },
    1491              : 
    1492              :     // multiple lines
    1493              :     {
    1494              :         .f_input = "this is line 1\nthen comes line 2\r\nand we got 3\rfinally line 4",
    1495              :         .f_plain_text = "this is line 1\nthen comes line 2\nand we got 3\nfinally line 4",
    1496              :         .f_html = "this is line 1<br/>\nthen comes line 2<br/>\nand we got 3<br/>\nfinally line 4",
    1497              :     },
    1498              : 
    1499              :     // unsupported system control
    1500              :     {
    1501              :         .f_input = "change title \033]0;This is the title\007",
    1502              :         .f_plain_text = "change title ]0;This is the title\007",
    1503              :         .f_html = "change title ]0;This is the title\007",
    1504              :     },
    1505              : 
    1506              :     // unsupported ST characters (for example the console can move the cursor)
    1507              :     {
    1508              :         .f_input = "A\033[AB\033[BC\033[CD\033[DE\033[EF\033[FG\033[GH\033[HJ\033[JK\033[KS\033[ST\033[Tf\033[fh\033[hi\033[il\033[ln\033[ns\033[su\033[u",
    1509              :         .f_plain_text = "ABCDEFGHJKSTfhilnsu",
    1510              :         .f_html = "ABCDEFGHJKSTfhilnsu",
    1511              :     },
    1512              : 
    1513              :     // fonts are ignored
    1514              :     {
    1515              :         .f_input = "\033[10mFon\033[11mt s\033[12mele\033[13mcti\033[14mons\033[15m ar\033[16me i\033[17mgno\033[18mred\033[19m Fr\033[20makt\033[mur.",
    1516              :         .f_plain_text = "Font selections are ignored Fraktur.",
    1517              :         .f_html = "Font selections are ignored Fraktur.",
    1518              :     },
    1519              : 
    1520              :     // frames are ignored
    1521              :     {
    1522              :         .f_input = "Normal \033[51mFramed \033[52mCircled \033[54mNormal",
    1523              :         .f_plain_text = "Normal Framed Circled Normal",
    1524              :         .f_html = "Normal Framed Circled Normal",
    1525              :     },
    1526              : 
    1527              :     // ideograms are ignored
    1528              :     {
    1529              :         .f_input = "Normal \033[60mIdeo0 \033[61mIdeo1 \033[62mIdeo2 \033[63mIdeo3 \033[64mIdeo4 \033[65mNormal",
    1530              :         .f_plain_text = "Normal Ideo0 Ideo1 Ideo2 Ideo3 Ideo4 Normal",
    1531              :         .f_html = "Normal Ideo0 Ideo1 Ideo2 Ideo3 Ideo4 Normal",
    1532              :     },
    1533              : };
    1534              : 
    1535              : 
    1536              : 
    1537              : }
    1538              : // no name namespace
    1539              : 
    1540              : 
    1541            1 : CATCH_TEST_CASE("convert_ansi", "[converter]")
    1542              : {
    1543            1 :     CATCH_START_SECTION("convert_ansi: simple conversions")
    1544              :     {
    1545            1 :         snaplogger::convert_ansi::pointer_t plain_text_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    1546            1 :         snaplogger::convert_ansi::pointer_t html_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_HTML));
    1547            1 :         snaplogger::convert_ansi::pointer_t markdown_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_MARKDOWN));
    1548              : 
    1549            1 :         CATCH_REQUIRE(plain_text_converter->get_type() == snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT);
    1550            1 :         CATCH_REQUIRE(html_converter->get_type() == snaplogger::ansi_output_t::ANSI_OUTPUT_HTML);
    1551            1 :         CATCH_REQUIRE(markdown_converter->get_type() == snaplogger::ansi_output_t::ANSI_OUTPUT_MARKDOWN);
    1552              : 
    1553            1 :         CATCH_REQUIRE_FALSE(plain_text_converter->get_optimize());
    1554            1 :         CATCH_REQUIRE_FALSE(html_converter->get_optimize());
    1555            1 :         CATCH_REQUIRE_FALSE(markdown_converter->get_optimize());
    1556              : 
    1557            1 :         CATCH_REQUIRE(plain_text_converter->get_br());
    1558            1 :         CATCH_REQUIRE(html_converter->get_br());
    1559            1 :         CATCH_REQUIRE(markdown_converter->get_br());
    1560              : 
    1561              :         // save cursor; we assume that the longest string will wrap one line
    1562              :         //
    1563            1 :         std::cout << "\n\n\033[s";
    1564              : 
    1565          106 :         for(auto const & convert : g_convert_data)
    1566              :         {
    1567              :             // to avoid the reuse of the line, change the \033[u with \033[s
    1568              :             //
    1569         2835 :             std::cout << "\033[u\033[2A--- working on [" << snapdev::string_replace_many(std::string(convert.f_input), {
    1570              :                     {"\r", "\\r"},
    1571              :                     {"\n", "\\n"},
    1572              :                     {"\033[A", "\\033[A"},
    1573              :                     {"\033[B", "\\033[B"},
    1574              :                     {"\033[C", "\\033[C"},
    1575              :                     {"\033[D", "\\033[D"},
    1576              :                     {"\033[E", "\\033[E"},
    1577              :                     {"\033[F", "\\033[F"},
    1578              :                     {"\033[G", "\\033[G"},
    1579              :                     {"\033[H", "\\033[H"},
    1580              :                     {"\033[J", "\\033[J"},
    1581              :                     {"\033[K", "\\033[K"},
    1582              :                     {"\033[S", "\\033[S"},
    1583              :                     {"\033[T", "\\033[T"},
    1584              :                     {"\033[f", "\\033[f"},
    1585              :                     {"\033[h", "\\033[h"},
    1586              :                     {"\033[i", "\\033[i"},
    1587              :                     {"\033[l", "\\033[l"},
    1588              :                     {"\033[n", "\\033[n"},
    1589              :                     {"\033[s", "\\033[s"},
    1590              :                     {"\033[u", "\\033[u"},
    1591          210 :                 }) << "]\033[K\n";
    1592              : 
    1593              :             // plain text
    1594              :             //
    1595          315 :             plain_text_converter->write(convert.f_input);
    1596          105 :             std::string result(plain_text_converter->read());
    1597          105 :             CATCH_REQUIRE_FALSE(plain_text_converter->has_invalid_data());
    1598          105 :             CATCH_REQUIRE(convert.f_plain_text == result);
    1599          105 :             CATCH_REQUIRE(plain_text_converter->get_styles().empty());
    1600              : 
    1601              :             // html
    1602              :             //
    1603          315 :             html_converter->write(convert.f_input);
    1604          105 :             result = html_converter->read();
    1605          105 :             CATCH_REQUIRE_FALSE(html_converter->has_invalid_data());
    1606          105 :             CATCH_REQUIRE(convert.f_html == result);
    1607              : 
    1608              :             // no br html
    1609              :             //
    1610          105 :             html_converter->set_br(false);
    1611          105 :             CATCH_REQUIRE_FALSE(html_converter->get_br());
    1612              : 
    1613          315 :             html_converter->write(convert.f_input);
    1614          105 :             result = html_converter->read();
    1615          105 :             CATCH_REQUIRE_FALSE(html_converter->has_invalid_data());
    1616          630 :             std::string const html_without_br(snapdev::string_replace_many(std::string(convert.f_html), {{"<br/>", ""}}));
    1617          105 :             CATCH_REQUIRE(html_without_br == result);
    1618              : 
    1619          105 :             html_converter->set_br(true);
    1620          105 :             CATCH_REQUIRE(html_converter->get_br());
    1621              : 
    1622              : //            {
    1623              : //                snaplogger::convert_ansi::pointer_t clean_html_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_HTML));
    1624              : //                clean_html_converter->write(convert.f_input);
    1625              : //                result = clean_html_converter->read();
    1626              : //                CATCH_REQUIRE_FALSE(clean_html_converter->has_invalid_data());
    1627              : //                CATCH_REQUIRE(convert.f_html == result);
    1628              : //                if(convert.f_styles != nullptr)
    1629              : //                {
    1630              : ////std::cout << " >>> (1)T:[" << snapdev::string_replace_many(std::string(convert.f_styles), {
    1631              : ////        {"\r", "\\r"},
    1632              : ////        {"\n", "\\n"},
    1633              : ////    }) << " && " << snapdev::string_replace_many(std::string(convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults), {
    1634              : ////        {"\r", "\\r"},
    1635              : ////        {"\n", "\\n"},
    1636              : ////    }) << "]\n";
    1637              : ////std::cout << " >>> (1)C:[" << snapdev::string_replace_many(clean_html_converter->get_styles(), {
    1638              : ////        {"\r", "\\r"},
    1639              : ////        {"\n", "\\n"},
    1640              : ////    }) << " && " << snapdev::string_replace_many(clean_html_converter->get_styles(true), {
    1641              : ////        {"\r", "\\r"},
    1642              : ////        {"\n", "\\n"},
    1643              : ////    }) << "]\n";
    1644              : //                    CATCH_REQUIRE(convert.f_styles == clean_html_converter->get_styles());
    1645              : //                    CATCH_REQUIRE(convert.f_styles == clean_html_converter->get_styles(true));
    1646              : //                    //CATCH_REQUIRE((convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults) == clean_html_converter->get_styles(true));
    1647              : //                }
    1648              : //                else
    1649              : //                {
    1650              : //                    if(!clean_html_converter->get_styles().empty())
    1651              : //                    {
    1652              : //                        std::cout << std::flush;
    1653              : //                        std::cerr << "error: styles are not empty:\n  "
    1654              : //                            << snapdev::string_replace_many(clean_html_converter->get_styles(), {{"\n", "\n  "}})
    1655              : //                            << "\n";
    1656              : //                    }
    1657              : //                    CATCH_REQUIRE(clean_html_converter->get_styles().empty());
    1658              : //                }
    1659              : //            }
    1660              : 
    1661              :             // clean html (to verify styles)
    1662              :             //
    1663              :             {
    1664          105 :                 snaplogger::convert_ansi::pointer_t clean_html_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_HTML));
    1665          315 :                 clean_html_converter->write(convert.f_input);
    1666          105 :                 result = clean_html_converter->read();
    1667          105 :                 CATCH_REQUIRE_FALSE(clean_html_converter->has_invalid_data());
    1668          105 :                 CATCH_REQUIRE(convert.f_html == result);
    1669          105 :                 if(convert.f_styles != nullptr)
    1670              :                 {
    1671              : //std::cout << " >>> (1)T:[" << snapdev::string_replace_many(std::string(convert.f_styles), {
    1672              : //        {"\r", "\\r"},
    1673              : //        {"\n", "\\n"},
    1674              : //    }) << " && " << snapdev::string_replace_many(std::string(convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults), {
    1675              : //        {"\r", "\\r"},
    1676              : //        {"\n", "\\n"},
    1677              : //    }) << "]\n";
    1678              : //std::cout << " >>> (1)C:[" << snapdev::string_replace_many(clean_html_converter->get_styles(), {
    1679              : //        {"\r", "\\r"},
    1680              : //        {"\n", "\\n"},
    1681              : //    }) << " && " << snapdev::string_replace_many(clean_html_converter->get_styles(true), {
    1682              : //        {"\r", "\\r"},
    1683              : //        {"\n", "\\n"},
    1684              : //    }) << "]\n";
    1685           48 :                     CATCH_REQUIRE(convert.f_styles == clean_html_converter->get_styles());
    1686           48 :                     CATCH_REQUIRE(convert.f_styles == clean_html_converter->get_styles(true));
    1687              :                     //CATCH_REQUIRE((convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults) == clean_html_converter->get_styles(true));
    1688              :                 }
    1689              :                 else
    1690              :                 {
    1691           57 :                     if(!clean_html_converter->get_styles().empty())
    1692              :                     {
    1693            0 :                         std::cout << std::flush;
    1694              :                         std::cerr << "error: styles are not empty:\n  "
    1695            0 :                             << snapdev::string_replace_many(clean_html_converter->get_styles(), {{"\n", "\n  "}})
    1696            0 :                             << "\n";
    1697              :                     }
    1698           57 :                     CATCH_REQUIRE(clean_html_converter->get_styles().empty());
    1699              :                 }
    1700          105 :             }
    1701              : 
    1702              :             // optimized html
    1703              :             //
    1704          105 :             html_converter->set_optimize(true);
    1705          105 :             CATCH_REQUIRE(html_converter->get_optimize());
    1706              : 
    1707          315 :             html_converter->write(convert.f_input);
    1708          105 :             result = html_converter->read();
    1709          105 :             CATCH_REQUIRE_FALSE(html_converter->has_invalid_data());
    1710          105 :             CATCH_REQUIRE((convert.f_optimized_html == nullptr ? convert.f_html : convert.f_optimized_html) == result);
    1711              : 
    1712          105 :             html_converter->set_optimize(false);
    1713          105 :             CATCH_REQUIRE_FALSE(html_converter->get_optimize());
    1714              : 
    1715              :             // clean optimized html
    1716              :             //
    1717              :             {
    1718          105 :                 snaplogger::convert_ansi::pointer_t clean_html_converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_HTML));
    1719          105 :                 clean_html_converter->set_optimize(true);
    1720          105 :                 CATCH_REQUIRE(clean_html_converter->get_optimize());
    1721              : 
    1722          315 :                 clean_html_converter->write(convert.f_input);
    1723          105 :                 result = clean_html_converter->read();
    1724          105 :                 CATCH_REQUIRE_FALSE(clean_html_converter->has_invalid_data());
    1725          105 :                 CATCH_REQUIRE((convert.f_optimized_html == nullptr ? convert.f_html : convert.f_optimized_html) == result);
    1726          105 :                 if(convert.f_styles != nullptr)
    1727              :                 {
    1728              : //std::cout << " >>> (2)T:[" << snapdev::string_replace_many(std::string(convert.f_styles), {
    1729              : //        {"\r", "\\r"},
    1730              : //        {"\n", "\\n"},
    1731              : //    }) << " && " << snapdev::string_replace_many(std::string(convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults), {
    1732              : //        {"\r", "\\r"},
    1733              : //        {"\n", "\\n"},
    1734              : //    }) << "]\n";
    1735              : //std::cout << " >>> (2)C:[" << snapdev::string_replace_many(clean_html_converter->get_styles(), {
    1736              : //        {"\r", "\\r"},
    1737              : //        {"\n", "\\n"},
    1738              : //    }) << " && " << snapdev::string_replace_many(clean_html_converter->get_styles(true), {
    1739              : //        {"\r", "\\r"},
    1740              : //        {"\n", "\\n"},
    1741              : //    }) << "]\n";
    1742              :                     //CATCH_REQUIRE(convert.f_styles == clean_html_converter->get_styles());
    1743           48 :                     CATCH_REQUIRE((convert.f_styles_with_defaults == nullptr ? convert.f_styles : convert.f_styles_with_defaults) == clean_html_converter->get_styles(true));
    1744              :                 }
    1745              :                 else
    1746              :                 {
    1747           57 :                     if(!clean_html_converter->get_styles().empty())
    1748              :                     {
    1749            0 :                         std::cout << std::flush;
    1750              :                         std::cerr << "error: styles are not empty:\n  "
    1751            0 :                             << snapdev::string_replace_many(clean_html_converter->get_styles(), {{"\n", "\n  "}})
    1752            0 :                             << "\n";
    1753              :                     }
    1754           57 :                     CATCH_REQUIRE(clean_html_converter->get_styles().empty());
    1755              :                 }
    1756          105 :             }
    1757              : 
    1758              :             // markdown
    1759              :             //
    1760          315 :             markdown_converter->write(convert.f_input);
    1761          105 :             result = markdown_converter->read();
    1762          105 :             CATCH_REQUIRE_FALSE(markdown_converter->has_invalid_data());
    1763          105 :             CATCH_REQUIRE((convert.f_markdown == nullptr ? convert.f_plain_text : convert.f_markdown) == result);
    1764          105 :             CATCH_REQUIRE(markdown_converter->get_styles().empty());
    1765          105 :         }
    1766            1 :         std::cout << "\033[K";
    1767            1 :     }
    1768            1 :     CATCH_END_SECTION()
    1769          211 : }
    1770              : 
    1771              : 
    1772            5 : CATCH_TEST_CASE("convert_ansi_invalid", "[converter][error]")
    1773              : {
    1774            5 :     CATCH_START_SECTION("convert_ansi_invalid: bad UTF-8 character")
    1775              :     {
    1776            1 :         snaplogger::convert_ansi::pointer_t converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    1777            3 :         converter->write("\033[4mBad char: \x83\033[m");
    1778            1 :         std::string const result(converter->read());
    1779            1 :         CATCH_REQUIRE(converter->has_invalid_data());
    1780            1 :         CATCH_REQUIRE("Bad char: " == result);
    1781            1 :     }
    1782            5 :     CATCH_END_SECTION()
    1783              : 
    1784            5 :     CATCH_START_SECTION("convert_ansi_invalid: unsupported character closing CSI")
    1785              :     {
    1786            1 :         char buf[4] = {
    1787              :             '\033',
    1788              :             '[',
    1789              :             '@',
    1790              :             '\0',
    1791              :         };
    1792           64 :         for(; buf[2] <= '~'; ++buf[2])
    1793              :         {
    1794           63 :             switch(buf[2])
    1795              :             {
    1796           20 :             case 'm':
    1797              :             case 'A':
    1798              :             case 'B':
    1799              :             case 'C':
    1800              :             case 'D':
    1801              :             case 'E':
    1802              :             case 'F':
    1803              :             case 'G':
    1804              :             case 'H':
    1805              :             case 'J':
    1806              :             case 'K':
    1807              :             case 'S':
    1808              :             case 'T':
    1809              :             case 'f':
    1810              :             case 'h':
    1811              :             case 'i':
    1812              :             case 'l':
    1813              :             case 'n':
    1814              :             case 's':
    1815              :             case 'u':
    1816              :                 // supported characters do not generate an invalid sequence
    1817              :                 // (even if we do not support any of them except the 'm')
    1818              :                 //
    1819           20 :                 break;
    1820              : 
    1821           43 :             default:
    1822              :                 {
    1823           43 :                     snaplogger::convert_ansi::pointer_t converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    1824          129 :                     converter->write(buf);
    1825           43 :                     std::string const result(converter->read());
    1826           43 :                     CATCH_REQUIRE(converter->has_invalid_data());
    1827           43 :                     CATCH_REQUIRE(result.empty());
    1828           43 :                 }
    1829              :                 break;
    1830              : 
    1831              :             }
    1832              :         }
    1833              :     }
    1834            5 :     CATCH_END_SECTION()
    1835              : 
    1836            5 :     CATCH_START_SECTION("convert_ansi_invalid: unsupported CSI value separator")
    1837              :     {
    1838      1114112 :         for(char32_t wc = 0x000001; wc <= 0x10FFFF; ++wc)
    1839              :         {
    1840              :             // skip invalid unicode (surrogates in char32_t are not valid)
    1841              :             //
    1842      1114111 :             if(wc >= 0xD800 && wc <= 0xDFFF)
    1843              :             {
    1844         2048 :                 continue;
    1845              :             }
    1846              : 
    1847              :             // skip digits, those are understood
    1848              :             //
    1849      1112063 :             if(wc >= U'0' && wc <= U'9')
    1850              :             {
    1851           10 :                 continue;
    1852              :             }
    1853              : 
    1854              :             // skip closing characters
    1855              :             //
    1856      1112053 :             if(wc >= U'@' && wc <= U'~')
    1857              :             {
    1858           63 :                 continue;
    1859              :             }
    1860              : 
    1861              :             // skip valid separators
    1862              :             //
    1863      1111990 :             if(wc == ';' || wc == ':')
    1864              :             {
    1865            2 :                 continue;
    1866              :             }
    1867              : //std::cerr << "--- checking character 0x" << std::hex << std::setw(6) << std::setfill('0') << static_cast<std::uint32_t>(wc) << std::dec << "\n";
    1868              : 
    1869      1111988 :             snaplogger::convert_ansi::pointer_t converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    1870      3335964 :             std::string sequence("\033[2");
    1871      1111988 :             sequence += libutf8::to_u8string(wc);
    1872      1111988 :             sequence += "3m";
    1873      1111988 :             converter->write(sequence);
    1874      1111988 :             std::string const result(converter->read());
    1875      1111988 :             CATCH_REQUIRE(converter->has_invalid_data());
    1876      1111988 :             CATCH_REQUIRE(result.empty());
    1877      1111988 :         }
    1878              :     }
    1879            5 :     CATCH_END_SECTION()
    1880              : 
    1881            5 :     CATCH_START_SECTION("convert_ansi_invalid: unsupported parameter numbers")
    1882              :     {
    1883            1 :         auto is_valid = [](int const value)
    1884              :         {
    1885          100 :             switch(value)
    1886              :             {
    1887            0 :             case 0:
    1888              :             case 1:
    1889              :             case 2:
    1890              :             case 3:
    1891              :             case 4:
    1892              :             case 5:
    1893              :             case 6:
    1894              :             case 7:
    1895              :             case 8:
    1896              :             case 9:
    1897              :             case 10:
    1898              :             case 11:
    1899              :             case 12:
    1900              :             case 13:
    1901              :             case 14:
    1902              :             case 15:
    1903              :             case 16:
    1904              :             case 17:
    1905              :             case 18:
    1906              :             case 19:
    1907              :             case 20:
    1908              :             case 21:
    1909              :             case 22:
    1910              :             case 23:
    1911              :             case 24:
    1912              :             case 25:
    1913              :             case 26:
    1914              :             case 27:
    1915              :             case 28:
    1916              :             case 29:
    1917              :             case 30:
    1918              :             case 31:
    1919              :             case 32:
    1920              :             case 33:
    1921              :             case 34:
    1922              :             case 35:
    1923              :             case 36:
    1924              :             case 37:
    1925              :             case 38:
    1926              :             case 39:
    1927              :             case 40:
    1928              :             case 41:
    1929              :             case 42:
    1930              :             case 43:
    1931              :             case 44:
    1932              :             case 45:
    1933              :             case 46:
    1934              :             case 47:
    1935              :             case 48:
    1936              :             case 49:
    1937              :             case 50:
    1938              :             case 51:
    1939              :             case 52:
    1940              :             case 53:
    1941              :             case 54:
    1942              :             case 55:
    1943              :             case 58:
    1944              :             case 59:
    1945              :             case 60:
    1946              :             case 61:
    1947              :             case 62:
    1948              :             case 63:
    1949              :             case 64:
    1950              :             case 65:
    1951              :             case 73:
    1952              :             case 74:
    1953              :             case 75:
    1954              :             case 90:
    1955              :             case 91:
    1956              :             case 92:
    1957              :             case 93:
    1958              :             case 94:
    1959              :             case 95:
    1960              :             case 96:
    1961              :             case 97:
    1962              :             case 100:
    1963              :             case 101:
    1964              :             case 102:
    1965              :             case 103:
    1966              :             case 104:
    1967              :             case 105:
    1968              :             case 106:
    1969              :             case 107:
    1970            0 :                 return true;
    1971              : 
    1972          100 :             default:
    1973          100 :                 return false;
    1974              : 
    1975              :             }
    1976              :         };
    1977              : 
    1978          101 :         for(int count(0); count < 100; ++count)
    1979              :         {
    1980          100 :             int value(0);
    1981              :             for(;;)
    1982              :             {
    1983          100 :                 value = rand();
    1984          100 :                 if(!is_valid(value))
    1985              :                 {
    1986          100 :                     break;
    1987              :                 }
    1988              :             }
    1989              : 
    1990          100 :             snaplogger::convert_ansi::pointer_t converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    1991          300 :             std::string sequence("\033[");
    1992          100 :             sequence += std::to_string(value);
    1993          100 :             sequence += "m";
    1994          100 :             converter->write(sequence);
    1995          100 :             std::string const result(converter->read());
    1996          100 :             CATCH_REQUIRE(converter->has_invalid_data());
    1997          100 :             CATCH_REQUIRE(result.empty());
    1998          100 :         }
    1999              :     }
    2000            5 :     CATCH_END_SECTION()
    2001              : 
    2002            5 :     CATCH_START_SECTION("convert_ansi_invalid: invalid color definitions")
    2003              :     {
    2004            1 :         constexpr char const * invalid_colors[] =
    2005              :         {
    2006              :             "\033[48;1m -> transparent not supported with backgrounds",
    2007              :             "\033[58;1m -> transparent not supported with underlines",
    2008              :             "\033[38;2m -> RGB missing for foreground color",
    2009              :             "\033[48;2;45m -> GB in RGB missing for background color",
    2010              :             "\033[58;2;45;78m -> B in RGB missing for underline color",
    2011              :             "\033[38;2;256;33;98m -> red value out of bound for foreground color",
    2012              :             "\033[48;2;45;256;11m -> green value out of bound for background color",
    2013              :             "\033[58;2;45;78;256m -> blue value out of bound for underline color",
    2014              :             "\033[38;3m -> CMY missing for foreground color",
    2015              :             "\033[48;3;45m -> MY in CMY missing for background color",
    2016              :             "\033[58;3;45;78m -> Y in CMY missing for underline color",
    2017              :             "\033[38;3;256;33;98m -> cyan value out of bound for foreground color",
    2018              :             "\033[48;3;45;256;11m -> magenta value out of bound for background color",
    2019              :             "\033[58;3;45;78;256m -> yellow value out of bound for underline color",
    2020              :             "\033[38;4m -> CMYK missing for foreground color",
    2021              :             "\033[48;4;45m -> MYK in CMYK missing for background color",
    2022              :             "\033[58;4;45;78m -> YK in CMYK missing for underline color",
    2023              :             "\033[38;4;45;78;14m -> K in CMYK missing for foreground color",
    2024              :             "\033[38;4;256;33;98;100m -> cyan value out of bound for foreground color",
    2025              :             "\033[48;4;45;256;11;200m -> magenta value out of bound for background color",
    2026              :             "\033[58;4;45;78;256;180m -> yellow value out of bound for underline color",
    2027              :             "\033[48;4;45;78;106;256m -> black value out of bound for background color",
    2028              :             "\033[38;5m -> index missing for foreground color",
    2029              :             "\033[48;5;256m -> index out of bound for background color",
    2030              :         };
    2031           25 :         for(auto const & bad_color : invalid_colors)
    2032              :         {
    2033           24 :             snaplogger::convert_ansi::pointer_t converter(std::make_shared<snaplogger::convert_ansi>(snaplogger::ansi_output_t::ANSI_OUTPUT_PLAIN_TEXT));
    2034           72 :             converter->write(bad_color);
    2035           24 :             std::string const result(converter->read());
    2036           24 :             CATCH_REQUIRE(converter->has_invalid_data());
    2037           24 :             CATCH_REQUIRE_FALSE(result.empty()); // not super useful, but we include a changing comment
    2038           24 :         }
    2039              :     }
    2040            5 :     CATCH_END_SECTION()
    2041            5 : }
    2042              : 
    2043              : 
    2044              : 
    2045              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions