UNPKG

react-native-wordpress-editor

Version:

React Native Wrapper for WordPress Rich Text Editor. The WordPress-Editor is the text editor used in the official WordPress mobile apps to create and edit pages & posts

158 lines (129 loc) 6.22 kB
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; }