UNPKG

@wordpress/blocks

Version:
222 lines (164 loc) 8.52 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.pasteHandler = pasteHandler; var _lodash = require("lodash"); var _dom = require("@wordpress/dom"); var _htmlToBlocks = require("./html-to-blocks"); var _registration = require("../registration"); var _serializer = require("../serializer"); var _parser = require("../parser"); var _normaliseBlocks = _interopRequireDefault(require("./normalise-blocks")); var _specialCommentConverter = _interopRequireDefault(require("./special-comment-converter")); var _commentRemover = _interopRequireDefault(require("./comment-remover")); var _isInlineContent = _interopRequireDefault(require("./is-inline-content")); var _phrasingContentReducer = _interopRequireDefault(require("./phrasing-content-reducer")); var _headRemover = _interopRequireDefault(require("./head-remover")); var _msListConverter = _interopRequireDefault(require("./ms-list-converter")); var _listReducer = _interopRequireDefault(require("./list-reducer")); var _imageCorrector = _interopRequireDefault(require("./image-corrector")); var _blockquoteNormaliser = _interopRequireDefault(require("./blockquote-normaliser")); var _figureContentReducer = _interopRequireDefault(require("./figure-content-reducer")); var _shortcodeConverter = _interopRequireDefault(require("./shortcode-converter")); var _markdownConverter = _interopRequireDefault(require("./markdown-converter")); var _iframeRemover = _interopRequireDefault(require("./iframe-remover")); var _googleDocsUidRemover = _interopRequireDefault(require("./google-docs-uid-remover")); var _htmlFormattingRemover = _interopRequireDefault(require("./html-formatting-remover")); var _brRemover = _interopRequireDefault(require("./br-remover")); var _utils = require("./utils"); var _emptyParagraphRemover = _interopRequireDefault(require("./empty-paragraph-remover")); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Browser dependencies */ const { console } = window; /** * Filters HTML to only contain phrasing content. * * @param {string} HTML The HTML to filter. * @param {boolean} preserveWhiteSpace Whether or not to preserve consequent white space. * * @return {string} HTML only containing phrasing content. */ function filterInlineHTML(HTML, preserveWhiteSpace) { HTML = (0, _utils.deepFilterHTML)(HTML, [_googleDocsUidRemover.default, _phrasingContentReducer.default, _commentRemover.default]); HTML = (0, _dom.removeInvalidHTML)(HTML, (0, _dom.getPhrasingContentSchema)('paste'), { inline: true }); if (!preserveWhiteSpace) { HTML = (0, _utils.deepFilterHTML)(HTML, [_htmlFormattingRemover.default, _brRemover.default]); } // Allows us to ask for this information when we get a report. console.log('Processed inline HTML:\n\n', HTML); return HTML; } /** * Converts an HTML string to known blocks. Strips everything else. * * @param {Object} options * @param {string} [options.HTML] The HTML to convert. * @param {string} [options.plainText] Plain text version. * @param {string} [options.mode] Handle content as blocks or inline content. * * 'AUTO': Decide based on the content passed. * * 'INLINE': Always handle as inline content, and return string. * * 'BLOCKS': Always handle as blocks, and return array of blocks. * @param {Array} [options.tagName] The tag into which content will be inserted. * @param {boolean} [options.preserveWhiteSpace] Whether or not to preserve consequent white space. * * @return {Array|string} A list of blocks or a string, depending on `handlerMode`. */ function pasteHandler({ HTML = '', plainText = '', mode = 'AUTO', tagName, preserveWhiteSpace }) { // First of all, strip any meta tags. HTML = HTML.replace(/<meta[^>]+>/g, ''); // Strip Windows markers. HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, ''); HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, ''); // If we detect block delimiters in HTML, parse entirely as blocks. if (mode !== 'INLINE') { // Check plain text if there is no HTML. const content = HTML ? HTML : plainText; if (content.indexOf('<!-- wp:') !== -1) { return (0, _parser.parseWithGrammar)(content); } } // Normalize unicode to use composed characters. // This is unsupported in IE 11 but it's a nice-to-have feature, not mandatory. // Not normalizing the content will only affect older browsers and won't // entirely break the app. // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize // See: https://core.trac.wordpress.org/ticket/30130 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075 if (String.prototype.normalize) { HTML = HTML.normalize(); } // Parse Markdown (and encoded HTML) if: // * There is a plain text version. // * There is no HTML version, or it has no formatting. if (plainText && (!HTML || (0, _utils.isPlain)(HTML))) { HTML = plainText; // The markdown converter (Showdown) trims whitespace. if (!/^\s+$/.test(plainText)) { HTML = (0, _markdownConverter.default)(HTML); } // Switch to inline mode if: // * The current mode is AUTO. // * The original plain text had no line breaks. // * The original plain text was not an HTML paragraph. // * The converted text is just a paragraph. if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) { mode = 'INLINE'; } } if (mode === 'INLINE') { return filterInlineHTML(HTML, preserveWhiteSpace); } // An array of HTML strings and block objects. The blocks replace matched // shortcodes. const pieces = (0, _shortcodeConverter.default)(HTML); // The call to shortcodeConverter will always return more than one element // if shortcodes are matched. The reason is when shortcodes are matched // empty HTML strings are included. const hasShortcodes = pieces.length > 1; if (mode === 'AUTO' && !hasShortcodes && (0, _isInlineContent.default)(HTML, tagName)) { return filterInlineHTML(HTML, preserveWhiteSpace); } const phrasingContentSchema = (0, _dom.getPhrasingContentSchema)('paste'); const blockContentSchema = (0, _utils.getBlockContentSchema)('paste'); const blocks = (0, _lodash.compact)((0, _lodash.flatMap)(pieces, piece => { // Already a block from shortcode. if (typeof piece !== 'string') { return piece; } const filters = [_googleDocsUidRemover.default, _msListConverter.default, _headRemover.default, _listReducer.default, _imageCorrector.default, _phrasingContentReducer.default, _specialCommentConverter.default, _commentRemover.default, _iframeRemover.default, _figureContentReducer.default, _blockquoteNormaliser.default]; const schema = { ...blockContentSchema, // Keep top-level phrasing content, normalised by `normaliseBlocks`. ...phrasingContentSchema }; piece = (0, _utils.deepFilterHTML)(piece, filters, blockContentSchema); piece = (0, _dom.removeInvalidHTML)(piece, schema); piece = (0, _normaliseBlocks.default)(piece); piece = (0, _utils.deepFilterHTML)(piece, [_htmlFormattingRemover.default, _brRemover.default, _emptyParagraphRemover.default], blockContentSchema); // Allows us to ask for this information when we get a report. console.log('Processed HTML piece:\n\n', piece); return (0, _htmlToBlocks.htmlToBlocks)(piece); })); // If we're allowed to return inline content, and there is only one // inlineable block, and the original plain text content does not have any // line breaks, then treat it as inline paste. if (mode === 'AUTO' && blocks.length === 1 && (0, _registration.hasBlockSupport)(blocks[0].name, '__unstablePasteTextInline', false)) { // Don't catch line breaks at the start or end. const trimmedPlainText = plainText.replace(/^[\n]+|[\n]+$/g, ''); if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) { return (0, _dom.removeInvalidHTML)((0, _serializer.getBlockInnerHTML)(blocks[0]), phrasingContentSchema); } } return blocks; } //# sourceMappingURL=paste-handler.js.map