diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index 7846766a7c..4cabd08403 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -148,3 +148,4 @@ SECRET_KEY = uuid.uuid4().hex ############################### PIPELINE ####################################### PIPELINE_ENABLED = False +REQUIRE_DEBUG = True diff --git a/cms/envs/common.py b/cms/envs/common.py index 64d5d95495..0a4522be3f 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1128,6 +1128,9 @@ INSTALLED_APPS = [ # Entitlements, used in openedx tests 'entitlements', + + # Asset management for mako templates + 'pipeline_mako', ] diff --git a/cms/static/cms/js/build.js b/cms/static/cms/js/build.js index a88009f2b3..d0221be3a9 100644 --- a/cms/static/cms/js/build.js +++ b/cms/static/cms/js/build.js @@ -28,7 +28,7 @@ 'js/certificates/factories/certificates_page_factory', 'js/factories/index', 'js/factories/library', - 'js/factories/login', + 'js/pages/login', 'js/factories/manage_users', 'js/factories/outline', 'js/factories/register', diff --git a/cms/static/js/factories/login.js b/cms/static/js/factories/login.js index 7d080cdb2b..fdbcef31e8 100644 --- a/cms/static/js/factories/login.js +++ b/cms/static/js/factories/login.js @@ -1,6 +1,6 @@ define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], function(cookie, utility, ViewUtils) { 'use strict'; - return function(homepageURL) { + return function LoginFactory(homepageURL) { function postJSON(url, data, callback) { $.ajax({ type: 'POST', diff --git a/cms/static/js/pages/login.js b/cms/static/js/pages/login.js new file mode 100644 index 0000000000..8c53644675 --- /dev/null +++ b/cms/static/js/pages/login.js @@ -0,0 +1,11 @@ +(function(define) { + 'use strict'; + + define( + ['js/factories/login', 'common/js/utils/page_factory'], + function(LoginFactory, invokePageFactory) { + invokePageFactory('LoginFactory', LoginFactory); + } + ); +}).call(this, define || RequireJS.define); + diff --git a/cms/templates/base.html b/cms/templates/base.html index 64a2a03668..1736677f2a 100644 --- a/cms/templates/base.html +++ b/cms/templates/base.html @@ -143,6 +143,7 @@ from openedx.core.djangolib.markup import HTML }); }); + <%block name='requirejs_page'> <%include file="widgets/segment-io-footer.html" /> diff --git a/cms/templates/login.html b/cms/templates/login.html index 205e64f3cd..7981ae6dc4 100644 --- a/cms/templates/login.html +++ b/cms/templates/login.html @@ -54,8 +54,8 @@ from openedx.core.djangolib.js_utils import js_escaped_string -<%block name="requirejs"> - require(["js/factories/login"], function(LoginFactory) { - LoginFactory("${reverse('homepage') | n, js_escaped_string}"); - }); +<%block name="requirejs_page"> + <%static:require_page page_name="js/pages/login" class_name="LoginFactory"> + "${reverse('homepage') | n, js_escaped_string}" + diff --git a/common/djangoapps/pipeline_mako/templates/static_content.html b/common/djangoapps/pipeline_mako/templates/static_content.html index 32b1da801c..68e3cd6175 100644 --- a/common/djangoapps/pipeline_mako/templates/static_content.html +++ b/common/djangoapps/pipeline_mako/templates/static_content.html @@ -111,7 +111,7 @@ source, template_path = Loader(engine).load_template_source(path) ${HTML(render_bundle(page))} -<%def name="webpack(entry)"> +<%def name="webpack(entry, extension=None, config='DEFAULT', attrs='')"> <%doc> Loads Javascript onto your page from a Webpack-generated bundle. Uses the Django template engine because our webpack loader only provides template tags for Jinja and Django. @@ -119,7 +119,7 @@ source, template_path = Loader(engine).load_template_source(path) <% body = capture(caller.body) %> - ${HTML(render_bundle(entry))} + ${HTML(render_bundle(entry, extension=None, config='DEFAULT', attrs=attrs))} % if body: +<%def name="require_page(page_name, class_name)"> + <%doc> + Loads Javascript onto your page synchronously. + Uses RequireJS in development and a plain script tag in production. + The body of the tag should be a comma-separated list of arguments + to be passed to the page factory specified by the class_name argument. + + <% + body = capture(caller.body) + %> + + % if not settings.REQUIRE_DEBUG: + + % endif + + + <%def name="require_module(module_name, class_name)"> <%doc> Loads Javascript onto your page synchronously. diff --git a/common/static/common/js/utils/page_factory.js b/common/static/common/js/utils/page_factory.js new file mode 100644 index 0000000000..8b3e72c827 --- /dev/null +++ b/common/static/common/js/utils/page_factory.js @@ -0,0 +1,27 @@ +define([], function() { + 'use strict'; + + return function invokePageFactory(name, factory) { + var args; + + if (typeof window.pageFactoryArguments === 'undefined') { + throw Error( + 'window.pageFactoryArguments must be initialized before calling invokePageFactory(' + + name + + '). Use the <%static:require_page> template tag.' + ); + } + args = window.pageFactoryArguments[name]; + + if (typeof args === 'undefined') { + throw Error( + 'window.pageFactoryArguments["' + + name + + '"] must be initialized before calling invokePageFactory(' + + name + + '). Use the <%static:require_page> template tag.' + ); + } + factory.apply(null, window.pageFactoryArguments[name]); + }; +}); diff --git a/common/test/test-theme/cms/templates/login.html b/common/test/test-theme/cms/templates/login.html index a5faf86f1c..8479674153 100644 --- a/common/test/test-theme/cms/templates/login.html +++ b/common/test/test-theme/cms/templates/login.html @@ -1,3 +1,4 @@ +<%namespace name='static' file='/static_content.html'/> <%page expression_filter="h"/> <%inherit file="base.html" /> @@ -51,8 +52,8 @@ from openedx.core.djangolib.js_utils import js_escaped_string -<%block name="requirejs"> - require(["js/factories/login"], function(LoginFactory) { - LoginFactory("${reverse('homepage') | n, js_escaped_string }"); - }); +<%block name="requirejs_page"> + <%static:require_page page_name="js/pages/login" class_name="LoginFactory"> + "${reverse('homepage') | n, js_escaped_string}" + diff --git a/conftest.py b/conftest.py index 1f32a76982..513e5f762d 100644 --- a/conftest.py +++ b/conftest.py @@ -14,5 +14,5 @@ from cms.conftest import _django_clear_site_cache, pytest_configure # pylint: d def no_webpack_loader(monkeypatch): monkeypatch.setattr( "webpack_loader.templatetags.webpack_loader.render_bundle", - lambda x: '' + lambda entry, extension=None, config='DEFAULT', attrs='': '' ) diff --git a/scripts/xss_linter.py b/scripts/xss_linter.py index db32f31cfe..d1d0fe0d07 100755 --- a/scripts/xss_linter.py +++ b/scripts/xss_linter.py @@ -314,7 +314,7 @@ class RuleViolation(object): found. """ - pragma_match = re.search(r'xss-lint:\s*disable=([a-zA-Z,-]+)', string) + pragma_match = re.search(r'xss-lint:\s*disable=([a-zA-Z,\- ]+)', string) if pragma_match is None: return if scope_start_string: @@ -324,7 +324,7 @@ class RuleViolation(object): return for disabled_rule in pragma_match.group(1).split(','): - if disabled_rule == self.rule.rule_id: + if disabled_rule.strip() == self.rule.rule_id: self.is_disabled = True return @@ -2383,6 +2383,8 @@ class MakoTemplateLinter(BaseLinter): | # script tag end <%static:require_module(_async)?.*?> | # require js script tag start (optionally the _async version) | # require js script tag end (optionally the _async version) + <%static:require_page.*?> | # require js script tag start + | # require js script tag end <%static:webpack.*?> | # webpack script tag start | # webpack script tag end <%static:studiofrontend.*?> | # studiofrontend script tag start diff --git a/themes/red-theme/cms/templates/login.html b/themes/red-theme/cms/templates/login.html index 8f9274f7a4..b50ed21855 100644 --- a/themes/red-theme/cms/templates/login.html +++ b/themes/red-theme/cms/templates/login.html @@ -1,3 +1,4 @@ +<%namespace name='static' file='/static_content.html'/> <%page expression_filter="h"/> <%inherit file="base.html" /> @@ -50,8 +51,8 @@ from django.utils.translation import ugettext as _ -<%block name="requirejs"> - require(["js/factories/login"], function(LoginFactory) { - LoginFactory("${reverse('homepage')}"); - }); +<%block name="requirejs_page"> + <%static:require_page page_name="js/pages/login" class_name="LoginFactory"> + "${reverse('homepage') | n, js_escaped_string}" +