Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
ae886f1b
Commit
ae886f1b
authored
Apr 22, 2014
by
cahrens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for raw HTML editor.
STUD-1562
parent
56bf7d86
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
157 additions
and
85 deletions
+157
-85
CHANGELOG.rst
+3
-0
cms/djangoapps/contentstore/features/html-editor.feature
+1
-1
cms/djangoapps/contentstore/features/html-editor.py
+7
-2
cms/templates/widgets/html-edit.html
+5
-2
common/lib/xmodule/xmodule/html_module.py
+11
-0
common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html
+10
-0
common/lib/xmodule/xmodule/js/fixtures/html-edit.html
+0
-3
common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html
+9
-0
common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee
+14
-14
common/lib/xmodule/xmodule/js/src/html/edit.coffee
+80
-58
common/lib/xmodule/xmodule/templates/html/raw.yaml
+6
-0
lms/templates/widgets/html-edit.html
+11
-5
No files found.
CHANGELOG.rst
View file @
ae886f1b
...
...
@@ -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.
...
...
cms/djangoapps/contentstore/features/html-editor.feature
View file @
ae886f1b
...
...
@@ -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
...
...
cms/djangoapps/contentstore/features/html-editor.py
View file @
ae886f1b
...
...
@@ -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$'
)
...
...
cms/templates/widgets/html-edit.html
View file @
ae886f1b
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<div
class=
"wrapper-comp-editor"
id=
"editor-tab"
data-base-asset-url=
"${base_asset_url}"
>
<div
class=
"wrapper-comp-editor"
id=
"editor-tab"
data-base-asset-url=
"${base_asset_url}"
data-editor=
"${editor}"
>
<section
class=
"html-editor editor"
>
<div
class=
"row"
>
<textarea
class=
"tiny-mce"
>
${data | h}
</textarea>
% if editor == 'visual':
<textarea
class=
"tiny-mce"
>
${data | h}
</textarea>
% endif
<textarea
name=
""
class=
"edit-box"
>
${data | h}
</textarea>
</div>
</section>
</div>
...
...
common/lib/xmodule/xmodule/html_module.py
View file @
ae886f1b
...
...
@@ -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 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor):
_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
...
...
common/lib/xmodule/xmodule/js/fixtures/html-edit-visual.html
0 → 100644
View file @
ae886f1b
<div
class=
"test-component"
>
<div
class=
"wrapper-comp-editor"
id=
"editor-tab"
data-base-asset-url=
"/c4x/foo/bar/asset/"
data-editor=
"visual"
>
<section
class=
"html-editor editor"
>
<div
class=
"row"
>
<textarea
class=
"tiny-mce"
><p>
original visual text
</p></textarea>
<textarea
name=
""
class=
"edit-box"
>
raw text
</textarea>
</div>
</section>
</div>
</div>
common/lib/xmodule/xmodule/js/fixtures/html-edit.html
deleted
100644 → 0
View file @
56bf7d86
<section
class=
"html-edit"
>
<textarea
class=
"tiny-mce"
>
dummy text
</textarea>
</section>
common/lib/xmodule/xmodule/js/fixtures/html-editor-raw.html
0 → 100644
View file @
ae886f1b
<div
class=
"test-component"
>
<div
class=
"wrapper-comp-editor"
id=
"editor-tab"
data-editor=
"raw"
>
<section
class=
"html-editor editor"
>
<div
class=
"row"
>
<textarea
name=
""
class=
"edit-box"
>
raw text
</textarea>
</div>
</section>
</div>
</div>
common/lib/xmodule/xmodule/js/spec/html/edit_spec.coffee
View file @
ae886f1b
...
...
@@ -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-edi
t'
))
it
'Returns data from Visual Editor if
Visual Editor is dirty
'
,
->
loadFixtures
'html-edit
-visual
.html'
@
descriptor
=
new
HTMLEditingDescriptor
(
$
(
'.
test-componen
t'
))
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
:
()
->
'<p>original visual text</p>'
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'
)
common/lib/xmodule/xmodule/js/src/html/edit.coffee
View file @
ae886f1b
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
common/lib/xmodule/xmodule/templates/html/raw.yaml
0 → 100644
View file @
ae886f1b
---
metadata
:
display_name
:
Raw HTML
editor
:
raw
data
:
|
<p>For use with complex HTML, to allow complete control over the final product.</p>
lms/templates/widgets/html-edit.html
View file @
ae886f1b
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<section
class=
"html-editor editor"
>
<div
class=
"row"
>
<textarea
class=
"tiny-mce"
>
${data | h}
</textarea>
</div>
</section>
<div
class=
"wrapper-comp-editor"
id=
"editor-tab"
data-editor=
"${editor}"
>
<section
class=
"html-editor editor"
>
<div
class=
"row"
>
% if editor == 'visual':
<textarea
class=
"tiny-mce"
>
${data | h}
</textarea>
% endif
<textarea
name=
""
class=
"edit-box"
>
${data | h}
</textarea>
</div>
</section>
</div>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment