diff options
author | cyfraeviolae <cyfraeviolae> | 2024-04-03 03:10:44 -0400 |
---|---|---|
committer | cyfraeviolae <cyfraeviolae> | 2024-04-03 03:10:44 -0400 |
commit | 6d7ba58f880be618ade07f8ea080fe8c4bf8a896 (patch) | |
tree | b1c931051ffcebd2bd9d61d98d6233ffa289bbce /venv/lib/python3.11/site-packages/jsbeautifier/core | |
parent | 4f884c9abc32990b4061a1bb6997b4b37e58ea0b (diff) |
venv
Diffstat (limited to 'venv/lib/python3.11/site-packages/jsbeautifier/core')
22 files changed, 1376 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__init__.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/__init__.py new file mode 100644 index 0000000..0c01055 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__init__.py @@ -0,0 +1 @@ +# Empty file :) diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/__init__.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..3840186 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/__init__.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/directives.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/directives.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..cd6e94e --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/directives.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/inputscanner.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/inputscanner.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..0218c99 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/inputscanner.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/options.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/options.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..c1d3e7f --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/options.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/output.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/output.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..54d1f74 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/output.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/pattern.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/pattern.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..f5613ef --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/pattern.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/templatablepattern.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/templatablepattern.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..1b40306 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/templatablepattern.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/token.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/token.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..aecbc5e --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/token.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenizer.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenizer.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..394b166 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenizer.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenstream.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenstream.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..588b014 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/tokenstream.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/whitespacepattern.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/whitespacepattern.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..664db5a --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/__pycache__/whitespacepattern.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/directives.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/directives.py new file mode 100644 index 0000000..566a2db --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/directives.py @@ -0,0 +1,55 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re + + +class Directives: + def __init__(self, start_block_pattern, end_block_pattern): + self.__directives_block_pattern = re.compile( + start_block_pattern + r" beautify( \w+[:]\w+)+ " + end_block_pattern + ) + self.__directive_pattern = re.compile(r" (\w+)[:](\w+)") + + self.__directives_end_ignore_pattern = re.compile( + start_block_pattern + r"\sbeautify\signore:end\s" + end_block_pattern + ) + + def get_directives(self, text): + if not self.__directives_block_pattern.match(text): + return None + + directives = {} + directive_match = self.__directive_pattern.search(text) + + while directive_match: + directives[directive_match.group(1)] = directive_match.group(2) + directive_match = self.__directive_pattern.search( + text, directive_match.end() + ) + + return directives + + def readIgnored(self, input): + return input.readUntilAfter(self.__directives_end_ignore_pattern) diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/inputscanner.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/inputscanner.py new file mode 100644 index 0000000..95dabfd --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/inputscanner.py @@ -0,0 +1,140 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re + + +class InputScanner: + def __init__(self, input_string): + self.__six = __import__("six") + if input_string is None: + input_string = "" + self.__input = input_string + self.__input_length = len(self.__input) + self.__position = 0 + + def restart(self): + self.__position = 0 + + def back(self): + if self.__position > 0: + self.__position -= 1 + + def hasNext(self): + return self.__position < self.__input_length + + def next(self): + val = None + if self.hasNext(): + val = self.__input[self.__position] + self.__position += 1 + + return val + + def peek(self, index=0): + val = None + index += self.__position + if index >= 0 and index < self.__input_length: + val = self.__input[index] + + return val + + def test(self, pattern, index=0): + index += self.__position + return ( + index >= 0 + and index < self.__input_length + and bool(pattern.match(self.__input, index)) + ) + + def testChar(self, pattern, index=0): + # test one character regex match + val = self.peek(index) + return val is not None and bool(pattern.match(val)) + + def match(self, pattern): + pattern_match = None + if self.hasNext(): + pattern_match = pattern.match(self.__input, self.__position) + if bool(pattern_match): + self.__position = pattern_match.end(0) + return pattern_match + + def read(self, starting_pattern, until_pattern=None, until_after=False): + val = "" + pattern_match = None + if bool(starting_pattern): + pattern_match = self.match(starting_pattern) + if bool(pattern_match): + val = pattern_match.group(0) + + if bool(until_pattern) and (bool(pattern_match) or not bool(starting_pattern)): + val += self.readUntil(until_pattern, until_after) + + return val + + def readUntil(self, pattern, include_match=False): + val = "" + pattern_match = None + match_index = self.__position + if self.hasNext(): + pattern_match = pattern.search(self.__input, self.__position) + if bool(pattern_match): + if include_match: + match_index = pattern_match.end(0) + else: + match_index = pattern_match.start(0) + else: + match_index = self.__input_length + + val = self.__input[self.__position : match_index] + self.__position = match_index + + return val + + def readUntilAfter(self, pattern): + return self.readUntil(pattern, True) + + def get_regexp(self, pattern, match_from=False): + result = None + # strings are converted to regexp + if isinstance(pattern, self.__six.string_types) and pattern != "": + result = re.compile(pattern) + elif pattern is not None: + result = re.compile(pattern.pattern) + return result + + # css beautifier legacy helpers + def peekUntilAfter(self, pattern): + start = self.__position + val = self.readUntilAfter(pattern) + self.__position = start + return val + + def lookBack(self, testVal): + start = self.__position - 1 + return ( + start >= len(testVal) + and self.__input[start - len(testVal) : start].lower() == testVal + ) diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/options.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/options.py new file mode 100644 index 0000000..16c90e6 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/options.py @@ -0,0 +1,230 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import copy +import re +from collections import namedtuple + + +class Options: + def __init__(self, options=None, merge_child_field=None): + self.css = None + self.js = None + self.html = None + + self.raw_options = _mergeOpts(options, merge_child_field) + + # Support passing the source text back with no change + self.disabled = self._get_boolean("disabled") + + self.eol = self._get_characters("eol", "auto") + self.end_with_newline = self._get_boolean("end_with_newline") + self.indent_size = self._get_number("indent_size", 4) + self.indent_char = self._get_characters("indent_char", " ") + self.indent_level = self._get_number("indent_level") + + self.preserve_newlines = self._get_boolean("preserve_newlines", True) + self.max_preserve_newlines = self._get_number("max_preserve_newlines", 32786) + + if not self.preserve_newlines: + self.max_preserve_newlines = 0 + + self.indent_with_tabs = self._get_boolean( + "indent_with_tabs", self.indent_char == "\t" + ) + if self.indent_with_tabs: + self.indent_char = "\t" + + # indent_size behavior changed after 1.8.6 + # It used to be that indent_size would be + # set to 1 for indent_with_tabs. That is no longer needed and + # actually doesn't make sense - why not use spaces? Further, + # that might produce unexpected behavior - tabs being used + # for single-column alignment. So, when indent_with_tabs is true + # and indent_size is 1, reset indent_size to 4. + if self.indent_size == 1: + self.indent_size = 4 + + # Backwards compat with 1.3.x + self.wrap_line_length = self._get_number( + "wrap_line_length", self._get_number("max_char") + ) + + # Support editor config setting + self.editorconfig = False + + self.indent_empty_lines = self._get_boolean("indent_empty_lines") + + # valid templating languages ['django', 'erb', 'handlebars', 'php', 'smarty', 'angular'] + # For now, 'auto' = all off for javascript, all except angular on for html (and inline javascript/css). + # other values ignored + self.templating = self._get_selection_list( + "templating", + ["auto", "none", "angular", "django", "erb", "handlebars", "php", "smarty"], + ["auto"], + ) + + def _get_array(self, name, default_value=[]): + option_value = getattr(self.raw_options, name, default_value) + result = [] + if isinstance(option_value, list): + result = copy.copy(option_value) + elif isinstance(option_value, str): + result = re.compile(r"[^a-zA-Z0-9_/\-]+").split(option_value) + + return result + + def _get_boolean(self, name, default_value=False): + option_value = getattr(self.raw_options, name, default_value) + result = False + try: + result = bool(option_value) + except ValueError: + pass + + return result + + def _get_characters(self, name, default_value=""): + option_value = getattr(self.raw_options, name, default_value) + result = "" + if isinstance(option_value, str): + result = ( + option_value.replace("\\r", "\r") + .replace("\\n", "\n") + .replace("\\t", "\t") + ) + + return result + + def _get_number(self, name, default_value=0): + option_value = getattr(self.raw_options, name, default_value) + result = 0 + try: + result = int(option_value) + except ValueError: + pass + + return result + + def _get_selection(self, name, selection_list, default_value=None): + result = self._get_selection_list(name, selection_list, default_value) + if len(result) != 1: + raise ValueError( + "Invalid Option Value: The option '" + + name + + "' can only be one of the following values:\n" + + str(selection_list) + + "\nYou passed in: '" + + str(getattr(self.raw_options, name, None)) + + "'" + ) + + return result[0] + + def _get_selection_list(self, name, selection_list, default_value=None): + if not selection_list: + raise ValueError("Selection list cannot be empty.") + + default_value = default_value or [selection_list[0]] + + if not self._is_valid_selection(default_value, selection_list): + raise ValueError("Invalid Default Value!") + + result = self._get_array(name, default_value) + if not self._is_valid_selection(result, selection_list): + raise ValueError( + "Invalid Option Value: The option '" + + name + + "' can contain only the following values:\n" + + str(selection_list) + + "\nYou passed in: '" + + str(getattr(self.raw_options, name, None)) + + "'" + ) + + return result + + def _is_valid_selection(self, result, selection_list): + if len(result) == 0 or len(selection_list) == 0: + return False + + for item in result: + if item not in selection_list: + return False + + return True + + +# merges child options up with the parent options object +# Example: obj = {a: 1, b: {a: 2}} +# mergeOpts(obj, 'b') +# +# Returns: {a: 2} + + +def _mergeOpts(options, childFieldName): + if options is None: + options = {} + + if isinstance(options, tuple): + options = dict(options) + + options = _normalizeOpts(options) + finalOpts = copy.copy(options) + if isinstance(options, dict): + local = finalOpts.get(childFieldName, None) + if local: + del finalOpts[childFieldName] + for key in local: + finalOpts[key] = local[key] + finalOpts = namedtuple("CustomOptions", finalOpts.keys())(*finalOpts.values()) + + if isinstance(options, Options): + local = getattr(finalOpts, childFieldName, None) + if local: + delattr(finalOpts, childFieldName) + for key in local: + setattr(finalOpts, key, local[key]) + + return finalOpts + + +def _normalizeOpts(options): + convertedOpts = copy.copy(options) + if isinstance(convertedOpts, dict): + option_keys = list(convertedOpts.keys()) + for key in option_keys: + if "-" in key: + del convertedOpts[key] + convertedOpts[key.replace("-", "_")] = options[key] + else: + option_keys = list(getattr(convertedOpts, "__dict__", {})) + for key in option_keys: + if "-" in key: + delattr(convertedOpts, key) + setattr( + convertedOpts, key.replace("-", "_"), getattr(options, key, None) + ) + + return convertedOpts diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/output.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/output.py new file mode 100644 index 0000000..d4d49e4 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/output.py @@ -0,0 +1,352 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re +import math + +# Using object instead of string to allow for later expansion of info +# about each line + +__all__ = ["Output"] + + +class OutputLine: + def __init__(self, parent): + self.__parent = parent + self.__character_count = 0 + self.__indent_count = -1 + self.__alignment_count = 0 + self.__wrap_point_index = 0 + self.__wrap_point_character_count = 0 + self.__wrap_point_indent_count = -1 + self.__wrap_point_alignment_count = 0 + + self.__items = [] + + def clone_empty(self): + line = OutputLine(self.__parent) + line.set_indent(self.__indent_count, self.__alignment_count) + return line + + def item(self, index): + return self.__items[index] + + def is_empty(self): + return len(self.__items) == 0 + + def set_indent(self, indent=0, alignment=0): + if self.is_empty(): + self.__indent_count = indent + self.__alignment_count = alignment + self.__character_count = self.__parent.get_indent_size( + self.__indent_count, self.__alignment_count + ) + + def _set_wrap_point(self): + if self.__parent.wrap_line_length: + self.__wrap_point_index = len(self.__items) + self.__wrap_point_character_count = self.__character_count + self.__wrap_point_indent_count = self.__parent.next_line.__indent_count + self.__wrap_point_alignment_count = ( + self.__parent.next_line.__alignment_count + ) + + def _should_wrap(self): + return ( + self.__wrap_point_index + and self.__character_count > self.__parent.wrap_line_length + and self.__wrap_point_character_count + > self.__parent.next_line.__character_count + ) + + def _allow_wrap(self): + if self._should_wrap(): + self.__parent.add_new_line() + next = self.__parent.current_line + next.set_indent( + self.__wrap_point_indent_count, self.__wrap_point_alignment_count + ) + next.__items = self.__items[self.__wrap_point_index :] + self.__items = self.__items[: self.__wrap_point_index] + + next.__character_count += ( + self.__character_count - self.__wrap_point_character_count + ) + self.__character_count = self.__wrap_point_character_count + + if next.__items[0] == " ": + next.__items.pop(0) + next.__character_count -= 1 + + return True + + return False + + def last(self): + if not self.is_empty(): + return self.__items[-1] + + return None + + def push(self, item): + self.__items.append(item) + last_newline_index = item.rfind("\n") + if last_newline_index != -1: + self.__character_count = len(item) - last_newline_index + else: + self.__character_count += len(item) + + def pop(self): + item = None + if not self.is_empty(): + item = self.__items.pop() + self.__character_count -= len(item) + return item + + def _remove_indent(self): + if self.__indent_count > 0: + self.__indent_count -= 1 + self.__character_count -= self.__parent.indent_size + + def _remove_wrap_indent(self): + if self.__wrap_point_indent_count > 0: + self.__wrap_point_indent_count -= 1 + + def trim(self): + while self.last() == " ": + self.__items.pop() + self.__character_count -= 1 + + def toString(self): + result = "" + if self.is_empty(): + if self.__parent.indent_empty_lines: + result = self.__parent.get_indent_string(self.__indent_count) + else: + result = self.__parent.get_indent_string( + self.__indent_count, self.__alignment_count + ) + result += "".join(self.__items) + return result + + +class IndentStringCache: + def __init__(self, options, base_string): + self.__cache = [""] + self.__indent_size = options.indent_size + self.__indent_string = options.indent_char + if not options.indent_with_tabs: + self.__indent_string = options.indent_char * options.indent_size + + # Set to null to continue support of auto detection of base indent + base_string = base_string or "" + if options.indent_level > 0: + base_string = options.indent_level * self.__indent_string + + self.__base_string = base_string + self.__base_string_length = len(base_string) + + def get_indent_size(self, indent, column=0): + result = self.__base_string_length + if indent < 0: + result = 0 + result += indent * self.__indent_size + result += column + return result + + def get_indent_string(self, indent_level, column=0): + result = self.__base_string + if indent_level < 0: + indent_level = 0 + result = "" + column += indent_level * self.__indent_size + self.__ensure_cache(column) + result += self.__cache[column] + return result + + def __ensure_cache(self, column): + while column >= len(self.__cache): + self.__add_column() + + def __add_column(self): + column = len(self.__cache) + indent = 0 + result = "" + if self.__indent_size and column >= self.__indent_size: + indent = int(math.floor(column / self.__indent_size)) + column -= indent * self.__indent_size + result = indent * self.__indent_string + if column: + result += column * " " + self.__cache.append(result) + + +class Output: + def __init__(self, options, baseIndentString=""): + self.__indent_cache = IndentStringCache(options, baseIndentString) + self.raw = False + self._end_with_newline = options.end_with_newline + self.indent_size = options.indent_size + self.wrap_line_length = options.wrap_line_length + self.indent_empty_lines = options.indent_empty_lines + self.__lines = [] + self.previous_line = None + self.current_line = None + self.next_line = OutputLine(self) + self.space_before_token = False + self.non_breaking_space = False + self.previous_token_wrapped = False + # initialize + self.__add_outputline() + + def __add_outputline(self): + self.previous_line = self.current_line + self.current_line = self.next_line.clone_empty() + self.__lines.append(self.current_line) + + def get_line_number(self): + return len(self.__lines) + + def get_indent_string(self, indent, column=0): + return self.__indent_cache.get_indent_string(indent, column) + + def get_indent_size(self, indent, column=0): + return self.__indent_cache.get_indent_size(indent, column) + + def is_empty(self): + return self.previous_line is None and self.current_line.is_empty() + + def add_new_line(self, force_newline=False): + # never newline at the start of file + # otherwise, newline only if we didn't just add one or we're forced + if self.is_empty() or (not force_newline and self.just_added_newline()): + return False + + # if raw output is enabled, don't print additional newlines, + # but still return True as though you had + if not self.raw: + self.__add_outputline() + return True + + def get_code(self, eol): + self.trim(True) + + # handle some edge cases where the last tokens + # has text that ends with newline(s) + last_item = self.current_line.pop() + if last_item: + if last_item[-1] == "\n": + last_item = re.sub(r"[\n]+$", "", last_item) + self.current_line.push(last_item) + + if self._end_with_newline: + self.__add_outputline() + + sweet_code = "\n".join(line.toString() for line in self.__lines) + + if not eol == "\n": + sweet_code = sweet_code.replace("\n", eol) + + return sweet_code + + def set_wrap_point(self): + self.current_line._set_wrap_point() + + def set_indent(self, indent=0, alignment=0): + # Next line stores alignment values + self.next_line.set_indent(indent, alignment) + + # Never indent your first output indent at the start of the file + if len(self.__lines) > 1: + self.current_line.set_indent(indent, alignment) + return True + self.current_line.set_indent() + return False + + def add_raw_token(self, token): + for _ in range(token.newlines): + self.__add_outputline() + + self.current_line.set_indent(-1) + self.current_line.push(token.whitespace_before) + self.current_line.push(token.text) + self.space_before_token = False + self.non_breaking_space = False + self.previous_token_wrapped = False + + def add_token(self, printable_token): + self.__add_space_before_token() + self.current_line.push(printable_token) + self.space_before_token = False + self.non_breaking_space = False + self.previous_token_wrapped = self.current_line._allow_wrap() + + def __add_space_before_token(self): + if self.space_before_token and not self.just_added_newline(): + if not self.non_breaking_space: + self.set_wrap_point() + self.current_line.push(" ") + self.space_before_token = False + + def remove_indent(self, index): + while index < len(self.__lines): + self.__lines[index]._remove_indent() + index += 1 + self.current_line._remove_wrap_indent() + + def trim(self, eat_newlines=False): + self.current_line.trim() + + while eat_newlines and len(self.__lines) > 1 and self.current_line.is_empty(): + self.__lines.pop() + self.current_line = self.__lines[-1] + self.current_line.trim() + + if len(self.__lines) > 1: + self.previous_line = self.__lines[-2] + else: + self.previous_line = None + + def just_added_newline(self): + return self.current_line.is_empty() + + def just_added_blankline(self): + return self.is_empty() or ( + self.current_line.is_empty() and self.previous_line.is_empty() + ) + + def ensure_empty_line_above(self, starts_with, ends_with): + index = len(self.__lines) - 2 + while index >= 0: + potentialEmptyLine = self.__lines[index] + if potentialEmptyLine.is_empty(): + break + elif ( + not potentialEmptyLine.item(0).startswith(starts_with) + and potentialEmptyLine.item(-1) != ends_with + ): + self.__lines.insert(index + 1, OutputLine(self)) + self.previous_line = self.__lines[-2] + break + index -= 1 diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/pattern.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/pattern.py new file mode 100644 index 0000000..7677854 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/pattern.py @@ -0,0 +1,83 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +__all__ = ["Pattern"] + + +class Pattern: + def __init__(self, input_scanner, parent=None): + self._input = input_scanner + self._starting_pattern = None + self._match_pattern = None + self._until_pattern = None + self._until_after = False + + if parent is not None: + self._starting_pattern = self._input.get_regexp(parent._starting_pattern) + self._match_pattern = self._input.get_regexp(parent._match_pattern) + self._until_pattern = self._input.get_regexp(parent._until_pattern) + self._until_after = parent._until_after + + def read(self): + result = self._input.read(self._starting_pattern) + if (self._starting_pattern is None) or result: + result += self._input.read( + self._match_pattern, self._until_pattern, self._until_after + ) + return result + + def read_match(self): + return self._input.match(self._match_pattern) + + def until_after(self, pattern): + result = self._create() + result._until_after = True + result._until_pattern = self._input.get_regexp(pattern) + result._update() + return result + + def until(self, pattern): + result = self._create() + result._until_after = False + result._until_pattern = self._input.get_regexp(pattern) + result._update() + return result + + def starting_with(self, pattern): + result = self._create() + result._starting_pattern = self._input.get_regexp(pattern) + result._update() + return result + + def matching(self, pattern): + result = self._create() + result._match_pattern = self._input.get_regexp(pattern) + result._update() + return result + + def _create(self): + return Pattern(self._input, self) + + def _update(self): + pass diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/templatablepattern.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/templatablepattern.py new file mode 100644 index 0000000..a2f8113 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/templatablepattern.py @@ -0,0 +1,192 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import copy +from ..core.pattern import Pattern + +__all__ = ["TemplatablePattern"] + + +class TemplateNames: + def __init__(self): + self.django = False + self.erb = False + self.handlebars = False + self.php = False + self.smarty = False + self.angular = False + + +class TemplatePatterns: + def __init__(self, input_scanner): + pattern = Pattern(input_scanner) + self.handlebars_comment = pattern.starting_with(r"{{!--").until_after(r"--}}") + self.handlebars_unescaped = pattern.starting_with(r"{{{").until_after(r"}}}") + self.handlebars = pattern.starting_with(r"{{").until_after(r"}}") + self.php = pattern.starting_with(r"<\?(?:[= ]|php)").until_after(r"\?>") + self.erb = pattern.starting_with(r"<%[^%]").until_after(r"[^%]%>") + # django coflicts with handlebars a bit. + self.django = pattern.starting_with(r"{%").until_after(r"%}") + self.django_value = pattern.starting_with(r"{{").until_after(r"}}") + self.django_comment = pattern.starting_with(r"{#").until_after(r"#}") + self.smarty_value = pattern.starting_with(r"{(?=[^}{\s\n])").until_after(r"}") + self.smarty_comment = pattern.starting_with(r"{\*").until_after(r"\*}") + self.smarty_literal = pattern.starting_with(r"{literal}").until_after( + r"{/literal}" + ) + + +class TemplatablePattern(Pattern): + def __init__(self, input_scanner, parent=None): + Pattern.__init__(self, input_scanner, parent) + self.__template_pattern = None + self._disabled = TemplateNames() + self._excluded = TemplateNames() + + if parent is not None: + self.__template_pattern = self._input.get_regexp(parent.__template_pattern) + self._disabled = copy.copy(parent._disabled) + self._excluded = copy.copy(parent._excluded) + + self.__patterns = TemplatePatterns(input_scanner) + + def _create(self): + return TemplatablePattern(self._input, self) + + def _update(self): + self.__set_templated_pattern() + + def read_options(self, options): + result = self._create() + for language in ["django", "erb", "handlebars", "php", "smarty", "angular"]: + setattr(result._disabled, language, not (language in options.templating)) + result._update() + return result + + def disable(self, language): + result = self._create() + setattr(result._disabled, language, True) + result._update() + return result + + def exclude(self, language): + result = self._create() + setattr(result._excluded, language, True) + result._update() + return result + + def read(self): + result = "" + if bool(self._match_pattern): + result = self._input.read(self._starting_pattern) + else: + result = self._input.read(self._starting_pattern, self.__template_pattern) + + next = self._read_template() + + while bool(next): + if self._match_pattern is not None: + next += self._input.read(self._match_pattern) + else: + next += self._input.readUntil(self.__template_pattern) + + result += next + next = self._read_template() + + if self._until_after: + result += self._input.readUntilAfter(self._until_after) + + return result + + def __set_templated_pattern(self): + items = list() + + if not self._disabled.php: + items.append(self.__patterns.php._starting_pattern.pattern) + + if not self._disabled.handlebars: + items.append(self.__patterns.handlebars._starting_pattern.pattern) + + if not self._disabled.erb: + items.append(self.__patterns.erb._starting_pattern.pattern) + + if not self._disabled.django: + items.append(self.__patterns.django._starting_pattern.pattern) + # The starting pattern for django is more complex because it has different + # patterns for value, comment, and other sections + items.append(self.__patterns.django_value._starting_pattern.pattern) + items.append(self.__patterns.django_comment._starting_pattern.pattern) + + if not self._disabled.smarty: + items.append(self.__patterns.smarty._starting_pattern.pattern) + + if self._until_pattern: + items.append(self._until_pattern.pattern) + + self.__template_pattern = self._input.get_regexp(r"(?:" + "|".join(items) + ")") + + def _read_template(self): + resulting_string = "" + c = self._input.peek() + if c == "<": + peek1 = self._input.peek(1) + if not self._disabled.php and not self._excluded.php and peek1 == "?": + resulting_string = resulting_string or self.__patterns.php.read() + + if not self._disabled.erb and not self._excluded.erb and peek1 == "%": + resulting_string = resulting_string or self.__patterns.erb.read() + elif c == "{": + if not self._disabled.handlebars and not self._excluded.handlebars: + resulting_string = ( + resulting_string or self.__patterns.handlebars_comment.read() + ) + resulting_string = ( + resulting_string or self.__patterns.handlebars_unescaped.read() + ) + resulting_string = resulting_string or self.__patterns.handlebars.read() + if not self._disabled.django: + # django coflicts with handlebars a bit. + if not self._excluded.django and not self._excluded.handlebars: + resulting_string = ( + resulting_string or self.__patterns.django_value.read() + ) + if not self._excluded.django: + resulting_string = ( + resulting_string or self.__patterns.django_comment.read() + ) + resulting_string = resulting_string or self.__patterns.django.read() + if not self._disabled.smarty: + # smarty cannot be enabled with django or handlebars enabled + + if self._disabled.django and self._disabled.handlebars: + resulting_string = ( + resulting_string or self.__patterns.smarty_comment.read() + ) + resulting_string = ( + resulting_string or self.__patterns.smarty_literal.read() + ) + + resulting_string = resulting_string or self.__patterns.smarty.read() + + return resulting_string diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/token.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/token.py new file mode 100644 index 0000000..50013ea --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/token.py @@ -0,0 +1,38 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +class Token: + def __init__(self, type, text, newlines=0, whitespace_before=""): + self.type = type + self.text = text + self.comments_before = None + self.newlines = newlines + self.whitespace_before = whitespace_before + self.parent = None + self.next = None + self.previous = None + self.opened = None + self.closed = None + self.directives = None diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenizer.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenizer.py new file mode 100644 index 0000000..35056fa --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenizer.py @@ -0,0 +1,138 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re +from ..core.inputscanner import InputScanner +from ..core.token import Token +from ..core.tokenstream import TokenStream +from ..core.pattern import Pattern +from ..core.whitespacepattern import WhitespacePattern + +__all__ = ["TOKEN", "Tokenizer", "TokenizerPatterns", "TokenTypes"] + + +class TokenTypes: + START = "TK_START" + RAW = "TK_RAW" + EOF = "TK_EOF" + + def __init__(self): + pass + + +TOKEN = TokenTypes() + + +class TokenizerPatterns: + def __init__(self, input_scanner): + self.whitespace = WhitespacePattern(input_scanner) + + +class Tokenizer: + def __init__(self, input_string, options): + self._input = InputScanner(input_string) + self._options = options + self.__tokens = None + + self._patterns = TokenizerPatterns(self._input) + + def tokenize(self): + self._input.restart() + self.__tokens = TokenStream() + + current = None + previous = Token(TOKEN.START, "") + open_token = None + open_stack = [] + comments = TokenStream() + + while previous.type != TOKEN.EOF: + current = self.__get_next_token_with_comments(previous, open_token) + + if self._is_opening(current): + open_stack.append(open_token) + open_token = current + elif open_token is not None and self._is_closing(current, open_token): + current.opened = open_token + open_token.closed = current + open_token = open_stack.pop() + current.parent = open_token + + self.__tokens.add(current) + previous = current + return self.__tokens + + def __get_next_token_with_comments(self, previous, open_token): + current = self._get_next_token(previous, open_token) + + if self._is_comment(current): + comments = TokenStream() + while self._is_comment(current): + comments.add(current) + current = self._get_next_token(previous, open_token) + + if not comments.isEmpty(): + current.comments_before = comments + comments = TokenStream() + + current.parent = open_token + current.previous = previous + previous.next = current + + return current + + def _is_first_token(self): + return self.__tokens.isEmpty() + + def _reset(self): + pass + + def _get_next_token(self, previous_token, open_token): + self._readWhitespace() + resulting_string = self._input.read(re.compile(r".+")) + if resulting_string: + return self._create_token(TOKEN.RAW, resulting_string) + else: + return self._create_token(TOKEN.EOF, "") + + def _is_comment(self, current_token): + return False + + def _is_opening(self, current_token): + return False + + def _is_closing(self, current_token, open_token): + return False + + def _create_token(self, token_type, text): + token = Token( + token_type, + text, + self._patterns.whitespace.newline_count, + self._patterns.whitespace.whitespace_before_token, + ) + return token + + def _readWhitespace(self): + return self._patterns.whitespace.read() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenstream.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenstream.py new file mode 100644 index 0000000..63c6412 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/tokenstream.py @@ -0,0 +1,74 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re +from ..core.inputscanner import InputScanner +from ..core.token import Token + + +class TokenStream: + def __init__(self, parent_token=None): + self.__tokens = [] + self.__tokens_length = len(self.__tokens) + self.__position = 0 + self.__parent_token = parent_token + + def restart(self): + self.__position = 0 + + def isEmpty(self): + return self.__tokens_length == 0 + + def hasNext(self): + return self.__position < self.__tokens_length + + def next(self): + if self.hasNext(): + val = self.__tokens[self.__position] + self.__position += 1 + return val + else: + raise StopIteration + + def peek(self, index=0): + val = None + index += self.__position + if index >= 0 and index < self.__tokens_length: + val = self.__tokens[index] + + return val + + def add(self, token): + if self.__parent_token: + token.parent = self.__parent_token + + self.__tokens.append(token) + self.__tokens_length += 1 + + def __iter__(self): + self.restart() + return self + + def __next__(self): + return self.next() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/core/whitespacepattern.py b/venv/lib/python3.11/site-packages/jsbeautifier/core/whitespacepattern.py new file mode 100644 index 0000000..7abd298 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/core/whitespacepattern.py @@ -0,0 +1,73 @@ +# The MIT License (MIT) +# +# Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import re +from ..core.pattern import Pattern + +__all__ = ["WhitespacePattern"] + + +class WhitespacePattern(Pattern): + def __init__(self, input_scanner, parent=None): + Pattern.__init__(self, input_scanner, parent) + + if parent is not None: + self._newline_regexp = self._input.get_regexp(parent._newline_regexp) + else: + self.__set_whitespace_patterns("", "") + + self.newline_count = 0 + self.whitespace_before_token = "" + + def __set_whitespace_patterns(self, whitespace_chars, newline_chars): + whitespace_chars += "\\t " + newline_chars += "\\n\\r" + + self._match_pattern = self._input.get_regexp( + "[" + whitespace_chars + newline_chars + "]+" + ) + self._newline_regexp = self._input.get_regexp("\\r\\n|[" + newline_chars + "]") + + def read(self): + self.newline_count = 0 + self.whitespace_before_token = "" + + resulting_string = self._input.read(self._match_pattern) + if resulting_string == " ": + self.whitespace_before_token = " " + elif bool(resulting_string): + lines = self._newline_regexp.split(resulting_string) + self.newline_count = len(lines) - 1 + self.whitespace_before_token = lines[-1] + + return resulting_string + + def matching(self, whitespace_chars, newline_chars): + result = self._create() + result.__set_whitespace_patterns(whitespace_chars, newline_chars) + result._update() + return result + + def _create(self): + return WhitespacePattern(self._input, self) |