Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for base64 images #56

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions text2qti/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def main():
'Consider creating solutions and QTI together, or setting a seed for the random number generator so it is reproducible.')
parser.add_argument('file',
help='File to convert from text to QTI')
parser.add_argument('--images-base64', action='store_const', const=True,
help='Save images as base64-encoded data URIs in the HTML file')
args = parser.parse_args()

config = Config()
Expand Down Expand Up @@ -91,6 +93,9 @@ def main():
if args.pandoc_mathml is not None:
config['pandoc_mathml'] = args.pandoc_mathml

if args.images_base64 is not None:
config['images_base64'] = args.images_base64

file_path = pathlib.Path(args.file).expanduser()
file_path_abs = file_path.absolute()
try:
Expand Down
2 changes: 2 additions & 0 deletions text2qti/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ def __init__(self, *args, **kwargs):
_defaults = {
'pandoc_mathml': False,
'run_code_blocks': False,
'images_base64': False,
}
_key_check = {
'latex_render_url': lambda x: isinstance(x, str),
'pandoc_mathml': lambda x: isinstance(x, bool),
'run_code_blocks': lambda x: isinstance(x, bool),
'images_base64': lambda x: isinstance(x, bool),
}
_config_path = pathlib.Path('~/.text2qti.bespon').expanduser()

Expand Down
29 changes: 27 additions & 2 deletions text2qti/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@


import atexit
import base64
import hashlib
import json
import pathlib
Expand Down Expand Up @@ -117,8 +118,29 @@ def handleMatch(self, match, data):
node.attrib['src'] = image.src_path
return node, start, end

class Text2qtiBase64ImagePattern(ImageInlineProcessor):
'''
Custom image processor for Python-Markdown that converts images to base64
and also accumulates all image data for QTI inclusion.
'''
def __init__(self, pattern_re, markdown_md, text2qti_md):
super().__init__(pattern_re, markdown_md)
self.text2qti_md = text2qti_md


def handleMatch(self, match, data):
node, start, end = super().handleMatch(match, data)
src = node.attrib.get('src')
if src and not any(src.startswith(x) for x in ('http://', 'https://')):
src_path = pathlib.Path(src).expanduser()
try:
data = src_path.read_bytes()
except FileNotFoundError:
raise Text2qtiError(f'File "{src_path}" does not exist')
except PermissionError as e:
raise Text2qtiError(f'File "{src_path}" cannot be read due to permission error:\n{e}')
base64image = base64.b64encode(data).decode('ascii')
node.attrib['src'] = 'data:image/jpeg;base64,{}'.format(base64image)
return node, start, end

class Markdown(object):
r'''
Expand All @@ -135,7 +157,10 @@ def __init__(self, config: Optional[Config]=None):
self.config = config

markdown_processor = markdown.Markdown(extensions=md_extensions)
markdown_image_processor = Text2qtiImagePattern(IMAGE_LINK_RE, markdown_processor, self)
if config is not None and config['images_base64']:
markdown_image_processor = Text2qtiBase64ImagePattern(IMAGE_LINK_RE, markdown_processor, self)
else:
markdown_image_processor = Text2qtiImagePattern(IMAGE_LINK_RE, markdown_processor, self)
markdown_processor.inlinePatterns.register(markdown_image_processor, 'image_link', 150)
self.markdown_processor = markdown_processor

Expand Down