diff --git a/issues/templates/issues/issue_stacktrace.html b/issues/templates/issues/issue_stacktrace.html index 877aeb1..dae1705 100644 --- a/issues/templates/issues/issue_stacktrace.html +++ b/issues/templates/issues/issue_stacktrace.html @@ -46,7 +46,9 @@ {% if not forloop.parentloop.last or not forloop.last %}data-collapsed="true" style="height: 0px"{% endif %}> {# collapsable part #}
{# convience div for padding & border; the border is basically the top-border of the next header #} -
{# code listing #} +
{# code listing #} + {{ frame|pygmentize }} + {% comment %} {# the spread-out pX-6 in this code is intentional to ensure the padding is visible when scrolling to the right, and not visible when scrolling is possible (i.e. the text is cut-off awkwardly to hint at scrolling #}
    {% for line in frame.pre_context %}
  1. {{ line }} {# leave space to avoid collapse #}
  2. {% endfor %} @@ -55,6 +57,7 @@
  3. {{ frame.context_line }} {# leave space to avoid collapse #}
  4. {% for line in frame.post_context %}
  5. {{ line }} {# leave space to avoid collapse #}
  6. {% endfor %}
+ {% endcomment %}
{% if frame.vars %} diff --git a/requirements.txt b/requirements.txt index 6fe5dd5..248be98 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ jsonschema==4.19.* semver==3.0.* Celery[librabbitmq] django-admin-autocomplete-filter==0.7.* +pygments==2.16.* diff --git a/theme/static/css/dist/styles.css b/theme/static/css/dist/styles.css index a292bdc..54d7427 100644 --- a/theme/static/css/dist/styles.css +++ b/theme/static/css/dist/styles.css @@ -833,10 +833,6 @@ select { margin: 1rem; } -.m-6 { - margin: 1.5rem; -} - .mx-auto { margin-left: auto; margin-right: auto; @@ -854,10 +850,6 @@ select { margin-bottom: 1rem; } -.mb-6 { - margin-bottom: 1.5rem; -} - .ml-0 { margin-left: 0px; } @@ -866,10 +858,6 @@ select { margin-left: 0.25rem; } -.ml-16 { - margin-left: 4rem; -} - .ml-4 { margin-left: 1rem; } @@ -894,18 +882,6 @@ select { margin-top: 1rem; } -.mt-6 { - margin-top: 1.5rem; -} - -.ml-2 { - margin-left: 0.5rem; -} - -.mt-8 { - margin-top: 2rem; -} - .block { display: block; } @@ -962,6 +938,10 @@ select { width: 3rem; } +.w-128 { + width: 32rem; +} + .w-3\/4 { width: 75%; } @@ -974,60 +954,16 @@ select { width: 1.5rem; } -.w-96 { - width: 24rem; -} - .w-full { width: 100%; } -.w-128 { - width: 32rem; -} - -.max-w-128 { - max-width: 32rem; -} - -.max-w-screen-xl { - max-width: 1280px; -} - -.flex-auto { - flex: 1 1 auto; -} - -.flex-none { - flex: none; -} - -.flex-\[2_2_1536px\] { - flex: 2 2 1536px; -} - -.flex-\[2_2_96rem\] { - flex: 2 2 96rem; -} - -.flex-\[1_1_96rem\] { - flex: 1 1 96rem; -} - .flex-\[2_1_96rem\] { flex: 2 1 96rem; } -.flex-\[3_1_96rem\] { - flex: 3 1 96rem; -} - -.shrink-0 { - flex-shrink: 0; -} - -.grow-0 { - flex-grow: 0; +.flex-auto { + flex: 1 1 auto; } .border-collapse { @@ -1076,14 +1012,6 @@ select { appearance: none; } -.flex-row { - flex-direction: row; -} - -.flex-row-reverse { - flex-direction: row-reverse; -} - .flex-col { flex-direction: column; } @@ -1108,10 +1036,6 @@ select { align-items: center; } -.items-stretch { - align-items: stretch; -} - .justify-center { justify-content: center; } @@ -1128,12 +1052,6 @@ select { overflow-x: auto; } -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - .whitespace-nowrap { white-space: nowrap; } @@ -1235,19 +1153,14 @@ select { border-color: rgb(148 163 184 / var(--tw-border-opacity)); } -.border-slate-500 { - --tw-border-opacity: 1; - border-color: rgb(100 116 139 / var(--tw-border-opacity)); -} - .border-slate-50 { --tw-border-opacity: 1; border-color: rgb(248 250 252 / var(--tw-border-opacity)); } -.border-slate-800 { +.border-slate-500 { --tw-border-opacity: 1; - border-color: rgb(30 41 59 / var(--tw-border-opacity)); + border-color: rgb(100 116 139 / var(--tw-border-opacity)); } .bg-cyan-200 { @@ -1289,31 +1202,10 @@ select { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-red-500 { - --tw-bg-opacity: 1; - background-color: rgb(239 68 68 / var(--tw-bg-opacity)); -} - -.bg-red-50 { - --tw-bg-opacity: 1; - background-color: rgb(254 242 242 / var(--tw-bg-opacity)); -} - -.bg-blue-50 { - --tw-bg-opacity: 1; - background-color: rgb(239 246 255 / var(--tw-bg-opacity)); -} - .bg-gradient-to-r { background-image: linear-gradient(to right, var(--tw-gradient-stops)); } -.from-slate-200 { - --tw-gradient-from: #e2e8f0 var(--tw-gradient-from-position); - --tw-gradient-to: rgb(226 232 240 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - .from-slate-300 { --tw-gradient-from: #cbd5e1 var(--tw-gradient-from-position); --tw-gradient-to: rgb(203 213 225 / 0) var(--tw-gradient-to-position); @@ -1328,18 +1220,6 @@ select { padding: 1rem; } -.p-6 { - padding: 1.5rem; -} - -.p-8 { - padding: 2rem; -} - -.p-16 { - padding: 4rem; -} - .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; @@ -1362,6 +1242,10 @@ select { padding-bottom: 1rem; } +.pb-6 { + padding-bottom: 1.5rem; +} + .pl-2 { padding-left: 0.5rem; } @@ -1370,6 +1254,10 @@ select { padding-left: 1rem; } +.pl-6 { + padding-left: 1.5rem; +} + .pr-2 { padding-right: 0.5rem; } @@ -1378,6 +1266,10 @@ select { padding-right: 1rem; } +.pr-6 { + padding-right: 1.5rem; +} + .pt-2 { padding-top: 0.5rem; } @@ -1386,36 +1278,12 @@ select { padding-top: 1rem; } -.pl-8 { - padding-left: 2rem; -} - -.pr-8 { - padding-right: 2rem; -} - -.pt-8 { - padding-top: 2rem; -} - .pt-6 { padding-top: 1.5rem; } -.pb-6 { - padding-bottom: 1.5rem; -} - -.pl-6 { - padding-left: 1.5rem; -} - -.pr-6 { - padding-right: 1.5rem; -} - -.pb-8 { - padding-bottom: 2rem; +.pt-8 { + padding-top: 2rem; } .text-left { @@ -1713,6 +1581,488 @@ select { display: flex; } +/* +The below is the output of: + +``` +import pygments +with open("useme.css", 'w') as f: + HtmlFormatter().get_style_defs(".syntax-coloring", f) +``` +*/ + +pre { + line-height: 125%; +} + +td.linenos .normal { + color: inherit; + background-color: transparent; + padding-left: 5px; + padding-right: 5px; +} + +span.linenos { + color: inherit; + background-color: transparent; + padding-left: 5px; + padding-right: 5px; +} + +td.linenos .special { + color: #000000; + background-color: #ffffc0; + padding-left: 5px; + padding-right: 5px; +} + +span.linenos.special { + color: #000000; + background-color: #ffffc0; + padding-left: 5px; + padding-right: 5px; +} + +.syntax-coloring .hll { + background-color: #ffffcc +} + +.syntax-coloring { + background: #f8f8f8; +} + +.syntax-coloring .c { + color: #3D7B7B; + font-style: italic +} + +/* Comment */ + +.syntax-coloring .err { + border: 1px solid #FF0000 +} + +/* Error */ + +.syntax-coloring .k { + color: #008000; + font-weight: bold +} + +/* Keyword */ + +.syntax-coloring .o { + color: #666666 +} + +/* Operator */ + +.syntax-coloring .ch { + color: #3D7B7B; + font-style: italic +} + +/* Comment.Hashbang */ + +.syntax-coloring .cm { + color: #3D7B7B; + font-style: italic +} + +/* Comment.Multiline */ + +.syntax-coloring .cp { + color: #9C6500 +} + +/* Comment.Preproc */ + +.syntax-coloring .cpf { + color: #3D7B7B; + font-style: italic +} + +/* Comment.PreprocFile */ + +.syntax-coloring .c1 { + color: #3D7B7B; + font-style: italic +} + +/* Comment.Single */ + +.syntax-coloring .cs { + color: #3D7B7B; + font-style: italic +} + +/* Comment.Special */ + +.syntax-coloring .gd { + color: #A00000 +} + +/* Generic.Deleted */ + +.syntax-coloring .ge { + font-style: italic +} + +/* Generic.Emph */ + +.syntax-coloring .ges { + font-weight: bold; + font-style: italic +} + +/* Generic.EmphStrong */ + +.syntax-coloring .gr { + color: #E40000 +} + +/* Generic.Error */ + +.syntax-coloring .gh { + color: #000080; + font-weight: bold +} + +/* Generic.Heading */ + +.syntax-coloring .gi { + color: #008400 +} + +/* Generic.Inserted */ + +.syntax-coloring .go { + color: #717171 +} + +/* Generic.Output */ + +.syntax-coloring .gp { + color: #000080; + font-weight: bold +} + +/* Generic.Prompt */ + +.syntax-coloring .gs { + font-weight: bold +} + +/* Generic.Strong */ + +.syntax-coloring .gu { + color: #800080; + font-weight: bold +} + +/* Generic.Subheading */ + +.syntax-coloring .gt { + color: #0044DD +} + +/* Generic.Traceback */ + +.syntax-coloring .kc { + color: #008000; + font-weight: bold +} + +/* Keyword.Constant */ + +.syntax-coloring .kd { + color: #008000; + font-weight: bold +} + +/* Keyword.Declaration */ + +.syntax-coloring .kn { + color: #008000; + font-weight: bold +} + +/* Keyword.Namespace */ + +.syntax-coloring .kp { + color: #008000 +} + +/* Keyword.Pseudo */ + +.syntax-coloring .kr { + color: #008000; + font-weight: bold +} + +/* Keyword.Reserved */ + +.syntax-coloring .kt { + color: #B00040 +} + +/* Keyword.Type */ + +.syntax-coloring .m { + color: #666666 +} + +/* Literal.Number */ + +.syntax-coloring .s { + color: #BA2121 +} + +/* Literal.String */ + +.syntax-coloring .na { + color: #687822 +} + +/* Name.Attribute */ + +.syntax-coloring .nb { + color: #008000 +} + +/* Name.Builtin */ + +.syntax-coloring .nc { + color: #0000FF; + font-weight: bold +} + +/* Name.Class */ + +.syntax-coloring .no { + color: #880000 +} + +/* Name.Constant */ + +.syntax-coloring .nd { + color: #AA22FF +} + +/* Name.Decorator */ + +.syntax-coloring .ni { + color: #717171; + font-weight: bold +} + +/* Name.Entity */ + +.syntax-coloring .ne { + color: #CB3F38; + font-weight: bold +} + +/* Name.Exception */ + +.syntax-coloring .nf { + color: #0000FF +} + +/* Name.Function */ + +.syntax-coloring .nl { + color: #767600 +} + +/* Name.Label */ + +.syntax-coloring .nn { + color: #0000FF; + font-weight: bold +} + +/* Name.Namespace */ + +.syntax-coloring .nt { + color: #008000; + font-weight: bold +} + +/* Name.Tag */ + +.syntax-coloring .nv { + color: #19177C +} + +/* Name.Variable */ + +.syntax-coloring .ow { + color: #AA22FF; + font-weight: bold +} + +/* Operator.Word */ + +.syntax-coloring .w { + color: #bbbbbb +} + +/* Text.Whitespace */ + +.syntax-coloring .mb { + color: #666666 +} + +/* Literal.Number.Bin */ + +.syntax-coloring .mf { + color: #666666 +} + +/* Literal.Number.Float */ + +.syntax-coloring .mh { + color: #666666 +} + +/* Literal.Number.Hex */ + +.syntax-coloring .mi { + color: #666666 +} + +/* Literal.Number.Integer */ + +.syntax-coloring .mo { + color: #666666 +} + +/* Literal.Number.Oct */ + +.syntax-coloring .sa { + color: #BA2121 +} + +/* Literal.String.Affix */ + +.syntax-coloring .sb { + color: #BA2121 +} + +/* Literal.String.Backtick */ + +.syntax-coloring .sc { + color: #BA2121 +} + +/* Literal.String.Char */ + +.syntax-coloring .dl { + color: #BA2121 +} + +/* Literal.String.Delimiter */ + +.syntax-coloring .sd { + color: #BA2121; + font-style: italic +} + +/* Literal.String.Doc */ + +.syntax-coloring .s2 { + color: #BA2121 +} + +/* Literal.String.Double */ + +.syntax-coloring .se { + color: #AA5D1F; + font-weight: bold +} + +/* Literal.String.Escape */ + +.syntax-coloring .sh { + color: #BA2121 +} + +/* Literal.String.Heredoc */ + +.syntax-coloring .si { + color: #A45A77; + font-weight: bold +} + +/* Literal.String.Interpol */ + +.syntax-coloring .sx { + color: #008000 +} + +/* Literal.String.Other */ + +.syntax-coloring .sr { + color: #A45A77 +} + +/* Literal.String.Regex */ + +.syntax-coloring .s1 { + color: #BA2121 +} + +/* Literal.String.Single */ + +.syntax-coloring .ss { + color: #19177C +} + +/* Literal.String.Symbol */ + +.syntax-coloring .bp { + color: #008000 +} + +/* Name.Builtin.Pseudo */ + +.syntax-coloring .fm { + color: #0000FF +} + +/* Name.Function.Magic */ + +.syntax-coloring .vc { + color: #19177C +} + +/* Name.Variable.Class */ + +.syntax-coloring .vg { + color: #19177C +} + +/* Name.Variable.Global */ + +.syntax-coloring .vi { + color: #19177C +} + +/* Name.Variable.Instance */ + +.syntax-coloring .vm { + color: #19177C +} + +/* Name.Variable.Magic */ + +.syntax-coloring .il { + color: #666666 +} + +/* Literal.Number.Integer.Long */ + .hover\:border-b-4:hover { border-bottom-width: 4px; } @@ -1829,82 +2179,10 @@ select { color: rgb(37 99 235 / var(--tw-text-opacity)); } -@media (min-width: 640px) { - .sm\:bg-red-500 { - --tw-bg-opacity: 1; - background-color: rgb(239 68 68 / var(--tw-bg-opacity)); - } -} - -@media (min-width: 768px) { - .md\:bg-blue-500 { - --tw-bg-opacity: 1; - background-color: rgb(59 130 246 / var(--tw-bg-opacity)); - } -} - @media (min-width: 1024px) { .lg\:flex { display: flex; } - - .lg\:flex-\[2_1_96rem\] { - flex: 2 1 96rem; - } - - .lg\:flex-row { - flex-direction: row; - } - - .lg\:flex-col { - flex-direction: column; - } - - .lg\:items-start { - align-items: flex-start; - } -} - -@media (min-width: 1280px) { - .xl\:flex { - display: flex; - } - - .xl\:bg-yellow-500 { - --tw-bg-opacity: 1; - background-color: rgb(234 179 8 / var(--tw-bg-opacity)); - } -} - -@media (min-width: 1536px) { - .\32xl\:block { - display: block; - } - - .\32xl\:flex { - display: flex; - } - - .\32xl\:w-128 { - width: 32rem; - } - - .\32xl\:shrink-0 { - flex-shrink: 0; - } - - .\32xl\:grow-0 { - flex-grow: 0; - } - - .\32xl\:flex-row { - flex-direction: row; - } - - .\32xl\:bg-pink-500 { - --tw-bg-opacity: 1; - background-color: rgb(236 72 153 / var(--tw-bg-opacity)); - } } .peer:focus ~ .rtl\:peer-focus\:left-auto:where([dir="rtl"], [dir="rtl"] *) { diff --git a/theme/static_src/src/styles.css b/theme/static_src/src/styles.css index 95e9eac..005f390 100644 --- a/theme/static_src/src/styles.css +++ b/theme/static_src/src/styles.css @@ -101,3 +101,88 @@ .dropdown:hover .dropdown-content-left, .dropdown:hover .dropdown-content-right { display: flex; } + +/* +The below is the output of: + +``` +import pygments +with open("useme.css", 'w') as f: + HtmlFormatter().get_style_defs(".syntax-coloring", f) +``` +*/ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.syntax-coloring .hll { background-color: #ffffcc } +.syntax-coloring { background: #f8f8f8; } +.syntax-coloring .c { color: #3D7B7B; font-style: italic } /* Comment */ +.syntax-coloring .err { border: 1px solid #FF0000 } /* Error */ +.syntax-coloring .k { color: #008000; font-weight: bold } /* Keyword */ +.syntax-coloring .o { color: #666666 } /* Operator */ +.syntax-coloring .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.syntax-coloring .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.syntax-coloring .cp { color: #9C6500 } /* Comment.Preproc */ +.syntax-coloring .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.syntax-coloring .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.syntax-coloring .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ +.syntax-coloring .gd { color: #A00000 } /* Generic.Deleted */ +.syntax-coloring .ge { font-style: italic } /* Generic.Emph */ +.syntax-coloring .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.syntax-coloring .gr { color: #E40000 } /* Generic.Error */ +.syntax-coloring .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.syntax-coloring .gi { color: #008400 } /* Generic.Inserted */ +.syntax-coloring .go { color: #717171 } /* Generic.Output */ +.syntax-coloring .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.syntax-coloring .gs { font-weight: bold } /* Generic.Strong */ +.syntax-coloring .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.syntax-coloring .gt { color: #0044DD } /* Generic.Traceback */ +.syntax-coloring .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.syntax-coloring .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.syntax-coloring .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.syntax-coloring .kp { color: #008000 } /* Keyword.Pseudo */ +.syntax-coloring .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.syntax-coloring .kt { color: #B00040 } /* Keyword.Type */ +.syntax-coloring .m { color: #666666 } /* Literal.Number */ +.syntax-coloring .s { color: #BA2121 } /* Literal.String */ +.syntax-coloring .na { color: #687822 } /* Name.Attribute */ +.syntax-coloring .nb { color: #008000 } /* Name.Builtin */ +.syntax-coloring .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.syntax-coloring .no { color: #880000 } /* Name.Constant */ +.syntax-coloring .nd { color: #AA22FF } /* Name.Decorator */ +.syntax-coloring .ni { color: #717171; font-weight: bold } /* Name.Entity */ +.syntax-coloring .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ +.syntax-coloring .nf { color: #0000FF } /* Name.Function */ +.syntax-coloring .nl { color: #767600 } /* Name.Label */ +.syntax-coloring .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.syntax-coloring .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.syntax-coloring .nv { color: #19177C } /* Name.Variable */ +.syntax-coloring .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.syntax-coloring .w { color: #bbbbbb } /* Text.Whitespace */ +.syntax-coloring .mb { color: #666666 } /* Literal.Number.Bin */ +.syntax-coloring .mf { color: #666666 } /* Literal.Number.Float */ +.syntax-coloring .mh { color: #666666 } /* Literal.Number.Hex */ +.syntax-coloring .mi { color: #666666 } /* Literal.Number.Integer */ +.syntax-coloring .mo { color: #666666 } /* Literal.Number.Oct */ +.syntax-coloring .sa { color: #BA2121 } /* Literal.String.Affix */ +.syntax-coloring .sb { color: #BA2121 } /* Literal.String.Backtick */ +.syntax-coloring .sc { color: #BA2121 } /* Literal.String.Char */ +.syntax-coloring .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.syntax-coloring .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.syntax-coloring .s2 { color: #BA2121 } /* Literal.String.Double */ +.syntax-coloring .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ +.syntax-coloring .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.syntax-coloring .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ +.syntax-coloring .sx { color: #008000 } /* Literal.String.Other */ +.syntax-coloring .sr { color: #A45A77 } /* Literal.String.Regex */ +.syntax-coloring .s1 { color: #BA2121 } /* Literal.String.Single */ +.syntax-coloring .ss { color: #19177C } /* Literal.String.Symbol */ +.syntax-coloring .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.syntax-coloring .fm { color: #0000FF } /* Name.Function.Magic */ +.syntax-coloring .vc { color: #19177C } /* Name.Variable.Class */ +.syntax-coloring .vg { color: #19177C } /* Name.Variable.Global */ +.syntax-coloring .vi { color: #19177C } /* Name.Variable.Instance */ +.syntax-coloring .vm { color: #19177C } /* Name.Variable.Magic */ +.syntax-coloring .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/theme/templatetags/issues.py b/theme/templatetags/issues.py index 1ad371a..9ec6832 100644 --- a/theme/templatetags/issues.py +++ b/theme/templatetags/issues.py @@ -1,7 +1,20 @@ from django import template +from pygments import highlight +from pygments.lexers import PythonLexer +from pygments.formatters import HtmlFormatter +from django.utils.safestring import mark_safe + + register = template.Library() +@register.filter +def pygmentize(value): + # first, get the actual code from the frame + code = "\n".join(value['pre_context'] + [value['context_line']] + value['post_context']) + return(mark_safe(highlight(code, PythonLexer(), HtmlFormatter()))) + + @register.filter(name='firstlineno') def firstlineno(value): return value['lineno'] - len(value['pre_context'])