instaui 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- instaui/components/content.py +4 -4
- instaui/components/echarts/echarts.js +128 -0
- instaui/components/echarts/echarts.py +194 -0
- instaui/components/echarts/static/echarts.esm.min.js +45 -0
- instaui/components/element.py +103 -13
- instaui/components/html/__init__.py +31 -18
- instaui/components/html/_preset.py +4 -0
- instaui/components/html/heading.py +51 -0
- instaui/components/html/range.py +3 -0
- instaui/components/html/select.py +16 -35
- instaui/components/html/table.py +36 -0
- instaui/components/html/textarea.py +28 -0
- instaui/components/markdown/markdown.js +33 -0
- instaui/components/markdown/markdown.py +41 -0
- instaui/components/markdown/static/github-markdown.css +12 -0
- instaui/components/markdown/static/marked.esm.js +2579 -0
- instaui/components/shiki_code/shiki_code.js +126 -0
- instaui/components/shiki_code/shiki_code.py +99 -0
- instaui/components/shiki_code/static/langs/css.mjs +5 -0
- instaui/components/shiki_code/static/langs/markdown.mjs +5 -0
- instaui/components/shiki_code/static/langs/python.mjs +5 -0
- instaui/components/shiki_code/static/langs/shell.mjs +2 -0
- instaui/components/shiki_code/static/langs/shellscript.mjs +5 -0
- instaui/components/shiki_code/static/shiki-core.js +5784 -0
- instaui/components/shiki_code/static/shiki-style.css +175 -0
- instaui/components/shiki_code/static/shiki-transformers.js +461 -0
- instaui/components/shiki_code/static/themes/vitesse-dark.mjs +2 -0
- instaui/components/shiki_code/static/themes/vitesse-light.mjs +2 -0
- instaui/components/value_element.py +7 -3
- instaui/components/vfor.py +1 -1
- instaui/consts.py +2 -1
- instaui/daisyui/__init__.py +26 -0
- instaui/daisyui/_index.py +20 -0
- instaui/daisyui/button.py +38 -0
- instaui/daisyui/checkbox.py +17 -0
- instaui/daisyui/static/daisyui.css +1 -0
- instaui/daisyui/static/themes.css +1 -0
- instaui/daisyui/table.py +35 -0
- instaui/dependencies/component_dependency.py +11 -5
- instaui/event/js_event.py +1 -0
- instaui/event/web_event.py +6 -7
- instaui/fastapi_server/dependency_router.py +4 -3
- instaui/fastapi_server/resource.py +12 -16
- instaui/fastapi_server/server.py +34 -24
- instaui/handlers/event_handler.py +3 -1
- instaui/handlers/watch_handler.py +4 -0
- instaui/html_tools.py +44 -2
- instaui/inject.py +3 -3
- instaui/runtime/_app.py +43 -4
- instaui/runtime/_link_manager.py +89 -0
- instaui/runtime/resource.py +21 -8
- instaui/shadcn_classless/_index.py +42 -0
- instaui/shadcn_classless/static/shadcn-classless.css +403 -0
- instaui/spa_router/_functions.py +1 -1
- instaui/spa_router/_route_model.py +1 -1
- instaui/static/insta-ui.css +1 -1
- instaui/static/insta-ui.esm-browser.prod.js +1308 -1252
- instaui/static/insta-ui.js.map +1 -1
- instaui/static/instaui-tools-browser.js +511 -0
- instaui/static/templates/webview.html +78 -0
- instaui/systems/module_system.py +30 -0
- instaui/tailwind/__init__.py +6 -0
- instaui/tailwind/_index.py +24 -0
- instaui/{static/tailwindcss.min.js → tailwind/static/tailwindcss-v3.min.js} +62 -62
- instaui/tailwind/static/tailwindcss-v4.min.js +8 -0
- instaui/template/_utils.py +23 -0
- instaui/template/webview_template.py +50 -0
- instaui/template/zero_template.py +18 -17
- instaui/ui/__build_init.py +73 -0
- instaui/ui/__init__.py +74 -58
- instaui/ui/__init__.pyi +135 -0
- instaui/ui/events.py +1 -1
- instaui/ui_functions/server.py +3 -1
- instaui/vars/event_context.py +4 -0
- instaui/vars/web_computed.py +30 -30
- instaui/watch/web_watch.py +5 -6
- instaui/webview/__init__.py +1 -0
- instaui/webview/_utils.py +8 -0
- instaui/webview/api.py +72 -0
- instaui/webview/func.py +114 -0
- instaui/webview/index.py +162 -0
- instaui/webview/resource.py +172 -0
- instaui/zero/func.py +31 -23
- instaui/zero/scope.py +110 -4
- {instaui-0.1.3.dist-info → instaui-0.1.5.dist-info}/METADATA +4 -1
- {instaui-0.1.3.dist-info → instaui-0.1.5.dist-info}/RECORD +88 -44
- instaui/handlers/computed_handler.py +0 -42
- instaui/handlers/config_handler.py +0 -13
- instaui/static/insta-ui.iife.js +0 -29
- instaui/static/insta-ui.iife.js.map +0 -1
- instaui/zero/test.html +0 -44
- {instaui-0.1.3.dist-info → instaui-0.1.5.dist-info}/LICENSE +0 -0
- {instaui-0.1.3.dist-info → instaui-0.1.5.dist-info}/WHEEL +0 -0
instaui/webview/api.py
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
from typing import Any, Dict
|
2
|
+
|
3
|
+
|
4
|
+
from instaui.runtime._app import get_app_slot
|
5
|
+
from instaui.handlers import watch_handler
|
6
|
+
from instaui.handlers import event_handler
|
7
|
+
from instaui.skip import is_skip_output
|
8
|
+
|
9
|
+
|
10
|
+
class Api:
|
11
|
+
def watch_call(self, data: Dict):
|
12
|
+
hkey = data.pop("key")
|
13
|
+
handler_info = watch_handler.get_handler_info(hkey)
|
14
|
+
if handler_info is None:
|
15
|
+
return {"error": "watch handler not found"}
|
16
|
+
|
17
|
+
update_app_page_info(data)
|
18
|
+
|
19
|
+
result = handler_info.fn(
|
20
|
+
*handler_info.get_handler_args(_get_binds_from_data(data))
|
21
|
+
)
|
22
|
+
return response_data(handler_info.outputs_binding_count, result)
|
23
|
+
|
24
|
+
def event_call(self, data: Dict):
|
25
|
+
handler = event_handler.get_handler(data["hKey"])
|
26
|
+
if handler is None:
|
27
|
+
raise ValueError("event handler not found")
|
28
|
+
|
29
|
+
update_app_page_info(data)
|
30
|
+
|
31
|
+
|
32
|
+
args = [bind for bind in data.get("bind", [])]
|
33
|
+
|
34
|
+
result = handler.fn(*handler.get_handler_args(args))
|
35
|
+
return response_data(handler.outputs_binding_count, result)
|
36
|
+
|
37
|
+
|
38
|
+
def update_app_page_info(data: Dict):
|
39
|
+
app = get_app_slot()
|
40
|
+
|
41
|
+
page_info = data.get("page", {})
|
42
|
+
app._page_path = page_info["path"]
|
43
|
+
|
44
|
+
if "params" in page_info:
|
45
|
+
app._page_params = page_info["params"]
|
46
|
+
|
47
|
+
if "queryParams" in page_info:
|
48
|
+
app._query_params = page_info["queryParams"]
|
49
|
+
|
50
|
+
|
51
|
+
def _get_binds_from_data(data: Dict):
|
52
|
+
return data.get("input", [])
|
53
|
+
|
54
|
+
|
55
|
+
def response_data(outputs_binding_count: int, result: Any):
|
56
|
+
data = {}
|
57
|
+
if outputs_binding_count > 0:
|
58
|
+
if not isinstance(result, tuple):
|
59
|
+
result = [result]
|
60
|
+
|
61
|
+
result_infos = [(r, int(is_skip_output(r))) for r in result]
|
62
|
+
|
63
|
+
if len(result_infos) == 1 and result_infos[0][1] == 1:
|
64
|
+
return data
|
65
|
+
|
66
|
+
data["values"] = [0 if info[1] == 1 else info[0] for info in result_infos]
|
67
|
+
skips = [info[1] for info in result_infos]
|
68
|
+
|
69
|
+
if sum(skips) > 0:
|
70
|
+
data["skips"] = skips
|
71
|
+
|
72
|
+
return data
|
instaui/webview/func.py
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import itertools
|
3
|
+
from pathlib import Path
|
4
|
+
import instaui.consts as consts
|
5
|
+
from instaui.runtime._app import get_app_slot, get_default_app_slot
|
6
|
+
from instaui.template import render_zero_html
|
7
|
+
from instaui.template import zero_template
|
8
|
+
from instaui.html_tools import to_config_data
|
9
|
+
from instaui.runtime.dataclass import JsLink
|
10
|
+
from instaui.runtime.resource import HtmlResource
|
11
|
+
|
12
|
+
|
13
|
+
def get_template_model():
|
14
|
+
system_slot = get_app_slot()
|
15
|
+
|
16
|
+
merge_global_resources = (system_slot.meta or {}).get(
|
17
|
+
"merge_global_resources", True
|
18
|
+
)
|
19
|
+
|
20
|
+
default_app_slot = get_default_app_slot()
|
21
|
+
html_resource = system_slot._html_resource
|
22
|
+
default_html_resource = (
|
23
|
+
default_app_slot._html_resource
|
24
|
+
if merge_global_resources
|
25
|
+
else _empty_html_resource()
|
26
|
+
)
|
27
|
+
|
28
|
+
config_data = to_config_data()
|
29
|
+
|
30
|
+
model = zero_template.ZeroTemplateModel(
|
31
|
+
vue_js_code=consts.VUE_ES_JS_PATH,
|
32
|
+
instaui_js_code=consts.APP_ES_JS_PATH,
|
33
|
+
css_links=[
|
34
|
+
consts.APP_CSS_PATH,
|
35
|
+
],
|
36
|
+
config_dict=config_data,
|
37
|
+
favicon=html_resource.favicon
|
38
|
+
or default_html_resource.favicon
|
39
|
+
or consts.FAVICON_PATH,
|
40
|
+
title=html_resource.title or default_html_resource.title or consts.PAGE_TITLE,
|
41
|
+
)
|
42
|
+
|
43
|
+
# register custom components
|
44
|
+
for component in system_slot._component_dependencies:
|
45
|
+
if not component.esm:
|
46
|
+
continue
|
47
|
+
|
48
|
+
model.vue_app_component.append(
|
49
|
+
zero_template.ZeroVueAppComponent(
|
50
|
+
name=component.tag_name,
|
51
|
+
url=component.esm,
|
52
|
+
)
|
53
|
+
)
|
54
|
+
|
55
|
+
if component.css:
|
56
|
+
for css_link in component.css:
|
57
|
+
model.css_links.append(css_link)
|
58
|
+
|
59
|
+
if component.externals:
|
60
|
+
for name, url in component.externals.items():
|
61
|
+
if url.is_file():
|
62
|
+
model.add_extra_import_map(name, url)
|
63
|
+
|
64
|
+
# register custom plugins
|
65
|
+
for plugin in set(
|
66
|
+
itertools.chain(
|
67
|
+
system_slot._plugin_dependencies, default_app_slot._plugin_dependencies
|
68
|
+
)
|
69
|
+
):
|
70
|
+
if not plugin.esm:
|
71
|
+
continue
|
72
|
+
|
73
|
+
model.vue_app_use.append(plugin.name)
|
74
|
+
|
75
|
+
model.add_extra_import_map(plugin.name, plugin.esm)
|
76
|
+
|
77
|
+
if plugin.css:
|
78
|
+
for css_link in plugin.css:
|
79
|
+
model.css_links.append(css_link)
|
80
|
+
|
81
|
+
# css file link to web static link
|
82
|
+
for link in html_resource.get_valid_css_links(
|
83
|
+
default_html_resource._css_links_manager
|
84
|
+
):
|
85
|
+
if isinstance(link, Path):
|
86
|
+
model.css_links.append(link)
|
87
|
+
|
88
|
+
# js file link to web static link
|
89
|
+
for info in html_resource.get_valid_js_links(
|
90
|
+
default_html_resource._js_links_manager
|
91
|
+
):
|
92
|
+
if isinstance(info.link, Path):
|
93
|
+
model.js_links.append(JsLink(info.link))
|
94
|
+
|
95
|
+
for js_code in itertools.chain(
|
96
|
+
html_resource._script_tags, default_html_resource._script_tags
|
97
|
+
):
|
98
|
+
model.script_tags.append(js_code)
|
99
|
+
|
100
|
+
for sylte_code in itertools.chain(
|
101
|
+
html_resource._style_tags, default_html_resource._style_tags
|
102
|
+
):
|
103
|
+
model.style_tags.append(sylte_code)
|
104
|
+
|
105
|
+
return model
|
106
|
+
|
107
|
+
|
108
|
+
def to_html_str():
|
109
|
+
model = get_template_model()
|
110
|
+
return render_zero_html(model)
|
111
|
+
|
112
|
+
|
113
|
+
def _empty_html_resource():
|
114
|
+
return HtmlResource()
|
instaui/webview/index.py
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from contextlib import contextmanager
|
3
|
+
from pathlib import Path
|
4
|
+
import shutil
|
5
|
+
from typing import Any, Callable, Dict, Iterable, List, Optional, Union
|
6
|
+
from typing_extensions import TypedDict, Unpack
|
7
|
+
import webview
|
8
|
+
import webview.http as http
|
9
|
+
from webview.guilib import GUIType
|
10
|
+
|
11
|
+
from instaui.runtime._app import get_app_slot, new_app_slot, reset_app_slot
|
12
|
+
from instaui.launch_collector import get_launch_collector
|
13
|
+
|
14
|
+
from . import resource
|
15
|
+
from . import api
|
16
|
+
from . import _utils
|
17
|
+
|
18
|
+
|
19
|
+
class WebviewWrapper:
|
20
|
+
"""Example usage:
|
21
|
+
.. code-block:: python
|
22
|
+
from instaui import ui
|
23
|
+
|
24
|
+
@ui.page("/")
|
25
|
+
def index_page():
|
26
|
+
ui.content("Hello, world!")
|
27
|
+
|
28
|
+
ui.webview().run()
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
*,
|
34
|
+
assets_path: Union[str, Path] = "./webview_assets",
|
35
|
+
debug: bool = False,
|
36
|
+
auto_create_window: Union[bool, str] = "/",
|
37
|
+
on_app_mounted: Optional[Callable] = None,
|
38
|
+
) -> None:
|
39
|
+
"""Create a new webview wrapper.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
assets_path (Union[str, Path], optional): Path to store assets. Defaults to "./webview_assets".
|
43
|
+
debug (bool, optional): Whether to run in debug mode. Defaults to False.
|
44
|
+
auto_create_window (Union[bool, str], optional): Whether to create a window automatically. If a string is provided, it will be used as the initial page URL. Defaults to "/".
|
45
|
+
testing (bool, optional): Whether to run in testing mode. Defaults to False.
|
46
|
+
"""
|
47
|
+
|
48
|
+
self.assets_path = (
|
49
|
+
Path(self._get_assets_path(assets_path))
|
50
|
+
if isinstance(assets_path, str)
|
51
|
+
else assets_path
|
52
|
+
)
|
53
|
+
_utils.reset_dir(self.assets_path)
|
54
|
+
self.debug = debug
|
55
|
+
self.on_app_mounted = on_app_mounted
|
56
|
+
|
57
|
+
self._auto_create_window = auto_create_window
|
58
|
+
|
59
|
+
def create_window(
|
60
|
+
self,
|
61
|
+
page_url: str = "/",
|
62
|
+
):
|
63
|
+
"""Create a new window. Returns the window object of pywebview.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
page_url (str, optional): Page URL to load. Defaults to "/".
|
67
|
+
|
68
|
+
"""
|
69
|
+
launch_collector = get_launch_collector()
|
70
|
+
with _scope():
|
71
|
+
app = get_app_slot()
|
72
|
+
app._page_path = page_url
|
73
|
+
page_info = launch_collector._page_router[page_url]
|
74
|
+
page_info.func()
|
75
|
+
|
76
|
+
resource_info = resource.resource_to_assets(
|
77
|
+
page_url=page_url,
|
78
|
+
assets_path=self.assets_path,
|
79
|
+
on_app_mounted=self.on_app_mounted,
|
80
|
+
)
|
81
|
+
|
82
|
+
window = webview.create_window(
|
83
|
+
resource_info.title, resource_info.index_html_url, js_api=api.Api()
|
84
|
+
)
|
85
|
+
|
86
|
+
if self.on_app_mounted:
|
87
|
+
|
88
|
+
def on_app_mounted():
|
89
|
+
self.on_app_mounted(window) # type: ignore
|
90
|
+
|
91
|
+
window.expose(on_app_mounted)
|
92
|
+
|
93
|
+
return window
|
94
|
+
|
95
|
+
def run(self, **webview_start_args: Unpack[WebviewStartArgs]):
|
96
|
+
"""Run the webview.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
:param func: Function to invoke upon starting the GUI loop.
|
100
|
+
:param args: Function arguments. Can be either a single value or a tuple of
|
101
|
+
values.
|
102
|
+
:param localization: A dictionary with localized strings. Default strings
|
103
|
+
and their keys are defined in localization.py.
|
104
|
+
:param gui: Force a specific GUI. Allowed values are ``cef``, ``qt``,
|
105
|
+
``gtk``, ``mshtml`` or ``edgechromium`` depending on a platform.
|
106
|
+
:param http_server: Enable built-in HTTP server. If enabled, local files
|
107
|
+
will be served using a local HTTP server on a random port. For each
|
108
|
+
window, a separate HTTP server is spawned. This option is ignored for
|
109
|
+
non-local URLs.
|
110
|
+
:param user_agent: Change user agent string.
|
111
|
+
:param private_mode: Enable private mode. In private mode, cookies and local storage are not preserved.
|
112
|
+
Default is True.
|
113
|
+
:param storage_path: Custom location for cookies and other website data
|
114
|
+
:param menu: List of menus to be included in the app menu
|
115
|
+
:param server: Server class. Defaults to BottleServer
|
116
|
+
:param server_args: Dictionary of arguments to pass through to the server instantiation
|
117
|
+
:param ssl: Enable SSL for local HTTP server. Default is False.
|
118
|
+
:param icon: Path to the icon file. Supported only on GTK/QT.
|
119
|
+
"""
|
120
|
+
|
121
|
+
if self._auto_create_window:
|
122
|
+
self.create_window(
|
123
|
+
"/" if self._auto_create_window is True else self._auto_create_window
|
124
|
+
)
|
125
|
+
|
126
|
+
webview.start(**webview_start_args, debug=self.debug)
|
127
|
+
|
128
|
+
@staticmethod
|
129
|
+
def _get_assets_path(file: Union[str, Path]) -> Path:
|
130
|
+
if isinstance(file, str):
|
131
|
+
import inspect
|
132
|
+
|
133
|
+
frame = inspect.currentframe().f_back.f_back.f_back # type: ignore
|
134
|
+
assert frame is not None
|
135
|
+
script_file = inspect.getfile(frame)
|
136
|
+
file = Path(script_file).parent.joinpath(file)
|
137
|
+
|
138
|
+
return file
|
139
|
+
|
140
|
+
|
141
|
+
@contextmanager
|
142
|
+
def _scope():
|
143
|
+
token = new_app_slot("webview")
|
144
|
+
yield
|
145
|
+
reset_app_slot(token)
|
146
|
+
|
147
|
+
|
148
|
+
class WebviewStartArgs(TypedDict, total=False):
|
149
|
+
func: Union[Callable[..., None], None]
|
150
|
+
args: Union[Iterable[Any], None]
|
151
|
+
localization: Dict[str, str]
|
152
|
+
gui: Union[GUIType, None]
|
153
|
+
http_server: bool
|
154
|
+
http_port: Union[int, None]
|
155
|
+
user_agent: Union[str, None]
|
156
|
+
private_mode: bool
|
157
|
+
storage_path: Union[str, None]
|
158
|
+
menu: List[Any]
|
159
|
+
server: type[http.ServerType] # type: ignore
|
160
|
+
server_args: Dict[Any, Any]
|
161
|
+
ssl: bool
|
162
|
+
icon: Union[str, None]
|
@@ -0,0 +1,172 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
import itertools
|
3
|
+
from pathlib import Path
|
4
|
+
import shutil
|
5
|
+
from typing import Callable, Optional
|
6
|
+
from urllib.parse import quote
|
7
|
+
|
8
|
+
from instaui.html_tools import to_config_data
|
9
|
+
from instaui.runtime._app import get_app_slot, get_default_app_slot
|
10
|
+
from instaui.systems import file_system
|
11
|
+
from instaui.template import webview_template
|
12
|
+
from instaui import consts
|
13
|
+
|
14
|
+
from . import _utils
|
15
|
+
|
16
|
+
|
17
|
+
_INDEX_HTML_NAME = "index.html"
|
18
|
+
|
19
|
+
|
20
|
+
@dataclass
|
21
|
+
class ResourceInfo:
|
22
|
+
title: str
|
23
|
+
index_html_url: str
|
24
|
+
|
25
|
+
|
26
|
+
def resource_to_assets(
|
27
|
+
page_url: str, assets_path: Path, on_app_mounted: Optional[Callable] = None
|
28
|
+
):
|
29
|
+
page_dir = assets_path.joinpath(quote(page_url, safe=""))
|
30
|
+
_utils.reset_dir(page_dir)
|
31
|
+
|
32
|
+
relative_to_assets = _get_relative_to_assets(page_dir)
|
33
|
+
file_to_assets = _get_file_to_assets(page_dir)
|
34
|
+
|
35
|
+
config_data = to_config_data()
|
36
|
+
|
37
|
+
system_slot = get_app_slot()
|
38
|
+
default_app_slot = get_default_app_slot()
|
39
|
+
html_resource = system_slot._html_resource
|
40
|
+
default_html_resource = default_app_slot._html_resource
|
41
|
+
|
42
|
+
if html_resource.favicon:
|
43
|
+
favicon_url = file_to_assets(html_resource.favicon)
|
44
|
+
else:
|
45
|
+
if default_html_resource.favicon:
|
46
|
+
favicon_url = file_to_assets(default_html_resource.favicon)
|
47
|
+
else:
|
48
|
+
favicon_url = file_to_assets(consts.FAVICON_PATH)
|
49
|
+
|
50
|
+
model = webview_template.WebViewTemplateModel(
|
51
|
+
vue_js_code=file_to_assets(consts.VUE_ES_JS_PATH),
|
52
|
+
instaui_js_code=file_to_assets(consts.APP_ES_JS_PATH),
|
53
|
+
css_links=[
|
54
|
+
file_to_assets(consts.APP_CSS_PATH),
|
55
|
+
],
|
56
|
+
config_dict=config_data,
|
57
|
+
favicon_url=favicon_url,
|
58
|
+
title=html_resource.title or default_html_resource.title or consts.PAGE_TITLE,
|
59
|
+
on_app_mounted=on_app_mounted,
|
60
|
+
)
|
61
|
+
|
62
|
+
# register custom components
|
63
|
+
for component in system_slot._component_dependencies:
|
64
|
+
if not component.esm:
|
65
|
+
continue
|
66
|
+
|
67
|
+
component_url = file_to_assets(component.esm)
|
68
|
+
model.add_extra_import_map(component_url, file_to_assets(component.esm))
|
69
|
+
|
70
|
+
model.vue_app_component.append(
|
71
|
+
webview_template.WebViewVueAppComponent(
|
72
|
+
name=component.tag_name,
|
73
|
+
url=component_url,
|
74
|
+
)
|
75
|
+
)
|
76
|
+
|
77
|
+
if component.css:
|
78
|
+
for css_link in component.css:
|
79
|
+
css_resource = file_to_assets(css_link)
|
80
|
+
if css_link.is_file():
|
81
|
+
model.css_links.append(css_resource)
|
82
|
+
|
83
|
+
if component.externals:
|
84
|
+
for name, file in component.externals.items():
|
85
|
+
model.add_extra_import_map(name, file_to_assets(file))
|
86
|
+
|
87
|
+
# register custom plugins
|
88
|
+
for plugin in set(
|
89
|
+
itertools.chain(
|
90
|
+
system_slot._plugin_dependencies, default_app_slot._plugin_dependencies
|
91
|
+
)
|
92
|
+
):
|
93
|
+
if not plugin.esm:
|
94
|
+
continue
|
95
|
+
|
96
|
+
model.vue_app_use.append(plugin.name)
|
97
|
+
|
98
|
+
model.add_extra_import_map(plugin.name, file_to_assets(plugin.esm))
|
99
|
+
|
100
|
+
if plugin.css:
|
101
|
+
for css_link in plugin.css:
|
102
|
+
model.css_links.append(file_to_assets(css_link))
|
103
|
+
|
104
|
+
# css file link to web static link
|
105
|
+
for link in html_resource.get_valid_css_links(
|
106
|
+
default_html_resource._css_links_manager
|
107
|
+
):
|
108
|
+
if isinstance(link, Path):
|
109
|
+
model.css_links.append(file_to_assets(link))
|
110
|
+
else:
|
111
|
+
model.css_links.append(link)
|
112
|
+
|
113
|
+
# js file link to web static link
|
114
|
+
for info in html_resource.get_valid_js_links(
|
115
|
+
default_html_resource._js_links_manager
|
116
|
+
):
|
117
|
+
link = file_to_assets(info.link) if isinstance(info.link, Path) else info.link
|
118
|
+
model.js_links.append(link)
|
119
|
+
|
120
|
+
for js_code in itertools.chain(
|
121
|
+
html_resource._script_tags, default_html_resource._script_tags
|
122
|
+
):
|
123
|
+
model.script_tags.append(js_code)
|
124
|
+
|
125
|
+
for sylte_code in itertools.chain(
|
126
|
+
html_resource._style_tags, default_html_resource._style_tags
|
127
|
+
):
|
128
|
+
model.style_tags.append(sylte_code)
|
129
|
+
|
130
|
+
html_str = webview_template.render_wbeview_html(model)
|
131
|
+
|
132
|
+
index_html_path = page_dir / _INDEX_HTML_NAME
|
133
|
+
index_html_path.write_text(html_str, encoding="utf-8")
|
134
|
+
relative_to_assets(index_html_path)
|
135
|
+
index_html_url = str(index_html_path.absolute())
|
136
|
+
return ResourceInfo(
|
137
|
+
title="test",
|
138
|
+
index_html_url=index_html_url,
|
139
|
+
)
|
140
|
+
|
141
|
+
|
142
|
+
def _get_relative_to_assets(assets_path: Path):
|
143
|
+
def wrapper(file_path: Path, relative_parent=False):
|
144
|
+
return str(
|
145
|
+
file_path.relative_to(
|
146
|
+
assets_path.parent if relative_parent else assets_path
|
147
|
+
)
|
148
|
+
).replace("\\", "/")
|
149
|
+
|
150
|
+
return wrapper
|
151
|
+
|
152
|
+
|
153
|
+
def _get_file_to_assets(assets_path: Path):
|
154
|
+
relative_to_assets = _get_relative_to_assets(assets_path)
|
155
|
+
|
156
|
+
def wrapper(file_path: Path):
|
157
|
+
hash_part = file_system.generate_hash_name_from_path(file_path.parent)
|
158
|
+
new_folder_path = assets_path.joinpath(hash_part)
|
159
|
+
|
160
|
+
if not new_folder_path.exists():
|
161
|
+
new_folder_path.mkdir(parents=True)
|
162
|
+
|
163
|
+
new_path = new_folder_path.joinpath(file_path.name)
|
164
|
+
|
165
|
+
if file_path.is_file():
|
166
|
+
shutil.copyfile(file_path, new_path)
|
167
|
+
return "./" + relative_to_assets(new_path)
|
168
|
+
else:
|
169
|
+
shutil.copytree(file_path, new_path, dirs_exist_ok=True)
|
170
|
+
return "./" + relative_to_assets(new_path) + "/"
|
171
|
+
|
172
|
+
return wrapper
|
instaui/zero/func.py
CHANGED
@@ -1,24 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
import itertools
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Union
|
5
4
|
import instaui.consts as consts
|
6
5
|
from instaui.runtime._app import get_app_slot, get_default_app_slot
|
7
6
|
from instaui.template import render_zero_html
|
8
7
|
from instaui.template import zero_template
|
9
8
|
from instaui.html_tools import to_config_data
|
10
9
|
from instaui.runtime.dataclass import JsLink
|
10
|
+
from instaui.runtime.resource import HtmlResource
|
11
11
|
|
12
12
|
|
13
|
-
def to_html(file:
|
14
|
-
if isinstance(file, str):
|
15
|
-
import inspect
|
16
|
-
|
17
|
-
frame = inspect.currentframe().f_back # type: ignore
|
18
|
-
assert frame is not None
|
19
|
-
script_file = inspect.getfile(frame)
|
20
|
-
file = Path(script_file).parent.joinpath(file)
|
21
|
-
|
13
|
+
def to_html(file: Path):
|
22
14
|
file = Path(file)
|
23
15
|
|
24
16
|
raw = to_html_str()
|
@@ -27,11 +19,20 @@ def to_html(file: Union[str, Path]):
|
|
27
19
|
return file.resolve().absolute()
|
28
20
|
|
29
21
|
|
30
|
-
def
|
22
|
+
def get_template_model():
|
31
23
|
system_slot = get_app_slot()
|
24
|
+
|
25
|
+
merge_global_resources = (system_slot.meta or {}).get(
|
26
|
+
"merge_global_resources", True
|
27
|
+
)
|
28
|
+
|
32
29
|
default_app_slot = get_default_app_slot()
|
33
30
|
html_resource = system_slot._html_resource
|
34
|
-
default_html_resource =
|
31
|
+
default_html_resource = (
|
32
|
+
default_app_slot._html_resource
|
33
|
+
if merge_global_resources
|
34
|
+
else _empty_html_resource()
|
35
|
+
)
|
35
36
|
|
36
37
|
config_data = to_config_data()
|
37
38
|
|
@@ -48,13 +49,6 @@ def to_html_str():
|
|
48
49
|
title=html_resource.title or default_html_resource.title or consts.PAGE_TITLE,
|
49
50
|
)
|
50
51
|
|
51
|
-
if html_resource.use_tailwind is None:
|
52
|
-
if default_html_resource.use_tailwind:
|
53
|
-
model.js_links.append(JsLink(consts.TAILWIND_JS_PATH))
|
54
|
-
else:
|
55
|
-
if html_resource.use_tailwind:
|
56
|
-
model.js_links.append(JsLink(consts.TAILWIND_JS_PATH))
|
57
|
-
|
58
52
|
# register custom components
|
59
53
|
for component in system_slot._component_dependencies:
|
60
54
|
if not component.esm:
|
@@ -71,6 +65,11 @@ def to_html_str():
|
|
71
65
|
for css_link in component.css:
|
72
66
|
model.css_links.append(css_link)
|
73
67
|
|
68
|
+
if component.externals:
|
69
|
+
for name, url in component.externals.items():
|
70
|
+
if url.is_file():
|
71
|
+
model.add_extra_import_map(name, url)
|
72
|
+
|
74
73
|
# register custom plugins
|
75
74
|
for plugin in set(
|
76
75
|
itertools.chain(
|
@@ -89,15 +88,15 @@ def to_html_str():
|
|
89
88
|
model.css_links.append(css_link)
|
90
89
|
|
91
90
|
# css file link to web static link
|
92
|
-
for link
|
93
|
-
|
91
|
+
for link in html_resource.get_valid_css_links(
|
92
|
+
default_html_resource._css_links_manager
|
94
93
|
):
|
95
94
|
if isinstance(link, Path):
|
96
95
|
model.css_links.append(link)
|
97
96
|
|
98
97
|
# js file link to web static link
|
99
|
-
for info in
|
100
|
-
|
98
|
+
for info in html_resource.get_valid_js_links(
|
99
|
+
default_html_resource._js_links_manager
|
101
100
|
):
|
102
101
|
if isinstance(info.link, Path):
|
103
102
|
model.js_links.append(JsLink(info.link))
|
@@ -112,4 +111,13 @@ def to_html_str():
|
|
112
111
|
):
|
113
112
|
model.style_tags.append(sylte_code)
|
114
113
|
|
114
|
+
return model
|
115
|
+
|
116
|
+
|
117
|
+
def to_html_str():
|
118
|
+
model = get_template_model()
|
115
119
|
return render_zero_html(model)
|
120
|
+
|
121
|
+
|
122
|
+
def _empty_html_resource():
|
123
|
+
return HtmlResource()
|