aboutsummaryrefslogtreecommitdiff
path: root/libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js
diff options
context:
space:
mode:
Diffstat (limited to 'libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js')
-rw-r--r--libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js b/libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js
new file mode 100644
index 000000000..69b0254ca
--- /dev/null
+++ b/libs/editor/WordPressEditor/src/main/assets/editor-utils-formatter.js
@@ -0,0 +1,158 @@
+function Formatter () {}
+
+// Video format tags supported by the [video] shortcode: https://codex.wordpress.org/Video_Shortcode
+// mp4, m4v and webm prioritized since they're supported by the stock player as of Android API 23
+Formatter.videoShortcodeFormats = ["mp4", "m4v", "webm", "ogv", "wmv", "flv"];
+
+Formatter.htmlToVisual = function(html) {
+ var mutatedHTML = wp.loadText(html);
+
+ // Perform extra transformations to properly wrap captioned images in paragraphs
+ mutatedHTML = mutatedHTML.replace(/^\[caption([^\]]*\])/igm, '<p>[caption$1');
+ mutatedHTML = mutatedHTML.replace(/([^\n>])\[caption/igm, '$1<br />\n[caption');
+ mutatedHTML = mutatedHTML.replace(/\[\/caption\]\n(?=<|$)/igm, '[/caption]</p>\n');
+ mutatedHTML = mutatedHTML.replace(/\[\/caption\]\n(?=[^<])/igm, '[/caption]<br />\n');
+
+ return Formatter.applyVisualFormatting(mutatedHTML);
+}
+
+Formatter.convertPToDiv = function(html) {
+ // Replace the paragraph tags we get from wpload with divs
+ var mutatedHTML = html.replace(/(<p(?=[>\s]))/igm, '<div').replace(/<\/p>/igm, '</div>');
+
+ // Replace break tags around media items with paragraphs
+ // The break tags appear when text and media are separated by only a line break rather than a paragraph break,
+ // which can happen when inserting media inline and switching to HTML mode and back, or by deleting line breaks
+ // in HTML mode
+ mutatedHTML = mutatedHTML.replace(/<br \/>(?=\s*(<img|<a href|<label|<video|<span class="edit-container"))/igm,
+ '</div><div>');
+ mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/label>|<\/video>|<\/span>)<br \/>/igm,
+ function replaceBrWithDivs(match) { return match.substr(0, match.length - 6) + '</div><div>'; });
+
+ // Append paragraph-wrapped break tag under media at the end of a post
+ mutatedHTML = mutatedHTML.replace(/(<img [^<>]*>|<\/a>|<\/label>|<\/video>|<\/span>)[^<>]*<\/div>\s$/igm,
+ function replaceBrWithDivs(match) { return match + '<div><br></div>'; });
+
+ return mutatedHTML;
+}
+
+Formatter.visualToHtml = function(html) {
+ return wp.saveText(html);
+ return Formatter.removeVisualFormatting(mutatedHTML);
+}
+
+Formatter.convertDivToP = function(html) {
+ return html.replace(/(<div(?=[>\s]))/igm, '<p').replace(/<\/div>/igm, '</p>');
+}
+
+/**
+ * @brief Applies editor specific visual formatting.
+ *
+ * @param html The markup to format
+ *
+ * @return Returns the string with the visual formatting applied.
+ */
+Formatter.applyVisualFormatting = function(html) {
+ var str = wp.shortcode.replace('caption', html, Formatter.applyCaptionFormatting);
+ str = wp.shortcode.replace('wpvideo', str, Formatter.applyVideoPressFormattingCallback);
+ str = wp.shortcode.replace('video', str, Formatter.applyVideoFormattingCallback);
+
+ // More tag
+ str = str.replace(/<!--more(.*?)-->/igm, "<hr class=\"more-tag\" wp-more-data=\"$1\">")
+ str = str.replace(/<!--nextpage-->/igm, "<hr class=\"nextpage-tag\">")
+ return str;
+}
+
+/**
+ * @brief Adds visual formatting to a caption shortcodes.
+ *
+ * @param html The markup containing caption shortcodes to process.
+ *
+ * @return The html with caption shortcodes replaced with editor specific markup.
+ * See shortcode.js::next or details
+ */
+Formatter.applyCaptionFormatting = function(match) {
+ var attrs = match.attrs.named;
+ // The empty 'onclick' is important. It prevents the cursor jumping to the end
+ // of the content body when `-webkit-user-select: none` is set and the caption is tapped.
+ var out = '<label class="wp-temp" data-wp-temp="caption" onclick="">';
+ out += '<span class="wp-caption"';
+
+ if (attrs.width) {
+ out += ' style="width:' + attrs.width + 'px; max-width:100% !important;"';
+ }
+ for (var key in attrs) {
+ out += " data-caption-" + key + '="' + attrs[key] + '"';
+ }
+
+ out += '>';
+ out += match.content;
+ out += '</span>';
+ out += '</label>';
+
+ return out;
+}
+
+Formatter.applyVideoPressFormattingCallback = function(match) {
+ if (match.attrs.numeric.length == 0) {
+ return match.content;
+ }
+ var videopressID = match.attrs.numeric[0];
+ var posterSVG = '"svg/wpposter.svg"';
+ // The empty 'onclick' is important. It prevents the cursor jumping to the end
+ // of the content body when `-webkit-user-select: none` is set and the video is tapped.
+ var out = '<video data-wpvideopress="' + videopressID + '" webkit-playsinline src="" preload="metadata" poster='
+ + posterSVG +' onclick="" onerror="ZSSEditor.sendVideoPressInfoRequest(\'' + videopressID +'\');"></video>';
+
+ // Wrap video in edit-container node for a permanent delete button overlay
+ var containerStart = '<span class="edit-container" contenteditable="false"><span class="delete-overlay"></span>';
+ out = containerStart + out + '</span>';
+
+ return out;
+}
+
+Formatter.applyVideoFormattingCallback = function(match) {
+ // Find the tag containing the video source
+ var srcTag = "";
+
+ if (match.attrs.named['src']) {
+ srcTag = "src";
+ } else {
+ for (var i = 0; i < Formatter.videoShortcodeFormats.length; i++) {
+ var format = Formatter.videoShortcodeFormats[i];
+ if (match.attrs.named[format]) {
+ srcTag = format;
+ break;
+ }
+ }
+ }
+
+ if (srcTag.length == 0) {
+ return match.content;
+ }
+
+ var out = '<video webkit-playsinline src="' + match.attrs.named[srcTag] + '"';
+
+ // Preserve all existing tags
+ for (var item in match.attrs.named) {
+ if (item != srcTag) {
+ out += ' ' + item + '="' + match.attrs.named[item] + '"';
+ }
+ }
+
+ if (!match.attrs.named['preload']) {
+ out += ' preload="metadata"';
+ }
+
+ out += ' onclick="" controls="controls"></video>';
+
+ // Wrap video in edit-container node for a permanent delete button overlay
+ var containerStart = '<span class="edit-container" contenteditable="false"><span class="delete-overlay"></span>';
+ out = containerStart + out + '</span>';
+
+ return out;
+}
+
+if (typeof module !== 'undefined' && module.exports != null) {
+ exports.Formatter = Formatter;
+} \ No newline at end of file