reflex-components-markdown 0.9.0a1__tar.gz

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.
@@ -0,0 +1,24 @@
1
+ **/.DS_Store
2
+ **/*.pyc
3
+ assets/external/*
4
+ dist/*
5
+ examples/
6
+ .web
7
+ .states
8
+ .idea
9
+ .vscode
10
+ .coverage
11
+ .coverage.*
12
+ .venv
13
+ venv
14
+ requirements.txt
15
+ .pyi_generator_last_run
16
+ .pyi_generator_diff
17
+ reflex.db
18
+ .codspeed
19
+ .env
20
+ .env.*
21
+ node_modules
22
+ package-lock.json
23
+ *.pyi
24
+ .pre-commit-config.yaml
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: reflex-components-markdown
3
+ Version: 0.9.0a1
4
+ Summary: Reflex markdown components.
5
+ Author-email: Khaleel Al-Adhami <khaleel@reflex.dev>
6
+ Maintainer-email: Khaleel Al-Adhami <khaleel@reflex.dev>
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: reflex-components-code
9
+ Requires-Dist: reflex-components-core
10
+ Requires-Dist: reflex-components-radix
11
+ Description-Content-Type: text/markdown
12
+
13
+ # reflex-components-markdown
14
+
15
+ Reflex markdown components.
@@ -0,0 +1,3 @@
1
+ # reflex-components-markdown
2
+
3
+ Reflex markdown components.
@@ -0,0 +1,37 @@
1
+ [project]
2
+ name = "reflex-components-markdown"
3
+ dynamic = ["version"]
4
+ description = "Reflex markdown components."
5
+ readme = "README.md"
6
+ authors = [{ name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" }]
7
+ maintainers = [{ name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" }]
8
+ requires-python = ">=3.10"
9
+ dependencies = [
10
+ "reflex-components-code",
11
+ "reflex-components-core",
12
+ "reflex-components-radix",
13
+ ]
14
+
15
+ [tool.hatch.version]
16
+ source = "uv-dynamic-versioning"
17
+
18
+ [tool.uv-dynamic-versioning]
19
+ pattern-prefix = "reflex-components-markdown-"
20
+ fallback-version = "0.0.0dev0"
21
+
22
+ [tool.hatch.build]
23
+ targets.sdist.artifacts = ["*.pyi"]
24
+ targets.wheel.artifacts = ["*.pyi"]
25
+
26
+ [tool.hatch.build.hooks.reflex-pyi]
27
+ dependencies = [
28
+ "ruff",
29
+ "reflex-base",
30
+ "reflex-components-core",
31
+ "reflex-components-lucide",
32
+ "reflex-components-sonner",
33
+ ]
34
+
35
+ [build-system]
36
+ requires = ["hatchling", "uv-dynamic-versioning", "hatch-reflex-pyi"]
37
+ build-backend = "hatchling.build"
@@ -0,0 +1,3 @@
1
+ """Markdown components."""
2
+
3
+ from .markdown import markdown as markdown
@@ -0,0 +1,585 @@
1
+ """Markdown component."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import textwrap
6
+ from collections.abc import Callable, Sequence
7
+ from functools import lru_cache
8
+ from hashlib import md5
9
+ from types import SimpleNamespace
10
+ from typing import Any
11
+
12
+ from reflex_base.components.component import (
13
+ BaseComponent,
14
+ Component,
15
+ ComponentNamespace,
16
+ CustomComponent,
17
+ field,
18
+ )
19
+ from reflex_base.components.tags.tag import Tag
20
+ from reflex_base.utils import console
21
+ from reflex_base.utils.imports import ImportDict, ImportTypes, ImportVar
22
+ from reflex_base.vars.base import LiteralVar, Var, VarData
23
+ from reflex_base.vars.number import ternary_operation
24
+ from reflex_base.vars.sequence import LiteralArrayVar
25
+ from reflex_components_core.core.markdown_component_map import MarkdownComponentMap
26
+ from reflex_components_core.el.elements.typography import Div
27
+
28
+ # Special vars used in the component map.
29
+ _CHILDREN = Var(_js_expr="children", _var_type=str)
30
+ _PROPS = Var(_js_expr="props")
31
+ _PROPS_SPREAD = Var(_js_expr="...props")
32
+ _REST = Var(_js_expr="rest")
33
+ _REST_SPREAD = Var(_js_expr="...rest")
34
+ _MOCK_ARG = Var(_js_expr="", _var_type=str)
35
+ _LANGUAGE = Var(_js_expr="_language", _var_type=str)
36
+
37
+
38
+ class Plugin(SimpleNamespace):
39
+ """Create new remark/rehype plugin or access pre-wrapped plugins."""
40
+
41
+ @staticmethod
42
+ def create(
43
+ package: str,
44
+ tag: str,
45
+ additional_imports: dict[str, ImportTypes] | None = None,
46
+ **import_var_kwargs,
47
+ ) -> Var:
48
+ """Create a plugin Var.
49
+
50
+ Args:
51
+ package: The package to import the plugin from.
52
+ tag: The imported identifier.
53
+ additional_imports: Additional imports to include in the VarData, such as CSS.
54
+ **import_var_kwargs: Additional kwargs to pass to the ImportVar.
55
+
56
+ Returns:
57
+ The plugin Var.
58
+ """
59
+ import_var_kwargs.setdefault("is_default", True)
60
+ return Var(
61
+ _js_expr=tag,
62
+ _var_data=VarData(
63
+ imports={
64
+ package: ImportVar(
65
+ tag=tag,
66
+ **import_var_kwargs,
67
+ ),
68
+ **(additional_imports or {}),
69
+ }
70
+ ),
71
+ )
72
+
73
+ __call__ = create
74
+
75
+ math = create("remark-math@6.0.0", "remarkMath")
76
+ gfm = create("remark-gfm@4.0.1", "remarkGfm")
77
+ unwrap_images = create("rehype-unwrap-images@1.0.0", "rehypeUnwrapImages")
78
+ katex = create(
79
+ "rehype-katex@7.0.1",
80
+ "rehypeKatex",
81
+ additional_imports={
82
+ "": "katex/dist/katex.min.css",
83
+ },
84
+ )
85
+ raw = create("rehype-raw@7.0.0", "rehypeRaw")
86
+ _undefined = Var(_js_expr="() => undefined")
87
+
88
+
89
+ def _h1(value: object):
90
+ from reflex_components_radix.themes.typography.heading import Heading
91
+
92
+ return Heading.create(value, as_="h1", size="6", margin_y="0.5em")
93
+
94
+
95
+ def _h2(value: object):
96
+ from reflex_components_radix.themes.typography.heading import Heading
97
+
98
+ return Heading.create(value, as_="h2", size="5", margin_y="0.5em")
99
+
100
+
101
+ def _h3(value: object):
102
+ from reflex_components_radix.themes.typography.heading import Heading
103
+
104
+ return Heading.create(value, as_="h3", size="4", margin_y="0.5em")
105
+
106
+
107
+ def _h4(value: object):
108
+ from reflex_components_radix.themes.typography.heading import Heading
109
+
110
+ return Heading.create(value, as_="h4", size="3", margin_y="0.5em")
111
+
112
+
113
+ def _h5(value: object):
114
+ from reflex_components_radix.themes.typography.heading import Heading
115
+
116
+ return Heading.create(value, as_="h5", size="2", margin_y="0.5em")
117
+
118
+
119
+ def _h6(value: object):
120
+ from reflex_components_radix.themes.typography.heading import Heading
121
+
122
+ return Heading.create(value, as_="h6", size="1", margin_y="0.5em")
123
+
124
+
125
+ def _p(value: object):
126
+ from reflex_components_radix.themes.typography.text import Text
127
+
128
+ return Text.create(value, margin_y="1em")
129
+
130
+
131
+ def _ul(value: object):
132
+ from reflex_components_radix.themes.layout.list import UnorderedList
133
+
134
+ return UnorderedList.create(value, margin_y="1em")
135
+
136
+
137
+ def _ol(value: object):
138
+ from reflex_components_radix.themes.layout.list import OrderedList
139
+
140
+ return OrderedList.create(value, margin_y="1em")
141
+
142
+
143
+ def _li(value: object):
144
+ from reflex_components_radix.themes.layout.list import ListItem
145
+
146
+ return ListItem.create(value, margin_y="0.5em")
147
+
148
+
149
+ def _a(value: object):
150
+ from reflex_components_radix.themes.typography.link import Link
151
+
152
+ return Link.create(value)
153
+
154
+
155
+ def _code(value: object):
156
+ from reflex_components_radix.themes.typography.code import Code
157
+
158
+ return Code.create(value)
159
+
160
+
161
+ def _codeblock(value: object, **props):
162
+ from reflex_components_code.code import CodeBlock
163
+
164
+ return CodeBlock.create(value, margin_y="1em", wrap_long_lines=True, **props)
165
+
166
+
167
+ # Component Mapping
168
+ @lru_cache
169
+ def get_base_component_map() -> dict[str, Callable]:
170
+ """Get the base component map.
171
+
172
+ Returns:
173
+ The base component map.
174
+ """
175
+ return {
176
+ "h1": _h1,
177
+ "h2": _h2,
178
+ "h3": _h3,
179
+ "h4": _h4,
180
+ "h5": _h5,
181
+ "h6": _h6,
182
+ "p": _p,
183
+ "ul": _ul,
184
+ "ol": _ol,
185
+ "li": _li,
186
+ "a": _a,
187
+ "code": _code,
188
+ "pre": _codeblock,
189
+ }
190
+
191
+
192
+ class Markdown(Component):
193
+ """A markdown component."""
194
+
195
+ library = "react-markdown@10.1.0"
196
+
197
+ tag = "ReactMarkdown"
198
+
199
+ is_default = True
200
+
201
+ component_map: dict[str, Any] = field(
202
+ doc="The component map from a tag to a lambda that creates a component.",
203
+ default_factory=dict,
204
+ is_javascript_property=False,
205
+ )
206
+
207
+ component_map_hash: str = field(
208
+ doc="The hash of the component map, generated at create() time.",
209
+ default="",
210
+ is_javascript_property=False,
211
+ )
212
+
213
+ remark_plugins: Var[Sequence[Var | tuple[Var, Var]]] = field(
214
+ doc="Remark plugins to use when rendering the content. Provide (plugin, options) if the plugin requires options."
215
+ )
216
+
217
+ rehype_plugins: Var[Sequence[Var | tuple[Var, Var]]] = field(
218
+ doc="Rehype (HTML processor) plugins to use when rendering the content. Provide (plugin, options) if the plugin requires options."
219
+ )
220
+
221
+ @classmethod
222
+ def create(
223
+ cls,
224
+ *children,
225
+ **props,
226
+ ) -> Component:
227
+ """Create a markdown component.
228
+
229
+ Args:
230
+ *children: The children of the component.
231
+ **props: The properties of the component.
232
+
233
+ Returns:
234
+ The markdown component.
235
+
236
+ Raises:
237
+ ValueError: If the children are not valid.
238
+ """
239
+ if len(children) != 1 or not isinstance(children[0], (str, Var)):
240
+ msg = "Markdown component must have exactly one child containing the markdown source."
241
+ raise ValueError(msg)
242
+
243
+ # Update the base component map with the custom component map.
244
+ component_map = {**get_base_component_map(), **props.pop("component_map", {})}
245
+ if "codeblock" in component_map:
246
+ console.deprecate(
247
+ feature_name="'codeblock' in component_map",
248
+ reason="Use 'pre' instead of 'codeblock' to customize code block rendering in markdown",
249
+ deprecation_version="0.8.25",
250
+ removal_version="0.9.0",
251
+ )
252
+ component_map["pre"] = component_map.pop("codeblock")
253
+
254
+ # Get the markdown source.
255
+ src = children[0]
256
+
257
+ # Dedent the source.
258
+ if isinstance(src, str):
259
+ src = textwrap.dedent(src)
260
+
261
+ # Create the component.
262
+ return super().create(
263
+ src,
264
+ component_map=component_map,
265
+ component_map_hash=cls._component_map_hash(component_map),
266
+ **props,
267
+ )
268
+
269
+ def add_imports(self) -> ImportDict | list[ImportDict]:
270
+ """Add imports for the markdown component.
271
+
272
+ Returns:
273
+ The imports for the markdown component.
274
+ """
275
+ return [
276
+ *[
277
+ component(_MOCK_ARG)._get_all_imports()
278
+ for component in self.component_map.values()
279
+ ],
280
+ *(
281
+ [codeblock_var_data.old_school_imports()]
282
+ if (
283
+ codeblock_var_data
284
+ := self._get_codeblock_fn_var()._get_all_var_data()
285
+ )
286
+ is not None
287
+ else []
288
+ ),
289
+ ]
290
+
291
+ def _get_tag_map_fn_var(self, tag: str) -> Var:
292
+ return self._get_map_fn_var_from_children(self.get_component(tag), tag)
293
+
294
+ def format_component_map(self) -> dict[str, Var]:
295
+ """Format the component map for rendering.
296
+
297
+ Returns:
298
+ The formatted component map.
299
+ """
300
+ components = {
301
+ tag: self._get_tag_map_fn_var(tag)
302
+ for tag in self.component_map
303
+ if tag != "pre"
304
+ }
305
+
306
+ # Special handling for code blocks to extract the language.
307
+ components["pre"] = self._get_codeblock_fn_var()
308
+
309
+ return components
310
+
311
+ def _get_codeblock_fn_var(self) -> Var:
312
+ """Get the function variable for codeblock.
313
+
314
+ This function creates a Var that represents a function to handle
315
+ both code blocks in markdown.
316
+
317
+ Returns:
318
+ The Var for pre code.
319
+ """
320
+ # Get any custom code from the code block "pre" component.
321
+ custom_code_list = self._get_map_fn_custom_code_from_children(
322
+ self.get_component("pre")
323
+ )
324
+ var_data = VarData.merge(*[
325
+ code._get_all_var_data()
326
+ for code in custom_code_list
327
+ if isinstance(code, Var)
328
+ ])
329
+ codeblock_custom_code = "\n".join(map(str, custom_code_list))
330
+
331
+ # Format the code to handle code block with language extraction.
332
+ formatted_code = f"""
333
+ const {{node: childNode, className, children: components, {_PROPS_SPREAD._js_expr}}} = {_REST._js_expr}.children.props;
334
+ const {_CHILDREN._js_expr} = String(Array.isArray(components) ? components.join('\\n') : components).replace(/\\n$/, '');
335
+ const match = (className || '').match(/language-(?<lang>.*)/);
336
+ let {_LANGUAGE!s} = match ? match[1] : '';
337
+ {codeblock_custom_code};
338
+ return {self.format_component("pre", language=_LANGUAGE)};
339
+ """.replace("\n", " ")
340
+
341
+ return MarkdownComponentMap.create_map_fn_var(
342
+ fn_body=Var(_js_expr=formatted_code),
343
+ fn_args=["node", _REST_SPREAD._js_expr],
344
+ explicit_return=True,
345
+ var_data=var_data,
346
+ )
347
+
348
+ def get_component(self, tag: str, **props) -> Component:
349
+ """Get the component for a tag and props.
350
+
351
+ Args:
352
+ tag: The tag of the component.
353
+ **props: The props of the component.
354
+
355
+ Returns:
356
+ The component.
357
+
358
+ Raises:
359
+ ValueError: If the tag is invalid.
360
+ """
361
+ # Check the tag is valid.
362
+ if tag not in self.component_map:
363
+ msg = f"No markdown component found for tag: {tag}."
364
+ raise ValueError(msg)
365
+
366
+ # If the children are set as a prop, don't pass them as children.
367
+ children = [_CHILDREN] if props.get("children") is None else []
368
+ # Get the component.
369
+ return self.component_map[tag](*children, **props).set(special_props=[_PROPS])
370
+
371
+ def format_component(self, tag: str, **props) -> str:
372
+ """Format a component for rendering in the component map.
373
+
374
+ Args:
375
+ tag: The tag of the component.
376
+ **props: Extra props to pass to the component function.
377
+
378
+ Returns:
379
+ The formatted component.
380
+ """
381
+ return str(self.get_component(tag, **props)).replace("\n", "")
382
+
383
+ def _get_map_fn_var_from_children(self, component: Component, tag: str) -> Var:
384
+ """Create a function Var for the component map for the specified tag.
385
+
386
+ Args:
387
+ component: The component to check for custom code.
388
+ tag: The tag of the component.
389
+
390
+ Returns:
391
+ The function Var for the component map.
392
+ """
393
+ formatted_component = Var(
394
+ _js_expr=f"({self.format_component(tag)})", _var_type=str
395
+ )
396
+ if isinstance(component, MarkdownComponentMap):
397
+ return component.create_map_fn_var(fn_body=formatted_component)
398
+
399
+ # fallback to the default fn Var creation if the component is not a MarkdownComponentMap.
400
+ return MarkdownComponentMap.create_map_fn_var(fn_body=formatted_component)
401
+
402
+ def _get_map_fn_custom_code_from_children(
403
+ self, component: BaseComponent
404
+ ) -> list[str | Var]:
405
+ """Recursively get markdown custom code from children components.
406
+
407
+ Args:
408
+ component: The component to check for custom code.
409
+
410
+ Returns:
411
+ A list of markdown custom code strings.
412
+ """
413
+ custom_code_list: list[str | Var] = []
414
+ if isinstance(component, MarkdownComponentMap):
415
+ custom_code_list.append(component.get_component_map_custom_code())
416
+
417
+ # If the component is a custom component(rx.memo), obtain the underlining
418
+ # component and get the custom code from the children.
419
+ if isinstance(component, CustomComponent):
420
+ custom_code_list.extend(
421
+ self._get_map_fn_custom_code_from_children(
422
+ component.component_fn(*component.get_prop_vars())
423
+ )
424
+ )
425
+ elif isinstance(component, Component):
426
+ for child in component.children:
427
+ custom_code_list.extend(
428
+ self._get_map_fn_custom_code_from_children(child)
429
+ )
430
+
431
+ return custom_code_list
432
+
433
+ @staticmethod
434
+ def _component_map_hash(component_map: dict) -> str:
435
+ inp = str({
436
+ tag: (
437
+ f"{component.__module__}.{component.__qualname__}"
438
+ if (
439
+ "<" not in component.__name__
440
+ ) # simple way to check against lambdas
441
+ else component(_MOCK_ARG)
442
+ )
443
+ for tag, component in component_map.items()
444
+ }).encode()
445
+ return md5(inp).hexdigest()
446
+
447
+ def _get_component_map_name(self) -> str:
448
+ return f"ComponentMap_{self.component_map_hash}"
449
+
450
+ def _get_custom_code(self) -> str | None:
451
+ hooks = {}
452
+ from reflex_base.compiler.templates import _render_hooks
453
+
454
+ for component_factory in self.component_map.values():
455
+ comp = component_factory(_MOCK_ARG)
456
+ hooks.update(comp._get_all_hooks())
457
+ formatted_hooks = _render_hooks(hooks)
458
+ return f"""
459
+ function {self._get_component_map_name()} () {{
460
+ {formatted_hooks}
461
+ return (
462
+ {LiteralVar.create(self.format_component_map())!s}
463
+ )
464
+ }}
465
+ """
466
+
467
+ def _render(self) -> Tag:
468
+ return (
469
+ super()
470
+ ._render()
471
+ .add_props(
472
+ components=Var(_js_expr=f"{self._get_component_map_name()}()"),
473
+ )
474
+ .remove_props("componentMap", "componentMapHash")
475
+ )
476
+
477
+
478
+ class MarkdownWrapper(Div):
479
+ """A markdown component, with optional div-wrapping when style props are given."""
480
+
481
+ @classmethod
482
+ def create(
483
+ cls,
484
+ *children,
485
+ use_math: bool | Var[bool] = True,
486
+ use_gfm: bool | Var[bool] = True,
487
+ use_unwrap_images: bool | Var[bool] = True,
488
+ use_katex: bool | Var[bool] = True,
489
+ use_raw: bool | Var[bool] = True,
490
+ **props,
491
+ ) -> Component:
492
+ """Create a markdown component.
493
+
494
+ Args:
495
+ *children: The children of the component.
496
+ use_math: Whether to use the remark-math plugin.
497
+ use_gfm: Whether to use the GitHub Flavored Markdown plugin.
498
+ use_unwrap_images: Whether to use the unwrap images plugin.
499
+ use_katex: Whether to use the KaTeX plugin.
500
+ use_raw: Whether to use the raw HTML plugin.
501
+ **props: The properties of the component.
502
+
503
+ Returns:
504
+ The markdown component or div wrapping markdown component.
505
+
506
+ Raises:
507
+ ValueError: If the children are not valid.
508
+ """
509
+ # Assemble the plugin lists.
510
+ builtin_remark_plugins = []
511
+ if isinstance(use_math, Var):
512
+ builtin_remark_plugins.append(
513
+ ternary_operation(
514
+ use_math, markdown.plugin.math, markdown.plugin._undefined
515
+ )
516
+ )
517
+ elif use_math:
518
+ builtin_remark_plugins.append(markdown.plugin.math)
519
+ if isinstance(use_gfm, Var):
520
+ builtin_remark_plugins.append(
521
+ ternary_operation(
522
+ use_gfm, markdown.plugin.gfm, markdown.plugin._undefined
523
+ )
524
+ )
525
+ elif use_gfm:
526
+ builtin_remark_plugins.append(markdown.plugin.gfm)
527
+ remark_plugins = LiteralArrayVar.create(builtin_remark_plugins)
528
+ if (user_remark_plugins := props.pop("remark_plugins", None)) is not None:
529
+ if not isinstance(user_remark_plugins, Var):
530
+ user_remark_plugins = Var.create(user_remark_plugins)
531
+ remark_plugins = remark_plugins + user_remark_plugins.to(list)
532
+
533
+ builtin_rehype_plugins = []
534
+ if isinstance(use_katex, Var):
535
+ builtin_rehype_plugins.append(
536
+ ternary_operation(
537
+ use_katex, markdown.plugin.katex, markdown.plugin._undefined
538
+ )
539
+ )
540
+ elif use_katex:
541
+ builtin_rehype_plugins.append(markdown.plugin.katex)
542
+ if isinstance(use_raw, Var):
543
+ builtin_rehype_plugins.append(
544
+ ternary_operation(
545
+ use_raw, markdown.plugin.raw, markdown.plugin._undefined
546
+ )
547
+ )
548
+ elif use_raw:
549
+ builtin_rehype_plugins.append(markdown.plugin.raw)
550
+ if isinstance(use_unwrap_images, Var):
551
+ builtin_rehype_plugins.append(
552
+ ternary_operation(
553
+ use_unwrap_images,
554
+ markdown.plugin.unwrap_images,
555
+ markdown.plugin._undefined,
556
+ )
557
+ )
558
+ elif use_unwrap_images:
559
+ builtin_rehype_plugins.append(markdown.plugin.unwrap_images)
560
+ rehype_plugins = LiteralArrayVar.create(builtin_rehype_plugins)
561
+ if (user_rehype_plugins := props.pop("rehype_plugins", None)) is not None:
562
+ if not isinstance(user_rehype_plugins, Var):
563
+ user_rehype_plugins = Var.create(user_rehype_plugins)
564
+ rehype_plugins = rehype_plugins + user_rehype_plugins.to(list)
565
+
566
+ return super().create(
567
+ Markdown.create(
568
+ *children,
569
+ component_map=props.pop("component_map", {}),
570
+ remark_plugins=remark_plugins.to(list[Var | tuple[Var, Var]]),
571
+ rehype_plugins=rehype_plugins.to(list[Var | tuple[Var, Var]]),
572
+ ),
573
+ **props,
574
+ )
575
+
576
+
577
+ class MarkdownNamespace(ComponentNamespace):
578
+ """A namespace for markdown components."""
579
+
580
+ __call__ = staticmethod(MarkdownWrapper.create)
581
+ root = staticmethod(Markdown.create)
582
+ plugin = Plugin()
583
+
584
+
585
+ markdown = MarkdownNamespace()
@@ -0,0 +1,243 @@
1
+ """Stub file for reflex_components_markdown/markdown.py"""
2
+
3
+ # ------------------- DO NOT EDIT ----------------------
4
+ # This file was generated by `reflex/utils/pyi_generator.py`!
5
+ # ------------------------------------------------------
6
+ from collections.abc import Callable, Mapping, Sequence
7
+ from functools import lru_cache
8
+ from types import SimpleNamespace
9
+ from typing import Any
10
+
11
+ from reflex_base.components.component import Component, ComponentNamespace
12
+ from reflex_base.event import EventType, PointerEventInfo
13
+ from reflex_base.utils.imports import ImportDict, ImportTypes, ImportVar
14
+ from reflex_base.vars.base import Var
15
+ from reflex_components_core.core.breakpoints import Breakpoints
16
+ from reflex_components_core.el.elements.typography import Div
17
+
18
+ _CHILDREN = Var(_js_expr="children", _var_type=str)
19
+ _PROPS = Var(_js_expr="props")
20
+ _PROPS_SPREAD = Var(_js_expr="...props")
21
+ _REST = Var(_js_expr="rest")
22
+ _REST_SPREAD = Var(_js_expr="...rest")
23
+ _MOCK_ARG = Var(_js_expr="", _var_type=str)
24
+ _LANGUAGE = Var(_js_expr="_language", _var_type=str)
25
+
26
+ class Plugin(SimpleNamespace):
27
+ @staticmethod
28
+ def create(
29
+ package: str,
30
+ tag: str,
31
+ additional_imports: dict[str, ImportTypes] | None = None,
32
+ **import_var_kwargs,
33
+ ) -> Var: ...
34
+ math = create("remark-math@6.0.0", "remarkMath")
35
+ gfm = create("remark-gfm@4.0.1", "remarkGfm")
36
+ unwrap_images = create("rehype-unwrap-images@1.0.0", "rehypeUnwrapImages")
37
+ katex = create(
38
+ "rehype-katex@7.0.1",
39
+ "rehypeKatex",
40
+ additional_imports={"": "katex/dist/katex.min.css"},
41
+ )
42
+ raw = create("rehype-raw@7.0.0", "rehypeRaw")
43
+ _undefined = Var(_js_expr="() => undefined")
44
+
45
+ @staticmethod
46
+ def __call__(
47
+ package: str,
48
+ tag: str,
49
+ additional_imports: dict[
50
+ str, ImportVar | list[ImportVar | str] | list[ImportVar] | str
51
+ ]
52
+ | None = None,
53
+ **props,
54
+ ) -> Var:
55
+ """Create a plugin Var.
56
+
57
+ Args:
58
+ package: The package to import the plugin from.
59
+ tag: The imported identifier.
60
+ additional_imports: Additional imports to include in the VarData, such as CSS.
61
+ **import_var_kwargs: Additional kwargs to pass to the ImportVar.
62
+
63
+ Returns:
64
+ The plugin Var.
65
+ """
66
+
67
+ @lru_cache
68
+ def get_base_component_map() -> dict[str, Callable]: ...
69
+
70
+ class Markdown(Component):
71
+ @classmethod
72
+ def create(
73
+ cls,
74
+ *children,
75
+ component_map: dict[str, Any] | None = None,
76
+ component_map_hash: str | None = None,
77
+ remark_plugins: Sequence[Var | tuple[Var, Var]]
78
+ | Var[Sequence[Var | tuple[Var, Var]]]
79
+ | None = None,
80
+ rehype_plugins: Sequence[Var | tuple[Var, Var]]
81
+ | Var[Sequence[Var | tuple[Var, Var]]]
82
+ | None = None,
83
+ style: Sequence[Mapping[str, Any]]
84
+ | Mapping[str, Any]
85
+ | Var[Mapping[str, Any]]
86
+ | Breakpoints
87
+ | None = None,
88
+ key: Any | None = None,
89
+ id: Any | None = None,
90
+ ref: Var | None = None,
91
+ class_name: Any | None = None,
92
+ custom_attrs: dict[str, Var | Any] | None = None,
93
+ on_blur: EventType[()] | None = None,
94
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
95
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
96
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
97
+ on_focus: EventType[()] | None = None,
98
+ on_mount: EventType[()] | None = None,
99
+ on_mouse_down: EventType[()] | None = None,
100
+ on_mouse_enter: EventType[()] | None = None,
101
+ on_mouse_leave: EventType[()] | None = None,
102
+ on_mouse_move: EventType[()] | None = None,
103
+ on_mouse_out: EventType[()] | None = None,
104
+ on_mouse_over: EventType[()] | None = None,
105
+ on_mouse_up: EventType[()] | None = None,
106
+ on_scroll: EventType[()] | None = None,
107
+ on_scroll_end: EventType[()] | None = None,
108
+ on_unmount: EventType[()] | None = None,
109
+ **props,
110
+ ) -> Markdown:
111
+ """Create a markdown component.
112
+
113
+ Args:
114
+ *children: The children of the component.
115
+ **props: The properties of the component.
116
+
117
+ Returns:
118
+ The markdown component.
119
+
120
+ Raises:
121
+ ValueError: If the children are not valid.
122
+ """
123
+
124
+ def add_imports(self) -> ImportDict | list[ImportDict]: ...
125
+ def format_component_map(self) -> dict[str, Var]: ...
126
+ def get_component(self, tag: str, **props) -> Component: ...
127
+ def format_component(self, tag: str, **props) -> str: ...
128
+
129
+ class MarkdownWrapper(Div):
130
+ @classmethod
131
+ def create(
132
+ cls,
133
+ *children,
134
+ use_math: bool | Var[bool] | bool = True,
135
+ use_gfm: bool | Var[bool] | bool = True,
136
+ use_unwrap_images: bool | Var[bool] | bool = True,
137
+ use_katex: bool | Var[bool] | bool = True,
138
+ use_raw: bool | Var[bool] | bool = True,
139
+ style: Sequence[Mapping[str, Any]]
140
+ | Mapping[str, Any]
141
+ | Var[Mapping[str, Any]]
142
+ | Breakpoints
143
+ | None = None,
144
+ key: Any | None = None,
145
+ id: Any | None = None,
146
+ ref: Var | None = None,
147
+ class_name: Any | None = None,
148
+ custom_attrs: dict[str, Var | Any] | None = None,
149
+ on_blur: EventType[()] | None = None,
150
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
151
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
152
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
153
+ on_focus: EventType[()] | None = None,
154
+ on_mount: EventType[()] | None = None,
155
+ on_mouse_down: EventType[()] | None = None,
156
+ on_mouse_enter: EventType[()] | None = None,
157
+ on_mouse_leave: EventType[()] | None = None,
158
+ on_mouse_move: EventType[()] | None = None,
159
+ on_mouse_out: EventType[()] | None = None,
160
+ on_mouse_over: EventType[()] | None = None,
161
+ on_mouse_up: EventType[()] | None = None,
162
+ on_scroll: EventType[()] | None = None,
163
+ on_scroll_end: EventType[()] | None = None,
164
+ on_unmount: EventType[()] | None = None,
165
+ **props,
166
+ ) -> MarkdownWrapper:
167
+ """Create a markdown component.
168
+
169
+ Args:
170
+ *children: The children of the component.
171
+ use_math: Whether to use the remark-math plugin.
172
+ use_gfm: Whether to use the GitHub Flavored Markdown plugin.
173
+ use_unwrap_images: Whether to use the unwrap images plugin.
174
+ use_katex: Whether to use the KaTeX plugin.
175
+ use_raw: Whether to use the raw HTML plugin.
176
+ **props: The properties of the component.
177
+
178
+ Returns:
179
+ The markdown component or div wrapping markdown component.
180
+
181
+ Raises:
182
+ ValueError: If the children are not valid.
183
+ """
184
+
185
+ class MarkdownNamespace(ComponentNamespace):
186
+ root = staticmethod(Markdown.create)
187
+ plugin = Plugin()
188
+
189
+ @staticmethod
190
+ def __call__(
191
+ *children,
192
+ use_math: bool | Var[bool] | bool = True,
193
+ use_gfm: bool | Var[bool] | bool = True,
194
+ use_unwrap_images: bool | Var[bool] | bool = True,
195
+ use_katex: bool | Var[bool] | bool = True,
196
+ use_raw: bool | Var[bool] | bool = True,
197
+ style: Sequence[Mapping[str, Any]]
198
+ | Mapping[str, Any]
199
+ | Var[Mapping[str, Any]]
200
+ | Breakpoints
201
+ | None = None,
202
+ key: Any | None = None,
203
+ id: Any | None = None,
204
+ ref: Var | None = None,
205
+ class_name: Any | None = None,
206
+ custom_attrs: dict[str, Var | Any] | None = None,
207
+ on_blur: EventType[()] | None = None,
208
+ on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
209
+ on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
210
+ on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
211
+ on_focus: EventType[()] | None = None,
212
+ on_mount: EventType[()] | None = None,
213
+ on_mouse_down: EventType[()] | None = None,
214
+ on_mouse_enter: EventType[()] | None = None,
215
+ on_mouse_leave: EventType[()] | None = None,
216
+ on_mouse_move: EventType[()] | None = None,
217
+ on_mouse_out: EventType[()] | None = None,
218
+ on_mouse_over: EventType[()] | None = None,
219
+ on_mouse_up: EventType[()] | None = None,
220
+ on_scroll: EventType[()] | None = None,
221
+ on_scroll_end: EventType[()] | None = None,
222
+ on_unmount: EventType[()] | None = None,
223
+ **props,
224
+ ) -> MarkdownWrapper:
225
+ """Create a markdown component.
226
+
227
+ Args:
228
+ *children: The children of the component.
229
+ use_math: Whether to use the remark-math plugin.
230
+ use_gfm: Whether to use the GitHub Flavored Markdown plugin.
231
+ use_unwrap_images: Whether to use the unwrap images plugin.
232
+ use_katex: Whether to use the KaTeX plugin.
233
+ use_raw: Whether to use the raw HTML plugin.
234
+ **props: The properties of the component.
235
+
236
+ Returns:
237
+ The markdown component or div wrapping markdown component.
238
+
239
+ Raises:
240
+ ValueError: If the children are not valid.
241
+ """
242
+
243
+ markdown = MarkdownNamespace()