Files
edx-platform/common/lib/xmodule/xmodule/static_content.py

108 lines
3.3 KiB
Python

"""
This module has utility functions for gathering up the static content
that is defined by XModules and XModuleDescriptors (javascript and css)
"""
import hashlib
import os
import errno
from collections import defaultdict
from .x_module import XModuleDescriptor
def write_module_styles(output_root, extra_descriptors):
return _write_styles('.xmodule_display', output_root, _list_modules(extra_descriptors))
def write_module_js(output_root, extra_descriptors):
return _write_js(output_root, _list_modules(extra_descriptors))
def write_descriptor_styles(output_root, extra_descriptors):
return _write_styles('.xmodule_edit', output_root, _list_descriptors(extra_descriptors))
def write_descriptor_js(output_root, extra_descriptors):
return _write_js(output_root, _list_descriptors(extra_descriptors))
def _list_descriptors(extra_descriptors):
return [
desc for desc in [
desc for (_, desc) in XModuleDescriptor.load_classes()
] + extra_descriptors
]
def _list_modules(extra_descriptors):
return [
desc.module_class
for desc
in _list_descriptors(extra_descriptors)
]
def _ensure_dir(dir_):
try:
os.makedirs(dir_)
except OSError as exc:
if exc.errno == errno.EEXIST:
pass
else:
raise
def _write_styles(selector, output_root, classes):
_ensure_dir(output_root)
css_fragments = defaultdict(set)
for class_ in classes:
class_css = class_.get_css()
for filetype in ('sass', 'scss', 'css'):
for idx, fragment in enumerate(class_css.get(filetype, [])):
css_fragments[idx, filetype, fragment].add(class_.__name__)
css_imports = defaultdict(set)
for (idx, filetype, fragment), classes in sorted(css_fragments.items()):
fragment_name = "{idx}-{hash}.{type}".format(
idx=idx,
hash=hashlib.md5(fragment).hexdigest(),
type=filetype)
# Prepend _ so that sass just includes the files into a single file
with open(output_root / '_' + fragment_name, 'w') as css_file:
css_file.write(fragment)
for class_ in classes:
css_imports[class_].add(fragment_name)
with open(output_root / '_module-styles.scss', 'w') as module_styles:
for class_, fragment_names in css_imports.items():
imports = "\n".join('@import "{0}";'.format(name) for name in fragment_names)
module_styles.write("""{selector}.xmodule_{class_} {{ {imports} }}""".format(
class_=class_, imports=imports, selector=selector
))
def _write_js(output_root, classes):
_ensure_dir(output_root)
js_fragments = set()
for class_ in classes:
module_js = class_.get_javascript()
for filetype in ('coffee', 'js'):
for idx, fragment in enumerate(module_js.get(filetype, [])):
js_fragments.add((idx, filetype, fragment))
module_js = []
for idx, filetype, fragment in sorted(js_fragments):
path = output_root / "{idx}-{hash}.{type}".format(
idx=idx,
hash=hashlib.md5(fragment).hexdigest(),
type=filetype)
with open(path, 'w') as js_file:
js_file.write(fragment)
module_js.append(path)
return module_js