# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto #0
__all__ = ['emoji_map', 'Subscript', 'Superscript', 'Highlight', 'Emoji', 'FootnoteEntry', 'FootnoteRef', 'Strikethrough',
           'AutoLink', 'AttrLink', 'FencedDiv', 'ExtendedHtmlRenderer', 'parse_attrs']

# %% ../nbs/00_core.ipynb #4be85a97
from fastcore.utils import *

import re
from mistletoe import Document
from mistletoe.html_renderer import HtmlRenderer
from mistletoe.span_token import SpanToken
from mistletoe.block_token import BlockToken, ListItem, List

# %% ../nbs/00_core.ipynb #0d4a8105
class Subscript(SpanToken):
    pattern = re.compile(r"~([^~\s]+)~")
    parse_inner = False
    def __init__(self, match): self.content = match.group(1)

class Superscript(SpanToken):
    pattern = re.compile(r"\^([^\^\s]+)\^")
    parse_inner = False
    def __init__(self, match): self.content = match.group(1)

class Highlight(SpanToken):
    pattern = re.compile(r"==([^=]+)==")
    parse_inner = True
    def __init__(self, match): pass

# %% ../nbs/00_core.ipynb #d6a10481
emoji_map = {
    ':smile:':'😊', ':laughing:':'😆', ':joy:':'😂', ':grin:':'😁', ':wink:':'😉',
    ':heart:':'❤️', ':blue_heart:':'💙', ':green_heart:':'💚', ':yellow_heart:':'💛', ':purple_heart:':'💜',
    ':thumbsup:':'👍', ':thumbsdown:':'👎', ':clap:':'👏', ':wave:':'👋', ':raised_hands:':'🙌',
    ':rocket:':'🚀', ':fire:':'🔥', ':star:':'⭐', ':sparkles:':'✨', ':zap:':'⚡',
    ':check:':'✓', ':x:':'✗', ':warning:':'⚠️', ':no_entry:':'⛔', ':white_check_mark:':'✅',
    ':eyes:':'👀', ':thinking:':'🤔', ':tada:':'🎉', ':100:':'💯', ':muscle:':'💪',
    ':pray:':'🙏', ':ok_hand:':'👌', ':point_right:':'👉', ':point_left:':'👈',
    ':bug:':'🐛', ':construction:':'🚧', ':pencil:':'✏️', ':memo:':'📝', ':books:':'📚',
    ':bulb:':'💡', ':gear:':'⚙️', ':link:':'🔗', ':lock:':'🔒', ':key:':'🔑',
    ':package:':'📦', ':inbox_tray:':'📥', ':outbox_tray:':'📤', ':email:':'📧',
    ':camera:':'📷', ':computer:':'💻', ':iphone:':'📱', ':hourglass:':'⏳',
    ':sunny:':'☀️', ':cloud:':'☁️', ':umbrella:':'☂️', ':snowflake:':'❄️',
    ':pizza:':'🍕', ':coffee:':'☕', ':beer:':'🍺', ':cake:':'🍰',
    ':cat:':'🐱', ':dog:':'🐶', ':whale:':'🐳', ':snake:':'🐍'
}

class Emoji(SpanToken):
    pattern = re.compile(r':(\w+):')
    parse_inner = False
    def __init__(self, match): self.name = match.group(1)

# %% ../nbs/00_core.ipynb #8e730486
class FootnoteEntry(BlockToken):
    @staticmethod
    def start(line): return line.startswith('[^') and ']: ' in line
    
    @staticmethod
    def read(lines):
        line = next(lines)
        match = re.match(r'^\[\^(\w+)\]: (.+)$', line)
        return match
    
    def __init__(self, match):
        self.label = match.group(1)
        self.content = match.group(2)
        self.children = []

class FootnoteRef(SpanToken):
    pattern = re.compile(r'\[\^(\w+)\]')
    parse_inner = False
    def __init__(self, match): self.label = match.group(1)

# %% ../nbs/00_core.ipynb #37d30cba
class Strikethrough(SpanToken):
    pattern = re.compile(r'~~([^~]+)~~')
    parse_inner = True
    def __init__(self, match): pass

class AutoLink(SpanToken):
    pattern = re.compile(r'(?<!\()(https?://[^\s<>]+)')
    parse_inner = False
    precedence = 6
    def __init__(self, match): self.target = match.group(1)

# %% ../nbs/00_core.ipynb #dd4b0566
class AttrLink(SpanToken):
    pattern = re.compile(r'\[([^\]]+)\]\(([^)]+)\)\{([^}]+)\}')
    parse_inner,precedence = False,4
    def __init__(self, match): self.text, self.target, self.attr_str = match.group(1), match.group(2), match.group(3)

