UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

65 lines (55 loc) 2.63 kB
export const AC_XMLNS = 'http://example.com/ac'; export const RI_XMLNS = 'http://example.com/ri'; export const FAB_XMLNS = 'http://example.com/fab'; export const XHTML_XMLNS = 'http://www.w3.org/1999/xhtml'; export default function(node: Node): string { // The naive approach here is to simply call .outerHTML on a node, however this has an undesirable // behaviour of including the xmlns:* attributes on the node. Confluence Storage Format expects that // these are *not* included. // // To avoid including these, we fall back to hacky plain text slicing. The strategy is to included // some wrapper elements that will contain the xmlns:* attributes. A document will be structured as: // // <wrapper xmlns="http://www.w3.org/1999/xhtml"> // <fab:wrapper xmlns="http://example.com/fab"> // <ac:wrapper xmlns="http://example.com/ac"> // <ri:wrapper xmlns="http://example.com/ri"> // … // </ri:wrapper> // </ac:wrapper> // </fab:wrapper> // </wrapper> // // Before content is added, `.outerHTML` of the `ac:wrapper` is used to determine the number of // leading/trailing bytes need to be trimmed in the final result (to remove the wrappers). // // WARNING: This method will move `element` into a new parent element, but will put it back // before returning. const doc = node.ownerDocument; const marker = doc.createElement('marker'); if (node.parentNode) { node.parentNode.replaceChild(marker, node); } const wrapper = doc.createElementNS(XHTML_XMLNS, 'wrapper'); const acWrapper = doc.createElementNS(AC_XMLNS, 'ac:wrapper'); const riWrapper = doc.createElementNS(RI_XMLNS, 'ri:wrapper'); const fabWrapper = doc.createElementNS(FAB_XMLNS, 'fab:wrapper'); wrapper.appendChild(fabWrapper); fabWrapper.appendChild(acWrapper); acWrapper.appendChild(riWrapper); // Force avoid self-closing tags, as these would invalidate suffix/prefix length calculations. const wedge = '|'; const wedgeText = doc.createTextNode(wedge); riWrapper.appendChild(wedgeText); const template = wrapper.outerHTML; const prefixLength = template.indexOf(wedge); const suffixLength = template.length - prefixLength - wedge.length; riWrapper.removeChild(wedgeText); riWrapper.appendChild(node); const wrappedResult = wrapper.outerHTML; const result = wrappedResult.slice(prefixLength, wrappedResult.length - suffixLength); if (marker.parentNode) { marker.parentNode.replaceChild(node, marker); } return result.replace(/\s\/>/g, '/>'); // Remove unnecessary white-space added by IE }