UNPKG

@atlaskit/editor-confluence-transformer

Version:
489 lines (484 loc) 20.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = encode; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _adfSchema = require("@atlaskit/adf-schema"); var _utils = require("@atlaskit/editor-common/utils"); var _parseCxhtml = _interopRequireDefault(require("./parse-cxhtml")); var _encodeCxhtml = _interopRequireWildcard(require("./encode-cxhtml")); var _languageMap = require("./languageMap"); var _utils2 = require("./utils"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function encode(node, schema) { var docType = document.implementation.createDocumentType('html', '-//W3C//DTD XHTML 1.0 Strict//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'); var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', docType); return (0, _encodeCxhtml.default)(encodeFragment(node.content)); function encodeNode(node) { if (node.isText) { return encodeText(node); } else if (node.type === schema.nodes.blockquote) { return encodeBlockquote(node); } else if (node.type === schema.nodes.bulletList) { return encodeBulletList(node); } else if (node.type === schema.nodes.heading) { return encodeHeading(node); } else if (node.type === schema.nodes.confluenceJiraIssue) { return encodeJiraIssue(node); } else if (node.type === schema.nodes.rule) { return encodeHorizontalRule(); } else if (node.type === schema.nodes.listItem) { return encodeListItem(node); } else if (node.type === schema.nodes.orderedList) { return encodeOrderedList(node); } else if (node.type === schema.nodes.paragraph) { return encodeParagraph(node); } else if (node.type === schema.nodes.hardBreak) { return encodeHardBreak(); } else if (node.type === schema.nodes.codeBlock) { return encodeCodeBlock(node); } else if (node.type === schema.nodes.panel) { return encodePanel(node); } else if (node.type === schema.nodes.mention) { return encodeMention(node); } else if (node.type === schema.nodes.confluenceUnsupportedBlock || node.type === schema.nodes.confluenceUnsupportedInline) { return encodeUnsupported(node); } else if (node.type === schema.nodes.mediaGroup) { return encodeMediaGroup(node); } else if (node.type === schema.nodes.mediaSingle) { return encodeMediaSingle(node); } else if (node.type === schema.nodes.media) { return encodeMedia(node); } else if (node.type === schema.nodes.table) { return encodeTable(node); } else if (node.type === schema.nodes.emoji) { return encodeEmoji(node); } else if (node.type === schema.nodes.taskList) { return encodeTaskList(node); } else if (node.type === schema.nodes.date) { return encodeDate(node); } else if (node.type === schema.nodes.placeholder) { return encodePlaceholder(node); } return encodeAsADF(node); } function encodeBlockquote(node) { var elem = doc.createElement('blockquote'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeFragment(fragment) { var documentFragment = doc.createDocumentFragment(); fragment.forEach(function (node) { var domNode = encodeNode(node); if (domNode) { documentFragment.appendChild(domNode); } }); return documentFragment; } function encodeEmoji(node) { var elem = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:emoticon'); var _node$attrs = node.attrs, id = _node$attrs.id, shortName = _node$attrs.shortName, text = _node$attrs.text; elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:name', (0, _adfSchema.getEmojiAcName)({ id: id, shortName: shortName })); elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:emoji-id', id); elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:emoji-shortname', shortName); if (text) { elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:emoji-fallback', text); } return elem; } function encodeHeading(node) { var elem = doc.createElement("h".concat(node.attrs.level)); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeParagraph(node) { var elem = doc.createElement('p'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeMediaGroup(node) { var elem = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:media-group'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeMediaSingle(node) { var elem = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:media-single'); var attrs = node.attrs; elem.setAttribute('layout', attrs.layout); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeMedia(node) { var elem = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:media'); var attrs = node.attrs; elem.setAttribute('media-id', attrs.id); elem.setAttribute('media-type', attrs.type); elem.setAttribute('media-collection', attrs.collection); if (attrs.width) { elem.setAttribute('width', "".concat(attrs.width)); } if (attrs.height) { elem.setAttribute('height', "".concat(attrs.height)); } if (attrs.__fileName) { elem.setAttribute('file-name', attrs.__fileName); } if (attrs.__fileSize) { elem.setAttribute('file-size', "".concat(attrs.__fileSize)); } if (attrs.__fileMimeType) { elem.setAttribute('file-mime-type', attrs.__fileMimeType); } return elem; } function encodeTable(node) { var elem = doc.createElement('table'); var colgroup = doc.createElement('colgroup'); var tbody = doc.createElement('tbody'); var isNumberColumnEnabled = node.attrs.isNumberColumnEnabled; var tableColumnWidths = (0, _utils.calcTableColumnWidths)(node); node.content.forEach(function (rowNode) { var rowElement = doc.createElement('tr'); rowNode.content.forEach(function (colNode, _, j) { var _colNode$attrs = colNode.attrs, background = _colNode$attrs.background, rowspan = _colNode$attrs.rowspan, colspan = _colNode$attrs.colspan; var cellElement = colNode.type === schema.nodes.tableCell ? doc.createElement('td') : doc.createElement('th'); if (isNumberColumnEnabled && j === 0) { cellElement.className = 'numberingColumn'; } if (background) { cellElement.setAttribute('data-highlight-colour', (_adfSchema.tableBackgroundColorPalette.get(background.toLowerCase()) || background).toLowerCase()); } if (colspan && colspan !== 1) { cellElement.setAttribute('colspan', colspan); } if (rowspan && rowspan !== 1) { cellElement.setAttribute('rowspan', rowspan); } cellElement.appendChild(encodeFragment(colNode.content)); rowElement.appendChild(cellElement); }); tbody.appendChild(rowElement); }); // now we have all the column widths, assign them to each <col> in the <colgroup> tableColumnWidths.forEach(function (colwidth) { var colInfoElement = document.createElement('col'); if (colwidth) { colInfoElement.style.width = colwidth + 'px'; } colgroup.appendChild(colInfoElement); }); elem.appendChild(colgroup); elem.appendChild(tbody); var tableClasses = ['wrapped']; if (tableColumnWidths.length && tableColumnWidths.every(function (width) { return width > 0; })) { tableClasses.push('fixed-table'); } elem.setAttribute('class', tableClasses.join(' ')); return elem; } function encodeText(node) { if (node.text) { var root = doc.createDocumentFragment(); var elem = root; // Group marks by type name so we can have better processing of duplicate types var groupedMarks = {}; node.marks.forEach(function (mark) { if (!groupedMarks[mark.type.name]) { groupedMarks[mark.type.name] = []; } groupedMarks[mark.type.name].push(mark); }, {}); for (var _i = 0, _Object$keys = Object.keys(groupedMarks); _i < _Object$keys.length; _i++) { var type = _Object$keys[_i]; var marks = groupedMarks[type]; switch (type) { case 'strong': elem = elem.appendChild(doc.createElement('strong')); break; case 'em': elem = elem.appendChild(doc.createElement('em')); break; case 'strike': elem = elem.appendChild(doc.createElement('s')); break; case 'underline': elem = elem.appendChild(doc.createElement('u')); break; case 'subsup': elem = elem.appendChild(doc.createElement(marks[0].attrs['type'])); break; case 'code': elem = elem.appendChild(doc.createElement('code')); break; case 'mentionQuery': break; case 'link': var mark = (0, _utils2.getNodeMarkOfType)(node, schema.marks.link); if (mark && mark.attrs.__confluenceMetadata !== null) { // need to use fab:adf to maintain confluenceMetadata return encodeAsADF(node); } else { elem = elem.appendChild(encodeLink(node)); } break; case 'confluenceInlineComment': // Because this function encodes marks into dom nodes inwards, multiple inline comment // marks on the same PM node will be applied in reverse order. The code below compensates // for that while retaining current behaviour. var _iterator = _createForOfIteratorHelper((0, _toConsumableArray2.default)(marks).reverse()), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var _mark = _step.value; elem = elem.appendChild(encodeConfluenceInlineComment(_mark)); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } break; case 'textColor': elem = elem.appendChild(encodeTextColor(node, schema)); break; case 'backgroundColor': elem = elem.appendChild(encodeBackgroundColor(node, schema)); break; case 'emojiQuery': break; default: throw new Error("Unable to encode mark '".concat(type, "'")); } } elem.textContent = node.text; return root; } else { return doc.createTextNode(''); } } function encodeHardBreak() { return doc.createElement('br'); } function encodeHorizontalRule() { return doc.createElement('hr'); } function encodeBulletList(node) { var elem = doc.createElement('ul'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeOrderedList(node) { var elem = doc.createElement('ol'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeListItem(node) { var elem = doc.createElement('li'); elem.appendChild(encodeFragment(node.content)); return elem; } function encodeLink(node) { var link = doc.createElement('a'); var mark = (0, _utils2.getNodeMarkOfType)(node, schema.marks.link); link.href = mark ? mark.attrs.href : ''; return link; } function encodeTextColor(node, schema) { var elem = doc.createElement('span'); var mark = (0, _utils2.getNodeMarkOfType)(node, schema.marks.textColor); var color = (0, _adfSchema.hexToRgb)(mark ? mark.attrs.color : ''); if (color !== null) { elem.style.color = color; } return elem; } function encodeBackgroundColor(node, schema) { var elem = doc.createElement('span'); var mark = (0, _utils2.getNodeMarkOfType)(node, schema.marks.backgroundColor); var color = (0, _adfSchema.hexToRgb)(mark ? mark.attrs.color : ''); if (color !== null) { elem.style.backgroundColor = color; } return elem; } function encodeCodeBlock(node) { var elem = createMacroElement('code', '1'); if (node.attrs.language) { elem.appendChild((0, _utils2.encodeMacroParams)(doc, { language: { value: (0, _languageMap.mapCodeLanguage)(node.attrs.language) } })); } var plainTextBody = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:plain-text-body'); var fragment = doc.createDocumentFragment(); (node.textContent || '' // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp ).split(/]]>/g).map(function (value, index, array) { var isFirst = index === 0; var isLast = index === array.length - 1; var prefix = isFirst ? '' : '>'; var suffix = isLast ? '' : ']]'; return doc.createCDATASection(prefix + value + suffix); }).forEach(function (cdata) { return fragment.appendChild(cdata); }); plainTextBody.appendChild(fragment); elem.appendChild(plainTextBody); return elem; } function encodePanel(node) { var panelType = (0, _utils2.mapPanelTypeToCxhtml)(node.attrs.panelType); var elem = createMacroElement(panelType, '1'); var body = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:rich-text-body'); var fragment = doc.createDocumentFragment(); node.descendants(function (node, pos) { // there is at least one top-level paragraph node in the panel body // all text nodes will be handled by "encodeNode" if (node.isBlock) { // panel title if (node.type.name === 'heading' && pos === 0) { elem.appendChild((0, _utils2.encodeMacroParams)(doc, { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion title: { value: node.firstChild.textContent } })); } else { // panel content var domNode = encodeNode(node); if (domNode) { fragment.appendChild(domNode); } } } return false; }); // special treatment for <ac:structured-macro ac:name="panel" /> // it should be converted to "purple" Confluence panel if (panelType === 'panel') { elem.appendChild((0, _utils2.encodeMacroParams)(doc, { borderColor: { value: '#998DD9' }, bgColor: { value: '#EAE6FF' } })); } body.appendChild(fragment); elem.appendChild(body); return elem; } function encodeMention(node) { var link = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:link'); var mention = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:mention'); mention.setAttribute('atlassian-id', node.attrs['id']); // ED-3634: we're removing cdata completely link.appendChild(mention); return link; } function encodeUnsupported(node) { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var domNode = (0, _parseCxhtml.default)(node.attrs.cxhtml || '').querySelector('body').firstChild; if (domNode) { return doc.importNode(domNode, true); } return; } function encodeJiraIssue(node) { var elem = createMacroElement('jira', node.attrs.schemaVersion); elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:macro-id', node.attrs.macroId); elem.appendChild((0, _utils2.encodeMacroParams)(doc, { key: { value: node.attrs.issueKey }, server: { value: node.attrs.server }, serverId: { value: node.attrs.serverId } })); return elem; } function createMacroElement(name, version) { var elem = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:structured-macro'); elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:name', name); elem.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:schema-version', version); return elem; } function encodeConfluenceInlineComment(mark) { var marker = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:inline-comment-marker'); var reference = mark ? mark.attrs.reference : ''; marker.setAttributeNS(_encodeCxhtml.AC_XMLNS, 'ac:ref', reference); return marker; } function encodeTaskList(node) { var elem = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:task-list'); node.descendants(function (item) { if (item.type === schema.nodes.taskItem) { var taskItem = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:task'); var id = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:task-id'); var status = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:task-status'); id.textContent = item.attrs.localId; status.textContent = item.attrs.state === 'DONE' ? 'complete' : 'incomplete'; taskItem.appendChild(id); taskItem.appendChild(status); if (item.content.size) { var body = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:task-body'); var span = doc.createElement('span'); span.setAttribute('class', 'placeholder-inline-tasks'); span.appendChild(encodeFragment(item.content)); body.appendChild(span); taskItem.appendChild(body); } elem.appendChild(taskItem); } return false; }); return elem; } function encodeDate(node) { var elem = doc.createElement('time'); var timestamp = node.attrs.timestamp; if (timestamp) { elem.setAttribute('datetime', (0, _utils.timestampToIsoFormat)(timestamp)); } return elem; } function encodePlaceholder(node) { var elem = doc.createElementNS(_encodeCxhtml.AC_XMLNS, 'ac:placeholder'); var text = node.attrs.text; elem.textContent = text; return elem; } function encodeAsADF(node) { var nsNode = doc.createElementNS(_encodeCxhtml.FAB_XMLNS, 'fab:adf'); nsNode.appendChild(doc.createCDATASection(JSON.stringify(node.toJSON()))); return nsNode; } }