@atlaskit/editor-confluence-transformer
Version:
Editor Confluence Transformer
489 lines (484 loc) • 20.5 kB
JavaScript
"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;
}
}