Skip to content

Commit

Permalink
Add footnote to demo
Browse files Browse the repository at this point in the history
  • Loading branch information
smoores-dev committed Mar 7, 2024
1 parent 0486dfc commit 7c45b60
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 23 deletions.
42 changes: 42 additions & 0 deletions demo/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,45 @@ main {
width: 80%;
max-width: 700px;
}

.ProseMirror .definition {
padding: 0.125rem;
border-left: 3px solid #a7a7a7;
margin: 1.25rem 0 1.25rem 1.5rem;
position: relative;
font-family: dskrptSans, sans-serif;
}

.ProseMirror[data-variant="viewer"] .definition {
font-family: dskrptSerif, SourceSerif, serif;
line-height: var(--lineHeightM);
}

.ProseMirror .definition:before {
content: "DEF";
position: absolute;
left: -1.875rem;
top: 0.125rem;
font-size: 0.7rem;
color: #343434;
font-family: dskrptSerif, SourceSerif, serif;
font-weight: 500;
}

.ProseMirror .definition-title {
font-weight: 500;
font-size: var(--fontSizeS);
width: 100%;
margin-left: 0.3rem;
margin-bottom: 0.5rem;
}

.ProseMirror .definition .definition-content {
font-size: var(--fontSizeS);
width: 100%;
margin-left: 0.3rem;
}

.ProseMirror .definition .definition-content p:last-child {
margin-bottom: 0;
}
106 changes: 104 additions & 2 deletions demo/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ import "prosemirror-gapcursor/style/gapcursor.css";
import { inputRules, wrappingInputRule } from "prosemirror-inputrules";
import { keymap } from "prosemirror-keymap";
import { Schema } from "prosemirror-model";
import { EditorState, Plugin } from "prosemirror-state";
import {
EditorState,
NodeSelection,
Plugin,
TextSelection,
} from "prosemirror-state";
import { columnResizing, tableEditing, tableNodes } from "prosemirror-tables";
import "prosemirror-tables/style/tables.css";
import { insertPoint } from "prosemirror-transform";
import {
Decoration,
DecorationSet,
Expand All @@ -23,6 +29,7 @@ import {
ProseMirrorDoc,
WidgetViewComponentProps,
reactKeys,
useEditorEventListener,
widget,
} from "../src/index.js";

Expand All @@ -43,6 +50,22 @@ const schema = new Schema({
cellAttributes: {},
tableGroup: "block",
}),
footnote: {
group: "inline",
content: "text*",
inline: true,
// This makes the view treat the node as a leaf, even though it
// technically has content
atom: true,
parseDOM: [
{
tag: "footnote",
},
],
toDOM(node) {
return ["footnote", { "data-guid": node.attrs.guid }, 0];
},
},
list: {
group: "block",
content: "list_item+",
Expand Down Expand Up @@ -131,6 +154,79 @@ const editorState = EditorState.create({
],
});

function insertFootnote(state: EditorState, dispatch?: EditorView["dispatch"]) {
// if (isFootnoteSelected(state.selection)) return false;
if (!state.schema.nodes["footnote"]) return false;

const validInsertPoint = insertPoint(
state.doc,
state.selection.from,
state.schema.nodes["footnote"]
);

if (validInsertPoint === null) return false;

const $from =
validInsertPoint === state.selection.from
? state.selection.$from
: state.doc.resolve(validInsertPoint);
const $to =
validInsertPoint === state.selection.from ? state.selection.$to : $from;

const { empty } = state.selection;
const isValidFootnoteContent =
$from.sameParent($to) && $from.parent.inlineContent;

const content =
isValidFootnoteContent && !empty
? $from.parent.content.cut($from.parentOffset, $to.parentOffset)
: null;

if (dispatch) {
const tr = state.tr;
tr.replaceSelectionWith(state.schema.nodes["footnote"].create({}, content));
let insertedPos: number | null = null;
tr.doc.nodesBetween(0, tr.selection.anchor, (node, pos) => {
if (node.type.name === "footnote") insertedPos = pos;
return true;
});
if (insertedPos) {
tr.setSelection(NodeSelection.create(tr.doc, insertedPos));
}
tr.setMeta("footnoteInserted", true);
dispatch(tr);
}
return true;
}

const Footnote = forwardRef<HTMLSpanElement, NodeViewComponentProps>(
function Footnote({ children: _, nodeProps, ...props }, ref) {
const { node } = nodeProps;

useEditorEventListener("keydown", (view, event) => {
if (event.key !== "Enter" && event.key !== " ") return false;

const { selection } = view.state;
if (!(selection instanceof NodeSelection && selection.node === node))
return false;

event.preventDefault();
// openAtomEditor()
// eslint-disable-next-line no-console
console.log("would have opened atom editor");
return true;
});

return (
<span {...props} ref={ref}>
<button>
<sup>1</sup>
</button>
</span>
);
}
);

const Paragraph = forwardRef(function Paragraph(
{ children, nodeProps, ...props }: NodeViewComponentProps,
ref: Ref<HTMLParagraphElement>
Expand Down Expand Up @@ -252,6 +348,7 @@ const plugins = [
...baseKeymap,
"Mod-i": toggleMark(schema.marks.em),
"Mod-b": toggleMark(schema.marks.strong),
"Mod-d": insertFootnote,
}),
viewPlugin,
gapCursor(),
Expand Down Expand Up @@ -301,7 +398,12 @@ function DemoEditor() {
plugins={plugins}
nodeViews={
showReactNodeViews
? { paragraph: Paragraph, list: List, list_item: ListItem }
? {
paragraph: Paragraph,
list: List,
list_item: ListItem,
footnote: Footnote,
}
: undefined
}
customNodeViews={showReactNodeViews ? undefined : customNodeViews}
Expand Down
Loading

0 comments on commit 7c45b60

Please sign in to comment.