instaui 0.1.4__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/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 +50 -4
- instaui/components/html/__init__.py +30 -19
- 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 +13 -31
- instaui/components/html/table.py +36 -0
- instaui/components/markdown/static/marked.esm.js +0 -1
- 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/consts.py +2 -1
- instaui/daisyui/__init__.py +8 -2
- instaui/daisyui/_index.py +5 -0
- instaui/daisyui/table.py +35 -0
- instaui/event/js_event.py +1 -0
- instaui/event/web_event.py +6 -7
- instaui/fastapi_server/server.py +4 -12
- instaui/handlers/event_handler.py +3 -1
- instaui/handlers/watch_handler.py +4 -0
- instaui/html_tools.py +40 -2
- instaui/runtime/_app.py +37 -3
- instaui/runtime/_link_manager.py +89 -0
- instaui/runtime/resource.py +19 -9
- instaui/shadcn_classless/_index.py +42 -0
- instaui/shadcn_classless/static/shadcn-classless.css +403 -0
- instaui/static/insta-ui.css +1 -1
- instaui/static/insta-ui.esm-browser.prod.js +1314 -1253
- instaui/static/insta-ui.js.map +1 -1
- instaui/static/instaui-tools-browser.js +511 -0
- instaui/static/templates/webview.html +78 -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/ui/__init__.py +8 -2
- instaui/ui/__init__.pyi +7 -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 +19 -12
- instaui/zero/scope.py +46 -28
- {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/METADATA +4 -1
- {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/RECORD +67 -47
- instaui/components/highlight_code/code.js +0 -63
- instaui/components/highlight_code/code.py +0 -117
- instaui/components/highlight_code/static/core.min.js +0 -307
- instaui/components/highlight_code/static/languages/css.min.js +0 -31
- instaui/components/highlight_code/static/languages/javascript.min.js +0 -81
- instaui/components/highlight_code/static/languages/json.min.js +0 -8
- instaui/components/highlight_code/static/languages/python-repl.min.js +0 -5
- instaui/components/highlight_code/static/languages/python.min.js +0 -42
- instaui/components/highlight_code/static/languages/shell.min.js +0 -5
- instaui/components/highlight_code/static/styles/default.min.css +0 -9
- instaui/components/highlight_code/static/styles/github-dark-dimmed.min.css +0 -9
- instaui/components/highlight_code/static/styles/github-dark.min.css +0 -10
- instaui/components/highlight_code/static/styles/github.min.css +0 -10
- instaui/handlers/computed_handler.py +0 -42
- instaui/handlers/config_handler.py +0 -13
- {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/LICENSE +0 -0
- {instaui-0.1.4.dist-info → instaui-0.1.5.dist-info}/WHEEL +0 -0
instaui/components/element.py
CHANGED
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
7
7
|
import re
|
8
8
|
from typing import (
|
9
9
|
Any,
|
10
|
+
Callable,
|
10
11
|
Dict,
|
11
12
|
Iterable,
|
12
13
|
List,
|
@@ -358,17 +359,58 @@ class Element(Component):
|
|
358
359
|
*,
|
359
360
|
css: Optional[Iterable[Path]] = None,
|
360
361
|
externals: Optional[Dict[str, Path]] = None,
|
362
|
+
replace: bool = False,
|
361
363
|
):
|
362
364
|
if not self.dependency:
|
363
365
|
return
|
364
366
|
|
367
|
+
app = get_app_slot()
|
368
|
+
dep = self.dependency.copy()
|
369
|
+
if replace:
|
370
|
+
dep.css.clear()
|
371
|
+
dep.externals.clear()
|
372
|
+
|
365
373
|
if css:
|
366
|
-
|
374
|
+
dep.css.update(css)
|
367
375
|
|
368
376
|
if externals:
|
369
|
-
|
377
|
+
dep.externals.update(externals)
|
378
|
+
|
379
|
+
app.add_temp_component_dependency(dep)
|
380
|
+
|
381
|
+
def use(self, *use_fns: Callable[[Self], None]) -> Self:
|
382
|
+
"""Use functions to the component object.
|
370
383
|
|
371
|
-
|
384
|
+
Args:
|
385
|
+
use_fns (Callable[[Self], None]): The list of use functions.
|
386
|
+
|
387
|
+
Examples:
|
388
|
+
.. code-block:: python
|
389
|
+
def use_red_color(element: html.paragraph):
|
390
|
+
element.style('color: red')
|
391
|
+
|
392
|
+
html.paragraph('Hello').use(use_red_color)
|
393
|
+
"""
|
394
|
+
|
395
|
+
for fn in use_fns:
|
396
|
+
fn(self)
|
397
|
+
return self
|
398
|
+
|
399
|
+
@classmethod
|
400
|
+
def use_init(cls, init_fn: Callable[[type[Self]], Self]) -> Self:
|
401
|
+
"""Use this method to initialize the component.
|
402
|
+
|
403
|
+
Args:
|
404
|
+
init_fn (Callable[[type[Self]], Self]): The initialization function.
|
405
|
+
|
406
|
+
Examples:
|
407
|
+
.. code-block:: python
|
408
|
+
def fack_init(cls: type[html.table]) -> html.table:
|
409
|
+
return cls(columns=['name', 'age'],rows = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}])
|
410
|
+
|
411
|
+
ui.table.use_init(fack_init)
|
412
|
+
"""
|
413
|
+
return init_fn(cls)
|
372
414
|
|
373
415
|
def _to_json_dict(self):
|
374
416
|
data = super()._to_json_dict()
|
@@ -420,7 +462,11 @@ class Element(Component):
|
|
420
462
|
data["dir"] = list(self._directives.keys())
|
421
463
|
|
422
464
|
if self.dependency:
|
423
|
-
get_app_slot()
|
465
|
+
app_slot = get_app_slot()
|
466
|
+
tag_name = self.dependency.tag_name
|
467
|
+
app_slot.use_component_dependency(
|
468
|
+
app_slot.get_temp_component_dependency(tag_name, self.dependency)
|
469
|
+
)
|
424
470
|
|
425
471
|
if self._element_ref:
|
426
472
|
scope = get_current_scope()
|
@@ -1,22 +1,3 @@
|
|
1
|
-
from .span import Span as span
|
2
|
-
from .label import Label as label
|
3
|
-
from .paragraph import Paragraph as paragraph
|
4
|
-
from .input import Input as input
|
5
|
-
from .number import Number as number
|
6
|
-
from .button import Button as button
|
7
|
-
from .checkbox import Checkbox as checkbox
|
8
|
-
from .form import Form as form
|
9
|
-
from .select import Select as select
|
10
|
-
from .ul import Ul as ul
|
11
|
-
from .li import Li as li
|
12
|
-
from .div import Div as div
|
13
|
-
from .range import Range as range
|
14
|
-
from .date import Date as date
|
15
|
-
from .link import Link as link
|
16
|
-
from .textarea import Textarea as textarea
|
17
|
-
|
18
|
-
option = select.Option
|
19
|
-
|
20
1
|
__all__ = [
|
21
2
|
"span",
|
22
3
|
"label",
|
@@ -35,4 +16,34 @@ __all__ = [
|
|
35
16
|
"date",
|
36
17
|
"link",
|
37
18
|
"textarea",
|
19
|
+
"table",
|
20
|
+
"h1",
|
21
|
+
"h2",
|
22
|
+
"h3",
|
23
|
+
"h4",
|
24
|
+
"h5",
|
25
|
+
"h6",
|
38
26
|
]
|
27
|
+
|
28
|
+
from .span import Span as span
|
29
|
+
from .label import Label as label
|
30
|
+
from .paragraph import Paragraph as paragraph
|
31
|
+
from .input import Input as input
|
32
|
+
from .number import Number as number
|
33
|
+
from .button import Button as button
|
34
|
+
from .checkbox import Checkbox as checkbox
|
35
|
+
from .form import Form as form
|
36
|
+
from .select import Select as select
|
37
|
+
from .ul import Ul as ul
|
38
|
+
from .li import Li as li
|
39
|
+
from .div import Div as div
|
40
|
+
from .range import Range as range
|
41
|
+
from .date import Date as date
|
42
|
+
from .link import Link as link
|
43
|
+
from .textarea import Textarea as textarea
|
44
|
+
from .table import Table as table
|
45
|
+
from .heading import H1 as h1, H2 as h2, H3 as h3, H4 as h4, H5 as h5, H6 as h6
|
46
|
+
|
47
|
+
option = select.Option
|
48
|
+
|
49
|
+
from . import _preset # noqa: E402, F401
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import TYPE_CHECKING, Any, Literal, Union
|
3
|
+
from instaui.components.element import Element
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
import instaui.vars as ui_vars
|
7
|
+
|
8
|
+
|
9
|
+
class Heading(Element):
|
10
|
+
def __init__(
|
11
|
+
self,
|
12
|
+
text: Union[str, ui_vars.TMaybeRef[Any]],
|
13
|
+
*,
|
14
|
+
level: Literal[1, 2, 3, 4, 5, 6] = 1,
|
15
|
+
):
|
16
|
+
super().__init__(f"h{level}")
|
17
|
+
self.props(
|
18
|
+
{
|
19
|
+
"innerText": text,
|
20
|
+
}
|
21
|
+
)
|
22
|
+
|
23
|
+
|
24
|
+
class H1(Heading):
|
25
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
26
|
+
super().__init__(text, level=1)
|
27
|
+
|
28
|
+
|
29
|
+
class H2(Heading):
|
30
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
31
|
+
super().__init__(text, level=2)
|
32
|
+
|
33
|
+
|
34
|
+
class H3(Heading):
|
35
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
36
|
+
super().__init__(text, level=3)
|
37
|
+
|
38
|
+
|
39
|
+
class H4(Heading):
|
40
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
41
|
+
super().__init__(text, level=4)
|
42
|
+
|
43
|
+
|
44
|
+
class H5(Heading):
|
45
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
46
|
+
super().__init__(text, level=5)
|
47
|
+
|
48
|
+
|
49
|
+
class H6(Heading):
|
50
|
+
def __init__(self, text: Union[str, ui_vars.TMaybeRef[Any]]):
|
51
|
+
super().__init__(text, level=6)
|
instaui/components/html/range.py
CHANGED
@@ -17,6 +17,7 @@ class Range(InputEventMixin, ValueElement[_T_value]):
|
|
17
17
|
*,
|
18
18
|
min: Union[_T_value, TMaybeRef[_T_value], None] = None,
|
19
19
|
max: Union[_T_value, TMaybeRef[_T_value], None] = None,
|
20
|
+
step: Union[_T_value, TMaybeRef[_T_value], None] = None,
|
20
21
|
):
|
21
22
|
super().__init__("input", value, is_html_component=True)
|
22
23
|
self.props({"type": "range"})
|
@@ -25,6 +26,8 @@ class Range(InputEventMixin, ValueElement[_T_value]):
|
|
25
26
|
self.props({"min": min})
|
26
27
|
if max is not None:
|
27
28
|
self.props({"max": max})
|
29
|
+
if step is not None:
|
30
|
+
self.props({"step": step})
|
28
31
|
|
29
32
|
def vmodel(
|
30
33
|
self,
|
@@ -1,71 +1,53 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from typing import (
|
3
3
|
TYPE_CHECKING,
|
4
|
-
Any,
|
5
4
|
Callable,
|
6
5
|
Dict,
|
7
6
|
List,
|
8
|
-
Literal,
|
9
7
|
Optional,
|
10
8
|
Union,
|
11
9
|
overload,
|
12
10
|
)
|
13
11
|
from typing_extensions import Self
|
14
|
-
|
15
|
-
from instaui.vars import Ref
|
16
12
|
from instaui.components.value_element import ValueElement
|
17
13
|
from instaui.components.element import Element
|
14
|
+
from instaui.event.event_mixin import EventMixin
|
18
15
|
from instaui.vars.types import TMaybeRef
|
19
16
|
from instaui.components.vfor import VFor
|
20
17
|
|
21
|
-
if TYPE_CHECKING:
|
22
|
-
import instaui.vars as ui_vars
|
23
|
-
|
24
|
-
|
25
18
|
_T_Select_Value = Union[List[str], str]
|
26
19
|
|
27
20
|
|
28
21
|
class Select(ValueElement[Union[List[str], str]]):
|
29
22
|
def __init__(
|
30
23
|
self,
|
31
|
-
value: Union[_T_Select_Value,
|
24
|
+
value: Union[_T_Select_Value, TMaybeRef[_T_Select_Value], None] = None,
|
32
25
|
*,
|
33
|
-
model_value: Union[str,
|
26
|
+
model_value: Union[str, TMaybeRef[str], None] = None,
|
34
27
|
):
|
35
28
|
super().__init__("select", value, is_html_component=True)
|
36
29
|
|
37
30
|
if model_value is not None:
|
38
31
|
self.props({"value": model_value})
|
39
32
|
|
40
|
-
@overload
|
41
|
-
def on_change(self, handler: Callable, *, key: Optional[str] = None) -> Self: ...
|
42
|
-
|
43
|
-
@overload
|
44
33
|
def on_change(
|
45
34
|
self,
|
46
|
-
handler:
|
35
|
+
handler: EventMixin,
|
47
36
|
*,
|
48
|
-
|
49
|
-
key: Optional[str] = None,
|
50
|
-
) -> Self: ...
|
51
|
-
|
52
|
-
def on_change(
|
53
|
-
self,
|
54
|
-
handler: Union[Callable, str],
|
55
|
-
*,
|
56
|
-
bindings: Optional[Dict] = None,
|
57
|
-
key: Optional[str] = None,
|
37
|
+
extends: Optional[List] = None,
|
58
38
|
):
|
59
|
-
self.on("change", handler
|
39
|
+
self.on("change", handler)
|
60
40
|
return self
|
61
41
|
|
62
42
|
@classmethod
|
63
43
|
def from_list(
|
64
44
|
cls,
|
65
45
|
options: TMaybeRef[List],
|
66
|
-
value: Union[_T_Select_Value,
|
46
|
+
value: Union[_T_Select_Value, TMaybeRef[_T_Select_Value], None] = None,
|
47
|
+
*,
|
48
|
+
model_value: Union[str, TMaybeRef[str], None] = None,
|
67
49
|
) -> Select:
|
68
|
-
with cls(value) as select:
|
50
|
+
with cls(value, model_value=model_value) as select:
|
69
51
|
with VFor(options) as item:
|
70
52
|
Select.Option(item) # type: ignore
|
71
53
|
|
@@ -74,9 +56,9 @@ class Select(ValueElement[Union[List[str], str]]):
|
|
74
56
|
class Option(Element):
|
75
57
|
def __init__(
|
76
58
|
self,
|
77
|
-
text: Optional[
|
78
|
-
value: Optional[
|
79
|
-
disabled: Optional[
|
59
|
+
text: Optional[TMaybeRef[str]] = None,
|
60
|
+
value: Optional[TMaybeRef[str]] = None,
|
61
|
+
disabled: Optional[TMaybeRef[bool]] = None,
|
80
62
|
):
|
81
63
|
props = {
|
82
64
|
key: value
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import TYPE_CHECKING, Any, List, Optional, Union
|
3
|
+
from instaui.components.element import Element
|
4
|
+
from instaui.components.content import Content
|
5
|
+
from instaui.components.vfor import VFor
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
import instaui.vars as ui_vars
|
9
|
+
|
10
|
+
|
11
|
+
class Table(Element):
|
12
|
+
def __init__(
|
13
|
+
self,
|
14
|
+
columns: Union[List[str], ui_vars.TMaybeRef[List[str]], None] = None,
|
15
|
+
rows: Union[List[List[Any]], ui_vars.TMaybeRef[List[List[Any]]], None] = None,
|
16
|
+
):
|
17
|
+
"""Create a table element.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
columns (Union[List[str], ui_vars.TMaybeRef[List[str]], None], optional): A list of column headers or a reactive reference to such a list. Defaults to None.
|
21
|
+
rows (Union[List[List[Any]], ui_vars.TMaybeRef[List[List[Any]]], None], optional): A list of row data, where each row is a list of cell values, or a reactive reference to such a list. Defaults to None.
|
22
|
+
"""
|
23
|
+
super().__init__("table")
|
24
|
+
|
25
|
+
with self:
|
26
|
+
with Element("thead"), Element("tr"):
|
27
|
+
with VFor(columns) as col: # type: ignore
|
28
|
+
with Element("th"):
|
29
|
+
Content(col)
|
30
|
+
|
31
|
+
with Element("tbody"):
|
32
|
+
with VFor(rows) as row: # type: ignore
|
33
|
+
with Element("tr"):
|
34
|
+
with VFor(row) as cell: # type: ignore
|
35
|
+
with Element("td"):
|
36
|
+
Content(cell)
|
@@ -2577,4 +2577,3 @@ const parser = _Parser.parse;
|
|
2577
2577
|
const lexer = _Lexer.lex;
|
2578
2578
|
|
2579
2579
|
export { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };
|
2580
|
-
//# sourceMappingURL=marked.esm.js.map
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import { h, ref, watch, computed, normalizeClass as _normalizeClass } from "vue";
|
2
|
+
import { createHighlighter } from "@shiki";
|
3
|
+
import { useClipboard } from "@instaui-tools/browser";
|
4
|
+
|
5
|
+
|
6
|
+
const highlighterTask = createHighlighter({
|
7
|
+
themes: ["vitesse-dark", 'vitesse-light']
|
8
|
+
})
|
9
|
+
const getTransformersModule = transformersModuleGetter()
|
10
|
+
|
11
|
+
|
12
|
+
export default {
|
13
|
+
props: ['code', 'language', 'theme', 'themes', 'transformers', 'lineNumbers'],
|
14
|
+
setup(props) {
|
15
|
+
const { transformers: transformerNames = [], themes = {
|
16
|
+
light: 'vitesse-light',
|
17
|
+
dark: 'vitesse-dark'
|
18
|
+
} } = props;
|
19
|
+
|
20
|
+
const highlightedCode = ref('');
|
21
|
+
const realLanguage = computed(() => props.language || 'python')
|
22
|
+
const realTheme = computed(() => props.theme || 'light')
|
23
|
+
const realLineNumbers = computed(() => props.lineNumbers ?? true)
|
24
|
+
const classes = computed(() => {
|
25
|
+
return _normalizeClass([
|
26
|
+
`language-${realLanguage.value}`,
|
27
|
+
`theme-${realTheme.value}`,
|
28
|
+
`shiki-code`,
|
29
|
+
{ 'line-numbers': realLineNumbers.value }
|
30
|
+
])
|
31
|
+
})
|
32
|
+
|
33
|
+
watch([() => props.code, realTheme], async ([code, _]) => {
|
34
|
+
if (!code) {
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
code = code.trim()
|
38
|
+
const highlighter = await highlighterTask;
|
39
|
+
const transformers = await getTransformers(transformerNames)
|
40
|
+
|
41
|
+
highlightedCode.value = await highlighter.codeToHtml(code, {
|
42
|
+
themes,
|
43
|
+
lang: realLanguage.value,
|
44
|
+
transformers,
|
45
|
+
defaultColor: realTheme.value,
|
46
|
+
colorReplacements: {
|
47
|
+
'#ffffff': '#f8f8f2'
|
48
|
+
}
|
49
|
+
});
|
50
|
+
|
51
|
+
}, { immediate: true });
|
52
|
+
|
53
|
+
|
54
|
+
// copy button
|
55
|
+
const { copyButtonClick, btnClasses } = readyCopyButton(props)
|
56
|
+
|
57
|
+
return () => h("div",
|
58
|
+
{ class: classes.value },
|
59
|
+
[h("button", { class: btnClasses.value, title: "Copy Code", onClick: copyButtonClick }),
|
60
|
+
h("span", { class: "lang", }, realLanguage.value),
|
61
|
+
h('div', { innerHTML: highlightedCode.value, style: 'overflow:hidden;' })
|
62
|
+
]
|
63
|
+
);
|
64
|
+
}
|
65
|
+
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
function readyCopyButton(props) {
|
70
|
+
const { copy, copied } = useClipboard({ source: props.code, legacy: true })
|
71
|
+
|
72
|
+
const btnClasses = computed(() => {
|
73
|
+
return _normalizeClass([
|
74
|
+
"copy",
|
75
|
+
{ "copied": copied.value }
|
76
|
+
])
|
77
|
+
})
|
78
|
+
|
79
|
+
/**
|
80
|
+
*
|
81
|
+
* @param {Event} e
|
82
|
+
*/
|
83
|
+
function copyButtonClick(e) {
|
84
|
+
copy(props.code)
|
85
|
+
|
86
|
+
watch(copied, (copied) => {
|
87
|
+
if (!copied) {
|
88
|
+
e.target.blur()
|
89
|
+
}
|
90
|
+
}, { once: true })
|
91
|
+
}
|
92
|
+
|
93
|
+
return {
|
94
|
+
copyButtonClick,
|
95
|
+
btnClasses,
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
|
100
|
+
/**
|
101
|
+
*
|
102
|
+
* @param {string[]} names
|
103
|
+
*/
|
104
|
+
async function getTransformers(names) {
|
105
|
+
if (names.length === 0) {
|
106
|
+
return [];
|
107
|
+
}
|
108
|
+
|
109
|
+
const tfModule = await getTransformersModule()
|
110
|
+
return names.map(name => {
|
111
|
+
const realName = `transformer${name.charAt(0).toUpperCase() + name.slice(1)}`
|
112
|
+
return tfModule[realName]()
|
113
|
+
})
|
114
|
+
}
|
115
|
+
|
116
|
+
|
117
|
+
function transformersModuleGetter() {
|
118
|
+
let module = null;
|
119
|
+
|
120
|
+
return async () => {
|
121
|
+
if (!module) {
|
122
|
+
module = await import(`@shiki/transformers`)
|
123
|
+
}
|
124
|
+
return module;
|
125
|
+
}
|
126
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Dict, Iterable, List, Literal, Optional
|
4
|
+
from instaui import ui
|
5
|
+
from instaui.runtime._app import get_app_slot
|
6
|
+
from instaui import consts
|
7
|
+
|
8
|
+
_STATIC_DIR = Path(__file__).parent / "static"
|
9
|
+
_THEME_DIR = _STATIC_DIR / "themes"
|
10
|
+
_LANG_DIR = _STATIC_DIR / "langs"
|
11
|
+
_SHIKI_CORE_FILE = _STATIC_DIR / "shiki-core.js"
|
12
|
+
_SHIKI_TRANSFORMERS_FILE = _STATIC_DIR / "shiki-transformers.js"
|
13
|
+
_STYLE = _STATIC_DIR / "shiki-style.css"
|
14
|
+
|
15
|
+
|
16
|
+
_LANGS_IMPORT_NAME = "@shiki/langs/"
|
17
|
+
_THEMES_IMPORT_NAME = "@shiki/themes/"
|
18
|
+
|
19
|
+
_IMPORT_MAPS = {
|
20
|
+
"@shiki": _SHIKI_CORE_FILE,
|
21
|
+
"@shiki/transformers": _SHIKI_TRANSFORMERS_FILE,
|
22
|
+
_LANGS_IMPORT_NAME: _LANG_DIR,
|
23
|
+
_THEMES_IMPORT_NAME: _THEME_DIR,
|
24
|
+
"@instaui-tools/browser": consts.TOOLS_BROWSER_JS_PATH,
|
25
|
+
}
|
26
|
+
|
27
|
+
_ZERO_IMPORT_MAPS = {
|
28
|
+
"@shiki": _SHIKI_CORE_FILE,
|
29
|
+
"@shiki/transformers": _SHIKI_TRANSFORMERS_FILE,
|
30
|
+
f"{_LANGS_IMPORT_NAME}python.mjs": _LANG_DIR / "python.mjs",
|
31
|
+
f"{_THEMES_IMPORT_NAME}vitesse-light.mjs": _THEME_DIR / "vitesse-light.mjs",
|
32
|
+
f"{_THEMES_IMPORT_NAME}vitesse-dark.mjs": _THEME_DIR / "vitesse-dark.mjs",
|
33
|
+
"@instaui-tools/browser": consts.TOOLS_BROWSER_JS_PATH,
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
class Code(
|
38
|
+
ui.element,
|
39
|
+
esm="./shiki_code.js",
|
40
|
+
externals=_IMPORT_MAPS,
|
41
|
+
css=[_STYLE],
|
42
|
+
):
|
43
|
+
# _language_folder: ClassVar[Path] = _LANGUAGE_DIR
|
44
|
+
|
45
|
+
def __init__(
|
46
|
+
self,
|
47
|
+
code: ui.TMaybeRef[str],
|
48
|
+
*,
|
49
|
+
language: Optional[ui.TMaybeRef[str]] = None,
|
50
|
+
theme: Optional[ui.TMaybeRef[str]] = None,
|
51
|
+
themes: Optional[Dict[str, str]] = None,
|
52
|
+
transformers: Optional[List[TTransformerNames]] = None,
|
53
|
+
line_numbers: Optional[ui.TMaybeRef[bool]] = None,
|
54
|
+
):
|
55
|
+
super().__init__()
|
56
|
+
self.props({"code": code})
|
57
|
+
|
58
|
+
if language:
|
59
|
+
self.props({"language": language})
|
60
|
+
|
61
|
+
if theme:
|
62
|
+
self.props({"theme": theme})
|
63
|
+
|
64
|
+
if themes:
|
65
|
+
self.props({"themes": themes})
|
66
|
+
|
67
|
+
if transformers:
|
68
|
+
self.props({"transformers": transformers})
|
69
|
+
|
70
|
+
if line_numbers is not None:
|
71
|
+
self.props({"lineNumbers": line_numbers})
|
72
|
+
|
73
|
+
def _to_json_dict(self):
|
74
|
+
self.use_zero_dependency()
|
75
|
+
return super()._to_json_dict()
|
76
|
+
|
77
|
+
def use_zero_dependency(self):
|
78
|
+
app = get_app_slot()
|
79
|
+
tag_name = self.dependency.tag_name # type: ignore
|
80
|
+
|
81
|
+
if app.mode != "zero" or app.has_temp_component_dependency(tag_name):
|
82
|
+
return
|
83
|
+
|
84
|
+
self.update_dependencies(
|
85
|
+
css=[_STYLE], externals=_ZERO_IMPORT_MAPS, replace=True
|
86
|
+
)
|
87
|
+
|
88
|
+
@staticmethod
|
89
|
+
def update_zero_dependency(add_languages: Optional[Iterable[str]] = None):
|
90
|
+
if isinstance(add_languages, str):
|
91
|
+
add_languages = [add_languages]
|
92
|
+
|
93
|
+
for lang in add_languages or []:
|
94
|
+
name = f"{_LANGS_IMPORT_NAME}{lang}.mjs"
|
95
|
+
path = _LANG_DIR / f"{lang}.mjs"
|
96
|
+
_ZERO_IMPORT_MAPS[name] = path
|
97
|
+
|
98
|
+
|
99
|
+
TTransformerNames = Literal["notationDiff"]
|