@mirrormedia/lilith-draft-editor
Version:
## Installation
252 lines (212 loc) • 11.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _immutable = require("immutable");
var _lodash = _interopRequireDefault(require("lodash"));
var InlineStylesProcessor = _interopRequireWildcard(require("./inline-styles-processor"));
var _apiDataInstance = _interopRequireDefault(require("./api-data-instance"));
var _atomicBlockProcessor = _interopRequireDefault(require("./atomic-block-processor"));
var _entities = _interopRequireDefault(require("./entities"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Modified from https://github.com/dburrows/draft-js-basic-html-editor/blob/master/src/utils/draftRawToHtml.js
// 'use strict';
const defaultBlockTagMap = {
atomic: `<div>%content%</div>`,
blockquote: `<blockquote>%content%</blockquote>`,
'code-block': `<code>%content%</code>`,
default: `<p>%content%</p>`,
'header-two': `<h2>%content%</h2>`,
'header-three': `<h3>%content%</h3>`,
'header-four': `<h4>%content%</h4>`,
'ordered-list-item': `<li>%content%</li>`,
paragraph: `<p>%content%</p>`,
'unordered-list-item': `<li>%content%</li>`,
unstyled: `<p>%content%</p>`
};
const inlineTagMap = {
BOLD: ['<strong>', '</strong>'],
CODE: ['<code>', '</code>'],
default: ['<span>', '</span>'],
ITALIC: ['<em>', '</em>'],
UNDERLINE: ['<u>', '</u>']
};
const defaultEntityTagMap = {
[_entities.default.DIVIDER.type]: ['<hr>', ''],
[_entities.default.ANNOTATION.type]: ['<abbr title="<%= data.body %>"><%= data.text %>', '</abbr>'],
[_entities.default.AUDIO.type]: ['<div class="audio-container center"><div class="audio-title"><%= data.name %></div><!-- <div class="audio-desc"><%= data.description %></div> --><audio src="<%= data.url %>" />', '</div>'],
[_entities.default.BLOCKQUOTE.type]: ['<blockquote class="center"><div><%= data.quote %></div><div><%= data.quotedBy %></div>', '<blockquote>'],
[_entities.default.EMBEDDEDCODE.type]: ['<div class="embedded <%= data.alignment %>" title="<%= data.caption %>"><%= data.code%>', '</div>'],
[_entities.default.INFOBOX.type]: ['<div class="info-box-container center"><div class="info-box-title"><%= data.title %></div><div class="info-box-body"><%= data.body %></div>', '</div>'],
[_entities.default.STOREDIMAGE.type]: ['<img alt="<%= data.name %>" src="<%= data.url %>" srcset="<%= data.urlMobileSized %> 800w, <%= data.urlTabletSized %> 1280w, <%= data.urlDesktopSized %> 2400w" class="center">', '</img>'],
[_entities.default.IMAGE.type]: ['<img alt="<%=data.name%>" src="<%=data.url%>" srcset="<%= data.mobile.url %> 800w, <%= data.tablet.url %> 1280w, <%= data.desktop.url %> 2400w" class="center">', '</img>'],
/*[ENTITY.IMAGEDIFF.type]: ['<!-- imageDiff component start --> <ol class="image-diff-container"> <% _.forEach(data, function(image, index) { if (index > 1) { return; } %><li class="image-diff-item"><img src="<%- image.url %>" /></li><% }); %>', '</ol><!-- imageDiff component end-->'],
[ENTITY.IMAGELINK.type]: ['<img alt="<%= data.description %>" src="<%= data.url %>" class="<%= data.alignment %>">', '</img>'],*/
[_entities.default.LINK.type]: ['<a target="_blank" href="<%= data.url %>">', '</a>'],
[_entities.default.SLIDESHOW.type]: ['<!-- slideshow component start --> <ol class="slideshow-container"> <% _.forEach(data, function(image) { %><li class="slideshow-slide"><img alt="<%- image.name %>" src="<%- image.url %>" srcset="<%= image.mobile.url %> 800w, <%= image.tablet.url %> 1280w, <%= image.desktop.url %> 2400w" /></li><% }); %>', '</ol><!-- slideshow component end -->'],
[_entities.default.VIDEO.type]: ['<div controls class="video-container <%= data.alignment %>"><div class="video-name"><%= data.title %></div><div class="video-desc"><%= data.description %></div><video src="<%= data.url %>" />', '</div>'],
[_entities.default.YOUTUBE.type]: ['<iframe width="560" alt="<%= data.description %>" height="315" src="https://www.youtube.com/embed/<%= data.id %>" frameborder="0" allowfullscreen>', '</iframe>']
};
const nestedTagMap = {
'ordered-list-item': ['<ol>', '</ol>'],
'unordered-list-item': ['<ul>', '</ul>']
};
/**
* @typedef {import('./jsdoc').RawDraftContentState} RawDraftContentState
* @typedef {import('./jsdoc').RawDraftContentBlock} RawDraftContentBlock
* @typedef {import('./jsdoc').EntityMap} EntityMap
* @typedef {import('./jsdoc').BlockTagMap} BlockTagMap
* @typedef {import('./jsdoc').EntityTagMap} EntityTagMap
*/
/**
* @param {RawDraftContentBlock} block
* @param {EntityMap} entityMap
* @param {BlockTagMap} blockTagMap
* @param {EntityTagMap} entityTagMap
*/
function _convertInlineStyle(block, entityMap, blockTagMap, entityTagMap) {
return blockTagMap[block.type] ? blockTagMap[block.type].replace('%content%', InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block)) : blockTagMap.default.replace('%content%', InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block));
}
/**
* @param {RawDraftContentBlock[]} blocks
* @param {EntityMap} entityMap
* @param {BlockTagMap} blockTagMap
* @param {EntityTagMap} entityTagMap
*/
function _convertBlocksToHtml(blocks, entityMap, blockTagMap, entityTagMap) {
let html = '';
/** @type {string[]} */
const nestLevel = []; // store the list type of the previous item: null/ol/ul
blocks.forEach(block => {
// create tag for <ol> or <ul>: deal with ordered/unordered list item
// if the block is a list-item && the previous block is not a list-item
if (block.type in nestedTagMap && // @ts-ignore: block.type is nestedTagMap property
nestedTagMap[block.type] && nestLevel[0] !== block.type) {
// @ts-ignore: block.type is nestedTagMap property
html += nestedTagMap[block.type][0]; // start with <ol> or <ul>
nestLevel.unshift(block.type);
} // end tag with </ol> or </ul>: deal with ordered/unordered list item
if (nestLevel.length > 0 && nestLevel[0] !== block.type) {
// @ts-ignore: nestLevel.shift() is not undefined
html += nestedTagMap[nestLevel.shift()][1]; // close with </ol> or </ul>
}
html += _convertInlineStyle(block, entityMap, blockTagMap, entityTagMap);
}); // end tag with </ol> or </ul>: or if it is the last block
// @ts-ignore: blocks[blocks.length - 1] is not undefined
if (blocks.length > 0 && nestedTagMap[blocks[blocks.length - 1].type]) {
// @ts-ignore: nestLevel.shift() should not be undefined
html += nestedTagMap[nestLevel.shift()][1]; // close with </ol> or </ul>
}
return html;
}
/**
* @param {RawDraftContentBlock[]} blocks
* @param {EntityMap} entityMap
* @param {EntityTagMap} entityTagMap
*/
function convertBlocksToApiData(blocks, entityMap, entityTagMap) {
let apiDataArr = (0, _immutable.List)();
/** @type {any[]} */
let content = [];
/** @type {string[]} */
const nestLevel = [];
blocks.forEach(block => {
// block is not a list-item
if (!(block.type in nestedTagMap)) {
// if previous block is a list-item
if (content.length > 0 && nestLevel.length > 0) {
apiDataArr = apiDataArr.push(new _apiDataInstance.default({
type: nestLevel[0],
content: [content]
}));
content = [];
nestLevel.shift();
}
if (block.type.startsWith('atomic') || block.type.startsWith('media')) {
try {
apiDataArr = apiDataArr.push(_atomicBlockProcessor.default.convertBlock(entityMap, block));
} catch (e) {
console.error(e);
}
} else {
var _block$data;
const converted = InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block);
const type = block.type;
const textAlign = (_block$data = block.data) === null || _block$data === void 0 ? void 0 : _block$data.textAlign;
apiDataArr = apiDataArr.push(new _apiDataInstance.default({
id: block.key,
type,
content: [converted],
textAlign
}));
}
} else {
const converted = InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block); // previous block is not an item-list block
if (nestLevel.length === 0) {
nestLevel.unshift(block.type);
content.push(converted);
} else if (nestLevel[0] === block.type) {
// previous block is a item-list and current block is the same item-list
content.push(converted);
} else if (nestLevel[0] !== block.type) {
// previous block is a different item-list.
apiDataArr = apiDataArr.push(new _apiDataInstance.default({
id: block.key,
type: nestLevel[0],
content: [content]
}));
content = [converted];
nestLevel[0] = block.type;
}
}
}); // last block is a item-list
if (blocks.length > 0 && nestLevel.length > 0) {
const block = blocks[blocks.length - 1];
apiDataArr = apiDataArr.push(new _apiDataInstance.default({
id: block.key,
type: block.type,
content: content
}));
}
return apiDataArr;
}
/**
* @param {RawDraftContentState} raw
* @param {BlockTagMap} [blockTagMap]
* @param {EntityTagMap} [entityTagMap]
*/
function convertRawToHtml(raw, blockTagMap, entityTagMap) {
blockTagMap = _lodash.default.merge({}, defaultBlockTagMap, blockTagMap);
entityTagMap = entityTagMap || defaultEntityTagMap;
let html = '';
raw = raw ||
/** @type {RawDraftContentState} */
{};
const blocks = Array.isArray(raw.blocks) ? raw.blocks : [];
const entityMap = typeof raw.entityMap === 'object' ? raw.entityMap : {};
html = _convertBlocksToHtml(blocks, entityMap, blockTagMap, entityTagMap);
return html;
}
/**
* @param {RawDraftContentState} raw
*/
function convertRawToApiData(raw) {
raw = raw ||
/** @type {RawDraftContentState} */
{};
const blocks = Array.isArray(raw.blocks) ? raw.blocks : [];
const entityMap = typeof raw.entityMap === 'object' ? raw.entityMap : {};
const entityTagMap = _lodash.default.merge({}, defaultEntityTagMap, {
[_entities.default.ANNOTATION.type]: [`<span data-entity-type="annotation" data-annotation-body="<%= data.bodyEscapedHTML %>">`, '</span>']
});
const apiData = convertBlocksToApiData(blocks, entityMap, entityTagMap);
return apiData;
}
var _default = {
convertToHtml: convertRawToHtml,
convertToApiData: convertRawToApiData
};
exports.default = _default;