Skip to content

Commit

Permalink
refactor: [AXM-349] move MathJax to assets
Browse files Browse the repository at this point in the history
  • Loading branch information
NiedielnitsevIvan committed Jun 6, 2024
1 parent cf7f366 commit 7db246b
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 38 deletions.
39 changes: 21 additions & 18 deletions openedx/features/offline_mode/assets_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,31 @@ def save_asset_file(xblock, path, filename):
asset_key = StaticContent.get_asset_key_from_path(xblock.location.course_key, path)
content = AssetManager.find(asset_key).data
except (ItemNotFoundError, NotFoundError):
pass
log.info(f"Asset not found: {filename}")

else:
base_path = base_storage_path(xblock)
base_path = block_storage_path(xblock)
file_path = os.path.join(base_path, 'assets', filename)
default_storage.save(file_path, ContentFile(content))


def remove_old_files(xblock):
"""
Removes the 'asset' directory, 'index.html', and 'offline_content.zip' files
Removes the 'assets' directory, 'index.html', and 'offline_content.zip' files
in the specified base path directory.
Args:
(XBlock): The XBlock instance
"""
try:
base_path = base_storage_path(xblock)
asset_path = os.path.join(base_path, 'asset')
base_path = block_storage_path(xblock)
assets_path = os.path.join(base_path, 'assets')
index_file_path = os.path.join(base_path, 'index.html')
offline_zip_path = os.path.join(base_path, OFFLINE_CONTENT_ARCHIVE_NAME)

# Delete the 'asset' directory if it exists
if os.path.isdir(asset_path):
shutil.rmtree(asset_path)
log.info(f"Successfully deleted the directory: {asset_path}")
# Delete the 'assets' directory if it exists
if os.path.isdir(assets_path):
shutil.rmtree(assets_path)
log.info(f"Successfully deleted the directory: {assets_path}")

# Delete the 'index.html' file if it exists
if default_storage.exists(index_file_path):
Expand All @@ -104,24 +105,25 @@ def is_offline_content_present(xblock):
Returns:
bool: True if the file is present, False otherwise
"""
base_path = base_storage_path(xblock)
base_path = block_storage_path(xblock)
offline_zip_path = os.path.join(base_path, OFFLINE_CONTENT_ARCHIVE_NAME)
return default_storage.exists(offline_zip_path)


def base_storage_path(xblock):
def block_storage_path(xblock=None, usage_key=None):
"""
Generates the base storage path for the given XBlock.
The path is constructed based on the XBlock's location, which includes the organization,
course, block type, and block ID.
Args:
xblock (XBlock): The XBlock instance for which to generate the storage path.
usage_key (UsageKey): The UsageKey of the XBlock.
Returns:
str: The constructed base storage path.
"""
loc = xblock.location
return f'{loc.org}/{loc.course}/{loc.block_type}/{loc.block_id}/'
loc = usage_key or getattr(xblock, 'location', None)
return f'{loc.org}/{loc.course}/{loc.block_type}/{loc.block_id}/' if loc else ''


def is_modified(xblock):
Expand All @@ -131,7 +133,7 @@ def is_modified(xblock):
Args:
xblock (XBlock): The XBlock instance to check.
"""
file_path = os.path.join(base_storage_path(xblock), 'content_html.zip')
file_path = os.path.join(block_storage_path(xblock), 'content_html.zip')

try:
last_modified = default_storage.get_created_time(file_path)
Expand All @@ -141,14 +143,15 @@ def is_modified(xblock):
return xblock.published_on > last_modified


def save_mathjax_to_local_static():
def save_mathjax_to_xblock_assets(xblock):
"""
Saves MathJax to the local static directory.
If MathJax is not already saved, it fetches MathJax from
the CDN and saves it to the local static directory.
"""
if not default_storage.exists(MATHJAX_STATIC_PATH):
file_path = os.path.join(block_storage_path(xblock), MATHJAX_STATIC_PATH)
if not default_storage.exists(file_path):
response = requests.get(MATHJAX_CDN_URL)
default_storage.save(MATHJAX_STATIC_PATH, ContentFile(response.content))
log.info(f"Successfully saved MathJax to {MATHJAX_STATIC_PATH}")
default_storage.save(file_path, ContentFile(response.content))
log.info(f"Successfully saved MathJax to {file_path}")
2 changes: 1 addition & 1 deletion openedx/features/offline_mode/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

