Skip to content

Commit d0d8dd4

Browse files
committed
Squashed 'libs/editor/' changes from a2a6a7c..a92ad9d
a92ad9d Merge pull request #424 from wordpress-mobile/issue/423-image-caption-backspace c04f955 add mocha call to the README cb1cb3c Don't add space in front of image captions 3f15fa3 Fixed paragraph formatting for captions when converting from HTML to visual fc0661e Added JS tests for images with captions daf9b96 Fixed mislabeled JS tests 5022799 Extended Formatter.convertPToDiv to apply paragraph formatting to images with captions 0594930 Removed jQuery dependency from Formatter.applyCaptionFormatting() cf03097 When adding caption formatting to an image, set the caret below the image 2b30987 Adjust handleCaptionNewLine() to handle pressing enter in the middle of the caption text 44fbd87 When pressing enter inside an image caption, strip caption styling from the new line 24f2423 Make image caption nodes editable git-subtree-dir: libs/editor git-subtree-split: a92ad9df3062c875b921f5bbb4a11b6dda11136f
1 parent 49ac398 commit d0d8dd4

File tree

4 files changed

+65
-11
lines changed

4 files changed

+65
-11
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ With npm and Mocha installed, from within `libs/editor-common/assets/test`, run:
4444

4545
npm install chai
4646

47-
It should now be possible to run the tests using `mocha` inside `libs/editor-common/assets`.
47+
And then run `mocha` inside `libs/editor-common/assets`:
48+
49+
cd libs/editor-common/assets; mocha; cd -
4850

4951
## LICENSE ##
5052

libs/editor-common/assets/ZSSRichTextEditor.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1942,11 +1942,15 @@ ZSSEditor.updateCurrentImageMeta = function( imageMetaString ) {
19421942
// in certain cases, modify the current and inserted markup depending on what
19431943
// elements surround the targeted node. This approach is safer.
19441944
var node = ZSSEditor.findImageCaptionNode( ZSSEditor.currentEditingImage );
1945+
var parent = node.parentNode;
1946+
19451947
node.insertAdjacentHTML( 'afterend', html );
19461948
// Use {node}.{parent}.removeChild() instead of {node}.remove(), since Android API<19 doesn't support Node.remove()
19471949
node.parentNode.removeChild(node);
19481950

19491951
ZSSEditor.currentEditingImage = null;
1952+
1953+
ZSSEditor.setFocusAfterElement(parent);
19501954
}
19511955

19521956
ZSSEditor.applyImageSelectionFormatting = function( imageNode ) {
@@ -2148,7 +2152,7 @@ ZSSEditor.createImageFromMeta = function( props ) {
21482152
html = wp.shortcode.string({
21492153
tag: 'caption',
21502154
attrs: shortcode,
2151-
content: html + ' ' + props.caption
2155+
content: html + props.caption
21522156
});
21532157

21542158
html = Formatter.applyVisualFormatting( html );
@@ -3227,6 +3231,9 @@ ZSSField.prototype.handleKeyDownEvent = function(e) {
32273231
} else if (sel.isCollapsed && sel.baseOffset == 0 && parentNode && parentNode.nodeName == 'BLOCKQUOTE') {
32283232
e.preventDefault();
32293233
ZSSEditor.setBlockquote();
3234+
// When pressing enter inside an image caption, clear the caption styling from the new line
3235+
} else if (parentNode.nodeName == NodeName.SPAN && $(parentNode).hasClass('wp-caption')) {
3236+
setTimeout(this.handleCaptionNewLine, 100);
32303237
}
32313238
}
32323239
}
@@ -3636,6 +3643,32 @@ ZSSField.prototype.wrapCaretInParagraphIfNecessary = function() {
36363643
}
36373644
};
36383645

3646+
/**
3647+
* @brief Called when enter is pressed inside an image caption. Clears away the span and label tags the new line
3648+
* inherits from the caption styling.
3649+
*/
3650+
ZSSField.prototype.handleCaptionNewLine = function() {
3651+
var selectedNode = document.getSelection().baseNode;
3652+
3653+
var contentsNode;
3654+
if (selectedNode.firstChild != null) {
3655+
contentsNode = selectedNode.firstChild.cloneNode();
3656+
} else {
3657+
contentsNode = selectedNode.cloneNode();
3658+
}
3659+
3660+
var parentSpan = selectedNode.parentNode.parentNode;
3661+
var parentDiv = parentSpan.parentNode;
3662+
3663+
var paragraph = document.createElement("div");
3664+
paragraph.appendChild(contentsNode);
3665+
3666+
parentDiv.insertBefore(paragraph, parentSpan);
3667+
parentDiv.removeChild(parentSpan);
3668+
3669+
ZSSEditor.giveFocusToElement(contentsNode);
3670+
};
3671+
36393672
// MARK: - i18n
36403673

