Skip to content
Snippets Groups Projects
Commit d2cc40df authored by Scott Euser's avatar Scott Euser
Browse files

Issue #3484654 by scott_euser, andreastkdf: Pasting content nests everything in an extra paragraph

parent a58a47bc
Branches 4.0.x
No related tags found
No related merge requests found
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.CKEditor5=n():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.footnotes=n())}(self,(()=>(()=>{var __webpack_modules__={"./assets/js/ckeditor5_plugins/footnotes/src/footnotes.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ Footnotes)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n/* harmony import */ var _footnotesediting__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./footnotesediting */ "./assets/js/ckeditor5_plugins/footnotes/src/footnotesediting.js");\n/* harmony import */ var _footnotesui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./footnotesui */ "./assets/js/ckeditor5_plugins/footnotes/src/footnotesui.js");\n// eslint-disable-next-line import/no-unresolved\n\n\n\n\n/**\n * Main entry point to the footnotes.\n */\nclass Footnotes extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n /**\n * @inheritdoc\n */\n static get requires() {\n return [_footnotesediting__WEBPACK_IMPORTED_MODULE_1__["default"], _footnotesui__WEBPACK_IMPORTED_MODULE_2__["default"]];\n }\n\n /**\n * @inheritdoc\n */\n static get pluginName() {\n return \'footnotes\';\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/footnotes.js?')},"./assets/js/ckeditor5_plugins/footnotes/src/footnotescommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Footnotescommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n// eslint-disable-next-line import/no-unresolved\n\n\n/**\n * Creates a <footnotes> element using the provided writer and attributes.\n *\n * @param {Object} writer - The CKEditor writer instance.\n * @param {Object} attributes - Attributes to be applied to the <footnotes> element.\n * @return {Object} The created <footnotes> element.\n */\nfunction createFootnotes(writer, attributes) {\n return writer.createElement('footnotes', attributes);\n}\n\n/**\n * Command for inserting <footnotes> tag into ckeditor.\n */\nclass Footnotescommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n const footnotesEditing = this.editor.plugins.get('footnotesEditing');\n\n // Create object that contains supported data-attributes in view data by\n // flipping `DrupalMediaEditing.attrs` object (i.e. keys from object become\n // values and values from object become keys).\n const dataAttributeMapping = Object.entries(footnotesEditing.attrs).reduce(\n (result, [key, value]) => {\n result[value] = key;\n return result;\n },\n {},\n );\n\n // \\Drupal\\media\\Form\\EditorMediaDialog returns data in keyed by\n // data-attributes used in view data. This converts data-attribute keys to\n // keys used in model.\n const modelAttributes = Object.keys(attributes).reduce(\n (result, attribute) => {\n if (dataAttributeMapping[attribute]) {\n if (typeof attributes[attribute].value !== 'undefined') {\n result[dataAttributeMapping[attribute]] =\n attributes[attribute].value;\n } else {\n result[dataAttributeMapping[attribute]] = attributes[attribute];\n }\n }\n return result;\n },\n {},\n );\n\n this.editor.model.change((writer) => {\n this.editor.model.insertContent(createFootnotes(writer, modelAttributes));\n });\n }\n\n refresh() {\n const { model } = this.editor;\n const { selection } = model.document;\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'footnotes',\n );\n this.isEnabled = allowedIn !== null;\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/footnotescommand.js?")},"./assets/js/ckeditor5_plugins/footnotes/src/footnotesdoubleclick.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ DoubleClickObserver)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/engine */ "ckeditor5/src/engine.js");\n// eslint-disable-next-line import/no-unresolved\n\n\n/**\n * Ckeditor5 doesn\'t support double click out of the box.\n * Register it here so we can use it.\n */\nclass DoubleClickObserver extends ckeditor5_src_engine__WEBPACK_IMPORTED_MODULE_0__.DomEventObserver {\n constructor(view) {\n super(view);\n this.domEventType = \'dblclick\';\n }\n\n onDomEvent(domEvent) {\n this.fire(domEvent.type, domEvent);\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/footnotesdoubleclick.js?')},"./assets/js/ckeditor5_plugins/footnotes/src/footnotesediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Footnotesediting)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _footnotescommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./footnotescommand */ \"./assets/js/ckeditor5_plugins/footnotes/src/footnotescommand.js\");\n/* eslint-disable import/no-unresolved */\n\n\n\n\n// Function to determine if we should output console logs.\nfunction isDebugMode() {\n const params = new URLSearchParams(window.location.search);\n return params.has('debug');\n}\n\nfunction transformClipboardContent(documentFragment) {\n // Function to create a new <footnotes> element\n function createFootnotesElement(value, reference) {\n const footnotesElement = document.createElement('footnotes');\n\n footnotesElement.setAttribute('data-value', value);\n footnotesElement.setAttribute('data-text', reference);\n footnotesElement.innerHTML = '&nbsp;'; // or any other content you wish to add\n\n return footnotesElement;\n }\n\n // Function to extract the reference html from the selected footnote.\n function extractFootnoteReference(htmlString) {\n // Ensure htmlString is actually a string (not an HTML element)\n if (typeof htmlString !== 'string') {\n throw new Error(`Expected a string as input, got: ${typeof htmlString}`);\n }\n\n // Create a DOM parser to parse the string\n const parser = new DOMParser();\n const doc = parser.parseFromString(htmlString, 'text/html');\n\n // Create a document fragment to hold the cleaned content\n const fragment = document.createDocumentFragment();\n\n // Function to traverse and extract only the relevant elements, namely\n // bold, italics, and links.\n function processNode(node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const tagName = node.tagName.toLowerCase();\n\n if (tagName === 'b' || tagName === 'strong') {\n const bold = document.createElement('b');\n bold.innerHTML = node.innerHTML;\n fragment.appendChild(bold);\n } else if (tagName === 'i' || tagName === 'em') {\n const italic = document.createElement('i');\n italic.innerHTML = node.innerHTML;\n fragment.appendChild(italic);\n } else if (tagName === 'a') {\n const hrefFragment = node.href.split('#')[1] || '';\n // Exclude if the fragment starts with \"sdfootnote\", \"ftn\", or \"_ftn\"\n if (\n !hrefFragment.startsWith('sdfootnote') &&\n !hrefFragment.startsWith('ftn') &&\n !hrefFragment.startsWith('_ftn')\n ) {\n const link = document.createElement('a');\n link.href = node.href;\n link.innerHTML = node.innerHTML;\n fragment.appendChild(link);\n }\n } else if (tagName === 'span') {\n // Unwrap the <span> element by processing its children\n Array.from(node.childNodes).forEach(processNode);\n } else {\n // Recursively extract from child nodes.\n Array.from(node.childNodes).forEach(processNode);\n }\n } else if (node.nodeType === Node.TEXT_NODE) {\n fragment.appendChild(document.createTextNode(node.textContent));\n }\n }\n\n // Start processing the body of the parsed document.\n Array.from(doc.body.childNodes).forEach(processNode);\n\n // Convert the document fragment back to HTML\n const container = document.createElement('div');\n container.appendChild(fragment);\n\n // Return the inner HTML of the cleaned content\n return container.innerHTML.trim();\n }\n\n if (isDebugMode()) {\n console.log('Content received from paste pipeline:');\n console.log(documentFragment);\n }\n\n // Find all the footnotes\n const footnotes = documentFragment.querySelectorAll(\n '.sdfootnote, [id*=\"ftn\"] > p, [id*=\"sdfootnote\"] > p',\n );\n\n footnotes.forEach((footnote) => {\n let footnoteText = extractFootnoteReference(footnote.innerHTML);\n\n // Find the anchor element\n const anchor = footnote.querySelector('.sdfootnotesym, [ href*=\"_ftnref\"]');\n if (anchor) {\n // Get the link, ensure that it only contains the fragment.\n let footnoteId = anchor.getAttribute('href').replace(/anc|ref|_/g, '');\n footnoteId = `#${footnoteId.split('#').pop()}`;\n\n // Find the corresponding anchor element and div\n const anchorSup = documentFragment.querySelector(\n `.sdfootnoteanc[href*=\"${footnoteId}sym\"], [href*=\"_ftn\"]`,\n );\n const anchorDiv = documentFragment.querySelector(`div${footnoteId}`);\n const supValue = '';\n\n if (anchorSup) {\n // Attempt to get footnote text from the anchor div\n // if not found yet.\n if (!footnoteText && anchorDiv.querySelector(`.MsoFootnoteReference`)) {\n // Find the reference number like [1] and remove it so the html\n // remaining is only the reference text itself.\n const anchorReferenceNumber = anchorDiv.querySelector(\n `.MsoFootnoteReference`,\n ).parentNode;\n\n // If there is a reference number, remove it.\n if (typeof anchorReferenceNumber !== 'undefined') {\n anchorReferenceNumber.parentNode.removeChild(anchorReferenceNumber);\n }\n const anchorDivText = anchorDiv.querySelector('.MsoFootnoteText');\n if (anchorDivText) {\n footnoteText = anchorDivText.innerHTML;\n }\n }\n\n // If we ultimately have text.\n if (footnoteText) {\n // Create the new drupal footnotes element\n const footnotesElement = createFootnotesElement(\n supValue,\n footnoteText,\n );\n\n if (isDebugMode()) {\n console.log('Created footnotes element:');\n console.log(footnotesElement);\n\n console.log('Replacing citation element:');\n console.log(anchorSup);\n\n console.log('Removing anchor div:');\n console.log(anchorDiv);\n }\n\n // Remove unwanted remaining html.\n anchorSup.parentNode.replaceChild(footnotesElement, anchorSup);\n anchorDiv.parentNode.removeChild(anchorDiv);\n }\n }\n }\n });\n\n // Remove any lingering elements.\n const remainingElements = documentFragment.querySelectorAll(\n 'div[style*=\"mso-element:footnote-list;\"]',\n );\n if (remainingElements && remainingElements.length > 0) {\n remainingElements.forEach((div) => {\n div.parentNode.removeChild(div);\n });\n }\n\n // Find all remaining/existing footnotes\n const drupalFootnotes = documentFragment.querySelectorAll('footnotes');\n\n // Reset the data value for automatic numbering\n drupalFootnotes.forEach((drupalFootnote) => {\n drupalFootnote.setAttribute('data-value', '');\n });\n\n if (isDebugMode()) {\n console.log('Returning document fragment:');\n console.log(documentFragment);\n }\n return documentFragment;\n}\n\n/**\n * Footnotes editing functionality.\n */\nclass Footnotesediting extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n /**\n * @inheritdoc\n */\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n /**\n * @inheritdoc\n */\n static get pluginName() {\n return 'footnotesEditing';\n }\n\n /**\n * @inheritdoc\n */\n init() {\n this.attrs = {\n footnotesText: 'data-text',\n footnotesValue: 'data-value',\n };\n const options = this.editor.config.get('footnotes');\n if (!options) {\n return;\n }\n const { previewURL, themeError } = options;\n this.previewUrl = previewURL;\n this.themeError =\n themeError ||\n `\n <p>${Drupal.t(\n 'An error occurred while trying to preview the embedded content. Please save your work and reload this page.',\n )}<p>\n `;\n\n this._defineSchema();\n this._defineConverters();\n\n this.editor.commands.add('footnotes', new _footnotescommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor));\n\n // Automatically convert pasted content from Word/LibreOffice to\n // Footnotes format.\n this.editor.plugins.get('ClipboardPipeline').on(\n 'inputTransformation',\n (evt, data) => {\n // Convert the view document fragment to a DOM document fragment.\n const viewFragment = data.content;\n const domFragment = this.editor.editing.view.domConverter.viewToDom(viewFragment);\n\n // Apply the footnotes changes and transform it back to a view document fragment.\n const transformedDomFragment = transformClipboardContent(domFragment);\n const transformedViewFragment = this.editor.editing.view.domConverter.domToView(transformedDomFragment);\n\n if (isDebugMode()) {\n console.log('Transformed view fragment:');\n console.log(transformedViewFragment);\n }\n\n // Convert the transformed view fragment to a model fragment.\n const modelFragment = this.editor.data.toModel(transformedViewFragment);\n\n this.editor.model.change(writer => {\n const selection = this.editor.model.document.selection;\n\n // If there is a selection, replace the selected content.\n if (selection && !selection.isCollapsed) {\n writer.remove(selection.getFirstRange());\n }\n\n // Insert the transformed content at the selection position (or cursor if collapsed).\n writer.insert(modelFragment, selection.getFirstPosition());\n });\n\n // Prevent default content handling, as we've already updated the model.\n evt.stop();\n },\n { priority: 'highest' },\n );\n }\n\n /**\n * Fetches the preview for the given model element.\n *\n * @param {Element} modelElement - The CKEditor model element representing footnotes.\n */\n async _fetchPreview(modelElement) {\n const query = {\n text: modelElement.getAttribute('footnotesText'),\n value: modelElement.getAttribute('footnotesValue'),\n };\n const response = await fetch(\n `${this.previewUrl}?${new URLSearchParams(query)}`,\n );\n if (response.ok) {\n return response.text();\n }\n\n return this.themeError;\n }\n\n /**\n * Registers footnotes as a block element in the DOM converter.\n */\n _defineSchema() {\n const { schema } = this.editor.model;\n schema.register('footnotes', {\n allowWhere: '$inlineObject',\n blockObject: false,\n isObject: true,\n isContent: true,\n isBlock: false,\n isInline: true,\n inlineObject: true,\n allowAttributes: Object.keys(this.attrs),\n });\n this.editor.editing.view.domConverter.blockElements.push('footnotes');\n }\n\n /**\n * Defines handling of drupal media element in the content lifecycle.\n *\n * @private\n */\n _defineConverters() {\n const { conversion } = this.editor;\n\n conversion.for('upcast').elementToElement({\n view: {\n name: 'footnotes',\n },\n model: 'footnotes',\n });\n\n conversion.for('dataDowncast').elementToElement({\n model: 'footnotes',\n view: {\n name: 'footnotes',\n },\n });\n conversion\n .for('editingDowncast')\n .elementToElement({\n model: 'footnotes',\n view: (modelElement, { writer }) => {\n const container = writer.createContainerElement('span');\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(container, writer, {\n label: Drupal.t('Footnotes'),\n });\n },\n })\n .add((dispatcher) => {\n const converter = (event, data, conversionApi) => {\n const viewWriter = conversionApi.writer;\n const modelElement = data.item;\n const container = conversionApi.mapper.toViewElement(data.item);\n const footnotes = viewWriter.createRawElement('span', {\n 'data-footnotes-preview': 'loading',\n class: 'footnotes-preview',\n });\n viewWriter.insert(\n viewWriter.createPositionAt(container, 0),\n footnotes,\n );\n this._fetchPreview(modelElement).then((preview) => {\n if (!footnotes) {\n return;\n }\n this.editor.editing.view.change((writer) => {\n const footnotesPreview = writer.createRawElement(\n 'span',\n {\n class: 'footnotes-preview',\n 'data-footnotes-preview': 'ready',\n },\n // eslint-disable-next-line max-nested-callbacks\n (domElement) => {\n domElement.innerHTML = preview;\n },\n );\n writer.insert(\n writer.createPositionBefore(footnotes),\n footnotesPreview,\n );\n writer.remove(footnotes);\n });\n });\n };\n dispatcher.on('attribute:footnotesValue:footnotes', converter);\n return dispatcher;\n });\n\n Object.keys(this.attrs).forEach((modelKey) => {\n const attributeMapping = {\n model: {\n key: modelKey,\n name: 'footnotes',\n },\n view: {\n name: 'footnotes',\n key: this.attrs[modelKey],\n },\n };\n conversion.for('dataDowncast').attributeToAttribute(attributeMapping);\n conversion.for('upcast').attributeToAttribute(attributeMapping);\n });\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/footnotesediting.js?")},"./assets/js/ckeditor5_plugins/footnotes/src/footnotesui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Footnotesui)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _footnotesdoubleclick__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./footnotesdoubleclick */ \"./assets/js/ckeditor5_plugins/footnotes/src/footnotesdoubleclick.js\");\n/* harmony import */ var _icons_footnotes_svg__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../icons/footnotes.svg */ \"./assets/js/ckeditor5_plugins/footnotes/icons/footnotes.svg\");\n/* eslint-disable import/no-unresolved */\n\n\n\n\n\n/**\n * Provides the embedded content button and editing.\n */\nclass Footnotesui extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const { editor } = this;\n const options = this.editor.config.get('footnotes');\n if (!options) {\n return;\n }\n\n const { dialogURL, openDialog, dialogSettings = {} } = options;\n if (!dialogURL || typeof openDialog !== 'function') {\n return;\n }\n editor.ui.componentFactory.add('footnotes', (locale) => {\n const command = editor.commands.get('footnotes');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n buttonView.set({\n label: Drupal.t('Footnotes'),\n icon: _icons_footnotes_svg__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n this.listenTo(buttonView, 'execute', () => {\n const modelElement =\n editor.model.document.selection.getSelectedElement();\n const url = new URL(dialogURL, document.baseURI);\n if (\n modelElement &&\n typeof modelElement.name !== 'undefined' &&\n modelElement.name === 'footnotes'\n ) {\n url.searchParams.append(\n 'text',\n modelElement.getAttribute('footnotesText'),\n );\n url.searchParams.append(\n 'value',\n modelElement.getAttribute('footnotesValue'),\n );\n }\n openDialog(\n url.toString(),\n ({ attributes }) => {\n editor.execute('footnotes', attributes);\n },\n dialogSettings,\n );\n });\n\n return buttonView;\n });\n\n const { view } = editor.editing;\n const viewDocument = view.document;\n\n view.addObserver(_footnotesdoubleclick__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n\n editor.listenTo(viewDocument, 'dblclick', (evt, data) => {\n const modelElement = editor.editing.mapper.toModelElement(\n data.target.parent,\n );\n if (\n modelElement &&\n typeof modelElement.name !== 'undefined' &&\n modelElement.name === 'footnotes'\n ) {\n const query = {\n text: modelElement.getAttribute('footnotesText'),\n value: modelElement.getAttribute('footnotesValue'),\n };\n openDialog(\n `${dialogURL}?${new URLSearchParams(query)}`,\n ({ attributes }) => {\n editor.execute('footnotes', attributes);\n },\n dialogSettings,\n );\n }\n });\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/footnotesui.js?")},"./assets/js/ckeditor5_plugins/footnotes/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _footnotes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./footnotes */ "./assets/js/ckeditor5_plugins/footnotes/src/footnotes.js");\n\n\n/**\n * @private\n */\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n Footnotes: _footnotes__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/src/index.js?')},"./assets/js/ckeditor5_plugins/footnotes/icons/footnotes.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("<?xml version=\\"1.0\\" standalone=\\"no\\"?>\\n<!DOCTYPE svg PUBLIC \\"-//W3C//DTD SVG 20010904//EN\\"\\n \\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\\">\\n<svg version=\\"1.0\\" xmlns=\\"http://www.w3.org/2000/svg\\"\\n width=\\"16.000000pt\\" height=\\"16.000000pt\\" viewBox=\\"0 0 16.000000 16.000000\\"\\n preserveAspectRatio=\\"xMidYMid meet\\">\\n\\n<g transform=\\"translate(0.000000,16.000000) scale(0.100000,-0.100000)\\"\\nfill=\\"#000000\\" stroke=\\"none\\">\\n<path d=\\"M115 115 c0 -14 5 -25 11 -25 7 0 9 10 6 25 -2 14 -7 25 -11 25 -3 0\\n-6 -11 -6 -25z\\"/>\\n<path d=\\"M35 110 c-4 -6 5 -10 19 -10 14 0 26 -4 26 -10 0 -5 -8 -10 -19 -10\\n-24 0 -45 -25 -38 -45 4 -9 19 -14 42 -13 33 1 35 3 35 38 0 20 -5 41 -12 48\\n-15 15 -45 16 -53 2z m45 -60 c0 -5 -9 -10 -20 -10 -11 0 -20 5 -20 10 0 6 9\\n10 20 10 11 0 20 -4 20 -10z\\"/>\\n</g>\\n</svg>\\n");\n\n//# sourceURL=webpack://CKEditor5.footnotes/./assets/js/ckeditor5_plugins/footnotes/icons/footnotes.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.footnotes/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/engine.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/engine.js");\n\n//# sourceURL=webpack://CKEditor5.footnotes/delegated_./engine.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.footnotes/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.footnotes/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var n=__webpack_module_cache__[e];if(void 0!==n)return n.exports;var t=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](t,t.exports,__webpack_require__),t.exports}__webpack_require__.d=(e,n)=>{for(var t in n)__webpack_require__.o(n,t)&&!__webpack_require__.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},__webpack_require__.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./assets/js/ckeditor5_plugins/footnotes/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})()));
\ No newline at end of file
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.footnotes=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/widget.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function o(n){var r=t[n];if(void 0!==r)return r.exports;var s=t[n]={exports:{}};return e[n](s,s.exports,o),s.exports}o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var n={};return(()=>{"use strict";o.d(n,{default:()=>m});var e=o("ckeditor5/src/core.js"),t=o("ckeditor5/src/widget.js");class r extends e.Command{execute(e){const t=this.editor.plugins.get("footnotesEditing"),o=Object.entries(t.attrs).reduce(((e,[t,o])=>(e[o]=t,e)),{}),n=Object.keys(e).reduce(((t,n)=>(o[n]&&(void 0!==e[n].value?t[o[n]]=e[n].value:t[o[n]]=e[n]),t)),{});this.editor.model.change((e=>{this.editor.model.insertContent(function(e,t){return e.createElement("footnotes",t)}(e,n))}))}refresh(){const{model:e}=this.editor,{selection:t}=e.document,o=e.schema.findAllowedParent(t.getFirstPosition(),"footnotes");this.isEnabled=null!==o}}function s(){return new URLSearchParams(window.location.search).has("debug")}function i(e){s()&&(console.log("Content received from paste pipeline:"),console.log(e));e.querySelectorAll('.sdfootnote, [id*="ftn"] > p, [id*="sdfootnote"] > p').forEach((t=>{let o=function(e){if("string"!=typeof e)throw new Error("Expected a string as input, got: "+typeof e);const t=(new DOMParser).parseFromString(e,"text/html"),o=document.createDocumentFragment();Array.from(t.body.childNodes).forEach((function e(t){if(t.nodeType===Node.ELEMENT_NODE){const n=t.tagName.toLowerCase();if("b"===n||"strong"===n){const e=document.createElement("b");e.innerHTML=t.innerHTML,o.appendChild(e)}else if("i"===n||"em"===n){const e=document.createElement("i");e.innerHTML=t.innerHTML,o.appendChild(e)}else if("a"===n){const e=t.href.split("#")[1]||"";if(!e.startsWith("sdfootnote")&&!e.startsWith("ftn")&&!e.startsWith("_ftn")){const e=document.createElement("a");e.href=t.href,e.innerHTML=t.innerHTML,o.appendChild(e)}}else Array.from(t.childNodes).forEach(e)}else t.nodeType===Node.TEXT_NODE&&o.appendChild(document.createTextNode(t.textContent))}));const n=document.createElement("div");return n.appendChild(o),n.innerHTML.trim()}(t.innerHTML);const n=t.querySelector('.sdfootnotesym, [ href*="_ftnref"]');if(n){let t=n.getAttribute("href").replace(/anc|ref|_/g,"");t=`#${t.split("#").pop()}`;const r=e.querySelector(`.sdfootnoteanc[href*="${t}sym"], [href*="_ftn"]`),i=e.querySelector(`div${t}`),c="";if(r){if(!o&&i.querySelector(".MsoFootnoteReference")){const e=i.querySelector(".MsoFootnoteReference").parentNode;void 0!==e&&e.parentNode.removeChild(e);const t=i.querySelector(".MsoFootnoteText");t&&(o=t.innerHTML)}if(o){const e=function(e,t){const o=document.createElement("footnotes");return o.setAttribute("data-value",e),o.setAttribute("data-text",t),o.innerHTML="&nbsp;",o}(c,o);s()&&(console.log("Created footnotes element:"),console.log(e),console.log("Replacing citation element:"),console.log(r),console.log("Removing anchor div:"),console.log(i)),r.parentNode.replaceChild(e,r),i.parentNode.removeChild(i)}}}}));const t=e.querySelectorAll('div[style*="mso-element:footnote-list;"]');t&&t.length>0&&t.forEach((e=>{e.parentNode.removeChild(e)}));return e.querySelectorAll("footnotes").forEach((e=>{e.setAttribute("data-value","")})),s()&&(console.log("Returning document fragment:"),console.log(e)),e}class c extends e.Plugin{static get requires(){return[t.Widget]}static get pluginName(){return"footnotesEditing"}init(){this.attrs={footnotesText:"data-text",footnotesValue:"data-value"};const e=this.editor.config.get("footnotes");if(!e)return;const{previewURL:t,themeError:o}=e;this.previewUrl=t,this.themeError=o||`\n <p>${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}<p>\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("footnotes",new r(this.editor)),this.editor.plugins.get("ClipboardPipeline").on("inputTransformation",((e,t)=>{const o=t.content,n=i(this.editor.editing.view.domConverter.viewToDom(o)),r=this.editor.editing.view.domConverter.domToView(n);s()&&(console.log("Transformed view fragment:"),console.log(r));const c=this.editor.data.toModel(r);this.editor.model.change((e=>{const t=this.editor.model.document.selection;t&&!t.isCollapsed&&e.remove(t.getFirstRange()),this.editor.model.insertContent(c,t)})),e.stop()}),{priority:"highest"})}async _fetchPreview(e){const t={text:e.getAttribute("footnotesText"),value:e.getAttribute("footnotesValue")},o=await fetch(`${this.previewUrl}?${new URLSearchParams(t)}`);return o.ok?o.text():this.themeError}_defineSchema(){const{schema:e}=this.editor.model;e.register("footnotes",{allowWhere:"$inlineObject",blockObject:!1,isObject:!0,isContent:!0,isBlock:!1,isInline:!0,inlineObject:!0,allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("footnotes")}_defineConverters(){const{conversion:e}=this.editor;e.for("upcast").elementToElement({view:{name:"footnotes"},model:"footnotes"}),e.for("dataDowncast").elementToElement({model:"footnotes",view:{name:"footnotes"}}),e.for("editingDowncast").elementToElement({model:"footnotes",view:(e,{writer:o})=>{const n=o.createContainerElement("span");return(0,t.toWidget)(n,o,{label:Drupal.t("Footnotes")})}}).add((e=>(e.on("attribute:footnotesValue:footnotes",((e,t,o)=>{const n=o.writer,r=t.item,s=o.mapper.toViewElement(t.item),i=n.createRawElement("span",{"data-footnotes-preview":"loading",class:"footnotes-preview"});n.insert(n.createPositionAt(s,0),i),this._fetchPreview(r).then((e=>{i&&this.editor.editing.view.change((t=>{const o=t.createRawElement("span",{class:"footnotes-preview","data-footnotes-preview":"ready"},(t=>{t.innerHTML=e}));t.insert(t.createPositionBefore(i),o),t.remove(i)}))}))})),e))),Object.keys(this.attrs).forEach((t=>{const o={model:{key:t,name:"footnotes"},view:{name:"footnotes",key:this.attrs[t]}};e.for("dataDowncast").attributeToAttribute(o),e.for("upcast").attributeToAttribute(o)}))}}var a=o("ckeditor5/src/ui.js"),d=o("ckeditor5/src/engine.js");class l extends d.DomEventObserver{constructor(e){super(e),this.domEventType="dblclick"}onDomEvent(e){this.fire(e.type,e)}}class f extends e.Plugin{init(){const{editor:e}=this,t=this.editor.config.get("footnotes");if(!t)return;const{dialogURL:o,openDialog:n,dialogSettings:r={}}=t;if(!o||"function"!=typeof n)return;e.ui.componentFactory.add("footnotes",(t=>{const s=e.commands.get("footnotes"),i=new a.ButtonView(t);return i.set({label:Drupal.t("Footnotes"),icon:'<?xml version="1.0" standalone="no"?>\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"\n "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n<svg version="1.0" xmlns="http://www.w3.org/2000/svg"\n width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"\n preserveAspectRatio="xMidYMid meet">\n\n<g transform="translate(0.000000,16.000000) scale(0.100000,-0.100000)"\nfill="#000000" stroke="none">\n<path d="M115 115 c0 -14 5 -25 11 -25 7 0 9 10 6 25 -2 14 -7 25 -11 25 -3 0\n-6 -11 -6 -25z"/>\n<path d="M35 110 c-4 -6 5 -10 19 -10 14 0 26 -4 26 -10 0 -5 -8 -10 -19 -10\n-24 0 -45 -25 -38 -45 4 -9 19 -14 42 -13 33 1 35 3 35 38 0 20 -5 41 -12 48\n-15 15 -45 16 -53 2z m45 -60 c0 -5 -9 -10 -20 -10 -11 0 -20 5 -20 10 0 6 9\n10 20 10 11 0 20 -4 20 -10z"/>\n</g>\n</svg>\n',tooltip:!0}),i.bind("isOn","isEnabled").to(s,"value","isEnabled"),this.listenTo(i,"execute",(()=>{const t=e.model.document.selection.getSelectedElement(),s=new URL(o,document.baseURI);t&&void 0!==t.name&&"footnotes"===t.name&&(s.searchParams.append("text",t.getAttribute("footnotesText")),s.searchParams.append("value",t.getAttribute("footnotesValue"))),n(s.toString(),(({attributes:t})=>{e.execute("footnotes",t)}),r)})),i}));const{view:s}=e.editing,i=s.document;s.addObserver(l),e.listenTo(i,"dblclick",((t,s)=>{const i=e.editing.mapper.toModelElement(s.target.parent);if(i&&void 0!==i.name&&"footnotes"===i.name){const t={text:i.getAttribute("footnotesText"),value:i.getAttribute("footnotesValue")};n(`${o}?${new URLSearchParams(t)}`,(({attributes:t})=>{e.execute("footnotes",t)}),r)}}))}}class u extends e.Plugin{static get requires(){return[c,f]}static get pluginName(){return"footnotes"}}const m={Footnotes:u}})(),n=n.default})()));
\ No newline at end of file
......@@ -40,7 +40,6 @@ function transformClipboardContent(documentFragment) {
function processNode(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
const tagName = node.tagName.toLowerCase();
if (tagName === 'b' || tagName === 'strong') {
const bold = document.createElement('b');
bold.innerHTML = node.innerHTML;
......@@ -262,8 +261,8 @@ export default class Footnotesediting extends Plugin {
writer.remove(selection.getFirstRange());
}
// Insert the transformed content at the selection position (or cursor if collapsed).
writer.insert(modelFragment, selection.getFirstPosition());
// Insert the transformed content at the selection position.
this.editor.model.insertContent(modelFragment, selection);
});
// Prevent default content handling, as we've already updated the model.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment