Skip to content

Commit

Permalink
experiment: Inline element
Browse files Browse the repository at this point in the history
  • Loading branch information
areknawo committed Dec 4, 2023
1 parent 03a8333 commit f8a4436
Show file tree
Hide file tree
Showing 7 changed files with 3,365 additions and 2,606 deletions.
1 change: 1 addition & 0 deletions apps/docs/.astro/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ declare module 'astro:content' {
import('astro/zod').ZodLiteral<'webp'>,
import('astro/zod').ZodLiteral<'gif'>,
import('astro/zod').ZodLiteral<'svg'>,
import('astro/zod').ZodLiteral<'avif'>,
]
>;
}>;
Expand Down
5 changes: 3 additions & 2 deletions apps/web/public/sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -945,9 +945,9 @@
}
});

// ../../node_modules/.pnpm/@sanity+eventsource@5.0.0/node_modules/@sanity/eventsource/browser.js
// ../../node_modules/.pnpm/@sanity+eventsource@5.0.1/node_modules/@sanity/eventsource/browser.js
var require_browser = __commonJS({
"../../node_modules/.pnpm/@sanity+eventsource@5.0.0/node_modules/@sanity/eventsource/browser.js"(exports, module) {
"../../node_modules/.pnpm/@sanity+eventsource@5.0.1/node_modules/@sanity/eventsource/browser.js"(exports, module) {
module.exports = require_eventsource().EventSourcePolyfill;
}
});
Expand Down Expand Up @@ -1001,6 +1001,7 @@
var import_eventsource, l, U, E, S, f, h, L, m, D, O, R, T, x, C, I, u, v, k, j, q, G, A, b, z, y, B, M;
var init_api = __esm({
"../../packages/sdk/javascript/dist/api.mjs"() {
"use strict";
import_eventsource = __toESM(require_browser(), 1);
l = "/content-groups";
U = (t) => ({ get: (e) => t("GET", `${l}`, { params: e }), list: (e) => t("GET", `${l}/list`, { params: e }), create: (e) => t("POST", `${l}`, { body: e }), update: (e) => t("PUT", `${l}`, { body: e }), delete: (e) => t("DELETE", `${l}`, { params: e }) });
Expand Down
10 changes: 2 additions & 8 deletions apps/web/src/lib/editor/extensions/element/node.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { Element as BaseElement, ElementAttributes } from "@vrite/editor";
import {
NodeViewContent,
NodeViewWrapper,
SolidEditor,
SolidNodeViewRenderer,
SolidRenderer
} from "@vrite/tiptap-solid";
import { SolidEditor, SolidRenderer } from "@vrite/tiptap-solid";
import { NodeView } from "@tiptap/core";
import { keymap } from "@tiptap/pm/keymap";
import { Node } from "@tiptap/pm/model";
Expand Down Expand Up @@ -44,7 +38,7 @@ const registeredComponent: Record<string, Component> = {
console.log("render");

return (
<Card class="flex items-center justify-start m-0 my-4" color="primary" bind:test="test">
<Card class="flex items-center justify-start m-0 my-4" color="primary">
<Icon path={mdiAlertCircleOutline} class="w-6 h-6 mr-2" />
<div class="flex-1 not-prose" data-content="true"></div>
</Card>
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/views/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const Editor: Component<EditorProps> = (props) => {
clipboardSerializer: createClipboardSerializer(editor, workspaceSettings()!)
});
}
window.editor = editor;
},
extensions: [
BlockPaste.configure({ workspaceSettings }),
Expand Down
11 changes: 5 additions & 6 deletions packages/editor/src/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ const Element = Node.create({
}
];
},
renderHTML({ node, HTMLAttributes }) {
renderHTML({ node }) {
return [
"div",
mergeAttributes(HTMLAttributes, {
mergeAttributes({
"data-element": "true",
"data-type": node.attrs.type,
"data-props": JSON.stringify(node.attrs.props)
Expand All @@ -68,7 +68,6 @@ const Element = Node.create({
props: {},
...attrs
}
// content: [{ type: "paragraph" }]
});
};
},
Expand All @@ -83,8 +82,8 @@ const Element = Node.create({
};
}
};
},
addInputRules() {
}
/*addInputRules() {
const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
const [code] = input;
const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
Expand All @@ -110,7 +109,7 @@ const Element = Node.create({
getAttributes
})
];
}
}*/
});

export { Element };
Expand Down
143 changes: 124 additions & 19 deletions packages/editor/src/inline-element.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import { ExtendedRegExpMatchArray, Mark, markInputRule, mergeAttributes } from "@tiptap/core";
import {
Editor,
ExtendedRegExpMatchArray,
Node,
NodeView,
markInputRule,
mergeAttributes,
nodeInputRule,
wrappingInputRule
} from "@tiptap/core";
import { Node as PMNode } from "@tiptap/pm/model";

interface InlineElementAttributes {
type?: string;
Expand All @@ -15,10 +25,30 @@ declare module "@tiptap/core" {
}
}

const getOpeningTag = (node: PMNode): string => {
const keyValueProps = Object.entries(node.attrs.props).map(([key, value]) => {
if (value === true) return key;

const useBrackets = typeof value !== "string" || value.includes("\n") || value.includes(`"`);

return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${useBrackets ? "}" : ""}`;
});
const c = `<${node.attrs.type}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`;
const codeTagClosed = c.trim().replace(/>$/, "/>") || "";
const formattedCode = codeTagClosed;

return formattedCode.replace(/ *?\/>;/gm, node.content.size ? ">" : "/>").trim();
};
const getClosingTag = (node: PMNode): string => node.attrs.type;
const InlineElement = Node.create({
name: "inlineElement",
exitable: true,
inclusive: true,
content: "inline*",
group: "inline",
inline: true,
atom: true,
selectable: false,
isolating: true,
defining: true,
addAttributes() {
return {
props: {
Expand All @@ -42,74 +72,149 @@ const InlineElement = Node.create({
}
];
},
renderHTML({ mark }) {
renderHTML({ node }) {
return [
"span",
mergeAttributes({
"data-element": "true",
"data-type": mark.attrs.type,
"data-props": JSON.stringify(mark.attrs.props)
"data-type": node.attrs.type,
"data-props": JSON.stringify(node.attrs.props),
"style": "display: inline-flex;"
}),
[
"span",
{
contentEditable: false,
class:
"!whitespace-pre-wrap leading-[26px] min-h-6.5 w-full !p-0 !bg-transparent !rounded-0 !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none"
"!whitespace-pre-wrap w-full !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none font-mono"
},
`<${mark.attrs.type}>`
`<${node.attrs.type}>`
],
["span", { class: "px-3" }, 0],
["span", {}, 0],
[
"span",
{
contentEditable: "false",
class:
"!whitespace-pre-wrap leading-[26px] min-h-6.5 w-full !p-0 !bg-transparent !rounded-0 !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none"
"!whitespace-pre-wrap w-full !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none font-mono"
},
`</${mark.attrs.type}>`
`</${node.attrs.type}>`
]
];
},
/*addNodeView() {
return (props) => {
let node = props.node as PMNode;
const referenceView = new NodeView(() => {}, props);
const container = document.createElement("span");
const codeStart = document.createElement("span");
const codeEnd = document.createElement("span");
const content = document.createElement("span");
container.setAttribute("style", "display: inline-flex;");
codeStart.setAttribute(
"class",
"!whitespace-pre-wrap w-full !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none font-mono"
);
codeEnd.setAttribute(
"class",
"!whitespace-pre-wrap w-full !text-gray-400 !dark:text-gray-400 cursor-pointer pointer-events-none select-none font-mono"
);
codeStart.setAttribute("contenteditable", "false");
codeEnd.setAttribute("contenteditable", "false");
codeStart.textContent = `<${node.attrs.type}>`;
codeEnd.textContent = `</${node.attrs.type}>`;
container.append(codeStart, content, codeEnd);
return {
dom: container,
contentDOM: content,
ignoreMutation(mutation: MutationRecord | { type: "selection"; target: Element }) {
if (mutation.type === "selection") {
return true;
}
return referenceView.ignoreMutation(mutation);
},
stopEvent(event) {
return referenceView.stopEvent(event);
},
update(newNode) {
if (newNode.type.name !== "element") return false;
node = newNode as PMNode;
return true;
}
};
};
},*/
addCommands() {
return {
setInlineElement: (attrs) => {
return ({ commands }) => {
return commands.setMark(this.name, {
type: "Element",
props: {},
...attrs
return commands.insertContent({
type: this.name,
attrs: {
type: "Element",
props: {},
...attrs
},
content: [
{
type: "text",
text: " "
}
]
});
};
},
toggleInlineElement: (attrs) => {
return ({ commands }) => {
return commands.toggleMark(this.name, attrs);
return commands.toggleWrap(this.name, attrs);
};
},
unsetInlineElement: () => {
return ({ commands }) => {
return commands.unsetMark(this.name);
return commands.lift(this.name);
};
}
};
},
addInputRules() {
const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
/*const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
const tag = input[1].trim();
if (tag && tag !== "undefined") {
return { type: tag, props: {} };
}
return {};
};*/
const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
const [code] = input;
const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
const [, tag] = tagRegex.exec(code.trim()) || [];

if (tag && tag !== "undefined") {
return { type: tag, props: {} };
}

return {};
};

return [
markInputRule({
/*nodeInputRule({
find: /(?:<(.+?)>)((?:.+))(?:<\/\1>)$/,
type: this.type,
getAttributes
}),*/
wrappingInputRule({
find: /^<.*?.+?>$/,
type: this.type,
joinPredicate: () => false,
getAttributes
})
];
}
Expand Down
Loading

0 comments on commit f8a4436

Please sign in to comment.