mirror of
https://github.com/vladmandic/automatic
synced 2026-09-20 01:31:13 +02:00
complete refactor javascript to typescript and reorg frontend files and folders
Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
+3
-5
@@ -71,12 +71,10 @@ def create_docs(app: FastAPI):
|
||||
res = get_swagger_ui_html(
|
||||
title=f'{app.title}: Swagger UI',
|
||||
openapi_url=app.openapi_url,
|
||||
swagger_favicon_url='/file=html/favicon.svg',
|
||||
swagger_css_url='/file=html/swagger.css',
|
||||
swagger_favicon_url='/file=ui/assets/favicon.svg',
|
||||
swagger_css_url='/file=ui/css/swagger.css',
|
||||
swagger_ui_parameters=swagger_ui_parameters,
|
||||
# swagger_extra_css_url='file=html/swagger.css',
|
||||
)
|
||||
# res = inject_css(html.content, 'html/swagger.css')
|
||||
return res
|
||||
|
||||
|
||||
@@ -86,6 +84,6 @@ def create_redocs(app: FastAPI):
|
||||
res = get_redoc_html(
|
||||
title=f'{app.title}: ReDoc',
|
||||
openapi_url=app.openapi_url,
|
||||
redoc_favicon_url='/file=html/favicon.svg',
|
||||
redoc_favicon_url='/file=ui/assets/favicon.svg',
|
||||
)
|
||||
return res
|
||||
|
||||
@@ -73,7 +73,7 @@ def setup_middleware(app: FastAPI, cmd_opts):
|
||||
}
|
||||
if err['code'] == 401 and 'file=' in req.url.path: # dont spam with unauth
|
||||
return JSONResponse(status_code=err['code'], content=jsonable_encoder(err))
|
||||
if err['code'] == 404 and 'file=html/' in req.url.path: # dont spam with locales
|
||||
if err['code'] == 404 and 'file=ui/' in req.url.path: # dont spam with locales
|
||||
return JSONResponse(status_code=err['code'], content=jsonable_encoder(err))
|
||||
if err["code"] == 429: # dont spam with rate limit errors
|
||||
return JSONResponse(status_code=err["code"], content=jsonable_encoder(err))
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# VQA Detection Utilities
|
||||
# Parsing, formatting, and drawing functions for detection results (points, bboxes, gaze)
|
||||
|
||||
import os
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from modules import shared
|
||||
from modules.paths import script_path
|
||||
|
||||
|
||||
def parse_points(result) -> list:
|
||||
@@ -311,7 +313,7 @@ def draw_bounding_boxes(image: Image.Image, detections: list, points: list | Non
|
||||
# Try to load a font, fall back to default if unavailable
|
||||
try:
|
||||
font_size = max(12, int(min(width, height) * 0.02))
|
||||
font_path = shared.opts.font or "javascript/notosans-nerdfont-regular.ttf"
|
||||
font_path = shared.opts.font or os.path.join(script_path, "ui", "fonts", "notosans-nerdfont-regular.ttf")
|
||||
font = ImageFont.truetype(font_path, size=font_size)
|
||||
except Exception:
|
||||
font = ImageFont.load_default()
|
||||
|
||||
@@ -96,7 +96,7 @@ def create_model_cards(all_models: list[CivitModel]) -> str:
|
||||
if image.url and not image.url.lower().endswith('.mp4'):
|
||||
previews.append(image.url)
|
||||
if not previews:
|
||||
previews = ['/sdapi/v1/network/thumb?filename=html/missing.png']
|
||||
previews = ['/sdapi/v1/network/thumb?filename=ui/assets/missing.png']
|
||||
all_cards += card.format(id=model.id, name=model.name, type=model.type, preview=previews[0])
|
||||
html = details + cards.format(cards=all_cards)
|
||||
return html
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import math
|
||||
from typing import NamedTuple
|
||||
|
||||
@@ -6,6 +7,7 @@ from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from modules import script_callbacks, shared
|
||||
from modules.logger import log
|
||||
from modules.paths import script_path
|
||||
|
||||
|
||||
class Grid(NamedTuple):
|
||||
@@ -143,9 +145,9 @@ class GridAnnotation:
|
||||
|
||||
def get_font(fontsize: float):
|
||||
try:
|
||||
return ImageFont.truetype(shared.opts.font or "javascript/notosans-nerdfont-regular.ttf", fontsize)
|
||||
return ImageFont.truetype(shared.opts.font or os.path.join(script_path, "ui", "fonts", "notosans-nerdfont-regular.ttf"), fontsize)
|
||||
except Exception:
|
||||
return ImageFont.truetype("javascript/notosans-nerdfont-regular.ttf", fontsize)
|
||||
return ImageFont.truetype(os.path.join(script_path, "ui", "fonts", "notosans-nerdfont-regular.ttf"), fontsize)
|
||||
|
||||
|
||||
def draw_grid_annotations(im: Image.Image, width: int, height: int, x_texts: list[list[GridAnnotation]], y_texts: list[list[GridAnnotation]], margin=0, title: list[GridAnnotation] | None = None):
|
||||
|
||||
@@ -1,9 +1,2 @@
|
||||
def hijack_transformers():
|
||||
# transformers>=4.56 flattened CLIPTextModel internals; diffusers single-file loader still expects `text_model`.
|
||||
return
|
||||
try:
|
||||
import transformers
|
||||
if hasattr(transformers, 'CLIPTextModel') and not hasattr(transformers.CLIPTextModel, 'text_model'):
|
||||
transformers.CLIPTextModel.text_model = property(lambda self: self)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -4,7 +4,7 @@ import logging
|
||||
import torch
|
||||
from modules import shared, errors, devices, sd_models, sd_models_utils
|
||||
from modules.logger import log
|
||||
from installer import setup_logging, install
|
||||
from installer import setup_logging
|
||||
|
||||
debug = os.environ.get('SD_COMPILE_DEBUG', None) is not None
|
||||
debug_log = log.trace if debug else lambda *args, **kwargs: None
|
||||
@@ -87,8 +87,8 @@ def optimize_openvino(sd_model, clear_cache=True):
|
||||
|
||||
|
||||
def compile_pruna(sd_model):
|
||||
# TODO
|
||||
# install('pruna') # TODO pruna: enable when it supports transformers==5.5
|
||||
# TODO pruna: enable when it supports transformers==5.5
|
||||
# install('pruna')
|
||||
"""
|
||||
from pruna import smash, SmashConfig
|
||||
smash_config = SmashConfig(["deepcache", "stable_fast"])
|
||||
|
||||
+1
-1
@@ -348,7 +348,7 @@ class StyleDatabase:
|
||||
for fn in style_files:
|
||||
future_items[executor.submit(self.load_style, fn, None)] = fn
|
||||
if self.built_in:
|
||||
fn = os.path.join('html', 'art-styles.json')
|
||||
fn = os.path.join('data', 'art-styles.json')
|
||||
future_items[executor.submit(self.load_style, fn, 'Reference')] = fn
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
future.result()
|
||||
|
||||
+4
-1
@@ -19,7 +19,10 @@ gradio_theme = gr.themes.Base()
|
||||
|
||||
|
||||
def list_builtin_themes():
|
||||
files = [os.path.splitext(f)[0] for f in os.listdir('javascript') if f.endswith('.css') and f not in ['base.css', 'sdnext.css', 'style.css']]
|
||||
from modules.paths import script_path
|
||||
folder = os.path.join(script_path, "ui", "css")
|
||||
exclude = ['base.css', 'sdnext.css', 'style.css', 'timesheet.css', 'swagger.css']
|
||||
files = [os.path.splitext(f)[0] for f in os.listdir(folder) if f.endswith('.css') and f not in exclude]
|
||||
return files
|
||||
|
||||
|
||||
|
||||
@@ -564,7 +564,7 @@ def create_settings(cmd_opts):
|
||||
"live_preview_downscale": OptionInfo(True, "Downscale high resolution live previews"),
|
||||
|
||||
"notification_audio_enable": OptionInfo(False, "Play a notification upon completion"),
|
||||
"notification_audio_path": OptionInfo("html/notification.mp3","Path to notification sound", component_args=hide_dirs, folder=True),
|
||||
"notification_audio_path": OptionInfo("ui/assets/notification.mp3","Path to notification sound", component_args=hide_dirs, folder=True),
|
||||
}))
|
||||
|
||||
# --- Postprocessing ---
|
||||
|
||||
@@ -61,8 +61,8 @@ def init_api():
|
||||
if filename is None or len(filename) == 0:
|
||||
return JSONResponse({ "error": "no filename" }, status_code=400)
|
||||
if not os.path.exists(filename) or not os.path.isfile(filename) or os.path.getsize(filename) == 0:
|
||||
return FileResponse('html/missing.png', headers={"Accept-Ranges": "bytes"})
|
||||
if filename.startswith('html/') or filename.startswith('models/'):
|
||||
return FileResponse('ui/assets/missing.png', headers={"Accept-Ranges": "bytes"})
|
||||
if filename.startswith('html/') or filename.startswith('models/') or filename.startswith('data/') or filename.startswith('ui/'):
|
||||
return FileResponse(filename, headers={"Accept-Ranges": "bytes"})
|
||||
if not any(Path(folder).absolute() in Path(filename).absolute().parents for folder in allowed_dirs):
|
||||
return JSONResponse({ "error": f"file {filename}: must be in one of allowed directories" }, status_code=403)
|
||||
@@ -414,7 +414,7 @@ class ExtraNetworksPage:
|
||||
"filename": html.escape(item.get('filename', ''), quote=True),
|
||||
"short": os.path.splitext(os.path.basename(item.get('filename', '')))[0],
|
||||
"tags": '|'.join([item.get('tags')] if isinstance(item.get('tags', {}), str) else list(item.get('tags', {}).keys())),
|
||||
"preview": html.escape(item.get('preview', None) or self.link_preview('html/missing.png')),
|
||||
"preview": html.escape(item.get('preview', None) or self.link_preview('ui/assets/missing.png')),
|
||||
"width": 'var(--card-size)',
|
||||
"height": 'var(--card-size)' if shared.opts.extra_networks_card_square else 'auto',
|
||||
"fit": shared.opts.extra_networks_card_fit,
|
||||
@@ -440,7 +440,7 @@ class ExtraNetworksPage:
|
||||
|
||||
def find_preview_file(self, path: str | None):
|
||||
if path is None:
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
if os.path.join('models', 'Reference') in path:
|
||||
return path
|
||||
exts = ["jpg", "jpeg", "png", "webp", "tiff", "jp2", "jxl"]
|
||||
@@ -457,7 +457,7 @@ class ExtraNetworksPage:
|
||||
if '.thumb.' not in file:
|
||||
self.missing_thumbs.append(file)
|
||||
return file
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
|
||||
def find_preview(self, filename: str):
|
||||
t0 = time.time()
|
||||
@@ -508,7 +508,7 @@ class ExtraNetworksPage:
|
||||
item['preview'] = self.link_preview(found)
|
||||
debug(f'EN mapped-preview: {item["name"]}={found}')
|
||||
if item.get('preview', None) is None:
|
||||
item['preview'] = self.link_preview('html/missing.png')
|
||||
item['preview'] = self.link_preview('ui/assets/missing.png')
|
||||
debug(f'EN missing-preview: {item["name"]}')
|
||||
self.preview_time += time.time() - t0
|
||||
|
||||
@@ -787,19 +787,19 @@ def create_ui(container, button_parent: gr.Button, tabname: str, skip_indexing =
|
||||
|
||||
def fn_save_img(image):
|
||||
if ui.last_item is None or ui.last_item.local_preview is None:
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
images = []
|
||||
if ui.gallery is not None:
|
||||
images = list(ui.gallery.temp_files) # gallery cannot be used as input component so looking at most recently registered temp files
|
||||
if len(images) < 1:
|
||||
log.warning(f'Network no image: item="{ui.last_item.name}"')
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
try:
|
||||
images.sort(key=lambda f: os.path.getmtime(f), reverse=True)
|
||||
image = Image.open(images[0])
|
||||
except Exception as e:
|
||||
log.error(f'Network error opening image: item="{ui.last_item.name}" {e}')
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
fn_delete_img(image)
|
||||
if image.width > 512 or image.height > 512:
|
||||
image = image.convert('RGB')
|
||||
@@ -818,7 +818,7 @@ def create_ui(container, button_parent: gr.Button, tabname: str, skip_indexing =
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
log.debug(f'Network delete image: item="{ui.last_item.name}" filename="{file}"')
|
||||
return 'html/missing.png'
|
||||
return 'ui/assets/missing.png'
|
||||
|
||||
def fn_save_desc(desc):
|
||||
if hasattr(ui.last_item, 'type') and ui.last_item.type == 'Style':
|
||||
|
||||
@@ -114,7 +114,7 @@ class ExtraNetworkStyles(extra_networks.ExtraNetwork):
|
||||
super().__init__('style')
|
||||
self.indexes = {}
|
||||
|
||||
def activate(self, p, params_list):
|
||||
def activate(self, p, params_list, *args, **kwargs):
|
||||
for param in params_list:
|
||||
if len(param.items) > 0:
|
||||
style = None
|
||||
|
||||
+14
-10
@@ -19,16 +19,17 @@ def webpath(fn):
|
||||
|
||||
def html_head():
|
||||
head = ''
|
||||
main = ['script.js']
|
||||
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, '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"):
|
||||
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:
|
||||
@@ -36,7 +37,7 @@ def html_head():
|
||||
else:
|
||||
head += f'<script type="text/javascript" src="{webpath(script.path)}"></script>\n'
|
||||
added.append(script.path)
|
||||
for script in scripts_manager.list_scripts("javascript", ".mjs"):
|
||||
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]
|
||||
@@ -54,7 +55,8 @@ def html_body():
|
||||
|
||||
|
||||
def html_login():
|
||||
fn = os.path.join(script_path, "javascript", "login.js")
|
||||
# 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'
|
||||
@@ -67,7 +69,8 @@ def html_css(css: list[str]):
|
||||
|
||||
head = ''
|
||||
for cssfile in css:
|
||||
f = os.path.join(script_path, 'javascript', cssfile)
|
||||
# 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"):
|
||||
@@ -77,7 +80,8 @@ def html_css(css: list[str]):
|
||||
|
||||
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, '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}"')
|
||||
@@ -98,7 +102,7 @@ def html_css(css: list[str]):
|
||||
|
||||
def reload_javascript():
|
||||
title = '<title>SD.Next</title>'
|
||||
manifest = f'<link rel="manifest" href="{webpath(os.path.join(script_path, "html", "manifest.json"))}">'
|
||||
manifest = f'<link rel="manifest" href="{webpath(os.path.join(script_path, "ui", "manifest", "manifest.json"))}">'
|
||||
login = html_login()
|
||||
js = html_head()
|
||||
|
||||
@@ -121,8 +125,8 @@ def reload_javascript():
|
||||
for line in lines:
|
||||
if 'meta name="twitter:' in line:
|
||||
res.body = res.body.replace(line.encode("utf8"), b'')
|
||||
if 'iframeResizer.contentWindow.min.js' in line:
|
||||
res.body = res.body.replace(line.encode("utf8"), b'src="file=javascript/iframeResizer.min.js"')
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user