planning
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s

This commit is contained in:
2024-10-14 09:15:30 +02:00
parent bcba00a730
commit 6e64e138e2
21059 changed files with 2317811 additions and 1 deletions

236
node_modules/remark-slate/src/ast-types.ts generated vendored Normal file
View 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
View 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
View 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
View 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
View 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 `![${(chunk as BlockType).caption}](${
(chunk as BlockType).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('');