From 3a520623877e3af0464c6c38b3dd1d309ba047af Mon Sep 17 00:00:00 2001 From: maerzhase Date: Thu, 28 Jul 2022 21:22:21 +0200 Subject: [PATCH 01/26] fix autoformat plugin custom directive change --- .../AutoFormatPlugin/CustomDirectiveChange.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts index 935d82db1..8a02ce1a6 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts @@ -57,13 +57,8 @@ export class CustomDirectiveChange implements AutoFormatChange { const text = matches.groups?.['text'] const attributes = matches.groups?.['attributes'] if (!type) return false; - const parsedAttributes = parseAttributes(attributes) - const nodeAttributes = { - value: text, - type, - ...parsedAttributes.attributes - } - const props = customNodes.leafDirective[type]?.getPropsFromNode?.(null as any, nodeAttributes) || nodeAttributes; + const { attributes: parsedAttributes } = parseAttributes(attributes) || {} + const props = customNodes.leafDirective[type]?.getPropsFromNode?.(null as any, parsedAttributes) || parsedAttributes; const [start] = Range.edges(editor.selection as Range); const charBefore = Editor.before(editor, start, { unit: 'character', @@ -79,8 +74,8 @@ export class CustomDirectiveChange implements AutoFormatChange { editor, { ...props, - type:props.type, - children: [{text: props.value}], + type, + children: [{text: ''}], } ) return true; From e07ea82860983ac580e81b16b08de4584d12c391 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 29 Jul 2022 16:56:50 +0200 Subject: [PATCH 02/26] add autoformat for headlines 1-6 --- .../NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 52df272c0..dd4f926ef 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -13,7 +13,7 @@ export type AutoFormatChange = { function createChangeTypeHeading():AutoFormatChange[] { const changes = []; - for (let i = 1; i < 6; i++) { + for (let i = 1; i <= 6; i++) { changes.push(new BlockTypeChange( Array(i).fill('#').join(''), { From f949352087f4e945612e9f233109b11559d0653f Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 29 Jul 2022 16:57:14 +0200 Subject: [PATCH 03/26] add autoformat for blockquote --- src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index dd4f926ef..0004f1f62 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -28,6 +28,7 @@ function createChangeTypeHeading():AutoFormatChange[] { const config: AutoFormatChange[] = [ ...createChangeTypeHeading(), new BlockTypeChange('p', {type: 'paragraph',} ), + new BlockTypeChange('>', {type: 'blockquote',} ), new InlineTypeChange('__', {strong: true}), new InlineTypeChange('_', {emphasis: true}), new CustomDirectiveChange('tezos-storage'), From c0b1bf524f374ecea623cc1600de82d299194d9f Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 29 Jul 2022 17:56:59 +0200 Subject: [PATCH 04/26] add espacing for inlinestyle regex --- .../SlateEditor/AutoFormatPlugin/InlineTypeChange.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index dcbf8174c..b6db48144 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -48,11 +48,13 @@ export class InlineTypeChange implements AutoFormatChange { ): boolean => { const textBeforeCursor = getTextFromBlockStartToCursor(editor) const beforeTextWithSpace = `${textBeforeCursor} ` + console.log('?', beforeTextWithSpace) if (!beforeTextWithSpace.endsWith(`${this.shortcut} `)) { return false } // retreive the matches based on usual markdown pattern, e.g. // __bold__, _italic_, etc. - const matcher = RegExp(`(? Date: Fri, 29 Jul 2022 17:58:10 +0200 Subject: [PATCH 05/26] add autoformat **, *, ` --- .../NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 0004f1f62..c0143fe45 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -30,7 +30,10 @@ const config: AutoFormatChange[] = [ new BlockTypeChange('p', {type: 'paragraph',} ), new BlockTypeChange('>', {type: 'blockquote',} ), new InlineTypeChange('__', {strong: true}), + new InlineTypeChange('**', {strong: true}), new InlineTypeChange('_', {emphasis: true}), + new InlineTypeChange('*', {emphasis: true}), + new InlineTypeChange('`', {inlineCode: true}), new CustomDirectiveChange('tezos-storage'), ] From c155220c9ca3269dbc46495a0fb3b4451b3a2616 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 29 Jul 2022 23:05:58 +0200 Subject: [PATCH 06/26] fix render children to allow slate selection --- src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx index 0b715b34e..49ea729d2 100644 --- a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx +++ b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx @@ -98,14 +98,13 @@ export const BlockDefinitions: Record = buttonInstantiable: true, render: ({ attributes, element, children }) => (
- - {children} - + />
), hasUtilityWrapper: true, From 30d6ccc5b6064e203896ab0b48c5e17ca6a152be Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 09:40:45 +0200 Subject: [PATCH 07/26] parse matched string for directive auto format via processor --- .../AutoFormatPlugin/CustomDirectiveChange.ts | 86 ++++++------------- .../getSlateEditorStateFromMarkdown.ts | 40 ++++++--- 2 files changed, 54 insertions(+), 72 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts index 8a02ce1a6..c6a683b2d 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts @@ -1,41 +1,7 @@ import { Range, Point, Node, Editor, Transforms, Ancestor, NodeEntry } from 'slate'; import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; -import { customNodes } from '../../processor/plugins'; import { getTextFromBlockStartToCursor } from '../utils'; - -function parseAttributes(attributes:string|undefined): {[key: string]: any} { - const classNames = [] - const parsed: {[key: string]: any} = {} - if (!attributes) return parsed; - const entries = decodeURI(attributes).split(' '); - entries.forEach(entry => { - if(entry.startsWith('#')) { - parsed.id = entry.substring(1) - return; - } else if(entry.startsWith('.')) { - classNames.push(entry.substring(1)) - return; - } else { - const keyValueMatcher = new RegExp('"*(?.*)"*="*(?[^"]*)"*', 'mg') - const keyValueMatches = keyValueMatcher.exec(entry) - if(keyValueMatches) { - const key = keyValueMatches.groups?.['key'] - const value = keyValueMatches.groups?.['value'] - if(!parsed.attributes) { - parsed.attributes = {} as {[key:string]: any} - } - if(key && value) { - parsed.attributes[key] = value - } - return - } - } - }) - - return parsed -} - - +import { getSlateEditorStateFromMarkdownSync } from '../../processor/getSlateEditorStateFromMarkdown'; export class CustomDirectiveChange implements AutoFormatChange { shortcut: string @@ -53,31 +19,29 @@ export class CustomDirectiveChange implements AutoFormatChange { const matchDirective = new RegExp('(:*s*(?[^\\s]*)\\s*\\[(?.*)]\\s*{(?.*)})', 'mg') const matches = matchDirective.exec(textBeforeCursor); if (!matches) return false; - const type = matches.groups?.['type'] - const text = matches.groups?.['text'] - const attributes = matches.groups?.['attributes'] - if (!type) return false; - const { attributes: parsedAttributes } = parseAttributes(attributes) || {} - const props = customNodes.leafDirective[type]?.getPropsFromNode?.(null as any, parsedAttributes) || parsedAttributes; - const [start] = Range.edges(editor.selection as Range); - const charBefore = Editor.before(editor, start, { - unit: 'character', - distance: matches[0].length, - }) as Point; - Transforms.delete(editor, { - at: { - anchor: charBefore, - focus: start - } - }) - Transforms.insertNodes( - editor, - { - ...props, - type, - children: [{text: ''}], - } - ) - return true; + try { + const parsed = getSlateEditorStateFromMarkdownSync(matches[0]) + if (!parsed) return false; + const {editorState: [parsedNode]} = parsed; + if (parsedNode.type !== this.shortcut) return false; + const [start] = Range.edges(editor.selection as Range); + const charBefore = Editor.before(editor, start, { + unit: 'character', + distance: matches[0].length, + }) as Point; + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + Transforms.insertNodes( + editor, + parsedNode + ) + return true + } catch { + return false; + } } } diff --git a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts index e9ec33624..4722392b0 100644 --- a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts +++ b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts @@ -70,21 +70,39 @@ interface PayloadSlateEditorStateFromMarkdown { editorState: Descendant[] } + +const mdToSlateProcessor = unified() + .use(remarkParse) + .use(remarkMath) + .use(remarkGfm) + .use(remarkUnwrapImages) + .use(remarkDirective) + .use(remarkFxHashCustom) + .use(remarkToSlate, { + overrides: remarkSlateTransformerOverrides + }) + + export default async function getSlateEditorStateFromMarkdown(markdown: string): Promise { try { const matterResult = matter(markdown) console.log(markdown) - const processed = await unified() - .use(remarkParse) - .use(remarkMath) - .use(remarkGfm) - .use(remarkUnwrapImages) - .use(remarkDirective) - .use(remarkFxHashCustom) - .use(remarkToSlate, { - overrides: remarkSlateTransformerOverrides - }) - .process(matterResult.content) + const processed = await mdToSlateProcessor.process(matterResult.content) + + return { + ...matterResult.data, + editorState: processed.result as Descendant[] + }; + } catch(e) { + console.error(e) + return null; + } +} +export function getSlateEditorStateFromMarkdownSync(markdown: string): PayloadSlateEditorStateFromMarkdown | null { + try { + const matterResult = matter(markdown) + console.log(markdown) + const processed = mdToSlateProcessor.processSync(matterResult.content) return { ...matterResult.data, From 3fa14550404d0130ba914b742575c2bce2f3fb82 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 10:15:44 +0200 Subject: [PATCH 08/26] add embed-media to void elements --- src/components/NFTArticle/SlateEditor/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/index.tsx b/src/components/NFTArticle/SlateEditor/index.tsx index 9e513c9e0..ffd9dc50c 100644 --- a/src/components/NFTArticle/SlateEditor/index.tsx +++ b/src/components/NFTArticle/SlateEditor/index.tsx @@ -94,7 +94,7 @@ interface SlateEditorProps { } const INLINE_ELEMENTS = ['inlineMath', 'link'] -const VOID_ELEMENTS = ['inlineMath', 'math'] +const VOID_ELEMENTS = ['inlineMath', 'math', 'embed-media'] export const SlateEditor = forwardRef(({ initialValue, From 837f79cafd3352cb361a7e80f1af0d50d68065ee Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 10:47:35 +0200 Subject: [PATCH 09/26] implement autoformat rule for links --- .../AutoFormatPlugin/InlineTypeChange.ts | 1 - .../AutoFormatPlugin/LinkChange.ts | 52 +++++++++++++++++++ .../SlateEditor/AutoFormatPlugin/index.tsx | 10 +++- 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index b6db48144..e707c4317 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -48,7 +48,6 @@ export class InlineTypeChange implements AutoFormatChange { ): boolean => { const textBeforeCursor = getTextFromBlockStartToCursor(editor) const beforeTextWithSpace = `${textBeforeCursor} ` - console.log('?', beforeTextWithSpace) if (!beforeTextWithSpace.endsWith(`${this.shortcut} `)) { return false } // retreive the matches based on usual markdown pattern, e.g. // __bold__, _italic_, etc. diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts new file mode 100644 index 000000000..5d8b823fb --- /dev/null +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts @@ -0,0 +1,52 @@ +import { Range, Point, Node, Editor, Transforms, Ancestor, NodeEntry } from 'slate'; +import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; +import { getTextFromBlockStartToCursor } from '../utils'; +import { getSlateEditorStateFromMarkdownSync } from '../../processor/getSlateEditorStateFromMarkdown'; + +const LINK_MATCHER = new RegExp('((?[.]*)s*\\[(?.*)\\]s*[{(]*(?.*)[)}]+)', 'gm'); + +export class LinkChange implements AutoFormatChange { + shortcut: string + type: AutoFormatChangeType + data?: ChangeData + + constructor(data?: ChangeData) { + this.shortcut = 'link' + if (data) this.data = data + this.type = 'LinkChange' + } + + apply(editor: Editor): boolean { + const textBeforeCursor = getTextFromBlockStartToCursor(editor); + const matchDirective = LINK_MATCHER; + const matches = matchDirective.exec(textBeforeCursor); + console.log(matches) + if (!matches) return false; + try { + const parsed = getSlateEditorStateFromMarkdownSync(matches[0]) + console.log(parsed) + if (!parsed) return false; + const {editorState: [parsedNode]} = parsed; + const linkNode = parsedNode?.children?.[0]; + if (!linkNode || linkNode.type !== this.shortcut) return false; + const [start] = Range.edges(editor.selection as Range); + const charBefore = Editor.before(editor, start, { + unit: 'character', + distance: matches[0].length, + }) as Point; + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + Transforms.insertNodes( + editor, + linkNode + ) + return true + } catch { + return false; + } + } +} diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index c0143fe45..df6ed41d0 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -1,7 +1,8 @@ -import { Range, Editor } from 'slate'; +import { Range, Editor, Element, Node} from 'slate'; import { BlockTypeChange } from './BlockTypeChange' import { InlineTypeChange } from './InlineTypeChange' import { CustomDirectiveChange } from './CustomDirectiveChange' +import { LinkChange } from './LinkChange' export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChange" | "CustomDirectiveChange"; export type ChangeData = {[key: string]: number | string | boolean} @@ -35,10 +36,13 @@ const config: AutoFormatChange[] = [ new InlineTypeChange('*', {emphasis: true}), new InlineTypeChange('`', {inlineCode: true}), new CustomDirectiveChange('tezos-storage'), + new CustomDirectiveChange('embed-media'), + new CustomDirectiveChange('link'), + new LinkChange(), ] export const withAutoFormat = (editor: Editor) => { - const {insertText } = editor; + const { insertText } = editor; editor.insertText = text => { const { selection } = editor; if (text === ' ' && selection && Range.isCollapsed(selection)) { @@ -49,6 +53,8 @@ export const withAutoFormat = (editor: Editor) => { return (change as InlineTypeChange).apply(editor) } else if(change.type === 'CustomDirectiveChange') { return (change as CustomDirectiveChange).apply(editor) + } else if(change.type === 'LinkChange') { + return (change as LinkChange).apply(editor) } return false; }); From 70a5a6349d0cb920a9f21a199aed26dc934456b4 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 11:08:00 +0200 Subject: [PATCH 10/26] move selection after inlinetypechange to end of string --- .../SlateEditor/AutoFormatPlugin/InlineTypeChange.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index e707c4317..520600a90 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -120,6 +120,10 @@ export class InlineTypeChange implements AutoFormatChange { at: rangeAfter, } ) + Transforms.move(editor, { + distance: selectionAfterMatch.anchor.offset, + unit: 'character' + }) return true; } } From 3a8026697dba822bbc238ef5baa16e8345108064 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 21:15:26 +0200 Subject: [PATCH 11/26] enable autoformat upon paste --- .../AutoFormatPlugin/BlockTypeChange.ts | 43 +++++++++++++------ .../AutoFormatPlugin/CustomDirectiveChange.ts | 37 ++++++++++------ .../AutoFormatPlugin/InlineTypeChange.ts | 3 +- .../AutoFormatPlugin/LinkChange.ts | 37 +++++++++------- .../SlateEditor/AutoFormatPlugin/index.tsx | 10 ++--- .../SlateEditor/Elements/Blocks.tsx | 16 +++---- 6 files changed, 92 insertions(+), 54 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts index 9a0e12fdb..32f8c7712 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts @@ -1,28 +1,47 @@ import { Range, Point, Node, Editor, Transforms, Ancestor, NodeEntry } from 'slate'; import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; import { getRangeFromBlockStartToCursor, getTextFromBlockStartToCursor } from '../utils'; - +import { BlockDefinitions, EArticleBlocks } from '../Elements/Blocks'; export class BlockTypeChange implements AutoFormatChange { shortcut: string type: AutoFormatChangeType data: ChangeData + trigger:string constructor(shortcut:string, data: ChangeData) { this.shortcut = shortcut this.data = data this.type = 'BlockTypeChange' + this.trigger = ' '; } - apply = (editor: Editor): boolean => { - const textBeforeCursor = `${getTextFromBlockStartToCursor(editor)} `; - if (!textBeforeCursor.startsWith(`${this.shortcut} `)) return false; - Transforms.delete(editor, { - at: getRangeFromBlockStartToCursor(editor), - }) - Transforms.setNodes( - editor, - { ...this.data }, - ) - return true; + apply = (editor: Editor, text: string): boolean => { + const isTrigger = text === this.trigger; + const textBeforeCursor = isTrigger ? getTextFromBlockStartToCursor(editor) : text; + if (isTrigger && textBeforeCursor === this.shortcut) { + Transforms.delete(editor, { + at: getRangeFromBlockStartToCursor(editor), + }) + Transforms.setNodes( + editor, + { ...this.data }, + ) + return true; + } else { + const matchLink = new RegExp(`^${this.shortcut}\\s(?.*)`, 'gm'); + const matches = matchLink.exec(textBeforeCursor); + if (!matches) return false; + const { type } = this.data; + const matchedText = matches.groups?.text; + if (!matchedText) return false; + const blockDefinition = BlockDefinitions[type as EArticleBlocks]; + const element = blockDefinition?.instanciateElement?.({...this.data, text: matchedText}) + if(!element) return false; + Transforms.insertNodes( + editor, + element, + ) + return true; + } } } diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts index c6a683b2d..811a2efc6 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts @@ -3,38 +3,51 @@ import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; import { getTextFromBlockStartToCursor } from '../utils'; import { getSlateEditorStateFromMarkdownSync } from '../../processor/getSlateEditorStateFromMarkdown'; + export class CustomDirectiveChange implements AutoFormatChange { shortcut: string type: AutoFormatChangeType data?: ChangeData + trigger: string constructor(shortcut:string, data?: ChangeData) { this.shortcut = shortcut if (data) this.data = data this.type = 'CustomDirectiveChange' + this.trigger = ' ' } - apply(editor: Editor): boolean { + getMarkdownFromCurrentCursorPosition(editor: Editor):string|undefined { const textBeforeCursor = getTextFromBlockStartToCursor(editor); - const matchDirective = new RegExp('(:*s*(?[^\\s]*)\\s*\\[(?.*)]\\s*{(?.*)})', 'mg') + const matchDirective = new RegExp('(:+(?.*)\\[(?.*)]{(?.*)})\\s*$', 'mg') const matches = matchDirective.exec(textBeforeCursor); - if (!matches) return false; + if (!matches) return null; + const index = textBeforeCursor.indexOf(matches[0]) + return matches[0]; + } + + apply(editor: Editor, text:string): boolean { + const isTrigger = text === this.trigger; + const markdownString = isTrigger ? this.getMarkdownFromCurrentCursorPosition(editor) : text; + if (!markdownString) return false; try { - const parsed = getSlateEditorStateFromMarkdownSync(matches[0]) - if (!parsed) return false; + const parsed = getSlateEditorStateFromMarkdownSync(markdownString) + if(!parsed) return false; const {editorState: [parsedNode]} = parsed; if (parsedNode.type !== this.shortcut) return false; const [start] = Range.edges(editor.selection as Range); const charBefore = Editor.before(editor, start, { unit: 'character', - distance: matches[0].length, + distance: markdownString.length, }) as Point; - Transforms.delete(editor, { - at: { - anchor: charBefore, - focus: start - } - }) + if (isTrigger) { + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + } Transforms.insertNodes( editor, parsedNode diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index 520600a90..9e1b180b3 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -52,8 +52,7 @@ export class InlineTypeChange implements AutoFormatChange { // retreive the matches based on usual markdown pattern, e.g. // __bold__, _italic_, etc. const matcher = RegExp(`(?[.]*)s*\\[(?.*)\\]s*[{(]*(?.*)[)}]+)', 'gm'); export class LinkChange implements AutoFormatChange { shortcut: string type: AutoFormatChangeType data?: ChangeData + trigger: string constructor(data?: ChangeData) { this.shortcut = 'link' if (data) this.data = data this.type = 'LinkChange' + this.trigger = ' ' } - apply(editor: Editor): boolean { + getMarkdownFromCurrentCursorPosition(editor: Editor) { const textBeforeCursor = getTextFromBlockStartToCursor(editor); - const matchDirective = LINK_MATCHER; - const matches = matchDirective.exec(textBeforeCursor); - console.log(matches) - if (!matches) return false; + const matchLink = new RegExp('((?[.]*)s*\\[(?.*)\\]s*[{(]*(?.*)[)}]+)', 'gm'); + const matches = matchLink.exec(textBeforeCursor); + return matches?.[0]; + } + + apply(editor: Editor, text: string): boolean { + const isTrigger = text === this.trigger; + const markdownString = isTrigger ? this.getMarkdownFromCurrentCursorPosition(editor) : text; + if (!markdownString) return false; try { - const parsed = getSlateEditorStateFromMarkdownSync(matches[0]) - console.log(parsed) + const parsed = getSlateEditorStateFromMarkdownSync(markdownString) if (!parsed) return false; const {editorState: [parsedNode]} = parsed; const linkNode = parsedNode?.children?.[0]; @@ -32,14 +37,16 @@ export class LinkChange implements AutoFormatChange { const [start] = Range.edges(editor.selection as Range); const charBefore = Editor.before(editor, start, { unit: 'character', - distance: matches[0].length, + distance: markdownString.length, }) as Point; - Transforms.delete(editor, { - at: { - anchor: charBefore, - focus: start - } - }) + if(isTrigger) { + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + } Transforms.insertNodes( editor, linkNode diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index df6ed41d0..ec4f8f462 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -3,7 +3,7 @@ import { BlockTypeChange } from './BlockTypeChange' import { InlineTypeChange } from './InlineTypeChange' import { CustomDirectiveChange } from './CustomDirectiveChange' import { LinkChange } from './LinkChange' -export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChange" | "CustomDirectiveChange"; +export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChange" | "CustomDirectiveChange" | "LinkChange"; export type ChangeData = {[key: string]: number | string | boolean} export type AutoFormatChange = { @@ -45,16 +45,16 @@ export const withAutoFormat = (editor: Editor) => { const { insertText } = editor; editor.insertText = text => { const { selection } = editor; - if (text === ' ' && selection && Range.isCollapsed(selection)) { + if (selection && Range.isCollapsed(selection)) { const handled = config.some(change => { if(change.type === 'BlockTypeChange') { - return (change as BlockTypeChange).apply(editor) + return (change as BlockTypeChange).apply(editor, text) } else if (change.type === 'InlineTypeChange') { return (change as InlineTypeChange).apply(editor) } else if(change.type === 'CustomDirectiveChange') { - return (change as CustomDirectiveChange).apply(editor) + return (change as CustomDirectiveChange).apply(editor, text) } else if(change.type === 'LinkChange') { - return (change as LinkChange).apply(editor) + return (change as LinkChange).apply(editor, text) } return false; }); diff --git a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx index 71d7a5879..652426e2c 100644 --- a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx +++ b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx @@ -78,7 +78,7 @@ export interface IArticleBlockDefinition { buttonInstantiable?: boolean render: (props: RenderElementProps) => ReactNode hasUtilityWrapper: boolean - instanciateElement?: () => Element + instanciateElement?: (props?: any) => Element editAttributeComp?: TEditAttributeComp editAttributeWrapper?: TAttributesEditorWrapper // the definition can specify a function which can be called to output a @@ -161,10 +161,10 @@ export const BlockDefinitions: Record =

{children}

), hasUtilityWrapper: true, - instanciateElement: () => ({ + instanciateElement: ({text=""}) => ({ type: "paragraph", children: [{ - text: "" + text, }] }), }, @@ -191,11 +191,11 @@ export const BlockDefinitions: Record = } }, hasUtilityWrapper: true, - instanciateElement: () => ({ + instanciateElement: ({depth=1, text=""}) => ({ type: "heading", - depth: 1, + depth, children: [{ - text: "" + text }] }), editAttributeComp: HeadingAttributeSettings, @@ -214,10 +214,10 @@ export const BlockDefinitions: Record = buttonInstantiable: true, render: BlockquoteElement, hasUtilityWrapper: true, - instanciateElement: () => ({ + instanciateElement: ({text=""}) => ({ type: "blockquote", children: [{ - text: "" + text }] }) }, From fc4044d70b45de220658246fc3be58463430ead9 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 21:21:00 +0200 Subject: [PATCH 12/26] escape the asterisk --- .../NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index ec4f8f462..2e56543fa 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -31,9 +31,9 @@ const config: AutoFormatChange[] = [ new BlockTypeChange('p', {type: 'paragraph',} ), new BlockTypeChange('>', {type: 'blockquote',} ), new InlineTypeChange('__', {strong: true}), - new InlineTypeChange('**', {strong: true}), + new InlineTypeChange('\*\*', {strong: true}), new InlineTypeChange('_', {emphasis: true}), - new InlineTypeChange('*', {emphasis: true}), + new InlineTypeChange('\*', {emphasis: true}), new InlineTypeChange('`', {inlineCode: true}), new CustomDirectiveChange('tezos-storage'), new CustomDirectiveChange('embed-media'), From 25dfdd4ba32c51ef6895cfeba4210a155ce80f4e Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 23:47:28 +0200 Subject: [PATCH 13/26] add tezos-storage to void elements --- src/components/NFTArticle/SlateEditor/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/index.tsx b/src/components/NFTArticle/SlateEditor/index.tsx index ef045dbf4..22014f767 100644 --- a/src/components/NFTArticle/SlateEditor/index.tsx +++ b/src/components/NFTArticle/SlateEditor/index.tsx @@ -97,7 +97,7 @@ interface SlateEditorProps { } const INLINE_ELEMENTS = ['inlineMath', 'link'] -const VOID_ELEMENTS = ['inlineMath', 'math', 'embed-media'] +const VOID_ELEMENTS = ['inlineMath', 'math', 'embed-media', 'tezos-storage'] export const SlateEditor = forwardRef(({ initialValue, From d4935e92d556f411fc564217d92e06e95e49533b Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sat, 30 Jul 2022 23:55:21 +0200 Subject: [PATCH 14/26] fix instanciateElement default props --- src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx index 5f70fa6df..b45966fa3 100644 --- a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx +++ b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx @@ -164,7 +164,7 @@ export const BlockDefinitions: Record =

{children}

), hasUtilityWrapper: true, - instanciateElement: ({text=""}) => ({ + instanciateElement: ({text=""}: {text?: string} = {}) => ({ type: "paragraph", children: [{ text, @@ -194,7 +194,7 @@ export const BlockDefinitions: Record = } }, hasUtilityWrapper: true, - instanciateElement: ({depth=1, text=""}) => ({ + instanciateElement: ({depth=1, text=""}: {depth?: number, text?:string} = {}) => ({ type: "heading", depth, children: [{ @@ -217,7 +217,7 @@ export const BlockDefinitions: Record = buttonInstantiable: true, render: BlockquoteElement, hasUtilityWrapper: true, - instanciateElement: ({text=""}) => ({ + instanciateElement: ({text=""}: {text?: string} = {}) => ({ type: "blockquote", children: [{ text From eb3ca453ef6fa434371aafb9c1326d6a049d2913 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Tue, 9 Aug 2022 21:57:45 +0200 Subject: [PATCH 15/26] remove console.log --- .../NFTArticle/processor/getSlateEditorStateFromMarkdown.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts index 601a6c43c..cb8bcab29 100644 --- a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts +++ b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts @@ -101,7 +101,6 @@ export default async function getSlateEditorStateFromMarkdown(markdown: string): export function getSlateEditorStateFromMarkdownSync(markdown: string): PayloadSlateEditorStateFromMarkdown | null { try { const matterResult = matter(markdown) - console.log(markdown) const processed = mdToSlateProcessor.processSync(matterResult.content) return { From 6473788264a3b29ef6045305f8118c7e88109834 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Thu, 11 Aug 2022 21:18:07 +0200 Subject: [PATCH 16/26] make inlinetypechange monolytic --- .../AutoFormatPlugin/InlineTypeChange.ts | 192 ++++++++++-------- .../SlateEditor/AutoFormatPlugin/index.tsx | 16 +- 2 files changed, 116 insertions(+), 92 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index 323e53747..f440fd659 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -34,103 +34,125 @@ function getSelectionAccrossNodes( return { anchor, focus }; } -export class InlineTypeChange implements AutoFormatChange { +export class InlineTypeChanges implements AutoFormatChange { shortcut: string | string[] type: AutoFormatChangeType data: ChangeData + formats: [ChangeData, string | string[]][] - constructor(shortcut: string | string[], data: ChangeData) { - this.shortcut = shortcut - this.data = data - this.type = 'InlineTypeChange' + constructor(formats: [ChangeData, string | string[]][]) { + this.type = 'InlineTypeChanges' + this.formats = formats; + this.shortcut = formats.map(([,shortcut]) => shortcut ).flat() + this.data = formats.reduce((acc:ChangeData, [data, shortcut]: [ChangeData, string | string[]]) => { + if (Array.isArray(shortcut)) { + shortcut.forEach((s: string) => { + acc[s] = data; + }) + } else { + acc[shortcut] = data; + } + return acc; + }, {}) + console.log(this.shortcut, this.data) } apply = ( editor: Editor, + text: string ): boolean => { - const testValues = typeof this.shortcut === 'string' ? [this.shortcut] : this.shortcut; - const textBeforeCursor = `${getTextFromBlockStartToCursor(editor)} `; - const shortcutMatch = testValues.find((shortcut) => textBeforeCursor.endsWith(`${shortcut} `)) - if (!shortcutMatch) return false; - - // retreive the matches based on usual markdown pattern, e.g. - // __bold__, _italic_, etc. - const escapedShortcut = escapeRegExp(shortcutMatch); - const matcher = RegExp(`(? { - const value = this.data[key]; - editor.addMark(key, value); - }) - Transforms.collapse(editor, { edge: 'anchor' }) - // Now lets cleanup the md shortcuts from the text. - // Setting the marks on text nodes can result in a new structure - // because elements might be split up to apply the styles. - // Therefore we retrieve the updated selection of the matched string. - const selectionBeforeMatch = getSelectionAccrossNodes( - editor, - matchStartIndex, - matchEndIndex, - shortcutMatch - ) - // Create a range that matches the md shortcut - // before the search string (anchor) - const rangeBefore = { - anchor: selectionBeforeMatch.anchor, - focus: { - ...selectionBeforeMatch.anchor, - offset: selectionBeforeMatch.anchor.offset + shortcutMatch.length + const testValues = typeof this.shortcut === 'string' ? [this.shortcut] : this.shortcut + const textBeforeCursor = getTextFromBlockStartToCursor(editor) + const isPasted = text.length > 1; + const shortcutMatch = testValues.find((shortcut) => textBeforeCursor.endsWith(shortcut)) + if (shortcutMatch) { + const changeData = this.data[shortcutMatch] as ChangeData; + const [, shortcut] = this.formats.find(([data]) => data === changeData) || []; + if (!shortcut) return false; + const formatAliases = typeof shortcut === 'string' ? [shortcut] : shortcut; + // retreive the matches based on usual markdown pattern, e.g. + // __bold__, _italic_, etc. + const escapedShortcuts = `(${formatAliases.map((shortcut: string) => escapeRegExp(shortcut)).join('|')})` + const matcher = RegExp(`(? { + const value = changeData[key]; + editor.addMark(key, value); + }) + Transforms.collapse(editor, { edge: 'anchor' }) + // Now lets cleanup the md shortcuts from the text. + // Setting the marks on text nodes can result in a new structure + // because elements might be split up to apply the styles. + // Therefore we retrieve the updated selection of the matched string. + const selectionBeforeMatch = getSelectionAccrossNodes( + editor, + matchStartIndex, + matchEndIndex, + shortcutMatch + ) + // Create a range that matches the md shortcut + // before the search string (anchor) + const rangeBefore = { + anchor: selectionBeforeMatch.anchor, + focus: { + ...selectionBeforeMatch.anchor, + offset: selectionBeforeMatch.anchor.offset + shortcutMatch.length + } } - } - Transforms.delete( - editor, - { - at: rangeBefore + Transforms.delete( + editor, + { + at: rangeBefore + } + ) + const selectionAfterMatch = getSelectionAccrossNodes( + editor, + matchStartIndex, + matchEndIndex, + shortcutMatch + ) + // Create a range that matches the md shortcut + // after the search string (focus) + const rangeAfter = { + anchor: selectionAfterMatch.anchor, + focus: { + ...selectionAfterMatch.anchor, + offset: selectionAfterMatch.anchor.offset + shortcutMatch.length + }, } - ) - const selectionAfterMatch = getSelectionAccrossNodes( - editor, - matchStartIndex, - matchEndIndex, - shortcutMatch - ) - // Create a range that matches the md shortcut - // after the search string (focus) - const rangeAfter = { - anchor: selectionAfterMatch.anchor, - focus: { - ...selectionAfterMatch.anchor, - offset: selectionAfterMatch.anchor.offset + shortcutMatch.length - }, + Transforms.delete( + editor, + { + at: rangeAfter, + } + ) + Transforms.move(editor, { + distance: selectionAfterMatch.anchor.offset, + unit: 'character' + }) + Object.keys(changeData).forEach((key: string) => { + editor.removeMark(key); + }) + return true; + } else if(isPasted) { + return false } - Transforms.delete( - editor, - { - at: rangeAfter, - } - ) - Transforms.move(editor, { - distance: selectionAfterMatch.anchor.offset, - unit: 'character' - }) - return true; + return false; } } diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index d66a4cbc6..4142dfacb 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -1,11 +1,11 @@ import { Range, Editor } from 'slate'; import { BlockTypeChange } from './BlockTypeChange' -import { InlineTypeChange } from './InlineTypeChange' +import { InlineTypeChanges } from './InlineTypeChange' import { CustomDirectiveChange } from './CustomDirectiveChange' import { LinkChange } from './LinkChange' -export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChange" | "CustomDirectiveChange" | "LinkChange"; -export type ChangeData = {[key: string]: number | string | boolean} +export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChanges" | "CustomDirectiveChange" | "LinkChange"; +export type ChangeData = {[key: string]: number | string | boolean | ChangeData} export type AutoFormatChange = { shortcut: string | string[] @@ -33,9 +33,11 @@ const config: AutoFormatChange[] = [ new BlockTypeChange('p', {type: 'paragraph',} ), new BlockTypeChange('>', {type: 'blockquote',} ), new BlockTypeChange(['---', '***', '___'], {type: 'thematicBreak'}), - new InlineTypeChange(['__', '**'], {strong: true}), - new InlineTypeChange(['_', '*'], {emphasis: true}), - new InlineTypeChange('`', {inlineCode: true}), + new InlineTypeChanges([ + [{strong: true}, ['__', '**']], + [{emphasis: true}, ['_', '*']], + [{inlineCodeg: true}, ['`']], + ]), new CustomDirectiveChange('tezos-storage'), new CustomDirectiveChange('embed-media'), new CustomDirectiveChange('link'), @@ -48,7 +50,7 @@ export const withAutoFormat = (editor: Editor) => { const { selection } = editor; if (selection && Range.isCollapsed(selection)) { const handled = config.some(change => { - return ['BlockTypeChange', 'InlineTypeChange', 'CustomDirectiveChange', 'LinkChange'].indexOf(change.type) > -1 ? + return ['BlockTypeChange', 'InlineTypeChanges', 'CustomDirectiveChange', 'LinkChange'].indexOf(change.type) > -1 ? change.apply(editor, text) : false }); if (handled) return true; From 8464b6920a01f60c5695a19780d77116fc2590f0 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Thu, 11 Aug 2022 21:25:22 +0200 Subject: [PATCH 17/26] dont skip insert text on inline type change --- .../NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index f440fd659..8a26264ec 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -145,6 +145,7 @@ export class InlineTypeChanges implements AutoFormatChange { distance: selectionAfterMatch.anchor.offset, unit: 'character' }) + Transforms.insertText(editor, text) Object.keys(changeData).forEach((key: string) => { editor.removeMark(key); }) From a3d76bc3a722750d6a30d5fe1e7d9fe5a3d4f3c7 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Fri, 12 Aug 2022 09:44:42 +0200 Subject: [PATCH 18/26] fix block type change on trigger --- .../NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts index f0d9285c2..3ce0ada8b 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts @@ -19,7 +19,7 @@ export class BlockTypeChange implements AutoFormatChange { const isTrigger = text === this.trigger; const textBeforeCursor = isTrigger ? getTextFromBlockStartToCursor(editor) : text; const testValues = typeof this.shortcut === 'string' ? [this.shortcut] : this.shortcut; - const shortcutMatch = testValues.find((shortcut) => `${textBeforeCursor} `.startsWith(`${shortcut}`)) + const shortcutMatch = testValues.find((shortcut) => `${textBeforeCursor} `.startsWith(`${shortcut} `)) if (isTrigger && shortcutMatch) { Transforms.delete(editor, { at: getRangeFromBlockStartToCursor(editor), From 21a2e73ab7f7b98bb0da2974803e299b6c36c41d Mon Sep 17 00:00:00 2001 From: maerzhase Date: Mon, 15 Aug 2022 10:15:37 +0200 Subject: [PATCH 19/26] fix inline type change writing ux --- .../AutoFormatPlugin/InlineTypeChange.ts | 17 ++++++++++++++--- .../SlateEditor/AutoFormatPlugin/index.tsx | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index 8a26264ec..4ac8a5d4c 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -76,12 +76,14 @@ export class InlineTypeChanges implements AutoFormatChange { const matcher = RegExp(`(? { - editor.removeMark(key); + editor.removeMark(key) }) + Transforms.collapse(editor, {edge: 'focus'}) return true; } else if(isPasted) { return false diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 4142dfacb..13efa115c 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -36,7 +36,7 @@ const config: AutoFormatChange[] = [ new InlineTypeChanges([ [{strong: true}, ['__', '**']], [{emphasis: true}, ['_', '*']], - [{inlineCodeg: true}, ['`']], + [{inlineCode: true}, ['`']], ]), new CustomDirectiveChange('tezos-storage'), new CustomDirectiveChange('embed-media'), From ec407bf0b65bf7d5eb83f6d30bc9995485a3070f Mon Sep 17 00:00:00 2001 From: maerzhase Date: Mon, 15 Aug 2022 10:33:21 +0200 Subject: [PATCH 20/26] transform pasted inline styles --- .../SlateEditor/AutoFormatPlugin/InlineTypeChange.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index 4ac8a5d4c..3fd65b005 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -2,6 +2,7 @@ import { Editor, Node, NodeEntry, Path, Range, Transforms } from 'slate'; import { AutoFormatChange, AutoFormatChangeType, ChangeData } from './index'; import { getTextFromBlockStartToCursor } from '../utils'; import { escapeRegExp } from "../../../../utils/regex"; +import { getSlateEditorStateFromMarkdownSync } from '../../processor/getSlateEditorStateFromMarkdown'; function getSelectionAccrossNodes( editor: Editor, @@ -162,7 +163,14 @@ export class InlineTypeChanges implements AutoFormatChange { Transforms.collapse(editor, {edge: 'focus'}) return true; } else if(isPasted) { - return false + try { + const parsed = getSlateEditorStateFromMarkdownSync(text) + if(!parsed) return false; + Transforms.insertFragment(editor, parsed.editorState[0].children) + return true; + } catch { + return false + } } return false; } From 7bd89f8b897261e8d9ddc0d530b99d295c164827 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Tue, 16 Aug 2022 19:09:03 +0200 Subject: [PATCH 21/26] fix type errors --- .../SlateEditor/AutoFormatPlugin/BlockTypeChange.ts | 5 +++-- .../SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts | 3 +-- .../NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts index 3ce0ada8b..de59c8780 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/BlockTypeChange.ts @@ -3,6 +3,7 @@ import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; import { getRangeFromBlockStartToCursor, getTextFromBlockStartToCursor } from '../utils'; import { BlockDefinitions, EArticleBlocks } from '../Elements/Blocks'; import { escapeRegExp } from "../../../../utils/regex"; + export class BlockTypeChange implements AutoFormatChange { shortcut: string | string[] type: AutoFormatChangeType @@ -30,8 +31,8 @@ export class BlockTypeChange implements AutoFormatChange { ) return true; } else { - const matchLink = new RegExp(`^(${testValues.map(testValue => escapeRegExp(testValue)).join('|')})\\s(?.*)`, 'gm'); - const matches = matchLink.exec(textBeforeCursor); + const matchShortcutWithText = new RegExp(`^(${testValues.map(testValue => escapeRegExp(testValue)).join('|')})\\s(?.*)`, 'gm'); + const matches = matchShortcutWithText.exec(textBeforeCursor); if (!matches) return false; const { type } = this.data; const matchedText = matches.groups?.text; diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts index 811a2efc6..0327bfc12 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/CustomDirectiveChange.ts @@ -17,12 +17,11 @@ export class CustomDirectiveChange implements AutoFormatChange { this.trigger = ' ' } - getMarkdownFromCurrentCursorPosition(editor: Editor):string|undefined { + getMarkdownFromCurrentCursorPosition(editor: Editor):string|null { const textBeforeCursor = getTextFromBlockStartToCursor(editor); const matchDirective = new RegExp('(:+(?.*)\\[(?.*)]{(?.*)})\\s*$', 'mg') const matches = matchDirective.exec(textBeforeCursor); if (!matches) return null; - const index = textBeforeCursor.indexOf(matches[0]) return matches[0]; } diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 13efa115c..9bab36696 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -40,7 +40,6 @@ const config: AutoFormatChange[] = [ ]), new CustomDirectiveChange('tezos-storage'), new CustomDirectiveChange('embed-media'), - new CustomDirectiveChange('link'), new LinkChange(), ] From 9c0ae949947d5ba19faf994301516fb7a417d560 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Tue, 16 Aug 2022 19:18:09 +0200 Subject: [PATCH 22/26] only parse inlineStyles if a style matches --- .../SlateEditor/AutoFormatPlugin/InlineTypeChange.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts index 3fd65b005..dd0ad5210 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/InlineTypeChange.ts @@ -164,8 +164,12 @@ export class InlineTypeChanges implements AutoFormatChange { return true; } else if(isPasted) { try { + const escapedShortcuts = `(${(this.shortcut as string[]).map((shortcut: string) => escapeRegExp(shortcut)).join('|')})` + const matcher = RegExp(`(? Date: Thu, 18 Aug 2022 09:33:07 +0200 Subject: [PATCH 23/26] add figure autoformat; fix link matcher regex --- .../AutoFormatPlugin/FigureAutoFormat.ts | 58 +++++++++++++++++++ .../AutoFormatPlugin/LinkChange.ts | 2 +- .../SlateEditor/AutoFormatPlugin/index.tsx | 12 +++- 3 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/components/NFTArticle/SlateEditor/AutoFormatPlugin/FigureAutoFormat.ts diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/FigureAutoFormat.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/FigureAutoFormat.ts new file mode 100644 index 000000000..6c0086f5a --- /dev/null +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/FigureAutoFormat.ts @@ -0,0 +1,58 @@ +import { Range, Point, Node, Editor, Transforms, Ancestor, NodeEntry } from 'slate'; +import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; +import { getTextFromBlockStartToCursor } from '../utils'; +import { getSlateEditorStateFromMarkdownSync } from '../../processor/getSlateEditorStateFromMarkdown'; + + +export class FigureAutoFormat implements AutoFormatChange { + shortcut: string + type: AutoFormatChangeType + data?: ChangeData + trigger: string + + constructor(data?: ChangeData) { + this.shortcut = 'figure' + if (data) this.data = data + this.type = 'FigureAutoFormat' + this.trigger = ' ' + } + + getMarkdownFromCurrentCursorPosition(editor: Editor) { + const textBeforeCursor = getTextFromBlockStartToCursor(editor); + const matchLink = new RegExp('!\\[(?.+?)\\]\\((?.+?)\\)', 'gm'); + const matches = matchLink.exec(textBeforeCursor); + return matches?.[0]; + } + + apply(editor: Editor, text: string): boolean { + const isTrigger = text === this.trigger; + const markdownString = isTrigger ? this.getMarkdownFromCurrentCursorPosition(editor) : text; + if (!markdownString) return false; + try { + const parsed = getSlateEditorStateFromMarkdownSync(markdownString) + if (!parsed) return false; + const {editorState: [figureNode]} = parsed; + if (!figureNode || figureNode.type !== this.shortcut) return false; + const [start] = Range.edges(editor.selection as Range); + const charBefore = Editor.before(editor, start, { + unit: 'character', + distance: markdownString.length, + }) as Point; + if(isTrigger) { + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + } + Transforms.insertNodes( + editor, + [figureNode] + ) + return true + } catch { + return false; + } + } +} diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts index 577a2550d..0bcfab7f7 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/LinkChange.ts @@ -19,7 +19,7 @@ export class LinkChange implements AutoFormatChange { getMarkdownFromCurrentCursorPosition(editor: Editor) { const textBeforeCursor = getTextFromBlockStartToCursor(editor); - const matchLink = new RegExp('((?[.]*)s*\\[(?.*)\\]s*[{(]*(?.*)[)}]+)', 'gm'); + const matchLink = new RegExp('[^!]\\[(?.+?)\\]\\((?.+?)\\)', 'gm'); const matches = matchLink.exec(textBeforeCursor); return matches?.[0]; } diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 9bab36696..6a0f8a6de 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -3,8 +3,9 @@ import { BlockTypeChange } from './BlockTypeChange' import { InlineTypeChanges } from './InlineTypeChange' import { CustomDirectiveChange } from './CustomDirectiveChange' import { LinkChange } from './LinkChange' +import { FigureAutoFormat } from './FigureAutoFormat' -export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChanges" | "CustomDirectiveChange" | "LinkChange"; +export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChanges" | "CustomDirectiveChange" | "LinkChange" | "FigureAutoFormat"; export type ChangeData = {[key: string]: number | string | boolean | ChangeData} export type AutoFormatChange = { @@ -40,6 +41,7 @@ const config: AutoFormatChange[] = [ ]), new CustomDirectiveChange('tezos-storage'), new CustomDirectiveChange('embed-media'), + new FigureAutoFormat(), new LinkChange(), ] @@ -49,8 +51,12 @@ export const withAutoFormat = (editor: Editor) => { const { selection } = editor; if (selection && Range.isCollapsed(selection)) { const handled = config.some(change => { - return ['BlockTypeChange', 'InlineTypeChanges', 'CustomDirectiveChange', 'LinkChange'].indexOf(change.type) > -1 ? - change.apply(editor, text) : false + const handler = ['BlockTypeChange', 'InlineTypeChanges', 'CustomDirectiveChange', 'FigureAutoFormat', 'LinkChange'].indexOf(change.type) > -1 ? + change.apply(editor, text) : false + if(handler) { + console.log(change.type) + } + return handler; }); if (handled) return true; } From 85c54484b1169ca38e3ca46a03583da2bb745b3e Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sun, 28 Aug 2022 12:26:35 +0200 Subject: [PATCH 24/26] add auto format for lists also adds a normalisation into the constraints plugin to wrap single listItems within a list parent --- .../NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx | 1 + .../NFTArticle/SlateEditor/Elements/Blocks.tsx | 11 +++++++++++ .../SlateEditor/Plugins/SlateConstraintsPlugin.ts | 9 ++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx index 6a0f8a6de..6fff1ce4f 100644 --- a/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/AutoFormatPlugin/index.tsx @@ -34,6 +34,7 @@ const config: AutoFormatChange[] = [ new BlockTypeChange('p', {type: 'paragraph',} ), new BlockTypeChange('>', {type: 'blockquote',} ), new BlockTypeChange(['---', '***', '___'], {type: 'thematicBreak'}), + new BlockTypeChange(['-', '*'], {type: 'listItem'}), new InlineTypeChanges([ [{strong: true}, ['__', '**']], [{emphasis: true}, ['_', '*']], diff --git a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx index 077f0601a..def31cac9 100644 --- a/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx +++ b/src/components/NFTArticle/SlateEditor/Elements/Blocks.tsx @@ -296,6 +296,17 @@ export const BlockDefinitions: Record = }) }, hasUtilityWrapper: false, + instanciateElement: ({text=""}) => ({ + type: "list", + ordered: false, + spread: false, + children: [{ + type: "listItem", + children: [{ + text, + }] + }] + }), }, "table": { name: "Table", diff --git a/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts b/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts index 7371e0a5e..f81301ae0 100644 --- a/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts +++ b/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts @@ -1,4 +1,4 @@ -import { Transforms } from "slate"; +import { Transforms, Node } from "slate"; import { EnhanceEditorWith } from "../../../../types/ArticleEditor/Editor"; /** @@ -48,6 +48,13 @@ export const withConstraints: EnhanceEditorWith = (editor) => { ) } } + // Make sure listItems are wrapped with a list node + if(node.type === 'listItem') { + const parentNode = Node.parent(editor, path); + if (parentNode.type !== 'list') { + Transforms.wrapNodes(editor, {type: 'list' }) + } + } normalizeNode(entry) } From c19b3f066f16f9272df5f2680b518bd9c24e8266 Mon Sep 17 00:00:00 2001 From: maerzhase Date: Sun, 28 Aug 2022 15:14:14 +0200 Subject: [PATCH 25/26] make unified figure and link auto format --- .../AutoFormatPlugin/FigureAutoFormat.ts | 58 ------------- .../AutoFormatPlugin/InlineTypeChange.ts | 1 - .../LinkAndFigureAutoFormat.ts | 87 +++++++++++++++++++ .../Plugins/AutoFormatPlugin/LinkChange.ts | 60 ------------- .../Plugins/AutoFormatPlugin/index.tsx | 10 +-- .../Plugins/SlateConstraintsPlugin.ts | 9 ++ .../getSlateEditorStateFromMarkdown.ts | 2 +- 7 files changed, 101 insertions(+), 126 deletions(-) delete mode 100644 src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/FigureAutoFormat.ts create mode 100644 src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkAndFigureAutoFormat.ts delete mode 100644 src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkChange.ts diff --git a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/FigureAutoFormat.ts b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/FigureAutoFormat.ts deleted file mode 100644 index b041c4acb..000000000 --- a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/FigureAutoFormat.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Range, Point, Node, Editor, Transforms, Ancestor, NodeEntry } from 'slate'; -import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; -import { getTextFromBlockStartToCursor } from '../../utils'; -import { getSlateEditorStateFromMarkdownSync } from '../../../processor/getSlateEditorStateFromMarkdown'; - - -export class FigureAutoFormat implements AutoFormatChange { - shortcut: string - type: AutoFormatChangeType - data?: ChangeData - trigger: string - - constructor(data?: ChangeData) { - this.shortcut = 'figure' - if (data) this.data = data - this.type = 'FigureAutoFormat' - this.trigger = ' ' - } - - getMarkdownFromCurrentCursorPosition(editor: Editor) { - const textBeforeCursor = getTextFromBlockStartToCursor(editor); - const matchLink = new RegExp('!\\[(?.+?)\\]\\((?.+?)\\)', 'gm'); - const matches = matchLink.exec(textBeforeCursor); - return matches?.[0]; - } - - apply(editor: Editor, text: string): boolean { - const isTrigger = text === this.trigger; - const markdownString = isTrigger ? this.getMarkdownFromCurrentCursorPosition(editor) : text; - if (!markdownString) return false; - try { - const parsed = getSlateEditorStateFromMarkdownSync(markdownString) - if (!parsed) return false; - const {editorState: [figureNode]} = parsed; - if (!figureNode || figureNode.type !== this.shortcut) return false; - const [start] = Range.edges(editor.selection as Range); - const charBefore = Editor.before(editor, start, { - unit: 'character', - distance: markdownString.length, - }) as Point; - if(isTrigger) { - Transforms.delete(editor, { - at: { - anchor: charBefore, - focus: start - } - }) - } - Transforms.insertNodes( - editor, - [figureNode] - ) - return true - } catch { - return false; - } - } -} diff --git a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/InlineTypeChange.ts b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/InlineTypeChange.ts index 199eabd4e..ab27ffe3c 100644 --- a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/InlineTypeChange.ts +++ b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/InlineTypeChange.ts @@ -56,7 +56,6 @@ export class InlineTypeChanges implements AutoFormatChange { } return acc; }, {}) - console.log(this.shortcut, this.data) } apply = ( diff --git a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkAndFigureAutoFormat.ts b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkAndFigureAutoFormat.ts new file mode 100644 index 000000000..8582cbb3a --- /dev/null +++ b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkAndFigureAutoFormat.ts @@ -0,0 +1,87 @@ +import { Range, Point, Editor, Transforms, Node } from 'slate'; +import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; +import { getTextFromBlockStartToCursor } from '../../utils'; +import { getSlateEditorStateFromMarkdownSync, PayloadSlateEditorStateFromMarkdown } from '../../../processor/getSlateEditorStateFromMarkdown'; + +interface ILinkAndFigureClassification { + markdown: string + type: 'figure'|'link' +} + +function classifyMarkdown(markdown:string): ILinkAndFigureClassification { + const firstChar = markdown.charAt(0) + if (firstChar === '!'){ + return { + type: 'figure', + markdown, + } + } + const needsTrimming = firstChar !== '['; + return { + type: 'link', + markdown: needsTrimming ? markdown.substring(1) : markdown + } +} + +function getNodeToInsert(type:string, parsedMarkdown:PayloadSlateEditorStateFromMarkdown): Node|null { + switch(type) { + case 'figure': + return parsedMarkdown?.editorState?.[0] + case 'link': + return parsedMarkdown?.editorState?.[0]?.children?.[0]; + default: + return null; + } +} + +export class LinkAndFigureAutoFormat implements AutoFormatChange { + shortcut: string[] + type: AutoFormatChangeType + data?: ChangeData + trigger: string + + constructor(data?: ChangeData) { + this.shortcut = ['link', 'figure'] + if (data) this.data = data + this.type = 'LinkAndFigureAutoFormat' + this.trigger = ' ' + } + + apply(editor: Editor, text: string): boolean { + const isTrigger = text === this.trigger; + const mdText = isTrigger ? getTextFromBlockStartToCursor(editor) : text; + const matcher = new RegExp('.?\\[(?.+?)\\]\\((?.+?\\))', 'gm') + const matches = matcher.exec(mdText) + if (!matches) return false + const matchedMarkdown = matches[0] + if (!matchedMarkdown) return false; + try { + const { type, markdown } = classifyMarkdown(matchedMarkdown) + const parsed = getSlateEditorStateFromMarkdownSync(markdown) + if (!parsed) return false; + const nodeToInsert = getNodeToInsert(type, parsed) + if (!nodeToInsert || !this.shortcut.includes(nodeToInsert.type)) return false; + const [start] = Range.edges(editor.selection as Range); + const charBefore = Editor.before(editor, start, { + unit: 'character', + distance: markdown.length, + }) as Point; + if(isTrigger) { + Transforms.delete(editor, { + at: { + anchor: charBefore, + focus: start + } + }) + } + Transforms.insertNodes( + editor, + [nodeToInsert, {text: " "}], + ) + return true + } catch (e) { + console.error(e) + return false; + } + } +} diff --git a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkChange.ts b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkChange.ts deleted file mode 100644 index 1f4119692..000000000 --- a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/LinkChange.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Range, Point, Editor, Transforms } from 'slate'; -import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index'; -import { getTextFromBlockStartToCursor } from '../../utils'; -import { getSlateEditorStateFromMarkdownSync } from '../../../processor/getSlateEditorStateFromMarkdown'; - - -export class LinkChange implements AutoFormatChange { - shortcut: string - type: AutoFormatChangeType - data?: ChangeData - trigger: string - - constructor(data?: ChangeData) { - this.shortcut = 'link' - if (data) this.data = data - this.type = 'LinkChange' - this.trigger = ' ' - } - - getMarkdownFromCurrentCursorPosition(editor: Editor) { - const textBeforeCursor = getTextFromBlockStartToCursor(editor); - const matchLink = new RegExp('[^!]\\[(?.+?)\\]\\((?.+?)\\)', 'gm'); - const matches = matchLink.exec(textBeforeCursor); - return matches?.[0]; - } - - apply(editor: Editor, text: string): boolean { - const isTrigger = text === this.trigger; - const markdownString = isTrigger ? this.getMarkdownFromCurrentCursorPosition(editor) : text; - if (!markdownString) return false; - try { - const parsed = getSlateEditorStateFromMarkdownSync(markdownString) - if (!parsed) return false; - const {editorState: [parsedNode]} = parsed; - const linkNode = parsedNode?.children?.[0]; - if (!linkNode || linkNode.type !== this.shortcut) return false; - const [start] = Range.edges(editor.selection as Range); - const charBefore = Editor.before(editor, start, { - unit: 'character', - distance: markdownString.length, - }) as Point; - if(isTrigger) { - Transforms.delete(editor, { - at: { - anchor: charBefore, - focus: start - } - }) - } - Transforms.insertNodes( - editor, - [linkNode, { text: " "}] - ) - return true - } catch (e) { - console.error(e) - return false; - } - } -} diff --git a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/index.tsx b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/index.tsx index 7b79a68f6..e44425aad 100644 --- a/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/index.tsx +++ b/src/components/NFTArticle/SlateEditor/Plugins/AutoFormatPlugin/index.tsx @@ -2,10 +2,9 @@ import { Range, Editor } from 'slate'; import { BlockTypeChange } from './BlockTypeChange' import { InlineTypeChanges } from './InlineTypeChange' import { CustomDirectiveChange } from './CustomDirectiveChange' -import { LinkChange } from './LinkChange' -import { FigureAutoFormat } from './FigureAutoFormat' +import { LinkAndFigureAutoFormat } from './LinkAndFigureAutoFormat' -export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChanges" | "CustomDirectiveChange" | "LinkChange" | "FigureAutoFormat"; +export type AutoFormatChangeType = "BlockTypeChange" | "InlineTypeChanges" | "CustomDirectiveChange" | "LinkAndFigureAutoFormat" export type ChangeData = {[key: string]: number | string | boolean | ChangeData} export type AutoFormatChange = { @@ -42,8 +41,7 @@ const config: AutoFormatChange[] = [ ]), new CustomDirectiveChange('embed-media'), new CustomDirectiveChange('tezos-storage-pointer'), - new FigureAutoFormat(), - new LinkChange(), + new LinkAndFigureAutoFormat(), ] export const withAutoFormat = (editor: Editor) => { @@ -52,7 +50,7 @@ export const withAutoFormat = (editor: Editor) => { const { selection } = editor; if (selection && Range.isCollapsed(selection)) { const handled = config.some(change => { - const handler = ['BlockTypeChange', 'InlineTypeChanges', 'CustomDirectiveChange', 'FigureAutoFormat', 'LinkChange'].indexOf(change.type) > -1 ? + const handler = ['BlockTypeChange', 'InlineTypeChanges', 'CustomDirectiveChange', 'LinkAndFigureAutoFormat'].indexOf(change.type) > -1 ? change.apply(editor, text) : false if(handler) { console.log(change.type) diff --git a/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts b/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts index f81301ae0..1724d11f5 100644 --- a/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts +++ b/src/components/NFTArticle/SlateEditor/Plugins/SlateConstraintsPlugin.ts @@ -54,6 +54,15 @@ export const withConstraints: EnhanceEditorWith = (editor) => { if (parentNode.type !== 'list') { Transforms.wrapNodes(editor, {type: 'list' }) } + } + + // delete link nodes that have no text content + if(node.type === 'link') { + const text = Node.string(node) + if(text.length === 0) { + Transforms.removeNodes(editor, {at: path}) + return; + } } normalizeNode(entry) diff --git a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts index 5112c8e0c..123b75213 100644 --- a/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts +++ b/src/components/NFTArticle/processor/getSlateEditorStateFromMarkdown.ts @@ -48,7 +48,7 @@ const remarkSlateTransformerOverrides: OverridedMdastBuilders = { image: imageProcessor.transformMarkdownMdhastToSlate, } -interface PayloadSlateEditorStateFromMarkdown { +export interface PayloadSlateEditorStateFromMarkdown { [p: string]: any editorState: Descendant[] } From 575df778b5fe099380dcde87160f77f51fca017f Mon Sep 17 00:00:00 2001 From: "baptiste.crespy@gmail.com" Date: Thu, 15 Sep 2022 17:29:29 +0200 Subject: [PATCH 26/26] =?UTF-8?q?=F0=9F=94=A7=20added=20eslint=20config=20?= =?UTF-8?q?back?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.json | 11 +- .prettierrc.json | 6 ++ package.json | 7 +- yarn.lock | 266 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 .prettierrc.json diff --git a/.eslintrc.json b/.eslintrc.json index bffb357a7..ab41625b3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,12 @@ { - "extends": "next/core-web-vitals" + "plugins": [ + "prettier" + ], + "extends": [ + "prettier", + "next/core-web-vitals" + ], + "rules": { + "prettier/prettier": "error" + } } diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..0a379d53a --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": false +} \ No newline at end of file diff --git a/package.json b/package.json index b68b9afe3..e43328d6e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "lint:fix": "next lint --fix" }, "dependencies": { "@apollo/client": "^3.4.16", @@ -86,6 +87,10 @@ "@types/react-router-dom": "^5.3.1", "eslint": "8.0.0", "eslint-config-next": "11.1.2", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.31.8", + "prettier": "2.6.2", "typescript": "4.4.3" } } diff --git a/yarn.lock b/yarn.lock index 7d4e061d8..17c40c982 100644 --- a/yarn.lock +++ b/yarn.lock @@ -860,6 +860,17 @@ array-includes@^3.1.3, array-includes@^3.1.4: get-intrinsic "^1.1.1" is-string "^1.0.7" +array-includes@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" + integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" @@ -883,6 +894,16 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +array.prototype.flatmap@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" + integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + asap@~2.0.3: version "2.0.6" resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" @@ -1488,6 +1509,14 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" @@ -1632,6 +1661,42 @@ es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.19.2, es-abstract@^1.19.5: + version "1.20.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3" + integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.2" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" @@ -1681,6 +1746,11 @@ eslint-config-next@11.1.2: eslint-plugin-react "^7.23.1" eslint-plugin-react-hooks "^4.2.0" +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6: version "0.3.6" resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz" @@ -1746,6 +1816,13 @@ eslint-plugin-jsx-a11y@^6.4.1: language-tags "^1.0.5" minimatch "^3.0.4" +eslint-plugin-prettier@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-react-hooks@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz" @@ -1771,6 +1848,26 @@ eslint-plugin-react@^7.23.1: semver "^6.3.0" string.prototype.matchall "^4.0.6" +eslint-plugin-react@^7.31.8: + version "7.31.8" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf" + integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw== + dependencies: + array-includes "^3.1.5" + array.prototype.flatmap "^1.3.0" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.1" + object.values "^1.1.5" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.7" + eslint-scope@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz" @@ -1913,6 +2010,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^3.1.1: version "3.2.7" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz" @@ -2096,11 +2198,26 @@ function-bind@^1.1.1: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + fuzzy-search@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/fuzzy-search/-/fuzzy-search-3.2.1.tgz" @@ -2115,6 +2232,15 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + get-orientation@1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/get-orientation/-/get-orientation-1.1.2.tgz" @@ -2236,6 +2362,11 @@ has-bigints@^1.0.1: resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" @@ -2246,11 +2377,23 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" @@ -2689,6 +2832,11 @@ is-negative-zero@^2.0.1: resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + is-number-object@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz" @@ -2724,6 +2872,13 @@ is-shared-array-buffer@^1.0.1: resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz" integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" @@ -2756,6 +2911,13 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.0" +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + isarray@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" @@ -3503,6 +3665,13 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimist@^1.2.0: version "1.2.5" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" @@ -3672,6 +3841,11 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz" integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== +object-inspect@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" @@ -3695,6 +3869,16 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.entries@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz" @@ -3721,6 +3905,14 @@ object.hasown@^1.1.0: define-properties "^1.1.3" es-abstract "^1.19.1" +object.hasown@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3" + integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== + dependencies: + define-properties "^1.1.4" + es-abstract "^1.19.5" + object.values@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" @@ -3955,6 +4147,18 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + prismjs@^1.24.1, prismjs@^1.28.0: version "1.28.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" @@ -3986,6 +4190,15 @@ prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + property-expr@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz" @@ -4130,7 +4343,7 @@ react-is@17.0.2: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -4274,6 +4487,15 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" +regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" @@ -4773,6 +4995,20 @@ string.prototype.matchall@^4.0.6: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" +string.prototype.matchall@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" + integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.4.1" + side-channel "^1.0.4" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" @@ -4781,6 +5017,15 @@ string.prototype.trimend@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" @@ -4789,6 +5034,15 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + string_decoder@1.3.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" @@ -5068,6 +5322,16 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + unified@^10.0.0, unified@^10.1.0: version "10.1.1" resolved "https://registry.npmjs.org/unified/-/unified-10.1.1.tgz"