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

feat: [AXM-755] save external files and fonts to offline block content #2583

Merged
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
15 changes: 15 additions & 0 deletions openedx/features/offline_mode/assets_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,18 @@ def save_mathjax_to_xblock_assets(temp_dir):
file.write(response.content)

log.info(f"Successfully saved MathJax to {file_path}")


def save_external_file(temp_dir, link, filename):
"""
Save external file to the local directory.
"""
file_path = os.path.join(temp_dir, filename)
try:
response = requests.get(link)
except requests.exceptions.RequestException as e:
log.error(f"Failed to download {link}: {e}")
else:
create_subdirectories_for_asset(file_path)
with open(file_path, 'wb') as file:
file.write(response.content)
38 changes: 37 additions & 1 deletion openedx/features/offline_mode/html_manipulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
"""
import os
import re
import uuid

from bs4 import BeautifulSoup

from django.conf import settings

from .assets_management import save_asset_file, save_mathjax_to_xblock_assets
from .assets_management import save_asset_file, save_external_file, save_mathjax_to_xblock_assets
from .constants import MATHJAX_CDN_URL, MATHJAX_STATIC_PATH


Expand All @@ -33,6 +34,8 @@ def process_html(self):
self._replace_asset_links()
self._replace_static_links()
self._replace_mathjax_link()
self._replace_external_links()
self._copy_platform_fonts()

soup = BeautifulSoup(self.html_data, 'html.parser')
self._replace_iframe(soup)
Expand Down Expand Up @@ -79,6 +82,39 @@ def _replace_link(self, match):
save_asset_file(self.temp_dir, self.xblock, link, filename)
return f'assets/{filename}'

def _replace_external_links(self):
"""
Replace external links to images and js files with local links.
"""
pattern = re.compile(r'https:\/\/[^"\s]+?\.(js|jpe?g|png|gif|bmp|svg)')
self.html_data = pattern.sub(self._replace_external_link, self.html_data)

def _replace_external_link(self, match):
"""
Returns the local path of the external file.

Downloads the external file and saves it to the local directory.
"""
link = match.group()
file_extension = match.group(1)
unique_id = uuid.uuid4()
filename = f"assets/external/{unique_id}.{file_extension}"
save_external_file(self.temp_dir, link, filename)

return filename

def _copy_platform_fonts(self):
"""
Copy platform fonts to the block temp directory.
"""
platform_fonts_dir = "xmodule/js/common_static/fonts/vendor/"
block_fonts_path = os.path.join(self.temp_dir, "assets", "fonts", "vendor")
os.makedirs(block_fonts_path)
for font in os.listdir(platform_fonts_dir):
font_path = os.path.join(platform_fonts_dir, font)
if os.path.isfile(font_path):
os.system(f'cp {font_path} {block_fonts_path}')

@staticmethod
def _replace_iframe(soup):
"""
Expand Down
Loading