webwidgets 1.1.0__py3-none-any.whl → 1.1.1__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,9 +10,11 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- __version__ = "1.1.0" # Dynamically set by build backend
13
+ __version__ = "1.1.1" # Dynamically set by build backend
14
14
 
15
15
  from . import compilation
16
16
  from . import utility
17
+ from .utility.enums import *
18
+ from .utility.sizes.sizes import *
17
19
  from .website import *
18
20
  from .widgets import *
@@ -170,7 +170,7 @@ def compile_css(trees: Union[HTMLNode, List[HTMLNode]],
170
170
  Every HTML node present in one or more of the input trees is included
171
171
  in the :py:attr:`CompiledCSS.mapping` attribute, even if the node does
172
172
  not have a style. Rules are alphabetically ordered by class name in the
173
- mapping.
173
+ mapping and in the :py:attr:`CompiledCSS.core` rule section.
174
174
  :rtype: CompiledCSS
175
175
  """
176
176
  # Handling case of a single tree
@@ -13,7 +13,8 @@
13
13
  from typing import Dict
14
14
  from webwidgets.utility.indentation import get_indentation
15
15
  from webwidgets.utility.representation import ReprMixin
16
- from webwidgets.utility.validation import validate_css_identifier, validate_css_selector
16
+ from webwidgets.utility.validation import validate_css_identifier, \
17
+ validate_css_selector, validate_css_value
17
18
 
18
19
 
19
20
  class CSSRule(ReprMixin):
@@ -60,6 +61,7 @@ class CSSRule(ReprMixin):
60
61
  css_code = self.selector + " {\n"
61
62
  for property_name, value in self.declarations.items():
62
63
  validate_css_identifier(property_name)
64
+ validate_css_value(value)
63
65
  css_code += f"{indentation}{property_name}: {value};\n"
64
66
  css_code += "}"
65
67
 
@@ -17,9 +17,9 @@ from webwidgets.compilation.css.css_rule import CSSRule
17
17
  class Preamble(RuleSection):
18
18
  """A set of CSS rules that apply globally to all HTML elements.
19
19
 
20
- The CSS preamble serves as a global default for multiple properties. It is
21
- used to define the document's box model and set all margin and padding
22
- values to 0.
20
+ The CSS preamble serves as a global default for multiple properties. For
21
+ example, it defines the document's box model and sets all margin and
22
+ padding values to 0.
23
23
  """
24
24
 
25
25
  def __init__(self):
@@ -33,7 +33,10 @@ class Preamble(RuleSection):
33
33
 
34
34
  # Setting all margin and padding values to 0
35
35
  "margin": "0",
36
- "padding": "0"
36
+ "padding": "0",
37
+
38
+ # Sets the overflow policy to hidden
39
+ "overflow": "hidden"
37
40
  })
38
41
  ],
39
42
  title="Preamble"
@@ -63,6 +63,33 @@ class HTMLNode(ReprMixin):
63
63
  f'{k}="{v}"' for k, v in sorted(self.attributes.items())
64
64
  )
65
65
 
66
+ @property
67
+ def end_tag(self) -> str:
68
+ """Returns the closing tag of the HTML node.
69
+
70
+ :return: A string containing the closing tag of the element.
71
+ :rtype: str
72
+ """
73
+ return f"</{self._get_tag_name()}>"
74
+
75
+ @property
76
+ def start_tag(self) -> str:
77
+ """Returns the opening tag of the HTML node, including any attributes.
78
+
79
+ Attributes are validated with :py:meth:`HTMLNode.validate_attributes`
80
+ before rendering.
81
+
82
+ :return: A string containing the opening tag of the element with its attributes.
83
+ :rtype: str
84
+ """
85
+ # Rendering attributes
86
+ self.validate_attributes()
87
+ attributes = self._render_attributes()
88
+ maybe_space = ' ' if attributes else ''
89
+
90
+ # Building start tag
91
+ return f"<{self._get_tag_name()}{maybe_space}{attributes}>"
92
+
66
93
  def add(self, child: 'HTMLNode') -> None:
67
94
  """Adds a child to the HTML node.
68
95
 
@@ -101,33 +128,6 @@ class HTMLNode(ReprMixin):
101
128
  styles.update(child.get_styles())
102
129
  return styles
103
130
 
104
- @property
105
- def start_tag(self) -> str:
106
- """Returns the opening tag of the HTML node, including any attributes.
107
-
108
- Attributes are validated with :py:meth:`HTMLNode.validate_attributes`
109
- before rendering.
110
-
111
- :return: A string containing the opening tag of the element with its attributes.
112
- :rtype: str
113
- """
114
- # Rendering attributes
115
- self.validate_attributes()
116
- attributes = self._render_attributes()
117
- maybe_space = ' ' if attributes else ''
118
-
119
- # Building start tag
120
- return f"<{self._get_tag_name()}{maybe_space}{attributes}>"
121
-
122
- @property
123
- def end_tag(self) -> str:
124
- """Returns the closing tag of the HTML node.
125
-
126
- :return: A string containing the closing tag of the element.
127
- :rtype: str
128
- """
129
- return f"</{self._get_tag_name()}>"
130
-
131
131
  def to_html(self, collapse_empty: bool = True,
132
132
  indent_size: int = 4, indent_level: int = 0,
133
133
  force_one_line: bool = False, return_lines: bool = False,
@@ -10,7 +10,9 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
+ from .enums import *
13
14
  from .indentation import *
14
15
  from .representation import *
15
16
  from .sanitizing import *
17
+ from .sizes import *
16
18
  from .validation import *
@@ -0,0 +1,18 @@
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 enum import auto, Enum
14
+
15
+
16
+ class Direction(Enum):
17
+ HORIZONTAL = auto()
18
+ VERTICAL = auto()
@@ -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 .size import *
14
+ from .sizes import *
@@ -0,0 +1,92 @@
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 webwidgets.utility.representation import ReprMixin
14
+ from typing import Callable, Type, Union
15
+
16
+
17
+ class Size(ReprMixin):
18
+ """Base class representing a length.
19
+
20
+ Sizes are specified by a numerical value and a CSS unit (e.g. `px`, `%`,
21
+ etc.). The value is provided upon creation and the unit is derived from the
22
+ class name of the :py:class:`Size` object.
23
+ """
24
+
25
+ def __init__(self, value: Union[float, int]):
26
+ """Creates a new :py:class:`Size` object with the given numerical
27
+ value.
28
+
29
+ :param value: The numerical value of the size.
30
+ :type value: Union[float, int]
31
+ """
32
+ self.value = value
33
+
34
+ @property
35
+ def unit(self) -> str:
36
+ """Returns the unit of the size's numerical value.
37
+
38
+ The unit of a size object is the name of its class in lowercase.
39
+
40
+ :return: The unit of the size.
41
+ :rtype: str
42
+ """
43
+ return self.__class__.__name__.lower()
44
+
45
+ def to_css(self) -> str:
46
+ """Compiles and returns the CSS representation of the :py:class:`Size`
47
+ object.
48
+
49
+ The CSS representation is obtained by concatenating the value of the
50
+ size with its unit (e.g. `"10px"`).
51
+
52
+ :return: The CSS representation of the size.
53
+ :rtype: str
54
+ """
55
+ return str(self.value) + self.unit
56
+
57
+
58
+ class AbsoluteSize(Size):
59
+ """A size whose unit is an absolute unit that does not depend on any
60
+ context. Examples include pixels (`"px"`) and centimeters (`"cm"`).
61
+ """
62
+ pass
63
+
64
+
65
+ class RelativeSize(Size):
66
+ """A size whose unit is relative to the size of other elements, such as the
67
+ size of a display or a font. Examples include percentages (`"%"`) and ems
68
+ (`"em"`).
69
+ """
70
+ pass
71
+
72
+
73
+ def with_unit(unit: str) -> Callable[[Type[Size]], Type[Size]]:
74
+ """Returns a decorator to override the unit of a Size subclass with the
75
+ given unit.
76
+
77
+ :param unit: The unit to be used for the Size subclass.
78
+ :type unit: str
79
+ :return: A decorator that overrides the unit of a Size subclass with the
80
+ given unit.
81
+ :rtype: Callable[[Type[Size]], Type[Size]]
82
+ """
83
+ def _decorator(cls):
84
+ """Decorator to override the unit of a Size subclass.
85
+
86
+ :param cls: A subclass of Size whose unit should be overridden.
87
+ :return: The given class with a new unit.
88
+ """
89
+ cls.unit = property(
90
+ lambda _: unit, doc=f"Always returns '{unit}'.")
91
+ return cls
92
+ return _decorator
@@ -0,0 +1,31 @@
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 .size import AbsoluteSize, RelativeSize, with_unit
14
+
15
+
16
+ # Only exposing concrete size classes when using a wildcard import
17
+ __all__ = [
18
+ "Percent",
19
+ "Px"
20
+ ]
21
+
22
+
23
+ @with_unit("%")
24
+ class Percent(RelativeSize):
25
+ """A size expressed in percentage (`"%"`)."""
26
+ pass
27
+
28
+
29
+ class Px(AbsoluteSize):
30
+ """A size expressed in pixels (`"px"`)."""
31
+ pass
@@ -10,7 +10,6 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- from typing import *
14
13
  import re
15
14
 
16
15
 
@@ -22,8 +21,8 @@ SPECIAL_SELECTORS = [
22
21
 
23
22
 
24
23
  def validate_css_comment(comment: str) -> None:
25
- """Validates that the given comment is a valid CSS comment according to the
26
- CSS syntax rules and raises an exception if not.
24
+ """Checks if the given comment is a valid CSS comment according to the CSS
25
+ syntax rules and raises an exception if not.
27
26
 
28
27
  This function just checks that the comment does not contain any closing
29
28
  sequence `*/` as defined in the CSS Syntax Module Level 3, paragraph 4.3.2
@@ -124,6 +123,38 @@ def validate_css_selector(selector: str) -> None:
124
123
  validate_css_identifier(selector[1:])
125
124
 
126
125
 
126
+ def validate_css_value(value: str) -> None:
127
+ """Checks if the given value is a valid CSS property value and raises an
128
+ exception if not.
129
+
130
+ To be valid, the value must only contain:
131
+ - letters (`a-z`, `A-Z`)
132
+ - digits (`0-9`)
133
+ - dots (`.`)
134
+ - spaces (` `)
135
+ - hyphens (`-`)
136
+ - percent characters (`%`)
137
+ - hashtags (`#`)
138
+
139
+ Note that this function imposes stricter rules than the official CSS
140
+ specification - more precisely, than chapter 2 of the CSS Values and Units
141
+ Module Level 3 (see source:
142
+ https://www.w3.org/TR/css-values-3/#value-defs). For example, this function
143
+ does not allow functional notations like `calc()` whereas the specification
144
+ does.
145
+
146
+ :param value: The value to validate as a CSS property value.
147
+ :type value: str
148
+ :raises ValueError: If the value is not a valid CSS property value.
149
+ """
150
+ if not re.match(r'^[a-zA-Z0-9. \-%#]+$', value):
151
+ invalid_chars = re.findall(r'[^a-zA-Z0-9. \-%#]', value)
152
+ raise ValueError("Invalid character(s) in CSS property value "
153
+ f"'{value}': {', '.join(invalid_chars)}\n"
154
+ "Only letters, digits, dots, spaces, hyphens, "
155
+ "percent characters, and hashtags are allowed.")
156
+
157
+
127
158
  def validate_html_class(class_attribute: str) -> None:
128
159
  """Checks if the given HTML class attribute is valid and raises an
129
160
  exception if not.
@@ -10,6 +10,6 @@
10
10
  #
11
11
  # =======================================================================
12
12
 
13
- from .box import Box, Direction
13
+ from .box import Box
14
14
  from .container import Container
15
15
  from .page import Page
@@ -11,13 +11,12 @@
11
11
  # =======================================================================
12
12
 
13
13
  from .container import Container
14
- from enum import auto, Enum
14
+ from dataclasses import dataclass
15
+ from typing import Dict, Union
15
16
  from webwidgets.compilation.html.html_tags import Div
16
-
17
-
18
- class Direction(Enum):
19
- HORIZONTAL = auto()
20
- VERTICAL = auto()
17
+ from webwidgets.utility.enums import Direction
18
+ from webwidgets.utility.sizes.sizes import AbsoluteSize
19
+ from webwidgets.widgets.widget import Widget
21
20
 
22
21
 
23
22
  class Box(Container):
@@ -34,8 +33,42 @@ class Box(Container):
34
33
  """
35
34
  super().__init__()
36
35
  self.direction = direction
36
+ self._properties: Dict[int, BoxItemProperties] = {}
37
+
38
+ def add(self, widget: Widget,
39
+ space: Union[int, float, AbsoluteSize] = 1) -> None:
40
+ """Adds a widget to the box with an optional space coefficient.
41
+
42
+ This function overrides :py:meth:`Container.add` from the base class to
43
+ extend its functionality and save additional properties on each widget
44
+ added to the box.
45
+
46
+ :param widget: The widget to add to the box.
47
+ :type widget: Widget
48
+ :param space: The amount of space to allocate for the widget to live
49
+ in.
50
+
51
+ If a numeric value (int or float), it must be at least 1, and it is
52
+ construed as the weight to give to the widget during space
53
+ allocation within the entire box. For example, if widget A has a
54
+ space of 1 and widget B has a space of 2, B will be allocated twice
55
+ as much space as A, i.e. a total of 2/3 of the entire box if the
56
+ only widgets the box contains are A and B.
57
+
58
+ If an instance of :py:class:`AbsoluteSize`, it is construed as the
59
+ exact size to allocate for the widget. For example, if widget A has
60
+ a space of `Px(100)` (i.e. 100px) and widget B has a space of 1, A
61
+ will be allocated exactly 100px while B will be allocated all the
62
+ remaining space if the only widgets the box contains are A and B.
63
+
64
+ Note that this value controls the amount of free space available
65
+ for the widget to grow in, not the size of the widget itself.
66
+ :type space: Union[int, float, AbsoluteSize]
67
+ """
68
+ super().add(widget=widget)
69
+ self._properties[id(widget)] = BoxItemProperties(space=space)
37
70
 
38
- def build(self):
71
+ def build(self) -> Div:
39
72
  """Builds the HTML representation of the Box.
40
73
 
41
74
  The box is constructed as a `<div>` element with a flexbox layout. Its
@@ -45,9 +78,13 @@ class Box(Container):
45
78
  Each child widget is wrapped inside its own `<div>` element with a
46
79
  `data-role` attribute of "box-item". The items are centered within
47
80
  their own `<div>`.
81
+
82
+ :return: A :py:class:`Div` element representing the Box.
83
+ :rtype: Div
48
84
  """
49
- # Building child nodes
85
+ # Building child nodes and retrieving their properties
50
86
  nodes = [w.build() for w in self.widgets]
87
+ properties = [self._properties[id(w)] for w in self.widgets]
51
88
 
52
89
  # Building box items that wrap around child nodes
53
90
  items = [Div(
@@ -57,9 +94,8 @@ class Box(Container):
57
94
  "display": "flex",
58
95
  "flex-direction": "row",
59
96
  "align-items": "center",
60
- "justify-content": "center",
61
- "flex-grow": "1"
62
- }) for node in nodes]
97
+ "justify-content": "center"
98
+ } | props.to_style()) for node, props in zip(nodes, properties)]
63
99
 
