UNPKG

@atlaskit/editor-wikimarkup-transformer

Version:

Wiki markup transformer for JIRA and Confluence

202 lines (198 loc) 7.06 kB
"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 }; }