mapres 2.3__tar.gz → 2.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapres
3
- Version: 2.3
3
+ Version: 2.4
4
4
  Summary: A powerfull mapping utility
5
5
  Author: iFamished
6
6
  License: MIT
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "mapres"
10
- version = "2.3"
10
+ version = "2.4"
11
11
  description = "A powerfull mapping utility"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.9"
@@ -7,7 +7,7 @@ try:
7
7
  except PackageNotFoundError:
8
8
  __version__ = '0.0.0'
9
9
 
10
- from .resolver import MapResolver, res
10
+ from .resolver import MapResolver, res, setGlobalMaps, setDefaultPasses
11
11
  from .datamap import DataMap, datamap, syntax
12
12
  from .layers import Layer, LayerStack
13
13
 
@@ -37,6 +37,8 @@ __all__ = [
37
37
  'syntax',
38
38
  'Layer',
39
39
  'LayerStack',
40
+ 'setGlobalMaps',
41
+ 'setDefaultPasses',
40
42
 
41
43
  # maps
42
44
  'ColorMap',
@@ -0,0 +1,90 @@
1
+ import re
2
+ from dataclasses import dataclass, fields, is_dataclass
3
+
4
+ class syntax:
5
+ double_braces = r'\{\{([A-Za-z][A-Za-z0-9_]*)\}\}' # {{value}}
6
+ dollars = r'\$\{([A-Za-z][A-Za-z0-9_]*)\}' # ${value}
7
+ angles = r'<([A-Za-z][A-Za-z0-9_]*)>' # <value>
8
+ percents = r'%([A-Za-z][A-Za-z0-9_]*)%' # %value%
9
+ at_tags = r'@([A-Za-z][A-Za-z0-9_]*)@' # @value@
10
+ hash_tags = r'#([A-Za-z][A-Za-z0-9_]*)#' # #value#
11
+ pipe_tags = r'\|([A-Za-z][A-Za-z0-9_]*)\|' # |value|
12
+ paren_dollar = r'\$\(([A-Za-z][A-Za-z0-9_]*)\)' # $(value)
13
+ colons = r':([A-Za-z][A-Za-z0-9_]*):' # :value:
14
+
15
+ @dataclass
16
+ class DataMap:
17
+ '''Core datamap class. Contains logic used to make datamaps'''
18
+ __syntax__: str = syntax.double_braces
19
+ __mode__: str | None = None
20
+
21
+ def as_map(self):
22
+ result = {}
23
+ for f in fields(self):
24
+ if not f.init or f.name in ('__syntax__', '__mode__'):
25
+ continue
26
+ val = getattr(self, f.name)
27
+ if self.__mode__ == 'dynamic':
28
+ providers = getattr(self, 'providers', None)
29
+ if isinstance(providers, dict) and f.name in providers:
30
+ val = providers[f.name]
31
+ if callable(val):
32
+ val = val()
33
+ result[f.name] = val
34
+ return result
35
+
36
+ @classmethod
37
+ def get_syntax(cls):
38
+ return getattr(cls, '__syntax__', syntax.double_braces)
39
+
40
+
41
+ # main decorator factory
42
+ def datamap(_cls=None, *, syntax=syntax.double_braces, mode=None):
43
+ '''@datamap decorator with optional values'''
44
+ def wrap(cls):
45
+ cls.__syntax__ = syntax
46
+ cls.__mode__ = mode
47
+ namespace = dict(cls.__dict__)
48
+ namespace['__dict__'] = {}
49
+ rules_obj = namespace.get('rules', None)
50
+ cls = type(cls.__name__, (DataMap,), namespace)
51
+ if rules_obj is not None:
52
+ setattr(cls, 'rules', rules_obj)
53
+ return dataclass(frozen=False)(cls)
54
+ if _cls is not None:
55
+ return wrap(_cls)
56
+ return wrap
57
+
58
+
59
+ # syntax-bound decorator factories
60
+ class _SyntaxFactory:
61
+ def __init__(self, syntax_value):
62
+ self._syntax = syntax_value
63
+
64
+ def __call__(self, _cls=None, **kwargs):
65
+ # Case 1: bare decorator: @datamap.colons
66
+ if _cls is not None and isinstance(_cls, type):
67
+ return datamap(_cls, syntax=self._syntax)
68
+
69
+ # Case 2: decorator with args: @datamap.colons(mode='config')
70
+ return datamap(syntax=self._syntax, **kwargs)
71
+
72
+ @property
73
+ def config(self):
74
+ # Case 3: @datamap.colons.config
75
+ return datamap(syntax=self._syntax, mode='config')
76
+
77
+
78
+ # build syntax shortcuts
79
+ datamap.double_braces = _SyntaxFactory(syntax.double_braces)
80
+ datamap.angles = _SyntaxFactory(syntax.angles)
81
+ datamap.dollars = _SyntaxFactory(syntax.dollars)
82
+ datamap.percents = _SyntaxFactory(syntax.percents)
83
+ datamap.at_tags = _SyntaxFactory(syntax.at_tags)
84
+ datamap.hash_tags = _SyntaxFactory(syntax.hash_tags)
85
+ datamap.pipe_tags = _SyntaxFactory(syntax.pipe_tags)
86
+ datamap.paren_dollar = _SyntaxFactory(syntax.paren_dollar)
87
+ datamap.colons = _SyntaxFactory(syntax.colons)
88
+
89
+ # global mode shortcut
90
+ datamap.config = datamap(mode='config')
@@ -0,0 +1,75 @@
1
+ from mapres.datamap import datamap, syntax
2
+
3
+ @datamap(syntax=syntax.angles) # produces <>
4
+ class ColorMap:
5
+ black: str = '\033[30m'
6
+ dark_blue: str = '\033[34m'
7
+ dark_green: str = '\033[32m'
8
+ dark_aqua: str = '\033[36m'
9
+ dark_red: str = '\033[31m'
10
+ dark_purple: str = '\033[35m'
11
+ gold: str = '\033[33m'
12
+ gray: str = '\033[37m'
13
+ dark_gray: str = '\033[90m'
14
+ blue: str = '\033[94m'
15
+ green: str = '\033[92m'
16
+ aqua: str = '\033[96m'
17
+ red: str = '\033[91m'
18
+ light_purple: str = '\033[95m'
19
+ yellow: str = '\033[93m'
20
+ white: str = '\033[97m'
21
+ reset: str = '\033[0m'
22
+ bold: str = '\033[1m'
23
+ italic: str = '\033[3m'
24
+
25
+ def as_dict(self):
26
+ return {f'<{k}>': getattr(self, k) for k in self.__dataclass_fields__}
27
+
28
+ # ASCII color map
29
+ ascii_colors = ColorMap()
30
+
31
+ # Minecraft color map
32
+ mc_colors = ColorMap(
33
+ black='§0',
34
+ dark_blue='§1',
35
+ dark_green='§2',
36
+ dark_aqua='§3',
37
+ dark_red='§4',
38
+ dark_purple='§5',
39
+ gold='§6',
40
+ gray='§7',
41
+ dark_gray='§8',
42
+ blue='§9',
43
+ green='§a',
44
+ aqua='§b',
45
+ red='§c',
46
+ light_purple='§d',
47
+ yellow='§e',
48
+ white='§f',
49
+ reset='§r',
50
+ bold='§l',
51
+ italic='§o'
52
+ )
53
+
54
+ # Color strip map
55
+ strip_colors = ColorMap(
56
+ black='',
57
+ dark_blue='',
58
+ dark_green='',
59
+ dark_aqua='',
60
+ dark_red='',
61
+ dark_purple='',
62
+ gold='',
63
+ gray='',
64
+ dark_gray='',
65
+ blue='',
66
+ green='',
67
+ aqua='',
68
+ red='',
69
+ light_purple='',
70
+ yellow='',
71
+ white='',
72
+ reset='',
73
+ bold='',
74
+ italic=''
75
+ )
@@ -1,31 +1,36 @@
1
- from datetime import datetime
1
+ from datetime import datetime, timezone
2
2
  from zoneinfo import ZoneInfo
3
3
  from mapres.datamap import datamap, syntax
4
4
 
5
5
 
6
+ def safe_zoneinfo(tz: str):
7
+ try:
8
+ return ZoneInfo(tz)
9
+ except Exception:
10
+ return timezone.utc
11
+
12
+
6
13
  @datamap(syntax=syntax.percents, mode='dynamic')
7
14
  class TimeMap:
8
- # default timezone
9
- _default_tz = ZoneInfo('UTC')
10
-
11
- # dynamic fields
12
- hh: str = None
13
- h: str = None
14
- h12: str = None
15
- hh12: str = None
16
- ampm: str = None
17
- mm: str = None
18
- m: str = None
19
- ss: str = None
20
- s: str = None
21
- ms: str = None
22
- YYYY: str = None
23
- MM: str = None
24
- DD: str = None
25
- weekday: str = None
15
+ _default_tz = safe_zoneinfo("America/Chicago")
16
+
17
+ hh: str | None = None
18
+ h: str | None = None
19
+ h12: str | None = None
20
+ hh12: str | None = None
21
+ ampm: str | None = None
22
+ mm: str | None = None
23
+ m: str | None = None
24
+ ss: str | None = None
25
+ s: str | None = None
26
+ ms: str | None = None
27
+ YYYY: str | None = None
28
+ MM: str | None = None
29
+ DD: str | None = None
30
+ weekday: str | None = None
26
31
 
27
32
  def __init__(self, tz: str | None = None):
28
- self.TZ = ZoneInfo(tz) if tz else self._default_tz
33
+ self.TZ = safe_zoneinfo(tz) if tz else self._default_tz
29
34
 
30
35
  @property
31
36
  def providers(self):
@@ -5,8 +5,40 @@ from .layers import Layer, LayerStack
5
5
  from .exceptions import MapResError, MissingKeyError, MapSyntaxError
6
6
 
7
7
 
8
+ # escape pipeline
9
+ ESCAPES = {
10
+ r'\:': '__ESC_COLON__',
11
+ r'\<': '__ESC_LT__',
12
+ r'\%': '__ESC_PERCENT__',
13
+ r'\$': '__ESC_DOLLAR__',
14
+ r'\{': '__ESC_LBRACE__',
15
+ r'\|': '__ESC_PIPE__',
16
+ }
17
+
18
+ # Reverse mapping: placeholder -> literal char (without backslash)
19
+ UNESCAPES = {
20
+ placeholder: esc[1:] # remove leading backslash
21
+ for esc, placeholder in ESCAPES.items()
22
+ }
23
+
24
+
25
+ def escape_stage(text: str, ctx: dict, resolver) -> str:
26
+ """Replace escaped opening delimiters with placeholders."""
27
+ for esc, placeholder in ESCAPES.items():
28
+ text = text.replace(esc, placeholder)
29
+ return text
30
+
31
+
32
+ def unescape_stage(text: str, ctx: dict, resolver) -> str:
33
+ """Restore escaped delimiters after resolution."""
34
+ for placeholder, literal in UNESCAPES.items():
35
+ text = text.replace(placeholder, literal)
36
+ return text
37
+
38
+
39
+ # core resolver
8
40
  class MapResolver:
9
- """
41
+ '''
10
42
  Core resolution engine for mapres.
11
43
 
12
44
  Handles:
@@ -14,9 +46,9 @@ class MapResolver:
14
46
  - syntax providers
15
47
  - layered maps
16
48
  - context substitution
17
- - recursive multi-pass resolution
49
+ - multi-pass resolution (controlled by `passes`)
18
50
  - optional caching
19
- """
51
+ '''
20
52
  def __init__(
21
53
  self,
22
54
  layers: list | None = None,
@@ -24,14 +56,22 @@ class MapResolver:
24
56
  pipeline: list | None = None,
25
57
  cache: bool = False,
26
58
  cache_size: int = 1024,
27
- max_depth: int = 5
59
+ passes_default: int = 5
28
60
  ):
29
61
  self.layers = layers or LayerStack()
30
62
  self.syntax = syntax or []
31
63
  self.pipeline = pipeline or []
32
64
  self.cache_enabled = cache
33
65
  self.cache = LRUCache(cache_size) if cache else None
34
- self.max_depth = max_depth
66
+
67
+ # unified recursion control
68
+ self.passes_default = passes_default
69
+
70
+ # Insert escape stage FIRST
71
+ self.pipeline.insert(0, escape_stage)
72
+
73
+ # Append unescape stage LAST
74
+ self.pipeline.append(unescape_stage)
35
75
 
36
76
  # pipeline
37
77
  def _apply_pipeline(self, text: str, ctx: dict) -> str:
@@ -40,81 +80,93 @@ class MapResolver:
40
80
  text = stage(text, ctx, self)
41
81
  return text
42
82
  except Exception as exc:
43
- raise MapResError(f"Pipeline stage failed: {exc}") from exc
83
+ raise MapResError(f'Pipeline stage failed: {exc}') from exc
44
84
 
45
85
  # syntax providers
46
86
  def _apply_syntax(self, text: str, ctx: dict) -> str:
47
87
  for provider in self.syntax:
48
88
  pattern = provider.pattern
49
89
  d = provider.get_map(ctx, self)
90
+
50
91
  def repl(match: re.Match) -> str:
51
92
  k = match.group(1)
52
93
  if k not in d:
53
- raise MissingKeyError(f"Missing key '{k}' in syntax provider {provider}")
94
+ raise MissingKeyError(f'Missing key "{k}" in syntax provider {provider}')
54
95
  return str(d[k])
96
+
55
97
  try:
56
98
  text = re.sub(pattern, repl, text)
57
99
  except re.error as exc:
58
100
  raise MapSyntaxError(
59
- f"Regex error in syntax provider {provider}: {exc}"
101
+ f'Regex error in syntax provider {provider}: {exc}'
60
102
  ) from exc
103
+
61
104
  return text
62
105
 
63
106
  # layered maps
64
107
  def _apply_maps(self, text: str, ctx: dict, layerstack: LayerStack):
65
108
  syntax_patterns = []
109
+
66
110
  for m in layerstack:
67
- if isinstance(m, type) and hasattr(m, "as_map"):
111
+ if isinstance(m, type) and hasattr(m, 'as_map'):
68
112
  m = m()
69
- if hasattr(m, "as_map"):
113
+ if hasattr(m, 'as_map'):
70
114
  syntax_patterns.append(m.get_syntax())
71
115
  elif isinstance(m, dict):
72
- pattern = ctx.get("syntax")
116
+ pattern = ctx.get('syntax')
73
117
  if pattern:
74
118
  syntax_patterns.append(pattern)
119
+
75
120
  syntax_patterns = list(dict.fromkeys(syntax_patterns))
121
+
76
122
  for pattern in syntax_patterns:
77
123
  def repl(match: re.Match):
78
124
  k = match.group(1)
125
+
79
126
  for m in layerstack:
80
127
  layer = m
81
- if isinstance(layer, type) and hasattr(layer, "as_map"):
128
+ if isinstance(layer, type) and hasattr(layer, 'as_map'):
82
129
  layer = layer()
83
- if hasattr(layer, "as_map"):
130
+ if hasattr(layer, 'as_map'):
84
131
  d = layer.as_map()
85
132
  elif isinstance(layer, dict):
86
133
  d = layer
87
134
  else:
88
135
  continue
136
+
89
137
  if k in d:
90
138
  return str(d[k])
91
139
 
92
140
  if k in ctx:
93
141
  return str(ctx[k])
94
142
 
95
- raise MissingKeyError(f"Missing key '{k}' in any layer or context")
143
+ raise MissingKeyError(f'Missing key "{k}" in any layer or context')
96
144
 
97
145
  try:
98
146
  text = re.sub(pattern, repl, text)
99
147
  except re.error as exc:
100
- raise MapSyntaxError(f"Regex error in syntax pattern {pattern}: {exc}") from exc
148
+ raise MapSyntaxError(f'Regex error in syntax pattern {pattern}: {exc}') from exc
149
+
101
150
  return text
102
151
 
103
152
  # context
104
153
  def _apply_ctx(self, text: str, ctx: dict) -> str:
105
154
  if not ctx:
106
155
  return text
107
- pattern = syntax.braces
156
+
157
+ pattern = syntax.double_braces
108
158
  d = ctx
159
+
109
160
  def repl(match: re.Match) -> str:
110
161
  k = match.group(1)
111
162
  if k not in d:
112
- raise MissingKeyError(f"Missing ctx key '{k}'")
163
+ raise MissingKeyError(f'Missing ctx key "{k}"')
113
164
  return str(d[k])
165
+
114
166
  try:
115
167
  return re.sub(pattern, repl, text)
116
168
  except re.error as exc:
117
- raise MapSyntaxError(f"Regex error in ctx syntax: {exc}") from exc
169
+ raise MapSyntaxError(f'Regex error in ctx syntax: {exc}') from exc
118
170
 
119
171
  # one pass
120
172
  def _resolve_once(self, text: str, ctx: dict, layerstack: LayerStack) -> str:
@@ -124,45 +176,52 @@ class MapResolver:
124
176
  text = self._apply_ctx(text, ctx)
125
177
  return text
126
178
 
127
- # recursion
128
- def _recursive(self, text: str, ctx: dict, layerstack: LayerStack) -> str:
129
- current = text
130
- for _ in range(self.max_depth):
131
- result = self._resolve_once(current, ctx, layerstack)
132
- if result == current:
133
- return result
134
- current = result
135
- return current
136
-
137
179
  # public api
138
180
  def res(
139
181
  self,
140
182
  text: str,
141
183
  *,
184
+ passes: int | None = None,
142
185
  extra_maps: dict | None = None,
143
186
  override_maps: dict | None = None,
144
187
  **ctx
145
188
  ) -> str:
146
- """
189
+ '''
147
190
  Resolve a string using maps, syntax providers, pipeline, and context.
148
- """
191
+ '''
149
192
  try:
193
+ depth = passes if passes is not None else self.passes_default
194
+
195
+ if depth <= 0:
196
+ raise MapResError("passes must be >= 1")
197
+
198
+ # override maps
150
199
  if override_maps is not None:
151
- temp = LayerStack([Layer("override", override_maps, priority=0)])
152
- return self._recursive(text, ctx, temp)
200
+ temp = LayerStack([Layer('override', override_maps, priority=0)])
201
+ return self._resolve_once(text, ctx, temp)
153
202
 
203
+ # extra maps
154
204
  if extra_maps:
155
205
  temp = self.layers.clone()
156
- temp.add_layer(Layer("extra", extra_maps, priority=999))
157
- return self._recursive(text, ctx, temp)
206
+ temp.add_layer(Layer('extra', extra_maps, priority=999))
207
+ return self._resolve_once(text, ctx, temp)
158
208
 
209
+ # caching
159
210
  if self.cache_enabled:
160
211
  key = (text, tuple(sorted(ctx.items())))
161
212
  cached = self.cache.get(key)
162
213
  if cached is not None:
163
214
  return cached
164
215
 
165
- result = self._recursive(text, ctx, self.layers)
216
+ # multi-pass resolution
217
+ current = text
218
+ for _ in range(depth):
219
+ new = self._resolve_once(current, ctx, self.layers)
220
+ if new == current:
221
+ break
222
+ current = new
223
+
224
+ result = current
166
225
 
167
226
  if self.cache_enabled:
168
227
  self.cache.set(key, result)
@@ -172,14 +231,34 @@ class MapResolver:
172
231
  except MapResError:
173
232
  raise
174
233
  except Exception as exc:
175
- raise MapResError(f"Unhandled resolver error: {exc}") from exc
234
+ raise MapResError(f'Unhandled resolver error: {exc}') from exc
235
+
236
+
237
+ # ----------------------------------
238
+ # ---------- SIMPLE USAGE ----------
239
+ # ----------------------------------
240
+
241
+ _DEFAULT_RESOLVER = MapResolver()
242
+
243
+ def setGlobalMaps(maps, *, name=None, priority=0):
244
+ '''
245
+ Register a global map or datamap class into the default resolver.
176
246
 
247
+ maps: datamap class OR dict
248
+ name: optional layer name (default = class name or 'global')
249
+ priority: layer priority (lower = earlier)
250
+ '''
251
+ layer_name = name or getattr(maps, "__name__", "global")
252
+ layer = Layer(layer_name, maps=[maps], priority=priority)
253
+ _DEFAULT_RESOLVER.layers.add_layer(layer)
177
254
 
178
- # global resolver
179
- _DEFAULT = MapResolver()
255
+ def setDefaultPasses(passes: int):
256
+ if passes < 1:
257
+ raise MapResError("Passes cannot be less than 1")
258
+ _DEFAULT_RESOLVER.passes_default = passes
180
259
 
181
- def res(text: str, **ctx) -> str:
182
- """
183
- Resolve using the global default resolver.
184
- """
185
- return _DEFAULT.res(text, **ctx)
260
+ def res(text: str, passes=None, **ctx) -> str:
261
+ '''
262
+ Simple resolution using the global default resolver.
263
+ '''
264
+ return _DEFAULT_RESOLVER.res(text, passes=passes, **ctx)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapres
3
- Version: 2.3
3
+ Version: 2.4
4
4
  Summary: A powerfull mapping utility
5
5
  Author: iFamished
6
6
  License: MIT
@@ -1,64 +0,0 @@
1
- import re
2
- from dataclasses import dataclass, fields, is_dataclass
3
-
4
- class syntax:
5
- braces = r"\{([^{}]+)\}"
6
- dollars = r"\$\{([^{}]+)\}"
7
- angles = r"<([^<>]+)>"
8
- percents = r"%([^%]+)%"
9
-
10
-
11
- @dataclass
12
- class DataMap:
13
- '''Core datamap class. Contains logic used to make datamaps'''
14
- __syntax__: str = syntax.braces
15
- __mode__: str | None = None
16
-
17
- def as_map(self):
18
- result = {}
19
- for f in fields(self):
20
- if not f.init or f.name in ("__syntax__", "__mode__"):
21
- continue
22
- val = getattr(self, f.name)
23
- if self.__mode__ == "dynamic":
24
- providers = getattr(self, "providers", None)
25
- if isinstance(providers, dict) and f.name in providers:
26
- val = providers[f.name]
27
- if callable(val):
28
- val = val()
29
- result[f.name] = val
30
- return result
31
-
32
- @classmethod
33
- def get_syntax(cls):
34
- return getattr(cls, "__syntax__", syntax.braces)
35
-
36
-
37
- # decorator
38
- def datamap(
39
- _cls = None,
40
- *,
41
- syntax: str = syntax.braces,
42
- mode: bool | None = None,
43
- ):
44
- '''@datamap decorator with optional values'''
45
- def wrap(cls):
46
- cls.__syntax__ = syntax
47
- cls.__mode__ = mode
48
- namespace = dict(cls.__dict__)
49
- namespace["__dict__"] = {}
50
- # preserve any rules class defined in the original namespace by attaching it to the generated class
51
- rules_obj = namespace.get("rules", None)
52
- cls = type(cls.__name__, (DataMap,), namespace)
53
- # attach rules (if present) to the new class so validators can read them via the datamap class
54
- if rules_obj is not None:
55
- setattr(cls, "rules", rules_obj)
56
- return dataclass(frozen=False)(cls)
57
- return wrap if _cls is None else wrap(_cls)
58
-
59
-
60
- # decorator shortcuts
61
- datamap.braces = datamap(syntax=syntax.braces)
62
- datamap.angles = datamap(syntax=syntax.angles)
63
- datamap.dollars = datamap(syntax=syntax.dollars)
64
- datamap.percents = datamap(syntax=syntax.percents)
@@ -1,75 +0,0 @@
1
- from mapres.datamap import datamap, syntax
2
-
3
- @datamap(syntax=syntax.angles) # produces <>
4
- class ColorMap:
5
- black: str = "\033[30m"
6
- dark_blue: str = "\033[34m"
7
- dark_green: str = "\033[32m"
8
- dark_aqua: str = "\033[36m"
9
- dark_red: str = "\033[31m"
10
- dark_purple: str = "\033[35m"
11
- gold: str = "\033[33m"
12
- gray: str = "\033[37m"
13
- dark_gray: str = "\033[90m"
14
- blue: str = "\033[94m"
15
- green: str = "\033[92m"
16
- aqua: str = "\033[96m"
17
- red: str = "\033[91m"
18
- light_purple: str = "\033[95m"
19
- yellow: str = "\033[93m"
20
- white: str = "\033[97m"
21
- reset: str = "\033[0m"
22
- bold: str = "\033[1m"
23
- italic: str = "\033[3m"
24
-
25
- def as_dict(self):
26
- return {f"<{k}>": getattr(self, k) for k in self.__dataclass_fields__}
27
-
28
- # ASCII color map
29
- ascii_colors = ColorMap()
30
-
31
- # Minecraft color map
32
- mc_colors = ColorMap(
33
- black="§0",
34
- dark_blue="§1",
35
- dark_green="§2",
36
- dark_aqua="§3",
37
- dark_red="§4",
38
- dark_purple="§5",
39
- gold="§6",
40
- gray="§7",
41
- dark_gray="§8",
42
- blue="§9",
43
- green="§a",
44
- aqua="§b",
45
- red="§c",
46
- light_purple="§d",
47
- yellow="§e",
48
- white="§f",
49
- reset="§r",
50
- bold="§l",
51
- italic="§o"
52
- )
53
-
54
- # Color strip map
55
- strip_colors = ColorMap(
56
- black="",
57
- dark_blue="",
58
- dark_green="",
59
- dark_aqua="",
60
- dark_red="",
61
- dark_purple="",
62
- gold="",
63
- gray="",
64
- dark_gray="",
65
- blue="",
66
- green="",
67
- aqua="",
68
- red="",
69
- light_purple="",
70
- yellow="",
71
- white="",
72
- reset="",
73
- bold="",
74
- italic=""
75
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes