{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "\n",
    "pn.extension('mathjax')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `Markdown` pane allows rendering arbitrary [Markdown](https://python-markdown.github.io) in a panel. It renders strings containing valid Markdown as well as objects with a `_repr_markdown_` method, and may define custom CSS styles.\n",
    "\n",
    "#### Parameters:\n",
    "\n",
    "For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n",
    "\n",
    "* **`dedent`** (bool, `default=True`): Whether to dedent common whitespace across all lines.\n",
    "* **`disable_anchors`** (boolean, `default=False`): Whether to disable automatically adding anchors to headings.\n",
    "* **`disable_math`** (boolean, `default=False`): Whether to disable MathJax math rendering for strings escaped with `$$` delimiters.\n",
    "* **`enable_streaming`** (boolean, `default=False`): Whether to enable streaming of text snippets. This will diff the `object` when it is updated and only send the trailing chunk that was added.\n",
    "* **`extensions`** (list): A list of [Python-Markdown extensions](https://python-markdown.github.io/extensions/) to use (does not apply for 'markdown-it' and 'myst' renderers).\n",
    "* **`hard_line_break`** (bool, `default=False`): Whether simple new lines are rendered as hard line breaks. False by default to conform with the original Markdown spec. Not supported by the `'myst'` renderer.\n",
    "* **`object`** (str or object): A string containing Markdown, or an object with a ``_repr_markdown_`` method.\n",
    "* **`plugins`** (function): A list of additional markdown-it-py plugins to apply.\n",
    "* **`renderer`** (literal: `'markdown-it'`, `'markdown'`, `'myst'`): Markdown renderer implementation.\n",
    "* **`renderer_options`** (dict): Options to pass to the markdown renderer.\n",
    "\n",
    "___"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `Markdown` pane accepts all *basic* Markdown syntax, including embedded HTML. It also supports most of the *extended* Markdown syntax."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "pn.pane.Markdown(\"\"\"\n",
    "\n",
    "# Markdown Sample\n",
    "\n",
    "This sample text is from [The Markdown Guide](https://www.markdownguide.org)!\n",
    "\n",
    "## Basic Syntax\n",
    "\n",
    "These are the elements outlined in John Gruber’s original design document. All Markdown applications support these elements.\n",
    "\n",
    "### Heading\n",
    "\n",
    "# H1\n",
    "## H2\n",
    "### H3\n",
    "\n",
    "### Bold\n",
    "\n",
    "**bold text**\n",
    "\n",
    "### Italic\n",
    "\n",
    "*italicized text*\n",
    "\n",
    "### Blockquote\n",
    "\n",
    "> blockquote\n",
    "\n",
    "### Ordered List\n",
    "\n",
    "1. First item\n",
    "2. Second item\n",
    "3. Third item\n",
    "\n",
    "### Unordered List\n",
    "\n",
    "- First item\n",
    "- Second item\n",
    "- Third item\n",
    "\n",
    "### Code\n",
    "\n",
    "`code`\n",
    "\n",
    "### Horizontal Rule\n",
    "\n",
    "---\n",
    "\n",
    "### Link\n",
    "\n",
    "[Markdown Guide](https://www.markdownguide.org)\n",
    "\n",
    "### Image\n",
    "\n",
    "![alt text](https://www.markdownguide.org/assets/images/tux.png)\n",
    "\n",
    "## Extended Syntax\n",
    "\n",
    "These elements extend the basic syntax by adding additional features. Not all Markdown applications support these elements.\n",
    "\n",
    "### Table\n",
    "\n",
    "| Syntax | Description |\n",
    "| ----------- | ----------- |\n",
    "| Header | Title |\n",
    "| Paragraph | Text |\n",
    "\n",
    "### Fenced Code Block\n",
    "\n",
    "```\n",
    "{\n",
    "  \"firstName\": \"John\",\n",
    "  \"lastName\": \"Smith\",\n",
    "  \"age\": 25\n",
    "}\n",
    "```\n",
    "\n",
    "### Footnote\n",
    "\n",
    "Here's a sentence with a footnote. [^1]\n",
    "\n",
    "[^1]: This is the footnote.\n",
    "\n",
    "### Definition List\n",
    "\n",
    "term\n",
    ": Some definition of the term goes here\n",
    "\n",
    "### Strikethrough\n",
    "\n",
    "~~The world is flat.~~\n",
    "\n",
    "### Task List\n",
    "\n",
    "- [x] Write the press release\n",
    "- [ ] Update the website\n",
    "- [ ] Contact the media\n",
    "\n",
    "### Emoji\n",
    "\n",
    "That is so funny! 😂\n",
    "\n",
    "(See also [Copying and Pasting Emoji](https://www.markdownguide.org/extended-syntax/#copying-and-pasting-emoji))\n",
    "\n",
    "\"\"\", width=500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Style\n",
    "\n",
    "If you want to control the behavior of the HTML that is generated from the Markdown source, it is often possible to do that by passing parameters to the `styles` parameter of this pane.  For instance, you can add a blue border around a Markdown table as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "pn.pane.Markdown(\"\"\"\n",
    "| Syntax | Description |\n",
    "| ----------- | ----------- |\n",
    "| Header | Title |\n",
    "| Paragraph | Text |\n",
    "\n",
    "\"\"\", styles={'border': \"4px solid blue\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, styles specified in this way will only be applied to the outermost Div, and there is not currently any way to apply styling in this way to specific internal elements of the HTML.  In this case, we cannot use the `styles` parameter to control styling of the rows or headings of the generated table. \n",
    "\n",
    "If we do want to change specific internal elements of the generated HTML, we can do so by providing an HTML/CSS &lt;style&gt; section. For instance, we can change the border thickness for headers and data as follows, but note that the changes will apply to subsequent Markdown as well, including other cells if in a notebook context:\n",
    "\n",
    "(For this reason the code here saves the result to a separate HTML file, to avoid changing the style for all other tables).\n",
    "\n",
    "````python\n",
    "import panel as pn\n",
    "from bokeh.resources import INLINE\n",
    "SimpleTable = pn.pane.Markdown(\"\"\"\n",
    "<style>\n",
    "table, th, td {\n",
    "  border: 5px solid black;\n",
    "}\n",
    "</style>\n",
    "| Syntax | Description |\n",
    "| ----------- | ----------- |\n",
    "| Header | Title |\n",
    "| Paragraph | Text |\n",
    "\n",
    "\"\"\")\n",
    "\n",
    "SimpleTable.save('SimpleTable', resources=INLINE)\n",
    "````"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../../assets/markdown_simpletable.png\" alt=\"SimpleTable\"></img>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to change styling only for a specific bit of Markdown text, you can easily do so by adding CSS classes that you can target with a stylesheet you pass to the component. Here we add the `special_table` class followed by the table use a red border:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "css = \"\"\"\n",
    "div.special_table + table * {\n",
    "  border: 1px solid red;\n",
    "}\n",
    "\"\"\"\n",
    "\n",
    "pn.panel(\"\"\"\n",
    "<div class=\"special_table\"></div>\n",
    "\n",
    "| Syntax | Description |\n",
    "| ----------- | ----------- |\n",
    "| Header | Title |\n",
    "| Paragraph | Text |\n",
    "\n",
    "\"\"\", stylesheets=[css])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code Highlighting\n",
    "\n",
    ":::{note} Code Highlighting\n",
    "To enable code highlighting in code blocks, `pip install pygments`\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Renderer\n",
    "\n",
    "Since the 1.0 release Panel uses [`markdown-it`](https://markdown-it-py.readthedocs.io/en/latest/) as the the default markdown renderer. If you want to restore the previous default `'markdown'` or switch to `MyST` flavored Markdown you can set it via the `renderer` parameter. As an example here we render a task list using 'markdown-it' and 'markdown':"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "tasklist = \"\"\"\n",
    "- [ ] Eggs\n",
    "- [x] Flour\n",
    "- [x] Milk\n",
    "\"\"\"\n",
    "\n",
    "pn.Row(\n",
    "    pn.pane.Markdown(tasklist, renderer='markdown-it'),\n",
    "    pn.pane.Markdown(tasklist, renderer='markdown')\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LaTeX Support\n",
    "\n",
    "The `Markdown` pane also supports math rendering by encapsulating the string to be rendered with ``$$`` delimiters. To enable LaTeX rendering you must load the 'mathjax' extensions explicitly in the `pn.extension` call."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "pn.pane.Markdown(r\"\"\"\n",
    "The Markdown pane supports math rendering for string encapsulated with double $ delimiters: $$\\sum_{j}{\\sum_{i}{a*w_{j, i}}}$$\n",
    "\"\"\", width=800)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please note the use of the `r` prefix to create the string as a *raw* strings. Python raw string treats the backslash character (\\\\) as a literal character. For example this won't work"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "pn.pane.Markdown(\"$$\\frac{1}{n}$$\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But prefixing with `r` will work"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "pn.pane.Markdown(r\"$$\\frac{1}{n}$$\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## New Lines\n",
    "\n",
    "Markdown renderers typically do not interpret new lines as hard line breaks. According to the Markdown standard, a hard line break requires the line to end with either *two spaces* or a *backslash*. Otherwise, it is treated as a soft line break. By default, Panel adheres to this standard, respecting the behavior where simple new lines are not displayed as hard line breaks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.pane.Markdown(\"\"\"\n",
    "Markdown displayed\n",
    "on two lines.\n",
    "\"\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Rendering simple new lines as hard line breaks can be enabled for all renderers but `'myst'` by setting `hard_line_break` to `True`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.pane.Markdown(\"\"\"\n",
    "Markdown displayed\n",
    "on one line.\n",
    "\n",
    "Markdown displayed on multiple lines  \n",
    "as each line ends with two spaces,  \n",
    "despite hard_line_break=True\n",
    "\"\"\", hard_line_break=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::{hint}\n",
    "`hard_line_break=True` is appropriate for displaying Markdown text generated by LLMs.\n",
    ":::\n"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
