@atlaskit/editor-wikimarkup-transformer
Version:
Wiki markup transformer for JIRA and Confluence
202 lines (198 loc) • 7.06 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.commonFormatter = commonFormatter;
var _ = require("./");
var _linkFormat = require("./links/link-format");
var _whitespace = require("./whitespace");
var _keyword = require("./keyword");
var _escape = require("../utils/escape");
var processState = {
START: 0,
BUFFER: 1,
END: 2,
INLINE_MACRO: 3,
LINK_FORMAT: 4,
ESCAPE: 5
};
function commonFormatter(input, position, schema, opt) {
var index = position;
var state = processState.START;
var buffer = [];
var openingSymbolLength = opt.opening.length;
var closingSymbolLength = opt.closing.length;
var openingWrapped = opt.opening.startsWith('{') && opt.opening.endsWith('}');
var closingWrapped = opt.closing.startsWith('{') && opt.closing.endsWith('}');
while (index < input.length) {
var char = input.charAt(index);
var twoChar = input.substr(index, 2);
var charsMatchClosingSymbol = input.substr(index, closingSymbolLength);
switch (state) {
case processState.START:
{
if (position > 0) {
/**
* If the previous char is a alphanumeric, then it's not a valid
* formatter
*/
var charBeforeOpening = input.charAt(position - 1);
if (!openingWrapped &&
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
/[a-zA-Z0-9]|[^\u0000-\u007F]/.test(charBeforeOpening) && charBeforeOpening !== "\xA0") {
return fallback(input, index, openingSymbolLength);
}
}
var charAfterOpening = input.charAt(index + openingSymbolLength);
if (!input.substring(position).startsWith(opt.opening) || charAfterOpening === ' ') {
// this is not a valid formatter mark
return fallback(input, position, openingSymbolLength);
}
state = processState.BUFFER;
index += openingSymbolLength;
continue;
}
case processState.BUFFER:
{
// the linebreak would break the strong marks
var length = (0, _whitespace.parseNewlineOnly)(input.substring(index));
if (length) {
return fallback(input, position, openingSymbolLength);
}
if (charsMatchClosingSymbol === opt.closing) {
state = processState.END;
continue;
} else if (twoChar === '{{') {
// this is a monospace
buffer.push(twoChar);
index += 2;
continue;
} else if (char === '{') {
state = processState.INLINE_MACRO;
continue;
} else if (char === '[') {
state = processState.LINK_FORMAT;
continue;
} else if (char === '\\') {
state = processState.ESCAPE;
continue;
} else {
buffer.push(char);
}
break;
}
case processState.END:
{
index += closingSymbolLength;
// empty formatter mark is treated as normal text
if (buffer.length === 0) {
return fallback(input, position, openingSymbolLength);
}
/**
* If the closing symbol is followed by a alphanumeric, it's
* not a valid formatter, and we keep looking for
* next valid closing formatter.
* ESS-1402: checking for the non-breaking space after closing symbol.
*/
if (index < input.length) {
var charAfterEnd = input.charAt(index);
if (!closingWrapped &&
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
/[a-zA-Z0-9]|[^\u0000-\u007F]/.test(charAfterEnd) && charAfterEnd !== "\xA0") {
buffer.push(charsMatchClosingSymbol);
state = processState.BUFFER;
continue;
}
}
/**
* If the closing symbol has an empty space before it,
* it's not a valid formatter
*/
if (buffer.length > 0 && buffer[buffer.length - 1].endsWith(' ')) {
return fallback(input, position, openingSymbolLength);
}
return opt.rawContentProcessor(buffer.join(''), index - position);
}
case processState.INLINE_MACRO:
{
var match = (0, _keyword.parseMacroKeyword)(input.substring(index));
if (!match) {
buffer.push(char);
state = processState.BUFFER;
break;
}
/**
* Is not a problem send an empty context because we're only checking
* if it has a nested macro inside.
*/
var token = (0, _.parseToken)(input, match.type, index, schema, {});
if (token.type === 'text') {
buffer.push(token.text);
index += token.length;
state = processState.BUFFER;
continue;
} else if (match.type === _.TokenType.COLOR_MACRO) {
/**
* {color} is valid in formatter, we simply jump over the length
*/
buffer.push(input.substr(index, token.length));
index += token.length;
state = processState.BUFFER;
continue;
} else {
// No macro are accepted in formater
return fallback(input, position, openingSymbolLength);
}
}
case processState.LINK_FORMAT:
{
/**
* We should "fly over" the link format and we dont want
* -awesome [link|https://www.atlass-ian.com] nice
* to be a strike through because of the '-' in link
*
* Also, is not a problem send an empty context because we're only
* checking if it has a nested macro inside.
*/
var _token = (0, _linkFormat.linkFormat)({
input: input,
schema: schema,
position: index,
context: {}
});
if (_token.type === 'text') {
buffer.push(_token.text);
index += _token.length;
state = processState.BUFFER;
continue;
} else if (_token.type === 'pmnode') {
buffer.push(input.substr(index, _token.length));
index += _token.length;
state = processState.BUFFER;
continue;
}
return fallback(input, position, openingSymbolLength);
}
case processState.ESCAPE:
{
var _token2 = (0, _escape.escapeHandler)(input, index);
buffer.push(_token2.text);
index += _token2.length;
state = processState.BUFFER;
continue;
}
default:
}
index++;
}
return fallback(input, position, openingSymbolLength);
}
function fallback(input, position, length) {
return {
type: 'text',
text: input.substr(position, length),
length: length
};
}