@kedao/convert
Version:
A convert helper for Kedao Editor.
640 lines • 22.4 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
/* eslint-disable react/display-name */
import React from 'react';
export const namedColors = {
aliceblue: '#f0f8ff',
antiquewhite: '#faebd7',
aqua: '#00ffff',
aquamarine: '#7fffd4',
azure: '#f0ffff',
beige: '#f5f5dc',
bisque: '#ffe4c4',
black: '#000000',
blanchedalmond: '#ffebcd',
blue: '#0000ff',
blueviolet: '#8a2be2',
brown: '#a52a2a',
burlywood: '#deb887',
cadetblue: '#5f9ea0',
chartreuse: '#7fff00',
chocolate: '#d2691e',
coral: '#ff7f50',
cornflowerblue: '#6495ed',
cornsilk: '#fff8dc',
crimson: '#dc143c',
cyan: '#00ffff',
darkblue: '#00008b',
darkcyan: '#008b8b',
darkgoldenrod: '#b8860b',
darkgray: '#a9a9a9',
darkgreen: '#006400',
darkkhaki: '#bdb76b',
darkmagenta: '#8b008b',
darkolivegreen: '#556b2f',
darkorange: '#ff8c00',
darkorchid: '#9932cc',
darkred: '#8b0000',
darksalmon: '#e9967a',
darkseagreen: '#8fbc8f',
darkslateblue: '#483d8b',
darkslategray: '#2f4f4f',
darkturquoise: '#00ced1',
darkviolet: '#9400d3',
deeppink: '#ff1493',
deepskyblue: '#00bfff',
dimgray: '#696969',
dodgerblue: '#1e90ff',
firebrick: '#b22222',
floralwhite: '#fffaf0',
forestgreen: '#228b22',
fuchsia: '#ff00ff',
gainsboro: '#dcdcdc',
ghostwhite: '#f8f8ff',
gold: '#ffd700',
goldenrod: '#daa520',
gray: '#808080',
green: '#008000',
greenyellow: '#adff2f',
honeydew: '#f0fff0',
hotpink: '#ff69b4',
'indianred ': '#cd5c5c',
indigo: '#4b0082',
ivory: '#fffff0',
khaki: '#f0e68c',
lavender: '#e6e6fa',
lavenderblush: '#fff0f5',
lawngreen: '#7cfc00',
lemonchiffon: '#fffacd',
lightblue: '#add8e6',
lightcoral: '#f08080',
lightcyan: '#e0ffff',
lightgoldenrodyellow: '#fafad2',
lightgrey: '#d3d3d3',
lightgreen: '#90ee90',
lightpink: '#ffb6c1',
lightsalmon: '#ffa07a',
lightseagreen: '#20b2aa',
lightskyblue: '#87cefa',
lightslategray: '#778899',
lightsteelblue: '#b0c4de',
lightyellow: '#ffffe0',
lime: '#00ff00',
limegreen: '#32cd32',
linen: '#faf0e6',
magenta: '#ff00ff',
maroon: '#800000',
mediumaquamarine: '#66cdaa',
mediumblue: '#0000cd',
mediumorchid: '#ba55d3',
mediumpurple: '#9370d8',
mediumseagreen: '#3cb371',
mediumslateblue: '#7b68ee',
mediumspringgreen: '#00fa9a',
mediumturquoise: '#48d1cc',
mediumvioletred: '#c71585',
midnightblue: '#191970',
mintcream: '#f5fffa',
mistyrose: '#ffe4e1',
moccasin: '#ffe4b5',
navajowhite: '#ffdead',
navy: '#000080',
oldlace: '#fdf5e6',
olive: '#808000',
olivedrab: '#6b8e23',
orange: '#ffa500',
orangered: '#ff4500',
orchid: '#da70d6',
palegoldenrod: '#eee8aa',
palegreen: '#98fb98',
paleturquoise: '#afeeee',
palevioletred: '#d87093',
papayawhip: '#ffefd5',
peachpuff: '#ffdab9',
peru: '#cd853f',
pink: '#ffc0cb',
plum: '#dda0dd',
powderblue: '#b0e0e6',
purple: '#800080',
rebeccapurple: '#663399',
red: '#ff0000',
rosybrown: '#bc8f8f',
royalblue: '#4169e1',
saddlebrown: '#8b4513',
salmon: '#fa8072',
sandybrown: '#f4a460',
seagreen: '#2e8b57',
seashell: '#fff5ee',
sienna: '#a0522d',
silver: '#c0c0c0',
skyblue: '#87ceeb',
slateblue: '#6a5acd',
slategray: '#708090',
snow: '#fffafa',
springgreen: '#00ff7f',
steelblue: '#4682b4',
tan: '#d2b48c',
teal: '#008080',
thistle: '#d8bfd8',
tomato: '#ff6347',
turquoise: '#40e0d0',
violet: '#ee82ee',
wheat: '#f5deb3',
white: '#ffffff',
whitesmoke: '#f5f5f5',
yellow: '#ffff00',
yellowgreen: '#9acd32'
};
const getStyleValue = (style) => style.split('-')[1];
const defaultUnitExportFn = (unit) => unit + 'px';
const defaultUnitImportFn = (unit) => unit.replace('px', '');
const ignoredNodeAttributes = ['style'];
const ignoredEntityNodeAttributes = [
'style',
'href',
'target',
'alt',
'title',
'id',
'controls',
'autoplay',
'loop',
'poster'
];
const spreadNodeAttributes = (attributesObject) => {
return Object.keys(attributesObject)
.reduce((attributeString, attributeName) => {
return `${attributeString} ${attributeName}="${attributesObject[attributeName]}"`;
}, '')
.replace(/^\s$/, '');
};
export const defaultFontFamilies = [
{
name: 'Araial',
family: 'Arial, Helvetica, sans-serif'
},
{
name: 'Georgia',
family: 'Georgia, serif'
},
{
name: 'Impact',
family: 'Impact, serif'
},
{
name: 'Monospace',
family: '"Courier New", Courier, monospace'
},
{
name: 'Tahoma',
family: "tahoma, arial, 'Hiragino Sans GB', 宋体, sans-serif"
}
];
export const getHexColor = (color) => {
color = color.replace('color:', '').replace(';', '').replace(' ', '');
if (/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(color)) {
return color;
}
else if (namedColors[color]) {
return namedColors[color];
}
else if (color.indexOf('rgb') === 0) {
const rgbArray = color.split(',');
const convertedColor = rgbArray.length < 3
? null
: '#' +
[rgbArray[0], rgbArray[1], rgbArray[2]]
.map((x) => {
const hex = parseInt(x.replace(/\D/g, ''), 10).toString(16);
return hex.length === 1 ? '0' + hex : hex;
})
.join('');
return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(convertedColor)
? convertedColor
: null;
}
else {
return null;
}
};
export const blocks = {
'header-one': 'h1',
'header-two': 'h2',
'header-three': 'h3',
'header-four': 'h4',
'header-five': 'h5',
'header-six': 'h6',
unstyled: 'p',
blockquote: 'blockquote'
};
const blockTypes = Object.keys(blocks);
const blockNames = blockTypes.map((key) => blocks[key]);
const convertAtomicBlock = (block, contentState, blockNodeAttributes) => {
if (!block || !block.key) {
return React.createElement("p", null);
}
const contentBlock = contentState.getBlockForKey(block.key);
const { class: className } = blockNodeAttributes, nodeAttrAsProps = __rest(blockNodeAttributes, ["class"]);
nodeAttrAsProps.className = className;
if (!contentBlock) {
return React.createElement("p", null);
}
const entityKey = contentBlock.getEntityAt(0);
if (!entityKey) {
return React.createElement("p", null);
}
const entity = contentState.getEntity(entityKey);
const mediaType = entity.getType().toLowerCase();
const { float, alignment } = block.data;
// eslint-disable-next-line @typescript-eslint/naming-convention
const { url, link, link_target, width, height, meta } = entity.getData();
if (mediaType === 'image') {
const imageWrapStyle = {};
let styledClassName = '';
if (float) {
imageWrapStyle.float = float;
styledClassName += ' float-' + float;
}
else if (alignment) {
imageWrapStyle.textAlign = alignment;
styledClassName += ' align-' + alignment;
}
if (link) {
return (React.createElement("div", { className: 'media-wrap image-wrap' + styledClassName, style: imageWrapStyle },
React.createElement("a", { style: { display: 'inline-block' }, href: link, target: link_target },
React.createElement("img", Object.assign({}, nodeAttrAsProps, meta, { src: url, width: width, height: height, style: { width, height } })))));
}
else {
return (React.createElement("div", { className: 'media-wrap image-wrap' + styledClassName, style: imageWrapStyle },
React.createElement("img", Object.assign({}, nodeAttrAsProps, meta, { src: url, width: width, height: height, style: { width, height } }))));
}
}
else if (mediaType === 'audio') {
return (React.createElement("div", { className: "media-wrap audio-wrap" },
React.createElement("audio", Object.assign({ controls: true }, nodeAttrAsProps, meta, { src: url }))));
}
else if (mediaType === 'video') {
return (React.createElement("div", { className: "media-wrap video-wrap" },
React.createElement("video", Object.assign({ controls: true }, nodeAttrAsProps, meta, { src: url, width: width, height: height }))));
}
else if (mediaType === 'embed') {
return (React.createElement("div", { className: "media-wrap embed-wrap" },
React.createElement("div", { dangerouslySetInnerHTML: { __html: url } })));
}
else if (mediaType === 'hr') {
return React.createElement("hr", null);
}
else {
return React.createElement("p", null);
}
};
const entityToHTML = (options) => (entity, originalText) => {
var _a;
const { entityExportFn } = options;
const entityType = entity.type.toLowerCase();
if (entityExportFn) {
const customOutput = entityExportFn(entity, originalText);
if (customOutput) {
return customOutput;
}
}
if (entityType === 'link') {
const _b = (_a = entity.data.nodeAttributes) !== null && _a !== void 0 ? _a : {}, { class: className } = _b, nodeAttrAsProps = __rest(_b, ["class"]);
nodeAttrAsProps.className = className;
return (React.createElement("a", Object.assign({ href: entity.data.href, target: entity.data.target }, nodeAttrAsProps)));
}
};
const styleToHTML = (options) => (style) => {
var _a;
const unitExportFn = (_a = options.unitExportFn) !== null && _a !== void 0 ? _a : defaultUnitExportFn;
if (options.styleExportFn) {
const customOutput = options.styleExportFn(style, options);
if (customOutput) {
return customOutput;
}
}
style = style.toLowerCase();
if (style === 'strikethrough') {
return React.createElement("span", { style: { textDecoration: 'line-through' } });
}
else if (style === 'superscript') {
return React.createElement("sup", null);
}
else if (style === 'subscript') {
return React.createElement("sub", null);
}
else if (style.indexOf('color-') === 0) {
return React.createElement("span", { style: { color: '#' + getStyleValue(style) } });
}
else if (style.indexOf('bgcolor-') === 0) {
return React.createElement("span", { style: { backgroundColor: '#' + getStyleValue(style) } });
}
else if (style.indexOf('fontsize-') === 0) {
return (React.createElement("span", { style: {
fontSize: unitExportFn(getStyleValue(style), 'font-size', 'html')
} }));
}
else if (style.indexOf('lineheight-') === 0) {
return (React.createElement("span", { style: {
lineHeight: unitExportFn(getStyleValue(style), 'line-height', 'html')
} }));
}
else if (style.indexOf('letterspacing-') === 0) {
return (React.createElement("span", { style: {
letterSpacing: unitExportFn(getStyleValue(style), 'letter-spacing', 'html')
} }));
}
else if (style.indexOf('fontfamily-') === 0) {
const fontFamily = options.fontFamilies.find((item) => item.name.toLowerCase() === getStyleValue(style));
if (!fontFamily)
return;
return React.createElement("span", { style: { fontFamily: fontFamily.family } });
}
};
const blockToHTML = (options) => (block) => {
const { blockExportFn, contentState } = options;
if (blockExportFn) {
const customOutput = blockExportFn(contentState, block);
if (customOutput) {
return customOutput;
}
}
let blockStyle = '';
const blockType = block.type.toLowerCase();
const { textAlign, textIndent, nodeAttributes = {} } = block.data;
const attributeString = spreadNodeAttributes(nodeAttributes);
if (textAlign || textIndent) {
blockStyle = ' style="';
if (textAlign) {
blockStyle += `text-align:${textAlign};`;
}
if (textIndent && !isNaN(textIndent) && textIndent > 0) {
blockStyle += `text-indent:${textIndent * 2}em;`;
}
blockStyle += '"';
}
if (blockType === 'atomic') {
return convertAtomicBlock(block, contentState, nodeAttributes);
}
else if (blockType === 'code-block') {
const previousBlock = contentState.getBlockBefore(block.key);
const nextBlock = contentState.getBlockAfter(block.key);
const previousBlockType = previousBlock === null || previousBlock === void 0 ? void 0 : previousBlock.getType();
const nextBlockType = nextBlock === null || nextBlock === void 0 ? void 0 : nextBlock.getType();
let start = '';
let end = '';
if (previousBlockType !== 'code-block') {
start = `<pre${attributeString}><code>`;
}
else {
start = '';
}
if (nextBlockType !== 'code-block') {
end = '</code></pre>';
}
else {
end = '<br/>';
}
return { start, end };
}
else if (blocks[blockType]) {
return {
start: `<${blocks[blockType]}${blockStyle}${attributeString}>`,
end: `</${blocks[blockType]}>`
};
}
else if (blockType === 'unordered-list-item') {
return {
start: `<li${blockStyle}${attributeString}>`,
end: '</li>',
nest: React.createElement("ul", null)
};
}
else if (blockType === 'ordered-list-item') {
return {
start: `<li${blockStyle}${attributeString}>`,
end: '</li>',
nest: React.createElement("ol", null)
};
}
};
const htmlToStyle = (options, source) => (nodeName, node, currentStyle) => {
if (!node || !node.style) {
return currentStyle;
}
const unitImportFn = options.unitImportFn || defaultUnitImportFn;
let newStyle = currentStyle;
[].forEach.call(node.style, (style) => {
if (nodeName === 'span' && style === 'color') {
const color = getHexColor(node.style.color);
newStyle = color
? newStyle.add('COLOR-' + color.replace('#', '').toUpperCase())
: newStyle;
}
else if (nodeName === 'span' && style === 'background-color') {
const color = getHexColor(node.style.backgroundColor);
newStyle = color
? newStyle.add('BGCOLOR-' + color.replace('#', '').toUpperCase())
: newStyle;
}
else if (nodeName === 'span' && style === 'font-size') {
newStyle = newStyle.add('FONTSIZE-' + unitImportFn(node.style.fontSize, 'font-size', source));
}
else if (nodeName === 'span' &&
style === 'line-height' &&
!isNaN(parseFloat(node.style.lineHeight))) {
newStyle = newStyle.add('LINEHEIGHT-' +
unitImportFn(node.style.lineHeight, 'line-height', source));
}
else if (nodeName === 'span' &&
style === 'letter-spacing' &&
!isNaN(parseFloat(node.style.letterSpacing))) {
newStyle = newStyle.add('LETTERSPACING-' +
unitImportFn(node.style.letterSpacing, 'letter-spacing', source));
}
else if (nodeName === 'span' && style === 'text-decoration') {
if (node.style.textDecoration === 'line-through') {
newStyle = newStyle.add('STRIKETHROUGH');
}
else if (node.style.textDecoration === 'underline') {
newStyle = newStyle.add('UNDERLINE');
}
}
else if (nodeName === 'span' && style === 'font-family') {
const fontFamily = options.fontFamilies.find((item) => item.family.toLowerCase() === node.style.fontFamily.toLowerCase());
if (!fontFamily)
return;
newStyle = newStyle.add('FONTFAMILY-' + fontFamily.name.toUpperCase());
}
});
if (nodeName === 'sup') {
newStyle = newStyle.add('SUPERSCRIPT');
}
else if (nodeName === 'sub') {
newStyle = newStyle.add('SUBSCRIPT');
}
options.styleImportFn &&
(newStyle =
options.styleImportFn(nodeName, node, newStyle, source) || newStyle);
return newStyle;
};
const htmlToEntity = (options, source) => (nodeName, node, createEntity) => {
var _a;
if (options === null || options === void 0 ? void 0 : options.entityImportFn) {
const customInput = options.entityImportFn(nodeName, node, createEntity, source);
if (customInput) {
return customInput;
}
}
nodeName = nodeName.toLowerCase();
const { alt, title, id, controls, autoplay, loop, poster } = node;
const meta = {};
const nodeAttributes = {};
id && (meta.id = id);
alt && (meta.alt = alt);
title && (meta.title = title);
controls && (meta.controls = controls);
autoplay && (meta.autoPlay = autoplay);
loop && (meta.loop = loop);
poster && (meta.poster = poster);
node.attributes &&
Object.keys(node.attributes).forEach((key) => {
const attr = node.attributes[key];
!ignoredEntityNodeAttributes.includes(attr.name) &&
(nodeAttributes[attr.name] = attr.value);
});
if (nodeName === 'a' && node.querySelectorAll('img').length > 0) {
const href = node.getAttribute('href');
const target = node.getAttribute('target');
return createEntity('LINK', 'MUTABLE', { href, target, nodeAttributes });
}
else if (nodeName === 'audio') {
return createEntity('AUDIO', 'IMMUTABLE', {
url: node.getAttribute('src'),
meta,
nodeAttributes
});
}
else if (nodeName === 'video') {
return createEntity('VIDEO', 'IMMUTABLE', {
url: node.getAttribute('src'),
meta,
nodeAttributes
});
}
else if (nodeName === 'img') {
const parentNode = node.parentNode;
const entityData = { meta };
const { width, height } = node.style;
entityData.url = node.getAttribute('src');
width && (entityData.width = width);
height && (entityData.height = height);
if (parentNode.nodeName.toLowerCase() === 'a') {
entityData.link = parentNode.getAttribute('href');
entityData.link_target = parentNode.getAttribute('target');
}
return createEntity('IMAGE', 'IMMUTABLE', entityData);
}
else if (nodeName === 'hr') {
return createEntity('HR', 'IMMUTABLE', {});
}
else if ((_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.classList.contains('embed-wrap')) {
const embedContent = node.innerHTML || node.outerHTML;
if (embedContent) {
return createEntity('EMBED', 'IMMUTABLE', {
url: embedContent
});
}
}
};
const htmlToBlock = (options, source) => (nodeName, node) => {
var _a, _b;
if (options === null || options === void 0 ? void 0 : options.blockImportFn) {
const customInput = options.blockImportFn(nodeName, node, source);
if (customInput) {
return customInput;
}
}
const nodeAttributes = {};
const nodeStyle = (_a = node.style) !== null && _a !== void 0 ? _a : {};
node.attributes &&
Object.keys(node.attributes).forEach((key) => {
const attr = node.attributes[key];
!ignoredNodeAttributes.includes(attr.name) &&
(nodeAttributes[attr.name] = attr.value);
});
if ((_b = node.classList) === null || _b === void 0 ? void 0 : _b.contains('media-wrap')) {
return {
type: 'atomic',
data: {
nodeAttributes: nodeAttributes,
float: nodeStyle.float,
alignment: nodeStyle.textAlign
}
};
}
else if (nodeName === 'img') {
return {
type: 'atomic',
data: {
nodeAttributes: nodeAttributes,
float: nodeStyle.float,
alignment: nodeStyle.textAlign
}
};
}
else if (nodeName === 'hr') {
return {
type: 'atomic',
data: { nodeAttributes }
};
}
else if (nodeName === 'pre') {
node.innerHTML = node.innerHTML
.replace(/<code(.*?)>/g, '')
.replace(/<\/code>/g, '');
return {
type: 'code-block',
data: { nodeAttributes }
};
}
else if (blockNames.includes(nodeName)) {
const blockData = { nodeAttributes };
if (nodeStyle.textAlign) {
blockData.textAlign = nodeStyle.textAlign;
}
if (nodeStyle.textIndent) {
blockData.textIndent = /^\d+em$/.test(nodeStyle.textIndent)
? Math.ceil(parseInt(nodeStyle.textIndent, 10) / 2)
: 1;
}
return {
type: blockTypes[blockNames.indexOf(nodeName)],
data: blockData
};
}
};
export const getToHTMLConfig = (options) => {
return {
styleToHTML: styleToHTML(options),
entityToHTML: entityToHTML(options),
blockToHTML: blockToHTML(options)
};
};
export const getFromHTMLConfig = (options, source = 'unknow') => {
return {
htmlToStyle: htmlToStyle(options, source),
htmlToEntity: htmlToEntity(options, source),
htmlToBlock: htmlToBlock(options, source)
};
};
//# sourceMappingURL=configs.js.map