Allow for modular css from XModules, and split capa module css out as a test
This commit is contained in:
@@ -24,6 +24,7 @@ import tempfile
|
||||
import glob2
|
||||
import errno
|
||||
import hashlib
|
||||
from collections import defaultdict
|
||||
|
||||
import djcelery
|
||||
from path import path
|
||||
@@ -336,31 +337,60 @@ main_vendor_js = [
|
||||
from xmodule.x_module import XModuleDescriptor
|
||||
from xmodule.hidden_module import HiddenDescriptor
|
||||
js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module"
|
||||
try:
|
||||
os.makedirs(js_file_dir)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
css_file_dir = PROJECT_ROOT / "static" / "sass" / "module"
|
||||
module_styles_path = css_file_dir / "_module-styles.scss"
|
||||
|
||||
fragments = set()
|
||||
for dir_ in (js_file_dir, css_file_dir):
|
||||
try:
|
||||
os.makedirs(dir_)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
js_fragments = set()
|
||||
css_fragments = defaultdict(set)
|
||||
for descriptor in XModuleDescriptor.load_classes() + [HiddenDescriptor]:
|
||||
module_js = descriptor.module_class.get_javascript()
|
||||
for filetype in ('coffee', 'js'):
|
||||
for idx, fragment in enumerate(module_js.get(filetype, [])):
|
||||
fragments.add((idx, filetype, fragment))
|
||||
js_fragments.add((idx, filetype, fragment))
|
||||
|
||||
module_css = descriptor.module_class.get_css()
|
||||
for filetype in ('sass', 'scss', 'css'):
|
||||
for idx, fragment in enumerate(module_css.get(filetype, [])):
|
||||
css_fragments[idx, filetype, fragment].add(descriptor.module_class.__name__)
|
||||
|
||||
module_js_sources = []
|
||||
for idx, filetype, fragment in sorted(fragments):
|
||||
path = os.path.join(js_file_dir, "{idx}-{hash}.{type}".format(
|
||||
for idx, filetype, fragment in sorted(js_fragments):
|
||||
path = js_file_dir / "{idx}-{hash}.{type}".format(
|
||||
idx=idx,
|
||||
hash=hashlib.md5(fragment).hexdigest(),
|
||||
type=filetype))
|
||||
type=filetype)
|
||||
with open(path, 'w') as js_file:
|
||||
js_file.write(fragment)
|
||||
module_js_sources.append(path.replace(PROJECT_ROOT / "static/", ""))
|
||||
|
||||
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(css_file_dir / '_' + fragment_name, 'w') as js_file:
|
||||
js_file.write(fragment)
|
||||
|
||||
for class_ in classes:
|
||||
css_imports[class_].add(fragment_name)
|
||||
|
||||
with open(module_styles_path, '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(""".xmodule_{class_} {{ {imports} }}""".format(
|
||||
class_=class_, imports=imports
|
||||
))
|
||||
|
||||
PIPELINE_JS = {
|
||||
'application': {
|
||||
|
||||
1
lms/static/sass/.gitignore
vendored
1
lms/static/sass/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
*.css
|
||||
module
|
||||
|
||||
@@ -20,4 +20,5 @@
|
||||
@import 'course/old/courseware/sidebar';
|
||||
@import 'course/old/courseware/video';
|
||||
@import 'course/old/courseware/amplifier';
|
||||
@import 'course/old/courseware/problems';
|
||||
|
||||
@import 'module/module-styles.scss';
|
||||
|
||||
@@ -49,142 +49,6 @@ div.course-wrapper {
|
||||
}
|
||||
}
|
||||
|
||||
.problem-set {
|
||||
position: relative;
|
||||
@extend .clearfix;
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 15px;
|
||||
width: flex-grid(2, 9);
|
||||
padding-right: flex-gutter(9);
|
||||
border-right: 1px dashed #ddd;
|
||||
@include box-sizing(border-box);
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
|
||||
&.problem-header {
|
||||
section.staff {
|
||||
margin-top: 30px;
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
display: block;
|
||||
width: auto;
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
section.problem {
|
||||
display: table-cell;
|
||||
width: flex-grid(7, 9);
|
||||
padding-left: flex-gutter(9);
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
|
||||
canvas, img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
&.unanswered, &.ui-icon-bullet {
|
||||
@include inline-block();
|
||||
background: url('../images/unanswered-icon.png') center center no-repeat;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&.correct, &.ui-icon-check {
|
||||
@include inline-block();
|
||||
background: url('../images/correct-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
&.incorrect, &.ui-icon-close {
|
||||
@include inline-block();
|
||||
background: url('../images/incorrect-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
> span {
|
||||
display: block;
|
||||
margin-bottom: lh(.5);
|
||||
|
||||
&[answer] {
|
||||
border-top: 1px solid #ededed;
|
||||
border-bottom: 1px solid #ededed;
|
||||
background: #f3f3f3;
|
||||
margin: 0 (-(lh()));
|
||||
padding: lh(.5) lh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
center {
|
||||
display: block;
|
||||
margin: lh() 0;
|
||||
border: 1px solid #ccc;
|
||||
padding: lh();
|
||||
}
|
||||
|
||||
section.action {
|
||||
margin-top: lh();
|
||||
|
||||
input[type="button"] {
|
||||
padding: lh(.4) lh();
|
||||
text-shadow: 0 -1px 0 #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.problems-wrapper, div#seq_content {
|
||||
@extend .problem-set;
|
||||
}
|
||||
|
||||
section.problems-wrapper {
|
||||
display: table;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
div#seq_content {
|
||||
h1 {
|
||||
background: none;
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
section.problem-set {
|
||||
position: relative;
|
||||
@extend .clearfix;
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 15px;
|
||||
width: flex-grid(2, 9);
|
||||
padding-right: flex-gutter(9);
|
||||
border-right: 1px dashed #ddd;
|
||||
@include box-sizing(border-box);
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
|
||||
&.problem-header {
|
||||
section.staff {
|
||||
margin-top: 30px;
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
display: block;
|
||||
width: auto;
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
section.problem {
|
||||
display: table-cell;
|
||||
width: flex-grid(7, 9);
|
||||
padding-left: flex-gutter(9);
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
|
||||
canvas, img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
p.status {
|
||||
text-indent: -9999px;
|
||||
margin: -1px 0 0 10px;
|
||||
}
|
||||
|
||||
&.unanswered {
|
||||
p.status {
|
||||
@include inline-block();
|
||||
background: url('../images/unanswered-icon.png') center center no-repeat;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&.correct, &.ui-icon-check {
|
||||
p.status {
|
||||
@include inline-block();
|
||||
background: url('../images/correct-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: green;
|
||||
}
|
||||
}
|
||||
|
||||
&.incorrect, &.ui-icon-close {
|
||||
p.status {
|
||||
@include inline-block();
|
||||
background: url('../images/incorrect-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
text-indent: -9999px;
|
||||
}
|
||||
|
||||
input {
|
||||
border-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
> span {
|
||||
display: block;
|
||||
margin-bottom: lh(.5);
|
||||
}
|
||||
|
||||
p.answer {
|
||||
@include inline-block();
|
||||
margin-bottom: 0;
|
||||
margin-left: 10px;
|
||||
|
||||
&:before {
|
||||
content: "Answer: ";
|
||||
font-weight: bold;
|
||||
display: inline;
|
||||
|
||||
}
|
||||
&:empty {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.equation {
|
||||
clear: both;
|
||||
padding: 6px;
|
||||
background: #eee;
|
||||
|
||||
span {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
&.unanswered, &.ui-icon-bullet {
|
||||
@include inline-block();
|
||||
background: url('../images/unanswered-icon.png') center center no-repeat;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&.correct, &.ui-icon-check {
|
||||
@include inline-block();
|
||||
background: url('../images/correct-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
&.incorrect, &.ui-icon-close {
|
||||
@include inline-block();
|
||||
background: url('../images/incorrect-icon.png') center center no-repeat;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: disc outside none;
|
||||
margin-bottom: lh();
|
||||
margin-left: .75em;
|
||||
margin-left: .75rem;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: decimal outside none;
|
||||
margin-bottom: lh();
|
||||
margin-left: .75em;
|
||||
margin-left: .75rem;
|
||||
}
|
||||
|
||||
dl {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: .5em;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
line-height: 1.4em;
|
||||
margin-bottom: lh(.5);
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: lh();
|
||||
}
|
||||
|
||||
table {
|
||||
margin-bottom: lh();
|
||||
width: 100%;
|
||||
// border: 1px solid #ddd;
|
||||
border-collapse: collapse;
|
||||
|
||||
th {
|
||||
// border-bottom: 2px solid #ccc;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
// border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
caption, th, td {
|
||||
padding: .25em .75em .25em 0;
|
||||
padding: .25rem .75rem .25rem 0;
|
||||
}
|
||||
|
||||
caption {
|
||||
background: #f1f1f1;
|
||||
margin-bottom: .75em;
|
||||
margin-bottom: .75rem;
|
||||
padding: .75em 0;
|
||||
padding: .75rem 0;
|
||||
}
|
||||
|
||||
tr, td, th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hr {
|
||||
background: #ddd;
|
||||
border: none;
|
||||
clear: both;
|
||||
color: #ddd;
|
||||
float: none;
|
||||
height: 1px;
|
||||
margin: 0 0 .75rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#{$all-text-inputs} {
|
||||
display: inline;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
// this supports a deprecated element and should be removed once the center tag is removed
|
||||
center {
|
||||
display: block;
|
||||
margin: lh() 0;
|
||||
border: 1px solid #ccc;
|
||||
padding: lh();
|
||||
}
|
||||
}
|
||||
|
||||
section.action {
|
||||
margin-top: lh(.5);
|
||||
|
||||
input[type="button"] {
|
||||
padding: lh(.4) lh();
|
||||
text-shadow: 0 -1px 0 #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.problems-wrapper, div#seq_content {
|
||||
@extend .problem-set;
|
||||
}
|
||||
|
||||
section.problems-wrapper {
|
||||
display: table;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (max-width:1120px) {
|
||||
display: block;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user