@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
303 lines • 12.9 kB
JavaScript
import * as namedColors from 'css-color-names';
import { isSchemaWithLists, isSchemaWithMentions, isSchemaWithLinks, isSchemaWithAdvancedTextFormattingMarks, isSchemaWithCodeBlock, isSchemaWithBlockQuotes, isSchemaWithMedia, isSchemaWithSubSupMark, isSchemaWithTextColor, isSchemaWithTables } from './schema';
import { Fragment, } from '../../prosemirror';
/**
* Ensure that each node in the fragment is a block, wrapping
* in a block node if necessary.
*/
export function ensureBlocks(fragment, schema) {
// If all the nodes are inline, we want to wrap in a single paragraph.
if (schema.nodes.paragraph.validContent(fragment)) {
return Fragment.fromArray([schema.nodes.paragraph.createChecked({}, fragment)]);
}
// Either all the nodes are blocks, or a mix of inline and blocks.
// We convert each (if any) inline nodes to blocks.
var blockNodes = [];
fragment.forEach(function (child) {
if (child.isBlock) {
blockNodes.push(child);
}
else {
blockNodes.push(schema.nodes.paragraph.createChecked({}, child));
}
});
return Fragment.fromArray(blockNodes);
}
export function convert(content, node, schema) {
// text
if (node.nodeType === Node.TEXT_NODE) {
var text = node.textContent;
return text ? schema.text(text) : null;
}
// marks and nodes
if (node instanceof HTMLElement) {
var tag = node.tagName.toUpperCase();
switch (tag) {
// Marks
case 'DEL':
if (!isSchemaWithAdvancedTextFormattingMarks(schema)) {
return null;
}
return addMarks(content, [schema.marks.strike.create()]);
case 'B':
return addMarks(content, [schema.marks.strong.create()]);
case 'EM':
return addMarks(content, [schema.marks.em.create()]);
case 'TT':
if (!isSchemaWithAdvancedTextFormattingMarks(schema)) {
return null;
}
return addMarks(content, [schema.marks.code.create()]);
case 'SUB':
case 'SUP':
if (!isSchemaWithSubSupMark(schema)) {
return null;
}
var type = tag === 'SUB' ? 'sub' : 'sup';
return addMarks(content, [schema.marks.subsup.create({ type: type })]);
case 'INS':
return addMarks(content, [schema.marks.underline.create()]);
case 'FONT':
if (!isSchemaWithTextColor(schema)) {
return null;
}
var color = getValidColor(node.getAttribute('color'));
return color ? addMarks(content, [schema.marks.textColor.create({ color: color })]) : content;
// Nodes
case 'A':
if (node.className === 'user-hover' && isSchemaWithMentions(schema)) {
return schema.nodes.mention.createChecked({
id: node.getAttribute('rel'),
text: node.innerText
});
}
var isAnchor = node.attributes.getNamedItem('href') === null;
if (isAnchor || node.className.match('jira-issue-macro-key') || !content || !isSchemaWithLinks(schema)) {
return null;
}
return addMarks(content, [schema.marks.link.create({
href: node.getAttribute('href'),
title: node.getAttribute('title')
})]);
case 'SPAN':
/**
* JIRA ISSUE MACROS
* `````````````````
* <span class="jira-issue-macro" data-jira-key="ED-1">
* <a href="https://product-fabric.atlassian.net/browse/ED-1" class="jira-issue-macro-key issue-link">
* <img class="icon" src="./epic.svg" />
* ED-1
* </a>
* <span class="aui-lozenge aui-lozenge-subtle aui-lozenge-current jira-macro-single-issue-export-pdf">
* In Progress
* </span>
* </span>
*/
if (node.className === 'jira-issue-macro') {
var jiraKey = node.dataset.jiraKey;
return jiraKey ? schema.text(jiraKey) : null;
}
else if (node.className.match('jira-macro-single-issue-export-pdf')) {
return null;
}
else if (node.className.match('code-')) {
return null;
}
else if (isMedia(node) && isSchemaWithMedia(schema)) {
var dataNode = node.querySelector('[data-media-services-id]');
if (dataNode && dataNode instanceof HTMLElement) {
var _a = dataNode.dataset, id = _a.mediaServicesId, type_1 = _a.mediaServicesType, _b = _a.mediaServicesCollection, collection = _b === void 0 ? '' : _b, attachmentName = _a.attachmentName, attachmentType = _a.attachmentType, fileName = _a.fileName, displayType = _a.displayType;
return schema.nodes.media.create({
id: id, type: type_1, collection: collection,
__fileName: attachmentName || fileName,
__displayType: attachmentType || displayType || 'thumbnail',
});
}
}
break;
case 'IMG':
if (node.parentElement && node.parentElement.className.match('jira-issue-macro-key')) {
return null;
}
break;
case 'H1':
case 'H2':
case 'H3':
case 'H4':
case 'H5':
case 'H6':
var level = Number(tag.charAt(1));
return schema.nodes.heading.createChecked({ level: level }, content);
case 'BR':
return schema.nodes.hardBreak.createChecked();
case 'HR':
return schema.nodes.rule.createChecked();
case 'P':
if (node.firstChild && (isMedia(node.firstChild))) {
// Filter out whitespace text nodes
var mediaContent_1 = [];
var hasNonMediaChildren_1 = false;
content.forEach(function (child) {
if (child.type === schema.nodes.media) {
mediaContent_1.push(child);
}
else if (!(child.isText && /^\s*$/.test(child.text || ''))) {
hasNonMediaChildren_1 = true;
}
});
if (hasNonMediaChildren_1) {
return schema.nodes.paragraph.createChecked({}, content);
}
if (isSchemaWithMedia(schema)) {
return schema.nodes.mediaGroup.createChecked({}, Fragment.fromArray(mediaContent_1));
}
return null;
}
return schema.nodes.paragraph.createChecked({}, content);
}
// lists
if (isSchemaWithLists(schema)) {
switch (tag) {
case 'UL':
return schema.nodes.bulletList.createChecked({}, content);
case 'OL':
return schema.nodes.orderedList.createChecked({}, content);
case 'LI':
var compatibleContent = schema.nodes.listItem.validContent(content)
? content
: ensureBlocks(content, schema);
return schema.nodes.listItem.createChecked({}, compatibleContent);
}
}
// code block
if (isSchemaWithCodeBlock(schema)) {
switch (tag) {
case 'DIV':
if (node.className === 'codeContent panelContent' || node.className.match('preformattedContent')) {
return null;
}
else if (node.className === 'code panel' || node.className === 'preformatted panel') {
var pre = node.querySelector('pre');
if (!pre) {
return null;
}
var language = node.className === 'preformatted panel'
? 'plain'
: pre.className.split('-')[1];
var textContent = pre.innerText.replace(/\r\n/g, '\n');
return schema.nodes.codeBlock.createChecked({ language: language }, textContent
? schema.text(textContent)
: undefined);
}
break;
case 'PRE':
return null;
}
}
if (isSchemaWithBlockQuotes(schema) && tag === 'BLOCKQUOTE') {
var blockquoteContent = content && content.content.length ? content : schema.nodes.paragraph.create();
return schema.nodes.blockquote.createChecked({}, blockquoteContent);
}
// table
if (isSchemaWithTables(schema)) {
switch (tag) {
case 'TABLE':
return schema.nodes.table.createChecked({}, content);
case 'TR':
return schema.nodes.tableRow.createChecked({}, content);
case 'TD':
var tdContent = schema.nodes.tableCell.validContent(content)
? content
: ensureBlocks(content, schema);
return schema.nodes.tableCell.createChecked({}, tdContent);
case 'TH':
var thContent = schema.nodes.tableHeader.validContent(content)
? content
: ensureBlocks(content, schema);
return schema.nodes.tableHeader.createChecked({}, thContent);
}
}
}
}
/*
* Flattens DOM tree into single array
*/
export function bfsOrder(root) {
var inqueue = [root];
var outqueue = [];
var elem;
while (elem = inqueue.shift()) {
outqueue.push(elem);
var childIndex = void 0;
for (childIndex = 0; childIndex < elem.childNodes.length; childIndex++) {
var child = elem.childNodes[childIndex];
switch (child.nodeType) {
case Node.ELEMENT_NODE:
case Node.TEXT_NODE:
inqueue.push(child);
break;
default:
console.error("Not pushing: " + child.nodeType + " " + child.nodeName);
}
}
}
outqueue.shift();
return outqueue;
}
/**
* Create a fragment by adding a set of marks to each node.
*/
function addMarks(fragment, marks) {
var result = fragment;
for (var i = 0; i < fragment.childCount; i++) {
var child = result.child(i);
var newChild = child;
for (var _i = 0, marks_1 = marks; _i < marks_1.length; _i++) {
var mark = marks_1[_i];
newChild = newChild.mark(mark.addToSet(newChild.marks));
}
result = result.replaceChild(i, newChild);
}
return result;
}
function getValidColor(color) {
if (!color) {
return null;
}
// Normalize
color = color.trim().toLowerCase();
if (color[0] === '#' && color.length === 4 || color.length === 7) {
if (/^#[\da-f]{3}$/.test(color)) {
color = color.split('').map(function (c) { return c === '#' ? '#' : "" + c + c; }).join('');
}
}
else {
// http://dev.w3.org/csswg/css-color/#named-colors
if (namedColors[color]) {
color = namedColors[color];
}
else {
return null;
}
}
// Default colour from old JIRA colour palette
if (color === '#333333') {
return null;
}
return color;
}
function getNodeName(node) {
return node.nodeName.toUpperCase();
}
function isMedia(node) {
if (node && node instanceof HTMLElement) {
if (node.parentNode && getNodeName(node.parentNode) === 'P') {
if (getNodeName(node) === 'SPAN') {
return !!node.querySelector('a > jira-attachment-thumbnail > img[data-attachment-type="thumbnail"], ' +
'a[data-attachment-type="file"]');
}
}
}
return false;
}
//# sourceMappingURL=util.js.map