├── .gitignore ├── Procfile ├── README.rst ├── extra_templates └── jinja2 │ └── demo │ └── a.html ├── images ├── 404.png └── 500.png ├── manage.py ├── package-lock.json ├── package.json ├── postcss.config.js ├── tailwind.config.js ├── technicalerrors ├── __init__.py ├── static │ ├── init.d.ts │ ├── init.js │ ├── init.js.map │ ├── init.ts │ ├── input.css │ └── tailwind.css └── templates │ ├── django-logo-positive-original.svg │ ├── django-logo-positive.svg │ ├── technical_404.html │ └── technical_500.html ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | .envrc 2 | node_modules 3 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | django: ag -l --python | entr -r -d -z python -O -B manage.py runserver 0:8000 2 | tailwind: postcss technicalerrors/static/input.css --verbose --watch --output technicalerrors/static/tailwind.css 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | django-technicalerrors 2 | ====================== 3 | 4 | :author: Keryn Knight 5 | :version: 0.1.0 6 | 7 | A reusable `Django`_ application which provides alternate templates for the error 8 | pages shown when `DEBUG = True` 9 | 10 | 11 | Screenshots 12 | ----------- 13 | 14 | These are heavily work-in-progress, as I think through the various bits... 15 | 16 | 500 (Server Error) 17 | ^^^^^^^^^^^^^^^^^^ 18 | 19 | .. image:: https://raw.githubusercontent.com/kezabelle/django-technicalerrors/main/images/500.png 20 | :alt: technical 500 page 21 | :width: 400px 22 | :align: left 23 | :target: https://raw.githubusercontent.com/kezabelle/django-technicalerrors/main/images/500.png 24 | 25 | 26 | 404 (Not found) 27 | ^^^^^^^^^^^^^^^^^^ 28 | 29 | .. image:: https://raw.githubusercontent.com/kezabelle/django-technicalerrors/main/images/404.png 30 | :alt: technical 404 page 31 | :width: 400px 32 | :align: left 33 | :target: https://raw.githubusercontent.com/kezabelle/django-technicalerrors/main/images/404.png 34 | 35 | Why though? 36 | ----------- 37 | 38 | Once upon a time, when the web was younger and simpler, I was a web designer. Times changed, the world of frontend exploded and things have changed enough that I'm not super familiar with things like `Tailwind`_, nor as familar with `TypeScript`_ as I'd like. 39 | 40 | To a degree then, this is just a toy repository for me to explore `Tailwind`_ and 41 | to a lesser extent, `TypeScript`_. 42 | 43 | Along the way, I may produce screens which are *subjectively* better than those 44 | currently bundled with `Django`_, whose error pages have largely stood still (and arguably stood the test of time) since 45 | **2005**. 46 | 47 | Goals 48 | ----- 49 | 50 | - Maintain the same level of information the current debug pages have (because 51 | that's all the context data I have). 52 | - Responsive. 53 | - Dark mode support. 54 | - Clarity of information. If it's harder to see the information, well, job failed. 55 | - Accessible. Mostly because I don't know as much about modern a11y as I should. 56 | - Ideally, reader mode friendly. I'm not sure how achievable that is, but it'd 57 | be super nice if the extraneous visuals *could* be stripped away by the browser. 58 | 59 | Non-goals 60 | --------- 61 | 62 | - TODO :) 63 | 64 | Targets 65 | ------- 66 | 67 | - Technical 404 page 68 | - Technical 500 page 69 | - ... others? 70 | 71 | Notes 72 | ----- 73 | 74 | There's a number of differences between the data given to the 500 and 404 pages, which I'd need to get fixed upstream to be consistent, but that's likely a hard sell if they're not *used* ... 75 | 76 | - Unfortunately, the context given to the **404** page doesn't include any of the following: 77 | 78 | - The Django version (e.g. ``4.0.1``) 79 | - The Python version (e.g. ``3.9.5``) 80 | - The server time (e.g. ``Fri, 21 Jan 2022 20:47:51 +0000``) 81 | - The frame which caused the ``Http404`` to be thrown. 82 | - Ideally the *source* lines shown in the **template** and **traceback** panels would be fixed up using ``textwrap.dedent`` based on the ``[top:bottom]`` being selected. 83 | - None of the contexts return the HTTP status code, which would mean having to hard-code the individual values if I wanted to suggest which HTML template would be rendered instead, in production. Not problematic, really ... 84 | 85 | .. _Django: https://docs.djangoproject.com/ 86 | .. _Tailwind: https://tailwindcss.com/ 87 | .. _TypeScript: https://www.typescriptlang.org/ 88 | -------------------------------------------------------------------------------- /extra_templates/jinja2/demo/a.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | test 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kezabelle/django-technicalerrors/8bafe7f756de177c11fd0bc3a43295449ef3b350/images/404.png -------------------------------------------------------------------------------- /images/500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kezabelle/django-technicalerrors/8bafe7f756de177c11fd0bc3a43295449ef3b350/images/500.png -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from datetime import datetime 4 | from tempfile import gettempdir 5 | 6 | import django 7 | from django.conf import settings 8 | from django.http import HttpResponse, Http404 9 | from django.urls import path, re_path, include 10 | from django.template.loader import select_template 11 | from django.template import Template, Context 12 | 13 | HAS_JINJA = False 14 | HAS_PATTERNLIBRARY = False 15 | HAS_LIVERELOADISH = False 16 | HAS_SHOUTY_TEMPLATES = False 17 | 18 | try: 19 | import jinja2 20 | HAS_JINJA = True 21 | except ModuleNotFoundError: 22 | sys.stderr.write("`jinja2` is necessary for this demo project") 23 | sys.exit(1) 24 | 25 | 26 | EXTRA_INSTALLED_APPS = () 27 | EXTRA_MIDDLEWARE = () 28 | 29 | USE_TECHNICALERRORS = os.environ.get("USE_TECHNICALERRORS", "1").lower() in { 30 | "1", 31 | "t", 32 | "true", 33 | "ok", 34 | "yes", 35 | } 36 | if USE_TECHNICALERRORS: 37 | EXTRA_INSTALLED_APPS += ("technicalerrors.TechnicalErrors",) 38 | 39 | try: 40 | from livereloadish import watch_file 41 | 42 | EXTRA_INSTALLED_APPS += ("livereloadish",) 43 | EXTRA_MIDDLEWARE += ("livereloadish.middleware.LivereloadishMiddleware",) 44 | HAS_LIVERELOADISH = True 45 | except ModuleNotFoundError: 46 | pass 47 | 48 | try: 49 | import pattern_library 50 | 51 | EXTRA_INSTALLED_APPS += ("pattern_library.apps.PatternLibraryAppConfig",) 52 | HAS_PATTERNLIBRARY = True 53 | except ModuleNotFoundError: 54 | pass 55 | 56 | try: 57 | import shouty 58 | # TODO: set this up and make sure the contexts are good. 59 | # EXTRA_INSTALLED_APPS += ("shouty.Shout",) 60 | HAS_SHOUTY_TEMPLATES = True 61 | except ModuleNotFoundError: 62 | pass 63 | 64 | 65 | HERE = os.path.abspath(os.path.dirname(__file__)) 66 | 67 | 68 | if not settings.configured: 69 | settings.configure( 70 | SECRET_KEY="??????????????????????????????????????????????????????????", 71 | DEBUG=True, 72 | INSTALLED_APPS=( 73 | "django.contrib.staticfiles", 74 | "django.contrib.contenttypes", 75 | "django.contrib.auth", 76 | "django.contrib.messages", 77 | "django.contrib.sessions", 78 | "django.contrib.admin", 79 | "django.contrib.admindocs", 80 | ) 81 | + EXTRA_INSTALLED_APPS, 82 | ALLOWED_HOSTS=("*"), 83 | ROOT_URLCONF=__name__, 84 | MIDDLEWARE=( 85 | "django.contrib.sessions.middleware.SessionMiddleware", 86 | "django.contrib.auth.middleware.AuthenticationMiddleware", 87 | "django.contrib.messages.middleware.MessageMiddleware", 88 | ) 89 | + EXTRA_MIDDLEWARE, 90 | TEMPLATES=[ 91 | { 92 | "BACKEND": "django.template.backends.django.DjangoTemplates", 93 | "DIRS": (os.path.join(HERE, "extra_templates"),), 94 | "APP_DIRS": True, 95 | "OPTIONS": { 96 | "context_processors": ( 97 | "django.template.context_processors.request", 98 | "django.contrib.auth.context_processors.auth", 99 | "django.contrib.messages.context_processors.messages", 100 | ), 101 | "builtins": ["pattern_library.loader_tags"] if HAS_PATTERNLIBRARY else [], 102 | }, 103 | }, 104 | { 105 | "BACKEND": "django.template.backends.jinja2.Jinja2", 106 | "DIRS": [os.path.join(HERE, "extra_templates")], 107 | "APP_DIRS": True, 108 | "OPTIONS": { 109 | "environment": "jinja2.Environment", 110 | # Not recommended, but supported 111 | "context_processors": ( 112 | "django.template.context_processors.request", 113 | "django.contrib.messages.context_processors.messages", 114 | ), 115 | }, 116 | }, 117 | ], 118 | LOGGING={ 119 | "version": 1, 120 | "disable_existing_loggers": False, 121 | "handlers": { 122 | "console": { 123 | "class": "logging.StreamHandler", 124 | }, 125 | }, 126 | "loggers": { 127 | "livereloadish": { 128 | "handlers": ["console"], 129 | "level": "WARNING", 130 | "propagate": False, 131 | }, 132 | "django.template": { 133 | "handlers": ["console"], 134 | "level": "DEBUG", 135 | "propagate": False, 136 | }, 137 | }, 138 | }, 139 | STATIC_URL="/static/", 140 | USE_I18N=True, 141 | USE_TZ=True, 142 | TIME_ZONE="UTC", 143 | X_FRAME_OPTIONS="SAMEORIGIN", 144 | PATTERN_LIBRARY={ 145 | "SECTIONS": ( 146 | ("components", ["patterns/components"]), 147 | ("pages", ["patterns/pages"]), 148 | ), 149 | "TEMPLATE_SUFFIX": ".html", 150 | "PATTERN_BASE_TEMPLATE_NAME": "patterns/base.html", 151 | "BASE_TEMPLATE_NAMES": ["patterns/base_page.html"], 152 | }, 153 | ) 154 | django.setup() 155 | 156 | from django.contrib import admin 157 | from django.contrib.admindocs import urls as admindocs_urls 158 | 159 | 160 | def demo404(request, *args, **kwargs) -> HttpResponse: 161 | raise Http404("Custom message") 162 | 163 | 164 | def demo404_with_long_message(request, *args, **kwargs) -> HttpResponse: 165 | raise Http404("Ruined"*50) 166 | 167 | 168 | def nested3(): 169 | filename = os.path.join( 170 | gettempdir(), 171 | "a_long_path", 172 | "that_probably", 173 | "goes_off_screen", 174 | "and_causes_wrapping_issues", 175 | "elsewhere", 176 | "on_the_page", 177 | "that_need_addressing", 178 | "a_random_file_that_shouldnt_exist.mp3", 179 | ) 180 | with open(filename, "rb") as f: 181 | return f.read() 182 | 183 | 184 | def nested2(): 185 | a = 1 186 | b = {1, 2, 3} 187 | c = (1, 2, 3) 188 | a_really_long_variable_name = 4 189 | nested_var = {"a": a, "b": b, "c": c} 190 | a_really_long_variable_value = "Ruined" * 50 191 | try: 192 | return nested3() 193 | except ZeroDivisionError as exc: 194 | raise ValueError("Ruined") 195 | except FileNotFoundError as exc: 196 | raise TypeError( 197 | "RuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuinedRuined" 198 | ) from exc 199 | 200 | 201 | def nested1(): 202 | nested_var = datetime.utcnow() 203 | return nested2() 204 | 205 | 206 | def nested(): 207 | nested_var = 1 208 | return nested1() 209 | 210 | 211 | def demo500(request) -> None: 212 | var = nested() 213 | 214 | 215 | def demo500templatemissing(request): 216 | return select_template(("demo/a.html", "demo/b.html", "demo/c.html", "demo/d.html")) 217 | 218 | 219 | def demo500templatesyntax(request): 220 | return Template( 221 | """Line 1 222 | More lines go here 223 | and then some 224 | and soon we'll maybe get to the error? 225 | Nah let's keep going 226 | Here's some HTML to keep us going 227 |
228 |
229 |
230 |
231 | Go away, line 1! 232 | Example template {{ 'syntax'|bad_filter }} some really long line error that might cause issues on small screens 233 | Ok now we've done the error 234 | How much more do we show afterwards? 235 | Got to be a few lines right? 236 | Probably... 237 | 5 or 10 maybe? 238 | Looks like 10, so onwards we go... 239 | At some point the EOF will get cut off. 240 | But not yet, lines aplenty 241 | Keep it up, nearly there 242 | One more line perhaps? Boom there it is. 243 | EOF""" 244 | ) 245 | 246 | 247 | def demo500unicodeencode(request): 248 | "🤞😡🤬👊😔".encode("ascii") 249 | 250 | 251 | def demo500unicodedecode(request): 252 | b"\xf0\x9f\xa4\x9e\xf0\x9f\x98\xa1\xf0\x9f\xa4\xac\xf0\x9f\x91\x8a\xf0\x9f\x98\x94".decode( 253 | "ascii" 254 | ) 255 | 256 | from django.template.response import TemplateResponse 257 | 258 | def index(request): 259 | class PatchedTemplate(Template): 260 | def render(self, context, request=None): 261 | return super().render(context=context) 262 | 263 | return TemplateResponse(request, PatchedTemplate(""" 264 | 265 | 278 | {{ something.goes.here }} 279 | 280 | """), Context({'something': {'goes': {}}})) 281 | 282 | 283 | 284 | urlpatterns = [ 285 | path("admin/docs/", include(admindocs_urls)), 286 | path("admin/", admin.site.urls), 287 | re_path("^404/" + '_'.join(['ruined']*30), demo404_with_long_message, name="demo404_ruined"), 288 | path("404/", demo404, name="demo404_with_value_arg"), 289 | re_path("^404/(.+)", demo404, name="demo404_with_any_args"), 290 | path("404", demo404, name="demo404"), 291 | path( 292 | "500/", 293 | include( 294 | ( 295 | [ 296 | re_path( 297 | "^unicode/", 298 | include( 299 | ( 300 | [ 301 | path( 302 | "decode", 303 | demo500unicodedecode, 304 | name="demo500unicodedecode", 305 | ), 306 | path( 307 | "encode", 308 | demo500unicodeencode, 309 | name="demo500unicodeencode", 310 | ), 311 | ], 312 | "unicodes", 313 | ) 314 | ), 315 | ), 316 | path( 317 | "inucedo/other_path", 318 | demo500unicodedecode, 319 | name="same_length_as_unicode", 320 | ), 321 | path( 322 | "template/syntax", 323 | demo500templatesyntax, 324 | name="demo500templatesyntax", 325 | ), 326 | path( 327 | "template/missing", 328 | demo500templatemissing, 329 | name="demo500templatemissing", 330 | ), 331 | ], 332 | "nested_appname", 333 | ) 334 | ), 335 | ), 336 | path("500", demo500, name="demo500"), 337 | path("", index, name="index"), 338 | ] 339 | if HAS_PATTERNLIBRARY: 340 | urlpatterns += [ 341 | path("pattern-library/", include("pattern_library.urls")), 342 | ] 343 | 344 | 345 | if __name__ == "__main__": 346 | from django.core import management 347 | 348 | management.execute_from_command_line() 349 | else: 350 | from django.core.wsgi import get_wsgi_application 351 | 352 | application = get_wsgi_application() 353 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@fullhuman/postcss-purgecss": "^4.1.3", 4 | "@tailwindcss/typography": "^0.5.0", 5 | "autoprefixer": "^10.4.2", 6 | "cssnano": "^5.0.15", 7 | "cssnano-preset-advanced": "^5.1.10", 8 | "postcss": "^8.4.5", 9 | "postcss-cli": "^9.1.0", 10 | "tailwindcss": "^3.0.15" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('tailwindcss'), 4 | require('autoprefixer'), 5 | // require('cssnano')({'preset': "advanced"}), 6 | require('@fullhuman/postcss-purgecss')({ 7 | content: ['**/templates/*.html'], 8 | variables: true, 9 | keyframes: true, 10 | fontFace: true, 11 | defaultExtractor: content => content.match(/[\w-/:]+(? bool: 15 | return requires_full_reload 16 | 17 | 18 | try: 19 | old_builtin_template_path = debug.builtin_template_path 20 | old_current_dir = None 21 | except AttributeError as e: 22 | old_builtin_template_path = None 23 | old_current_dir = debug.CURRENT_DIR 24 | 25 | 26 | logger = logging.getLogger(__name__) 27 | __all__ = ["TechnicalErrors"] 28 | 29 | 30 | def new_builtin_template_path(name): 31 | new_path = Path(__file__).parent / "templates" / name 32 | if os.path.exists(new_path): 33 | watch_file(new_path.name, str(new_path), requires_full_reload=True) 34 | return new_path 35 | return old_builtin_template_path(name) 36 | 37 | 38 | default_app_config = "technicalerrors.TechnicalErrors" 39 | 40 | 41 | class TechnicalErrors(AppConfig): 42 | name = "technicalerrors" 43 | 44 | def ready(self) -> bool: 45 | return self.patch(settings.DEBUG) 46 | 47 | def patch(self, enabled: bool) -> bool: 48 | if enabled: 49 | if old_current_dir is not None: 50 | debug.CURRENT_DIR = Path(__file__).parent 51 | for file in (debug.CURRENT_DIR / "templates").iterdir(): 52 | if file.is_file(): 53 | watch_file(file.name, str(file), requires_full_reload=True) 54 | return True 55 | elif old_builtin_template_path is not None: 56 | debug.builtin_template_path = new_builtin_template_path 57 | return True 58 | return False 59 | return False 60 | -------------------------------------------------------------------------------- /technicalerrors/static/init.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kezabelle/django-technicalerrors/8bafe7f756de177c11fd0bc3a43295449ef3b350/technicalerrors/static/init.d.ts -------------------------------------------------------------------------------- /technicalerrors/static/init.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | ; 3 | (function () { 4 | "use strict"; 5 | const setUp = () => { 6 | const allPanels = document.querySelectorAll('[data-tab-target]'); 7 | const showable = document.querySelectorAll('[data-toggle-target]'); 8 | const hidePanel = (element) => { 9 | const panelSelector = element.dataset.tabTarget || ""; 10 | if (panelSelector !== "") { 11 | const panel = document.querySelector(panelSelector); 12 | if (panel !== null) { 13 | panel.classList.add('hidden'); 14 | element.classList.remove("active"); 15 | } 16 | } 17 | }; 18 | const showHideOthers = (event) => { 19 | const element = event.target; 20 | if (element !== null) { 21 | const panelSelector = element.dataset.tabTarget || ""; 22 | if (panelSelector !== "") { 23 | const panel = document.querySelector(panelSelector); 24 | if (panel !== null) { 25 | allPanels.forEach(hidePanel); 26 | panel.classList.remove('hidden'); 27 | element.classList.add("active"); 28 | } 29 | } 30 | } 31 | }; 32 | const show = (element, panel) => { 33 | if (panel.classList.contains("hidden")) { 34 | panel.classList.remove('hidden'); 35 | } 36 | else { 37 | panel.classList.add('hidden'); 38 | } 39 | element.classList.add("active"); 40 | }; 41 | const showBoxContents = (event) => { 42 | const element = event.target; 43 | if (element !== null) { 44 | const toggleSelector = element.dataset.toggleTarget || ""; 45 | if (toggleSelector !== "") { 46 | const panel = document.querySelector(toggleSelector); 47 | if (panel !== null) { 48 | return show(element, panel); 49 | } 50 | } 51 | } 52 | }; 53 | class Tooltip { 54 | constructor(element, template = '') { 55 | this.owner = element; 56 | const parsedTemplate = new DOMParser().parseFromString(template, 'text/html').body.firstElementChild; 57 | if (parsedTemplate === null) { 58 | throw new Error("No HTML parsed"); 59 | } 60 | this.template = parsedTemplate; 61 | this.open = false; 62 | this.show = this.show.bind(this); 63 | this.hide = this.hide.bind(this); 64 | this.maybeHide = this.maybeHide.bind(this); 65 | this.bind(); 66 | } 67 | static ready(selector) { 68 | const foundTips = document.querySelectorAll(selector); 69 | return foundTips.forEach((value) => { 70 | return new Tooltip(value); 71 | }); 72 | } 73 | bind() { 74 | this.owner.addEventListener("touchstart", this.show); 75 | this.owner.addEventListener("mouseenter", this.show); 76 | } 77 | unbind() { 78 | this.owner.removeEventListener("touchstart", this.show); 79 | this.owner.removeEventListener("mouseenter", this.show); 80 | this.owner.removeEventListener("mouseleave", this.hide); 81 | } 82 | show(event) { 83 | if (!this.open) { 84 | event.stopPropagation(); 85 | // Remove opportunities to try and show this again WHILE it is open. 86 | this.owner.removeEventListener("touchstart", this.show); 87 | this.owner.removeEventListener("mouseenter", this.show); 88 | // Set up the listeners to handle removing this 89 | this.owner.addEventListener("mouseleave", this.hide); 90 | document.addEventListener("touchstart", this.maybeHide); 91 | document.addEventListener("scroll", this.maybeHide); 92 | document.addEventListener("keydown", this.maybeHide); 93 | const { x, y, height, width } = this.owner.getBoundingClientRect(); 94 | console.log('show', event); 95 | const yTether = (y + height + (height / 2)).toFixed(0); 96 | const xTether = (x + (width / 2)).toFixed(0); 97 | this.template.textContent = this.owner.getAttribute("aria-label"); 98 | this.template.style.top = `${yTether}px`; 99 | this.template.style.left = `${xTether}px`; 100 | this.owner.dataset.tooltipIsOpen = 'true'; 101 | this.owner.classList.add("tooltip-open"); 102 | document.body.appendChild(this.template); 103 | // Await any animations which run on DOM node creation 104 | Promise.allSettled(this.template.getAnimations().map((animation) => animation.finished)).then(() => { 105 | this.template.classList.add("open"); 106 | // Await any animations which run on entering. 107 | Promise.allSettled(this.template.getAnimations().map((animation) => animation.finished)).then(() => { 108 | this.open = true; 109 | }); 110 | }); 111 | } 112 | } 113 | hide(event) { 114 | if (this.open) { 115 | console.log('hide', event); 116 | // Remove opportunities to try and hide this again WHILE it is hidden. 117 | this.owner.removeEventListener("mouseleave", this.hide); 118 | document.removeEventListener("touchstart", this.maybeHide); 119 | document.removeEventListener("scroll", this.maybeHide); 120 | document.removeEventListener("keydown", this.maybeHide); 121 | // Set up the listeners to handle showing this again subsequently. 122 | this.owner.addEventListener("touchstart", this.show); 123 | this.owner.addEventListener("mouseenter", this.show); 124 | this.owner.classList.remove("tooltip-open"); 125 | this.owner.dataset.tooltipIsOpen = 'false'; 126 | this.template.classList.remove("open"); 127 | // Await any animations which occur when open is removed and it's leaving 128 | Promise.allSettled(this.template.getAnimations().map((animation) => animation.finished)).then(() => { 129 | document.body.removeChild(this.template); 130 | this.open = false; 131 | }); 132 | } 133 | } 134 | maybeHide(event) { 135 | if (this.open) { 136 | console.log('maybe hide', event); 137 | if (event.type === 'scroll') { 138 | return this.hide(event); 139 | } 140 | else if (event.type === 'keydown' && event.key === "Escape") { 141 | // Pressing escape should hide the tooltip for Accessibility reasons. 142 | // Stop the propagation to prevent this having any other consequences. 143 | event.stopPropagation(); 144 | return this.hide(event); 145 | } 146 | else if (event.target !== this.owner) { 147 | return this.hide(event); 148 | } 149 | } 150 | } 151 | } 152 | class ExpandableBox { 153 | constructor(element) { 154 | this.owner = element; 155 | this.show = this.show.bind(this); 156 | this.bind(); 157 | } 158 | bind() { 159 | if (this.owner.classList.contains("inactive") || !this.owner.classList.contains("active")) { 160 | this.owner.addEventListener("click", this.show); 161 | } 162 | } 163 | static ready(selector) { 164 | const foundTraces = document.querySelectorAll(selector); 165 | return foundTraces.forEach((value) => { 166 | return new ExpandableBox(value); 167 | }); 168 | } 169 | show(event) { 170 | if (this.owner.classList.contains("active")) { 171 | return; 172 | } 173 | this.owner.classList.add('active'); 174 | this.owner.classList.remove('inactive'); 175 | const { x, y, top } = this.owner.getBoundingClientRect(); 176 | const { scrollX, scrollY } = window; 177 | const goTo = scrollY + top; 178 | // if (goTo > scrollY) { 179 | const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); 180 | if (reducedMotion.matches) { 181 | return; 182 | } 183 | // Don't perform any auto-scrolling if it's not smooth... 184 | if (!('scrollBehavior' in document.documentElement.style)) { 185 | return; 186 | } 187 | window.scroll({ 188 | top: goTo, 189 | behavior: 'smooth' 190 | }); 191 | // } else { 192 | // window.scrollTo(scrollX, scrollY); 193 | // } 194 | // const silencedChildren: NodeListOf = this.owner.querySelectorAll('.traceback-locals, .traceback-context'); 195 | // silencedChildren.forEach((value) => { 196 | // value.classList.remove('hidden'); 197 | // }); 198 | // const contextLine: HTMLElement | null = this.owner.querySelector('.active'); 199 | // if (contextLine) { 200 | // contextLine.classList.add('bg-red-500'); 201 | // contextLine.classList.add('text-white') 202 | // } 203 | } 204 | } 205 | allPanels.forEach((value) => { 206 | value.addEventListener("click", showHideOthers); 207 | }); 208 | showable.forEach((value) => { 209 | value.addEventListener("click", showBoxContents); 210 | }); 211 | const initialTab = document.location.hash; 212 | if (initialTab !== '') { 213 | allPanels.forEach((value) => { 214 | if (value.dataset.tabTarget === initialTab) { 215 | value.click(); 216 | } 217 | }); 218 | } 219 | Tooltip.ready('[data-tooltip-target]'); 220 | ExpandableBox.ready('[data-expandable]'); 221 | const copyToClipboardButton = document.querySelector('.traceback-clipboard'); 222 | const copyToClipboardContents = document.getElementById("traceback_area"); 223 | if (copyToClipboardButton !== null && copyToClipboardContents !== null) { 224 | const originalText = copyToClipboardButton.textContent; 225 | copyToClipboardButton.addEventListener('click', () => { 226 | navigator.clipboard.writeText(copyToClipboardContents.value).then(function () { 227 | copyToClipboardButton.textContent = "Copied!"; 228 | setTimeout(() => { 229 | copyToClipboardButton.textContent = originalText; 230 | }, 1000); 231 | }, function () { 232 | copyToClipboardButton.textContent = "Failed to copy"; 233 | setTimeout(() => { 234 | copyToClipboardButton.textContent = originalText; 235 | }, 1000); 236 | }); 237 | }); 238 | } 239 | }; 240 | if (document.readyState !== 'loading') { 241 | console.debug("ready"); 242 | return setUp(); 243 | } 244 | else { 245 | return document.addEventListener('DOMContentLoaded', setUp); 246 | } 247 | })(); 248 | //# sourceMappingURL=init.js.map -------------------------------------------------------------------------------- /technicalerrors/static/init.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"init.js","sourceRoot":"","sources":["init.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /technicalerrors/static/init.ts: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | "use strict"; 3 | const setUp = () => { 4 | 5 | const allPanels: NodeListOf = document.querySelectorAll('[data-tab-target]'); 6 | const showable: NodeListOf = document.querySelectorAll('[data-toggle-target]'); 7 | 8 | const hidePanel = (element: HTMLElement) => { 9 | const panelSelector = element.dataset.tabTarget || ""; 10 | if (panelSelector !== "") { 11 | const panel = document.querySelector(panelSelector); 12 | if (panel !== null) { 13 | panel.classList.add('hidden'); 14 | element.classList.remove("active"); 15 | } 16 | } 17 | } 18 | 19 | const showHideOthers = (event: Event) => { 20 | const element = event.target as HTMLElement | null; 21 | if (element !== null) { 22 | const panelSelector = element.dataset.tabTarget || ""; 23 | if (panelSelector !== "") { 24 | const panel = document.querySelector(panelSelector); 25 | if (panel !== null) { 26 | allPanels.forEach(hidePanel); 27 | panel.classList.remove('hidden'); 28 | element.classList.add("active"); 29 | } 30 | } 31 | } 32 | } 33 | 34 | const show = (element: HTMLElement, panel: Element) => { 35 | if (panel.classList.contains("hidden")) { 36 | panel.classList.remove('hidden'); 37 | } else { 38 | panel.classList.add('hidden'); 39 | } 40 | element.classList.add("active"); 41 | } 42 | 43 | const showBoxContents = (event: Event) => { 44 | const element = event.target as HTMLElement | null; 45 | if (element !== null) { 46 | const toggleSelector = element.dataset.toggleTarget || ""; 47 | if (toggleSelector !== "") { 48 | const panel = document.querySelector(toggleSelector); 49 | if (panel !== null) { 50 | return show(element, panel); 51 | } 52 | } 53 | } 54 | } 55 | 56 | class Tooltip { 57 | private owner: HTMLElement; 58 | public template: HTMLElement; 59 | private open: boolean; 60 | 61 | constructor(element: HTMLElement, template: string = '') { 62 | this.owner = element; 63 | const parsedTemplate = new DOMParser().parseFromString(template, 'text/html').body.firstElementChild as HTMLElement | null; 64 | if (parsedTemplate === null) { 65 | throw new Error("No HTML parsed") 66 | } 67 | this.template = parsedTemplate; 68 | this.open = false; 69 | this.show = this.show.bind(this); 70 | this.hide = this.hide.bind(this); 71 | this.maybeHide = this.maybeHide.bind(this); 72 | this.bind(); 73 | } 74 | 75 | static ready(selector: string) { 76 | const foundTips: NodeListOf = document.querySelectorAll(selector); 77 | return foundTips.forEach((value) => { 78 | return new Tooltip(value); 79 | }); 80 | } 81 | 82 | bind() { 83 | this.owner.addEventListener("touchstart", this.show); 84 | this.owner.addEventListener("mouseenter", this.show); 85 | } 86 | 87 | unbind() { 88 | this.owner.removeEventListener("touchstart", this.show); 89 | this.owner.removeEventListener("mouseenter", this.show); 90 | this.owner.removeEventListener("mouseleave", this.hide); 91 | } 92 | 93 | show(event: MouseEvent | PointerEvent | TouchEvent) { 94 | if (!this.open) { 95 | event.stopPropagation(); 96 | 97 | // Remove opportunities to try and show this again WHILE it is open. 98 | this.owner.removeEventListener("touchstart", this.show); 99 | this.owner.removeEventListener("mouseenter", this.show); 100 | 101 | // Set up the listeners to handle removing this 102 | this.owner.addEventListener("mouseleave", this.hide); 103 | document.addEventListener("touchstart", this.maybeHide); 104 | document.addEventListener("scroll", this.maybeHide); 105 | document.addEventListener("keydown", this.maybeHide); 106 | 107 | const {x, y, height, width} = this.owner.getBoundingClientRect(); 108 | console.log('show', event); 109 | 110 | const yTether = (y + height + (height / 2)).toFixed(0); 111 | const xTether = (x + (width / 2)).toFixed(0); 112 | this.template.textContent = this.owner.getAttribute("aria-label"); 113 | this.template.style.top = `${yTether}px`; 114 | this.template.style.left = `${xTether}px`; 115 | 116 | this.owner.dataset.tooltipIsOpen = 'true'; 117 | this.owner.classList.add("tooltip-open"); 118 | document.body.appendChild(this.template); 119 | 120 | // Await any animations which run on DOM node creation 121 | Promise.allSettled(this.template.getAnimations().map( 122 | (animation) => animation.finished 123 | )).then(() => { 124 | this.template.classList.add("open"); 125 | 126 | // Await any animations which run on entering. 127 | Promise.allSettled(this.template.getAnimations().map( 128 | (animation) => animation.finished 129 | )).then(() => { 130 | this.open = true; 131 | }); 132 | 133 | }); 134 | } 135 | } 136 | 137 | hide(event: MouseEvent | PointerEvent | Event) { 138 | if (this.open) { 139 | console.log('hide', event); 140 | 141 | // Remove opportunities to try and hide this again WHILE it is hidden. 142 | this.owner.removeEventListener("mouseleave", this.hide); 143 | document.removeEventListener("touchstart", this.maybeHide); 144 | document.removeEventListener("scroll", this.maybeHide); 145 | document.removeEventListener("keydown", this.maybeHide); 146 | 147 | // Set up the listeners to handle showing this again subsequently. 148 | this.owner.addEventListener("touchstart", this.show); 149 | this.owner.addEventListener("mouseenter", this.show); 150 | 151 | this.owner.classList.remove("tooltip-open"); 152 | this.owner.dataset.tooltipIsOpen = 'false'; 153 | 154 | this.template.classList.remove("open"); 155 | 156 | // Await any animations which occur when open is removed and it's leaving 157 | Promise.allSettled(this.template.getAnimations().map( 158 | (animation) => animation.finished 159 | )).then(() => { 160 | document.body.removeChild(this.template); 161 | this.open = false; 162 | }); 163 | 164 | } 165 | } 166 | 167 | maybeHide(event: MouseEvent | PointerEvent | KeyboardEvent | Event) { 168 | if (this.open) { 169 | console.log('maybe hide', event); 170 | if (event.type === 'scroll') { 171 | return this.hide(event); 172 | } else if (event.type === 'keydown' && (event as KeyboardEvent).key === "Escape") { 173 | // Pressing escape should hide the tooltip for Accessibility reasons. 174 | // Stop the propagation to prevent this having any other consequences. 175 | event.stopPropagation(); 176 | return this.hide(event); 177 | } else if (event.target !== this.owner) { 178 | return this.hide(event); 179 | } 180 | } 181 | } 182 | } 183 | 184 | class ExpandableBox { 185 | private owner: HTMLElement; 186 | 187 | constructor(element: HTMLElement) { 188 | this.owner = element; 189 | this.show = this.show.bind(this); 190 | this.bind(); 191 | } 192 | 193 | bind() { 194 | if (this.owner.classList.contains("inactive") || !this.owner.classList.contains("active")) { 195 | this.owner.addEventListener("click", this.show); 196 | } 197 | } 198 | 199 | static ready(selector: string) { 200 | const foundTraces: NodeListOf = document.querySelectorAll(selector); 201 | return foundTraces.forEach((value) => { 202 | return new ExpandableBox(value); 203 | }); 204 | } 205 | 206 | show(event: MouseEvent | PointerEvent) { 207 | if (this.owner.classList.contains("active")) { 208 | return; 209 | } 210 | this.owner.classList.add('active'); 211 | this.owner.classList.remove('inactive'); 212 | const {x, y, top} = this.owner.getBoundingClientRect(); 213 | const {scrollX, scrollY} = window; 214 | const goTo = scrollY + top; 215 | // if (goTo > scrollY) { 216 | 217 | const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); 218 | if (reducedMotion.matches) { 219 | return; 220 | } 221 | // Don't perform any auto-scrolling if it's not smooth... 222 | // e.g. for Safari <= 15.2, which doesn't support it. 223 | if (!('scrollBehavior' in document.documentElement.style)) { 224 | return; 225 | } 226 | window.scroll({ 227 | top: goTo, 228 | behavior: 'smooth' 229 | }); 230 | // } else { 231 | // window.scrollTo(scrollX, scrollY); 232 | // } 233 | // const silencedChildren: NodeListOf = this.owner.querySelectorAll('.traceback-locals, .traceback-context'); 234 | // silencedChildren.forEach((value) => { 235 | // value.classList.remove('hidden'); 236 | // }); 237 | // const contextLine: HTMLElement | null = this.owner.querySelector('.active'); 238 | // if (contextLine) { 239 | // contextLine.classList.add('bg-red-500'); 240 | // contextLine.classList.add('text-white') 241 | // } 242 | } 243 | } 244 | 245 | 246 | allPanels.forEach((value) => { 247 | value.addEventListener("click", showHideOthers); 248 | }); 249 | showable.forEach((value) => { 250 | value.addEventListener("click", showBoxContents); 251 | }); 252 | 253 | 254 | const initialTab = document.location.hash; 255 | if (initialTab !== '') { 256 | allPanels.forEach((value) => { 257 | if (value.dataset.tabTarget === initialTab) { 258 | value.click(); 259 | } 260 | }); 261 | } 262 | 263 | Tooltip.ready('[data-tooltip-target]'); 264 | ExpandableBox.ready('[data-expandable]'); 265 | 266 | const copyToClipboardButton = document.querySelector('.traceback-clipboard') as HTMLButtonElement | null; 267 | const copyToClipboardContents = document.getElementById("traceback_area") as HTMLTextAreaElement | null ; 268 | if (copyToClipboardButton !== null && copyToClipboardContents !== null) { 269 | const originalText = copyToClipboardButton.textContent; 270 | copyToClipboardButton.addEventListener('click', () => { 271 | navigator.clipboard.writeText(copyToClipboardContents.value).then(function () { 272 | copyToClipboardButton.textContent = "Copied!" 273 | setTimeout(() => { 274 | copyToClipboardButton.textContent = originalText; 275 | }, 1000); 276 | }, function () { 277 | copyToClipboardButton.textContent = "Failed to copy"; 278 | setTimeout(() => { 279 | copyToClipboardButton.textContent = originalText; 280 | }, 1000); 281 | }); 282 | }); 283 | } 284 | }; 285 | if (document.readyState !== 'loading') { 286 | console.debug("ready"); 287 | return setUp(); 288 | } else { 289 | return document.addEventListener('DOMContentLoaded', setUp); 290 | } 291 | })(); 292 | -------------------------------------------------------------------------------- /technicalerrors/static/input.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | @tailwind variants; 5 | 6 | @layer base { 7 | html { 8 | max-width: 100vw; 9 | /*height: 100%;*/ 10 | } 11 | 12 | body { 13 | @apply overflow-y-scroll 14 | text-gray-500 dark:text-gray-400 15 | flex flex-col 16 | bg-white dark:bg-gray-800 17 | ; 18 | max-width: 100vw; 19 | /*height: 100%;*/ 20 | overscroll-behavior: none; 21 | } 22 | /*body.debug-grid {*/ 23 | /* @apply relative top-0 left-0;*/ 24 | /*}*/ 25 | /*body.debug-grid:before {*/ 26 | /* @apply absolute top-0 left-0 right-0 bottom-0 h-full select-none pointer-events-none z-50;*/ 27 | /* max-width: 100vw;*/ 28 | /* content: "";*/ 29 | /* background-size: 0.5rem 1rem;*/ 30 | /* background-image:*/ 31 | /* !*linear-gradient(to bottom, rgba(0, 0, 255, 0.1) 1px, transparent 1px),*!*/ 32 | /* linear-gradient(to right, rgba(0, 0, 255, 0.1) 1px, transparent 1px);*/ 33 | /*}*/ 34 | } 35 | 36 | @layer components { 37 | .guideline:before { 38 | content: ""; 39 | @apply block fixed top-0 bottom-0 left-0 border-l border-l-black w-0 h-full ml-4 md:ml-8 z-50; 40 | } 41 | .guideline:after { 42 | content: ""; 43 | @apply block fixed top-0 bottom-0 left-0 border-l border-l-black w-0 h-full ml-8 md:ml-12 z-50; 44 | } 45 | 46 | .guideline2:before { 47 | content: ""; 48 | @apply block fixed top-0 bottom-0 right-0 border-r border-r-black w-0 h-full mr-4 md:mr-8 z-50; 49 | } 50 | .guideline2:after { 51 | content: ""; 52 | @apply block fixed top-0 bottom-0 right-0 border-r border-r-black w-0 h-full mr-8 md:mr-12 z-50; 53 | } 54 | 55 | footer { 56 | @apply 57 | py-2 px-8 sm:py-4 md:px-12 58 | bg-red-700 dark:bg-sky-800 59 | text-white max-w-[100vw] 60 | text-sm text-left md:text-base xl:text-center 61 | order-1 62 | ; 63 | } 64 | footer > code { 65 | @apply font-bold; 66 | } 67 | 68 | header { 69 | @apply 70 | p-4 md:p-8 71 | order-2 72 | dark:md:pb-0 73 | bg-red-400 dark:bg-sky-900 74 | ; 75 | } 76 | 77 | .masthead-details { 78 | @apply 79 | bg-white dark:bg-gray-800 80 | dark:border dark:border-sky-700 81 | rounded w-full 82 | ; 83 | /* 84 | https://shadows.brumm.af/ 85 | https://www.joshwcomeau.com/css/designing-shadows/ 86 | */ 87 | box-shadow: 88 | 0px 0px 0.087rem rgba(0, 0, 0, 0.035), 89 | 0px 0px 0.250rem rgba(0, 0, 0, 0.05), 90 | 0px 0px 0.600rem rgba(0, 0, 0, 0.065), 91 | 0px 0px 2rem rgba(0, 0, 0, 0.1) 92 | ; 93 | 94 | } 95 | 96 | .masthead-request { 97 | @apply 98 | px-4 99 | py-2 100 | md:py-4 101 | border-b dark:border-b-sky-700 102 | flex flex-row items-start justify-start truncate; 103 | } 104 | 105 | .masthead-request-badge { 106 | @apply inline-flex items-center justify-center px-2 py-1 font-bold leading-none text-sm rounded 107 | text-gray-500 dark:text-gray-400 108 | bg-gray-200 dark:bg-gray-600 109 | ; 110 | } 111 | 112 | .masthead-request-url { 113 | @apply px-2 py-1 leading-none text-sm truncate; 114 | } 115 | 116 | .masthead-request-url-scheme, 117 | .masthead-request-url-host, 118 | .masthead-request-url-path, 119 | .masthead-request-url-qs { 120 | @apply pb-px border-b-white border-b; 121 | @apply motion-reduce:transition-none transition ease-out duration-300; 122 | @apply hover:border-b-gray-500 ease-in; 123 | } 124 | 125 | .masthead-error { 126 | @apply 127 | p-4; 128 | } 129 | 130 | .masthead-error-title { 131 | @apply text-xl font-semibold 132 | text-red-500 dark:text-gray-300 133 | 134 | md:text-3xl 135 | ; 136 | } 137 | 138 | .masthead-error-subtitle { 139 | @apply 140 | text-base font-normal 141 | text-red-500 dark:text-gray-300 142 | md:text-lg 143 | ; 144 | word-break: break-word; 145 | } 146 | 147 | .masthead-location { 148 | @apply block text-gray-900 149 | } 150 | .masthead-location > code { 151 | @apply underline underline-offset-1 decoration-from-font decoration-gray-300; 152 | } 153 | 154 | .masthead-server-info { 155 | @apply p-4 156 | flex flex-col 157 | w-full 158 | border-t dark:border-t-sky-700 159 | text-gray-500 dark:text-gray-400 160 | text-sm 161 | md:flex-row; 162 | } 163 | 164 | 165 | main { 166 | @apply 167 | max-w-[100vw] 168 | px-4 md:px-8 169 | order-4 170 | /*md:px-6 lg:px-10;*/ 171 | } 172 | 173 | main > section { 174 | /*@apply block;*/ 175 | /*@apply px-6;*/ 176 | } 177 | 178 | 179 | .tab-group { 180 | @apply 181 | py-4 182 | px-4 md:px-8 183 | mb-8 184 | bg-red-50 dark:bg-sky-900 185 | border-b border-b-red-100 dark:border-b-sky-700 186 | flex-row flex-wrap flex max-w-[100vw] 187 | order-2 188 | ; 189 | } 190 | 191 | .tab { 192 | @apply uppercase rounded text-sm grow cursor-pointer text-center px-1 py-2 font-semibold mx-1 193 | /*bg-red-50*/ 194 | border-red-50 195 | /*border*/ 196 | /*dark:border-gray-600 dark:border*/ 197 | hover:bg-red-100 hover:text-red-500 198 | hover:dark:bg-sky-800 hover:dark:text-gray-300 199 | /*hover:border-red-500*/ 200 | ; 201 | } 202 | 203 | /*.tab:first-child {*/ 204 | /* @apply rounded-l;*/ 205 | /*}*/ 206 | 207 | /*.tab:last-child {*/ 208 | /* @apply rounded-r;*/ 209 | /*}*/ 210 | 211 | .tab.active { 212 | @apply 213 | text-red-50 214 | bg-red-400 215 | dark:bg-sky-700 dark:text-gray-300 216 | /*shadow*/ 217 | /*pt-3*/ 218 | /*pb-4*/ 219 | ; 220 | /*transition: padding ease-out 0.2s;*/ 221 | } 222 | 223 | .wrappable { 224 | word-break: break-word; 225 | } 226 | 227 | /*.urls-explanation {*/ 228 | /* @apply pb-4;*/ 229 | /*}*/ 230 | 231 | /*.urls-tried {*/ 232 | /* @apply bg-gray-50 -mx-6 border border-gray-200 rounded;*/ 233 | /*}*/ 234 | 235 | /*.urls-tried li {*/ 236 | /* @apply px-6 py-2 flex flex-row border-b border-b-gray-200;*/ 237 | /* @apply hover:bg-gray-100;*/ 238 | /*}*/ 239 | 240 | /*.urls-tried li:first-child {*/ 241 | /* @apply border-t-0;*/ 242 | /*}*/ 243 | 244 | /*.urls-tried li:last-child {*/ 245 | /* @apply border-b-0;*/ 246 | /*}*/ 247 | 248 | /*.urls-tried-regex {*/ 249 | /* @apply flex-grow;*/ 250 | /*}*/ 251 | 252 | /*.urls-tried-name {*/ 253 | /* @apply flex-grow-0 text-sm font-normal;*/ 254 | /*}*/ 255 | 256 | main > p { 257 | @apply m-4 mt-0; 258 | } 259 | 260 | .related-settings { 261 | @apply py-4; 262 | } 263 | 264 | .related-settings h6 { 265 | @apply 266 | px-4 267 | text-red-400 font-semibold; 268 | } 269 | 270 | 271 | .traceback { 272 | /*@apply border-l border-r border-gray-200 rounded;*/ 273 | /*@apply -mx-6;*/ 274 | /*@apply shadow*/ 275 | } 276 | 277 | .traceback-cause-chain { 278 | @apply py-4 px-4 font-semibold bg-white text-red-500; 279 | word-break: break-word; 280 | } 281 | 282 | .traceback-frame { 283 | @apply cursor-pointer 284 | border border-gray-200 285 | dark:border-gray-600 286 | mb-4 287 | ; 288 | } 289 | [data-expandable] { 290 | @apply hover:border-gray-400 hover:dark:border-gray-500 291 | } 292 | /*.traceback-frame + .traceback-frame {*/ 293 | /* @apply border-t-0*/ 294 | /*}*/ 295 | 296 | .traceback-frame.active { 297 | @apply cursor-auto; 298 | } 299 | 300 | .traceback-where { 301 | @apply 302 | py-2 px-4 303 | border-b border-b-gray-200 304 | dark:border-b-gray-600 305 | flex flex-row items-center text-sm 306 | sticky top-0 z-40; 307 | } 308 | 309 | .traceback-frame.library .traceback-where { 310 | @apply bg-gray-50 text-gray-400 311 | dark:bg-gray-700 312 | ; 313 | } 314 | 315 | .traceback-frame.user .traceback-where { 316 | @apply bg-gray-100 text-gray-900 317 | dark:bg-gray-600 dark:text-gray-300 318 | ; 319 | } 320 | 321 | .traceback-file { 322 | @apply flex-grow truncate; 323 | } 324 | 325 | .traceback-file code:first-child { 326 | @apply font-semibold; 327 | } 328 | 329 | .traceback-function { 330 | @apply flex-grow-0 pl-4; /* pr-4 relative; */ 331 | } 332 | /*.traceback-function:before {*/ 333 | /* @apply block bg-gray-300 absolute w-3 h-0.5 top-2.5 right-0*/ 334 | /* ;*/ 335 | /* content : "";*/ 336 | /* transition: transform 200ms ease-out;*/ 337 | /* transform: rotate(0deg);*/ 338 | /*}*/ 339 | /*.traceback-function:after {*/ 340 | /* @apply block bg-gray-300 absolute w-3 h-0.5 top-2.5 right-0*/ 341 | /* ;*/ 342 | /* transition: transform 200ms ease-out;*/ 343 | /* transform: rotate(90deg);*/ 344 | /* content : "";*/ 345 | /*}*/ 346 | /*.traceback-frame.active .traceback-function:before {*/ 347 | /* transform: rotate(180deg);*/ 348 | /*}*/ 349 | /*.traceback-frame.active .traceback-function:after {*/ 350 | /* transform: rotate(180deg);*/ 351 | /*}*/ 352 | 353 | .traceback-frame.user .traceback-function { 354 | @apply font-semibold; 355 | } 356 | 357 | /*.traceback-content {*/ 358 | /* @apply py-4;*/ 359 | /*}*/ 360 | 361 | 362 | .traceback-context { 363 | @apply block overflow-hidden 364 | my-4 mx-4 365 | ; 366 | word-break: break-all; 367 | font-size: 0; 368 | line-height: 0; 369 | } 370 | .traceback-context > span { 371 | /* this is necessary for horizontal scrolling to paint the whole line red */ 372 | @apply inline-block min-w-full; 373 | } 374 | 375 | .traceback-frame.active .traceback-context { 376 | @apply text-sm overflow-x-auto relative; 377 | } 378 | /*.traceback-frame.active .traceback-context:before {*/ 379 | /* @apply block w-0 h-full absolute left-[80ch] top-0 border-r border-r-red-100*/ 380 | /* ;*/ 381 | /* z-index: -1;*/ 382 | /* content: "";*/ 383 | /*}*/ 384 | 385 | .traceback-context-raising { 386 | @apply text-sm 387 | block w-full pr-2 388 | ; 389 | } 390 | .traceback-context-raising .specific { 391 | @apply text-white 392 | bg-red-700 dark:bg-sky-700 dark:text-sky-100 393 | font-semibold px-2 py-[2px]; 394 | } 395 | 396 | .traceback-frame.library .traceback-context-raising { 397 | @apply text-gray-400; 398 | } 399 | 400 | .traceback-frame.user .traceback-context-raising { 401 | @apply 402 | text-gray-900 403 | dark:text-gray-300 404 | ; 405 | } 406 | 407 | .traceback-frame.active .traceback-context-raising { 408 | @apply text-white bg-red-500 409 | dark:bg-sky-900 410 | ; 411 | } 412 | 413 | .traceback-locals { 414 | @apply hidden ; 415 | /*my-4;*/ 416 | } 417 | .traceback-locals > h6 { 418 | @apply py-2 px-4 419 | font-semibold 420 | border-b border-b-gray-200 421 | dark:border-b-gray-600 422 | text-sm 423 | ; 424 | } 425 | .traceback-locals > code { 426 | @apply block 427 | ; 428 | } 429 | .traceback-locals > p { 430 | @apply px-4 431 | } 432 | 433 | .traceback-frame.active .traceback-locals { 434 | @apply block; 435 | } 436 | 437 | .traceback-clipboard { 438 | @apply font-semibold uppercase bg-red-50 text-sm py-2 px-3 rounded; 439 | @apply hover:bg-red-400 hover:text-white; 440 | } 441 | 442 | 443 | 444 | 445 | 446 | .rowable { 447 | @apply block table-auto border-collapse text-sm w-full 448 | lg:table 449 | ; 450 | max-width: 100vw; 451 | } 452 | 453 | .rowable li { 454 | @apply 455 | block 456 | border-b 457 | dark:border-b-gray-600 458 | pb-2 459 | lg:pb-0 lg:table-row 460 | /*hover:bg-yellow-50*/ 461 | } 462 | 463 | .rowable li:last-child { 464 | @apply border-b-0 pb-0; 465 | } 466 | 467 | .rowable li code { 468 | @apply 469 | block w-full 470 | py-2 pl-4 471 | lg:w-4 lg:table-cell 472 | /*lg:min-w-[10%] lg:max-w-[40%]*/ 473 | ; 474 | } 475 | 476 | .rowable li pre { 477 | @apply block max-w-full 478 | overflow-y-hidden overflow-x-auto 479 | py-0 mx-4 480 | lg:py-2 lg:px-4 lg:mx-0 lg:table-cell 481 | /*lg:min-w-[60%] lg:max-w-[90%]*/ 482 | ; 483 | word-break: break-word; 484 | } 485 | 486 | .rowable.locals { 487 | 488 | } 489 | .rowable.settings { 490 | 491 | } 492 | .rowable.request { 493 | 494 | } 495 | /*.rowable.urls {*/ 496 | /* @apply lg:block;*/ 497 | /*}*/ 498 | 499 | .rowable.urls li { 500 | /*@apply border-0;*/ 501 | } 502 | .rowable.urls li pre { 503 | @apply truncate; 504 | word-break: break-word; 505 | } 506 | /*.rowable.urls li > span {*/ 507 | /* @apply*/ 508 | /* flex max-w-full*/ 509 | /* whitespace-nowrap text-right*/ 510 | /* mx-4*/ 511 | /* px-2 py-1 leading-none bg-gray-100 rounded*/ 512 | /* !*w-4 whitespace-nowrap text-right*!*/ 513 | /* !*py-0 mx-4*!*/ 514 | /* !*!*lg:py-2 lg:px-4 *!*!*/ 515 | /* !*lg:mx-0 lg:table-cell*!*/ 516 | /* ;*/ 517 | /*}*/ 518 | /*.rowable.urls li code span {*/ 519 | /* @apply inline-flex truncate*/ 520 | /* !*@apply py-2 px-4 inline-flex text-sm;*!*/ 521 | /*}*/ 522 | .pattern { 523 | @apply 524 | /*mr-4*/ 525 | whitespace-normal 526 | ; 527 | } 528 | /*.url-match {*/ 529 | /* @apply*/ 530 | /* inline-flex*/ 531 | /* bg-green-50 text-green-700*/ 532 | /* py-0.5 px-1*/ 533 | /* mr-1*/ 534 | /* !*-ml-1.5 mr-0.5*!*/ 535 | /* border-green-200 border rounded*/ 536 | /* ;*/ 537 | /*}*/ 538 | .url-match { 539 | @apply 540 | inline-flex 541 | text-green-600 542 | /*py-0.5*/ 543 | /* border*/ 544 | /*border-green-50*/ 545 | bg-green-100 546 | dark:text-sky-400 547 | dark:bg-inherit 548 | /*rounded*/ 549 | /*mr-1*/ 550 | /*-ml-1.5 mr-0.5*/ 551 | /*border-gray-200 border rounded*/ 552 | ; 553 | } 554 | 555 | 556 | 557 | 558 | 559 | .tooltip2 { 560 | @apply absolute z-50 top-6 rounded px-3 py-2 max-w-prose bg-gray-500 font-semibold select-none pointer-events-none text-white text-xs text-center; 561 | @apply transition ease-out opacity-0 duration-100 delay-100; 562 | transform: translateX(-50%) scale(0, 1); 563 | left: 50%; 564 | } 565 | 566 | .tooltip2.open { 567 | @apply opacity-100 duration-200; 568 | transform: translateX(-50%) scale(1, 1); 569 | transition-delay: 0s; 570 | 571 | box-shadow: 0px 0px 3.2px rgba(0, 0, 0, 0.035), 572 | 0px 0px 8.8px rgba(0, 0, 0, 0.05), 573 | 0px 0px 21.1px rgba(0, 0, 0, 0.065), 574 | 0px 0px 70px rgba(0, 0, 0, 0.1) 575 | } 576 | 577 | .tooltip2:after { 578 | @apply absolute top-0 w-0 h-0 border-transparent border-b-gray-500 border-8 -ml-2 select-none pointer-events-none; 579 | @apply ease-linear duration-100; 580 | transition-property: top; 581 | content: ""; 582 | left: 50%; 583 | z-index: -1; 584 | transition-delay: 0s; 585 | } 586 | 587 | .tooltip2.open:after { 588 | @apply -top-4 delay-200; 589 | } 590 | 591 | .tooltip2:hover:after { 592 | @apply -bottom-4 delay-200; 593 | } 594 | 595 | .tooltip { 596 | @apply relative; 597 | } 598 | 599 | .tooltip:before { 600 | @apply absolute z-20 top-6 rounded px-3 py-2 max-w-prose bg-gray-500 select-none pointer-events-none text-white text-xs text-center transition opacity-0 scale-0 ease-out duration-200 delay-1000; 601 | content: attr(aria-label); 602 | transform-origin: center; 603 | transform: translateX(-50%) scale(0); 604 | left: 50%; 605 | /*pointer-events: none;*/ 606 | } 607 | 608 | .tooltip:hover:before { 609 | @apply opacity-100 ease-in; 610 | transition-delay: 0s; 611 | transform: translateX(-50%) scale(1); 612 | } 613 | 614 | .tooltip:after { 615 | @apply absolute z-10 w-0 h-0 -bottom-4 border-transparent border-b-gray-500 border-8 -ml-2 select-none pointer-events-none opacity-0 ease-out duration-100; 616 | transition-property: opacity, bottom; 617 | left: 50%; 618 | content: ""; 619 | position: absolute; 620 | pointer-events: none; 621 | } 622 | 623 | .tooltip:hover:after { 624 | @apply opacity-100 ease-in -bottom-2.5 delay-200; 625 | } 626 | } 627 | -------------------------------------------------------------------------------- /technicalerrors/static/tailwind.css: -------------------------------------------------------------------------------- 1 | /* 2 | ! tailwindcss v3.0.15 | MIT License | https://tailwindcss.com 3 | *//* 4 | 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) 5 | 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) 6 | */ 7 | 8 | *, 9 | ::before, 10 | ::after { 11 | box-sizing: border-box; /* 1 */ 12 | border-width: 0; /* 2 */ 13 | border-style: solid; /* 2 */ 14 | border-color: #e5e7eb; /* 2 */ 15 | } 16 | 17 | ::before, 18 | ::after { 19 | } 20 | 21 | /* 22 | 1. Use a consistent sensible line-height in all browsers. 23 | 2. Prevent adjustments of font size after orientation changes in iOS. 24 | 3. Use a more readable tab size. 25 | 4. Use the user's configured `sans` font-family by default. 26 | */ 27 | 28 | html { 29 | line-height: 1.5; /* 1 */ 30 | -webkit-text-size-adjust: 100%; /* 2 */ 31 | -moz-tab-size: 4; /* 3 */ 32 | -o-tab-size: 4; 33 | tab-size: 4; /* 3 */ 34 | font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ 35 | } 36 | 37 | /* 38 | 1. Remove the margin in all browsers. 39 | 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. 40 | */ 41 | 42 | body { 43 | margin: 0; /* 1 */ 44 | line-height: inherit; /* 2 */ 45 | } 46 | 47 | /* 48 | 1. Add the correct height in Firefox. 49 | 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) 50 | 3. Ensure horizontal rules are visible by default. 51 | */ 52 | 53 | /* 54 | Add the correct text decoration in Chrome, Edge, and Safari. 55 | */ 56 | 57 | /* 58 | Remove the default font size and weight for headings. 59 | */ 60 | 61 | h1, 62 | h2, 63 | h6 { 64 | font-size: inherit; 65 | font-weight: inherit; 66 | } 67 | 68 | /* 69 | Reset links to optimize for opt-in styling instead of opt-out. 70 | */ 71 | 72 | a { 73 | color: inherit; 74 | text-decoration: inherit; 75 | } 76 | 77 | /* 78 | Add the correct font weight in Edge and Safari. 79 | */ 80 | 81 | 82 | strong { 83 | font-weight: bolder; 84 | } 85 | 86 | /* 87 | 1. Use the user's configured `mono` font family by default. 88 | 2. Correct the odd `em` font sizing in all browsers. 89 | */ 90 | 91 | code, 92 | pre { 93 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ 94 | font-size: 1em; /* 2 */ 95 | } 96 | 97 | /* 98 | Add the correct font size in all browsers. 99 | */ 100 | 101 | /* 102 | Prevent `sub` and `sup` elements from affecting the line height in all browsers. 103 | */ 104 | 105 | /* 106 | 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) 107 | 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) 108 | 3. Remove gaps between table borders by default. 109 | */ 110 | 111 | /* 112 | 1. Change the font styles in all browsers. 113 | 2. Remove the margin in Firefox and Safari. 114 | 3. Remove default padding in all browsers. 115 | */ 116 | 117 | button, 118 | input, 119 | textarea { 120 | font-family: inherit; /* 1 */ 121 | font-size: 100%; /* 1 */ 122 | line-height: inherit; /* 1 */ 123 | color: inherit; /* 1 */ 124 | margin: 0; /* 2 */ 125 | padding: 0; /* 3 */ 126 | } 127 | 128 | /* 129 | Remove the inheritance of text transform in Edge and Firefox. 130 | */ 131 | 132 | button { 133 | text-transform: none; 134 | } 135 | 136 | /* 137 | 1. Correct the inability to style clickable types in iOS and Safari. 138 | 2. Remove default button styles. 139 | */ 140 | 141 | button, 142 | [type='button'] { 143 | -webkit-appearance: button; /* 1 */ 144 | background-color: transparent; /* 2 */ 145 | background-image: none; /* 2 */ 146 | } 147 | 148 | /* 149 | Use the modern Firefox focus style for all focusable elements. 150 | */ 151 | 152 | /* 153 | Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) 154 | */ 155 | 156 | /* 157 | Add the correct vertical alignment in Chrome and Firefox. 158 | */ 159 | 160 | /* 161 | Correct the cursor style of increment and decrement buttons in Safari. 162 | */ 163 | 164 | ::-webkit-inner-spin-button, 165 | ::-webkit-outer-spin-button { 166 | height: auto; 167 | } 168 | 169 | /* 170 | 1. Correct the odd appearance in Chrome and Safari. 171 | 2. Correct the outline style in Safari. 172 | */ 173 | 174 | /* 175 | Remove the inner padding in Chrome and Safari on macOS. 176 | */ 177 | 178 | ::-webkit-search-decoration { 179 | -webkit-appearance: none; 180 | } 181 | 182 | /* 183 | 1. Correct the inability to style clickable types in iOS and Safari. 184 | 2. Change font properties to `inherit` in Safari. 185 | */ 186 | 187 | ::-webkit-file-upload-button { 188 | -webkit-appearance: button; /* 1 */ 189 | font: inherit; /* 2 */ 190 | } 191 | 192 | /* 193 | Add the correct display in Chrome and Safari. 194 | */ 195 | 196 | /* 197 | Removes the default spacing and border for appropriate elements. 198 | */ 199 | 200 | 201 | h1, 202 | h2, 203 | h6, 204 | p, 205 | pre { 206 | margin: 0; 207 | } 208 | 209 | ol, 210 | ul { 211 | list-style: none; 212 | margin: 0; 213 | padding: 0; 214 | } 215 | 216 | /* 217 | Prevent resizing textareas horizontally by default. 218 | */ 219 | 220 | textarea { 221 | resize: vertical; 222 | } 223 | 224 | /* 225 | 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) 226 | 2. Set the default placeholder color to the user's configured gray 400 color. 227 | */ 228 | 229 | input::-moz-placeholder, textarea::-moz-placeholder { 230 | opacity: 1; /* 1 */ 231 | color: #9ca3af; /* 2 */ 232 | } 233 | 234 | input:-ms-input-placeholder, textarea:-ms-input-placeholder { 235 | opacity: 1; /* 1 */ 236 | color: #9ca3af; /* 2 */ 237 | } 238 | 239 | input::placeholder, 240 | textarea::placeholder { 241 | opacity: 1; /* 1 */ 242 | color: #9ca3af; /* 2 */ 243 | } 244 | 245 | /* 246 | Set the default cursor for buttons. 247 | */ 248 | 249 | button, 250 | [role="button"] { 251 | cursor: pointer; 252 | } 253 | 254 | /* 255 | Make sure disabled buttons don't get the pointer cursor. 256 | */ 257 | 258 | /* 259 | 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) 260 | 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) 261 | This can trigger a poorly considered lint error in some tools but is included by design. 262 | */ 263 | 264 | 265 | svg { 266 | display: block; /* 1 */ 267 | vertical-align: middle; /* 2 */ 268 | } 269 | 270 | /* 271 | Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) 272 | */ 273 | 274 | /* 275 | Ensure the default browser behavior of the `hidden` attribute. 276 | */ 277 | 278 | [hidden] { 279 | display: none; 280 | } 281 | html { 282 | max-width: 100vw; 283 | /*height: 100%;*/ 284 | } 285 | 286 | body { 287 | display: flex; 288 | flex-direction: column; 289 | overflow-y: scroll; 290 | --tw-bg-opacity: 1; 291 | background-color: rgb(255 255 255 / var(--tw-bg-opacity)); 292 | --tw-text-opacity: 1; 293 | color: rgb(107 114 128 / var(--tw-text-opacity)); 294 | } 295 | 296 | @media (prefers-color-scheme: dark) { 297 | 298 | body { 299 | --tw-bg-opacity: 1; 300 | background-color: rgb(31 41 55 / var(--tw-bg-opacity)); 301 | } 302 | 303 | body { 304 | --tw-text-opacity: 1; 305 | color: rgb(156 163 175 / var(--tw-text-opacity)); 306 | } 307 | } 308 | 309 | body { 310 | max-width: 100vw; 311 | /*height: 100%;*/ 312 | -ms-scroll-chaining: none; 313 | overscroll-behavior: none; 314 | } 315 | /*body.debug-grid {*/ 316 | /* @apply relative top-0 left-0;*/ 317 | /*}*/ 318 | /*body.debug-grid:before {*/ 319 | /* @apply absolute top-0 left-0 right-0 bottom-0 h-full select-none pointer-events-none z-50;*/ 320 | /* max-width: 100vw;*/ 321 | /* content: "";*/ 322 | /* background-size: 0.5rem 1rem;*/ 323 | /* background-image:*/ 324 | /* !*linear-gradient(to bottom, rgba(0, 0, 255, 0.1) 1px, transparent 1px),*!*/ 325 | /* linear-gradient(to right, rgba(0, 0, 255, 0.1) 1px, transparent 1px);*/ 326 | /*}*/ 327 | 328 | *, ::before, ::after { 329 | --tw-translate-x: 0; 330 | --tw-translate-y: 0; 331 | --tw-rotate: 0; 332 | --tw-skew-x: 0; 333 | --tw-skew-y: 0; 334 | --tw-scale-x: 1; 335 | --tw-scale-y: 1; 336 | } 337 | .guideline:before { 338 | content: ""; 339 | position: fixed; 340 | top: 0px; 341 | bottom: 0px; 342 | left: 0px; 343 | z-index: 50; 344 | margin-left: 1rem; 345 | display: block; 346 | height: 100%; 347 | width: 0px; 348 | border-left-width: 1px; 349 | --tw-border-opacity: 1; 350 | border-left-color: rgb(0 0 0 / var(--tw-border-opacity)); 351 | } 352 | @media (min-width: 768px) { 353 | 354 | .guideline:before { 355 | margin-left: 2rem; 356 | } 357 | } 358 | .guideline:after { 359 | content: ""; 360 | position: fixed; 361 | top: 0px; 362 | bottom: 0px; 363 | left: 0px; 364 | z-index: 50; 365 | margin-left: 2rem; 366 | display: block; 367 | height: 100%; 368 | width: 0px; 369 | border-left-width: 1px; 370 | --tw-border-opacity: 1; 371 | border-left-color: rgb(0 0 0 / var(--tw-border-opacity)); 372 | } 373 | @media (min-width: 768px) { 374 | 375 | .guideline:after { 376 | margin-left: 3rem; 377 | } 378 | } 379 | .guideline2:before { 380 | content: ""; 381 | position: fixed; 382 | top: 0px; 383 | bottom: 0px; 384 | right: 0px; 385 | z-index: 50; 386 | margin-right: 1rem; 387 | display: block; 388 | height: 100%; 389 | width: 0px; 390 | border-right-width: 1px; 391 | --tw-border-opacity: 1; 392 | border-right-color: rgb(0 0 0 / var(--tw-border-opacity)); 393 | } 394 | @media (min-width: 768px) { 395 | 396 | .guideline2:before { 397 | margin-right: 2rem; 398 | } 399 | } 400 | .guideline2:after { 401 | content: ""; 402 | position: fixed; 403 | top: 0px; 404 | bottom: 0px; 405 | right: 0px; 406 | z-index: 50; 407 | margin-right: 2rem; 408 | display: block; 409 | height: 100%; 410 | width: 0px; 411 | border-right-width: 1px; 412 | --tw-border-opacity: 1; 413 | border-right-color: rgb(0 0 0 / var(--tw-border-opacity)); 414 | } 415 | @media (min-width: 768px) { 416 | 417 | .guideline2:after { 418 | margin-right: 3rem; 419 | } 420 | } 421 | footer { 422 | order: 1; 423 | max-width: 100vw; 424 | --tw-bg-opacity: 1; 425 | background-color: rgb(185 28 28 / var(--tw-bg-opacity)); 426 | padding-top: 0.5rem; 427 | padding-bottom: 0.5rem; 428 | padding-left: 2rem; 429 | padding-right: 2rem; 430 | text-align: left; 431 | font-size: 0.875rem; 432 | line-height: 1.25rem; 433 | --tw-text-opacity: 1; 434 | color: rgb(255 255 255 / var(--tw-text-opacity)); 435 | } 436 | @media (prefers-color-scheme: dark) { 437 | 438 | footer { 439 | --tw-bg-opacity: 1; 440 | background-color: rgb(7 89 133 / var(--tw-bg-opacity)); 441 | } 442 | } 443 | @media (min-width: 640px) { 444 | 445 | footer { 446 | padding-top: 1rem; 447 | padding-bottom: 1rem; 448 | } 449 | } 450 | @media (min-width: 768px) { 451 | 452 | footer { 453 | padding-left: 3rem; 454 | padding-right: 3rem; 455 | } 456 | 457 | footer { 458 | font-size: 1rem; 459 | line-height: 1.5rem; 460 | } 461 | } 462 | @media (min-width: 1280px) { 463 | 464 | footer { 465 | text-align: center; 466 | } 467 | } 468 | footer > code { 469 | font-weight: 700; 470 | } 471 | header { 472 | order: 2; 473 | --tw-bg-opacity: 1; 474 | background-color: rgb(248 113 113 / var(--tw-bg-opacity)); 475 | padding: 1rem; 476 | } 477 | @media (prefers-color-scheme: dark) { 478 | 479 | header { 480 | --tw-bg-opacity: 1; 481 | background-color: rgb(12 74 110 / var(--tw-bg-opacity)); 482 | } 483 | } 484 | @media (min-width: 768px) { 485 | 486 | header { 487 | padding: 2rem; 488 | } 489 | } 490 | @media (prefers-color-scheme: dark) { 491 | 492 | @media (min-width: 768px) { 493 | 494 | header { 495 | padding-bottom: 0px; 496 | } 497 | } 498 | } 499 | .masthead-details { 500 | width: 100%; 501 | border-radius: 0.25rem; 502 | --tw-bg-opacity: 1; 503 | background-color: rgb(255 255 255 / var(--tw-bg-opacity)); 504 | } 505 | @media (prefers-color-scheme: dark) { 506 | 507 | .masthead-details { 508 | border-width: 1px; 509 | } 510 | 511 | .masthead-details { 512 | --tw-border-opacity: 1; 513 | border-color: rgb(3 105 161 / var(--tw-border-opacity)); 514 | } 515 | 516 | .masthead-details { 517 | --tw-bg-opacity: 1; 518 | background-color: rgb(31 41 55 / var(--tw-bg-opacity)); 519 | } 520 | } 521 | .masthead-details { 522 | /* 523 | https://shadows.brumm.af/ 524 | https://www.joshwcomeau.com/css/designing-shadows/ 525 | */ 526 | box-shadow: 527 | 0px 0px 0.087rem rgba(0, 0, 0, 0.035), 528 | 0px 0px 0.250rem rgba(0, 0, 0, 0.05), 529 | 0px 0px 0.600rem rgba(0, 0, 0, 0.065), 530 | 0px 0px 2rem rgba(0, 0, 0, 0.1) 531 | ; 532 | 533 | } 534 | .masthead-request { 535 | display: flex; 536 | flex-direction: row; 537 | align-items: flex-start; 538 | justify-content: flex-start; 539 | overflow: hidden; 540 | text-overflow: ellipsis; 541 | white-space: nowrap; 542 | border-bottom-width: 1px; 543 | padding-left: 1rem; 544 | padding-right: 1rem; 545 | padding-top: 0.5rem; 546 | padding-bottom: 0.5rem; 547 | } 548 | @media (prefers-color-scheme: dark) { 549 | 550 | .masthead-request { 551 | --tw-border-opacity: 1; 552 | border-bottom-color: rgb(3 105 161 / var(--tw-border-opacity)); 553 | } 554 | } 555 | @media (min-width: 768px) { 556 | 557 | .masthead-request { 558 | padding-top: 1rem; 559 | padding-bottom: 1rem; 560 | } 561 | } 562 | .masthead-request-badge { 563 | display: inline-flex; 564 | align-items: center; 565 | justify-content: center; 566 | border-radius: 0.25rem; 567 | --tw-bg-opacity: 1; 568 | background-color: rgb(229 231 235 / var(--tw-bg-opacity)); 569 | padding-left: 0.5rem; 570 | padding-right: 0.5rem; 571 | padding-top: 0.25rem; 572 | padding-bottom: 0.25rem; 573 | font-size: 0.875rem; 574 | line-height: 1.25rem; 575 | font-weight: 700; 576 | line-height: 1; 577 | --tw-text-opacity: 1; 578 | color: rgb(107 114 128 / var(--tw-text-opacity)); 579 | } 580 | @media (prefers-color-scheme: dark) { 581 | 582 | .masthead-request-badge { 583 | --tw-bg-opacity: 1; 584 | background-color: rgb(75 85 99 / var(--tw-bg-opacity)); 585 | } 586 | 587 | .masthead-request-badge { 588 | --tw-text-opacity: 1; 589 | color: rgb(156 163 175 / var(--tw-text-opacity)); 590 | } 591 | } 592 | .masthead-request-url { 593 | overflow: hidden; 594 | text-overflow: ellipsis; 595 | white-space: nowrap; 596 | padding-left: 0.5rem; 597 | padding-right: 0.5rem; 598 | padding-top: 0.25rem; 599 | padding-bottom: 0.25rem; 600 | font-size: 0.875rem; 601 | line-height: 1.25rem; 602 | line-height: 1; 603 | } 604 | .masthead-request-url-scheme, .masthead-request-url-host, .masthead-request-url-path, .masthead-request-url-qs { 605 | border-bottom-width: 1px; 606 | --tw-border-opacity: 1; 607 | border-bottom-color: rgb(255 255 255 / var(--tw-border-opacity)); 608 | padding-bottom: 1px; 609 | transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 610 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 611 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 612 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 613 | transition-duration: 300ms; 614 | transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 615 | } 616 | @media (prefers-reduced-motion: reduce) { 617 | 618 | .masthead-request-url-scheme, .masthead-request-url-host, .masthead-request-url-path, .masthead-request-url-qs { 619 | transition-property: none; 620 | } 621 | } 622 | .masthead-request-url-scheme, .masthead-request-url-host, .masthead-request-url-path, .masthead-request-url-qs { 623 | transition-timing-function: cubic-bezier(0.4, 0, 1, 1); 624 | } 625 | .masthead-request-url-scheme:hover, .masthead-request-url-host:hover, .masthead-request-url-path:hover, .masthead-request-url-qs:hover { 626 | --tw-border-opacity: 1; 627 | border-bottom-color: rgb(107 114 128 / var(--tw-border-opacity)); 628 | } 629 | .masthead-error { 630 | padding: 1rem; 631 | } 632 | .masthead-error-title { 633 | font-size: 1.25rem; 634 | line-height: 1.75rem; 635 | font-weight: 600; 636 | --tw-text-opacity: 1; 637 | color: rgb(239 68 68 / var(--tw-text-opacity)); 638 | } 639 | @media (prefers-color-scheme: dark) { 640 | 641 | .masthead-error-title { 642 | --tw-text-opacity: 1; 643 | color: rgb(209 213 219 / var(--tw-text-opacity)); 644 | } 645 | } 646 | @media (min-width: 768px) { 647 | 648 | .masthead-error-title { 649 | font-size: 1.875rem; 650 | line-height: 2.25rem; 651 | } 652 | } 653 | .masthead-error-subtitle { 654 | font-size: 1rem; 655 | line-height: 1.5rem; 656 | font-weight: 400; 657 | --tw-text-opacity: 1; 658 | color: rgb(239 68 68 / var(--tw-text-opacity)); 659 | } 660 | @media (prefers-color-scheme: dark) { 661 | 662 | .masthead-error-subtitle { 663 | --tw-text-opacity: 1; 664 | color: rgb(209 213 219 / var(--tw-text-opacity)); 665 | } 666 | } 667 | @media (min-width: 768px) { 668 | 669 | .masthead-error-subtitle { 670 | font-size: 1.125rem; 671 | line-height: 1.75rem; 672 | } 673 | } 674 | .masthead-error-subtitle { 675 | word-break: break-word; 676 | } 677 | .masthead-location { 678 | display: block; 679 | --tw-text-opacity: 1; 680 | color: rgb(17 24 39 / var(--tw-text-opacity)); 681 | } 682 | .masthead-location > code { 683 | -webkit-text-decoration-line: underline; 684 | text-decoration-line: underline; 685 | -webkit-text-decoration-color: #d1d5db; 686 | text-decoration-color: #d1d5db; 687 | text-decoration-thickness: from-font; 688 | text-underline-offset: 1px; 689 | } 690 | .masthead-server-info { 691 | display: flex; 692 | width: 100%; 693 | flex-direction: column; 694 | border-top-width: 1px; 695 | padding: 1rem; 696 | font-size: 0.875rem; 697 | line-height: 1.25rem; 698 | --tw-text-opacity: 1; 699 | color: rgb(107 114 128 / var(--tw-text-opacity)); 700 | } 701 | @media (prefers-color-scheme: dark) { 702 | 703 | .masthead-server-info { 704 | --tw-border-opacity: 1; 705 | border-top-color: rgb(3 105 161 / var(--tw-border-opacity)); 706 | } 707 | 708 | .masthead-server-info { 709 | --tw-text-opacity: 1; 710 | color: rgb(156 163 175 / var(--tw-text-opacity)); 711 | } 712 | } 713 | @media (min-width: 768px) { 714 | 715 | .masthead-server-info { 716 | flex-direction: row; 717 | } 718 | } 719 | main { 720 | order: 4; 721 | max-width: 100vw; 722 | padding-left: 1rem; 723 | padding-right: 1rem; 724 | } 725 | @media (min-width: 768px) { 726 | 727 | main { 728 | padding-left: 2rem; 729 | padding-right: 2rem; 730 | } 731 | } 732 | main > section { 733 | /*@apply block;*/ 734 | /*@apply px-6;*/ 735 | } 736 | .tab-group { 737 | order: 2; 738 | margin-bottom: 2rem; 739 | display: flex; 740 | max-width: 100vw; 741 | flex-direction: row; 742 | flex-wrap: wrap; 743 | border-bottom-width: 1px; 744 | --tw-border-opacity: 1; 745 | border-bottom-color: rgb(254 226 226 / var(--tw-border-opacity)); 746 | --tw-bg-opacity: 1; 747 | background-color: rgb(254 242 242 / var(--tw-bg-opacity)); 748 | padding-top: 1rem; 749 | padding-bottom: 1rem; 750 | padding-left: 1rem; 751 | padding-right: 1rem; 752 | } 753 | @media (prefers-color-scheme: dark) { 754 | 755 | .tab-group { 756 | --tw-border-opacity: 1; 757 | border-bottom-color: rgb(3 105 161 / var(--tw-border-opacity)); 758 | } 759 | 760 | .tab-group { 761 | --tw-bg-opacity: 1; 762 | background-color: rgb(12 74 110 / var(--tw-bg-opacity)); 763 | } 764 | } 765 | @media (min-width: 768px) { 766 | 767 | .tab-group { 768 | padding-left: 2rem; 769 | padding-right: 2rem; 770 | } 771 | } 772 | .tab { 773 | margin-left: 0.25rem; 774 | margin-right: 0.25rem; 775 | flex-grow: 1; 776 | cursor: pointer; 777 | border-radius: 0.25rem; 778 | --tw-border-opacity: 1; 779 | border-color: rgb(254 242 242 / var(--tw-border-opacity)); 780 | padding-left: 0.25rem; 781 | padding-right: 0.25rem; 782 | padding-top: 0.5rem; 783 | padding-bottom: 0.5rem; 784 | text-align: center; 785 | font-size: 0.875rem; 786 | line-height: 1.25rem; 787 | font-weight: 600; 788 | text-transform: uppercase; 789 | } 790 | .tab:hover { 791 | --tw-bg-opacity: 1; 792 | background-color: rgb(254 226 226 / var(--tw-bg-opacity)); 793 | --tw-text-opacity: 1; 794 | color: rgb(239 68 68 / var(--tw-text-opacity)); 795 | } 796 | @media (prefers-color-scheme: dark) { 797 | 798 | .tab:hover { 799 | --tw-bg-opacity: 1; 800 | background-color: rgb(7 89 133 / var(--tw-bg-opacity)); 801 | } 802 | 803 | .tab:hover { 804 | --tw-text-opacity: 1; 805 | color: rgb(209 213 219 / var(--tw-text-opacity)); 806 | } 807 | } 808 | /*.tab:first-child {*/ 809 | /* @apply rounded-l;*/ 810 | /*}*/ 811 | /*.tab:last-child {*/ 812 | /* @apply rounded-r;*/ 813 | /*}*/ 814 | .tab.active { 815 | --tw-bg-opacity: 1; 816 | background-color: rgb(248 113 113 / var(--tw-bg-opacity)); 817 | --tw-text-opacity: 1; 818 | color: rgb(254 242 242 / var(--tw-text-opacity)); 819 | } 820 | @media (prefers-color-scheme: dark) { 821 | 822 | .tab.active { 823 | --tw-bg-opacity: 1; 824 | background-color: rgb(3 105 161 / var(--tw-bg-opacity)); 825 | } 826 | 827 | .tab.active { 828 | --tw-text-opacity: 1; 829 | color: rgb(209 213 219 / var(--tw-text-opacity)); 830 | } 831 | } 832 | .tab.active { 833 | /*transition: padding ease-out 0.2s;*/ 834 | } 835 | /*.urls-explanation {*/ 836 | /* @apply pb-4;*/ 837 | /*}*/ 838 | /*.urls-tried {*/ 839 | /* @apply bg-gray-50 -mx-6 border border-gray-200 rounded;*/ 840 | /*}*/ 841 | /*.urls-tried li {*/ 842 | /* @apply px-6 py-2 flex flex-row border-b border-b-gray-200;*/ 843 | /* @apply hover:bg-gray-100;*/ 844 | /*}*/ 845 | /*.urls-tried li:first-child {*/ 846 | /* @apply border-t-0;*/ 847 | /*}*/ 848 | /*.urls-tried li:last-child {*/ 849 | /* @apply border-b-0;*/ 850 | /*}*/ 851 | /*.urls-tried-regex {*/ 852 | /* @apply flex-grow;*/ 853 | /*}*/ 854 | /*.urls-tried-name {*/ 855 | /* @apply flex-grow-0 text-sm font-normal;*/ 856 | /*}*/ 857 | main > p { 858 | margin: 1rem; 859 | margin-top: 0px; 860 | } 861 | .related-settings { 862 | padding-top: 1rem; 863 | padding-bottom: 1rem; 864 | } 865 | .related-settings h6 { 866 | padding-left: 1rem; 867 | padding-right: 1rem; 868 | font-weight: 600; 869 | --tw-text-opacity: 1; 870 | color: rgb(248 113 113 / var(--tw-text-opacity)); 871 | } 872 | .traceback { 873 | /*@apply border-l border-r border-gray-200 rounded;*/ 874 | /*@apply -mx-6;*/ 875 | /*@apply shadow*/ 876 | } 877 | .traceback-cause-chain { 878 | --tw-bg-opacity: 1; 879 | background-color: rgb(255 255 255 / var(--tw-bg-opacity)); 880 | padding-top: 1rem; 881 | padding-bottom: 1rem; 882 | padding-left: 1rem; 883 | padding-right: 1rem; 884 | font-weight: 600; 885 | --tw-text-opacity: 1; 886 | color: rgb(239 68 68 / var(--tw-text-opacity)); 887 | word-break: break-word; 888 | } 889 | .traceback-frame { 890 | margin-bottom: 1rem; 891 | cursor: pointer; 892 | border-width: 1px; 893 | --tw-border-opacity: 1; 894 | border-color: rgb(229 231 235 / var(--tw-border-opacity)); 895 | } 896 | @media (prefers-color-scheme: dark) { 897 | 898 | .traceback-frame { 899 | --tw-border-opacity: 1; 900 | border-color: rgb(75 85 99 / var(--tw-border-opacity)); 901 | } 902 | } 903 | [data-expandable]:hover { 904 | --tw-border-opacity: 1; 905 | border-color: rgb(156 163 175 / var(--tw-border-opacity)); 906 | } 907 | @media (prefers-color-scheme: dark) { 908 | 909 | [data-expandable]:hover { 910 | --tw-border-opacity: 1; 911 | border-color: rgb(107 114 128 / var(--tw-border-opacity)); 912 | } 913 | } 914 | /*.traceback-frame + .traceback-frame {*/ 915 | /* @apply border-t-0*/ 916 | /*}*/ 917 | .traceback-frame.active { 918 | cursor: auto; 919 | } 920 | .traceback-where { 921 | position: -webkit-sticky; 922 | position: sticky; 923 | top: 0px; 924 | z-index: 40; 925 | display: flex; 926 | flex-direction: row; 927 | align-items: center; 928 | border-bottom-width: 1px; 929 | --tw-border-opacity: 1; 930 | border-bottom-color: rgb(229 231 235 / var(--tw-border-opacity)); 931 | padding-top: 0.5rem; 932 | padding-bottom: 0.5rem; 933 | padding-left: 1rem; 934 | padding-right: 1rem; 935 | font-size: 0.875rem; 936 | line-height: 1.25rem; 937 | } 938 | @media (prefers-color-scheme: dark) { 939 | 940 | .traceback-where { 941 | --tw-border-opacity: 1; 942 | border-bottom-color: rgb(75 85 99 / var(--tw-border-opacity)); 943 | } 944 | } 945 | .traceback-frame.library .traceback-where { 946 | --tw-bg-opacity: 1; 947 | background-color: rgb(249 250 251 / var(--tw-bg-opacity)); 948 | --tw-text-opacity: 1; 949 | color: rgb(156 163 175 / var(--tw-text-opacity)); 950 | } 951 | @media (prefers-color-scheme: dark) { 952 | 953 | .traceback-frame.library .traceback-where { 954 | --tw-bg-opacity: 1; 955 | background-color: rgb(55 65 81 / var(--tw-bg-opacity)); 956 | } 957 | } 958 | .traceback-frame.user .traceback-where { 959 | --tw-bg-opacity: 1; 960 | background-color: rgb(243 244 246 / var(--tw-bg-opacity)); 961 | --tw-text-opacity: 1; 962 | color: rgb(17 24 39 / var(--tw-text-opacity)); 963 | } 964 | @media (prefers-color-scheme: dark) { 965 | 966 | .traceback-frame.user .traceback-where { 967 | --tw-bg-opacity: 1; 968 | background-color: rgb(75 85 99 / var(--tw-bg-opacity)); 969 | } 970 | 971 | .traceback-frame.user .traceback-where { 972 | --tw-text-opacity: 1; 973 | color: rgb(209 213 219 / var(--tw-text-opacity)); 974 | } 975 | } 976 | .traceback-file { 977 | flex-grow: 1; 978 | overflow: hidden; 979 | text-overflow: ellipsis; 980 | white-space: nowrap; 981 | } 982 | .traceback-file code:first-child { 983 | font-weight: 600; 984 | } 985 | .traceback-function { 986 | flex-grow: 0; 987 | padding-left: 1rem; /* pr-4 relative; */ 988 | } 989 | /*.traceback-function:before {*/ 990 | /* @apply block bg-gray-300 absolute w-3 h-0.5 top-2.5 right-0*/ 991 | /* ;*/ 992 | /* content : "";*/ 993 | /* transition: transform 200ms ease-out;*/ 994 | /* transform: rotate(0deg);*/ 995 | /*}*/ 996 | /*.traceback-function:after {*/ 997 | /* @apply block bg-gray-300 absolute w-3 h-0.5 top-2.5 right-0*/ 998 | /* ;*/ 999 | /* transition: transform 200ms ease-out;*/ 1000 | /* transform: rotate(90deg);*/ 1001 | /* content : "";*/ 1002 | /*}*/ 1003 | /*.traceback-frame.active .traceback-function:before {*/ 1004 | /* transform: rotate(180deg);*/ 1005 | /*}*/ 1006 | /*.traceback-frame.active .traceback-function:after {*/ 1007 | /* transform: rotate(180deg);*/ 1008 | /*}*/ 1009 | .traceback-frame.user .traceback-function { 1010 | font-weight: 600; 1011 | } 1012 | /*.traceback-content {*/ 1013 | /* @apply py-4;*/ 1014 | /*}*/ 1015 | .traceback-context { 1016 | margin-top: 1rem; 1017 | margin-bottom: 1rem; 1018 | margin-left: 1rem; 1019 | margin-right: 1rem; 1020 | display: block; 1021 | overflow: hidden; 1022 | word-break: break-all; 1023 | font-size: 0; 1024 | line-height: 0; 1025 | } 1026 | .traceback-context > span { 1027 | /* this is necessary for horizontal scrolling to paint the whole line red */ 1028 | display: inline-block; 1029 | min-width: 100%; 1030 | } 1031 | .traceback-frame.active .traceback-context { 1032 | position: relative; 1033 | overflow-x: auto; 1034 | font-size: 0.875rem; 1035 | line-height: 1.25rem; 1036 | } 1037 | /*.traceback-frame.active .traceback-context:before {*/ 1038 | /* @apply block w-0 h-full absolute left-[80ch] top-0 border-r border-r-red-100*/ 1039 | /* ;*/ 1040 | /* z-index: -1;*/ 1041 | /* content: "";*/ 1042 | /*}*/ 1043 | .traceback-context-raising { 1044 | display: block; 1045 | width: 100%; 1046 | padding-right: 0.5rem; 1047 | font-size: 0.875rem; 1048 | line-height: 1.25rem; 1049 | } 1050 | .traceback-context-raising .specific { 1051 | --tw-bg-opacity: 1; 1052 | background-color: rgb(185 28 28 / var(--tw-bg-opacity)); 1053 | padding-left: 0.5rem; 1054 | padding-right: 0.5rem; 1055 | padding-top: 2px; 1056 | padding-bottom: 2px; 1057 | font-weight: 600; 1058 | --tw-text-opacity: 1; 1059 | color: rgb(255 255 255 / var(--tw-text-opacity)); 1060 | } 1061 | @media (prefers-color-scheme: dark) { 1062 | 1063 | .traceback-context-raising .specific { 1064 | --tw-bg-opacity: 1; 1065 | background-color: rgb(3 105 161 / var(--tw-bg-opacity)); 1066 | } 1067 | 1068 | .traceback-context-raising .specific { 1069 | --tw-text-opacity: 1; 1070 | color: rgb(224 242 254 / var(--tw-text-opacity)); 1071 | } 1072 | } 1073 | .traceback-frame.library .traceback-context-raising { 1074 | --tw-text-opacity: 1; 1075 | color: rgb(156 163 175 / var(--tw-text-opacity)); 1076 | } 1077 | .traceback-frame.user .traceback-context-raising { 1078 | --tw-text-opacity: 1; 1079 | color: rgb(17 24 39 / var(--tw-text-opacity)); 1080 | } 1081 | @media (prefers-color-scheme: dark) { 1082 | 1083 | .traceback-frame.user .traceback-context-raising { 1084 | --tw-text-opacity: 1; 1085 | color: rgb(209 213 219 / var(--tw-text-opacity)); 1086 | } 1087 | } 1088 | .traceback-frame.active .traceback-context-raising { 1089 | --tw-bg-opacity: 1; 1090 | background-color: rgb(239 68 68 / var(--tw-bg-opacity)); 1091 | --tw-text-opacity: 1; 1092 | color: rgb(255 255 255 / var(--tw-text-opacity)); 1093 | } 1094 | @media (prefers-color-scheme: dark) { 1095 | 1096 | .traceback-frame.active .traceback-context-raising { 1097 | --tw-bg-opacity: 1; 1098 | background-color: rgb(12 74 110 / var(--tw-bg-opacity)); 1099 | } 1100 | } 1101 | .traceback-locals { 1102 | display: none; 1103 | /*my-4;*/ 1104 | } 1105 | .traceback-locals > h6 { 1106 | border-bottom-width: 1px; 1107 | --tw-border-opacity: 1; 1108 | border-bottom-color: rgb(229 231 235 / var(--tw-border-opacity)); 1109 | padding-top: 0.5rem; 1110 | padding-bottom: 0.5rem; 1111 | padding-left: 1rem; 1112 | padding-right: 1rem; 1113 | font-size: 0.875rem; 1114 | line-height: 1.25rem; 1115 | font-weight: 600; 1116 | } 1117 | @media (prefers-color-scheme: dark) { 1118 | 1119 | .traceback-locals > h6 { 1120 | --tw-border-opacity: 1; 1121 | border-bottom-color: rgb(75 85 99 / var(--tw-border-opacity)); 1122 | } 1123 | } 1124 | .traceback-locals > code { 1125 | display: block; 1126 | } 1127 | .traceback-locals > p { 1128 | padding-left: 1rem; 1129 | padding-right: 1rem; 1130 | } 1131 | .traceback-frame.active .traceback-locals { 1132 | display: block; 1133 | } 1134 | .traceback-clipboard { 1135 | border-radius: 0.25rem; 1136 | --tw-bg-opacity: 1; 1137 | background-color: rgb(254 242 242 / var(--tw-bg-opacity)); 1138 | padding-top: 0.5rem; 1139 | padding-bottom: 0.5rem; 1140 | padding-left: 0.75rem; 1141 | padding-right: 0.75rem; 1142 | font-size: 0.875rem; 1143 | line-height: 1.25rem; 1144 | font-weight: 600; 1145 | text-transform: uppercase; 1146 | } 1147 | .traceback-clipboard:hover { 1148 | --tw-bg-opacity: 1; 1149 | background-color: rgb(248 113 113 / var(--tw-bg-opacity)); 1150 | --tw-text-opacity: 1; 1151 | color: rgb(255 255 255 / var(--tw-text-opacity)); 1152 | } 1153 | .rowable { 1154 | display: block; 1155 | width: 100%; 1156 | table-layout: auto; 1157 | border-collapse: collapse; 1158 | font-size: 0.875rem; 1159 | line-height: 1.25rem; 1160 | } 1161 | @media (min-width: 1024px) { 1162 | 1163 | .rowable { 1164 | display: table; 1165 | } 1166 | } 1167 | .rowable { 1168 | max-width: 100vw; 1169 | } 1170 | .rowable li { 1171 | display: block; 1172 | border-bottom-width: 1px; 1173 | padding-bottom: 0.5rem; 1174 | } 1175 | @media (prefers-color-scheme: dark) { 1176 | 1177 | .rowable li { 1178 | --tw-border-opacity: 1; 1179 | border-bottom-color: rgb(75 85 99 / var(--tw-border-opacity)); 1180 | } 1181 | } 1182 | @media (min-width: 1024px) { 1183 | 1184 | .rowable li { 1185 | display: table-row; 1186 | } 1187 | 1188 | .rowable li { 1189 | padding-bottom: 0px; 1190 | } 1191 | } 1192 | .rowable li:last-child { 1193 | border-bottom-width: 0px; 1194 | padding-bottom: 0px; 1195 | } 1196 | .rowable li code { 1197 | display: block; 1198 | width: 100%; 1199 | padding-top: 0.5rem; 1200 | padding-bottom: 0.5rem; 1201 | padding-left: 1rem; 1202 | } 1203 | @media (min-width: 1024px) { 1204 | 1205 | .rowable li code { 1206 | display: table-cell; 1207 | } 1208 | 1209 | .rowable li code { 1210 | width: 1rem; 1211 | } 1212 | } 1213 | .rowable li pre { 1214 | margin-left: 1rem; 1215 | margin-right: 1rem; 1216 | display: block; 1217 | max-width: 100%; 1218 | overflow-x: auto; 1219 | overflow-y: hidden; 1220 | padding-top: 0px; 1221 | padding-bottom: 0px; 1222 | } 1223 | @media (min-width: 1024px) { 1224 | 1225 | .rowable li pre { 1226 | margin-left: 0px; 1227 | margin-right: 0px; 1228 | } 1229 | 1230 | .rowable li pre { 1231 | display: table-cell; 1232 | } 1233 | 1234 | .rowable li pre { 1235 | padding-top: 0.5rem; 1236 | padding-bottom: 0.5rem; 1237 | } 1238 | 1239 | .rowable li pre { 1240 | padding-left: 1rem; 1241 | padding-right: 1rem; 1242 | } 1243 | } 1244 | .rowable li pre { 1245 | word-break: break-word; 1246 | } 1247 | .rowable.locals { 1248 | 1249 | } 1250 | .rowable.settings { 1251 | 1252 | } 1253 | .rowable.request { 1254 | 1255 | } 1256 | /*.rowable.urls {*/ 1257 | /* @apply lg:block;*/ 1258 | /*}*/ 1259 | .rowable.urls li { 1260 | /*@apply border-0;*/ 1261 | } 1262 | .rowable.urls li pre { 1263 | overflow: hidden; 1264 | text-overflow: ellipsis; 1265 | white-space: nowrap; 1266 | word-break: break-word; 1267 | } 1268 | /*.rowable.urls li > span {*/ 1269 | /* @apply*/ 1270 | /* flex max-w-full*/ 1271 | /* whitespace-nowrap text-right*/ 1272 | /* mx-4*/ 1273 | /* px-2 py-1 leading-none bg-gray-100 rounded*/ 1274 | /* !*w-4 whitespace-nowrap text-right*!*/ 1275 | /* !*py-0 mx-4*!*/ 1276 | /* !*!*lg:py-2 lg:px-4 *!*!*/ 1277 | /* !*lg:mx-0 lg:table-cell*!*/ 1278 | /* ;*/ 1279 | /*}*/ 1280 | /*.rowable.urls li code span {*/ 1281 | /* @apply inline-flex truncate*/ 1282 | /* !*@apply py-2 px-4 inline-flex text-sm;*!*/ 1283 | /*}*/ 1284 | .pattern { 1285 | white-space: normal; 1286 | } 1287 | /*.url-match {*/ 1288 | /* @apply*/ 1289 | /* inline-flex*/ 1290 | /* bg-green-50 text-green-700*/ 1291 | /* py-0.5 px-1*/ 1292 | /* mr-1*/ 1293 | /* !*-ml-1.5 mr-0.5*!*/ 1294 | /* border-green-200 border rounded*/ 1295 | /* ;*/ 1296 | /*}*/ 1297 | .url-match { 1298 | display: inline-flex; 1299 | --tw-bg-opacity: 1; 1300 | background-color: rgb(220 252 231 / var(--tw-bg-opacity)); 1301 | --tw-text-opacity: 1; 1302 | color: rgb(22 163 74 / var(--tw-text-opacity)); 1303 | } 1304 | @media (prefers-color-scheme: dark) { 1305 | 1306 | .url-match { 1307 | background-color: inherit; 1308 | } 1309 | 1310 | .url-match { 1311 | --tw-text-opacity: 1; 1312 | color: rgb(56 189 248 / var(--tw-text-opacity)); 1313 | } 1314 | } 1315 | .tooltip2 { 1316 | pointer-events: none; 1317 | position: absolute; 1318 | top: 1.5rem; 1319 | z-index: 50; 1320 | max-width: 65ch; 1321 | -webkit-user-select: none; 1322 | -moz-user-select: none; 1323 | -ms-user-select: none; 1324 | user-select: none; 1325 | border-radius: 0.25rem; 1326 | --tw-bg-opacity: 1; 1327 | background-color: rgb(107 114 128 / var(--tw-bg-opacity)); 1328 | padding-left: 0.75rem; 1329 | padding-right: 0.75rem; 1330 | padding-top: 0.5rem; 1331 | padding-bottom: 0.5rem; 1332 | text-align: center; 1333 | font-size: 0.75rem; 1334 | line-height: 1rem; 1335 | font-weight: 600; 1336 | --tw-text-opacity: 1; 1337 | color: rgb(255 255 255 / var(--tw-text-opacity)); 1338 | opacity: 0; 1339 | transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 1340 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 1341 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 1342 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1343 | transition-delay: 100ms; 1344 | transition-duration: 100ms; 1345 | transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1346 | transform: translateX(-50%) scale(0, 1); 1347 | left: 50%; 1348 | } 1349 | .tooltip2:after { 1350 | pointer-events: none; 1351 | position: absolute; 1352 | top: 0px; 1353 | margin-left: -0.5rem; 1354 | height: 0px; 1355 | width: 0px; 1356 | -webkit-user-select: none; 1357 | -moz-user-select: none; 1358 | -ms-user-select: none; 1359 | user-select: none; 1360 | border-width: 8px; 1361 | border-color: transparent; 1362 | --tw-border-opacity: 1; 1363 | border-bottom-color: rgb(107 114 128 / var(--tw-border-opacity)); 1364 | transition-duration: 100ms; 1365 | transition-timing-function: linear; 1366 | transition-property: top; 1367 | content: ""; 1368 | left: 50%; 1369 | z-index: -1; 1370 | transition-delay: 0s; 1371 | } 1372 | .tooltip2:hover:after { 1373 | bottom: -1rem; 1374 | transition-delay: 200ms; 1375 | } 1376 | .tooltip { 1377 | position: relative; 1378 | } 1379 | .tooltip:before { 1380 | pointer-events: none; 1381 | position: absolute; 1382 | top: 1.5rem; 1383 | z-index: 20; 1384 | max-width: 65ch; 1385 | --tw-scale-x: 0; 1386 | --tw-scale-y: 0; 1387 | transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); 1388 | -webkit-user-select: none; 1389 | -moz-user-select: none; 1390 | -ms-user-select: none; 1391 | user-select: none; 1392 | border-radius: 0.25rem; 1393 | --tw-bg-opacity: 1; 1394 | background-color: rgb(107 114 128 / var(--tw-bg-opacity)); 1395 | padding-left: 0.75rem; 1396 | padding-right: 0.75rem; 1397 | padding-top: 0.5rem; 1398 | padding-bottom: 0.5rem; 1399 | text-align: center; 1400 | font-size: 0.75rem; 1401 | line-height: 1rem; 1402 | --tw-text-opacity: 1; 1403 | color: rgb(255 255 255 / var(--tw-text-opacity)); 1404 | opacity: 0; 1405 | transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 1406 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 1407 | transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; 1408 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1409 | transition-delay: 1000ms; 1410 | transition-duration: 200ms; 1411 | transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1412 | content: attr(aria-label); 1413 | transform-origin: center; 1414 | transform: translateX(-50%) scale(0); 1415 | left: 50%; 1416 | /*pointer-events: none;*/ 1417 | } 1418 | .tooltip:hover:before { 1419 | opacity: 1; 1420 | transition-timing-function: cubic-bezier(0.4, 0, 1, 1); 1421 | transition-delay: 0s; 1422 | transform: translateX(-50%) scale(1); 1423 | } 1424 | .tooltip:after { 1425 | bottom: -1rem; 1426 | z-index: 10; 1427 | margin-left: -0.5rem; 1428 | height: 0px; 1429 | width: 0px; 1430 | -webkit-user-select: none; 1431 | -moz-user-select: none; 1432 | -ms-user-select: none; 1433 | user-select: none; 1434 | border-width: 8px; 1435 | border-color: transparent; 1436 | --tw-border-opacity: 1; 1437 | border-bottom-color: rgb(107 114 128 / var(--tw-border-opacity)); 1438 | opacity: 0; 1439 | transition-duration: 100ms; 1440 | transition-timing-function: cubic-bezier(0, 0, 0.2, 1); 1441 | transition-property: opacity, bottom; 1442 | left: 50%; 1443 | content: ""; 1444 | position: absolute; 1445 | pointer-events: none; 1446 | } 1447 | .tooltip:hover:after { 1448 | bottom: -0.625rem; 1449 | opacity: 1; 1450 | transition-delay: 200ms; 1451 | transition-timing-function: cubic-bezier(0.4, 0, 1, 1); 1452 | } 1453 | .flex { 1454 | display: flex; 1455 | } 1456 | .inline-flex { 1457 | display: inline-flex; 1458 | } 1459 | .table-cell { 1460 | display: table-cell; 1461 | } 1462 | .table-row { 1463 | display: table-row; 1464 | } 1465 | .hidden { 1466 | display: none; 1467 | } 1468 | .w-full { 1469 | width: 100%; 1470 | } 1471 | .flex-grow { 1472 | flex-grow: 1; 1473 | } 1474 | .flex-grow-0 { 1475 | flex-grow: 0; 1476 | } 1477 | .flex-col { 1478 | flex-direction: column; 1479 | } 1480 | .items-center { 1481 | align-items: center; 1482 | } 1483 | .justify-center { 1484 | justify-content: center; 1485 | } 1486 | .rounded { 1487 | border-radius: 0.25rem; 1488 | } 1489 | .border-b { 1490 | border-bottom-width: 1px; 1491 | } 1492 | .bg-gray-100 { 1493 | --tw-bg-opacity: 1; 1494 | background-color: rgb(243 244 246 / var(--tw-bg-opacity)); 1495 | } 1496 | .bg-red-200 { 1497 | --tw-bg-opacity: 1; 1498 | background-color: rgb(254 202 202 / var(--tw-bg-opacity)); 1499 | } 1500 | .bg-gray-200 { 1501 | --tw-bg-opacity: 1; 1502 | background-color: rgb(229 231 235 / var(--tw-bg-opacity)); 1503 | } 1504 | .px-6 { 1505 | padding-left: 1.5rem; 1506 | padding-right: 1.5rem; 1507 | } 1508 | .py-2 { 1509 | padding-top: 0.5rem; 1510 | padding-bottom: 0.5rem; 1511 | } 1512 | .py-4 { 1513 | padding-top: 1rem; 1514 | padding-bottom: 1rem; 1515 | } 1516 | .px-10 { 1517 | padding-left: 2.5rem; 1518 | padding-right: 2.5rem; 1519 | } 1520 | .px-2 { 1521 | padding-left: 0.5rem; 1522 | padding-right: 0.5rem; 1523 | } 1524 | .py-1 { 1525 | padding-top: 0.25rem; 1526 | padding-bottom: 0.25rem; 1527 | } 1528 | .pr-10 { 1529 | padding-right: 2.5rem; 1530 | } 1531 | .pt-4 { 1532 | padding-top: 1rem; 1533 | } 1534 | .text-right { 1535 | text-align: right; 1536 | } 1537 | .text-sm { 1538 | font-size: 0.875rem; 1539 | line-height: 1.25rem; 1540 | } 1541 | .text-xs { 1542 | font-size: 0.75rem; 1543 | line-height: 1rem; 1544 | } 1545 | .font-semibold { 1546 | font-weight: 600; 1547 | } 1548 | .font-bold { 1549 | font-weight: 700; 1550 | } 1551 | .leading-none { 1552 | line-height: 1; 1553 | } 1554 | .text-gray-500 { 1555 | --tw-text-opacity: 1; 1556 | color: rgb(107 114 128 / var(--tw-text-opacity)); 1557 | } 1558 | .text-gray-400 { 1559 | --tw-text-opacity: 1; 1560 | color: rgb(156 163 175 / var(--tw-text-opacity)); 1561 | } 1562 | .text-red-500 { 1563 | --tw-text-opacity: 1; 1564 | color: rgb(239 68 68 / var(--tw-text-opacity)); 1565 | } 1566 | @media (min-width: 1024px) { 1567 | 1568 | .lg\:w-1\/2 { 1569 | width: 50%; 1570 | } 1571 | 1572 | .lg\:flex-row { 1573 | flex-direction: row; 1574 | } 1575 | } 1576 | -------------------------------------------------------------------------------- /technicalerrors/templates/django-logo-positive-original.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /technicalerrors/templates/django-logo-positive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /technicalerrors/templates/technical_404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {# #} 8 | 9 | Page not found at {{ request.path_info }} 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 |
20 | 21 |
22 |
{{ request.META.REQUEST_METHOD }}
23 |
24 | {{ request.scheme }}://{{ request.get_host }}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %} 25 |
26 | 27 | 28 | 29 | 30 |
31 |
32 |

URL not found

33 | 34 | {% if reason and resolved %} 35 | {# Only show the reason if it's not the __repr__ of a Resolver404 #} 36 |

{{ reason }}

37 | {% endif %} 38 |
39 | {% if raising_view_name %} 40 |
41 | raised by {{ raising_view_name }} 42 |
43 | {% endif %} 44 |
45 |
46 | 47 |
    48 | {% if urlpatterns %} 49 |
  • 50 | URL Patterns 51 |
  • 52 | {% endif %} 53 |
  • 54 | Request Data 55 |
  • 56 |
  • 57 | Cookies 58 |
  • 59 |
  • 60 | Environment 61 |
  • 62 |
  • 63 | Settings 64 |
  • 65 |
66 | 67 |
68 | 69 |
70 |

Django tried these URL patterns, in this order

71 | 72 | Using the URLconf 73 | {% if urlconf != root_urlconf %} 74 | {{ urlconf }} instead of ROOT_URLCONF {{ root_urlconf }} 75 | {% else %} 76 | {{ root_urlconf }}{% endif %}{% if urlpatterns %}, tried {{ urlpatterns|length }} route{{ urlpatterns|length|pluralize:"s" }}:{% endif %} 77 | 78 | {% if urlpatterns %} 79 |
    80 | {% for pattern in urlpatterns %} 81 |
  1. 82 |
    83 | 84 | {% for pat in pattern %}{% if forloop.parentloop.last and resolved or pattern|length > 1 and not forloop.last %}{{ pat.pattern.regex.pattern }}{% else %}{{ pat.pattern.regex.pattern }}{% endif %}{% endfor %} 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | {% if forloop.parentloop.last and resolved or pattern|length > 1 and not forloop.last %} 95 | 96 | Partial match 97 | 98 | {% endif %} 99 |
    100 |
      101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | {% for pat in pattern %} 109 | {% if pat.urlconf_module|force_escape|slice:"0:10" == "<module" %} 110 |
    1. Module
      {{ pat.urlconf_module|force_escape|slice:"10:-4" }}
    2. 111 | {% endif %} 112 | {% if pat.lookup_str %} 113 |
    3. View 114 |
      {{ pat.lookup_str }}
      115 |
    4. 116 | {% endif %} 117 | {% endfor %} 118 | 119 |
    5. Name 120 |
      {% for pat in pattern %}{% if pat.app_name %}{{ pat.app_name }}:{% endif %}{% if pat.namespace != pat.app_name %}{{ pat.namespace}}:{% endif %}{% if pat.name %}{{ pat.name }}{% elif forloop.last %}...{% endif %}{% endfor %}
      121 |
    6. 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 |
    149 |
  2. 150 | {% endfor %} 151 |
152 | 153 | {% endif %} 154 | 155 | 156 | {% if resolved %} 157 |

158 | The last pattern matched {{ request.path_info }} but an Http404 exception was raised. 159 |

160 | {% else %} 161 |

162 | None of the patterns matched {{ request.path_info }}, so a Resolver404 was raised. 163 |

164 | {% endif %} 165 | 166 | 167 | 168 | 169 |
    170 | {% for key, value in settings.items|dictsort:0 %} 171 | {% if 'URL' in key or 'PREPEND_WWW' in key or 'APPEND_SLASH' in key or 'MEDIA_' in key or 'STATICFILES' in key or 'STATIC_' in key or 'X_FORWARDED' in key %} 172 |
  • 173 | {{ key }} 174 |
    {{ value|pprint }}
    175 |
  • 176 | {% endif %} 177 | {% endfor %} 178 |
179 |
180 | 181 | 182 | 249 | 250 | 251 | {% if request.COOKIES.items %} 252 | 278 | {% endif %} 279 | 280 | 281 | 309 | 310 | 311 | 346 | 347 | 348 |
349 | 350 |
351 | You’re seeing this because you have DEBUG = True in your 352 | Django settings. When set to False, Django will 353 | display a generic 404 template. 354 |
355 | 356 | 357 | -------------------------------------------------------------------------------- /technicalerrors/templates/technical_500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% if exception_type %}{{ exception_type }}{% else %}An error occurred{% endif %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | {% if request %} 23 |
24 |
{{ request.META.REQUEST_METHOD }}
25 |
{{ request_insecure_uri }}
26 |
27 | {% endif %} 28 |
29 |

{% if exception_type %}{{ exception_type }}{% else %}An error occurred{% endif %}

30 | 31 | {% if unicode_hint %} 32 |

The string that could not be encoded/decoded was: {{ unicode_hint }}

33 |

{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}

34 | {% elif template_does_not_exist and postmortem %} 35 | 36 |

37 | Failed to load a template {% if exception_value %}matching {{ exception_value|force_escape }}{% endif %} 38 |

39 | 40 | {% elif template_does_not_exist %} 41 |

No templates were found because your 'TEMPLATES' setting is not configured.

42 | {% else %} 43 |

{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}

44 | {% endif %} 45 |
46 | 47 | 54 | 55 |

56 | Raised 57 | {% if raising_view_name %} during view {{ raising_view_name }}{% endif %} 58 | 59 | {% if lastframe %} by {{ lastframe.function }} on line {{ lastframe.lineno }} in {{ lastframe.filename }}{% endif %} 60 |

61 | 62 |
63 |
Django {{ django_version_info }} 64 | 65 |
66 |
Python {{ sys_version_info }}
67 | {% if user_str %} 68 |
{{ user_str }}
69 | {% endif %} 70 |
{{ server_time|date:"r" }}
71 | 72 | 73 |
74 | 75 |
76 | 77 | 78 |
79 | 80 |
    81 | {% if template_info or postmortem %} 82 |
  • 83 | Template 84 |
  • 85 | {% endif %} 86 | {% if frames %} 87 |
  • 88 | Traceback 89 |
  • 90 | {% endif %} 91 |
  • 92 | Request Data 93 |
  • 94 | 95 | 96 | 97 |
  • 98 | Environment 99 |
  • 100 |
  • 101 | Settings 102 |
  • 103 |
104 | 105 |
106 | 107 | {% if template_info %} 108 |
109 |
    110 |
  1. 111 |
    112 | Line {{ template_info.line }} in template {{ template_info.name }} 113 |
    114 |
    {% for source_line in template_info.source_lines %}{% if source_line.0 == template_info.line %}{{ template_info.before }}{{ template_info.during }}{{ template_info.after }}{% else %}{{ source_line.1 }}{% endif %}{% endfor %}
    115 |
  2. 116 |
117 | 118 | {% if settings and settings.TEMPLATES or settings.FORM_RENDERER %} 119 | 132 | {% endif %} 133 | 134 |
135 | {% elif postmortem %} 136 |
137 | 138 |

Templates were tried in the following order:

139 | 140 |
    141 | {% for entry in postmortem %} 142 | {% if entry.tried %} 143 |
  1. 144 | {% regroup entry.tried by 0.loader_name as attempts_by_loader %} 145 | {% for loader_name, items in attempts_by_loader %} 146 |
    147 | {{ entry }} using {{ loader_name }} 148 | 149 |
    150 |
    151 |
      152 | {% for item in items %}
    1. {{ item.0.name }}
    2. {% endfor %} 153 |
    154 |
    155 | {% endfor %} 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | {% else %} 173 |
  2. 174 |
    175 | {{ entry }} using {{ entry.backend.name }} engine 176 |
    177 |
    178 |

    Did not provide a list of tried template paths.

    179 |
    180 |
  3. 181 | {% endif %} 182 | {% endfor %} 183 |
184 | 185 | 206 | 207 | {% if settings and settings.TEMPLATES or settings.FORM_RENDERER %} 208 | 221 | {% endif %} 222 |
223 | {% endif %} 224 | 225 | {% if frames %} 226 |
227 | 228 |
    229 | {% for frame in frames %} 230 | {% ifchanged frame.exc_cause %} 231 | {% if frame.exc_cause %} 232 |
  1. 233 | {% if frame.exc_cause_explicit %} 234 | The above was was the direct cause of:
    235 | {{ frame.exc_cause }} 236 | {% else %} 237 | A nother exception occurred during handling of:
    238 | {{ frame.exc_cause|force_escape }} 239 | {% endif %} 240 |
  2. 241 | {% endif %} 242 | {% endifchanged %} 243 | 244 | {% if frame.tb %} 245 |
  3. 246 |
    247 | Line {{ frame.lineno }} in {{ frame.filename }} 248 | {{ frame.function }} 249 |
    250 | 251 | {% if frame.context_line %} 252 |
    {% for line in frame.pre_context %}{{ line }}
    253 | {% endfor %}{{ frame.context_line }}{% for line in frame.post_context %}{{ line }}
    254 | {% endfor %}
    255 | {% endif %} 256 | 257 | 258 | {% if frame.vars %} 259 |
    260 |
    {{ frame.vars|length }} local variable{{ frame.vars|pluralize:"s" }}
    261 |
      262 | {% for var_name, var_value in frame.vars|dictsort:0 %} 263 |
    • 264 | {{ var_name }} 265 | 266 | {{ var_value }} 267 |
    • 268 | {% endfor %} 269 |
    270 |
    271 | {% endif %} 272 |
  4. 273 | {% endif %} 274 | {% endfor %} 275 |
276 | 277 | 316 | 317 | 318 | 319 | 320 | 321 | 338 |
339 | {% endif %} 340 | 341 | 342 | 343 | 441 | 442 | {% if request_COOKIES_items %} 443 | 471 | {% endif %} 472 | 473 | 498 | 499 | 530 | 531 |
532 | 533 | 534 | {% if not is_email %} 535 | 540 | {% endif %} 541 | 542 | 543 | 544 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "strictNullChecks": true, 5 | "sourceMap": true, 6 | "strictFunctionTypes": true, 7 | "strictPropertyInitialization": true, 8 | "strictBindCallApply": true, 9 | "noImplicitThis": true, 10 | "noImplicitReturns": true, 11 | "alwaysStrict": true, 12 | "allowUnreachableCode": false, 13 | "allowUnusedLabels": false, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "esModuleInterop": true, 17 | "declaration": true, 18 | "lib": ["ES2020", "DOM"], 19 | "target": "es2017", 20 | "module": "AMD", 21 | "jsx": "react" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "no-console": false 9 | }, 10 | "rulesDirectory": [] 11 | } 12 | --------------------------------------------------------------------------------