webwidgets 0.2.1__py3-none-any.whl → 1.0.0__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.
webwidgets/__init__.py CHANGED
@@ -10,6 +10,9 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- __version__ = "0.2.1" # Dynamically set by build backend
13
+ __version__ = "1.0.0" # Dynamically set by build backend
14
14
 
15
15
  from . import compilation
16
+ from . import utility
17
+ from .website import *
18
+ from .widgets import *
@@ -13,6 +13,7 @@
13
13
  import itertools
14
14
  from typing import Callable, Dict, List, Union
15
15
  from webwidgets.compilation.html.html_node import HTMLNode
16
+ from webwidgets.utility.indentation import get_indentation
16
17
  from webwidgets.utility.representation import ReprMixin
17
18
  from webwidgets.utility.validation import validate_css_identifier
18
19
 
@@ -74,7 +75,7 @@ class CompiledCSS(ReprMixin):
74
75
  """
75
76
  # Initializing code and defining indentation
76
77
  css_code = ""
77
- indentation = ' ' * indent_size
78
+ indentation = get_indentation(level=1, size=indent_size)
78
79
 
79
80
  # Writing down each rule
80
81
  for i, rule in enumerate(self.rules):
@@ -157,8 +158,8 @@ def compile_css(trees: Union[HTMLNode, List[HTMLNode]],
157
158
  # Handling default rule_namer
158
159
  rule_namer = default_rule_namer if rule_namer is None else rule_namer
159
160
 
160
- # For now, we just return a simple mapping where each CSS property defines
161
- # its own ruleset
161
+ # We compute a simple mapping where each CSS property defines its own
162
+ # ruleset
162
163
  styles = {k: v for tree in trees for k, v in tree.get_styles().items()}
163
164
  properties = set(itertools.chain.from_iterable(s.items()
164
165
  for s in styles.values()))
@@ -10,5 +10,6 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- from .html_node import HTMLNode, no_start_tag, no_end_tag, one_line, RawText
13
+ from .html_node import HTMLNode, no_start_tag, no_end_tag, one_line, RawText, \
14
+ RootNode
14
15
  from .html_tags import TextNode
@@ -13,6 +13,7 @@
13
13
  import copy
14
14
  import itertools
15
15
  from typing import Any, Dict, List, Union
16
+ from webwidgets.utility.indentation import get_indentation
16
17
  from webwidgets.utility.representation import ReprMixin
17
18
  from webwidgets.utility.sanitizing import sanitize_html_text
18
19
  from webwidgets.utility.validation import validate_html_class
@@ -53,11 +54,13 @@ class HTMLNode(ReprMixin):
53
54
  def _render_attributes(self) -> str:
54
55
  """Renders the attributes of the HTML node into a string that can be added to the start tag.
55
56
 
57
+ Attributes are sorted alphabetically by name.
58
+
56
59
  :return: A string containing all attribute key-value pairs separated by spaces.
57
60
  :rtype: str
58
61
  """
59
62
  return ' '.join(
60
- f'{key}="{value}"' for key, value in self.attributes.items()
63
+ f'{k}="{v}"' for k, v in sorted(self.attributes.items())
61
64
  )
62
65
 
63
66
  def add(self, child: 'HTMLNode') -> None:
@@ -136,7 +139,14 @@ class HTMLNode(ReprMixin):
136
139
  :type collapse_empty: bool
137
140
  :param indent_size: The number of spaces to use for each indentation level.
138
141
  :type indent_size: int
139
- :param indent_level: The current level of indentation in the HTML output.
142
+ :param indent_level: The current level of indentation in the HTML
143
+ output.
144
+
145
+ This argument supports negative values as a way to flatten the HTML
146
+ output down to a certain depth with indentation resuming as normal
147
+ afterwards. If negative, `indent_level` is construed as an offset
148
+ on the depth in the HTML tree represented by the node, in which
149
+ case the node will wait for that depth before starting indentation.
140
150
  :type indent_level: int
141
151
  :param force_one_line: If True, forces all child elements to be rendered on a single line without additional
142
152
  indentation. Defaults to False.
@@ -151,7 +161,8 @@ class HTMLNode(ReprMixin):
151
161
  :rtype: str or List[str]
152
162
  """
