From b5e99614c3bda5fbdc46bc378630f31345a9f402 Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Tue, 22 Apr 2014 18:53:52 -0400 Subject: [PATCH 1/7] Make TinyMCE more tolerant about HTML elements STUD-1565 --- .../contentstore/features/html-editor.feature | 22 ++++++++++++++++++- .../xmodule/xmodule/js/src/html/edit.coffee | 8 +++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/features/html-editor.feature b/cms/djangoapps/contentstore/features/html-editor.feature index a23bc4650db8..6da09b75d2b8 100644 --- a/cms/djangoapps/contentstore/features/html-editor.feature +++ b/cms/djangoapps/contentstore/features/html-editor.feature @@ -47,6 +47,26 @@ Feature: CMS.HTML Editor --> """ + Scenario: TinyMCE and CodeMirror preserve span tags + Given I have created a Blank HTML Page + When I edit the page + And type "Test" in the code editor and press OK + And I save the page + Then the page text contains: + """ + Test + """ + + Scenario: TinyMCE and CodeMirror preserve math tags + Given I have created a Blank HTML Page + When I edit the page + And type "x2" in the code editor and press OK + And I save the page + Then the page text contains: + """ + x2 + """ + Scenario: TinyMCE toolbar buttons are as expected Given I have created a Blank HTML Page When I edit the page @@ -57,7 +77,7 @@ Feature: CMS.HTML Editor When I edit the page And type "" in the code editor and press OK Then the src link is rewritten to "c4x/MITx/999/asset/image.jpg" - And the code editor displays "

" + And the code editor displays "

" Scenario: Code format toolbar button wraps text with code tags Given I have created a Blank HTML Page diff --git a/common/lib/xmodule/xmodule/js/src/html/edit.coffee b/common/lib/xmodule/xmodule/js/src/html/edit.coffee index 97e713dad538..4af098cf8999 100644 --- a/common/lib/xmodule/xmodule/js/src/html/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/html/edit.coffee @@ -48,8 +48,16 @@ class @HTMLEditingDescriptor height: '400px', menubar: false, statusbar: false, + # Necessary to avoid stripping of style tags. valid_children : "+body[style]", + + # Allow any elements to be used, e.g. link, script, math + verify_html: false, + valid_elements: "*[*]", + extended_valid_elements: "*[*]", + invalid_elements: "", + setup: @setupTinyMCE, # Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered. # The tinyMCE callback passes in the editor as a parameter. From d61abab1d882a0c953c31a97f0ae22d696861f11 Mon Sep 17 00:00:00 2001 From: Adam Palay Date: Wed, 23 Apr 2014 09:13:23 -0400 Subject: [PATCH 2/7] fixes templating error (LMS-2560) --- lms/templates/static_templates/server-error.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/templates/static_templates/server-error.html b/lms/templates/static_templates/server-error.html index cf5d79c7ce28..6fce0c9a3015 100644 --- a/lms/templates/static_templates/server-error.html +++ b/lms/templates/static_templates/server-error.html @@ -4,7 +4,7 @@

${_(u"There has been a 500 error on the {platform_name} servers").format( - platform_name=u"{}".format(platform_name=settings.PLATFORM_NAME) + platform_name=u"{platform_name}".format(platform_name=settings.PLATFORM_NAME) )}

From 4cfa280502df42eac647300c060bdd02fc5334fe Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Wed, 23 Apr 2014 09:52:23 -0400 Subject: [PATCH 3/7] Remove verify_html as it isn't supported in TinyMCE 4 --- common/lib/xmodule/xmodule/js/src/html/edit.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/js/src/html/edit.coffee b/common/lib/xmodule/xmodule/js/src/html/edit.coffee index 4af098cf8999..af0b047999f9 100644 --- a/common/lib/xmodule/xmodule/js/src/html/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/html/edit.coffee @@ -53,7 +53,6 @@ class @HTMLEditingDescriptor valid_children : "+body[style]", # Allow any elements to be used, e.g. link, script, math - verify_html: false, valid_elements: "*[*]", extended_valid_elements: "*[*]", invalid_elements: "", From ae886f1bc691f59c8a50d5539936667fc4bf9be8 Mon Sep 17 00:00:00 2001 From: cahrens Date: Tue, 22 Apr 2014 15:07:32 -0400 Subject: [PATCH 4/7] Add support for raw HTML editor. STUD-1562 --- CHANGELOG.rst | 3 + .../contentstore/features/html-editor.feature | 2 +- .../contentstore/features/html-editor.py | 9 +- cms/templates/widgets/html-edit.html | 7 +- common/lib/xmodule/xmodule/html_module.py | 11 ++ .../xmodule/js/fixtures/html-edit-visual.html | 10 ++ .../xmodule/js/fixtures/html-edit.html | 3 - .../xmodule/js/fixtures/html-editor-raw.html | 9 ++ .../xmodule/js/spec/html/edit_spec.coffee | 28 ++-- .../xmodule/xmodule/js/src/html/edit.coffee | 138 ++++++++++-------- .../xmodule/xmodule/templates/html/raw.yaml | 6 + lms/templates/widgets/html-edit.html | 15 +- 12 files changed, 156 insertions(+), 85 deletions(-) create mode 100644 common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html delete mode 100644 common/lib/xmodule/xmodule/js/fixtures/html-edit.html create mode 100644 common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html create mode 100644 common/lib/xmodule/xmodule/templates/html/raw.yaml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 01894935bd7f..dd3b57da60cf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes, in roughly chronological order, most recent first. Add your entries at or near the top. Include a label indicating the component affected. +Studio: Add "raw HTML" editor so that authors can write HTML that will not be +changed in any way. STUD-1562 + Blades: Show the HD button only if there is an HD version available. BLD-937. Studio: Add edit button to leaf xblocks on the container page. STUD-1306. diff --git a/cms/djangoapps/contentstore/features/html-editor.feature b/cms/djangoapps/contentstore/features/html-editor.feature index 6da09b75d2b8..31fcd9fd3b61 100644 --- a/cms/djangoapps/contentstore/features/html-editor.feature +++ b/cms/djangoapps/contentstore/features/html-editor.feature @@ -5,7 +5,7 @@ Feature: CMS.HTML Editor Scenario: User can view metadata Given I have created a Blank HTML Page And I edit and select Settings - Then I see only the HTML display name setting + Then I see the HTML component settings # Safari doesn't save the name properly @skip_safari diff --git a/cms/djangoapps/contentstore/features/html-editor.py b/cms/djangoapps/contentstore/features/html-editor.py index 8b1717e61759..ad1be7f13fb4 100644 --- a/cms/djangoapps/contentstore/features/html-editor.py +++ b/cms/djangoapps/contentstore/features/html-editor.py @@ -18,9 +18,14 @@ def i_created_blank_html_page(step): ) -@step('I see only the HTML display name setting$') +@step('I see the HTML component settings$') def i_see_only_the_html_display_name(step): - world.verify_all_setting_entries([['Display Name', "Text", False]]) + world.verify_all_setting_entries( + [ + ['Display Name', "Text", False], + ['Editor', "Visual", False] + ] + ) @step('I have created an E-text Written in LaTeX$') diff --git a/cms/templates/widgets/html-edit.html b/cms/templates/widgets/html-edit.html index a27225e36bc3..15cf1789657c 100644 --- a/cms/templates/widgets/html-edit.html +++ b/cms/templates/widgets/html-edit.html @@ -1,9 +1,12 @@ <%! from django.utils.translation import ugettext as _ %> -

+
- + % if editor == 'visual': + + % endif +
diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index d8888018d62c..526ead81f9a3 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -36,6 +36,16 @@ class HtmlFields(object): default=False, scope=Scope.settings ) + editor = String( + help="Supports switching between the Visual Editor and the Raw HTML Editor. The change does not take effect until Save is pressed.", + display_name="Editor", + default="visual", + values=[ + {"display_name": "Visual", "value": "visual"}, + {"display_name": "Raw", "value": "raw"} + ], + scope=Scope.settings + ) class HtmlModule(HtmlFields, XModule): @@ -113,6 +123,7 @@ def get_context(self): _context.update({ 'base_asset_url': StaticContent.get_base_url_path_for_course_assets(self.location) + '/', 'enable_latex_compiler': self.use_latex_compiler, + 'editor': self.editor }) return _context diff --git a/common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html b/common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html new file mode 100644 index 000000000000..6f1ff82e5041 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html @@ -0,0 +1,10 @@ +
+
+
+
+ + +
+
+
+
diff --git a/common/lib/xmodule/xmodule/js/fixtures/html-edit.html b/common/lib/xmodule/xmodule/js/fixtures/html-edit.html deleted file mode 100644 index 11f7868ff71e..000000000000 --- a/common/lib/xmodule/xmodule/js/fixtures/html-edit.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html b/common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html new file mode 100644 index 000000000000..54cbf8ba6912 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html @@ -0,0 +1,9 @@ +
+
+
+
+ +
+
+
+
diff --git a/common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee b/common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee index 9b5cb0c5820a..104e045d2915 100644 --- a/common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee @@ -3,39 +3,32 @@ describe 'HTMLEditingDescriptor', -> window.baseUrl = "/static/deadbeef" afterEach -> delete window.baseUrl - describe 'HTML Editor', -> + describe 'Visual HTML Editor', -> beforeEach -> - loadFixtures 'html-edit.html' - @descriptor = new HTMLEditingDescriptor($('.html-edit')) - it 'Returns data from Visual Editor if Visual Editor is dirty', -> + loadFixtures 'html-edit-visual.html' + @descriptor = new HTMLEditingDescriptor($('.test-component')) + it 'Returns data from Visual Editor if text has changed', -> visualEditorStub = - isDirty: () -> true getContent: () -> 'from visual editor' spyOn(@descriptor, 'getVisualEditor').andCallFake () -> visualEditorStub data = @descriptor.save().data expect(data).toEqual('from visual editor') - it 'Returns data from Visual Editor even if Visual Editor is not dirty', -> + it 'Returns data from Raw Editor if text has not changed', -> visualEditorStub = - isDirty: () -> false - getContent: () -> 'from visual editor' + getContent: () -> '

original visual text

' spyOn(@descriptor, 'getVisualEditor').andCallFake () -> visualEditorStub data = @descriptor.save().data - expect(data).toEqual('from visual editor') + expect(data).toEqual('raw text') it 'Performs link rewriting for static assets when saving', -> visualEditorStub = - isDirty: () -> true getContent: () -> 'from visual editor with /c4x/foo/bar/asset/image.jpg' spyOn(@descriptor, 'getVisualEditor').andCallFake () -> visualEditorStub - @descriptor.base_asset_url = '/c4x/foo/bar/asset/' data = @descriptor.save().data expect(data).toEqual('from visual editor with /static/image.jpg') it 'When showing visual editor links are rewritten to c4x format', -> - @descriptor = new HTMLEditingDescriptor($('.html-edit')) - @descriptor.base_asset_url = '/c4x/foo/bar/asset/' - visualEditorStub = content: 'text /static/image.jpg' startContent: 'text /static/image.jpg' @@ -45,3 +38,10 @@ describe 'HTMLEditingDescriptor', -> @descriptor.initInstanceCallback(visualEditorStub) expect(visualEditorStub.getContent()).toEqual('text /c4x/foo/bar/asset/image.jpg') + describe 'Raw HTML Editor', -> + beforeEach -> + loadFixtures 'html-editor-raw.html' + @descriptor = new HTMLEditingDescriptor($('.test-component')) + it 'Returns data from raw editor', -> + data = @descriptor.save().data + expect(data).toEqual('raw text') diff --git a/common/lib/xmodule/xmodule/js/src/html/edit.coffee b/common/lib/xmodule/xmodule/js/src/html/edit.coffee index af0b047999f9..59fbb6f981ad 100644 --- a/common/lib/xmodule/xmodule/js/src/html/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/html/edit.coffee @@ -1,68 +1,79 @@ class @HTMLEditingDescriptor constructor: (element) -> - @element = element; + @element = element @base_asset_url = @element.find("#editor-tab").data('base-asset-url') + @editor_choice = @element.find("#editor-tab").data('editor') if @base_asset_url == undefined @base_asset_url = null - # Create an array of all content CSS links to use in and pass to Tiny MCE. - # We create this dynamically in order to support hashed files from our Django pipeline. - # CSS files that are to be used by Tiny MCE should contain the string "tinymce" so - # they can be found by the search below. - # We filter for only those files that are "content" files (as opposed to "skin" files). - tiny_mce_css_links = [] - $("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each -> - tiny_mce_css_links.push $(this).attr("href") - return - -# This is a workaround for the fact that tinyMCE's baseURL property is not getting correctly set on AWS -# instances (like sandbox). It is not necessary to explicitly set baseURL when running locally. - tinyMCE.baseURL = "#{baseUrl}/js/vendor/tinymce/js/tinymce" -# This is necessary for the LMS bulk e-mail acceptance test. In that particular scenario, -# tinyMCE incorrectly decides that the suffix should be "", which means it fails to load files. - tinyMCE.suffix = ".min" - @tiny_mce_textarea = $(".tiny-mce", @element).tinymce({ - script_url : "#{baseUrl}/js/vendor/tinymce/js/tinymce/tinymce.full.min.js", - theme : "modern", - skin: 'studio-tmce4', - schema: "html5", - # Necessary to preserve relative URLs to our images. - convert_urls : false, - content_css : tiny_mce_css_links.join(", "), - formats : { - # tinyMCE does block level for code by default - code: {inline: 'code'} - }, - # Disable visual aid on borderless table. - visual: false, - plugins: "textcolor, link, image, codemirror", - codemirror: { - path: "#{baseUrl}/js/vendor" - }, - image_advtab: true, - # We may want to add "styleselect" when we collect all styles used throughout the LMS - toolbar: "formatselect | fontselect | bold italic underline forecolor wrapAsCode | bullist numlist outdent indent blockquote | link unlink image | code", - block_formats: "Paragraph=p;Preformatted=pre;Heading 1=h1;Heading 2=h2;Heading 3=h3", - width: '100%', - height: '400px', - menubar: false, - statusbar: false, - - # Necessary to avoid stripping of style tags. - valid_children : "+body[style]", - - # Allow any elements to be used, e.g. link, script, math - valid_elements: "*[*]", - extended_valid_elements: "*[*]", - invalid_elements: "", - - setup: @setupTinyMCE, - # Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered. - # The tinyMCE callback passes in the editor as a parameter. - init_instance_callback: @initInstanceCallback + # We always create the "raw editor" so we can get the text out of it if necessary on save. + @advanced_editor = CodeMirror.fromTextArea($(".edit-box", @element)[0], { + mode: "text/html" + lineNumbers: true + lineWrapping: true }) + if @editor_choice == 'visual' + @$advancedEditorWrapper = $(@advanced_editor.getWrapperElement()) + @$advancedEditorWrapper.addClass('is-inactive') + # Create an array of all content CSS links to use in and pass to Tiny MCE. + # We create this dynamically in order to support hashed files from our Django pipeline. + # CSS files that are to be used by Tiny MCE should contain the string "tinymce" so + # they can be found by the search below. + # We filter for only those files that are "content" files (as opposed to "skin" files). + tiny_mce_css_links = [] + $("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each -> + tiny_mce_css_links.push $(this).attr("href") + return + + # This is a workaround for the fact that tinyMCE's baseURL property is not getting correctly set on AWS + # instances (like sandbox). It is not necessary to explicitly set baseURL when running locally. + tinyMCE.baseURL = "#{baseUrl}/js/vendor/tinymce/js/tinymce" + # This is necessary for the LMS bulk e-mail acceptance test. In that particular scenario, + # tinyMCE incorrectly decides that the suffix should be "", which means it fails to load files. + tinyMCE.suffix = ".min" + @tiny_mce_textarea = $(".tiny-mce", @element).tinymce({ + script_url : "#{baseUrl}/js/vendor/tinymce/js/tinymce/tinymce.full.min.js", + theme : "modern", + skin: 'studio-tmce4', + schema: "html5", + # Necessary to preserve relative URLs to our images. + convert_urls : false, + content_css : tiny_mce_css_links.join(", "), + formats : { + # tinyMCE does block level for code by default + code: {inline: 'code'} + }, + # Disable visual aid on borderless table. + visual: false, + plugins: "textcolor, link, image, codemirror", + codemirror: { + path: "#{baseUrl}/js/vendor" + }, + image_advtab: true, + # We may want to add "styleselect" when we collect all styles used throughout the LMS + toolbar: "formatselect | fontselect | bold italic underline forecolor wrapAsCode | bullist numlist outdent indent blockquote | link unlink image | code", + block_formats: "Paragraph=p;Preformatted=pre;Heading 1=h1;Heading 2=h2;Heading 3=h3", + width: '100%', + height: '400px', + menubar: false, + statusbar: false, + + # Necessary to avoid stripping of style tags. + valid_children : "+body[style]", + + # Allow any elements to be used, e.g. link, script, math + valid_elements: "*[*]", + extended_valid_elements: "*[*]", + invalid_elements: "", + + setup: @setupTinyMCE, + # Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered. + # The tinyMCE callback passes in the editor as a parameter. + init_instance_callback: @initInstanceCallback + }) + setupTinyMCE: (ed) => ed.addButton('wrapAsCode', { title : 'Code block', @@ -116,6 +127,9 @@ class @HTMLEditingDescriptor initInstanceCallback: (visualEditor) => visualEditor.setContent(rewriteStaticLinks(visualEditor.getContent({no_events: 1}), '/static/', @base_asset_url)) + # Unfortunately, just setting visualEditor.isNortDirty = true is not enough to convince TinyMCE we + # haven't dirtied the Editor. Store the raw content so we can compare it later. + @starting_content = visualEditor.getContent({format:"raw", no_events: 1}) visualEditor.focus() getVisualEditor: () -> @@ -127,6 +141,14 @@ class @HTMLEditingDescriptor return @visualEditor save: -> - visualEditor = @getVisualEditor() - text = rewriteStaticLinks(visualEditor.getContent({no_events: 1}), @base_asset_url, '/static/') + text = undefined + if @editor_choice == 'visual' + visualEditor = @getVisualEditor() + content = visualEditor.getContent({format:"raw", no_events: 1}) + if @starting_content != content + text = rewriteStaticLinks(content, @base_asset_url, '/static/') + + if text == undefined + text = @advanced_editor.getValue() + data: text diff --git a/common/lib/xmodule/xmodule/templates/html/raw.yaml b/common/lib/xmodule/xmodule/templates/html/raw.yaml new file mode 100644 index 000000000000..32851479008c --- /dev/null +++ b/common/lib/xmodule/xmodule/templates/html/raw.yaml @@ -0,0 +1,6 @@ +--- +metadata: + display_name: Raw HTML + editor: raw +data: | +

For use with complex HTML, to allow complete control over the final product.

diff --git a/lms/templates/widgets/html-edit.html b/lms/templates/widgets/html-edit.html index a3ad0ef7d3a6..8dcf6b67b876 100644 --- a/lms/templates/widgets/html-edit.html +++ b/lms/templates/widgets/html-edit.html @@ -1,7 +1,12 @@ <%! from django.utils.translation import ugettext as _ %> -
-
- -
-
+
+
+
+ % if editor == 'visual': + + % endif + +
+
+
\ No newline at end of file From 6e8ccc51dbc690feda9ede2e7fb925722d3e4c39 Mon Sep 17 00:00:00 2001 From: Frances Botsford Date: Tue, 22 Apr 2014 15:53:15 -0400 Subject: [PATCH 5/7] adjust codemirror window on raw HTML editor --- common/lib/xmodule/xmodule/css/html/edit.scss | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/html/edit.scss b/common/lib/xmodule/xmodule/css/html/edit.scss index 8b8e48d9444d..ec98e9b945fc 100644 --- a/common/lib/xmodule/xmodule/css/html/edit.scss +++ b/common/lib/xmodule/xmodule/css/html/edit.scss @@ -1,30 +1,13 @@ -// HTML component editor: +// HTML component editor: .html-editor { @include clearfix(); .CodeMirror { @include box-sizing(border-box); - position: absolute; - top: 46px; - width: 100%; - height: 379px; - border: 1px solid #3c3c3c; - border-top: 1px solid #8891a1; - background: #fff; - color: #3c3c3c; - } - - .CodeMirror-scroll { - height: 100%; - } - - .editor-tabs { - top: 0 !important; - right: 10px; - z-index: 99; + height: 435px; } .is-inactive { display: none; } -} \ No newline at end of file +} From fe50a350b5d166943ddb3ae40212bfe059f39c5c Mon Sep 17 00:00:00 2001 From: Mark Hoeber Date: Wed, 23 Apr 2014 12:52:09 -0400 Subject: [PATCH 6/7] UI String Updates for Raw HTML Editor Change Modified the Raw HTML template text and the help string for the Editor setting. --- common/lib/xmodule/xmodule/html_module.py | 2 +- common/lib/xmodule/xmodule/templates/html/raw.yaml | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 526ead81f9a3..1a19e1f99e00 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -37,7 +37,7 @@ class HtmlFields(object): scope=Scope.settings ) editor = String( - help="Supports switching between the Visual Editor and the Raw HTML Editor. The change does not take effect until Save is pressed.", + help="Select Visual to enter content and have the editor automatically create the HTML. Select Raw to edit HTML directly. If you change this setting, you must save the component, then re-open it for editing.", display_name="Editor", default="visual", values=[ diff --git a/common/lib/xmodule/xmodule/templates/html/raw.yaml b/common/lib/xmodule/xmodule/templates/html/raw.yaml index 32851479008c..4f44427b9b24 100644 --- a/common/lib/xmodule/xmodule/templates/html/raw.yaml +++ b/common/lib/xmodule/xmodule/templates/html/raw.yaml @@ -3,4 +3,13 @@ metadata: display_name: Raw HTML editor: raw data: | -

For use with complex HTML, to allow complete control over the final product.

+

This template is similar to the Text template. The only difference is + that this template opens in a raw HTML editor rather than in the Visual + editor. Raw HTML is most useful when you need to use script and span tags + to format your content.

+ +

The raw HTML editor saves your HTML exactly as you enter it. + You can switch to the Visual editor by clicking the Settings tab and + changing the Editor setting to Visual. Note, however, that some of your + HTML may be modified when you save the component if you switch to the + Visual editor.

From f61421d7fed2ebf0687ffe828573cd805c7a92b5 Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 23 Apr 2014 13:25:23 -0400 Subject: [PATCH 7/7] Tests for raw editor and minor wording changes. --- .../contentstore/features/component.feature | 2 + .../contentstore/features/component.py | 2 + .../contentstore/features/html-editor.feature | 39 +++++++++++++++++++ .../contentstore/features/html-editor.py | 36 ++++++++++++++++- common/lib/xmodule/xmodule/html_module.py | 2 +- .../xmodule/xmodule/js/src/html/edit.coffee | 6 +-- .../xmodule/xmodule/templates/html/raw.yaml | 7 ++-- 7 files changed, 85 insertions(+), 9 deletions(-) diff --git a/cms/djangoapps/contentstore/features/component.feature b/cms/djangoapps/contentstore/features/component.feature index 90b8a8b843fc..482a0707169f 100644 --- a/cms/djangoapps/contentstore/features/component.feature +++ b/cms/djangoapps/contentstore/features/component.feature @@ -20,11 +20,13 @@ Feature: CMS.Component Adding | Text | | Announcement | | Zooming Image | + | Raw HTML | Then I see HTML components in this order: | Component | | Text | | Announcement | | Zooming Image | + | Raw HTML | Scenario: I can add Latex HTML components Given I am in Studio editing a new unit diff --git a/cms/djangoapps/contentstore/features/component.py b/cms/djangoapps/contentstore/features/component.py index e700c49df685..05598065b582 100644 --- a/cms/djangoapps/contentstore/features/component.py +++ b/cms/djangoapps/contentstore/features/component.py @@ -63,6 +63,8 @@ def see_a_multi_step_component(step, category): '

ZOOMING DIAGRAMS

', 'E-text Written in LaTeX': '

Example: E-text page

', + 'Raw HTML': + '

This template is similar to the Text template. The only difference is', } actual_html = world.css_html(selector, index=idx) assert_in(html_matcher[step_hash['Component']], actual_html) diff --git a/cms/djangoapps/contentstore/features/html-editor.feature b/cms/djangoapps/contentstore/features/html-editor.feature index 31fcd9fd3b61..df44d06420df 100644 --- a/cms/djangoapps/contentstore/features/html-editor.feature +++ b/cms/djangoapps/contentstore/features/html-editor.feature @@ -89,3 +89,42 @@ Feature: CMS.HTML Editor """