36413674
ZSSField.prototype.isRightToLeftTextEnabled = function() {

libs/editor-common/assets/editor-utils-formatter.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ Formatter.videoShortcodeFormats = ["mp4", "m4v", "webm", "ogv", "wmv", "flv"];
66

77
Formatter.htmlToVisual = function(html) {
88
var mutatedHTML = wp.loadText(html);
9+
10+
// Perform extra transformations to properly wrap captioned images in paragraphs
11+
mutatedHTML = mutatedHTML.replace(/^\[caption([^\]]*\])/igm, '<p>[caption$1');
12+
mutatedHTML = mutatedHTML.replace(/([^\n>])\[caption/igm, '$1<br />\n[caption');
13+
mutatedHTML = mutatedHTML.replace(/\[\/caption\]\n(?=<|$)/igm, '[/caption]</p>\n');
14+
mutatedHTML = mutatedHTML.replace(/\[\/caption\]\n(?=[^<])/igm, '[/caption]<br />\n');
15+
916
return Formatter.applyVisualFormatting(mutatedHTML);
1017
}
1118

@@ -17,13 +24,13 @@ Formatter.convertPToDiv = function(html) {
1724
// The break tags appear when text and media are separated by only a line break rather than a paragraph break,
1825
// which can happen when inserting media inline and switching to HTML mode and back, or by deleting line breaks
1926
// in HTML mode
20-
mutatedHTML = mutatedHTML.replace(/<br \/>(?=\s*(<a href|<img|<video|<span class="edit-container"))/igm,
27+
mutatedHTML = mutatedHTML.replace(/<br \/>(?=\s*(<img|<a href|<label|<video|<span class="edit-container"))/igm,
2128
'</div><div>');
22-
mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/video>|<\/span>)<br \/>/igm,
29+
mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/label>|<\/video>|<\/span>)<br \/>/igm,
2330
function replaceBrWithDivs(match) { return match.substr(0, match.length - 6) + '</div><div>'; });
2431

2532
// Append paragraph-wrapped break tag under media at the end of a post
26-
mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/video>|<\/span>)[^<>]*<\/div>\s$/igm,
33+
mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/label>|<\/video>|<\/span>)[^<>]*<\/div>\s$/igm,
2734
function replaceBrWithDivs(match) { return match + '<div><br></div>'; });
2835

2936
return mutatedHTML;
@@ -68,15 +75,15 @@ Formatter.applyCaptionFormatting = function(match) {
6875
var attrs = match.attrs.named;
6976
// The empty 'onclick' is important. It prevents the cursor jumping to the end
7077
// of the content body when `-webkit-user-select: none` is set and the caption is tapped.
71-
var out = '<label class="wp-temp" data-wp-temp="caption" contenteditable="false" onclick="">';
78+
var out = '<label class="wp-temp" data-wp-temp="caption" onclick="">';
7279
out += '<span class="wp-caption"';
7380

7481
if (attrs.width) {
7582
out += ' style="width:' + attrs.width + 'px; max-width:100% !important;"';
7683
}
77-
$.each(attrs, function(key, value) {
78-
out += " data-caption-" + key + '="' + value + '"';
79-
});
84+
for (var key in attrs) {
85+
out += " data-caption-" + key + '="' + attrs[key] + '"';
86+
}
8087

8188
out += '>';
8289
out += match.content;

libs/editor-common/assets/test/test-formatter.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ var imageSrc = 'content://com.android.providers.media.documents/document/image%3
2121
var plainImageHtml = '<img src="' + imageSrc + '" alt="" class="wp-image-123 size-full" width="172" height="244">';
2222
var imageWrappedInLinkHtml = '<a href="' + imageSrc + '">' + plainImageHtml + '</a>';
2323

24+
// Captioned image strings
25+
var imageCaptionShortcode = '[caption width="600" align="alignnone"]' + imageSrc + 'Text[/caption]';
26+
var imageWithCaptionHtml = '<label class="wp-temp" data-wp-temp="caption" onclick="">' +
27+
'<span class="wp-caption" style="width:600px; max-width:100% !important;" data-caption-width="600" ' +
28+
'data-caption-align="alignnone">' + imageSrc + 'Text</span></label>';
29+
var linkedImageCaptionShortcode = '[caption width="600" align="alignnone"]' + imageWrappedInLinkHtml + 'Text[/caption]';
30+
var linkedImageCaptionHtml = '<label class="wp-temp" data-wp-temp="caption" onclick="">' +
31+
'<span class="wp-caption" style="width:600px; max-width:100% !important;" data-caption-width="600" ' +
32+
'data-caption-align="alignnone">' + imageWrappedInLinkHtml + 'Text</span></label>';
33+
2434
// Video strings
2535
var videoSrc = 'content://com.android.providers.media.documents/document/video%3A12966';
2636
var videoShortcode = '[video src="' + videoSrc + '" poster=""][/video]';
@@ -43,8 +53,10 @@ describe('HTML to Visual formatter should correctly convert', function () {
4353
assert.equal('<p>Some text</p>\n<p>More text</p>\n', formatter.htmlToVisual('Some text\n\nMore text'));
4454
});
4555

46-
testMediaParagraphWrapping('image wrapped in link', plainImageHtml, plainImageHtml);
47-
testMediaParagraphWrapping('image not wrapped in link', imageWrappedInLinkHtml, imageWrappedInLinkHtml);
56+
testMediaParagraphWrapping('non-linked image', plainImageHtml, plainImageHtml);
57+
testMediaParagraphWrapping('linked image', imageWrappedInLinkHtml, imageWrappedInLinkHtml);
58+
testMediaParagraphWrapping('non-linked image, with caption', imageCaptionShortcode, imageWithCaptionHtml);
59+
testMediaParagraphWrapping('linked image, with caption', linkedImageCaptionShortcode, linkedImageCaptionHtml);
4860
testMediaParagraphWrapping('non-VideoPress video', videoShortcode, videoHtml);
4961
testMediaParagraphWrapping('VideoPress video', vpVideoShortcode, vpVideoHtml);
5062
});

0 commit comments

Comments
 (0)