UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

277 lines • 11.1 kB
"use strict"; 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