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

Note linking #223

Merged
merged 1 commit into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"test": "mocha 'src/**/*.test.bundle.js'"
},
"dependencies": {
"@ariakit/react": "^0.4.8",
"ajv": "^8.6.2",
"ajv-formats": "^2.1.0",
"better-sqlite3": "^9.2.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import {
ELEMENT_UL,
ELEMENT_CODE_BLOCK,
ELEMENT_CODE_LINE,
ELEMENT_LINK,
} from "@udecode/plate"; // todo: sub-package which has only elements?

import { toSlateLink } from "../../../views/edit/editor/features/note-linking/toMdast";

export type Decoration = {
[key in (
| mdast.Emphasis
Expand Down Expand Up @@ -43,7 +46,6 @@ function convertNodes(nodes: mdast.Content[], deco: Decoration): slate.Node[] {
}, []);
}

// NOTE: Added
const DECORATION_MAPPING = {
emphasis: "italic",
strong: "bold",
Expand Down Expand Up @@ -365,9 +367,14 @@ function createBreak(node: mdast.Break) {
export type Link = ReturnType<typeof createLink>;

function createLink(node: mdast.Link, deco: Decoration) {
const { type, children, url, title } = node;
const { children, url, title } = node;

const res = toSlateLink({ url, children, deco, convertNodes });

if (res) return res;

return {
type: "a", // NOTE: Default plate link component uses "a"
type: ELEMENT_LINK,
children: convertNodes(children, deco),
url,
title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ import { Node as SNode } from "slate";
// NOTE: https://github.com/inokawa/remark-slate-transformer/issues/31
import { unPrefixUrl } from "../../../hooks/images";

// NOTE: added, and a good example of what changes I would want to make to this library!
import {
ELEMENT_LI,
ELEMENT_LIC,
ELEMENT_OL,
ELEMENT_TODO_LI,
ELEMENT_UL,
ELEMENT_CODE_BLOCK,
} from "@udecode/plate"; // todo: sub-package which has only elements?
} from "@udecode/plate";

import {
createLinkFromNoteLinkFactory,
ELEMENT_NOTE_LINK,
} from "../../../views/edit/editor/features/note-linking";

// NOTE: Changed these, they were just mirroring mdasts' before
// which doesn't make sense
Expand Down Expand Up @@ -56,7 +60,7 @@ function createMdastRoot(node: slate.Node): unistLib.Node {
return root as any as unistLib.Node;
}

function convertNodes(nodes: slate.Node[]): unistLib.Node[] {
export function convertNodes(nodes: slate.Node[]): unistLib.Node[] {
const mdastNodes: unistLib.Node[] = [];
let textQueue: SlateNodes.Text[] = [];
for (let i = 0; i <= nodes.length; i++) {
Expand Down Expand Up @@ -238,6 +242,8 @@ function createMdastNode(
return createImage(node);
case "linkReference":
return createLinkReference(node);
case ELEMENT_NOTE_LINK:
return createLinkFromNoteLink(node);
case "imageReference":
return createImageReference(node);
case "footnote":
Expand Down Expand Up @@ -461,13 +467,15 @@ function createBreak(node: SlateNodes.Break): mdast.Break {
function createLink(node: SlateNodes.Link): mdast.Link {
const { type, url, title, children } = node;
return {
type: "link", // note: changes from type to type: "link" so it can accept "a", see the switch statement
url, // note: converted, "as any" added because mdast.Link thinks its url and not link?
type: "link",
url,
title,
children: convertNodes(children) as any as mdast.Link["children"],
} as any;
children: convertNodes(children) as any, //
};
}

const createLinkFromNoteLink = createLinkFromNoteLinkFactory(convertNodes);

function createImage(node: SlateNodes.Image | SlateNodes.Video): mdast.Image {
const { type, url, title, alt } = node;
return {
Expand Down
60 changes: 36 additions & 24 deletions src/views/edit/PlateContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import React, { useContext } from "react";
import { withProps } from "@udecode/cn";
import { observer } from "mobx-react-lite";
import { Node as SNode } from "slate";
import { Editor, Node as SNode } from "slate";
import {
Plate,
PlateContent,
Expand All @@ -11,6 +11,7 @@ import {
createHistoryPlugin,
isBlockAboveEmpty,
isSelectionAtBlockStart,
isSelectionAtBlockEnd,
PlateLeaf,
PlateElement,
} from "@udecode/plate-common";
Expand Down Expand Up @@ -73,7 +74,6 @@ import {
createLinkPlugin,
createSoftBreakPlugin,
createExitBreakPlugin,
createResetNodePlugin,
createListPlugin,
} from "@udecode/plate";

Expand All @@ -96,17 +96,23 @@ import {

import { autoformatRules } from "./editor/plugins/autoformat/autoformatRules";
import { createCodeBlockNormalizationPlugin } from "./editor/plugins/createCodeBlockNormalizationPlugin";
import { createResetNodePlugin } from "./editor/plugins/createResetNodePlugin";
import { createInlineEscapePlugin } from "./editor/plugins/createInlineEscapePlugin";
import {
NOTE_LINK,
ELEMENT_NOTE_LINK,
createNoteLinkDropdownPlugin,
createNoteLinkElementPlugin,
NoteLinkDropdownElement,
NoteLinkElement,
} from "./editor/features/note-linking";

import {
ELEMENT_VIDEO,
createVideoPlugin,
} from "./editor/plugins/createVideoPlugin";
import { createFilesPlugin } from "./editor/plugins/createFilesPlugin";

// Ideally this is injected; also createVideoPlugin and createFilesPlugin do this
import { IClient } from "../../preload/client/types";
const client: IClient = (window as any).chronicles.createClient();

import { EditorMode } from "./EditorMode";
import { EditableDocument } from "./EditableDocument";
import { JournalResponse } from "../../hooks/useClient";
Expand All @@ -121,8 +127,16 @@ export interface Props {
setSelectedEditorMode: (s: EditorMode) => any;
}

import { JournalsStoreContext } from "../../hooks/useJournalsLoader";
import useClient from "../../hooks/useClient";
import { SearchStore } from "../documents/SearchStore";

export default observer(
({ children, saving, value, setValue }: React.PropsWithChildren<Props>) => {
const jstore = useContext(JournalsStoreContext);
const client = useClient();
const store = new SearchStore(client, jstore!, () => {}, []);

const plugins = createPlugins(
[
createCodeBlockNormalizationPlugin(),
Expand Down Expand Up @@ -166,6 +180,8 @@ export default observer(
// dropped video files and this won't be called.
createVideoPlugin(),
createFilesPlugin(),
createNoteLinkDropdownPlugin({ options: { store } } as any),
createNoteLinkElementPlugin(),

// Backspacing into an element selects the block before deleting it.
createSelectOnBackspacePlugin({
Expand Down Expand Up @@ -256,6 +272,11 @@ export default observer(
},
}),

// When editing "inline" elements, allow space at the end to "escape" from the element.
// ex: link or note link editing.
// See plugin comments for links and details; this is
createInlineEscapePlugin(),

// Set text block indentation for differentiating structural
// elements or emphasizing certain content sections.
// https://platejs.org/docs/indent
Expand Down Expand Up @@ -286,7 +307,8 @@ export default observer(
// being confused about how to exit an e.g. code block to add more content.
createTrailingBlockPlugin({ type: ELEMENT_PARAGRAPH }),

// e.g. # -> h1, ``` -> code block, etc
// convert markdown to wysiwyg sa you type:
// # -> h1, ``` -> code block, etc
createAutoformatPlugin({
options: {
rules: autoformatRules,
Expand All @@ -302,7 +324,6 @@ export default observer(
[ELEMENT_CODE_LINE]: CodeLineElement,
[ELEMENT_CODE_SYNTAX]: CodeSyntaxLeaf,
[MARK_CODE]: CodeLeaf,
// [ELEMENT_HR]: HrElement,
[ELEMENT_H1]: withProps(HeadingElement, { variant: "h1" }),
[ELEMENT_H2]: withProps(HeadingElement, { variant: "h2" }),
[ELEMENT_H3]: withProps(HeadingElement, { variant: "h3" }),
Expand All @@ -311,31 +332,22 @@ export default observer(
[ELEMENT_H6]: withProps(HeadingElement, { variant: "h6" }),
[ELEMENT_IMAGE]: ImageElement,
[ELEMENT_LINK]: LinkElement,
// todo: need more plugins to make these truly usable.
// [ELEMENT_MEDIA_EMBED]: MediaEmbedElement,
// [ELEMENT_MENTION]: MentionElement,
// [ELEMENT_MENTION_INPUT]: MentionInputElement,

// NoteLinkDropdown provides the dropdown when typing `@`; NoteLinkElement
// is the actual element that gets inserted when you select a note.
[NOTE_LINK]: NoteLinkDropdownElement,
[ELEMENT_NOTE_LINK]: NoteLinkElement,

[ELEMENT_UL]: withProps(ListElement, { variant: "ul" }),
[ELEMENT_LI]: withProps(PlateElement, { as: "li" }),
[ELEMENT_OL]: withProps(ListElement, { variant: "ol" }),
[ELEMENT_PARAGRAPH]: ParagraphElement,
// [ELEMENT_TABLE]: TableElement,
// [ELEMENT_TD]: TableCellElement,
// [ELEMENT_TH]: TableCellHeaderElement,
// [ELEMENT_TODO_LI]: TodoListElement,
// [ELEMENT_TR]: TableRowElement,
// [ELEMENT_EXCALIDRAW]: ExcalidrawElement,
[MARK_BOLD]: withProps(PlateLeaf, { as: "strong" }),

// Unsure about these:
// [MARK_HIGHLIGHT]: HighlightLeaf,
[MARK_ITALIC]: withProps(PlateLeaf, { as: "em" }),
// [MARK_KBD]: KbdLeaf,
[MARK_STRIKETHROUGH]: withProps(PlateLeaf, { as: "s" }),
[MARK_SUBSCRIPT]: withProps(PlateLeaf, { as: "sub" }),
[MARK_SUPERSCRIPT]: withProps(PlateLeaf, { as: "sup" }),
[MARK_UNDERLINE]: withProps(PlateLeaf, { as: "u" }),
// [MARK_COMMENT]: CommentLeaf,
},
},
);
Expand Down
Loading
Loading