153
163
  # Opening the element
154
- indentation = "" if force_one_line else ' ' * indent_size * indent_level
164
+ indentation = "" if force_one_line else get_indentation(
165
+ indent_level, indent_size)
155
166
  html_lines = [indentation + self.start_tag]
156
167
 
157
168
  # If content must be in one line
@@ -264,7 +275,34 @@ class RawText(HTMLNode):
264
275
  """
265
276
  sanitized = sanitize_html_text(
266
277
  self.text, replace_all_entities=replace_all_entities)
267
- line = ' ' * indent_size * indent_level + sanitized
278
+ line = get_indentation(indent_level, indent_size) + sanitized
268
279
  if return_lines:
269
280
  return [line]
270
281
  return line
282
+
283
+
284
+ @no_start_tag
285
+ @no_end_tag
286
+ class RootNode(HTMLNode):
287
+ """The root node of an HTML document.
288
+
289
+ This is the top-level node that contains all other nodes.
290
+ """
291
+
292
+ def to_html(self, indent_level: int = 0, **kwargs: Any) -> Union[str, List[str]]:
293
+ """Converts the root node to HTML code.
294
+
295
+ This method overrides :py:meth:`HTMLNode.to_html`. The only difference
296
+ between this method and that of the base class is that the indentation
297
+ level is adjusted by one level, so the root node acts as an array of
298
+ elements.
299
+
300
+ :param indent_level: See :py:meth:`HTMLNode.to_html`.
301
+ :type indent_level: int
302
+ :param kwargs: Other keyword arguments. These are passed to
303
+ :py:meth:`HTMLNode.to_html`.
304
+ :type kwargs: Any
305
+ :return: See :py:meth:`HTMLNode.to_html`.
306
+ :type return: str or List[str]
307
+ """
308
+ return super().to_html(indent_level=indent_level - 1, **kwargs)
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- from .html_node import HTMLNode, one_line, RawText
13
+ from .html_node import HTMLNode, no_end_tag, one_line, RawText
14
14
  from typing import Dict
15
15
 
16
16
 
@@ -38,3 +38,40 @@ class TextNode(HTMLNode):
38
38
  super().__init__(children=[
39
39
  RawText(text)
40
40
  ], attributes=attributes, style=style)
41
+
42
+
43
+ class Body(HTMLNode):
44
+ """The `<body>` element containing the visible content of a document."""
45
+ pass
46
+
47
+
48
+ @one_line
49
+ @no_end_tag
50
+ class Doctype(HTMLNode):
51
+ """The `<!DOCTYPE html>` doctype declaration of a document."""
52
+
53
+ def __init__(self):
54
+ """Creates a `<!DOCTYPE html>` doctype declaration element."""
55
+ super().__init__()
56
+
57
+ @property
58
+ def start_tag(self) -> str:
59
+ """Overrides the start tag for this node."""
60
+ return "<!DOCTYPE html>"
61
+
62
+
63
+ class Head(HTMLNode):
64
+ """The `<head>` element containing metadata about a document."""
65
+ pass
66
+
67
+
68
+ class Html(HTMLNode):
69
+ """The `<html>` element of an HTML document."""
70
+ pass
71
+
72
+
73
+ @one_line
74
+ @no_end_tag
75
+ class Link(HTMLNode):
76
+ """A `<link>` element for linking to external resources."""
77
+ pass
@@ -10,6 +10,7 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
+ from .indentation import *
13
14
  from .representation import *
14
15
  from .sanitizing import *
15
16
  from .validation import *
@@ -0,0 +1,25 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ def get_indentation(level: int, size: int = 4) -> str:
14
+ """Returns an indentation string for the given level.
15
+
16
+ :param level: The level of indentation. If negative, this
17
+ function will return an empty string representing no indentation.
18
+ :type level: int
19
+ :param size: The number of spaces to use for each indentation level.
20
+ Defaults to 4 spaces.
21
+ :type size: int
22
+ :return: A string representing the indentation.
23
+ :rtype: str
24
+ """
25
+ return ' ' * (max(level, 0) * size)
@@ -0,0 +1,14 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from .compiled_website import CompiledWebsite
14
+ from .website import Website
@@ -0,0 +1,34 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from typing import List
14
+ from webwidgets.utility.representation import ReprMixin
15
+
16
+
17
+ class CompiledWebsite(ReprMixin):
18
+ """A utility class to store compiled HTML and CSS code obtained from a
19
+ :py:class:`Website` object.
20
+ """
21
+
22
+ def __init__(self, html_content: List[str], css_content: str):
23
+ """Stores compiled HTML and CSS content.
24
+
25
+ :param html_content: The compiled HTML code of each page in the
26
+ website.
27
+ :type html_content: List[str]
28
+ :param css_content: The compiled CSS code of the website, shared across
29
+ all pages.
30
+ :type css_content: str
31
+ """
32
+ super().__init__()
33
+ self.html_content = html_content
34
+ self.css_content = css_content
@@ -0,0 +1,88 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from .compiled_website import CompiledWebsite
14
+ from typing import Any, Callable, List
15
+ from webwidgets.compilation.css import compile_css, CSSRule, apply_css
16
+ from webwidgets.utility.representation import ReprMixin
17
+ from webwidgets.widgets.containers.page import Page
18
+
19
+
20
+ class Website(ReprMixin):
21
+ """A collection of :py:class:`Page` objects that make up the structure of a
22
+ web site."""
23
+
24
+ def __init__(self, pages: List[Page] = None):
25
+ """Creates a new website with an optional list of pages.
26
+
27
+ :param pages: The pages of the website. Defaults to an empty list.
28
+ :type pages: List[Page]
29
+ """
30
+ super().__init__()
31
+ self.pages = [] if pages is None else pages
32
+
33
+ def add(self, page: Page):
34
+ """Adds a new page to the website.
35
+
36
+ :param page: The page to be added.
37
+ :type page: Page
38
+ """
39
+ self.pages.append(page)
40
+
41
+ def compile(self,
42
+ collapse_empty: bool = True,
43
+ css_file_name: str = "styles.css",
44
+ force_one_line: bool = False,
45
+ indent_level: int = 0,
46
+ indent_size: int = 4,
47
+ rule_namer: Callable[[List[CSSRule], int], str] = None,
48
+ **kwargs: Any) -> CompiledWebsite:
49
+ """Compiles the website into HTML and CSS code.
50
+
51
+ :param collapse_empty: See :py:meth:`HTMLNode.to_html`.
52
+ :type collapse_empty: bool
53
+ :param css_file_name: See :py:meth:`Page.build`.
54
+ :type css_file_name: str
55
+ :param force_one_line: See :py:meth:`HTMLNode.to_html`.
56
+ :type force_one_line: bool
57
+ :param indent_level: See :py:meth:`HTMLNode.to_html`.
58
+ :type indent_level: int
59
+ :param indent_size: See :py:meth:`HTMLNode.to_html` and
60
+ :py:meth:`CompiledCSS.to_css`.
61
+ :type indent_size: int
62
+ :param rule_namer: See :py:func:`compile_css`.
63
+ :type rule_namer: Callable[[List[CSSRule], int], str]
64
+ :param kwargs: See :py:meth:`HTMLNode.to_html`.
65
+ :type kwargs: Any
66
+ :return: A new :py:class:`CompiledWebsite` object containing the
67
+ compiled HTML and CSS code.
68
+ :rtype: CompiledWebsite
69
+ """
70
+ # Building the HTML representation of each page
71
+ trees = [page.build(css_file_name=css_file_name)
72
+ for page in self.pages]
73
+
74
+ # Compiling HTML and CSS code
75
+ compiled_css = compile_css(trees, rule_namer)
76
+ for tree in trees:
77
+ apply_css(compiled_css, tree)
78
+ html_content = [tree.to_html(
79
+ collapse_empty=collapse_empty,
80
+ force_one_line=force_one_line,
81
+ indent_level=indent_level,
82
+ indent_size=indent_size,
83
+ **kwargs
84
+ ) for tree in trees]
85
+ css_content = compiled_css.to_css(indent_size=indent_size)
86
+
87
+ # Storing the result in a new CompiledWebsite object
88
+ return CompiledWebsite(html_content, css_content)
@@ -0,0 +1,14 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from .containers import *
14
+ from .widget import Widget
@@ -0,0 +1,14 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from .container import Container
14
+ from .page import Page
@@ -0,0 +1,38 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from typing import List
14
+ from webwidgets.widgets.widget import Widget
15
+
16
+
17
+ class Container(Widget):
18
+ """
19
+ A widget that can contain other widgets.
20
+ """
21
+
22
+ def __init__(self, widgets: List[Widget] = None):
23
+ """Creates a new Container with optional widgets inside.
24
+
25
+ :param widgets: A list of widgets to be contained within the container.
26
+ Defaults to an empty list.
27
+ :type widgets: List[Widget]
28
+ """
29
+ super().__init__()
30
+ self.widgets = [] if widgets is None else widgets
31
+
32
+ def add(self, widget: Widget) -> None:
33
+ """Adds a widget to the container.
34
+
35
+ :param widget: The widget to add to the container.
36
+ :type widget: Widget
37
+ """
38
+ self.widgets.append(widget)
@@ -0,0 +1,59 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from .container import Container
14
+ from webwidgets.compilation.html.html_node import RootNode
15
+ from webwidgets.compilation.html.html_tags import Body, Doctype, Head, Html, \
16
+ Link
17
+
18
+
19
+ class Page(Container):
20
+ """A widget representing a web page. It contains other widgets and is
21
+ responsible for laying them out within the page.
22
+ """
23
+
24
+ def build(self, css_file_name: str = "styles.css") -> RootNode:
25
+ """Builds the HTML representation of the page.
26
+
27
+ This method constructs an HTML structure that includes a doctype
28
+ declaration, a head section with meta tags, and a body section
29
+ containing the widgets. The widgets are rendered recurisvely by calling
30
+ their :py:meth:`build` method.
31
+
32
+ :param css_file_name: The name of the CSS file to link to the page if
33
+ the page elements contain any styles. Defaults to "styles.css".
34
+ :type css_file_name: str
35
+ :return: An :py:class:`RootNode` object representing the page.
36
+ :rtype: RootNode
37
+ """
38
+ # Building nodes from the page's widgets
39
+ nodes = [w.build() for w in self.widgets]
40
+
41
+ # Initializing the head section of the page
42
+ head = Head()
43
+
44
+ # Checking if there is any style sheet to link to the page.
45
+ # To do so, we just check if any child node has a non-empty style.
46
+ if any(style for n in nodes for style in n.get_styles().values()):
47
+ head.add(Link(
48
+ attributes={"href": css_file_name, "rel": "stylesheet"}
49
+ ))
50
+
51
+ # Building the HTML representation of the page
52
+ return RootNode(
53
+ children=[
54
+ Doctype(),
55
+ Html(
56
+ children=[head, Body(children=nodes)]
57
+ )
58
+ ]
59
+ )
@@ -0,0 +1,34 @@
1
+ # =======================================================================
2
+ #
3
+ # This file is part of WebWidgets, a Python package for designing web
4
+ # UIs.
5
+ #
6
+ # You should have received a copy of the MIT License along with
7
+ # WebWidgets. If not, see <https://opensource.org/license/mit>.
8
+ #
9
+ # Copyright(C) 2025, mlaasri
10
+ #
11
+ # =======================================================================
12
+
13
+ from abc import ABC, abstractmethod
14
+ from webwidgets.compilation.html.html_node import HTMLNode
15
+ from webwidgets.utility.representation import ReprMixin
16
+
17
+
18
+ class Widget(ABC, ReprMixin):
19
+ """
20
+ Abstract base class for all widgets.
21
+
22
+ All subclasses of :py:class:`Widget` must implement a :py:meth:`build`
23
+ method that returns an :py:class:`HTMLNode` object.
24
+ """
25
+
26
+ @abstractmethod
27
+ def build(self) -> HTMLNode:
28
+ """Builds the widget and returns the corresponding :py:class:`HTMLNode`
29
+ object.
30
+
31
+ This method must be overridden by subclasses to create specific HTML
32
+ elements.
33
+ """
34
+ pass
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: webwidgets
3
+ Version: 1.0.0
4
+ Summary: A Python package for designing web UIs.
5
+ Project-URL: Source code, https://github.com/mlaasri/WebWidgets
6
+ Author: mlaasri
7
+ License-File: LICENSE
8
+ Keywords: design,webui
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+
14
+ # WebWidgets
15
+
16
+ ![CI Status](https://img.shields.io/github/actions/workflow/status/mlaasri/WebWidgets/ci-full.yml?branch=main)
17
+
18
+ A Python package for creating web UIs
19
+
20
+ ## Installation
21
+
22
+ You can install **WebWidgets** with `pip`. To install the latest stable version, run:
23
+
24
+ ```bash
25
+ pip install webwidgets
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ **WebWidgets** allows you to create custom widgets and build websites with them. For example:
31
+
32
+ ```python
33
+ import webwidgets as ww
34
+ from webwidgets.compilation.html import HTMLNode, RawText
35
+
36
+ # A <div> element
37
+ class Div(HTMLNode):
38
+ pass
39
+
40
+ # A simple text widget
41
+ class Text(ww.Widget):
42
+ def build(self):
43
+ return Div([RawText("Hello, World!")])
44
+
45
+ # A website with one page containing a Text widget
46
+ page = ww.Page([Text()])
47
+ website = ww.Website([page])
48
+
49
+ # Compile the website into HTML code
50
+ compiled = website.compile()
51
+ print(compiled.html_content[0])
52
+ ```
53
+
54
+ Prints the following result:
55
+
56
+ ```console
57
+ <!DOCTYPE html>
58
+ <html>
59
+ <head></head>
60
+ <body>
61
+ <div>
62
+ Hello, World!
63
+ </div>
64
+ </body>
65
+ </html>
66
+ ```
@@ -0,0 +1,24 @@
1
+ webwidgets/__init__.py,sha256=IZAAOuEwU_cC_oy0dJ2WSw9wXnwrLyZ4mqszBPma7MA,549
2
+ webwidgets/compilation/__init__.py,sha256=hb61nhmPTghIzuA_hun98xT5Ngv7QFAgMHD44g-9uOo,433
3
+ webwidgets/compilation/css/__init__.py,sha256=ZisiFaw9RqNuVqewOjnEOLLLZwgjfW95yruMXGRGp_I,484
4
+ webwidgets/compilation/css/css.py,sha256=93WuxY-ADUDK_cBuGS-hUuV4HctZjtaG3cqeoE4S3oQ,9725
5
+ webwidgets/compilation/html/__init__.py,sha256=iupXt6punHDLAFdygshmQeFVOLCeZ8HbwCWclL1FH54,521
6
+ webwidgets/compilation/html/html_node.py,sha256=lOf1LEoVx23teWHfdlt5IpSv14cE6EI-aDyFGC_BXSU,11697
7
+ webwidgets/compilation/html/html_tags.py,sha256=tFc5P6_rqyetFXJKlxt8n_IhBD758LHPql9peU9__6o,2188
8
+ webwidgets/utility/__init__.py,sha256=Sl-dzpPPTHykkmLSfobhqHmlzUSPtvhaR4xtJy_tiOg,505
9
+ webwidgets/utility/indentation.py,sha256=BaOQRqWdG7T5k_g1-ia9jewPFZjD3afjZH_Fc4NSVwo,906
10
+ webwidgets/utility/representation.py,sha256=lQ15v_DZOHBQKLM8pzRE1tuJkU_modhPTpWpSJ2lBCE,1061
11
+ webwidgets/utility/sanitizing.py,sha256=OKJRDqk-OXYCWeK6ie3GdfQvb49wTs93kd971mg5oK0,5770
12
+ webwidgets/utility/validation.py,sha256=bUjpiGP59GW3DPvQ1hwR5ezBMmcSd6v4xlDLwTHZv_A,4261
13
+ webwidgets/website/__init__.py,sha256=zp4N3CtY0SLNfDV9p2Y0tqbta-vFOX1PSJr7eQ9rQdk,471
14
+ webwidgets/website/compiled_website.py,sha256=lR_sabYtdWiRWicyxEFs4yxRUB_TbMowpsNz3CtqQBQ,1129
15
+ webwidgets/website/website.py,sha256=a5Qmm4DOIYMXHoBDyKzB6Ex2kaPFCSPgodF7LAVyrPE,3339
16
+ webwidgets/widgets/__init__.py,sha256=J2br7F-16URKvWshkJcc4nth27YQsaLrdVZu0xXx5CU,449
17
+ webwidgets/widgets/widget.py,sha256=8ZRcVmmtjQzeA_uGZi10H4XvqgGEtGmr9275FId8zt0,1039
18
+ webwidgets/widgets/containers/__init__.py,sha256=6LPlYaxXiMgC5YPHhi0HLhn7iCeh_5IFY70mv7a-wSA,452
19
+ webwidgets/widgets/containers/container.py,sha256=blpO2y9IiZ_4opwe9pqsSJPAZEN1P_ZRK4a27NpnMrg,1158
20
+ webwidgets/widgets/containers/page.py,sha256=sJ8QDmZ_6jzRFt4lyiAEPwjPvDTKm8EWOjz_Tq_cdjU,2180
21
+ webwidgets-1.0.0.dist-info/METADATA,sha256=DHfGCHdolxBicrkQjAzWGm_B7d_SgY2OnwZ261tSxUk,1434
22
+ webwidgets-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ webwidgets-1.0.0.dist-info/licenses/LICENSE,sha256=LISw1mw5eK6i8adFSlx6zltZxrJFwurngVdZAEU8g_I,1064
24
+ webwidgets-1.0.0.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: webwidgets
3
- Version: 0.2.1
4
- Summary: A Python package for designing web UIs.
5
- Project-URL: Source code, https://github.com/mlaasri/WebWidgets
6
- Author: mlaasri
7
- License-File: LICENSE
8
- Keywords: design,webui
9
- Classifier: Operating System :: OS Independent
10
- Classifier: Programming Language :: Python :: 3
11
- Requires-Python: >=3.9
12
- Description-Content-Type: text/markdown
13
-
14
- # WebWidgets
15
-
16
- ![CI Status](https://img.shields.io/github/actions/workflow/status/mlaasri/WebWidgets/ci-full.yml?branch=main)
17
-
18
- A Python package for creating web UIs
@@ -1,15 +0,0 @@
1
- webwidgets/__init__.py,sha256=lWweaTCcPhSUa2zi5l7UnoDSgup_q81dh0pn_kGYYT0,481
2
- webwidgets/compilation/__init__.py,sha256=hb61nhmPTghIzuA_hun98xT5Ngv7QFAgMHD44g-9uOo,433
3
- webwidgets/compilation/css/__init__.py,sha256=ZisiFaw9RqNuVqewOjnEOLLLZwgjfW95yruMXGRGp_I,484
4
- webwidgets/compilation/css/css.py,sha256=msFTyuIjEvLTKk4H-tvvr9HK1K6N-_hcF1pmOJWT1S8,9654
5
- webwidgets/compilation/html/__init__.py,sha256=NRccbCUKdhmK51MnYFO8q1sS8fWhAggRnMiGDG7lQMQ,505
6
- webwidgets/compilation/html/html_node.py,sha256=QptDwSD2ljzR5S-r5rXuRBeOz8EF55OlZlWTXgQzI4Y,10189
7
- webwidgets/compilation/html/html_tags.py,sha256=U2HmhLkV6BOqTmgvIMlmMCQysQ7i2nEAVWJzZe74ucA,1388
8
- webwidgets/utility/__init__.py,sha256=nY-j5tu45qGl09lRyMyxkT4zsUf2jCfeXWcx954yIvM,478
9
- webwidgets/utility/representation.py,sha256=lQ15v_DZOHBQKLM8pzRE1tuJkU_modhPTpWpSJ2lBCE,1061
10
- webwidgets/utility/sanitizing.py,sha256=OKJRDqk-OXYCWeK6ie3GdfQvb49wTs93kd971mg5oK0,5770
11
- webwidgets/utility/validation.py,sha256=bUjpiGP59GW3DPvQ1hwR5ezBMmcSd6v4xlDLwTHZv_A,4261
12
- webwidgets-0.2.1.dist-info/METADATA,sha256=Adl61Eg47Lw7AuZ5sJN_9-MMumjgsEVFZ33glOceGUk,550
13
- webwidgets-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- webwidgets-0.2.1.dist-info/licenses/LICENSE,sha256=LISw1mw5eK6i8adFSlx6zltZxrJFwurngVdZAEU8g_I,1064
15
- webwidgets-0.2.1.dist-info/RECORD,,