Skip to content

Commit

Permalink
chore: update output attachment extention
Browse files Browse the repository at this point in the history
Co-authored-by: hunghg255 <[email protected]>
  • Loading branch information
Zizitto and hunghg255 committed Dec 11, 2024
1 parent 91a169d commit 269587a
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 26 deletions.
41 changes: 39 additions & 2 deletions src/extensions/Attachment/Attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { getDatasetAttribute } from '@/utils/dom-dataset'
import { NodeViewAttachment } from '@/extensions/Attachment/components/NodeViewAttachment/NodeViewAttachment'
import { ActionButton } from '@/components'
import type { GeneralOptions } from '@/types'
import { getFileTypeIcon } from '@/extensions/Attachment/components/NodeViewAttachment/FileIcon'
import { normalizeFileSize } from '@/utils/file'

declare module '@tiptap/core' {
interface Commands<ReturnType> {
Expand Down Expand Up @@ -52,8 +54,43 @@ export const Attachment = Node.create<AttachmentOptions>({
},

renderHTML({ HTMLAttributes }) {
// @ts-expect-error
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]
// Destructure and provide fallback defaults
const {
url = '',
fileName = '',
fileSize = '',
fileType = '',
fileExt = '',
} = HTMLAttributes || {}

// Validate attributes and merge safely
const mergedAttributes = mergeAttributes(
// @ts-expect-error
this.options.HTMLAttributes || {},
HTMLAttributes || {},
)

// Return the structured array
return [
'div',
mergedAttributes,
url
? [
'a',
{ href: url || '#' },
[
'span',
{ class: 'attachment__icon' },
getFileTypeIcon(fileType, true),
],
[
'span',
{ class: 'attachment__text' },
`${fileName}.${fileExt} (${normalizeFileSize(fileSize)})`,
],
]
: ['div', { class: 'attachment__placeholder' }],
]
},

addAttributes() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,67 @@
import { LucideAudioLines, LucideFile, LucideImage, LucideSheet, LucideTableProperties, LucideVideo } from 'lucide-react'
import ReactDOMServer from 'react-dom/server'
import { normalizeFileType } from '@/utils/file'
import { ExportPdf } from '@/components/icons/ExportPdf'
import ExportWord from '@/components/icons/ExportWord'

export function getFileTypeIcon(fileType: string) {
const type = normalizeFileType(fileType)
function iconToProseMirror(icon: JSX.Element) {
// Render SVG as a static string
const svgString = ReactDOMServer.renderToStaticMarkup(icon)

switch (type) {
case 'audio':
return <LucideAudioLines />
// Parse the string into ProseMirror-compatible structure
const parser = new DOMParser()
const svgDocument = parser.parseFromString(svgString, 'image/svg+xml')
const svgElement = svgDocument.documentElement

case 'video':
return <LucideVideo />
const iconToReturn = [
'svg',
{
...Array.from(svgElement.attributes).reduce((acc: any, attr: any) => {
acc[attr.name] = attr.value
return acc
}, {}),
},
]

case 'file':
return <LucideFile />
Array.from(svgElement.childNodes).forEach((child: any) => {
if (child.nodeType === 1) {
// Element node
const childElement = [
child.tagName.toLowerCase(),
Array.from(child.attributes).reduce((acc: any, attr: any) => {
acc[attr.name] = attr.value
return acc
}, {}),
]

case 'image':
return <LucideImage />
if (child.textContent) {
childElement.push(child.textContent)
}

case 'pdf':
return <ExportPdf />
iconToReturn.push(childElement)
}
})

case 'word':
return <ExportWord />
return iconToReturn
}

case 'excel':
return <LucideSheet />
// React components for rendering directly in JSX
const icons = {
audio: <LucideAudioLines />,
video: <LucideVideo />,
file: <LucideFile />,
image: <LucideImage />,
pdf: <ExportPdf />,
word: <ExportWord />,
excel: <LucideSheet />,
ppt: <LucideTableProperties />,
}

case 'ppt':
return <LucideTableProperties />
export function getFileTypeIcon(fileType: string, forProseMirror = false) {
const type = normalizeFileType(fileType)

default: {
return <></>
}
}
const icon = icons[type] || <></>

// Return ProseMirror-compatible structure or React component
return forProseMirror ? iconToProseMirror(icon) : icon
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
.wrap {
.attachment, /* for browser ready HTML */
.wrap { /* for NodeView */
border-width: 1px !important;
border-radius: 4px;
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px 0;

:global {
.attachment__icon {
width: 32px;
text-align: center;
}

.attachment__icon svg {
width: 32px;
display: inline-block;
}
}
}

0 comments on commit 269587a

Please sign in to comment.