# %% ../nbs/00_core.ipynb #c2898abb
class FencedDiv(BlockToken):
    @staticmethod
    def start(line): return bool(re.match(r'^:{3,}\s*(\{|$)', line.strip()))

    @staticmethod
    def read(lines):
        line = next(lines)
        stripped = line.strip()
        n = len(stripped) - len(stripped.lstrip(':'))
        attr_str = stripped[n:].strip()
        inner = []
        for line in lines:
            if re.match(f'^:{{{n},}}\\s*$', line.strip()): break
            inner.append(line)
        return n, attr_str, inner

    def __init__(self, result):
        n, attr_str, inner = result
        self.attr_str = attr_str
        self.children = Document('\n'.join(inner)).children if inner else []

# %% ../nbs/00_core.ipynb #be9bbac9
class ExtendedHtmlRenderer(HtmlRenderer):
    def __init__(self, *args, **kw): 
        super().__init__(FencedDiv, AttrLink, Subscript, Superscript, Highlight, Emoji, FootnoteRef,
            FootnoteEntry, Strikethrough, AutoLink, *args, **kw)
        self.footnotes = {}
        ListItem.pattern = re.compile(r'( {0,3})(\d{1,9}[.)]|[+\-*])($|\s+)')
        List.pattern = re.compile(r' {0,3}(?:\d{1,9}[.)]|[+\-*])(?:[ \t]*$|[ \t]+)')
    def render_subscript(self, token): return f'<sub>{token.content}</sub>'
    def render_superscript(self, token): return f'<sup>{token.content}</sup>'
    def render_highlight(self, token): return f'<mark>{self.render_inner(token)}</mark>'
    def render_strikethrough(self, token): return f'<del>{self.render_inner(token)}</del>'
    def render_emoji(self, token): return emoji_map.get(f':{token.name}:', f':{token.name}:')
    def render_auto_link(self, token): return f'<a href="{token.target}">{token.target}</a>'
    def render_footnote_ref(self, token): 
        lbl = token.label
        return f'<sup><a href="#fn-{lbl}" id="fnref-{lbl}">[{lbl}]</a></sup>'
    def render_footnote_entry(self, token):
        lbl = token.label
        return f'<div id="fn-{lbl}" class="footnote"><sup>{lbl}</sup> {token.content} <a href="#fnref-{lbl}">↩</a></div>\n'
    def render_list_item(self, token):
        inner = self.render_inner(token)
        match = re.match(r'\[( |x|X)\] ', inner)
        if not match: return f'<li>{inner}</li>\n'
        checked = 'checked' if match.group(1).lower() == 'x' else ''
        checkbox = f'<input type="checkbox" disabled {checked}>'
        content = inner[match.end():]
        return f'<li>{checkbox} {content}</li>\n'
    def render_attr_link(self, token):
        attrs = parse_attrs('{' + token.attr_str + '}')
        return f'<a href="{token.target}"{attrs}>{token.text}</a>'
    def render_fenced_div(self, token):
        attrs = parse_attrs(token.attr_str) if token.attr_str else ''
        return f'<div{attrs}>\n{self.render_inner(token)}</div>\n'

# %% ../nbs/00_core.ipynb #5768db34
def parse_attrs(text):
    if not text: return ''
    pattern = r'#([^}\s]+)|\.([^}\s]+)|([\w-]+)="([^"]*)"'
    id_,classes,attrs = '',[],{}
    for match in re.finditer(pattern, text):
        id_m,cls,key,val = match.groups()
        if id_m: id_ = id_m
        elif cls: classes.append(cls)
        elif key: attrs[key] = val
    parts = []
    if id_: parts.append(f'id="{id_}"')
    if classes: parts.append(f'class="{" ".join(classes)}"')
    for k,v in attrs.items(): parts.append(f'{k}="{v}"')
    return ' ' + ' '.join(parts) if parts else ''

# %% ../nbs/00_core.ipynb #eeb3170d
@patch
def render_heading(self:ExtendedHtmlRenderer, token):
    inner = self.render_inner(token)
    attr_match = re.search(r'\s*\{([^}]+)\}$', inner)
    if attr_match:
        attrs = parse_attrs(attr_match.group(0))
        inner = inner[:attr_match.start()]
        return f'<h{token.level}{attrs}>{inner}</h{token.level}>'
    return f'<h{token.level}>{inner}</h{token.level}>'
