This commit is contained in:
236
node_modules/remark-slate/src/ast-types.ts
generated
vendored
Normal file
236
node_modules/remark-slate/src/ast-types.ts
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
export interface NodeTypes {
|
||||
paragraph: 'paragraph';
|
||||
block_quote: 'block_quote';
|
||||
code_block: 'code_block';
|
||||
link: 'link';
|
||||
ul_list: 'ul_list';
|
||||
ol_list: 'ol_list';
|
||||
listItem: 'list_item';
|
||||
heading: {
|
||||
1: 'heading_one';
|
||||
2: 'heading_two';
|
||||
3: 'heading_three';
|
||||
4: 'heading_four';
|
||||
5: 'heading_five';
|
||||
6: 'heading_six';
|
||||
};
|
||||
emphasis_mark: 'italic';
|
||||
strong_mark: 'bold';
|
||||
delete_mark: 'strikeThrough';
|
||||
inline_code_mark: 'code';
|
||||
thematic_break: 'thematic_break';
|
||||
image: 'image';
|
||||
}
|
||||
|
||||
export type MdastNodeType =
|
||||
| 'paragraph'
|
||||
| 'heading'
|
||||
| 'list'
|
||||
| 'listItem'
|
||||
| 'link'
|
||||
| 'image'
|
||||
| 'blockquote'
|
||||
| 'code'
|
||||
| 'html'
|
||||
| 'emphasis'
|
||||
| 'strong'
|
||||
| 'delete'
|
||||
| 'inlineCode'
|
||||
| 'thematicBreak'
|
||||
| 'text';
|
||||
|
||||
export const defaultNodeTypes: NodeTypes = {
|
||||
paragraph: 'paragraph',
|
||||
block_quote: 'block_quote',
|
||||
code_block: 'code_block',
|
||||
link: 'link',
|
||||
ul_list: 'ul_list',
|
||||
ol_list: 'ol_list',
|
||||
listItem: 'list_item',
|
||||
heading: {
|
||||
1: 'heading_one',
|
||||
2: 'heading_two',
|
||||
3: 'heading_three',
|
||||
4: 'heading_four',
|
||||
5: 'heading_five',
|
||||
6: 'heading_six',
|
||||
},
|
||||
emphasis_mark: 'italic',
|
||||
strong_mark: 'bold',
|
||||
delete_mark: 'strikeThrough',
|
||||
inline_code_mark: 'code',
|
||||
thematic_break: 'thematic_break',
|
||||
image: 'image',
|
||||
};
|
||||
|
||||
export interface LeafType {
|
||||
text: string;
|
||||
strikeThrough?: boolean;
|
||||
bold?: boolean;
|
||||
italic?: boolean;
|
||||
code?: boolean;
|
||||
parentType?: string;
|
||||
}
|
||||
|
||||
export interface BlockType {
|
||||
type: string;
|
||||
parentType?: string;
|
||||
link?: string;
|
||||
caption?: string;
|
||||
language?: string;
|
||||
break?: boolean;
|
||||
children: Array<BlockType | LeafType>;
|
||||
}
|
||||
|
||||
export interface InputNodeTypes {
|
||||
paragraph: string;
|
||||
block_quote: string;
|
||||
code_block: string;
|
||||
link: string;
|
||||
ul_list: string;
|
||||
ol_list: string;
|
||||
listItem: string;
|
||||
heading: {
|
||||
1: string;
|
||||
2: string;
|
||||
3: string;
|
||||
4: string;
|
||||
5: string;
|
||||
6: string;
|
||||
};
|
||||
emphasis_mark: string;
|
||||
strong_mark: string;
|
||||
delete_mark: string;
|
||||
inline_code_mark: string;
|
||||
thematic_break: string;
|
||||
image: string;
|
||||
}
|
||||
|
||||
type RecursivePartial<T> = {
|
||||
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||
};
|
||||
|
||||
export interface OptionType<T extends InputNodeTypes = InputNodeTypes> {
|
||||
nodeTypes?: RecursivePartial<T>;
|
||||
linkDestinationKey?: string;
|
||||
imageSourceKey?: string;
|
||||
imageCaptionKey?: string;
|
||||
}
|
||||
|
||||
export interface MdastNode {
|
||||
type?: MdastNodeType;
|
||||
ordered?: boolean;
|
||||
value?: string;
|
||||
text?: string;
|
||||
children?: Array<MdastNode>;
|
||||
depth?: 1 | 2 | 3 | 4 | 5 | 6;
|
||||
url?: string;
|
||||
alt?: string;
|
||||
lang?: string;
|
||||
// mdast metadata
|
||||
position?: any;
|
||||
spread?: any;
|
||||
checked?: any;
|
||||
indent?: any;
|
||||
}
|
||||
|
||||
export type TextNode = { text?: string | undefined };
|
||||
|
||||
export type CodeBlockNode<T extends InputNodeTypes> = {
|
||||
type: T['code_block'];
|
||||
language: string | undefined;
|
||||
children: Array<TextNode>;
|
||||
};
|
||||
|
||||
export type HeadingNode<T extends InputNodeTypes> = {
|
||||
type:
|
||||
| T['heading'][1]
|
||||
| T['heading'][2]
|
||||
| T['heading'][3]
|
||||
| T['heading'][4]
|
||||
| T['heading'][5]
|
||||
| T['heading'][6];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type ListNode<T extends InputNodeTypes> = {
|
||||
type: T['ol_list'] | T['ul_list'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type ListItemNode<T extends InputNodeTypes> = {
|
||||
type: T['listItem'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type ParagraphNode<T extends InputNodeTypes> = {
|
||||
type: T['paragraph'];
|
||||
break?: true;
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type LinkNode<T extends InputNodeTypes> = {
|
||||
type: T['link'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
[urlKey: string]: string | undefined | Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type ImageNode<T extends InputNodeTypes> = {
|
||||
type: T['image'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
[sourceOrCaptionKey: string]: string | undefined | Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type BlockQuoteNode<T extends InputNodeTypes> = {
|
||||
type: T['block_quote'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type InlineCodeMarkNode<T extends InputNodeTypes> = {
|
||||
type: T['inline_code_mark'];
|
||||
children: Array<TextNode>;
|
||||
language: string | undefined;
|
||||
};
|
||||
|
||||
export type ThematicBreakNode<T extends InputNodeTypes> = {
|
||||
type: T['thematic_break'];
|
||||
children: Array<DeserializedNode<T>>;
|
||||
};
|
||||
|
||||
export type ItalicNode<T extends InputNodeTypes> = {
|
||||
[K in T['emphasis_mark']]: true;
|
||||
} & {
|
||||
children: TextNode;
|
||||
};
|
||||
|
||||
export type BoldNode = {
|
||||
bold: true;
|
||||
children: TextNode;
|
||||
};
|
||||
|
||||
export type StrikeThoughNode = {
|
||||
strikeThrough: true;
|
||||
children: TextNode;
|
||||
};
|
||||
|
||||
export type InlineCodeNode = {
|
||||
code: true;
|
||||
text: string | undefined;
|
||||
};
|
||||
|
||||
export type DeserializedNode<T extends InputNodeTypes> =
|
||||
| CodeBlockNode<T>
|
||||
| HeadingNode<T>
|
||||
| ListNode<T>
|
||||
| ListItemNode<T>
|
||||
| ParagraphNode<T>
|
||||
| LinkNode<T>
|
||||
| ImageNode<T>
|
||||
| BlockQuoteNode<T>
|
||||
| InlineCodeMarkNode<T>
|
||||
| ThematicBreakNode<T>
|
||||
| ItalicNode<T>
|
||||
| BoldNode
|
||||
| StrikeThoughNode
|
||||
| InlineCodeNode
|
||||
| TextNode;
|
||||
154
node_modules/remark-slate/src/deserialize.ts
generated
vendored
Normal file
154
node_modules/remark-slate/src/deserialize.ts
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
import {
|
||||
BlockQuoteNode,
|
||||
CodeBlockNode,
|
||||
defaultNodeTypes,
|
||||
DeserializedNode,
|
||||
HeadingNode,
|
||||
ImageNode,
|
||||
InputNodeTypes,
|
||||
ItalicNode,
|
||||
LinkNode,
|
||||
ListItemNode,
|
||||
ListNode,
|
||||
MdastNode,
|
||||
OptionType,
|
||||
ParagraphNode,
|
||||
TextNode,
|
||||
ThematicBreakNode,
|
||||
} from './ast-types';
|
||||
|
||||
export default function deserialize<T extends InputNodeTypes>(
|
||||
node: MdastNode,
|
||||
opts?: OptionType<T>
|
||||
) {
|
||||
const types = {
|
||||
...defaultNodeTypes,
|
||||
...opts?.nodeTypes,
|
||||
heading: {
|
||||
...defaultNodeTypes.heading,
|
||||
...opts?.nodeTypes?.heading,
|
||||
},
|
||||
};
|
||||
|
||||
const linkDestinationKey = opts?.linkDestinationKey ?? 'link';
|
||||
const imageSourceKey = opts?.imageSourceKey ?? 'link';
|
||||
const imageCaptionKey = opts?.imageCaptionKey ?? 'caption';
|
||||
|
||||
let children: Array<DeserializedNode<T>> = [{ text: '' }];
|
||||
|
||||
const nodeChildren = node.children;
|
||||
if (nodeChildren && Array.isArray(nodeChildren) && nodeChildren.length > 0) {
|
||||
children = nodeChildren.flatMap((c: MdastNode) =>
|
||||
deserialize(
|
||||
{
|
||||
...c,
|
||||
ordered: node.ordered || false,
|
||||
},
|
||||
opts
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case 'heading':
|
||||
return {
|
||||
type: types.heading[node.depth || 1],
|
||||
children,
|
||||
} as HeadingNode<T>;
|
||||
case 'list':
|
||||
return {
|
||||
type: node.ordered ? types.ol_list : types.ul_list,
|
||||
children,
|
||||
} as ListNode<T>;
|
||||
case 'listItem':
|
||||
return { type: types.listItem, children } as ListItemNode<T>;
|
||||
case 'paragraph':
|
||||
return { type: types.paragraph, children } as ParagraphNode<T>;
|
||||
case 'link':
|
||||
return {
|
||||
type: types.link,
|
||||
[linkDestinationKey]: node.url,
|
||||
children,
|
||||
} as LinkNode<T>;
|
||||
case 'image':
|
||||
return {
|
||||
type: types.image,
|
||||
children: [{ text: '' }],
|
||||
[imageSourceKey]: node.url,
|
||||
[imageCaptionKey]: node.alt,
|
||||
} as ImageNode<T>;
|
||||
case 'blockquote':
|
||||
return { type: types.block_quote, children } as BlockQuoteNode<T>;
|
||||
case 'code':
|
||||
return {
|
||||
type: types.code_block,
|
||||
language: node.lang,
|
||||
children: [{ text: node.value }],
|
||||
} as CodeBlockNode<T>;
|
||||
|
||||
case 'html':
|
||||
if (node.value?.includes('<br>')) {
|
||||
return {
|
||||
break: true,
|
||||
type: types.paragraph,
|
||||
children: [{ text: node.value?.replace(/<br>/g, '') || '' }],
|
||||
} as ParagraphNode<T>;
|
||||
}
|
||||
return { type: 'paragraph', children: [{ text: node.value || '' }] };
|
||||
|
||||
case 'emphasis':
|
||||
return {
|
||||
[types.emphasis_mark as string]: true,
|
||||
...forceLeafNode(children as Array<TextNode>),
|
||||
...persistLeafFormats(children as Array<MdastNode>),
|
||||
} as unknown as ItalicNode<T>;
|
||||
case 'strong':
|
||||
return {
|
||||
[types.strong_mark as string]: true,
|
||||
...forceLeafNode(children as Array<TextNode>),
|
||||
...persistLeafFormats(children as Array<MdastNode>),
|
||||
};
|
||||
case 'delete':
|
||||
return {
|
||||
[types.delete_mark as string]: true,
|
||||
...forceLeafNode(children as Array<TextNode>),
|
||||
...persistLeafFormats(children as Array<MdastNode>),
|
||||
};
|
||||
case 'inlineCode':
|
||||
return {
|
||||
[types.inline_code_mark as string]: true,
|
||||
text: node.value,
|
||||
...persistLeafFormats(children as Array<MdastNode>),
|
||||
};
|
||||
case 'thematicBreak':
|
||||
return {
|
||||
type: types.thematic_break,
|
||||
children: [{ text: '' }],
|
||||
} as ThematicBreakNode<T>;
|
||||
|
||||
case 'text':
|
||||
default:
|
||||
return { text: node.value || '' };
|
||||
}
|
||||
}
|
||||
|
||||
const forceLeafNode = (children: Array<TextNode>) => ({
|
||||
text: children.map((k) => k?.text).join(''),
|
||||
});
|
||||
|
||||
// This function is will take any unknown keys, and bring them up a level
|
||||
// allowing leaf nodes to have many different formats at once
|
||||
// for example, bold and italic on the same node
|
||||
function persistLeafFormats(
|
||||
children: Array<MdastNode>
|
||||
): Omit<MdastNode, 'children' | 'type' | 'text'> {
|
||||
return children.reduce((acc, node) => {
|
||||
(Object.keys(node) as Array<keyof MdastNode>).forEach(function (key) {
|
||||
if (key === 'children' || key === 'type' || key === 'text') return;
|
||||
|
||||
acc[key] = node[key];
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
9
node_modules/remark-slate/src/index.ts
generated
vendored
Normal file
9
node_modules/remark-slate/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import deserialize from './deserialize';
|
||||
import serialize from './serialize';
|
||||
import plugin from './plugin';
|
||||
|
||||
export * from './ast-types';
|
||||
|
||||
export { deserialize, serialize };
|
||||
|
||||
export default plugin;
|
||||
11
node_modules/remark-slate/src/plugin.ts
generated
vendored
Normal file
11
node_modules/remark-slate/src/plugin.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { MdastNode, OptionType } from './ast-types';
|
||||
import transform from './deserialize';
|
||||
|
||||
export default function plugin(opts?: OptionType) {
|
||||
const compiler = (node: { children: Array<MdastNode> }) => {
|
||||
return node.children.map((c) => transform(c, opts));
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
this.Compiler = compiler;
|
||||
}
|
||||
243
node_modules/remark-slate/src/serialize.ts
generated
vendored
Normal file
243
node_modules/remark-slate/src/serialize.ts
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
import { BlockType, defaultNodeTypes, LeafType, NodeTypes } from './ast-types';
|
||||
import escapeHtml from 'escape-html';
|
||||
|
||||
interface Options {
|
||||
nodeTypes: NodeTypes;
|
||||
listDepth?: number;
|
||||
ignoreParagraphNewline?: boolean;
|
||||
}
|
||||
|
||||
const isLeafNode = (node: BlockType | LeafType): node is LeafType => {
|
||||
return typeof (node as LeafType).text === 'string';
|
||||
};
|
||||
|
||||
const VOID_ELEMENTS: Array<keyof NodeTypes> = ['thematic_break', 'image'];
|
||||
|
||||
const BREAK_TAG = '<br>';
|
||||
|
||||
export default function serialize(
|
||||
chunk: BlockType | LeafType,
|
||||
opts: Options = { nodeTypes: defaultNodeTypes }
|
||||
) {
|
||||
const {
|
||||
nodeTypes: userNodeTypes = defaultNodeTypes,
|
||||
ignoreParagraphNewline = false,
|
||||
listDepth = 0,
|
||||
} = opts;
|
||||
|
||||
let text = (chunk as LeafType).text || '';
|
||||
let type = (chunk as BlockType).type || '';
|
||||
|
||||
const nodeTypes: NodeTypes = {
|
||||
...defaultNodeTypes,
|
||||
...userNodeTypes,
|
||||
heading: {
|
||||
...defaultNodeTypes.heading,
|
||||
...userNodeTypes.heading,
|
||||
},
|
||||
};
|
||||
|
||||
const LIST_TYPES = [nodeTypes.ul_list, nodeTypes.ol_list];
|
||||
|
||||
let children = text;
|
||||
|
||||
if (!isLeafNode(chunk)) {
|
||||
children = chunk.children
|
||||
.map((c: BlockType | LeafType) => {
|
||||
const isList = !isLeafNode(c)
|
||||
? (LIST_TYPES as string[]).includes(c.type || '')
|
||||
: false;
|
||||
|
||||
const selfIsList = (LIST_TYPES as string[]).includes(chunk.type || '');
|
||||
|
||||
// Links can have the following shape
|
||||
// In which case we don't want to surround
|
||||
// with break tags
|
||||
// {
|
||||
// type: 'paragraph',
|
||||
// children: [
|
||||
// { text: '' },
|
||||
// { type: 'link', children: [{ text: foo.com }]}
|
||||
// { text: '' }
|
||||
// ]
|
||||
// }
|
||||
let childrenHasLink = false;
|
||||
|
||||
if (!isLeafNode(chunk) && Array.isArray(chunk.children)) {
|
||||
childrenHasLink = chunk.children.some(
|
||||
(f) => !isLeafNode(f) && f.type === nodeTypes.link
|
||||
);
|
||||
}
|
||||
|
||||
return serialize(
|
||||
{ ...c, parentType: type },
|
||||
{
|
||||
nodeTypes,
|
||||
// WOAH.
|
||||
// what we're doing here is pretty tricky, it relates to the block below where
|
||||
// we check for ignoreParagraphNewline and set type to paragraph.
|
||||
// We want to strip out empty paragraphs sometimes, but other times we don't.
|
||||
// If we're the descendant of a list, we know we don't want a bunch
|
||||
// of whitespace. If we're parallel to a link we also don't want
|
||||
// to respect neighboring paragraphs
|
||||
ignoreParagraphNewline:
|
||||
(ignoreParagraphNewline ||
|
||||
isList ||
|
||||
selfIsList ||
|
||||
childrenHasLink) &&
|
||||
// if we have c.break, never ignore empty paragraph new line
|
||||
!(c as BlockType).break,
|
||||
|
||||
// track depth of nested lists so we can add proper spacing
|
||||
listDepth: (LIST_TYPES as string[]).includes(
|
||||
(c as BlockType).type || ''
|
||||
)
|
||||
? listDepth + 1
|
||||
: listDepth,
|
||||
}
|
||||
);
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
|
||||
// This is pretty fragile code, check the long comment where we iterate over children
|
||||
if (
|
||||
!ignoreParagraphNewline &&
|
||||
(text === '' || text === '\n') &&
|
||||
chunk.parentType === nodeTypes.paragraph
|
||||
) {
|
||||
type = nodeTypes.paragraph;
|
||||
children = BREAK_TAG;
|
||||
}
|
||||
|
||||
if (children === '' && !VOID_ELEMENTS.find((k) => nodeTypes[k] === type))
|
||||
return;
|
||||
|
||||
// Never allow decorating break tags with rich text formatting,
|
||||
// this can malform generated markdown
|
||||
// Also ensure we're only ever applying text formatting to leaf node
|
||||
// level chunks, otherwise we can end up in a situation where
|
||||
// we try applying formatting like to a node like this:
|
||||
// "Text foo bar **baz**" resulting in "**Text foo bar **baz****"
|
||||
// which is invalid markup and can mess everything up
|
||||
if (children !== BREAK_TAG && isLeafNode(chunk)) {
|
||||
if (chunk.strikeThrough && chunk.bold && chunk.italic) {
|
||||
children = retainWhitespaceAndFormat(children, '~~***');
|
||||
} else if (chunk.bold && chunk.italic) {
|
||||
children = retainWhitespaceAndFormat(children, '***');
|
||||
} else {
|
||||
if (chunk.bold) {
|
||||
children = retainWhitespaceAndFormat(children, '**');
|
||||
}
|
||||
|
||||
if (chunk.italic) {
|
||||
children = retainWhitespaceAndFormat(children, '_');
|
||||
}
|
||||
|
||||
if (chunk.strikeThrough) {
|
||||
children = retainWhitespaceAndFormat(children, '~~');
|
||||
}
|
||||
|
||||
if (chunk.code) {
|
||||
children = retainWhitespaceAndFormat(children, '`');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case nodeTypes.heading[1]:
|
||||
return `# ${children}\n`;
|
||||
case nodeTypes.heading[2]:
|
||||
return `## ${children}\n`;
|
||||
case nodeTypes.heading[3]:
|
||||
return `### ${children}\n`;
|
||||
case nodeTypes.heading[4]:
|
||||
return `#### ${children}\n`;
|
||||
case nodeTypes.heading[5]:
|
||||
return `##### ${children}\n`;
|
||||
case nodeTypes.heading[6]:
|
||||
return `###### ${children}\n`;
|
||||
|
||||
case nodeTypes.block_quote:
|
||||
// For some reason, marked is parsing blockquotes w/ one new line
|
||||
// as contiued blockquotes, so adding two new lines ensures that doesn't
|
||||
// happen
|
||||
return `> ${children}\n\n`;
|
||||
|
||||
case nodeTypes.code_block:
|
||||
return `\`\`\`${
|
||||
(chunk as BlockType).language || ''
|
||||
}\n${children}\n\`\`\`\n`;
|
||||
|
||||
case nodeTypes.link:
|
||||
return `[${children}](${(chunk as BlockType).link || ''})`;
|
||||
case nodeTypes.image:
|
||||
return `.link || ''
|
||||
})`;
|
||||
|
||||
case nodeTypes.ul_list:
|
||||
case nodeTypes.ol_list:
|
||||
return `\n${children}\n`;
|
||||
|
||||
case nodeTypes.listItem:
|
||||
const isOL = chunk && chunk.parentType === nodeTypes.ol_list;
|
||||
const treatAsLeaf =
|
||||
(chunk as BlockType).children.length === 1 &&
|
||||
isLeafNode((chunk as BlockType).children[0]);
|
||||
|
||||
let spacer = '';
|
||||
for (let k = 0; listDepth > k; k++) {
|
||||
if (isOL) {
|
||||
// https://github.com/remarkjs/remark-react/issues/65
|
||||
spacer += ' ';
|
||||
} else {
|
||||
spacer += ' ';
|
||||
}
|
||||
}
|
||||
return `${spacer}${isOL ? '1.' : '-'} ${children}${
|
||||
treatAsLeaf ? '\n' : ''
|
||||
}`;
|
||||
|
||||
case nodeTypes.paragraph:
|
||||
return `${children}\n`;
|
||||
|
||||
case nodeTypes.thematic_break:
|
||||
return `---\n`;
|
||||
|
||||
default:
|
||||
return escapeHtml(children);
|
||||
}
|
||||
}
|
||||
|
||||
// This function handles the case of a string like this: " foo "
|
||||
// Where it would be invalid markdown to generate this: "** foo **"
|
||||
// We instead, want to trim the whitespace out, apply formatting, and then
|
||||
// bring the whitespace back. So our returned string looks like this: " **foo** "
|
||||
function retainWhitespaceAndFormat(string: string, format: string) {
|
||||
// we keep this for a comparison later
|
||||
const frozenString = string.trim();
|
||||
|
||||
// children will be mutated
|
||||
let children = frozenString;
|
||||
|
||||
// We reverse the right side formatting, to properly handle bold/italic and strikeThrough
|
||||
// formats, so we can create ~~***FooBar***~~
|
||||
const fullFormat = `${format}${children}${reverseStr(format)}`;
|
||||
|
||||
// This conditions accounts for no whitespace in our string
|
||||
// if we don't have any, we can return early.
|
||||
if (children.length === string.length) {
|
||||
return fullFormat;
|
||||
}
|
||||
|
||||
// if we do have whitespace, let's add our formatting around our trimmed string
|
||||
// We reverse the right side formatting, to properly handle bold/italic and strikeThrough
|
||||
// formats, so we can create ~~***FooBar***~~
|
||||
const formattedString = format + children + reverseStr(format);
|
||||
|
||||
// and replace the non-whitespace content of the string
|
||||
return string.replace(frozenString, formattedString);
|
||||
}
|
||||
|
||||
const reverseStr = (string: string) => string.split('').reverse().join('');
|
||||
Reference in New Issue
Block a user