1+ import { mergeAttributes , Node , Range } from '@tiptap/core'
2+
3+ import { handleRestoreMentionBackspace } from '../utils/handleRestoreMentionBackspace'
4+ import { insertContent } from '../utils/insertContent'
5+
6+ declare module '@tiptap/core' {
7+ interface Commands < ReturnType > {
8+ issue : {
9+ insertIssue : ( props : {
10+ id : string
11+ label : string
12+ range : Range
13+ } ) => ReturnType
14+ }
15+ }
16+ }
17+
18+ export interface IssueNodeAttrs {
19+ /**
20+ * The identifier for the selected issue, stored as a `data-id` attribute.
21+ */
22+ id : string | null
23+ /**
24+ * The label to be rendered by the editor as the displayed text for this issue.
25+ */
26+ label ?: string | null
27+ }
28+
29+ export type IssueOptions = {
30+ HTMLAttributes : Record < string , any >
31+ }
32+
33+ export const LinkIssue = Node . create < IssueOptions > ( {
34+ name : 'linkIssue' ,
35+
36+ addOptions ( ) {
37+ return {
38+ HTMLAttributes : {
39+ class : 'link-issue'
40+ }
41+ }
42+ } ,
43+
44+ group : 'inline' ,
45+
46+ inline : true ,
47+
48+ selectable : false ,
49+
50+ atom : true ,
51+
52+ addAttributes ( ) {
53+ return {
54+ id : {
55+ default : null ,
56+ parseHTML : ( element ) => element . getAttribute ( 'data-id' ) ,
57+ renderHTML : ( attributes ) => {
58+ if ( ! attributes . id ) {
59+ return { }
60+ }
61+
62+ return {
63+ 'data-id' : attributes . id
64+ }
65+ }
66+ } ,
67+
68+ label : {
69+ default : null ,
70+ parseHTML : ( element ) => element . getAttribute ( 'data-label' ) ,
71+ renderHTML : ( attributes ) => {
72+ if ( ! attributes . label ) {
73+ return { }
74+ }
75+
76+ return {
77+ 'data-label' : attributes . label
78+ }
79+ }
80+ }
81+ }
82+ } ,
83+
84+ parseHTML ( ) {
85+ return [
86+ {
87+ tag : `span[data-type="${ this . name } "]`
88+ }
89+ ]
90+ } ,
91+
92+ renderHTML ( { node, HTMLAttributes } ) {
93+ return [
94+ 'span' ,
95+ mergeAttributes ( this . options . HTMLAttributes , { 'data-type' : this . name } , HTMLAttributes ) ,
96+ `$${ node . attrs . label ?? node . attrs . id } `
97+ ]
98+ } ,
99+
100+ renderText ( { node } ) {
101+ return `$${ node . attrs . label ?? node . attrs . id } `
102+ } ,
103+
104+ addCommands ( ) {
105+ return {
106+ insertIssue :
107+ ( { range, ...attrs } ) =>
108+ ( { chain, state } ) =>
109+ insertContent ( {
110+ chain,
111+ range,
112+ state,
113+ content : { type : this . name , attrs }
114+ } )
115+ }
116+ } ,
117+
118+ addKeyboardShortcuts ( ) {
119+ return {
120+ Backspace : ( ) =>
121+ this . editor . commands . command ( ( { tr, state } ) =>
122+ handleRestoreMentionBackspace ( { transaction : tr , state, nodeName : this . name , char : '$' } )
123+ )
124+ }
125+ }
126+ } )
0 commit comments