@atlaskit/editor-wikimarkup-transformer
Version:
Wiki markup transformer for JIRA and Confluence
266 lines (260 loc) • 9.27 kB
JavaScript
"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
};
}