"""Some various utilities."""
from os import remove
from os.path import join, exists, basename
from re import finditer as re_finditer, sub as re_sub
from base64 import b64encode
from json import load as json_load, dumps as json_dumps
from json.decoder import JSONDecodeError
from cioprocessor.lib.utils import select_files
from .i18n import _, translate
# =============================================================================
[docs]
def special_protect(content):
"""Convert special characters (&, <, >) in a secure representation.
:param str content:
Content to protect.
:rtype: str
"""
return content\
.replace('&', '&').replace(' ', '‧')\
.replace('<', '<').replace('>', '>') \
if content else ''
# =============================================================================
[docs]
def special_unprotect(content):
"""Cancel the protection made by _special_protect().
:param str content:
Protected content.
:rtype: str
"""
return content\
.replace('&', '&').replace('‧', ' ')\
.replace('<', '<').replace('>', '>').replace('’', "'") \
if content else ''
# =============================================================================
[docs]
def image_base64(pbuild, abs_path, html):
""""Replace image source with its content in base64.
:type pbuild: .lib.pbuild.PBuild
:param pbuild:
Current processor build object.
:param str abs_path:
Absolute path to current directory.
:param str html:
HTML to process.
:rtype: str
"""
modified = False
for match in re_finditer(r'src="((.*)\?cioreplace=(base64))"', html):
filename = join(abs_path, match.group(2))
if not exists(filename):
pbuild.warning(translate(
_('${f} does not exist.', {'f': match.group(2)}), pbuild.lang))
continue
with open(filename, 'rb') as hdl:
encoded = b64encode(hdl.read())
html = html.replace(
match.group(1),
'data:image/png;base64,{0}'.format(encoded.decode("utf-8")))
modified = True
return html if modified else None
# =============================================================================
[docs]
def remove_css_maps(pbuild, step):
"""Remove CSS maps and their call.
:type build: cioprocessor.lib.build.PBuild
:param build:
Current build object.
:param dict step:
Dictionary defining the current step.
"""
if not pbuild.current['values'].get('remove_css_map'):
return
if 'select' not in step:
step['select'] = '\\.css$'
for path in select_files(pbuild, step):
map_file = '{}.map'.format(path)
if exists(map_file):
remove(map_file)
with open(path, 'r', encoding='utf8') as hdl:
content = hdl.read()
content = re_sub('/\\*# sourceMappingURL=[^*]+\\*/', '', content)
with open(path, 'w', encoding='utf8') as hdl:
hdl.write(content)
# =============================================================================
[docs]
def ajust_css_maps(pbuild, step):
"""Ajust CSS maps and their call.
:type build: cioprocessor.lib.build.PBuild
:param build:
Current build object.
:param dict step:
Dictionary defining the current step.
"""
if 'select' not in step:
step['select'] = '\\.css$'
for path in select_files(pbuild, step):
with open(path, 'r', encoding='utf8') as hdl:
content = hdl.read()
content = re_sub(
'/\\*# sourceMappingURL=[^*]+\\*/',
f'/*# sourceMappingURL={basename(path)}.map */', content)
with open(path, 'w', encoding='utf8') as hdl:
hdl.write(content)
# =============================================================================
[docs]
def pretty_print_json(pbuild, step):
"""Pretty print JSON files.
:type build: cioprocessor.lib.build.PBuild
:param build:
Current build object.
:param dict step:
Dictionary defining the current step.
:rtype: bool
"""
if 'select' not in step:
step['select'] = '\\.json$'
has_error = False
for path in select_files(pbuild, step):
with open(path, 'r', encoding='utf8') as hdl:
try:
json = json_load(hdl)
except (OSError, JSONDecodeError) as error:
pbuild.error(translate(
_('JSON: ${e}', {'e': error}), pbuild.lang))
has_error = True
continue
with open(path, 'w', encoding='utf8') as hdl:
hdl.write(json_dumps(json, indent=4, ensure_ascii=False))
return has_error