display as code

""" + + Scenario: Raw HTML component does not change text + Given I have created a raw HTML component + When I edit the page + And type "
  • zzzz
      " into the Raw Editor + And I save the page + Then the page text contains: + """ +
    1. zzzz
        + """ + And I edit the page + Then the Raw Editor contains exactly: + """ +
      1. zzzz
          + """ + + Scenario: Can switch from Visual Editor to Raw + Given I have created a Blank HTML Page + When I edit the component and select the Raw Editor + And I save the page + When I edit the page + And type "fancy html" into the Raw Editor + And I save the page + Then the page text contains: + """ + fancy html + """ + + Scenario: Can switch from Raw Editor to Visual + Given I have created a raw HTML component + And I edit the component and select the Visual Editor + And I save the page + When I edit the page + And type "less fancy html" in the code editor and press OK + And I save the page + Then the page text contains: + """ + less fancy html + """ diff --git a/cms/djangoapps/contentstore/features/html-editor.py b/cms/djangoapps/contentstore/features/html-editor.py index ad1be7f13fb4..6baed40eacd6 100644 --- a/cms/djangoapps/contentstore/features/html-editor.py +++ b/cms/djangoapps/contentstore/features/html-editor.py @@ -2,7 +2,7 @@ # pylint: disable=C0111 from lettuce import world, step -from nose.tools import assert_in, assert_equal # pylint: disable=no-name-in-module +from nose.tools import assert_in, assert_false, assert_true, assert_equal # pylint: disable=no-name-in-module from common import type_in_codemirror, get_codemirror_value CODEMIRROR_SELECTOR_PREFIX = "$('iframe').contents().find" @@ -18,6 +18,16 @@ def i_created_blank_html_page(step): ) +@step('I have created a raw HTML component') +def i_created_raw_html(step): + world.create_course_with_unit() + world.create_component_instance( + step=step, + category='html', + component_type='Raw HTML' + ) + + @step('I see the HTML component settings$') def i_see_only_the_html_display_name(step): world.verify_all_setting_entries( @@ -86,6 +96,10 @@ def check_link_in_link_plugin(step, path): @step('type "(.*)" in the code editor and press OK$') def type_in_codemirror_plugin(step, text): + # Verify that raw code editor is not visible. + assert_true(world.css_has_class('.CodeMirror', 'is-inactive')) + # Verify that TinyMCE editor is present + assert_true(world.is_css_present('.tiny-mce')) use_code_editor( lambda: type_in_codemirror(0, text, CODEMIRROR_SELECTOR_PREFIX) ) @@ -136,6 +150,11 @@ def check_page_text(step): assert_in(step.multiline, world.css_find('.xmodule_HtmlModule').html) +@step('the Raw Editor contains exactly:') +def check_raw_editor_text(step): + assert_equal(step.multiline, get_codemirror_value(0)) + + @step('the src link is rewritten to "(.*)"$') def image_static_link_is_rewritten(step, path): # Find the TinyMCE iframe within the main window @@ -204,3 +223,18 @@ def set_text_and_select(step, text): def select_code_button(step): # This is our custom "code style" button. It uses an image instead of a class. world.css_click(".mce-i-none") + + +@step('type "(.*)" into the Raw Editor$') +def type_in_raw_editor(step, text): + # Verify that CodeMirror editor is not hidden + assert_false(world.css_has_class('.CodeMirror', 'is-inactive')) + # Verify that TinyMCE Editor is not present + assert_true(world.is_css_not_present('.tiny-mce')) + type_in_codemirror(0, text) + + +@step('I edit the component and select the (Raw|Visual) Editor$') +def select_editor(step, editor): + world.edit_component_and_select_settings() + world.browser.select('Editor', editor) diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 1a19e1f99e00..2b58eaf4d364 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -37,7 +37,7 @@ class HtmlFields(object): scope=Scope.settings ) editor = String( - help="Select Visual to enter content and have the editor automatically create the HTML. Select Raw to edit HTML directly. If you change this setting, you must save the component, then re-open it for editing.", + help="Select Visual to enter content and have the editor automatically create the HTML. Select Raw to edit HTML directly. If you change this setting, you must save the component and then re-open it for editing.", display_name="Editor", default="visual", values=[ diff --git a/common/lib/xmodule/xmodule/js/src/html/edit.coffee b/common/lib/xmodule/xmodule/js/src/html/edit.coffee index 59fbb6f981ad..e55ad3b787d6 100644 --- a/common/lib/xmodule/xmodule/js/src/html/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/html/edit.coffee @@ -144,9 +144,9 @@ class @HTMLEditingDescriptor text = undefined if @editor_choice == 'visual' visualEditor = @getVisualEditor() - content = visualEditor.getContent({format:"raw", no_events: 1}) - if @starting_content != content - text = rewriteStaticLinks(content, @base_asset_url, '/static/') + raw_content = visualEditor.getContent({format:"raw", no_events: 1}) + if @starting_content != raw_content + text = rewriteStaticLinks(visualEditor.getContent({no_events: 1}), @base_asset_url, '/static/') if text == undefined text = @advanced_editor.getValue() diff --git a/common/lib/xmodule/xmodule/templates/html/raw.yaml b/common/lib/xmodule/xmodule/templates/html/raw.yaml index 4f44427b9b24..8d4c78ca8900 100644 --- a/common/lib/xmodule/xmodule/templates/html/raw.yaml +++ b/common/lib/xmodule/xmodule/templates/html/raw.yaml @@ -4,11 +4,10 @@ metadata: editor: raw data: |

          This template is similar to the Text template. The only difference is - that this template opens in a raw HTML editor rather than in the Visual - editor. Raw HTML is most useful when you need to use script and span tags - to format your content.

          + that this template opens in the Raw HTML editor rather than in the Visual + editor.

          -

          The raw HTML editor saves your HTML exactly as you enter it. +

          The Raw HTML editor saves your HTML exactly as you enter it. You can switch to the Visual editor by clicking the Settings tab and changing the Editor setting to Visual. Note, however, that some of your HTML may be modified when you save the component if you switch to the