From e170103bedd9314c40c665cf70e9abf987fc0545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=B2=D0=B0=D0=BD=20=D0=9D=D1=94=D0=B4=D1=94=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=96=D1=86=D0=B5=D0=B2?= Date: Sat, 22 Jun 2024 16:08:41 +0300 Subject: [PATCH] feat: [AXM-755] save extrnal files and fonts to offline block content --- .../offline_mode/assets_management.py | 15 ++++++++ .../features/offline_mode/html_manipulator.py | 36 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/openedx/features/offline_mode/assets_management.py b/openedx/features/offline_mode/assets_management.py index e90d00fe20d6..225990449e5f 100644 --- a/openedx/features/offline_mode/assets_management.py +++ b/openedx/features/offline_mode/assets_management.py @@ -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) diff --git a/openedx/features/offline_mode/html_manipulator.py b/openedx/features/offline_mode/html_manipulator.py index fbbca2af6494..d68bc71d4f38 100644 --- a/openedx/features/offline_mode/html_manipulator.py +++ b/openedx/features/offline_mode/html_manipulator.py @@ -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 @@ -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) @@ -79,6 +82,37 @@ 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. + """ + link = match.group() + file_extension = match.group(1) + unique_id = uuid.uuid4() + filename = f"assets/eternal/{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): """