VVladimir Mandicadditional exports
5f04d472创建于 5月23日历史提交
import os

import gradio.routes

from modules import extensions, scripts_manager, shared, theme
from modules.logger import log
from modules.paths import data_path, script_path


def webpath(fn):
    if fn.startswith(script_path):
        uri = os.path.relpath(fn, script_path)
    else:
        uri = fn
    uri = uri.replace('\\', '/')
    uri = f'file={uri}?{int(os.path.getmtime(fn))}'
    return uri


def html_head():
    head = ''
    main = ['sdnext.mjs']
    skip = ['login.js']
    for js in main:
        # script_js = os.path.join(script_path, 'javascript', js)
        script_js = os.path.join(script_path, "ui", "dist", js)
        if '.esm' in js or '.mjs' in js:
            head += f'<script type="module" src="{webpath(script_js)}"></script>\n'
        else:
            head += f'<script type="text/javascript" src="{webpath(script_js)}"></script>\n'
    added = []
    for script in scripts_manager.list_scripts('javascript', ".js"):
        if script.filename in main or script.filename in skip:
            continue
        if '.esm' in script.filename or '.mjs' in script.filename:
            head += f'<script type="module" src="{webpath(script.path)}"></script>\n'
        else:
            head += f'<script type="text/javascript" defer src="{webpath(script.path)}"></script>\n'
        added.append(script.path)
    for script in scripts_manager.list_scripts('javascript', ".mjs"):
        head += f'<script type="module" src="{webpath(script.path)}"></script>\n'
        added.append(script.path)
    added = [a.replace(script_path, '').replace('\\', '/') for a in added]
    # log.debug(f'Adding JS scripts: {added}')
    return head


def html_body():
    body = ''
    inline = ''
    if shared.opts.theme_style != 'Auto':
        inline += f"set_theme('{shared.opts.theme_style.lower()}');"
    body += f'<script type="text/javascript">{inline}</script>\n'
    return body


def html_login():
    # fn = os.path.join(script_path, 'javascript', 'login.js')
    fn = os.path.join(script_path, "ui", "js", "login.js")
    with open(fn, encoding='utf8') as f:
        inline = f.read()
    js = f'<script type="text/javascript">{inline}</script>\n'
    return js


def html_css(css: list[str]):
    def stylesheet(fn):
        return f'<link rel="stylesheet" property="stylesheet" href="{webpath(fn)}">'

    head = ''
    for cssfile in css:
        # f = os.path.join(script_path, 'javascript', cssfile)
        f = os.path.join(script_path, 'ui', 'css', cssfile)
        if os.path.isfile(f):
            head += stylesheet(f)
    for cssfile in scripts_manager.list_files_with_name("style.css"):
        if not os.path.isfile(cssfile):
            continue
        head += stylesheet(cssfile)

    usercss = os.path.join(data_path, "user.css") if os.path.exists(os.path.join(data_path, "user.css")) else None
    if shared.opts.theme_type == 'Standard':
        # themecss = os.path.join(script_path, 'javascript', f"{shared.opts.gradio_theme}.css")
        themecss = os.path.join(script_path, 'ui', 'css', f"{shared.opts.gradio_theme}.css")
        if os.path.exists(themecss):
            head += stylesheet(themecss)
            log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
        else:
            log.error(f'UI theme: css="{themecss}" path="{os.getcwd()}" not found')
    elif shared.opts.theme_type == 'Modern':
        theme_folder = next((e.path for e in extensions.extensions if e.name == 'sdnext-modernui'), None)
        themecss = os.path.join(theme_folder or '', 'themes', f'{shared.opts.gradio_theme}.css')
        if os.path.exists(themecss):
            head += stylesheet(themecss)
            log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
        else:
            log.error(f'UI theme: css="{themecss}" not found')
    if usercss is not None:
        head += stylesheet(usercss)
    return head


def reload_javascript():
    title = '<title>SD.Next</title>'
    manifest = f'<link rel="manifest" href="{webpath(os.path.join(script_path, "ui", "manifest", "manifest.json"))}">'
    login = html_login()
    js = html_head()

    css_files: list[str] = []
    if (css_base := theme.reload_gradio_theme()) is not None:
        css_files.append(css_base)
    css_files.append("timesheet.css")

    css = html_css(css_files)
    body = html_body()

    def template_response(*args, **kwargs):
        res = shared.GradioTemplateResponseOriginal(*args, **kwargs)
        res.body = res.body.replace(b'<head>', f'<head>{title}'.encode())
        res.body = res.body.replace(b'</head>', f'{manifest}</head>'.encode())
        res.body = res.body.replace(b'</head>', f'{login}</head>'.encode())
        res.body = res.body.replace(b'</head>', f'{js}</head>'.encode())
        res.body = res.body.replace(b'</body>', f'{css}{body}</body>'.encode())
        lines = res.body.decode("utf8").split('\n')
        for line in lines:
            if 'meta name="twitter:' in line:
                res.body = res.body.replace(line.encode("utf8"), b'')
            if 'iframeResizer.contentWindow' in line:
                res.body = res.body.replace(line.encode("utf8"), b'src="file=ui/js/iframeResizer.js"')
        res.init_headers()
        return res

    gradio.routes.templates.TemplateResponse = template_response


if not hasattr(shared, 'GradioTemplateResponseOriginal'):
    shared.GradioTemplateResponseOriginal = gradio.routes.templates.TemplateResponse