UNPKG

@atlaskit/editor-wikimarkup-transformer

Version:

Wiki markup transformer for JIRA and Confluence

266 lines (260 loc) 9.27 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.list = exports.MAX_LIST_DEPTH = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _listBuilder = require("../builder/list-builder"); var _text = require("../text"); var _normalize = require("../utils/normalize"); var _keyword = require("./keyword"); var _ = require("./"); var _whitespace = require("./whitespace"); var _text2 = require("../utils/text"); var MAX_LIST_DEPTH = exports.MAX_LIST_DEPTH = 20; // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp var LIST_ITEM_REGEXP = new RegExp("^ *([*\\-#]{1,".concat(MAX_LIST_DEPTH, "}) ")); // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp var EMPTY_LINE_REGEXP = /^[ \t]*\r?\n/; // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp var RULER_SYMBOL_REGEXP = /^-{4,5}/; var processState = { NEW_LINE: 0, BUFFER: 1, END: 2, MACRO: 3 }; var list = exports.list = function list(_ref) { var input = _ref.input, position = _ref.position, schema = _ref.schema, context = _ref.context; /** * The following token types will be ignored in parsing * the content of a listItem */ var ignoreTokenTypes = [_.TokenType.QUADRUPLE_DASH_SYMBOL, _.TokenType.LIST, _.TokenType.TABLE]; var index = position; var state = processState.NEW_LINE; var buffer = []; var lastListSymbols = null; var builder = null; var contentBuffer = []; var output = []; while (index < input.length) { var char = input.charAt(index); switch (state) { case processState.NEW_LINE: { var substring = input.substring(index); var listMatch = substring.match(LIST_ITEM_REGEXP); if (listMatch) { var _listMatch = (0, _slicedToArray2.default)(listMatch, 2), symbols = _listMatch[1]; // Handle ruler in list var rulerMatch = symbols.match(RULER_SYMBOL_REGEXP); if (rulerMatch) { var remainingAfterSymbol = input.substring(index + rulerMatch[0].length); var _emptyLineMatch = remainingAfterSymbol.match(EMPTY_LINE_REGEXP); // If this is an empty line skip to the buffering step rather than match as a list element if (_emptyLineMatch) { state = processState.BUFFER; continue; } } if (!builder) { // It happens because this is the first item of the list builder = new _listBuilder.ListBuilder(schema, symbols); lastListSymbols = symbols; } else { /** * There is a builder, so we are in the middle of building a list * and now there is a new list item */ if (buffer.length > 0) { var _contentBuffer; // Wrap up previous list item and clear buffer var content = (0, _text.parseString)({ ignoreTokenTypes: ignoreTokenTypes, schema: schema, context: context, input: buffer.join(''), includeLeadingSpace: true }); (_contentBuffer = contentBuffer).push.apply(_contentBuffer, (0, _toConsumableArray2.default)(content)); builder.add([{ style: lastListSymbols, content: sanitize((0, _normalize.normalizePMNodes)(contentBuffer, schema), schema) }]); buffer = []; contentBuffer = []; } // We finished last list item here, going to the new one lastListSymbols = symbols; var type = (0, _listBuilder.getType)(symbols); // If it's top level and doesn't match, create a new list if (type !== builder.type && symbols.length === 1) { output.push.apply(output, (0, _toConsumableArray2.default)(builder.buildPMNode())); builder = new _listBuilder.ListBuilder(schema, symbols); } } index += listMatch[0].length; } // If we encounter an empty line, we should end the list var emptyLineMatch = substring.match(EMPTY_LINE_REGEXP); if (emptyLineMatch) { state = processState.END; continue; } state = processState.BUFFER; continue; } case processState.BUFFER: { var length = (0, _whitespace.parseNewlineOnly)(input.substring(index)); if (length) { buffer.push(input.substr(index, length)); state = processState.NEW_LINE; index += length; continue; } if (char === '{') { state = processState.MACRO; continue; } else { buffer.push(char); } break; } case processState.MACRO: { var match = (0, _keyword.parseMacroKeyword)(input.substring(index)); if (!match) { buffer.push(char); state = processState.BUFFER; break; } var token = (0, _.parseToken)(input, match.type, index, schema, context); buffer.push(input.substr(index, token.length)); index += token.length; state = processState.BUFFER; continue; } case processState.END: { if (!builder) { // Something is really wrong here return fallback(input, position); } if (buffer.length > 0) { var _contentBuffer2; // Wrap up previous list item and clear buffer var _content = (0, _text.parseString)({ ignoreTokenTypes: ignoreTokenTypes, schema: schema, context: context, input: buffer.join(''), includeLeadingSpace: true }); (_contentBuffer2 = contentBuffer).push.apply(_contentBuffer2, (0, _toConsumableArray2.default)(_content)); } builder.add([{ style: lastListSymbols, content: sanitize((0, _normalize.normalizePMNodes)(contentBuffer, schema), schema) }]); output.push.apply(output, (0, _toConsumableArray2.default)(builder.buildPMNode())); return { type: 'pmnode', nodes: output, length: index - position }; } } index++; } if (buffer.length > 0) { var _contentBuffer3; // Wrap up what's left in the buffer var _content2 = (0, _text.parseString)({ ignoreTokenTypes: ignoreTokenTypes, schema: schema, context: context, input: buffer.join(''), includeLeadingSpace: true }); (_contentBuffer3 = contentBuffer).push.apply(_contentBuffer3, (0, _toConsumableArray2.default)(_content2)); } if (builder) { builder.add([{ style: lastListSymbols, content: sanitize((0, _normalize.normalizePMNodes)(contentBuffer, schema), schema) }]); output.push.apply(output, (0, _toConsumableArray2.default)(builder.buildPMNode())); } return { type: 'pmnode', nodes: output, length: index - position }; }; function sanitize(nodes, schema) { return nodes.reduce(function (result, curr) { switch (curr.type.name) { case 'blockquote': { /** * If a blockquote is inside a list item * - Convert it to paragraph */ curr.content.forEach(function (n) { result.push(n); }); break; } case 'heading': { /** * If a heading is inside a list item * - Convert the heading to paragraph * - Convert text to upper case * - Mark text with strong. */ var contentBuffer = []; curr.content.forEach(function (n) { var mark = schema.marks.strong.create(); if (n.type.name === 'text') { if (n.text) { // @ts-ignore - [unblock prosemirror bump] allow assign to readonly n.text = n.text.toUpperCase(); } if (n.type.name === 'text' && !(0, _text2.hasAnyOfMarks)(n, ['strong', 'code'])) { contentBuffer.push(n.mark([].concat((0, _toConsumableArray2.default)(n.marks), [mark]))); } else { contentBuffer.push(n); } } else { contentBuffer.push(n); } }); var p = schema.nodes.paragraph.createChecked({}, contentBuffer); result.push(p); break; } default: result.push(curr); } return result; }, []); } function fallback(input, position) { return { type: 'text', text: input.substr(position, 1), length: 1 }; }