instaui 0.1.1__py3-none-any.whl → 0.1.3__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/component.py +1 -1
- instaui/components/element.py +37 -17
- instaui/components/html/checkbox.py +0 -7
- instaui/components/html/select.py +1 -1
- instaui/components/vfor.py +1 -1
- instaui/consts.py +4 -0
- instaui/dependencies/component_dependency.py +16 -0
- instaui/dependencies/plugin_dependency.py +28 -0
- instaui/fastapi_server/debug_mode_router.py +0 -1
- instaui/fastapi_server/dependency_router.py +21 -0
- instaui/fastapi_server/resource.py +34 -0
- instaui/fastapi_server/server.py +147 -95
- instaui/html_tools.py +19 -105
- instaui/page_info.py +1 -11
- instaui/runtime/_app.py +9 -20
- instaui/runtime/resource.py +13 -48
- instaui/static/insta-ui.esm-browser.prod.js +3663 -3663
- instaui/static/insta-ui.ico +0 -0
- instaui/static/insta-ui.iife.js +29 -29
- instaui/static/templates/debug/sse.html +2 -2
- instaui/static/templates/web.html +32 -76
- instaui/static/templates/zero.html +48 -32
- instaui/systems/file_system.py +3 -14
- instaui/template/web_template.py +40 -46
- instaui/template/zero_template.py +95 -15
- instaui/ui/__init__.py +4 -5
- instaui/ui_functions/ui_page.py +3 -18
- instaui/vars/path_var.py +2 -1
- instaui/zero/func.py +115 -0
- instaui/zero/scope.py +12 -1
- instaui/zero/test.html +44 -0
- {instaui-0.1.1.dist-info → instaui-0.1.3.dist-info}/METADATA +1 -1
- {instaui-0.1.1.dist-info → instaui-0.1.3.dist-info}/RECORD +35 -32
- instaui/dependencies/__init__.py +0 -15
- instaui/dependencies/component_registrar.py +0 -82
- instaui/dependencies/installer.py +0 -5
- instaui/fastapi_server/config_router.py +0 -60
- {instaui-0.1.1.dist-info → instaui-0.1.3.dist-info}/LICENSE +0 -0
- {instaui-0.1.1.dist-info → instaui-0.1.3.dist-info}/WHEEL +0 -0
instaui/components/component.py
CHANGED
instaui/components/element.py
CHANGED
@@ -13,6 +13,7 @@ from typing import (
|
|
13
13
|
Optional,
|
14
14
|
Tuple,
|
15
15
|
Union,
|
16
|
+
cast,
|
16
17
|
overload,
|
17
18
|
TYPE_CHECKING,
|
18
19
|
)
|
@@ -21,11 +22,11 @@ from collections import defaultdict
|
|
21
22
|
from instaui.runtime._app import get_app_slot
|
22
23
|
from instaui.runtime._app import get_current_scope
|
23
24
|
from instaui.vars.element_ref import ElementRef
|
24
|
-
|
25
|
-
|
26
25
|
from instaui.vars.vfor_item import VForItem
|
27
26
|
from instaui.components.directive import Directive
|
28
|
-
from instaui.dependencies import
|
27
|
+
from instaui.dependencies.component_dependency import (
|
28
|
+
ComponentDependencyInfo,
|
29
|
+
)
|
29
30
|
from .slot import SlotManager, Slot
|
30
31
|
from instaui import consts
|
31
32
|
from instaui.components.component import Component
|
@@ -69,14 +70,14 @@ PROPS_PATTERN = re.compile(
|
|
69
70
|
|
70
71
|
|
71
72
|
class Element(Component):
|
72
|
-
|
73
|
+
dependency: ClassVar[Optional[ComponentDependencyInfo]] = None
|
73
74
|
_default_props: ClassVar[Dict[str, Any]] = {}
|
74
75
|
_default_classes: ClassVar[List[str]] = []
|
75
76
|
_default_style: ClassVar[Dict[str, str]] = {}
|
76
77
|
|
77
78
|
def __init__(self, tag: Optional[Union[str, ElementBindingMixin]] = None):
|
78
|
-
if self.
|
79
|
-
tag = self.
|
79
|
+
if self.dependency:
|
80
|
+
tag = self.dependency.tag_name or ""
|
80
81
|
|
81
82
|
super().__init__(tag)
|
82
83
|
|
@@ -101,19 +102,28 @@ class Element(Component):
|
|
101
102
|
def __init_subclass__(
|
102
103
|
cls,
|
103
104
|
*,
|
104
|
-
|
105
|
+
esm: Union[str, Path, None] = None,
|
106
|
+
externals: Optional[List[Union[str, Path]]] = None,
|
107
|
+
css: Union[List[Union[str, Path]], None] = None,
|
105
108
|
) -> None:
|
106
109
|
super().__init_subclass__()
|
107
110
|
|
108
|
-
if
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
if esm:
|
112
|
+
esm = _make_dependency_path(esm, cls)
|
113
|
+
|
114
|
+
if externals:
|
115
|
+
externals = [_make_dependency_path(e, cls) for e in externals]
|
116
|
+
|
117
|
+
if css:
|
118
|
+
css = [_make_dependency_path(c, cls) for c in css]
|
113
119
|
|
114
|
-
|
115
|
-
|
116
|
-
|
120
|
+
tag_name = f"instaui-{esm.stem}"
|
121
|
+
|
122
|
+
cls.dependency = ComponentDependencyInfo(
|
123
|
+
tag_name=tag_name,
|
124
|
+
esm=esm,
|
125
|
+
externals=cast(List[Path], externals or []),
|
126
|
+
css=cast(List[Path], css or []),
|
117
127
|
)
|
118
128
|
|
119
129
|
cls._default_props = copy(cls._default_props)
|
@@ -365,8 +375,8 @@ class Element(Component):
|
|
365
375
|
if self._directives:
|
366
376
|
data["dir"] = list(self._directives.keys())
|
367
377
|
|
368
|
-
if self.
|
369
|
-
get_app_slot().
|
378
|
+
if self.dependency:
|
379
|
+
get_app_slot().use_component_dependency(self.dependency)
|
370
380
|
|
371
381
|
if self._element_ref:
|
372
382
|
scope = get_current_scope()
|
@@ -460,3 +470,13 @@ def _classifyBindableDict(
|
|
460
470
|
value_data[key] = value
|
461
471
|
|
462
472
|
return value_data, bind_data
|
473
|
+
|
474
|
+
|
475
|
+
def _make_dependency_path(path: Union[str, Path], cls: type):
|
476
|
+
if isinstance(path, str):
|
477
|
+
path = Path(path)
|
478
|
+
|
479
|
+
if not path.is_absolute():
|
480
|
+
path = Path(inspect.getfile(cls)).parent / path
|
481
|
+
|
482
|
+
return path
|
@@ -31,12 +31,5 @@ class Checkbox(InputEventMixin, ValueElement[Union[bool, str]]):
|
|
31
31
|
if model_value is not None:
|
32
32
|
self.props({"value": model_value})
|
33
33
|
|
34
|
-
# def vmodel(
|
35
|
-
# self,
|
36
|
-
# value: Any,
|
37
|
-
# *modifiers: Literal["trim"] | Literal["number"] | Literal["lazy"],
|
38
|
-
# ):
|
39
|
-
# return super().vmodel(value, *modifiers) # type: ignore
|
40
|
-
|
41
34
|
def _input_event_mixin_element(self) -> Element:
|
42
35
|
return self
|
instaui/components/vfor.py
CHANGED
@@ -60,7 +60,7 @@ class VFor(Component, Generic[_T]):
|
|
60
60
|
def __enter__(self) -> _T:
|
61
61
|
self.__scope = self.__scope_manager.__enter__()
|
62
62
|
super().__enter__()
|
63
|
-
return VForItem(self).proxy
|
63
|
+
return VForItem(self).proxy # type: ignore
|
64
64
|
|
65
65
|
def __exit__(self, *_) -> None:
|
66
66
|
self.__scope_manager.__exit__(*_)
|
instaui/consts.py
CHANGED
@@ -8,11 +8,15 @@ _STATIC_DIR = _THIS_DIR.joinpath("static")
|
|
8
8
|
INDEX_TEMPLATE_PATH = _TEMPLATES_DIR.joinpath("index.html")
|
9
9
|
APP_IIFE_JS_PATH = _STATIC_DIR.joinpath("insta-ui.iife.js")
|
10
10
|
APP_ES_JS_PATH = _STATIC_DIR.joinpath("insta-ui.esm-browser.prod.js")
|
11
|
+
APP_ES_JS_MAP_PATH = _STATIC_DIR.joinpath("insta-ui.js.map")
|
11
12
|
APP_CSS_PATH = _STATIC_DIR.joinpath("insta-ui.css")
|
12
13
|
VUE_IIFE_JS_PATH = _STATIC_DIR.joinpath("vue.global.prod.js")
|
13
14
|
VUE_ES_JS_PATH = _STATIC_DIR.joinpath("vue.esm-browser.prod.js")
|
14
15
|
VUE_ES_RUNTIME_JS_PATH = _STATIC_DIR.joinpath("vue.runtime.esm-browser.prod.js")
|
15
16
|
TAILWIND_JS_PATH = _STATIC_DIR.joinpath("tailwindcss.min.js")
|
17
|
+
FAVICON_PATH = _STATIC_DIR.joinpath("insta-ui.ico")
|
18
|
+
|
19
|
+
PAGE_TITLE = "insta-ui"
|
16
20
|
|
17
21
|
_T_App_Mode = Literal["zero", "web", "webview"]
|
18
22
|
TModifier = Literal["trim", "number", "lazy"]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import List, Optional
|
5
|
+
|
6
|
+
_TTagName = str
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass(frozen=True)
|
10
|
+
class ComponentDependencyInfo:
|
11
|
+
tag_name: _TTagName = field(hash=True)
|
12
|
+
esm: Path = field(hash=False)
|
13
|
+
externals: Optional[List[Path]] = field(
|
14
|
+
default_factory=list, compare=False, hash=False
|
15
|
+
)
|
16
|
+
css: List[Path] = field(default_factory=list, compare=False, hash=False)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import List, Optional
|
5
|
+
from instaui.runtime._app import get_app_slot
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass(frozen=True)
|
9
|
+
class PluginDependencyInfo:
|
10
|
+
name: str = field(hash=True)
|
11
|
+
esm: Path = field(hash=False)
|
12
|
+
externals: Optional[List[Path]] = field(
|
13
|
+
default_factory=list, compare=False, hash=False
|
14
|
+
)
|
15
|
+
css: List[Path] = field(default_factory=list, compare=False, hash=False)
|
16
|
+
|
17
|
+
|
18
|
+
def register_plugin(
|
19
|
+
name: str,
|
20
|
+
esm: Path,
|
21
|
+
*,
|
22
|
+
externals: Optional[List[Path]] = None,
|
23
|
+
css: Optional[List[Path]] = None,
|
24
|
+
):
|
25
|
+
info = PluginDependencyInfo(f"plugin/{name}", esm, externals or [], css or [])
|
26
|
+
|
27
|
+
get_app_slot().use_plugin_dependency(info)
|
28
|
+
return info
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from fastapi import FastAPI
|
2
|
+
from fastapi.responses import FileResponse
|
3
|
+
|
4
|
+
from instaui.fastapi_server import resource
|
5
|
+
|
6
|
+
|
7
|
+
URL = f"{resource.URL}/{{hash_part:path}}"
|
8
|
+
|
9
|
+
|
10
|
+
def create_router(app: FastAPI):
|
11
|
+
_dependency_handler(app)
|
12
|
+
|
13
|
+
|
14
|
+
def _dependency_handler(app: FastAPI):
|
15
|
+
@app.get(URL)
|
16
|
+
def _(hash_part: str) -> FileResponse:
|
17
|
+
local_file = resource.get_by_hash(hash_part)
|
18
|
+
|
19
|
+
return FileResponse(
|
20
|
+
local_file, headers={"Cache-Control": "public, max-age=3600"}
|
21
|
+
)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Dict
|
3
|
+
from instaui.systems import file_system
|
4
|
+
from instaui.version import __version__ as _INSTA_VERSION
|
5
|
+
|
6
|
+
URL = f"/_instaui_{_INSTA_VERSION}/resource"
|
7
|
+
_THashPart = str
|
8
|
+
_HASH_PART_MAP: Dict[_THashPart, Path] = {}
|
9
|
+
_FILE_URL_MAP: Dict[Path, _THashPart] = {}
|
10
|
+
|
11
|
+
|
12
|
+
def get_by_hash(hash_part: str) -> Path:
|
13
|
+
return _HASH_PART_MAP[hash_part]
|
14
|
+
|
15
|
+
|
16
|
+
def record_resource(path: Path):
|
17
|
+
if path in _FILE_URL_MAP:
|
18
|
+
return _FILE_URL_MAP[path]
|
19
|
+
|
20
|
+
hash_part = _generate_hash_part(path)
|
21
|
+
_HASH_PART_MAP[hash_part] = path
|
22
|
+
url = f"{URL}/{hash_part}"
|
23
|
+
_FILE_URL_MAP[path] = url
|
24
|
+
return url
|
25
|
+
|
26
|
+
|
27
|
+
def _generate_hash_part(path: Path):
|
28
|
+
path = Path(path).resolve()
|
29
|
+
is_file = path.is_file()
|
30
|
+
|
31
|
+
if is_file:
|
32
|
+
return f"{file_system.generate_hash_name_from_path(path.parent)}/{path.name}"
|
33
|
+
|
34
|
+
return file_system.generate_hash_name_from_path(path)
|
instaui/fastapi_server/server.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
from contextlib import contextmanager
|
2
3
|
import inspect
|
3
4
|
import os
|
4
5
|
import multiprocessing
|
@@ -8,30 +9,44 @@ import __main__
|
|
8
9
|
|
9
10
|
from fastapi import FastAPI
|
10
11
|
from fastapi import Request
|
11
|
-
from fastapi.responses import FileResponse, HTMLResponse
|
12
12
|
from fastapi.staticfiles import StaticFiles
|
13
|
+
|
14
|
+
from fastapi.responses import HTMLResponse
|
13
15
|
import uvicorn
|
14
16
|
from uvicorn.supervisors import ChangeReload
|
17
|
+
import itertools
|
15
18
|
|
16
|
-
from instaui.html_tools import
|
19
|
+
from instaui.html_tools import to_config_data
|
17
20
|
from instaui.launch_collector import get_launch_collector
|
18
21
|
from instaui.page_info import PageInfo
|
19
|
-
|
20
|
-
from instaui.systems import file_system
|
22
|
+
|
21
23
|
from instaui import consts
|
22
|
-
from instaui.runtime._app import get_app_slot
|
24
|
+
from instaui.runtime._app import get_app_slot, get_default_app_slot
|
25
|
+
from instaui.runtime.dataclass import JsLink, VueAppComponent
|
23
26
|
from instaui.template import web_template
|
24
|
-
|
27
|
+
|
28
|
+
|
29
|
+
from . import dependency_router
|
25
30
|
from . import event_router
|
26
31
|
from . import watch_router
|
27
32
|
from . import debug_mode_router
|
28
33
|
from .middlewares import RequestContextMiddleware
|
29
34
|
from ._uvicorn import UvicornServer
|
30
|
-
|
35
|
+
from . import resource
|
36
|
+
from instaui.version import __version__ as _INSTA_VERSION
|
31
37
|
|
32
38
|
APP_IMPORT_STRING = "instaui.fastapi_server.server:Server._instance.app"
|
33
39
|
|
34
40
|
|
41
|
+
INSTAUI_STATIC_URL = f"/_instaui_{_INSTA_VERSION}/static"
|
42
|
+
|
43
|
+
VUE_JS_HASH_LINK = f"{INSTAUI_STATIC_URL}/{consts.VUE_ES_JS_PATH.name}"
|
44
|
+
INSTAUI_JS_HASH_LINK = f"{INSTAUI_STATIC_URL}/{consts.APP_ES_JS_PATH.name}"
|
45
|
+
APP_CSS_LINK = f"{INSTAUI_STATIC_URL}/{consts.APP_CSS_PATH.name}"
|
46
|
+
TAILWIND_JS_HASH_LINK = f"{INSTAUI_STATIC_URL}/{consts.TAILWIND_JS_PATH.name}"
|
47
|
+
FAVICON_LINK = f"{INSTAUI_STATIC_URL}/{consts.FAVICON_PATH.name}"
|
48
|
+
|
49
|
+
|
35
50
|
class Server:
|
36
51
|
_instance: Optional[Server] = None
|
37
52
|
|
@@ -44,12 +59,12 @@ class Server:
|
|
44
59
|
def __init__(self):
|
45
60
|
self.app = FastAPI()
|
46
61
|
self.app.add_middleware(RequestContextMiddleware)
|
47
|
-
|
62
|
+
dependency_router.create_router(self.app)
|
48
63
|
event_router.create_router(self.app)
|
49
64
|
watch_router.create_router(self.app)
|
50
65
|
debug_mode_router.create_router(self.app)
|
51
66
|
|
52
|
-
self.
|
67
|
+
self.add_instaui_static(self.app)
|
53
68
|
|
54
69
|
for page_info in get_launch_collector()._page_router.values():
|
55
70
|
self.register_page(page_info)
|
@@ -61,125 +76,145 @@ class Server:
|
|
61
76
|
|
62
77
|
self._remove_route(info.path)
|
63
78
|
|
64
|
-
|
65
|
-
config_handler.register_handler(key, info.func)
|
66
|
-
config_fetch_url = (
|
67
|
-
config_handler.ASYNC_URL if is_async else config_handler.SYNC_URL
|
68
|
-
)
|
79
|
+
if is_async:
|
69
80
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
81
|
+
@self.app.get(info.path)
|
82
|
+
async def _(request: Request):
|
83
|
+
self._update_page_info(request, info)
|
84
|
+
with _execute_request_lifespans():
|
85
|
+
await info.func()
|
86
|
+
html = self._to_web_html(
|
87
|
+
page_info=info,
|
88
|
+
request=request,
|
89
|
+
)
|
90
|
+
|
91
|
+
return HTMLResponse(html)
|
92
|
+
|
93
|
+
else:
|
94
|
+
|
95
|
+
@self.app.get(info.path)
|
96
|
+
def _(request: Request):
|
97
|
+
self._update_page_info(request, info)
|
98
|
+
with _execute_request_lifespans():
|
99
|
+
info.func()
|
100
|
+
html = self._to_web_html(
|
101
|
+
page_info=info,
|
102
|
+
request=request,
|
103
|
+
)
|
89
104
|
|
90
|
-
|
105
|
+
return HTMLResponse(html)
|
91
106
|
|
92
107
|
def _to_web_html(
|
93
108
|
self,
|
94
109
|
*,
|
95
110
|
page_info: PageInfo,
|
96
|
-
query_path: str,
|
97
|
-
config_json: Optional[str] = None,
|
98
|
-
config_fetch_url: Optional[str] = None,
|
99
|
-
config_fetch_key: Optional[str] = None,
|
100
|
-
page_loadding_json: Optional[str] = None,
|
101
111
|
request: Request,
|
102
112
|
):
|
113
|
+
config_data = to_config_data()
|
114
|
+
|
103
115
|
system_slot = get_app_slot()
|
116
|
+
default_app_slot = get_default_app_slot()
|
104
117
|
html_resource = system_slot._html_resource
|
105
|
-
|
106
|
-
|
107
|
-
html_resource.add_import_map(
|
108
|
-
"vue", self._static_dir_url + f"/{consts.VUE_ES_JS_PATH.name}"
|
109
|
-
)
|
118
|
+
default_html_resource = default_app_slot._html_resource
|
110
119
|
|
111
|
-
|
112
|
-
|
120
|
+
favicon_url = FAVICON_LINK
|
121
|
+
if html_resource.favicon:
|
122
|
+
favicon_url = resource.record_resource(html_resource.favicon)
|
123
|
+
else:
|
124
|
+
if default_html_resource.favicon:
|
125
|
+
favicon_url = resource.record_resource(default_html_resource.favicon)
|
126
|
+
|
127
|
+
model = web_template.WebTemplateModel(
|
128
|
+
vue_js_link=VUE_JS_HASH_LINK,
|
129
|
+
instaui_js_link=INSTAUI_JS_HASH_LINK,
|
130
|
+
css_links=[
|
131
|
+
APP_CSS_LINK,
|
132
|
+
],
|
133
|
+
config_dict=config_data,
|
134
|
+
favicon_url=favicon_url,
|
135
|
+
title=html_resource.title
|
136
|
+
or default_html_resource.title
|
137
|
+
or consts.PAGE_TITLE,
|
113
138
|
)
|
114
|
-
html_resource.add_css_link(consts.APP_CSS_PATH)
|
115
139
|
|
116
|
-
if html_resource.use_tailwind:
|
117
|
-
|
118
|
-
|
140
|
+
if html_resource.use_tailwind is None:
|
141
|
+
if default_html_resource.use_tailwind:
|
142
|
+
model.js_links.append(JsLink(TAILWIND_JS_HASH_LINK))
|
143
|
+
else:
|
144
|
+
if html_resource.use_tailwind:
|
145
|
+
model.js_links.append(JsLink(TAILWIND_JS_HASH_LINK))
|
119
146
|
|
120
147
|
# register custom components
|
121
|
-
|
122
|
-
for component in system_slot._js_components:
|
148
|
+
for component in system_slot._component_dependencies:
|
123
149
|
if not component.esm:
|
124
150
|
continue
|
125
|
-
|
126
|
-
|
151
|
+
|
152
|
+
model.vue_app_component.append(
|
153
|
+
VueAppComponent(
|
154
|
+
name=component.tag_name,
|
155
|
+
url=resource.record_resource(component.esm),
|
156
|
+
)
|
157
|
+
)
|
127
158
|
|
128
159
|
if component.css:
|
129
160
|
for css_link in component.css:
|
130
|
-
|
161
|
+
model.css_links.append(resource.record_resource(css_link))
|
131
162
|
|
132
163
|
# register custom plugins
|
133
|
-
for plugin in
|
164
|
+
for plugin in set(
|
165
|
+
itertools.chain(
|
166
|
+
system_slot._plugin_dependencies, default_app_slot._plugin_dependencies
|
167
|
+
)
|
168
|
+
):
|
134
169
|
if not plugin.esm:
|
135
170
|
continue
|
136
|
-
|
137
|
-
|
171
|
+
|
172
|
+
model.vue_app_use.append(plugin.name)
|
173
|
+
|
174
|
+
model.add_extra_import_map(
|
175
|
+
plugin.name, resource.record_resource(plugin.esm)
|
176
|
+
)
|
138
177
|
|
139
178
|
if plugin.css:
|
140
179
|
for css_link in plugin.css:
|
141
|
-
|
180
|
+
model.css_links.append(resource.record_resource(css_link))
|
142
181
|
|
143
182
|
# css file link to web static link
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
183
|
+
for link, attrs in itertools.chain(
|
184
|
+
html_resource._css_links.items(), default_html_resource._css_links.items()
|
185
|
+
):
|
186
|
+
if isinstance(link, Path):
|
187
|
+
model.css_links.append(resource.record_resource(link))
|
148
188
|
|
149
189
|
# js file link to web static link
|
150
|
-
for info in
|
190
|
+
for info in itertools.chain(
|
191
|
+
html_resource._js_links, default_html_resource._js_links
|
192
|
+
):
|
151
193
|
if isinstance(info.link, Path):
|
152
|
-
|
194
|
+
model.js_links.append(JsLink((resource.record_resource(info.link))))
|
195
|
+
|
196
|
+
for js_code in itertools.chain(
|
197
|
+
html_resource._script_tags, default_html_resource._script_tags
|
198
|
+
):
|
199
|
+
model.script_tags.append(js_code)
|
200
|
+
|
201
|
+
for sylte_code in itertools.chain(
|
202
|
+
html_resource._style_tags, default_html_resource._style_tags
|
203
|
+
):
|
204
|
+
model.style_tags.append(sylte_code)
|
153
205
|
|
154
|
-
prefix = request.headers.get(
|
206
|
+
model.prefix = request.headers.get(
|
155
207
|
"X-Forwarded-Prefix", request.scope.get("root_path", "")
|
156
208
|
)
|
157
209
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
query_path_params=str(request.path_params),
|
163
|
-
query_params=dict(request.query_params),
|
164
|
-
query_path=query_path,
|
165
|
-
page_loadding_json=page_loadding_json,
|
166
|
-
prefix=prefix,
|
167
|
-
)
|
168
|
-
get_app_slot().reset_html_resource()
|
169
|
-
return result
|
170
|
-
|
171
|
-
def add_static_file_route(self, local_file: Path) -> str:
|
172
|
-
path = file_system.generate_static_url_from_file_path(local_file)
|
173
|
-
if path in self._registered_static_routes:
|
174
|
-
return path
|
175
|
-
|
176
|
-
@self.app.get(path)
|
177
|
-
def _() -> FileResponse:
|
178
|
-
return FileResponse(
|
179
|
-
local_file, headers={"Cache-Control": "public, max-age=3600"}
|
180
|
-
)
|
210
|
+
return web_template.render_web_html(model)
|
211
|
+
|
212
|
+
def _update_page_info(self, request: Request, page_info: PageInfo):
|
213
|
+
app = get_app_slot()
|
181
214
|
|
182
|
-
|
215
|
+
app._page_path = page_info.path
|
216
|
+
app._page_params = request.path_params
|
217
|
+
app._query_params = dict(request.query_params)
|
183
218
|
|
184
219
|
def _remove_route(self, path: str) -> None:
|
185
220
|
self.app.routes[:] = [
|
@@ -235,12 +270,29 @@ class Server:
|
|
235
270
|
def run_with(self, app):
|
236
271
|
assert isinstance(app, FastAPI), "app must be a FastAPI instance"
|
237
272
|
|
238
|
-
|
239
|
-
def
|
240
|
-
|
241
|
-
|
242
|
-
|
273
|
+
@staticmethod
|
274
|
+
def add_instaui_static(app: FastAPI):
|
275
|
+
app.mount(
|
276
|
+
INSTAUI_STATIC_URL,
|
277
|
+
StaticFiles(directory=consts._STATIC_DIR),
|
278
|
+
name=INSTAUI_STATIC_URL,
|
279
|
+
)
|
243
280
|
|
244
281
|
|
245
282
|
def _split_args(args: str):
|
246
283
|
return [a.strip() for a in args.split(",")]
|
284
|
+
|
285
|
+
|
286
|
+
@contextmanager
|
287
|
+
def _execute_request_lifespans():
|
288
|
+
events = [iter(event()) for event in get_launch_collector().page_request_lifespans]
|
289
|
+
for event in events:
|
290
|
+
next(event)
|
291
|
+
|
292
|
+
yield
|
293
|
+
|
294
|
+
for event in events:
|
295
|
+
try:
|
296
|
+
next(event)
|
297
|
+
except StopIteration:
|
298
|
+
pass
|