64
100
  # Assembling the box
65
101
  flex_dir = "row" if self.direction == Direction.HORIZONTAL else "column"
@@ -68,3 +104,35 @@ class Box(Container):
68
104
  "flex-direction": flex_dir
69
105
  })
70
106
  return box
107
+
108
+
109
+ @dataclass
110
+ class BoxItemProperties:
111
+ """A utility dataclass to store extra properties to apply to a widget
112
+ contained in a :py:class:`Box` during compilation.
113
+ """
114
+
115
+ space: Union[int, float, AbsoluteSize]
116
+
117
+ def to_style(self) -> Dict[str, str]:
118
+ """Converts the properties of the :py:class:`BoxItemProperties`
119
+ instance into a dictionary of CSS properties that can be added to the
120
+ style of an HTML node.
121
+
122
+ :return: A dictionary of CSS properties.
123
+ :rtype: Dict[str, str]
124
+ """
125
+ # If a numeric value, the space serves as a relative weight
126
+ if isinstance(self.space, (int, float)):
127
+ return {
128
+ "flex-basis": "0",
129
+ "flex-grow": str(self.space),
130
+ "flex-shrink": str(self.space)
131
+ }
132
+
133
+ # If an AbsoluteSize object, the space is a fixed size
134
+ return {
135
+ "flex-basis": self.space.to_css(),
136
+ "flex-grow": "0",
137
+ "flex-shrink": "0"
138
+ }
@@ -27,7 +27,12 @@ class Container(Widget):
27
27
  :type widgets: List[Widget]
