Repository: benbusby/whoogle-search
File: app/utils/results.py (Python)

Code before:
    'wikipedia.org': os.getenv('WHOOGLE_ALT_WIKI', 'farside.link/wikiless'),
    'imdb.com': os.getenv('WHOOGLE_ALT_IMDB', 'farside.link/libremdb'),
    'quora.com': os.getenv('WHOOGLE_ALT_QUORA', 'farside.link/quetre')
}


def contains_cjko(s: str) -> bool:
    """This function check whether or not a string contains Chinese, Japanese,
    or Korean characters. It employs regex and uses the u escape sequence to
    match any character in the following Unicode ranges:
    - 4e00-9fff: Chinese characters
    - 3040-309f: Japanese hiragana
    - 30a0-30ff: Japanese katakana
    - 4e00-9faf: Japanese kanji
    - ac00-d7af: Korean hangul syllables
    - 1100-11ff: Korean hangul jamo

    Args:
        s (str): string to be checked

    Returns:
        bool: True if the input s contains the characters and False otherwise
    """
    return bool(
        re.search(
            r'[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\u4e00-\u9faf\uac00-\ud7af\u1100-\u11ff]', s))


def bold_search_terms(response: str, query: str) -> BeautifulSoup:
    """Wraps all search terms in bold tags (<b>). If any terms are wrapped
    in quotes, only that exact phrase will be made bold.

    Args:
        response: The initial response body for the query
        query: The original search query

    Returns:
        BeautifulSoup: modified soup object with bold items
    """
    response = BeautifulSoup(response, 'html.parser')

    def replace_any_case(element: NavigableString, target_word: str) -> None:
        # Replace all instances of the word, but maintaining the same case in
        # the replacement
        if len(element) == len(target_word):
            return

        # Ensure target word is escaped for regex
        target_word = re.escape(target_word)

        # Check if the word contains Chinese, Japanese, or Korean characters

Review comment (security):
I think I'd prefer if the unicode ranges were defined inline with the code instead of in the function documentation. That way it's a bit easier to visually parse if/when one of the ranges ever needs to be updated in the future, and the change would only have to be made to one spot. Thoughts?

```suggestion
def contains_cjko(s: str) -> bool:
    """This function check whether or not a string contains Chinese, Japanese,
    or Korean characters. It employs regex and uses the u escape sequence to
    match any character in a set of Unicode ranges.

    Args:
        s (str): string to be checked

    Returns:
        bool: True if the input s contains the characters and False otherwise
    """
    unicode_ranges = ('\u4e00-\u9fff' # Chinese characters
                      '\u3040-\u309f' # Japanese hiragana
                      '\u30a0-\u30ff' # Japanese katakana
                      '\u4e00-\u9faf' # Japanese kanji
                      '\uac00-\ud7af' # Korean hangul syllables
                      '\u1100-\u11ff' # Korean hangul jamo
                      )
    return bool(re.search(fr'[{unicode_ranges}]', s))
```

Code after:
    'wikipedia.org': os.getenv('WHOOGLE_ALT_WIKI', 'farside.link/wikiless'),
    'imdb.com': os.getenv('WHOOGLE_ALT_IMDB', 'farside.link/libremdb'),
    'quora.com': os.getenv('WHOOGLE_ALT_QUORA', 'farside.link/quetre')
}


def contains_cjko(s: str) -> bool:
    """This function check whether or not a string contains Chinese, Japanese,
    or Korean characters. It employs regex and uses the u escape sequence to
    match any character in a set of Unicode ranges.

    Args:
        s (str): string to be checked

    Returns:
        bool: True if the input s contains the characters and False otherwise
    """
    unicode_ranges = ('\u4e00-\u9fff' # Chinese characters
                      '\u3040-\u309f' # Japanese hiragana
                      '\u30a0-\u30ff' # Japanese katakana
                      '\u4e00-\u9faf' # Japanese kanji
                      '\uac00-\ud7af' # Korean hangul syllables
                      '\u1100-\u11ff' # Korean hangul jamo
                      )
    return bool(re.search(fr'[{unicode_ranges}]', s))


def bold_search_terms(response: str, query: str) -> BeautifulSoup:
    """Wraps all search terms in bold tags (<b>). If any terms are wrapped
    in quotes, only that exact phrase will be made bold.

    Args:
        response: The initial response body for the query
        query: The original search query

    Returns:
        BeautifulSoup: modified soup object with bold items
    """
    response = BeautifulSoup(response, 'html.parser')

    def replace_any_case(element: NavigableString, target_word: str) -> None:
        # Replace all instances of the word, but maintaining the same case in
        # the replacement
        if len(element) == len(target_word):
            return

        # Ensure target word is escaped for regex
        target_word = re.escape(target_word)

        # Check if the word contains Chinese, Japanese, or Korean characters
        if contains_cjko(target_word):