diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0ff18822 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/docs/overrides/__pycache__/ \ No newline at end of file diff --git a/docs/assets/extra.css b/docs/assets/extra.css index 329346f7..1b5411f9 100644 --- a/docs/assets/extra.css +++ b/docs/assets/extra.css @@ -5,4 +5,14 @@ --md-accent-fg-color: #eb4432; --md-accent-fg-color--light: #eb4432; --md-accent-fg-color--dark: #eb4432; +} + +.mdx-badge__icon{ + background:var(--md-accent-fg-color--transparent); + padding:.2rem +} +.mdx-badge__text{ + font-size:.85em; + box-shadow:0 0 0 1px inset var(--md-accent-fg-color--transparent); + padding:.2rem .3rem } \ No newline at end of file diff --git a/docs/collectors.md b/docs/collectors.md index 27593a2b..dd93b2ce 100644 --- a/docs/collectors.md +++ b/docs/collectors.md @@ -130,6 +130,16 @@ The Query Collector has the following features ], ``` +#### On-demand query EXPLAIN + + + + +Enable the `options.db.explain` option to run on-demand EXPLAIN queries for any SELECT query in the Debugbar. +This will update in the interface. You also have an option to navigate to mysqlexplain.com for a visual explain. + +![Query On-demand Explain](img/query-explain.gif) + ### RouteCollector This shows the current route and middleware. diff --git a/docs/img/query-explain.gif b/docs/img/query-explain.gif new file mode 100644 index 00000000..7b5a4188 Binary files /dev/null and b/docs/img/query-explain.gif differ diff --git a/docs/overrides/shortcodes.py b/docs/overrides/shortcodes.py new file mode 100644 index 00000000..d29eddf4 --- /dev/null +++ b/docs/overrides/shortcodes.py @@ -0,0 +1,106 @@ +## File based on https://github.com/processone/docs.ejabberd.im/blob/master/shortcodes.py and +## https://github.com/squidfunk/mkdocs-material/tree/master/material/overrides/hooks + +# Copyright (c) 2016-2024 Martin Donath + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +from __future__ import annotations + +import posixpath +import re + +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.structure.files import File, Files +from mkdocs.structure.pages import Page +from re import Match + +# ----------------------------------------------------------------------------- +# Hooks +# ----------------------------------------------------------------------------- + +# @todo +def on_page_markdown( + markdown: str, *, page: Page, config: MkDocsConfig, files: Files +): + + # Replace callback + def replace(match: Match): + type, args = match.groups() + args = args.strip() + if type == "version": + return _badge_for_version(args, page, files) + elif type == "flag": return flag(args, page, files) + + # Otherwise, raise an error + raise RuntimeError(f"Unknown shortcode: {type}") + + # Find and replace all external asset URLs in current page + return re.sub( + r"", + replace, markdown, flags = re.I | re.M + ) + +# ----------------------------------------------------------------------------- +# Create a flag of a specific type +def flag(args: str, page: Page, files: Files): + type, *_ = args.split(" ", 1) + if type == "experimental": return _badge_for_experimental(page, files) + + raise RuntimeError(f"Unknown type: {type}") + +# Create badge +def _badge(icon: str, text: str = "", type: str = ""): + classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge" + return "".join([ + f"", + *([f"{icon}"] if icon else []), + *([f"{text}"] if text else []), + f"", + ]) + + +# Create badge for version +def _badge_for_version(text: str, page: Page, files: Files): + spec = text + path = f"https://github.com/barryvdh/laravel-debugbar/releases/tag/{spec}" + + # Return badge + icon = "material-tag-outline" + return _badge( + icon = f"[:{icon}:]({path} 'Minimum version')", + text = f"{text}" if spec else "" + ) + +# Create badge for default value +def _badge_for_default(text: str, page: Page, files: Files): + icon = "material-water" + return _badge( + icon = f"[:{icon}:]('Default value')", + text = text + ) + + +# Create badge for experimental flag +def _badge_for_experimental(page: Page, files: Files): + icon = "material-flask-outline" + return _badge( + icon = f"[:{icon}:]('Experimental')", + text = f"Experimental" + ) diff --git a/mkdocs.yml b/mkdocs.yml index d7994198..b0358e8a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,6 +33,7 @@ theme: - navigation.footer - navigation.sections - navigation.expand + - content.tooltips - content.code.copy - content.action.edit - toc.follow @@ -44,6 +45,7 @@ extra_javascript: - assets/debugbar.js markdown_extensions: - admonition + - abbr - attr_list - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji @@ -78,3 +80,5 @@ extra: - icon: fontawesome/brands/github link: https://github.com/barryvdh/laravel-debugbar +hooks: + - docs/overrides/shortcodes.py