Move to TanStack Start from Next.js (#184)

This commit is contained in:
Aslam
2024-10-07 16:44:17 +07:00
committed by GitHub
parent 3a89a1c07f
commit 950ebc3dad
514 changed files with 20021 additions and 15508 deletions
@@ -0,0 +1,17 @@
import { CodeBlockLowlight as TiptapCodeBlockLowlight } from "@tiptap/extension-code-block-lowlight"
import { common, createLowlight } from "lowlight"
export const CodeBlockLowlight = TiptapCodeBlockLowlight.extend({
addOptions() {
return {
...this.parent?.(),
lowlight: createLowlight(common),
defaultLanguage: null,
HTMLAttributes: {
class: "block-node",
},
}
},
})
export default CodeBlockLowlight
@@ -0,0 +1 @@
export * from "./code-block-lowlight"
@@ -0,0 +1,20 @@
import { Color as TiptapColor } from "@tiptap/extension-color"
import { Plugin } from "@tiptap/pm/state"
export const Color = TiptapColor.extend({
addProseMirrorPlugins() {
return [
...(this.parent?.() || []),
new Plugin({
props: {
handleKeyDown: (_, event) => {
if (event.key === "Enter") {
this.editor.commands.unsetColor()
}
return false
},
},
}),
]
},
})
@@ -0,0 +1 @@
export * from "./color"
@@ -0,0 +1,18 @@
/*
* Wrap the horizontal rule in a div element.
* Also add a keyboard shortcut to insert a horizontal rule.
*/
import { HorizontalRule as TiptapHorizontalRule } from "@tiptap/extension-horizontal-rule"
export const HorizontalRule = TiptapHorizontalRule.extend({
addKeyboardShortcuts() {
return {
"Mod-Alt--": () =>
this.editor.commands.insertContent({
type: this.name,
}),
}
},
})
export default HorizontalRule
@@ -0,0 +1 @@
export * from "./horizontal-rule"
@@ -0,0 +1,55 @@
import * as React from "react"
import { isNumber, NodeViewProps, NodeViewWrapper } from "@tiptap/react"
import { useImageLoad } from "../../../hooks/use-image-load"
import { cn } from "@/lib/utils"
const ImageViewBlock = ({ editor, node, getPos }: NodeViewProps) => {
const imgSize = useImageLoad(node.attrs.src)
const paddingBottom = React.useMemo(() => {
if (!imgSize.width || !imgSize.height) {
return 0
}
return (imgSize.height / imgSize.width) * 100
}, [imgSize.width, imgSize.height])
return (
<NodeViewWrapper>
<div draggable data-drag-handle>
<figure>
<div
className="relative w-full"
style={{
paddingBottom: `${isNumber(paddingBottom) ? paddingBottom : 0}%`,
}}
>
<div className="absolute h-full w-full">
<div
className={cn(
"relative h-full max-h-full w-full max-w-full rounded transition-all",
)}
style={{
boxShadow:
editor.state.selection.from === getPos()
? "0 0 0 1px hsl(var(--primary))"
: "none",
}}
>
<div className="relative flex h-full max-h-full w-full max-w-full overflow-hidden">
<img
alt={node.attrs.alt}
src={node.attrs.src}
className="absolute left-2/4 top-2/4 m-0 h-full max-w-full -translate-x-2/4 -translate-y-2/4 transform object-contain"
/>
</div>
</div>
</div>
</div>
</figure>
</div>
</NodeViewWrapper>
)
}
export { ImageViewBlock }
@@ -0,0 +1,9 @@
import { Image as TiptapImage } from "@tiptap/extension-image"
import { ReactNodeViewRenderer } from "@tiptap/react"
import { ImageViewBlock } from "./components/image-view-block"
export const Image = TiptapImage.extend({
addNodeView() {
return ReactNodeViewRenderer(ImageViewBlock)
},
})
@@ -0,0 +1 @@
export * from "./image"
@@ -0,0 +1,8 @@
export * from "./code-block-lowlight"
export * from "./color"
export * from "./horizontal-rule"
export * from "./image"
export * from "./link"
export * from "./selection"
export * from "./unset-all-marks"
export * from "./reset-marks-on-enter"
@@ -0,0 +1 @@
export * from "./link"
@@ -0,0 +1,97 @@
import { mergeAttributes } from "@tiptap/core"
import TiptapLink from "@tiptap/extension-link"
import { EditorView } from "@tiptap/pm/view"
import { getMarkRange } from "@tiptap/core"
import { Plugin, TextSelection } from "@tiptap/pm/state"
export const Link = TiptapLink.extend({
/*
* Determines whether typing next to a link automatically becomes part of the link.
* In this case, we dont want any characters to be included as part of the link.
*/
inclusive: false,
/*
* Match all <a> elements that have an href attribute, except for:
* - <a> elements with a data-type attribute set to button
* - <a> elements with an href attribute that contains 'javascript:'
*/
parseHTML() {
return [
{
tag: 'a[href]:not([data-type="button"]):not([href *= "javascript:" i])',
},
]
},
renderHTML({ HTMLAttributes }) {
return [
"a",
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
0,
]
},
addOptions() {
return {
...this.parent?.(),
openOnClick: false,
HTMLAttributes: {
class: "link",
},
}
},
addProseMirrorPlugins() {
const { editor } = this
return [
...(this.parent?.() || []),
new Plugin({
props: {
handleKeyDown: (_: EditorView, event: KeyboardEvent) => {
const { selection } = editor.state
/*
* Handles the 'Escape' key press when there's a selection within the link.
* This will move the cursor to the end of the link.
*/
if (event.key === "Escape" && selection.empty !== true) {
editor.commands.focus(selection.to, { scrollIntoView: false })
}
return false
},
handleClick(view, pos) {
/*
* Marks the entire link when the user clicks on it.
*/
const { schema, doc, tr } = view.state
const range = getMarkRange(doc.resolve(pos), schema.marks.link)
if (!range) {
return
}
const { from, to } = range
const start = Math.min(from, to)
const end = Math.max(from, to)
if (pos < start || pos > end) {
return
}
const $start = doc.resolve(start)
const $end = doc.resolve(end)
const transaction = tr.setSelection(new TextSelection($start, $end))
view.dispatch(transaction)
},
},
}),
]
},
})
export default Link
@@ -0,0 +1 @@
export * from "./reset-marks-on-enter"
@@ -0,0 +1,25 @@
import { Extension } from "@tiptap/core"
export const ResetMarksOnEnter = Extension.create({
name: "resetMarksOnEnter",
addKeyboardShortcuts() {
return {
Enter: ({ editor }) => {
if (
editor.isActive("bold") ||
editor.isActive("italic") ||
editor.isActive("strike") ||
editor.isActive("underline") ||
editor.isActive("code")
) {
editor.commands.splitBlock({ keepMarks: false })
return true
}
return false
},
}
},
})
@@ -0,0 +1 @@
export * from "./selection"
@@ -0,0 +1,36 @@
import { Extension } from "@tiptap/core"
import { Plugin, PluginKey } from "@tiptap/pm/state"
import { Decoration, DecorationSet } from "@tiptap/pm/view"
export const Selection = Extension.create({
name: "selection",
addProseMirrorPlugins() {
const { editor } = this
return [
new Plugin({
key: new PluginKey("selection"),
props: {
decorations(state) {
if (state.selection.empty) {
return null
}
if (editor.isFocused === true) {
return null
}
return DecorationSet.create(state.doc, [
Decoration.inline(state.selection.from, state.selection.to, {
class: "selection",
}),
])
},
},
}),
]
},
})
export default Selection
@@ -0,0 +1 @@
export * from "./unset-all-marks"
@@ -0,0 +1,9 @@
import { Extension } from "@tiptap/core"
export const UnsetAllMarks = Extension.create({
addKeyboardShortcuts() {
return {
"Mod-\\": () => this.editor.commands.unsetAllMarks(),
}
},
})