@tiptap/extension-ruby-text 3.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +20 -0
- package/dist/index.cjs +317 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +290 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
- package/src/index.ts +5 -0
- package/src/ruby-text-decoration-plugin.ts +295 -0
- package/src/ruby-text.ts +174 -0
package/src/ruby-text.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from '@tiptap/core'
|
|
2
|
+
|
|
3
|
+
import type { RubyTextAnnotationEditorProps } from './ruby-text-decoration-plugin.js'
|
|
4
|
+
import { RubyTextDecorationPlugin } from './ruby-text-decoration-plugin.js'
|
|
5
|
+
|
|
6
|
+
export type { RubyTextAnnotationEditorProps }
|
|
7
|
+
|
|
8
|
+
export interface RubyTextOptions {
|
|
9
|
+
/**
|
|
10
|
+
* HTML attributes to add to the ruby element.
|
|
11
|
+
* @default {}
|
|
12
|
+
*/
|
|
13
|
+
HTMLAttributes: Record<string, any>
|
|
14
|
+
/**
|
|
15
|
+
* Whether clicking an annotation opens an inline editor.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
allowClickToEdit: boolean
|
|
19
|
+
/**
|
|
20
|
+
* Renders a custom element used as the inline annotation editor.
|
|
21
|
+
* The returned element is mounted inside the `rt` element. A descendant
|
|
22
|
+
* with the `autofocus` attribute is focused, otherwise the element itself.
|
|
23
|
+
* When not set, a plain text input is rendered.
|
|
24
|
+
* @default undefined
|
|
25
|
+
*/
|
|
26
|
+
renderAnnotationEditor?: (props: RubyTextAnnotationEditorProps) => HTMLElement
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RubyTextAttributes {
|
|
30
|
+
/**
|
|
31
|
+
* The ruby text annotation rendered in the HTML `rt` element.
|
|
32
|
+
*/
|
|
33
|
+
rt: string | null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare module '@tiptap/core' {
|
|
37
|
+
interface Commands<ReturnType> {
|
|
38
|
+
rubyText: {
|
|
39
|
+
/**
|
|
40
|
+
* Set a ruby text mark with an annotation on the current selection.
|
|
41
|
+
* @example editor.commands.setRubyText({ rt: 'かんじ' })
|
|
42
|
+
*/
|
|
43
|
+
setRubyText: (attributes: RubyTextAttributes) => ReturnType
|
|
44
|
+
/**
|
|
45
|
+
* Toggle a ruby text mark on the current selection.
|
|
46
|
+
* @example editor.commands.toggleRubyText({ rt: 'かんじ' })
|
|
47
|
+
*/
|
|
48
|
+
toggleRubyText: (attributes: RubyTextAttributes) => ReturnType
|
|
49
|
+
/**
|
|
50
|
+
* Remove the ruby text mark from the current selection.
|
|
51
|
+
* @example editor.commands.unsetRubyText()
|
|
52
|
+
*/
|
|
53
|
+
unsetRubyText: () => ReturnType
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* This extension adds support for HTML ruby text annotations.
|
|
60
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby
|
|
61
|
+
*/
|
|
62
|
+
export const RubyText = Mark.create<RubyTextOptions>({
|
|
63
|
+
name: 'rubyText',
|
|
64
|
+
|
|
65
|
+
inclusive: false,
|
|
66
|
+
|
|
67
|
+
addOptions() {
|
|
68
|
+
return {
|
|
69
|
+
HTMLAttributes: {},
|
|
70
|
+
allowClickToEdit: true,
|
|
71
|
+
renderAnnotationEditor: undefined,
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
addAttributes() {
|
|
76
|
+
return {
|
|
77
|
+
rt: {
|
|
78
|
+
default: null,
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
parseHTML() {
|
|
84
|
+
return [
|
|
85
|
+
{
|
|
86
|
+
tag: 'ruby',
|
|
87
|
+
contentElement: (node: HTMLElement) => {
|
|
88
|
+
const rb = node.querySelector('rb')
|
|
89
|
+
|
|
90
|
+
if (rb) {
|
|
91
|
+
return rb
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const surrogate = document.createElement('span')
|
|
95
|
+
|
|
96
|
+
Array.from(node.childNodes).forEach(child => {
|
|
97
|
+
if (child.nodeName !== 'RT' && child.nodeName !== 'RP') {
|
|
98
|
+
surrogate.appendChild(child.cloneNode(true))
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return surrogate
|
|
103
|
+
},
|
|
104
|
+
getAttrs: (node: HTMLElement) => {
|
|
105
|
+
const rt = node.querySelector('rt')
|
|
106
|
+
|
|
107
|
+
if (!rt) {
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { rt: rt.textContent ?? '' }
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
renderHTML({ HTMLAttributes, mark }) {
|
|
118
|
+
return [
|
|
119
|
+
'ruby',
|
|
120
|
+
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
|
|
121
|
+
['rb', 0],
|
|
122
|
+
...(mark.attrs.rt == null ? [] : [['rt', { contenteditable: 'false' }, mark.attrs.rt]]),
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
addCommands() {
|
|
127
|
+
return {
|
|
128
|
+
setRubyText:
|
|
129
|
+
attributes =>
|
|
130
|
+
({ commands }) => {
|
|
131
|
+
return commands.setMark(this.name, attributes)
|
|
132
|
+
},
|
|
133
|
+
toggleRubyText:
|
|
134
|
+
attributes =>
|
|
135
|
+
({ commands }) => {
|
|
136
|
+
return commands.toggleMark(this.name, attributes, { extendEmptyMarkRange: true })
|
|
137
|
+
},
|
|
138
|
+
unsetRubyText:
|
|
139
|
+
() =>
|
|
140
|
+
({ commands }) => {
|
|
141
|
+
return commands.unsetMark(this.name, { extendEmptyMarkRange: true })
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
addProseMirrorPlugins() {
|
|
147
|
+
return [
|
|
148
|
+
RubyTextDecorationPlugin(this.type, {
|
|
149
|
+
editor: this.editor,
|
|
150
|
+
allowClickToEdit: this.options.allowClickToEdit,
|
|
151
|
+
renderAnnotationEditor: this.options.renderAnnotationEditor,
|
|
152
|
+
}),
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
addMarkView() {
|
|
157
|
+
return ({ HTMLAttributes }) => {
|
|
158
|
+
const ruby = document.createElement('ruby')
|
|
159
|
+
|
|
160
|
+
Object.entries(mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)).forEach(
|
|
161
|
+
([key, value]) => {
|
|
162
|
+
if (value != null) {
|
|
163
|
+
ruby.setAttribute(key, String(value))
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
dom: ruby,
|
|
170
|
+
contentDOM: ruby,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
})
|