Spaces:
Running
Running
import os | |
import re | |
from typing import Callable | |
import gradio as gr | |
import modelscope_studio as mgr | |
from .parse_markdown import parse_markdown | |
with open(os.path.join(os.path.dirname(__file__), "tab-link.js")) as f: | |
tab_link_js = f.read() | |
custom_components = { | |
"tab-link": { | |
"props": ["tab", "component-tab"], | |
"js": tab_link_js | |
} | |
} | |
def remove_formatter(markdown_text): | |
pattern = r"^ *---[\s\S]*?---" | |
replaced_text = re.sub(pattern, "", markdown_text) | |
return replaced_text | |
def list_demos(dir_path: str, prefix=''): | |
result = [] | |
if (not os.path.isdir(dir_path)): | |
return result | |
for name in os.listdir(dir_path): | |
path = os.path.join(dir_path, name) | |
if os.path.isfile(path): | |
result.append(prefix + name) | |
elif os.path.isdir(path): | |
sub_prefix = prefix + name + '/' | |
result.extend(list_demos(path, sub_prefix)) | |
return result | |
def get_demo_modules(file_path: str): | |
import importlib.util | |
demos = [ | |
demo for demo in list_demos( | |
os.path.join(os.path.dirname(file_path), "demos")) | |
if demo.endswith(".py") and not demo.startswith("__") | |
] | |
demo_modules = {} | |
for demo in demos: | |
demo_name = demo.split(".")[0] | |
spec = importlib.util.spec_from_file_location( | |
"demo", os.path.join(os.path.dirname(file_path), "demos", demo)) | |
module = importlib.util.module_from_spec(spec) | |
spec.loader.exec_module(module) | |
demo_modules[demo_name] = module | |
return demo_modules | |
is_modelscope_studio = os.getenv('MODELSCOPE_ENVIRONMENT') == 'studio' | |
class Docs: | |
def __init__(self, file_path: str, markdown_files: list = None): | |
self.file_path = file_path | |
self.demo_modules = get_demo_modules(file_path) | |
# default current directory | |
self.markdown_files = markdown_files if markdown_files else [ | |
filename for filename in os.listdir(os.path.dirname(file_path)) | |
if filename.endswith(".md") | |
] | |
if is_modelscope_studio: | |
self.markdown_files = list( | |
filter( | |
lambda x: x.endswith("-zh_CN.md") or | |
(f"{'.'.join(x.split('.')[:-1])}-zh_CN.md" not in self. | |
markdown_files), self.markdown_files)) | |
else: | |
self.markdown_files = list( | |
filter(lambda x: not x.endswith("-zh_CN.md"), | |
self.markdown_files)) | |
self.tabs = None | |
def read_file(self, relative_path: str): | |
with open(os.path.join(os.path.dirname(self.file_path), relative_path), | |
"r") as f: | |
return f.read() | |
def render_demo(self, | |
demo_name, | |
code_position='left', | |
prefix='', | |
suffix=''): | |
content = self.read_file(f"./demos/{demo_name}.py") | |
module = self.demo_modules[demo_name] | |
with gr.Accordion("Show Demo", open=False): | |
def render_code(): | |
mgr.Markdown(f"""{prefix} | |
````python | |
{content} | |
```` | |
{suffix}""", | |
header_links=True, | |
custom_components=custom_components) | |
if code_position == 'top': | |
with gr.Row(): | |
with gr.Column(): | |
render_code() | |
with gr.Row(): | |
if code_position == 'left': | |
with gr.Column(): | |
render_code() | |
with gr.Column(): | |
module.demo.render() | |
if code_position == 'right': | |
with gr.Column(): | |
render_code() | |
if code_position == 'bottom': | |
with gr.Row(): | |
with gr.Column(): | |
render_code() | |
def render_markdown(self, | |
markdown_file, | |
on_tab_link_click: Callable = None, | |
components_tabs=None): | |
items = parse_markdown(remove_formatter(self.read_file(markdown_file)), | |
read_file=self.read_file) | |
for item in items: | |
if item["type"] == "text": | |
md = mgr.Markdown(item["value"], | |
header_links=True, | |
custom_components=custom_components, | |
preview=False) | |
deps = [dep for dep in [components_tabs, self.tabs] if dep] | |
if len(deps) > 0: | |
md.custom(fn=on_tab_link_click, outputs=deps) | |
elif item["type"] == "demo": | |
self.render_demo(item["name"], | |
prefix=item["prefix"], | |
suffix=item["suffix"], | |
code_position=item["code_position"]) | |
def render(self, components_tabs=None): | |
def tab_link_click(data: gr.EventData): | |
tab: str = data._data["value"].get("tab", '') | |
component_tab: str = data._data["value"].get("component_tab", '') | |
if tab and tabs: | |
return {tabs: gr.update(selected=tab)} | |
elif components_tabs and component_tab: | |
return {components_tabs: gr.update(selected=component_tab)} | |
with gr.Blocks() as demo: | |
if len(self.markdown_files) > 1: | |
with gr.Tabs() as tabs: | |
self.tabs = tabs | |
for markdown_file in self.markdown_files: | |
tab_name = ".".join(markdown_file.split(".")[:-1]) | |
tab_name = tab_name.split("-zh_CN")[0] | |
with gr.TabItem(tab_name, id=tab_name): | |
self.render_markdown( | |
markdown_file, | |
on_tab_link_click=tab_link_click, | |
components_tabs=components_tabs) | |
elif (len(self.markdown_files) == 1): | |
self.render_markdown(self.markdown_files[0], | |
on_tab_link_click=tab_link_click, | |
components_tabs=components_tabs) | |
return demo | |