diff --git a/apps/server/src/utils/report/markdown-to-platejs.test.ts b/apps/server/src/utils/report/markdown-to-platejs.test.ts index a17e3847f..928b74e70 100644 --- a/apps/server/src/utils/report/markdown-to-platejs.test.ts +++ b/apps/server/src/utils/report/markdown-to-platejs.test.ts @@ -1,5 +1,5 @@ +import { describe, expect, it } from 'vitest'; import { markdownToPlatejs } from './markdown-to-platejs'; -import { describe, it, expect } from 'vitest'; describe('markdownToPlatejs', () => { it('should convert elaborate markdown to platejs', async () => { diff --git a/apps/server/src/utils/report/markdown-to-platejs.ts b/apps/server/src/utils/report/markdown-to-platejs.ts index 2c9ec2116..253314ab9 100644 --- a/apps/server/src/utils/report/markdown-to-platejs.ts +++ b/apps/server/src/utils/report/markdown-to-platejs.ts @@ -1,31 +1,31 @@ -import { MarkdownPlugin, remarkMdx, remarkMention } from '@platejs/markdown'; -import { createSlateEditor } from 'platejs'; -import { AutoformatPlugin } from '@platejs/autoformat'; import { ReportElementsSchema } from '@buster/server-shared/reports'; +import { AutoformatPlugin } from '@platejs/autoformat'; import { + BaseBasicBlocksPlugin, + BaseBasicMarksPlugin, + BaseBlockquotePlugin, BaseBoldPlugin, - BaseItalicPlugin, + BaseCodePlugin, BaseH1Plugin, BaseH2Plugin, BaseH3Plugin, BaseH4Plugin, BaseH5Plugin, BaseH6Plugin, - BaseBasicBlocksPlugin, - BaseBasicMarksPlugin, - BaseBlockquotePlugin, - BaseCodePlugin, BaseHeadingPlugin, BaseHighlightPlugin, BaseHorizontalRulePlugin, + BaseItalicPlugin, BaseKbdPlugin, BaseStrikethroughPlugin, BaseSubscriptPlugin, BaseSuperscriptPlugin, - BaseUnderlinePlugin + BaseUnderlinePlugin, } from '@platejs/basic-nodes'; -import { z } from 'zod'; +import { MarkdownPlugin, remarkMdx, remarkMention } from '@platejs/markdown'; +import { createSlateEditor } from 'platejs'; import remarkGfm from 'remark-gfm'; +import { z } from 'zod'; const serverNode = [ BaseBoldPlugin, @@ -51,13 +51,13 @@ const serverNode = [ AutoformatPlugin, MarkdownPlugin.configure({ options: { - remarkPlugins: [remarkGfm, remarkMdx, remarkMention] - } - }) + remarkPlugins: [remarkGfm, remarkMdx, remarkMention], + }, + }), ]; const SERVER_EDITOR = createSlateEditor({ - plugins: serverNode + plugins: serverNode, }); export const markdownToPlatejs = async (markdown: string) => { diff --git a/apps/web/src/components/ui/report/elements/BlockDiscussion.tsx b/apps/web/src/components/ui/report/elements/BlockDiscussion.tsx index 1c3167096..8df08e881 100644 --- a/apps/web/src/components/ui/report/elements/BlockDiscussion.tsx +++ b/apps/web/src/components/ui/report/elements/BlockDiscussion.tsx @@ -53,7 +53,7 @@ export const BlockDiscussion: RenderNodeWrapper = (props) => { return; } - return (props) => ( + const Component = (props: PlateElementProps) => ( = (props) => { {...props} /> ); + + Component.displayName = 'BlockDiscussion'; + + return Component; }; const BlockCommentContent = ({ diff --git a/apps/web/src/components/ui/report/elements/BlockDraggable.tsx b/apps/web/src/components/ui/report/elements/BlockDraggable.tsx index fac16c895..068d15956 100644 --- a/apps/web/src/components/ui/report/elements/BlockDraggable.tsx +++ b/apps/web/src/components/ui/report/elements/BlockDraggable.tsx @@ -61,7 +61,10 @@ export const BlockDraggable: RenderNodeWrapper = ({ editor, element, path }) => if (!enabled) return; // Return a function that renders the Draggable component - return (props) => ; + const Component = (props: PlateElementProps) => ; + Component.displayName = 'BlockDraggable'; + + return Component; }; function Draggable(props: PlateElementProps) { diff --git a/apps/web/src/components/ui/report/elements/BlockList.tsx b/apps/web/src/components/ui/report/elements/BlockList.tsx index 6ff35bea1..21e5ddcbb 100644 --- a/apps/web/src/components/ui/report/elements/BlockList.tsx +++ b/apps/web/src/components/ui/report/elements/BlockList.tsx @@ -27,7 +27,10 @@ const config: Record< export const BlockList: RenderNodeWrapper = (props) => { if (!props.element.listStyleType) return; - return (props) => ; + const Component = (props: PlateElementProps) => ; + Component.displayName = 'BlockList'; + + return Component; }; function List(props: PlateElementProps) { diff --git a/apps/web/src/components/ui/report/elements/BlockSuggestion.tsx b/apps/web/src/components/ui/report/elements/BlockSuggestion.tsx index 1738d2e41..e8e787aad 100644 --- a/apps/web/src/components/ui/report/elements/BlockSuggestion.tsx +++ b/apps/web/src/components/ui/report/elements/BlockSuggestion.tsx @@ -339,8 +339,8 @@ export const useResolveSuggestion = ( let newText = ''; let text = ''; - let properties: any = {}; - let newProperties: any = {}; + let properties = {}; + let newProperties = {}; // overlapping suggestion entries.forEach(([node]) => { diff --git a/apps/web/src/components/ui/report/elements/Comment.tsx b/apps/web/src/components/ui/report/elements/Comment.tsx index c580e96af..5ae412d9f 100644 --- a/apps/web/src/components/ui/report/elements/Comment.tsx +++ b/apps/web/src/components/ui/report/elements/Comment.tsx @@ -8,7 +8,7 @@ import { getCommentKey, getDraftCommentKey } from '@platejs/comment'; import { CommentPlugin, useCommentId } from '@platejs/comment/react'; import dayjs from 'dayjs'; import { ArrowUp, Check, Dots, Pencil, Trash, Xmark } from '@/components/ui/icons'; -import { type Value, KEYS, nanoid, NodeApi } from 'platejs'; +import { type TElement, type Value, KEYS, nanoid, NodeApi } from 'platejs'; import { Plate, useEditorPlugin, @@ -363,7 +363,7 @@ function CommentMoreDropdown(props: { const useCommentEditor = ( options: Omit = {}, - deps: any[] = [] + deps: Value[] = [] ) => { const commentEditor = usePlateEditor( { diff --git a/apps/web/src/components/ui/report/elements/LinkNode.tsx b/apps/web/src/components/ui/report/elements/LinkNode.tsx index ba8e8b3e8..9b8068c75 100644 --- a/apps/web/src/components/ui/report/elements/LinkNode.tsx +++ b/apps/web/src/components/ui/report/elements/LinkNode.tsx @@ -18,7 +18,7 @@ export function LinkElement(props: PlateElementProps) { className="text-primary decoration-primary font-medium underline underline-offset-4" attributes={{ ...props.attributes, - ...(linkProps as any) + ...linkProps }}> {props.children} diff --git a/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx b/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx index 49edd4d4d..8e9acc5fe 100644 --- a/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx +++ b/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx @@ -64,7 +64,7 @@ export const PlaceholderElement = withHOC( const { openFilePicker } = useFilePicker({ accept: currentContent.accept, multiple: true, - onFilesSelected: (data: { plainFiles?: File[]; errors?: any[] }) => { + onFilesSelected: (data: { plainFiles?: File[]; errors?: [] }) => { if (!data.plainFiles || data.plainFiles.length === 0) return; const updatedFiles = data.plainFiles; @@ -204,6 +204,7 @@ export function ImageProgress({ return (
+ {/* eslint-disable-next-line @next/next/no-img-element */} } className="h-auto w-full rounded-sm object-cover" diff --git a/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx b/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx index 22ceef0ca..55073a281 100644 --- a/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx +++ b/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx @@ -419,13 +419,13 @@ export function TableRowElement(props: PlateElementProps) { ); } -function RowDragHandle({ dragRef }: { dragRef: React.Ref }) { +function RowDragHandle({ dragRef }: { dragRef: React.Ref }) { const editor = useEditorRef(); const element = useElement(); return (
)} diff --git a/apps/web/src/components/ui/report/plugins/align-kit.tsx b/apps/web/src/components/ui/report/plugins/align-kit.tsx index 169c3f444..198394a88 100644 --- a/apps/web/src/components/ui/report/plugins/align-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/align-kit.tsx @@ -10,9 +10,9 @@ export const AlignKit = [ defaultNodeValue: 'start', nodeKey: 'align', styleKey: 'textAlign', - validNodeValues: ['start', 'left', 'center', 'right', 'end', 'justify'], + validNodeValues: ['start', 'left', 'center', 'right', 'end', 'justify'] }, - targetPlugins: [...KEYS.heading, KEYS.p, KEYS.img, KEYS.mediaEmbed], - }, - }), + targetPlugins: [...KEYS.heading, KEYS.p, KEYS.img, KEYS.mediaEmbed] + } + }) ]; diff --git a/apps/web/src/components/ui/report/plugins/autoformat-kit.tsx b/apps/web/src/components/ui/report/plugins/autoformat-kit.tsx index 8da4ec916..3b56a582f 100644 --- a/apps/web/src/components/ui/report/plugins/autoformat-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/autoformat-kit.tsx @@ -9,7 +9,7 @@ import { autoformatMath, AutoformatPlugin, autoformatPunctuation, - autoformatSmartQuotes, + autoformatSmartQuotes } from '@platejs/autoformat'; import { insertEmptyCodeBlock } from '@platejs/code-block'; import { toggleList } from '@platejs/list'; @@ -19,110 +19,110 @@ const autoformatMarks: AutoformatRule[] = [ { match: '***', mode: 'mark', - type: [KEYS.bold, KEYS.italic], + type: [KEYS.bold, KEYS.italic] }, { match: '__*', mode: 'mark', - type: [KEYS.underline, KEYS.italic], + type: [KEYS.underline, KEYS.italic] }, { match: '__**', mode: 'mark', - type: [KEYS.underline, KEYS.bold], + type: [KEYS.underline, KEYS.bold] }, { match: '___***', mode: 'mark', - type: [KEYS.underline, KEYS.bold, KEYS.italic], + type: [KEYS.underline, KEYS.bold, KEYS.italic] }, { match: '**', mode: 'mark', - type: KEYS.bold, + type: KEYS.bold }, { match: '__', mode: 'mark', - type: KEYS.underline, + type: KEYS.underline }, { match: '*', mode: 'mark', - type: KEYS.italic, + type: KEYS.italic }, { match: '_', mode: 'mark', - type: KEYS.italic, + type: KEYS.italic }, { match: '~~', mode: 'mark', - type: KEYS.strikethrough, + type: KEYS.strikethrough }, { match: '^', mode: 'mark', - type: KEYS.sup, + type: KEYS.sup }, { match: '~', mode: 'mark', - type: KEYS.sub, + type: KEYS.sub }, { match: '==', mode: 'mark', - type: KEYS.highlight, + type: KEYS.highlight }, { match: '≡', mode: 'mark', - type: KEYS.highlight, + type: KEYS.highlight }, { match: '`', mode: 'mark', - type: KEYS.code, - }, + type: KEYS.code + } ]; const autoformatBlocks: AutoformatRule[] = [ { match: '# ', mode: 'block', - type: KEYS.h1, + type: KEYS.h1 }, { match: '## ', mode: 'block', - type: KEYS.h2, + type: KEYS.h2 }, { match: '### ', mode: 'block', - type: KEYS.h3, + type: KEYS.h3 }, { match: '#### ', mode: 'block', - type: KEYS.h4, + type: KEYS.h4 }, { match: '##### ', mode: 'block', - type: KEYS.h5, + type: KEYS.h5 }, { match: '###### ', mode: 'block', - type: KEYS.h6, + type: KEYS.h6 }, { match: '> ', mode: 'block', - type: KEYS.blockquote, + type: KEYS.blockquote }, { match: '```', @@ -131,9 +131,9 @@ const autoformatBlocks: AutoformatRule[] = [ format: (editor) => { insertEmptyCodeBlock(editor, { defaultType: KEYS.p, - insertNodesOptions: { select: true }, + insertNodesOptions: { select: true } }); - }, + } }, // { // match: '+ ', @@ -149,10 +149,10 @@ const autoformatBlocks: AutoformatRule[] = [ editor.tf.setNodes({ type: KEYS.hr }); editor.tf.insertNodes({ children: [{ text: '' }], - type: KEYS.p, + type: KEYS.p }); - }, - }, + } + } ]; const autoformatLists: AutoformatRule[] = [ @@ -162,9 +162,9 @@ const autoformatLists: AutoformatRule[] = [ type: 'list', format: (editor) => { toggleList(editor, { - listStyleType: KEYS.ul, + listStyleType: KEYS.ul }); - }, + } }, { match: [String.raw`^\d+\.$ `, String.raw`^\d+\)$ `], @@ -174,9 +174,9 @@ const autoformatLists: AutoformatRule[] = [ format: (editor, { matchString }) => { toggleList(editor, { listRestartPolite: Number(matchString) || 1, - listStyleType: KEYS.ol, + listStyleType: KEYS.ol }); - }, + } }, { match: ['[] '], @@ -184,13 +184,13 @@ const autoformatLists: AutoformatRule[] = [ type: 'list', format: (editor) => { toggleList(editor, { - listStyleType: KEYS.listTodo, + listStyleType: KEYS.listTodo }); editor.tf.setNodes({ checked: false, - listStyleType: KEYS.listTodo, + listStyleType: KEYS.listTodo }); - }, + } }, { match: ['[x] '], @@ -198,14 +198,14 @@ const autoformatLists: AutoformatRule[] = [ type: 'list', format: (editor) => { toggleList(editor, { - listStyleType: KEYS.listTodo, + listStyleType: KEYS.listTodo }); editor.tf.setNodes({ checked: true, - listStyleType: KEYS.listTodo, + listStyleType: KEYS.listTodo }); - }, - }, + } + } ]; export const AutoformatKit = [ @@ -221,16 +221,16 @@ export const AutoformatKit = [ ...autoformatLegalHtml, ...autoformatArrow, ...autoformatMath, - ...autoformatLists, + ...autoformatLists ].map( (rule): AutoformatRule => ({ ...rule, query: (editor) => !editor.api.some({ - match: { type: editor.getType(KEYS.codeBlock) }, - }), + match: { type: editor.getType(KEYS.codeBlock) } + }) }) - ), - }, - }), + ) + } + }) ]; diff --git a/apps/web/src/components/ui/report/plugins/block-placeholder-kit.tsx b/apps/web/src/components/ui/report/plugins/block-placeholder-kit.tsx index 777dab6c1..2a58853a0 100644 --- a/apps/web/src/components/ui/report/plugins/block-placeholder-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/block-placeholder-kit.tsx @@ -9,11 +9,11 @@ export const BlockPlaceholderKit = [ className: 'before:absolute before:cursor-text before:opacity-30 before:content-[attr(placeholder)]', placeholders: { - [KEYS.p]: 'Type something...', + [KEYS.p]: 'Type something...' }, query: ({ path }) => { return path.length === 1; - }, - }, - }), + } + } + }) ]; diff --git a/apps/web/src/components/ui/report/plugins/indent-kit.tsx b/apps/web/src/components/ui/report/plugins/indent-kit.tsx index 82dacd518..df4adae61 100644 --- a/apps/web/src/components/ui/report/plugins/indent-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/indent-kit.tsx @@ -6,16 +6,10 @@ import { KEYS } from 'platejs'; export const IndentKit = [ IndentPlugin.configure({ inject: { - targetPlugins: [ - ...KEYS.heading, - KEYS.p, - KEYS.blockquote, - KEYS.codeBlock, - KEYS.toggle, - ], + targetPlugins: [...KEYS.heading, KEYS.p, KEYS.blockquote, KEYS.codeBlock, KEYS.toggle] }, options: { - offset: 24, - }, - }), + offset: 24 + } + }) ]; diff --git a/apps/web/src/components/ui/report/plugins/suggestion-kit.tsx b/apps/web/src/components/ui/report/plugins/suggestion-kit.tsx index 9a1ea1e06..6f0b2bd81 100644 --- a/apps/web/src/components/ui/report/plugins/suggestion-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/suggestion-kit.tsx @@ -88,7 +88,7 @@ export const suggestionPlugin = toTPlatePlugin( const suggestionLineBreakPlugin = createPlatePlugin({ key: 'suggestionLineBreak', - render: { belowNodes: SuggestionLineBreak as any } + render: { belowNodes: SuggestionLineBreak } }); export const SuggestionKit = [suggestionPlugin, suggestionLineBreakPlugin]; diff --git a/apps/web/src/hooks/useIsTouchDevice.test.ts b/apps/web/src/hooks/useIsTouchDevice.test.ts deleted file mode 100644 index 2becc77c8..000000000 --- a/apps/web/src/hooks/useIsTouchDevice.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { renderHook } from '@testing-library/react'; -import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { useIsTouchDevice } from './useIsTouchDevice'; - -// Mock window.matchMedia -const mockMatchMedia = vi.fn(); -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: mockMatchMedia -}); - -describe('useIsTouchDevice', () => { - beforeEach(() => { - // Reset all mocks before each test - vi.clearAllMocks(); - - // Reset navigator properties - Object.defineProperty(navigator, 'maxTouchPoints', { - writable: true, - value: 0 - }); - - // Reset window properties - delete (window as any).ontouchstart; - }); - - it('should return true when device has touch support via ontouchstart', () => { - // Test case: Device supports touch via ontouchstart property - // Expected output: true - Object.defineProperty(window, 'ontouchstart', { - value: null, - writable: true - }); - - mockMatchMedia.mockReturnValue({ matches: false }); - - const { result } = renderHook(() => useIsTouchDevice()); - - expect(result.current).toBe(true); - }); - - it('should return true when device has maxTouchPoints > 0', () => { - // Test case: Device supports touch via navigator.maxTouchPoints - // Expected output: true - Object.defineProperty(navigator, 'maxTouchPoints', { - writable: true, - value: 1 - }); - - mockMatchMedia.mockReturnValue({ matches: false }); - - const { result } = renderHook(() => useIsTouchDevice()); - - expect(result.current).toBe(true); - }); - - it('should return true when media query matches coarse pointer', () => { - // Test case: Device supports touch via pointer: coarse media query - // Expected output: true - mockMatchMedia.mockReturnValue({ matches: true }); - - const { result } = renderHook(() => useIsTouchDevice()); - - expect(result.current).toBe(true); - expect(mockMatchMedia).toHaveBeenCalledWith('(pointer: coarse)'); - }); - - it('should return false when no touch support is detected', () => { - // Test case: Device has no touch support detected by any method - // Expected output: false - mockMatchMedia.mockReturnValue({ matches: false }); - - const { result } = renderHook(() => useIsTouchDevice()); - - expect(result.current).toBe(false); - }); - - it('should handle missing matchMedia gracefully', () => { - // Test case: Browser doesn't support matchMedia (older browsers) - // Expected output: false (no touch support detected) - Object.defineProperty(window, 'matchMedia', { - writable: true, - value: undefined - }); - - const { result } = renderHook(() => useIsTouchDevice()); - - expect(result.current).toBe(false); - }); -}); diff --git a/apps/web/src/hooks/useIsTouchDevice.ts b/apps/web/src/hooks/useIsTouchDevice.ts index 7ea3bbc7f..001a78c8e 100644 --- a/apps/web/src/hooks/useIsTouchDevice.ts +++ b/apps/web/src/hooks/useIsTouchDevice.ts @@ -15,8 +15,7 @@ export const useIsTouchDevice = (): boolean => { // Multiple detection methods for better accuracy const hasTouchStart = 'ontouchstart' in window; const hasMaxTouchPoints = navigator.maxTouchPoints && navigator.maxTouchPoints > 0; - const hasMsMaxTouchPoints = - (navigator as any).msMaxTouchPoints && (navigator as any).msMaxTouchPoints > 0; + const hasMsMaxTouchPoints = navigator.maxTouchPoints && navigator.maxTouchPoints > 0; // Match media query for touch devices const hasCoarsePointer = window.matchMedia && window.matchMedia('(pointer: coarse)').matches;