28
28
  """
29
29
  super().__init__()
30
- self.widgets = [] if widgets is None else widgets
30
+ self._widgets = [] if widgets is None else widgets
31
+
32
+ @property
33
+ def widgets(self) -> List[Widget]:
34
+ """Returns the list of widgets contained within the container."""
35
+ return self._widgets
31
36
 
32
37
  def add(self, widget: Widget) -> None:
33
38
  """Adds a widget to the container.
@@ -35,4 +40,4 @@ class Container(Widget):
35
40
  :param widget: The widget to add to the container.
36
41
  :type widget: Widget
37
42
  """
38
- self.widgets.append(widget)
43
+ self._widgets.append(widget)
@@ -32,7 +32,7 @@ class Page(Container):
32
32
  :param css_file_name: The name of the CSS file to link to the page if
33
33
  the page elements contain any styles. Defaults to "styles.css".
34
34
  :type css_file_name: str
35
- :return: An :py:class:`RootNode` object representing the page.
35
+ :return: A :py:class:`RootNode` object representing the page.
36
36
  :rtype: RootNode
37
37
  """
38
38
  # Building nodes from the page's widgets
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webwidgets
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: A Python package for designing web UIs.
5
5
  Project-URL: Source code, https://github.com/mlaasri/WebWidgets
