@accordproject/markdown-editor
Version:
A rich text editor that can read and write markdown text. Based on Slate.js.
307 lines (231 loc) • 8 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.transformParagraphToList = exports.transformBlockQuoteToList = exports.transformListSwap = exports.transformListToParagraph = exports.transformPtoBQSwap = exports.transformListToBlockQuote = exports.currentList = exports.isClickHeading = exports.isClickBlockQuote = exports.isSelectionList = exports.isSelectionInput = exports.applyLinkUpdate = exports.removeLink = exports.hasBlock = exports.getListBool = exports.getTypeBool = exports.getSelectedListBlock = exports.isOnlyLink = exports.hasLinks = exports.hasMark = void 0;
var CONST = _interopRequireWildcard(require("../constants"));
/**
*************** INTERNAL METHODS ***************
*/
/**
* A change helper to standardize wrapping links.
*/
const wrapLink = (editor, href) => {
editor.wrapInline({
type: 'link',
data: {
href
}
}).moveToEnd().focus();
};
/**
* A Slate helper to get ancestors of the selection.
*/
const ancestors = val => val.document.getAncestors(val.selection.anchor.path);
/**
* A helper to find boolean of if Slate ancestors includes ol_list.
*/
const isSelectionOLList = val => ancestors(val).find(b => b.type === CONST.OL_LIST);
/**
* A helper to find boolean of if Slate ancestors includes ul_list.
*/
const isSelectionULList = val => ancestors(val).find(b => b.type === CONST.UL_LIST);
/**
*************** EXPORT METHODS ***************
*/
/**
* Check if the current selection has a mark with `type` in it.
*/
const hasMark = (editor, type) => {
const value = editor.value;
return value.activeMarks.some(mark => mark.type === type);
};
/**
* Check whether the current selection has a link in it.
*/
exports.hasMark = hasMark;
const hasLinks = editor => {
const value = editor.value;
return value.inlines.some(inline => inline.type === 'link');
};
exports.hasLinks = hasLinks;
const isOnlyLink = editor => {
const currentInline = editor.value.inlines.find(inline => inline.type === 'link');
if (!currentInline) return false;
const linkText = currentInline.text;
const selectedText = editor.value.document.getFragmentAtRange(editor.value.selection).text;
return linkText.includes(selectedText);
};
/**
* Return selected block of 'list_item' type.
*/
exports.isOnlyLink = isOnlyLink;
const getSelectedListBlock = editor => {
const value = editor.value;
return value.blocks.find(node => node.type === 'list_item');
};
/**
* Return whether current selection is a given type.
*/
exports.getSelectedListBlock = getSelectedListBlock;
const getTypeBool = (editor, type) => {
const value = editor.value;
const document = value.document;
return value.blocks.some(block => !!document.getClosest(block.key, parent => parent.type === type));
};
/**
* Return whether current selection is a list.
*/
exports.getTypeBool = getTypeBool;
const getListBool = (editor, type) => {
const value = editor.value;
const selectedBlockHere = getSelectedListBlock(editor);
return selectedBlockHere ? selectedBlockHere.type === 'list_item' : value.blocks.some(node => node.type === type);
};
/**
* Check if the any of the currently selected blocks are of `type`.
*/
exports.getListBool = getListBool;
const hasBlock = (editor, type) => editor.value.blocks.some(node => node.type === type);
/**
* When clicking remove, update the text by removing the link
*/
exports.hasBlock = hasBlock;
const removeLink = (event, editor) => {
event.preventDefault();
editor.unwrapInline({
type: 'link'
}).moveToEnd().focus();
};
/**
* When clicking apply, update the link with the specified text and href
*/
exports.removeLink = removeLink;
const applyLinkUpdate = (event, editor, isLink) => {
event.preventDefault();
const href = event.target.url.value;
const text = event.target.text.value;
if (!isLink && !href) return;
if (isLink && !(event.target && event.target.url && event.target.url.value) && !href) {
editor.unwrapInline({
type: 'link'
}).moveToEnd();
return;
}
if (!href || !text) return;
if (isLink) {
const linkInlineSelection = editor.value.inlines.find(inline => inline.type === 'link');
editor.withoutNormalizing(() => {
editor.unwrapInline({
type: 'link'
}).moveToRangeOfNode(linkInlineSelection).delete().insertText(text).moveFocusBackward(text.length).command(wrapLink, href);
});
return;
}
editor.insertText(text).moveFocusBackward(text.length).command(wrapLink, href);
};
/**
* A helper to find boolean of if Slate ancestors includes input block type.
*/
exports.applyLinkUpdate = applyLinkUpdate;
const isSelectionInput = (val, input) => ancestors(val).reverse().some(mark => mark.type === input);
/**
* A helper to find boolean of if Slate ancestors includes list_item.
*/
exports.isSelectionInput = isSelectionInput;
const isSelectionList = value => ancestors(value).reverse().some(mark => mark.type === CONST.LIST_ITEM);
/**
* A helper to find boolean of if input type is a block_quote.
*/
exports.isSelectionList = isSelectionList;
const isClickBlockQuote = input => input === CONST.BLOCK_QUOTE;
/**
* A helper to find boolean of if input type is a heading.
*/
exports.isClickBlockQuote = isClickBlockQuote;
const isClickHeading = input => input === CONST.H1 || input === CONST.H2 || input === CONST.H3 || input === CONST.PARAGRAPH;
/**
* A helper to hold the list type of the selection.
*/
exports.isClickHeading = isClickHeading;
const currentList = value => isSelectionOLList(value) || isSelectionULList(value);
/**
* A trigger to the Slate editor to make a list_item into a block_quote.
*/
exports.currentList = currentList;
const transformListToBlockQuote = (editor, type, value) => {
editor.withoutNormalizing(() => {
editor.unwrapBlock(CONST.LIST_ITEM).unwrapBlock(currentList(value).type).wrapBlock({
type,
data: {
tight: true
}
});
});
};
/**
* A trigger to the Slate editor to make a paragraph into a block_quote.
*/
/* eslint no-unused-expressions: 0 */
exports.transformListToBlockQuote = transformListToBlockQuote;
const transformPtoBQSwap = (editor, type) => {
isSelectionInput(editor.value, CONST.BLOCK_QUOTE) ? editor.unwrapBlock(CONST.BLOCK_QUOTE) : editor.wrapBlock({
type,
data: {
tight: true
}
});
};
/**
* A trigger to the Slate editor to make a list_item into a paragraph.
*/
exports.transformPtoBQSwap = transformPtoBQSwap;
const transformListToParagraph = (editor, type) => {
editor.withoutNormalizing(() => {
editor.setBlocks(CONST.PARAGRAPH).unwrapBlock(CONST.LIST_ITEM).unwrapBlock(type);
});
};
/**
* A trigger to the Slate editor to swap a ul_list to ol_list or vice versa.
*/
exports.transformListToParagraph = transformListToParagraph;
const transformListSwap = (editor, type, value) => {
editor.withoutNormalizing(() => {
editor.unwrapBlock(CONST.LIST_ITEM).unwrapBlock(currentList(value).type).wrapBlock({
type,
data: {
tight: true
}
}).wrapBlock(CONST.LIST_ITEM);
});
};
/**
* A trigger to the Slate editor to make a block_quote into a list_item.
*/
exports.transformListSwap = transformListSwap;
const transformBlockQuoteToList = (editor, type) => {
editor.withoutNormalizing(() => {
editor.unwrapBlock(CONST.BLOCK_QUOTE).wrapBlock({
type,
data: {
tight: true
}
}).wrapBlock(CONST.LIST_ITEM);
});
};
/**
* A trigger to the Slate editor to make a paragraph into a list_item.
*/
exports.transformBlockQuoteToList = transformBlockQuoteToList;
const transformParagraphToList = (editor, type) => {
editor.withoutNormalizing(() => {
editor.wrapBlock({
type,
data: {
tight: true
}
}).wrapBlock(CONST.LIST_ITEM);
});
};
exports.transformParagraphToList = transformParagraphToList;