@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
277 lines • 11.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var _1 = require("../");
var matches_1 = require("./matches");
var schema_1 = require("./schema");
/**
* ProseMirror doesn't support empty text nodes, which can be quite
* inconvenient when you want to capture a position ref without introducing
* text.
*
* Take a couple of examples:
*
* p('{<>}')
* p('Hello ', '{<>}', 'world!')
*
* After the ref syntax is stripped you're left with:
*
* p('')
* p('Hello ', '', 'world!')
*
* This violates the rule of text nodes being non-empty. This class solves the
* problem by providing an alternative data structure that *only* stores refs,
* and can be used in scenarios where an empty text would be forbidden.
*
* This is done under the hood when using `text()` factory, and instead of
* always returning a text node, it'll instead return one of two things:
*
* - a text node -- when given a non-empty string
* - a refs tracker -- when given a string that *only* contains refs.
*/
var RefsTracker = (function () {
function RefsTracker() {
}
return RefsTracker;
}());
exports.RefsTracker = RefsTracker;
/**
* Create a text node.
*
* Special markers called "refs" can be put in the text. Refs provide a way to
* declaratively describe a position within some text, and then access the
* position in the resulting node.
*/
function text(value, schema) {
var stripped = '';
var textIndex = 0;
var refs = {};
// Helpers
var isEven = function (n) { return n % 2 === 0; };
for (var _i = 0, _a = matches_1.default(value, /([\\]+)?{(\w+|<|>|<>)}/g); _i < _a.length; _i++) {
var match = _a[_i];
var refToken = match[0], skipChars = match[1], refName = match[2];
var index = match.index;
var skipLen = skipChars && skipChars.length;
if (skipLen) {
if (isEven(skipLen)) {
index += (skipLen / 2);
}
else {
stripped += value.slice(textIndex, index + ((skipLen - 1) / 2));
stripped += value.slice(index + skipLen, index + refToken.length);
textIndex = index + refToken.length;
continue;
}
}
stripped += value.slice(textIndex, index);
refs[refName] = stripped.length;
textIndex = match.index + refToken.length;
}
stripped += value.slice(textIndex);
var node = stripped === ''
? new RefsTracker()
: schema.text(stripped);
node.refs = refs;
return node;
}
exports.text = text;
/**
* Offset ref position values by some amount.
*/
function offsetRefs(refs, offset) {
var result = {};
for (var name_1 in refs) {
result[name_1] = refs[name_1] + offset;
}
return result;
}
exports.offsetRefs = offsetRefs;
/**
* Given a collection of nodes, sequence them in an array and return the result
* along with the updated refs.
*/
function sequence() {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
var position = 0;
var refs = {};
var nodes = [];
// It's bizarre that this is necessary. An if/else in the for...of should have
// sufficient but it did not work at the time of writing.
var isRefsTracker = function (n) { return n instanceof RefsTracker; };
var isRefsNode = function (n) { return !isRefsTracker(n); };
for (var _a = 0, content_1 = content; _a < content_1.length; _a++) {
var node = content_1[_a];
if (isRefsTracker(node)) {
refs = tslib_1.__assign({}, refs, offsetRefs(node.refs, position));
}
if (isRefsNode(node)) {
var thickness = node.isText ? 0 : 1;
refs = tslib_1.__assign({}, refs, offsetRefs(node.refs, position + thickness));
position += node.nodeSize;
nodes.push(node);
}
}
return { nodes: nodes, refs: refs };
}
exports.sequence = sequence;
/**
* Given a jagged array, flatten it down to a single level.
*/
function flatten(deep) {
var flat = [];
for (var _i = 0, deep_1 = deep; _i < deep_1.length; _i++) {
var item = deep_1[_i];
if (Array.isArray(item)) {
flat.splice.apply(flat, [flat.length, 0].concat(item));
}
else {
flat.push(item);
}
}
return flat;
}
exports.flatten = flatten;
/**
* Coerce builder content into ref nodes.
*/
function coerce(content, schema) {
var refsContent = content
.map(function (item) { return typeof item === 'string'
? text(item, schema)
: item; });
return sequence.apply(void 0, flatten(refsContent));
}
exports.coerce = coerce;
/**
* Create a factory for nodes.
*/
function nodeFactory(type, attrs) {
if (attrs === void 0) { attrs = {}; }
return function () {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
var _a = coerce(content, type.schema), nodes = _a.nodes, refs = _a.refs;
var node = type.create(attrs, nodes);
node.refs = refs;
return node;
};
}
exports.nodeFactory = nodeFactory;
/**
* Create a factory for marks.
*/
function markFactory(type, attrs) {
if (attrs === void 0) { attrs = {}; }
var mark = type.create(attrs);
return function () {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
var nodes = coerce(content, type.schema).nodes;
return nodes
.map(function (node) {
if (mark.type.isInSet(node.marks)) {
return node;
}
else {
var refNode = node.mark(mark.addToSet(node.marks));
refNode.refs = node.refs;
return refNode;
}
});
};
}
exports.markFactory = markFactory;
exports.createCell = function (colspan, rowspan) { return exports.td({ colspan: colspan, rowspan: rowspan })(exports.p('x')); };
exports.createHeaderCell = function (colspan, rowspan) { return exports.th({ colspan: colspan, rowspan: rowspan })(exports.p('x')); };
exports.doc = nodeFactory(schema_1.default.nodes.doc, {});
exports.p = nodeFactory(schema_1.default.nodes.paragraph, {});
exports.blockquote = nodeFactory(schema_1.default.nodes.blockquote, {});
exports.h1 = nodeFactory(schema_1.default.nodes.heading, { level: 1 });
exports.h2 = nodeFactory(schema_1.default.nodes.heading, { level: 2 });
exports.h3 = nodeFactory(schema_1.default.nodes.heading, { level: 3 });
exports.h4 = nodeFactory(schema_1.default.nodes.heading, { level: 4 });
exports.h5 = nodeFactory(schema_1.default.nodes.heading, { level: 5 });
exports.h6 = nodeFactory(schema_1.default.nodes.heading, { level: 6 });
exports.li = nodeFactory(schema_1.default.nodes.listItem, {});
exports.ul = nodeFactory(schema_1.default.nodes.bulletList, {});
exports.ol = nodeFactory(schema_1.default.nodes.orderedList, {});
exports.br = schema_1.default.nodes.hardBreak.createChecked();
exports.panel = nodeFactory(schema_1.default.nodes.panel, {});
exports.panelNote = nodeFactory(schema_1.default.nodes.panel, { panelType: 'note' });
exports.plain = nodeFactory(schema_1.default.nodes.plain, {});
exports.hardBreak = nodeFactory(schema_1.default.nodes.hardBreak, {});
// tslint:disable-next-line:variable-name
exports.code_block = function (attrs) {
if (attrs === void 0) { attrs = {}; }
return nodeFactory(schema_1.default.nodes.codeBlock, attrs);
};
exports.img = function (attrs) { return schema_1.default.nodes.image.createChecked(attrs); };
exports.emoji = function (attrs) {
var emojiNodeAttrs = {
shortName: attrs.shortName,
id: attrs.id,
text: attrs.fallback || attrs.shortName,
};
return schema_1.default.nodes.emoji.createChecked(emojiNodeAttrs);
};
exports.mention = function (attrs) { return schema_1.default.nodes.mention.createChecked(attrs); };
exports.hr = schema_1.default.nodes.rule.createChecked();
exports.em = markFactory(schema_1.default.marks.em, {});
exports.subsup = function (attrs) { return markFactory(schema_1.default.marks.subsup, attrs); };
exports.underline = markFactory(schema_1.default.marks.underline, {});
exports.strong = markFactory(schema_1.default.marks.strong, {});
exports.code = markFactory(schema_1.default.marks.code, {});
exports.strike = markFactory(schema_1.default.marks.strike, {});
exports.mentionQuery = function (attrs) {
if (attrs === void 0) { attrs = { active: true }; }
return markFactory(schema_1.default.marks.mentionQuery, attrs ? attrs : {});
};
exports.a = function (attrs) { return markFactory(schema_1.default.marks.link, attrs); };
exports.fragment = function () {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
return flatten(content);
};
exports.slice = function () {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
return new _1.Slice(_1.Fragment.from(coerce(content, schema_1.default).nodes), 0, 0);
};
exports.emojiQuery = markFactory(schema_1.default.marks.emojiQuery, {});
exports.singleImage = function (attrs) {
if (attrs === void 0) { attrs = {}; }
return nodeFactory(schema_1.default.nodes.singleImage, attrs);
};
exports.mediaGroup = nodeFactory(schema_1.default.nodes.mediaGroup);
exports.media = function (attrs) { return schema_1.default.nodes.media.create(attrs); };
exports.textColor = function (attrs) { return markFactory(schema_1.default.marks.textColor, attrs); };
exports.table = nodeFactory(schema_1.default.nodes.table, {});
exports.tr = nodeFactory(schema_1.default.nodes.tableRow, {});
exports.td = function (attrs) { return nodeFactory(schema_1.default.nodes.tableCell, attrs); };
exports.th = function (attrs) { return nodeFactory(schema_1.default.nodes.tableHeader, attrs); };
exports.tdEmpty = exports.td({})(exports.p(''));
exports.thEmpty = exports.th({})(exports.p(''));
exports.tdCursor = exports.td({})(exports.p('{<>}'));
exports.thCursor = exports.th({})(exports.p('{<>}'));
exports.td11 = exports.createCell(1, 1);
exports.th11 = exports.createHeaderCell(1, 1);
exports.decisionList = nodeFactory(schema_1.default.nodes.decisionList, {});
exports.decisionItem = nodeFactory(schema_1.default.nodes.decisionItem, {});
exports.taskList = nodeFactory(schema_1.default.nodes.taskList, {});
exports.taskItem = nodeFactory(schema_1.default.nodes.taskItem, {});
exports.confluenceUnsupportedBlock = function (cxhtml) { return nodeFactory(schema_1.default.nodes.confluenceUnsupportedBlock, { cxhtml: cxhtml })(); };
exports.confluenceUnsupportedInline = function (cxhtml) { return nodeFactory(schema_1.default.nodes.confluenceUnsupportedInline, { cxhtml: cxhtml })(); };
exports.confluenceJiraIssue = function (attrs) { return schema_1.default.nodes.confluenceJiraIssue.create(attrs); };
//# sourceMappingURL=schema-builder.js.map