UNPKG

@bauerpub/bauer-draft-js-export-markdown

Version:
288 lines (265 loc) 11.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); exports.default = stateToMarkdown; var _bauerDraftJsUtils = require('@bauerpub/bauer-draft-js-utils'); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var BOLD = _bauerDraftJsUtils.INLINE_STYLE.BOLD, CODE = _bauerDraftJsUtils.INLINE_STYLE.CODE, ITALIC = _bauerDraftJsUtils.INLINE_STYLE.ITALIC, STRIKETHROUGH = _bauerDraftJsUtils.INLINE_STYLE.STRIKETHROUGH, UNDERLINE = _bauerDraftJsUtils.INLINE_STYLE.UNDERLINE; var CODE_INDENT = ' '; function swapWhitespace(text, wrapper) { var _$exec = /(^\s?)(.+)/g.exec(text), _$exec2 = _slicedToArray(_$exec, 3), _ = _$exec2[0], leadingSpace = _$exec2[1], rest = _$exec2[2]; var suffix = /\s$/.test(rest) ? wrapper + ' ' : wrapper; var isSingleSpace = text === ' '; return isSingleSpace ? text : '' + leadingSpace + wrapper + rest.trim() + suffix; } var MarkupGenerator = function () { function MarkupGenerator(contentState) { _classCallCheck(this, MarkupGenerator); this.contentState = contentState; } _createClass(MarkupGenerator, [{ key: 'generate', value: function generate() { this.output = []; this.blocks = this.contentState.getBlockMap().toArray(); this.totalBlocks = this.blocks.length; this.currentBlock = 0; this.listItemCounts = {}; while (this.currentBlock < this.totalBlocks) { this.processBlock(); } return this.output.join(''); } }, { key: 'processBlock', value: function processBlock() { var block = this.blocks[this.currentBlock]; var blockType = block.getType(); switch (blockType) { case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_ONE: { this.insertLineBreaks(1); this.output.push('# ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_TWO: { this.insertLineBreaks(1); if (block.text !== "") { this.output.push('## ' + this.renderBlockContent(block) + '\n'); } break; } case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_THREE: { this.insertLineBreaks(1); this.output.push('### ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_FOUR: { this.insertLineBreaks(1); this.output.push('#### ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_FIVE: { this.insertLineBreaks(1); this.output.push('##### ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.HEADER_SIX: { this.insertLineBreaks(1); this.output.push('###### ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.UNORDERED_LIST_ITEM: { var blockDepth = block.getDepth(); var lastBlock = this.getLastBlock(); var lastBlockType = lastBlock ? lastBlock.getType() : null; var lastBlockDepth = lastBlock && canHaveDepth(lastBlockType) ? lastBlock.getDepth() : null; if (lastBlockType !== blockType && lastBlockDepth !== blockDepth - 1) { this.insertLineBreaks(1); // Insert an additional line break if following opposite list type. if (lastBlockType === _bauerDraftJsUtils.BLOCK_TYPE.ORDERED_LIST_ITEM) { this.insertLineBreaks(1); } } var indent = ' '.repeat(block.depth * 4); this.output.push(indent + '- ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.ORDERED_LIST_ITEM: { var _blockDepth = block.getDepth(); var _lastBlock = this.getLastBlock(); var _lastBlockType = _lastBlock ? _lastBlock.getType() : null; var _lastBlockDepth = _lastBlock && canHaveDepth(_lastBlockType) ? _lastBlock.getDepth() : null; if (_lastBlockType !== blockType && _lastBlockDepth !== _blockDepth - 1) { this.insertLineBreaks(1); // Insert an additional line break if following opposite list type. if (_lastBlockType === _bauerDraftJsUtils.BLOCK_TYPE.UNORDERED_LIST_ITEM) { this.insertLineBreaks(1); } } var _indent = ' '.repeat(_blockDepth * 4); // TODO: figure out what to do with two-digit numbers var count = this.getListItemCount(block) % 10; this.output.push(_indent + (count + '. ') + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.BLOCKQUOTE: { this.insertLineBreaks(1); this.output.push(' > ' + this.renderBlockContent(block) + '\n'); break; } case _bauerDraftJsUtils.BLOCK_TYPE.CODE: { this.insertLineBreaks(1); this.output.push(CODE_INDENT + this.renderBlockContent(block) + '\n'); break; } default: { this.insertLineBreaks(1); this.output.push(this.renderBlockContent(block) + '\n'); break; } } this.currentBlock += 1; } }, { key: 'getLastBlock', value: function getLastBlock() { return this.blocks[this.currentBlock - 1]; } }, { key: 'getNextBlock', value: function getNextBlock() { return this.blocks[this.currentBlock + 1]; } }, { key: 'getListItemCount', value: function getListItemCount(block) { var blockType = block.getType(); var blockDepth = block.getDepth(); // To decide if we need to start over we need to backtrack (skipping list // items that are of greater depth) var index = this.currentBlock - 1; var prevBlock = this.blocks[index]; while (prevBlock && canHaveDepth(prevBlock.getType()) && prevBlock.getDepth() > blockDepth) { index -= 1; prevBlock = this.blocks[index]; } if (!prevBlock || prevBlock.getType() !== blockType || prevBlock.getDepth() !== blockDepth) { this.listItemCounts[blockDepth] = 0; } return this.listItemCounts[blockDepth] = this.listItemCounts[blockDepth] + 1; } }, { key: 'insertLineBreaks', value: function insertLineBreaks() { if (this.currentBlock > 0) { this.output.push('\n'); } } }, { key: 'renderBlockContent', value: function renderBlockContent(block) { var contentState = this.contentState; var blockType = block.getType(); var text = block.getText(); if (text === '') { // Prevent element collapse if completely empty. // TODO: Replace with constant. return text; } var charMetaList = block.getCharacterList(); var entityPieces = (0, _bauerDraftJsUtils.getEntityRanges)(text, charMetaList); return entityPieces.map(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), entityKey = _ref2[0], stylePieces = _ref2[1]; var content = stylePieces.map(function (_ref3) { var _ref4 = _slicedToArray(_ref3, 2), text = _ref4[0], style = _ref4[1]; // Don't allow empty inline elements. if (!text) { return ''; } var content = text; if (style.has(BOLD)) { content = swapWhitespace(content, '**'); } if (style.has(UNDERLINE)) { // TODO: encode `+`? content = '++' + content + '++'; } if (style.has(ITALIC)) { content = swapWhitespace(content.replace(/\*\*/g, '__'), '_'); } if (style.has(STRIKETHROUGH)) { // TODO: encode `~`? content = '~~' + content + '~~'; } if (style.has(CODE)) { content = blockType === _bauerDraftJsUtils.BLOCK_TYPE.CODE ? content : '`' + content + '`'; } return content; }).join(''); var entity = entityKey ? contentState.getEntity(entityKey) : null; if (entity != null && entity.getType() === _bauerDraftJsUtils.ENTITY_TYPE.LINK) { var data = entity.getData(); var url = data.url || ''; var target = data.target || '_self'; return '[' + content + '](' + encodeURL(url) + ' "' + target + '")'; } else if (entity != null && entity.getType() === _bauerDraftJsUtils.ENTITY_TYPE.IMAGE) { var _data = entity.getData(); var _url = encodeURL(_data.src || '').replace(/https?\:/, ''); var alt = _data.alt ? '' + escapeTitle(_data.alt) : ''; var title = _data.title ? '"' + escapeTitle(_data.title) + '"' : ''; return '![' + alt + '](' + _url + ' ' + title + ')'; } else { return content; } }).join(''); } }]); return MarkupGenerator; }(); function canHaveDepth(blockType) { switch (blockType) { case _bauerDraftJsUtils.BLOCK_TYPE.UNORDERED_LIST_ITEM: case _bauerDraftJsUtils.BLOCK_TYPE.ORDERED_LIST_ITEM: return true; default: return false; } } // Encode chars that would normally be allowed in a URL but would conflict with // our markdown syntax: `[foo](http://foo/)` function encodeURL(url) { return url.replace(/\)/g, '%29'); } // Escape quotes using backslash. function escapeTitle(text) { return text.replace(/"/g, '\\"'); } function stateToMarkdown(content) { return new MarkupGenerator(content).generate(); }