6
6
  Author: mlaasri
@@ -0,0 +1,34 @@
1
+ webwidgets/__init__.py,sha256=fkkQsGyTLNHc3pL-njm0KmAZRqDfvmwDhun0ZT7N92w,613
2
+ webwidgets/compilation/__init__.py,sha256=hb61nhmPTghIzuA_hun98xT5Ngv7QFAgMHD44g-9uOo,433
3
+ webwidgets/compilation/css/__init__.py,sha256=A4VUGyy92Vn32Km2VuJL5bBmLdovN6PDfv_DctRdzJk,534
4
+ webwidgets/compilation/css/css.py,sha256=v2GSyegop8JmE_9ITZ-2oc9P_8bE33-YWsjiO8FGaWI,9351
5
+ webwidgets/compilation/css/css_rule.py,sha256=8NKQwNfETc52KDrMoy_rJtie6si1SrdfnxKRBRjLJqM,3594
6
+ webwidgets/compilation/css/sections/__init__.py,sha256=qPLq_w0kIPGvIIXxsblF7iUdm9AOA-CUl06krTMnHHI,465
7
+ webwidgets/compilation/css/sections/css_section.py,sha256=LfQojXSYbsh9UcbqD4vn6heEO7qjGNrwy7Py5bsvy9U,4020
8
+ webwidgets/compilation/css/sections/preamble.py,sha256=zDU3JZpIYoc9Xynquc50awqhvYxNi0EbprbwCVScvoY,1355
9
+ webwidgets/compilation/css/sections/rule_section.py,sha256=BBeIJyVRz2ZeBxEC6VrEymXF6LjzE_GPu6X04A-lGF8,1456
10
+ webwidgets/compilation/html/__init__.py,sha256=h8eWh8BbjLZA1wIGAeOxyhZIUM1e36ZgMTwL5SQajHc,514
11
+ webwidgets/compilation/html/html_node.py,sha256=QJgUWpAsvJSd4C9FUAvtcCZWlCLA0fZK5A0c8_pbsWc,11697
12
+ webwidgets/compilation/html/html_tags.py,sha256=R13axcPAOnqRVPM8FP0k04QIW7gZMSJt3jlsv7Q-fXg,2276
13
+ webwidgets/utility/__init__.py,sha256=GDS2bOS36He7EAde1YAcSQ_P49zkKIPGIRP8NRCFJbs,547
14
+ webwidgets/utility/enums.py,sha256=RDgYT2S85DrhKL-3T7oHN20iW4vYoD8TKLsEmsO2OaE,495
15
+ webwidgets/utility/indentation.py,sha256=BaOQRqWdG7T5k_g1-ia9jewPFZjD3afjZH_Fc4NSVwo,906
16
+ webwidgets/utility/representation.py,sha256=lQ15v_DZOHBQKLM8pzRE1tuJkU_modhPTpWpSJ2lBCE,1061
17
+ webwidgets/utility/sanitizing.py,sha256=OKJRDqk-OXYCWeK6ie3GdfQvb49wTs93kd971mg5oK0,5770
18
+ webwidgets/utility/validation.py,sha256=ZKKEkhkdhuC7JxVG1_BKFBLT80DOGaSCOCo6ZJgzwmU,8239
19
+ webwidgets/utility/sizes/__init__.py,sha256=2tmSdXRBlIWuOfZUmToc0_gFiVKJIFUCh6H9B2Bf9rw,437
20
+ webwidgets/utility/sizes/size.py,sha256=UjffvXNNV4BhgyJ_OV_ZArYas7FP4Bhul_ujktsQbQM,2867
21
+ webwidgets/utility/sizes/sizes.py,sha256=DoKIruTw2RjuvH9MmM-CG5C2_WnmLt0mlAWphPstM6E,747
22
+ webwidgets/website/__init__.py,sha256=zp4N3CtY0SLNfDV9p2Y0tqbta-vFOX1PSJr7eQ9rQdk,471
23
+ webwidgets/website/compiled_website.py,sha256=lR_sabYtdWiRWicyxEFs4yxRUB_TbMowpsNz3CtqQBQ,1129
24
+ webwidgets/website/website.py,sha256=2vdIxYLXOu_otiF-KTOBigoic0aUWwgglfXAAZRzURg,3349
25
+ webwidgets/widgets/__init__.py,sha256=J2br7F-16URKvWshkJcc4nth27YQsaLrdVZu0xXx5CU,449
26
+ webwidgets/widgets/widget.py,sha256=NRyiy_vBStX2r-LBeJpqFy-AMw1aaqxrx4sz-GIdJnE,1034
27
+ webwidgets/widgets/containers/__init__.py,sha256=0y63aqzzJzC77oKOK1rcqQGDk710lkalc6vyZr7iJWo,473
28
+ webwidgets/widgets/containers/box.py,sha256=iwr-n09ePMICQLF4MZeAzRjBuPCdqHF2cFF8OLSH_oA,5435
29
+ webwidgets/widgets/containers/container.py,sha256=-UAnDEC0o-rP2PBF1ji8xUGRQYRnDvKmVSDaQH3_DYE,1317
30
+ webwidgets/widgets/containers/page.py,sha256=JQBV9U803nfiC20_4kJ4RkibqVeMKf30FZOGmii6YV4,2179
31
+ webwidgets-1.1.1.dist-info/METADATA,sha256=UBIZPHX_nOWMcxrnmWEgOcDJdzTuVK90DuX43JMhMi4,1607
32
+ webwidgets-1.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
+ webwidgets-1.1.1.dist-info/licenses/LICENSE,sha256=LISw1mw5eK6i8adFSlx6zltZxrJFwurngVdZAEU8g_I,1064
34
+ webwidgets-1.1.1.dist-info/RECORD,,
@@ -1,30 +0,0 @@
1
- webwidgets/__init__.py,sha256=XGu3i9D0Zs9W12E62C5Yq-Aejh_GTlyz6197FAoxiME,549
2
- webwidgets/compilation/__init__.py,sha256=hb61nhmPTghIzuA_hun98xT5Ngv7QFAgMHD44g-9uOo,433
3
- webwidgets/compilation/css/__init__.py,sha256=A4VUGyy92Vn32Km2VuJL5bBmLdovN6PDfv_DctRdzJk,534
4
- webwidgets/compilation/css/css.py,sha256=d7sxMOfT2s2sxG2O4LB4zSuknDb_fPcikKkiQk70vpc,9299
5
- webwidgets/compilation/css/css_rule.py,sha256=QkeyVc9hmRwz0QY1avDugBpMM849VXcvJi18-c9h4x4,3530
6
- webwidgets/compilation/css/sections/__init__.py,sha256=qPLq_w0kIPGvIIXxsblF7iUdm9AOA-CUl06krTMnHHI,465
7
- webwidgets/compilation/css/sections/css_section.py,sha256=LfQojXSYbsh9UcbqD4vn6heEO7qjGNrwy7Py5bsvy9U,4020
8
- webwidgets/compilation/css/sections/preamble.py,sha256=DwRwcKrVVeiypsHQn0FIQojpOQ3KUcrlaawxfipCue8,1251
9
- webwidgets/compilation/css/sections/rule_section.py,sha256=BBeIJyVRz2ZeBxEC6VrEymXF6LjzE_GPu6X04A-lGF8,1456
10
- webwidgets/compilation/html/__init__.py,sha256=h8eWh8BbjLZA1wIGAeOxyhZIUM1e36ZgMTwL5SQajHc,514
11
- webwidgets/compilation/html/html_node.py,sha256=lOf1LEoVx23teWHfdlt5IpSv14cE6EI-aDyFGC_BXSU,11697
12
- webwidgets/compilation/html/html_tags.py,sha256=R13axcPAOnqRVPM8FP0k04QIW7gZMSJt3jlsv7Q-fXg,2276
13
- webwidgets/utility/__init__.py,sha256=Sl-dzpPPTHykkmLSfobhqHmlzUSPtvhaR4xtJy_tiOg,505
14
- webwidgets/utility/indentation.py,sha256=BaOQRqWdG7T5k_g1-ia9jewPFZjD3afjZH_Fc4NSVwo,906
15
- webwidgets/utility/representation.py,sha256=lQ15v_DZOHBQKLM8pzRE1tuJkU_modhPTpWpSJ2lBCE,1061
16
- webwidgets/utility/sanitizing.py,sha256=OKJRDqk-OXYCWeK6ie3GdfQvb49wTs93kd971mg5oK0,5770
17
- webwidgets/utility/validation.py,sha256=RB3JvMcVP6AKP1yrl44kFUQRzswtMa6ql7r2tqvrojE,6989
18
- webwidgets/website/__init__.py,sha256=zp4N3CtY0SLNfDV9p2Y0tqbta-vFOX1PSJr7eQ9rQdk,471
19
- webwidgets/website/compiled_website.py,sha256=lR_sabYtdWiRWicyxEFs4yxRUB_TbMowpsNz3CtqQBQ,1129
20
- webwidgets/website/website.py,sha256=2vdIxYLXOu_otiF-KTOBigoic0aUWwgglfXAAZRzURg,3349
21
- webwidgets/widgets/__init__.py,sha256=J2br7F-16URKvWshkJcc4nth27YQsaLrdVZu0xXx5CU,449
22
- webwidgets/widgets/widget.py,sha256=NRyiy_vBStX2r-LBeJpqFy-AMw1aaqxrx4sz-GIdJnE,1034
23
- webwidgets/widgets/containers/__init__.py,sha256=bKhkQHUfBMjYi7f0lPSBwP2EMn_M7n9VIh3He4gRqyc,484
24
- webwidgets/widgets/containers/box.py,sha256=L5qYFsHWs0YzpAZ2Mv_i3pWzMp5od98tLjjf8KpnDhY,2351
25
- webwidgets/widgets/containers/container.py,sha256=blpO2y9IiZ_4opwe9pqsSJPAZEN1P_ZRK4a27NpnMrg,1158
26
- webwidgets/widgets/containers/page.py,sha256=sJ8QDmZ_6jzRFt4lyiAEPwjPvDTKm8EWOjz_Tq_cdjU,2180
27
- webwidgets-1.1.0.dist-info/METADATA,sha256=b4hRl-cnHN3ndE_8RhOZPM_YFNtoJJfn6u8ovtFi8LA,1607
28
- webwidgets-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- webwidgets-1.1.0.dist-info/licenses/LICENSE,sha256=LISw1mw5eK6i8adFSlx6zltZxrJFwurngVdZAEU8g_I,1064
30
- webwidgets-1.1.0.dist-info/RECORD,,