@mirrormedia/lilith-draft-renderer
Version:
## Introduction
420 lines (374 loc) • 12.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = DraftRenderer;
exports.noSpacingBetweenContent = exports.draftEditorLineHeight = void 0;
var _react = _interopRequireDefault(require("react"));
var _styledComponents = _interopRequireWildcard(require("styled-components"));
var _draftJs = require("draft-js");
var _blockRendererFn = require("./block-renderer-fn");
var _entityDecorator = _interopRequireDefault(require("./entity-decorator"));
var _const = require("../../draft-js/const");
var _sharedStyle = require("./shared-style");
var _theme = _interopRequireDefault(require("./theme"));
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 }; }
const blockquoteDecoration = "https://unpkg.com/@mirrormedia/lilith-draft-renderer@1.4.0/lib/public/662d20f531567a273f99efc70e8c85a6.png";
const draftEditorLineHeight = 2;
/**
* Due to the data structure from draftjs, each default block contain one HTML element which class name is `public-DraftStyleDefault-block`.
* So we use this behavior to create spacing between blocks by assign margin-bottom of which.
* However, some block should not set spacing (e.g. block in <li> and <blockquote>), so we need to unset its margin-top.
*/
exports.draftEditorLineHeight = draftEditorLineHeight;
const noSpacingBetweenContent = {
blockquote: (0, _styledComponents.css)`
margin-bottom: unset;
`,
list: (0, _styledComponents.css)`
margin-bottom: 4px;
`
};
exports.noSpacingBetweenContent = noSpacingBetweenContent;
const draftEditorCssNormal = (0, _styledComponents.css)`
color: black;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-weight: normal;
.public-DraftStyleDefault-header-two {
font-size: 36px;
line-height: 1.5;
}
.public-DraftStyleDefault-header-three {
font-size: 30px;
line-height: 1.5;
}
.public-DraftStyleDefault-header-four {
}
.public-DraftStyleDefault-blockquote {
color: rgba(97, 184, 198, 1);
border-image: linear-gradient(
to right,
rgba(97, 184, 198, 1) 42.5%,
transparent 42.5%,
transparent 57.5%,
rgba(97, 184, 198, 1) 57.5%
)
100% 1;
&::before {
background-color: rgba(97, 184, 198, 1);
}
}
`;
const draftEditorCssWide = (0, _styledComponents.css)`
color: rgba(64, 64, 64, 0.87);
font-family: 'Noto Serif TC', source-han-serif-tc, 'Songti TC', serif,
PMingLiU;
font-weight: 600;
font-size: 18px;
line-height: 2;
[style*='font-weight:bold'] {
font-weight: 900 !important;
}
.public-DraftStyleDefault-header-two {
text-align: center;
color: black;
font-size: 36px;
font-weight: 700;
}
.public-DraftStyleDefault-header-three {
text-align: center;
color: black;
font-size: 32px;
font-weight: 700;
}
.public-DraftStyleDefault-header-four {
}
.public-DraftStyleDefault-blockquote {
color: rgba(0, 0, 0, 1);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
font-weight: 400;
border-image: linear-gradient(
to right,
rgba(0, 0, 0, 1) 42.5%,
transparent 42.5%,
transparent 57.5%,
rgba(0, 0, 0, 1) 57.5%
)
100% 1;
&::before {
background-color: rgba(0, 0, 0, 1);
}
}
`;
const draftEditorCssPremium = (0, _styledComponents.css)`
color: black;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-weight: normal;
.public-DraftStyleDefault-header-two {
color: rgba(5, 79, 119, 1);
font-weight: 500;
text-align: center;
font-size: 36px;
line-height: 1.5;
}
.public-DraftStyleDefault-header-three {
color: rgba(5, 79, 119, 1);
text-align: center;
font-weight: 500;
font-size: 30px;
line-height: 1.5;
}
.public-DraftStyleDefault-header-four {
}
.public-DraftStyleDefault-blockquote {
color: rgba(5, 79, 119, 1);
border-image: linear-gradient(
to right,
rgba(5, 79, 119, 1) 42.5%,
transparent 42.5%,
transparent 57.5%,
rgba(5, 79, 119, 1) 57.5%
)
100% 1;
&::before {
background-color: rgba(5, 79, 119, 1);
}
}
`; //目前 Photography 文末樣式僅支援:H2, H3, 粗體、底線、斜體、超連結
//目前 photography 裡的 <figure> 都會被隱藏(因此 video、infobox、colorbox,就算在 CMS 裡上稿也都無法呈現 )
// Todo: 新增一個 util function 篩選出 Image
const draftEditorCssPhotography = (0, _styledComponents.css)`
color: white;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-weight: normal;
.public-DraftStyleDefault-header-two {
font-weight: 500;
text-align: center;
font-size: 24px;
line-height: 1.5;
${({
theme
}) => theme.breakpoint.md} {
font-size: 32px;
}
}
.public-DraftStyleDefault-header-three {
text-align: center;
font-weight: 500;
font-size: 18px;
line-height: 1.5;
${({
theme
}) => theme.breakpoint.md} {
font-size: 24px;
}
}
`;
const DraftEditorWrapper = _styledComponents.default.div`
width: 100%;
height: 100%;
border: 0;
padding: 0px;
font-size: 18px;
line-height: ${draftEditorLineHeight};
.public-DraftStyleDefault-block {
${_sharedStyle.defaultMarginBottom}
}
//last item in raw-content block should not have margin-bottom
.public-DraftEditor-content {
> div {
> *:last-child {
> *:last-child {
margin-bottom: 0;
}
}
}
}
/* Draft built-in buttons' style */
.public-DraftStyleDefault-blockquote {
position: relative;
width: 100%;
margin: 0 auto;
max-width: 480px;
text-align: left;
margin: 48px auto;
padding-top: 34px;
border-top: 2px solid;
&::before {
content: '';
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 20px;
mask-image: url(${blockquoteDecoration});
mask-repeat: no-repeat;
mask-position: center center;
}
${noSpacingBetweenContent.blockquote}
${({
theme
}) => theme.breakpoint.md} {
padding-top: 26px;
}
}
.public-DraftStyleDefault-ul {
margin-left: 18px;
list-style: none;
${_sharedStyle.defaultMarginBottom}
.public-DraftStyleDefault-block {
${noSpacingBetweenContent.list}
}
}
.public-DraftStyleDefault-unorderedListItem {
position: relative;
&::before {
content: '';
position: absolute;
top: calc((1rem * ${draftEditorLineHeight}) / 2);
left: -12px;
width: 6px;
height: 6px;
transform: translateX(-50%);
border-radius: 50%;
background-color: #054f77;
}
}
.public-DraftStyleDefault-ol {
margin-left: 18px;
${_sharedStyle.defaultMarginBottom}
.public-DraftStyleDefault-block {
${noSpacingBetweenContent.list}
}
}
.public-DraftStyleDefault-orderedListItem {
position: relative;
counter-increment: list;
padding-left: 6px;
&::before {
content: counter(list) '.';
position: absolute;
color: #054f77;
left: -15px;
width: auto;
}
}
/* code-block */
.public-DraftStyleDefault-pre {
}
${({
contentLayout
}) => {
switch (contentLayout) {
case 'normal':
return draftEditorCssNormal;
case 'wide':
return draftEditorCssWide;
case 'premium':
return draftEditorCssPremium;
case 'photography':
return draftEditorCssPhotography;
default:
return draftEditorCssNormal;
}
}}
.alignCenter * {
text-align: center;
}
.alignLeft * {
text-align: left;
}
`;
const customStyleMap = {
CODE: {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
fontSize: 16,
padding: 2
}
};
const customStyleFn = style => {
return style.reduce((styles, styleName) => {
if (styleName !== null && styleName !== void 0 && styleName.startsWith(_const.CUSTOM_STYLE_PREFIX_FONT_COLOR)) {
styles['color'] = styleName.split(_const.CUSTOM_STYLE_PREFIX_FONT_COLOR)[1];
}
if (styleName !== null && styleName !== void 0 && styleName.startsWith(_const.CUSTOM_STYLE_PREFIX_BACKGROUND_COLOR)) {
styles['backgroundColor'] = styleName.split(_const.CUSTOM_STYLE_PREFIX_BACKGROUND_COLOR)[1];
}
return styles;
}, {});
};
const blockStyleFn = (editorState, block) => {
var _entity$getData;
const entityKey = block.getEntityAt(0);
const entity = entityKey ? editorState.getCurrentContent().getEntity(entityKey) : null;
let result = '';
const blockData = block.getData();
if (blockData) {
const textAlign = blockData === null || blockData === void 0 ? void 0 : blockData.get('textAlign');
if (textAlign === 'center') {
result += 'alignCenter ';
} else if (textAlign === 'left') {
result += 'alignLeft ';
}
}
switch (block.getType()) {
case 'header-two':
case 'header-three':
case 'header-four':
case 'blockquote':
result += 'public-DraftStyleDefault-' + block.getType();
break;
case 'atomic':
if ((_entity$getData = entity.getData()) !== null && _entity$getData !== void 0 && _entity$getData.alignment) {
// support all atomic block to set alignment
result += ' ' + entity.getData().alignment;
}
break;
default:
break;
}
return result;
};
/**
* TODO: add type of params `rawContentBlock`
*/
function DraftRenderer({
rawContentBlock,
contentLayout = 'normal',
firstImageAdComponent
}) {
const contentState = (0, _draftJs.convertFromRaw)(rawContentBlock);
const decorators = (0, _entityDecorator.default)(contentLayout);
const editorState = _draftJs.EditorState.createWithContent(contentState, decorators);
const blockRendererFn = block => {
const atomicBlockObj = (0, _blockRendererFn.atomicBlockRenderer)(block, contentLayout, firstImageAdComponent);
return atomicBlockObj;
};
return /*#__PURE__*/_react.default.createElement(_styledComponents.ThemeProvider, {
theme: _theme.default
}, /*#__PURE__*/_react.default.createElement(DraftEditorWrapper, {
contentLayout: contentLayout
}, /*#__PURE__*/_react.default.createElement(_draftJs.Editor, {
editorState: editorState,
customStyleMap: customStyleMap,
blockStyleFn: blockStyleFn.bind(null, editorState),
blockRendererFn: blockRendererFn,
customStyleFn: customStyleFn,
readOnly: true // eslint-disable-next-line @typescript-eslint/no-empty-function
,
onChange: () => {}
})));
}