UNPKG

@wordpress/blocks

Version:
191 lines (175 loc) 8.88 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.pasteHandler = pasteHandler; var _dom = require("@wordpress/dom"); var _htmlToBlocks = require("./html-to-blocks"); var _registration = require("../registration"); var _serializer = require("../serializer"); var _parser = _interopRequireDefault(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 _msListIgnore = _interopRequireDefault(require("./ms-list-ignore")); var _listReducer = _interopRequireDefault(require("./list-reducer")); var _imageCorrector = _interopRequireDefault(require("./image-corrector")); var _blockquoteNormaliser = _interopRequireDefault(require("./blockquote-normaliser")); var _divNormaliser = _interopRequireDefault(require("./div-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")); var _slackParagraphCorrector = _interopRequireDefault(require("./slack-paragraph-corrector")); /** * WordPress dependencies */ /** * Internal dependencies */ const log = (...args) => window?.console?.log?.(...args); /** * Filters HTML to only contain phrasing content. * * @param {string} HTML The HTML to filter. * * @return {string} HTML only containing phrasing content. */ function filterInlineHTML(HTML) { HTML = (0, _utils.deepFilterHTML)(HTML, [_headRemover.default, _googleDocsUidRemover.default, _msListIgnore.default, _phrasingContentReducer.default, _commentRemover.default]); HTML = (0, _dom.removeInvalidHTML)(HTML, (0, _dom.getPhrasingContentSchema)('paste'), { inline: true }); HTML = (0, _utils.deepFilterHTML)(HTML, [_htmlFormattingRemover.default, _brRemover.default]); // Allows us to ask for this information when we get a report. 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. * * @return {Array|string} A list of blocks or a string, depending on `handlerMode`. */ function pasteHandler({ HTML = '', plainText = '', mode = 'AUTO', tagName }) { // 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) { const parseResult = (0, _parser.default)(content); const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform'; if (!isSingleFreeFormBlock) { return parseResult; } } } // Normalize unicode to use composed characters. // 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(); } // Must be run before checking if it's inline content. HTML = (0, _utils.deepFilterHTML)(HTML, [_slackParagraphCorrector.default]); // Consider plain text if: // * There is a plain text version. // * There is no HTML version, or it has no formatting. const isPlainText = plainText && (!HTML || (0, _utils.isPlain)(HTML)); // Parse Markdown (and encoded HTML) if it's considered plain text. if (isPlainText) { HTML = plainText; // The markdown converter (Showdown) trims whitespace. if (!/^\s+$/.test(plainText)) { HTML = (0, _markdownConverter.default)(HTML); } } // 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 (isPlainText && !hasShortcodes) { // 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); } if (mode === 'AUTO' && !hasShortcodes && (0, _isInlineContent.default)(HTML, tagName)) { return filterInlineHTML(HTML); } const phrasingContentSchema = (0, _dom.getPhrasingContentSchema)('paste'); const blockContentSchema = (0, _utils.getBlockContentSchema)('paste'); const blocks = pieces.map(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, (0, _blockquoteNormaliser.default)(), _divNormaliser.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. log('Processed HTML piece:\n\n', piece); return (0, _htmlToBlocks.htmlToBlocks)(piece, pasteHandler); }).flat().filter(Boolean); // 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)) { const trimRegex = /^[\n]+|[\n]+$/g; // Don't catch line breaks at the start or end. const trimmedPlainText = plainText.replace(trimRegex, ''); if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) { return (0, _dom.removeInvalidHTML)((0, _serializer.getBlockInnerHTML)(blocks[0]), phrasingContentSchema).replace(trimRegex, ''); } } return blocks; } //# sourceMappingURL=paste-handler.js.map