Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/articles: transform valid markdown to nodes #301

Open
wants to merge 32 commits into
base: feature/articles
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3a52062
fix autoformat plugin custom directive change
maerzhase Jul 28, 2022
e07ea82
add autoformat for headlines 1-6
maerzhase Jul 29, 2022
f949352
add autoformat for blockquote
maerzhase Jul 29, 2022
c0b1bf5
add espacing for inlinestyle regex
maerzhase Jul 29, 2022
bf40e93
add autoformat **, *, `
maerzhase Jul 29, 2022
c155220
fix render children to allow slate selection
maerzhase Jul 29, 2022
30d6ccc
parse matched string for directive auto format via processor
maerzhase Jul 30, 2022
3fa1455
add embed-media to void elements
maerzhase Jul 30, 2022
837f79c
implement autoformat rule for links
maerzhase Jul 30, 2022
37d124a
Merge branch 'feature/articles' into feature/#219-transform-valid-mar…
maerzhase Jul 30, 2022
70a5a63
move selection after inlinetypechange to end of string
maerzhase Jul 30, 2022
3a80266
enable autoformat upon paste
maerzhase Jul 30, 2022
fc4044d
escape the asterisk
maerzhase Jul 30, 2022
88470bc
Merge branch 'feature/articles' into feature/#219-transform-valid-mar…
maerzhase Jul 30, 2022
25dfdd4
add tezos-storage to void elements
maerzhase Jul 30, 2022
d4935e9
fix instanciateElement default props
maerzhase Jul 30, 2022
e5f8083
Merge branch 'feature/articles' into feature/#219-transform-valid-mar…
maerzhase Aug 9, 2022
eb3ca45
remove console.log
maerzhase Aug 9, 2022
6473788
make inlinetypechange monolytic
maerzhase Aug 11, 2022
9b55cc4
Merge branch 'feature/articles' into feature/#219-transform-valid-mar…
maerzhase Aug 11, 2022
8464b69
dont skip insert text on inline type change
maerzhase Aug 11, 2022
a3d76bc
fix block type change on trigger
maerzhase Aug 12, 2022
21a2e73
fix inline type change writing ux
maerzhase Aug 15, 2022
ec407bf
transform pasted inline styles
maerzhase Aug 15, 2022
7bd89f8
fix type errors
maerzhase Aug 16, 2022
9c0ae94
only parse inlineStyles if a style matches
maerzhase Aug 16, 2022
a86656a
add figure autoformat; fix link matcher regex
maerzhase Aug 18, 2022
85c5448
add auto format for lists
maerzhase Aug 28, 2022
4fb2f6f
Merge branch 'dev' into feature/#219-transform-valid-markdown-to-nodes
maerzhase Aug 28, 2022
c19b3f0
make unified figure and link auto format
maerzhase Aug 28, 2022
d02d2be
Merge branch 'feature/articles' into feature/#219-transform-valid-mar…
maerzhase Sep 24, 2022
575df77
🔧 added eslint config back
ciphrd Sep 15, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
{
"extends": "next/core-web-vitals"
"plugins": [
"prettier"
],
"extends": [
"prettier",
"next/core-web-vitals"
],
"rules": {
"prettier/prettier": "error"
}
}
6 changes: 6 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": false
}
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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"
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,50 @@
import { Editor, Transforms } from 'slate';
import { AutoFormatChangeType, ChangeData, AutoFormatChange } from './index';
import { getRangeFromBlockStartToCursor, getTextFromBlockStartToCursor } from '../../utils';
import { BlockDefinitions, EArticleBlocks } from '../../Blocks';
import { escapeRegExp } from "../../../../../utils/regex";

export class BlockTypeChange implements AutoFormatChange {
shortcut: string | string[]
type: AutoFormatChangeType
data: ChangeData
trigger:string
constructor(shortcut:string | string[], data: ChangeData) {
this.shortcut = shortcut
this.data = data
this.type = 'BlockTypeChange'
this.trigger = ' ';
}

apply = (editor: Editor): boolean => {
const textBeforeCursor = `${getTextFromBlockStartToCursor(editor)} `;
apply = (editor: Editor, text: string): boolean => {
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} `))
if (!shortcutMatch) return false;

Transforms.delete(editor, {
at: getRangeFromBlockStartToCursor(editor),
})
Transforms.setNodes(
editor,
{ ...this.data },
)
return true;
const shortcutMatch = testValues.find((shortcut) => `${textBeforeCursor} `.startsWith(`${shortcut} `))
if (isTrigger && shortcutMatch) {
Transforms.delete(editor, {
at: getRangeFromBlockStartToCursor(editor),
})
Transforms.setNodes(
editor,
{ ...this.data },
)
return true;
} else {
const matchShortcutWithText = new RegExp(`^(${testValues.map(testValue => escapeRegExp(testValue)).join('|')})\\s(?<text>.*)`, 'gm');
const matches = matchShortcutWithText.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;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +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';
import { getSlateEditorStateFromMarkdownSync } from '../../../processor/getSlateEditorStateFromMarkdown';

function parseAttributes(attributes:string|undefined): {[key: string]: any} {
const classNames = []
Expand Down Expand Up @@ -35,54 +35,56 @@ function parseAttributes(attributes:string|undefined): {[key: string]: any} {
return parsed
}



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|null {
const textBeforeCursor = getTextFromBlockStartToCursor(editor);
const matchDirective = new RegExp('(:*s*(?<type>[^\\s]*)\\s*\\[(?<text>.*)]\\s*{(?<attributes>.*)})', 'mg')
const matchDirective = new RegExp('(:+(?<type>.*)\\[(?<text>.*)]{(?<attributes>.*)})\\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 parsedAttributes = parseAttributes(attributes)
const nodeAttributes = {
value: text,
type,
...parsedAttributes.attributes
}
const props = customNodes.leafDirective[type]?.transformMdhastToComponent?.(null as any, nodeAttributes) || nodeAttributes;
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:props.type,
children: [{text: props.value}],
if (!matches) return null;
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;
if (parsedNode.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
}
})
}
)
return true;
Transforms.insertNodes(
editor,
parsedNode
)
return true
} catch {
return false;
}
}
}
Loading