MATHJAX_VERSION = '2.7.5'
MATHJAX_CDN_URL = f'https://cdn.jsdelivr.net/npm/mathjax@{MATHJAX_VERSION}/MathJax.js'
MATHJAX_STATIC_PATH = os.path.join('offline_mode_shared_static', 'js', f'MathJax-{MATHJAX_VERSION}.js')
MATHJAX_STATIC_PATH = os.path.join('assets', 'js', f'MathJax-{MATHJAX_VERSION}.js')

OFFLINE_CONTENT_ARCHIVE_NAME = 'offline_content.zip'

Expand Down
15 changes: 3 additions & 12 deletions openedx/features/offline_mode/html_manipulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@

from django.conf import settings

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


# Relative path difference between the HTML content and the shared static files.
RELATIVE_PATH_DIFF = '../../../../'


class HtmlManipulator:
"""
Class to prepare HTML content for offline use.
Expand All @@ -31,11 +27,9 @@ def _replace_mathjax_link(self):
"""
Replace MathJax CDN link with local path to MathJax.js file.
"""
save_mathjax_to_xblock_assets(self.xblock)
mathjax_pattern = re.compile(fr'src="{MATHJAX_CDN_URL}[^"]*"')
self.html_data = mathjax_pattern.sub(
f'src="{RELATIVE_PATH_DIFF}{MATHJAX_STATIC_PATH}"',
self.html_data
)
self.html_data = mathjax_pattern.sub(f'src="{MATHJAX_STATIC_PATH}"', self.html_data)

def _replace_static_links(self):
"""
Expand Down Expand Up @@ -71,8 +65,6 @@ def _replace_iframe(soup):
def _add_js_bridge(soup):
"""
Add JS bridge script to the HTML content.
:param soup:
:return:
"""
script_tag = soup.new_tag('script')
with open('openedx/features/offline_mode/static/offline_mode/js/bridge.js', 'r') as file:
Expand All @@ -89,7 +81,6 @@ def process_html(self):
Changes links to static files to paths to pre-generated static files for offline use.
"""
save_mathjax_to_local_static()
self._replace_static_links()
self._replace_mathjax_link()

Expand Down
13 changes: 6 additions & 7 deletions openedx/features/offline_mode/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

from zipfile import ZipFile


from .assets_management import base_storage_path, remove_old_files, is_modified
from .assets_management import block_storage_path, remove_old_files, is_modified
from .constants import OFFLINE_CONTENT_ARCHIVE_NAME, OFFLINE_SUPPORTED_XBLOCKS
from .html_manipulator import HtmlManipulator

Expand All @@ -31,13 +30,13 @@ def add_files_to_zip(zip_file, current_base_path, current_path_in_zip):
Recursively adds files to the zip file.
"""
try:
directories, files = default_storage.listdir(current_base_path)
directories, filenames = default_storage.listdir(current_base_path)
except OSError:
return

for file_name in files:
full_path = os.path.join(current_base_path, file_name)
zip_file.write(full_path, os.path.join(current_path_in_zip, file_name))
for filename in filenames:
full_path = os.path.join(current_base_path, filename)
zip_file.write(full_path, os.path.join(current_path_in_zip, filename))

for directory in directories:
add_files_to_zip(zip_file, os.path.join(current_base_path, directory),
Expand All @@ -58,7 +57,7 @@ def generate_offline_content(xblock, html_data):
if not is_modified(xblock):
return

base_path = base_storage_path(xblock)
base_path = block_storage_path(xblock)
remove_old_files(xblock)
html_manipulator = HtmlManipulator(xblock, html_data)
updated_html = html_manipulator.process_html()
Expand Down

0 comments on commit 7db246b

Please sign in to comment.